diff --git a/CMakeLists.txt b/CMakeLists.txt index 8aa274ec9..997fd42f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ add_compile_definitions(CINTERFACE XML_STATIC VFS_STATIC VFS_WITH_SLF VFS_WITH_7 include_directories( "${CMAKE_SOURCE_DIR}/Ja2" "${CMAKE_SOURCE_DIR}/ext/VFS/include" + "${CMAKE_SOURCE_DIR}/ext/libsmacker" "${CMAKE_SOURCE_DIR}/Utils" "${CMAKE_SOURCE_DIR}/TileEngine" "${CMAKE_SOURCE_DIR}/TacticalAI" @@ -62,6 +63,7 @@ include_directories( # external libraries add_subdirectory("ext/libpng") +add_subdirectory("ext/libsmacker") add_subdirectory("ext/zlib") add_subdirectory("ext/VFS") target_link_libraries(bfVFS PRIVATE 7z) @@ -79,13 +81,13 @@ set(Ja2_Libraries "${CMAKE_SOURCE_DIR}/libexpatMT.lib" "${CMAKE_SOURCE_DIR}/lua51.lib" "${CMAKE_SOURCE_DIR}/lua51.vc9.lib" -"${CMAKE_SOURCE_DIR}/SMACKW32.LIB" "Dbghelp.lib" "Winmm.lib" "ws2_32.lib" bfVFS Lua Multiplayer +smacker wine ) @@ -162,6 +164,9 @@ foreach(app IN LISTS ApplicationTargets) target_link_libraries(${exe} PRIVATE ${app}_${lib}) endforeach() + # for Utils only + target_link_libraries(${app}_Utils PRIVATE smacker) + # for SGP only target_link_libraries(${app}_sgp PRIVATE "ddraw.lib" "${PROJECT_SOURCE_DIR}/fmodvc.lib") target_link_libraries(${app}_sgp PRIVATE libpng) diff --git a/Ja2/Intro.cpp b/Ja2/Intro.cpp index 17c3940f4..005f439bc 100644 --- a/Ja2/Intro.cpp +++ b/Ja2/Intro.cpp @@ -38,7 +38,7 @@ public: { if(_type & VT_SMK) { - SmkInitialize( ghWindow, SCREEN_WIDTH, SCREEN_HEIGHT); + SmkInitialize(); } if(_type & VT_BINK) { diff --git a/SMACKW32.LIB b/SMACKW32.LIB deleted file mode 100644 index 24979d46a..000000000 Binary files a/SMACKW32.LIB and /dev/null differ diff --git a/Utils/Cinematics Bink.cpp b/Utils/Cinematics Bink.cpp index a6eecf200..d5daa4d4c 100644 --- a/Utils/Cinematics Bink.cpp +++ b/Utils/Cinematics Bink.cpp @@ -10,7 +10,6 @@ #include "DEBUG.H" #include "FileMan.h" -#include "SMACK.H" #include "ddraw.h" #include "Mss.h" #include "DirectX Common.h" diff --git a/Utils/Cinematics.cpp b/Utils/Cinematics.cpp index 579152bf7..2a929fa30 100644 --- a/Utils/Cinematics.cpp +++ b/Utils/Cinematics.cpp @@ -1,329 +1,379 @@ -//---------------------------------------------------------------------------------- -// Cinematics Module -// -// -// Stolen from Nemesis by Derek Beland. -// Originally by Derek Beland and Bret Rowden. -// -// ChangeLog: -// 10.12.2005 Lesh ripped everything that refers to MSS -// 15.12.2005 Lesh enabled sound in video -//---------------------------------------------------------------------------------- -//#include "LocalCodeAll.h" - -#include "types.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include "DEBUG.H" -#include "FileMan.h" -#include "SMACK.H" -#include "ddraw.h" -#include "DirectX Common.h" -#include "DirectDraw Calls.h" -#include "Cinematics.h" -#include "soundman.h" -#include -#include - - #include "video.h" - -#include "vsurface_private.h" - - - - - -#include - -//-Structures---------------------------------------------------------------------- - -//-Flags-and-Symbols--------------------------------------------------------------- - -#define SMK_NUM_FLICS 4 // Maximum number of flics open - -// SMKFLIC uiFlags -#define SMK_FLIC_OPEN 0x00000001 // Flic is open -#define SMK_FLIC_PLAYING 0x00000002 // Flic is playing -#define SMK_FLIC_LOOP 0x00000004 // Play flic in a loop -#define SMK_FLIC_AUTOCLOSE 0x00000008 // Close when done - -//-Globals------------------------------------------------------------------------- -SMKFLIC SmkList[SMK_NUM_FLICS]; - -HWND hDisplayWindow = 0; -UINT32 uiDisplayHeight, uiDisplayWidth; -BOOLEAN fSuspendFlics = FALSE; -UINT32 uiFlicsPlaying = 0; -UINT32 guiSmackPixelFormat = SMACKBUFFER565; - -LPDIRECTDRAWSURFACE lpVideoPlayback=NULL; -LPDIRECTDRAWSURFACE2 lpVideoPlayback2=NULL; - - -//-Function-Prototypes------------------------------------------------------------- -void SmkInitialize(HWND hWindow, UINT32 uiWidth, UINT32 uiHeight); -void SmkShutdown(void); -SMKFLIC *SmkPlayFlic(CHAR8 *cFilename, UINT32 uiLeft, UINT32 uiTop, BOOLEAN fAutoClose); -BOOLEAN SmkPollFlics(void); -SMKFLIC *SmkOpenFlic(CHAR8 *cFilename); -void SmkSetBlitPosition(SMKFLIC *pSmack, UINT32 uiLeft, UINT32 uiTop); -void SmkCloseFlic(SMKFLIC *pSmack); -SMKFLIC *SmkGetFreeFlic(void); -void SmkSetupVideo(void); -void SmkShutdownVideo(void); - - -BOOLEAN SmkPollFlics(void) -{ - UINT32 uiCount; - BOOLEAN fFlicStatus = FALSE; - DDSURFACEDESC SurfaceDescription; - - for(uiCount=0; uiCount < SMK_NUM_FLICS; uiCount++) - { - if(SmkList[uiCount].uiFlags & SMK_FLIC_PLAYING) - { - fFlicStatus=TRUE; - if(!fSuspendFlics) - { - if(!SmackWait(SmkList[uiCount].SmackHandle)) - { - DDLockSurface(SmkList[uiCount].lpDDS, NULL, &SurfaceDescription, 0, NULL); - SmackToBuffer(SmkList[uiCount].SmackHandle,SmkList[uiCount].uiLeft, - SmkList[uiCount].uiTop, - SurfaceDescription.lPitch, - SmkList[uiCount].SmackHandle->Height, - SurfaceDescription.lpSurface, - guiSmackPixelFormat); - SmackDoFrame(SmkList[uiCount].SmackHandle); - DDUnlockSurface(SmkList[uiCount].lpDDS, SurfaceDescription.lpSurface); - // temp til I figure out what to do with it - //InvalidateRegion(0,0, 640, 480, FALSE); - - // Check to see if the flic is done the last frame - if(SmkList[uiCount].SmackHandle->FrameNum==(SmkList[uiCount].SmackHandle->Frames-1)) - { - // If flic is looping, reset frame to 0 - if(SmkList[uiCount].uiFlags & SMK_FLIC_LOOP) - SmackGoto(SmkList[uiCount].SmackHandle, 0); - else if(SmkList[uiCount].uiFlags & SMK_FLIC_AUTOCLOSE) - SmkCloseFlic(&SmkList[uiCount]); - } - else - { - SmackNextFrame(SmkList[uiCount].SmackHandle); - } - } - } - } - } - if(!fFlicStatus) - SmkShutdownVideo(); - - return(fFlicStatus); -} - -// Lesh changed this function only ----------------------------- -void SmkInitialize(HWND hWindow, UINT32 uiWidth, UINT32 uiHeight) -{ - // Wipe the flic list clean - memset(SmkList, 0, sizeof(SMKFLIC)*SMK_NUM_FLICS); - - // Set playback window properties - hDisplayWindow = hWindow; - uiDisplayWidth = uiWidth; - uiDisplayHeight= uiHeight; - - // Use MMX acceleration, if available - SmackUseMMX(1); - - //Get the sound Driver handle - void* pSoundDriver = SoundGetDriverHandle(); - - //if we got the sound handle, use sound during the intro - if( pSoundDriver ) - SmackSoundUseDirectSound( pSoundDriver ); -} - -void SmkShutdown(void) -{ - UINT32 uiCount; - - // Close and deallocate any open flics - for(uiCount=0; uiCount < SMK_NUM_FLICS; uiCount++) - { - if(SmkList[uiCount].uiFlags & SMK_FLIC_OPEN) - SmkCloseFlic(&SmkList[uiCount]); - } -} - -SMKFLIC *SmkPlayFlic(const CHAR8 *cFilename, UINT32 uiLeft, UINT32 uiTop, BOOLEAN fClose) -{ - SMKFLIC *pSmack; - - // Open the flic - if((pSmack=SmkOpenFlic(cFilename))==NULL) - return(NULL); - - // Set the blitting position on the screen - SmkSetBlitPosition(pSmack, uiLeft, uiTop); - - // We're now playing, flag the flic for the poller to update - pSmack->uiFlags|=SMK_FLIC_PLAYING; - if(fClose) - pSmack->uiFlags|=SMK_FLIC_AUTOCLOSE; - - return(pSmack); -} - -SMKFLIC *SmkOpenFlic(const CHAR8 *cFilename) -{ - SMKFLIC *pSmack; - - // Get an available flic slot from the list - if(!(pSmack=SmkGetFreeFlic())) - { - ErrorMsg("SMK ERROR: Out of flic slots, cannot open another"); - return(NULL); - } - - vfs::Path introname(cFilename); - vfs::Path dir,filename; - introname.splitLast(dir,filename); - vfs::Path tempfile = vfs::Path(L"Temp") + filename; - if(!getVFS()->fileExists(tempfile)) - { - try - { - if(!getVFS()->fileExists(introname)) - { - return NULL; - } - vfs::COpenReadFile rfile(introname); - vfs::size_t size = rfile->getSize(); - std::vector data(size); - rfile->read(&data[0],size); - - vfs::COpenWriteFile wfile(tempfile,true); - wfile->write(&data[0],size); - } - catch(std::exception& ex) - { - SGP_RETHROW(_BS(L"Intro file \"") << filename << L"\" could not be extracted" << _BS::wget, ex); - } - } - - // Allocate a Smacker buffer for video decompression - if(!(pSmack->SmackBuffer=SmackBufferOpen(hDisplayWindow,SMACKAUTOBLIT,SCREEN_WIDTH,SCREEN_HEIGHT,0,0))) - { - ErrorMsg("SMK ERROR: Can't allocate a Smacker decompression buffer"); - return(NULL); - } -// if(!(pSmack->SmackHandle=SmackOpen(cFilename, SMACKTRACKS, SMACKAUTOEXTRA))) - vfs::Path tempfilename; - try - { - vfs::COpenWriteFile wfile(tempfile); - if(!wfile->_getRealPath(tempfilename)) - { - return NULL; - } - } - catch(std::exception& ex) - { - SGP_RETHROW(L"Temporary intro file could not be read", ex); - } - if(!(pSmack->SmackHandle=SmackOpen(tempfilename.to_string().c_str(), SMACKTRACKS, SMACKAUTOEXTRA))) - { - ErrorMsg("SMK ERROR: Smacker won't open the SMK file"); - return(NULL); - } - - // Make sure we have a video surface - SmkSetupVideo(); - - pSmack->cFilename=cFilename; - pSmack->lpDDS=lpVideoPlayback2; - pSmack->hWindow=hDisplayWindow; - - // Smack flic is now open and ready to go - pSmack->uiFlags|=SMK_FLIC_OPEN; - - return(pSmack); -} - -void SmkSetBlitPosition(SMKFLIC *pSmack, UINT32 uiLeft, UINT32 uiTop) -{ - pSmack->uiLeft=uiLeft; - pSmack->uiTop=uiTop; -} - -void SmkCloseFlic(SMKFLIC *pSmack) -{ - // Attempt opening the filename - FileClose(pSmack->hFileHandle); - - // Deallocate the smack buffers - SmackBufferClose(pSmack->SmackBuffer); - - // Close the smack flic - SmackClose(pSmack->SmackHandle); - - // Zero the memory, flags, etc. - memset(pSmack, 0, sizeof(SMKFLIC)); -} - -SMKFLIC *SmkGetFreeFlic(void) -{ - UINT32 uiCount; - - for(uiCount=0; uiCount < SMK_NUM_FLICS; uiCount++) - if(!(SmkList[uiCount].uiFlags & SMK_FLIC_OPEN)) - return(&SmkList[uiCount]); - - return(NULL); -} - -void SmkSetupVideo(void) -{ -// DEF: -// lpVideoPlayback2 = CinematicModeOn(); - - HVSURFACE hVSurface; - GetVideoSurface( &hVSurface, FRAME_BUFFER ); - lpVideoPlayback2 = GetVideoSurfaceDDSurface( hVSurface ); - - DDSURFACEDESC SurfaceDescription; - ZEROMEM(SurfaceDescription); - SurfaceDescription.dwSize = sizeof (DDSURFACEDESC); - HRESULT ReturnCode = IDirectDrawSurface2_GetSurfaceDesc ( lpVideoPlayback2, &SurfaceDescription ); - if (ReturnCode != DD_OK) - { - DirectXAttempt ( ReturnCode, __LINE__, __FILE__ ); - return; - } - - UINT16 usRed, usGreen, usBlue; - usRed = (UINT16) SurfaceDescription.ddpfPixelFormat.dwRBitMask; - usGreen = (UINT16) SurfaceDescription.ddpfPixelFormat.dwGBitMask; - usBlue = (UINT16) SurfaceDescription.ddpfPixelFormat.dwBBitMask; - - if((usRed==0xf800) && (usGreen==0x07e0) && (usBlue==0x001f)) - guiSmackPixelFormat=SMACKBUFFER565; - else - guiSmackPixelFormat=SMACKBUFFER555; - -} - -void SmkShutdownVideo(void) -{ -//DEF: -// CinematicModeOff(); -} +#include "types.h" +#include +#include +#include +#include +#include + +extern "C" +{ + #include "smacker.h" +} + +#include "DEBUG.H" +#include "Cinematics.h" +#include "himage.h" +#include "local.h" +#include "soundman.h" +#include "vobject.h" +#include "vsurface.h" +#include +#include + +static constexpr UINT32 MAX_FLICS = 4; // How many flics can be open at once +static constexpr UINT32 NUM_AUDIO_TRACKS = 7; // Audio tracks an SMK file can carry +static constexpr UINT32 WAV_HEADER_SIZE = 44; // Header we prepend to the decoded audio + +struct SMKFLIC { + // libsmacker decoder; null means the slot is free + smk decoder = nullptr; + bool playing = false; + // Close the flic once it has played to the end + bool autoClose = false; + // Where on the screen the flic is blitted + UINT32 left = 0, top = 0; + // Tick count the flic started playing at + UINT32 startTime = 0; + // Frame the decoder is on + UINT32 frame = 0; + double millisecondsPerFrame = 0.0; + // Last result of smk_first()/smk_next() + char status = SMK_DONE; + + // WAV header followed by the decoded audio + std::array, NUM_AUDIO_TRACKS> audio; + // SOUND_ERROR when the track isn't playing + std::array soundId; +}; + +static std::array flics; + +static auto SmkGetFreeFlic() -> SMKFLIC*; +static auto SmkReadFile(const CHAR8 *filename) -> std::optional>; +static auto SmkDecodeAudio(SMKFLIC &flic) -> void; +static auto SmkStartAudio(SMKFLIC &flic, const CHAR8 *filename) -> void; +static auto SmkWriteWavHeader(UINT8 *wav, UINT32 pcmSize, UINT8 channels, UINT8 bitDepth, UINT32 rate) -> void; +static auto SmkAdvanceToCurrentFrame(SMKFLIC &flic) -> void; +static auto SmkBlitFrame(SMKFLIC &flic) -> void; + + +BOOLEAN SmkPollFlics() +{ + bool anyPlaying = false; + + for (SMKFLIC &flic : flics) + { + if (!flic.playing) + continue; + + SmkAdvanceToCurrentFrame(flic); + + if (flic.status == SMK_DONE || flic.status == SMK_ERROR) + { + if (flic.autoClose) + SmkCloseFlic(&flic); + else + flic.playing = false; + } + else + { + anyPlaying = true; + SmkBlitFrame(flic); + } + } + + return anyPlaying; +} + +void SmkInitialize() +{ + for (SMKFLIC &flic : flics) + { + flic.decoder = nullptr; + flic.playing = false; + flic.autoClose = false; + flic.soundId.fill(SOUND_ERROR); + } +} + +void SmkShutdown() +{ + // Close and deallocate any open flics + for (SMKFLIC &flic : flics) + SmkCloseFlic(&flic); +} + +SMKFLIC *SmkPlayFlic(const CHAR8 *filename, UINT32 left, UINT32 top, BOOLEAN autoClose) +{ + SMKFLIC *flic = SmkGetFreeFlic(); + if (flic == nullptr) + { + ErrorMsg("SMK ERROR: Out of flic slots, cannot open another"); + return nullptr; + } + + std::optional> fileData = SmkReadFile(filename); + if (!fileData) + return nullptr; + + // libsmacker copies the compressed frames it needs out of the buffer, so + // fileData can go away again as soon as the file is open + flic->decoder = smk_open_memory(reinterpret_cast(fileData->data()), static_cast(fileData->size())); + if (flic->decoder == nullptr) + { + ErrorMsg("SMK ERROR: libsmacker won't open the SMK file"); + return nullptr; + } + + // The slot is now taken (decoder != nullptr) and ready to go + flic->left = left; + flic->top = top; + + double microsecondsPerFrame = 0.0; + if (smk_info_all(flic->decoder, nullptr, nullptr, µsecondsPerFrame) < 0 || microsecondsPerFrame <= 0.0) + { + ErrorMsg("SMK ERROR: Can't read the playback speed of the SMK file"); + SmkCloseFlic(flic); + return nullptr; + } + // The video plays too slowly at microsecond resolution, speed it up by + // rounding down to milliseconds + flic->millisecondsPerFrame = microsecondsPerFrame / 1000.0; + + SmkDecodeAudio(*flic); + + // Rewind, this time to decode the picture + if (smk_enable_all(flic->decoder, SMK_VIDEO_TRACK) < 0) + { + ErrorMsg("SMK ERROR: Can't enable the video track of the SMK file"); + SmkCloseFlic(flic); + return nullptr; + } + flic->status = smk_first(flic->decoder); + flic->frame = 0; + flic->startTime = GetTickCount(); + + SmkStartAudio(*flic, filename); + + // We're now playing, flag the flic for the poller to update + flic->playing = true; + flic->autoClose = autoClose != FALSE; + + return flic; +} + +void SmkCloseFlic(SMKFLIC *flic) +{ + // SmkPollFlics() closes flics that have played to the end by itself, so the + // caller may well be handing us a slot that is already free + if (flic->decoder == nullptr) + return; + + for (UINT32 track = 0; track < NUM_AUDIO_TRACKS; ++track) + { + // The sound was streaming straight out of the audio buffer, so it has to + // be stopped before that buffer is released + if (flic->soundId[track] != SOUND_ERROR) + { + SoundStop(flic->soundId[track]); + flic->soundId[track] = SOUND_ERROR; + } + flic->audio[track] = {}; + } + + smk_close(flic->decoder); + flic->decoder = nullptr; + flic->playing = false; + flic->autoClose = false; +} + +static SMKFLIC *SmkGetFreeFlic() +{ + for (SMKFLIC &flic : flics) + if (flic.decoder == nullptr) + return &flic; + + return nullptr; +} + +// Reads a video file out of the VFS in one go. libsmacker can only read from a +// plain file or from memory, and the file may well be sitting inside an archive. +static std::optional> SmkReadFile(const CHAR8 *filename) +{ + vfs::Path videoName(filename); + std::vector data; + + try + { + if (!getVFS()->fileExists(videoName)) + return std::nullopt; + + vfs::COpenReadFile file(videoName); + vfs::size_t size = file->getSize(); + if (size == 0) + return std::nullopt; + + data.resize(size); + file->read(data.data(), size); + } + catch (std::exception &ex) + { + SGP_RETHROW(_BS(L"Video file \"") << videoName << L"\" could not be read" << _BS::wget, ex); + } + + return data; +} + +// Decodes the audio of the whole file into flic.audio, each track preceded by a +// WAV header. Unlike SMACKW32.DLL, libsmacker hands out audio a frame at a time +// and leaves playing it to us, so it all has to be collected up front. +static void SmkDecodeAudio(SMKFLIC &flic) +{ + unsigned char trackMask = 0; + std::array channels{}; + std::array bitDepth{}; + std::array rate{}; + + if (smk_info_audio(flic.decoder, &trackMask, channels.data(), bitDepth.data(), rate.data()) < 0 || trackMask == 0) + return; + + // Decoding the audio means running through the entire file. Leave the video + // track disabled so that this pass doesn't decode the picture as well. + if (smk_enable_all(flic.decoder, trackMask) < 0) + return; + + // Leave room for the WAV header, which can only be written once the size of + // the track is known + for (UINT32 track = 0; track < NUM_AUDIO_TRACKS; ++track) + if (trackMask & (1 << track)) + flic.audio[track].resize(WAV_HEADER_SIZE); + + for (char status = smk_first(flic.decoder); status != SMK_DONE; status = smk_next(flic.decoder)) + { + if (status == SMK_ERROR) + { + ErrorMsg("SMK ERROR: libsmacker failed to decode the audio of the SMK file"); + break; + } + + for (UINT32 track = 0; track < NUM_AUDIO_TRACKS; ++track) + { + if (!(trackMask & (1 << track))) + continue; + + unsigned long size = smk_get_audio_size(flic.decoder, static_cast(track)); + if (size == 0) + continue; + + const UINT8 *pcm = smk_get_audio(flic.decoder, static_cast(track)); + flic.audio[track].insert(flic.audio[track].end(), pcm, pcm + size); + } + } + + for (UINT32 track = 0; track < NUM_AUDIO_TRACKS; ++track) + { + std::vector &trackAudio = flic.audio[track]; + + if (trackAudio.size() <= WAV_HEADER_SIZE) + { + // Track carries no audio after all + trackAudio = {}; + continue; + } + + SmkWriteWavHeader(trackAudio.data(), static_cast(trackAudio.size()) - WAV_HEADER_SIZE, + channels[track], bitDepth[track], static_cast(rate[track])); + } +} + +static void SmkStartAudio(SMKFLIC &flic, const CHAR8 *filename) +{ + SOUNDPARMS params; + memset(¶ms, 0xff, sizeof(params)); // 0xffffffff in every field means "use the default" + params.uiLoop = 1; + + for (UINT32 track = 0; track < NUM_AUDIO_TRACKS; ++track) + { + if (flic.audio[track].empty()) + continue; + + flic.soundId[track] = SoundPlayFromBuffer(filename, flic.audio[track].data(), + static_cast(flic.audio[track].size()), ¶ms); + } +} + +// Writes a canonical 44 byte WAV header for uncompressed PCM, so that the audio +// we decoded can be handed to the sound module as if it came from a sound file. +static void SmkWriteWavHeader(UINT8 *wav, UINT32 pcmSize, UINT8 channels, UINT8 bitDepth, UINT32 rate) +{ + const UINT16 blockAlign = static_cast(channels * (bitDepth / 8)); + + memcpy(wav + 0, "RIFF", 4); + *reinterpret_cast(wav + 4) = 36 + pcmSize; // size of everything after this field + memcpy(wav + 8, "WAVEfmt ", 8); + *reinterpret_cast(wav + 16) = 16; // size of the fmt chunk + *reinterpret_cast(wav + 20) = 1; // format: uncompressed PCM + *reinterpret_cast(wav + 22) = channels; + *reinterpret_cast(wav + 24) = rate; + *reinterpret_cast(wav + 28) = rate * blockAlign; // byte rate + *reinterpret_cast(wav + 32) = blockAlign; + *reinterpret_cast(wav + 34) = bitDepth; + memcpy(wav + 36, "data", 4); + *reinterpret_cast(wav + 40) = pcmSize; +} + +// Decodes forward until the frame that should be on screen by now. SMACKW32.DLL +// kept the playback clock itself, libsmacker leaves that to the caller. +static void SmkAdvanceToCurrentFrame(SMKFLIC &flic) +{ + UINT32 milliseconds = GetTickCount() - flic.startTime; + UINT32 targetFrame = static_cast(milliseconds / flic.millisecondsPerFrame); + + while (flic.status != SMK_DONE && flic.status != SMK_ERROR && flic.frame != targetFrame) + { + flic.status = smk_next(flic.decoder); + ++flic.frame; + } +} + +static void SmkBlitFrame(SMKFLIC &flic) +{ + // TODO: the Y scale modes (SMK_FLAG_Y_INTERLACE, SMK_FLAG_Y_DOUBLE) are not + // handled, none of the videos that ship with the game use them + const UINT8 *source = smk_get_video(flic.decoder); + if (source == nullptr) + return; + const UINT8 *sourcePalette = smk_get_palette(flic.decoder); + if (sourcePalette == nullptr) + return; + unsigned long sourceWidth, sourceHeight; + if (smk_info_video(flic.decoder, &sourceWidth, &sourceHeight, nullptr) < 0) + return; + + UINT16 palette[256]; + for (UINT32 i = 0; i < 256; ++i) + palette[i] = Get16BPPColor(FROMRGB(sourcePalette[i * 3], sourcePalette[i * 3 + 1], sourcePalette[i * 3 + 2])); + + UINT32 destPitch; + UINT16 *dest = reinterpret_cast(LockVideoSurface(FRAME_BUFFER, &destPitch)); + if (dest == nullptr) + return; + destPitch /= sizeof(UINT16); // pitch in pixels rather than bytes + + // Blit the part of the frame that lands on the screen + // std::min is parenthesised to keep windows.h's min() macro off it + unsigned long columns = flic.left >= static_cast(SCREEN_WIDTH) ? 0 : (std::min)(sourceWidth, static_cast(SCREEN_WIDTH - flic.left)); + unsigned long rows = flic.top >= static_cast(SCREEN_HEIGHT) ? 0 : (std::min)(sourceHeight, static_cast(SCREEN_HEIGHT - flic.top)); + + dest += flic.left + flic.top * destPitch; + for (unsigned long y = 0; y < rows; ++y) + { + for (unsigned long x = 0; x < columns; ++x) + dest[x] = palette[source[x]]; + + dest += destPitch; + source += sourceWidth; + } + + UnLockVideoSurface(FRAME_BUFFER); +} diff --git a/Utils/Cinematics.h b/Utils/Cinematics.h index 5aebbfbdc..fad33471d 100644 --- a/Utils/Cinematics.h +++ b/Utils/Cinematics.h @@ -1,65 +1,14 @@ -#ifndef _CINEMATICS_H_ -#define _CINEMATICS_H_ - -#include "SMACK.H" - -struct SMKFLIC -{ - const CHAR8 *cFilename; -// HFILE hFileHandle; - HWFILE hFileHandle; - Smack *SmackHandle; - SmackBuf *SmackBuffer; - UINT32 uiFlags; - LPDIRECTDRAWSURFACE2 lpDDS; - HWND hWindow; - UINT32 uiFrame; - UINT32 uiLeft, uiTop; -// LPDIRECTDRAW2 lpDD; -// UINT32 uiNumFrames; -// UINT8 *pAudioData; -// UINT8 *pCueData; -}; - -void SmkInitialize(HWND hWindow, UINT32 uiWidth, UINT32 uiHeight); -void SmkShutdown(void); -SMKFLIC *SmkPlayFlic(const CHAR8 *cFilename, UINT32 uiLeft, UINT32 uiTop, BOOLEAN fAutoClose); -BOOLEAN SmkPollFlics(void); -SMKFLIC *SmkOpenFlic(const CHAR8 *cFilename); -void SmkSetBlitPosition(SMKFLIC *pSmack, UINT32 uiLeft, UINT32 uiTop); -void SmkCloseFlic(SMKFLIC *pSmack); -SMKFLIC *SmkGetFreeFlic(void); - -/* -//-------------------------------------------------------------------------- -// Prototypes etc. for our functions that make use of the Smacker library. -// -// Written by Derek Beland, Jan 11, 1995 - -#define FLICSOUNDID "BLAH" // ID for smack flic w/ sound :) - -typedef struct { - unsigned long offset; - unsigned long length; -} SMPLARRAY; - -extern SmackBuf *sbuf; -extern Smack *smk; -extern int smktag; -extern HANDLE smkhandle; -extern int SmackFlicIsOpened; -extern int SmackFlicIsPlaying; - - -HANDLE OpenSmackFlic(char *fname,Smack **s,u32); -int GetNextCue(void); -void PlayCueSamples(void); -void InitFlicSamples(HANDLE fhandle); -void FreeFlicSamples(void); - -int SmackPlayFlic(char *,u32); -void SmackShowNextFrame(void); -void CloseSmackFlic(void); -void InitPal(HWND wh); -*/ -#endif +#ifndef _CINEMATICS_H_ +#define _CINEMATICS_H_ + +#include "types.h" + +struct SMKFLIC; + +void SmkInitialize(); +void SmkShutdown(); +SMKFLIC *SmkPlayFlic(const CHAR8 *filename, UINT32 left, UINT32 top, BOOLEAN autoClose); +BOOLEAN SmkPollFlics(); +void SmkCloseFlic(SMKFLIC *flic); + +#endif diff --git a/sgp/SMACK.H b/sgp/SMACK.H deleted file mode 100644 index ff9f74881..000000000 --- a/sgp/SMACK.H +++ /dev/null @@ -1,434 +0,0 @@ -#ifndef SMACKH -#define SMACKH - -#define SMACKVERSION "3.2f" - -#ifndef __RADRES__ - -#include "RAD.H" - -RADDEFSTART - -typedef struct SmackTag { - u32 Version; // SMK2 only right now - u32 Width; // Width (1 based, 640 for example) - u32 Height; // Height (1 based, 480 for example) - u32 Frames; // Number of frames (1 based, 100 = 100 frames) - u32 MSPerFrame; // Frame Rate - u32 SmackerType; // bit 0 set=ring frame - u32 LargestInTrack[7]; // Largest single size for each track - u32 tablesize; // Size of the init tables - u32 codesize; // Compression info - u32 absize; // ditto - u32 detailsize; // ditto - u32 typesize; // ditto - u32 TrackType[7]; // high byte=0x80-Comp,0x40-PCM data,0x20-16 bit,0x10-stereo - u32 extra; // extra value (should be zero) - u32 NewPalette; // set to one if the palette changed - u8 Palette[772]; // palette data - u32 PalType; // type of palette - u32 FrameNum; // Frame Number to be displayed - u32 FrameSize; // The current frame's size in bytes - u32 SndSize; // The current frame sound tracks' size in bytes - s32 LastRectx; // Rect set in from SmackToBufferRect (X coord) - s32 LastRecty; // Rect set in from SmackToBufferRect (Y coord) - s32 LastRectw; // Rect set in from SmackToBufferRect (Width) - s32 LastRecth; // Rect set in from SmackToBufferRect (Height) - u32 OpenFlags; // flags used on open - u32 LeftOfs; // Left Offset used in SmackTo - u32 TopOfs; // Top Offset used in SmackTo - u32 LargestFrameSize; // Largest frame size - u32 Highest1SecRate; // Highest 1 sec data rate - u32 Highest1SecFrame; // Highest 1 sec data rate starting frame - u32 ReadError; // Set to non-zero if a read error has ocurred - u32 addr32; // translated address for 16 bit interface -} Smack; - -#define SmackHeaderSize(smk) ((((u8*)&((smk)->extra))-((u8*)(smk)))+4) - -typedef struct SmackSumTag { - u32 TotalTime; // total time - u32 MS100PerFrame; // MS*100 per frame (100000/MS100PerFrame=Frames/Sec) - u32 TotalOpenTime; // Time to open and prepare for decompression - u32 TotalFrames; // Total Frames displayed - u32 SkippedFrames; // Total number of skipped frames - u32 SoundSkips; // Total number of sound skips - u32 TotalBlitTime; // Total time spent blitting - u32 TotalReadTime; // Total time spent reading - u32 TotalDecompTime; // Total time spent decompressing - u32 TotalBackReadTime; // Total time spent reading in background - u32 TotalReadSpeed; // Total io speed (bytes/second) - u32 SlowestFrameTime; // Slowest single frame time - u32 Slowest2FrameTime; // Second slowest single frame time - u32 SlowestFrameNum; // Slowest single frame number - u32 Slowest2FrameNum; // Second slowest single frame number - u32 AverageFrameSize; // Average size of the frame - u32 HighestMemAmount; // Highest amount of memory allocated - u32 TotalExtraMemory; // Total extra memory allocated - u32 HighestExtraUsed; // Highest extra memory actually used -} SmackSum; - - -//======================================================================= -#define SMACKNEEDPAN 0x00020L // Will be setting the pan -#define SMACKNEEDVOLUME 0x00040L // Will be setting the volume -#define SMACKFRAMERATE 0x00080L // Override fr (call SmackFrameRate first) -#define SMACKLOADEXTRA 0x00100L // Load the extra buffer during SmackOpen -#define SMACKPRELOADALL 0x00200L // Preload the entire animation -#define SMACKNOSKIP 0x00400L // Don't skip frames if falling behind -#define SMACKSIMULATE 0x00800L // Simulate the speed (call SmackSim first) -#define SMACKFILEHANDLE 0x01000L // Use when passing in a file handle -#define SMACKTRACK1 0x02000L // Play audio track 1 -#define SMACKTRACK2 0x04000L // Play audio track 2 -#define SMACKTRACK3 0x08000L // Play audio track 3 -#define SMACKTRACK4 0x10000L // Play audio track 4 -#define SMACKTRACK5 0x20000L // Play audio track 5 -#define SMACKTRACK6 0x40000L // Play audio track 6 -#define SMACKTRACK7 0x80000L // Play audio track 7 -#define SMACKTRACKS (SMACKTRACK1|SMACKTRACK2|SMACKTRACK3|SMACKTRACK4|SMACKTRACK5|SMACKTRACK6|SMACKTRACK7) - -#define SMACKBUFFERREVERSED 0x00000001 -#define SMACKBUFFER555 0x80000000 -#define SMACKBUFFER565 0xc0000000 -#define SMACKBUFFER16 (SMACKBUFFER555|SMACKBUFFER565) - -#define SMACKYINTERLACE 0x100000L // Force interleaving Y scaling -#define SMACKYDOUBLE 0x200000L // Force doubling Y scaling -#define SMACKYNONE (SMACKYINTERLACE|SMACKYDOUBLE) // Force normal Y scaling -#define SMACKFILEISSMK 0x2000000L // Internal flag for 16 to 32 bit thunking - -#define SMACKAUTOEXTRA 0xffffffffL // NOT A FLAG! - Use as extrabuf param -//======================================================================= - -#define SMACKSURFACEFAST 0 -#define SMACKSURFACESLOW 1 -#define SMACKSURFACEDIRECT 2 - -RADEXPFUNC Smack PTR4* RADEXPLINK SmackOpen(const char PTR4* name,u32 flags,u32 extrabuf); - -#ifdef __RADMAC__ - #include - - RADEXPFUNC Smack PTR4* RADEXPLINK SmackMacOpen(FSSpec* fsp,u32 flags,u32 extrabuf); -#endif - -RADEXPFUNC u32 RADEXPLINK SmackDoFrame(Smack PTR4* smk); -RADEXPFUNC void RADEXPLINK SmackNextFrame(Smack PTR4* smk); -RADEXPFUNC u32 RADEXPLINK SmackWait(Smack PTR4* smk); -RADEXPFUNC void RADEXPLINK SmackClose(Smack PTR4* smk); - -RADEXPFUNC void RADEXPLINK SmackVolumePan(Smack PTR4* smk, u32 trackflag,u32 volume,u32 pan); - -RADEXPFUNC void RADEXPLINK SmackSummary(Smack PTR4* smk,SmackSum PTR4* sum); - -RADEXPFUNC u32 RADEXPLINK SmackSoundInTrack(Smack PTR4* smk,u32 trackflags); -RADEXPFUNC u32 RADEXPLINK SmackSoundOnOff(Smack PTR4* smk,u32 on); - -#ifndef __RADMAC__ -RADEXPFUNC void RADEXPLINK SmackToScreen(Smack PTR4* smk,u32 left,u32 top,u32 BytePS,const u16 PTR4* WinTbl,void* SetBank,u32 Flags); -#endif - -RADEXPFUNC void RADEXPLINK SmackToBuffer(Smack PTR4* smk,u32 left,u32 top,u32 Pitch,u32 destheight,const void PTR4* buf,u32 Flags); -RADEXPFUNC u32 RADEXPLINK SmackToBufferRect(Smack PTR4* smk, u32 SmackSurface); - -RADEXPFUNC void RADEXPLINK SmackGoto(Smack PTR4* smk,u32 frame); -RADEXPFUNC void RADEXPLINK SmackColorRemapWithTrans(Smack PTR4* smk,const void PTR4* remappal,u32 numcolors,u32 paltype,u32 transindex); -#define SmackColorRemap(smk,remappal,numcolors,paltype) SmackColorRemapWithTrans(smk,remappal,numcolors,paltype,1000) -RADEXPFUNC void RADEXPLINK SmackColorTrans(Smack PTR4* smk,const void PTR4* trans); -RADEXPFUNC void RADEXPLINK SmackFrameRate(u32 forcerate); -RADEXPFUNC void RADEXPLINK SmackSimulate(u32 sim); - -RADEXPFUNC u32 RADEXPLINK SmackGetTrackData(Smack PTR4* smk,void PTR4* dest,u32 trackflag); - -RADEXPFUNC void RADEXPLINK SmackSoundCheck(void); - - -//====================================================================== - -// the functions for the new SmackBlit API - -typedef struct _SMACKBLIT PTR4* HSMACKBLIT; - -typedef struct _SMACKBLIT { - u32 Flags; - u8 PTR4* Palette; - u32 PalType; - u16 PTR4* SmoothTable; - u16 PTR4* Conv8to16Table; - u32 whichmode; - u32 palindex; - u32 t16index; - u32 smoothindex; - u32 smoothtype; - u32 firstpalette; -} SMACKBLIT; - -#define SMACKBLIT1X 1 -#define SMACKBLIT2X 2 -#define SMACKBLIT2XSMOOTHING 4 -#define SMACKBLIT2XINTERLACE 8 - -RADEXPFUNC HSMACKBLIT RADEXPLINK SmackBlitOpen(u32 flags); -RADEXPFUNC void RADEXPLINK SmackBlitSetPalette(HSMACKBLIT sblit, void PTR4* Palette,u32 PalType); -RADEXPFUNC u32 RADEXPLINK SmackBlitSetFlags(HSMACKBLIT sblit,u32 flags); -RADEXPFUNC void RADEXPLINK SmackBlit(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, void PTR4* src, u32 srcpitch, u32 srcx, u32 srcy, u32 srcw, u32 srch); -RADEXPFUNC void RADEXPLINK SmackBlitClear(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, u32 destw, u32 desth, s32 color); -RADEXPFUNC void RADEXPLINK SmackBlitClose(HSMACKBLIT sblit); -RADEXPFUNC void RADEXPLINK SmackBlitTrans(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, void PTR4* src, u32 srcpitch, u32 srcx, u32 srcy, u32 srcw, u32 srch, u32 trans); -RADEXPFUNC void RADEXPLINK SmackBlitMask(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, void PTR4* src, u32 srcpitch, u32 srcx, u32 srcy, u32 srcw, u32 srch, u32 trans,void PTR4* mask); -RADEXPFUNC void RADEXPLINK SmackBlitMerge(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, void PTR4* src, u32 srcpitch, u32 srcx, u32 srcy, u32 srcw, u32 srch, u32 trans,void PTR4* back); -RADEXPFUNC char PTR4* RADEXPLINK SmackBlitString(HSMACKBLIT sblit,char PTR4* dest); - -#ifndef __RADMAC__ -RADEXPFUNC u32 RADEXPLINK SmackUseMMX(u32 flag); //0=off, 1=on, 2=query current -#endif - -//====================================================================== -#ifdef __RADDOS__ - - #define SMACKSOUNDNONE -1 - - extern void* SmackTimerSetupAddr; - extern void* SmackTimerReadAddr; - extern void* SmackTimerDoneAddr; - - typedef void RADEXPLINK (*SmackTimerSetupType)(void); - typedef u32 RADEXPLINK (*SmackTimerReadType)(void); - typedef void RADEXPLINK (*SmackTimerDoneType)(void); - - #define SmackTimerSetup() ((SmackTimerSetupType)(SmackTimerSetupAddr))() - #define SmackTimerRead() ((SmackTimerReadType)(SmackTimerReadAddr))() - #define SmackTimerDone() ((SmackTimerDoneType)(SmackTimerDoneAddr))() - - RADEXPFUNC u8 RADEXPLINK SmackSoundUseMSS(void* DigDriver); - - #ifndef AIL_startup - #ifdef __SW_3R - extern s32 cdecl AIL_startup_reg(void); - #define AIL_startup AIL_startup_reg - #else - extern s32 cdecl AIL_startup_stack(void); - #define AIL_startup AIL_startup_stack - #endif - #endif - #define SmackSoundMSSLiteInit() SmackSoundMSSLiteInitWithStart(&AIL_startup); - RADEXPFUNC void RADEXPLINK SmackSoundMSSLiteInitWithStart(void* start); - RADEXPFUNC void RADEXPLINK SmackSoundMSSLiteDone(void); - - RADEXPFUNC u8 RADEXPLINK SmackSoundUseSOS3r(u32 SOSDriver,u32 MaxTimerSpeed); - RADEXPFUNC u8 RADEXPLINK SmackSoundUseSOS3s(u32 SOSDriver,u32 MaxTimerSpeed); - RADEXPFUNC u8 RADEXPLINK SmackSoundUseSOS4r(u32 SOSDriver,u32 MaxTimerSpeed); - RADEXPFUNC u8 RADEXPLINK SmackSoundUseSOS4s(u32 SOSDriver,u32 MaxTimerSpeed); - - #ifdef __SW_3R - #define SmackSoundUseSOS3 SmackSoundUseSOS3r - #define SmackSoundUseSOS4 SmackSoundUseSOS4r - #else - #define SmackSoundUseSOS3 SmackSoundUseSOS3s - #define SmackSoundUseSOS4 SmackSoundUseSOS4s - #endif - -#else - - #define SMACKRESRESET 0 - #define SMACKRES640X400 1 - #define SMACKRES640X480 2 - #define SMACKRES800X600 3 - #define SMACKRES1024X768 4 - - RADEXPFUNC u32 RADEXPLINK SmackSetSystemRes(u32 mode); // use SMACKRES* values - - #define SMACKNOCUSTOMBLIT 128 - #define SMACKSMOOTHBLIT 256 - #define SMACKINTERLACEBLIT 512 - - #ifdef __RADMAC__ - - #include - #include - #include - - #define SmackTimerSetup() - #define SmackTimerDone() - RADEXPFUNC u32 RADEXPLINK SmackTimerRead(void); - - RADEXPFUNC s32 RADEXPLINK SmackGDSurfaceType( GDHandle gd ); - - #define SMACKAUTOBLIT 0 - #define SMACKDIRECTBLIT 1 - #define SMACKGWORLDBLIT 2 - - typedef struct SmackBufTag { - u32 Reversed; - u32 SurfaceType; // SMACKSURFACExxxxxx - u32 BlitType; // SMACKxxxxxBLIT - u32 Width; - u32 Height; - u32 Pitch; - u32 Zoomed; - u32 ZWidth; - u32 ZHeight; - u32 DispColors; // colors on screen - u32 MaxPalColors; - u32 PalColorsInUse; - u32 StartPalColor; - u32 EndPalColor; - void* Buffer; - void* Palette; - u32 PalType; - u32 SoftwareCursor; - - WindowPtr wp; - GWorldPtr gwp; - CTabHandle cth; - PaletteHandle palh; - - GDHandle gd; - u32 gdSurfaceType; - HSMACKBLIT sblit; - void * ScreenAddr; - u32 ScreenPitch; - - s32 manyblits; - s32 PTR4* blitrects; - s32 PTR4* rectsptr; - s32 maxrects; - s32 numrects; - - } SmackBuf; - - #else - - #ifdef __RADWIN__ - - #define INCLUDE_MMSYSTEM_H - #include "windows.h" - #include "windowsx.h" - - #ifdef __RADNT__ // to combat WIN32_LEAN_AND_MEAN - - #include "mmsystem.h" - - RADEXPFUNC s32 RADEXPLINK SmackDDSurfaceType(void* lpDDS); - - #endif - - #define SMACKAUTOBLIT 0 - #define SMACKFULL320X240BLIT 1 - #define SMACKFULL320X200BLIT 2 - #define SMACKFULL320X200DIRECTBLIT 3 - #define SMACKSTANDARDBLIT 4 - #define SMACKWINGBLIT 5 - #define SMACKDIBSECTIONBLIT 5 - - #define WM_SMACKACTIVATE WM_USER+0x5678 - - typedef struct SmackBufTag { - u32 Reversed; // 1 if the buffer is upside down - u32 SurfaceType; // SMACKSURFACExxxx defines - u32 BlitType; // SMACKxxxxBLIT defines - u32 FullScreen; // 1 if full-screen - u32 Width; - u32 Height; - u32 Pitch; - u32 Zoomed; - u32 ZWidth; - u32 ZHeight; - u32 DispColors; // colors on the screen - u32 MaxPalColors; // total possible colors in palette (usually 256) - u32 PalColorsInUse; // Used colors in palette (usually 236) - u32 StartPalColor; // first usable color index (usually 10) - u32 EndPalColor; // last usable color index (usually 246) - RGBQUAD Palette[256]; - u32 PalType; - u32 forceredraw; // force a complete redraw on next blit (for >8bit) - u32 didapalette; // force an invalidate on the next palette change - - void PTR4* Buffer; - void PTR4* DIBRestore; - u32 OurBitmap; - u32 OrigBitmap; - u32 OurPalette; - u32 WinGDC; - u32 FullFocused; - u32 ParentHwnd; - u32 OldParWndProc; - u32 OldDispWndProc; - u32 DispHwnd; - u32 WinGBufHandle; - void PTR4* lpDD; - void PTR4* lpDDSP; - u32 DDSurfaceType; - HSMACKBLIT DDblit; - s32 ddSoftwarecur; - s32 didaddblit; - s32 lastwasdd; - RECT ddscreen; - s32 manyblits; - s32 PTR4* blitrects; - s32 PTR4* rectsptr; - s32 maxrects; - s32 numrects; - HDC lastdc; - } SmackBuf; - - RADEXPFUNC void RADEXPLINK SmackGet(Smack PTR4* smk,void PTR4* dest); - RADEXPFUNC void RADEXPLINK SmackBufferGet( SmackBuf PTR4* sbuf, void PTR4* dest); - - RADEXPFUNC u8 RADEXPLINK SmackSoundUseMSS(void PTR4* dd); - RADEXPFUNC u8 RADEXPLINK SmackSoundUseDirectSound(void PTR4* dd); // NULL=Create - RADEXPFUNC void RADEXPLINK SmackSoundSetDirectSoundHWND(HWND hw); - RADEXPFUNC u8 RADEXPLINK SmackSoundUseDW(u32 openfreq, u32 openbits, u32 openchans); - - #define SmackTimerSetup() - #define SmackTimerDone() - #define SmackTimerRead timeGetTime - - #endif - - #endif - - #ifdef __RADMAC__ - RADEXPFUNC SmackBuf PTR4* RADEXPLINK SmackBufferOpen( WindowPtr wp, u32 BlitType, u32 width, u32 height, u32 ZoomW, u32 ZoomH ); - RADEXPFUNC u32 RADEXPLINK SmackBufferBlit( SmackBuf PTR4* sbuf, s32 hwndx, s32 hwndy, s32 subx, s32 suby, s32 subw, s32 subh ); - RADEXPFUNC void RADEXPLINK SmackBufferFromScreen( SmackBuf PTR4* destbuf, s32 x, s32 y); - - RADEXPFUNC s32 RADEXPLINK SmackIsSoftwareCursor(GDHandle gd); - RADEXPFUNC s32 RADEXPLINK SmackCheckCursor(WindowPtr wp,s32 x,s32 y,s32 w,s32 h); - RADEXPFUNC void RADEXPLINK SmackRestoreCursor(s32 checkcount); - #else - RADEXPFUNC SmackBuf PTR4* RADEXPLINK SmackBufferOpen( HWND wnd, u32 BlitType, u32 width, u32 height, u32 ZoomW, u32 ZoomH ); - RADEXPFUNC u32 RADEXPLINK SmackBufferBlit( SmackBuf PTR4* sbuf, HDC dc, s32 hwndx, s32 hwndy, s32 subx, s32 suby, s32 subw, s32 subh ); - RADEXPFUNC void RADEXPLINK SmackBufferFromScreen( SmackBuf PTR4* destbuf, HWND hw, s32 x, s32 y); - - RADEXPFUNC s32 RADEXPLINK SmackIsSoftwareCursor(void* lpDDSP,HCURSOR cur); - RADEXPFUNC s32 RADEXPLINK SmackCheckCursor(HWND wnd,s32 x,s32 y,s32 w,s32 h); - RADEXPFUNC void RADEXPLINK SmackRestoreCursor(s32 checkcount); - #endif - - RADEXPFUNC void RADEXPLINK SmackBufferStartMultipleBlits( SmackBuf PTR4* sbuf ); - RADEXPFUNC void RADEXPLINK SmackBufferEndMultipleBlits( SmackBuf PTR4* sbuf ); - - RADEXPFUNC char PTR4* RADEXPLINK SmackBufferString(SmackBuf PTR4* sb,char PTR4* dest); - - RADEXPFUNC void RADEXPLINK SmackBufferNewPalette( SmackBuf PTR4* sbuf, const void PTR4* pal, u32 paltype ); - RADEXPFUNC u32 RADEXPLINK SmackBufferSetPalette( SmackBuf PTR4* sbuf ); - RADEXPFUNC void RADEXPLINK SmackBufferClose( SmackBuf PTR4* sbuf ); - - RADEXPFUNC void RADEXPLINK SmackBufferClear( SmackBuf PTR4* destbuf, u32 color); - - RADEXPFUNC void RADEXPLINK SmackBufferToBuffer( SmackBuf PTR4* destbuf, s32 destx, s32 desty, const SmackBuf PTR4* sourcebuf,s32 sourcex,s32 sourcey,s32 sourcew,s32 sourceh); - RADEXPFUNC void RADEXPLINK SmackBufferToBufferTrans( SmackBuf PTR4* destbuf, s32 destx, s32 desty, const SmackBuf PTR4* sourcebuf,s32 sourcex,s32 sourcey,s32 sourcew,s32 sourceh,u32 TransColor); - RADEXPFUNC void RADEXPLINK SmackBufferToBufferMask( SmackBuf PTR4* destbuf, s32 destx, s32 desty, const SmackBuf PTR4* sourcebuf,s32 sourcex,s32 sourcey,s32 sourcew,s32 sourceh,u32 TransColor,const SmackBuf PTR4* maskbuf); - RADEXPFUNC void RADEXPLINK SmackBufferToBufferMerge( SmackBuf PTR4* destbuf, s32 destx, s32 desty, const SmackBuf PTR4* sourcebuf,s32 sourcex,s32 sourcey,s32 sourcew,s32 sourceh,u32 TransColor,const SmackBuf PTR4* mergebuf); - RADEXPFUNC void RADEXPLINK SmackBufferCopyPalette( SmackBuf PTR4* destbuf, SmackBuf PTR4* sourcebuf, u32 remap); - - RADEXPFUNC u32 RADEXPLINK SmackBufferFocused( SmackBuf PTR4* sbuf); - -#endif - -RADDEFEND - -#endif - -#endif