From 3687544fbbcfccb2e032651b68fd4e9d109d987a Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 30 Aug 2009 19:47:47 +0000 Subject: Adding support for AVI in SCI games (such as kq6) and implement kPlatform. svn-id: r43834 --- engines/sci/detection_tables.h | 12 ++++- engines/sci/engine/kernel.cpp | 3 +- engines/sci/engine/kernel.h | 1 + engines/sci/engine/kgraphics.cpp | 96 +++++++++++++++++++++++++++++++++++++++- engines/sci/engine/kmisc.cpp | 18 ++++++++ 5 files changed, 127 insertions(+), 3 deletions(-) diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index f935bdff0d..0720cd1284 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -1019,7 +1019,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { 0 }, - // King's Quest 6 - English Windows CD (from the King's Quest Collection) + // King's Quest 6 - English DOS CD (from the King's Quest Collection) // Executable scanning reports "1.cfs.158", VERSION file reports "1.034 9/11/94 - KQ6 version 1.000.00G" // SCI interpreter version 1.001.054 {{"kq6", "CD", { @@ -1028,6 +1028,16 @@ static const struct SciGameDescription SciGameDescriptions[] = { {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0 }, + + // King's Quest 6 - English Windows CD (from the King's Quest Collection) + // Executable scanning reports "1.cfs.158", VERSION file reports "1.034 9/11/94 - KQ6 version 1.000.00G" + // SCI interpreter version 1.001.054 + {{"kq6", "CD", { + {"resource.map", 0, "7a550ebfeae2575ca00d47703a6a774c", 9215}, + {"resource.000", 0, "233394a5f33b475ae5975e7e9a420865", 8376352}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformWindows, 0, GUIO_NONE}, + 0 + }, // King's Quest 6 - Spanish DOS CD (from jvprat) // Executable scanning reports "1.cfs.158", VERSION file reports "1.000.000, July 5, 1994" diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 15d37a55fd..37524ab940 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -339,8 +339,9 @@ SciKernelFunction kfunct_mappers[] = { DEFUN("DoSync", kDoSync, ".*"), DEFUN("ResCheck", kResCheck, "iii*"), DEFUN("SetQuitStr", kSetQuitStr, "r"), - DEFUN("ShowMovie", kShowMovie, "ri"), + DEFUN("ShowMovie", kShowMovie, "..*"), DEFUN("SetVideoMode", kSetVideoMode, "i"), + DEFUN("Platform", kPlatform, "i*"), // Special and NOP stuff DEFUN("Dummy", kStub, ".*"), diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 29228baee7..7c2ad50382 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -502,6 +502,7 @@ reg_t kShowMovie(EngineState *s, int funct_nr, int argc, reg_t *argv); reg_t kSetVideoMode(EngineState *s, int funct_nr, int argc, reg_t *argv); reg_t kStrSplit(EngineState *s, int funct_nr, int argc, reg_t *argv); reg_t k_Unknown(EngineState *s, int funct_nr, int argc, reg_t *argv); +reg_t kPlatform(EngineState *s, int funct_nr, int argc, reg_t *argv); // The Unknown/Unnamed kernel function reg_t kStub(EngineState *s, int funct_nr, int argc, reg_t *argv); diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index b152864804..9916a2f9e8 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -26,6 +26,8 @@ #include "common/system.h" #include "common/events.h" #include "graphics/cursorman.h" +#include "graphics/video/avi_player.h" +#include "graphics/surface.h" #include "sci/sci.h" #include "sci/debug.h" // for g_debug_sleeptime_factor @@ -3341,7 +3343,85 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } -reg_t kShowMovie(EngineState *s, int funct_nr, int argc, reg_t *argv) { +static reg_t kShowMovie_Windows(EngineState *s, int funct_nr, int argc, reg_t *argv) { + const char *filename = kernel_dereference_char_pointer(s->segmentManager, argv[1], 0); + + Graphics::AVIPlayer *player = new Graphics::AVIPlayer(g_system); + + if (!player->open(filename)) { + warning("Failed to open movie file %s", filename); + return s->r_acc; + } + + uint32 startTime = g_system->getMillis(); + bool play = true; + + while (play && player->getCurFrame() < player->getFrameCount()) { + uint32 elapsed = g_system->getMillis() - startTime; + + if (elapsed >= player->getCurFrame() * 1000 / player->getFrameRate()) { + Graphics::Surface *surface = player->getNextFrame(); + + Palette *palette = NULL; + + if (player->dirtyPalette()) { + byte *rawPalette = player->getPalette(); + gfx_pixmap_color_t *colors = new gfx_pixmap_color_t[256]; + + for (uint16 i = 0; i < 256; i++) { + colors[i].r = rawPalette[i * 4]; + colors[i].g = rawPalette[i * 4 + 1]; + colors[i].b = rawPalette[i * 4 + 2]; + colors[i].global_index = i; + } + + palette = new Palette(colors, 256); + palette->forceInto(s->gfx_state->driver->getMode()->palette); + } + + if (surface) { + // Allocate a pixmap + gfx_pixmap_t *pixmap = gfx_new_pixmap(surface->w, surface->h, 0, 0, 0); + assert(pixmap); + gfx_pixmap_alloc_index_data(pixmap); + + // Copy data from the surface + memcpy(pixmap->index_data, surface->pixels, surface->w * surface->h); + pixmap->xoffset = (g_system->getWidth() - surface->w) / 2; + pixmap->yoffset = (g_system->getHeight() - surface->h) / 2; + pixmap->palette = palette; + + // Copy the frame to the screen + 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); + + // Surface is freed when the codec in the video is deleted + } + } + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_QUIT: + play = false; + quit_vm(); + break; + default: + break; + } + } + + g_system->delayMillis(10); + } + + delete player; + + return s->r_acc; +} + +static reg_t kShowMovie_DOS(EngineState *s, int funct_nr, int argc, reg_t *argv) { const char *filename = kernel_dereference_char_pointer(s->segmentManager, argv[0], 0); int delay = argv[1].toUint16(); // Time between frames in ticks int frameNr = 0; @@ -3387,6 +3467,20 @@ reg_t kShowMovie(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } +reg_t kShowMovie(EngineState *s, int funct_nr, int argc, reg_t *argv) { + // KQ6 Windows calls this with one argument. It doesn't seem + // to have a purpose... + if (argc == 1) + return NULL_REG; + + // The Windows and DOS versions use different video format as well + // as a different argument set. + if (argv[0].toUint16() == 0) + return kShowMovie_Windows(s, funct_nr, argc, argv); + + return kShowMovie_DOS(s, funct_nr, argc, argv); +} + reg_t kSetVideoMode(EngineState *s, int funct_nr, int argc, reg_t *argv) { // This call is used for KQ6's intro. It has one parameter, which is // 1 when the intro begins, and 0 when it ends. It is suspected that diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 16eb7ae7d5..4782b19280 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -250,6 +250,24 @@ reg_t kMemory(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } +reg_t kPlatform(EngineState *s, int funct_nr, int argc, reg_t *argv) { + if (argc == 1) { + if (argv[0].toUint16() == 4) + if (((SciEngine*)g_engine)->getPlatform() == Common::kPlatformWindows) + return make_reg(0, 2); + else + return make_reg(0, 1); + else if (argv[0].toUint16() == 5) + warning("kPlatform(5)"); // TODO: return 1 based on some variable + else if (argv[0].toUint16() == 6) + warning("kPlatform(6)"); // TODO: return some variable + else if (argv[0].toUint16() == 7 && ((SciEngine*)g_engine)->getPlatform() == Common::kPlatformWindows) + return make_reg(0, 1); + } + + return NULL_REG; +} + reg_t kStub(EngineState *s, int funct_nr, int argc, reg_t *argv) { char tmpbuf[200]; sprintf(tmpbuf, "Unimplemented syscall: %s[%x] (", -- cgit v1.2.3