parent
ef9e4d668d
commit
f3515d5f64
|
@ -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)
|
||||
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
### 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
|
||||
|
||||
|
@ -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.
|
||||
|
||||
_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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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>
|
||||
|
@ -60,32 +60,24 @@ 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);
|
||||
|
@ -93,61 +85,50 @@ void PlaySmackerFile(char* pSmack_name) {
|
|||
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;
|
||||
for (i = 1; i <= smk->Frames; i++) {
|
||||
SmackToBuffer(smk, 0, 0, gBack_screen->row_bytes, gBack_screen->height, gBack_screen->pixels, 0);
|
||||
|
||||
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();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
@ -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()
|
||||
|
||||
|
|
|
@ -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