Skip to content

Commit

Permalink
SmackerLib API (#303)
Browse files Browse the repository at this point in the history
* adds better smack support

* more docs
  • Loading branch information
dethrace-labs committed Apr 19, 2023
1 parent ef9e4d6 commit f3515d5
Show file tree
Hide file tree
Showing 11 changed files with 237 additions and 119 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ option(DETHRACE_FIX_BUGS "Fix Dethrace bugs" ON)

add_subdirectory(src/harness)
add_subdirectory(src/S3)
add_subdirectory(src/smackw32)
add_subdirectory(src/BRSRC13)
add_subdirectory(src/DETHRACE)

Expand Down
19 changes: 12 additions & 7 deletions docs/CODE_LAYOUT.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,32 @@
### DETHRACE
Game logic. According to the symbol dump, these files were originally stored in `C:\DETHRACE\src`.

- `DETHRACE/common` - all common logic
- `DETHRACE/pc-dos` - all platform-specific functions (DOS, in this case)
- `DETHRACE/common` - common game logic
- `DETHRACE/pc-dos` - DOS-specific functions
- `DETHRACE/win95sys.c` - Windows-specific functions
- `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

Graphics rendering library. [BRender](https://en.wikipedia.org/wiki/Argonaut_Games#BRender), originally stored in `C:\BRSRC13`.

- 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

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

- 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
12 changes: 6 additions & 6 deletions lib/libsmacker/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
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)
target_compile_options(smacker PRIVATE -Wall)
target_compile_options(libsmacker PRIVATE -Wall)
else()
target_compile_definitions(smacker PRIVATE -D_CRT_SECURE_NO_WARNINGS)
target_compile_definitions(libsmacker PRIVATE -D_CRT_SECURE_NO_WARNINGS)
endif()

target_sources(smacker PRIVATE
target_sources(libsmacker PRIVATE
smacker.c
smk_bitstream.c
smk_hufftree.c
Expand Down
2 changes: 1 addition & 1 deletion src/DETHRACE/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ target_include_directories(dethrace_obj
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")
Expand Down
75 changes: 28 additions & 47 deletions src/DETHRACE/common/cutscene.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include "input.h"
#include "loading.h"
#include "pd/sys.h"
#include "smacker.h"
#include "smackw32/smackw32.h"
#include "sound.h"
#include "utility.h"
#include <stdlib.h>
Expand Down Expand Up @@ -60,94 +60,75 @@ void PlaySmackerFile(char* pSmack_name) {
tPath_name the_path;
br_colour* br_colours_ptr;
tU8* smack_colours_ptr;
// Smack* smk;
Smack* smk;
int i;
int j;
int len;
int fuck_off;

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) {
StopMusic();
FadePaletteDown();
ClearEntireScreen();
SmackSoundUseDirectSound(NULL);
br_colours_ptr = gCurrent_palette->pixels;
PathCat(the_path, gApplication_path, "CUTSCENE");
PathCat(the_path, the_path, pSmack_name);

dr_dprintf("Trying to open smack file '%s'", the_path);
s = smk_open_file(the_path, SMK_MODE_MEMORY);
if (s == NULL) {
smk = SmackOpen(the_path, SMACKTRACKS, SMACKAUTOEXTRA);
if (smk == NULL) {
dr_dprintf("Unable to open smack file - attempt to load smack from CD...");
if (GetCDPathFromPathsTxtFile(the_path)) {
strcat(the_path, gDir_separator);
strcat(the_path, "DATA");
PathCat(the_path, the_path, "CUTSCENE");
PathCat(the_path, the_path, pSmack_name);
if (PDCheckDriveExists(the_path)) {
s = smk_open_file(the_path, SMK_MODE_MEMORY);
smk = SmackOpen(the_path, SMACKTRACKS, SMACKAUTOEXTRA);
}
} else {
dr_dprintf("Can't get CD directory name");
}
}
if (s != NULL) {
if (smk != NULL) {
dr_dprintf("Smack file opened OK");
smk_info_all(s, NULL, &f, &usf);
smk_info_video(s, &w, &h, NULL);
double fps = 1000000.0 / usf;
int delay_ms = (1 / fps) * 1000;

smk_enable_video(s, 1);

smk_first(s);
do {
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();
for (i = 1; i <= smk->Frames; i++) {
SmackToBuffer(smk, 0, 0, gBack_screen->row_bytes, gBack_screen->height, gBack_screen->pixels, 0);

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];
if (smk->NewPalette) {
smack_colours_ptr = smk->Palette;
for (j = 0; j < 256; j++) {
br_colours_ptr[j] = (smack_colours_ptr[j * 3] << 16) | smack_colours_ptr[j * 3 + 2] | (smack_colours_ptr[j * 3 + 1] << 8);
}

// 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);
last_frame_time = PDGetTotalTime();

do {
fuck_off = AnyKeyDown() || EitherMouseButtonDown();
// added by dethrace to avoid 100% cpu
gHarness_platform.Sleep(1);
} while (!fuck_off && PDGetTotalTime() - last_frame_time < delay_ms);
} while (!fuck_off && SmackWait(smk));
if (fuck_off) {
break;
}
} while (smk_next(s) == SMK_MORE);

smk_close(s);

}
FadePaletteDown();
ClearEntireScreen();
StartMusic();
SmackClose(smk);
} else {
dr_dprintf("Smack file '%s' failed to open", pSmack_name);
StartMusic();
}
StartMusic();
}
}

Expand Down
56 changes: 0 additions & 56 deletions src/DETHRACE/dr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -2942,62 +2942,6 @@ typedef struct _tag_sos_timer_system {
W32 wMIDIActiveSongHandle;
} _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
typedef struct _heapinfo {
void* _pentry;
Expand Down
3 changes: 1 addition & 2 deletions src/harness/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ if(DETHRACE_FIX_BUGS)
target_compile_definitions(harness PRIVATE DETHRACE_FIX_BUGS)
endif()

target_link_libraries(harness PRIVATE brender compile_with_werror)
target_link_libraries(harness PRIVATE brender s3 compile_with_werror)

if(WIN32)
target_link_libraries(harness PRIVATE dbghelp)
Expand Down Expand Up @@ -89,7 +89,6 @@ if (IO_PLATFORM STREQUAL "SDL_OpenGL")
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/S3/include")
target_link_libraries(harness PRIVATE SDL2::SDL2 glad)
endif()

Expand Down
24 changes: 24 additions & 0 deletions src/smackw32/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
)
10 changes: 10 additions & 0 deletions src/smackw32/README.md
Original file line number Diff line number Diff line change
@@ -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
55 changes: 55 additions & 0 deletions src/smackw32/include/smackw32/smackw32.h
Original file line number Diff line number Diff line change
@@ -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);
Loading

0 comments on commit f3515d5

Please sign in to comment.