#include "displays.h"
 
#include "brender/brender.h"
 
#include "constants.h"
 
#include "controls.h"
 
#include "depth.h"
 
#include "flicplay.h"
 
#include "globvars.h"
 
#include "globvrkm.h"
 
#include "globvrpb.h"
 
#include "grafdata.h"
 
#include "graphics.h"
 
#include "harness/trace.h"
 
#include "netgame.h"
 
#include "pd/sys.h"
 
#include "utility.h"
 
#include <stdlib.h>
 
 
 
int gLast_fancy_index;
 
int gLast_credit_headup__displays; // suffix added to avoid duplicate symbol
 
int gLast_time_credit_headup;
 
tDR_font* gCached_font;
 
br_font* gBR_fonts[4];
 
tQueued_headup gQueued_headups[4];
 
int gOld_times[10];
 
int gLast_fancy_headup;
 
tU32 gLast_time_earn_time;
 
tU32 gLast_centre_headup;
 
tU32 gLast_fancy_time;
 
int gQueued_headup_count;
 
tU32 gLast_earn_time;
 
tU32 gLast_time_credit_amount;
 
int gLast_credit_amount;
 
tHeadup gHeadups[15];
 
int gLaps_headup;
 
int gCar_kill_count_headup;
 
int gTimer_headup;
 
int gTime_awarded_headup;
 
int gPed_kill_count_headup;
 
int gDim_amount;
 
br_pixelmap* gHeadup_images[32]; // Modified by DethRace for the demo
 
int gNet_cash_headup;
 
int gNet_ped_headup;
 
int gCredits_lost_headup;
 
int gCredits_won_headup;
 
 
 
// IDA: void __usercall GetTimerString(char *pStr@<EAX>, int pFudge_colon@<EDX>)
 
void GetTimerString(char* pStr, int pFudge_colon) {
 
    LOG_TRACE("(\"%s\", %d)", pStr, pFudge_colon);
 
 
 
    TimerString(gTimer, pStr, pFudge_colon, 0);
 
}
 
 
 
// IDA: void __cdecl InitHeadups()
 
void InitHeadups(void) {
 
    int i;
 
    LOG_TRACE("()");
 
 
 
    for (i = 0; i < 15; i++) {
 
        gHeadups[i].type = eHeadup_unused;
 
    }
 
    gBR_fonts[0] = BrFontProp7x9;
 
    gBR_fonts[1] = BrFontFixed3x5;
 
    gBR_fonts[2] = gFont_7;
 
    gBR_fonts[3] = gHeadup_font;
 
}
 
 
 
// IDA: void __usercall ClearHeadup(int pIndex@<EAX>)
 
void ClearHeadup(int pIndex) {
 
    LOG_TRACE("(%d)", pIndex);
 
 
 
    gHeadups[pIndex].type = eHeadup_unused;
 
}
 
 
 
// IDA: void __usercall ClearHeadupSlot(int pSlot_index@<EAX>)
 
void ClearHeadupSlot(int pSlot_index) {
 
    int i;
 
    tHeadup* the_headup;
 
    LOG_TRACE("(%d)", pSlot_index);
 
 
 
    the_headup = gHeadups;
 
    for (i = 0; i < COUNT_OF(gHeadups); i++) {
 
        if (the_headup->type != eHeadup_unused && the_headup->slot_index == pSlot_index) {
 
            ClearHeadup(i);
 
            return;
 
        }
 
        the_headup++;
 
    }
 
}
 
 
 
// IDA: void __cdecl ClearHeadups()
 
void ClearHeadups(void) {
 
    int i;
 
    LOG_TRACE("()");
 
 
 
    for (i = 0; i < COUNT_OF(gHeadups); i++) {
 
        if (gHeadups[i].type) {
 
            ClearHeadup(i);
 
        }
 
    }
 
    gLast_fancy_index = -1;
 
    gLast_credit_headup__displays = -1;
 
    gLast_time_credit_headup = -1;
 
    gLast_earn_time = 0;
 
    gLast_fancy_time = 0;
 
    gLast_time_earn_time = 0;
 
    for (i = 0; i < COUNT_OF(gOld_times); i++) {
 
        gOld_times[i] = 0;
 
    }
 
    gQueued_headup_count = 0;
 
    gLast_centre_headup = 0;
 
}
 
 
 
// IDA: int __usercall HeadupActive@<EAX>(int pIndex@<EAX>)
 
int HeadupActive(int pIndex) {
 
    LOG_TRACE("(%d)", pIndex);
 
 
 
    return gHeadups[pIndex].type != eHeadup_unused;
 
}
 
 
 
// IDA: void __usercall DRPixelmapText(br_pixelmap *pPixelmap@<EAX>, int pX@<EDX>, int pY@<EBX>, tDR_font *pFont@<ECX>, char *pText, int pRight_edge)
 
void DRPixelmapText(br_pixelmap* pPixelmap, int pX, int pY, tDR_font* pFont, char* pText, int pRight_edge) {
 
    int i;
 
    int x;
 
    int len;
 
    int chr;
 
    int ch_width;
 
    unsigned char* ch;
 
    LOG_TRACE9("(%p, %d, %d, %p, \"%s\", %d)", pPixelmap, pX, pY, pFont, pText, pRight_edge);
 
 
 
    ch = (unsigned char*)pText;
 
    if (pX >= 0 && pPixelmap->width >= pRight_edge && pY >= 0 && (pY + pFont->height) <= pPixelmap->height) {
 
        x = pX;
 
        for (i = 0; i < len; i++) {
 
            chr = ch[i] - pFont->offset;
 
            ch_width = pFont->width_table[chr];
 
            DRPixelmapRectangleOnscreenCopy(
 
                gBack_screen,
 
                x,
 
                pY,
 
                pFont->images,
 
                0,
 
                pFont->height * chr,
 
                ch_width,
 
                pFont->height);
 
 
 
            x += ch_width + pFont->spacing;
 
        }
 
    } else {
 
        x = pX;
 
        for (i = 0; i < len; i++) {
 
            chr = ch[i] - pFont->offset;
 
            ch_width = pFont->width_table[chr];
 
            DRPixelmapRectangleMaskedCopy(
 
                gBack_screen,
 
                x,
 
                pY,
 
                pFont->images,
 
                0,
 
                pFont->height * chr,
 
                ch_width,
 
                pFont->height);
 
 
 
            x += ch_width + pFont->spacing;
 
        }
 
    }
 
}
 
 
 
// IDA: void __usercall DRPixelmapCleverText2(br_pixelmap *pPixelmap@<EAX>, int pX@<EDX>, int pY@<EBX>, tDR_font *pFont@<ECX>, signed char *pText, int pRight_edge)
 
void DRPixelmapCleverText2(br_pixelmap* pPixelmap, int pX, int pY, tDR_font* pFont, char* pText, int pRight_edge) {
 
    int i;
 
    int x;
 
    int len;
 
    int chr;
 
    int ch_width;
 
    unsigned char* ch;
 
    tDR_font* new_font;
 
    LOG_TRACE("(%p, %d, %d, %p, %p, %d)", pPixelmap, pX, pY, pFont, pText, pRight_edge);
 
 
 
    x = pX;
 
    ch = (unsigned char*)pText;
 
    if (pX >= 0 && pPixelmap->width >= pRight_edge && pY >= 0 && pY + pFont->height <= pPixelmap->height) {
 
        for (i = 0; i < len; i++) {
 
            if (*ch < 224) {
 
                chr = *ch - pFont->offset;
 
                ch_width = pFont->width_table[chr];
 
                DRPixelmapRectangleOnscreenCopy(
 
                    gBack_screen,
 
                    x,
 
                    pY,
 
                    pFont->images,
 
                    0,
 
                    chr * pFont->height,
 
                    ch_width,
 
                    pFont->height);
 
                x += ch_width + pFont->spacing;
 
            } else {
 
                new_font = &gFonts[-*ch + 256];
 
                pY -= (new_font->height - pFont->height) / 2;
 
                pFont = new_font;
 
            }
 
            ch++;
 
        }
 
    } else {
 
        for (i = 0; i < len; i++) {
 
            if (*ch < 224) {
 
                chr = *ch - pFont->offset;
 
                ch_width = pFont->width_table[chr];
 
                DRPixelmapRectangleMaskedCopy(
 
                    gBack_screen,
 
                    x,
 
                    pY,
 
                    pFont->images,
 
                    0,
 
                    chr * pFont->height,
 
                    ch_width,
 
                    pFont->height);
 
                x += ch_width + pFont->spacing;
 
            } else {
 
                new_font = &gFonts[-*ch + 256];
 
                pY -= (new_font->height - pFont->height) / 2;
 
                pFont = new_font;
 
            }
 
            ch++;
 
        }
 
    }
 
}
 
 
 
// IDA: void __usercall DeviouslyDimRectangle(br_pixelmap *pPixelmap@<EAX>, int pLeft@<EDX>, int pTop@<EBX>, int pRight@<ECX>, int pBottom, int pKnock_out_corners)
 
void DeviouslyDimRectangle(br_pixelmap* pPixelmap, int pLeft, int pTop, int pRight, int pBottom, int pKnock_out_corners) {
 
    LOG_TRACE("(%p, %d, %d, %d, %d, %d)", pPixelmap, pLeft, pTop, pRight, pBottom, pKnock_out_corners);
 
    NOT_IMPLEMENTED();
 
}
 
 
 
// IDA: void __cdecl DimRectangle(br_pixelmap *pPixelmap, int pLeft, int pTop, int pRight, int pBottom, int pKnock_out_corners)
 
void DimRectangle(br_pixelmap* pPixelmap, int pLeft, int pTop, int pRight, int pBottom, int pKnock_out_corners) {
 
    tU8* ptr;
 
    tU8* depth_table_ptr;
 
    tU8* right_ptr;
 
    int x;
 
    int y;
 
    int line_skip;
 
    int width;
 
    LOG_TRACE9("(%p, %d, %d, %d, %d, %d)", pPixelmap, pLeft, pTop, pRight, pBottom, pKnock_out_corners);
 
 
 
    ptr = (tU8*)pPixelmap->pixels + pLeft + pPixelmap->row_bytes * pTop;
 
    line_skip = pPixelmap->row_bytes - pRight + pLeft;
 
    depth_table_ptr = gDepth_shade_table->pixels;
 
    x = gDepth_shade_table->row_bytes * gDim_amount;
 
    width = pRight - pLeft;
 
 
 
    if (pKnock_out_corners) {
 
        ptr++;
 
        for (right_ptr = ptr + width - 2; ptr < right_ptr; ptr++) {
 
            *ptr = depth_table_ptr[*ptr + x];
 
        }
 
        ptr += line_skip + 1;
 
        for (y = pTop + 1; y < (pBottom - 1); y++, ptr += line_skip) {
 
            for (right_ptr = ptr + width; ptr < right_ptr; ptr++) {
 
                *ptr = depth_table_ptr[*ptr + x];
 
            }
 
        }
 
        ptr++;
 
        for (right_ptr = ptr + width - 2; ptr < right_ptr; ptr++) {
 
            *ptr = depth_table_ptr[*ptr + x];
 
        }
 
    } else {
 
        for (y = pTop; y < pBottom; y++) {
 
            for (right_ptr = ptr + width; ptr < right_ptr; ptr++) {
 
                *ptr = depth_table_ptr[*ptr + x];
 
            }
 
            ptr += line_skip;
 
        }
 
    }
 
}
 
 
 
// IDA: void __cdecl DimAFewBits()
 
void DimAFewBits(void) {
 
    int i;
 
    LOG_TRACE("()");
 
 
 
    int dim_index; // Added
 
    dim_index = gProgram_state.cockpit_on && gProgram_state.cockpit_image_index >= 0;
 
    for (i = 0; i < gProgram_state.current_car.dim_count[dim_index]; i++) {
 
        DimRectangle(
 
            gBack_screen,
 
            gProgram_state.current_car.dim_left[dim_index][i],
 
            gProgram_state.current_car.dim_top[dim_index][i],
 
            gProgram_state.current_car.dim_right[dim_index][i],
 
            gProgram_state.current_car.dim_bottom[dim_index][i],
 
            1);
 
    }
 
}
 
 
 
// IDA: void __cdecl KillOldestQueuedHeadup()
 
void KillOldestQueuedHeadup(void) {
 
    LOG_TRACE("()");
 
 
 
    gQueued_headup_count--;
 
    memmove(&gQueued_headups
[0], &gQueued_headups
[1], gQueued_headup_count 
* sizeof(tQueued_headup
));  
}
 
 
 
// IDA: void __usercall DubreyBar(int pX_index@<EAX>, int pY@<EDX>, int pColour@<EBX>)
 
void DubreyBar(int pX_index, int pY, int pColour) {
 
    int x;
 
    LOG_TRACE("(%d, %d, %d)", pX_index, pY, pColour);
 
 
 
    x = gCurrent_graf_data->ps_bar_left - gCurrent_graf_data->ps_x_pitch * pX_index;
 
    BrPixelmapLine(gBack_screen, x, pY, x, gCurrent_graf_data->ps_bar_height + pY, pColour);
 
}
 
 
 
// IDA: void __usercall DoPSPowerHeadup(int pY@<EAX>, int pLevel@<EDX>, char *pName@<EBX>, int pBar_colour@<ECX>)
 
void DoPSPowerHeadup(int pY, int pLevel, char* pName, int pBar_colour) {
 
    //char s[16]; // Pierre-Marie Baty -- unused variable
 
    int i;
 
    LOG_TRACE("(%d, %d, \"%s\", %d)", pY, pLevel, pName, pBar_colour);
 
 
 
    DimRectangle(gBack_screen, gCurrent_graf_data->ps_dim_left, pY, gCurrent_graf_data->ps_dim_right, gCurrent_graf_data->ps_dim_height + pY, 1);
 
    TransDRPixelmapText(gBack_screen, gCurrent_graf_data->ps_name_left, gCurrent_graf_data->ps_name_top_border + pY, gFonts + 6, pName, gBack_screen->width);
 
 
 
    for (i = (6 - gCurrent_graf_data->ps_bars_per_level) * gCurrent_graf_data->ps_bars_per_level + 1; i > (gCurrent_graf_data->ps_bars_per_level * pLevel + 1); i--) {
 
        DubreyBar(i, pY + gCurrent_graf_data->ps_bar_top_border, 0);
 
    }
 
    for (i = gCurrent_graf_data->ps_bars_per_level * pLevel + 1; i >= 0; i--) {
 
        DubreyBar(i, pY + gCurrent_graf_data->ps_bar_top_border, pBar_colour);
 
    }
 
}
 
 
 
// IDA: void __cdecl DoPSPowerupHeadups()
 
void DoPSPowerupHeadups(void) {
 
    LOG_TRACE("()");
 
 
 
    DoPSPowerHeadup(gCurrent_graf_data->armour_headup_y[gProgram_state.cockpit_on], gProgram_state.current_car.power_up_levels[0], "A", 45);
 
    DoPSPowerHeadup(gCurrent_graf_data->power_headup_y[gProgram_state.cockpit_on], gProgram_state.current_car.power_up_levels[1], "P", 99);
 
    DoPSPowerHeadup(gCurrent_graf_data->offense_headup_y[gProgram_state.cockpit_on], gProgram_state.current_car.power_up_levels[2], "O", 4);
 
}
 
 
 
// IDA: void __usercall DoHeadups(tU32 pThe_time@<EAX>)
 
void DoHeadups(tU32 pThe_time) {
 
    int i;
 
    int x_offset;
 
    int y_offset;
 
    tHeadup* the_headup;
 
    int time_factor;
 
    LOG_TRACE("(%d)", pThe_time);
 
 
 
    if (gNet_mode) {
 
        DoNetScores();
 
    }
 
    if (gQueued_headup_count && PDGetTotalTime() - gLast_centre_headup >= 1000) {
 
        NewTextHeadupSlot(4, gQueued_headups[0].flash_rate,
 
            gQueued_headups[0].lifetime,
 
            gQueued_headups[0].font_index,
 
            gQueued_headups[0].text);
 
        KillOldestQueuedHeadup();
 
    }
 
 
 
    for (i = 0; i < COUNT_OF(gHeadups); i++) {
 
        the_headup = &gHeadups[i];
 
        if (the_headup->type != eHeadup_unused
 
            && (gProgram_state.which_view == eView_forward || !the_headup->cockpit_anchored)
 
            && (the_headup->type == eHeadup_image
 
                || the_headup->type == eHeadup_fancy
 
                || (the_headup->type == eHeadup_text && the_headup->data.text_info.text[0] != '\0')
 
                || ((the_headup->type == eHeadup_coloured_text || the_headup->type == eHeadup_box_text)
 
                    && the_headup->data.text_info.text[0] != '\0'))) {
 
            if (the_headup->type == eHeadup_fancy || the_headup->end_time == 0 || pThe_time < the_headup->end_time) {
 
                if (the_headup->dimmed_background) {
 
                    DimRectangle(
 
                        gBack_screen,
 
                        the_headup->dim_left,
 
                        the_headup->dim_top,
 
                        the_headup->dim_right,
 
                        the_headup->dim_bottom,
 
                        1);
 
                }
 
                if (the_headup->flash_period == 0
 
                    || Flash(the_headup->flash_period, &the_headup->last_flash, &the_headup->flash_state)) {
 
                    switch (the_headup->type) {
 
                    case eHeadup_text:
 
                        if (the_headup->cockpit_anchored) {
 
                            y_offset = gScreen_wobble_y;
 
                        } else {
 
                            y_offset = 0;
 
                        }
 
                        if (the_headup->cockpit_anchored) {
 
                            x_offset = gScreen_wobble_x;
 
                        } else {
 
                            x_offset = 0;
 
                        }
 
                        TransBrPixelmapText(
 
                            gBack_screen,
 
                            x_offset + the_headup->x,
 
                            y_offset + the_headup->y,
 
                            the_headup->data.text_info.colour,
 
                            the_headup->data.text_info.font,
 
                            the_headup->data.text_info.text);
 
                        break;
 
                    case eHeadup_coloured_text:
 
                        if (the_headup->clever) {
 
                            if (the_headup->cockpit_anchored) {
 
                                y_offset = gScreen_wobble_y;
 
                            } else {
 
                                y_offset = 0;
 
                            }
 
                            if (the_headup->cockpit_anchored) {
 
                                x_offset = gScreen_wobble_x;
 
                            } else {
 
                                x_offset = 0;
 
                            }
 
                            TransDRPixelmapCleverText(
 
                                gBack_screen,
 
                                x_offset + the_headup->x,
 
                                y_offset + the_headup->y,
 
                                the_headup->data.coloured_text_info.coloured_font,
 
                                the_headup->data.coloured_text_info.text,
 
                                the_headup->right_edge);
 
                        } else {
 
                            if (the_headup->cockpit_anchored) {
 
                                y_offset = gScreen_wobble_y;
 
                            } else {
 
                                y_offset = 0;
 
                            }
 
                            if (the_headup->cockpit_anchored) {
 
                                x_offset = gScreen_wobble_x;
 
                            } else {
 
                                x_offset = 0;
 
                            }
 
                            TransDRPixelmapText(
 
                                gBack_screen,
 
                                x_offset + the_headup->x,
 
                                y_offset + the_headup->y,
 
                                the_headup->data.coloured_text_info.coloured_font,
 
                                the_headup->data.coloured_text_info.text,
 
                                the_headup->right_edge);
 
                        }
 
                        break;
 
                    case eHeadup_image:
 
                        if (the_headup->cockpit_anchored) {
 
                            y_offset = gScreen_wobble_y;
 
                        } else {
 
                            y_offset = 0;
 
                        }
 
                        if (the_headup->cockpit_anchored) {
 
                            x_offset = gScreen_wobble_x;
 
                        } else {
 
                            x_offset = 0;
 
                        }
 
                        DRPixelmapRectangleMaskedCopy(
 
                            gBack_screen,
 
                            x_offset + the_headup->x,
 
                            y_offset + the_headup->y,
 
                            the_headup->data.image_info.image,
 
                            0,
 
                            0,
 
                            the_headup->data.image_info.image->width,
 
                            the_headup->data.image_info.image->height);
 
                        break;
 
 
 
                    case eHeadup_fancy:
 
                        switch (the_headup->data.fancy_info.fancy_stage) {
 
                        case eFancy_stage_incoming:
 
                            the_headup->data.fancy_info.offset -= 500 * gFrame_period / 1000;
 
                            if (the_headup->data.fancy_info.offset <= the_headup->data.fancy_info.shear_amount) {
 
                                the_headup->data.fancy_info.offset = the_headup->data.fancy_info.shear_amount;
 
                                the_headup->data.fancy_info.fancy_stage = eFancy_stage_halting;
 
                                the_headup->data.fancy_info.start_time = GetTotalTime();
 
                            }
 
                            DRPixelmapRectangleShearedCopy(
 
                                gBack_screen,
 
                                the_headup->x + the_headup->data.fancy_info.offset,
 
                                the_headup->y,
 
                                the_headup->data.fancy_info.image,
 
                                0,
 
                                0,
 
                                the_headup->data.fancy_info.image->width,
 
                                the_headup->data.fancy_info.image->height,
 
                                -65536);
 
                            break;
 
                        case eFancy_stage_halting:
 
                            time_factor = 1000 * (pThe_time - the_headup->data.fancy_info.start_time) / 100;
 
                            if (time_factor > 1000) {
 
                                if (time_factor > 1500) {
 
                                    time_factor = 1500;
 
                                    the_headup->data.fancy_info.fancy_stage = eFancy_stage_waiting;
 
                                    the_headup->data.fancy_info.start_time = GetTotalTime();
 
                                }
 
                                DRPixelmapRectangleShearedCopy(
 
                                    gBack_screen,
 
                                    the_headup->x - (1500 - time_factor) * the_headup->data.fancy_info.shear_amount / 500,
 
                                    the_headup->y,
 
                                    the_headup->data.image_info.image,
 
                                    0,
 
                                    0,
 
                                    the_headup->data.image_info.image->width,
 
                                    the_headup->data.image_info.image->height,
 
                                    (((1500 - time_factor) * the_headup->data.fancy_info.shear_amount / 500) << 16)
 
                                        / the_headup->data.image_info.image->height);
 
                            } else {
 
#if DETHRACE_FIX_BUGS
 
                                time_factor = MAX(time_factor, 0);
 
#endif
 
                                DRPixelmapRectangleShearedCopy(
 
                                    gBack_screen,
 
                                    the_headup->x - the_headup->data.fancy_info.shear_amount * (time_factor - 500) / 500,
 
                                    the_headup->y,
 
                                    the_headup->data.image_info.image,
 
                                    0,
 
                                    0,
 
                                    the_headup->data.image_info.image->width,
 
                                    the_headup->data.image_info.image->height,
 
                                    ((the_headup->data.fancy_info.shear_amount * (time_factor - 500) / 500) << 16)
 
                                        / the_headup->data.image_info.image->height);
 
                            }
 
                            break;
 
                        case eFancy_stage_waiting:
 
                            if (pThe_time - the_headup->data.fancy_info.start_time > 1000) {
 
                                the_headup->data.fancy_info.fancy_stage = eFancy_stage_readying;
 
                                the_headup->data.fancy_info.start_time = GetTotalTime();
 
                            }
 
                            DRPixelmapRectangleMaskedCopy(
 
                                gBack_screen,
 
                                the_headup->x,
 
                                the_headup->y,
 
                                the_headup->data.image_info.image,
 
                                0,
 
                                0,
 
                                the_headup->data.image_info.image->width,
 
                                the_headup->data.image_info.image->height);
 
                            break;
 
                        case eFancy_stage_readying:
 
                            time_factor = 1000 * (pThe_time - the_headup->data.fancy_info.start_time) / 100;
 
                            if (time_factor > 1000) {
 
                                time_factor = 1000;
 
                                the_headup->data.fancy_info.fancy_stage = eFancy_stage_leaving;
 
                                the_headup->data.fancy_info.start_time = GetTotalTime();
 
                                the_headup->data.fancy_info.offset = 0;
 
                            }
 
                            DRPixelmapRectangleShearedCopy(
 
                                gBack_screen,
 
                                the_headup->x,
 
                                the_headup->y,
 
                                the_headup->data.image_info.image,
 
                                0,
 
                                0,
 
                                the_headup->data.image_info.image->width,
 
                                the_headup->data.image_info.image->height,
 
                                -(((time_factor * the_headup->data.fancy_info.shear_amount / 1000) << 16)
 
                                    / the_headup->data.image_info.image->height));
 
                            break;
 
                        case eFancy_stage_leaving:
 
                            the_headup->data.fancy_info.offset -= 500 * gFrame_period / 1000;
 
                            if (the_headup->data.fancy_info.offset <= the_headup->data.fancy_info.end_offset) {
 
                                ClearHeadup(i);
 
                            } else {
 
                                DRPixelmapRectangleShearedCopy(
 
                                    gBack_screen,
 
                                    the_headup->data.fancy_info.offset + the_headup->x,
 
                                    the_headup->y,
 
                                    the_headup->data.image_info.image,
 
                                    0,
 
                                    0,
 
                                    the_headup->data.image_info.image->width,
 
                                    the_headup->data.image_info.image->height,
 
                                    -65536);
 
                            }
 
                            break;
 
                        default:
 
                            break;
 
                        }
 
                        break;
 
 
 
                    case eHeadup_box_text:
 
                        if (the_headup->cockpit_anchored) {
 
                            y_offset = gScreen_wobble_y;
 
                        } else {
 
                            y_offset = 0;
 
                        }
 
                        if (the_headup->cockpit_anchored) {
 
                            x_offset = gScreen_wobble_x;
 
                        } else {
 
                            x_offset = 0;
 
                        }
 
                        OoerrIveGotTextInMeBoxMissus(
 
                            the_headup->data.coloured_text_info.coloured_font - gFonts,
 
                            the_headup->data.coloured_text_info.text,
 
                            gBack_screen,
 
                            gBack_screen->width / 10,
 
                            x_offset + the_headup->y,
 
                            9 * gBack_screen->width / 10,
 
                            y_offset + the_headup->y + 60,
 
                            1);
 
                        break;
 
                    default:
 
                        break;
 
                    }
 
                }
 
            } else {
 
                ClearHeadup(i);
 
            }
 
        }
 
    }
 
    DoPSPowerupHeadups();
 
}
 
 
 
// IDA: int __usercall FindAHeadupHoleWoofBarkSoundsABitRude@<EAX>(int pSlot_index@<EAX>)
 
int FindAHeadupHoleWoofBarkSoundsABitRude(int pSlot_index) {
 
    int i;
 
    int empty_one;
 
    tHeadup* the_headup;
 
    LOG_TRACE("(%d)", pSlot_index);
 
 
 
    empty_one = -1;
 
    for (i = 0, the_headup = gHeadups; i < COUNT_OF(gHeadups); i++, the_headup++) {
 
        if (pSlot_index >= 0 && the_headup->slot_index == pSlot_index) {
 
            return i;
 
        }
 
        if (the_headup->type == eHeadup_unused) {
 
            empty_one = i;
 
        }
 
    }
 
    return empty_one;
 
}
 
 
 
// IDA: int __usercall DRTextWidth@<EAX>(tDR_font *pFont@<EAX>, char *pText@<EDX>)
 
int DRTextWidth(tDR_font* pFont, char* pText) {
 
    int i;
 
    int len;
 
    int result;
 
    char* c;
 
    LOG_TRACE("(%p, \"%s\")", pFont, pText);
 
 
 
    c = pText;
 
    result = 0;
 
 
 
    for (i = 0; i < len; i++) {
 
        result += pFont->width_table[*c - pFont->offset];
 
        c++;
 
    }
 
    return result + pFont->spacing * (len - 1);
 
}
 
 
 
// IDA: int __usercall DRTextCleverWidth@<EAX>(tDR_font *pFont@<EAX>, signed char *pText@<EDX>)
 
int DRTextCleverWidth(tDR_font* pFont, signed char* pText) {
 
    int i;
 
    int len;
 
    int result;
 
    unsigned char* c;
 
    LOG_TRACE("(%p, %p)", pFont, pText);
 
 
 
    result = 0;
 
    len 
= strlen((char*)pText
) + 1; 
 
 
    for (i = 0, c = (unsigned char*)pText; i < len; i++, c++) {
 
        if (*c < 224) {
 
            if (i < (len - 1)) {
 
                result += pFont->spacing;
 
            }
 
            result += pFont->width_table[*c - pFont->offset];
 
        } else {
 
            pFont = &gFonts[256 - *c];
 
        }
 
    }
 
    return result;
 
}
 
 
 
// IDA: void __usercall DRPixelmapCentredText(br_pixelmap *pPixelmap@<EAX>, int pX@<EDX>, int pY@<EBX>, tDR_font *pFont@<ECX>, char *pText)
 
void DRPixelmapCentredText(br_pixelmap* pPixelmap, int pX, int pY, tDR_font* pFont, char* pText) {
 
    int width_over_2;
 
    LOG_TRACE("(%p, %d, %d, %p, \"%s\")", pPixelmap, pX, pY, pFont, pText);
 
 
 
    width_over_2 = DRTextWidth(pFont, pText) / 2;
 
    TransDRPixelmapText(pPixelmap, pX - width_over_2, pY, pFont, pText, width_over_2 + pX);
 
}
 
 
 
// IDA: int __usercall IsHeadupTextClever@<EAX>(signed char *pText@<EAX>)
 
int IsHeadupTextClever(signed char* pText) {
 
    LOG_TRACE("(%p)", pText);
 
 
 
    while (*pText) {
 
        if (*pText < 0) {
 
            return 1;
 
        }
 
        pText++;
 
    }
 
    return 0;
 
}
 
 
 
// IDA: int __usercall MungeHeadupWidth@<EAX>(tHeadup *pHeadup@<EAX>)
 
int MungeHeadupWidth(tHeadup* pHeadup) {
 
    int width;
 
    LOG_TRACE("(%p)", pHeadup);
 
 
 
    width = 0;
 
    if (pHeadup->type == eHeadup_box_text) {
 
        return 0;
 
    }
 
    if (pHeadup->type == eHeadup_coloured_text) {
 
        pHeadup->clever = IsHeadupTextClever((signed char*)(&pHeadup->data.text_info.text));
 
        if (pHeadup->justification) {
 
            if (pHeadup->justification == eJust_right) {
 
                if (pHeadup->clever) {
 
                    width = DRTextCleverWidth(
 
                        pHeadup->data.coloured_text_info.coloured_font,
 
                        (signed char*)(&pHeadup->data.text_info.text));
 
                } else {
 
                    width = DRTextWidth(pHeadup->data.coloured_text_info.coloured_font, pHeadup->data.text_info.text);
 
                }
 
                pHeadup->x = pHeadup->original_x - width;
 
            } else if (pHeadup->justification == eJust_centre) {
 
                if (pHeadup->clever) {
 
                    width = DRTextCleverWidth(
 
                        pHeadup->data.coloured_text_info.coloured_font,
 
                        (signed char*)(&pHeadup->data.text_info.text));
 
                } else {
 
                    width = DRTextWidth(pHeadup->data.coloured_text_info.coloured_font, pHeadup->data.text_info.text);
 
                }
 
                pHeadup->x = pHeadup->original_x - width / 2;
 
            }
 
        } else {
 
            pHeadup->x = pHeadup->original_x;
 
        }
 
    } else {
 
        pHeadup->clever = 0;
 
        if (pHeadup->justification) {
 
            if (pHeadup->justification == eJust_right) {
 
                width = BrPixelmapTextWidth(gBack_screen, pHeadup->data.text_info.font, pHeadup->data.text_info.text);
 
                pHeadup->x = pHeadup->original_x - width;
 
            } else if (pHeadup->justification == eJust_centre) {
 
                width = BrPixelmapTextWidth(gBack_screen, pHeadup->data.text_info.font, pHeadup->data.text_info.text);
 
                pHeadup->x = pHeadup->original_x - width / 2;
 
            }
 
        } else {
 
            pHeadup->x = pHeadup->original_x;
 
        }
 
    }
 
    return width;
 
}
 
 
 
// IDA: int __usercall NewTextHeadupSlot2@<EAX>(int pSlot_index@<EAX>, int pFlash_rate@<EDX>, int pLifetime@<EBX>, int pFont_index@<ECX>, char *pText, int pQueue_it)
 
int NewTextHeadupSlot2(int pSlot_index, int pFlash_rate, int pLifetime, int pFont_index, char* pText, int pQueue_it) {
 
    int index;
 
    tHeadup* the_headup;
 
    tHeadup_slot* headup_slot;
 
    LOG_TRACE("(%d, %d, %d, %d, \"%s\", %d)", pSlot_index, pFlash_rate, pLifetime, pFont_index, pText, pQueue_it);
 
 
 
    if (pQueue_it 
&& pSlot_index 
== 4 && time - gLast_centre_headup 
< 1000) {  
        if (gQueued_headup_count == 4) {
 
            KillOldestQueuedHeadup();
 
        }
 
        gQueued_headups[gQueued_headup_count].flash_rate = pFlash_rate;
 
        gQueued_headups[gQueued_headup_count].lifetime = pLifetime;
 
        gQueued_headups[gQueued_headup_count].font_index = pFont_index;
 
        strcpy(gQueued_headups
[gQueued_headup_count
].
text, pText
);  
        gQueued_headup_count++;
 
        index = -1;
 
    } else {
 
        index = FindAHeadupHoleWoofBarkSoundsABitRude(pSlot_index);
 
        if (index >= 0) {
 
            if (pSlot_index == 4) {
 
                gLast_centre_headup 
= time; 
            }
 
            headup_slot = &gProgram_state.current_car.headup_slots[gProgram_state.cockpit_on][pSlot_index];
 
            the_headup = &gHeadups[index];
 
            the_headup->data.coloured_text_info.coloured_font = &gFonts[-pFont_index];
 
            if (pSlot_index == 4) {
 
                the_headup->type = eHeadup_box_text;
 
            } else {
 
                the_headup->type = eHeadup_coloured_text;
 
            }
 
            if (!pText) {
 
                LOG_PANIC("panic");
 
            }
 
            strcpy(the_headup
->data.
text_info.
text, pText
);  
 
 
            the_headup->slot_index = pSlot_index;
 
            the_headup->justification = headup_slot->justification;
 
            if (pSlot_index < 0) {
 
                the_headup->cockpit_anchored = 0;
 
            } else {
 
                the_headup->cockpit_anchored = headup_slot->cockpit_anchored;
 
            }
 
            the_headup->dimmed_background = headup_slot->dimmed_background;
 
            the_headup->dim_left = headup_slot->dim_left;
 
            the_headup->dim_top = headup_slot->dim_top;
 
            the_headup->dim_right = headup_slot->dim_right;
 
            the_headup->dim_bottom = headup_slot->dim_bottom;
 
            the_headup->original_x = headup_slot->x;
 
            the_headup->right_edge = MungeHeadupWidth(the_headup) + the_headup->x;
 
            the_headup->y = headup_slot->y;
 
            if (pFlash_rate) {
 
                the_headup->flash_period = 1000 / pFlash_rate;
 
            } else {
 
                the_headup->flash_period = 0;
 
            }
 
            the_headup->last_flash = 0;
 
            the_headup->flash_state = 0;
 
            if (pLifetime) {
 
                the_headup->end_time = GetTotalTime() + pLifetime;
 
            } else {
 
                the_headup->end_time = 0;
 
            }
 
        }
 
    }
 
    return index;
 
}
 
 
 
// IDA: int __usercall NewTextHeadupSlot@<EAX>(int pSlot_index@<EAX>, int pFlash_rate@<EDX>, int pLifetime@<EBX>, int pFont_index@<ECX>, char *pText)
 
int NewTextHeadupSlot(int pSlot_index, int pFlash_rate, int pLifetime, int pFont_index, char* pText) {
 
    LOG_TRACE("(%d, %d, %d, %d, \"%s\")", pSlot_index, pFlash_rate, pLifetime, pFont_index, pText);
 
 
 
    return NewTextHeadupSlot2(pSlot_index, pFlash_rate, pLifetime, pFont_index, pText, 1);
 
}
 
 
 
// IDA: int __usercall NewImageHeadupSlot@<EAX>(int pSlot_index@<EAX>, int pFlash_rate@<EDX>, int pLifetime@<EBX>, int pImage_index@<ECX>)
 
int NewImageHeadupSlot(int pSlot_index, int pFlash_rate, int pLifetime, int pImage_index) {
 
    int index;
 
    tHeadup* the_headup;
 
    tHeadup_slot* headup_slot;
 
    LOG_TRACE("(%d, %d, %d, %d)", pSlot_index, pFlash_rate, pLifetime, pImage_index);
 
 
 
    index = FindAHeadupHoleWoofBarkSoundsABitRude(pSlot_index);
 
    if (index >= 0) {
 
        headup_slot = &gProgram_state.current_car.headup_slots[gProgram_state.cockpit_on][pSlot_index];
 
        the_headup = &gHeadups[index];
 
        the_headup->type = eHeadup_image;
 
        the_headup->slot_index = pSlot_index;
 
        the_headup->justification = headup_slot->justification;
 
        if (pSlot_index < 0) {
 
            the_headup->cockpit_anchored = 0;
 
        } else {
 
            the_headup->cockpit_anchored = headup_slot->cockpit_anchored;
 
        }
 
        the_headup->dimmed_background = headup_slot->dimmed_background;
 
        the_headup->dim_left = headup_slot->dim_left;
 
        the_headup->dim_top = headup_slot->dim_top;
 
        the_headup->dim_right = headup_slot->dim_right;
 
        the_headup->dim_bottom = headup_slot->dim_bottom;
 
        the_headup->original_x = headup_slot->x;
 
 
 
        if (headup_slot->justification) {
 
            if (headup_slot->justification == eJust_right) {
 
                the_headup->x = the_headup->original_x - gHeadup_images[pImage_index]->width;
 
            } else if (headup_slot->justification == eJust_centre) {
 
                the_headup->x = the_headup->original_x - gHeadup_images[pImage_index]->width / 2;
 
            }
 
        } else {
 
            the_headup->x = the_headup->original_x;
 
        }
 
        the_headup->y = headup_slot->y;
 
        if (pFlash_rate) {
 
            the_headup->flash_period = 1000 / pFlash_rate;
 
        } else {
 
            the_headup->flash_period = 0;
 
        }
 
        the_headup->last_flash = 0;
 
        the_headup->flash_state = 0;
 
        if (pLifetime) {
 
            the_headup->end_time = GetTotalTime() + pLifetime;
 
        } else {
 
            the_headup->end_time = 0;
 
        }
 
        the_headup->data.image_info.image = gHeadup_images[pImage_index];
 
    }
 
    return index;
 
}
 
 
 
// IDA: void __usercall DoFancyHeadup(int pIndex@<EAX>)
 
void DoFancyHeadup(int pIndex) {
 
    tU32 the_time;
 
    tHeadup* the_headup;
 
    int temp_ref;
 
    LOG_TRACE("(%d)", pIndex);
 
 
 
    the_time = GetTotalTime();
 
    if (!gMap_mode && (gLast_fancy_index < 0 || the_time - gLast_fancy_time > 2000 || gLast_fancy_index <= pIndex)) {
 
        temp_ref = NewImageHeadupSlot(6, 0, 2000, pIndex + 10);
 
        if (temp_ref >= 0) {
 
            gLast_fancy_headup = temp_ref;
 
            gLast_fancy_index = pIndex;
 
            gLast_fancy_time = the_time;
 
            the_headup = &gHeadups[temp_ref];
 
            the_headup->type = eHeadup_fancy;
 
            the_headup->data.fancy_info.offset = (the_headup->data.image_info.image->width + gBack_screen->width) / 2;
 
            the_headup->data.fancy_info.end_offset = -the_headup->data.fancy_info.offset;
 
            the_headup->data.fancy_info.fancy_stage = eFancy_stage_incoming;
 
            the_headup->data.fancy_info.shear_amount = the_headup->data.image_info.image->height;
 
        }
 
    }
 
}
 
 
 
// IDA: void __cdecl AdjustHeadups()
 
void AdjustHeadups(void) {
 
    int i;
 
    int delta_x;
 
    int delta_y;
 
    tHeadup* the_headup;
 
    LOG_TRACE("()");
 
 
 
    the_headup = gHeadups;
 
    for (i = 0; i < COUNT_OF(gHeadups); i++) {
 
        the_headup = &gHeadups[i];
 
        if (the_headup->type == eHeadup_unused) {
 
            continue;
 
        }
 
        delta_x = gProgram_state.current_car.headup_slots[gProgram_state.cockpit_on && gProgram_state.cockpit_image_index >= 0][the_headup->slot_index].x
 
            - gProgram_state.current_car.headup_slots[!gProgram_state.cockpit_on || gProgram_state.cockpit_image_index < 0][the_headup->slot_index].x;
 
        delta_y = gProgram_state.current_car.headup_slots[gProgram_state.cockpit_on && gProgram_state.cockpit_image_index >= 0][the_headup->slot_index].y
 
            - gProgram_state.current_car.headup_slots[!gProgram_state.cockpit_on || gProgram_state.cockpit_image_index < 0][the_headup->slot_index].y;
 
        the_headup->x += delta_x;
 
        the_headup->original_x += delta_x;
 
        the_headup->y += delta_y;
 
        the_headup->dim_left += delta_x;
 
        the_headup->dim_top += delta_y;
 
        the_headup->dim_right += delta_x;
 
        the_headup->dim_bottom += delta_y;
 
    }
 
}
 
 
 
// IDA: void __usercall MoveHeadupTo(int pHeadup_index@<EAX>, int pNew_x@<EDX>, int pNew_y@<EBX>)
 
void MoveHeadupTo(int pHeadup_index, int pNew_x, int pNew_y) {
 
    //int delta_x; // Pierre-Marie Baty -- unused variable
 
    //tHeadup* the_headup; // Pierre-Marie Baty -- unused variable
 
    LOG_TRACE("(%d, %d, %d)", pHeadup_index, pNew_x, pNew_y);
 
    NOT_IMPLEMENTED();
 
}
 
 
 
// IDA: void __usercall ChangeHeadupText(int pHeadup_index@<EAX>, char *pNew_text@<EDX>)
 
void ChangeHeadupText(int pHeadup_index, char* pNew_text) {
 
    tHeadup* the_headup;
 
    LOG_TRACE("(%d, \"%s\")", pHeadup_index, pNew_text);
 
 
 
    if (pHeadup_index >= 0) {
 
        the_headup = &gHeadups[pHeadup_index];
 
        strcpy(the_headup
->data.
text_info.
text, pNew_text
);  
        MungeHeadupWidth(the_headup);
 
    }
 
}
 
 
 
// IDA: void __usercall ChangeHeadupImage(int pHeadup_index@<EAX>, int pNew_image@<EDX>)
 
void ChangeHeadupImage(int pHeadup_index, int pNew_image) {
 
    tHeadup* the_headup;
 
    LOG_TRACE("(%d, %d)", pHeadup_index, pNew_image);
 
 
 
    if (pHeadup_index >= 0) {
 
        the_headup = &gHeadups[pHeadup_index];
 
        the_headup->data.image_info.image = gHeadup_images[pNew_image];
 
        switch (the_headup->justification) {
 
        case eJust_left:
 
            the_headup->x = the_headup->original_x;
 
            break;
 
        case eJust_right:
 
            the_headup->x = the_headup->original_x - the_headup->data.image_info.image->width;
 
            break;
 
        case eJust_centre:
 
            the_headup->x = the_headup->original_x - the_headup->data.image_info.image->width / 2;
 
            break;
 
        }
 
    }
 
}
 
 
 
// IDA: void __usercall ChangeHeadupColour(int pHeadup_index@<EAX>, int pNew_colour@<EDX>)
 
void ChangeHeadupColour(int pHeadup_index, int pNew_colour) {
 
    LOG_TRACE("(%d, %d)", pHeadup_index, pNew_colour);
 
 
 
    if (pHeadup_index >= 0) {
 
        gHeadups[pHeadup_index].data.text_info.colour = gColours[pNew_colour];
 
    }
 
}
 
 
 
// IDA: void __usercall DoDamageScreen(tU32 pThe_time@<EAX>)
 
void DoDamageScreen(tU32 pThe_time) {
 
    int i;
 
    int y_pitch;
 
    int the_step;
 
    int the_wobble_x;
 
    int the_wobble_y;
 
    br_pixelmap* the_image;
 
    tDamage_unit* the_damage;
 
    LOG_TRACE("(%d)", pThe_time);
 
 
 
    if (&gProgram_state.current_car != gCar_to_view || gProgram_state.current_car_index != gProgram_state.current_car.index) {
 
        return;
 
    }
 
    if (gProgram_state.cockpit_on && gProgram_state.cockpit_image_index >= 0) {
 
        if (gProgram_state.which_view != eView_forward) {
 
            return;
 
        }
 
        the_wobble_x = gScreen_wobble_x;
 
        the_wobble_y = gScreen_wobble_y;
 
    } else {
 
        the_wobble_x = gProgram_state.current_car.damage_x_offset;
 
        the_wobble_y = gProgram_state.current_car.damage_y_offset;
 
        if (gProgram_state.current_car.damage_background != NULL) {
 
            DRPixelmapRectangleMaskedCopy(
 
                gBack_screen,
 
                gProgram_state.current_car.damage_background_x,
 
                gProgram_state.current_car.damage_background_y,
 
                gProgram_state.current_car.damage_background,
 
                0,
 
                0,
 
                gProgram_state.current_car.damage_background->width,
 
                gProgram_state.current_car.damage_background->height);
 
        }
 
    }
 
    for (i = 0; i < COUNT_OF(gProgram_state.current_car.damage_units); i++) {
 
        the_damage = &gProgram_state.current_car.damage_units[i];
 
        if (i != eDamage_driver) {
 
            the_image = the_damage->images;
 
            the_step = 5 * the_damage->damage_level / 100;
 
            y_pitch = (the_image->height / 2) / 5;
 
            DRPixelmapRectangleMaskedCopy(
 
                gBack_screen,
 
                the_wobble_x + gProgram_state.current_car.damage_units[i].x_coord,
 
                the_wobble_y + gProgram_state.current_car.damage_units[i].y_coord,
 
                the_image,
 
                0,
 
                y_pitch * (2 * the_step + ((pThe_time / the_damage->periods[the_step]) & 1)),
 
                the_image->width,
 
                y_pitch);
 
        }
 
    }
 
}
 
 
 
// IDA: void __cdecl PoshDrawLine(float pAngle, br_pixelmap *pDestn, int pX1, int pY1, int pX2, int pY2, int pColour)
 
void PoshDrawLine(float pAngle, br_pixelmap* pDestn, int pX1, int pY1, int pX2, int pY2, int pColour) {
 
    LOG_TRACE("(%f, %p, %d, %d, %d, %d, %d)", pAngle, pDestn, pX1, pY1, pX2, pY2, pColour);
 
 
 
    if (pColour < 0) {
 
        if (pAngle >= 0.785 && pAngle <= 5.498 && (pAngle <= 2.356 || pAngle >= 3.926)) {
 
            if ((pAngle <= 0.785 || pAngle >= 1.57) && (pAngle <= 3.926 || pAngle >= 4.712)) {
 
                DRDrawLine(pDestn, pX1 - 1, pY1, pX2 - 1, pY2, -pColour - 1);
 
                DRDrawLine(pDestn, pX1 + 1, pY1, pX2 + 1, pY2, 1 - pColour);
 
            } else {
 
                DRDrawLine(pDestn, pX1 - 1, pY1, pX2 - 1, pY2, 1 - pColour);
 
                DRDrawLine(pDestn, pX1 + 1, pY1, pX2 + 1, pY2, -pColour - 1);
 
            }
 
        } else {
 
            DRDrawLine(pDestn, pX1, pY1 + 1, pX2, pY2 + 1, -pColour - 1);
 
            DRDrawLine(pDestn, pX1, pY1 - 1, pX2, pY2 - 1, 1 - pColour);
 
        }
 
        DRDrawLine(pDestn, pX1, pY1, pX2, pY2, -pColour);
 
    } else {
 
        DRDrawLine(pDestn, pX1, pY1, pX2, pY2, pColour);
 
    }
 
}
 
 
 
// IDA: void __usercall DoInstruments(tU32 pThe_time@<EAX>)
 
void DoInstruments(tU32 pThe_time) {
 
    br_pixelmap* speedo_image;
 
    br_pixelmap* tacho_image;
 
    int the_wobble_x;
 
    int the_wobble_y;
 
    int gear;
 
    int gear_height; /* Added by dethrace. */
 
    double the_angle;
 
    double the_angle2;
 
    double sin_angle;
 
    double cos_angle;
 
    double speed_mph;
 
    LOG_TRACE("(%d)", pThe_time);
 
 
 
    if (gProgram_state.current_car_index == gProgram_state.current_car.index) {
 
        speed_mph = gCar_to_view->speedo_speed * WORLD_SCALE / 1600.0f * 3600000.0f;
 
        if (speed_mph < 0.0f) {
 
            speed_mph = 0.0f;
 
        }
 
        if (gProgram_state.cockpit_on && gProgram_state.cockpit_image_index >= 0) {
 
            if (gProgram_state.which_view != eView_forward) {
 
                return;
 
            }
 
            the_wobble_x = gScreen_wobble_x;
 
            the_wobble_y = gScreen_wobble_y;
 
        } else {
 
            the_wobble_x = 0;
 
            the_wobble_y = 0;
 
        }
 
        tacho_image = gProgram_state.current_car.tacho_image[gProgram_state.cockpit_on];
 
        if (gProgram_state.current_car.tacho_radius_2[gProgram_state.cockpit_on] >= 0) {
 
            if (gCar_to_view->red_line >= gCar_to_view->revs) {
 
                the_angle = DEG_TO_RAD((double)(gProgram_state.current_car.tacho_end_angle[gProgram_state.cockpit_on] - gProgram_state.current_car.tacho_start_angle[gProgram_state.cockpit_on]) * gCar_to_view->revs / (double)gCar_to_view->red_line + (double)gProgram_state.current_car.tacho_start_angle[gProgram_state.cockpit_on]);
 
            } else {
 
                the_angle = DEG_TO_RAD((double)gProgram_state.current_car.tacho_end_angle[gProgram_state.cockpit_on]);
 
            }
 
            if (the_angle >= 0.0) {
 
                if (the_angle >= TAU) {
 
                    the_angle -= TAU;
 
                }
 
            } else {
 
                the_angle += TAU;
 
            }
 
            the_angle2 = DR_PI_OVER_2 - the_angle;
 
            if (the_angle2 < 0) {
 
                the_angle2 += TAU;
 
            }
 
            if (the_angle2 > DR_3PI_OVER_2) {
 
                cos_angle = gCosine_array[(unsigned int)((TAU - the_angle2) / DR_PI * 128.0)];
 
            } else if (the_angle2 > DR_PI) {
 
                cos_angle = -gCosine_array[(unsigned int)((the_angle2 - DR_PI) / DR_PI * 128.0)];
 
#if defined(DETHRACE_FIX_BUGS)
 
            } else if (the_angle2 >= DR_PI_OVER_2) {
 
#else
 
            } else if (the_angle2 > DR_PI_OVER_2) {
 
#endif
 
                cos_angle = -gCosine_array[(unsigned int)((DR_PI - the_angle2) / DR_PI * 128.0)];
 
            } else {
 
                cos_angle = gCosine_array[(unsigned int)(the_angle2 / DR_PI * 128.0)];
 
            }
 
            if (the_angle > DR_3PI_OVER_2) {
 
                sin_angle = gCosine_array[(unsigned int)((TAU - the_angle) / DR_PI * 128.0)];
 
            } else if (the_angle > DR_PI) {
 
                sin_angle = -gCosine_array[(unsigned int)((the_angle - DR_PI) / DR_PI * 128.0)];
 
#if defined(DETHRACE_FIX_BUGS)
 
            } else if (the_angle >= DR_PI_OVER_2) {
 
#else
 
            } else if (the_angle > DR_PI_OVER_2) {
 
#endif
 
                sin_angle = -gCosine_array[(unsigned int)((DR_PI - the_angle) / DR_PI * 128.0)];
 
            } else {
 
                sin_angle = gCosine_array[(unsigned int)(the_angle / DR_PI * 128.0)];
 
            }
 
            if (tacho_image != NULL) {
 
                DRPixelmapRectangleMaskedCopy(
 
                    gBack_screen,
 
                    the_wobble_x + gProgram_state.current_car.tacho_x[gProgram_state.cockpit_on],
 
                    the_wobble_y + gProgram_state.current_car.tacho_y[gProgram_state.cockpit_on],
 
                    tacho_image,
 
                    0,
 
                    0,
 
                    tacho_image->width,
 
                    tacho_image->height);
 
            }
 
 
 
            PoshDrawLine(
 
                the_angle,
 
                gBack_screen,
 
                ((double)gProgram_state.current_car.tacho_radius_1[gProgram_state.cockpit_on] * sin_angle
 
                    + (double)gProgram_state.current_car.tacho_centre_x[gProgram_state.cockpit_on]
 
                    + (double)the_wobble_x),
 
                ((double)gProgram_state.current_car.tacho_centre_y[gProgram_state.cockpit_on]
 
                    - (double)gProgram_state.current_car.tacho_radius_1[gProgram_state.cockpit_on] * cos_angle
 
                    + (double)the_wobble_y),
 
                ((double)gProgram_state.current_car.tacho_radius_2[gProgram_state.cockpit_on] * sin_angle
 
                    + (double)gProgram_state.current_car.tacho_centre_x[gProgram_state.cockpit_on]
 
                    + (double)the_wobble_x),
 
                ((double)gProgram_state.current_car.tacho_centre_y[gProgram_state.cockpit_on]
 
                    - (double)gProgram_state.current_car.tacho_radius_2[gProgram_state.cockpit_on] * cos_angle
 
                    + (double)the_wobble_y),
 
                gProgram_state.current_car.tacho_needle_colour[gProgram_state.cockpit_on]);
 
        } else if (tacho_image != NULL) {
 
            BrPixelmapRectangleCopy(
 
                gBack_screen,
 
                the_wobble_x + gProgram_state.current_car.tacho_x[gProgram_state.cockpit_on],
 
                the_wobble_y + gProgram_state.current_car.tacho_y[gProgram_state.cockpit_on],
 
                gProgram_state.current_car.tacho_image[gProgram_state.cockpit_on],
 
                0,
 
                0,
 
                ((gCar_to_view->revs - 1.0) / (double)gCar_to_view->red_line * (double)gProgram_state.current_car.tacho_image[gProgram_state.cockpit_on]->width + 1.0),
 
                gProgram_state.current_car.tacho_image[gProgram_state.cockpit_on]->height);
 
        }
 
        if (!gProgram_state.cockpit_on || gProgram_state.cockpit_image_index < 0 || gProgram_state.which_view == eView_forward) {
 
            if (gCar_to_view->gear < 0) {
 
                gear = -1;
 
            } else {
 
                gear = gCar_to_view->gear;
 
            }
 
#if defined(DETHRACE_FIX_BUGS)
 
/*
 
 * The OG derives gear mask height of 16 or 28 by `gears_image->height / 8`, but
 
 * this is only valid for HGEARS.PIX, which contains 8 gear images. Hardcoding
 
 * this number fixes gear rendering for cars using HGEARS4.PIX, which consists
 
 * of 11 gear images.
 
 */
 
#define GEAR_HEIGHT 16
 
#define GEAR_HEIGHT_HIRES 28
 
#else
 
#define GEAR_HEIGHT ((int)gProgram_state.current_car.gears_image->height / 8)
 
#define GEAR_HEIGHT_HIRES GEAR_HEIGHT
 
#endif
 
            gear_height = gGraf_spec_index ? GEAR_HEIGHT_HIRES : GEAR_HEIGHT;
 
            DRPixelmapRectangleMaskedCopy(
 
                gBack_screen,
 
                the_wobble_x + gProgram_state.current_car.gear_x[gProgram_state.cockpit_on],
 
                the_wobble_y + gProgram_state.current_car.gear_y[gProgram_state.cockpit_on],
 
                gProgram_state.current_car.gears_image,
 
                0,
 
                (gear + 1) * gear_height,
 
                gProgram_state.current_car.gears_image->width,
 
                gear_height);
 
        }
 
        speedo_image = gProgram_state.current_car.speedo_image[gProgram_state.cockpit_on];
 
        if (gProgram_state.current_car.speedo_radius_2[gProgram_state.cockpit_on] >= 0) {
 
            if (speedo_image && (!gProgram_state.cockpit_on || gProgram_state.cockpit_image_index < 0)) {
 
                DRPixelmapRectangleMaskedCopy(
 
                    gBack_screen,
 
                    the_wobble_x + gProgram_state.current_car.speedo_x[gProgram_state.cockpit_on],
 
                    the_wobble_y + gProgram_state.current_car.speedo_y[gProgram_state.cockpit_on],
 
                    speedo_image,
 
                    0,
 
                    0,
 
                    speedo_image->width,
 
                    speedo_image->height);
 
            }
 
            if ((double)gProgram_state.current_car.max_speed >= speed_mph) {
 
                the_angle = DEG_TO_RAD((double)(gProgram_state.current_car.speedo_end_angle[gProgram_state.cockpit_on] - gProgram_state.current_car.speedo_start_angle[gProgram_state.cockpit_on]) * speed_mph / (double)gProgram_state.current_car.max_speed + (double)gProgram_state.current_car.speedo_start_angle[gProgram_state.cockpit_on]);
 
            } else {
 
                the_angle = DEG_TO_RAD((double)gProgram_state.current_car.speedo_end_angle[gProgram_state.cockpit_on]);
 
            }
 
 
 
            if (the_angle < 0.0) {
 
                the_angle = the_angle + TAU;
 
            } else if (the_angle >= TAU) {
 
                the_angle -= TAU;
 
            }
 
            the_angle2 = DR_PI_OVER_2 - the_angle;
 
            if (the_angle2 < 0.0) {
 
                the_angle2 += TAU;
 
            }
 
            if (the_angle2 > DR_3PI_OVER_2) {
 
                cos_angle = gCosine_array[(unsigned int)((TAU - the_angle2) / DR_PI * 128.0)];
 
            } else if (the_angle2 > DR_PI) {
 
                cos_angle = -gCosine_array[(unsigned int)((the_angle2 - DR_PI) / DR_PI * 128.0)];
 
            } else if (the_angle2 > DR_PI_OVER_2) {
 
                cos_angle = -gCosine_array[(unsigned int)((DR_PI - the_angle2) / DR_PI * 128.0)];
 
            } else {
 
                cos_angle = gCosine_array[(unsigned int)(the_angle2 / DR_PI * 128.0)];
 
            }
 
 
 
            if (the_angle > DR_3PI_OVER_2) {
 
                sin_angle = gCosine_array[(unsigned int)((TAU - the_angle) / DR_PI * 128.0)];
 
            } else if (the_angle > DR_PI) {
 
                sin_angle = -gCosine_array[(unsigned int)((the_angle - DR_PI) / DR_PI * 128.0)];
 
            } else if (the_angle > DR_PI_OVER_2) {
 
                sin_angle = -gCosine_array[(unsigned int)((DR_PI - the_angle) / DR_PI * 128.0)];
 
            } else {
 
                sin_angle = gCosine_array[(unsigned int)(the_angle / DR_PI * 128.0)];
 
            }
 
 
 
            PoshDrawLine(
 
                the_angle,
 
                gBack_screen,
 
                ((double)gProgram_state.current_car.speedo_radius_1[gProgram_state.cockpit_on] * sin_angle
 
                    + (double)gProgram_state.current_car.speedo_centre_x[gProgram_state.cockpit_on]
 
                    + (double)the_wobble_x),
 
                ((double)gProgram_state.current_car.speedo_centre_y[gProgram_state.cockpit_on]
 
                    - (double)gProgram_state.current_car.speedo_radius_1[gProgram_state.cockpit_on] * cos_angle
 
                    + (double)the_wobble_y),
 
                ((double)gProgram_state.current_car.speedo_radius_2[gProgram_state.cockpit_on] * sin_angle
 
                    + (double)gProgram_state.current_car.speedo_centre_x[gProgram_state.cockpit_on]
 
                    + (double)the_wobble_x),
 
                ((double)gProgram_state.current_car.speedo_centre_y[gProgram_state.cockpit_on]
 
                    - (double)gProgram_state.current_car.speedo_radius_2[gProgram_state.cockpit_on] * cos_angle
 
                    + (double)the_wobble_y),
 
                gProgram_state.current_car.speedo_needle_colour[gProgram_state.cockpit_on]);
 
            if (speedo_image != NULL && gProgram_state.cockpit_on && gProgram_state.cockpit_image_index >= 0) {
 
                DRPixelmapRectangleMaskedCopy(
 
                    gBack_screen,
 
                    the_wobble_x + gProgram_state.current_car.speedo_x[gProgram_state.cockpit_on],
 
                    the_wobble_y + gProgram_state.current_car.speedo_y[gProgram_state.cockpit_on],
 
                    speedo_image,
 
                    0,
 
                    0,
 
                    speedo_image->width,
 
                    speedo_image->height);
 
            }
 
        } else if (speedo_image != NULL) {
 
            DrawNumberAt(
 
                speedo_image,
 
                the_wobble_x + gProgram_state.current_car.speedo_x[gProgram_state.cockpit_on],
 
                the_wobble_y + gProgram_state.current_car.speedo_y[gProgram_state.cockpit_on],
 
                gProgram_state.current_car.speedo_x_pitch[gProgram_state.cockpit_on],
 
                gProgram_state.current_car.speedo_y_pitch[gProgram_state.cockpit_on],
 
                speed_mph,
 
                3,
 
                1);
 
        }
 
    }
 
}
 
 
 
// IDA: void __usercall DoSteeringWheel(tU32 pThe_time@<EAX>)
 
void DoSteeringWheel(tU32 pThe_time) {
 
    br_pixelmap* hands_image;
 
    int hands_index;
 
    LOG_TRACE("(%d)", pThe_time);
 
 
 
    if (gProgram_state.current_car_index == gProgram_state.current_car.index && gProgram_state.cockpit_on && gProgram_state.cockpit_image_index >= 0 && gProgram_state.which_view == eView_forward) {
 
        hands_index 
= (int)floor(gProgram_state.
current_car.
number_of_hands_images * ((1.
f - gProgram_state.
current_car.
steering_angle / 10.
f) / 2.
f)); 
        if (hands_index < 0) {
 
            hands_index = 0;
 
        } else if (hands_index >= gProgram_state.current_car.number_of_hands_images) {
 
            hands_index = gProgram_state.current_car.number_of_hands_images - 1;
 
        }
 
        hands_image = gProgram_state.current_car.lhands_images[hands_index];
 
        if (hands_image != NULL) {
 
            DRPixelmapRectangleMaskedCopy(gBack_screen,
 
                gProgram_state.current_car.lhands_x[hands_index] + gScreen_wobble_x,
 
                gProgram_state.current_car.lhands_y[hands_index] + gScreen_wobble_y,
 
                hands_image, 0, 0, hands_image->width, hands_image->height);
 
        }
 
        hands_image = gProgram_state.current_car.rhands_images[hands_index];
 
        if (hands_image != NULL) {
 
            DRPixelmapRectangleMaskedCopy(gBack_screen,
 
                gProgram_state.current_car.rhands_x[hands_index] + gScreen_wobble_x,
 
                gProgram_state.current_car.rhands_y[hands_index] + gScreen_wobble_y,
 
                hands_image, 0, 0, hands_image->width, hands_image->height);
 
        }
 
    }
 
}
 
 
 
// IDA: void __cdecl ChangingView()
 
void ChangingView(void) {
 
    tU32 the_time;
 
    LOG_TRACE("()");
 
 
 
    if (gProgram_state.new_view == eView_undefined) {
 
        return;
 
    }
 
    the_time = PDGetTotalTime() - gProgram_state.view_change_start;
 
    gScreen_wobble_x = 0;
 
    gScreen_wobble_y = 0;
 
    if (the_time > 175 && gProgram_state.which_view == gProgram_state.new_view) {
 
        if (gProgram_state.pending_view != eView_undefined) {
 
            if (gProgram_state.pending_view == eView_left) {
 
                LookLeft();
 
                return;
 
            }
 
            if (gProgram_state.pending_view == eView_forward) {
 
                LookForward();
 
                return;
 
            }
 
            if (gProgram_state.pending_view == eView_right) {
 
                LookRight();
 
                return;
 
            }
 
            gScreen_wobble_x = 0;
 
            gScreen_wobble_y = 0;
 
            return;
 
        }
 
        if (gProgram_state.which_view == gProgram_state.new_view) {
 
            gProgram_state.new_view = eView_undefined;
 
            gScreen_wobble_x = 0;
 
            gScreen_wobble_y = 0;
 
            return;
 
        }
 
    }
 
    if (the_time < 88) {
 
        if (gProgram_state.old_view < gProgram_state.new_view) {
 
            gScreen_wobble_x = -gCurrent_graf_data->cock_margin_x * the_time * 2.f / 175.f;
 
        } else {
 
            gScreen_wobble_x = gCurrent_graf_data->cock_margin_x * the_time * 2.f / 175.f;
 
        }
 
    } else {
 
        gProgram_state.which_view = gProgram_state.new_view;
 
        switch (gProgram_state.new_view) {
 
        case eView_left:
 
            gProgram_state.cockpit_image_index = 1;
 
            break;
 
        case eView_forward:
 
            gProgram_state.cockpit_image_index = 0;
 
            break;
 
        case eView_right:
 
            gProgram_state.cockpit_image_index = 2;
 
            break;
 
        default:
 
            break;
 
        }
 
        AdjustRenderScreenSize();
 
        if (gProgram_state.old_view < gProgram_state.new_view) {
 
            gScreen_wobble_x = gCurrent_graf_data->cock_margin_x * (175 - the_time) * 2.f / 175.f;
 
        } else {
 
            gScreen_wobble_x = -gCurrent_graf_data->cock_margin_x * (175 - the_time) * 2.f / 175.f;
 
        }
 
    }
 
}
 
 
 
// IDA: void __usercall EarnCredits2(int pAmount@<EAX>, char *pPrefix_text@<EDX>)
 
void EarnCredits2(int pAmount, char* pPrefix_text) {
 
    char s[256];
 
    int original_amount;
 
    tU32 the_time;
 
    LOG_TRACE("(%d, \"%s\")", pAmount, pPrefix_text);
 
 
 
    if (gRace_finished) {
 
        return;
 
    }
 
    the_time = GetTotalTime();
 
    if (pAmount == 0) {
 
        return;
 
    }
 
    if (gNet_mode != eNet_mode_none && gProgram_state.credits_earned - gProgram_state.credits_lost + pAmount < 0) {
 
        pAmount = gProgram_state.credits_lost - gProgram_state.credits_lost;
 
    }
 
    original_amount = pAmount;
 
    if (gLast_credit_headup__displays >= 0 && the_time - gLast_earn_time < 2000) {
 
        pAmount += gLast_credit_amount;
 
    }
 
    gLast_credit_amount = pAmount;
 
    if (pAmount >= 2) {
 
        sprintf(s
, "%s%d %s", pPrefix_text
, pAmount
, GetMiscString
(kMiscString_Credits
));  
        gProgram_state.credits_earned += original_amount;
 
    } else if (pAmount >= 1) {
 
        sprintf(s
, "%s1 %s", pPrefix_text
, GetMiscString
(kMiscString_Credit
));  
        gProgram_state.credits_earned += original_amount;
 
    } else if (pAmount >= -1) {
 
        sprintf(s
, "%s%s 1 %s", pPrefix_text
, GetMiscString
(kMiscString_Lost
), GetMiscString
(kMiscString_Credit
));  
        gProgram_state.credits_lost -= original_amount;
 
    } else {
 
        sprintf(s
, "%s%s %d %s", GetMiscString
(kMiscString_Lost
), pPrefix_text
, -pAmount
, GetMiscString
(kMiscString_Credits
));  
        gProgram_state.credits_lost -= original_amount;
 
    }
 
    gLast_credit_headup__displays = NewTextHeadupSlot(4, 0, 2000, -4, s);
 
    gLast_earn_time = the_time;
 
}
 
 
 
// IDA: void __usercall EarnCredits(int pAmount@<EAX>)
 
void EarnCredits(int pAmount) {
 
    LOG_TRACE("(%d)", pAmount);
 
 
 
    EarnCredits2(pAmount, "");
 
}
 
 
 
// IDA: int __usercall SpendCredits@<EAX>(int pAmount@<EAX>)
 
int SpendCredits(int pAmount) {
 
    int amount;
 
    LOG_TRACE("(%d)", pAmount);
 
 
 
    gProgram_state.credits_lost += pAmount;
 
    if (gNet_mode == eNet_mode_none) {
 
        return 0;
 
    }
 
    amount = gProgram_state.credits_earned - gProgram_state.credits_lost;
 
    if (gProgram_state.credits_earned - gProgram_state.credits_lost >= 0) {
 
        return 0;
 
    }
 
    gProgram_state.credits_lost = gProgram_state.credits_earned;
 
    return amount;
 
}
 
 
 
// IDA: void __usercall AwardTime(tU32 pTime@<EAX>)
 
void AwardTime(tU32 pTime) {
 
    char s[256];
 
    tU32 original_amount;
 
    tU32 the_time;
 
    int i;
 
    LOG_TRACE("(%d)", pTime);
 
 
 
    if (gRace_finished || gFreeze_timer || gNet_mode != eNet_mode_none || pTime == 0) {
 
        return;
 
    }
 
 
 
    original_amount = pTime;
 
    the_time = GetTotalTime();
 
    for (i = COUNT_OF(gOld_times) - 1; i > 0; i--) {
 
        gOld_times[i] = gOld_times[i - 1];
 
    }
 
    gOld_times[0] = pTime;
 
    if (gLast_time_credit_headup >= 0 && (the_time - gLast_time_earn_time) < 2000) {
 
        pTime += gLast_time_credit_amount;
 
    }
 
    gLast_time_credit_amount = pTime;
 
    gTimer += original_amount * 1000;
 
    s[0] = '+';
 
    TimerString(1000 * pTime, &s[1], 0, 0);
 
    gLast_time_credit_headup = NewTextHeadupSlot(11, 0, 2000, -2, s);
 
    gLast_time_earn_time = the_time;
 
}
 
 
 
// IDA: void __usercall DrawRectangle(br_pixelmap *pPixelmap@<EAX>, int pLeft@<EDX>, int pTop@<EBX>, int pRight@<ECX>, int pBottom, int pColour)
 
void DrawRectangle(br_pixelmap* pPixelmap, int pLeft, int pTop, int pRight, int pBottom, int pColour) {
 
    LOG_TRACE("(%p, %d, %d, %d, %d, %d)", pPixelmap, pLeft, pTop, pRight, pBottom, pColour);
 
 
 
    BrPixelmapLine(pPixelmap, pLeft, pTop, pRight, pTop, pColour);
 
    BrPixelmapLine(pPixelmap, pLeft, pBottom, pRight, pBottom, pColour);
 
    BrPixelmapLine(pPixelmap, pLeft, pTop, pLeft, pBottom, pColour);
 
    BrPixelmapLine(pPixelmap, pRight, pTop, pRight, pBottom, pColour);
 
}
 
 
 
// IDA: void __usercall DrawRRectangle(br_pixelmap *pPixelmap@<EAX>, int pLeft@<EDX>, int pTop@<EBX>, int pRight@<ECX>, int pBottom, int pColour)
 
void DrawRRectangle(br_pixelmap* pPixelmap, int pLeft, int pTop, int pRight, int pBottom, int pColour) {
 
    LOG_TRACE("(%p, %d, %d, %d, %d, %d)", pPixelmap, pLeft, pTop, pRight, pBottom, pColour);
 
 
 
    BrPixelmapLine(pPixelmap, pLeft + 1, pTop, pRight - 1, pTop, pColour);
 
    BrPixelmapLine(pPixelmap, pLeft + 1, pBottom, pRight - 1, pBottom, pColour);
 
    BrPixelmapLine(pPixelmap, pLeft, pTop + 1, pLeft, pBottom - 1, pColour);
 
    BrPixelmapLine(pPixelmap, pRight, pTop + 1, pRight, pBottom - 1, pColour);
 
}
 
 
 
// IDA: void __usercall OoerrIveGotTextInMeBoxMissus(int pFont_index@<EAX>, char *pText@<EDX>, br_pixelmap *pPixelmap@<EBX>, int pLeft@<ECX>, int pTop, int pRight, int pBottom, int pCentred)
 
void OoerrIveGotTextInMeBoxMissus(int pFont_index, char* pText, br_pixelmap* pPixelmap, int pLeft, int pTop, int pRight, int pBottom, int pCentred) {
 
    tDR_font* font;
 
    int width;
 
    int current_width;
 
    int i;
 
    int centre;
 
    int line_char_index;
 
    int input_str_index;
 
    int start_line;
 
    int current_y;
 
    int font_needed_loading;
 
    char line[256];
 
    LOG_TRACE("(%d, \"%s\", %p, %d, %d, %d, %d, %d)", pFont_index, pText, pPixelmap, pLeft, pTop, pRight, pBottom, pCentred);
 
 
 
    font = &gFonts[pFont_index];
 
    current_width = 0;
 
    font_needed_loading = font->images == NULL;
 
    if (font_needed_loading) {
 
        LoadFont(pFont_index);
 
    }
 
    centre = (pRight + pLeft) / 2;
 
    current_y = pTop;
 
    width = pRight - pLeft;
 
    line_char_index = 0;
 
    input_str_index = 0;
 
    start_line = 0;
 
 
 
    while (pText[input_str_index]) {
 
        line[line_char_index] = pText[input_str_index];
 
        line[line_char_index + 1] = 0;
 
        current_width += font->spacing + font->width_table[pText[input_str_index] - font->offset];
 
        if (current_width > width) {
 
            for (i = input_str_index; i >= start_line; i--) {
 
                if (pText[i] == ' ') {
 
                    break;
 
                }
 
            }
 
            if (i == start_line) {
 
                i = input_str_index;
 
            }
 
            line_char_index += i - input_str_index;
 
            input_str_index = i;
 
            if (pText[input_str_index] == ' ') {
 
                input_str_index++;
 
            }
 
            line[line_char_index] = 0;
 
            if (pCentred) {
 
                DRPixelmapCentredText(gBack_screen, centre, current_y, font, line);
 
            } else {
 
                TransDRPixelmapText(gBack_screen, pLeft, current_y, font, line, pRight);
 
            }
 
            current_width = 0;
 
            current_y += 3 * (font->height - (TranslationMode() ? 2 : 0)) / 2;
 
            line_char_index = 0;
 
            start_line = input_str_index;
 
        } else {
 
            line_char_index++;
 
            input_str_index++;
 
        }
 
    }
 
    if (line_char_index != 0) {
 
        if (pCentred) {
 
            TransDRPixelmapText(gBack_screen, centre - (DRTextWidth(font, line) / 2), current_y, font, line, (DRTextWidth(font, line) / 2) + centre);
 
        } else {
 
            TransDRPixelmapText(gBack_screen, pLeft, current_y, font, line, pRight);
 
        }
 
    }
 
    if (font_needed_loading) {
 
        DisposeFont(pFont_index);
 
    }
 
}
 
 
 
// IDA: void __usercall TransBrPixelmapText(br_pixelmap *pPixelmap@<EAX>, int pX@<EDX>, int pY@<EBX>, br_uint_32 pColour@<ECX>, br_font *pFont, signed char *pText)
 
void TransBrPixelmapText(br_pixelmap* pPixelmap, int pX, int pY, br_uint_32 pColour, br_font* pFont, char* pText) {
 
    int len;
 
    LOG_TRACE("(%p, %d, %d, %d, %p, %p)", pPixelmap, pX, pY, pColour, pFont, pText);
 
 
 
    len = TranslationMode() ? 2 : 0;
 
    BrPixelmapText(pPixelmap, pX, pY - len, pColour, pFont, (char*)pText);
 
}
 
 
 
// IDA: void __usercall TransDRPixelmapText(br_pixelmap *pPixelmap@<EAX>, int pX@<EDX>, int pY@<EBX>, tDR_font *pFont@<ECX>, char *pText, int pRight_edge)
 
void TransDRPixelmapText(br_pixelmap* pPixelmap, int pX, int pY, tDR_font* pFont, char* pText, int pRight_edge) {
 
    LOG_TRACE("(%p, %d, %d, %p, \"%s\", %d)", pPixelmap, pX, pY, pFont, pText, pRight_edge);
 
 
 
    if (gAusterity_mode && FlicsPlayedFromDisk() && pFont != gCached_font) {
 
        if (gCached_font != NULL && gCached_font - gFonts > 13) {
 
            DisposeFont(gCached_font - gFonts);
 
        }
 
        gCached_font = pFont;
 
    }
 
    LoadFont(pFont - gFonts);
 
    DRPixelmapText(pPixelmap, pX, pY - (TranslationMode() ? 2 : 0), pFont, pText, pRight_edge);
 
}
 
 
 
// IDA: void __usercall TransDRPixelmapCleverText(br_pixelmap *pPixelmap@<EAX>, int pX@<EDX>, int pY@<EBX>, tDR_font *pFont@<ECX>, char *pText, int pRight_edge)
 
void TransDRPixelmapCleverText(br_pixelmap* pPixelmap, int pX, int pY, tDR_font* pFont, char* pText, int pRight_edge) {
 
    LOG_TRACE("(%p, %d, %d, %p, \"%s\", %d)", pPixelmap, pX, pY, pFont, pText, pRight_edge);
 
 
 
    if (gAusterity_mode && FlicsPlayedFromDisk() && gCached_font != pFont) {
 
        if (gCached_font && gCached_font - gFonts > 13) {
 
            DisposeFont(gCached_font - gFonts);
 
        }
 
        gCached_font = pFont;
 
    }
 
    LoadFont(pFont - gFonts);
 
    DRPixelmapCleverText2(pPixelmap, pX, pY - (TranslationMode() == 0 ? 0 : 2), pFont, pText, pRight_edge);
 
}