diff options
-rw-r--r-- | engines/cruise/cruise.h | 1 | ||||
-rw-r--r-- | engines/cruise/cruise_main.cpp | 13 | ||||
-rw-r--r-- | engines/cruise/cruise_main.h | 1 | ||||
-rw-r--r-- | engines/cruise/menu.cpp | 2 | ||||
-rw-r--r-- | engines/sci/console.cpp | 7 | ||||
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 4 | ||||
-rw-r--r-- | engines/sci/gfx/gfx_driver.cpp | 159 | ||||
-rw-r--r-- | engines/sci/gfx/gfx_driver.h | 74 | ||||
-rw-r--r-- | engines/sci/gfx/gfx_resmgr.cpp | 48 | ||||
-rw-r--r-- | engines/sci/gfx/gfx_resmgr.h | 8 | ||||
-rw-r--r-- | engines/sci/gfx/gfx_resource.cpp | 11 | ||||
-rw-r--r-- | engines/sci/gfx/gfx_resource.h | 6 | ||||
-rw-r--r-- | engines/sci/gfx/gfx_system.h | 1 | ||||
-rw-r--r-- | engines/sci/gfx/gfx_widgets.cpp | 2 | ||||
-rw-r--r-- | engines/sci/gfx/operations.cpp | 168 | ||||
-rw-r--r-- | engines/sci/gfx/operations.h | 2 | ||||
-rw-r--r-- | engines/sci/resource.cpp | 428 | ||||
-rw-r--r-- | engines/sci/resource.h | 32 | ||||
-rw-r--r-- | engines/sci/sci.cpp | 5 | ||||
-rw-r--r-- | engines/scumm/detection_tables.h | 2 | ||||
-rw-r--r-- | engines/scumm/he/logic_he.cpp | 86 | ||||
-rw-r--r-- | engines/scumm/he/logic_he.h | 8 | ||||
-rw-r--r-- | engines/scumm/scumm.cpp | 4 | ||||
-rw-r--r-- | engines/scumm/scumm.h | 1 |
24 files changed, 631 insertions, 442 deletions
diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h index 1599c992ac..2fc69acea0 100644 --- a/engines/cruise/cruise.h +++ b/engines/cruise/cruise.h @@ -105,6 +105,7 @@ public: virtual bool canSaveGameStateCurrently(); const CRUISEGameDescription *_gameDescription; + void initAllData(void); Common::RandomSource _rnd; }; diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp index 649cc72cb8..136aa92b81 100644 --- a/engines/cruise/cruise_main.cpp +++ b/engines/cruise/cruise_main.cpp @@ -376,7 +376,7 @@ uint8 *mainProc14(uint16 overlay, uint16 idx) { return NULL; } -int initAllData(void) { +void CruiseEngine::initAllData(void) { int i; setupFuncArray(); @@ -514,7 +514,9 @@ int initAllData(void) { strcpy(lastOverlay, "AUTO00"); - return (bootOverlayNumber); + _gameSpeed = GAME_FRAME_DELAY_1; + + return; } int removeFinishedScripts(scriptInstanceStruct *ptrHandle) { @@ -1790,6 +1792,9 @@ void CruiseEngine::mainLoop(void) { // User waiting has ended changeScriptParamInList(-1, -1, &procHead, 9999, 0); changeScriptParamInList(-1, -1, &relHead, 9999, 0); + + mainDraw(0); + flipScreen(); } if (enableUser) { @@ -1881,13 +1886,13 @@ void CruiseEngine::mainLoop(void) { // flipScreen(); } else { // Standard handling - +/* manageScripts(&relHead); manageScripts(&procHead); removeFinishedScripts(&relHead); removeFinishedScripts(&procHead); - +*/ if (isBlack) { // This is a bit of a hack to ensure that user waits directly after a palette fade // have time to restore the palette before waiting starts diff --git a/engines/cruise/cruise_main.h b/engines/cruise/cruise_main.h index 1b300bd587..86e8dc1591 100644 --- a/engines/cruise/cruise_main.h +++ b/engines/cruise/cruise_main.h @@ -117,7 +117,6 @@ void closeAllMenu(void); int removeFinishedScripts(scriptInstanceStruct *ptrHandle); void initBigVar3(void); void resetActorPtr(actorStruct *ptr); -int initAllData(void); } // End of namespace Cruise diff --git a/engines/cruise/menu.cpp b/engines/cruise/menu.cpp index 9b59494f96..136bd281dc 100644 --- a/engines/cruise/menu.cpp +++ b/engines/cruise/menu.cpp @@ -264,7 +264,7 @@ int playerMenu(int menuX, int menuY) { Op_FadeOut(); memset(globalScreen, 0, 320 * 200); initVars(); - initAllData(); + _vm->initAllData(); changeCursor(CURSOR_NORMAL); userEnabled = 0; break; diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 26ff08d065..f9e13304c5 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -963,8 +963,7 @@ bool Console::cmdUpdateZone(int argc, const char **argv) { int width = atoi(argv[3]); int height = atoi(argv[4]); - g_EngineState->gfx_state->driver->update(g_EngineState->gfx_state->driver, gfx_rect(x, y, width, height), - Common::Point(x, y), GFX_BUFFER_FRONT); + g_EngineState->gfx_state->driver->update(gfx_rect(x, y, width, height), Common::Point(x, y), GFX_BUFFER_FRONT); return false; } @@ -1389,12 +1388,12 @@ bool Console::cmdShowMap(int argc, const char **argv) { break; case 1: - gfx_xlate_pixmap(g_EngineState->gfx_state->pic->priority_map, g_EngineState->gfx_state->driver->mode, GFX_XLATE_FILTER_NONE); + gfx_xlate_pixmap(g_EngineState->gfx_state->pic->priority_map, g_EngineState->gfx_state->driver->getMode(), GFX_XLATE_FILTER_NONE); gfxop_draw_pixmap(g_EngineState->gfx_state, g_EngineState->gfx_state->pic->priority_map, gfx_rect(0, 0, 320, 200), Common::Point(0, 0)); break; case 2: - gfx_xlate_pixmap(g_EngineState->gfx_state->control_map, g_EngineState->gfx_state->driver->mode, GFX_XLATE_FILTER_NONE); + gfx_xlate_pixmap(g_EngineState->gfx_state->control_map, g_EngineState->gfx_state->driver->getMode(), GFX_XLATE_FILTER_NONE); gfxop_draw_pixmap(g_EngineState->gfx_state, g_EngineState->gfx_state->control_map, gfx_rect(0, 0, 320, 200), Common::Point(0, 0)); break; diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 1e0e675603..e58fc79244 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -3328,9 +3328,9 @@ reg_t kShowMovie(EngineState *s, int funct_nr, int argc, reg_t *argv) { gfx_pixmap_t *pixmap = seq.getFrame(play); if (frameNr++ == 0) - pixmap->palette->forceInto(s->gfx_state->driver->mode->palette); + pixmap->palette->forceInto(s->gfx_state->driver->getMode()->palette); - gfx_xlate_pixmap(pixmap, s->gfx_state->driver->mode, GFX_XLATE_FILTER_NONE); + gfx_xlate_pixmap(pixmap, s->gfx_state->driver->getMode(), GFX_XLATE_FILTER_NONE); GFX_ASSERT(gfxop_draw_pixmap(s->gfx_state, pixmap, gfx_rect(0, 0, 320, 200), Common::Point(pixmap->xoffset, pixmap->yoffset))); gfxop_update_box(s->gfx_state, gfx_rect(0, 0, 320, 200)); gfx_free_pixmap(pixmap); diff --git a/engines/sci/gfx/gfx_driver.cpp b/engines/sci/gfx/gfx_driver.cpp index fcac77245e..961eecc6fd 100644 --- a/engines/sci/gfx/gfx_driver.cpp +++ b/engines/sci/gfx/gfx_driver.cpp @@ -33,66 +33,43 @@ namespace Sci { -struct _scummvm_driver_state { - gfx_pixmap_t *priority[2]; - byte *visual[2]; - int xsize, ysize; -}; - -#define S ((struct _scummvm_driver_state *)(drv->state)) - -static int scummvm_init(gfx_driver_t *drv, int xfact, int yfact, int bytespp) { +GfxDriver::GfxDriver(int xfact, int yfact, int bytespp) { int i; - if (!drv->state) // = S - drv->state = new _scummvm_driver_state; - if (!drv->state) - return GFX_FATAL; - - S->xsize = xfact * 320; - S->ysize = yfact * 200; - - //S->buckystate = 0; + Graphics::PixelFormat format = { bytespp, 0, 0, 0, 0, 0, 0, 0, 0 }; + _mode = gfx_new_mode(xfact, yfact, format, new Palette(256), 0); + _mode->xsize = xfact * 320; + _mode->ysize = yfact * 200; for (i = 0; i < 2; i++) { - S->priority[i] = gfx_pixmap_alloc_index_data(gfx_new_pixmap(S->xsize, S->ysize, GFX_RESID_NONE, -i, -777)); - if (!S->priority[i]) { - printf("Out of memory: Could not allocate priority maps! (%dx%d)\n", S->xsize, S->ysize); - return GFX_FATAL; + _priority[i] = gfx_pixmap_alloc_index_data(gfx_new_pixmap(_mode->xsize, _mode->ysize, GFX_RESID_NONE, -i, -777)); + if (!_priority[i]) { + error("Out of memory: Could not allocate priority maps! (%dx%d)\n", _mode->xsize, _mode->ysize); } } // create the visual buffers for (i = 0; i < 2; i++) { - S->visual[i] = NULL; - S->visual[i] = new byte[S->xsize * S->ysize]; - if (!S->visual[i]) { - printf("Out of memory: Could not allocate visual buffers! (%dx%d)\n", S->xsize, S->ysize); - return GFX_FATAL; + _visual[i] = NULL; + _visual[i] = new byte[_mode->xsize * _mode->ysize]; + if (!_visual[i]) { + error("Out of memory: Could not allocate visual buffers! (%dx%d)\n", _mode->xsize, _mode->ysize); } - memset(S->visual[i], 0, S->xsize * S->ysize); + memset(_visual[i], 0, _mode->xsize * _mode->ysize); } - Graphics::PixelFormat format = { bytespp, 0, 0, 0, 0, 0, 0, 0, 0 }; - drv->mode = gfx_new_mode(xfact, yfact, format, new Palette(256), 0); - drv->mode->palette->name = "global"; - - return GFX_OK; + _mode->palette->name = "global"; } -static void scummvm_exit(gfx_driver_t *drv) { +GfxDriver::~GfxDriver() { int i; - if (S) { - for (i = 0; i < 2; i++) { - gfx_free_pixmap(S->priority[i]); - S->priority[i] = NULL; - } - - for (i = 0; i < 2; i++) { - delete[] S->visual[i]; - S->visual[i] = NULL; - } + for (i = 0; i < 2; i++) { + gfx_free_pixmap(_priority[i]); + _priority[i] = NULL; + } - delete S; + for (i = 0; i < 2; i++) { + delete[] _visual[i]; + _visual[i] = NULL; } } @@ -100,18 +77,18 @@ static void scummvm_exit(gfx_driver_t *drv) { // Drawing operations static void drawProc(int x, int y, int c, void *data) { - gfx_driver_t *drv = (gfx_driver_t *)data; - uint8 *p = S->visual[0]; - p[y * 320*drv->mode->xfact + x] = c; + GfxDriver *drv = (GfxDriver *)data; + byte *p = drv->getVisual0(); + p[y * 320* drv->getMode()->xfact + x] = c; } -static int scummvm_draw_line(gfx_driver_t *drv, Common::Point start, Common::Point end, - gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style) { +int GfxDriver::drawLine(Common::Point start, Common::Point end, gfx_color_t color, + gfx_line_mode_t line_mode, gfx_line_style_t line_style) { uint32 scolor = color.visual.parent_index; - int xfact = (line_mode == GFX_LINE_MODE_FINE)? 1: drv->mode->xfact; - int yfact = (line_mode == GFX_LINE_MODE_FINE)? 1: drv->mode->yfact; - int xsize = S->xsize; - int ysize = S->ysize; + int xfact = (line_mode == GFX_LINE_MODE_FINE)? 1: _mode->xfact; + int yfact = (line_mode == GFX_LINE_MODE_FINE)? 1: _mode->yfact; + int xsize = _mode->xsize; + int ysize = _mode->ysize; if (color.mask & GFX_MASK_VISUAL) { Common::Point nstart, nend; @@ -124,10 +101,10 @@ static int scummvm_draw_line(gfx_driver_t *drv, Common::Point start, Common::Poi nend.x = CLIP<int16>(end.x + xc, 0, xsize - 1); nend.y = CLIP<int16>(end.y + yc, 0, ysize - 1); - Graphics::drawLine(nstart.x, nstart.y, nend.x, nend.y, scolor, drawProc, drv); + Graphics::drawLine(nstart.x, nstart.y, nend.x, nend.y, scolor, drawProc, this); if (color.mask & GFX_MASK_PRIORITY) { - gfx_draw_line_pixmap_i(S->priority[0], nstart, nend, color.priority); + gfx_draw_line_pixmap_i(_priority[0], nstart, nend, color.priority); } } } @@ -136,24 +113,23 @@ static int scummvm_draw_line(gfx_driver_t *drv, Common::Point start, Common::Poi return GFX_OK; } -static int scummvm_draw_filled_rect(gfx_driver_t *drv, rect_t rect, gfx_color_t color1, gfx_color_t color2, +int GfxDriver::drawFilledRect(rect_t rect, gfx_color_t color1, gfx_color_t color2, gfx_rectangle_fill_t shade_mode) { if (color1.mask & GFX_MASK_VISUAL) { for (int i = rect.y; i < rect.y + rect.height; i++) { - memset(S->visual[0] + i * S->xsize + rect.x, color1.visual.parent_index, rect.width); + memset(_visual[0] + i * _mode->xsize + rect.x, color1.visual.parent_index, rect.width); } } if (color1.mask & GFX_MASK_PRIORITY) - gfx_draw_box_pixmap_i(S->priority[0], rect, color1.priority); + gfx_draw_box_pixmap_i(_priority[0], rect, color1.priority); return GFX_OK; } // Pixmap operations -static int scummvm_draw_pixmap(gfx_driver_t *drv, gfx_pixmap_t *pxm, int priority, - rect_t src, rect_t dest, gfx_buffer_t buffer) { +int GfxDriver::drawPixmap(gfx_pixmap_t *pxm, int priority, rect_t src, rect_t dest, gfx_buffer_t buffer) { int bufnr = (buffer == GFX_BUFFER_STATIC) ? 1 : 0; if (dest.width != src.width || dest.height != src.height) { @@ -161,13 +137,13 @@ static int scummvm_draw_pixmap(gfx_driver_t *drv, gfx_pixmap_t *pxm, int priorit return GFX_ERROR; } - gfx_crossblit_pixmap(drv->mode, pxm, priority, src, dest, S->visual[bufnr], S->xsize, - S->priority[bufnr]->index_data, S->priority[bufnr]->index_width, 1, 0); + gfx_crossblit_pixmap(_mode, pxm, priority, src, dest, _visual[bufnr], _mode->xsize, + _priority[bufnr]->index_data, _priority[bufnr]->index_width, 1, 0); return GFX_OK; } -static int scummvm_grab_pixmap(gfx_driver_t *drv, rect_t src, gfx_pixmap_t *pxm, gfx_map_mask_t map) { +int GfxDriver::grabPixmap(rect_t src, gfx_pixmap_t *pxm, gfx_map_mask_t map) { if (src.x < 0 || src.y < 0) { printf("Attempt to grab pixmap from invalid coordinates (%d,%d)\n", src.x, src.y); return GFX_ERROR; @@ -184,7 +160,7 @@ static int scummvm_grab_pixmap(gfx_driver_t *drv, rect_t src, gfx_pixmap_t *pxm, pxm->width = src.width; pxm->height = src.height; for (int i = 0; i < src.height; i++) { - memcpy(pxm->data + i * src.width, S->visual[0] + (i + src.y) * S->xsize + src.x, src.width); + memcpy(pxm->data + i * src.width, _visual[0] + (i + src.y) * _mode->xsize + src.x, src.width); } break; @@ -202,7 +178,7 @@ static int scummvm_grab_pixmap(gfx_driver_t *drv, rect_t src, gfx_pixmap_t *pxm, // Buffer operations -static int scummvm_update(gfx_driver_t *drv, rect_t src, Common::Point dest, gfx_buffer_t buffer) { +int GfxDriver::update(rect_t src, Common::Point dest, gfx_buffer_t buffer) { //TODO /* @@ -216,15 +192,15 @@ static int scummvm_update(gfx_driver_t *drv, rect_t src, Common::Point dest, gfx switch (buffer) { case GFX_BUFFER_BACK: for (int i = 0; i < src.height; i++) { - memcpy(S->visual[0] + (dest.y + i) * S->xsize + dest.x, - S->visual[1] + (src.y + i) * S->xsize + src.x, src.width); + memcpy(_visual[0] + (dest.y + i) * _mode->xsize + dest.x, + _visual[1] + (src.y + i) * _mode->xsize + src.x, src.width); } if ((src.x == dest.x) && (src.y == dest.y)) - gfx_copy_pixmap_box_i(S->priority[0], S->priority[1], src); + gfx_copy_pixmap_box_i(_priority[0], _priority[1], src); break; case GFX_BUFFER_FRONT: - g_system->copyRectToScreen(S->visual[0] + src.x + src.y * S->xsize, S->xsize, dest.x, dest.y, src.width, src.height); + g_system->copyRectToScreen(_visual[0] + src.x + src.y * _mode->xsize, _mode->xsize, dest.x, dest.y, src.width, src.height); g_system->updateScreen(); break; default: @@ -235,9 +211,9 @@ static int scummvm_update(gfx_driver_t *drv, rect_t src, Common::Point dest, gfx return GFX_OK; } -static int scummvm_set_static_buffer(gfx_driver_t *drv, gfx_pixmap_t *pic, gfx_pixmap_t *priority) { - memcpy(S->visual[1], pic->data, S->xsize * S->ysize); - gfx_copy_pixmap_box_i(S->priority[1], priority, gfx_rect(0, 0, S->xsize, S->ysize)); +int GfxDriver::setStaticBuffer(gfx_pixmap_t *pic, gfx_pixmap_t *priority) { + memcpy(_visual[1], pic->data, _mode->xsize * _mode->ysize); + gfx_copy_pixmap_box_i(_priority[1], priority, gfx_rect(0, 0, _mode->xsize, _mode->ysize)); return GFX_OK; } @@ -245,45 +221,44 @@ static int scummvm_set_static_buffer(gfx_driver_t *drv, gfx_pixmap_t *pic, gfx_p // Mouse pointer operations // Scale cursor and map its colors to the global palette -static uint8 *create_cursor(gfx_driver_t *drv, gfx_pixmap_t *pointer, int mode) -{ +byte *GfxDriver::createCursor(gfx_pixmap_t *pointer) { int linewidth = pointer->width; int lines = pointer->height; - uint8 *data = new uint8[linewidth*lines]; - uint8 *linebase = data, *pos; - uint8 *src = pointer->index_data; + byte *data = new byte[linewidth*lines]; + byte *linebase = data, *pos; + byte *src = pointer->index_data; for (int yc = 0; yc < pointer->index_height; yc++) { pos = linebase; for (int xc = 0; xc < pointer->index_width; xc++) { - uint8 color = *src; + byte color = *src; // FIXME: The palette size check is a workaround for cursors using non-palette colour GFX_CURSOR_TRANSPARENT // Note that some cursors don't have a palette in SQ5 if (pointer->palette && color < pointer->palette->size()) color = pointer->palette->getColor(color).parent_index; - for (int scalectr = 0; scalectr < drv->mode->xfact; scalectr++) { + for (int scalectr = 0; scalectr < _mode->xfact; scalectr++) { *pos++ = color; } src++; } - for (int scalectr = 1; scalectr < drv->mode->yfact; scalectr++) + for (int scalectr = 1; scalectr < _mode->yfact; scalectr++) memcpy(linebase + linewidth * scalectr, linebase, linewidth); - linebase += linewidth * drv->mode->yfact; + linebase += linewidth * _mode->yfact; } return data; } -static int scummvm_set_pointer(gfx_driver_t *drv, gfx_pixmap_t *pointer, Common::Point *hotspot) { +int GfxDriver::setPointer(gfx_pixmap_t *pointer, Common::Point *hotspot) { if ((pointer == NULL) || (hotspot == NULL)) { g_system->showMouse(false); } else { - uint8 *cursorData = create_cursor(drv, pointer, 1); + byte *cursorData = createCursor(pointer); // FIXME: The palette size check is a workaround for cursors using non-palette colour GFX_CURSOR_TRANSPARENT // Note that some cursors don't have a palette in SQ5 - uint8 color_key = GFX_CURSOR_TRANSPARENT; + byte color_key = GFX_CURSOR_TRANSPARENT; if ((pointer->color_key != GFX_PIXMAP_COLOR_KEY_NONE) && (pointer->palette && (unsigned int)pointer->color_key < pointer->palette->size())) color_key = pointer->palette->getColor(pointer->color_key).parent_index; // Some cursors in SQ5 don't have a palette. The cursor palette seems to use 64 colors, so setting the color key to 63 works @@ -301,18 +276,4 @@ static int scummvm_set_pointer(gfx_driver_t *drv, gfx_pixmap_t *pointer, Common: return GFX_OK; } -gfx_driver_t gfx_driver_scummvm = { - NULL, - scummvm_init, - scummvm_exit, - scummvm_draw_line, - scummvm_draw_filled_rect, - scummvm_draw_pixmap, - scummvm_grab_pixmap, - scummvm_update, - scummvm_set_static_buffer, - scummvm_set_pointer, - NULL -}; - } // End of namespace Sci diff --git a/engines/sci/gfx/gfx_driver.h b/engines/sci/gfx/gfx_driver.h index 47b5e7de21..b74511de77 100644 --- a/engines/sci/gfx/gfx_driver.h +++ b/engines/sci/gfx/gfx_driver.h @@ -62,18 +62,13 @@ enum gfx_buffer_t { ** must use a reasonable default value. */ -// FIXME: Turn this into a class, or get rid of it completely. -struct gfx_driver_t { /* Graphics driver */ - - gfx_mode_t *mode; /* Currently active mode, NULL if no mode is active */ - +class GfxDriver { +public: /*** Initialization ***/ - int (*init)(gfx_driver_t *drv, int xres, int yres, - int bytespp); + GfxDriver(int xfact, int yfact, int bytespp); /* Attempts to initialize a specific graphics mode - ** Parameters: (gfx_driver_t *) drv: The affected driver - ** (int x int) xres, yres: Horizontal and vertical scaling + ** Parameters: (int x int) xres, yres: Horizontal and vertical scaling ** factors ** (int) bytespp: Any of GFX_COLOR_MODE_*. GFX_COLOR_MODE_INDEX ** implies color index mode. @@ -83,14 +78,12 @@ struct gfx_driver_t { /* Graphics driver */ ** and is used for internal representation of graphical data. The physical ** resolution set by the graphics driver may be different for practical ** reasons. - ** Must also set drv->mode, preferably with the gfx_new_mode() function + ** Must also set _mode, preferably with the gfx_new_mode() function ** specified in gfx_tools.h. */ - void (*exit)(gfx_driver_t *drv); + ~GfxDriver(); /* Uninitializes the current graphics mode - ** Paramters: (gfx_driver_t *) drv: The driver to uninitialize - ** Return : (void) ** This function frees all memory allocated by the graphics driver, ** including mode and palette information, uninstalls all console commands ** introduced by preceeding init() or init_specific() commands, and does any @@ -101,13 +94,10 @@ struct gfx_driver_t { /* Graphics driver */ /*** Drawing operations ***/ - int (*draw_line)(gfx_driver_t *drv, - Common::Point start, Common::Point end, - gfx_color_t color, - gfx_line_mode_t line_mode, gfx_line_style_t line_style); + int drawLine(Common::Point start, Common::Point end, gfx_color_t color, + gfx_line_mode_t line_mode, gfx_line_style_t line_style); /* Draws a single line to the back buffer. - ** Parameters: (gfx_driver_t *) drv: The driver affected - ** (Common::Point) start: Starting point of the line to draw + ** Parameters: (Common::Point) start: Starting point of the line to draw ** (Common::Point) end: End point of the line to draw ** (gfx_color_t *) color: The color to draw with ** (int) line_mode: Any of the line modes @@ -122,12 +112,10 @@ struct gfx_driver_t { /* Graphics driver */ ** set. */ - int (*draw_filled_rect)(gfx_driver_t *drv, rect_t rect, - gfx_color_t color1, gfx_color_t color2, - gfx_rectangle_fill_t shade_mode); + int drawFilledRect(rect_t rect, gfx_color_t color1, gfx_color_t color2, + gfx_rectangle_fill_t shade_mode); /* Draws a single filled and possibly shaded rectangle to the back buffer. - ** Parameters: (gfx_driver_t *) drv: The driver affected - ** (rect_t *) rect: The rectangle to draw + ** Parameters: (rect_t *) rect: The rectangle to draw ** (gfx_color_t *) color1, color2: The colors to draw with ** (int) shade_mode: Any of GFX_SHADE_*. ** Returns : (int) GFX_OK or GFX_FATAL @@ -139,11 +127,10 @@ struct gfx_driver_t { /* Graphics driver */ /*** Pixmap operations ***/ - int (*draw_pixmap)(gfx_driver_t *drv, gfx_pixmap_t *pxm, int priority, - rect_t src, rect_t dest, gfx_buffer_t buffer); + int drawPixmap(gfx_pixmap_t *pxm, int priority, + rect_t src, rect_t dest, gfx_buffer_t buffer); /* Draws part of a pixmap to the static or back buffer - ** Parameters: (gfx_driver_t *) drv: The affected driver - ** (gfx_pixmap_t *) pxm: The pixmap to draw + ** Parameters: (gfx_pixmap_t *) pxm: The pixmap to draw ** (int) priority: The priority to draw with, or GFX_NO_PRIORITY ** to draw on top of everything without setting the ** priority back buffer @@ -154,11 +141,9 @@ struct gfx_driver_t { /* Graphics driver */ ** (but should have been) registered. */ - int (*grab_pixmap)(gfx_driver_t *drv, rect_t src, gfx_pixmap_t *pxm, - gfx_map_mask_t map); + int grabPixmap(rect_t src, gfx_pixmap_t *pxm, gfx_map_mask_t map); /* Grabs an image from the visual or priority back buffer - ** Parameters: (gfx_driver_t *) drv: The affected driver - ** (rect_t) src: The rectangle to grab + ** Parameters: (rect_t) src: The rectangle to grab ** (gfx_pixmap_t *) pxm: The pixmap structure the data is to ** be written to ** (int) map: GFX_MASK_VISUAL or GFX_MASK_PRIORITY @@ -171,11 +156,9 @@ struct gfx_driver_t { /* Graphics driver */ /*** Buffer operations ***/ - int (*update)(gfx_driver_t *drv, rect_t src, Common::Point dest, - gfx_buffer_t buffer); + int update(rect_t src, Common::Point dest, gfx_buffer_t buffer); /* Updates the front buffer or the back buffers - ** Parameters: (gfx_driver_t *) drv: The affected driver - ** (rect_t) src: Source rectangle + ** Parameters: (rect_t) src: Source rectangle ** (Common::Point) dest: Destination point ** (int) buffer: One of GFX_BUFFER_FRONT or GFX_BUFFER_BACK ** Returns : (int) GFX_OK, GFX_ERROR or GFX_FATAL @@ -187,11 +170,9 @@ struct gfx_driver_t { /* Graphics driver */ ** If they aren't, the priority map will not be required to be copied. */ - int (*set_static_buffer)(gfx_driver_t *drv, gfx_pixmap_t *pic, - gfx_pixmap_t *priority); + int setStaticBuffer(gfx_pixmap_t *pic, gfx_pixmap_t *priority); /* Sets the contents of the static visual and priority buffers - ** Parameters: (gfx_driver_t *) drv: The affected driver - ** (gfx_pixmap_t *) pic: The image defining the new content + ** Parameters: (gfx_pixmap_t *) pic: The image defining the new content ** of the visual back buffer ** (gfx_pixmap_t *) priority: The priority map containing ** the new content of the priority back buffer @@ -209,10 +190,9 @@ struct gfx_driver_t { /* Graphics driver */ /*** Mouse pointer operations ***/ - int (*set_pointer)(gfx_driver_t *drv, gfx_pixmap_t *pointer, Common::Point *hotspot); + int setPointer(gfx_pixmap_t *pointer, Common::Point *hotspot); /* Sets a new mouse pointer. - ** Parameters: (gfx_driver_t *) drv: The driver to modify - ** (gfx_pixmap_t *) pointer: The pointer to set, or NULL to set + ** Parameters: (gfx_pixmap_t *) pointer: The pointer to set, or NULL to set ** no pointer ** (Common::Point *) hotspot: The coordinates of the hotspot, ** or NULL to set no pointer @@ -224,9 +204,15 @@ struct gfx_driver_t { /* Graphics driver */ ** 0, 1, and GFX_COLOR_INDEX_TRANSPARENT are used. */ + gfx_mode_t *getMode() { return _mode; } + byte *getVisual0() { return _visual[0]; } - void *state; /* Reserved for internal use */ +private: + byte *createCursor(gfx_pixmap_t *pointer); + gfx_pixmap_t *_priority[2]; + byte *_visual[2]; + gfx_mode_t *_mode; /* Currently active mode, NULL if no mode is active */ }; } // End of namespace Sci diff --git a/engines/sci/gfx/gfx_resmgr.cpp b/engines/sci/gfx/gfx_resmgr.cpp index 9eeada7b39..c5269bc544 100644 --- a/engines/sci/gfx/gfx_resmgr.cpp +++ b/engines/sci/gfx/gfx_resmgr.cpp @@ -46,10 +46,10 @@ namespace Sci { struct param_struct { int args[4]; - gfx_driver_t *driver; + GfxDriver *driver; }; -GfxResManager::GfxResManager(int version, bool isVGA, gfx_options_t *options, gfx_driver_t *driver, ResourceManager *resManager) : +GfxResManager::GfxResManager(int version, bool isVGA, gfx_options_t *options, GfxDriver *driver, ResourceManager *resManager) : _version(version), _isVGA(isVGA), _options(options), _driver(driver), _resManager(resManager), _lockCounter(0), _tagLockCounter(0), _staticPalette(0) { gfxr_init_static_palette(); @@ -268,7 +268,7 @@ void GfxResManager::setStaticPalette(Palette *newPalette) _staticPalette = newPalette; _staticPalette->name = "static palette"; - _staticPalette->mergeInto(_driver->mode->palette); + _staticPalette->mergeInto(_driver->getMode()->palette); } #if 0 @@ -307,13 +307,27 @@ static gfxr_pic_t *gfxr_pic_xlate_common(gfx_resource_t *res, int maps, int scal } #undef XLATE_AS_APPROPRIATE +/* unscaled color index mode: Used in addition to a scaled mode +** to render the pic resource twice. +*/ +// FIXME: this is an ugly hack. Perhaps we could do it some other way? +gfx_mode_t mode_1x1_color_index = { /* Fake 1x1 mode */ + /* xfact */ 1, /* yfact */ 1, + /* xsize */ 1, /* ysize */ 1, + /* bytespp */ 1, + /* flags */ 0, + /* palette */ NULL, + + /* color masks */ 0, 0, 0, 0, + /* color shifts */ 0, 0, 0, 0 +}; gfxr_pic_t *GfxResManager::getPic(int num, int maps, int flags, int default_palette, bool scaled) { gfxr_pic_t *npic = NULL; IntResMap &resMap = _resourceMaps[GFX_RESOURCE_TYPE_PIC]; gfx_resource_t *res = NULL; int hash = getOptionsHash(GFX_RESOURCE_TYPE_PIC); - int need_unscaled = (_driver->mode->xfact != 1 || _driver->mode->yfact != 1); + int need_unscaled = (_driver->getMode()->xfact != 1 || _driver->getMode()->yfact != 1); hash |= (flags << 20) | ((default_palette & 0x7) << 28); @@ -328,10 +342,10 @@ gfxr_pic_t *GfxResManager::getPic(int num, int maps, int flags, int default_pale need_unscaled = 0; pic = gfxr_init_pic(&mode_1x1_color_index, GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _version >= SCI_VERSION_01_VGA); } else - pic = gfxr_init_pic(_driver->mode, GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _version >= SCI_VERSION_01_VGA); + pic = gfxr_init_pic(_driver->getMode(), GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _version >= SCI_VERSION_01_VGA); #else need_unscaled = 0; - pic = gfxr_init_pic(&mode_1x1_color_index, GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _version >= SCI_VERSION_01_VGA); + pic = gfxr_init_pic(_driver->getMode(), GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _version >= SCI_VERSION_01_VGA); #endif if (!pic) { @@ -382,10 +396,10 @@ gfxr_pic_t *GfxResManager::getPic(int num, int maps, int flags, int default_pale } #ifdef CUSTOM_GRAPHICS_OPTIONS - npic = gfxr_pic_xlate_common(res, maps, scaled || _options->pic0_unscaled, 0, _driver->mode, + npic = gfxr_pic_xlate_common(res, maps, scaled || _options->pic0_unscaled, 0, _driver->getMode(), _options->pic_xlate_filter, _options); #else - npic = gfxr_pic_xlate_common(res, maps, 1, 0, _driver->mode, + npic = gfxr_pic_xlate_common(res, maps, 1, 0, _driver->getMode(), GFX_XLATE_FILTER_NONE, _options); #endif @@ -446,7 +460,7 @@ gfxr_pic_t *GfxResManager::addToPic(int old_nr, int new_nr, int flags, int old_d gfx_resource_t *res = NULL; int hash = getOptionsHash(GFX_RESOURCE_TYPE_PIC); #ifdef CUSTOM_GRAPHICS_OPTIONS - int need_unscaled = !(_options->pic0_unscaled) && (_driver->mode->xfact != 1 || _driver->mode->yfact != 1); + int need_unscaled = !(_options->pic0_unscaled) && (_driver->getMode()->xfact != 1 || _driver->getMode()->yfact != 1); #else int need_unscaled = 1; #endif @@ -467,7 +481,7 @@ gfxr_pic_t *GfxResManager::addToPic(int old_nr, int new_nr, int flags, int old_d #ifdef CUSTOM_GRAPHICS_OPTIONS if (_options->pic0_unscaled) // Unscale priority map, if we scaled it earlier #endif - _gfxr_unscale_pixmap_index_data(res->scaled_data.pic->priority_map, _driver->mode); + _gfxr_unscale_pixmap_index_data(res->scaled_data.pic->priority_map, _driver->getMode()); // The following two operations are needed when returning scaled maps (which is always the case here) #ifdef CUSTOM_GRAPHICS_OPTIONS @@ -483,15 +497,15 @@ gfxr_pic_t *GfxResManager::addToPic(int old_nr, int new_nr, int flags, int old_d #ifdef CUSTOM_GRAPHICS_OPTIONS if (_options->pic0_unscaled) // Scale priority map again, if needed #endif - res->scaled_data.pic->priority_map = gfx_pixmap_scale_index_data(res->scaled_data.pic->priority_map, _driver->mode); + res->scaled_data.pic->priority_map = gfx_pixmap_scale_index_data(res->scaled_data.pic->priority_map, _driver->getMode()); { int old_ID = get_pic_id(res); set_pic_id(res, GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, new_nr)); // To ensure that our graphical translation options work properly #ifdef CUSTOM_GRAPHICS_OPTIONS - pic = gfxr_pic_xlate_common(res, GFX_MASK_VISUAL, 1, 1, _driver->mode, _options->pic_xlate_filter, _options); + pic = gfxr_pic_xlate_common(res, GFX_MASK_VISUAL, 1, 1, _driver->getMode(), _options->pic_xlate_filter, _options); #else - pic = gfxr_pic_xlate_common(res, GFX_MASK_VISUAL, 1, 1, _driver->mode, GFX_XLATE_FILTER_NONE, _options); + pic = gfxr_pic_xlate_common(res, GFX_MASK_VISUAL, 1, 1, _driver->getMode(), GFX_XLATE_FILTER_NONE, _options); #endif set_pic_id(res, old_ID); } @@ -590,9 +604,9 @@ gfxr_view_t *GfxResManager::getView(int nr, int *loop, int *cel, int palette) { if (!cel_data->data) { #ifdef CUSTOM_GRAPHICS_OPTIONS gfx_get_res_config(_options, cel_data); - gfx_xlate_pixmap(cel_data, _driver->mode, _options->view_xlate_filter); + gfx_xlate_pixmap(cel_data, _driver->getMode(), _options->view_xlate_filter); #else - gfx_xlate_pixmap(cel_data, _driver->mode, GFX_XLATE_FILTER_NONE); + gfx_xlate_pixmap(cel_data, _driver->getMode(), GFX_XLATE_FILTER_NONE); #endif } @@ -671,9 +685,9 @@ gfx_pixmap_t *GfxResManager::getCursor(int num) { } #ifdef CUSTOM_GRAPHICS_OPTIONS gfx_get_res_config(_options, cursor); - gfx_xlate_pixmap(cursor, _driver->mode, _options->cursor_xlate_filter); + gfx_xlate_pixmap(cursor, _driver->getMode(), _options->cursor_xlate_filter); #else - gfx_xlate_pixmap(cursor, _driver->mode, GFX_XLATE_FILTER_NONE); + gfx_xlate_pixmap(cursor, _driver->getMode(), GFX_XLATE_FILTER_NONE); #endif res->unscaled_data.pointer = cursor; diff --git a/engines/sci/gfx/gfx_resmgr.h b/engines/sci/gfx/gfx_resmgr.h index 7e7d71f934..c5878bf529 100644 --- a/engines/sci/gfx/gfx_resmgr.h +++ b/engines/sci/gfx/gfx_resmgr.h @@ -88,7 +88,7 @@ typedef Common::HashMap<int, gfx_resource_t *> IntResMap; class GfxResManager { public: - GfxResManager(int version, bool isVGA, gfx_options_t *options, gfx_driver_t *driver, ResourceManager *resManager); + GfxResManager(int version, bool isVGA, gfx_options_t *options, GfxDriver *driver, ResourceManager *resManager); ~GfxResManager(); @@ -239,13 +239,13 @@ public: void setPaletteIntensity(int16 from, int16 to, int16 intensity) { Palette *pal = _staticPalette->getref(); - for (uint16 i = 0; i < _driver->mode->palette->size(); i++) { + for (uint16 i = 0; i < _driver->getMode()->palette->size(); i++) { byte r = pal->getColor(i).r * intensity / 100; byte g = pal->getColor(i).g * intensity / 100; byte b = pal->getColor(i).b * intensity / 100; pal->makeSystemColor(i, PaletteEntry(r, g, b)); } - pal->mergeInto(_driver->mode->palette); + pal->mergeInto(_driver->getMode()->palette); _driver->install_palette(_driver, pal); pal->unmerge(); pal->free(); @@ -258,7 +258,7 @@ private: int _version; bool _isVGA; gfx_options_t *_options; - gfx_driver_t *_driver; + GfxDriver *_driver; Palette *_staticPalette; int _lockCounter; /* Global lock counter; increased for each new resource allocated. ** The newly allocated resource will then be assigned the new value diff --git a/engines/sci/gfx/gfx_resource.cpp b/engines/sci/gfx/gfx_resource.cpp index 59170ec4fa..4eae7942c5 100644 --- a/engines/sci/gfx/gfx_resource.cpp +++ b/engines/sci/gfx/gfx_resource.cpp @@ -29,17 +29,6 @@ namespace Sci { -gfx_mode_t mode_1x1_color_index = { /* Fake 1x1 mode */ - /* xfact */ 1, /* yfact */ 1, - /* bytespp */ 1, - /* flags */ 0, - /* palette */ NULL, - - /* color masks */ 0, 0, 0, 0, - /* color shifts */ 0, 0, 0, 0 -}; - - static void gfxr_free_loop(gfxr_loop_t *loop) { int i; diff --git a/engines/sci/gfx/gfx_resource.h b/engines/sci/gfx/gfx_resource.h index fb05975dc0..8ce4a8ea83 100644 --- a/engines/sci/gfx/gfx_resource.h +++ b/engines/sci/gfx/gfx_resource.h @@ -122,12 +122,6 @@ struct gfxr_view_t { int translation[GFX_SCI0_IMAGE_COLORS_NR]; }; - -/* unscaled color index mode: Used in addition to a scaled mode -** to render the pic resource twice. See gfxr_remove_artifacts_pic0(). -*/ -extern gfx_mode_t mode_1x1_color_index; - void gfxr_init_static_palette(); /* Initializes the static 256 color palette ** Parameters: (void) diff --git a/engines/sci/gfx/gfx_system.h b/engines/sci/gfx/gfx_system.h index d21c28629b..bc25364b92 100644 --- a/engines/sci/gfx/gfx_system.h +++ b/engines/sci/gfx/gfx_system.h @@ -60,6 +60,7 @@ namespace Sci { struct gfx_mode_t { int xfact, yfact; /* Horizontal and vertical scaling factors */ + int xsize, ysize; /* Horizontal and vertical size */ int bytespp; /* Bytes per pixel */ uint32 flags; /* GFX_MODE_FLAG_* Flags- see above */ diff --git a/engines/sci/gfx/gfx_widgets.cpp b/engines/sci/gfx/gfx_widgets.cpp index e17ffae6f1..08600c94b2 100644 --- a/engines/sci/gfx/gfx_widgets.cpp +++ b/engines/sci/gfx/gfx_widgets.cpp @@ -409,7 +409,7 @@ GfxBox::GfxBox(GfxState *state, rect_t area, gfx_color_t color1, gfx_color_t col _flags |= GFXW_FLAG_VISIBLE; - if ((_color1.mask & GFX_MASK_VISUAL) && ((state && (state->driver->mode->palette)) || (!_color1.alpha && !_color2.alpha))) + if ((_color1.mask & GFX_MASK_VISUAL) && ((state && (state->driver->getMode()->palette)) || (!_color1.alpha && !_color2.alpha))) _flags |= GFXW_FLAG_OPAQUE; _gfxw_set_ops_BOX(this); diff --git a/engines/sci/gfx/operations.cpp b/engines/sci/gfx/operations.cpp index d9dc539c79..cb73771528 100644 --- a/engines/sci/gfx/operations.cpp +++ b/engines/sci/gfx/operations.cpp @@ -69,7 +69,7 @@ if (!state) { \ } // How to determine whether colors have to be allocated -#define PALETTE_MODE state->driver->mode->palette +#define PALETTE_MODE state->driver->getMode()->palette //#define GFXOP_DEBUG_DIRTY @@ -124,13 +124,13 @@ int _gfxop_clip(rect_t *rect, rect_t clipzone) { static int _gfxop_grab_pixmap(GfxState *state, gfx_pixmap_t **pxmp, int x, int y, int xl, int yl, int priority, rect_t *zone) { // Returns 1 if the resulting data size was zero, GFX_OK or an error code otherwise */ - int xfact = state->driver->mode->xfact; - int yfact = state->driver->mode->yfact; + int xfact = state->driver->getMode()->xfact; + int yfact = state->driver->getMode()->yfact; int unscaled_xl = (xl + xfact - 1) / xfact; int unscaled_yl = (yl + yfact - 1) / yfact; *zone = gfx_rect(x, y, xl, yl); - if (_gfxop_clip(zone, gfx_rect(0, 0, 320 * state->driver->mode->xfact, 200 * state->driver->mode->yfact))) + if (_gfxop_clip(zone, gfx_rect(0, 0, 320 * state->driver->getMode()->xfact, 200 * state->driver->getMode()->yfact))) return GFX_ERROR; if (!*pxmp) @@ -144,9 +144,9 @@ static int _gfxop_grab_pixmap(GfxState *state, gfx_pixmap_t **pxmp, int x, int y if (!(*pxmp)->data) { (*pxmp)->index_width = unscaled_xl + 1; (*pxmp)->index_height = unscaled_yl + 1; - gfx_pixmap_alloc_data(*pxmp, state->driver->mode); + gfx_pixmap_alloc_data(*pxmp, state->driver->getMode()); } - return state->driver->grab_pixmap(state->driver, *zone, *pxmp, priority ? GFX_MASK_PRIORITY : GFX_MASK_VISUAL); + return state->driver->grabPixmap(*zone, *pxmp, priority ? GFX_MASK_PRIORITY : GFX_MASK_VISUAL); } #define DRAW_LOOP(condition) \ @@ -192,24 +192,24 @@ DRAW_LOOP(map->index_data[offset] < color) // Draw only lower priority #undef DRAW_LOOP -static int _gfxop_install_pixmap(gfx_driver_t *driver, gfx_pixmap_t *pxm) { - if (!driver->mode->palette) return GFX_OK; +static int _gfxop_install_pixmap(GfxDriver *driver, gfx_pixmap_t *pxm) { + if (!driver->getMode()->palette) return GFX_OK; if (!pxm->palette) return GFX_OK; - pxm->palette->mergeInto(driver->mode->palette); - assert(pxm->palette->getParent() == driver->mode->palette); + pxm->palette->mergeInto(driver->getMode()->palette); + assert(pxm->palette->getParent() == driver->getMode()->palette); if (pxm->palette_revision != pxm->palette->getRevision()) - gfx_xlate_pixmap(pxm, driver->mode, GFX_XLATE_FILTER_NONE); + gfx_xlate_pixmap(pxm, driver->getMode(), GFX_XLATE_FILTER_NONE); - if (!driver->mode->palette->isDirty()) return GFX_OK; + if (!driver->getMode()->palette->isDirty()) return GFX_OK; // TODO: We probably want to only update the colours used by this pixmap // here. This will require updating the 'dirty' system. - uint8 paletteData[4*256]; - const uint paletteSize = driver->mode->palette->size(); + byte paletteData[4*256]; + const uint paletteSize = driver->getMode()->palette->size(); for (uint i = 0; i < paletteSize; ++i) { - const PaletteEntry& c = (*driver->mode->palette)[i]; + const PaletteEntry& c = (*driver->getMode()->palette)[i]; paletteData[4*i+0] = c.r; paletteData[4*i+1] = c.g; paletteData[4*i+2] = c.b; @@ -217,18 +217,18 @@ static int _gfxop_install_pixmap(gfx_driver_t *driver, gfx_pixmap_t *pxm) { } g_system->setPalette(paletteData, 0, paletteSize); - driver->mode->palette->markClean(); + driver->getMode()->palette->markClean(); return GFX_OK; } -static int _gfxop_draw_pixmap(gfx_driver_t *driver, gfx_pixmap_t *pxm, int priority, int control, +static int _gfxop_draw_pixmap(GfxDriver *driver, gfx_pixmap_t *pxm, int priority, int control, rect_t src, rect_t dest, rect_t clip, int static_buf, gfx_pixmap_t *control_map, gfx_pixmap_t *priority_map) { int err; rect_t clipped_dest = gfx_rect(dest.x, dest.y, dest.width, dest.height); if (control >= 0 || priority >= 0) { - Common::Point original_pos = Common::Point(dest.x / driver->mode->xfact, dest.y / driver->mode->yfact); + Common::Point original_pos = Common::Point(dest.x / driver->getMode()->xfact, dest.y / driver->getMode()->yfact); if (control >= 0) _gfxop_draw_control(control_map, pxm, control, original_pos); @@ -251,10 +251,10 @@ static int _gfxop_draw_pixmap(gfx_driver_t *driver, gfx_pixmap_t *pxm, int prior if (err) return err; - DDIRTY(stderr, "\\-> Drawing to actual %d %d %d %d\n", clipped_dest.x / driver->mode->xfact, - clipped_dest.y / driver->mode->yfact, clipped_dest.width / driver->mode->xfact, clipped_dest.height / driver->mode->yfact); + DDIRTY(stderr, "\\-> Drawing to actual %d %d %d %d\n", clipped_dest.x / driver->getMode()->xfact, + clipped_dest.y / driver->getMode()->yfact, clipped_dest.width / driver->getMode()->xfact, clipped_dest.height / driver->getMode()->yfact); - err = driver->draw_pixmap(driver, pxm, priority, src, clipped_dest, static_buf ? GFX_BUFFER_STATIC : GFX_BUFFER_BACK); + err = driver->drawPixmap(pxm, priority, src, clipped_dest, static_buf ? GFX_BUFFER_STATIC : GFX_BUFFER_BACK); if (err) { GFXERROR("driver->draw_pixmap() returned err!\n"); @@ -266,8 +266,8 @@ static int _gfxop_draw_pixmap(gfx_driver_t *driver, gfx_pixmap_t *pxm, int prior static void _gfxop_full_pointer_refresh(GfxState *state) { Common::Point mousePoint = g_system->getEventManager()->getMousePos(); - state->pointer_pos.x = mousePoint.x / state->driver->mode->xfact; - state->pointer_pos.y = mousePoint.y / state->driver->mode->yfact; + state->pointer_pos.x = mousePoint.x / state->driver->getMode()->xfact; + state->pointer_pos.y = mousePoint.y / state->driver->getMode()->yfact; } static int _gfxop_buffer_propagate_box(GfxState *state, rect_t box, gfx_buffer_t buffer); @@ -298,7 +298,7 @@ gfx_pixmap_t *_gfxr_get_cel(GfxState *state, int nr, int *loop, int *cel, int pa static int _gfxop_update_box(GfxState *state, rect_t box) { int retval; - _gfxop_scale_rect(&box, state->driver->mode); + _gfxop_scale_rect(&box, state->driver->getMode()); if ((retval = _gfxop_buffer_propagate_box(state, box, GFX_BUFFER_FRONT))) { GFXERROR("Error occured while propagating box (%d,%d,%d,%d) to front buffer\n", box.x, box.y, box.width, box.height); @@ -430,15 +430,7 @@ int gfxop_init(int version, bool isVGA, GfxState *state, gfx_options_t *options, state->pic_port_bounds = gfx_rect(0, 10, 320, 190); state->_dirtyRects.clear(); - do { - if (!state->driver->init(state->driver, xfact, yfact, color_depth)) - initialized = 1; - else - color_depth++; - } while (!initialized && color_depth < 9 && !bpp); - - if (!initialized) - return GFX_FATAL; + state->driver = new GfxDriver(xfact, yfact, bpp); state->gfxResMan = new GfxResManager(version, isVGA, state->options, state->driver, resManager); @@ -471,7 +463,7 @@ int gfxop_exit(GfxState *state) { state->static_priority_map = NULL; } - state->driver->exit(state->driver); + delete state->driver; return GFX_OK; } @@ -532,8 +524,8 @@ int gfxop_set_clip_zone(GfxState *state, rect_t zone) { DDIRTY(stderr, "-- Setting clip zone %d %d %d %d\n", GFX_PRINT_RECT(zone)); - xfact = state->driver->mode->xfact; - yfact = state->driver->mode->yfact; + xfact = state->driver->getMode()->xfact; + yfact = state->driver->getMode()->yfact; if (zone.x < MIN_X) { zone.width -= (zone.x - MIN_X); @@ -582,7 +574,7 @@ int gfxop_set_color(GfxState *state, gfx_color_t *color, int r, int g, int b, in color->alpha = a; if (PALETTE_MODE) { - color->visual.parent_index = state->driver->mode->palette->findNearbyColor(r,g,b,true); + color->visual.parent_index = state->driver->getMode()->palette->findNearbyColor(r,g,b,true); } } @@ -606,12 +598,12 @@ int gfxop_set_system_color(GfxState *state, unsigned int index, gfx_color_t *col if (!PALETTE_MODE) return GFX_OK; - if (index >= state->driver->mode->palette->size()) { + if (index >= state->driver->getMode()->palette->size()) { GFXERROR("Attempt to set invalid color index %02x as system color\n", color->visual.parent_index); return GFX_ERROR; } - state->driver->mode->palette->makeSystemColor(index, color->visual); + state->driver->getMode()->palette->makeSystemColor(index, color->visual); return GFX_OK; } @@ -716,11 +708,11 @@ static void draw_line_to_control_map(GfxState *state, Common::Point start, Commo gfx_draw_line_pixmap_i(state->control_map, start, end, color.control); } -static int simulate_stippled_line_draw(gfx_driver_t *driver, int skipone, Common::Point start, Common::Point end, gfx_color_t color, gfx_line_mode_t line_mode) { +static int simulate_stippled_line_draw(GfxDriver *driver, int skipone, Common::Point start, Common::Point end, gfx_color_t color, gfx_line_mode_t line_mode) { // Draws a stippled line if this isn't supported by the driver (skipone is ignored ATM) int xl = end.x - start.x; int yl = end.y - start.y; - int stepwidth = (xl) ? driver->mode->xfact : driver->mode->yfact; + int stepwidth = (xl) ? driver->getMode()->xfact : driver->getMode()->yfact; int dbl_stepwidth = 2 * stepwidth; int linelength = (line_mode == GFX_LINE_MODE_FINE) ? stepwidth - 1 : 0; int16 *posvar; @@ -759,7 +751,7 @@ static int simulate_stippled_line_draw(gfx_driver_t *driver, int skipone, Common int retval; Common::Point nextpos = Common::Point(start.x + xl, start.y + yl); - if ((retval = driver->draw_line(driver, start, nextpos, color, line_mode, GFX_LINE_STYLE_NORMAL))) { + if ((retval = driver->drawLine(start, nextpos, color, line_mode, GFX_LINE_STYLE_NORMAL))) { GFXERROR("Failed to draw partial stippled line (%d,%d) -- (%d,%d)\n", start.x, start.y, nextpos.x, nextpos.y); return retval; } @@ -781,7 +773,7 @@ static int simulate_stippled_line_draw(gfx_driver_t *driver, int skipone, Common nextpos = Common::Point(start.x + xl, start.y + yl); - if ((retval = driver->draw_line(driver, start, nextpos, color, line_mode, GFX_LINE_STYLE_NORMAL))) { + if ((retval = driver->drawLine(start, nextpos, color, line_mode, GFX_LINE_STYLE_NORMAL))) { GFXERROR("Failed to draw partial stippled line (%d,%d) -- (%d,%d)\n", start.x, start.y, nextpos.x, nextpos.y); return retval; } @@ -809,7 +801,7 @@ static int _gfxop_draw_line_clipped(GfxState *state, Common::Point start, Common || start.y < state->clip_zone.y || end.x >= (state->clip_zone.x + state->clip_zone.width) || end.y >= (state->clip_zone.y + state->clip_zone.height)) - if (point_clip(&start, &end, state->clip_zone, state->driver->mode->xfact - 1, state->driver->mode->yfact - 1)) + if (point_clip(&start, &end, state->clip_zone, state->driver->getMode()->xfact - 1, state->driver->getMode()->yfact - 1)) return GFX_OK; // Clipped off if (line_style == GFX_LINE_STYLE_STIPPLED) { @@ -820,7 +812,7 @@ static int _gfxop_draw_line_clipped(GfxState *state, Common::Point start, Common return simulate_stippled_line_draw(state->driver, skipone, start, end, color, line_mode); } - if ((retval = state->driver->draw_line(state->driver, start, end, color, line_mode, line_style))) { + if ((retval = state->driver->drawLine(start, end, color, line_mode, line_style))) { GFXERROR("Failed to draw line (%d,%d) -- (%d,%d)\n", start.x, start.y, end.x, end.y); return retval; } @@ -835,13 +827,13 @@ int gfxop_draw_line(GfxState *state, Common::Point start, Common::Point end, BASIC_CHECKS(GFX_FATAL); _gfxop_add_dirty_x(state, gfx_rect(start.x, start.y, end.x - start.x, end.y - start.y)); - xfact = state->driver->mode->xfact; - yfact = state->driver->mode->yfact; + xfact = state->driver->getMode()->xfact; + yfact = state->driver->getMode()->yfact; draw_line_to_control_map(state, start, end, color); - _gfxop_scale_point(&start, state->driver->mode); - _gfxop_scale_point(&end, state->driver->mode); + _gfxop_scale_point(&start, state->driver->getMode()); + _gfxop_scale_point(&end, state->driver->getMode()); if (line_mode == GFX_LINE_MODE_FINE) { start.x += xfact >> 1; @@ -866,8 +858,8 @@ int gfxop_draw_rectangle(GfxState *state, rect_t rect, gfx_color_t color, gfx_li BASIC_CHECKS(GFX_FATAL); _gfxop_full_pointer_refresh(state); - xfact = state->driver->mode->xfact; - yfact = state->driver->mode->yfact; + xfact = state->driver->getMode()->xfact; + yfact = state->driver->getMode()->yfact; int offset = line_mode == GFX_LINE_MODE_FINE ? 1 : 0; x = rect.x * xfact + (xfact - 1) * offset; @@ -908,7 +900,7 @@ int gfxop_draw_rectangle(GfxState *state, rect_t rect, gfx_color_t color, gfx_li #define COLOR_MIX(type, dist) ((color1.type * dist) + (color2.type * (1.0 - dist))) int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t color2, gfx_box_shade_t shade_type) { - gfx_driver_t *drv = state->driver; + GfxDriver *drv = state->driver; int reverse = 0; // switch color1 and color2 float mod_offset = 0.0, mod_breadth = 1.0; // 0.0 to 1.0: Color adjustment gfx_rectangle_fill_t driver_shade_type; @@ -930,7 +922,7 @@ int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t gfx_draw_box_pixmap_i(state->control_map, new_box, color1.control); } - _gfxop_scale_rect(&box, state->driver->mode); + _gfxop_scale_rect(&box, state->driver->getMode()); if (!(color1.mask & (GFX_MASK_VISUAL | GFX_MASK_PRIORITY))) return GFX_OK; @@ -981,7 +973,7 @@ int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t color1.control = 0; if (color1.visual.parent_index == GFX_COLOR_INDEX_UNMAPPED) gfxop_set_color(state, &color1, color1); - return drv->draw_filled_rect(drv, new_box, color1, color1, GFX_SHADE_FLAT); + return drv->drawFilledRect(new_box, color1, color1, GFX_SHADE_FLAT); } else { if (PALETTE_MODE) { GFXWARN("Attempting to draw shaded box in palette mode!\n"); @@ -997,22 +989,22 @@ int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t draw_color1.priority = draw_color2.priority = color1.priority; if (draw_color1.mask & GFX_MASK_VISUAL) { - draw_color1.visual.r = (uint8) COLOR_MIX(visual.r, mod_offset); - draw_color1.visual.g = (uint8) COLOR_MIX(visual.g, mod_offset); - draw_color1.visual.b = (uint8) COLOR_MIX(visual.b, mod_offset); - draw_color1.alpha = (uint8) COLOR_MIX(alpha, mod_offset); + draw_color1.visual.r = (byte) COLOR_MIX(visual.r, mod_offset); + draw_color1.visual.g = (byte) COLOR_MIX(visual.g, mod_offset); + draw_color1.visual.b = (byte) COLOR_MIX(visual.b, mod_offset); + draw_color1.alpha = (byte) COLOR_MIX(alpha, mod_offset); mod_offset += mod_breadth; - draw_color2.visual.r = (uint8) COLOR_MIX(visual.r, mod_offset); - draw_color2.visual.g = (uint8) COLOR_MIX(visual.g, mod_offset); - draw_color2.visual.b = (uint8) COLOR_MIX(visual.b, mod_offset); - draw_color2.alpha = (uint8) COLOR_MIX(alpha, mod_offset); + draw_color2.visual.r = (byte) COLOR_MIX(visual.r, mod_offset); + draw_color2.visual.g = (byte) COLOR_MIX(visual.g, mod_offset); + draw_color2.visual.b = (byte) COLOR_MIX(visual.b, mod_offset); + draw_color2.alpha = (byte) COLOR_MIX(alpha, mod_offset); } if (reverse) - return drv->draw_filled_rect(drv, new_box, draw_color2, draw_color1, driver_shade_type); + return drv->drawFilledRect(new_box, draw_color2, draw_color1, driver_shade_type); else - return drv->draw_filled_rect(drv, new_box, draw_color1, draw_color2, driver_shade_type); + return drv->drawFilledRect(new_box, draw_color1, draw_color2, driver_shade_type); } } #undef COLOR_MIX @@ -1024,10 +1016,10 @@ int gfxop_fill_box(GfxState *state, rect_t box, gfx_color_t color) { static int _gfxop_buffer_propagate_box(GfxState *state, rect_t box, gfx_buffer_t buffer) { int err; - if (_gfxop_clip(&box, gfx_rect(0, 0, 320 * state->driver->mode->xfact, 200 * state->driver->mode->yfact))) + if (_gfxop_clip(&box, gfx_rect(0, 0, 320 * state->driver->getMode()->xfact, 200 * state->driver->getMode()->yfact))) return GFX_OK; - if ((err = state->driver->update(state->driver, box, Common::Point(box.x, box.y), buffer))) { + if ((err = state->driver->update(box, Common::Point(box.x, box.y), buffer))) { GFXERROR("Error occured while updating region (%d,%d,%d,%d) in buffer %d\n", box.x, box.y, box.width, box.height, buffer); return err; } @@ -1049,7 +1041,7 @@ int gfxop_clear_box(GfxState *state, rect_t box) { gfx_copy_pixmap_box_i(state->priority_map, state->static_priority_map, box); #endif - _gfxop_scale_rect(&box, state->driver->mode); + _gfxop_scale_rect(&box, state->driver->getMode()); return _gfxop_buffer_propagate_box(state, box, GFX_BUFFER_BACK); } @@ -1094,7 +1086,7 @@ int gfxop_update(GfxState *state) { if (state->fullscreen_override) { // We've been asked to re-draw the active full-screen image, essentially. rect_t rect = gfx_rect(0, 0, 320, 200); - gfx_xlate_pixmap(state->fullscreen_override, state->driver->mode, GFX_XLATE_FILTER_NONE); + gfx_xlate_pixmap(state->fullscreen_override, state->driver->getMode(), GFX_XLATE_FILTER_NONE); gfxop_draw_pixmap(state, state->fullscreen_override, rect, Common::Point(0, 0)); retval |= _gfxop_update_box(state, rect); } @@ -1174,8 +1166,8 @@ static int _gfxop_set_pointer(GfxState *state, gfx_pixmap_t *pxm, Common::Point // from this pxm at that point. (An alternative might be to ensure the // cursor only uses colours in the static part of the palette?) if (pxm && pxm->palette) - pxm->palette->mergeInto(state->driver->mode->palette); - state->driver->set_pointer(state->driver, pxm, hotspot); + pxm->palette->mergeInto(state->driver->getMode()->palette); + state->driver->setPointer(pxm, hotspot); return GFX_OK; } @@ -1237,7 +1229,7 @@ int gfxop_set_pointer_position(GfxState *state, Common::Point pos) { return 0; // Not fatal } - g_system->warpMouse(pos.x * state->driver->mode->xfact, pos.y * state->driver->mode->yfact); + g_system->warpMouse(pos.x * state->driver->getMode()->xfact, pos.y * state->driver->getMode()->yfact); _gfxop_full_pointer_refresh(state); return 0; @@ -1352,7 +1344,7 @@ static int _gfxop_numlockify(int c) { } } -static sci_event_t scummvm_get_event(gfx_driver_t *drv) { +static sci_event_t scummvm_get_event(GfxDriver *drv) { static int _modifierStates = 0; // FIXME: Avoid non-const global vars sci_event_t input = { SCI_EVT_NONE, 0, 0, 0 }; @@ -1726,8 +1718,8 @@ static int _gfxop_draw_cel_buffer(GfxState *state, int nr, int loop, int cel, Co old_x = pos.x -= pxm->xoffset; old_y = pos.y -= pxm->yoffset; - pos.x *= state->driver->mode->xfact; - pos.y *= state->driver->mode->yfact; + pos.x *= state->driver->getMode()->xfact; + pos.y *= state->driver->getMode()->yfact; if (!static_buf) _gfxop_add_dirty(state, gfx_rect(old_x, old_y, pxm->index_width, pxm->index_height)); @@ -1746,7 +1738,7 @@ int gfxop_draw_cel_static(GfxState *state, int nr, int loop, int cel, Common::Po rect_t oldclip = state->clip_zone; state->clip_zone = gfx_rect_fullscreen; - _gfxop_scale_rect(&(state->clip_zone), state->driver->mode); + _gfxop_scale_rect(&(state->clip_zone), state->driver->getMode()); retval = gfxop_draw_cel_static_clipped(state, nr, loop, cel, pos, color, palette); // Except that the area it's clipped against is... unusual ;-) state->clip_zone = oldclip; @@ -1769,14 +1761,14 @@ static int _gfxop_set_pic(GfxState *state) { // FIXME: The _gfxop_install_pixmap call below updates the OSystem palette. // This is too soon, since it causes brief palette corruption until the // screen is updated too. (Possibly related: EngineState::pic_not_valid .) - state->pic->visual_map->palette->forceInto(state->driver->mode->palette); + state->pic->visual_map->palette->forceInto(state->driver->getMode()->palette); _gfxop_install_pixmap(state->driver, state->pic->visual_map); #ifdef CUSTOM_GRAPHICS_OPTIONS if (state->options->pic0_unscaled) #endif - state->pic->priority_map = gfx_pixmap_scale_index_data(state->pic->priority_map, state->driver->mode); - return state->driver->set_static_buffer(state->driver, state->pic->visual_map, state->pic->priority_map); + state->pic->priority_map = gfx_pixmap_scale_index_data(state->pic->priority_map, state->driver->getMode()); + return state->driver->setStaticBuffer(state->pic->visual_map, state->pic->priority_map); } int *gfxop_get_pic_metainfo(GfxState *state) { @@ -1791,7 +1783,7 @@ int gfxop_new_pic(GfxState *state, int nr, int flags, int default_palette) { state->palette_nr = default_palette; state->pic = state->gfxResMan->getPic(nr, GFX_MASK_VISUAL, flags, default_palette, true); - if (state->driver->mode->xfact == 1 && state->driver->mode->yfact == 1) { + if (state->driver->getMode()->xfact == 1 && state->driver->getMode()->yfact == 1) { state->pic_unscaled = state->pic; } else { state->pic = state->gfxResMan->getPic(nr, GFX_MASK_VISUAL, flags, default_palette, false); @@ -2003,9 +1995,9 @@ int gfxop_draw_text(GfxState *state, TextHandle *handle, rect_t zone) { return GFX_OK; } - _gfxop_scale_rect(&zone, state->driver->mode); + _gfxop_scale_rect(&zone, state->driver->getMode()); - line_height = handle->line_height * state->driver->mode->yfact; + line_height = handle->line_height * state->driver->getMode()->yfact; pos.y = zone.y; @@ -2033,9 +2025,9 @@ int gfxop_draw_text(GfxState *state, TextHandle *handle, rect_t zone) { if (!pxm->data) { #ifdef CUSTOM_GRAPHICS_OPTIONS - gfx_xlate_pixmap(pxm, state->driver->mode, state->options->text_xlate_filter); + gfx_xlate_pixmap(pxm, state->driver->getMode(), state->options->text_xlate_filter); #else - gfx_xlate_pixmap(pxm, state->driver->mode, GFX_XLATE_FILTER_NONE); + gfx_xlate_pixmap(pxm, state->driver->getMode(), GFX_XLATE_FILTER_NONE); #endif } if (!pxm) { @@ -2082,7 +2074,7 @@ gfx_pixmap_t *gfxop_grab_pixmap(GfxState *state, rect_t area) { BASIC_CHECKS(NULL); _gfxop_full_pointer_refresh(state); - _gfxop_scale_rect(&area, state->driver->mode); + _gfxop_scale_rect(&area, state->driver->getMode()); if (_gfxop_grab_pixmap(state, &pixmap, area.x, area.y, area.width, area.height, 0, &resultzone)) return NULL; // area CUT the visual screen had a null or negative size @@ -2109,11 +2101,11 @@ int gfxop_draw_pixmap(GfxState *state, gfx_pixmap_t *pxm, rect_t zone, Common::P return GFX_ERROR; } - _gfxop_scale_rect(&zone, state->driver->mode); - _gfxop_scale_rect(&target, state->driver->mode); + _gfxop_scale_rect(&zone, state->driver->getMode()); + _gfxop_scale_rect(&target, state->driver->getMode()); - return _gfxop_draw_pixmap(state->driver, pxm, -1, -1, zone, target, gfx_rect(0, 0, 320*state->driver->mode->xfact, - 200*state->driver->mode->yfact), 0, NULL, NULL); + return _gfxop_draw_pixmap(state->driver, pxm, -1, -1, zone, target, gfx_rect(0, 0, 320*state->driver->getMode()->xfact, + 200*state->driver->getMode()->yfact), 0, NULL, NULL); } int gfxop_free_pixmap(GfxState *state, gfx_pixmap_t *pxm) { diff --git a/engines/sci/gfx/operations.h b/engines/sci/gfx/operations.h index 88af32c624..d559d3b6d2 100644 --- a/engines/sci/gfx/operations.h +++ b/engines/sci/gfx/operations.h @@ -98,7 +98,7 @@ struct GfxState { rect_t clip_zone_unscaled; /* The current UNSCALED clipping zone */ rect_t clip_zone; /* The current SCALED clipping zone; a cached scaled version of clip_zone_unscaled */ - gfx_driver_t *driver; + GfxDriver *driver; int visible_map; diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 24b4d9beed..01be4c5ba6 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -108,6 +108,8 @@ Resource::Resource() { status = kResStatusNoMalloc; lockers = 0; source = NULL; + header = NULL; + headerSize = 0; } Resource::~Resource() { @@ -141,20 +143,20 @@ ResourceSource *ResourceManager::addExternalMap(const char *file_name) { return newsrc; } -ResourceSource *ResourceManager::addVolume(ResourceSource *map, const char *filename, int number, int extended_addressing) { +ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const char *filename, int number) { ResourceSource *newsrc = new ResourceSource(); // Add the new source to the SLL of sources newsrc->next = _sources; _sources = newsrc; - newsrc->source_type = kSourceVolume; + newsrc->source_type = type; newsrc->scanned = false; newsrc->location_name = filename; newsrc->volume_number = number; newsrc->associated_map = map; - return 0; + return newsrc; } ResourceSource *ResourceManager::addPatchDir(const char *dirname) { @@ -175,8 +177,8 @@ ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { ResourceSource *seeker = _sources; while (seeker) { - if (seeker->source_type == kSourceVolume && seeker->associated_map == map && - seeker->volume_number == volume_nr) + if ((seeker->source_type == kSourceVolume || seeker->source_type == kSourceAudioVolume) + && seeker->associated_map == map && seeker->volume_number == volume_nr) return seeker; seeker = seeker->next; } @@ -186,6 +188,34 @@ ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { // Resource manager constructors and operations +bool ResourceManager::loadPatch(Resource *res, Common::File &file) { + // We assume that the resource type matches res->type + file.seek(res->file_offset + 2, SEEK_SET); + + res->data = new byte[res->size]; + + if (res->headerSize > 0) + res->header = new byte[res->headerSize]; + + if ((res->data == NULL) || ((res->headerSize > 0) && (res->header == NULL))) { + error("Can't allocate %d bytes needed for loading %s.%i", res->size + res->headerSize, resourceTypeNames[res->type], res->number); + } + + unsigned int really_read; + if (res->headerSize > 0) { + really_read = file.read(res->header, res->headerSize); + if (really_read != res->headerSize) + error("Read %d bytes from %s.%i but expected %d", really_read, resourceTypeNames[res->type], res->number, res->headerSize); + } + + really_read = file.read(res->data, res->size); + if (really_read != res->size) + error("Read %d bytes from %s.%i but expected %d", really_read, resourceTypeNames[res->type], res->number, res->size); + + res->status = kResStatusAllocated; + return true; +} + bool ResourceManager::loadFromPatchFile(Resource *res) { Common::File file; const char *filename = res->source->location_name.c_str(); @@ -194,19 +224,43 @@ bool ResourceManager::loadFromPatchFile(Resource *res) { res->unalloc(); return false; } - res->data = new byte[res->size]; - if (res->data == NULL) { - error("Can't allocate %d bytes needed for loading %s!", res->size, filename); + return loadPatch(res, file); +} + +bool ResourceManager::loadFromAudioVolume(Resource *res) { + Common::File file; + const char *filename = res->source->location_name.c_str(); + if (file.open(filename) == false) { + warning("Failed to open audio volume %s", filename); + res->unalloc(); + return false; } file.seek(res->file_offset, SEEK_SET); - unsigned int really_read = file.read(res->data, res->size); - if (really_read != res->size) { - error("Read %d bytes from %s but expected %d!", really_read, filename, res->size); + + int type = file.readByte() & 0x7f; + if (type != res->type) { + warning("Resource type mismatch loading %s.%i from %s", resourceTypeNames[res->type], res->number, filename); + res->unalloc(); + return false; } - res->status = kResStatusAllocated; - return true; + + res->headerSize = file.readByte(); + + if (type == kResourceTypeAudio) { + if (res->headerSize != 11 && res->headerSize != 12) { + warning("Unsupported audio header"); + res->unalloc(); + return false; + } + + // Load sample size + file.seek(7, SEEK_CUR); + res->size = file.readUint32LE(); + } + + return loadPatch(res, file); } Common::File *ResourceManager::getVolumeFile(const char *filename) { @@ -247,6 +301,8 @@ void ResourceManager::loadResource(Resource *res) { if (res->source->source_type == kSourcePatch && loadFromPatchFile(res)) return; + if (res->source->source_type == kSourceAudioVolume && loadFromAudioVolume(res)) + return; // Either loading from volume or patch loading failed file = getVolumeFile(res->source->location_name.c_str()); if (!file) { @@ -355,12 +411,25 @@ int ResourceManager::addAppropriateSources() { const char *dot = strrchr(name.c_str(), '.'); int number = atoi(dot + 1); - addVolume(map, name.c_str(), number, 0); + addSource(map, kSourceVolume, name.c_str(), number); } - addPatchDir(""); + addPatchDir("."); // TODO: add RESOURCE.AUD and RESOURCE.SFX for SCI1.1 games if (Common::File::exists("MESSAGE.MAP")) - addVolume(addExternalMap("MESSAGE.MAP"), "RESOURCE.MSG",0 ,0); + addSource(addExternalMap("MESSAGE.MAP"), kSourceVolume, "RESOURCE.MSG", 0); + return 1; +} + +int ResourceManager::addInternalSources() { + if (testResource(kResourceTypeMap, 65535)) { + ResourceSource *src = addSource(NULL, kSourceIntMap, "65535.MAP", 65535); + + if (Common::File::exists("RESOURCE.SFX")) + addSource(src, kSourceAudioVolume, "RESOURCE.SFX", 0); + else if (Common::File::exists("RESOURCE.AUD")) + addSource(src, kSourceAudioVolume, "RESOURCE.AUD", 0); + } + return 1; } @@ -395,6 +464,10 @@ int ResourceManager::scanNewSources(ResourceSource *source) { resource_error = 0; } break; + case kSourceIntMap: + if (source->volume_number == 65535) + resource_error = readMap65535(source); + break; default: break; } @@ -431,6 +504,9 @@ ResourceManager::ResourceManager(int version, int maxMemory) { debug("Using volume version %d %s", _volVersion, sci_version_types[_volVersion]); scanNewSources(_sources); + addInternalSources(); + scanNewSources(_sources); + if (version == SCI_VERSION_AUTODETECT) switch (_mapVersion) { case SCI_VERSION_0: @@ -819,7 +895,15 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, } // Prepare destination, if neccessary if (_resMap.contains(resId) == false) { - newrsc = new Resource; + // FIXME: code duplication + switch (restype) { + case kResourceTypeSync: + newrsc = new ResourceSync; + break; + default: + newrsc = new Resource; + break; + } _resMap.setVal(resId, newrsc); } else newrsc = _resMap.getVal(resId); @@ -830,7 +914,8 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, newrsc->type = restype; newrsc->source = source; newrsc->size = fsize - patch_data_offset - 2; - newrsc->file_offset = 2 + patch_data_offset; + newrsc->headerSize = patch_data_offset; + newrsc->file_offset = 0; debug("Patching %s - OK", source->location_name.c_str()); } @@ -1006,6 +1091,73 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { return 0; } +int ResourceManager::readMap65535(ResourceSource *map) { + // Early SCI1.1 65535.MAP structure (uses RESOURCE.AUD): + // ========= + // 6-byte entries: + // w nEntry + // dw offset + + // Late SCI1.1 65535.MAP structure (uses RESOURCE.SFX): + // ========= + // 5-byte entries: + // w nEntry + // tb offset (cumulative) + + Resource *mapRes = findResource(kResourceTypeMap, map->volume_number, false); + + if (!mapRes) { + warning("Failed to open 65535.MAP"); + return SCI_ERROR_RESMAP_NOT_FOUND; + } + + ResourceSource *src = getVolume(map, 0); + + if (!src) { + warning("No audio resource files found"); + return SCI_ERROR_NO_RESOURCE_FILES_FOUND; + } + + bool isEarly = true; + + byte *ptr = mapRes->data; + // Heuristic to detect late SCI1.1 map format + if ((mapRes->size >= 6) && (ptr[mapRes->size - 6] != 0xff)) + isEarly = false; + + uint32 offset = 0; + + while (ptr < mapRes->data + mapRes->size) { + uint16 n = READ_LE_UINT16(ptr); + ptr += 2; + + if (n == 0xffff) + break; + + if (isEarly) { + offset = READ_LE_UINT32(ptr); + ptr += 4; + } else { + offset += READ_LE_UINT24(ptr); + ptr += 3; + } + + uint32 resId = RESOURCE_HASH(kResourceTypeAudio, n); + // Adding new resource only if it does not exist + if (_resMap.contains(resId) == false) { + Resource *res = new Resource; + _resMap.setVal(resId, res); + res->type = kResourceTypeAudio; + res->number = n; + res->id = resId; + res->source = src; + res->file_offset = offset; + } + } + + return 0; +} + int ResourceManager::readResourceInfo(Resource *res, Common::File *file, uint32&szPacked, ResourceCompression &compression) { // SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes @@ -1361,15 +1513,6 @@ bool AudioResource::findAudEntrySCI11Early(uint32 audioNumber, uint32 &offset, b } bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 &offset, bool getSync, uint32 *size) { - // 65535.MAP structure: - // ========= - // 6 byte entries: - // w nEntry - // dw offset - - uint32 n; - offset = 0; - if (_audioMapSCI11 && _audioMapSCI11->number != volume) { _resMgr->unlockResource(_audioMapSCI11, _audioMapSCI11->number, kResourceTypeMap); _audioMapSCI11 = 0; @@ -1381,32 +1524,19 @@ bool AudioResource::findAudEntrySCI11(uint32 audioNumber, uint32 volume, uint32 byte *ptr = _audioMapSCI11->data; - if (volume == 65535) { - while (ptr < _audioMapSCI11->data + _audioMapSCI11->size) { - n = READ_LE_UINT16(ptr); - ptr += 2; - - if (n == 0xffff) - break; - - offset = READ_LE_UINT32(ptr); - ptr += 4; + if (volume == 65535) + return false; - if (n == audioNumber) - return true; - } - } else { - // In early SCI1.1 the map is terminated with 10x 0xff, in late SCI1.1 - // with 11x 0xff. If we look at the 11th last byte in an early SCI1.1 - // map, this will be the high byte of the Sync length of the last entry. - // As Sync resources are relative small, we should never encounter a - // Sync with a size of 0xffnn. As such, the following heuristic should be - // sufficient to tell these map formats apart. - if (_audioMapSCI11->size >= 11 && (ptr[_audioMapSCI11->size - 11] == 0xff)) - return findAudEntrySCI11Late(audioNumber, offset, getSync, size); - else { - return findAudEntrySCI11Early(audioNumber, offset, getSync, size); - } + // In early SCI1.1 the map is terminated with 10x 0xff, in late SCI1.1 + // with 11x 0xff. If we look at the 11th last byte in an early SCI1.1 + // map, this will be the high byte of the Sync length of the last entry. + // As Sync resources are relative small, we should never encounter a + // Sync with a size of 0xffnn. As such, the following heuristic should be + // sufficient to tell these map formats apart. + if (_audioMapSCI11->size >= 11 && (ptr[_audioMapSCI11->size - 11] == 0xff)) + return findAudEntrySCI11Late(audioNumber, offset, getSync, size); + else { + return findAudEntrySCI11Early(audioNumber, offset, getSync, size); } return false; @@ -1470,55 +1600,43 @@ static void deDPCM8(byte *soundBuf, Common::SeekableReadStream &audioStream, uin // Sierra SOL audio file reader // Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio -byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 *size, uint16 *audioRate, byte *flags) { - byte audioFlags; - byte type = audioStream->readByte(); - - if (type != 0x8D) { - warning("SOL audio type should be 0x8D, but it's %d", type); - return NULL; - } - - int headerSize = audioStream->readByte(); - +static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags) { if (headerSize != 11 && headerSize != 12) { warning("SOL audio header of size %i not supported", headerSize); - return NULL; + return false; } audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes) - *audioRate = audioStream->readUint16LE(); + audioRate = audioStream->readUint16LE(); audioFlags = audioStream->readByte(); + size = audioStream->readUint32LE(); + return true; +} + +static byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 &size, byte audioFlags, byte &flags) { + byte *buffer; + // Convert the SOL stream flags to our own format - *flags = 0; + flags = 0; if (audioFlags & kSolFlag16Bit) - *flags |= Audio::Mixer::FLAG_16BITS; + flags |= Audio::Mixer::FLAG_16BITS; if (!(audioFlags & kSolFlagIsSigned)) - *flags |= Audio::Mixer::FLAG_UNSIGNED; - - *size = audioStream->readUint32LE(); - - if (headerSize == 12) { - // Unknown byte - audioStream->readByte(); - } - - byte *buffer; + flags |= Audio::Mixer::FLAG_UNSIGNED; if (audioFlags & kSolFlagCompressed) { - buffer = new byte[*size * 2]; + buffer = new byte[size * 2]; if (audioFlags & kSolFlag16Bit) - deDPCM16(buffer, *audioStream, *size); + deDPCM16(buffer, *audioStream, size); else - deDPCM8(buffer, *audioStream, *size); + deDPCM8(buffer, *audioStream, size); - *size *= 2; + size *= 2; } else { // We assume that the sound data is raw PCM - buffer = new byte[*size]; - audioStream->read(buffer, *size); + buffer = (byte *)malloc(size); + audioStream->read(buffer, size); } return buffer; @@ -1533,96 +1651,110 @@ Audio::AudioStream* AudioResource::getAudioStream(uint32 audioNumber, uint32 vol char filename[40]; byte flags = 0; -#if 0 - // TODO: this is disabled for now, as the resource manager returns - // only the data chunk of the audio file, and not its headers + // Try to load from resource manager + if (volume == 65535) { + Sci::Resource* audioRes = _resMgr->findResource(kResourceTypeAudio, audioNumber, false); - // Try to load from an external patch file first - Sci::Resource* audioRes = _resMgr->findResource(kResourceTypeAudio, audioNumber, 1); - if (audioRes) { if (_sciVersion < SCI_VERSION_1_1) { size = audioRes->size; data = audioRes->data; } else { - Common::MemoryReadStream *memStream = - new Common::MemoryReadStream(audioRes->data, audioRes->size, true); - data = readSOLAudio(memStream, &size, &_audioRate, &flags); - delete memStream; + byte audioFlags; + + Common::MemoryReadStream *headerStream = + new Common::MemoryReadStream(audioRes->header, audioRes->headerSize, false); + + if (readSOLHeader(headerStream, audioRes->headerSize, size, _audioRate, audioFlags)) { + Common::MemoryReadStream *dataStream = + new Common::MemoryReadStream(audioRes->data, audioRes->size, false); + data = readSOLAudio(dataStream, size, audioFlags, flags); + delete dataStream; + } + delete headerStream; } if (data) { - *sampleLen = size * 60 / _audioRate; - return Audio::makeLinearInputStream(data, size, _audioRate, + audioStream = Audio::makeLinearInputStream(data, size, _audioRate, flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0); } - } -#endif - - // Patch file not found, load it from the audio file - if (_sciVersion < SCI_VERSION_1_1) { - byte sci1Volume; - found = findAudEntrySCI1(audioNumber, sci1Volume, offset, size); - sprintf(filename, "AUDIO%03d.%03d", _lang, sci1Volume); - flags |= Audio::Mixer::FLAG_UNSIGNED; } else { - found = findAudEntrySCI11(audioNumber, volume, offset); - strcpy(filename, "RESOURCE.AUD"); - // TODO: resource.sfx. Perhaps its files are read with map 65535? - /* - if (Common::File::exists("RESOURCE.SFX") && volume == 65535) { - strcpy(filename, "RESOURCE.SFX"); + // Load it from the audio file + if (_sciVersion < SCI_VERSION_1_1) { + byte sci1Volume; + found = findAudEntrySCI1(audioNumber, sci1Volume, offset, size); + sprintf(filename, "AUDIO%03d.%03d", _lang, sci1Volume); + flags |= Audio::Mixer::FLAG_UNSIGNED; } else { + found = findAudEntrySCI11(audioNumber, volume, offset); strcpy(filename, "RESOURCE.AUD"); } - */ - } - if (found) { -#if 0 - // TODO: This tries to load directly from the KQ5CD audio file with MP3/OGG/FLAC - // compression. Once we got a tool to compress this file AND update the map file - // at the same time, we can use this code to play compressed audio. - if (_sciVersion < SCI_VERSION_1_1) { - uint32 start = offset * 1000 / _audioRate; - uint32 duration = size * 1000 / _audioRate; + if (found) { + #if 0 + // TODO: This tries to load directly from the KQ5CD audio file with MP3/OGG/FLAC + // compression. Once we got a tool to compress this file AND update the map file + // at the same time, we can use this code to play compressed audio. + if (_sciVersion < SCI_VERSION_1_1) { + uint32 start = offset * 1000 / _audioRate; + uint32 duration = size * 1000 / _audioRate; - // Try to load compressed - audioStream = Audio::AudioStream::openStreamFile(filename, start, duration); - } -#endif - - if (!audioStream) { - // Compressed file load failed, try to load original raw data - Common::File* audioFile = new Common::File(); - if (audioFile->open(filename)) { - audioFile->seek(offset); - - if (_sciVersion < SCI_VERSION_1_1) { - data = (byte *)malloc(size); - audioFile->read(data, size); - } else { - data = readSOLAudio(audioFile, &size, &_audioRate, &flags); - if (!data) - return NULL; + // Try to load compressed + audioStream = Audio::AudioStream::openStreamFile(filename, start, duration); + } + #endif + + if (!audioStream) { + // Compressed file load failed, try to load original raw data + Common::File* audioFile = new Common::File(); + if (audioFile->open(filename)) { + audioFile->seek(offset); + + if (_sciVersion < SCI_VERSION_1_1) { + data = (byte *)malloc(size); + audioFile->read(data, size); + } else { + byte type = audioFile->readByte() & 0x7f; + byte audioFlags; + + if (type != kResourceTypeAudio) { + warning("Resource type mismatch"); + delete audioFile; + return NULL; + } + + byte headerSize = audioFile->readByte(); + + if (readSOLHeader(audioFile, headerSize, size, _audioRate, audioFlags)) + data = readSOLAudio(audioFile, size, audioFlags, flags); + + if (!data) { + delete audioFile; + return NULL; + } + } + + audioFile->close(); + + if (data) { + audioStream = Audio::makeLinearInputStream(data, size, _audioRate, + flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0); + } } - audioFile->close(); delete audioFile; - - if (data) { - audioStream = Audio::makeLinearInputStream(data, size, _audioRate, - flags | Audio::Mixer::FLAG_AUTOFREE, 0, 0); - } } + } else { + warning("Failed to find audio entry (%i, %i, %i, %i, %i)", volume, (audioNumber >> 24) & 0xff, + (audioNumber >> 16) & 0xff, (audioNumber >> 8) & 0xff, audioNumber & 0xff); } + } + if (audioStream) { *sampleLen = (flags & Audio::Mixer::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate; - } else { - warning("Failed to find audio entry (%i, %i, %i, %i, %i)", volume, (audioNumber >> 24) & 0xff, - (audioNumber >> 16) & 0xff, (audioNumber >> 8) & 0xff, audioNumber & 0xff); + return audioStream; } - return audioStream; + return NULL; } } // End of namespace Sci diff --git a/engines/sci/resource.h b/engines/sci/resource.h index eade4acbd0..219979b383 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -76,6 +76,7 @@ enum ResSourceType { kSourceVolume = 2, kSourceExtMap = 3, kSourceIntMap = 4, + kSourceAudioVolume = 5, kSourceMask = 127 }; @@ -156,6 +157,8 @@ public: ResourceType type; uint32 id; //!< contains number and type. uint32 size; + byte *header; + uint32 headerSize; protected: uint32 file_offset; /**< Offset in file */ ResourceStatus status; @@ -232,21 +235,27 @@ protected: ResourceSource *getVolume(ResourceSource *map, int volume_nr); /** - * Add a volume to the resource manager's list of sources. - * @param map The map associated with this volume - * @param filename The name of the volume to add - * @param extended_addressing 1 if this volume uses extended addressing, - * 0 otherwise. + * Adds a source to the resource manager's list of sources. + * @param map The map associated with this source + * @param type The source type + * @param filename The name of the source to add * @return A pointer to the added source structure, or NULL if an error occurred. */ - ResourceSource *addVolume(ResourceSource *map, const char *filename, - int number, int extended_addressing); + ResourceSource *addSource(ResourceSource *map, ResSourceType type, const char *filename, + int number); /** * Add an external (i.e., separate file) map resource to the resource manager's list of sources. * @param file_name The name of the volume to add * @return A pointer to the added source structure, or NULL if an error occurred. */ ResourceSource *addExternalMap(const char *file_name); + /** + * Add an internal (i.e., resource) map to the resource manager's list of sources. + * @param name The name of the resource to add + * @param resNr The map resource number + * @return A pointer to the added source structure, or NULL if an error occurred. + */ + ResourceSource *addInternalMap(const char *name, int resNr); /** * Scans newly registered resource sources for resources, earliest addition first. @@ -256,11 +265,14 @@ protected: */ int scanNewSources(ResourceSource *source); int addAppropriateSources(); + int addInternalSources(); void freeResourceSources(ResourceSource *rss); Common::File *getVolumeFile(const char *filename); void loadResource(Resource *res); + bool loadPatch(Resource *res, Common::File &file); bool loadFromPatchFile(Resource *res); + bool loadFromAudioVolume(Resource *res); void freeOldResources(int last_invulnerable); int decompress(Resource *res, Common::File *file); int readResourceInfo(Resource *res, Common::File *file, uint32&szPacked, ResourceCompression &compression); @@ -281,6 +293,12 @@ protected: */ int readResourceMapSCI1(ResourceSource *map); + /** + * Reads the SCI1.1 65535.map resource + * @return 0 on success, an SCI_ERROR_* code otherwise + */ + int readMap65535(ResourceSource *map); + /**--- Patch management functions ---*/ /** diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 8083ddad73..f58d729bf6 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -40,7 +40,7 @@ namespace Sci { -extern gfx_driver_t gfx_driver_scummvm; +class GfxDriver; const char *versionNames[9] = { "Autodetected", @@ -194,10 +194,9 @@ Common::Error SciEngine::run() { script_set_gamestate_save_dir(_gamestate, "/"); GfxState gfx_state; - gfx_state.driver = &gfx_driver_scummvm; + _gamestate->gfx_state = &gfx_state; _gamestate->animation_granularity = 4; - _gamestate->gfx_state = &gfx_state; // Default config: gfx_options_t gfx_options; diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index 60c9837bb4..abdc5b4e91 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -355,7 +355,7 @@ static const GameSettings gameVariantsTable[] = { // Uses bink in external files for logos {"Baseball2003", 0, 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK}, - {"basketball", 0, 0, GID_HEGAME, 6, 100, MDT_NONE, GF_USE_KEY| GF_16BIT_COLOR, UNK}, + {"basketball", 0, 0, GID_BASKETBALL, 6, 100, MDT_NONE, GF_USE_KEY| GF_16BIT_COLOR, UNK}, {"football2002", 0, 0, GID_FOOTBALL, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK}, {"Soccer2004", 0, 0, GID_SOCCER, 6, 100, MDT_NONE, GF_USE_KEY | GF_16BIT_COLOR, UNK}, diff --git a/engines/scumm/he/logic_he.cpp b/engines/scumm/he/logic_he.cpp index 5f3bdd7018..a095622173 100644 --- a/engines/scumm/he/logic_he.cpp +++ b/engines/scumm/he/logic_he.cpp @@ -960,6 +960,92 @@ int LogicHEsoccer::op_1021(int32 *args) { } /*********************** + * Backyard Basketball + * + */ + +int LogicHEbasketball::versionID() { + return 1; +} + +int32 LogicHEbasketball::dispatch(int op, int numArgs, int32 *args) { + int res = 0; + + switch (op) { + case 1001: + break; + + case 1006: + break; + + case 1011: + break; + + case 1012: + break; + + case 1035: + break; + + case 1050: + break; + + case 1051: + break; + + case 1052: + break; + + case 1056: + break; + + case 1057: + break; + + case 1058: + break; + + case 1060: + break; + + case 1064: + break; + + case 1067: + break; + + case 1073: + break; + + case 1075: + break; + + case 1076: + break; + + case 1080: + break; + + case 1081: + break; + + case 1090: + break; + + case 1091: + break; + + case 1513: + break; + + default: + LogicHE::dispatch(op, numArgs, args); + } + + return res; +} + +/*********************** * Moonbase Commander * */ diff --git a/engines/scumm/he/logic_he.h b/engines/scumm/he/logic_he.h index 67b3ce78d3..29304b7468 100644 --- a/engines/scumm/he/logic_he.h +++ b/engines/scumm/he/logic_he.h @@ -135,6 +135,14 @@ private: int op_1021(int32 *args); }; +class LogicHEbasketball : public LogicHE { +public: + LogicHEbasketball(ScummEngine_v90he *vm) : LogicHE(vm) {} + + int versionID(); + int32 dispatch(int op, int numArgs, int32 *args); +}; + class LogicHEmoonbase : public LogicHE { public: LogicHEmoonbase(ScummEngine_v90he *vm) : LogicHE(vm) {} diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 022eba1e5b..0599139778 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -1528,6 +1528,10 @@ void ScummEngine_v90he::resetScumm() { _logicHE = new LogicHEsoccer(this); break; + case GID_BASKETBALL: + _logicHE = new LogicHEbasketball(this); + break; + case GID_MOONBASE: _logicHE = new LogicHEmoonbase(this); break; diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index 5580c4c73d..9682e5e1ee 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -226,6 +226,7 @@ enum ScummGameId { GID_FUNSHOP, // Used for all three funshops GID_FOOTBALL, GID_SOCCER, + GID_BASKETBALL, GID_MOONBASE, GID_HECUP // CUP demos }; |