parent
ef9e4d668d
commit
f3515d5f64
|
@ -67,6 +67,7 @@ option(DETHRACE_FIX_BUGS "Fix Dethrace bugs" ON)
|
||||||
|
|
||||||
add_subdirectory(src/harness)
|
add_subdirectory(src/harness)
|
||||||
add_subdirectory(src/S3)
|
add_subdirectory(src/S3)
|
||||||
|
add_subdirectory(src/smackw32)
|
||||||
add_subdirectory(src/BRSRC13)
|
add_subdirectory(src/BRSRC13)
|
||||||
add_subdirectory(src/DETHRACE)
|
add_subdirectory(src/DETHRACE)
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
### DETHRACE
|
### DETHRACE
|
||||||
Game logic. According to the symbol dump, these files were originally stored in `C:\DETHRACE\src`.
|
Game logic. According to the symbol dump, these files were originally stored in `C:\DETHRACE\src`.
|
||||||
|
|
||||||
- `DETHRACE/common` - all common logic
|
- `DETHRACE/common` - common game logic
|
||||||
- `DETHRACE/pc-dos` - all platform-specific functions (DOS, in this case)
|
- `DETHRACE/pc-dos` - DOS-specific functions
|
||||||
|
- `DETHRACE/win95sys.c` - Windows-specific functions
|
||||||
- `DETHRACE/pd` - platform-dependent generic headers.
|
- `DETHRACE/pd` - platform-dependent generic headers.
|
||||||
|
|
||||||
_All code here is kept as similar to how we think the original code might have been. Any changes required are implemented as hooks into `harness`._
|
_All code here is kept as similar to how we think the original code might have looked. Any changes required are implemented as hooks into `harness`._
|
||||||
|
|
||||||
### BRSRC13
|
### BRSRC13
|
||||||
|
|
||||||
|
@ -15,15 +16,19 @@ Graphics rendering library. [BRender](https://en.wikipedia.org/wiki/Argonaut_Gam
|
||||||
|
|
||||||
- Stainless Software used their own build of BRender with unknown modifications.
|
- Stainless Software used their own build of BRender with unknown modifications.
|
||||||
|
|
||||||
_All code here is kept as similar to how we think the original code might have been. Any changes required are implemented as hooks into `harness`._
|
_All code here is kept as similar to how we think the original code might have looked. Any changes required are implemented as hooks into `harness`._
|
||||||
|
|
||||||
### S3
|
### S3
|
||||||
|
|
||||||
Audio library. No other information.
|
Audio library. Possibly short for "Stainless Sound System"?! Supports at least two audio backends - [SOS](http://web.archive.org/web/19990221132448/http://www.humanmachine.com/sos.html) (DOS) and DirectSound.
|
||||||
|
|
||||||
_All code here is kept as similar to how we think the original code might have been. Any changes required are implemented as hooks into `harness`._
|
_All code here is kept as similar to how we think the original code might have looked, with the addition of a small amount of code integrating [miniaudio](https://miniaud.io)
|
||||||
|
|
||||||
|
### smackw32
|
||||||
|
|
||||||
|
Implements the [RAD Smacker lib](https://wiki.multimedia.cx/index.php/RAD_Game_Tools_Smacker_API) interface. The implementation is backed by [libsmacker](https://libsmacker.sourceforge.net/).
|
||||||
|
|
||||||
### harness
|
### harness
|
||||||
|
|
||||||
- Provides functions that the original game logic calls to implement modern cross-platform support.
|
- Provides functions that the original game logic calls to implement modern cross-platform support.
|
||||||
- SDL2 for windowing + input + networking, OpenGL for rendering, OpenAL for audio
|
- SDL2, OpenGL, miniaudio
|
||||||
|
|
|
@ -6,21 +6,21 @@ if(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo" FORCE)
|
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(smacker C)
|
project(libsmacker C)
|
||||||
|
|
||||||
add_library(smacker STATIC)
|
add_library(libsmacker STATIC)
|
||||||
|
|
||||||
target_include_directories(smacker PUBLIC
|
target_include_directories(libsmacker PUBLIC
|
||||||
.
|
.
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
target_compile_options(smacker PRIVATE -Wall)
|
target_compile_options(libsmacker PRIVATE -Wall)
|
||||||
else()
|
else()
|
||||||
target_compile_definitions(smacker PRIVATE -D_CRT_SECURE_NO_WARNINGS)
|
target_compile_definitions(libsmacker PRIVATE -D_CRT_SECURE_NO_WARNINGS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_sources(smacker PRIVATE
|
target_sources(libsmacker PRIVATE
|
||||||
smacker.c
|
smacker.c
|
||||||
smk_bitstream.c
|
smk_bitstream.c
|
||||||
smk_hufftree.c
|
smk_hufftree.c
|
||||||
|
|
|
@ -10,7 +10,7 @@ target_include_directories(dethrace_obj
|
||||||
pd
|
pd
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(dethrace_obj PUBLIC SDL2::SDL2 smacker harness brender s3)
|
target_link_libraries(dethrace_obj PUBLIC SDL2::SDL2 smackw32 harness brender s3)
|
||||||
|
|
||||||
|
|
||||||
if (CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
if (CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "loading.h"
|
#include "loading.h"
|
||||||
#include "pd/sys.h"
|
#include "pd/sys.h"
|
||||||
#include "smacker.h"
|
#include "smackw32/smackw32.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -60,32 +60,24 @@ void PlaySmackerFile(char* pSmack_name) {
|
||||||
tPath_name the_path;
|
tPath_name the_path;
|
||||||
br_colour* br_colours_ptr;
|
br_colour* br_colours_ptr;
|
||||||
tU8* smack_colours_ptr;
|
tU8* smack_colours_ptr;
|
||||||
// Smack* smk;
|
Smack* smk;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
int len;
|
int len;
|
||||||
int fuck_off;
|
int fuck_off;
|
||||||
|
|
||||||
LOG_TRACE("(\"%s\")", pSmack_name);
|
LOG_TRACE("(\"%s\")", pSmack_name);
|
||||||
|
|
||||||
smk s;
|
|
||||||
br_uint_8* dest_pix = (br_uint_8*)gBack_screen->pixels;
|
|
||||||
unsigned long w, h, f;
|
|
||||||
unsigned char r, g, b;
|
|
||||||
double usf;
|
|
||||||
tU32 last_frame_time;
|
|
||||||
|
|
||||||
if (!gSound_override && !gCut_scene_override) {
|
if (!gSound_override && !gCut_scene_override) {
|
||||||
StopMusic();
|
StopMusic();
|
||||||
FadePaletteDown();
|
FadePaletteDown();
|
||||||
ClearEntireScreen();
|
ClearEntireScreen();
|
||||||
|
SmackSoundUseDirectSound(NULL);
|
||||||
br_colours_ptr = gCurrent_palette->pixels;
|
br_colours_ptr = gCurrent_palette->pixels;
|
||||||
PathCat(the_path, gApplication_path, "CUTSCENE");
|
PathCat(the_path, gApplication_path, "CUTSCENE");
|
||||||
PathCat(the_path, the_path, pSmack_name);
|
PathCat(the_path, the_path, pSmack_name);
|
||||||
|
|
||||||
dr_dprintf("Trying to open smack file '%s'", the_path);
|
dr_dprintf("Trying to open smack file '%s'", the_path);
|
||||||
s = smk_open_file(the_path, SMK_MODE_MEMORY);
|
smk = SmackOpen(the_path, SMACKTRACKS, SMACKAUTOEXTRA);
|
||||||
if (s == NULL) {
|
if (smk == NULL) {
|
||||||
dr_dprintf("Unable to open smack file - attempt to load smack from CD...");
|
dr_dprintf("Unable to open smack file - attempt to load smack from CD...");
|
||||||
if (GetCDPathFromPathsTxtFile(the_path)) {
|
if (GetCDPathFromPathsTxtFile(the_path)) {
|
||||||
strcat(the_path, gDir_separator);
|
strcat(the_path, gDir_separator);
|
||||||
|
@ -93,61 +85,50 @@ void PlaySmackerFile(char* pSmack_name) {
|
||||||
PathCat(the_path, the_path, "CUTSCENE");
|
PathCat(the_path, the_path, "CUTSCENE");
|
||||||
PathCat(the_path, the_path, pSmack_name);
|
PathCat(the_path, the_path, pSmack_name);
|
||||||
if (PDCheckDriveExists(the_path)) {
|
if (PDCheckDriveExists(the_path)) {
|
||||||
s = smk_open_file(the_path, SMK_MODE_MEMORY);
|
smk = SmackOpen(the_path, SMACKTRACKS, SMACKAUTOEXTRA);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dr_dprintf("Can't get CD directory name");
|
dr_dprintf("Can't get CD directory name");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s != NULL) {
|
if (smk != NULL) {
|
||||||
dr_dprintf("Smack file opened OK");
|
dr_dprintf("Smack file opened OK");
|
||||||
smk_info_all(s, NULL, &f, &usf);
|
for (i = 1; i <= smk->Frames; i++) {
|
||||||
smk_info_video(s, &w, &h, NULL);
|
SmackToBuffer(smk, 0, 0, gBack_screen->row_bytes, gBack_screen->height, gBack_screen->pixels, 0);
|
||||||
double fps = 1000000.0 / usf;
|
|
||||||
int delay_ms = (1 / fps) * 1000;
|
|
||||||
|
|
||||||
smk_enable_video(s, 1);
|
if (smk->NewPalette) {
|
||||||
|
smack_colours_ptr = smk->Palette;
|
||||||
smk_first(s);
|
for (j = 0; j < 256; j++) {
|
||||||
do {
|
br_colours_ptr[j] = (smack_colours_ptr[j * 3] << 16) | smack_colours_ptr[j * 3 + 2] | (smack_colours_ptr[j * 3 + 1] << 8);
|
||||||
const unsigned char* pal = smk_get_palette(s);
|
|
||||||
for (i = 0; i < 256; i++) {
|
|
||||||
r = pal[(i * 3)];
|
|
||||||
g = pal[(i * 3) + 1];
|
|
||||||
b = pal[(i * 3) + 2];
|
|
||||||
br_colours_ptr[i] = b | (g << 8) | (r << 16);
|
|
||||||
}
|
|
||||||
DRSetPalette(gCurrent_palette);
|
|
||||||
EnsurePaletteUp();
|
|
||||||
|
|
||||||
const unsigned char* frame = smk_get_video(s);
|
|
||||||
for (i = 0; i < h; i++) {
|
|
||||||
for (j = 0; j < w; j++) {
|
|
||||||
dest_pix[(i * gBack_screen->row_bytes) + j] = frame[i * w + j];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TOOD: remove the commented-out line below when smk->NewPalette is set correctly per-frame
|
||||||
|
// memset(gBack_screen->pixels, 0, gBack_screen->row_bytes * gBack_screen->height);
|
||||||
|
DRSetPalette(gCurrent_palette);
|
||||||
|
PDScreenBufferSwap(0);
|
||||||
|
EnsurePaletteUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
SmackDoFrame(smk);
|
||||||
|
if (i != smk->Frames) {
|
||||||
|
SmackNextFrame(smk);
|
||||||
}
|
}
|
||||||
PDScreenBufferSwap(0);
|
PDScreenBufferSwap(0);
|
||||||
last_frame_time = PDGetTotalTime();
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
fuck_off = AnyKeyDown() || EitherMouseButtonDown();
|
fuck_off = AnyKeyDown() || EitherMouseButtonDown();
|
||||||
// added by dethrace to avoid 100% cpu
|
} while (!fuck_off && SmackWait(smk));
|
||||||
gHarness_platform.Sleep(1);
|
|
||||||
} while (!fuck_off && PDGetTotalTime() - last_frame_time < delay_ms);
|
|
||||||
if (fuck_off) {
|
if (fuck_off) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (smk_next(s) == SMK_MORE);
|
}
|
||||||
|
|
||||||
smk_close(s);
|
|
||||||
|
|
||||||
FadePaletteDown();
|
FadePaletteDown();
|
||||||
ClearEntireScreen();
|
ClearEntireScreen();
|
||||||
StartMusic();
|
SmackClose(smk);
|
||||||
} else {
|
} else {
|
||||||
dr_dprintf("Smack file '%s' failed to open", pSmack_name);
|
dr_dprintf("Smack file '%s' failed to open", pSmack_name);
|
||||||
StartMusic();
|
|
||||||
}
|
}
|
||||||
|
StartMusic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2942,62 +2942,6 @@ typedef struct _tag_sos_timer_system {
|
||||||
W32 wMIDIActiveSongHandle;
|
W32 wMIDIActiveSongHandle;
|
||||||
} _SOS_TIMER_SYSTEM;
|
} _SOS_TIMER_SYSTEM;
|
||||||
|
|
||||||
typedef struct SmackTag {
|
|
||||||
unsigned long Version;
|
|
||||||
unsigned long Width;
|
|
||||||
unsigned long Height;
|
|
||||||
unsigned long Frames;
|
|
||||||
unsigned long MSPerFrame;
|
|
||||||
unsigned long SmackerType;
|
|
||||||
unsigned long LargestInTrack[7];
|
|
||||||
unsigned long tablesize;
|
|
||||||
unsigned long codesize;
|
|
||||||
unsigned long absize;
|
|
||||||
unsigned long detailsize;
|
|
||||||
unsigned long typesize;
|
|
||||||
unsigned long TrackType[7];
|
|
||||||
unsigned long extra;
|
|
||||||
unsigned long NewPalette;
|
|
||||||
unsigned char Palette[772];
|
|
||||||
unsigned long PalType;
|
|
||||||
unsigned long FrameNum;
|
|
||||||
unsigned long FrameSize;
|
|
||||||
unsigned long SndSize;
|
|
||||||
unsigned long LastRectx;
|
|
||||||
unsigned long LastRecty;
|
|
||||||
unsigned long LastRectw;
|
|
||||||
unsigned long LastRecth;
|
|
||||||
unsigned long OpenFlags;
|
|
||||||
unsigned long LeftOfs;
|
|
||||||
unsigned long TopOfs;
|
|
||||||
unsigned long ReadError;
|
|
||||||
unsigned long addr32;
|
|
||||||
} Smack;
|
|
||||||
|
|
||||||
typedef struct SmackSumTag {
|
|
||||||
unsigned long TotalTime;
|
|
||||||
unsigned long MS100PerFrame;
|
|
||||||
unsigned long TotalOpenTime;
|
|
||||||
unsigned long TotalFrames;
|
|
||||||
unsigned long SkippedFrames;
|
|
||||||
unsigned long SoundSkips;
|
|
||||||
unsigned long TotalBlitTime;
|
|
||||||
unsigned long TotalReadTime;
|
|
||||||
unsigned long TotalDecompTime;
|
|
||||||
unsigned long TotalBackReadTime;
|
|
||||||
unsigned long TotalReadSpeed;
|
|
||||||
unsigned long SlowestFrameTime;
|
|
||||||
unsigned long Slowest2FrameTime;
|
|
||||||
unsigned long SlowestFrameNum;
|
|
||||||
unsigned long Slowest2FrameNum;
|
|
||||||
unsigned long AverageFrameSize;
|
|
||||||
unsigned long Highest1SecRate;
|
|
||||||
unsigned long Highest1SecFrame;
|
|
||||||
unsigned long HighestMemAmount;
|
|
||||||
unsigned long TotalExtraMemory;
|
|
||||||
unsigned long HighestExtraUsed;
|
|
||||||
} SmackSum;
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
typedef struct _heapinfo {
|
typedef struct _heapinfo {
|
||||||
void* _pentry;
|
void* _pentry;
|
||||||
|
|
|
@ -20,7 +20,7 @@ if(DETHRACE_FIX_BUGS)
|
||||||
target_compile_definitions(harness PRIVATE DETHRACE_FIX_BUGS)
|
target_compile_definitions(harness PRIVATE DETHRACE_FIX_BUGS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(harness PRIVATE brender compile_with_werror)
|
target_link_libraries(harness PRIVATE brender s3 compile_with_werror)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(harness PRIVATE dbghelp)
|
target_link_libraries(harness PRIVATE dbghelp)
|
||||||
|
@ -89,7 +89,6 @@ if (IO_PLATFORM STREQUAL "SDL_OpenGL")
|
||||||
resources/3d_frag.glsl.h
|
resources/3d_frag.glsl.h
|
||||||
)
|
)
|
||||||
target_include_directories(harness PRIVATE "${dethrace_SOURCE_DIR}/src/DETHRACE/common")
|
target_include_directories(harness PRIVATE "${dethrace_SOURCE_DIR}/src/DETHRACE/common")
|
||||||
target_include_directories(harness PRIVATE "${dethrace_SOURCE_DIR}/src/S3/include")
|
|
||||||
target_link_libraries(harness PRIVATE SDL2::SDL2 glad)
|
target_link_libraries(harness PRIVATE SDL2::SDL2 glad)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
add_library(smackw32 STATIC)
|
||||||
|
|
||||||
|
target_include_directories(smackw32
|
||||||
|
PUBLIC
|
||||||
|
include
|
||||||
|
PRIVATE
|
||||||
|
${CMAKE_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(smackw32 PRIVATE harness brender libsmacker compile_with_werror)
|
||||||
|
|
||||||
|
if(NOT MSVC)
|
||||||
|
|
||||||
|
else()
|
||||||
|
target_compile_definitions(smackw32 PRIVATE -D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
target_compile_options(smackw32 PRIVATE
|
||||||
|
/wd4101
|
||||||
|
/wd4996
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_sources(smackw32 PRIVATE
|
||||||
|
smackw32.c
|
||||||
|
)
|
|
@ -0,0 +1,10 @@
|
||||||
|
# smackw32
|
||||||
|
|
||||||
|
Implementation of a minimal form of the Smacker API used by dethrace.
|
||||||
|
|
||||||
|
See:
|
||||||
|
- https://wiki.multimedia.cx/index.php/RAD_Game_Tools_Smacker_API
|
||||||
|
- https://github.com/OpenSourcedGames/Aliens-vs-Predator/blob/master/source/AvP_vc/3dc/win95/SMACK.H
|
||||||
|
|
||||||
|
|
||||||
|
Backed by http://libsmacker.sourceforge.net
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define SMACKTRACK1 0x02000 // Play audio track 1
|
||||||
|
#define SMACKTRACK2 0x04000 // Play audio track 2
|
||||||
|
#define SMACKTRACK3 0x08000 // Play audio track 3
|
||||||
|
#define SMACKTRACK4 0x10000 // Play audio track 4
|
||||||
|
#define SMACKTRACK5 0x20000 // Play audio track 5
|
||||||
|
#define SMACKTRACK6 0x40000 // Play audio track 6
|
||||||
|
#define SMACKTRACK7 0x80000 // Play audio track 7
|
||||||
|
#define SMACKTRACKS (SMACKTRACK1 | SMACKTRACK2 | SMACKTRACK3 | SMACKTRACK4 | SMACKTRACK5 | SMACKTRACK6 | SMACKTRACK7)
|
||||||
|
#define SMACKAUTOEXTRA 0xffffffff
|
||||||
|
|
||||||
|
typedef struct SmackTag {
|
||||||
|
unsigned long Version;
|
||||||
|
unsigned long Width;
|
||||||
|
unsigned long Height;
|
||||||
|
unsigned long Frames;
|
||||||
|
unsigned long MSPerFrame;
|
||||||
|
unsigned long SmackerType;
|
||||||
|
unsigned long LargestInTrack[7];
|
||||||
|
unsigned long tablesize;
|
||||||
|
unsigned long codesize;
|
||||||
|
unsigned long absize;
|
||||||
|
unsigned long detailsize;
|
||||||
|
unsigned long typesize;
|
||||||
|
unsigned long TrackType[7];
|
||||||
|
unsigned long extra;
|
||||||
|
unsigned long NewPalette;
|
||||||
|
unsigned char Palette[772];
|
||||||
|
unsigned long PalType;
|
||||||
|
unsigned long FrameNum;
|
||||||
|
unsigned long FrameSize;
|
||||||
|
unsigned long SndSize;
|
||||||
|
unsigned long LastRectx;
|
||||||
|
unsigned long LastRecty;
|
||||||
|
unsigned long LastRectw;
|
||||||
|
unsigned long LastRecth;
|
||||||
|
unsigned long OpenFlags;
|
||||||
|
unsigned long LeftOfs;
|
||||||
|
unsigned long TopOfs;
|
||||||
|
unsigned long ReadError;
|
||||||
|
unsigned long addr32;
|
||||||
|
|
||||||
|
// added by dethrace
|
||||||
|
void* smk_handle;
|
||||||
|
} Smack;
|
||||||
|
|
||||||
|
Smack* SmackOpen(const char* name, uint32_t flags, uint32_t extrabuf);
|
||||||
|
int SmackSoundUseDirectSound(void* dd); // NULL mean create instance (apparently)
|
||||||
|
void SmackToBuffer(Smack* smack, uint32_t left, uint32_t top, uint32_t pitch, uint32_t destheight, void* buf, uint32_t flags);
|
||||||
|
uint32_t SmackDoFrame(Smack* smack);
|
||||||
|
void SmackNextFrame(Smack* smack);
|
||||||
|
uint32_t SmackWait(Smack* smack);
|
||||||
|
void SmackClose(Smack* smack);
|
|
@ -0,0 +1,99 @@
|
||||||
|
#include "include/smackw32/smackw32.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "harness/hooks.h"
|
||||||
|
// lib/libsmacker
|
||||||
|
#include "smacker.h"
|
||||||
|
|
||||||
|
uint32_t smack_last_frame_time;
|
||||||
|
|
||||||
|
void copy_palette(Smack* smack) {
|
||||||
|
const unsigned char* pal = smk_get_palette(smack->smk_handle);
|
||||||
|
memcpy(smack->Palette, pal, 256 * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
Smack* SmackOpen(const char* name, uint32_t flags, uint32_t extrabuf) {
|
||||||
|
double usf;
|
||||||
|
Smack* smack;
|
||||||
|
double fps;
|
||||||
|
|
||||||
|
smk smk_handle = smk_open_file(name, SMK_MODE_MEMORY);
|
||||||
|
if (smk_handle == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
smack = malloc(sizeof(Smack));
|
||||||
|
|
||||||
|
// libsmacker doesn't tell us whether the palette is new on each frame or not, so just assume it always is new
|
||||||
|
smack->NewPalette = 1;
|
||||||
|
|
||||||
|
// smk_handle is added to hold a pointer to the underlying libsmacker instance
|
||||||
|
smack->smk_handle = smk_handle;
|
||||||
|
|
||||||
|
smk_info_all(smk_handle, NULL, &smack->Frames, &usf);
|
||||||
|
fps = 1000000.0 / usf;
|
||||||
|
smack->MSPerFrame = (1 / fps) * 1000;
|
||||||
|
smk_info_video(smk_handle, &smack->Width, &smack->Height, NULL);
|
||||||
|
smk_enable_video(smk_handle, 1);
|
||||||
|
|
||||||
|
if (smk_first(smk_handle) == SMK_ERROR) {
|
||||||
|
smk_close(smk_handle);
|
||||||
|
free(smack);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
copy_palette(smack);
|
||||||
|
return smack;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SmackSoundUseDirectSound(void* dd) {
|
||||||
|
// TODO: do some miniaudio init
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmackToBuffer(Smack* smack, uint32_t left, uint32_t top, uint32_t pitch, uint32_t destheight, void* buf, uint32_t flags) {
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
// minimal implementation
|
||||||
|
assert(left == 0);
|
||||||
|
assert(top == 0);
|
||||||
|
assert(flags == 0);
|
||||||
|
|
||||||
|
char* char_buf = buf;
|
||||||
|
|
||||||
|
const unsigned char* frame = smk_get_video(smack->smk_handle);
|
||||||
|
for (i = 0; i < destheight; i++) {
|
||||||
|
memcpy(&char_buf[(i * pitch)], &frame[i * pitch], pitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SmackDoFrame(Smack* smack) {
|
||||||
|
smack_last_frame_time = gHarness_platform.GetTicks();
|
||||||
|
|
||||||
|
// TODO: audio processing
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmackNextFrame(Smack* smack) {
|
||||||
|
smk_next(smack->smk_handle);
|
||||||
|
copy_palette(smack);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SmackWait(Smack* smack) {
|
||||||
|
uint32_t now = gHarness_platform.GetTicks();
|
||||||
|
if (now < smack_last_frame_time + smack->MSPerFrame) {
|
||||||
|
gHarness_platform.Sleep(1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmackClose(Smack* smack) {
|
||||||
|
smk_close(smack->smk_handle);
|
||||||
|
free(smack);
|
||||||
|
}
|
Loading…
Reference in New Issue