Fixes for Portuguese Carmageddon (#353)

* Fix bugs exposed by Portuguese Carmageddon

* Fixes for warnings/errors found in rec2

* Macos says "no"

* Last argument of _partSet can be a pointer

* feof is a macro dereferencing f on some systems

* Allow longer program_name in addr2ine

* Fix casing issue with sounds

French Carmageddon provides DATA/SOUND/fyeah1.WAV where it expects DATA/SOUND/FYEAH1.WAV

* tools: add encode capability to decode script

* Replace font id integers with enum

* Result of BrFileGetLine is not used

* Document the StripControls fix

Co-authored-by: Dethrace Engineering Department <78985374+dethrace-labs@users.noreply.github.com>

---------

Co-authored-by: Dethrace Engineering Department <78985374+dethrace-labs@users.noreply.github.com>
This commit is contained in:
Anonymous Maarten 2024-05-28 14:59:37 +02:00 committed by GitHub
parent e07b7114a3
commit 62bbf66deb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 192 additions and 106 deletions

View File

@ -308,15 +308,17 @@ int TextReadLine(br_datafile* df, char** ident, char** data) {
LOG_TRACE9("(%p, %p, %p)", df, ident, data);
while (1) {
int a;
cp = BrScratchString();
int a = BrFileGetLine(cp, 256, df->h);
BrFileGetLine(cp, 256, df->h);
if (BrFileEof(df->h) != 0) {
return 0;
}
for (; (*cp == ' ') || (*cp == '\t'); cp++) {
}
if (*cp != '\0')
if (*cp != '\0') {
break;
}
}
*ident = cp;
while ((*cp != ' ') && (*cp != '\t') && (*cp != '\0')) {

View File

@ -114,7 +114,7 @@ br_scalar BrMatrix4Inverse(br_matrix4* A, br_matrix4* B) {
if (fabs(det) < BR_SCALAR_EPSILON * 2)
return 0;
idet = 1.0 / det;
idet = 1.0f / det;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
A(i, j) = A(i, j) * idet;

View File

@ -362,7 +362,7 @@ br_uint_16 BrPixelmapTextWidth(br_pixelmap* dst, br_font* font, char* text) {
if (font->flags & BR_FONTF_PROPORTIONAL) {
for (i = 0, w = 0, j = BrStrLen(text); i < j; i++, text++)
w += font->width[(int)*text] + 1;
w += font->width[*(br_uint_8*)text] + 1;
w -= 1;
return w;
} else

View File

@ -173,10 +173,10 @@ br_error _M_br_device_pixelmap_gen_text(br_device_pixelmap* self, br_point* poin
}
} else {
while (*text != '\0') {
r.w = font->width[(int)*text];
r.w = font->width[*(br_uint_8*)text];
s_stride = (r.w + 7) / 8;
if (x + r.w > 0) {
self->dispatch->_copyBits(self, &p, &font->glyphs[font->encoding[(unsigned)*text]], s_stride, &r, colour);
self->dispatch->_copyBits(self, &p, &font->glyphs[font->encoding[*(br_uint_8*)text]], s_stride, &r, colour);
}
x += r.w + 1;
p.x += r.w + 1;

View File

@ -275,10 +275,11 @@ void pm_mem_copy_bits(br_uint_8* dst, br_uint_32 dst_qual, br_uint_32 dst_stride
colour_byte1 = colour;
for (; height != 0; height--, src += src_stride, dst += dst_stride) {
br_uint_8 row_end_bit_byte;
mask = *src & start_mask;
tmp_dst = dst;
tmp_src = src;
br_uint_8 row_end_bit_byte = end_bit_byte;
row_end_bit_byte = end_bit_byte;
while (row_end_bit_byte != 0) {
if (mask & 0x80) {
tmp_dst[0] = colour_byte1;

View File

@ -89,7 +89,7 @@ void BrStdioClose(void* f) {
}
int BrStdioEof(void* f) {
return feof(f);
return feof((FILE*)f);
}
int BrStdioGetChar(void* f) {

View File

@ -245,9 +245,7 @@ void CopyVertex(v11group* group, int v, prep_vertex* src, br_model* model) {
srcv = model->vertices + src->v;
group->vertices[v].p.v[0] = srcv->p.v[0] - model->pivot.v[0];
group->vertices[v].p.v[1] = srcv->p.v[1] - model->pivot.v[1];
group->vertices[v].p.v[2] = srcv->p.v[2] - model->pivot.v[2];
BrVector3Sub(&group->vertices[v].p, &srcv->p, &model->pivot);
group->vertices[v].map = srcv->map;

View File

@ -355,6 +355,7 @@ int FopWrite_VERTICES(br_datafile* df, br_vertex* vertices, int nvertices) {
df->prims->chunk_write(df, CHUNKID_MODEL_VERTICES, df->prims->struct_size(df, &br_vertex_F, NULL) * nvertices + df->prims->count_size(df));
df->prims->count_write(df, nvertices);
DfStructWriteArray(df, &br_vertex_F, vertices, nvertices);
return 0;
}
// IDA: int __usercall FopRead_VERTICES@<EAX>(br_datafile *df@<EAX>, br_uint_32 id@<EDX>, br_uint_32 length@<EBX>, br_uint_32 count@<ECX>)
@ -389,6 +390,7 @@ int FopWrite_VERTEX_UV(br_datafile* df, br_vertex* vertices, int nvertices) {
df->prims->chunk_write(df, CHUNKID_MODEL_VERTEX_UV, df->prims->struct_size(df, &br_vertex_uv_F, NULL) * nvertices + df->prims->count_size(df));
df->prims->count_write(df, nvertices);
DfStructWriteArray(df, &br_vertex_uv_F, vertices, nvertices);
return 0;
}
// IDA: int __usercall FopRead_VERTEX_UV@<EAX>(br_datafile *df@<EAX>, br_uint_32 id@<EDX>, br_uint_32 length@<EBX>, br_uint_32 count@<ECX>)
@ -413,6 +415,7 @@ int FopRead_OLD_VERTICES_UV(br_datafile* df, br_uint_32 id, br_uint_32 length, b
ptr = BrResAllocate(v1db.res, count * sizeof(br_vertex), BR_MEMORY_VERTICES);
DfStructReadArray(df, &br_old_vertex_uv_F, ptr, count);
DfPush(DF_VERTEX, ptr, count);
return 0;
}
// IDA: int __usercall FopRead_MATERIAL_INDEX@<EAX>(br_datafile *df@<EAX>, br_uint_32 id@<EDX>, br_uint_32 length@<EBX>, br_uint_32 count@<ECX>)
@ -447,6 +450,7 @@ int FopWrite_MATERIAL_INDEX(br_datafile* df, br_material** materials, int nmater
for (i = 0; i < nmaterials; i++) {
df->prims->name_write(df, materials[i]->identifier);
}
return 0;
}
// IDA: int __usercall FopRead_OLD_MATERIAL_INDEX@<EAX>(br_datafile *df@<EAX>, br_uint_32 id@<EDX>, br_uint_32 length@<EBX>, br_uint_32 count@<ECX>)

View File

@ -1911,7 +1911,7 @@ typedef struct br_renderer_dispatch {
br_error (*_stateStoredAvail)(br_renderer*, br_int_32*, br_uint_32, br_token_value*);
br_error (*_bufferStoredNew)(br_renderer*, br_buffer_stored**, br_token, br_device_pixelmap*, br_token_value*);
br_error (*_bufferStoredAvail)(br_renderer*, br_int_32*, br_token, br_token_value*);
br_error (*_partSet)(br_renderer*, br_token, br_int_32, br_token, br_uint_32);
br_error (*_partSet)(br_renderer*, br_token, br_int_32, br_token, uintptr_t);
br_error (*_partSetMany)(br_renderer*, br_token, br_int_32, br_token_value*, br_int_32*);
br_error (*_partQuery)(br_renderer*, br_token, br_int_32, br_uint_32*, br_token);
br_error (*_partQueryBuffer)(br_renderer*, br_token, br_int_32, br_uint_32*, br_uint_32*, br_size_t, br_token);
@ -2261,7 +2261,7 @@ typedef struct br_primitive_state_dispatch {
br_error (*_queryManySize)(br_object*, br_size_t*, br_token_value*);
br_error (*_queryAll)(br_object*, br_token_value*, br_size_t);
br_error (*_queryAllSize)(br_object*, br_size_t*);
br_error (*_partSet)(br_primitive_state*, br_token, br_int_32, br_token, br_uint_32);
br_error (*_partSet)(br_primitive_state*, br_token, br_int_32, br_token, uintptr_t);
br_error (*_partSetMany)(br_primitive_state*, br_token, br_int_32, br_token_value*, br_int_32*);
br_error (*_partQuery)(br_primitive_state*, br_token, br_int_32, br_uint_32*, br_token);
br_error (*_partQueryBuffer)(br_primitive_state*, br_token, br_int_32, br_uint_32*, br_uint_32*, br_size_t, br_token);

View File

@ -2445,13 +2445,13 @@ void DrawSomeText2(tDR_font* pFont) {
// IDA: void __cdecl DrawSomeText()
void DrawSomeText(void) {
DrawSomeText2(&gFonts[1]);
DrawSomeText2(&gFonts[2]);
DrawSomeText2(&gFonts[3]);
DrawSomeText2(&gFonts[4]);
DrawSomeText2(&gFonts[6]);
DrawSomeText2(&gFonts[7]);
DrawSomeText2(&gFonts[8]);
DrawSomeText2(&gFonts[kFont_ORANGHED]);
DrawSomeText2(&gFonts[kFont_BLUEHEAD]);
DrawSomeText2(&gFonts[kFont_GREENHED]);
DrawSomeText2(&gFonts[kFont_MEDIUMHD]);
DrawSomeText2(&gFonts[kFont_NEWHITE]);
DrawSomeText2(&gFonts[kFont_NEWRED]);
DrawSomeText2(&gFonts[kFont_NEWBIGGR]);
}
// IDA: void __cdecl SaySorryYouLittleBastard()

View File

@ -2025,34 +2025,34 @@ void LoadInterfaceStrings(void) {
gTranslations[i].text = BrMemAllocate(strlen(str) + 1, kMem_translations_text);
strcpy(gTranslations[i].text, str);
}
LoadFont(2);
LoadFont(1);
LoadFont(3);
LoadFont(15);
LoadFont(14);
LoadFont(16);
LoadFont(13);
LoadFont(10);
LoadFont(12);
LoadFont(9);
LoadFont(11);
LoadFont(19);
LoadFont(18);
LoadFont(20);
LoadFont(17);
gTrans_fonts[0] = &gFonts[1];
gTrans_fonts[1] = &gFonts[15];
gTrans_fonts[2] = &gFonts[14];
gTrans_fonts[3] = &gFonts[16];
gTrans_fonts[4] = &gFonts[13];
gTrans_fonts[5] = &gFonts[10];
gTrans_fonts[6] = &gFonts[12];
gTrans_fonts[7] = &gFonts[9];
gTrans_fonts[8] = &gFonts[11];
gTrans_fonts[9] = &gFonts[19];
gTrans_fonts[10] = &gFonts[20];
gTrans_fonts[11] = &gFonts[18];
gTrans_fonts[12] = &gFonts[17];
LoadFont(kFont_BLUEHEAD);
LoadFont(kFont_ORANGHED);
LoadFont(kFont_GREENHED);
LoadFont(kFont_LITPLAQ);
LoadFont(kFont_BUTTOUT);
LoadFont(kFont_DRKPLAQ);
LoadFont(kFont_BUTTIN);
LoadFont(kFont_GRNLIT);
LoadFont(kFont_GRYLIT);
LoadFont(kFont_GRNDK);
LoadFont(kFont_GRYDK);
LoadFont(kFont_LITPLAQ1);
LoadFont(kFont_BUTTOUT1);
LoadFont(kFont_DRKPLAQ1);
LoadFont(kFont_BUTTIN1);
gTrans_fonts[0] = &gFonts[kFont_ORANGHED];
gTrans_fonts[1] = &gFonts[kFont_LITPLAQ];
gTrans_fonts[2] = &gFonts[kFont_BUTTOUT];
gTrans_fonts[3] = &gFonts[kFont_DRKPLAQ];
gTrans_fonts[4] = &gFonts[kFont_BUTTIN];
gTrans_fonts[5] = &gFonts[kFont_GRNLIT];
gTrans_fonts[6] = &gFonts[kFont_GRYLIT];
gTrans_fonts[7] = &gFonts[kFont_GRNDK];
gTrans_fonts[8] = &gFonts[kFont_GRYDK];
gTrans_fonts[9] = &gFonts[kFont_LITPLAQ1];
gTrans_fonts[10] = &gFonts[kFont_DRKPLAQ1];
gTrans_fonts[11] = &gFonts[kFont_BUTTOUT1];
gTrans_fonts[12] = &gFonts[kFont_BUTTIN1];
#ifdef DETHRACE_FIX_BUGS
fclose(f);

View File

@ -1725,13 +1725,13 @@ void RenderAFrame(int pDepth_mask_on) {
map_timer_x - gCurrent_graf_data->map_timer_border_x,
gCurrent_graf_data->map_timer_text_y - gCurrent_graf_data->map_timer_border_y,
map_timer_width + 2 * gCurrent_graf_data->map_timer_border_x,
gFonts[2].height + 2 * gCurrent_graf_data->map_timer_border_y,
gFonts[kFont_BLUEHEAD].height + 2 * gCurrent_graf_data->map_timer_border_y,
0);
TransDRPixelmapText(
gBack_screen,
map_timer_x,
gCurrent_graf_data->map_timer_text_y,
&gFonts[2],
&gFonts[kFont_BLUEHEAD],
the_text,
gBack_screen->width);
}

View File

@ -530,16 +530,16 @@ void InitRace(void) {
FlushInterfaceFonts();
}
} else {
LoadFont(1);
LoadFont(2);
LoadFont(3);
LoadFont(kFont_ORANGHED);
LoadFont(kFont_BLUEHEAD);
LoadFont(kFont_GREENHED);
}
LoadFont(4);
LoadFont(5);
LoadFont(kFont_MEDIUMHD);
LoadFont(kFont_TIMER);
PossibleService();
LoadFont(6);
LoadFont(7);
LoadFont(8);
LoadFont(kFont_NEWHITE);
LoadFont(kFont_NEWRED);
LoadFont(kFont_NEWBIGGR);
PossibleService();
ResetRecoveryVouchers();
gMap_mode = 0;

View File

@ -943,7 +943,7 @@ void DoSaveGame(int pSave_allowed) {
gProgram_state.saving = 1;
gSave_allowed = pSave_allowed;
LoadSavedGames();
LoadFont(0);
LoadFont(kFont_TYPEABLE);
if (!pSave_allowed && !ConfirmMidGameSave()) {
gProgram_state.saving = 0;
return;

View File

@ -1172,7 +1172,7 @@ void NetFullScreenMessage(int pStr_index, int pLeave_it_up_there) {
s,
gBack_screen,
0,
gGraf_specs[gGraf_spec_index].total_height / 2 - gFonts[4].height,
gGraf_specs[gGraf_spec_index].total_height / 2 - gFonts[kFont_MEDIUMHD].height,
gGraf_specs[gGraf_spec_index].total_width,
gGraf_specs[gGraf_spec_index].total_height,
1);

View File

@ -495,9 +495,9 @@ void DrawColumnHeading__newgame(int pStr_index, int pX) {
TransDRPixelmapText(gBack_screen,
pX,
gCurrent_graf_data->joinable_games_y - gCurrent_graf_data->joinable_games_y_pitch,
&gFonts[12],
&gFonts[kFont_GRYLIT],
GetMiscString(pStr_index),
pX + DRTextWidth(&gFonts[12], GetMiscString(pStr_index)));
pX + DRTextWidth(&gFonts[kFont_GRYLIT], GetMiscString(pStr_index)));
}
// IDA: void __usercall DrawGames(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
@ -529,9 +529,9 @@ void DrawGames(int pCurrent_choice, int pCurrent_mode) {
DrawColumnHeading__newgame(kMiscString_NetworkGamesTableHeading_STATUS, gCurrent_graf_data->joinable_games_x_4);
BrPixelmapLine(gBack_screen,
gCurrent_graf_data->joinable_games_sel_left,
gCurrent_graf_data->joinable_games_y + gFonts[12].height + 1 - (TranslationMode() ? 2 : 0) - gCurrent_graf_data->joinable_games_y_pitch,
gCurrent_graf_data->joinable_games_y + gFonts[kFont_GRYLIT].height + 1 - (TranslationMode() ? 2 : 0) - gCurrent_graf_data->joinable_games_y_pitch,
gCurrent_graf_data->joinable_games_sel_right - 1,
gCurrent_graf_data->joinable_games_y + gFonts[12].height + 1 - (TranslationMode() ? 2 : 0) - gCurrent_graf_data->joinable_games_y_pitch,
gCurrent_graf_data->joinable_games_y + gFonts[kFont_GRYLIT].height + 1 - (TranslationMode() ? 2 : 0) - gCurrent_graf_data->joinable_games_y_pitch,
6);
for (i = 0; i < COUNT_OF(gGames_to_join); i++) {
if (gGames_to_join[i].game == NULL) {
@ -788,10 +788,10 @@ tJoin_or_host_result JoinOrHostGame(tNet_game_details** pGame_to_join) {
LOG_TRACE("(%p)", pGame_to_join);
gCurrent_game_selection = 0;
LoadFont(9);
LoadFont(10);
LoadFont(3);
LoadFont(12);
LoadFont(kFont_GRNDK);
LoadFont(kFont_GRNLIT);
LoadFont(kFont_GREENHED);
LoadFont(kFont_GRYLIT);
SetAlwaysTyping();
InitGamesToJoin();
NetStartProducingJoinList(AddToJoinList);
@ -1258,7 +1258,7 @@ void DoNetOptions(tNet_game_options* pGame_options) {
gThe_interface_spec__newgame = &interface_spec;
gRadio_selected = -1;
LoadFont(12);
LoadFont(kFont_GRYLIT);
SetNetOptions(pGame_options);
if (DoInterfaceScreen(&interface_spec, 0, 0) == 0) {
GetNetOptions(pGame_options);
@ -1391,12 +1391,12 @@ void DrawNetChoose(int pCurrent_choice, int pCurrent_mode) {
gCurrent_graf_data->net_descr_race_l,
gCurrent_graf_data->net_choose_race_y,
gCurrent_graf_data->net_descr_race_r - gCurrent_graf_data->net_descr_race_l,
gFonts[10].height + 1 - (TranslationMode() ? 2 : 0), 0);
gFonts[kFont_GRNLIT].height + 1 - (TranslationMode() ? 2 : 0), 0);
sprintf(s, "%s %s", GetMiscString(kMiscString_FIRST_RACE), gRace_list[gRace_index].name);
DRPixelmapCentredText(gBack_screen,
gCurrent_graf_data->net_choose_race_x,
gCurrent_graf_data->net_choose_race_y,
&gFonts[10], s);
&gFonts[kFont_GRNLIT], s);
BrPixelmapRectangleFill(gBack_screen,
gCurrent_graf_data->net_descr_race_l,
gCurrent_graf_data->net_descr_race_top - (TranslationMode() ? 2 : 0),
@ -1526,8 +1526,8 @@ int NetGameChoices(tNet_game_type* pGame_type, tNet_game_options* pGame_options,
gRace_index = *pRace_index;
gLast_game_type = *pGame_type;
do {
LoadFont(10);
LoadFont(9);
LoadFont(kFont_GRNLIT);
LoadFont(kFont_GRNDK);
gThe_interface_spec__newgame = &interface_spec;
gLast_net_choose_box = -1;
gOptions = pGame_options;

View File

@ -651,7 +651,7 @@ void PlotAGraphBox__options(int pIndex, int pColour_value) {
gThe_interface_spec__options->mouse_areas[2].left[gGraf_data_index] - 6,
gRadio_bastards__options[pIndex].top - 3,
gThe_interface_spec__options->mouse_areas[2].right[gGraf_data_index] + 3,
gRadio_bastards__options[pIndex].top + gFonts[12].height + (TranslationMode() ? 2 : 0), pColour_value);
gRadio_bastards__options[pIndex].top + gFonts[kFont_GRYLIT].height + 2 - (TranslationMode() ? 2 : 0), pColour_value);
}
// IDA: void __usercall DrawAGraphBox(int pIndex@<EAX>)
@ -803,7 +803,7 @@ void DoGraphicsOptions(void) {
gThe_interface_spec__options = &interface_spec;
gCurrent_key = -1;
LoadFont(12);
LoadFont(kFont_GRYLIT);
GetGraphicsOptions();
if (DoInterfaceScreen(&interface_spec, 0, 0) == 0) {
SetGraphicsOptions();
@ -855,6 +855,10 @@ void StripControls(unsigned char* pStr) {
if (pStr[i] < ' ') {
memmove(&pStr[i], &pStr[i + 1], (len - i) * sizeof(char));
len--;
#ifdef DETHRACE_FIX_BUGS
// correctly handle stripping multiple control characters
i--;
#endif
}
}
}
@ -990,12 +994,12 @@ void DrawKeyAssignments(int pCurrent_choice, int pCurrent_mode) {
LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode);
#if defined(DETHRACE_FIX_BUGS)
font_k = &gFonts[11];
font_k = &gFonts[kFont_GRYDK];
#endif
if (gMouse_in_use && pCurrent_choice == 4) {
GetMousePosition(&x_coord, &y_coord);
if (y_coord >= gCurrent_graf_data->key_assign_key_map_y
&& y_coord <= gCurrent_graf_data->key_assign_key_map_y + gFonts[12].height + 5
&& y_coord <= gCurrent_graf_data->key_assign_key_map_y + gFonts[kFont_GRYLIT].height + 5
&& x_coord > gCurrent_graf_data->key_assign_col_1
&& x_coord < gCurrent_graf_data->key_assign_col_2 + gCurrent_graf_data->key_assign_col_2 - gCurrent_graf_data->key_assign_col_1 - 7) {
gCurrent_key = -1;
@ -1021,15 +1025,15 @@ void DrawKeyAssignments(int pCurrent_choice, int pCurrent_mode) {
gCurrent_graf_data->key_assign_y_pitch * gKey_count / 2 + 4,
0);
GetKeyCoords(-1, &y, &name_x, &key_x, &end_box);
DrawRRectangle(gBack_screen, name_x - 3, y - 3, end_box, gFonts[12].height + y + 2 - (TranslationMode() ? 2 : 0), 0);
DrawRRectangle(gBack_screen, name_x - 3, y - 3, end_box, gFonts[kFont_GRYLIT].height + y + 2 - (TranslationMode() ? 2 : 0), 0);
for (i = 0; i < gKey_count; i++) {
GetKeyCoords(i, &y, &name_x, &key_x, &end_box);
if (i == gCurrent_key && pCurrent_mode != 0) {
font_n = &gFonts[10];
font_k = &gFonts[12];
font_n = &gFonts[kFont_GRNLIT];
font_k = &gFonts[kFont_GRYLIT];
} else {
font_n = &gFonts[9];
font_k = &gFonts[11];
font_n = &gFonts[kFont_GRNDK];
font_k = &gFonts[kFont_GRYDK];
}
TransDRPixelmapText(gBack_screen, name_x, y, font_n, GetMiscString(kMiscString_InputOptions_START + i), 640);
TransDRPixelmapText(gBack_screen, key_x, y, font_k, gKey_names[gKey_mapping[gKey_defns[i]] + 2], 640);
@ -1251,7 +1255,7 @@ int KeyAssignGoAhead(int* pCurrent_choice, int* pCurrent_mode) {
PollKeys();
WaitForNoKeys();
GetKeyCoords(gCurrent_key, &y, &name_x, &key_x, &end_box);
font = &gFonts[12];
font = &gFonts[kFont_GRYLIT];
gPending_entry = -1;
while (1) {
key = PDAnyKeyDown();
@ -1390,10 +1394,10 @@ void DoControlOptions(void) {
gThe_interface_spec__options = &interface_spec;
SaveOrigKeyMapping();
LoadKeyNames();
LoadFont(9);
LoadFont(11);
LoadFont(10);
LoadFont(12);
LoadFont(kFont_GRNDK);
LoadFont(kFont_GRYDK);
LoadFont(kFont_GRNLIT);
LoadFont(kFont_GRYLIT);
gPending_entry = -1;
gKey_count = 18;
gCurrent_key = 8;

View File

@ -443,13 +443,13 @@ void DrawPowerups(tU32 pTime) {
TransDRPixelmapText(gBack_screen,
gCurrent_graf_data->power_up_icon_countdown_x,
y + gCurrent_graf_data->power_up_icon_countdown_y_offset,
&gFonts[1], s, gCurrent_graf_data->power_up_icon_countdown_x + 30);
&gFonts[kFont_ORANGHED], s, gCurrent_graf_data->power_up_icon_countdown_x + 30);
} else if (the_powerup->current_value > 0) {
sprintf(s, "%d", the_powerup->current_value);
TransDRPixelmapText(gBack_screen,
gCurrent_graf_data->power_up_icon_countdown_x,
y + gCurrent_graf_data->power_up_icon_countdown_y_offset,
&gFonts[2], s, gCurrent_graf_data->power_up_icon_countdown_x + 30);
&gFonts[kFont_BLUEHEAD], s, gCurrent_graf_data->power_up_icon_countdown_x + 30);
}
} else {
fizzle_pix = gFizzle_in[the_powerup->fizzle_type];

View File

@ -187,9 +187,9 @@ void ActualActionReplayHeadups(int pSpecial_zappy_bastard) {
}
if (the_time - gCam_change_time < 2000) {
TransDRPixelmapText(gBack_screen,
gCurrent_graf_data->action_replay_cam_text_x - DRTextWidth(&gFonts[1], GetMiscString(gAction_replay_camera_mode ? kMiscString_PanningCamera : kMiscString_StandardCamera)),
gCurrent_graf_data->action_replay_cam_text_x - DRTextWidth(&gFonts[kFont_ORANGHED], GetMiscString(gAction_replay_camera_mode ? kMiscString_PanningCamera : kMiscString_StandardCamera)),
gCurrent_graf_data->action_replay_cam_text_y,
&gFonts[1],
&gFonts[kFont_ORANGHED],
GetMiscString(gAction_replay_camera_mode ? kMiscString_PanningCamera : kMiscString_StandardCamera),
2 * gCurrent_graf_data->action_replay_cam_text_x);
}

View File

@ -706,6 +706,32 @@ enum {
kMiscString_QUOTE_IT_QUOTE = 241,
kMiscString_TOO_LATE_TO_CANCEL = 242,
kMiscString_CouldNotFindTheCarmageddonCD = 243,
kMiscString_NotAvailableInEvaluationCopy = 244,
kMiscString_EvaluationCopy = 245,
};
enum {
kFont_TYPEABLE = 0,
kFont_ORANGHED = 1,
kFont_BLUEHEAD = 2,
kFont_GREENHED = 3,
kFont_MEDIUMHD = 4,
kFont_TIMER = 5,
kFont_NEWHITE = 6,
kFont_NEWRED = 7,
kFont_NEWBIGGR = 8,
kFont_GRNDK = 9,
kFont_GRNLIT = 10,
kFont_GRYDK = 11,
kFont_GRYLIT = 12,
kFont_BUTTIN = 13,
kFont_BUTTOUT = 14,
kFont_LITPLAQ = 15,
kFont_DRKPLAQ = 16,
kFont_BUTTIN1 = 17,
kFont_BUTTOUT1 = 18,
kFont_LITPLAQ1 = 19,
kFont_DRKPLAQ1 = 20,
};
enum {

View File

@ -1,6 +1,7 @@
#include "s3sound.h"
#include "audio.h"
#include "backends/backend.h"
#include "harness/hooks.h"
#include "harness/trace.h"
#include "resource.h"
#include <stdio.h>
@ -144,7 +145,7 @@ void* S3LoadWavFile_DOS(char* pFile_name) {
size_t bytes_read;
char* buf;
f = fopen(pFile_name, "rb");
f = Harness_Hook_fopen(pFile_name, "rb");
if (f == NULL) {
gS3_last_error = eS3_error_readfile;
return 0;
@ -185,7 +186,7 @@ void* S3LoadWavFile_Win95(char* pFile_name, tS3_sample* pSample) {
// char* locked_buffer_data; // [esp+CCh] [ebp-8h] BYREF
size_t file_len; // [esp+D0h] [ebp-4h]
f = fopen(pFile_name, "rb");
f = Harness_Hook_fopen(pFile_name, "rb");
if (f == NULL) {
gS3_last_error = eS3_error_readfile;
return 0;

View File

@ -58,10 +58,10 @@ static intptr_t get_dethrace_offset(void) {
// Resolve symbol name and source location given the path to the executable and an address
int addr2line(char const* const program_name, void const* const addr) {
char addr2line_cmd[512] = { 0 };
char addr2line_cmd[512];
/* have addr2line map the address to the related line in the code */
sprintf(addr2line_cmd, "addr2line -f -p -e %.256s %p", program_name, addr - get_dethrace_offset());
sprintf(addr2line_cmd, "addr2line -f -p -e %.480s %p", program_name, addr - get_dethrace_offset());
fprintf(stderr, "%d: ", stack_nbr++);
return system(addr2line_cmd);

View File

@ -5,10 +5,10 @@
void test_graphics_loadfont() {
REQUIRES_DATA_DIRECTORY();
TEST_ASSERT_EQUAL_INT(0, gFonts[0].file_read_once);
LoadFont(0);
TEST_ASSERT_EQUAL_INT(1, gFonts[0].file_read_once);
TEST_ASSERT_NOT_NULL(gFonts[0].images);
TEST_ASSERT_EQUAL_INT(0, gFonts[kFont_TYPEABLE].file_read_once);
LoadFont(kFont_TYPEABLE);
TEST_ASSERT_EQUAL_INT(1, gFonts[kFont_TYPEABLE].file_read_once);
TEST_ASSERT_NOT_NULL(gFonts[kFont_TYPEABLE].images);
}
void test_graphics_suite() {

View File

@ -59,11 +59,14 @@ class Byte:
return self.v == (other & 0xff)
raise ValueError(f"Object {other:r} of invalid type {type(other)}")
def __repr__(self):
return f"(byte 0x{self.v:02x})"
def decode_line(line: bytes, method: int) -> str:
def decode_line(line: bytes, method: int) -> bytes:
line = line.rstrip(b"\r\n")
key = LONG_KEY
seed = len(line) % len(LONG_KEY)
seed = len(line) % len(key)
dline = bytearray(len(line))
for i, c in enumerate(line):
b = Byte(c)
@ -98,13 +101,58 @@ def decode_line(line: bytes, method: int) -> str:
if b == 0x80:
b = Byte(ord(b'\t'))
dline[i] = b.v
return dline.decode(errors="replace")
return dline
def encode_line(line: bytes, method: int) -> bytes:
line = line.rstrip(b"\r\n")
key = LONG_KEY
seed = len(line) % len(key)
count = 0
eline = bytearray(len(line))
for i, c in enumerate(line):
if count == 2:
key = OTHER_LONG_KEY
if c == ord('/'):
count += 1
else:
count = 0
if method == 1:
if c == ord('\t'):
c = 0x9f
b = Byte(c)
b -= 0x20
b ^= key[seed]
b &= 0x7f
b += 0x20
seed += 7
seed %= len(key)
if b == 0x9f:
b = Byte(ord('\t'))
else:
if c == ord('\t'):
c = 0x80
b = Byte(c - 0x20)
if (b & 0x80) == 0:
b ^= key[seed] & 0x7f
b += 0x20
seed += 7
seed %= len(key)
if b == 0x80:
b = Byte(ord('\t'))
eline[i] = b.v
return bytes(eline)
def main():
parser = argparse.ArgumentParser(allow_abbrev=False, description="Decode a Carmageddon encoded file")
parser = argparse.ArgumentParser(allow_abbrev=False, description="Decode/encode a Carmageddon text file")
parser.add_argument("file", metavar="FILE", nargs="?", help="input file (default=stdin)")
parser.add_argument("--method", choices=[1, 2], type=int, default=2, help="decryption method to use")
parser.add_argument("--method", choices=[1, 2], type=int, default=2, help="encryption method to use (default=2)")
args = parser.parse_args()
istream = open(args.file, "rb") if args.file else sys.stdin.buffer
@ -112,9 +160,11 @@ def main():
for line in istream.readlines():
if line[0] == ord(b'@'):
dline = decode_line(line[1:], args.method)
print(dline)
sys.stdout.buffer.write(dline)
else:
print(line.decode())
eline = b"@" + encode_line(line, args.method)
sys.stdout.buffer.write(eline)
sys.stdout.buffer.write(b'\n')
if __name__ == "__main__":