# SPDX-License-Identifier: BSD-3-Clause # # Configuration file for textgen. This file defines the graphic lumps # that are generated, and the text to show in each one. # import re # Adjustments for character position based on character pairs. Some # pairs of characters can fit more snugly together, which looks more # visually appealing. This is highly dependent on the font graphics, # and if the font is changed this probably needs to be redone. FONT_KERNING_RULES = { # Right character fits under left character: r"T[0ACOSZacos]": -2, r"V[OC]": -2, r"Y[ASZacs]": -2, r"Y[CO0]": -1, r"P[Aa]": -3, r"P[7]": -2, r"P[Z]": -1, r"[0O][Aa]": -1, r"S[A]": -1, r"Sa": -2, r"Wa": -1, r"p[a]": -1, r"s[ao]": -1, r"ta": -2, r"v[oc]": -1, r"y[oacs]": -1, # Left character fits under right character: r"L[4Q]": -3, r"L[O0CTYtcq]": -2, r"L[oyVv]": -1, r"l[tTY]": -2, r"l[y]": -1, r"[0O][4TYy]": -2, r"[0O][1]": -1, r"Q[1TY]": -2, r"A[CGTYt]": -2, r"A[cgy]": -1, r"a[cTYt]": -2, r"a[vVy]": -1, # Fits into "hole" in left character: r"B[0CGOQ]": -2, r"B[0cgq]": -2, r"C[0CGOQ]": -3, r"C[q]": -2, r"C[cgo]": -1, r"X[0CO]": -3, r"X[Qqco]": -2, r"8[0CO]": -3, r"8[GQcgqo]": -2, r"Z[0CO]": -2, r"Z[GQocgq]": -1, r"I[0COQcoq]": -1, r"K[0CO]": -4, r"K[GQ]": -3, r"K[cgo]": -2, r"K[Eq]": -1, r"P[0COQcoq]": -1, r"R[0COQcoq]": -1, # Fits into "hole" in right character: r"[O0][2X8]": -3, r"[O0][9Kx]": -2, r"[O0][Iik]": -1, r"Q[28X]": -2, r"Q[9Iix]": -1, r"q[IXx]": -1, # Just because. r"[O0][O0]": -1, } white_graphics = { "wibp1": "P1", "wibp2": "P2", "wibp3": "P3", "wibp4": "P4", "wicolon": ":", # These files are for the title screens of Phase 1 and Phase 2 "t_phase1": "PHASE 1", "t_phase2": "PHASE 2", # Note: level names are also included in this dictionary, with # the data added programatically from the DEHACKED lump, see # code below. } blue_graphics = { "m_disopt": "DISPLAY OPTIONS", "m_episod": "Choose Episode:", "m_optttl": "OPTIONS", "m_skill": "Choose Skill Level:", } red_graphics = { # Title for the HELP/HELP1 screen: "helpttl": "Help", # Title for CREDIT "freettl": "Freedoom", "m_ngame": "New Game", "m_option": "Options", "m_loadg": "Load Game", "m_saveg": "Save Game", "m_rdthis": "Read This!", "m_quitg": "Quit Game", "m_newg": "NEW GAME", "m_epi1": "Outpost Outbreak", "m_epi2": "Military Labs", "m_epi3": "Event Horizon", "m_epi4": "Double Impact", "m_jkill": "Please don't kill me!", "m_rough": "Will this hurt?", "m_hurt": "Bring on the pain.", "m_ultra": "Extreme Carnage.", "m_nmare": "MAYHEM!", "m_lgttl": "LOAD GAME", "m_sgttl": "SAVE GAME", "m_endgam": "End Game", "m_messg": "Messages:", "m_msgoff": "off", "m_msgon": "on", "m_msens": "Mouse Sensitivity", "m_detail": "Graphic Detail:", "m_gdhigh": "high", "m_gdlow": "low", "m_scrnsz": "Screen Size", "m_svol": "Sound Volume", "m_sfxvol": "Sfx Volume", "m_musvol": "Music Volume", "m_disp": "Display", "wif": "finished", "wiostk": "kills", "wiosti": "items", "wiscrt2": "secret", "wiosts": "scrt", "wifrgs": "frgs", "witime": "Time:", "wisucks": "sucks", "wimstt": "Total:", "wipar": "Par:", "wip1": "P1", "wip2": "P2", "wip3": "P3", "wip4": "P4", "wiostf": "f.", "wimstar": "you", "winum0": "0", "winum1": "1", "winum2": "2", "winum3": "3", "winum4": "4", "winum5": "5", "winum6": "6", "winum7": "7", "winum8": "8", "winum9": "9", "wipcnt": "%", "wiminus": "-", "wienter": "ENTERING", "m_pause": "pause", # Extra graphics used in PrBoom's menus. Generate these as well # so that when we play in PrBoom the menus look consistent. "prboom": "PrBoom", "m_generl": "General", "m_setup": "Setup", "m_keybnd": "Key Bindings", "m_weap": "Weapons", "m_stat": "Status Bar/HUD", "m_auto": "Automap", "m_enem": "Enemies", "m_mess": "Messages", "m_chat": "Chat Strings", "m_horsen": "horizontal", "m_versen": "vertical", "m_loksen": "mouse look", "m_accel": "acceleration", # Extra graphics from SMMU/Eternity Engine: "m_about": "about", "m_chatm": "Chat Strings", "m_compat": "Compatibility", "m_demos": "demos", "m_dmflag": "deathmatch flags", "m_etcopt": "eternity options", "m_feat": "Features", "m_gset": "game settings", "m_hud": "heads up display", "m_joyset": "joysticks", "m_ldsv": "Load/Save", "m_menus": "Menu Options", "m_mouse": "mouse options", "m_player": "player setup", "m_serial": "serial connection", "m_sound": "sound options", "m_status": "status bar", "m_tcpip": "tcp/ip connection", "m_video": "video options", "m_wad": "load wad", "m_wadopt": "wad options", # This is from SMMU too, and if we follow things to the letter, # ought to be all lower-case. However, same lump name is used # by other ports (Zandronum) which expect a taller graphic to # match the other main menu graphics. Eternity Engine doesn't # use it any more, and on SMMU there's enough space for it. "m_multi": "Multiplayer", # Crispy Doom's Crispness menu: "m_crispy": "Crispness", } def read_bex_lump(filename): """Read the BEX (Dehacked) lump from the given filename. Returns: Dictionary mapping from name to value. """ result = {} with open(filename) as f: for line in f: # Ignore comments: line = line.strip() if len(line) == 0 or line[0] in "#;": continue # Just split on '=' and interpret that as an # assignment. This is primitive and doesn't read # like a full BEX parser should, but it's good # enough for our purposes here. assign = line.split("=", 2) if len(assign) != 2: continue result[assign[0].strip()] = assign[1].strip() return result def update_level_name(lumpname, bexdata, bexname): """Set the level name for the given graphic from BEX file. Args: lumpname: Name of output graphic file. bexdata: Dictionary of data read from BEX file. bexname: Name of entry in BEX file to use. """ if bexname not in bexdata: raise Exception( "Level name %s not defined in " "DEHACKED lump!" % bexname ) # Strip "MAP01: " or "E1M2: " etc. from start, if present: levelname = re.sub("^\w*\d:\s*", "", bexdata[bexname]) white_graphics[lumpname] = levelname freedoom_bex = read_bex_lump("../../lumps/p2_deh.lmp") freedm_bex = read_bex_lump("../../lumps/fdm_deh.lmp") for e in range(4): for m in range(9): # HUSTR_E1M1 from BEX => wilv00 update_level_name( "wilv%i%i" % (e, m), freedoom_bex, "HUSTR_E%iM%i" % (e + 1, m + 1) ) for m in range(32): # HUSTR_1 => cwilv00 update_level_name("cwilv%02i" % m, freedoom_bex, "HUSTR_%i" % (m + 1)) # HUSTR_1 => dmwilv00 (from freedm.bex) update_level_name("dmwilv%02i" % m, freedm_bex, "HUSTR_%i" % (m + 1))