Fix for running with -robots + implement DOS gore password check (#249)

* Fix SIGSEGV when running with -robots

We cannot write to read-only memory.

* Add --dos-mode argument to require entering password
This commit is contained in:
Anonymous Maarten 2023-04-01 02:42:28 +00:00 committed by GitHub
parent 3a91a526c8
commit dd6a7cbc6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 124 additions and 5 deletions

View File

@ -335,7 +335,13 @@ void Init2DStuff() {
// IDA: void __usercall InitialiseApplication(int pArgc@<EAX>, char **pArgv@<EDX>)
void InitialiseApplication(int pArgc, char** pArgv) {
gProgram_state.sausage_eater_mode = gSausage_override;
if (harness_game_config.dos_mode) {
gProgram_state.sausage_eater_mode = gSausage_override ? 1 : (PDGetGorePassword() ? 0 : 1);
PDDisplayGoreworthiness(!gProgram_state.sausage_eater_mode);
} else {
gProgram_state.sausage_eater_mode = gSausage_override;
}
MAMSInitMem();
PrintMemoryDump(gSausage_override, *pArgv);
if (gAustere_override || PDDoWeLeadAnAustereExistance() != 0) {

View File

@ -110,22 +110,30 @@ void InitSkids() {
int sl;
br_model* square;
char* str;
#if defined(DETHRACE_FIX_BUGS)
char mat_name[32];
#endif
LOG_TRACE("()");
for (mat = 0; mat < 2; mat++) {
for (mat = 0; mat < COUNT_OF(gMaterial_names); mat++) {
if (gProgram_state.sausage_eater_mode) {
str = gBoring_material_names[mat];
} else {
str = gMaterial_names[mat];
}
gMaterial[mat] = BrMaterialFind(str);
if (!gMaterial[mat]) {
if (gMaterial[mat] == NULL) {
if (gProgram_state.sausage_eater_mode) {
str = gBoring_material_names[mat];
} else {
str = gMaterial_names[mat];
}
#if defined(DETHRACE_FIX_BUGS)
// Avoid modification of read-only data by strtok.
strcpy(mat_name, str);
str = mat_name;
#endif
sl = strlen(strtok(str, "."));
strcpy(str + sl, ".PIX");
BrMapAdd(LoadPixelmap(str));

View File

@ -687,6 +687,34 @@ int OurGetChar() {
NOT_IMPLEMENTED();
}
int CheckGorePasswordFile(char* pPassword) {
tPath_name path;
FILE* f;
char line[10];
PathCat(path, "DATA", "PASS.TXT");
f = fopen(path, "rb");
if (f == NULL) {
return 0;
}
if (fgets(line, sizeof(line), f) == NULL) {
fclose(f);
return 0;
}
fclose(f);
#if defined(DETHRACE_FIX_BUGS)
// Allow a final newline in DATA/PASS.TXT
while (strlen(line) > 0 && (line[strlen(line) - 1] == '\n' || line[strlen(line) - 1] == '\r')) {
line[strlen(line) - 1] = '\0';
}
#endif
#ifdef _WIN32
return stricmp(line, pPassword) == 0;
#else
return strcasecmp(line, pPassword) == 0;
#endif
}
// IDA: int __cdecl PDGetGorePassword()
int PDGetGorePassword() {
int ch;
@ -694,14 +722,26 @@ int PDGetGorePassword() {
int chances;
char password[17];
LOG_TRACE("()");
NOT_IMPLEMENTED();
for (chances = 0; chances < 3; chances++) {
printf(chances == 0 ? "\n\n\n\n\nEnter password for uncut version...\n" : "\nIncorrect password, please try again...\n");
OS_ConsoleReadPassword(password, sizeof(password));
dr_dprintf("Password entered is '%s'", password);
if (CheckGorePasswordFile(password)) {
return 1;
}
}
return 0;
}
// IDA: void __usercall PDDisplayGoreworthiness(int pGory@<EAX>)
void PDDisplayGoreworthiness(int pGory) {
tU32 delay_start;
LOG_TRACE("(%d)", pGory);
NOT_IMPLEMENTED();
printf(pGory ? "\nPlaying full version...\n" : "\nPlaying zombie version...\n");
delay_start = 2;
OS_Sleep(delay_start * 1000);
}
// IDA: void __usercall PDEnterDebugger(char *pStr@<EAX>)

View File

@ -195,6 +195,8 @@ void Harness_Init(int* argc, char* argv[]) {
harness_game_config.start_full_screen = 0;
// disable replay by default
harness_game_config.enable_replay = 0;
// Emulate DOS behavior
harness_game_config.dos_mode = 0;
// install signal handler by default
harness_game_config.install_signalhandler = 1;
@ -286,6 +288,9 @@ int Harness_ProcessCommandLine(int* argc, char* argv[]) {
} else if (strcasecmp(argv[i], "--enable-replay") == 0) {
harness_game_config.enable_replay = 1;
handled = 1;
} else if (strcasecmp(argv[i], "--dos-mode") == 0) {
harness_game_config.dos_mode = 1;
handled = 1;
}
if (handled) {

View File

@ -40,6 +40,7 @@ typedef struct tHarness_game_config {
float volume_multiplier;
int start_full_screen;
int enable_replay;
int dos_mode;
int install_signalhandler;
} tHarness_game_config;

View File

@ -49,4 +49,6 @@ FILE* OS_fopen(const char* pathname, const char* mode);
// Required: return a buffer for action replay. Preferably 20MB. If that is not available, then allocate a buffer of 12MB, 6MB, 4MB, 500kB or 64kiB
void OS_AllocateActionReplayBuffer(char** pBuffer, unsigned* pBuffer_size);
size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen);
#endif

View File

@ -20,6 +20,7 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
@ -367,3 +368,45 @@ void OS_AllocateActionReplayBuffer(char** pBuffer, unsigned* pBuffer_size) {
*pBuffer = buffer;
*pBuffer_size = buffer_size;
}
size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen) {
struct termios old, new;
char c;
size_t len;
tcgetattr(STDIN_FILENO, &old);
new = old;
new.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &new);
len = 0;
pBuffer[len] = '\0';
while (1) {
if (read(STDIN_FILENO, &c, 1) == 1) {
if (c == 0x7f) {
if (len > 0) {
len--;
pBuffer[len] = '\0';
printf("\033[1D \033[1D");
fflush(stdout);
continue;
}
} else if (c == '\r' || c == '\n') {
printf("\n");
fflush(stdout);
break;
} else if (len < pBufferLen - 1) {
if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
pBuffer[len] = c;
printf("*");
fflush(stdout);
len++;
pBuffer[len] = '\0';
}
}
}
}
tcsetattr(STDIN_FILENO, TCSANOW, &old);
return len;
}

View File

@ -324,3 +324,10 @@ void OS_AllocateActionReplayBuffer(char** pBuffer, unsigned* pBuffer_size) {
*pBuffer = buffer;
*pBuffer_size = buffer_size;
}
size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen) {
// FIXME: unsafe implementation (echos the password)
pBuffer[0] = '\0';
fgets(pBuffer, pBufferLen, stdin);
return strlen(pBuffer);
}

View File

@ -308,3 +308,10 @@ void OS_AllocateActionReplayBuffer(char** pBuffer, unsigned* pBuffer_size) {
*pBuffer = buffer;
*pBuffer_size = buffer_size;
}
size_t OS_ConsoleReadPassword(char* pBuffer, size_t pBufferLen) {
// FIXME: unsafe implementation (echos the password)
pBuffer[0] = '\0';
fgets(pBuffer, pBufferLen, stdin);
return strlen(pBuffer);
}