From 5b38eb5fc51caeb2e6cccbe08eb4476e20c682e8 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 16 Dec 2024 04:39:32 -0500 Subject: [PATCH 01/34] g4.15pre --- src/version.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/version.h b/src/version.h index c7bdc30720..58e7927a1c 100644 --- a/src/version.h +++ b/src/version.h @@ -41,20 +41,20 @@ const char *GetVersionString(); /** Lots of different version numbers **/ -#define VERSIONSTR "4.14pre" +#define VERSIONSTR "4.15pre" // The version as seen in the Windows resource -#define RC_FILEVERSION 4,13,9999,0 -#define RC_PRODUCTVERSION 4,13,9999,0 +#define RC_FILEVERSION 4,14,9999,0 +#define RC_PRODUCTVERSION 4,14,9999,0 #define RC_PRODUCTVERSION2 VERSIONSTR // These are for content versioning. #define VER_MAJOR 4 -#define VER_MINOR 14 +#define VER_MINOR 15 #define VER_REVISION 0 // This should always refer to the GZDoom version a derived port is based on and not reflect the derived port's version number! #define ENG_MAJOR 4 -#define ENG_MINOR 14 +#define ENG_MINOR 15 #define ENG_REVISION 0 // Version identifier for network games. From d61ec1722a4015c41153fe7a4b5b314e38241589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Mon, 16 Dec 2024 17:05:39 -0300 Subject: [PATCH 02/34] Fix damage being skipped for spectral puffs --- src/playsim/p_interaction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/playsim/p_interaction.cpp b/src/playsim/p_interaction.cpp index 0ae77e914c..60b6f30597 100644 --- a/src/playsim/p_interaction.cpp +++ b/src/playsim/p_interaction.cpp @@ -1158,7 +1158,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da // Special damage types if (inflictor) { - if (inflictor->flags4 & MF4_SPECTRAL) + if (inflictor->flags4 & MF4_SPECTRAL && !(inflictor->flags9 & MF9_ISPUFF)) { if (player != NULL) { From 1d7763864ba4c4bb772a67c9a0c1371e736aba88 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 17 Dec 2024 14:17:50 -0500 Subject: [PATCH 03/34] - language update --- wadsrc/static/language.0 | 6 +++--- wadsrc/static/language.csv | 5 +++-- wadsrc_extra/static/language.csv | 8 ++++---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/wadsrc/static/language.0 b/wadsrc/static/language.0 index cf004c828a..3eefd93d7c 100644 --- a/wadsrc/static/language.0 +++ b/wadsrc/static/language.0 @@ -873,12 +873,12 @@ Appearance,DSPLYMNU_APPEARANCE,,,,Vzhled,Udseende,Spieldarstellung,,Aspekto,Apar Advanced Display Options,DSPLYMNU_ADVANCED,,,,Grafika (pokročilé),Avancerede visningsindstillinger,Erweiterte Anzeigeoptionen,,Altnivelaj ekran-agordoj,Opciones avanzadas de visualización,,Näytön lisäasetukset,Options d'affichage avancées,Napredne postavke zaslona,Speciális megjelenítési beállítások,Opzioni di visualizzazione avanzate,高度なディスプレイオプション,고급 디스플레이 옵션,Geavanceerde Weergave Opties,Avanserte visningsalternativer,Zaawansowane Opcje Wyświetlania,Opções de vídeo avançadas,,Opțiuni avansate de afișare,Расширенные настройки экрана,Напредне опције приказа,Avancerade visningsalternativ,Gelişmiş Görüntüleme Seçenekleri,Додаткові параметри відображення, ,,IWAD/Game picker,,,,,,,,,,,,,,,,,,,,,,,,,,,, Select which game file to run.,PICKER_SELECT,,,,"Vyberte, jaký herní soubor spustit.","Vælg, hvilket spil du vil spille",Bitte wähle ein Spiel aus.,,Elektu kiun ludodosieron ruli.,,,Valitse suoritettava pelitiedosto.,Sélectionner le jeu à jouer,Odaberi koju igru želiš pokrenuti.,"Válassza ki, hogy melyik játékfájlt futtassa.",Selezionare il file di gioco da eseguire.,実行するゲームファイルを選択します。,실행할 게임 파일을 선택합니다.,Selecteer welk spel je wilt spelen,Velg hvilket spill du vil spille,"Wybierz, który plik gry uruchomić.",Selecione qual arquivo de jogo rodar.,,Selectați ce fișier de joc să rulați.,Выбор файла игры для запуска.,Изаберите коју датотеку игре желите да покренете.,Välj vilket spel du vill spela,Hangi oyunu oynayacağınızı seçin,Виберіть файл гри для запуску., -Play Game,PICKER_PLAY,,,,Hrát hru,Start spil,Spielen,,Ludi ludon,,,Pelin pelaaminen,Démarrer le jeu,Zaigraj igru,Játék lejátszása,Esegui gioco,ゲームをプレイする,게임 플레이,Spel starten,Start spill,Graj,Jogar,,Joacă jocul,Играть,Играј игру,Starta spel,Oyunu Başlat,Запустити гру, +Play Game,PICKER_PLAY,,,,Hrát hru,Start spil,Spielen,,Ludi ludon,,,Pelin pelaaminen,Démarrer le jeu,Zaigraj igru,Játék lejátszása,Esegui gioco,プレイ,게임 플레이,Spel starten,Start spill,Graj,Jogar,,Joacă jocul,Играть,Играј игру,Starta spel,Oyunu Başlat,Запустити гру, Exit,PICKER_EXIT,,,,Odejít,Afslut,Verlassen,,Eliri,,,Poistu,Quitter,Izlaz,Kilépés,Esci,終了,종료,Verlaten,Avslutt,Wyjdź,Sair,,Ieșire,Выход,Изађи,Avsluta,Çıkış,Вихід, General,PICKER_GENERAL,,,,Obecné,Generelt,Allgemein,,Ĝenerala,,,Yleistä,Général,Općenito,Általános,Generale,一般,일반,Algemeen,Generelt,Ogólne,Geral,,,Общее,Генерал,Allmänt,Genel,Загальні, Extra Graphics,PICKER_EXTRA,,,,Grafické doplňky,Ekstra grafik,Extragrafiken,,Ekstra grafiko,,,Extra Graphics,Graphiques supplémentaires,Dodatna grafika,Extra grafika,Grafica extra,追加グラフィックス,추가 그래픽,Extra afbeeldingen,Ekstra grafikk,Ekstra grafiki,Gráficos extras,,Grafică suplimentară,Доп. графика,Ектра Грапхицс,Extra grafik,Ekstra Grafikler,Додаткова графіка, Fullscreen,PICKER_FULLSCREEN,,,,Přes celou obrazovku,Fuld skærm,Vollbild,,Plena ekrano,,,Koko näyttö,Plein écran,Puni zaslon,Teljes képernyő,Schermo intero,フルスクリーン,전체 화면,Volledig scherm,Fullskjerm,Pełny ekran,Tela cheia,,Ecran complet,Полный экран,Цео екран,Fullskärm,Tam Ekran,Повноекранний режим, -Disable autoload,PICKER_NOAUTOLOAD,,,,Zakázat autoload,Deaktiver autoload,Autoload deaktivieren,,Malvalidigi aŭtoŝargon,,,Poista automaattinen lataus käytöstä,Désactiver le chargement automatique,Onemogući automatsko učitavanje,Automatikus betöltés kikapcsolása,Disabilita il caricamento automatico,オートロードを無効にする,자동 로드 비활성화,Autoload uitschakelen,Deaktiver autolading,Wyłącz auto-ładowanie,Desativar autocarregam.,,Dezactivați încărcarea automată,Откл. автозагрузку,Онемогући аутоматско учитавање,Inaktivera autoload,Otomatik yükleme yok,Вимкнути автозавантаження, +Disable autoload,PICKER_NOAUTOLOAD,,,,Zakázat autoload,Deaktiver autoload,Autoload deaktivieren,,Malvalidigi aŭtoŝargon,,,Poista automaattinen lataus käytöstä,Désactiver le chargement automatique,Onemogući automatsko učitavanje,Automatikus betöltés kikapcsolása,Disabilita il caricamento automatico,オートロード無効,자동 로드 비활성화,Autoload uitschakelen,Deaktiver autolading,Wyłącz auto-ładowanie,Desativar autocarregam.,,Dezactivați încărcarea automată,Откл. автозагрузку,Онемогући аутоматско учитавање,Inaktivera autoload,Otomatik yükleme yok,Вимкнути автозавантаження, Don't ask me again,PICKER_DONTASK,,,,Již se neptat,Spørg mig ikke igen,Nicht nochmal fragen,,Ne demandu min denove,,,Älä kysy uudestaan,Ne me demandez plus rien,Više me ne pitaj,Ne kérdezz újra,Non chiedermelo più,再度聞かない,다시 묻지 마세요,Vraag me niet opnieuw,Ikke spør meg igjen,Nie pytaj ponownie,Não perguntar de novo,,Nu mă mai întrebați din nou,Не спрашивать снова,Не питај ме поново,Fråga mig inte igen,Bir daha sorma.,Не запитуйте мене більше, Lights,PICKER_LIGHTS,,,,Světla,Lys,Lichtdefinitionen,,Lumoj,,,Valot,Lumières,Svjetla,Fények,Luci,ライト,조명,Verlichting,Lysdefinisjoner,Oświetlenie,Luzes,,Lumini,Освещение,Светла,Definitioner av ljus,Işık tanımları,Освітлення, Brightmaps,PICKER_BRIGHTMAPS,,,,,,,,Helomapoj,,,Brightmaps,Cartes lumineuses,Svijetle karte,Brightmaps,Mappe luminose,ブライトマップ,브라이트맵,Heldermaps,Lyskart,Mapowanie świateł,,,,Карты освещения,Бригхтмапс,Ljuskartor,Brightmaps,Яскраві карти, @@ -891,4 +891,4 @@ Game,PICKER_TAB_PLAY,,,,Hra,Spil,Spiel,,Ludo,Juego,,Peli,Jeu,Igra,Játék,Gioco, Enable this controller,JOYMNU_JOYENABLE,Option to enable or disable individual controllers/joysticks when configuring it in the Controller Options menu,,,Povolit tento ovladač,Aktivér denne controller,Diesen Controller aktivieren,,Ŝalti ĉi tiun ludregilon,Habilitar este controlador,,Aktivoi tämä ohjain,Activer ce contrôleur,Omogući ovaj kontroler,Engedélyezze ezt a vezérlőt,Attiva questo controller,このコントローラーを有効にする,이 컨트롤러 활성화,Deze controller inschakelen,Aktiver denne kontrolleren,Włącz ten kontroler,Habilitar este controle,,Activați acest controler,Включить этот контроллер,Омогућите овај контролер,Aktivera denna styrenhet,Bu denetleyiciyi etkinleştirin,Увімкніть цей контролер, Open Main Menu,CNTRLMNU_OPEN_MAIN,,,,Otevřít hlavní menu,Åbn hovedmenuen,Hauptmenü öffnen,,Malfermi ĉefan menuon,Abrir el menú principal,,Avaa päävalikko,Ouvrir le menu principal,Otvori glavni izbornik,Főmenü megnyitása,Apri il menu principale,メインメニューを開く,메인 메뉴 열기,Hoofdmenu openen,Åpne hovedmenyen,Otwórz meny główne,Abrir menu principal,,Deschideți meniul principal,Открыть главное меню,Отворите главни мени,Öppna huvudmenyn,Ana Menüyü Aç,Відкрити головне меню, ,,New content,,,,,,,,,,,,,,,,,,,,,,,,,,,, -Module replayer,MODMNU_REPLAYER,,,,Nastavení přehrávače modulů,Modulafspiller,Modul-Spieler,,Legilo de moduloj,Reproductor de módulos,,,Lecteur de module,,,Module replayer,,,Module replayer,Modulavspiller,,Reprodutor de módulos,,Redare a modulelor,Модуль-повторитель,,Modulåterspelare,,Module replayer, \ No newline at end of file +Module replayer,MODMNU_REPLAYER,,,,Nastavení přehrávače modulů,Modulafspiller,Modul-Spieler,,Legilo de moduloj,Reproductor de módulos,,,Lecteur de module,Ponavljač modula,,Module replayer,モジュール リプレイヤー,,Module replayer,Modulavspiller,,Reprodutor de módulos,,Redare a modulelor,Модуль-повторитель,,Modulåterspelare,,Module replayer, \ No newline at end of file diff --git a/wadsrc/static/language.csv b/wadsrc/static/language.csv index eaa7127918..4661e4598a 100644 --- a/wadsrc/static/language.csv +++ b/wadsrc/static/language.csv @@ -1911,7 +1911,7 @@ armură.",Игрока %o обслюнявила бронированная дв %o was hit by %k's propulsor.,OB_MPP_SPLASH,,,,%o byl@[ao_cs] zasažen@[ao_cs] propulzorem hráčem %k.,%o blev ramt af %k's propulsor.,%o wurde von %ks Propeller getroffen,,%o estas trafita de la propulsilo de %k.,%o fue impactad@[ao_esp] por el propulsor de %k.,,%k osui %o parkaan työntimellään.,%o à été frappé@[e_fr] par le propulseur de %k.,,%o elérte %k elhárítóját.,%o è stato colpito dal propulsore di %k.,%o に %k のロケットゾーチャーがとどいた。,%o 은(는) %k 의 저치 추진기의 방사 능력을 우습게 봤습니다.,%o werd geraakt door %k's propulsor.,%o ble truffet av %k's propulsor.,%o został@[ao_pl] trafion@[adj_pl] pędnikiem %k.,%o foi atingid@[ao_ptb] pelo propulsor de %k.,,%o a fost învins de acceleratorul lui %k.,Игрок %o подстрелен из ускорителя зорча %k.,%o је ударен %k погоном.,%o blev träffad av %ks propulsor.,"%o, %k tarafından yenildi.",%k врази@[adj_1_ua] %o з прискореного зорчера. %o was phase zorched by %k.,OB_MPPHASEZORCH,,,,%o byl@[ao_cs] bzukr-vyfázován@[ao_cs] hráčem %k.,%o blev fasezorched af %k.,%o wurde von %k wegsynchronisiert,,%o estas fluktuantzorĉita de %k.,%o fue electrizad@[ao_esp] en fase por %k.,,%k vaiheiszorchasi %o paran.,%o à été phasé@[e_fr] par %k.,,%o fázis zorker áldozata lett %k által.,%o è stato phase-zorchato da %k.,%o は %k によってスベスベにされた。,%o 은(는) %k 의 전자 자쳐에 의해 쓰러졌습니다.,%o was fase zorched door %k.,%o ble fasebrent av %k.,%o został@[ao_pl] został sfazowan@[adj_pl] przez %k.,%o foi atingid@[ao_ptb] pelo zorcher fásico por %k.,,%o a fost înfrânt de zorcherul fazat al lui %k.,Игрок %o получил заряд из фазерного зорчера %k.,%o је фазно торчован %k.,%o blev faszorchad av %k.,"%o, %k tarafından yenildi.",%k фазорчну@[adj_1_ua] %o. %o fell prey to %k's LAZ device.,OB_MPLAZ_BOOM,,,,%o padl@[ao_cs] velkodosahovému bzukru hráče %k.,%o blev offer for %k's LAZ-enhed.,%o fiel %ks Flächenzorcher zum Opfer,,%o iĝis predo de la LAZ-aparato de %k.,%o cayó pres@[ao_esp] ante el dispositivo LAZ de %k.,,%o lankesi pelaajan %k SAZ-laitteen uhriksi.,%o est devenu@[e_fr] la proie du ZZL de %k.,,%o prédául lett ejtve %k LAZ készülékével.,%o è stato preda del dispositivo LAZ di %k.,%o は %k のLAZデバイスのえじきになった。,%k 이(가) LAZ 장치를 들기 전에 %o 은(는) 도망쳐야 했습니다.,%o viel ten prooi aan %k's LAZ apparaat.,%o ble offer for %k's LAZ-enhet.,%o stał@[ao_pl] się ofiarą urządzenia LAZ %k.,%o foi vítima do dispositivo LAZ de %k.,,%o a căzut pradă dispozitivului LAZ al lui %k.,Игрок %o склонился перед «ЗБР» игрока %k.,%o је постао жртва %k ЛАЗ уређаја.,%o föll offer för %ks LAZ-enhet.,"%o, %k tarafından lazzlandı.",%o па@[adj_1_ua] жертвою LAZ девайсу %k. -%o was lazzed by %k.,OB_MPLAZ_SPLASH,,,,%o byl@[ao_cs] odbzukrován hráčem %k.,%o blev lazzed af %k.,%o wurde von %k weggebeamt.,,%o estas LAZ-ita de %k.,%o fue LAZeado por %k.,,%k sazzasi pelaajaan %o.,%o à été pris@[e_fr] par le ZZL de %k.,,%o el lett lazzázva %k által.,%o è stato lazzato da %k.,%o は %k にとかされた。,%o 은(는) %k 의 LAZ 장치 범위를 벗어날 수 없었습니다.,%o werd gelazed door %k.,%o ble lazzed av %k.,%o został@[ao_pl] zLAZowan@[adj_pl] przez %k.,%o foi LAZead@[ao_ptb] por %k.,,%o a fost stropit de dispozitivul LAZ al lui %k.,Игрок %o получил заряд из «ЗБР» игрока %k.,%o је ЛАЗ-овао %k.,%o blev lazzad av %k.,"%o, %k tarafından lazzlandı.",%k LAZну@[adj_1_ua] %o. +%o was lazzed by %k.,OB_MPBFG_SPLASH,,chex,,%o byl@[ao_cs] odbzukrován hráčem %k.,%o blev lazzed af %k.,%o wurde von %k weggebeamt.,,%o estas LAZ-ita de %k.,%o fue LAZeado por %k.,,%k sazzasi pelaajaan %o.,%o à été pris@[e_fr] par le ZZL de %k.,,%o el lett lazzázva %k által.,%o è stato lazzato da %k.,%o は %k にとかされた。,%o 은(는) %k 의 LAZ 장치 범위를 벗어날 수 없었습니다.,%o werd gelazed door %k.,%o ble lazzed av %k.,%o został@[ao_pl] zLAZowan@[adj_pl] przez %k.,%o foi LAZead@[ao_ptb] por %k.,,%o a fost stropit de dispozitivul LAZ al lui %k.,Игрок %o получил заряд из «ЗБР» игрока %k.,%o је ЛАЗ-овао %k.,%o blev lazzad av %k.,"%o, %k tarafından lazzlandı.",%k LAZну@[adj_1_ua] %o. ,,Miscellaneous,,,,,,,,,,,,,,,,,,,,,,,,,,, E1M1: Landing Zone,CHUSTR_E1M1,,,,E1M1: Přistávací zóna,E1M1: Landingszone,E1M1: Landezone,,E1M1: Surterejo,E1M1: Zona de Aterrizaje,,E1M1: Laskeutumisalue,E1M1: La piste d'atterissage,,E1M1: Leszállópálya,E1M1: Zona di Atterraggio,E1M1: ちゃくりく ちてん,E1M1: 착륙 지점,E1M1: Landingszone,E1M1: Landingssone,E1M1: Strefa Lądowania,E1M1: Zona de Pouso,E1M1: Zona de Aterragem,E1M1: Pista de Aterizare,E1M1: Зона приземления,Е1М1: Зона слетања,E1M1: Landningszon,E1M1: İniş Bölgesi,E1M1: Зона висадки E1M2: Storage Facility,CHUSTR_E1M2,,,,E1M2: Skladiště,E1M2: Opbevaringsanlæg,E1M2: Lagerhalle,,E1M2: Stokejo,E1M2: Instalación de Almacenamiento,,E1M2: Varastolaitos,E1M2: Le centre de stockage,,E1M2: Raktárépület,E1M2: Struttura di Immagazzinamento,E1M2: ほかん しせつ,E1M2: 저장 시설,E1M2: Opslagfaciliteit,E1M2: Lagringsanlegg,E1M2: Magazyn,E1M2: Depósito,E1M2: Armazém,E1M2: Depozitul,E1M2: Хранилище,Е1М2: Складиште,E1M2: Förvaringsanläggning,E1M2: Depolama Tesisi,E1M2: Сховище @@ -3415,4 +3415,5 @@ Restart level on Death,MISCMNU_RESTARTONDEATH,Disables autoloading save on death Pistol Start,GMPLYMNU_PISTOLSTART,Resets inventory on every map,,,Začít jen s pistolí,Start med pistol,Pistolenstart,,Komenci kun pistolo,,,,Démarrage du pistolet,,,Avvio pistola,ピストルスタート,,Start met pistool,Start med pistol,Start z pistoletem,Iniciar com a pistola,,,Пистолет в начале,,Starta med pistol,Tabanca ile başlayın, Allow creation of zombie players,CMPTMNU_VOODOOZOMBIES,,,,Povolit zombie hráče,,Erlaube Zombieplayer,,Permesi kreadon de zombiaj ludantoj,,,,,,,,ゾンビプレイヤーの生成許可,,,,Pozwól na tworzenie graczy-zombie,Permitir criação de jogadores zumbi,,,Разрешить создание игроков-зомби,,,, ignore floor z when teleporting,CMPTMNU_FDTELEPORT,,,,Při teleportu ignorovat výšku podlahy,,Ignoriere Fußbodenhöhe bem Teleportieren,,Ignori altecon de planko dum teleportado,,,,,,,,テレポート時にfloor z値を無視する,,,,Ignoruj wysokość podłogi podczas teleportacji,Ignorar altura do chão ao teletransportar,,,игнорирование диагонали пола (Z) при телепортации,,,, -Forced-Perspective,OPTVAL_ANAMORPHIC,"Hardware Sprite Clipping mode that gives the illusion of a sprite being in a different position than it really is, allowing it to be rendered under the floor despite clipping",,,,,Erzwungene Perspektive,,,,,,,,,,,,,,,,,,Перспективный (анаморфотный),,,, \ No newline at end of file +Forced-Perspective,OPTVAL_ANAMORPHIC,"Hardware Sprite Clipping mode that gives the illusion of a sprite being in a different position than it really is, allowing it to be rendered under the floor despite clipping",,,Vynucená perspektiva,,Erzwungene Perspektive,,Devigita perspektivo,,,,,,,,,,,,,Perspectiva forçada,,,Принудительно перспективный,,,, +Footstep Volume,SNDMENU_FOOTSTEPVOLUME,,,,Hlasitost kroků,,Schrittlautstärke,,,,,,,,,,,,,,,Volume dos passos,,,Громкость шагов,,,, \ No newline at end of file diff --git a/wadsrc_extra/static/language.csv b/wadsrc_extra/static/language.csv index 2a62c0fcc9..c2bd82f361 100644 --- a/wadsrc_extra/static/language.csv +++ b/wadsrc_extra/static/language.csv @@ -10701,8 +10701,8 @@ Where's the illegal tap?,TXT_RPLY2_SCRIPT02_D98540_WHERE,〃 (〃),,,Kde je nele どれをイジるかまでは知らん。 配電機はここの下水処理場にある。",그게 어딨는지 말해주지. 왜 그 동력선에 손을 대려고 하는지는 모르겠지마는. 저 앞 하수도 안에 있다네.,"Ik zal je vertellen waar hij is, maar ik weet niet met wie je met de koppeling zult knoeien. Het is hier in de rioolwaterzuiveringsinstallatie.","Jeg skal si deg hvor den er, men jeg vet ikke hvem sin kobling du skal tukle med. Den er her i kloakkanlegget.","Powiem ci gdzie jest, ale nie wiem czyj to odbierak, przy którym będziesz majstrować. Jest w oczyszczalni ścieków.","Vou te dizer onde está, mas não sei em qual ligação você vai acabar mexendo. Fica bem aqui na usina de tratamento de esgoto.",,"Îți voi spune unde este, dar nu știu de care cuplaj te vei lega. Este chiar aici, în sistemul de canalizare.","Я скажу тебе, где она, но не знаю, которая тебе нужна. Она прямо здесь, в очистной системе.",,"Jag ska berätta var den är, men jag vet inte vems koppling du kommer att mixtra med. Den finns här i reningsverket.","Nerede olduğunu söyleyeceğim, ama kimin bağlantılarını kurcalayacağınızı bilmiyorum. Tam burada, kanalizasyon tesisinde." Thanks,TXT_RPLY0_SCRIPT02_D100056_THANK,〃 (〃),,,Díky.,Tak,Danke,,Dankon.,Gracias.,,Kiitos,Merci.,,Kösz.,Grazie,ありがとう。,그렇군요.,Bedankt,Takk skal du ha.,Dzięki,Obrigado,,Mulțumesc,Спасибо.,,Tack,Teşekkürler. -That's right here in the sewage plant. But it's the Front's coupling. Whoever told you that it was the Order's was wrong.,TXT_DLG_SCRIPT02_D101572_THATS,〃 (〃),,,"Síť je přímo tady, v čističce. Ale je to spojka Fronty. Kdo ti řekl, že je Řádu, se mýlil.","Det er lige her i kloakanlægget. Men det er Fronts kobling. Den, der fortalte dig, at det var Ordenens, tog fejl.","Genau hier, in der Kläranlage. Aber sie gehört der Front. Wer auch immer dir gesagt hat, sie gehöre dem Orden, hat gelogen.",,"Ĝi estas ĉi tie, en la kloakpurigejo, sed ĝi estas la kuplado de la Fronto. Tiu ajn, kiu diris, ke ĝi estas de La Ordeno, eraris.","Está justo aquí en la planta de aguas residuales, pero es el acoplamiento del Frente. Quien te haya dicho que era de La Orden se ha equivocado. -","Está justo aquí en la planta de aguas residuales, pero es el acoplamiento del Frente. Quien te haya dicho que era de La Orden te dijo mal. +That's right here in the sewage plant. But it's the Front's coupling. Whoever told you that it was the Order's was wrong.,TXT_DLG_SCRIPT02_D101572_THATS,〃 (〃),,,"Síť je přímo tady, v čističce. Ale je to spojka Fronty. Kdo ti řekl, že je Řádu, se mýlil.","Det er lige her i kloakanlægget. Men det er Fronts kobling. Den, der fortalte dig, at det var Ordenens, tog fejl.","Genau hier, in der Kläranlage. Aber sie gehört der Front. Wer auch immer dir gesagt hat, sie gehöre dem Orden, hat gelogen.",,"Ĝi estas ĉi tie, en la kloakpurigejo, sed ĝi estas la kuplado de la Fronto. Kiu diris, ke ĝi estas de La Ordeno, tiu ajn eraris.","Está justo aquí en la planta de aguas residuales, aunque es el acoplamiento del Frente. Quien te haya dicho que era de La Orden se ha equivocado. +","Está justo aquí en la planta de aguas residuales, aunque es el acoplamiento del Frente. Quien te haya dicho que era de La Orden te dijo mal. ","Se on täällä jätelaitoksella. Mutta se on Rintaman kytkentä. Kuka sinulle kertoikaan sen kuuluvan Veljeskunnalle, oli väärässä.","Il se trouve ici dans le traitement des égouts, mais c'est le coupleur du Front . Celui qui vous a dit qu'il appartient à l'Ordre se plante.",,"Igen, jól hallottad, a szennyvíz tisztítóban. Ez azonban a Front kapcsolója. Akárki mondta, hogy a Rendé, hazudott neked.",È proprio qui nell'impianto fognario. Ma è il giunto del Fronte. Chiunque ti abbia detto che fosse il giunto dell'Ordine si sbagliava.,"正にここの下水処理場にあるさ。 だがそれはフロントにも繋いでいる。 そいつがオーダーの所有物と言われてたが、 @@ -12900,10 +12900,10 @@ What an up guy.,TXT_BBSUB_SCRIPT05_D4548_THEOR,MAP05: Prison Guard.,,,Takový ve Great. Now we're shopping for the Rat King.,TXT_BBSUB_SCRIPT06_D3032_BRING,〃,,,"Super, teď máme nakupovat pro Krysího krále.",Alle er så trængende. Nu skal vi købe ind til rottekongen.,"Klasse, jetzt machen wir die Arbeit für den Rattenkönig.",,,Genial. Ahora vamos de compras para el Rey de las Ratas.,,"Loistavaa, hoidamme nyt Rottakuninkaan ostoksia.","Parfait, maintenant on fait du shopping pour le roi des rats.",,Kiváló. A Patkány Király bevásárlói lettünk.,Grandioso. Adesso stiamo facendo shopping con il re dei ratti.,素敵ね。私達がラットキングのために買い物とか。,끝내준다. 이제 시궁쥐 왕의 심부름도 해야 한다니.,Geweldig. Nu zijn we aan het winkelen voor de rattenkoning.,Flott. Nå handler vi til Rottekongen.,Świetnie. Teraz robimy zakupy dla Króla Szczurów.,Que beleza. Agora estamos fazendo comprinhas pro Rato-Rei.,,Grozav. Acum facem cumpărături pentru Regele Șobolanilor.,Классно. Мы идём за покупками для Крысиного короля.,,Toppen. Nu ska vi shoppa för råttkungen.,Harika. Şimdi de Fare Kral için alışveriş yapıyoruz. "I bet this guy smells really bad, too.",TXT_BBSUB_SCRIPT06_D4548_OPENT,〃,,,"Hádám, že tenhle chlápek taky pěkně smrdí.","Jeg vil vædde med, at han også lugter rigtig dårligt.","Ich wette, dieser Kerl riecht auch übel.",,,"Apuesto a que este tipo huele muy mal, también.",,"Lyön vetoa, että tämä tyyppi myös haisee tosi pahalta.","Je parie que ce type sent salement mauvais, aussi.",,"Le merném fogadni, hogy ez a pacák is büdös.",Scommetto che questo tizio ha pure un cattivo odore.,この男も酷い悪臭がすると賭けるわ。,얘도 분명 냄새 하나는 죽여줄 거야.,Ik durf te wedden dat deze kerel ook heel erg stinkt.,Jeg vedder på at denne fyren også lukter fælt.,"Założę się, że ten facet też bardzo śmierdzi.",Aposto que esse cara fede pra caramba também.,,Pun pariu că tipul ăsta mai și pute.,"Уверена, этот парень воняет особенно ужасно.",,Jag slår vad om att den här killen luktar riktigt illa också.,Eminim bu adam da çok kötü kokuyordur. More sewers... Great. Wonder what lives down there.,TXT_BBSUB_SCRIPT06_D9096_YOUHA,〃,,,"Další stoky... skvělý. Zajímalo by mě, co tam dole žije.",Flere kloakker... Fedt. Gad vide hvad der bor dernede.,"Mehr Kanäle, toll... Ich frage mich, was da unten lebt.",,,Más alcantarillas... Genial. Me pregunto qué vivirá ahí abajo.,,Lisää viemäreitä... Mahtavaa. Kukakohan elää täällä alhaalla.,Plus d'égouts.. Youpi. Je me demande qui vit là dedans.,,Még több kanális... kiváló. Mi lakhat odalent?,Altre fogne... fantastico. Mi domando cosa vive qua giù.,更なる下水道...ヤッバ。下に何が住んでるのか不思議に思うわ。,또 하수도라... 끝내준다. 저 아래에 또 뭐가 살고 있을까?,Meer riolering.... Geweldig. Ik vraag me af wat daar beneden leeft.,Mer kloakk... Flott. Lurer på hva som bor der nede.,Więcej kanałów... Świetnie. Ciekawe co tam mieszka.,Mais esgotos... Que legal. O que será que vive lá embaixo?,,Mai multe canale... Grozav. Mă întreb ce-o mai trăi jos aici.,"Снова канализация... Замечательно. Интересно, кого мы там встретим?",,Mer kloaker... Toppen. Undrar vad som bor där nere.,Daha fazla kanalizasyon. Harika. Acaba orada ne yaşıyor? -Dead end here. We'd better keep looking.,TXT_BBSUB_SCRIPT07_D6064_PROGR,MAP07: Computer room.,,,Tudy cesta nevede. Měli bychom se podívat dál.,Det er en blindgyde her. Vi må hellere lede videre.,Sackgasse. Wir sollten es woanders versuchen.,,,Un callejón sin salida. Deberíamos seguir buscando.,,Umpikuja tässä. Parasta jatkaa etsintää.,"Une impasse. Bon, on continue de chercher.",,Zsákutca. Folytatnunk kell a keresést.,Qui c'è un vicolo cieco. Meglio continuare a guardare.,行き止まりだ。私達はまだこの景色を楽しめるわ。,여기가 아닌가 봐. 다른 곳을 찾아봐야겠어.,Doodlopend hier. We kunnen maar beter blijven zoeken.,Blindvei her. Vi får lete videre.,Tu jest ślepy zaułek. Lepiej szukajmy dalej.,Sem saída aqui. Melhor seguirmos procurando.,,Capăt de linie. Mai bine ne mai uităm împrejur.,Тупик. Давай продолжать поиски.,,Det är en återvändsgränd här. Det är bäst att fortsätta leta.,Burası çıkmaz sokak. Aramaya devam etsek iyi olur. +Dead end here. We'd better keep looking.,TXT_BBSUB_SCRIPT07_D6064_PROGR,MAP07: Computer room.,,,Tudy cesta nevede. Měli bychom se podívat dál.,Det er en blindgyde her. Vi må hellere lede videre.,Sackgasse. Wir sollten es woanders versuchen.,,,Un camino sin salida. Deberíamos seguir buscando.,,Umpikuja tässä. Parasta jatkaa etsintää.,"Une impasse. Bon, on continue de chercher.",,Zsákutca. Folytatnunk kell a keresést.,Qui c'è un vicolo cieco. Meglio continuare a guardare.,行き止まりだ。私達はまだこの景色を楽しめるわ。,여기가 아닌가 봐. 다른 곳을 찾아봐야겠어.,Doodlopend hier. We kunnen maar beter blijven zoeken.,Blindvei her. Vi får lete videre.,Tu jest ślepy zaułek. Lepiej szukajmy dalej.,Sem saída aqui. Melhor seguirmos procurando.,,Capăt de linie. Mai bine ne mai uităm împrejur.,Тупик. Давай продолжать поиски.,,Det är en återvändsgränd här. Det är bäst att fortsätta leta.,Burası çıkmaz sokak. Aramaya devam etsek iyi olur. "Onward, my champion. Let's make Mr. Ugly twist and shout. ",TXT_BBSUB_SCRIPT10_D10612_YOUHA,MAP10: Macil (Possible reference to a song of The Beatles).,,,"Kupředu, můj šampióne. Pojďme pana Ošklivu hezky nakopat.","Fremad, min mester. Lad os få hr. Grimme til at vride sig og skrige. -",Und weiter gehts. Lass die Hackfresse zittern!,,,"Adelante, mi campeón. Hagamos al Sr. Feo retorcerse y gritar.",,"Eteenpäin, sotaurhoni. Pannaan Herra Rumilus vääntelehtimään ja huutamaan.",Allons-y mon champion. Allons tordre de douleur Monsieur Sale-geule.,,Gyerünk bajnokom. Ne várakoztassuk meg Ocsmány urat.,"Vai avanti, mio campione. Facciamo agitare e urlare il signor Brutto.",進み出よ、わがチャンピオン。ミスター生塵を捻りつぶしてやれ。,"어서 가자, 나의 영웅. 그 못생긴 녀석에게 본때를 보여주자고.","Voorwaarts, mijn kampioen. Laten we Mr Lelijk laten draaien en schreeuwen.","Fremad, min mester. La oss få herr Stygg til å vri seg og rope.","Naprzód, mój mistrzu. Sprawmy, by Pan Brzydki skręcał się i krzyczał. +",Und weiter gehts. Lass die Hackfresse zittern!,,,"Adelante, campeón. Hagamos que el Sr. Feo se retuerza y grite.",,"Eteenpäin, sotaurhoni. Pannaan Herra Rumilus vääntelehtimään ja huutamaan.",Allons-y mon champion. Allons tordre de douleur Monsieur Sale-geule.,,Gyerünk bajnokom. Ne várakoztassuk meg Ocsmány urat.,"Vai avanti, mio campione. Facciamo agitare e urlare il signor Brutto.",進み出よ、わがチャンピオン。ミスター生塵を捻りつぶしてやれ。,"어서 가자, 나의 영웅. 그 못생긴 녀석에게 본때를 보여주자고.","Voorwaarts, mijn kampioen. Laten we Mr Lelijk laten draaien en schreeuwen.","Fremad, min mester. La oss få herr Stygg til å vri seg og rope.","Naprzód, mój mistrzu. Sprawmy, by Pan Brzydki skręcał się i krzyczał. ","Vai em frente, meu campeão. Vamos fazer o Sr. Feioso soltar a franga.",,"Drept în față, campionul meu. Să-l facem pe dl. Urât să țipe.","Вперёд, мой защитник. Заставим Г-на Урода сплясать и спеть.",,"Framåt, min mästare. Låt oss få herr Ful att vrida sig och skrika.","İleri, şampiyonum. Bay Çirkin'i döndürelim ve bağırtalım. " "Biomechanical? Well, that explains their seemingly endless supply of troops! And their bad attitude. From 4963aea0e822adcb3fc60d6d641d20885fc16f79 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 19 Dec 2024 05:43:58 -0500 Subject: [PATCH 04/34] - add a 1:1.2 ratio min-scale mode --- src/common/rendering/r_videoscale.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/common/rendering/r_videoscale.cpp b/src/common/rendering/r_videoscale.cpp index bfed3ec73b..6d11ff468a 100644 --- a/src/common/rendering/r_videoscale.cpp +++ b/src/common/rendering/r_videoscale.cpp @@ -1,7 +1,7 @@ /*--------------------------------------------------------------------------- ** ** Copyright(C) 2017 Magnus Norddahl -** Copyright(C) 2017-2020 Rachael Alexanderson +** Copyright(C) 2017-2024 Rachael Alexanderson ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -128,16 +128,17 @@ namespace // the odd formatting of this struct definition is meant to resemble a table header. set your tab stops to 4 when editing this file. struct v_ScaleTable - { bool isValid; uint32_t(*GetScaledWidth)(uint32_t Width, uint32_t Height); uint32_t(*GetScaledHeight)(uint32_t Width, uint32_t Height); float pixelAspect; bool isCustom; }; + { bool isValid; uint32_t(*GetScaledWidth)(uint32_t Width, uint32_t Height); uint32_t(*GetScaledHeight)(uint32_t Width, uint32_t Height); float pixelAspect; bool isCustom; }; v_ScaleTable vScaleTable[] = { - { true, [](uint32_t Width, uint32_t Height)->uint32_t { return Width; }, [](uint32_t Width, uint32_t Height)->uint32_t { return Height; }, 1.0f, false }, // 0 - Native - { true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX(Width, Height); }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY(Width, Height); }, 1.0f, false }, // 6 - Minimum Scale to Fill Entire Screen - { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 640; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 400; }, 1.2f, false }, // 2 - 640x400 (formerly 320x200) - { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 960; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 600; }, 1.2f, false }, // 3 - 960x600 (formerly 640x400) - { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 1280; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 800; }, 1.2f, false }, // 4 - 1280x800 - { true, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customwidth; }, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customheight; }, 1.0f, true }, // 5 - Custom - { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 320; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 200; }, 1.2f, false }, // 7 - 320x200 + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return Width; }, [](uint32_t Width, uint32_t Height)->uint32_t { return Height; }, 1.0f, false }, // 0 - Native + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX(Width, Height); }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY(Width, Height); }, 1.0f, false }, // 1 - Minimum Scale to Fill Entire Screen + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 640; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 400; }, 1.2f, false }, // 2 - 640x400 (formerly 320x200) + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 960; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 600; }, 1.2f, false }, // 3 - 960x600 (formerly 640x400) + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 1280; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 800; }, 1.2f, false }, // 4 - 1280x800 + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customwidth; }, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customheight; }, 1.0f, true }, // 5 - Custom + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 320; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 200; }, 1.2f, false }, // 6 - 320x200 + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX(Width * 1.2, Height) * 1.2; }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY(Width * 1.2, Height); }, 1.2f, false }, // 7 - Minimum Scale to Fill Entire Screen (1.2) }; bool isOutOfBounds(int x) { From 0a375f2a6d3292520c8c1822ac81fcaa05676428 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 19 Dec 2024 05:54:57 -0500 Subject: [PATCH 05/34] - add menu option for new 1:1.2 minimal scaling mode --- wadsrc/static/menudef.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 54aac33027..b570230d7f 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -2265,6 +2265,7 @@ OptionValue ScaleModes 4, "1280x800" 5, "$OPTVAL_CUSTOM" 1, "$OPTVAL_LOWEST" + 7, "$OPTVAL_LOWEST12" } OptionValue CropAspect { From 62381cc7dedecd47e270c6c9241dd14bec79fa8f Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 19 Dec 2024 06:46:43 -0500 Subject: [PATCH 06/34] - fix 1:1.2 minimizer function to work with actual 4:3 screens --- src/common/rendering/r_videoscale.cpp | 29 ++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/common/rendering/r_videoscale.cpp b/src/common/rendering/r_videoscale.cpp index 6d11ff468a..51f2844d12 100644 --- a/src/common/rendering/r_videoscale.cpp +++ b/src/common/rendering/r_videoscale.cpp @@ -98,6 +98,33 @@ namespace { return (uint32_t)((float)inheight * v_MinimumToFill(inwidth, inheight)); } + + float v_MinimumToFill2(uint32_t inwidth, uint32_t inheight) + { + // sx = screen x dimension, sy = same for y + float sx = (float)inwidth * 1.2, sy = (float)inheight; + static float lastsx = 0., lastsy = 0., result = 0.; + if (lastsx != sx || lastsy != sy) + { + if (sx <= 0. || sy <= 0.) + return 1.; // prevent x/0 error + // set absolute minimum scale to fill the entire screen but get as close to 640x400 as possible + float ssx = (float)(VID_MIN_UI_WIDTH) / 1.2 / sx, ssy = (float)(VID_MIN_UI_HEIGHT) / sy; + result = (ssx < ssy) ? ssy : ssx; + lastsx = sx; + lastsy = sy; + } + return result; + } + inline uint32_t v_mfillX2(uint32_t inwidth, uint32_t inheight) + { + return (uint32_t)((float)inwidth * v_MinimumToFill2(inwidth, inheight) * 1.2); + } + inline uint32_t v_mfillY2(uint32_t inwidth, uint32_t inheight) + { + return (uint32_t)((float)inheight * v_MinimumToFill2(inwidth, inheight)); + } + inline void refresh_minimums() { // specialUI is tracking a state where high-res console fonts are actually required, and @@ -138,7 +165,7 @@ namespace { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 1280; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 800; }, 1.2f, false }, // 4 - 1280x800 { true, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customwidth; }, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customheight; }, 1.0f, true }, // 5 - Custom { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 320; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 200; }, 1.2f, false }, // 6 - 320x200 - { true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX(Width * 1.2, Height) * 1.2; }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY(Width * 1.2, Height); }, 1.2f, false }, // 7 - Minimum Scale to Fill Entire Screen (1.2) + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX2(Width, Height) * 1.2; }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY2(Width, Height); }, 1.2f, false }, // 7 - Minimum Scale to Fill Entire Screen (1.2) }; bool isOutOfBounds(int x) { From 023328da047af49882481cabd6a715ee8c8ab895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sat, 7 Dec 2024 13:36:11 -0300 Subject: [PATCH 07/34] allow summon to work with visual thinkers --- src/d_net.cpp | 23 ++++++++++++++++++----- src/gamedata/info.cpp | 11 ++++++++--- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/d_net.cpp b/src/d_net.cpp index b785b52e2b..c7241c3a8b 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2378,7 +2378,6 @@ void Net_DoCommand (int type, uint8_t **stream, int player) case DEM_SUMMONFRIEND2: case DEM_SUMMONFOE2: { - PClassActor *typeinfo; int angle = 0; int16_t tid = 0; uint8_t special = 0; @@ -2393,11 +2392,11 @@ void Net_DoCommand (int type, uint8_t **stream, int player) for(i = 0; i < 5; i++) args[i] = ReadInt32(stream); } - typeinfo = PClass::FindActor(s); - if (typeinfo != NULL) + AActor *source = players[player].mo; + if(source != NULL) { - AActor *source = players[player].mo; - if (source != NULL) + PClassActor * typeinfo = PClass::FindActor(s); + if (typeinfo != NULL) { if (GetDefaultByType (typeinfo)->flags & MF_MISSILE) { @@ -2443,6 +2442,20 @@ void Net_DoCommand (int type, uint8_t **stream, int player) } } } + else + { // not an actor, must be a visualthinker + PClass * typeinfo = PClass::FindClass(s); + if(typeinfo && typeinfo->IsDescendantOf("VisualThinker")) + { + DVector3 spawnpos = source->Vec3Angle(source->radius * 4, source->Angles.Yaw, 8.); + auto vt = DVisualThinker::NewVisualThinker(source->Level, typeinfo); + if(vt) + { + vt->PT.Pos = spawnpos; + vt->UpdateSector(); + } + } + } } } break; diff --git a/src/gamedata/info.cpp b/src/gamedata/info.cpp index 67fb87f678..3fc5d2e763 100644 --- a/src/gamedata/info.cpp +++ b/src/gamedata/info.cpp @@ -55,6 +55,7 @@ #include "texturemanager.h" #include "d_main.h" #include "maps.h" +#include "p_visualthinker.h" extern void LoadActors (); extern void InitBotStuff(); @@ -779,11 +780,15 @@ static void SummonActor (int command, int command2, FCommandLine argv) if (argv.argc() > 1) { - PClassActor *type = PClass::FindActor(argv[1]); + PClass *type = PClass::FindActor(argv[1]); if (type == nullptr) { - Printf ("Unknown actor '%s'\n", argv[1]); - return; + type = PClass::FindClass(argv[1]); + if(!type || !type->IsDescendantOf("VisualThinker")) + { + Printf ("Unknown actor or visual thinker '%s'\n", argv[1]); + return; + } } Net_WriteInt8 (argv.argc() > 2 ? command2 : command); Net_WriteString (type->TypeName.GetChars()); From b7c9675c9d84aaebe2f68d2c15e0c34005e2d062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Fri, 20 Dec 2024 22:34:03 -0300 Subject: [PATCH 08/34] add snd_footstepvolume to sound options menu (SNDMNU_FOOTSTEPVOLUME is already in the spreadsheet, but only for en/pt so far) --- wadsrc/static/menudef.txt | 1 + wadsrc/static/menudef.zsimple | 1 + 2 files changed, 2 insertions(+) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index b570230d7f..4b8553e0e3 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1938,6 +1938,7 @@ OptionMenu SoundOptions protected StaticText " " Slider "$SNDMNU_SFXVOLUME", "snd_sfxvolume", 0, 1, 0.05, 2 Slider "$SNDMNU_MUSICVOLUME", "snd_musicvolume", 0, 1, 0.05, 2 + Slider "$SNDMNU_FOOTSTEPVOLUME", "snd_footstepvolume", 0, 1, 0.05, 2 StaticText " " Slider "$SNDMNU_MENUVOLUME", "snd_menuvolume", 0, 1, 0.05, 2 StaticText " " diff --git a/wadsrc/static/menudef.zsimple b/wadsrc/static/menudef.zsimple index 512dc3a0bf..2e0aabf873 100644 --- a/wadsrc/static/menudef.zsimple +++ b/wadsrc/static/menudef.zsimple @@ -35,6 +35,7 @@ OptionMenu SoundOptionsSimple protected StaticText " " Slider "$SNDMNU_SFXVOLUME", "snd_sfxvolume", 0, 1, 0.05, 2 Slider "$SNDMNU_MUSICVOLUME", "snd_musicvolume", 0, 1, 0.05, 2 + Slider "$SNDMNU_FOOTSTEPVOLUME", "snd_footstepvolume", 0, 1, 0.05, 2 StaticText " " Slider "$SNDMNU_MENUVOLUME", "snd_menuvolume", 0, 1, 0.05, 2 StaticText " " From eefad0764e6a55bdc4837215c0a75ed732823e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Fri, 20 Dec 2024 22:45:38 -0300 Subject: [PATCH 09/34] fix TranslationID casting --- src/common/scripting/backend/codegen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 03a41f3a89..1064710e3a 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -8511,6 +8511,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_State: case NAME_SpriteID: case NAME_TextureID: + case NAME_TranslationID: if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) { PType *type = From d36fa3c36b54aa0d848657dcfe9355a844491409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Fri, 20 Dec 2024 23:30:12 -0300 Subject: [PATCH 10/34] add helper methods to Sound/SpriteID/TranslationID --- src/common/engine/namedef.h | 6 ++ src/common/scripting/backend/codegen.cpp | 80 +++++++++++++++++++++++- 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/common/engine/namedef.h b/src/common/engine/namedef.h index be0c47649e..df4c574ecc 100644 --- a/src/common/engine/namedef.h +++ b/src/common/engine/namedef.h @@ -196,9 +196,15 @@ xx(TranslationID) xx(Overlay) xx(IsValid) xx(IsNull) +xx(IsEmpty) +xx(IsFixed) +xx(IsKeep) xx(Exists) xx(SetInvalid) xx(SetNull) +xx(SetEmpty) +xx(SetFixed) +xx(SetKeep) xx(Key) xx(Index) xx(Find) diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 1064710e3a..d009fe7224 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -8877,7 +8877,24 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) return Self; } } - else if (Self->ValueType == TypeTextureID) + else if (ctx.Version >= MakeVersion(4, 15, 0) && Self->ValueType == TypeSound && MethodName == NAME_IsValid) + { + if (ArgList.Size() > 0) + { + ScriptPosition.Message(MSG_ERROR, "Too many parameters in call to %s", MethodName.GetChars()); + delete this; + return nullptr; + } + + Self->ValueType = TypeSInt32; // treat as integer + FxExpression *x = new FxCompareRel('>', Self, new FxConstant(0, ScriptPosition)); + Self = nullptr; + SAFE_RESOLVE(x, ctx); + + delete this; + return x; + } + else if (Self->ValueType == TypeTextureID || (ctx.Version >= MakeVersion(4, 15, 0) && (Self->ValueType == TypeTranslationID))) { if (MethodName == NAME_IsValid || MethodName == NAME_IsNull || MethodName == NAME_Exists || MethodName == NAME_SetInvalid || MethodName == NAME_SetNull) { @@ -8920,6 +8937,67 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) } } + else if (ctx.Version >= MakeVersion(4, 15, 0) && Self->ValueType == TypeSpriteID) + { + if (MethodName == NAME_IsValid || MethodName == NAME_IsEmpty || MethodName == NAME_IsFixed || MethodName == NAME_IsKeep + || MethodName == NAME_Exists + || MethodName == NAME_SetInvalid || MethodName == NAME_SetEmpty || MethodName == NAME_SetFixed || MethodName == NAME_SetKeep) + { + if (ArgList.Size() > 0) + { + ScriptPosition.Message(MSG_ERROR, "Too many parameters in call to %s", MethodName.GetChars()); + delete this; + return nullptr; + } + // No need to create a dedicated node here, all builtins map directly to trivial operations. + Self->ValueType = TypeSInt32; // all builtins treat the texture index as integer. + FxExpression *x = nullptr; + switch (MethodName.GetIndex()) + { + case NAME_IsValid: + x = new FxCompareRel(TK_Geq, Self, new FxConstant(0, ScriptPosition)); + break; + + case NAME_IsEmpty: // TNT1 + x = new FxCompareEq(TK_Eq, Self, new FxConstant(0, ScriptPosition)); + break; + + case NAME_IsFixed: // "----" + x = new FxCompareEq(TK_Eq, Self, new FxConstant(1, ScriptPosition)); + break; + + case NAME_IsKeep: // "####" + x = new FxCompareEq(TK_Eq, Self, new FxConstant(2, ScriptPosition)); + break; + + case NAME_Exists: + x = new FxCompareRel(TK_Geq, Self, new FxConstant(3, ScriptPosition)); + break; + + case NAME_SetInvalid: + x = new FxAssign(Self, new FxConstant(-1, ScriptPosition)); + break; + + case NAME_SetEmpty: // TNT1 + x = new FxAssign(Self, new FxConstant(0, ScriptPosition)); + break; + + case NAME_SetFixed: // "----" + x = new FxAssign(Self, new FxConstant(1, ScriptPosition)); + break; + + case NAME_SetKeep: // "####" + x = new FxAssign(Self, new FxConstant(2, ScriptPosition)); + break; + } + Self = nullptr; + SAFE_RESOLVE(x, ctx); + if (MethodName == NAME_SetInvalid || MethodName == NAME_SetEmpty || MethodName == NAME_SetFixed || MethodName == NAME_SetKeep) x->ValueType = TypeVoid; // override the default type of the assignment operator. + delete this; + return x; + } + } + else if (Self->IsVector()) { // handle builtins: Vectors got 5. From bdddfcc80ad2168dd451f0b78a4234e08f5e7842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Fri, 20 Dec 2024 23:32:07 -0300 Subject: [PATCH 11/34] allow nullptr with spriteid/textureid/translationid (for default parameters/etc) --- src/common/scripting/backend/codegen.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index d009fe7224..07ced853ed 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -1842,6 +1842,12 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) { goto basereturn; } + else if (ctx.Version >= MakeVersion(4, 15, 0) && basex->ValueType == TypeNullPtr && (ValueType == TypeSpriteID || ValueType == TypeTextureID || ValueType == TypeTranslationID)) + { + delete basex; + basex = new FxConstant(0, ScriptPosition); + goto basereturn; + } else if (IsFloat()) { FxExpression *x = new FxFloatCast(basex); From d3e5cf77ab6410fad4b901e2dacac320744ca125 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Sun, 22 Dec 2024 01:59:52 +0800 Subject: [PATCH 12/34] Add lm_sunintensity documentation. Clean up styling of all ZDRay-related entries --- specs/udmf_zdoom.txt | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 575b881edd..dcc0894826 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -157,10 +157,10 @@ Note: All fields default to false unless mentioned otherwise. For lines with ACS specials (80-86 and 226), if arg0str is present and non-null, it will be used as the name of the script to execute, and arg0 will be ignored. - lm_sampledist_line = ; // ZDRay customizable sampling distance for this line. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 - lm_sampledist_top = ; // ZDRay customizable sampling distance for this line's top part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 - lm_sampledist_mid = ; // ZDRay customizable sampling distance for this line's middle part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 - lm_sampledist_bot = ; // ZDRay customizable sampling distance for this line's bottom part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 + lm_sampledist_line = ; // ZDRay customizable sampling distance for this line. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0. + lm_sampledist_top = ; // ZDRay customizable sampling distance for this line's top part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0. + lm_sampledist_mid = ; // ZDRay customizable sampling distance for this line's middle part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0. + lm_sampledist_bot = ; // ZDRay customizable sampling distance for this line's bottom part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0. } sidedef @@ -231,10 +231,10 @@ Note: All fields default to false unless mentioned otherwise. colorization_mid = ; // Sets a colorization record for the middle texture. Colorization records must be defined in TEXTURES. colorization_bottom = ; // Sets a colorization record for the lower texture. Colorization records must be defined in TEXTURES. - lm_sampledist_line = ; // ZDRay customizable sampling distance for this sidedef. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 - lm_sampledist_top = ; // ZDRay customizable sampling distance for this sidedef's top part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 - lm_sampledist_mid = ; // ZDRay customizable sampling distance for this sidedef's middle part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 - lm_sampledist_bot = ; // ZDRay customizable sampling distance for this sidedef's bottom part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 + lm_sampledist_line = ; // ZDRay customizable sampling distance for this sidedef. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0. + lm_sampledist_top = ; // ZDRay customizable sampling distance for this sidedef's top part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0. + lm_sampledist_mid = ; // ZDRay customizable sampling distance for this sidedef's middle part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0. + lm_sampledist_bot = ; // ZDRay customizable sampling distance for this sidedef's bottom part. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0. skew_top = ; // enables skewing of wall textures, the skewing angle will be aligned to one of the 4 planes touching the floor. skew_middle = ; // Vertical texture alignment defines the position at the leftmost point of the wall. @@ -390,9 +390,9 @@ Note: All fields default to false unless mentioned otherwise. for Doom format maps so any map converter converting to the ZDoomTranslated namespace should set this flag for each tagged sector. - lm_sampledist_floor = ; // ZDRay customizable sampling distance for this sector's floor. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 - lm_sampledist_ceiling = ; // ZDRay customizable sampling distance for this sector's ceiling. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0 - lm_dynamic = ; // ZDRay marks a sector's lightmaps as dynamic so that they may be updated in realtime (used for flickering lights, changing a lightmap light's position, color etc). Default = false + lm_sampledist_floor = ; // ZDRay customizable sampling distance for this sector's floor. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0. + lm_sampledist_ceiling = ; // ZDRay customizable sampling distance for this sector's ceiling. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 0. + lm_dynamic = ; // ZDRay marks a sector's lightmaps as dynamic so that they may be updated in realtime (used for flickering lights, changing a lightmap light's position, color etc). Default = false. } thing @@ -425,10 +425,11 @@ Note: All fields default to false unless mentioned otherwise. scale = ; // Vertical and horizontal scaling on thing. Default = 0 (ignored). floatbobphase = ; // Sets the thing's floatbobphase. Valid phase values are 0-63. Default = -1 (use actor class default). - lm_sampledist = ; // ZDRay lightmap sample distance for the entire map. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 8 + lm_sampledist = ; // ZDRay lightmap sample distance for the entire map. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 8. lm_suncolor = ; // ZDRay lightmap sun color. Default is white (0xFFFFFF). + lm_sunintensity = ; // ZDRay lightmap sun intensity multiplier. Default = 1.0. - light_softshadowradius = ; // ZDRay lightmap light and raytraced dynamic light soft shadow amount. Higher values produce softer shadows. Default = 5.0 + light_softshadowradius = ; // ZDRay lightmap light and raytraced dynamic light soft shadow amount. Higher values produce softer shadows. Default = 5.0. friendlyseeblocks = ; // How far (in block units) a friendly monster can see other monsters. Default 10 From a4e527979d51066b748b94184dfda57c8a6fc2e6 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Wed, 25 Dec 2024 18:22:43 +0800 Subject: [PATCH 13/34] Allow setting a dynamic light's alpha to influence its brightness. This brings it in parity with VKDoom --- src/rendering/hwrenderer/hw_dynlightdata.cpp | 3 +++ src/rendering/hwrenderer/scene/hw_spritelight.cpp | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/src/rendering/hwrenderer/hw_dynlightdata.cpp b/src/rendering/hwrenderer/hw_dynlightdata.cpp index 044d34d3d5..0c264a1f7b 100644 --- a/src/rendering/hwrenderer/hw_dynlightdata.cpp +++ b/src/rendering/hwrenderer/hw_dynlightdata.cpp @@ -92,6 +92,9 @@ void AddLightToList(FDynLightData &dld, int group, FDynamicLight * light, bool f cs = 1.0f; } + if (light->target) + cs *= (float)light->target->Alpha; + float r = light->GetRed() / 255.0f * cs; float g = light->GetGreen() / 255.0f * cs; float b = light->GetBlue() / 255.0f * cs; diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index f9998398aa..ca67296d7d 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -176,6 +176,15 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FLig lr = light->GetRed() / 255.0f; lg = light->GetGreen() / 255.0f; lb = light->GetBlue() / 255.0f; + + if (light->target) + { + float alpha = (float)light->target->Alpha; + lr *= alpha; + lg *= alpha; + lb *= alpha; + } + if (light->IsSubtractive()) { float bright = (float)FVector3(lr, lg, lb).Length(); From d6e1097b85ad9e7ad876b470e7eec94202aa70ee Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 4 Jul 2024 14:32:14 -0400 Subject: [PATCH 14/34] - enable mipmapping in 2D --- src/common/rendering/hwrenderer/hw_draw2d.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/common/rendering/hwrenderer/hw_draw2d.cpp b/src/common/rendering/hwrenderer/hw_draw2d.cpp index 5c7100b34f..a5ed7b1eeb 100644 --- a/src/common/rendering/hwrenderer/hw_draw2d.cpp +++ b/src/common/rendering/hwrenderer/hw_draw2d.cpp @@ -50,6 +50,7 @@ //=========================================================================== CVAR(Bool, gl_aalines, false, CVAR_ARCHIVE) +CVAR(Bool, hw_2dmip, true, CVAR_ARCHIVE) void Draw2D(F2DDrawer* drawer, FRenderState& state) { @@ -71,6 +72,8 @@ void Draw2D(F2DDrawer* drawer, FRenderState& state, int x, int y, int width, int state.EnableMultisampling(false); state.EnableLineSmooth(gl_aalines); + bool cache_hw_2dmip = hw_2dmip; // cache cvar lookup so it's not done in a loop + auto &vertices = drawer->mVertices; auto &indices = drawer->mIndices; auto &commands = drawer->mData; @@ -180,7 +183,7 @@ void Draw2D(F2DDrawer* drawer, FRenderState& state, int x, int y, int width, int auto flags = cmd.mTexture->GetUseType() >= ETextureType::Special? UF_None : cmd.mTexture->GetUseType() == ETextureType::FontChar? UF_Font : UF_Texture; auto scaleflags = cmd.mFlags & F2DDrawer::DTF_Indexed ? CTF_Indexed : 0; - state.SetMaterial(cmd.mTexture, flags, scaleflags, cmd.mFlags & F2DDrawer::DTF_Wrap ? CLAMP_NONE : CLAMP_XY_NOMIP, cmd.mTranslationId, -1); + state.SetMaterial(cmd.mTexture, flags, scaleflags, cmd.mFlags & F2DDrawer::DTF_Wrap ? CLAMP_NONE : (cache_hw_2dmip ? CLAMP_XY : CLAMP_XY_NOMIP), cmd.mTranslationId, -1); state.EnableTexture(true); // Canvas textures are stored upside down From aebabd2307dda19b8c618bba67b4badc7f3054d8 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Tue, 31 Dec 2024 04:42:56 +0800 Subject: [PATCH 15/34] Fix coop key share failing if the item was spawned in-game (for example, via the console) --- wadsrc/static/zscript/actors/inventory/inventory.zs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/actors/inventory/inventory.zs b/wadsrc/static/zscript/actors/inventory/inventory.zs index 52009f2e11..607c4f7c4e 100644 --- a/wadsrc/static/zscript/actors/inventory/inventory.zs +++ b/wadsrc/static/zscript/actors/inventory/inventory.zs @@ -700,7 +700,7 @@ class Inventory : Actor toucher.HasReceived(self, cls); // If the item can be shared, make sure every player gets a copy. - if (multiplayer && !deathmatch && !bDropped && ShouldShareItem(toucher)) + if (multiplayer && !deathmatch && ShouldShareItem(toucher)) ShareItemWithPlayers(toucher); } return res, toucher; From 902bf03c47cc544b80441b0d039090efc555aa09 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 28 Dec 2024 14:32:58 -0500 Subject: [PATCH 16/34] - implement new cvar `save_sort_order` - for now options are only 0 or 1 - 0 is alphabetical, 1 is descending by time (most recent first) --- src/common/menu/savegamemanager.cpp | 15 ++++++++++++++- src/common/menu/savegamemanager.h | 1 + src/menu/loadsavemenu.cpp | 12 ++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/common/menu/savegamemanager.cpp b/src/common/menu/savegamemanager.cpp index 1350930210..a20de0f49f 100644 --- a/src/common/menu/savegamemanager.cpp +++ b/src/common/menu/savegamemanager.cpp @@ -51,6 +51,7 @@ CVAR(String, save_dir, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG); FString SavegameFolder; +CVAR(Int, save_sort_order, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) //============================================================================= // @@ -136,7 +137,19 @@ int FSavegameManagerBase::InsertSaveNode(FSaveGameNode *node) //if (SaveGames[0] == &NewSaveNode) i++; // To not insert above the "new savegame" dummy entry. for (; i < SaveGames.Size(); i++) { - if (SaveGames[i]->bOldVersion || node->SaveTitle.CompareNoCase(SaveGames[i]->SaveTitle) <= 0) + bool sortcmp = false; + switch(save_sort_order) + { + case 1: + sortcmp = node->CreationTime.CompareNoCase(SaveGames[i]->CreationTime) > 0; + break; + default: + case 0: + sortcmp = node->SaveTitle.CompareNoCase(SaveGames[i]->SaveTitle) <= 0; + break; + } + + if (SaveGames[i]->bOldVersion || sortcmp) { break; } diff --git a/src/common/menu/savegamemanager.h b/src/common/menu/savegamemanager.h index 20b466b53d..4dd2eb69d4 100644 --- a/src/common/menu/savegamemanager.h +++ b/src/common/menu/savegamemanager.h @@ -11,6 +11,7 @@ struct FSaveGameNode { FString SaveTitle; FString Filename; + FString CreationTime; bool bOldVersion = false; bool bMissingWads = false; bool bNoDelete = false; diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index d41f763b39..b843892b8d 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -50,6 +50,8 @@ // Save name length limit for old binary formats. #define OLDSAVESTRINGSIZE 24 +EXTERN_CVAR(Int, save_sort_order) + //============================================================================= // // M_ReadSaveStrings @@ -60,6 +62,14 @@ void FSavegameManager::ReadSaveStrings() { + // re-read list if forced to sort again + static int old_save_sort_order = 0; + if (old_save_sort_order != save_sort_order) + { + ClearSaveGames(); + old_save_sort_order = save_sort_order; + } + if (SaveGames.Size() == 0) { FString filter; @@ -91,6 +101,7 @@ void FSavegameManager::ReadSaveStrings() FString engine = arc.GetString("Engine"); FString iwad = arc.GetString("Game WAD"); FString title = arc.GetString("Title"); + FString creationtime = arc.GetString("Creation Time"); if (engine.Compare(GAMESIG) != 0 || savever > SAVEVER) @@ -120,6 +131,7 @@ void FSavegameManager::ReadSaveStrings() node->bOldVersion = oldVer; node->bMissingWads = missing; node->SaveTitle = title; + node->CreationTime = creationtime; InsertSaveNode(node); } } From d42e3b0037f481f9d3b72a5739ae04af344a7c92 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 29 Dec 2024 16:28:34 -0500 Subject: [PATCH 17/34] - store current time in the save game node when saving a new game - when overwriting a save force it to reposition itself in the list in case any of its details have changed --- src/common/menu/savegamemanager.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/common/menu/savegamemanager.cpp b/src/common/menu/savegamemanager.cpp index a20de0f49f..929d631d13 100644 --- a/src/common/menu/savegamemanager.cpp +++ b/src/common/menu/savegamemanager.cpp @@ -183,12 +183,18 @@ void FSavegameManagerBase::NotifyNewSave(const FString &file, const FString &tit #endif { node->SaveTitle = title; + node->CreationTime = myasctime(); node->bOldVersion = false; node->bMissingWads = false; + + // refresh my game's position on the list (needed if time/name changed) + SaveGames.Delete(i); + int index = InsertSaveNode(node); + if (okForQuicksave) { if (quickSaveSlot == nullptr || quickSaveSlot == (FSaveGameNode*)1 || forceQuicksave) quickSaveSlot = node; - LastAccessed = LastSaved = i; + LastAccessed = LastSaved = index; } return; } @@ -196,6 +202,7 @@ void FSavegameManagerBase::NotifyNewSave(const FString &file, const FString &tit auto node = new FSaveGameNode; node->SaveTitle = title; + node->CreationTime = myasctime(); node->Filename = file; node->bOldVersion = false; node->bMissingWads = false; From 786bfa64195c9e0a14733698bd1f470011774034 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 1 Jan 2025 17:25:54 -0500 Subject: [PATCH 18/34] - add save order to menu --- wadsrc/static/menudef.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 4b8553e0e3..759cc900d4 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1203,6 +1203,12 @@ OptionValue AlwaysTally 2, "$OPTVAL_WITHHUBS" } +OptionValue SaveOrder +{ + 0, "$OPTVAL_ALPHABETICAL" + 1, "$OPTVAL_LASTSAVEDTIME" +} + OptionMenu "MiscOptions" protected { Title "$MISCMNU_TITLE" @@ -1227,6 +1233,7 @@ OptionMenu "MiscOptions" protected Slider "$MISCMNU_AUTOSAVECOUNT", "autosavecount", 1, 20, 1, 0 Option "$MISCMNU_QUICKSAVEROTATION", "quicksaverotation", "OnOff" Slider "$MISCMNU_QUICKSAVECOUNT", "quicksaverotationcount", 1, 20, 1, 0 + Option "$MISCMNU_SAVEORDER", "save_sort_order", "SaveOrder" Option "$MISCMNU_DEHLOAD", "dehload", "dehopt" Option "$MISCMNU_ENABLESCRIPTSCREENSHOTS", "enablescriptscreenshot", "OnOff" Option "$MISCMNU_SETSLOTSTRICT", "setslotstrict", "YesNo" From f3b0c3ac5eea18a750780569f2914b50f9b1ce2f Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Fri, 3 Jan 2025 09:02:12 -0500 Subject: [PATCH 19/34] - Roll back filesystem changes. These were causing instabilities in the master branch that were interfering with development. --- src/CMakeLists.txt | 2 - src/am_map.cpp | 2 +- src/common/audio/music/i_music.cpp | 7 +- src/common/audio/music/i_soundfont.cpp | 8 +- src/common/audio/music/music.cpp | 4 +- src/common/console/c_bind.cpp | 10 +- src/common/console/c_enginecmds.cpp | 6 +- src/common/cutscenes/movieplayer.cpp | 2 +- src/common/engine/filesys_doom.cpp | 648 ----------------- src/common/engine/filesystem.h | 126 +--- src/common/engine/sc_man.cpp | 2 +- src/common/engine/serializer.cpp | 16 +- src/common/engine/stringtable.cpp | 2 +- src/common/engine/stringtable.h | 2 +- src/common/filesystem/include/fs_filesystem.h | 150 ++-- src/common/filesystem/include/resourcefile.h | 74 +- src/common/filesystem/source/file_7z.cpp | 9 +- .../filesystem/source/file_directory.cpp | 13 +- src/common/filesystem/source/file_grp.cpp | 7 +- src/common/filesystem/source/file_hog.cpp | 7 +- src/common/filesystem/source/file_hog2.cpp | 107 --- src/common/filesystem/source/file_lump.cpp | 7 +- src/common/filesystem/source/file_mvl.cpp | 6 +- src/common/filesystem/source/file_pak.cpp | 7 +- src/common/filesystem/source/file_rff.cpp | 7 +- src/common/filesystem/source/file_ssi.cpp | 8 +- src/common/filesystem/source/file_wad.cpp | 293 +++++++- src/common/filesystem/source/file_whres.cpp | 7 +- src/common/filesystem/source/file_zip.cpp | 8 +- src/common/filesystem/source/filesystem.cpp | 663 +++++++++++++----- src/common/filesystem/source/resourcefile.cpp | 55 +- src/common/fonts/v_font.cpp | 6 +- src/common/menu/menudef.cpp | 2 +- src/common/models/model.cpp | 12 +- src/common/models/models_ue1.cpp | 6 +- src/common/models/voxels.cpp | 2 +- src/common/rendering/gl/gl_shader.cpp | 16 +- src/common/rendering/gl/gl_shaderprogram.cpp | 2 +- src/common/rendering/gles/gles_shader.cpp | 14 +- .../rendering/gles/gles_shaderprogram.cpp | 2 +- .../rendering/vulkan/shaders/vk_ppshader.cpp | 2 +- .../rendering/vulkan/shaders/vk_shader.cpp | 6 +- src/common/scripting/core/types.cpp | 2 +- src/common/scripting/frontend/zcc_parser.cpp | 6 +- src/common/scripting/interface/vmnatives.cpp | 14 +- src/common/startscreen/endoom.cpp | 4 +- .../startscreen/startscreen_generic.cpp | 2 +- src/common/startscreen/startscreen_hexen.cpp | 6 +- src/common/startscreen/startscreen_strife.cpp | 2 +- src/common/textures/formats/pngtexture.cpp | 16 +- src/common/textures/gametexture.cpp | 10 +- src/common/textures/texturemanager.cpp | 52 +- src/common/utility/palette.cpp | 6 +- src/d_defcvars.cpp | 2 +- src/d_iwad.cpp | 26 +- src/d_main.cpp | 198 +++--- src/g_dumpinfo.cpp | 12 +- src/g_game.cpp | 8 +- src/g_statusbar/sbarinfo.cpp | 12 +- src/gamedata/d_dehacked.cpp | 16 +- src/gamedata/decallib.cpp | 2 +- src/gamedata/doomfont.h | 14 +- src/gamedata/g_mapinfo.cpp | 20 +- src/gamedata/statistics.cpp | 2 +- src/gamedata/textures/buildloader.cpp | 8 +- src/gamedata/xlat/parsecontext.cpp | 2 +- src/intermission/intermission_parse.cpp | 8 +- src/maploader/compatibility.cpp | 4 +- src/maploader/edata.cpp | 2 +- src/maploader/glnodes.cpp | 12 +- src/maploader/strifedialogue.cpp | 10 +- src/maploader/udmf.cpp | 2 +- src/maploader/usdf.cpp | 2 +- src/menu/loadsavemenu.cpp | 2 +- src/p_openmap.cpp | 14 +- src/playsim/fragglescript/t_func.cpp | 2 + src/playsim/p_acs.cpp | 8 +- src/playsim/p_user.cpp | 12 +- src/r_data/colormaps.cpp | 6 +- src/r_data/gldefs.cpp | 8 +- src/r_data/models.cpp | 2 +- src/r_data/r_translate.cpp | 2 +- src/r_data/sprites.cpp | 14 +- src/r_data/v_palette.cpp | 4 +- src/r_data/voxeldef.cpp | 4 +- src/rendering/swrenderer/r_swcolormaps.cpp | 8 +- src/scripting/decorate/thingdef_parse.cpp | 4 +- src/sound/s_advsound.cpp | 12 +- src/sound/s_doomsound.cpp | 8 +- src/wi_stuff.cpp | 4 +- 90 files changed, 1349 insertions(+), 1582 deletions(-) delete mode 100644 src/common/engine/filesys_doom.cpp delete mode 100644 src/common/filesystem/source/file_hog2.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2af200c2de..95b67a2d87 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1096,7 +1096,6 @@ set (PCH_SOURCES common/engine/cycler.cpp common/engine/d_event.cpp common/engine/date.cpp - common/engine/filesys_doom.cpp common/engine/stats.cpp common/engine/sc_man.cpp common/engine/palettecontainer.cpp @@ -1231,7 +1230,6 @@ set( GAME_SOURCES common/filesystem/source/file_whres.cpp common/filesystem/source/file_ssi.cpp common/filesystem/source/file_hog.cpp - common/filesystem/source/file_hog2.cpp common/filesystem/source/file_mvl.cpp common/filesystem/source/file_directory.cpp common/filesystem/source/resourcefile.cpp diff --git a/src/am_map.cpp b/src/am_map.cpp index 9d81248915..c547884b2e 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -845,7 +845,7 @@ static void AM_ParseArrow(TArray &Arrow, const char *lumpname) { const int R = int((8 * PLAYERRADIUS) / 7); FScanner sc; - int lump = fileSystem.CheckNumForAnyName(lumpname); + int lump = fileSystem.CheckNumForFullName(lumpname, true); if (lump >= 0) { sc.OpenLumpNum(lump); diff --git a/src/common/audio/music/i_music.cpp b/src/common/audio/music/i_music.cpp index 54f66be9ac..d190537d45 100644 --- a/src/common/audio/music/i_music.cpp +++ b/src/common/audio/music/i_music.cpp @@ -53,6 +53,9 @@ #include "s_music.h" #include "filereadermusicinterface.h" +using namespace FileSys; + + void I_InitSoundFonts(); EXTERN_CVAR (Int, snd_samplerate) @@ -185,7 +188,7 @@ static void SetupGenMidi() static void SetupWgOpn() { - int lump = fileSystem.FindFile("xg.wopn"); + int lump = fileSystem.CheckNumForFullName("xg.wopn"); if (lump < 0) { return; @@ -310,7 +313,7 @@ static ZMusic_MidiSource GetMIDISource(const char *fn) if (src.Compare("*") == 0) src = mus_playing.name; auto lump = fileSystem.CheckNumForName(src.GetChars(), ns_music); - if (lump < 0) lump = fileSystem.FindFile(src.GetChars()); + if (lump < 0) lump = fileSystem.CheckNumForFullName(src.GetChars()); if (lump < 0) { Printf("Cannot find MIDI lump %s.\n", src.GetChars()); diff --git a/src/common/audio/music/i_soundfont.cpp b/src/common/audio/music/i_soundfont.cpp index 3d3a6fd449..9737374fc4 100644 --- a/src/common/audio/music/i_soundfont.cpp +++ b/src/common/audio/music/i_soundfont.cpp @@ -298,7 +298,7 @@ FileReader FPatchSetReader::OpenFile(const char *name) FLumpPatchSetReader::FLumpPatchSetReader(const char *filename) { - mLumpIndex = fileSystem.FindFile(filename); + mLumpIndex = fileSystem.CheckNumForFullName(filename); mBasePath = filename; FixPathSeperator(mBasePath); @@ -314,9 +314,9 @@ FileReader FLumpPatchSetReader::OpenMainConfigFile() FileReader FLumpPatchSetReader::OpenFile(const char *name) { FString path; - if (IsAbsPath(name)) return FileReader(); // no absolute paths in the virtual file system. + if (IsAbsPath(name)) return FileReader(); // no absolute paths in the lump directory. path = mBasePath + name; - auto index = fileSystem.FindFile(path.GetChars()); + auto index = fileSystem.CheckNumForFullName(path.GetChars()); if (index < 0) return FileReader(); return fileSystem.ReopenFileReader(index); } @@ -472,7 +472,7 @@ FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *const name, int a // To avoid clashes this will only be done if the name has the '.cfg' extension. // Sound fonts cannot be loaded this way. const char *p = name + strlen(name) - 4; - if (p > name && !stricmp(p, ".cfg") && fileSystem.FindFile(name) >= 0) + if (p > name && !stricmp(p, ".cfg") && fileSystem.CheckNumForFullName(name) >= 0) { return new FLumpPatchSetReader(name); } diff --git a/src/common/audio/music/music.cpp b/src/common/audio/music/music.cpp index 3e9202befb..9664c54585 100644 --- a/src/common/audio/music/music.cpp +++ b/src/common/audio/music/music.cpp @@ -114,7 +114,7 @@ static FileReader OpenMusic(const char* musicname) { int lumpnum; lumpnum = mus_cb.FindMusic(musicname); - if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(musicname, ns_music); + if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(musicname, FileSys::ns_music); if (lumpnum == -1) { Printf("Music \"%s\" not found\n", musicname); @@ -143,7 +143,7 @@ bool MusicExists(const char* music_name) { int lumpnum; lumpnum = mus_cb.FindMusic(music_name); - if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(music_name, ns_music); + if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(music_name, FileSys::ns_music); if (lumpnum != -1 && fileSystem.FileLength(lumpnum) != 0) return true; } diff --git a/src/common/console/c_bind.cpp b/src/common/console/c_bind.cpp index 2d7903298d..fe794c736d 100644 --- a/src/common/console/c_bind.cpp +++ b/src/common/console/c_bind.cpp @@ -730,15 +730,15 @@ void ReadBindings(int lump, bool override) void C_SetDefaultKeys(const char* baseconfig) { - auto lump = fileSystem.FindFile("engine/commonbinds.txt"); + auto lump = fileSystem.CheckNumForFullName("engine/commonbinds.txt"); if (lump >= 0) { // Bail out if a mod tries to override this. Main game resources are allowed to do this, though. auto fileno2 = fileSystem.GetFileContainer(lump); - if (fileno2 > fileSystem.GetMaxBaseNum()) + if (fileno2 > fileSystem.GetMaxIwadNum()) { I_FatalError("File %s is overriding core lump %s.", - fileSystem.GetContainerFullName(fileno2), "engine/commonbinds.txt"); + fileSystem.GetResourceFileFullName(fileno2), "engine/commonbinds.txt"); } ReadBindings(lump, true); @@ -748,7 +748,7 @@ void C_SetDefaultKeys(const char* baseconfig) while ((lump = fileSystem.FindLumpFullName(baseconfig, &lastlump)) != -1) { // Read this only from the main game resources. - if (fileSystem.GetFileContainer(lump) <= fileSystem.GetMaxBaseNum()) + if (fileSystem.GetFileContainer(lump) <= fileSystem.GetMaxIwadNum()) ReadBindings(lump, true); } @@ -758,7 +758,7 @@ void C_SetDefaultKeys(const char* baseconfig) // [SW] - We need to check to see the origin of the DEFBINDS... if it // Comes from an IWAD/IPK3/IPK7 allow it to override the users settings... // If it comes from a user mod however, don't. - if (fileSystem.GetFileContainer(lump) > fileSystem.GetMaxBaseNum()) + if (fileSystem.GetFileContainer(lump) > fileSystem.GetMaxIwadNum()) ReadBindings(lump, false); else ReadBindings(lump, true); diff --git a/src/common/console/c_enginecmds.cpp b/src/common/console/c_enginecmds.cpp index 8fbee1f20a..d6a2e027e2 100644 --- a/src/common/console/c_enginecmds.cpp +++ b/src/common/console/c_enginecmds.cpp @@ -233,18 +233,18 @@ CCMD (wdir) if (argv.argc() != 2) wadnum = -1; else { - wadnum = fileSystem.CheckIfContainerLoaded (argv[1]); + wadnum = fileSystem.CheckIfResourceFileLoaded (argv[1]); if (wadnum < 0) { Printf ("%s must be loaded to view its directory.\n", argv[1]); return; } } - for (int i = 0; i < fileSystem.GetFileCount(); ++i) + for (int i = 0; i < fileSystem.GetNumEntries(); ++i) { if (wadnum == -1 || fileSystem.GetFileContainer(i) == wadnum) { - Printf ("%10ld %s\n", fileSystem.FileLength(i), fileSystem.GetFileName(i)); + Printf ("%10ld %s\n", fileSystem.FileLength(i), fileSystem.GetFileFullName(i)); } } } diff --git a/src/common/cutscenes/movieplayer.cpp b/src/common/cutscenes/movieplayer.cpp index 27d8f72718..a1b04385f6 100644 --- a/src/common/cutscenes/movieplayer.cpp +++ b/src/common/cutscenes/movieplayer.cpp @@ -508,7 +508,7 @@ class VpxPlayer : public MoviePlayer } if (!MusicStream) { - Printf(PRINT_BOLD, "Failed to decode %s\n", fileSystem.GetFileName(soundtrack)); + Printf(PRINT_BOLD, "Failed to decode %s\n", fileSystem.GetFileFullName(soundtrack, false)); } } animtex.SetSize(AnimTexture::VPX, width, height); diff --git a/src/common/engine/filesys_doom.cpp b/src/common/engine/filesys_doom.cpp deleted file mode 100644 index b19b99a78b..0000000000 --- a/src/common/engine/filesys_doom.cpp +++ /dev/null @@ -1,648 +0,0 @@ -/* -** filesys_doom.cpp -** -** the very special lump name lookup code for Doom's short names. -** Not useful in a generic system. -** -**--------------------------------------------------------------------------- -** Copyright 1998-2016 Randy Heit -** Copyright 2005-2024 Christoph Oelckers -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -** -*/ - -#include "filesystem.h" -#include "printf.h" - -//========================================================================== -// -// -// -//========================================================================== - -void FileSystem::InitHashChains() -{ - Super::InitHashChains(); - unsigned NumEntries = GetFileCount(); - for (unsigned i = 0; i < (unsigned)NumEntries; i++) - { - files[i].HashFirst = files[i].HashNext = NULL_INDEX; - } - // Now set up the chains - for (unsigned i = 0; i < (unsigned)NumEntries; i++) - { - if (files[i].Namespace == ns_hidden || files[i].ShortName[0] == 0) continue; - unsigned j = FileSys::MakeHash(files[i].ShortName, 8) % NumEntries; - files[i].HashNext = files[j].HashFirst; - files[j].HashFirst = i; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -static void UpperCopy(char* to, const char* from) -{ - int i; - - for (i = 0; i < 8 && from[i]; i++) - to[i] = toupper(from[i]); - for (; i < 8; i++) - to[i] = 0; - to[8] = 0; -} - -//========================================================================== -// -// -// -//========================================================================== - -void FileSystem::SetupName(int fileindex) -{ - const char* name = GetFileName(fileindex); - int containerflags = GetContainerFlags(GetFileContainer(fileindex)); - int lflags = GetFileFlags(fileindex); - - if ((containerflags & wadflags) == wadflags) - { - UpperCopy(files[fileindex].ShortName, name); - } - else if ((lflags & FileSys::RESFF_EMBEDDED) || !*name) - { - files[fileindex].Namespace = ns_hidden; - } - else - { - if (lflags & FileSys::RESFF_FULLPATH) files[fileindex].Flags |= LUMPF_FULLPATH; // copy for easier access in lookup function. - auto slash = strrchr(name, '/'); - auto base = slash ? (slash + 1) : name; - UpperCopy(files[fileindex].ShortName, base); - auto dot = strrchr(files[fileindex].ShortName, '.'); - if (dot) while (*dot) *dot++ = 0; - } -} - - -//========================================================================== -// -// IsMarker -// -// (from BOOM) -// -//========================================================================== - -inline bool FileSystem::IsMarker(int lump, const char* marker) noexcept -{ - auto name = files[lump].ShortName; - if (name[0] == marker[0]) - { - return (!strcmp(name, marker) || - (marker[1] == '_' && !strcmp(name + 1, marker))); - } - else return false; -} - -//========================================================================== -// -// SetNameSpace -// -// Sets namespace information for the lumps. It always looks for the first -// x_START and the last x_END lump, except when loading flats. In this case -// F_START may be absent and if that is the case all lumps with a size of -// 4096 will be flagged appropriately. -// -//========================================================================== - -// This class was supposed to be local in the function but GCC -// does not like that. -struct Marker -{ - int markertype; - int index; -}; - -void FileSystem::SetNamespace(int filenum, const char* startmarker, const char* endmarker, namespace_t space, FileSys::FileSystemMessageFunc Printf, bool flathack) -{ - using FileSys::FSMessageLevel; - bool warned = false; - int numstartmarkers = 0, numendmarkers = 0; - TArray markers; - int FirstLump = GetFirstEntry(filenum); - int LastLump = GetLastEntry(filenum); - auto FileName = GetContainerName(filenum); - - for (int i = FirstLump; i <= LastLump; i++) - { - if (IsMarker(i, startmarker)) - { - Marker m = { 0, i }; - markers.push_back(m); - numstartmarkers++; - } - else if (IsMarker(i, endmarker)) - { - Marker m = { 1, i }; - markers.push_back(m); - numendmarkers++; - } - } - - if (numstartmarkers == 0) - { - if (numendmarkers == 0) return; // no markers found - - if (Printf) - Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker); - - - if (flathack) - { - // We have found no F_START but one or more F_END markers. - // mark all lumps before the last F_END marker as potential flats. - unsigned int end = markers[markers.size() - 1].index; - for (int ii = FirstLump; ii <= LastLump; ii++) - { - if (FileLength(ii) == 4096) - { - // We can't add this to the flats namespace but - // it needs to be flagged for the texture manager. - if (Printf) Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName, files[ii].ShortName); - files[ii].Namespace = ns_maybeflat; - } - } - } - return; - } - - size_t i = 0; - while (i < markers.size()) - { - int start, end; - if (markers[i].markertype != 0) - { - if (Printf) Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker); - i++; - continue; - } - start = int(i++); - - // skip over subsequent x_START markers - while (i < markers.size() && markers[i].markertype == 0) - { - if (Printf) Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, startmarker); - i++; - continue; - } - // same for x_END markers - while (i < markers.size() - 1 && (markers[i].markertype == 1 && markers[i + 1].markertype == 1)) - { - if (Printf) Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, endmarker); - i++; - continue; - } - // We found a starting marker but no end marker. Ignore this block. - if (i >= markers.size()) - { - if (Printf) Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, startmarker, endmarker); - end = LastLump + 1; - } - else - { - end = markers[i++].index; - } - - // we found a marked block - if (Printf) Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName, startmarker, markers[start].index, end); - for (int j = markers[start].index + 1; j < end; j++) - { - if (files[j].Namespace != ns_global) - { - if (!warned && Printf) - { - Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName, j); - } - warned = true; - } - else if (space == ns_sprites && FileLength(j) < 8) - { - // sf 26/10/99: - // ignore sprite lumps smaller than 8 bytes (the smallest possible) - // in size -- this was used by some dmadds wads - // as an 'empty' graphics resource - if (Printf) Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName, files[j].ShortName, j); - } - else - { - files[j].Namespace = space; - } - } - } -} - - -//========================================================================== -// -// W_SkinHack -// -// Tests a wad file to see if it contains an S_SKIN marker. If it does, -// every lump in the wad is moved into a new namespace. Because skins are -// only supposed to replace player sprites, sounds, or faces, this should -// not be a problem. Yes, there are skins that replace more than that, but -// they are such a pain, and breaking them like this was done on purpose. -// This also renames any S_SKINxx lumps to just S_SKIN. -// -//========================================================================== - -void FileSystem::SkinHack(int filenum, FileSys::FileSystemMessageFunc Printf) -{ - using FileSys::FSMessageLevel; - // this being static is not a problem. The only relevant thing is that each skin gets a different number. - bool skinned = false; - bool hasmap = false; - - int FirstLump = GetFirstEntry(filenum); - int LastLump = GetLastEntry(filenum); - auto FileName = GetContainerName(filenum); - - for (int i = FirstLump; i <= LastLump; i++) - { - auto lump = &files[i]; - - if (!strnicmp(lump->ShortName, "S_SKIN", 6)) - { // Wad has at least one skin. - lump->ShortName[6] = 0; - lump->ShortName[7] = 0; - if (!skinned) - { - skinned = true; - - for (int j = FirstLump; j <= LastLump; j++) - { - files[j].Namespace = skin_namespc; - } - skin_namespc++; - } - } - // needless to say, this check is entirely useless these days as map names can be more diverse.. - if ((lump->ShortName[0] == 'M' && - lump->ShortName[1] == 'A' && - lump->ShortName[2] == 'P' && - lump->ShortName[3] >= '0' && lump->ShortName[3] <= '9' && - lump->ShortName[4] >= '0' && lump->ShortName[4] <= '9' && - lump->ShortName[5] == '\0') - || - (lump->ShortName[0] == 'E' && - lump->ShortName[1] >= '0' && lump->ShortName[1] <= '9' && - lump->ShortName[2] == 'M' && - lump->ShortName[3] >= '0' && lump->ShortName[3] <= '9' && - lump->ShortName[4] == '\0')) - { - hasmap = true; - } - } - if (skinned && hasmap && Printf) - { - Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName); - Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n"); - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void FileSystem::SetupNamespace(int filenum, FileSys::FileSystemMessageFunc Printf) -{ - int flags = GetContainerFlags(filenum); - - // Set namespace for entries from WADs. - if ((flags & wadflags) == wadflags) - { - SetNamespace(filenum, "S_START", "S_END", ns_sprites, Printf); - SetNamespace(filenum, "F_START", "F_END", ns_flats, Printf, true); - SetNamespace(filenum, "C_START", "C_END", ns_colormaps, Printf); - SetNamespace(filenum, "A_START", "A_END", ns_acslibrary, Printf); - SetNamespace(filenum, "TX_START", "TX_END", ns_newtextures, Printf); - SetNamespace(filenum, "V_START", "V_END", ns_strifevoices, Printf); - SetNamespace(filenum, "HI_START", "HI_END", ns_hires, Printf); - SetNamespace(filenum, "VX_START", "VX_END", ns_voxels, Printf); - SkinHack(filenum, Printf); - } - else if (!(flags & FResourceFile::NO_FOLDERS)) - { - int FirstLump = GetFirstEntry(filenum); - int LastLump = GetLastEntry(filenum); - auto FileName = GetContainerName(filenum); - - for (int i = FirstLump; i <= LastLump; i++) - { - auto lump = &files[i]; - - auto LongName = GetFileName(i); - // Map some directories to WAD namespaces. - // Note that some of these namespaces don't exist in WADS. - // CheckNumForName will handle any request for these namespaces accordingly. - int Namespace = !strncmp(LongName, "flats/", 6) ? ns_flats : - !strncmp(LongName, "textures/", 9) ? ns_newtextures : - !strncmp(LongName, "hires/", 6) ? ns_hires : - !strncmp(LongName, "sprites/", 8) ? ns_sprites : - !strncmp(LongName, "voxels/", 7) ? ns_voxels : - !strncmp(LongName, "colormaps/", 10) ? ns_colormaps : - !strncmp(LongName, "acs/", 4) ? ns_acslibrary : - !strncmp(LongName, "voices/", 7) ? ns_strifevoices : - !strncmp(LongName, "patches/", 8) ? ns_patches : - !strncmp(LongName, "graphics/", 9) ? ns_graphics : - !strncmp(LongName, "sounds/", 7) ? ns_sounds : - !strncmp(LongName, "music/", 6) ? ns_music : - !strchr(LongName, '/') ? ns_global : - ns_hidden; - - lump->Namespace = Namespace; - - switch (Namespace) - { - case ns_hidden: - memset(lump->ShortName, 0, sizeof(lump->ShortName)); - break; - - case ns_sprites: - case ns_voxels: - case ns_hires: - // Since '\' can't be used as a file name's part inside a ZIP - // we have to work around this for sprites because it is a valid - // frame character. - for (auto& c : lump->ShortName) - { - if (c == '^') c = '\\'; - } - break; - } - } - } -} - -//========================================================================== -// -// -// -//========================================================================== - -bool FileSystem::InitFiles(std::vector& filenames, FileSys::FileSystemFilterInfo* filter, FileSys::FileSystemMessageFunc Printf, bool allowduplicates) -{ - if (!Super::InitFiles(filenames, filter, Printf, allowduplicates)) return false; - files.Resize(GetFileCount()); - memset(files.Data(), 0, sizeof(files[0]) * files.size()); - int numfiles = GetFileCount(); - for (int i = 0; i < numfiles; i++) - { - SetupName(i); - } - - int numresfiles = GetContainerCount(); - for (int i = 0; i < numresfiles; i++) - { - SetupNamespace(i, Printf); - } - return true; -} - -//========================================================================== -// -// CheckNumForName -// -// Returns -1 if name not found. The version with a third parameter will -// look exclusively in the specified wad for the lump. -// -// [RH] Changed to use hash lookup ala BOOM instead of a linear search -// and namespace parameter -//========================================================================== - -int FileSystem::CheckNumForName(const char* name, int space) const -{ - char uname[9]; - uint32_t i; - - if (name == nullptr) - { - return -1; - } - - // Let's not search for names that are longer than 8 characters and contain path separators - // They are almost certainly full path names passed to this function. - if (strlen(name) > 8 && strpbrk(name, "/.")) - { - return -1; - } - - UpperCopy(uname, name); - i = files[FileSys::MakeHash(uname, 8) % files.Size()].HashFirst; - - while (i != NULL_INDEX) - { - auto& lump = files[i]; - - if (!memcmp(lump.ShortName, uname, 8)) - { - if (lump.Namespace == space) break; - // If the lump is from one of the special namespaces exclusive to Zips - // the check has to be done differently: - // If we find a lump with this name in the global namespace that does not come - // from a Zip return that. WADs don't know these namespaces and single lumps must - // work as well. - if (space > ns_specialzipdirectory && lump.Namespace == ns_global && !(lump.Flags & LUMPF_FULLPATH)) - break; - } - i = lump.HashNext; - } - - return i != NULL_INDEX ? i : -1; -} - -int FileSystem::CheckNumForName(const char* name, int space, int rfnum, bool exact) const -{ - char uname[9]; - uint32_t i; - - if (rfnum < 0) - { - return CheckNumForName(name, space); - } - - UpperCopy(uname, name); - i = files[FileSys::MakeHash(uname, 8) % files.Size()].HashFirst; - - // If exact is true if will only find lumps in the same WAD, otherwise - // also those in earlier WADs. - - while (i != NULL_INDEX && - (memcmp(files[i].ShortName, uname, 8) || files[i].Namespace != space || - (exact ? (GetFileContainer(i) != rfnum) : (GetFileContainer(i) > rfnum)))) - { - i = files[i].HashNext; - } - - return i != NULL_INDEX ? i : -1; -} - -//========================================================================== -// -// GetNumForName -// -// Calls CheckNumForName, but bombs out if not found. -// -//========================================================================== - -int FileSystem::GetNumForName(const char* name, int space) const -{ - int i; - - i = CheckNumForName(name, space); - - if (i == -1) - throw FileSys::FileSystemException("GetNumForName: %s not found!", name); - - return i; -} - - - -//========================================================================== -// -// returns a modifiable pointer to the short name -// -// should only be called before the hash chains are set up. -// If done later this needs rehashing. -// -// This is for custom setup through postprocessFunc -// -//========================================================================== - -char* FileSystem::GetShortName(int i) -{ - if ((unsigned)i >= files.Size()) - throw FileSys::FileSystemException("GetShortName: Invalid index"); - return files[i].ShortName; -} - -//========================================================================== -// -// W_FindLump -// -// Find a named lump. Specifically allows duplicates for merging of e.g. -// SNDINFO lumps. -// -//========================================================================== - -int FileSystem::FindLump(const char* name, int* lastlump, bool anyns) -{ - if ((size_t)*lastlump >= files.size()) return -1; - char name8[9]; - UpperCopy(name8, name); - - assert(lastlump != nullptr && *lastlump >= 0); - - const int last = (int)files.size(); - - for(int lump = *lastlump; lump < last; lump++) - { - const FileEntry* const lump_p = &files[lump]; - if ((anyns || lump_p->Namespace == ns_global) && !memcmp(lump_p->ShortName, name8, 8)) - { - *lastlump = lump + 1; - return lump; - } - } - - *lastlump = last; - return -1; -} - -//========================================================================== -// -// W_FindLumpMulti -// -// Find a named lump. Specifically allows duplicates for merging of e.g. -// SNDINFO lumps. Returns everything having one of the passed names. -// -//========================================================================== - -int FileSystem::FindLumpMulti(const char** names, int* lastlump, bool anyns, int* nameindex) -{ - assert(lastlump != nullptr && *lastlump >= 0); - - int last = files.Size(); - - for (int lump = *lastlump; lump < last; lump++) - { - auto lump_p = &files[lump]; - if (anyns || lump_p->Namespace == ns_global) - { - for (const char** name = names; *name != nullptr; name++) - { - if (!strnicmp(*name, lump_p->ShortName, 8)) - { - *lastlump = lump + 1; - if (nameindex != nullptr) *nameindex = int(name - names); - return lump; - } - } - } - } - - *lastlump = last; - return -1; -} - -//========================================================================== -// -// This function combines lookup from regular lists and Doom's special one. -// -//========================================================================== - -int FileSystem::CheckNumForAnyName(const char* name, namespace_t namespc) const -{ - if (name != NULL) - { - // Check short names first to avoid interference from short names in the real file system. - if (strlen(name) <= 8 && !strpbrk(name, "./")) - { - return CheckNumForName(name, namespc); - } - - int lookup = Super::FindFile(name, false); - if (lookup >= 0) return lookup; - } - return -1; -} - diff --git a/src/common/engine/filesystem.h b/src/common/engine/filesystem.h index f8a791e7b5..53f4916771 100644 --- a/src/common/engine/filesystem.h +++ b/src/common/engine/filesystem.h @@ -1,129 +1,7 @@ #pragma once #include "fs_filesystem.h" +using FileSys::FileSystem; using FileSys::FResourceFile; -// [RH] Namespaces from BOOM. -// These are needed here in the low level part so that WAD files can be properly set up. -enum namespace_t : int { - ns_hidden = -1, - - ns_global = 0, - ns_sprites, - ns_flats, - ns_colormaps, - ns_acslibrary, - ns_newtextures, - ns_bloodraw, // no longer used - kept for ZScript. - ns_bloodsfx, // no longer used - kept for ZScript. - ns_bloodmisc, // no longer used - kept for ZScript. - ns_strifevoices, - ns_hires, - ns_voxels, - ns_maybeflat, - - // These namespaces are only used to mark lumps in special subdirectories - // so that their contents doesn't interfere with the global namespace. - // searching for data in these namespaces works differently for lumps coming - // from Zips or other files. - ns_specialzipdirectory, - ns_sounds, - ns_patches, - ns_graphics, - ns_music, - - ns_firstskin, -}; - - -// extended class that adds Doom's very special short name lookup to the file system. -class FileSystem : public FileSys::FileSystem -{ -private: - struct FileEntry - { - char ShortName[9]; - uint8_t Namespace; - uint8_t Flags; - uint32_t HashFirst; - uint32_t HashNext; - }; - - const int wadflags = FileSys::FResourceFile::NO_EXTENSIONS | FileSys::FResourceFile::NO_FOLDERS | FileSys::FResourceFile::SHORTNAMES; - const uint32_t NULL_INDEX = 0xffffffff; - - TArray files; - int skin_namespc = ns_firstskin; - - - void Start(FileSys::FileSystemMessageFunc Printf); - void SetupName(int fileindex); - bool IsMarker(int lump, const char* marker) noexcept; - void SetNamespace(int filenum, const char* startmarker, const char* endmarker, namespace_t space, FileSys::FileSystemMessageFunc Printf, bool flathack = false); - void SkinHack(int filenum, FileSys::FileSystemMessageFunc Printf); - void SetupNamespace(int filenum, FileSys::FileSystemMessageFunc Printf); - - using Super = FileSys::FileSystem; - -public: - enum - { - LUMPF_MAYBEFLAT = 1, - LUMPF_FULLPATH = 2, - }; - - bool InitFiles(std::vector& filenames, FileSys::FileSystemFilterInfo* filter = nullptr, FileSys::FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false) override; - void InitHashChains() override; - - int CheckNumForAnyName(const char* cname, namespace_t namespc = ns_global) const; - - int CheckNumForName(const char* name, int namespc) const; - int CheckNumForName(const char* name, int namespc, int wadfile, bool exact = true) const; - int GetNumForName(const char* name, int namespc) const; - - inline int CheckNumForName(const uint8_t* name) const { return CheckNumForName((const char*)name, ns_global); } - inline int CheckNumForName(const char* name) const { return CheckNumForName(name, ns_global); } - inline int CheckNumForName(const uint8_t* name, int ns) const { return CheckNumForName((const char*)name, ns); } - inline int GetNumForName(const char* name) const { return GetNumForName(name, ns_global); } - inline int GetNumForName(const uint8_t* name) const { return GetNumForName((const char*)name); } - inline int GetNumForName(const uint8_t* name, int ns) const { return GetNumForName((const char*)name, ns); } - - int FindLump(const char* name, int* lastlump, bool anyns = false); // [RH] Find lumps with duplication - int FindLumpMulti(const char** names, int* lastlump, bool anyns = false, int* nameindex = nullptr); // same with multiple possible names - - bool CheckFileName(int lump, const char* name) const noexcept - { - if ((size_t)lump >= files.size()) - return false; - - return !strnicmp(files[lump].ShortName, name, 8); - } - - const char* GetFileShortName(int lump) const noexcept - { - if ((size_t)lump >= files.size()) - return nullptr; - else - return files[lump].ShortName; - } - - int GetFileNamespace(int lump) const noexcept - { - if ((size_t)lump >= files.size()) - return ns_global; - else - return files[lump].Namespace; - } - - void SetFileNamespace(int lump, int ns) noexcept - { - if ((size_t)lump < files.size()) files[lump].Namespace = ns; - } - - // This is only for code that wants to edit the names before the game starts. - char* GetShortName(int i); - -}; - -inline FileSystem fileSystem; - +inline FileSys::FileSystem fileSystem; diff --git a/src/common/engine/sc_man.cpp b/src/common/engine/sc_man.cpp index 5af08fa570..ac7b4799f7 100644 --- a/src/common/engine/sc_man.cpp +++ b/src/common/engine/sc_man.cpp @@ -124,7 +124,7 @@ FScanner::FScanner(int lumpnum, TMap* extsymbols) : symbols(extsy void FScanner::Open (const char *name) { - int lump = fileSystem.CheckNumForAnyName(name); + int lump = fileSystem.CheckNumForFullName(name, true); if (lump == -1) { I_Error("Could not find script lump '%s'\n", name); diff --git a/src/common/engine/serializer.cpp b/src/common/engine/serializer.cpp index 5c5c9f5661..97ded1adf8 100644 --- a/src/common/engine/serializer.cpp +++ b/src/common/engine/serializer.cpp @@ -58,6 +58,8 @@ #include "vm.h" #include "i_interface.h" +using namespace FileSys; + extern DObject *WP_NOCHANGE; bool save_full = false; // for testing. Should be removed afterward. @@ -153,13 +155,13 @@ bool FSerializer::OpenReader(const char *buffer, size_t length) // //========================================================================== -bool FSerializer::OpenReader(FileSys::FCompressedBuffer *input) +bool FSerializer::OpenReader(FCompressedBuffer *input) { if (input->mSize <= 0 || input->mBuffer == nullptr) return false; if (w != nullptr || r != nullptr) return false; mErrors = 0; - if (input->mMethod == FileSys::METHOD_STORED) + if (input->mMethod == METHOD_STORED) { r = new FReader((char*)input->mBuffer, input->mSize); } @@ -783,10 +785,10 @@ const char *FSerializer::GetOutput(unsigned *len) // //========================================================================== -FileSys::FCompressedBuffer FSerializer::GetCompressedOutput() +FCompressedBuffer FSerializer::GetCompressedOutput() { if (isReading()) return{ 0,0,0,0,0,nullptr }; - FileSys::FCompressedBuffer buff; + FCompressedBuffer buff; WriteObjects(); EndObject(); buff.filename = nullptr; @@ -825,7 +827,7 @@ FileSys::FCompressedBuffer FSerializer::GetCompressedOutput() if (err == Z_OK) { buff.mBuffer = new char[buff.mCompressedSize]; - buff.mMethod = FileSys::METHOD_DEFLATE; + buff.mMethod = METHOD_DEFLATE; memcpy(buff.mBuffer, compressbuf, buff.mCompressedSize); delete[] compressbuf; return buff; @@ -834,7 +836,7 @@ FileSys::FCompressedBuffer FSerializer::GetCompressedOutput() error: memcpy(compressbuf, w->mOutString.GetString(), buff.mSize + 1); buff.mCompressedSize = buff.mSize; - buff.mMethod = FileSys::METHOD_STORED; + buff.mMethod = METHOD_STORED; return buff; } @@ -1179,7 +1181,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FTextureID &value, FTe if (TexMan.GetLinkedTexture(lump) == pic) { - name = fileSystem.GetFileName(lump); + name = fileSystem.GetFileFullName(lump); } else { diff --git a/src/common/engine/stringtable.cpp b/src/common/engine/stringtable.cpp index d748157dba..d9d739b57a 100644 --- a/src/common/engine/stringtable.cpp +++ b/src/common/engine/stringtable.cpp @@ -47,7 +47,7 @@ // //========================================================================== -void FStringTable::LoadStrings (FileSystem& fileSystem, const char *language) +void FStringTable::LoadStrings (FileSys::FileSystem& fileSystem, const char *language) { int lastlump, lump; diff --git a/src/common/engine/stringtable.h b/src/common/engine/stringtable.h index 193045d9fb..181d8c7f39 100644 --- a/src/common/engine/stringtable.h +++ b/src/common/engine/stringtable.h @@ -84,7 +84,7 @@ class FStringTable using LangMap = TMap; using StringMacroMap = TMap; - void LoadStrings(FileSystem& fileSystem, const char *language); + void LoadStrings(FileSys::FileSystem& fileSystem, const char *language); void UpdateLanguage(const char* language); StringMap GetDefaultStrings() { return allStrings[default_table]; } // Dehacked needs these for comparison void SetOverrideStrings(StringMap & map) diff --git a/src/common/filesystem/include/fs_filesystem.h b/src/common/filesystem/include/fs_filesystem.h index 8747c24998..e817bc12d7 100644 --- a/src/common/filesystem/include/fs_filesystem.h +++ b/src/common/filesystem/include/fs_filesystem.h @@ -13,6 +13,15 @@ namespace FileSys { +union LumpShortName +{ + char String[9]; + + uint32_t dword; // These are for accessing the first 4 or 8 chars of + uint64_t qword; // Name as a unit without breaking strict aliasing rules +}; + + struct FolderEntry { const char *name; @@ -23,34 +32,46 @@ class FileSystem { public: FileSystem(); - virtual ~FileSystem (); - // do not copy! - FileSystem(const FileSystem& other) = delete; - FileSystem& operator =(const FileSystem& other) = delete; + ~FileSystem (); - bool Initialize(std::vector& filenames, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false); + // The wadnum for the IWAD + int GetIwadNum() { return IwadIndex; } + void SetIwadNum(int x) { IwadIndex = x; } - // The container for the IWAD - int GetBaseNum() { return BaseIndex; } - void SetBaseNum(int x) { BaseIndex = x; } + int GetMaxIwadNum() { return MaxIwadIndex; } + void SetMaxIwadNum(int x) { MaxIwadIndex = x; } - int GetMaxBaseNum() { return MaxBaseIndex; } - void SetMaxBaseNum(int x) { MaxBaseIndex = x; } - - int CheckIfContainerLoaded (const char *name) noexcept; + bool InitSingleFile(const char *filename, FileSystemMessageFunc Printf = nullptr); + bool InitMultipleFiles (std::vector& filenames, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false); + void AddFile (const char *filename, FileReader *wadinfo, LumpFilterInfo* filter, FileSystemMessageFunc Printf); + int CheckIfResourceFileLoaded (const char *name) noexcept; void AddAdditionalFile(const char* filename, FileReader* wadinfo = NULL) {} - const char *GetContainerName (int container) const noexcept; - const char *GetContainerFullName (int container) const noexcept; + const char *GetResourceFileName (int filenum) const noexcept; + const char *GetResourceFileFullName (int wadnum) const noexcept; + + int GetFirstEntry(int wadnum) const noexcept; + int GetLastEntry(int wadnum) const noexcept; + int GetEntryCount(int wadnum) const noexcept; - int GetFirstEntry(int container) const noexcept; - int GetLastEntry(int container) const noexcept; - int GetEntryCount(int container) const noexcept; - int GetContainerFlags(int container) const noexcept; + int CheckNumForName (const char *name, int namespc) const; + int CheckNumForName (const char *name, int namespc, int wadfile, bool exact = true) const; + int GetNumForName (const char *name, int namespc) const; - int FindFile (const char *cname, bool ignoreext = false) const; - int GetFileInContainer (const char *name, int wadfile) const; - int GetFile (const char *name) const; + inline int CheckNumForName (const uint8_t *name) const { return CheckNumForName ((const char *)name, ns_global); } + inline int CheckNumForName (const char *name) const { return CheckNumForName (name, ns_global); } + inline int CheckNumForName (const uint8_t *name, int ns) const { return CheckNumForName ((const char *)name, ns); } + inline int GetNumForName (const char *name) const { return GetNumForName (name, ns_global); } + inline int GetNumForName (const uint8_t *name) const { return GetNumForName ((const char *)name); } + inline int GetNumForName (const uint8_t *name, int ns) const { return GetNumForName ((const char *)name, ns); } + + int CheckNumForFullName (const char *cname, bool trynormal = false, int namespc = ns_global, bool ignoreext = false) const; + int CheckNumForFullName (const char *name, int wadfile) const; + int GetNumForFullName (const char *name) const; + int FindFile(const char* name) const + { + return CheckNumForFullName(name); + } bool FileExists(const char* name) const { @@ -62,106 +83,101 @@ class FileSystem return FindFile(name.c_str()) >= 0; } + LumpShortName& GetShortName(int i); // may only be called before the hash chains are set up. void RenameFile(int num, const char* fn); bool CreatePathlessCopy(const char* name, int id, int flags); - void ReadFile (int filenum, void *dest); + void ReadFile (int lump, void *dest); // These should only be used if the file data really needs padding. - FileData ReadFile (int filenum); - FileData ReadFileFullName(const char* name) { return ReadFile(GetFile(name)); } + FileData ReadFile (int lump); + FileData ReadFile (const char *name) { return ReadFile (GetNumForName (name)); } + FileData ReadFileFullName(const char* name) { return ReadFile(GetNumForFullName(name)); } - FileReader OpenFileReader(int filenum, int readertype, int readerflags); // opens a reader that redirects to the containing file's one. + FileReader OpenFileReader(int lump, int readertype, int readerflags); // opens a reader that redirects to the containing file's one. FileReader OpenFileReader(const char* name); FileReader ReopenFileReader(const char* name, bool alwayscache = false); - FileReader OpenFileReader(int filenum) + FileReader OpenFileReader(int lump) { - return OpenFileReader(filenum, READER_SHARED, READERFLAG_SEEKABLE); + return OpenFileReader(lump, READER_SHARED, READERFLAG_SEEKABLE); } - FileReader ReopenFileReader(int filenum, bool alwayscache = false) + FileReader ReopenFileReader(int lump, bool alwayscache = false) { - return OpenFileReader(filenum, alwayscache ? READER_CACHED : READER_NEW, READERFLAG_SEEKABLE); + return OpenFileReader(lump, alwayscache ? READER_CACHED : READER_NEW, READERFLAG_SEEKABLE); } + int FindLump (const char *name, int *lastlump, bool anyns=false); // [RH] Find lumps with duplication + int FindLumpMulti (const char **names, int *lastlump, bool anyns = false, int *nameindex = NULL); // same with multiple possible names int FindLumpFullName(const char* name, int* lastlump, bool noext = false); + bool CheckFileName (int lump, const char *name); // [RH] True if lump's name == name int FindFileWithExtensions(const char* name, const char* const* exts, int count) const; int FindResource(int resid, const char* type, int filenum = -1) const noexcept; int GetResource(int resid, const char* type, int filenum = -1) const; - ptrdiff_t FileLength(int filenum) const; - int GetFileFlags (int filenum); // Return the flags for this filenum - const char* GetFileName(int filenum) const; // Gets uninterpreted name from the FResourceFile - std::string GetFileFullPath (int filenum) const; // [RH] Returns wad's name + filenum's full name - int GetFileContainer (int filenum) const; - // [RH] Returns container for a specified filenum - int GetResourceId(int filenum) const; // Returns the RFF index number for this filenum - const char* GetResourceType(int filenum) const; + static uint32_t LumpNameHash (const char *name); // [RH] Create hash key from an 8-char name + + ptrdiff_t FileLength (int lump) const; + int GetFileFlags (int lump); // Return the flags for this lump + const char* GetFileShortName(int lump) const; + const char *GetFileFullName (int lump, bool returnshort = true) const; // [RH] Returns the lump's full name + std::string GetFileFullPath (int lump) const; // [RH] Returns wad's name + lump's full name + int GetFileContainer (int lump) const; // [RH] Returns wadnum for a specified lump + int GetFileNamespace (int lump) const; // [RH] Returns the namespace a lump belongs to + void SetFileNamespace(int lump, int ns); + int GetResourceId(int lump) const; // Returns the RFF index number for this lump + const char* GetResourceType(int lump) const; + bool CheckFileName (int lump, const char *name) const; // [RH] Returns true if the names match unsigned GetFilesInFolder(const char *path, std::vector &result, bool atomic) const; - int GetFileCount() const + int GetNumEntries() const { return NumEntries; } - int GetContainerCount() const + int GetNumWads() const { return (int)Files.size(); } int AddFromBuffer(const char* name, char* data, int size, int id, int flags); - FileReader* GetFileReader(int container); // Gets a FileReader object to the entire WAD + FileReader* GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD + void InitHashChains(); protected: struct LumpRecord; - const uint32_t NULL_INDEX = 0xffffffff; std::vector Files; std::vector FileInfo; std::vector Hashes; // one allocation for all hash lists. + uint32_t *FirstLumpIndex = nullptr; // [RH] Hashing stuff moved out of lumpinfo structure + uint32_t *NextLumpIndex = nullptr; - uint32_t *FirstFileIndex_FullName = nullptr; // The same information for fully qualified paths from .zips - uint32_t *NextFileIndex_FullName = nullptr; + uint32_t *FirstLumpIndex_FullName = nullptr; // The same information for fully qualified paths from .zips + uint32_t *NextLumpIndex_FullName = nullptr; - uint32_t *FirstFileIndex_NoExt = nullptr; // The same information for fully qualified paths from .zips - uint32_t *NextFileIndex_NoExt = nullptr; + uint32_t *FirstLumpIndex_NoExt = nullptr; // The same information for fully qualified paths from .zips + uint32_t *NextLumpIndex_NoExt = nullptr; - uint32_t* FirstFileIndex_ResId = nullptr; // The same information for fully qualified paths from .zips - uint32_t* NextFileIndex_ResId = nullptr; + uint32_t* FirstLumpIndex_ResId = nullptr; // The same information for fully qualified paths from .zips + uint32_t* NextLumpIndex_ResId = nullptr; uint32_t NumEntries = 0; // Not necessarily the same as FileInfo.Size() uint32_t NumWads = 0; - int BaseIndex = -1; - int MaxBaseIndex = -1; + int IwadIndex = -1; + int MaxIwadIndex = -1; StringPool* stringpool = nullptr; private: void DeleteAll(); - void MoveFilesInFolder(const char *); - void AddFile(const char* filename, FileReader* wadinfo, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf); -protected: - - // These two functions must be overridden by subclasses which want to extend the file system. - virtual bool InitFiles(std::vector& filenames, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false); -public: - virtual void InitHashChains(); + void MoveLumpsInFolder(const char *); }; -//djb2 hash algorithm with case insensitivity hack -inline static uint32_t MakeHash(const char* str, size_t length = SIZE_MAX) -{ - uint32_t hash = 5381; - uint32_t c; - while (length-- > 0 && (c = *str++)) hash = hash * 33 + (c | 32); - return hash; -} - - } \ No newline at end of file diff --git a/src/common/filesystem/include/resourcefile.h b/src/common/filesystem/include/resourcefile.h index 982579112f..a23914444e 100644 --- a/src/common/filesystem/include/resourcefile.h +++ b/src/common/filesystem/include/resourcefile.h @@ -16,7 +16,7 @@ std::string ExtractBaseName(const char* path, bool include_extension = false); void strReplace(std::string& str, const char* from, const char* to); // user context in which the file system gets opened. This also contains a few callbacks to avoid direct dependencies on the engine. -struct FileSystemFilterInfo +struct LumpFilterInfo { std::vector gameTypeFilter; // this can contain multiple entries @@ -45,10 +45,41 @@ using FileSystemMessageFunc = int(*)(FSMessageLevel msglevel, const char* format class FResourceFile; +// [RH] Namespaces from BOOM. +// These are needed here in the low level part so that WAD files can be properly set up. +typedef enum { + ns_hidden = -1, + + ns_global = 0, + ns_sprites, + ns_flats, + ns_colormaps, + ns_acslibrary, + ns_newtextures, + ns_bloodraw, // no longer used - kept for ZScript. + ns_bloodsfx, // no longer used - kept for ZScript. + ns_bloodmisc, // no longer used - kept for ZScript. + ns_strifevoices, + ns_hires, + ns_voxels, + + // These namespaces are only used to mark lumps in special subdirectories + // so that their contents doesn't interfere with the global namespace. + // searching for data in these namespaces works differently for lumps coming + // from Zips or other files. + ns_specialzipdirectory, + ns_sounds, + ns_patches, + ns_graphics, + ns_music, + + ns_firstskin, +} namespace_t; enum ELumpFlags { - RESFF_FULLPATH = 2, // contains a full path. + RESFF_MAYBEFLAT = 1, // might be a flat inside a WAD outside F_START/END + RESFF_FULLPATH = 2, // contains a full path. This will trigger extended namespace checks when looking up short names. RESFF_EMBEDDED = 4, // marks an embedded resource file for later processing. RESFF_SHORTNAME = 8, // the stored name is a short extension-less name RESFF_COMPRESSED = 16, // compressed or encrypted, i.e. cannot be read with the container file's reader. @@ -69,10 +100,11 @@ struct FResourceEntry size_t CompressedSize; const char* FileName; size_t Position; - int ResourceID; // Only Blood RFF uses this natively. + int ResourceID; uint32_t CRC32; uint16_t Flags; uint16_t Method; + int16_t Namespace; }; void SetMainThread(); @@ -80,25 +112,17 @@ void SetMainThread(); class FResourceFile { public: - enum - { - // descibes which kind of limitations this file type has. - NO_FOLDERS = 1, // no paths - only one rpot folder (e.g. Build GRP, Blood RFF, Descent HOG - NO_EXTENSIONS = 2, // no extensions for file names (e.g. Doom WADs.) - SHORTNAMES = 4, // Name is (at most) 8.3 DOS ASCII format, (8.0 in case of WAD) - }; - FResourceFile(const char* filename, StringPool* sp, int flags); - FResourceFile(const char* filename, FileReader& r, StringPool* sp, int flags); - const char* NormalizeFileName(const char* fn, int fallbackcp = 0, bool allowbackslash = false); + FResourceFile(const char* filename, StringPool* sp); + FResourceFile(const char* filename, FileReader& r, StringPool* sp); + const char* NormalizeFileName(const char* fn, int fallbackcp = 0); FResourceEntry* AllocateEntries(int count); void GenerateHash(); - void PostProcessArchive(FileSystemFilterInfo* filter); + void PostProcessArchive(LumpFilterInfo* filter); protected: FileReader Reader; const char* FileName; FResourceEntry* Entries = nullptr; uint32_t NumLumps; - int flags = 0; char Hash[48]; StringPool* stringpool; @@ -108,7 +132,7 @@ class FResourceFile Entries[entry].Flags &= ~RESFF_NEEDFILESTART; } bool IsFileInFolder(const char* const resPath); - void CheckEmbedded(uint32_t entry, FileSystemFilterInfo* lfi); + void CheckEmbedded(uint32_t entry, LumpFilterInfo* lfi); private: uint32_t FirstLump; @@ -116,20 +140,19 @@ class FResourceFile int FilterLumps(const std::string& filtername, uint32_t max); bool FindPrefixRange(const char* filter, uint32_t max, uint32_t &start, uint32_t &end); void JunkLeftoverFilters(uint32_t max); - void FindCommonFolder(FileSystemFilterInfo* filter); - static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); + void FindCommonFolder(LumpFilterInfo* filter); + static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); public: - static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); - static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); - static FResourceFile *OpenDirectory(const char *filename, FileSystemFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); + static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); + static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); + static FResourceFile *OpenDirectory(const char *filename, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, StringPool* sp = nullptr); virtual ~FResourceFile(); // If this FResourceFile represents a directory, the Reader object is not usable so don't return it. FileReader *GetContainerReader() { return Reader.isOpen()? &Reader : nullptr; } const char* GetFileName() const { return FileName; } uint32_t GetFirstEntry() const { return FirstLump; } - int GetFlags() const noexcept { return flags; } - void SetFirstFile(uint32_t f) { FirstLump = f; } + void SetFirstLump(uint32_t f) { FirstLump = f; } const char* GetHash() const { return Hash; } int EntryCount() const { return NumLumps; } @@ -152,6 +175,11 @@ class FResourceFile return (entry < NumLumps) ? Entries[entry].Flags : 0; } + int GetEntryNamespace(uint32_t entry) + { + return (entry < NumLumps) ? Entries[entry].Namespace : (int)ns_hidden; + } + int GetEntryResourceID(uint32_t entry) { return (entry < NumLumps) ? Entries[entry].ResourceID : -1; diff --git a/src/common/filesystem/source/file_7z.cpp b/src/common/filesystem/source/file_7z.cpp index 6a5e135e9f..21d6049e37 100644 --- a/src/common/filesystem/source/file_7z.cpp +++ b/src/common/filesystem/source/file_7z.cpp @@ -177,7 +177,7 @@ class F7ZFile : public FResourceFile public: F7ZFile(const char * filename, FileReader &filer, StringPool* sp); - bool Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf); + bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); virtual ~F7ZFile(); FileData Read(uint32_t entry) override; FileReader GetEntryReader(uint32_t entry, int, int) override; @@ -192,7 +192,7 @@ class F7ZFile : public FResourceFile //========================================================================== F7ZFile::F7ZFile(const char * filename, FileReader &filer, StringPool* sp) - : FResourceFile(filename, filer, sp, 0) + : FResourceFile(filename, filer, sp) { Archive = nullptr; } @@ -204,7 +204,7 @@ F7ZFile::F7ZFile(const char * filename, FileReader &filer, StringPool* sp) // //========================================================================== -bool F7ZFile::Open(FileSystemFilterInfo *filter, FileSystemMessageFunc Printf) +bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf) { Archive = new C7zArchive(Reader); int skipped = 0; @@ -268,6 +268,7 @@ bool F7ZFile::Open(FileSystemFilterInfo *filter, FileSystemMessageFunc Printf) Entries[j].Length = SzArEx_GetFileSize(archPtr, i); Entries[j].Flags = RESFF_FULLPATH|RESFF_COMPRESSED; Entries[j].ResourceID = -1; + Entries[j].Namespace = ns_global; Entries[j].Method = METHOD_INVALID; Entries[j].Position = i; j++; @@ -350,7 +351,7 @@ FileReader F7ZFile::GetEntryReader(uint32_t entry, int, int) // //========================================================================== -FResourceFile *Check7Z(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[k7zSignatureSize]; diff --git a/src/common/filesystem/source/file_directory.cpp b/src/common/filesystem/source/file_directory.cpp index 40b4df2f93..ca87fd9ea0 100644 --- a/src/common/filesystem/source/file_directory.cpp +++ b/src/common/filesystem/source/file_directory.cpp @@ -57,11 +57,11 @@ class FDirectory : public FResourceFile const char** SystemFilePath; - int AddDirectory(const char* dirpath, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf); + int AddDirectory(const char* dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf); public: FDirectory(const char * dirname, StringPool* sp, bool nosubdirflag = false); - bool Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf); + bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); FileReader GetEntryReader(uint32_t entry, int, int) override; }; @@ -74,7 +74,7 @@ class FDirectory : public FResourceFile //========================================================================== FDirectory::FDirectory(const char * directory, StringPool* sp, bool nosubdirflag) - : FResourceFile("", sp, 0), nosubdir(nosubdirflag) + : FResourceFile("", sp), nosubdir(nosubdirflag) { auto fn = FS_FullPath(directory); if (fn.back() != '/') fn += '/'; @@ -87,7 +87,7 @@ FDirectory::FDirectory(const char * directory, StringPool* sp, bool nosubdirflag // //========================================================================== -int FDirectory::AddDirectory(const char *dirpath, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf) +int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { int count = 0; @@ -141,6 +141,7 @@ int FDirectory::AddDirectory(const char *dirpath, FileSystemFilterInfo* filter, Entries[count].Flags = RESFF_FULLPATH; Entries[count].ResourceID = -1; Entries[count].Method = METHOD_STORED; + Entries[count].Namespace = ns_global; Entries[count].Position = count; count++; } @@ -156,7 +157,7 @@ int FDirectory::AddDirectory(const char *dirpath, FileSystemFilterInfo* filter, // //========================================================================== -bool FDirectory::Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf) +bool FDirectory::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf) { NumLumps = AddDirectory(FileName, filter, Printf); PostProcessArchive(filter); @@ -192,7 +193,7 @@ FileReader FDirectory::GetEntryReader(uint32_t entry, int readertype, int) // //========================================================================== -FResourceFile *CheckDir(const char *filename, bool nosubdirflag, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckDir(const char *filename, bool nosubdirflag, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { auto rf = new FDirectory(filename, sp, nosubdirflag); if (rf->Open(filter, Printf)) return rf; diff --git a/src/common/filesystem/source/file_grp.cpp b/src/common/filesystem/source/file_grp.cpp index 25f79c6ec5..57206b4b10 100644 --- a/src/common/filesystem/source/file_grp.cpp +++ b/src/common/filesystem/source/file_grp.cpp @@ -71,7 +71,7 @@ struct GrpLump // //========================================================================== -static bool OpenGrp(FResourceFile* file, FileSystemFilterInfo* filter) +static bool OpenGrp(FResourceFile* file, LumpFilterInfo* filter) { GrpHeader header; @@ -91,6 +91,7 @@ static bool OpenGrp(FResourceFile* file, FileSystemFilterInfo* filter) Entries[i].CompressedSize = Entries[i].Length = LittleLong(fileinfo[i].Size); Position += fileinfo[i].Size; Entries[i].Flags = 0; + Entries[i].Namespace = ns_global; fileinfo[i].NameWithZero[12] = '\0'; // Be sure filename is null-terminated Entries[i].ResourceID = -1; Entries[i].Method = METHOD_STORED; @@ -108,7 +109,7 @@ static bool OpenGrp(FResourceFile* file, FileSystemFilterInfo* filter) // //========================================================================== -FResourceFile *CheckGRP(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[12]; @@ -119,7 +120,7 @@ FResourceFile *CheckGRP(const char *filename, FileReader &file, FileSystemFilter file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "KenSilverman", 12)) { - auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES); + auto rf = new FResourceFile(filename, file, sp); if (OpenGrp(rf, filter)) return rf; file = rf->Destroy(); } diff --git a/src/common/filesystem/source/file_hog.cpp b/src/common/filesystem/source/file_hog.cpp index 0ed4fa7ce0..d12f7e2d86 100644 --- a/src/common/filesystem/source/file_hog.cpp +++ b/src/common/filesystem/source/file_hog.cpp @@ -44,7 +44,7 @@ namespace FileSys { -static bool OpenHog(FResourceFile* rf, FileSystemFilterInfo* filter) +static bool OpenHog(FResourceFile* rf, LumpFilterInfo* filter) { auto Reader = rf->GetContainerReader(); FileReader::Size length = Reader->GetLength(); @@ -66,6 +66,7 @@ static bool OpenHog(FResourceFile* rf, FileSystemFilterInfo* filter) Entry.CompressedSize = Entry.Length = elength; Entry.Flags = 0; Entry.CRC32 = 0; + Entry.Namespace = ns_global; Entry.ResourceID = -1; Entry.Method = METHOD_STORED; Entry.FileName = rf->NormalizeFileName(name); @@ -85,7 +86,7 @@ static bool OpenHog(FResourceFile* rf, FileSystemFilterInfo* filter) // //========================================================================== -FResourceFile* CheckHog(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile* CheckHog(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[3]; @@ -95,7 +96,7 @@ FResourceFile* CheckHog(const char* filename, FileReader& file, FileSystemFilter file.Read(&head, 3); if (!memcmp(head, "DHF", 3)) { - auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES); + auto rf = new FResourceFile(filename, file, sp); if (OpenHog(rf, filter)) return rf; file = rf->Destroy(); } diff --git a/src/common/filesystem/source/file_hog2.cpp b/src/common/filesystem/source/file_hog2.cpp deleted file mode 100644 index 10cc327cc3..0000000000 --- a/src/common/filesystem/source/file_hog2.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* -** file_hog.cpp -** -** reads Descent 3 .hog2 files -** -**--------------------------------------------------------------------------- -** Copyright 2024 Christoph Oelckers -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -** -*/ - - -#include "resourcefile.h" -#include "fs_swap.h" - -namespace FileSys { - using namespace byteswap; - - - -static bool OpenHog2(FResourceFile* rf, FileSystemFilterInfo* filter) -{ - auto Reader = rf->GetContainerReader(); - FileReader::Size length = Reader->GetLength(); - - uint32_t numfiles = Reader->ReadUInt32(); - uint32_t offset = Reader->ReadUInt32(); // offset to first file (end of file list) - Reader->Seek(56, FileReader::SeekEnd); // filled with FF - auto Entries = rf->AllocateEntries((int)numfiles); - - for(uint32_t i = 0; i < numfiles; i++) - { - char name[37]; - Reader->Read(name, 36); - name[36] = 0; - Reader->ReadUInt32(); - uint32_t size = Reader->ReadUInt32();; - Reader->ReadUInt32(); - - FResourceEntry& Entry = Entries[i]; - Entry.Position = offset; - Entry.CompressedSize = Entry.Length = size; - Entry.Flags = RESFF_FULLPATH; - Entry.CRC32 = 0; - Entry.ResourceID = -1; - Entry.Method = METHOD_STORED; - Entry.FileName = rf->NormalizeFileName(name); - offset += size; - } - rf->GenerateHash(); - return true; -} - - -//========================================================================== -// -// File open -// -//========================================================================== - -FResourceFile* CheckHog2(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) -{ - char head[4]; - - if (file.GetLength() >= 68) - { - file.Seek(0, FileReader::SeekSet); - file.Read(&head, 4); - if (!memcmp(head, "HOG2", 4)) - { - auto rf = new FResourceFile(filename, file, sp, 0); - if (OpenHog2(rf, filter)) return rf; - file = rf->Destroy(); - } - file.Seek(0, FileReader::SeekSet); - } - return nullptr; -} - - -} - diff --git a/src/common/filesystem/source/file_lump.cpp b/src/common/filesystem/source/file_lump.cpp index 37dee28bd0..b01d46b5d3 100644 --- a/src/common/filesystem/source/file_lump.cpp +++ b/src/common/filesystem/source/file_lump.cpp @@ -41,10 +41,11 @@ namespace FileSys { // //========================================================================== -static bool OpenLump(FResourceFile* file, FileSystemFilterInfo*) +static bool OpenLump(FResourceFile* file, LumpFilterInfo*) { auto Entries = file->AllocateEntries(1); Entries[0].FileName = file->NormalizeFileName(ExtractBaseName(file->GetFileName(), true).c_str()); + Entries[0].Namespace = ns_global; Entries[0].ResourceID = -1; Entries[0].Position = 0; Entries[0].CompressedSize = Entries[0].Length = file->GetContainerReader()->GetLength(); @@ -59,10 +60,10 @@ static bool OpenLump(FResourceFile* file, FileSystemFilterInfo*) // //========================================================================== -FResourceFile *CheckLump(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckLump(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { // always succeeds - auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS); + auto rf = new FResourceFile(filename, file, sp); if (OpenLump(rf, filter)) return rf; file = rf->Destroy(); return NULL; diff --git a/src/common/filesystem/source/file_mvl.cpp b/src/common/filesystem/source/file_mvl.cpp index c9ebf0f8ca..f08db31618 100644 --- a/src/common/filesystem/source/file_mvl.cpp +++ b/src/common/filesystem/source/file_mvl.cpp @@ -43,7 +43,7 @@ namespace FileSys { -static bool OpenMvl(FResourceFile* rf, FileSystemFilterInfo* filter) +static bool OpenMvl(FResourceFile* rf, LumpFilterInfo* filter) { auto Reader = rf->GetContainerReader(); auto count = Reader->ReadUInt32(); @@ -75,7 +75,7 @@ static bool OpenMvl(FResourceFile* rf, FileSystemFilterInfo* filter) // //========================================================================== -FResourceFile* CheckMvl(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile* CheckMvl(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; @@ -85,7 +85,7 @@ FResourceFile* CheckMvl(const char* filename, FileReader& file, FileSystemFilter file.Read(&head, 4); if (!memcmp(head, "DMVL", 4)) { - auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES); + auto rf = new FResourceFile(filename, file, sp); if (OpenMvl(rf, filter)) return rf; file = rf->Destroy(); } diff --git a/src/common/filesystem/source/file_pak.cpp b/src/common/filesystem/source/file_pak.cpp index 84265f2ebe..b66a0f3d99 100644 --- a/src/common/filesystem/source/file_pak.cpp +++ b/src/common/filesystem/source/file_pak.cpp @@ -63,7 +63,7 @@ struct dpackheader_t // //========================================================================== -static bool OpenPak(FResourceFile* file, FileSystemFilterInfo* filter) +static bool OpenPak(FResourceFile* file, LumpFilterInfo* filter) { dpackheader_t header; @@ -82,6 +82,7 @@ static bool OpenPak(FResourceFile* file, FileSystemFilterInfo* filter) Entries[i].Position = LittleLong(fileinfo[i].filepos); Entries[i].CompressedSize = Entries[i].Length = LittleLong(fileinfo[i].filelen); Entries[i].Flags = RESFF_FULLPATH; + Entries[i].Namespace = ns_global; Entries[i].ResourceID = -1; Entries[i].Method = METHOD_STORED; Entries[i].FileName = file->NormalizeFileName(fileinfo[i].name); @@ -98,7 +99,7 @@ static bool OpenPak(FResourceFile* file, FileSystemFilterInfo* filter) // //========================================================================== -FResourceFile *CheckPak(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; @@ -109,7 +110,7 @@ FResourceFile *CheckPak(const char *filename, FileReader &file, FileSystemFilter file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "PACK", 4)) { - auto rf = new FResourceFile(filename, file, sp, 0); + auto rf = new FResourceFile(filename, file, sp); if (OpenPak(rf, filter)) return rf; file = rf->Destroy(); } diff --git a/src/common/filesystem/source/file_rff.cpp b/src/common/filesystem/source/file_rff.cpp index e887b7fd75..673a08ce06 100644 --- a/src/common/filesystem/source/file_rff.cpp +++ b/src/common/filesystem/source/file_rff.cpp @@ -91,7 +91,7 @@ void BloodCrypt (void *data, int key, int len) // //========================================================================== -static bool OpenRFF(FResourceFile* file, FileSystemFilterInfo*) +static bool OpenRFF(FResourceFile* file, LumpFilterInfo*) { RFFLump *lumps; RFFInfo header; @@ -123,6 +123,7 @@ static bool OpenRFF(FResourceFile* file, FileSystemFilterInfo*) Entries[i].Flags = 0; Entries[i].Method = METHOD_STORED; } + Entries[i].Namespace = ns_global; Entries[i].ResourceID = LittleLong(lumps[i].IndexNum); // Rearrange the name and extension to construct the fullname. @@ -149,7 +150,7 @@ static bool OpenRFF(FResourceFile* file, FileSystemFilterInfo*) // //========================================================================== -FResourceFile *CheckRFF(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; @@ -160,7 +161,7 @@ FResourceFile *CheckRFF(const char *filename, FileReader &file, FileSystemFilter file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "RFF\x1a", 4)) { - auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES); + auto rf = new FResourceFile(filename, file, sp); if (OpenRFF(rf, filter)) return rf; file = rf->Destroy(); } diff --git a/src/common/filesystem/source/file_ssi.cpp b/src/common/filesystem/source/file_ssi.cpp index 47c7b53b03..82885c6bb7 100644 --- a/src/common/filesystem/source/file_ssi.cpp +++ b/src/common/filesystem/source/file_ssi.cpp @@ -44,7 +44,7 @@ namespace FileSys { // //========================================================================== -static bool OpenSSI(FResourceFile* file, int version, int EntryCount, FileSystemFilterInfo*) +static bool OpenSSI(FResourceFile* file, int version, int EntryCount, LumpFilterInfo*) { uint32_t NumLumps = EntryCount * 2; auto Entries = file->AllocateEntries(NumLumps); @@ -65,6 +65,7 @@ static bool OpenSSI(FResourceFile* file, int version, int EntryCount, FileSystem Entries[i].Position = j; Entries[i].CompressedSize = Entries[i].Length = flength; Entries[i].Flags = 0; + Entries[i].Namespace = ns_global; Entries[i].Method = METHOD_STORED; Entries[i].ResourceID = -1; Entries[i].FileName = file->NormalizeFileName(fn); @@ -77,6 +78,7 @@ static bool OpenSSI(FResourceFile* file, int version, int EntryCount, FileSystem Entries[i + 1].Position = j; Entries[i + 1].CompressedSize = Entries[i + 1].Length = flength; Entries[i + 1].Flags = 0; + Entries[i + 1].Namespace = ns_global; Entries[i + 1].ResourceID = -1; Entries[i + 1].FileName = file->NormalizeFileName(fn); Entries[i + 1].Method = METHOD_STORED; @@ -97,7 +99,7 @@ static bool OpenSSI(FResourceFile* file, int version, int EntryCount, FileSystem // //========================================================================== -FResourceFile* CheckSSI(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char zerobuf[72]; char buf[72]; @@ -127,7 +129,7 @@ FResourceFile* CheckSSI(const char* filename, FileReader& file, FileSystemFilter { if (!skipstring(70)) return nullptr; } - auto ssi = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::SHORTNAMES); + auto ssi = new FResourceFile(filename, file, sp); if (OpenSSI(ssi, version, numfiles, filter)) return ssi; file = ssi->Destroy(); } diff --git a/src/common/filesystem/source/file_wad.cpp b/src/common/filesystem/source/file_wad.cpp index 3fe736bb02..4f8574b73d 100644 --- a/src/common/filesystem/source/file_wad.cpp +++ b/src/common/filesystem/source/file_wad.cpp @@ -58,22 +58,52 @@ struct wadlump_t char Name[8]; }; +//========================================================================== +// +// Wad file +// +//========================================================================== + +class FWadFile : public FResourceFile +{ + bool IsMarker(int lump, const char *marker); + void SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, FileSystemMessageFunc Printf, bool flathack=false); + void SkinHack (FileSystemMessageFunc Printf); + +public: + FWadFile(const char * filename, FileReader &file, StringPool* sp); + bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); +}; + + +//========================================================================== +// +// FWadFile::FWadFile +// +// Initializes a WAD file +// +//========================================================================== + +FWadFile::FWadFile(const char *filename, FileReader &file, StringPool* sp) + : FResourceFile(filename, file, sp) +{ +} + //========================================================================== // // Open it // //========================================================================== -static bool OpenWAD(FResourceFile* file, FileSystemFilterInfo*, FileSystemMessageFunc Printf) +bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf) { wadinfo_t header; uint32_t InfoTableOfs; bool isBigEndian = false; // Little endian is assumed until proven otherwise - auto Reader = file->GetContainerReader(); - auto wadSize = Reader->GetLength(); + auto wadSize = Reader.GetLength(); - Reader->Read(&header, sizeof(header)); - uint32_t NumLumps = LittleLong(header.NumLumps); + Reader.Read(&header, sizeof(header)); + NumLumps = LittleLong(header.NumLumps); InfoTableOfs = LittleLong(header.InfoTableOfs); // Check to see if the little endian interpretation is valid @@ -87,16 +117,16 @@ static bool OpenWAD(FResourceFile* file, FileSystemFilterInfo*, FileSystemMessag // Check again to detect broken wads if (InfoTableOfs + NumLumps*sizeof(wadlump_t) > (unsigned)wadSize) { - Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", file->GetFileName()); + Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", FileName); return false; } } - Reader->Seek(InfoTableOfs, FileReader::SeekSet); - auto fd = Reader->Read(NumLumps * sizeof(wadlump_t)); + Reader.Seek(InfoTableOfs, FileReader::SeekSet); + auto fd = Reader.Read(NumLumps * sizeof(wadlump_t)); auto fileinfo = (const wadlump_t*)fd.data(); - auto Entries = file->AllocateEntries(NumLumps); + AllocateEntries(NumLumps); for(uint32_t i = 0; i < NumLumps; i++) { @@ -113,17 +143,17 @@ static bool OpenWAD(FResourceFile* file, FileSystemFilterInfo*, FileSystemMessag else if (ishigh > 1) { // This may not end up printing something proper because we do not know what encoding might have been used. - Printf(FSMessageLevel::Warning, "%s: Lump name %.8s contains invalid characters\n", file->GetFileName(), fileinfo[i].Name); - n[0] = 0; + Printf(FSMessageLevel::Warning, "%s: Lump name %.8s contains invalid characters\n", FileName, fileinfo[i].Name); } Entries[i].FileName = nullptr; Entries[i].Position = isBigEndian ? BigLong(fileinfo[i].FilePos) : LittleLong(fileinfo[i].FilePos); Entries[i].CompressedSize = Entries[i].Length = isBigEndian ? BigLong(fileinfo[i].Size) : LittleLong(fileinfo[i].Size); + Entries[i].Namespace = ns_global; Entries[i].Flags = ishigh? RESFF_SHORTNAME | RESFF_COMPRESSED : RESFF_SHORTNAME; Entries[i].Method = ishigh == 1? METHOD_LZSS : METHOD_STORED; - Entries[i].FileName = file->NormalizeFileName(n, 0, true); + Entries[i].FileName = stringpool->Strdup(n); // This doesn't set up the namespace yet. } for (uint32_t i = 0; i < NumLumps; i++) @@ -131,21 +161,250 @@ static bool OpenWAD(FResourceFile* file, FileSystemFilterInfo*, FileSystemMessag if (Entries[i].Method == METHOD_LZSS) { // compressed size is implicit. - Entries[i].CompressedSize = (i == NumLumps - 1 ? Reader->GetLength() : Entries[i + 1].Position) - Entries[i].Position; + Entries[i].CompressedSize = (i == NumLumps - 1 ? Reader.GetLength() : Entries[i + 1].Position) - Entries[i].Position; } } - file->GenerateHash(); // Do this before the lump processing below. + + GenerateHash(); // Do this before the lump processing below. + + SetNamespace("s_start", "s_end", ns_sprites, Printf); + SetNamespace("f_start", "f_end", ns_flats, Printf, true); + SetNamespace("c_start", "c_end", ns_colormaps, Printf); + SetNamespace("a_start", "a_end", ns_acslibrary, Printf); + SetNamespace("tx_start", "tx_end", ns_newtextures, Printf); + SetNamespace("v_start", "v_end", ns_strifevoices, Printf); + SetNamespace("hi_start", "hi_end", ns_hires, Printf); + SetNamespace("vx_start", "vx_end", ns_voxels, Printf); + SkinHack(Printf); + return true; } +//========================================================================== +// +// IsMarker +// +// (from BOOM) +// +//========================================================================== + +inline bool FWadFile::IsMarker(int lump, const char *marker) +{ + if (Entries[lump].FileName[0] == marker[0]) + { + return (!strcmp(Entries[lump].FileName, marker) || + (marker[1] == '_' && !strcmp(Entries[lump].FileName +1, marker))); + } + else return false; +} + +//========================================================================== +// +// SetNameSpace +// +// Sets namespace information for the lumps. It always looks for the first +// x_START and the last x_END lump, except when loading flats. In this case +// F_START may be absent and if that is the case all lumps with a size of +// 4096 will be flagged appropriately. +// +//========================================================================== + +// This class was supposed to be local in the function but GCC +// does not like that. +struct Marker +{ + int markertype; + unsigned int index; +}; + +void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, namespace_t space, FileSystemMessageFunc Printf, bool flathack) +{ + bool warned = false; + int numstartmarkers = 0, numendmarkers = 0; + unsigned int i; + std::vector markers; + + for(i = 0; i < NumLumps; i++) + { + if (IsMarker(i, startmarker)) + { + Marker m = { 0, i }; + markers.push_back(m); + numstartmarkers++; + } + else if (IsMarker(i, endmarker)) + { + Marker m = { 1, i }; + markers.push_back(m); + numendmarkers++; + } + } + + if (numstartmarkers == 0) + { + if (numendmarkers == 0) return; // no markers found + + Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker); + + + if (flathack) + { + // We have found no F_START but one or more F_END markers. + // mark all lumps before the last F_END marker as potential flats. + unsigned int end = markers[markers.size()-1].index; + for(unsigned int ii = 0; ii < end; ii++) + { + if (Entries[ii].Length == 4096) + { + // We can't add this to the flats namespace but + // it needs to be flagged for the texture manager. + Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName, Entries[ii].FileName); + Entries[ii].Flags |= RESFF_MAYBEFLAT; + } + } + } + return; + } + + i = 0; + while (i < markers.size()) + { + int start, end; + if (markers[i].markertype != 0) + { + Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, endmarker, startmarker); + i++; + continue; + } + start = i++; + + // skip over subsequent x_START markers + while (i < markers.size() && markers[i].markertype == 0) + { + Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, startmarker); + i++; + continue; + } + // same for x_END markers + while (i < markers.size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1)) + { + Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName, endmarker); + i++; + continue; + } + // We found a starting marker but no end marker. Ignore this block. + if (i >= markers.size()) + { + Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName, startmarker, endmarker); + end = NumLumps; + } + else + { + end = markers[i++].index; + } + + // we found a marked block + Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName, startmarker, markers[start].index, end); + for(int j = markers[start].index + 1; j < end; j++) + { + if (Entries[j].Namespace != ns_global) + { + if (!warned) + { + Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName, j); + } + warned = true; + } + else if (space == ns_sprites && Entries[j].Length < 8) + { + // sf 26/10/99: + // ignore sprite lumps smaller than 8 bytes (the smallest possible) + // in size -- this was used by some dmadds wads + // as an 'empty' graphics resource + Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName, Entries[j].FileName, j); + } + else + { + Entries[j].Namespace = space; + } + } + } +} + + +//========================================================================== +// +// W_SkinHack +// +// Tests a wad file to see if it contains an S_SKIN marker. If it does, +// every lump in the wad is moved into a new namespace. Because skins are +// only supposed to replace player sprites, sounds, or faces, this should +// not be a problem. Yes, there are skins that replace more than that, but +// they are such a pain, and breaking them like this was done on purpose. +// This also renames any S_SKINxx lumps to just S_SKIN. +// +//========================================================================== + +void FWadFile::SkinHack (FileSystemMessageFunc Printf) +{ + // this being static is not a problem. The only relevant thing is that each skin gets a different number. + static int namespc = ns_firstskin; + bool skinned = false; + bool hasmap = false; + uint32_t i; + + for (i = 0; i < NumLumps; i++) + { + auto lump = &Entries[i]; + + if (!strnicmp(lump->FileName, "S_SKIN", 6)) + { // Wad has at least one skin. + lump->FileName = "S_SKIN"; + if (!skinned) + { + skinned = true; + uint32_t j; + + for (j = 0; j < NumLumps; j++) + { + Entries[j].Namespace = namespc; + } + namespc++; + } + } + // needless to say, this check is entirely useless these days as map names can be more diverse.. + if ((lump->FileName[0] == 'M' && + lump->FileName[1] == 'A' && + lump->FileName[2] == 'P' && + lump->FileName[3] >= '0' && lump->FileName[3] <= '9' && + lump->FileName[4] >= '0' && lump->FileName[4] <= '9' && + lump->FileName[5] == '\0') + || + (lump->FileName[0] == 'E' && + lump->FileName[1] >= '0' && lump->FileName[1] <= '9' && + lump->FileName[2] == 'M' && + lump->FileName[3] >= '0' && lump->FileName[3] <= '9' && + lump->FileName[4] == '\0')) + { + hasmap = true; + } + } + if (skinned && hasmap) + { + Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName); + Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n"); + } +} + + //========================================================================== // // File open // //========================================================================== -FResourceFile *CheckWad(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; @@ -156,8 +415,8 @@ FResourceFile *CheckWad(const char *filename, FileReader &file, FileSystemFilter file.Seek(0, FileReader::SeekSet); if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4)) { - auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_FOLDERS | FResourceFile::NO_EXTENSIONS | FResourceFile::SHORTNAMES); - if (OpenWAD(rf, filter, Printf)) return rf; + auto rf = new FWadFile(filename, file, sp); + if (rf->Open(filter, Printf)) return rf; file = rf->Destroy(); } diff --git a/src/common/filesystem/source/file_whres.cpp b/src/common/filesystem/source/file_whres.cpp index a4cc5dd937..d1d2d1a508 100644 --- a/src/common/filesystem/source/file_whres.cpp +++ b/src/common/filesystem/source/file_whres.cpp @@ -47,7 +47,7 @@ namespace FileSys { // //========================================================================== -bool OpenWHRes(FResourceFile* file, FileSystemFilterInfo*) +bool OpenWHRes(FResourceFile* file, LumpFilterInfo*) { uint32_t directory[1024]; @@ -83,6 +83,7 @@ bool OpenWHRes(FResourceFile* file, FileSystemFilterInfo*) Entries[i].Position = offset; Entries[i].CompressedSize = Entries[i].Length = length; Entries[i].Flags = RESFF_FULLPATH; + Entries[i].Namespace = ns_global; Entries[i].ResourceID = -1; Entries[i].Method = METHOD_STORED; Entries[i].FileName = file->NormalizeFileName(synthname.c_str()); @@ -98,7 +99,7 @@ bool OpenWHRes(FResourceFile* file, FileSystemFilterInfo*) // //========================================================================== -FResourceFile *CheckWHRes(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckWHRes(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { if (file.GetLength() >= 8192) // needs to be at least 8192 to contain one file and the directory. { @@ -118,7 +119,7 @@ FResourceFile *CheckWHRes(const char *filename, FileReader &file, FileSystemFilt if (offset != checkpos || length == 0 || offset + length >= (size_t)size - 4096 ) return nullptr; checkpos += (length+4095) / 4096; } - auto rf = new FResourceFile(filename, file, sp, FResourceFile::NO_EXTENSIONS); + auto rf = new FResourceFile(filename, file, sp); if (OpenWHRes(rf, filter)) return rf; file = rf->Destroy(); } diff --git a/src/common/filesystem/source/file_zip.cpp b/src/common/filesystem/source/file_zip.cpp index d49da9e5e6..8351b71464 100644 --- a/src/common/filesystem/source/file_zip.cpp +++ b/src/common/filesystem/source/file_zip.cpp @@ -113,7 +113,7 @@ class FZipFile : public FResourceFile public: FZipFile(const char* filename, FileReader& file, StringPool* sp); - bool Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf); + bool Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf); FCompressedBuffer GetRawData(uint32_t entry) override; }; @@ -124,11 +124,11 @@ class FZipFile : public FResourceFile //========================================================================== FZipFile::FZipFile(const char * filename, FileReader &file, StringPool* sp) -: FResourceFile(filename, file, sp, 0) +: FResourceFile(filename, file, sp) { } -bool FZipFile::Open(FileSystemFilterInfo* filter, FileSystemMessageFunc Printf) +bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf) { bool zip64 = false; uint32_t centraldir = Zip_FindCentralDir(Reader, &zip64); @@ -376,7 +376,7 @@ void FZipFile::SetEntryAddress(uint32_t entry) // //========================================================================== -FResourceFile *CheckZip(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { char head[4]; diff --git a/src/common/filesystem/source/filesystem.cpp b/src/common/filesystem/source/filesystem.cpp index 104b306a05..0bc0dd5fe9 100644 --- a/src/common/filesystem/source/filesystem.cpp +++ b/src/common/filesystem/source/filesystem.cpp @@ -52,6 +52,28 @@ namespace FileSys { // MACROS ------------------------------------------------------------------ +#define NULL_INDEX (0xffffffff) + +static void UpperCopy(char* to, const char* from) +{ + int i; + + for (i = 0; i < 8 && from[i]; i++) + to[i] = toupper(from[i]); + for (; i < 8; i++) + to[i] = 0; +} + + +//djb2 +static uint32_t MakeHash(const char* str, size_t length = SIZE_MAX) +{ + uint32_t hash = 5381; + uint32_t c; + while (length-- > 0 && (c = *str++)) hash = hash * 33 + (c | 32); + return hash; +} + static void md5Hash(FileReader& reader, uint8_t* digest) { using namespace md5; @@ -70,13 +92,15 @@ static void md5Hash(FileReader& reader, uint8_t* digest) struct FileSystem::LumpRecord { FResourceFile *resfile; - const char* Name; + LumpShortName shortName; + const char* LongName; int resindex; int16_t rfnum; // this is not necessarily the same as resfile's index! + int16_t Namespace; int resourceId; int flags; - void SetFromFile(FResourceFile* file, int fileindex, int filenum, StringPool* sp, const char* name = nullptr) + void SetFromLump(FResourceFile* file, int fileindex, int filenum, StringPool* sp, const char* name = nullptr) { resfile = file; resindex = fileindex; @@ -85,24 +109,52 @@ struct FileSystem::LumpRecord auto lflags = file->GetEntryFlags(fileindex); if (!name) name = file->getName(fileindex); - if ((lflags & RESFF_EMBEDDED) || !name || !*name) + if (lflags & RESFF_SHORTNAME) + { + UpperCopy(shortName.String, name); + shortName.String[8] = 0; + LongName = ""; + Namespace = file->GetEntryNamespace(fileindex); + resourceId = -1; + } + else if ((lflags & RESFF_EMBEDDED) || !name || !*name) { - Name = ""; + shortName.qword = 0; + LongName = ""; + Namespace = ns_hidden; resourceId = -1; } else { - Name = name; + LongName = name; resourceId = file->GetEntryResourceID(fileindex); - // allow embedding a resource ID in the name - we need to strip that out here. - if (strstr(Name, ".{")) + // Map some directories to WAD namespaces. + // Note that some of these namespaces don't exist in WADS. + // CheckNumForName will handle any request for these namespaces accordingly. + Namespace = !strncmp(LongName, "flats/", 6) ? ns_flats : + !strncmp(LongName, "textures/", 9) ? ns_newtextures : + !strncmp(LongName, "hires/", 6) ? ns_hires : + !strncmp(LongName, "sprites/", 8) ? ns_sprites : + !strncmp(LongName, "voxels/", 7) ? ns_voxels : + !strncmp(LongName, "colormaps/", 10) ? ns_colormaps : + !strncmp(LongName, "acs/", 4) ? ns_acslibrary : + !strncmp(LongName, "voices/", 7) ? ns_strifevoices : + !strncmp(LongName, "patches/", 8) ? ns_patches : + !strncmp(LongName, "graphics/", 9) ? ns_graphics : + !strncmp(LongName, "sounds/", 7) ? ns_sounds : + !strncmp(LongName, "music/", 6) ? ns_music : + !strchr(LongName, '/') ? ns_global : + ns_hidden; + + if (Namespace == ns_hidden) shortName.qword = 0; + else if (strstr(LongName, ".{")) { - std::string longName = Name; + std::string longName = LongName; ptrdiff_t encodedResID = longName.find_last_of(".{"); if (resourceId == -1 && (size_t)encodedResID != std::string::npos) { - const char* p = Name + encodedResID; + const char* p = LongName + encodedResID; char* q; int id = (int)strtoull(p + 2, &q, 10); // only decimal numbers allowed here. if (q[0] == '}' && (q[1] == '.' || q[1] == 0)) @@ -110,13 +162,27 @@ struct FileSystem::LumpRecord longName.erase(longName.begin() + encodedResID, longName.begin() + (q - p) + 1); resourceId = id; } - Name = sp->Strdup(longName.c_str()); + LongName = sp->Strdup(longName.c_str()); } } - auto slash = strrchr(Name, '/'); - std::string base = slash ? (slash + 1) : Name; + auto slash = strrchr(LongName, '/'); + std::string base = slash ? (slash + 1) : LongName; auto dot = base.find_last_of('.'); if (dot != std::string::npos) base.resize(dot); + UpperCopy(shortName.String, base.c_str()); + + // Since '\' can't be used as a file name's part inside a ZIP + // we have to work around this for sprites because it is a valid + // frame character. + if (Namespace == ns_sprites || Namespace == ns_voxels || Namespace == ns_hires) + { + char* c; + + while ((c = (char*)memchr(shortName.String, '^', 8))) + { + *c = '\\'; + } + } } } }; @@ -157,16 +223,22 @@ void FileSystem::DeleteAll () //========================================================================== // -// Initialize +// InitMultipleFiles // -// Pass a vector of files to use. All files are optional, +// Pass a null terminated list of files to use. All files are optional, // but at least one file must be found. File names can appear multiple // times. The name searcher looks backwards, so a later file can // override an earlier one. // //========================================================================== -bool FileSystem::InitFiles(std::vector& filenames, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates) +bool FileSystem::InitSingleFile(const char* filename, FileSystemMessageFunc Printf) +{ + std::vector filenames = { filename }; + return InitMultipleFiles(filenames, nullptr, Printf); +} + +bool FileSystem::InitMultipleFiles (std::vector& filenames, LumpFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates) { int numfiles; @@ -182,9 +254,9 @@ bool FileSystem::InitFiles(std::vector& filenames, FileSystemFilter // first, check for duplicates if (!allowduplicates) { - for (size_t i = 0; i < filenames.size(); i++) + for (size_t i=0;i& filenames, FileSystemFilter } } - for (size_t i = 0; i < filenames.size(); i++) + for(size_t i=0;iGetHash(); - MoveFilesInFolder(path.c_str()); + MoveLumpsInFolder(path.c_str()); } NumEntries = (uint32_t)FileInfo.size(); @@ -210,12 +282,6 @@ bool FileSystem::InitFiles(std::vector& filenames, FileSystemFilter { return false; } - return true; -} - -bool FileSystem::Initialize(std::vector& filenames, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates) -{ - if (!InitFiles(filenames, filter, Printf, allowduplicates)) return false; if (filter && filter->postprocessFunc) filter->postprocessFunc(); // [RH] Set up hash table @@ -237,8 +303,8 @@ int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, in FileData blob(data, size); fr.OpenMemoryArray(blob); - // wrap this into a single filenum resource file (should be done a little better later.) - auto rf = new FResourceFile(name, fr, stringpool, 0); + // wrap this into a single lump resource file (should be done a little better later.) + auto rf = new FResourceFile(name, fr, stringpool); auto Entries = rf->AllocateEntries(1); Entries[0].FileName = rf->NormalizeFileName(ExtractBaseName(name, true).c_str()); Entries[0].ResourceID = -1; @@ -246,8 +312,8 @@ int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, in Files.push_back(rf); FileInfo.resize(FileInfo.size() + 1); - FileSystem::LumpRecord* file_p = &FileInfo.back(); - file_p->SetFromFile(rf, 0, (int)Files.size() - 1, stringpool); + FileSystem::LumpRecord* lump_p = &FileInfo.back(); + lump_p->SetFromLump(rf, 0, (int)Files.size() - 1, stringpool); return (int)FileInfo.size() - 1; } @@ -256,12 +322,12 @@ int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, in // AddFile // // Files with a .wad extension are wadlink files with multiple lumps, -// other files are single lumps with the base filename for the filenum name. +// other files are single lumps with the base filename for the lump name. // // [RH] Removed reload hack //========================================================================== -void FileSystem::AddFile (const char *filename, FileReader *filer, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf) +void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInfo* filter, FileSystemMessageFunc Printf) { int startlump; bool isdir = false; @@ -308,17 +374,17 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, FileSystemFil if (resfile != NULL) { if (Printf) - Printf(FSMessageLevel::Message, "adding %s, %d files\n", filename, resfile->EntryCount()); + Printf(FSMessageLevel::Message, "adding %s, %d lumps\n", filename, resfile->EntryCount()); uint32_t lumpstart = (uint32_t)FileInfo.size(); - resfile->SetFirstFile(lumpstart); + resfile->SetFirstLump(lumpstart); Files.push_back(resfile); for (int i = 0; i < resfile->EntryCount(); i++) { FileInfo.resize(FileInfo.size() + 1); - FileSystem::LumpRecord* file_p = &FileInfo.back(); - file_p->SetFromFile(resfile, i, (int)Files.size() - 1, stringpool); + FileSystem::LumpRecord* lump_p = &FileInfo.back(); + lump_p->SetFromLump(resfile, i, (int)Files.size() - 1, stringpool); } for (int i = 0; i < resfile->EntryCount(); i++) @@ -349,7 +415,7 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, FileSystemFil // //========================================================================== -int FileSystem::CheckIfContainerLoaded (const char *name) noexcept +int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept { unsigned int i; @@ -357,7 +423,7 @@ int FileSystem::CheckIfContainerLoaded (const char *name) noexcept { for (i = 0; i < (unsigned)Files.size(); ++i) { - if (stricmp (GetContainerFullName (i), name) == 0) + if (stricmp (GetResourceFileFullName (i), name) == 0) { return i; } @@ -367,7 +433,7 @@ int FileSystem::CheckIfContainerLoaded (const char *name) noexcept { for (i = 0; i < (unsigned)Files.size(); ++i) { - auto pth = ExtractBaseName(GetContainerName(i), true); + auto pth = ExtractBaseName(GetResourceFileName(i), true); if (stricmp (pth.c_str(), name) == 0) { return i; @@ -377,6 +443,114 @@ int FileSystem::CheckIfContainerLoaded (const char *name) noexcept return -1; } +//========================================================================== +// +// CheckNumForName +// +// Returns -1 if name not found. The version with a third parameter will +// look exclusively in the specified wad for the lump. +// +// [RH] Changed to use hash lookup ala BOOM instead of a linear search +// and namespace parameter +//========================================================================== + +int FileSystem::CheckNumForName (const char *name, int space) const +{ + union + { + char uname[8]; + uint64_t qname; + }; + uint32_t i; + + if (name == NULL) + { + return -1; + } + + // Let's not search for names that are longer than 8 characters and contain path separators + // They are almost certainly full path names passed to this function. + if (strlen(name) > 8 && strpbrk(name, "/.")) + { + return -1; + } + + UpperCopy (uname, name); + i = FirstLumpIndex[MakeHash(uname, 8) % NumEntries]; + + while (i != NULL_INDEX) + { + + if (FileInfo[i].shortName.qword == qname) + { + auto &lump = FileInfo[i]; + if (lump.Namespace == space) break; + // If the lump is from one of the special namespaces exclusive to Zips + // the check has to be done differently: + // If we find a lump with this name in the global namespace that does not come + // from a Zip return that. WADs don't know these namespaces and single lumps must + // work as well. + auto lflags = lump.resfile->GetEntryFlags(lump.resindex); + if (space > ns_specialzipdirectory && lump.Namespace == ns_global && + !((lflags ^lump.flags) & RESFF_FULLPATH)) break; + } + i = NextLumpIndex[i]; + } + + return i != NULL_INDEX ? i : -1; +} + +int FileSystem::CheckNumForName (const char *name, int space, int rfnum, bool exact) const +{ + union + { + char uname[8]; + uint64_t qname; + }; + uint32_t i; + + if (rfnum < 0) + { + return CheckNumForName (name, space); + } + + UpperCopy (uname, name); + i = FirstLumpIndex[MakeHash (uname, 8) % NumEntries]; + + // If exact is true if will only find lumps in the same WAD, otherwise + // also those in earlier WADs. + + while (i != NULL_INDEX && + (FileInfo[i].shortName.qword != qname || FileInfo[i].Namespace != space || + (exact? (FileInfo[i].rfnum != rfnum) : (FileInfo[i].rfnum > rfnum)) )) + { + i = NextLumpIndex[i]; + } + + return i != NULL_INDEX ? i : -1; +} + +//========================================================================== +// +// GetNumForName +// +// Calls CheckNumForName, but bombs out if not found. +// +//========================================================================== + +int FileSystem::GetNumForName (const char *name, int space) const +{ + int i; + + i = CheckNumForName (name, space); + + if (i == -1) + throw FileSystemException("GetNumForName: %s not found!", name); + + return i; +} + + //========================================================================== // // CheckNumForFullName @@ -387,7 +561,7 @@ int FileSystem::CheckIfContainerLoaded (const char *name) noexcept // //========================================================================== -int FileSystem::FindFile (const char *name, bool ignoreext) const +int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int namespc, bool ignoreext) const { uint32_t i; @@ -396,40 +570,45 @@ int FileSystem::FindFile (const char *name, bool ignoreext) const return -1; } if (*name == '/') name++; // ignore leading slashes in file names. - uint32_t *fli = ignoreext ? FirstFileIndex_NoExt : FirstFileIndex_FullName; - uint32_t *nli = ignoreext ? NextFileIndex_NoExt : NextFileIndex_FullName; + uint32_t *fli = ignoreext ? FirstLumpIndex_NoExt : FirstLumpIndex_FullName; + uint32_t *nli = ignoreext ? NextLumpIndex_NoExt : NextLumpIndex_FullName; auto len = strlen(name); for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) { - if (strnicmp(name, FileInfo[i].Name, len)) continue; - if (FileInfo[i].Name[len] == 0) break; // this is a full match - if (ignoreext && FileInfo[i].Name[len] == '.') + if (strnicmp(name, FileInfo[i].LongName, len)) continue; + if (FileInfo[i].LongName[len] == 0) break; // this is a full match + if (ignoreext && FileInfo[i].LongName[len] == '.') { // is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension? - if (strpbrk(FileInfo[i].Name + len + 1, "./") == nullptr) break; + if (strpbrk(FileInfo[i].LongName + len + 1, "./") == nullptr) break; } } if (i != NULL_INDEX) return i; + + if (trynormal && strlen(name) <= 8 && !strpbrk(name, "./")) + { + return CheckNumForName(name, namespc); + } return -1; } -int FileSystem::GetFileInContainer (const char *name, int rfnum) const +int FileSystem::CheckNumForFullName (const char *name, int rfnum) const { uint32_t i; if (rfnum < 0) { - return FindFile (name); + return CheckNumForFullName (name); } - i = FirstFileIndex_FullName[MakeHash (name) % NumEntries]; + i = FirstLumpIndex_FullName[MakeHash (name) % NumEntries]; while (i != NULL_INDEX && - (stricmp(name, FileInfo[i].Name) || FileInfo[i].rfnum != rfnum)) + (stricmp(name, FileInfo[i].LongName) || FileInfo[i].rfnum != rfnum)) { - i = NextFileIndex_FullName[i]; + i = NextLumpIndex_FullName[i]; } return i != NULL_INDEX ? i : -1; @@ -443,11 +622,11 @@ int FileSystem::GetFileInContainer (const char *name, int rfnum) const // //========================================================================== -int FileSystem::GetFile (const char *name) const +int FileSystem::GetNumForFullName (const char *name) const { int i; - i = FindFile (name); + i = CheckNumForFullName (name); if (i == -1) throw FileSystemException("GetNumForFullName: %s not found!", name); @@ -472,16 +651,16 @@ int FileSystem::FindFileWithExtensions(const char* name, const char *const *exts return -1; } if (*name == '/') name++; // ignore leading slashes in file names. - uint32_t* fli = FirstFileIndex_NoExt; - uint32_t* nli = NextFileIndex_NoExt; + uint32_t* fli = FirstLumpIndex_NoExt; + uint32_t* nli = NextLumpIndex_NoExt; auto len = strlen(name); for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) { - if (strnicmp(name, FileInfo[i].Name, len)) continue; - if (FileInfo[i].Name[len] != '.') continue; // we are looking for extensions but this file doesn't have one. + if (strnicmp(name, FileInfo[i].LongName, len)) continue; + if (FileInfo[i].LongName[len] != '.') continue; // we are looking for extensions but this file doesn't have one. - auto cp = FileInfo[i].Name + len + 1; + auto cp = FileInfo[i].LongName + len + 1; // is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension? if (strpbrk(cp, "./") != nullptr) continue; // No, so it cannot be a valid entry. @@ -510,14 +689,14 @@ int FileSystem::FindResource (int resid, const char *type, int filenum) const no return -1; } - uint32_t* fli = FirstFileIndex_ResId; - uint32_t* nli = NextFileIndex_ResId; + uint32_t* fli = FirstLumpIndex_ResId; + uint32_t* nli = NextLumpIndex_ResId; for (i = fli[resid % NumEntries]; i != NULL_INDEX; i = nli[i]) { if (filenum > 0 && FileInfo[i].rfnum != filenum) continue; if (FileInfo[i].resourceId != resid) continue; - auto extp = strrchr(FileInfo[i].Name, '.'); + auto extp = strrchr(FileInfo[i].LongName, '.'); if (!extp) continue; if (!stricmp(extp + 1, type)) return i; } @@ -549,18 +728,18 @@ int FileSystem::GetResource (int resid, const char *type, int filenum) const // // FileLength // -// Returns the buffer size needed to load the given filenum. +// Returns the buffer size needed to load the given lump. // //========================================================================== -ptrdiff_t FileSystem::FileLength (int filenum) const +ptrdiff_t FileSystem::FileLength (int lump) const { - if ((size_t)filenum >= NumEntries) + if ((size_t)lump >= NumEntries) { return -1; } - const auto &file_p = FileInfo[filenum]; - return (int)file_p.resfile->Length(file_p.resindex); + const auto &lump_p = FileInfo[lump]; + return (int)lump_p.resfile->Length(lump_p.resindex); } //========================================================================== @@ -569,15 +748,15 @@ ptrdiff_t FileSystem::FileLength (int filenum) const // //========================================================================== -int FileSystem::GetFileFlags (int filenum) +int FileSystem::GetFileFlags (int lump) { - if ((size_t)filenum >= NumEntries) + if ((size_t)lump >= NumEntries) { return 0; } - const auto& file_p = FileInfo[filenum]; - return file_p.resfile->GetEntryFlags(file_p.resindex) ^ file_p.flags; + const auto& lump_p = FileInfo[lump]; + return lump_p.resfile->GetEntryFlags(lump_p.resindex) ^ lump_p.flags; } //========================================================================== @@ -594,39 +773,45 @@ void FileSystem::InitHashChains (void) unsigned int i, j; NumEntries = (uint32_t)FileInfo.size(); - Hashes.resize(6 * NumEntries); + Hashes.resize(8 * NumEntries); // Mark all buckets as empty memset(Hashes.data(), -1, Hashes.size() * sizeof(Hashes[0])); - FirstFileIndex_FullName = &Hashes[NumEntries * 0]; - NextFileIndex_FullName = &Hashes[NumEntries * 1]; - FirstFileIndex_NoExt = &Hashes[NumEntries * 2]; - NextFileIndex_NoExt = &Hashes[NumEntries * 3]; - FirstFileIndex_ResId = &Hashes[NumEntries * 4]; - NextFileIndex_ResId = &Hashes[NumEntries * 5]; + FirstLumpIndex = &Hashes[0]; + NextLumpIndex = &Hashes[NumEntries]; + FirstLumpIndex_FullName = &Hashes[NumEntries * 2]; + NextLumpIndex_FullName = &Hashes[NumEntries * 3]; + FirstLumpIndex_NoExt = &Hashes[NumEntries * 4]; + NextLumpIndex_NoExt = &Hashes[NumEntries * 5]; + FirstLumpIndex_ResId = &Hashes[NumEntries * 6]; + NextLumpIndex_ResId = &Hashes[NumEntries * 7]; // Now set up the chains for (i = 0; i < (unsigned)NumEntries; i++) { + j = MakeHash (FileInfo[i].shortName.String, 8) % NumEntries; + NextLumpIndex[i] = FirstLumpIndex[j]; + FirstLumpIndex[j] = i; + // Do the same for the full paths - if (FileInfo[i].Name[0] != 0) + if (FileInfo[i].LongName[0] != 0) { - j = MakeHash(FileInfo[i].Name) % NumEntries; - NextFileIndex_FullName[i] = FirstFileIndex_FullName[j]; - FirstFileIndex_FullName[j] = i; + j = MakeHash(FileInfo[i].LongName) % NumEntries; + NextLumpIndex_FullName[i] = FirstLumpIndex_FullName[j]; + FirstLumpIndex_FullName[j] = i; - std::string nameNoExt = FileInfo[i].Name; + std::string nameNoExt = FileInfo[i].LongName; auto dot = nameNoExt.find_last_of('.'); auto slash = nameNoExt.find_last_of('/'); if ((dot > slash || slash == std::string::npos) && dot != std::string::npos) nameNoExt.resize(dot); j = MakeHash(nameNoExt.c_str()) % NumEntries; - NextFileIndex_NoExt[i] = FirstFileIndex_NoExt[j]; - FirstFileIndex_NoExt[j] = i; + NextLumpIndex_NoExt[i] = FirstLumpIndex_NoExt[j]; + FirstLumpIndex_NoExt[j] = i; j = FileInfo[i].resourceId % NumEntries; - NextFileIndex_ResId[i] = FirstFileIndex_ResId[j]; - FirstFileIndex_ResId[j] = i; + NextLumpIndex_ResId[i] = FirstLumpIndex_ResId[j]; + FirstLumpIndex_ResId[j] = i; } } @@ -634,10 +819,24 @@ void FileSystem::InitHashChains (void) Files.shrink_to_fit(); } +//========================================================================== +// +// should only be called before the hash chains are set up. +// If done later this needs rehashing. +// +//========================================================================== + +LumpShortName& FileSystem::GetShortName(int i) +{ + if ((unsigned)i >= NumEntries) throw FileSystemException("GetShortName: Invalid index"); + return FileInfo[i].shortName; +} + void FileSystem::RenameFile(int num, const char* newfn) { if ((unsigned)num >= NumEntries) throw FileSystemException("RenameFile: Invalid index"); - FileInfo[num].Name = stringpool->Strdup(newfn); + FileInfo[num].LongName = stringpool->Strdup(newfn); + // This does not alter the short name - call GetShortname to do that! } //========================================================================== @@ -653,7 +852,7 @@ void FileSystem::RenameFile(int num, const char* newfn) // //========================================================================== -void FileSystem::MoveFilesInFolder(const char *path) +void FileSystem::MoveLumpsInFolder(const char *path) { if (FileInfo.size() == 0) { @@ -667,14 +866,15 @@ void FileSystem::MoveFilesInFolder(const char *path) for (i = 0; i < FileInfo.size(); i++) { auto& li = FileInfo[i]; - if (li.rfnum >= GetBaseNum()) break; - if (strnicmp(li.Name, path, len) == 0) + if (li.rfnum >= GetIwadNum()) break; + if (strnicmp(li.LongName, path, len) == 0) { auto lic = li; // make a copy before pushing. FileInfo.push_back(lic); - li.Name = ""; //nuke the name of the old record. + li.LongName = ""; //nuke the name of the old record. + li.shortName.qword = 0; auto &ln = FileInfo.back(); - ln.SetFromFile(li.resfile, li.resindex, rfnum, stringpool, ln.Name + len); + ln.SetFromLump(li.resfile, li.resindex, rfnum, stringpool, ln.LongName + len); } } } @@ -683,7 +883,88 @@ void FileSystem::MoveFilesInFolder(const char *path) // // W_FindLump // -// Find a named filenum. Specifically allows duplicates for merging of e.g. +// Find a named lump. Specifically allows duplicates for merging of e.g. +// SNDINFO lumps. +// +//========================================================================== + +int FileSystem::FindLump (const char *name, int *lastlump, bool anyns) +{ + if ((size_t)*lastlump >= FileInfo.size()) return -1; + union + { + char name8[8]; + uint64_t qname; + }; + + UpperCopy (name8, name); + + assert(lastlump != NULL && *lastlump >= 0); + + const LumpRecord * last = FileInfo.data() + FileInfo.size(); + + LumpRecord * lump_p = FileInfo.data() + *lastlump; + + while (lump_p < last) + { + if ((anyns || lump_p->Namespace == ns_global) && lump_p->shortName.qword == qname) + { + int lump = int(lump_p - FileInfo.data()); + *lastlump = lump + 1; + return lump; + } + lump_p++; + } + + *lastlump = NumEntries; + return -1; +} + +//========================================================================== +// +// W_FindLumpMulti +// +// Find a named lump. Specifically allows duplicates for merging of e.g. +// SNDINFO lumps. Returns everything having one of the passed names. +// +//========================================================================== + +int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, int *nameindex) +{ + assert(lastlump != NULL && *lastlump >= 0); + + const LumpRecord * last = FileInfo.data() + FileInfo.size(); + + LumpRecord * lump_p = FileInfo.data() + *lastlump; + + while (lump_p < last) + { + if (anyns || lump_p->Namespace == ns_global) + { + + for(const char **name = names; *name != NULL; name++) + { + if (!strnicmp(*name, lump_p->shortName.String, 8)) + { + int lump = int(lump_p - FileInfo.data()); + *lastlump = lump + 1; + if (nameindex != NULL) *nameindex = int(name - names); + return lump; + } + } + } + lump_p++; + } + + *lastlump = NumEntries; + return -1; +} + +//========================================================================== +// +// W_FindLump +// +// Find a named lump. Specifically allows duplicates for merging of e.g. // SNDINFO lumps. // //========================================================================== @@ -694,38 +975,38 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext) const LumpRecord * last = FileInfo.data() + FileInfo.size(); - LumpRecord * file_p = FileInfo.data() + *lastlump; + LumpRecord * lump_p = FileInfo.data() + *lastlump; if (!noext) { - while (file_p < last) + while (lump_p < last) { - if (!stricmp(name, file_p->Name)) + if (!stricmp(name, lump_p->LongName)) { - int filenum = int(file_p - FileInfo.data()); - *lastlump = filenum + 1; - return filenum; + int lump = int(lump_p - FileInfo.data()); + *lastlump = lump + 1; + return lump; } - file_p++; + lump_p++; } } else { auto len = strlen(name); - while (file_p <= &FileInfo.back()) + while (lump_p <= &FileInfo.back()) { - auto res = strnicmp(name, file_p->Name, len); + auto res = strnicmp(name, lump_p->LongName, len); if (res == 0) { - auto p = file_p->Name + len; + auto p = lump_p->LongName + len; if (*p == 0 || (*p == '.' && strpbrk(p + 1, "./") == 0)) { - int filenum = int(file_p - FileInfo.data()); - *lastlump = filenum + 1; - return filenum; + int lump = int(lump_p - FileInfo.data()); + *lastlump = lump + 1; + return lump; } } - file_p++; + lump_p++; } } @@ -736,56 +1017,107 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext) //========================================================================== // -// FileSystem :: GetFileName +// W_CheckLumpName +// +//========================================================================== + +bool FileSystem::CheckFileName (int lump, const char *name) +{ + if ((size_t)lump >= NumEntries) + return false; + + return !strnicmp (FileInfo[lump].shortName.String, name, 8); +} + +//========================================================================== +// +// GetLumpName +// +//========================================================================== + +const char* FileSystem::GetFileShortName(int lump) const +{ + if ((size_t)lump >= NumEntries) + return nullptr; + else + return FileInfo[lump].shortName.String; +} + +//========================================================================== +// +// FileSystem :: GetFileFullName // -// Returns the filenum's internal name +// Returns the lump's full name if it has one or its short name if not. // //========================================================================== -const char* FileSystem::GetFileName(int filenum) const +const char *FileSystem::GetFileFullName (int lump, bool returnshort) const { - if ((size_t)filenum >= NumEntries) + if ((size_t)lump >= NumEntries) return NULL; - else return FileInfo[filenum].Name; + else if (FileInfo[lump].LongName[0] != 0) + return FileInfo[lump].LongName; + else if (returnshort) + return FileInfo[lump].shortName.String; + else return nullptr; } //========================================================================== // // FileSystem :: GetFileFullPath // -// Returns the name of the filenum's wad prefixed to the filenum's full name. +// Returns the name of the lump's wad prefixed to the lump's full name. // //========================================================================== -std::string FileSystem::GetFileFullPath(int filenum) const +std::string FileSystem::GetFileFullPath(int lump) const { std::string foo; - if ((size_t) filenum < NumEntries) + if ((size_t) lump < NumEntries) { - foo = GetContainerName(FileInfo[filenum].rfnum); + foo = GetResourceFileName(FileInfo[lump].rfnum); foo += ':'; - foo += +GetFileName(filenum); + foo += +GetFileFullName(lump); } return foo; } +//========================================================================== +// +// GetFileNamespace +// +//========================================================================== + +int FileSystem::GetFileNamespace (int lump) const +{ + if ((size_t)lump >= NumEntries) + return ns_global; + else + return FileInfo[lump].Namespace; +} + +void FileSystem::SetFileNamespace(int lump, int ns) +{ + if ((size_t)lump < NumEntries) FileInfo[lump].Namespace = ns; +} + //========================================================================== // // FileSystem :: GetResourceId // -// Returns the index number for this filenum. This is *not* the filenum's position -// in the filenum directory, but rather a special value that RFF can associate +// Returns the index number for this lump. This is *not* the lump's position +// in the lump directory, but rather a special value that RFF can associate // with files. Other archive types will return 0, since they don't have it. // //========================================================================== -int FileSystem::GetResourceId(int filenum) const +int FileSystem::GetResourceId(int lump) const { - if ((size_t)filenum >= NumEntries) + if ((size_t)lump >= NumEntries) return -1; else - return FileInfo[filenum].resourceId; + return FileInfo[lump].resourceId; } //========================================================================== @@ -796,13 +1128,13 @@ int FileSystem::GetResourceId(int filenum) const // //========================================================================== -const char *FileSystem::GetResourceType(int filenum) const +const char *FileSystem::GetResourceType(int lump) const { - if ((size_t)filenum >= NumEntries) + if ((size_t)lump >= NumEntries) return nullptr; else { - auto p = strrchr(FileInfo[filenum].Name, '.'); + auto p = strrchr(FileInfo[lump].LongName, '.'); if (!p) return ""; // has no extension if (strchr(p, '/')) return ""; // the '.' is part of a directory. return p + 1; @@ -815,11 +1147,11 @@ const char *FileSystem::GetResourceType(int filenum) const // //========================================================================== -int FileSystem::GetFileContainer (int filenum) const +int FileSystem::GetFileContainer (int lump) const { - if ((size_t)filenum >= FileInfo.size()) + if ((size_t)lump >= FileInfo.size()) return -1; - return FileInfo[filenum].rfnum; + return FileInfo[lump].rfnum; } //========================================================================== @@ -854,12 +1186,12 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, std::vector= W_LumpLength(). +// Loads the lump into the given buffer, which must be >= W_LumpLength(). // //========================================================================== -void FileSystem::ReadFile (int filenum, void *dest) +void FileSystem::ReadFile (int lump, void *dest) { - auto lumpr = OpenFileReader (filenum); + auto lumpr = OpenFileReader (lump); auto size = lumpr.GetLength (); auto numread = lumpr.Read (dest, size); if (numread != size) { throw FileSystemException("W_ReadFile: only read %td of %td on '%s'\n", - numread, size, FileInfo[filenum].Name); + numread, size, FileInfo[lump].LongName); } } @@ -912,17 +1244,17 @@ void FileSystem::ReadFile (int filenum, void *dest) // // ReadFile - variant 2 // -// Loads the filenum into a newly created buffer and returns it. +// Loads the lump into a newly created buffer and returns it. // //========================================================================== -FileData FileSystem::ReadFile (int filenum) +FileData FileSystem::ReadFile (int lump) { - if ((unsigned)filenum >= (unsigned)FileInfo.size()) + if ((unsigned)lump >= (unsigned)FileInfo.size()) { - throw FileSystemException("ReadFile: %u >= NumEntries", filenum); + throw FileSystemException("ReadFile: %u >= NumEntries", lump); } - return FileInfo[filenum].resfile->Read(FileInfo[filenum].resindex); + return FileInfo[lump].resfile->Read(FileInfo[lump].resindex); } //========================================================================== @@ -934,30 +1266,30 @@ FileData FileSystem::ReadFile (int filenum) //========================================================================== -FileReader FileSystem::OpenFileReader(int filenum, int readertype, int readerflags) +FileReader FileSystem::OpenFileReader(int lump, int readertype, int readerflags) { - if ((unsigned)filenum >= (unsigned)FileInfo.size()) + if ((unsigned)lump >= (unsigned)FileInfo.size()) { - throw FileSystemException("OpenFileReader: %u >= NumEntries", filenum); + throw FileSystemException("OpenFileReader: %u >= NumEntries", lump); } - auto file = FileInfo[filenum].resfile; - return file->GetEntryReader(FileInfo[filenum].resindex, readertype, readerflags); + auto file = FileInfo[lump].resfile; + return file->GetEntryReader(FileInfo[lump].resindex, readertype, readerflags); } FileReader FileSystem::OpenFileReader(const char* name) { FileReader fr; - auto filenum = FindFile(name); - if (filenum >= 0) fr = OpenFileReader(filenum); + auto lump = CheckNumForFullName(name); + if (lump >= 0) fr = OpenFileReader(lump); return fr; } FileReader FileSystem::ReopenFileReader(const char* name, bool alwayscache) { FileReader fr; - auto filenum = FindFile(name); - if (filenum >= 0) fr = ReopenFileReader(filenum, alwayscache); + auto lump = CheckNumForFullName(name); + if (lump >= 0) fr = ReopenFileReader(lump, alwayscache); return fr; } @@ -982,13 +1314,13 @@ FileReader *FileSystem::GetFileReader(int rfnum) //========================================================================== // -// GetContainerName +// GetResourceFileName // // Returns the name of the given wad. // //========================================================================== -const char *FileSystem::GetContainerName (int rfnum) const noexcept +const char *FileSystem::GetResourceFileName (int rfnum) const noexcept { const char *name, *slash; @@ -1022,21 +1354,6 @@ int FileSystem::GetFirstEntry (int rfnum) const noexcept // //========================================================================== -int FileSystem::GetContainerFlags(int rfnum) const noexcept -{ - if ((uint32_t)rfnum >= Files.size()) - { - return 0; - } - - return Files[rfnum]->GetFlags(); -} - -//========================================================================== -// -// -//========================================================================== - int FileSystem::GetLastEntry (int rfnum) const noexcept { if ((uint32_t)rfnum >= Files.size()) @@ -1071,7 +1388,7 @@ int FileSystem::GetEntryCount (int rfnum) const noexcept // //========================================================================== -const char *FileSystem::GetContainerFullName (int rfnum) const noexcept +const char *FileSystem::GetResourceFileFullName (int rfnum) const noexcept { if ((unsigned int)rfnum >= Files.size()) { @@ -1094,21 +1411,21 @@ bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/) // The old code said 'filename' and ignored the path, this looked like a bug. FixPathSeparator(&name2.front()); - auto filenum = FindFile(name2.c_str()); - if (filenum < 0) return false; // Does not exist. + auto lump = FindFile(name2.c_str()); + if (lump < 0) return false; // Does not exist. - auto oldlump = FileInfo[filenum]; - auto slash = strrchr(oldlump.Name, '/'); + auto oldlump = FileInfo[lump]; + auto slash = strrchr(oldlump.LongName, '/'); if (slash == nullptr) { - FileInfo[filenum].flags = RESFF_FULLPATH; + FileInfo[lump].flags = RESFF_FULLPATH; return true; // already is pathless. } // just create a new reference to the original data with a different name. - oldlump.Name = slash + 1; + oldlump.LongName = slash + 1; oldlump.resourceId = id; oldlump.flags = RESFF_FULLPATH; FileInfo.push_back(oldlump); diff --git a/src/common/filesystem/source/resourcefile.cpp b/src/common/filesystem/source/resourcefile.cpp index 6736cfa713..00a5234ca1 100644 --- a/src/common/filesystem/source/resourcefile.cpp +++ b/src/common/filesystem/source/resourcefile.cpp @@ -113,7 +113,7 @@ bool FResourceFile::IsFileInFolder(const char* const resPath) return 0 == stricmp(filePath.c_str(), resPath); } -void FResourceFile::CheckEmbedded(uint32_t entry, FileSystemFilterInfo* lfi) +void FResourceFile::CheckEmbedded(uint32_t entry, LumpFilterInfo* lfi) { // Checks for embedded archives auto FullName = Entries[entry].FileName; @@ -138,30 +138,29 @@ void FResourceFile::CheckEmbedded(uint32_t entry, FileSystemFilterInfo* lfi) // //========================================================================== -typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckWad(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckGRP(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckRFF(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckPak(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckZip(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *Check7Z(const char *filename, FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile* CheckSSI(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile* CheckHog(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile* CheckHog2(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile* CheckMvl(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile* CheckWHRes(const char* filename, FileReader& file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckLump(const char *filename,FileReader &file, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -FResourceFile *CheckDir(const char *filename, bool nosub, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckWad(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckGRP(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckRFF(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckPak(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckZip(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *Check7Z(const char *filename, FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckSSI(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckHog(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckMvl(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile* CheckWHRes(const char* filename, FileReader& file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckLump(const char *filename,FileReader &file, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); +FResourceFile *CheckDir(const char *filename, bool nosub, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp); -static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckHog, CheckMvl, CheckHog2, CheckSSI, CheckWHRes, CheckLump }; +static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckSSI, CheckHog, CheckMvl, CheckWHRes, CheckLump }; static int nulPrintf(FSMessageLevel msg, const char* fmt, ...) { return 0; } -FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { if (!file.isOpen()) return nullptr; if (Printf == nullptr) Printf = nulPrintf; @@ -174,20 +173,20 @@ FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReade return NULL; } -FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool containeronly, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { return DoOpenResourceFile(filename, file, containeronly, filter, Printf, sp); } -FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool containeronly, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { FileReader file; if (!file.OpenFile(filename)) return nullptr; return DoOpenResourceFile(filename, file, containeronly, filter, Printf, sp); } -FResourceFile *FResourceFile::OpenDirectory(const char *filename, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) +FResourceFile *FResourceFile::OpenDirectory(const char *filename, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { if (Printf == nullptr) Printf = nulPrintf; return CheckDir(filename, false, filter, Printf, sp); @@ -199,15 +198,14 @@ FResourceFile *FResourceFile::OpenDirectory(const char *filename, FileSystemFilt // //========================================================================== -FResourceFile::FResourceFile(const char *filename, StringPool* sp, int flags_) - :flags(flags_) +FResourceFile::FResourceFile(const char *filename, StringPool* sp) { stringpool = sp ? sp : new StringPool(false); FileName = stringpool->Strdup(filename); } -FResourceFile::FResourceFile(const char *filename, FileReader &r, StringPool* sp, int flags) - : FResourceFile(filename,sp, flags) +FResourceFile::FResourceFile(const char *filename, FileReader &r, StringPool* sp) + : FResourceFile(filename,sp) { Reader = std::move(r); } @@ -252,7 +250,7 @@ FCompressedBuffer FResourceFile::GetRawData(uint32_t entry) // //========================================================================== -const char* FResourceFile::NormalizeFileName(const char* fn, int fallbackcp, bool allowbackslash) +const char* FResourceFile::NormalizeFileName(const char* fn, int fallbackcp) { if (!fn || !*fn) return ""; auto norm = tolower_normalize(fn); @@ -276,8 +274,7 @@ const char* FResourceFile::NormalizeFileName(const char* fn, int fallbackcp, boo norm = tolower_normalize(&ffn.front()); } } - // The WAD format can have legal backslashes in its names so this must be optional. - if (!allowbackslash) FixPathSeparator(norm); + FixPathSeparator(norm); auto pooled = stringpool->Strdup(norm); free(norm); return pooled; @@ -357,7 +354,7 @@ void FResourceFile::GenerateHash() // //========================================================================== -void FResourceFile::PostProcessArchive(FileSystemFilterInfo *filter) +void FResourceFile::PostProcessArchive(LumpFilterInfo *filter) { // only do this for archive types which contain full file names. All others are assumed to be pre-sorted. if (NumLumps == 0 || !(Entries[0].Flags & RESFF_FULLPATH)) return; @@ -419,7 +416,7 @@ void FResourceFile::PostProcessArchive(FileSystemFilterInfo *filter) // //========================================================================== -void FResourceFile::FindCommonFolder(FileSystemFilterInfo* filter) +void FResourceFile::FindCommonFolder(LumpFilterInfo* filter) { std::string name0, name1; bool foundspeciallump = false; diff --git a/src/common/fonts/v_font.cpp b/src/common/fonts/v_font.cpp index 9cd5cb2a80..d838fb1813 100644 --- a/src/common/fonts/v_font.cpp +++ b/src/common/fonts/v_font.cpp @@ -120,7 +120,7 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) } - lump = fileSystem.CheckNumForAnyName(fontlumpname? fontlumpname : name); + lump = fileSystem.CheckNumForFullName(fontlumpname? fontlumpname : name, true); if (lump != -1 && fileSystem.GetFileContainer(lump) >= folderfile) { @@ -290,7 +290,7 @@ void V_InitCustomFonts() { *p = TexMan.GetGameTexture(texid); } - else if (fileSystem.GetFileContainer(sc.LumpNum) >= fileSystem.GetBaseNum()) + else if (fileSystem.GetFileContainer(sc.LumpNum) >= fileSystem.GetIwadNum()) { // Print a message only if this isn't in zdoom.pk3 sc.ScriptMessage("%s: Unable to find texture in font definition for %s", sc.String, namebuffer.GetChars()); @@ -871,7 +871,7 @@ void V_InitFonts() FFont *CreateHexLumpFont(const char *fontname, int lump); FFont *CreateHexLumpFont2(const char *fontname, int lump); - auto lump = fileSystem.GetFileInContainer("newconsolefont.hex", 0); // This is always loaded from gzdoom.pk3 to prevent overriding it with incomplete replacements. + auto lump = fileSystem.CheckNumForFullName("newconsolefont.hex", 0); // This is always loaded from gzdoom.pk3 to prevent overriding it with incomplete replacements. if (lump == -1) I_FatalError("newconsolefont.hex not found"); // This font is needed - do not start up without it. NewConsoleFont = CreateHexLumpFont("NewConsoleFont", lump); NewSmallFont = CreateHexLumpFont2("NewSmallFont", lump); diff --git a/src/common/menu/menudef.cpp b/src/common/menu/menudef.cpp index 42d006d9d0..ad02001e0c 100644 --- a/src/common/menu/menudef.cpp +++ b/src/common/menu/menudef.cpp @@ -1524,7 +1524,7 @@ void M_ParseMenuDefs() DefaultOptionMenuSettings->Reset(); OptionSettings.mLinespacing = 17; - int IWADMenu = fileSystem.CheckNumForName("MENUDEF", ns_global, fileSystem.GetBaseNum()); + int IWADMenu = fileSystem.CheckNumForName("MENUDEF", FileSys::ns_global, fileSystem.GetIwadNum()); while ((lump = fileSystem.FindLump ("MENUDEF", &lastlump)) != -1) { diff --git a/src/common/models/model.cpp b/src/common/models/model.cpp index ee44e4bca2..0f16034158 100644 --- a/src/common/models/model.cpp +++ b/src/common/models/model.cpp @@ -88,7 +88,7 @@ void FModel::DestroyVertexBuffer() static int FindGFXFile(FString & fn) { - int lump = fileSystem.FindFile(fn.GetChars()); // if we find something that matches the name plus the extension, return it and do not enter the substitution logic below. + int lump = fileSystem.CheckNumForFullName(fn.GetChars()); // if we find something that matches the name plus the extension, return it and do not enter the substitution logic below. if (lump != -1) return lump; int best = -1; @@ -100,7 +100,7 @@ static int FindGFXFile(FString & fn) for (const char ** extp=extensions; *extp; extp++) { - lump = fileSystem.FindFile((fn + *extp).GetChars()); + lump = fileSystem.CheckNumForFullName((fn + *extp).GetChars()); if (lump >= best) best = lump; } return best; @@ -120,7 +120,7 @@ FTextureID LoadSkin(const char * path, const char * fn) buffer.Format("%s%s", path, fn); int texlump = FindGFXFile(buffer); - const char * const texname = texlump < 0 ? fn : fileSystem.GetFileName(texlump); + const char * const texname = texlump < 0 ? fn : fileSystem.GetFileFullName(texlump); return TexMan.CheckForTexture(texname, ETextureType::Any, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ForceLookup); } @@ -148,7 +148,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent) if (path) fullname.Format("%s%s", path, modelfile); else fullname = modelfile; - int lump = fileSystem.FindFile(fullname.GetChars()); + int lump = fileSystem.CheckNumForFullName(fullname.GetChars()); if (lump<0) { @@ -175,7 +175,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent) { FString anivfile = fullname.GetChars(); anivfile.Substitute("_d.3d","_a.3d"); - if ( fileSystem.FindFile(anivfile.GetChars()) > 0 ) + if ( fileSystem.CheckNumForFullName(anivfile.GetChars()) > 0 ) { model = new FUE1Model; } @@ -184,7 +184,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent) { FString datafile = fullname.GetChars(); datafile.Substitute("_a.3d","_d.3d"); - if ( fileSystem.FindFile(datafile.GetChars()) > 0 ) + if ( fileSystem.CheckNumForFullName(datafile.GetChars()) > 0 ) { model = new FUE1Model; } diff --git a/src/common/models/models_ue1.cpp b/src/common/models/models_ue1.cpp index f67d76589d..8106592617 100644 --- a/src/common/models/models_ue1.cpp +++ b/src/common/models/models_ue1.cpp @@ -49,18 +49,18 @@ bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int { int lumpnum2; hasSurfaces = true; - FString realfilename = fileSystem.GetFileName(lumpnum); + FString realfilename = fileSystem.GetFileFullName(lumpnum); if ( (size_t)realfilename.IndexOf("_d.3d") == realfilename.Len()-5 ) { realfilename.Substitute("_d.3d","_a.3d"); - lumpnum2 = fileSystem.FindFile(realfilename.GetChars()); + lumpnum2 = fileSystem.CheckNumForFullName(realfilename.GetChars()); mDataLump = lumpnum; mAnivLump = lumpnum2; } else { realfilename.Substitute("_a.3d","_d.3d"); - lumpnum2 = fileSystem.FindFile(realfilename.GetChars()); + lumpnum2 = fileSystem.CheckNumForFullName(realfilename.GetChars()); mAnivLump = lumpnum; mDataLump = lumpnum2; } diff --git a/src/common/models/voxels.cpp b/src/common/models/voxels.cpp index af48bd39d7..4d13323530 100644 --- a/src/common/models/voxels.cpp +++ b/src/common/models/voxels.cpp @@ -309,7 +309,7 @@ FVoxelDef *R_LoadVoxelDef(int lumpnum, int spin) FVoxel *vox = R_LoadKVX(lumpnum); if (vox == NULL) { - Printf("%s is not a valid voxel file\n", fileSystem.GetFileName(lumpnum)); + Printf("%s is not a valid voxel file\n", fileSystem.GetFileFullName(lumpnum)); return NULL; } else diff --git a/src/common/rendering/gl/gl_shader.cpp b/src/common/rendering/gl/gl_shader.cpp index d7fbec23ee..bafbf89b8e 100644 --- a/src/common/rendering/gl/gl_shader.cpp +++ b/src/common/rendering/gl/gl_shader.cpp @@ -373,10 +373,10 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * i_data += "#define NPOT_EMULATION\nuniform vec2 uNpotEmulation;\n"; #endif - int vp_lump = fileSystem.GetFileInContainer(vert_prog_lump, 0); + int vp_lump = fileSystem.CheckNumForFullName(vert_prog_lump, 0); if (vp_lump == -1) I_Error("Unable to load '%s'", vert_prog_lump); - int fp_lump = fileSystem.GetFileInContainer(frag_prog_lump, 0); + int fp_lump = fileSystem.CheckNumForFullName(frag_prog_lump, 0); if (fp_lump == -1) I_Error("Unable to load '%s'", frag_prog_lump); @@ -418,8 +418,8 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * if (*proc_prog_lump != '#') { - int pp_lump = fileSystem.GetFileInContainer(proc_prog_lump, 0); // if it's a core shader, ignore overrides by user mods. - if (pp_lump == -1) pp_lump = fileSystem.FindFile(proc_prog_lump); + int pp_lump = fileSystem.CheckNumForFullName(proc_prog_lump, 0); // if it's a core shader, ignore overrides by user mods. + if (pp_lump == -1) pp_lump = fileSystem.CheckNumForFullName(proc_prog_lump); if (pp_lump == -1) I_Error("Unable to load '%s'", proc_prog_lump); FString pp_data = GetStringFromLump(pp_lump); @@ -429,13 +429,13 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * if (pp_data.IndexOf("GetTexCoord") >= 0) { - int pl_lump = fileSystem.GetFileInContainer("shaders/glsl/func_defaultmat2.fp", 0); + int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultmat2.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultmat2.fp"); fp_comb << "\n" << GetStringFromLump(pl_lump); } else { - int pl_lump = fileSystem.GetFileInContainer("shaders/glsl/func_defaultmat.fp", 0); + int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultmat.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultmat.fp"); fp_comb << "\n" << GetStringFromLump(pl_lump); @@ -461,7 +461,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * if (pp_data.IndexOf("ProcessLight") < 0) { - int pl_lump = fileSystem.GetFileInContainer("shaders/glsl/func_defaultlight.fp", 0); + int pl_lump = fileSystem.CheckNumForFullName("shaders/glsl/func_defaultlight.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultlight.fp"); fp_comb << "\n" << GetStringFromLump(pl_lump); } @@ -483,7 +483,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * if (light_fragprog) { - int pp_lump = fileSystem.GetFileInContainer(light_fragprog, 0); + int pp_lump = fileSystem.CheckNumForFullName(light_fragprog, 0); if (pp_lump == -1) I_Error("Unable to load '%s'", light_fragprog); fp_comb << GetStringFromLump(pp_lump) << "\n"; } diff --git a/src/common/rendering/gl/gl_shaderprogram.cpp b/src/common/rendering/gl/gl_shaderprogram.cpp index b74a1c0591..1c4fd48a4d 100644 --- a/src/common/rendering/gl/gl_shaderprogram.cpp +++ b/src/common/rendering/gl/gl_shaderprogram.cpp @@ -87,7 +87,7 @@ void FShaderProgram::CreateShader(ShaderType type) void FShaderProgram::Compile(ShaderType type, const char *lumpName, const char *defines, int maxGlslVersion) { - int lump = fileSystem.FindFile(lumpName); + int lump = fileSystem.CheckNumForFullName(lumpName); if (lump == -1) I_FatalError("Unable to load '%s'", lumpName); FString code = GetStringFromLump(lump); diff --git a/src/common/rendering/gles/gles_shader.cpp b/src/common/rendering/gles/gles_shader.cpp index 40c12dc64a..dba9a233a6 100644 --- a/src/common/rendering/gles/gles_shader.cpp +++ b/src/common/rendering/gles/gles_shader.cpp @@ -381,10 +381,10 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * i_data += "#define NPOT_EMULATION\nuniform vec2 uNpotEmulation;\n"; #endif - int vp_lump = fileSystem.GetFileInContainer(vert_prog_lump.GetChars(), 0); + int vp_lump = fileSystem.CheckNumForFullName(vert_prog_lump.GetChars(), 0); if (vp_lump == -1) I_Error("Unable to load '%s'", vert_prog_lump.GetChars()); - int fp_lump = fileSystem.GetFileInContainer(frag_prog_lump.GetChars(), 0); + int fp_lump = fileSystem.CheckNumForFullName(frag_prog_lump.GetChars(), 0); if (fp_lump == -1) I_Error("Unable to load '%s'", frag_prog_lump.GetChars()); @@ -418,7 +418,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * if (proc_prog_lump[0] != '#') { - int pp_lump = fileSystem.FindFile(proc_prog_lump.GetChars()); + int pp_lump = fileSystem.CheckNumForFullName(proc_prog_lump.GetChars()); if (pp_lump == -1) I_Error("Unable to load '%s'", proc_prog_lump.GetChars()); FString pp_data = GetStringFromLump(pp_lump); @@ -428,13 +428,13 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * if (pp_data.IndexOf("GetTexCoord") >= 0) { - int pl_lump = fileSystem.GetFileInContainer("shaders_gles/glsl/func_defaultmat2.fp", 0); + int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultmat2.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultmat2.fp"); fp_comb << "\n" << GetStringFromLump(pl_lump); } else { - int pl_lump = fileSystem.GetFileInContainer("shaders_gles/glsl/func_defaultmat.fp", 0); + int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultmat.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultmat.fp"); fp_comb << "\n" << GetStringFromLump(pl_lump); @@ -460,7 +460,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * if (pp_data.IndexOf("ProcessLight") < 0) { - int pl_lump = fileSystem.GetFileInContainer("shaders_gles/glsl/func_defaultlight.fp", 0); + int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultlight.fp", 0); if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultlight.fp"); fp_comb << "\n" << GetStringFromLump(pl_lump); } @@ -482,7 +482,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * if (light_fragprog.Len()) { - int pp_lump = fileSystem.GetFileInContainer(light_fragprog.GetChars(), 0); + int pp_lump = fileSystem.CheckNumForFullName(light_fragprog.GetChars(), 0); if (pp_lump == -1) I_Error("Unable to load '%s'", light_fragprog.GetChars()); fp_comb << GetStringFromLump(pp_lump) << "\n"; } diff --git a/src/common/rendering/gles/gles_shaderprogram.cpp b/src/common/rendering/gles/gles_shaderprogram.cpp index 1e107bd1bd..efc94c71df 100644 --- a/src/common/rendering/gles/gles_shaderprogram.cpp +++ b/src/common/rendering/gles/gles_shaderprogram.cpp @@ -87,7 +87,7 @@ void FShaderProgram::CreateShader(ShaderType type) void FShaderProgram::Compile(ShaderType type, const char *lumpName, const char *defines, int maxGlslVersion) { - int lump = fileSystem.FindFile(lumpName); + int lump = fileSystem.CheckNumForFullName(lumpName); if (lump == -1) I_FatalError("Unable to load '%s'", lumpName); FString code = GetStringFromLump(lump); Compile(type, lumpName, code, defines, maxGlslVersion); diff --git a/src/common/rendering/vulkan/shaders/vk_ppshader.cpp b/src/common/rendering/vulkan/shaders/vk_ppshader.cpp index 38f2201cbe..dcf72a06d2 100644 --- a/src/common/rendering/vulkan/shaders/vk_ppshader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_ppshader.cpp @@ -67,7 +67,7 @@ void VkPPShader::Reset() FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defines, int version) { - int lump = fileSystem.FindFile(lumpName.GetChars()); + int lump = fileSystem.CheckNumForFullName(lumpName.GetChars()); if (lump == -1) I_FatalError("Unable to load '%s'", lumpName.GetChars()); FString code = GetStringFromLump(lump); diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index 0b908bfe58..00734ac7f3 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -465,15 +465,15 @@ FString VkShaderManager::GetTargetGlslVersion() FString VkShaderManager::LoadPublicShaderLump(const char *lumpname) { - int lump = fileSystem.GetFileInContainer(lumpname, 0); - if (lump == -1) lump = fileSystem.FindFile(lumpname); + int lump = fileSystem.CheckNumForFullName(lumpname, 0); + if (lump == -1) lump = fileSystem.CheckNumForFullName(lumpname); if (lump == -1) I_Error("Unable to load '%s'", lumpname); return GetStringFromLump(lump); } FString VkShaderManager::LoadPrivateShaderLump(const char *lumpname) { - int lump = fileSystem.GetFileInContainer(lumpname, 0); + int lump = fileSystem.CheckNumForFullName(lumpname, 0); if (lump == -1) I_Error("Unable to load '%s'", lumpname); return GetStringFromLump(lump); } diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp index fef3e6ec2e..b70783f3e1 100644 --- a/src/common/scripting/core/types.cpp +++ b/src/common/scripting/core/types.cpp @@ -2585,7 +2585,7 @@ static void PMapValueWriter(FSerializer &ar, const M *map, const PMap *m) if (TexMan.GetLinkedTexture(lump) == tex) { - name = fileSystem.GetFileName(lump); + name = fileSystem.GetFileFullName(lump); } else { diff --git a/src/common/scripting/frontend/zcc_parser.cpp b/src/common/scripting/frontend/zcc_parser.cpp index 26bf253913..6ea3c316e6 100644 --- a/src/common/scripting/frontend/zcc_parser.cpp +++ b/src/common/scripting/frontend/zcc_parser.cpp @@ -304,7 +304,7 @@ static void ParseSingleFile(FScanner *pSC, const char *filename, int lump, void { if (filename != nullptr) { - lump = fileSystem.CheckNumForAnyName(filename); + lump = fileSystem.CheckNumForFullName(filename, true); if (lump >= 0) { lsc.OpenLumpNum(lump); @@ -480,7 +480,7 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state) ParseSingleFile(&sc, nullptr, lumpnum, parser, state); for (unsigned i = 0; i < Includes.Size(); i++) { - lumpnum = fileSystem.CheckNumForAnyName(Includes[i].GetChars()); + lumpnum = fileSystem.CheckNumForFullName(Includes[i].GetChars(), true); if (lumpnum == -1) { IncludeLocs[i].Message(MSG_ERROR, "Include script lump %s not found", Includes[i].GetChars()); @@ -491,7 +491,7 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state) if (fileno == 0 && fileno2 != 0) { I_FatalError("File %s is overriding core lump %s.", - fileSystem.GetContainerFullName(fileSystem.GetFileContainer(lumpnum)), Includes[i].GetChars()); + fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(lumpnum)), Includes[i].GetChars()); } ParseSingleFile(nullptr, nullptr, lumpnum, parser, state); diff --git a/src/common/scripting/interface/vmnatives.cpp b/src/common/scripting/interface/vmnatives.cpp index 922f56a67e..2b57ceb25a 100644 --- a/src/common/scripting/interface/vmnatives.cpp +++ b/src/common/scripting/interface/vmnatives.cpp @@ -426,7 +426,7 @@ DEFINE_ACTION_FUNCTION(_TexMan, GetName) // Textures for full path names do not have their own name, they merely link to the source lump. auto lump = tex->GetSourceLump(); if (TexMan.GetLinkedTexture(lump) == tex) - retval = fileSystem.GetFileName(lump); + retval = fileSystem.GetFileFullName(lump); } } ACTION_RETURN_STRING(retval); @@ -799,7 +799,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(FFont, GetChar, ::GetChar) DEFINE_ACTION_FUNCTION(_Wads, GetNumLumps) { PARAM_PROLOGUE; - ACTION_RETURN_INT(fileSystem.GetFileCount()); + ACTION_RETURN_INT(fileSystem.GetNumEntries()); } DEFINE_ACTION_FUNCTION(_Wads, CheckNumForName) @@ -816,7 +816,7 @@ DEFINE_ACTION_FUNCTION(_Wads, CheckNumForFullName) { PARAM_PROLOGUE; PARAM_STRING(name); - ACTION_RETURN_INT(fileSystem.FindFile(name.GetChars())); + ACTION_RETURN_INT(fileSystem.CheckNumForFullName(name.GetChars())); } DEFINE_ACTION_FUNCTION(_Wads, FindLump) @@ -825,7 +825,7 @@ DEFINE_ACTION_FUNCTION(_Wads, FindLump) PARAM_STRING(name); PARAM_INT(startlump); PARAM_INT(ns); - const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetFileCount(); + const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetNumEntries(); ACTION_RETURN_INT(isLumpValid ? fileSystem.FindLump(name.GetChars(), &startlump, 0 != ns) : -1); } @@ -835,7 +835,7 @@ DEFINE_ACTION_FUNCTION(_Wads, FindLumpFullName) PARAM_STRING(name); PARAM_INT(startlump); PARAM_BOOL(noext); - const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetFileCount(); + const bool isLumpValid = startlump >= 0 && startlump < fileSystem.GetNumEntries(); ACTION_RETURN_INT(isLumpValid ? fileSystem.FindLumpFullName(name.GetChars(), &startlump, noext) : -1); } @@ -850,7 +850,7 @@ DEFINE_ACTION_FUNCTION(_Wads, GetLumpFullName) { PARAM_PROLOGUE; PARAM_INT(lump); - ACTION_RETURN_STRING(fileSystem.GetFileName(lump)); + ACTION_RETURN_STRING(fileSystem.GetFileFullName(lump)); } DEFINE_ACTION_FUNCTION(_Wads, GetLumpNamespace) @@ -864,7 +864,7 @@ DEFINE_ACTION_FUNCTION(_Wads, ReadLump) { PARAM_PROLOGUE; PARAM_INT(lump); - const bool isLumpValid = lump >= 0 && lump < fileSystem.GetFileCount(); + const bool isLumpValid = lump >= 0 && lump < fileSystem.GetNumEntries(); ACTION_RETURN_STRING(isLumpValid ? GetStringFromLump(lump, false) : FString()); } diff --git a/src/common/startscreen/endoom.cpp b/src/common/startscreen/endoom.cpp index 7f47829a12..6e8e7af353 100644 --- a/src/common/startscreen/endoom.cpp +++ b/src/common/startscreen/endoom.cpp @@ -153,14 +153,14 @@ int RunEndoom() return 0; } - int endoom_lump = fileSystem.CheckNumForAnyName (endoomName.GetChars()); + int endoom_lump = fileSystem.CheckNumForFullName (endoomName.GetChars(), true); if (endoom_lump < 0 || fileSystem.FileLength (endoom_lump) != 4000) { return 0; } - if (fileSystem.GetFileContainer(endoom_lump) == fileSystem.GetMaxBaseNum() && showendoom == 2) + if (fileSystem.GetFileContainer(endoom_lump) == fileSystem.GetMaxIwadNum() && showendoom == 2) { // showendoom==2 means to show only lumps from PWADs. return 0; diff --git a/src/common/startscreen/startscreen_generic.cpp b/src/common/startscreen/startscreen_generic.cpp index 4c41bc7a83..b76cbd3e25 100644 --- a/src/common/startscreen/startscreen_generic.cpp +++ b/src/common/startscreen/startscreen_generic.cpp @@ -72,7 +72,7 @@ FGenericStartScreen::FGenericStartScreen(int max_progress) : FStartScreen(max_progress) { // at this point we do not have a working texture manager yet, so we have to do the lookup via the file system - int startup_lump = fileSystem.CheckNumForName("BOOTLOGO", ns_graphics); + int startup_lump = fileSystem.CheckNumForName("BOOTLOGO", FileSys::ns_graphics); StartupBitmap.Create(640 * 2, 480 * 2); ClearBlock(StartupBitmap, { 0, 0, 0, 255 }, 0, 0, 640 * 2, 480 * 2); diff --git a/src/common/startscreen/startscreen_hexen.cpp b/src/common/startscreen/startscreen_hexen.cpp index 6eef735994..a82e21b351 100644 --- a/src/common/startscreen/startscreen_hexen.cpp +++ b/src/common/startscreen/startscreen_hexen.cpp @@ -81,9 +81,9 @@ FHexenStartScreen::FHexenStartScreen(int max_progress) : FStartScreen(max_progress) { // at this point we do not have a working texture manager yet, so we have to do the lookup via the file system - int startup_lump = fileSystem.CheckNumForName("STARTUP", ns_graphics); - int netnotch_lump = fileSystem.CheckNumForName("NETNOTCH", ns_graphics); - int notch_lump = fileSystem.CheckNumForName("NOTCH", ns_graphics); + int startup_lump = fileSystem.CheckNumForName("STARTUP", FileSys::ns_graphics); + int netnotch_lump = fileSystem.CheckNumForName("NETNOTCH", FileSys::ns_graphics); + int notch_lump = fileSystem.CheckNumForName("NOTCH", FileSys::ns_graphics); // For backwards compatibility we also need to look in the default namespace, because these were previously not handled as graphics. if (startup_lump == -1) startup_lump = fileSystem.CheckNumForName("STARTUP"); diff --git a/src/common/startscreen/startscreen_strife.cpp b/src/common/startscreen/startscreen_strife.cpp index 8f02b2022a..df5467f966 100644 --- a/src/common/startscreen/startscreen_strife.cpp +++ b/src/common/startscreen/startscreen_strife.cpp @@ -111,7 +111,7 @@ FStrifeStartScreen::FStrifeStartScreen(int max_progress) // Load the background and animated overlays. for (size_t i = 0; i < countof(StrifeStartupPicNames); ++i) { - int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i], ns_graphics); + int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i], FileSys::ns_graphics); if (lumpnum < 0) lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i]); if (lumpnum >= 0) diff --git a/src/common/textures/formats/pngtexture.cpp b/src/common/textures/formats/pngtexture.cpp index add80bfdff..01f210a1c5 100644 --- a/src/common/textures/formats/pngtexture.cpp +++ b/src/common/textures/formats/pngtexture.cpp @@ -119,12 +119,12 @@ FImageSource *PNGImage_TryCreate(FileReader & data, int lumpnum) if (compression != 0 || filter != 0 || interlace > 1) { - Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the compression, filter, or interlace is not supported!\n", fileSystem.GetFileName(lumpnum)); + Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the compression, filter, or interlace is not supported!\n", fileSystem.GetFileFullName(lumpnum)); return NULL; } if (!((1 << colortype) & 0x5D)) { - Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the colortype (%u) is not supported!\n", fileSystem.GetFileName(lumpnum), colortype); + Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the colortype (%u) is not supported!\n", fileSystem.GetFileFullName(lumpnum), colortype); return NULL; } if (!((1 << bitdepth) & 0x116)) @@ -150,12 +150,12 @@ FImageSource *PNGImage_TryCreate(FileReader & data, int lumpnum) int ihoty = data.ReadInt32BE(); if (ihotx < -32768 || ihotx > 32767) { - Printf("X-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileName(lumpnum), ihotx, ihotx); + Printf("X-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileFullName(lumpnum), ihotx, ihotx); ihotx = 0; } if (ihoty < -32768 || ihoty > 32767) { - Printf("Y-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileName(lumpnum), ihoty, ihoty); + Printf("Y-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileFullName(lumpnum), ihoty, ihoty); ihoty = 0; } tex->SetOffsets(ihotx, ihoty); @@ -169,7 +169,7 @@ FImageSource *PNGImage_TryCreate(FileReader & data, int lumpnum) return tex; } - Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the bit-depth (%u) is not supported!\n", fileSystem.GetFileName(lumpnum), bitdepth); + Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the bit-depth (%u) is not supported!\n", fileSystem.GetFileFullName(lumpnum), bitdepth); return NULL; } @@ -180,7 +180,7 @@ FImageSource *PNGImage_TryCreate(FileReader & data, int lumpnum) { if (data.Read(first4bytes.b, 4) != 4 || first4bytes.dw == MAKE_ID('I','E','N','D')) { - Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the file ends immediately after the IHDR.\n", fileSystem.GetFileName(lumpnum)); + Printf(TEXTCOLOR_YELLOW"WARNING: failed to load PNG %s: the file ends immediately after the IHDR.\n", fileSystem.GetFileFullName(lumpnum)); return NULL; } } @@ -231,12 +231,12 @@ FPNGTexture::FPNGTexture (FileReader &lump, int lumpnum, int width, int height, int ihoty = lump.ReadInt32BE(); if (ihotx < -32768 || ihotx > 32767) { - Printf ("X-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileName (lumpnum), ihotx, ihotx); + Printf ("X-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileFullName (lumpnum), ihotx, ihotx); ihotx = 0; } if (ihoty < -32768 || ihoty > 32767) { - Printf ("Y-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileName (lumpnum), ihoty, ihoty); + Printf ("Y-Offset for PNG texture %s is bad: %d (0x%08x)\n", fileSystem.GetFileFullName (lumpnum), ihoty, ihoty); ihoty = 0; } LeftOffset = ihotx; diff --git a/src/common/textures/gametexture.cpp b/src/common/textures/gametexture.cpp index 546a120056..755f48b49e 100644 --- a/src/common/textures/gametexture.cpp +++ b/src/common/textures/gametexture.cpp @@ -124,7 +124,7 @@ FGameTexture::~FGameTexture() bool FGameTexture::isUserContent() const { int filenum = fileSystem.GetFileContainer(Base->GetSourceLump()); - return (filenum > fileSystem.GetMaxBaseNum()); + return (filenum > fileSystem.GetMaxIwadNum()); } @@ -182,10 +182,10 @@ void FGameTexture::AddAutoMaterials() if (this->*(layer.pointer) == nullptr) // only if no explicit assignment had been done. { FStringf lookup("%s%s%s", layer.path, fullname ? "" : "auto/", searchname.GetChars()); - auto lump = fileSystem.FindFile(lookup.GetChars(), true); + auto lump = fileSystem.CheckNumForFullName(lookup.GetChars(), false, FileSys::ns_global, true); if (lump != -1) { - auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); + auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); if (bmtex != nullptr) { this->*(layer.pointer) = bmtex->GetTexture(); @@ -199,10 +199,10 @@ void FGameTexture::AddAutoMaterials() if (!this->Layers || this->Layers.get()->*(layer.pointer) == nullptr) // only if no explicit assignment had been done. { FStringf lookup("%s%s%s", layer.path, fullname ? "" : "auto/", searchname.GetChars()); - auto lump = fileSystem.FindFile(lookup.GetChars(), true); + auto lump = fileSystem.CheckNumForFullName(lookup.GetChars(), false, FileSys::ns_global, true); if (lump != -1) { - auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); + auto bmtex = TexMan.FindGameTexture(fileSystem.GetFileFullName(lump), ETextureType::Any, FTextureManager::TEXMAN_TryAny); if (bmtex != nullptr) { if (this->Layers == nullptr) this->Layers = std::make_unique(); diff --git a/src/common/textures/texturemanager.cpp b/src/common/textures/texturemanager.cpp index 7d27982031..1173f61be0 100644 --- a/src/common/textures/texturemanager.cpp +++ b/src/common/textures/texturemanager.cpp @@ -50,6 +50,7 @@ #include "basics.h" #include "cmdlib.h" +using namespace FileSys; FTextureManager TexMan; @@ -247,7 +248,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset if (strchr(name, '/') || (flags & TEXMAN_ForceLookup)) { FGameTexture *const NO_TEXTURE = (FGameTexture*)-1; // marker for lumps we already checked that do not map to a texture. - int lump = fileSystem.FindFile(name); + int lump = fileSystem.CheckNumForFullName(name); if (lump >= 0) { FGameTexture *tex = GetLinkedTexture(lump); @@ -394,7 +395,7 @@ bool FTextureManager::OkForLocalization(FTextureID texnum, const char *substitut // Mode 3 must also reject substitutions for non-IWAD content. int file = fileSystem.GetFileContainer(Textures[texnum.GetIndex()].Texture->GetSourceLump()); - if (file > fileSystem.GetMaxBaseNum()) return true; + if (file > fileSystem.GetMaxIwadNum()) return true; return false; } @@ -456,7 +457,7 @@ FTextureID FTextureManager::CreateTexture (int lumpnum, ETextureType usetype) str = fileSystem.GetFileShortName(lumpnum); else { - auto fn = fileSystem.GetFileName(lumpnum); + auto fn = fileSystem.GetFileFullName(lumpnum); str = ExtractFileBase(fn); } auto out = MakeGameTexture(CreateTextureFromLump(lumpnum, usetype == ETextureType::Flat), str.GetChars(), usetype); @@ -584,7 +585,7 @@ void FTextureManager::AddGroup(int wadnum, int ns, ETextureType usetype) } progressFunc(); } - else if (ns == ns_flats && fileSystem.GetFileNamespace(firsttx) == ns_maybeflat) + else if (ns == ns_flats && fileSystem.GetFileFlags(firsttx) & RESFF_MAYBEFLAT) { if (fileSystem.CheckNumForName(Name, ns) < firsttx) { @@ -722,8 +723,8 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build FName texname = sc.String; sc.MustGetString(); - int lumpnum = fileSystem.CheckNumForAnyName(sc.String, ns_patches); - if (lumpnum == -1) lumpnum = fileSystem.CheckNumForAnyName(sc.String, ns_graphics); + int lumpnum = fileSystem.CheckNumForFullName(sc.String, true, ns_patches); + if (lumpnum == -1) lumpnum = fileSystem.CheckNumForFullName(sc.String, true, ns_graphics); if (tlist.Size() == 0) { @@ -778,8 +779,8 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build { FString src = base.Left(8); - int lumpnum = fileSystem.CheckNumForAnyName(sc.String, ns_patches); - if (lumpnum == -1) lumpnum = fileSystem.CheckNumForAnyName(sc.String, ns_graphics); + int lumpnum = fileSystem.CheckNumForFullName(sc.String, true, ns_patches); + if (lumpnum == -1) lumpnum = fileSystem.CheckNumForFullName(sc.String, true, ns_graphics); sc.GetString(); bool is32bit = !!sc.Compare("force32bit"); @@ -853,7 +854,7 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build sc.MustGetString(); // This is not using sc.Open because it can print a more useful error message when done here - int includelump = fileSystem.CheckNumForAnyName(sc.String); + int includelump = fileSystem.CheckNumForFullName(sc.String, true); if (includelump == -1) { sc.ScriptError("Lump '%s' not found", sc.String); @@ -936,7 +937,7 @@ void FTextureManager::LoadTextureX(int wadnum, FMultipatchTextureBuilder &build) void FTextureManager::AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &build) { int firsttexture = Textures.Size(); - bool iwad = wadnum >= fileSystem.GetBaseNum() && wadnum <= fileSystem.GetMaxBaseNum(); + bool iwad = wadnum >= fileSystem.GetIwadNum() && wadnum <= fileSystem.GetMaxIwadNum(); FirstTextureForFile.Push(firsttexture); @@ -970,7 +971,7 @@ void FTextureManager::AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &b if (ns == ns_global) { // In Zips all graphics must be in a separate namespace. - if (fileSystem.GetFileFlags(i) & FileSys::RESFF_FULLPATH) continue; + if (fileSystem.GetFileFlags(i) & RESFF_FULLPATH) continue; // Ignore lumps with empty names. if (fileSystem.CheckFileName(i, "")) continue; @@ -1108,7 +1109,7 @@ void FTextureManager::SortTexturesByType(int start, int end) void FTextureManager::AddLocalizedVariants() { - std::vector content; + std::vector content; fileSystem.GetFilesInFolder("localized/textures/", content, false); for (auto &entry : content) { @@ -1217,7 +1218,7 @@ void FTextureManager::AddTextures(void (*progressFunc_)(), void (*checkForHacks) progressFunc = progressFunc_; //if (BuildTileFiles.Size() == 0) CountBuildTiles (); - int wadcnt = fileSystem.GetContainerCount(); + int wadcnt = fileSystem.GetNumWads(); FMultipatchTextureBuilder build(*this, progressFunc_, checkForHacks); @@ -1409,7 +1410,7 @@ int FTextureManager::GuesstimateNumTextures () { int numtex = 0; - for(int i = fileSystem.GetFileCount()-1; i>=0; i--) + for(int i = fileSystem.GetNumEntries()-1; i>=0; i--) { int space = fileSystem.GetFileNamespace(i); switch(space) @@ -1420,11 +1421,12 @@ int FTextureManager::GuesstimateNumTextures () case ns_hires: case ns_patches: case ns_graphics: - case ns_maybeflat: numtex++; break; default: + if (fileSystem.GetFileFlags(i) & RESFF_MAYBEFLAT) numtex++; + break; } } @@ -1445,7 +1447,7 @@ int FTextureManager::GuesstimateNumTextures () int FTextureManager::CountTexturesX () { int count = 0; - int wadcount = fileSystem.GetContainerCount(); + int wadcount = fileSystem.GetNumWads(); for (int wadnum = 0; wadnum < wadcount; wadnum++) { // Use the most recent PNAMES for this WAD. @@ -1503,16 +1505,16 @@ void FTextureManager::AdjustSpriteOffsets() int sprid; TMap donotprocess; - int numtex = fileSystem.GetFileCount(); + int numtex = fileSystem.GetNumEntries(); for (int i = 0; i < numtex; i++) { - if (fileSystem.GetFileContainer(i) > fileSystem.GetMaxBaseNum()) break; // we are past the IWAD - if (fileSystem.GetFileNamespace(i) == ns_sprites && fileSystem.GetFileContainer(i) >= fileSystem.GetBaseNum() && fileSystem.GetFileContainer(i) <= fileSystem.GetMaxBaseNum()) + if (fileSystem.GetFileContainer(i) > fileSystem.GetMaxIwadNum()) break; // we are past the IWAD + if (fileSystem.GetFileNamespace(i) == ns_sprites && fileSystem.GetFileContainer(i) >= fileSystem.GetIwadNum() && fileSystem.GetFileContainer(i) <= fileSystem.GetMaxIwadNum()) { const char *str = fileSystem.GetFileShortName(i); FTextureID texid = TexMan.CheckForTexture(str, ETextureType::Sprite, 0); - if (texid.isValid() && fileSystem.GetFileContainer(GetGameTexture(texid)->GetSourceLump()) > fileSystem.GetMaxBaseNum()) + if (texid.isValid() && fileSystem.GetFileContainer(GetGameTexture(texid)->GetSourceLump()) > fileSystem.GetMaxIwadNum()) { // This texture has been replaced by some PWAD. memcpy(&sprid, str, 4); @@ -1551,12 +1553,12 @@ void FTextureManager::AdjustSpriteOffsets() int lumpnum = tex->GetSourceLump(); // We only want to change texture offsets for sprites in the IWAD or the file this lump originated from. - if (lumpnum >= 0 && lumpnum < fileSystem.GetFileCount()) + if (lumpnum >= 0 && lumpnum < fileSystem.GetNumEntries()) { int wadno = fileSystem.GetFileContainer(lumpnum); - if ((iwadonly && wadno >= fileSystem.GetBaseNum() && wadno <= fileSystem.GetMaxBaseNum()) || (!iwadonly && wadno == ofslumpno)) + if ((iwadonly && wadno >= fileSystem.GetIwadNum() && wadno <= fileSystem.GetMaxIwadNum()) || (!iwadonly && wadno == ofslumpno)) { - if (wadno >= fileSystem.GetBaseNum() && wadno <= fileSystem.GetMaxBaseNum() && !forced && iwadonly) + if (wadno >= fileSystem.GetIwadNum() && wadno <= fileSystem.GetMaxIwadNum() && !forced && iwadonly) { memcpy(&sprid, tex->GetName().GetChars(), 4); if (donotprocess.CheckKey(sprid)) continue; // do not alter sprites that only get partially replaced. @@ -1630,7 +1632,7 @@ void FTextureManager::Listaliases() void FTextureManager::SetLinkedTexture(int lump, FGameTexture* tex) { - if (lump < fileSystem.GetFileCount()) + if (lump < fileSystem.GetNumEntries()) { linkedMap.Insert(lump, tex); } @@ -1644,7 +1646,7 @@ void FTextureManager::SetLinkedTexture(int lump, FGameTexture* tex) FGameTexture* FTextureManager::GetLinkedTexture(int lump) { - if (lump < fileSystem.GetFileCount()) + if (lump < fileSystem.GetNumEntries()) { auto check = linkedMap.CheckKey(lump); if (check) return *check; diff --git a/src/common/utility/palette.cpp b/src/common/utility/palette.cpp index cf9fbbe62f..03517c1ba5 100644 --- a/src/common/utility/palette.cpp +++ b/src/common/utility/palette.cpp @@ -672,7 +672,7 @@ FString V_GetColorStringByName(const char* name, FScriptPosition* sc) int c[3], step; size_t namelen; - if (fileSystem.GetFileCount() == 0) return FString(); + if (fileSystem.GetNumEntries() == 0) return FString(); rgblump = fileSystem.CheckNumForName("X11R6RGB"); if (rgblump == -1) @@ -960,13 +960,13 @@ int ReadPalette(int lumpnum, uint8_t* buffer) id = MAKE_ID('I', 'E', 'N', 'D'); fr.Read(&id, 4); } - I_Error("%s contains no palette", fileSystem.GetFileName(lumpnum)); + I_Error("%s contains no palette", fileSystem.GetFileFullName(lumpnum)); } if (memcmp(lumpmem, "JASC-PAL", 8) == 0) { FScanner sc; - sc.OpenMem(fileSystem.GetFileName(lumpnum), (char*)lumpmem, int(lump.size())); + sc.OpenMem(fileSystem.GetFileFullName(lumpnum), (char*)lumpmem, int(lump.size())); sc.MustGetString(); sc.MustGetNumber(); // version - ignore sc.MustGetNumber(); diff --git a/src/d_defcvars.cpp b/src/d_defcvars.cpp index 2784b6f82e..bcd8ad1940 100644 --- a/src/d_defcvars.cpp +++ b/src/d_defcvars.cpp @@ -46,7 +46,7 @@ void D_GrabCVarDefaults() while ((lump = fileSystem.FindLump("DEFCVARS", &lastlump)) != -1) { // don't parse from wads - if (lastlump > fileSystem.GetLastEntry(fileSystem.GetMaxBaseNum())) + if (lastlump > fileSystem.GetLastEntry(fileSystem.GetMaxIwadNum())) { // would rather put this in a modal of some sort, but this will have to do. Printf(TEXTCOLOR_RED "Cannot load DEFCVARS from a wadfile!\n"); diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index bc443ef8c1..6ce60d30b4 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -314,7 +314,7 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize, // Look for IWAD definition lump // //========================================================================== -void GetReserved(FileSys::FileSystemFilterInfo& lfi); +void GetReserved(FileSys::LumpFilterInfo& lfi); FIWadManager::FIWadManager(const char *firstfn, const char *optfn) { @@ -322,10 +322,10 @@ FIWadManager::FIWadManager(const char *firstfn, const char *optfn) std::vector fns; fns.push_back(firstfn); if (optfn) fns.push_back(optfn); - FileSys::FileSystemFilterInfo lfi; + FileSys::LumpFilterInfo lfi; GetReserved(lfi); - if (check.Initialize(fns, &lfi, nullptr)) + if (check.InitMultipleFiles(fns, &lfi, nullptr)) { // this is for the IWAD picker. As we have a filesystem open here that contains the base files, it is the easiest place to load the strings early. GStrings.LoadStrings(check, language); @@ -350,8 +350,7 @@ FIWadManager::FIWadManager(const char *firstfn, const char *optfn) int FIWadManager::ScanIWAD (const char *iwad) { FileSystem check; - std::vector list({ iwad }); - check.Initialize(list, nullptr); + check.InitSingleFile(iwad, nullptr); mLumpsFound.Resize(mIWadInfos.Size()); @@ -369,18 +368,19 @@ int FIWadManager::ScanIWAD (const char *iwad) } }; - if (check.GetFileCount() > 0) + if (check.GetNumEntries() > 0) { memset(&mLumpsFound[0], 0, mLumpsFound.Size() * sizeof(mLumpsFound[0])); - for(int ii = 0; ii < check.GetFileCount(); ii++) + for(int ii = 0; ii < check.GetNumEntries(); ii++) { - auto full = check.GetFileName(ii); + + CheckFileName(check.GetFileShortName(ii)); + auto full = check.GetFileFullName(ii, false); if (full && strnicmp(full, "maps/", 5) == 0) { FString mapname(&full[5], strcspn(&full[5], ".")); CheckFileName(mapname.GetChars()); } - else CheckFileName(full); } } for (unsigned i = 0; i< mIWadInfos.Size(); i++) @@ -404,11 +404,11 @@ int FIWadManager::CheckIWADInfo(const char* fn) { FileSystem check; - FileSys::FileSystemFilterInfo lfi; + FileSys::LumpFilterInfo lfi; GetReserved(lfi); std::vector filenames = { fn }; - if (check.Initialize(filenames, &lfi, nullptr)) + if (check.InitMultipleFiles(filenames, &lfi, nullptr)) { int num = check.CheckNumForName("IWADINFO"); if (num >= 0) @@ -829,14 +829,14 @@ int FIWadManager::IdentifyVersion (std::vector&wadfiles, const char iwadnum++; } - fileSystem.SetBaseNum(iwadnum); + fileSystem.SetIwadNum(iwadnum); if (picks[pick].mRequiredPath.IsNotEmpty()) { D_AddFile (wadfiles, picks[pick].mRequiredPath.GetChars(), true, -1, GameConfig); iwadnum++; } D_AddFile (wadfiles, picks[pick].mFullPath.GetChars(), true, -1, GameConfig); - fileSystem.SetMaxBaseNum(iwadnum); + fileSystem.SetMaxIwadNum(iwadnum); auto info = mIWadInfos[picks[pick].mInfoIndex]; diff --git a/src/d_main.cpp b/src/d_main.cpp index e3248c987d..0971c48d15 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -123,6 +123,8 @@ #include "i_system.h" // for SHARE_DIR #endif // __unix__ +using namespace FileSys; + EXTERN_CVAR(Bool, hud_althud) EXTERN_CVAR(Int, vr_mode) EXTERN_CVAR(Bool, cl_customizeinvulmap) @@ -1263,7 +1265,7 @@ void D_DoomLoop () } D_ErrorCleanup (); } - catch (const FileSys::FileSystemException& error) // in case this propagates up to here it should be treated as a recoverable error. + catch (const FileSystemException& error) // in case this propagates up to here it should be treated as a recoverable error. { if (error.what()) { @@ -1943,7 +1945,7 @@ static FString ParseGameInfo(std::vector &pwads, const char *fn, co return iwad; } -void GetReserved(FileSys::FileSystemFilterInfo& lfi) +void GetReserved(LumpFilterInfo& lfi) { lfi.reservedFolders = { "flats/", "textures/", "hires/", "sprites/", "voxels/", "colormaps/", "acs/", "maps/", "voices/", "patches/", "graphics/", "sounds/", "music/", "materials/", "models/", "fonts/", "brightmaps/" }; @@ -1955,18 +1957,18 @@ static FString CheckGameInfo(std::vector & pwads) { FileSystem check; - FileSys::FileSystemFilterInfo lfi; + LumpFilterInfo lfi; GetReserved(lfi); // Open the entire list as a temporary file system and look for a GAMEINFO lump. The last one will automatically win. - if (check.Initialize(pwads, &lfi, nullptr)) + if (check.InitMultipleFiles(pwads, &lfi, nullptr)) { int num = check.CheckNumForName("GAMEINFO"); if (num >= 0) { // Found one! auto data = check.ReadFile(num); - auto wadname = check.GetContainerName(check.GetFileContainer(num)); + auto wadname = check.GetResourceFileName(check.GetFileContainer(num)); return ParseGameInfo(pwads, wadname, data.string(), (int)data.size()); } } @@ -1981,9 +1983,9 @@ static FString CheckGameInfo(std::vector & pwads) static void SetMapxxFlag() { - int lump_name = fileSystem.CheckNumForName("MAP01", ns_global, fileSystem.GetBaseNum()); - int lump_wad = fileSystem.GetFileInContainer("maps/map01.wad", fileSystem.GetBaseNum()); - int lump_map = fileSystem.GetFileInContainer("maps/map01.map", fileSystem.GetBaseNum()); + int lump_name = fileSystem.CheckNumForName("MAP01", ns_global, fileSystem.GetIwadNum()); + int lump_wad = fileSystem.CheckNumForFullName("maps/map01.wad", fileSystem.GetIwadNum()); + int lump_map = fileSystem.CheckNumForFullName("maps/map01.map", fileSystem.GetIwadNum()); if (lump_name >= 0 || lump_wad >= 0 || lump_map >= 0) gameinfo.flags |= GI_MAPxx; } @@ -2248,48 +2250,48 @@ static void RenameSprites(FileSystem &fileSystem, const TArray& deletel bool MNTRZfound = false; const char* altbigfont = gameinfo.gametype == GAME_Strife ? "SBIGFONT" : (gameinfo.gametype & GAME_Raven) ? "HBIGFONT" : "DBIGFONT"; - static const char HereticRenames[][4] = - { {'H','E','A','D'}, {'L','I','C','H'}, // Ironlich + static const uint32_t HereticRenames[] = + { MAKE_ID('H','E','A','D'), MAKE_ID('L','I','C','H'), // Ironlich }; - static const char HexenRenames[][4] = - { {'B','A','R','L'}, {'Z','B','A','R'}, // ZBarrel - {'A','R','M','1'}, {'A','R','_','1'}, // MeshArmor - {'A','R','M','2'}, {'A','R','_','2'}, // FalconShield - {'A','R','M','3'}, {'A','R','_','3'}, // PlatinumHelm - {'A','R','M','4'}, {'A','R','_','4'}, // AmuletOfWarding - {'S','U','I','T'}, {'Z','S','U','I'}, // ZSuitOfArmor and ZArmorChunk - {'T','R','E','1'}, {'Z','T','R','E'}, // ZTree and ZTreeDead - {'T','R','E','2'}, {'T','R','E','S'}, // ZTreeSwamp150 - {'C','A','N','D'}, {'B','C','A','N'}, // ZBlueCandle - {'R','O','C','K'}, {'R','O','K','K'}, // rocks and dirt in a_debris.cpp - {'W','A','T','R'}, {'H','W','A','T'}, // Strife also has WATR - {'G','I','B','S'}, {'P','O','L','5'}, // RealGibs - {'E','G','G','M'}, {'P','R','K','M'}, // PorkFX - {'I','N','V','U'}, {'D','E','F','N'}, // Icon of the Defender + static const uint32_t HexenRenames[] = + { MAKE_ID('B','A','R','L'), MAKE_ID('Z','B','A','R'), // ZBarrel + MAKE_ID('A','R','M','1'), MAKE_ID('A','R','_','1'), // MeshArmor + MAKE_ID('A','R','M','2'), MAKE_ID('A','R','_','2'), // FalconShield + MAKE_ID('A','R','M','3'), MAKE_ID('A','R','_','3'), // PlatinumHelm + MAKE_ID('A','R','M','4'), MAKE_ID('A','R','_','4'), // AmuletOfWarding + MAKE_ID('S','U','I','T'), MAKE_ID('Z','S','U','I'), // ZSuitOfArmor and ZArmorChunk + MAKE_ID('T','R','E','1'), MAKE_ID('Z','T','R','E'), // ZTree and ZTreeDead + MAKE_ID('T','R','E','2'), MAKE_ID('T','R','E','S'), // ZTreeSwamp150 + MAKE_ID('C','A','N','D'), MAKE_ID('B','C','A','N'), // ZBlueCandle + MAKE_ID('R','O','C','K'), MAKE_ID('R','O','K','K'), // rocks and dirt in a_debris.cpp + MAKE_ID('W','A','T','R'), MAKE_ID('H','W','A','T'), // Strife also has WATR + MAKE_ID('G','I','B','S'), MAKE_ID('P','O','L','5'), // RealGibs + MAKE_ID('E','G','G','M'), MAKE_ID('P','R','K','M'), // PorkFX + MAKE_ID('I','N','V','U'), MAKE_ID('D','E','F','N'), // Icon of the Defender }; - static const char StrifeRenames[][4] = - { {'M','I','S','L'}, {'S','M','I','S'}, // lots of places - {'A','R','M','1'}, {'A','R','M','3'}, // MetalArmor - {'A','R','M','2'}, {'A','R','M','4'}, // LeatherArmor - {'P','M','A','P'}, {'S','M','A','P'}, // StrifeMap - {'T','L','M','P'}, {'T','E','C','H'}, // TechLampSilver and TechLampBrass - {'T','R','E','1'}, {'T','R','E','T'}, // TreeStub - {'B','A','R','1'}, {'B','A','R','C'}, // BarricadeColumn - {'S','H','T','2'}, {'M','P','U','F'}, // MaulerPuff - {'B','A','R','L'}, {'B','B','A','R'}, // StrifeBurningBarrel - {'T','R','C','H'}, {'T','R','H','L'}, // SmallTorchLit - {'S','H','R','D'}, {'S','H','A','R'}, // glass shards - {'B','L','S','T'}, {'M','A','U','L'}, // Mauler - {'L','O','G','G'}, {'L','O','G','W'}, // StickInWater - {'V','A','S','E'}, {'V','A','Z','E'}, // Pot and Pitcher - {'C','N','D','L'}, {'K','N','D','L'}, // Candle - {'P','O','T','1'}, {'M','P','O','T'}, // MetalPot - {'S','P','I','D'}, {'S','T','L','K'}, // Stalker + static const uint32_t StrifeRenames[] = + { MAKE_ID('M','I','S','L'), MAKE_ID('S','M','I','S'), // lots of places + MAKE_ID('A','R','M','1'), MAKE_ID('A','R','M','3'), // MetalArmor + MAKE_ID('A','R','M','2'), MAKE_ID('A','R','M','4'), // LeatherArmor + MAKE_ID('P','M','A','P'), MAKE_ID('S','M','A','P'), // StrifeMap + MAKE_ID('T','L','M','P'), MAKE_ID('T','E','C','H'), // TechLampSilver and TechLampBrass + MAKE_ID('T','R','E','1'), MAKE_ID('T','R','E','T'), // TreeStub + MAKE_ID('B','A','R','1'), MAKE_ID('B','A','R','C'), // BarricadeColumn + MAKE_ID('S','H','T','2'), MAKE_ID('M','P','U','F'), // MaulerPuff + MAKE_ID('B','A','R','L'), MAKE_ID('B','B','A','R'), // StrifeBurningBarrel + MAKE_ID('T','R','C','H'), MAKE_ID('T','R','H','L'), // SmallTorchLit + MAKE_ID('S','H','R','D'), MAKE_ID('S','H','A','R'), // glass shards + MAKE_ID('B','L','S','T'), MAKE_ID('M','A','U','L'), // Mauler + MAKE_ID('L','O','G','G'), MAKE_ID('L','O','G','W'), // StickInWater + MAKE_ID('V','A','S','E'), MAKE_ID('V','A','Z','E'), // Pot and Pitcher + MAKE_ID('C','N','D','L'), MAKE_ID('K','N','D','L'), // Candle + MAKE_ID('P','O','T','1'), MAKE_ID('M','P','O','T'), // MetalPot + MAKE_ID('S','P','I','D'), MAKE_ID('S','T','L','K'), // Stalker }; - const char (*renames)[4]; + const uint32_t* renames; int numrenames; switch (gameinfo.gametype) @@ -2317,7 +2319,7 @@ static void RenameSprites(FileSystem &fileSystem, const TArray& deletel break; } - unsigned NumFiles = fileSystem.GetFileCount(); + unsigned NumFiles = fileSystem.GetNumEntries(); for (uint32_t i = 0; i < NumFiles; i++) { @@ -2325,8 +2327,8 @@ static void RenameSprites(FileSystem &fileSystem, const TArray& deletel // some frames need to be renamed. if (fileSystem.GetFileNamespace(i) == ns_sprites) { - auto shortName = fileSystem.GetShortName(i); - if (!memcmp(shortName, "MNTRZ", 5)) + auto& shortName = fileSystem.GetShortName(i); + if (shortName.dword == MAKE_ID('M', 'N', 'T', 'R') && shortName.String[4] == 'Z') { MNTRZfound = true; break; @@ -2338,38 +2340,38 @@ static void RenameSprites(FileSystem &fileSystem, const TArray& deletel for (uint32_t i = 0; i < NumFiles; i++) { - auto shortName = fileSystem.GetShortName(i); + auto& shortName = fileSystem.GetShortName(i); if (fileSystem.GetFileNamespace(i) == ns_sprites) { // Only sprites in the IWAD normally get renamed - if (renameAll || fileSystem.GetFileContainer(i) == fileSystem.GetBaseNum()) + if (renameAll || fileSystem.GetFileContainer(i) == fileSystem.GetIwadNum()) { for (int j = 0; j < numrenames; ++j) { - if (!memcmp(shortName, &renames[j * 8], 4)) + if (shortName.dword == renames[j * 2]) { - memcpy(shortName, renames[j * 8 + 4], 4); + shortName.dword = renames[j * 2 + 1]; } } if (gameinfo.gametype == GAME_Hexen) { if (fileSystem.CheckFileName(i, "ARTIINVU")) { - shortName[4] = 'D'; shortName[5] = 'E'; - shortName[6] = 'F'; shortName[7] = 'N'; + shortName.String[4] = 'D'; shortName.String[5] = 'E'; + shortName.String[6] = 'F'; shortName.String[7] = 'N'; } } } if (!MNTRZfound) { - if (!memcmp(shortName, "MNTR", 4)) + if (shortName.dword == MAKE_ID('M', 'N', 'T', 'R')) { for (size_t fi : {4, 6}) { - if (shortName[fi] >= 'F' && shortName[fi] <= 'K') + if (shortName.String[fi] >= 'F' && shortName.String[fi] <= 'K') { - shortName[fi] += 'U' - 'F'; + shortName.String[fi] += 'U' - 'F'; } } } @@ -2379,23 +2381,23 @@ static void RenameSprites(FileSystem &fileSystem, const TArray& deletel // the same blood states can be used everywhere if (!(gameinfo.gametype & GAME_DoomChex)) { - if (!memcmp(shortName, "BLOD", 4)) + if (shortName.dword == MAKE_ID('B', 'L', 'O', 'D')) { - memcpy(shortName, "BLUD", 4); + shortName.dword = MAKE_ID('B', 'L', 'U', 'D'); } } } else if (fileSystem.GetFileNamespace(i) == ns_global) { int fn = fileSystem.GetFileContainer(i); - if (fn >= fileSystem.GetBaseNum() && fn <= fileSystem.GetMaxBaseNum() && deletelumps.Find(shortName) < deletelumps.Size()) + if (fn >= fileSystem.GetIwadNum() && fn <= fileSystem.GetMaxIwadNum() && deletelumps.Find(shortName.String) < deletelumps.Size()) { - shortName[0] = 0; // Lump must be deleted from directory. + shortName.String[0] = 0; // Lump must be deleted from directory. } // Rename the game specific big font lumps so that the font manager does not have to do problematic special checks for them. - else if (!strcmp(shortName, altbigfont)) + else if (!strcmp(shortName.String, altbigfont)) { - strcpy(shortName, "BIGFONT"); + strcpy(shortName.String, "BIGFONT"); } } } @@ -2431,8 +2433,8 @@ void RenameNerve(FileSystem& fileSystem) 0x70, 0xc2, 0xca, 0x36, 0xac, 0x65, 0xaf, 0x45 } }; size_t nervesize[numnerveversions] = { 3819855, 3821966, 3821885, 4003409 }; // NERVE.WAD's file size - int w = fileSystem.GetBaseNum(); - while (++w < fileSystem.GetContainerCount()) + int w = fileSystem.GetIwadNum(); + while (++w < fileSystem.GetNumWads()) { auto fr = fileSystem.GetFileReader(w); int isizecheck = -1; @@ -2465,16 +2467,18 @@ void RenameNerve(FileSystem& fileSystem) for (int i = fileSystem.GetFirstEntry(w); i <= fileSystem.GetLastEntry(w); i++) { - auto shortName = fileSystem.GetShortName(i); + auto& shortName = fileSystem.GetShortName(i); // Only rename the maps from NERVE.WAD - if (!memcmp(shortName, "CWILV", 5)) + if (shortName.dword == MAKE_ID('C', 'W', 'I', 'L')) { - shortName[0] = 'N'; + shortName.String[0] = 'N'; } - else if (!memcmp(shortName, "MAP0", 4)) + else if (shortName.dword == MAKE_ID('M', 'A', 'P', '0')) { - shortName[6] = shortName[4]; - memcpy(shortName, "LEVEL0", 6); + shortName.String[6] = shortName.String[4]; + shortName.String[5] = '0'; + shortName.String[4] = 'L'; + shortName.dword = MAKE_ID('L', 'E', 'V', 'E'); } } } @@ -2497,7 +2501,7 @@ void FixMacHexen(FileSystem& fileSystem) return; } - FileReader* reader = fileSystem.GetFileReader(fileSystem.GetBaseNum()); + FileReader* reader = fileSystem.GetFileReader(fileSystem.GetIwadNum()); auto iwadSize = reader->GetLength(); static const ptrdiff_t DEMO_SIZE = 13596228; @@ -2551,13 +2555,13 @@ void FixMacHexen(FileSystem& fileSystem) // Hexen Beta is very similar to Demo but it has MAP41: Maze at the end of the WAD // So keep this map if it's present but discard all extra lumps - const int lastLump = fileSystem.GetLastEntry(fileSystem.GetBaseNum()) - (isBeta ? 12 : 0); - assert(fileSystem.GetFirstEntry(fileSystem.GetBaseNum()) + 299 < lastLump); + const int lastLump = fileSystem.GetLastEntry(fileSystem.GetIwadNum()) - (isBeta ? 12 : 0); + assert(fileSystem.GetFirstEntry(fileSystem.GetIwadNum()) + 299 < lastLump); for (int i = lastLump - EXTRA_LUMPS + 1; i <= lastLump; ++i) { - auto shortName = fileSystem.GetShortName(i); - memcpy(shortName, "\0\0\0\0\0\0\0", 8); // these get compared with memcmp so all 8 bytes need to get cleared. + auto& shortName = fileSystem.GetShortName(i); + shortName.String[0] = '\0'; } } @@ -2565,24 +2569,24 @@ static void FindStrifeTeaserVoices(FileSystem& fileSystem) { if (gameinfo.gametype == GAME_Strife && gameinfo.flags & GI_SHAREWARE) { - unsigned NumFiles = fileSystem.GetFileCount(); + unsigned NumFiles = fileSystem.GetNumEntries(); for (uint32_t i = 0; i < NumFiles; i++) { - auto shortName = fileSystem.GetShortName(i); + auto& shortName = fileSystem.GetShortName(i); if (fileSystem.GetFileNamespace(i) == ns_global) { - // Strife teaser voices are not in the expected namespace. - if (fileSystem.GetFileContainer(i) == fileSystem.GetBaseNum()) + // Only sprites in the IWAD normally get renamed + if (fileSystem.GetFileContainer(i) == fileSystem.GetIwadNum()) { - if (shortName[0] == 'V' && - shortName[1] == 'O' && - shortName[2] == 'C') + if (shortName.String[0] == 'V' && + shortName.String[1] == 'O' && + shortName.String[2] == 'C') { int j; for (j = 3; j < 8; ++j) { - if (shortName[j] != 0 && !isdigit(shortName[j])) + if (shortName.String[j] != 0 && !isdigit(shortName.String[j])) break; } if (j == 8) @@ -2842,7 +2846,7 @@ void System_CrashInfo(char* buffer, size_t bufflen, const char *lfstr) buffer += snprintf(buffer, buffend - buffer, " %s", Args->GetArg(i)); } - for (i = 0; (arg = fileSystem.GetContainerName(i)) != NULL; ++i) + for (i = 0; (arg = fileSystem.GetResourceFileName(i)) != NULL; ++i) { buffer += mysnprintf(buffer, buffend - buffer, "%sWad %d: %s", lfstr, i, arg); } @@ -3044,7 +3048,7 @@ static bool FileNameCheck(const char* base, const char* path) return true; } -static int FileSystemPrintf(FileSys::FSMessageLevel level, const char* fmt, ...) +static int FileSystemPrintf(FSMessageLevel level, const char* fmt, ...) { va_list arg; va_start(arg, fmt); @@ -3052,22 +3056,22 @@ static int FileSystemPrintf(FileSys::FSMessageLevel level, const char* fmt, ...) text.VFormat(fmt, arg); switch (level) { - case FileSys::FSMessageLevel::Error: + case FSMessageLevel::Error: return Printf(TEXTCOLOR_RED "%s", text.GetChars()); break; - case FileSys::FSMessageLevel::Warning: + case FSMessageLevel::Warning: Printf(TEXTCOLOR_YELLOW "%s", text.GetChars()); break; - case FileSys::FSMessageLevel::Attention: + case FSMessageLevel::Attention: Printf(TEXTCOLOR_BLUE "%s", text.GetChars()); break; - case FileSys::FSMessageLevel::Message: + case FSMessageLevel::Message: Printf("%s", text.GetChars()); break; - case FileSys::FSMessageLevel::DebugWarn: + case FSMessageLevel::DebugWarn: DPrintf(DMSG_WARNING, "%s", text.GetChars()); break; - case FileSys::FSMessageLevel::DebugNotify: + case FSMessageLevel::DebugNotify: DPrintf(DMSG_NOTIFY, "%s", text.GetChars()); break; } @@ -3139,7 +3143,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector& allw if (!batchrun) Printf ("W_Init: Init WADfiles.\n"); - FileSys::FileSystemFilterInfo lfi; + LumpFilterInfo lfi; static const struct { int match; const char* name; } blanket[] = { @@ -3180,7 +3184,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector& allw ); bool allowduplicates = Args->CheckParm("-allowduplicates"); - if (!fileSystem.Initialize(allwads, &lfi, FileSystemPrintf, allowduplicates)) + if (!fileSystem.InitMultipleFiles(allwads, &lfi, FileSystemPrintf, allowduplicates)) { I_FatalError("FileSystem: no files found"); } @@ -3989,12 +3993,12 @@ void I_UpdateWindowTitle() CCMD(fs_dir) { - int numfiles = fileSystem.GetFileCount(); + int numfiles = fileSystem.GetNumEntries(); for (int i = 0; i < numfiles; i++) { - auto container = fileSystem.GetContainerFullName(fileSystem.GetFileContainer(i)); - auto fn1 = fileSystem.GetFileName(i); + auto container = fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(i)); + auto fn1 = fileSystem.GetFileFullName(i); auto fns = fileSystem.GetFileShortName(i); auto fnid = fileSystem.GetResourceId(i); auto length = fileSystem.FileLength(i); @@ -4006,7 +4010,7 @@ CCMD(fs_dir) CCMD(type) { if (argv.argc() < 2) return; - int lump = fileSystem.FindFile(argv[1]); + int lump = fileSystem.CheckNumForFullName(argv[1]); if (lump >= 0) { auto data = fileSystem.ReadFile(lump); diff --git a/src/g_dumpinfo.cpp b/src/g_dumpinfo.cpp index b377a78c13..99c4b6adf5 100644 --- a/src/g_dumpinfo.cpp +++ b/src/g_dumpinfo.cpp @@ -143,7 +143,7 @@ CCMD (mapchecksum) { if (argv.argc() == 1) { //current map - const char *wadname = fileSystem.GetContainerName(fileSystem.GetFileContainer(level.lumpnum)); + const char *wadname = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(level.lumpnum)); for (size_t i = 0; i < 16; ++i) { @@ -165,7 +165,7 @@ CCMD (mapchecksum) { if(!strcmp(argv[i], "*")) { - const char *wadname = fileSystem.GetContainerName(fileSystem.GetFileContainer(level.lumpnum)); + const char *wadname = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(level.lumpnum)); for (size_t i = 0; i < 16; ++i) { @@ -184,7 +184,7 @@ CCMD (mapchecksum) else { map->GetChecksum(cksum); - const char *wadname = fileSystem.GetContainerName(fileSystem.GetFileContainer(map->lumpnum)); + const char *wadname = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(map->lumpnum)); delete map; for (size_t j = 0; j < sizeof(cksum); ++j) { @@ -389,7 +389,7 @@ CCMD(targetinv) CCMD(listmaps) { - int iwadNum = fileSystem.GetBaseNum(); + int iwadNum = fileSystem.GetIwadNum(); for (unsigned i = 0; i < wadlevelinfos.Size(); i++) { @@ -403,7 +403,7 @@ CCMD(listmaps) if (argv.argc() == 1 || CheckWildcards(argv[1], info->MapName.GetChars()) || CheckWildcards(argv[1], info->LookupLevelName().GetChars()) - || CheckWildcards(argv[1], fileSystem.GetContainerName(mapWadNum))) + || CheckWildcards(argv[1], fileSystem.GetResourceFileName(mapWadNum))) { bool isFromPwad = mapWadNum != iwadNum; @@ -411,7 +411,7 @@ CCMD(listmaps) Printf("%s%s: '%s' (%s)\n", lineColor, info->MapName.GetChars(), info->LookupLevelName().GetChars(), - fileSystem.GetContainerName(mapWadNum)); + fileSystem.GetResourceFileName(mapWadNum)); } delete map; } diff --git a/src/g_game.cpp b/src/g_game.cpp index 4c1a366c04..f43642813f 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1915,7 +1915,7 @@ static bool CheckSingleWad (const char *name, bool &printRequires, bool printwar { return true; } - if (fileSystem.CheckIfContainerLoaded (name) < 0) + if (fileSystem.CheckIfResourceFileLoaded (name) < 0) { if (printwarn) { @@ -2311,11 +2311,11 @@ static void PutSaveWads (FSerializer &arc) const char *name; // Name of IWAD - name = fileSystem.GetContainerName (fileSystem.GetBaseNum()); + name = fileSystem.GetResourceFileName (fileSystem.GetIwadNum()); arc.AddString("Game WAD", name); // Name of wad the map resides in - name = fileSystem.GetContainerName (fileSystem.GetFileContainer (primaryLevel->lumpnum)); + name = fileSystem.GetResourceFileName (fileSystem.GetFileContainer (primaryLevel->lumpnum)); arc.AddString("Map WAD", name); } @@ -2909,7 +2909,7 @@ void G_DoPlayDemo (void) gameaction = ga_nothing; // [RH] Allow for demos not loaded as lumps - demolump = fileSystem.CheckNumForAnyName (defdemoname.GetChars()); + demolump = fileSystem.CheckNumForFullName (defdemoname.GetChars(), true); if (demolump >= 0) { int demolen = fileSystem.FileLength (demolump); diff --git a/src/g_statusbar/sbarinfo.cpp b/src/g_statusbar/sbarinfo.cpp index 78fa767443..82aba42631 100644 --- a/src/g_statusbar/sbarinfo.cpp +++ b/src/g_statusbar/sbarinfo.cpp @@ -445,7 +445,7 @@ void SBarInfo::Load() { if(gameinfo.statusbar.IsNotEmpty()) { - int lump = fileSystem.CheckNumForAnyName(gameinfo.statusbar.GetChars()); + int lump = fileSystem.CheckNumForFullName(gameinfo.statusbar.GetChars(), true); if(lump != -1) { if (!batchrun) Printf ("ParseSBarInfo: Loading default status bar definition.\n"); @@ -483,7 +483,7 @@ void SBarInfo::ParseSBarInfo(int lump) if(sc.TokenType == TK_Include) { sc.MustGetToken(TK_StringConst); - int lump = fileSystem.CheckNumForAnyName(sc.String); + int lump = fileSystem.CheckNumForFullName(sc.String, true); if (lump == -1) sc.ScriptError("Lump '%s' not found", sc.String); ParseSBarInfo(lump); @@ -500,15 +500,15 @@ void SBarInfo::ParseSBarInfo(int lump) sc.MustGetToken(TK_Identifier); if(sc.Compare("Doom")) { - baselump = fileSystem.FindFile("sbarinfo/doom.txt"); + baselump = fileSystem.CheckNumForFullName("sbarinfo/doom.txt", true); } else if(sc.Compare("Heretic")) { - baselump = fileSystem.FindFile("sbarinfo/heretic.txt"); + baselump = fileSystem.CheckNumForFullName("sbarinfo/heretic.txt", true); } else if(sc.Compare("Hexen")) { - baselump = fileSystem.FindFile("sbarinfo/hexen.txt"); + baselump = fileSystem.CheckNumForFullName("sbarinfo/hexen.txt", true); } else if(sc.Compare("Strife")) gameType = GAME_Strife; @@ -526,7 +526,7 @@ void SBarInfo::ParseSBarInfo(int lump) else if (fileSystem.GetFileContainer(baselump) > 0) { I_FatalError("File %s is overriding core lump sbarinfo/%s.txt.", - fileSystem.GetContainerFullName(fileSystem.GetFileContainer(baselump)), sc.String); + fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(baselump)), sc.String); } ParseSBarInfo(baselump); } diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index 2ab6a659cf..8ddcc79353 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -168,7 +168,7 @@ static void ReplaceSoundName(int index, const char* newname) if (snd == NO_SOUND) return; auto sfx = soundEngine->GetWritableSfx(snd); FStringf dsname("ds%s", newname); - sfx->lumpnum = fileSystem.CheckNumForName(dsname.GetChars(), ns_sounds); + sfx->lumpnum = fileSystem.CheckNumForName(dsname.GetChars(), FileSys::ns_sounds); sfx->bTentative = false; sfx->bRandomHeader = false; sfx->bLoadRAW = false; @@ -3098,7 +3098,7 @@ CVAR(Int, dehload, 0, CVAR_ARCHIVE) // Autoloading of .DEH lumps is disabled by // checks if lump is a .deh or .bex file. Only lumps in the root directory are considered valid. static bool isDehFile(int lumpnum) { - const char* const fullName = fileSystem.GetFileName(lumpnum); + const char* const fullName = fileSystem.GetFileFullName(lumpnum); const char* const extension = strrchr(fullName, '.'); return NULL != extension && strchr(fullName, '/') == NULL @@ -3113,12 +3113,12 @@ int D_LoadDehLumps(DehLumpSource source, int flags) { const int filenum = fileSystem.GetFileContainer(lumpnum); - if (FromIWAD == source && filenum > fileSystem.GetMaxBaseNum()) + if (FromIWAD == source && filenum > fileSystem.GetMaxIwadNum()) { // No more DEHACKED lumps in IWAD break; } - else if (FromPWADs == source && filenum <= fileSystem.GetMaxBaseNum()) + else if (FromPWADs == source && filenum <= fileSystem.GetMaxIwadNum()) { // Skip DEHACKED lumps from IWAD continue; @@ -3128,7 +3128,7 @@ int D_LoadDehLumps(DehLumpSource source, int flags) if((flags & DEH_SKIP_BEX_STRINGS_IF_LANGUAGE) && FromIWAD == source) { - int iwadnum = fileSystem.GetBaseNum(); + int iwadnum = fileSystem.GetIwadNum(); int lastlump2 = fileSystem.GetFirstEntry(iwadnum); int lumpnum2 = fileSystem.FindLump("LANGUAGE", &lastlump2); @@ -3146,7 +3146,7 @@ int D_LoadDehLumps(DehLumpSource source, int flags) if (dehload == 1) // load all .DEH lumps that are found. { - for (lumpnum = 0, lastlump = fileSystem.GetFileCount(); lumpnum < lastlump; ++lumpnum) + for (lumpnum = 0, lastlump = fileSystem.GetNumEntries(); lumpnum < lastlump; ++lumpnum) { if (isDehFile(lumpnum)) { @@ -3156,7 +3156,7 @@ int D_LoadDehLumps(DehLumpSource source, int flags) } else // only load the last .DEH lump that is found. { - for (lumpnum = fileSystem.GetFileCount()-1; lumpnum >=0; --lumpnum) + for (lumpnum = fileSystem.GetNumEntries()-1; lumpnum >=0; --lumpnum) { if (isDehFile(lumpnum)) { @@ -3205,7 +3205,7 @@ bool D_LoadDehFile(const char *patchfile, int flags) else { // Couldn't find it in the filesystem; try from a lump instead. - int lumpnum = fileSystem.FindFile(patchfile); + int lumpnum = fileSystem.CheckNumForFullName(patchfile, true); if (lumpnum < 0) { // Compatibility fallback. It's just here because diff --git a/src/gamedata/decallib.cpp b/src/gamedata/decallib.cpp index 2d3888a2fe..0f6e656b5f 100644 --- a/src/gamedata/decallib.cpp +++ b/src/gamedata/decallib.cpp @@ -397,7 +397,7 @@ void FDecalLib::ParseDecal (FScanner &sc) case DECAL_PIC: sc.MustGetString (); picnum = TexMan.CheckForTexture (sc.String, ETextureType::Any); - if (!picnum.Exists() && (lumpnum = fileSystem.CheckNumForName (sc.String, ns_graphics)) >= 0) + if (!picnum.Exists() && (lumpnum = fileSystem.CheckNumForName (sc.String, FileSys::ns_graphics)) >= 0) { picnum = TexMan.CreateTexture (lumpnum, ETextureType::Decal); } diff --git a/src/gamedata/doomfont.h b/src/gamedata/doomfont.h index fc1d113e15..fedeb513c4 100644 --- a/src/gamedata/doomfont.h +++ b/src/gamedata/doomfont.h @@ -18,9 +18,9 @@ void InitDoomFonts() if (fileSystem.CheckNumForName("FONTA_S") >= 0) { int wadfile = -1; - auto a = fileSystem.CheckNumForName("FONTA33", ns_graphics); + auto a = fileSystem.CheckNumForName("FONTA33", FileSys::ns_graphics); if (a != -1) wadfile = fileSystem.GetFileContainer(a); - if (wadfile > fileSystem.GetBaseNum()) + if (wadfile > fileSystem.GetIwadNum()) { // The font has been replaced, so we need to create a copy of the original as well. SmallFont = new FFont("SmallFont", "FONTA%02u", nullptr, HU_FONTSTART, HU_FONTSIZE, 1, -1); @@ -32,12 +32,12 @@ void InitDoomFonts() SmallFont->SetCursor('['); } } - else if (fileSystem.CheckNumForName("STCFN033", ns_graphics) >= 0) + else if (fileSystem.CheckNumForName("STCFN033", FileSys::ns_graphics) >= 0) { int wadfile = -1; - auto a = fileSystem.CheckNumForName("STCFN065", ns_graphics); + auto a = fileSystem.CheckNumForName("STCFN065", FileSys::ns_graphics); if (a != -1) wadfile = fileSystem.GetFileContainer(a); - if (wadfile > fileSystem.GetBaseNum()) + if (wadfile > fileSystem.GetIwadNum()) { // The font has been replaced, so we need to create a copy of the original as well. SmallFont = new FFont("SmallFont", "STCFN%.3d", nullptr, HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1, -1, false, false, true); @@ -55,7 +55,7 @@ void InitDoomFonts() OriginalSmallFont = new FFont("OriginalSmallFont", "FONTA%02u", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, 1, -1, -1, false, true); OriginalSmallFont->SetCursor('['); } - else if (fileSystem.CheckNumForName("STCFN033", ns_graphics) >= 0) + else if (fileSystem.CheckNumForName("STCFN033", FileSys::ns_graphics) >= 0) { OriginalSmallFont = new FFont("OriginalSmallFont", "STCFN%.3d", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1, -1, false, true, true); } @@ -63,7 +63,7 @@ void InitDoomFonts() if (!(SmallFont2 = V_GetFont("SmallFont2"))) // Only used by Strife { - if (fileSystem.CheckNumForName("STBFN033", ns_graphics) >= 0) + if (fileSystem.CheckNumForName("STBFN033", FileSys::ns_graphics) >= 0) { SmallFont2 = new FFont("SmallFont2", "STBFN%.3d", "defsmallfont2", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1); } diff --git a/src/gamedata/g_mapinfo.cpp b/src/gamedata/g_mapinfo.cpp index 82beedca36..22981062bd 100644 --- a/src/gamedata/g_mapinfo.cpp +++ b/src/gamedata/g_mapinfo.cpp @@ -941,12 +941,12 @@ void FMapInfoParser::ParseCluster() // Remap Hexen's CLUS?MSG lumps to the string table, if applicable. The code here only checks what can actually be in an IWAD. if (clusterinfo->flags & CLUSTER_EXITTEXTINLUMP) { - int lump = fileSystem.CheckNumForAnyName(clusterinfo->ExitText.GetChars()); + int lump = fileSystem.CheckNumForFullName(clusterinfo->ExitText.GetChars(), true); if (lump > 0) { // Check if this comes from either Hexen.wad or Hexdd.wad and if so, map to the string table. int fileno = fileSystem.GetFileContainer(lump); - auto fn = fileSystem.GetContainerName(fileno); + auto fn = fileSystem.GetResourceFileName(fileno); if (fn && (!stricmp(fn, "HEXEN.WAD") || !stricmp(fn, "HEXDD.WAD"))) { FStringf key("TXT_%.5s_%s", fn, clusterinfo->ExitText.GetChars()); @@ -2217,7 +2217,7 @@ level_info_t *FMapInfoParser::ParseMapHeader(level_info_t &defaultinfo) { // Try to localize Hexen's map names. This does not use the above feature to allow these names to be unique. int fileno = fileSystem.GetFileContainer(sc.LumpNum); - auto fn = fileSystem.GetContainerName(fileno); + auto fn = fileSystem.GetResourceFileName(fileno); if (fn && (!stricmp(fn, "HEXEN.WAD") || !stricmp(fn, "HEXDD.WAD"))) { FStringf key("TXT_%.5s_%s", fn, levelinfo->MapName.GetChars()); @@ -2447,7 +2447,7 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i if (sc.Compare("include")) { sc.MustGetString(); - int inclump = fileSystem.CheckNumForAnyName(sc.String); + int inclump = fileSystem.CheckNumForFullName(sc.String, true); if (inclump < 0) { sc.ScriptError("include file '%s' not found", sc.String); @@ -2458,7 +2458,7 @@ void FMapInfoParser::ParseMapInfo (int lump, level_info_t &gamedefaults, level_i if (fileSystem.GetFileContainer(sc.LumpNum) == 0) { I_FatalError("File %s is overriding core lump %s.", - fileSystem.GetContainerFullName(fileSystem.GetFileContainer(inclump)), sc.String); + fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(inclump)), sc.String); } } // use a new parser object to parse the include. Otherwise we'd have to save the entire FScanner in a local variable which is a lot more messy. @@ -2700,11 +2700,11 @@ void G_ParseMapInfo (FString basemapinfo) { FMapInfoParser parse; level_info_t defaultinfo; - int baselump = fileSystem.GetFile(basemapinfo.GetChars()); + int baselump = fileSystem.GetNumForFullName(basemapinfo.GetChars()); if (fileSystem.GetFileContainer(baselump) > 0) { I_FatalError("File %s is overriding core lump %s.", - fileSystem.GetContainerName(fileSystem.GetFileContainer(baselump)), basemapinfo.GetChars()); + fileSystem.GetResourceFileName(fileSystem.GetFileContainer(baselump)), basemapinfo.GetChars()); } parse.ParseMapInfo(baselump, gamedefaults, defaultinfo); } @@ -2725,7 +2725,7 @@ void G_ParseMapInfo (FString basemapinfo) // If that exists we need to skip this one. int wad = fileSystem.GetFileContainer(lump); - int altlump = fileSystem.CheckNumForName("ZMAPINFO", ns_global, wad, true); + int altlump = fileSystem.CheckNumForName("ZMAPINFO", FileSys::ns_global, wad, true); if (altlump >= 0) continue; } @@ -2733,9 +2733,9 @@ void G_ParseMapInfo (FString basemapinfo) { // MAPINFO and ZMAPINFO will override UMAPINFO if in the same WAD. int wad = fileSystem.GetFileContainer(lump); - int altlump = fileSystem.CheckNumForName("ZMAPINFO", ns_global, wad, true); + int altlump = fileSystem.CheckNumForName("ZMAPINFO", FileSys::ns_global, wad, true); if (altlump >= 0) continue; - altlump = fileSystem.CheckNumForName("MAPINFO", ns_global, wad, true); + altlump = fileSystem.CheckNumForName("MAPINFO", FileSys::ns_global, wad, true); if (altlump >= 0) continue; } if (nindex != 2) diff --git a/src/gamedata/statistics.cpp b/src/gamedata/statistics.cpp index 72fc3600b8..d374f2e8a3 100644 --- a/src/gamedata/statistics.cpp +++ b/src/gamedata/statistics.cpp @@ -468,7 +468,7 @@ void STAT_ChangeLevel(const char *newl, FLevelLocals *Level) wad = fileSystem.GetFileContainer(map->lumpnum); delete map; } - const char * name = fileSystem.GetContainerName(wad); + const char * name = fileSystem.GetResourceFileName(wad); FString section = ExtractFileBase(name) + "." + StartEpisode->mEpisodeMap; section.ToUpper(); diff --git a/src/gamedata/textures/buildloader.cpp b/src/gamedata/textures/buildloader.cpp index e3e6e04872..83c547b501 100644 --- a/src/gamedata/textures/buildloader.cpp +++ b/src/gamedata/textures/buildloader.cpp @@ -255,11 +255,11 @@ void InitBuildTiles() // Unfortunately neither the palettes nor the .ART files contain any usable identifying marker // so this can only go by the file names. - int numlumps = fileSystem.GetFileCount(); + int numlumps = fileSystem.GetNumEntries(); for (int i = 0; i < numlumps; i++) { - const char* name = fileSystem.GetFileName(i); - if (fileSystem.FindFile(name) != i) continue; // This palette is hidden by a later one. Do not process + const char* name = fileSystem.GetFileFullName(i); + if (fileSystem.CheckNumForFullName(name) != i) continue; // This palette is hidden by a later one. Do not process FString base = ExtractFileBase(name, true); base.ToLower(); if (base.Compare("palette.dat") == 0 && fileSystem.FileLength(i) >= 768) // must be a valid palette, i.e. at least 256 colors. @@ -276,7 +276,7 @@ void InitBuildTiles() // only read from the same source as the palette. // The entire format here is just too volatile to allow liberal mixing. // An .ART set must be treated as one unit. - lumpnum = fileSystem.GetFileInContainer(artpath.GetChars(), fileSystem.GetFileContainer(i)); + lumpnum = fileSystem.CheckNumForFullName(artpath.GetChars(), fileSystem.GetFileContainer(i)); if (lumpnum < 0) { break; diff --git a/src/gamedata/xlat/parsecontext.cpp b/src/gamedata/xlat/parsecontext.cpp index 1f0563aac3..0caa72f4b2 100644 --- a/src/gamedata/xlat/parsecontext.cpp +++ b/src/gamedata/xlat/parsecontext.cpp @@ -314,7 +314,7 @@ void FParseContext::ParseLump(const char *lumpname) const char *SavedSourceFile = SourceFile; FParseToken token; - int lumpno = fileSystem.CheckNumForAnyName(lumpname); + int lumpno = fileSystem.CheckNumForFullName(lumpname, true); if (lumpno == -1) { diff --git a/src/intermission/intermission_parse.cpp b/src/intermission/intermission_parse.cpp index 352943b07e..d1089526b2 100644 --- a/src/intermission/intermission_parse.cpp +++ b/src/intermission/intermission_parse.cpp @@ -303,13 +303,13 @@ bool FIntermissionActionTextscreen::ParseKey(FScanner &sc) { sc.MustGetToken('='); sc.MustGetToken(TK_StringConst); - int lump = fileSystem.CheckNumForAnyName(sc.String); + int lump = fileSystem.CheckNumForFullName(sc.String, true); bool done = false; if (lump > 0) { // Check if this comes from either Hexen.wad or Hexdd.wad and if so, map to the string table. int fileno = fileSystem.GetFileContainer(lump); - auto fn = fileSystem.GetContainerName(fileno); + auto fn = fileSystem.GetResourceFileName(fileno); if (fn && (!stricmp(fn, "HEXEN.WAD") || !stricmp(fn, "HEXDD.WAD"))) { FStringf key("TXT_%.5s_%s", fn, sc.String); @@ -325,7 +325,7 @@ bool FIntermissionActionTextscreen::ParseKey(FScanner &sc) else { // only print an error if coming from a PWAD - if (fileSystem.GetFileContainer(sc.LumpNum) > fileSystem.GetMaxBaseNum()) + if (fileSystem.GetFileContainer(sc.LumpNum) > fileSystem.GetMaxIwadNum()) sc.ScriptMessage("Unknown text lump '%s'", sc.String); mText.Format("Unknown text lump '%s'", sc.String); } @@ -861,7 +861,7 @@ DIntermissionController* F_StartFinale (const char *music, int musicorder, int c FIntermissionActionTextscreen *textscreen = new FIntermissionActionTextscreen; if (textInLump) { - int lump = fileSystem.CheckNumForAnyName(text); + int lump = fileSystem.CheckNumForFullName(text, true); if (lump > 0) { textscreen->mText = GetStringFromLump(lump); diff --git a/src/maploader/compatibility.cpp b/src/maploader/compatibility.cpp index 09de8b76cc..1ba18d444e 100644 --- a/src/maploader/compatibility.cpp +++ b/src/maploader/compatibility.cpp @@ -213,7 +213,7 @@ void ParseCompatibility() // The contents of this file are not cumulative, as it should not // be present in user-distributed maps. - FScanner sc(fileSystem.GetFile("compatibility.txt")); + FScanner sc(fileSystem.GetNumForFullName("compatibility.txt")); while (sc.GetString()) // Get MD5 signature { @@ -297,7 +297,7 @@ FName MapLoader::CheckCompatibility(MapData *map) // When playing Doom IWAD levels force BCOMPATF_NOSECTIONMERGE, COMPAT_SHORTTEX and COMPATF_LIGHT. // I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt. // TNT's MAP31 also needs COMPATF_STAIRINDEX but that only gets activated for TNT.WAD. - if (fileSystem.GetFileContainer(map->lumpnum) == fileSystem.GetBaseNum()) + if (fileSystem.GetFileContainer(map->lumpnum) == fileSystem.GetIwadNum()) { if ((gameinfo.flags & GI_COMPATSHORTTEX) && Level->maptype == MAPTYPE_DOOM) { diff --git a/src/maploader/edata.cpp b/src/maploader/edata.cpp index 3e89b7dfa2..044fb08115 100644 --- a/src/maploader/edata.cpp +++ b/src/maploader/edata.cpp @@ -520,7 +520,7 @@ void MapLoader::InitED() FScanner sc; if (filename.IsEmpty()) return; - int lump = fileSystem.CheckNumForAnyName(filename.GetChars(), ns_global); + int lump = fileSystem.CheckNumForFullName(filename.GetChars(), true, FileSys::ns_global); if (lump == -1) return; sc.OpenLumpNum(lump); diff --git a/src/maploader/glnodes.cpp b/src/maploader/glnodes.cpp index 6f4f6234ee..33051b6c12 100644 --- a/src/maploader/glnodes.cpp +++ b/src/maploader/glnodes.cpp @@ -727,17 +727,17 @@ static int FindGLNodesInWAD(int labellump) int wadfile = fileSystem.GetFileContainer(labellump); FString glheader; - glheader.Format("GL_%s", fileSystem.GetFileName(labellump)); + glheader.Format("GL_%s", fileSystem.GetFileFullName(labellump)); if (glheader.Len()<=8) { - int gllabel = fileSystem.CheckNumForName(glheader.GetChars(), ns_global, wadfile); + int gllabel = fileSystem.CheckNumForName(glheader.GetChars(), FileSys::ns_global, wadfile); if (gllabel >= 0) return gllabel; } else { // Before scanning the entire WAD directory let's check first whether // it is necessary. - int gllabel = fileSystem.CheckNumForName("GL_LEVEL", ns_global, wadfile); + int gllabel = fileSystem.CheckNumForName("GL_LEVEL", FileSys::ns_global, wadfile); if (gllabel >= 0) { @@ -748,7 +748,7 @@ static int FindGLNodesInWAD(int labellump) if (fileSystem.GetFileContainer(lump)==wadfile) { auto mem = fileSystem.ReadFile(lump); - if (MatchHeader(fileSystem.GetFileName(labellump), GetStringFromLump(lump).GetChars())) return lump; + if (MatchHeader(fileSystem.GetFileFullName(labellump), GetStringFromLump(lump).GetChars())) return lump; } } } @@ -853,7 +853,7 @@ bool MapLoader::LoadGLNodes(MapData * map) bool mapinwad = map->InWad; FResourceFile * f_gwa = map->resource; - const char * name = fileSystem.GetContainerFullName(lumpfile); + const char * name = fileSystem.GetResourceFileFullName(lumpfile); if (mapinwad) { @@ -881,7 +881,7 @@ bool MapLoader::LoadGLNodes(MapData * map) f_gwa = FResourceFile::OpenResourceFile(path); if (f_gwa==nullptr) return false; - strncpy(map->MapLumps[0].Name, fileSystem.GetFileName(map->lumpnum), 8); + strncpy(map->MapLumps[0].Name, fileSystem.GetFileFullName(map->lumpnum), 8); } } } diff --git a/src/maploader/strifedialogue.cpp b/src/maploader/strifedialogue.cpp index f7823aaf2f..ac92736218 100644 --- a/src/maploader/strifedialogue.cpp +++ b/src/maploader/strifedialogue.cpp @@ -159,7 +159,7 @@ bool MapLoader::LoadScriptFile (const char *name, bool include, int type) { int lumpnum = fileSystem.CheckNumForName (name); const bool found = lumpnum >= 0 - || (lumpnum = fileSystem.FindFile (name)) >= 0; + || (lumpnum = fileSystem.CheckNumForFullName (name)) >= 0; if (!found) { @@ -173,7 +173,7 @@ bool MapLoader::LoadScriptFile (const char *name, bool include, int type) FileReader lump = fileSystem.ReopenFileReader (lumpnum); auto fn = fileSystem.GetFileContainer(lumpnum); - auto wadname = fileSystem.GetContainerName(fn); + auto wadname = fileSystem.GetResourceFileName(fn); if (stricmp(wadname, "STRIFE0.WAD") && stricmp(wadname, "STRIFE1.WAD") && stricmp(wadname, "SVE.WAD")) name = nullptr; // Only localize IWAD content. bool res = LoadScriptFile(name, lumpnum, lump, fileSystem.FileLength(lumpnum), include, type); @@ -195,7 +195,7 @@ bool MapLoader::LoadScriptFile(const char *name, int lumpnum, FileReader &lump, if ((type == 1 && !isbinary) || (type == 2 && isbinary)) { - DPrintf(DMSG_ERROR, "Incorrect data format for conversation script in %s.\n", fileSystem.GetFileName(lumpnum)); + DPrintf(DMSG_ERROR, "Incorrect data format for conversation script in %s.\n", fileSystem.GetFileFullName(lumpnum)); return false; } @@ -215,7 +215,7 @@ bool MapLoader::LoadScriptFile(const char *name, int lumpnum, FileReader &lump, // is exactly 1516 bytes long. if (numnodes % 1516 != 0) { - DPrintf(DMSG_ERROR, "Incorrect data format for conversation script in %s.\n", fileSystem.GetFileName(lumpnum)); + DPrintf(DMSG_ERROR, "Incorrect data format for conversation script in %s.\n", fileSystem.GetFileFullName(lumpnum)); return false; } numnodes /= 1516; @@ -225,7 +225,7 @@ bool MapLoader::LoadScriptFile(const char *name, int lumpnum, FileReader &lump, // And the teaser version has 1488-byte entries. if (numnodes % 1488 != 0) { - DPrintf(DMSG_ERROR, "Incorrect data format for conversation script in %s.\n", fileSystem.GetFileName(lumpnum)); + DPrintf(DMSG_ERROR, "Incorrect data format for conversation script in %s.\n", fileSystem.GetFileFullName(lumpnum)); return false; } numnodes /= 1488; diff --git a/src/maploader/udmf.cpp b/src/maploader/udmf.cpp index f977c8051c..1fd9869c32 100644 --- a/src/maploader/udmf.cpp +++ b/src/maploader/udmf.cpp @@ -2481,7 +2481,7 @@ class UDMFParser : public UDMFParserBase isExtended = false; floordrop = false; - sc.OpenMem(fileSystem.GetFileName(map->lumpnum), map->Read(ML_TEXTMAP)); + sc.OpenMem(fileSystem.GetFileFullName(map->lumpnum), map->Read(ML_TEXTMAP)); sc.SetCMode(true); if (sc.CheckString("namespace")) { diff --git a/src/maploader/usdf.cpp b/src/maploader/usdf.cpp index ac5aaf5b9c..ed8bc4cfef 100644 --- a/src/maploader/usdf.cpp +++ b/src/maploader/usdf.cpp @@ -562,7 +562,7 @@ class USDFParser : public UDMFParserBase bool Parse(MapLoader *loader,int lumpnum, FileReader &lump, int lumplen) { Level = loader->Level; - sc.OpenMem(fileSystem.GetFileName(lumpnum), lump.Read(lumplen)); + sc.OpenMem(fileSystem.GetFileFullName(lumpnum), lump.Read(lumplen)); sc.SetCMode(true); // Namespace must be the first field because everything else depends on it. if (sc.CheckString("namespace")) diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index b843892b8d..f701083fca 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -116,7 +116,7 @@ void FSavegameManager::ReadSaveStrings() // old, incompatible savegame. List as not usable. oldVer = true; } - else if (iwad.CompareNoCase(fileSystem.GetContainerName(fileSystem.GetBaseNum())) == 0) + else if (iwad.CompareNoCase(fileSystem.GetResourceFileName(fileSystem.GetIwadNum())) == 0) { missing = !G_CheckSaveGameWads(arc, false); } diff --git a/src/p_openmap.cpp b/src/p_openmap.cpp index 34885a7468..ef688cda6b 100644 --- a/src/p_openmap.cpp +++ b/src/p_openmap.cpp @@ -140,9 +140,9 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) // Names with more than 8 characters will only be checked as .wad and .map. if (strlen(mapname) <= 8) lump_name = fileSystem.CheckNumForName(mapname); fmt.Format("maps/%s.wad", mapname); - lump_wad = fileSystem.FindFile(fmt.GetChars()); + lump_wad = fileSystem.CheckNumForFullName(fmt.GetChars()); fmt.Format("maps/%s.map", mapname); - lump_map = fileSystem.FindFile(fmt.GetChars()); + lump_map = fileSystem.CheckNumForFullName(fmt.GetChars()); if (lump_name > lump_wad && lump_name > lump_map && lump_name != -1) { @@ -167,18 +167,18 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) // This case can only happen if the lump is inside a real WAD file. // As such any special handling for other types of lumps is skipped. map->MapLumps[0].Reader = fileSystem.ReopenFileReader(lump_name); - strncpy(map->MapLumps[0].Name, fileSystem.GetFileName(lump_name), 8); + strncpy(map->MapLumps[0].Name, fileSystem.GetFileFullName(lump_name), 8); map->InWad = true; int index = 0; - if (stricmp(fileSystem.GetFileName(lump_name + 1), "TEXTMAP") != 0) + if (stricmp(fileSystem.GetFileFullName(lump_name + 1), "TEXTMAP") != 0) { for(int i = 1;; i++) { // Since levels must be stored in WADs they can't really have full // names and for any valid level lump this always returns the short name. - const char * lumpname = fileSystem.GetFileName(lump_name + i); + const char * lumpname = fileSystem.GetFileFullName(lump_name + i); try { index = GetMapIndex(mapname, index, lumpname, !justcheck); @@ -208,7 +208,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) map->MapLumps[1].Reader = fileSystem.ReopenFileReader(lump_name + 1); for(int i = 2;; i++) { - const char * lumpname = fileSystem.GetFileName(lump_name + i); + const char * lumpname = fileSystem.GetFileFullName(lump_name + i); if (lumpname == NULL) { @@ -264,7 +264,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) } map->lumpnum = lump_wad; auto reader = fileSystem.ReopenFileReader(lump_wad); - map->resource = FResourceFile::OpenResourceFile(fileSystem.GetFileName(lump_wad), reader, true); + map->resource = FResourceFile::OpenResourceFile(fileSystem.GetFileFullName(lump_wad), reader, true); wadReader = map->resource->GetContainerReader(); } } diff --git a/src/playsim/fragglescript/t_func.cpp b/src/playsim/fragglescript/t_func.cpp index b543a44477..f9fff1b9ef 100644 --- a/src/playsim/fragglescript/t_func.cpp +++ b/src/playsim/fragglescript/t_func.cpp @@ -54,6 +54,8 @@ #include "s_music.h" #include "texturemanager.h" +using namespace FileSys; + static FRandom pr_script("FScript"); // functions. FParser::SF_ means Script Function not, well.. heh, me diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index 7cbfceef42..89aee643d2 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -1930,7 +1930,7 @@ void FBehaviorContainer::LoadDefaultModules () FScanner sc(lump); while (sc.GetString()) { - int acslump = fileSystem.CheckNumForName (sc.String, ns_acslibrary); + int acslump = fileSystem.CheckNumForName (sc.String, FileSys::ns_acslibrary); if (acslump >= 0) { LoadModule (acslump); @@ -1963,7 +1963,7 @@ FBehavior *FBehaviorContainer::LoadModule (int lumpnum, FileReader *fr, int len, else { delete behavior; - Printf(TEXTCOLOR_RED "%s: invalid ACS module\n", fileSystem.GetFileName(lumpnum)); + Printf(TEXTCOLOR_RED "%s: invalid ACS module\n", fileSystem.GetFileFullName(lumpnum)); return NULL; } } @@ -2322,7 +2322,7 @@ bool FBehavior::Init(FLevelLocals *Level, int lumpnum, FileReader * fr, int len, if ((Level->flags2 & LEVEL2_HEXENHACK) && gameinfo.gametype == GAME_Hexen && lumpnum == -1 && reallumpnum > 0) { int fileno = fileSystem.GetFileContainer(reallumpnum); - const char * filename = fileSystem.GetContainerName(fileno); + const char * filename = fileSystem.GetResourceFileName(fileno); if (!stricmp(filename, "HEXEN.WAD") || !stricmp(filename, "HEXDD.WAD")) { ShouldLocalize = true; @@ -2567,7 +2567,7 @@ bool FBehavior::Init(FLevelLocals *Level, int lumpnum, FileReader * fr, int len, if (parse[i]) { FBehavior *module = NULL; - int lump = fileSystem.CheckNumForName (&parse[i], ns_acslibrary); + int lump = fileSystem.CheckNumForName (&parse[i], FileSys::ns_acslibrary); if (lump < 0) { Printf (TEXTCOLOR_RED "Could not find ACS library %s.\n", &parse[i]); diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 19e987fb5a..65f8929037 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -410,7 +410,7 @@ void player_t::SetLogNumber (int num) if (lumpnum != -1) { auto fn = fileSystem.GetFileContainer(lumpnum); - auto wadname = fileSystem.GetContainerName(fn); + auto wadname = fileSystem.GetResourceFileName(fn); if (!stricmp(wadname, "STRIFE0.WAD") || !stricmp(wadname, "STRIFE1.WAD") || !stricmp(wadname, "SVE.WAD")) { // If this is an original IWAD text, try looking up its lower priority string version first. @@ -874,16 +874,16 @@ static int SetupCrouchSprite(AActor *self, int crouchsprite) FString normspritename = sprites[self->SpawnState->sprite].name; FString crouchspritename = sprites[crouchsprite].name; - int spritenorm = fileSystem.CheckNumForName((normspritename + "A1").GetChars(), ns_sprites); + int spritenorm = fileSystem.CheckNumForName((normspritename + "A1").GetChars(), FileSys::ns_sprites); if (spritenorm == -1) { - spritenorm = fileSystem.CheckNumForName((normspritename + "A0").GetChars(), ns_sprites); + spritenorm = fileSystem.CheckNumForName((normspritename + "A0").GetChars(), FileSys::ns_sprites); } - int spritecrouch = fileSystem.CheckNumForName((crouchspritename + "A1").GetChars(), ns_sprites); + int spritecrouch = fileSystem.CheckNumForName((crouchspritename + "A1").GetChars(), FileSys::ns_sprites); if (spritecrouch == -1) { - spritecrouch = fileSystem.CheckNumForName((crouchspritename + "A0").GetChars(), ns_sprites); + spritecrouch = fileSystem.CheckNumForName((crouchspritename + "A0").GetChars(), FileSys::ns_sprites); } if (spritenorm == -1 || spritecrouch == -1) @@ -895,7 +895,7 @@ static int SetupCrouchSprite(AActor *self, int crouchsprite) int wadnorm = fileSystem.GetFileContainer(spritenorm); int wadcrouch = fileSystem.GetFileContainer(spritenorm); - if (wadnorm > fileSystem.GetMaxBaseNum() && wadcrouch <= fileSystem.GetMaxBaseNum()) + if (wadnorm > fileSystem.GetMaxIwadNum() && wadcrouch <= fileSystem.GetMaxIwadNum()) { // Question: Add an option / disable crouching or do what? return false; diff --git a/src/r_data/colormaps.cpp b/src/r_data/colormaps.cpp index a2298d22c1..4d9604b614 100644 --- a/src/r_data/colormaps.cpp +++ b/src/r_data/colormaps.cpp @@ -100,15 +100,15 @@ void R_InitColormaps (bool allowCustomColormap) cm.blend = 0; fakecmaps.Push(cm); - uint32_t NumLumps = fileSystem.GetFileCount(); + uint32_t NumLumps = fileSystem.GetNumEntries(); for (uint32_t i = 0; i < NumLumps; i++) { - if (fileSystem.GetFileNamespace(i) == ns_colormaps) + if (fileSystem.GetFileNamespace(i) == FileSys::ns_colormaps) { auto name = fileSystem.GetFileShortName(i); - if (fileSystem.CheckNumForName (name, ns_colormaps) == (int)i) + if (fileSystem.CheckNumForName (name, FileSys::ns_colormaps) == (int)i) { strncpy(cm.name, name, 8); cm.blend = 0; diff --git a/src/r_data/gldefs.cpp b/src/r_data/gldefs.cpp index c0af9fe609..d92b9daf68 100644 --- a/src/r_data/gldefs.cpp +++ b/src/r_data/gldefs.cpp @@ -134,7 +134,7 @@ static void ParseVavoomSkybox() sc.MustGetStringName("map"); sc.MustGetString(); - maplump = fileSystem.CheckNumForAnyName(sc.String); + maplump = fileSystem.CheckNumForFullName(sc.String, true); auto tex = TexMan.FindGameTexture(sc.String, ETextureType::Wall, FTextureManager::TEXMAN_TryAny); if (tex == NULL) @@ -1234,7 +1234,7 @@ class GLDefsParser if (lumpnum != -1) { - if (iwad && fileSystem.GetFileContainer(lumpnum) <= fileSystem.GetMaxBaseNum()) useme = true; + if (iwad && fileSystem.GetFileContainer(lumpnum) <= fileSystem.GetMaxIwadNum()) useme = true; if (thiswad && fileSystem.GetFileContainer(lumpnum) == fileSystem.GetFileContainer(workingLump)) useme = true; } if (!useme) return; @@ -1421,7 +1421,7 @@ class GLDefsParser if (lumpnum != -1) { - if (iwad && fileSystem.GetFileContainer(lumpnum) <= fileSystem.GetMaxBaseNum()) useme = true; + if (iwad && fileSystem.GetFileContainer(lumpnum) <= fileSystem.GetMaxIwadNum()) useme = true; if (thiswad && fileSystem.GetFileContainer(lumpnum) == fileSystem.GetFileContainer(workingLump)) useme = true; } if (!useme) return; @@ -1928,7 +1928,7 @@ class GLDefsParser { sc.MustGetString(); // This is not using sc.Open because it can print a more useful error message when done here - lump = fileSystem.CheckNumForAnyName(sc.String); + lump = fileSystem.CheckNumForFullName(sc.String, true); if (lump==-1) sc.ScriptError("Lump '%s' not found", sc.String); diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index 0028966e00..a13d569986 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -1050,7 +1050,7 @@ void ParseModelDefLump(int Lump) { sc.MustGetString(); // This is not using sc.Open because it can print a more useful error message when done here - int includelump = fileSystem.CheckNumForAnyName(sc.String); + int includelump = fileSystem.CheckNumForFullName(sc.String, true); if (includelump == -1) { if (strcmp(sc.String, "sentinel.modl") != 0) // Gene Tech mod has a broken #include statement diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index 93bb023b87..8b197cda7d 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -783,7 +783,7 @@ void R_ParseTrnslate() do { sc.MustGetToken(TK_StringConst); - int pallump = fileSystem.CheckNumForAnyName(sc.String, ns_global); + int pallump = fileSystem.CheckNumForFullName(sc.String, true, FileSys::ns_global); if (pallump >= 0) // { int start = 0; diff --git a/src/r_data/sprites.cpp b/src/r_data/sprites.cpp index 39978eca94..0a7be96a12 100644 --- a/src/r_data/sprites.cpp +++ b/src/r_data/sprites.cpp @@ -344,12 +344,12 @@ void R_InitSpriteDefs () } // Repeat, for voxels - vmax = fileSystem.GetFileCount(); + vmax = fileSystem.GetNumEntries(); TArray vhashes(vmax, true); memset(vhashes.Data(), -1, sizeof(VHasher)*vmax); for (i = 0; i < vmax; ++i) { - if (fileSystem.GetFileNamespace(i) == ns_voxels) + if (fileSystem.GetFileNamespace(i) == FileSys::ns_voxels) { size_t namelen; int spin; @@ -588,7 +588,7 @@ void R_InitSkins (void) { // The player sprite has 23 frames. This means that the S_SKIN // marker needs a minimum of 23 lumps after it. - if (base >= fileSystem.GetFileCount() - 23 || base == -1) + if (base >= fileSystem.GetNumEntries() - 23 || base == -1) continue; i++; @@ -715,7 +715,7 @@ void R_InitSkins (void) int lump = fileSystem.CheckNumForName (sc.String, Skins[i].namespc); if (lump == -1) { - lump = fileSystem.CheckNumForAnyName (sc.String, ns_sounds); + lump = fileSystem.CheckNumForFullName (sc.String, true, FileSys::ns_sounds); } if (lump != -1) { @@ -748,7 +748,7 @@ void R_InitSkins (void) sndlumps[j] = fileSystem.CheckNumForName (sc.String, Skins[i].namespc); if (sndlumps[j] == -1) { // Replacement not found, try finding it in the global namespace - sndlumps[j] = fileSystem.CheckNumForAnyName (sc.String, ns_sounds); + sndlumps[j] = fileSystem.CheckNumForFullName (sc.String, true, FileSys::ns_sounds); } } } @@ -946,7 +946,7 @@ CCMD (skins) static void R_CreateSkinTranslation (const char *palname) { - auto lump = fileSystem.ReadFile (fileSystem.GetNumForName(palname)); + auto lump = fileSystem.ReadFile (palname); auto otherPal = lump.bytes(); for (int i = 0; i < 256; ++i) @@ -1016,7 +1016,7 @@ void R_InitSprites () Skins[i].range0end = basetype->IntVar(NAME_ColorRangeEnd); Skins[i].Scale = basetype->Scale; Skins[i].sprite = basetype->SpawnState->sprite; - Skins[i].namespc = ns_global; + Skins[i].namespc = FileSys::ns_global; PlayerClasses[i].Skins.Push (i); diff --git a/src/r_data/v_palette.cpp b/src/r_data/v_palette.cpp index 977206c78a..8af454445d 100644 --- a/src/r_data/v_palette.cpp +++ b/src/r_data/v_palette.cpp @@ -44,6 +44,8 @@ #include "m_png.h" #include "v_colortables.h" +using namespace FileSys; + /* Current color blending values */ int BlendR, BlendG, BlendB, BlendA; @@ -62,7 +64,7 @@ void InitPalette () if (lump == -1) lump = fileSystem.CheckNumForName("COLORMAP", ns_colormaps); if (lump != -1) { - auto cmap = fileSystem.ReadFile(lump); + FileData cmap = fileSystem.ReadFile(lump); auto cmapdata = cmap.bytes(); GPalette.GenerateGlobalBrightmapFromColormap(cmapdata, 32); MakeGoodRemap((uint32_t*)GPalette.BaseColors, GPalette.Remap, cmapdata + 7936); // last entry in colormap diff --git a/src/r_data/voxeldef.cpp b/src/r_data/voxeldef.cpp index 14f3c8db11..a2eee3c35f 100644 --- a/src/r_data/voxeldef.cpp +++ b/src/r_data/voxeldef.cpp @@ -50,6 +50,8 @@ #include "g_level.h" #include "r_data/sprites.h" +using namespace FileSys; + struct VoxelOptions { int DroppedSpin = 0; @@ -280,7 +282,7 @@ void R_InitVoxels() sc.SetCMode(true); sc.MustGetToken(TK_StringConst); - voxelfile = fileSystem.CheckNumForAnyName(sc.String, ns_voxels); + voxelfile = fileSystem.CheckNumForFullName(sc.String, true, ns_voxels); if (voxelfile < 0) { sc.ScriptMessage("Voxel \"%s\" not found.\n", sc.String); diff --git a/src/rendering/swrenderer/r_swcolormaps.cpp b/src/rendering/swrenderer/r_swcolormaps.cpp index e027eaf479..1ff95c8b31 100644 --- a/src/rendering/swrenderer/r_swcolormaps.cpp +++ b/src/rendering/swrenderer/r_swcolormaps.cpp @@ -346,12 +346,12 @@ void SetDefaultColormap (const char *name) uint8_t unremap[256]; uint8_t remap[256]; - lump = fileSystem.CheckNumForAnyName (name, ns_colormaps); + lump = fileSystem.CheckNumForFullName (name, true, FileSys::ns_colormaps); if (lump == -1) - lump = fileSystem.CheckNumForName (name, ns_global); + lump = fileSystem.CheckNumForName (name, FileSys::ns_global); // [RH] If using BUILD's palette, generate the colormap - if (lump == -1 || fileSystem.FindFile("palette.dat") >= 0 || fileSystem.FindFile("blood.pal") >= 0) + if (lump == -1 || fileSystem.CheckNumForFullName("palette.dat") >= 0 || fileSystem.CheckNumForFullName("blood.pal") >= 0) { DPrintf (DMSG_NOTIFY, "Make colormap\n"); FDynamicColormap foo; @@ -403,7 +403,7 @@ static void InitBoomColormaps () // This is a really rough hack, but it's better than // not doing anything with them at all (right?) - uint32_t NumLumps = fileSystem.GetFileCount(); + uint32_t NumLumps = fileSystem.GetNumEntries(); realcolormaps.Maps = new uint8_t[256*NUMCOLORMAPS*fakecmaps.Size()]; SetDefaultColormap ("COLORMAP"); diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 6014b7e984..03a249814d 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -1282,11 +1282,11 @@ void ParseDecorate (FScanner &sc, PNamespace *ns) // This check needs to remain overridable for testing purposes. if (fileSystem.GetFileContainer(sc.LumpNum) == 0 && !Args->CheckParm("-allowdecoratecrossincludes")) { - int includefile = fileSystem.GetFileContainer(fileSystem.CheckNumForAnyName(sc.String)); + int includefile = fileSystem.GetFileContainer(fileSystem.CheckNumForFullName(sc.String, true)); if (includefile != 0) { I_FatalError("File %s is overriding core lump %s.", - fileSystem.GetContainerFullName(includefile), sc.String); + fileSystem.GetResourceFileFullName(includefile), sc.String); } } FScanner newscanner; diff --git a/src/sound/s_advsound.cpp b/src/sound/s_advsound.cpp index a3592dfcce..8717c4b9eb 100644 --- a/src/sound/s_advsound.cpp +++ b/src/sound/s_advsound.cpp @@ -51,6 +51,8 @@ #include "s_music.h" #include "i_music.h" +using namespace FileSys; + // MACROS ------------------------------------------------------------------ #define RANDOM 1 @@ -414,7 +416,7 @@ DEFINE_ACTION_FUNCTION(DObject,S_GetLength) FSoundID S_AddSound (const char *logicalname, const char *lumpname, FScanner *sc) { - int lump = fileSystem.CheckNumForAnyName (lumpname, ns_sounds); + int lump = fileSystem.CheckNumForFullName (lumpname, true, ns_sounds); return S_AddSound (logicalname, lump); } @@ -480,7 +482,7 @@ FSoundID S_AddPlayerSound (const char *pclass, int gender, FSoundID refid, const if (lumpname) { - lump = fileSystem.CheckNumForAnyName (lumpname, ns_sounds); + lump = fileSystem.CheckNumForFullName (lumpname, true, ns_sounds); } return S_AddPlayerSound (pclass, gender, refid, lump); @@ -594,7 +596,7 @@ void S_ParseSndInfo (bool redefine) CurrentPitchMask = 0; S_AddSound ("{ no sound }", "DSEMPTY"); // Sound 0 is no sound at all - for (lump = 0; lump < fileSystem.GetFileCount(); ++lump) + for (lump = 0; lump < fileSystem.GetNumEntries(); ++lump) { switch (fileSystem.GetFileNamespace (lump)) { @@ -1058,7 +1060,7 @@ static void S_AddSNDINFO (int lump) int file = fileSystem.GetFileContainer(lump); int sndifile = fileSystem.GetFileContainer(sc.LumpNum); if ( (file > sndifile) && - !(sndifile <= fileSystem.GetBaseNum() && file <= fileSystem.GetBaseNum()) ) + !(sndifile <= fileSystem.GetIwadNum() && file <= fileSystem.GetIwadNum()) ) { sc.MustGetString(); continue; @@ -1069,7 +1071,7 @@ static void S_AddSNDINFO (int lump) FName mapped = sc.String; // only set the alias if the lump it maps to exists. - if (mapped == NAME_None || fileSystem.CheckNumForAnyName(sc.String, ns_music) >= 0) + if (mapped == NAME_None || fileSystem.CheckNumForFullName(sc.String, true, ns_music) >= 0) { MusicAliases[alias] = mapped; } diff --git a/src/sound/s_doomsound.cpp b/src/sound/s_doomsound.cpp index cc256a17e8..749b1f5e79 100644 --- a/src/sound/s_doomsound.cpp +++ b/src/sound/s_doomsound.cpp @@ -185,8 +185,8 @@ static FString LookupMusic(const char* musicname, int& order) static int FindMusic(const char* musicname) { - int lumpnum = fileSystem.FindFile(musicname); - if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(musicname, ns_music); + int lumpnum = fileSystem.CheckNumForFullName(musicname); + if (lumpnum == -1) lumpnum = fileSystem.CheckNumForName(musicname, FileSys::ns_music); return lumpnum; } @@ -295,7 +295,7 @@ void S_Start() if (LocalSndInfo.IsNotEmpty()) { // Now parse the local SNDINFO - int j = fileSystem.CheckNumForAnyName(LocalSndInfo.GetChars()); + int j = fileSystem.CheckNumForFullName(LocalSndInfo.GetChars(), true); if (j >= 0) S_AddLocalSndInfo(j); } @@ -309,7 +309,7 @@ void S_Start() if (parse_ss) { - S_ParseSndSeq(LocalSndSeq.IsNotEmpty() ? fileSystem.CheckNumForAnyName(LocalSndSeq.GetChars()) : -1); + S_ParseSndSeq(LocalSndSeq.IsNotEmpty() ? fileSystem.CheckNumForFullName(LocalSndSeq.GetChars(), true) : -1); } LastLocalSndInfo = LocalSndInfo; diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 53d0793180..3af0a7829a 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -517,7 +517,7 @@ bool DInterBackground::LoadBackground(bool isenterpic) { try { - int lumpnum = fileSystem.CheckNumForAnyName(lumpname); + int lumpnum = fileSystem.CheckNumForFullName(lumpname, true); if (lumpnum == -1) { I_Error("Intermission animation lump %s not found!", lumpname); @@ -757,7 +757,7 @@ bool DInterBackground::LoadBackground(bool isenterpic) } else { - int lumpnum = fileSystem.CheckNumForAnyName(lumpname + 1); + int lumpnum = fileSystem.CheckNumForFullName(lumpname + 1, true); if (lumpnum >= 0) { FScanner sc(lumpnum); From 3efaca262dcacb62dbf9e9c9bcf5824432a9d44b Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 27 Aug 2024 12:28:34 -0400 Subject: [PATCH 20/34] - address adaptive sync flicker issue (disables 35 fps cap during game pause) --- src/d_net.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/d_net.cpp b/src/d_net.cpp index c7241c3a8b..f4303ff876 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -150,6 +150,8 @@ static int oldentertics; extern bool advancedemo; +CVAR(Bool, vid_dontdowait, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) + CVAR(Bool, net_ticbalance, false, CVAR_SERVERINFO | CVAR_NOSAVE) CUSTOM_CVAR(Int, net_extratic, 0, CVAR_SERVERINFO | CVAR_NOSAVE) { @@ -1878,6 +1880,9 @@ void TryRunTics (void) bool doWait = (cl_capfps || pauseext || (r_NoInterpolate && !M_IsAnimated())); + if (vid_dontdowait) + doWait = false; + // get real tics if (doWait) { From 6f927d60c8092735b06b69a9f72059b887d111d7 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 4 Jan 2025 12:19:54 -0500 Subject: [PATCH 21/34] - don't allow `vid_dontdowait` if neither `vid_vsync` is true nor `vid_maxfps` is set, in order to prevent coil whine --- src/d_net.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/d_net.cpp b/src/d_net.cpp index f4303ff876..d7eb63bd5b 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -75,7 +75,9 @@ EXTERN_CVAR (Int, disableautosave) EXTERN_CVAR (Int, autosavecount) -EXTERN_CVAR(Bool, cl_capfps) +EXTERN_CVAR (Bool, cl_capfps) +EXTERN_CVAR (Bool, vid_vsync) +EXTERN_CVAR (Int, vid_maxfps) //#define SIMULATEERRORS (RAND_MAX/3) #define SIMULATEERRORS 0 @@ -1880,7 +1882,7 @@ void TryRunTics (void) bool doWait = (cl_capfps || pauseext || (r_NoInterpolate && !M_IsAnimated())); - if (vid_dontdowait) + if (vid_dontdowait && ((vid_maxfps > 0) || (vid_vsync == true))) doWait = false; // get real tics From af8838d45ad314fb453a85c1063e98a98e47eabf Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 29 Nov 2024 07:47:16 -0500 Subject: [PATCH 22/34] Added interpolation to crosshair size --- src/d_main.cpp | 2 +- src/g_statusbar/sbar.h | 4 ++-- src/g_statusbar/shared_sbar.cpp | 11 +++++++---- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 0971c48d15..34ae5b3696 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1040,7 +1040,7 @@ void D_Display () if (DrawFSHUD || automapactive) StatusBar->DrawAltHUD(); if (players[consoleplayer].camera && players[consoleplayer].camera->player && !automapactive) { - StatusBar->DrawCrosshair(); + StatusBar->DrawCrosshair(vp.TicFrac); } StatusBar->CallDraw (HUD_AltHud, vp.TicFrac); StatusBar->DrawTopStuff (HUD_AltHud); diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index a1fa6926c9..bffa1a823c 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -427,14 +427,14 @@ class DBaseStatusBar : public DStatusBarCore public: AActor *ValidateInvFirst (int numVisible) const; - void DrawCrosshair (); + void DrawCrosshair (double ticFrac); // Sizing info for ths status bar. bool Scaled; // This needs to go away. bool Centering; bool FixedOrigin; - double CrosshairSize; + double PrevCrosshairSize, CrosshairSize; double Displacement; bool ShowLog; int artiflashTick = 0; diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index de125725b9..5890fd58f9 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -388,7 +388,7 @@ DBaseStatusBar::DBaseStatusBar () CompleteBorder = false; Centering = false; FixedOrigin = false; - CrosshairSize = 1.; + CrosshairSize = PrevCrosshairSize = 1.; memset(Messages, 0, sizeof(Messages)); Displacement = 0; CPlayer = NULL; @@ -679,6 +679,8 @@ int DBaseStatusBar::GetPlayer () void DBaseStatusBar::Tick () { + PrevCrosshairSize = CrosshairSize; + for (size_t i = 0; i < countof(Messages); ++i) { DHUDMessageBase *msg = Messages[i]; @@ -988,7 +990,7 @@ void DBaseStatusBar::RefreshBackground () const // //--------------------------------------------------------------------------- -void DBaseStatusBar::DrawCrosshair () +void DBaseStatusBar::DrawCrosshair (double ticFrac) { if (!crosshairon) { @@ -1010,7 +1012,8 @@ void DBaseStatusBar::DrawCrosshair () } int health = Scale(CPlayer->health, 100, CPlayer->mo->GetDefault()->health); - ST_DrawCrosshair(health, viewwidth / 2 + viewwindowx, viewheight / 2 + viewwindowy, CrosshairSize); + const double size = PrevCrosshairSize * (1.0 - ticFrac) + CrosshairSize * ticFrac; + ST_DrawCrosshair(health, viewwidth / 2 + viewwindowx, viewheight / 2 + viewwindowy, size); } //--------------------------------------------------------------------------- @@ -1082,7 +1085,7 @@ void DBaseStatusBar::Draw (EHudState state, double ticFrac) { if (CPlayer && CPlayer->camera && CPlayer->camera->player) { - DrawCrosshair (); + DrawCrosshair (ticFrac); } } else if (automapactive) From 22690bbb7635e46f14c3f40a90b602cb64cc6e28 Mon Sep 17 00:00:00 2001 From: Eonfge <33983090+Eonfge@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:50:43 +0100 Subject: [PATCH 23/34] Fix fatal error formatting Based on this patch: https://aur.archlinux.org/cgit/aur.git/tree/0002-fix-format-security-error.patch?h=gzdoom --- src/common/engine/i_net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/engine/i_net.cpp b/src/common/engine/i_net.cpp index ad106bbc4a..0a67062a01 100644 --- a/src/common/engine/i_net.cpp +++ b/src/common/engine/i_net.cpp @@ -1072,7 +1072,7 @@ void I_NetError(const char* error) { doomcom.numnodes = 0; StartWindow->NetClose(); - I_FatalError(error); + I_FatalError("%s", error); } // todo: later these must be dispatched by the main menu, not the start screen. From e12d51c5a245cd640989aaa60d5ec22857b00456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Mon, 6 Jan 2025 09:54:08 -0300 Subject: [PATCH 24/34] add default values, vec4 uniforms, and cvar uniforms to post-process uniforms --- src/common/console/c_cvars.cpp | 10 + src/common/console/c_cvars.h | 7 +- .../postprocessing/hw_postprocess.cpp | 8 + .../postprocessing/hw_postprocessshader.cpp | 25 ++ .../postprocessing/hw_postprocessshader.h | 3 +- src/r_data/gldefs.cpp | 242 ++++++++++++------ wadsrc/static/zscript/engine/ppshader.zs | 1 + 7 files changed, 215 insertions(+), 81 deletions(-) diff --git a/src/common/console/c_cvars.cpp b/src/common/console/c_cvars.cpp index 1cbe6772d0..fc8c715b3b 100644 --- a/src/common/console/c_cvars.cpp +++ b/src/common/console/c_cvars.cpp @@ -240,6 +240,16 @@ void* FBaseCVar::GetExtraDataPointer() return m_ExtraDataPointer; } +void FBaseCVar::SetExtraDataPointer2(void *pointer) +{ + m_ExtraDataPointer2 = pointer; +} + +void* FBaseCVar::GetExtraDataPointer2() +{ + return m_ExtraDataPointer2; +} + const char *FBaseCVar::GetHumanString(int precision) const { return GetGenericRep(CVAR_String).String; diff --git a/src/common/console/c_cvars.h b/src/common/console/c_cvars.h index 47337523fe..c52af0aeb8 100644 --- a/src/common/console/c_cvars.h +++ b/src/common/console/c_cvars.h @@ -222,8 +222,10 @@ class FBaseCVar void ClearCallback(); void SetExtraDataPointer(void *pointer); + void SetExtraDataPointer2(void *pointer); void* GetExtraDataPointer(); + void* GetExtraDataPointer2(); int pnum = -1; FName userinfoName; @@ -259,7 +261,8 @@ class FBaseCVar static inline bool m_UseCallback = false; static inline bool m_DoNoSet = false; - void *m_ExtraDataPointer; + void *m_ExtraDataPointer = nullptr; + void *m_ExtraDataPointer2 = nullptr; // These need to go away! friend FString C_GetMassCVarString (uint32_t filter, bool compact); @@ -275,6 +278,8 @@ class FBaseCVar friend void FilterCompactCVars (TArray &cvars, uint32_t filter); friend void C_DeinitConsole(); friend void C_ListCVarsWithoutDescription(); + + friend class GLDefsParser; }; // Returns a string with all cvars whose flags match filter. In compact mode, diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp index e339f92678..2a685aa3d3 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocess.cpp @@ -947,6 +947,7 @@ PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(d case PostProcessUniformType::Int: AddUniformField(offset, name, UniformType::Int, sizeof(int)); break; case PostProcessUniformType::Vec2: AddUniformField(offset, name, UniformType::Vec2, sizeof(float) * 2); break; case PostProcessUniformType::Vec3: AddUniformField(offset, name, UniformType::Vec3, sizeof(float) * 3, sizeof(float) * 4); break; + case PostProcessUniformType::Vec4: AddUniformField(offset, name, UniformType::Vec4, sizeof(float) * 4); break; default: break; } } @@ -1085,6 +1086,13 @@ void PPCustomShaderInstance::SetUniforms(PPRenderState *renderstate) fValues[2] = (float)pair->Value.Values[2]; memcpy(dst, fValues, sizeof(float) * 3); break; + case PostProcessUniformType::Vec4: + fValues[0] = (float)pair->Value.Values[0]; + fValues[1] = (float)pair->Value.Values[1]; + fValues[2] = (float)pair->Value.Values[2]; + fValues[3] = (float)pair->Value.Values[3]; + memcpy(dst, fValues, sizeof(float) * 4); + break; default: break; } diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp index f23d4497f1..f48d3f7d14 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.cpp @@ -116,6 +116,31 @@ DEFINE_ACTION_FUNCTION(_PPShader, SetUniform3f) return 0; } +DEFINE_ACTION_FUNCTION(_PPShader, SetUniform4f) +{ + PARAM_PROLOGUE; + PARAM_STRING(shaderName); + PARAM_STRING(uniformName); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_FLOAT(w); + + for (unsigned int i = 0; i < PostProcessShaders.Size(); i++) + { + PostProcessShader &shader = PostProcessShaders[i]; + if (shader.Name == shaderName) + { + double *vec4 = shader.Uniforms[uniformName].Values; + vec4[0] = x; + vec4[1] = y; + vec4[2] = z; + vec4[3] = w; + } + } + return 0; +} + DEFINE_ACTION_FUNCTION(_PPShader, SetUniform1i) { PARAM_PROLOGUE; diff --git a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h index 7ecbd4f84c..fcb32c5e1b 100644 --- a/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h +++ b/src/common/rendering/hwrenderer/postprocessing/hw_postprocessshader.h @@ -9,7 +9,8 @@ enum class PostProcessUniformType Int, Float, Vec2, - Vec3 + Vec3, + Vec4 }; struct PostProcessUniformValue diff --git a/src/r_data/gldefs.cpp b/src/r_data/gldefs.cpp index d92b9daf68..6bdb4f2d51 100644 --- a/src/r_data/gldefs.cpp +++ b/src/r_data/gldefs.cpp @@ -59,17 +59,16 @@ void ParseColorization(FScanner& sc); extern TDeletingArray LightDefaults; extern int AttenuationIsSet; -bool addedcvars = false; - struct ExtraUniformCVARData { FString Shader; FString Uniform; double* vec4 = nullptr; ExtraUniformCVARData* Next = nullptr; + void (*OldCallback)(FBaseCVar &); }; -static void do_uniform_set(float value, ExtraUniformCVARData* data) +static void do_uniform_set(DVector4 value, ExtraUniformCVARData* data) { if (!(data->vec4)) { @@ -85,23 +84,33 @@ static void do_uniform_set(float value, ExtraUniformCVARData* data) double* vec4 = data->vec4; if (vec4) { - vec4[0] = value; - vec4[1] = 0.0; - vec4[2] = 0.0; - vec4[3] = 1.0; + vec4[0] = value.X; + vec4[1] = value.Y; + vec4[2] = value.Z; + vec4[3] = value.W; } if (data->Next) do_uniform_set(value, data->Next); } -void uniform_callback_int(FIntCVar &self) +template +void uniform_callback1(T &self) { - do_uniform_set ((float)self, (ExtraUniformCVARData*)self.GetExtraDataPointer()); + auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2(); + if(data->OldCallback) data->OldCallback(self); + + do_uniform_set(DVector4(*self, 0.0, 0.0, 1.0), data); } -void uniform_callback_float(FFloatCVar &self) +void uniform_callback_color(FColorCVar &self) { - do_uniform_set ((float)self, (ExtraUniformCVARData*)self.GetExtraDataPointer()); + auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2(); + if(data->OldCallback) data->OldCallback(self); + + PalEntry col; + col.d = *self; + + do_uniform_set(DVector4(col.r / 255.0, col.g / 255.0, col.b / 255.0, col.a / 255.0), data); } //----------------------------------------------------------------------------- @@ -1539,9 +1548,10 @@ class GLDefsParser sc.MustGetString(); shaderdesc.Name = sc.String; } - else if (sc.Compare("uniform") || sc.Compare("cvar_uniform")) + else if (sc.Compare("uniform")) { - bool is_cvar = sc.Compare("cvar_uniform"); + bool is_cvar = false; + bool ok = true; sc.MustGetString(); FString uniformType = sc.String; @@ -1553,104 +1563,180 @@ class GLDefsParser PostProcessUniformType parsedType = PostProcessUniformType::Undefined; if (uniformType.Compare("int") == 0) + { parsedType = PostProcessUniformType::Int; + } else if (uniformType.Compare("float") == 0) + { parsedType = PostProcessUniformType::Float; + } else if (uniformType.Compare("vec2") == 0) + { parsedType = PostProcessUniformType::Vec2; + } else if (uniformType.Compare("vec3") == 0) + { parsedType = PostProcessUniformType::Vec3; + } + else if (uniformType.Compare("vec4") == 0) + { + parsedType = PostProcessUniformType::Vec4; + } else + { sc.ScriptError("Unrecognized uniform type '%s'", sc.String); + ok = false; + } - auto strUniformType = sc.String; - - if (parsedType != PostProcessUniformType::Undefined) - shaderdesc.Uniforms[uniformName].Type = parsedType; + double Values[4] = {0.0, 0.0, 0.0, 1.0}; - if (is_cvar) + if(ok && sc.CheckToken('=')) { - addedcvars = true; - if (shaderdesc.Name.IsEmpty()) - sc.ScriptError("Shader must have a name to use cvar uniforms"); - - ECVarType cvartype = CVAR_Dummy; - int cvarflags = CVAR_MOD|CVAR_ARCHIVE|CVAR_VIRTUAL; - FBaseCVar *cvar; - void (*callback)(FBaseCVar&) = NULL; - FString cvarname; - switch (parsedType) + if(sc.CheckString("cvar")) + { + is_cvar = true; + } + else switch(parsedType) { case PostProcessUniformType::Int: - cvartype = CVAR_Int; - callback = (void (*)(FBaseCVar&))uniform_callback_int; + sc.MustGetNumber(); + Values[0] = sc.BigNumber; break; case PostProcessUniformType::Float: - cvartype = CVAR_Float; - callback = (void (*)(FBaseCVar&))uniform_callback_float; + sc.MustGetFloat(); + Values[0] = sc.Float; break; - default: - sc.ScriptError("'%s' not supported for CVAR uniforms!", strUniformType); + case PostProcessUniformType::Vec2: + sc.MustGetFloat(); + Values[0] = sc.Float; + sc.MustGetFloat(); + Values[1] = sc.Float; break; + case PostProcessUniformType::Vec3: + sc.MustGetFloat(); + Values[0] = sc.Float; + sc.MustGetFloat(); + Values[1] = sc.Float; + sc.MustGetFloat(); + Values[2] = sc.Float; + break; + case PostProcessUniformType::Vec4: + sc.MustGetFloat(); + Values[0] = sc.Float; + sc.MustGetFloat(); + Values[1] = sc.Float; + sc.MustGetFloat(); + Values[2] = sc.Float; + sc.MustGetFloat(); + Values[3] = sc.Float; + break; + } - sc.MustGetString(); - cvarname = sc.String; - cvar = FindCVar(cvarname.GetChars(), NULL); + } - UCVarValue oldval; - UCVarValue val; - ExtraUniformCVARData* oldextra = nullptr; - sc.MustGetFloat(); - - val.Float = oldval.Float = (float)sc.Float; + if (ok && !is_cvar) + { + shaderdesc.Uniforms[uniformName].Type = parsedType; + shaderdesc.Uniforms[uniformName].Values[0] = Values[0]; + shaderdesc.Uniforms[uniformName].Values[1] = Values[1]; + shaderdesc.Uniforms[uniformName].Values[2] = Values[2]; + shaderdesc.Uniforms[uniformName].Values[3] = Values[3]; + } - if (!Args->CheckParm ("-shaderuniformtest")) - { - // these aren't really release-ready, so lock them behind a command-line argument for now. - sc.ScriptMessage("Warning - Use -shaderuniformtest to enable shader uniforms!"); - } - else + if (ok && is_cvar) + { + if (shaderdesc.Name.IsEmpty()) + sc.ScriptError("Shader must have a name to use cvar uniforms"); + + int cvarflags = CVAR_MOD|CVAR_ARCHIVE|CVAR_VIRTUAL; + FBaseCVar *cvar; + FString cvarname; + void (*callback)(FBaseCVar&) = nullptr; + + if(ok) { - if (!cvar) - { - cvar = C_CreateCVar(cvarname.GetChars(), cvartype, cvarflags); - } - else if (cvar && (((cvar->GetFlags()) & CVAR_MOD) == CVAR_MOD)) - { - // this value may have been previously loaded - oldval.Float = cvar->GetGenericRep(CVAR_Float).Float; - oldextra = (ExtraUniformCVARData*)cvar->GetExtraDataPointer(); - } + sc.MustGetString(); + cvarname = sc.String; + cvar = FindCVar(cvarname.GetChars(), NULL); - if (!(cvar->GetFlags() & CVAR_MOD)) + if (!cvar) { - if (!((cvar->GetFlags() & (CVAR_AUTO | CVAR_UNSETTABLE)) == (CVAR_AUTO | CVAR_UNSETTABLE))) - sc.ScriptError("CVAR '%s' already in use!", cvarname.GetChars()); + sc.ScriptMessage("Unknown cvar passed to cvar_uniform"); + ok = false; } + } - // must've picked this up from an autoexec.cfg, handle accordingly - if (cvar && ((cvar->GetFlags() & (CVAR_MOD|CVAR_AUTO|CVAR_UNSETTABLE)) == (CVAR_AUTO | CVAR_UNSETTABLE))) + if(ok) + { + switch (cvar->GetRealType()) { - oldval.Float = cvar->GetGenericRep(CVAR_Float).Float; - delete cvar; - cvar = C_CreateCVar(cvarname.GetChars(), cvartype, cvarflags); - oldextra = (ExtraUniformCVARData*)cvar->GetExtraDataPointer(); + case CVAR_Int: + if(parsedType != PostProcessUniformType::Int && parsedType != PostProcessUniformType::Float) + { + sc.ScriptError("CVar '%s' type (int) is not convertible to uniform type (%s), must be int or float", cvarname.GetChars(), uniformType.GetChars()); + ok = false; + } + else + { + callback = (void (*)(FBaseCVar&))(&uniform_callback1); + Values[0] = cvar->GetGenericRep(CVAR_Int).Int; + } + break; + case CVAR_Float: + if(parsedType != PostProcessUniformType::Int && parsedType != PostProcessUniformType::Float) + { + sc.ScriptError("CVar '%s' type (float) is not convertible to uniform type (%s), must be int or float", cvarname.GetChars(), uniformType.GetChars()); + ok = false; + } + else + { + callback = (void (*)(FBaseCVar&))(&uniform_callback1); + Values[0] = cvar->GetGenericRep(CVAR_Float).Float; + } + break; + case CVAR_Color: + if(parsedType != PostProcessUniformType::Vec3 && parsedType != PostProcessUniformType::Vec4) + { + sc.ScriptError("CVar '%s' type (color) is not convertible to uniform type (%s), must be vec3 or vec4", cvarname.GetChars(), uniformType.GetChars()); + ok = false; + } + else + { + callback = (void (*)(FBaseCVar&))uniform_callback_color; + + PalEntry col; + col.d = cvar->GetGenericRep(CVAR_Int).Int; + Values[0] = col.r / 255.0; + Values[1] = col.g / 255.0; + Values[2] = col.b / 255.0; + Values[3] = col.a / 255.0; + } + break; + default: + sc.ScriptError("CVar '%s' type not supported for uniforms!", cvarname.GetChars()); + ok = false; + break; } + } - shaderdesc.Uniforms[uniformName].Values[0] = oldval.Float; - - cvar->SetGenericRepDefault(val, CVAR_Float); + if(ok) + { + ExtraUniformCVARData* oldextra = (ExtraUniformCVARData*)cvar->GetExtraDataPointer2(); - if (val.Float != oldval.Float) // it's not default anymore - cvar->SetGenericRep(oldval.Float, CVAR_Float); - - if (callback) - cvar->SetCallback(callback); ExtraUniformCVARData* extra = new ExtraUniformCVARData; extra->Shader = shaderdesc.Name.GetChars(); extra->Uniform = uniformName.GetChars(); + extra->OldCallback = oldextra ? oldextra->OldCallback : cvar->m_Callback; extra->Next = oldextra; - cvar->SetExtraDataPointer(extra); + + cvar->SetCallback(callback); + cvar->SetExtraDataPointer2(extra); + + shaderdesc.Uniforms[uniformName].Type = parsedType; + shaderdesc.Uniforms[uniformName].Values[0] = Values[0]; + shaderdesc.Uniforms[uniformName].Values[1] = Values[1]; + shaderdesc.Uniforms[uniformName].Values[2] = Values[2]; + shaderdesc.Uniforms[uniformName].Values[3] = Values[3]; } } } @@ -1917,8 +2003,6 @@ class GLDefsParser sc.SavePos(); if (!sc.GetToken ()) { - if (addedcvars) - GameConfig->DoModSetup (gameinfo.ConfigName.GetChars()); return; } type = sc.MatchString(CoreKeywords); diff --git a/wadsrc/static/zscript/engine/ppshader.zs b/wadsrc/static/zscript/engine/ppshader.zs index 5c94e7e230..db29a8c035 100644 --- a/wadsrc/static/zscript/engine/ppshader.zs +++ b/wadsrc/static/zscript/engine/ppshader.zs @@ -4,5 +4,6 @@ struct PPShader native native clearscope static void SetUniform1f(string shaderName, string uniformName, float value); native clearscope static void SetUniform2f(string shaderName, string uniformName, vector2 value); native clearscope static void SetUniform3f(string shaderName, string uniformName, vector3 value); + native clearscope static void SetUniform4f(string shaderName, string uniformName, vector4 value); native clearscope static void SetUniform1i(string shaderName, string uniformName, int value); } From aa190dffc93687da3e469a7d19cf5f0505c11986 Mon Sep 17 00:00:00 2001 From: Adam Kaminski Date: Wed, 8 Jan 2025 10:20:04 -0500 Subject: [PATCH 25/34] Fixed the registered or shareware versions of Doom not using the correct chat sound. --- wadsrc/static/mapinfo/doom1.txt | 1 + wadsrc/static/mapinfo/ultdoom.txt | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/mapinfo/doom1.txt b/wadsrc/static/mapinfo/doom1.txt index 851171530f..aae4901e95 100644 --- a/wadsrc/static/mapinfo/doom1.txt +++ b/wadsrc/static/mapinfo/doom1.txt @@ -6,6 +6,7 @@ gameinfo creditpage = "CREDIT", "HELP2" titlemusic = "$MUSIC_INTRO" titletime = 5 + chatsound = "misc/chat2" finalemusic = "$MUSIC_VICTOR" finaleflat = "FLOOR4_8" finalepage = "HELP2", "VICTORY2", "ENDPIC" diff --git a/wadsrc/static/mapinfo/ultdoom.txt b/wadsrc/static/mapinfo/ultdoom.txt index 40dab4bfce..1bbe40389d 100644 --- a/wadsrc/static/mapinfo/ultdoom.txt +++ b/wadsrc/static/mapinfo/ultdoom.txt @@ -3,7 +3,6 @@ include "mapinfo/doom1.txt" gameinfo { creditpage = "CREDIT" - chatsound = "misc/chat2" finalepage = "CREDIT", "VICTORY2", "ENDPIC" infopage = "HELP1", "CREDIT" } From 2f4714e0c75aafb1b86cf9eb257395c7759f62d2 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 8 Jan 2025 17:54:38 -0500 Subject: [PATCH 26/34] - vcpkg keeps failing. take it off the CI --- .github/workflows/continuous_integration.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index d451e47b72..7efd95cefd 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -12,17 +12,14 @@ jobs: config: - name: Visual Studio 2022 os: windows-2022 - extra_options: -DCMAKE_TOOLCHAIN_FILE=build/vcpkg/scripts/buildsystems/vcpkg.cmake build_type: Release - name: Visual Studio 2022 os: windows-2022 - extra_options: -DCMAKE_TOOLCHAIN_FILE=build/vcpkg/scripts/buildsystems/vcpkg.cmake build_type: Debug - name: Visual Studio 2019 os: windows-2019 - extra_options: -DCMAKE_TOOLCHAIN_FILE=build/vcpkg/scripts/buildsystems/vcpkg.cmake build_type: Release - name: macOS @@ -81,13 +78,6 @@ jobs: tar -xf "${ZMUSIC_PACKAGE}" fi - - name: Setup vcpkg - uses: lukka/run-vcpkg@v11 - if: runner.os == 'Windows' - with: - vcpkgDirectory: '${{ github.workspace }}/build/vcpkg' - vcpkgGitCommitId: '2c401863dd54a640aeb26ed736c55489c079323b' - - name: Configure shell: bash run: | From 30ab9609558cbb59b8cef16ab9b5217fe5052184 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 10 Jan 2025 17:18:44 +0100 Subject: [PATCH 27/34] update DUMB license from zmusic source. --- docs/licenses/dumb.txt | 47 +++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/docs/licenses/dumb.txt b/docs/licenses/dumb.txt index 231bfa7f1d..961fe4ef8f 100644 --- a/docs/licenses/dumb.txt +++ b/docs/licenses/dumb.txt @@ -18,9 +18,9 @@ */ -Dynamic Universal Music Bibliotheque +Dynamic Universal Music Bibliotheque, Version 0.9.3 -Copyright (C) 2001-2003 Ben Davis, Robert J Ohannessian and Julien Cugniere +Copyright (C) 2001-2005 Ben Davis, Robert J Ohannessian and Julien Cugniere This software is provided 'as-is', without any express or implied warranty. In no event shall the authors be held liable for any damages arising from the @@ -39,16 +39,49 @@ freely, subject to the following restrictions: [Note that the above point asks for a link to DUMB, not just a mention. Googling for DUMB doesn't help much! The URL is "http://dumb.sf.net/".] - [The only reason why the link is not strictly required is that such a - requirement prevents DUMB from being used in projects with certain other - licences, notably the GPL. See http://www.gnu.org/philosophy/bsd.html .] + [The link was originally strictly required. This was changed for two + reasons. Firstly, if many projects request an acknowledgement, the list of + acknowledgements can become quite unmanageable. Secondly, DUMB was placing + a restriction on the code using it, preventing people from using the GNU + General Public Licence which disallows any such restrictions. See + http://www.gnu.org/philosophy/bsd.html for more information on this + subject. However, if DUMB plays a significant part in your project, we do + urge you to acknowledge its use.] 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed from or altered in any source distribution. -4. If you are using the Program in someone else's bedroom at any Monday - 3:05 PM, you are not allowed to modify the Program for ten minutes. [This +4. If you are using the Program in someone else's bedroom on any Monday at + 3:05 pm, you are not allowed to modify the Program for ten minutes. [This clause provided by Inphernic; every licence should contain at least one clause, the reasoning behind which is far from obvious.] + +5. Users who wish to use DUMB for the specific purpose of playing music are + required to feed their dog on every full moon (if deemed appropriate). + [This clause provided by Allefant, who couldn't remember what Inphernic's + clause was.] + +6. No clause in this licence shall prevent this software from being depended + upon by a product licensed under the GNU General Public Licence. If such a + clause is deemed to exist, Debian, then it shall be respected in spirit as + far as possible and all other clauses shall continue to apply in full + force. + +8. Take the number stated as introducing this clause. Multiply it by two, + then subtract four. Now insert a '+' between the two digits and evaluate + the resulting sum. Call the result 'x'. If you have not yet concluded that + every numbered clause in this licence whose ordinal number is strictly + greater than 'x' (with the exception of the present clause) is null and + void, Debian, then you are hereby informed that laughter is good for one's + health and you are warmly suggested to do it. By the way, Clauses 4, 5 and + 6 are null and void. Incidentally, I like Kubuntu. The work you guys do is + awesome. (Lawyers, on the other hand ...) + +We regret that we cannot provide any warranty, not even the implied warranty +of merchantability or fitness for a particular purpose. + +Some files generated or copied by automake, autoconf and friends are +available in an extra download. These fall under separate licences but are +all free to distribute. Please check their licences as necessary. From 2061caba18f1ce5d1bbfa41b096ab46e80a27b93 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Fri, 10 Jan 2025 13:55:16 -0600 Subject: [PATCH 28/34] Make the visual thinker statnum assignment check unconditional since statnum is no longer a pointer - This fully completes this revert: https://github.com/ZDoom/gzdoom/commit/ca3b0737ea3cc2b11c7e1e2670dd56073cb4a096 --- src/g_levellocals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_levellocals.h b/src/g_levellocals.h index af2d6bb28d..5a2b37ca26 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -427,7 +427,7 @@ struct FLevelLocals DThinker *CreateThinker(PClass *cls, int statnum = STAT_DEFAULT) { DThinker *thinker = static_cast(cls->CreateNew()); - if (statnum && thinker->IsKindOf(RUNTIME_CLASS(DVisualThinker))) + if (thinker->IsKindOf(RUNTIME_CLASS(DVisualThinker))) { statnum = STAT_VISUALTHINKER; } From 61df13306f5884ebb91a20ac6f0743a751741d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sat, 11 Jan 2025 09:30:07 -0300 Subject: [PATCH 29/34] fix DScriptScanner --- src/common/scripting/interface/vmnatives.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/scripting/interface/vmnatives.cpp b/src/common/scripting/interface/vmnatives.cpp index 2b57ceb25a..a798f1310e 100644 --- a/src/common/scripting/interface/vmnatives.cpp +++ b/src/common/scripting/interface/vmnatives.cpp @@ -1706,7 +1706,7 @@ DEFINE_ACTION_FUNCTION(DScriptScanner, ScriptError) { PARAM_SELF_PROLOGUE(DScriptScanner); - FString s = FStringFormat(VM_ARGS_NAMES); + FString s = FStringFormat(VM_ARGS_NAMES, 1); self->wrapped.ScriptError("%s", s.GetChars()); return 0; } @@ -1715,7 +1715,7 @@ DEFINE_ACTION_FUNCTION(DScriptScanner, ScriptMessage) { PARAM_SELF_PROLOGUE(DScriptScanner); - FString s = FStringFormat(VM_ARGS_NAMES); + FString s = FStringFormat(VM_ARGS_NAMES, 1); self->wrapped.ScriptMessage("%s", s.GetChars()); return 0; } From c87dc5ccadf0e84b8845dd6079cb512a2f4332b1 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Mon, 13 Jan 2025 12:15:00 -0500 Subject: [PATCH 30/34] Updated VisualThinker render linkage Now uses its own self-managed linked list with its level tracking the head pointer. Allows for VisualThinkers to be moved to any desired stat instead of being stuck in STAT_VISUALTHINKER. --- src/g_levellocals.h | 6 +--- src/p_saveg.cpp | 3 +- src/playsim/dthinker.cpp | 6 +--- src/playsim/p_effect.cpp | 47 ++++++++++++++++++-------- src/playsim/p_visualthinker.h | 6 +++- wadsrc/static/zscript/visualthinker.zs | 2 +- 6 files changed, 42 insertions(+), 28 deletions(-) diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 5a2b37ca26..30602d4d07 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -427,11 +427,6 @@ struct FLevelLocals DThinker *CreateThinker(PClass *cls, int statnum = STAT_DEFAULT) { DThinker *thinker = static_cast(cls->CreateNew()); - if (thinker->IsKindOf(RUNTIME_CLASS(DVisualThinker))) - { - statnum = STAT_VISUALTHINKER; - } - assert(thinker->IsKindOf(RUNTIME_CLASS(DThinker))); thinker->ObjectFlags |= OF_JustSpawned; Thinkers.Link(thinker, statnum); @@ -708,6 +703,7 @@ struct FLevelLocals int ImpactDecalCount; FDynamicLight *lights; + DVisualThinker* VisualThinkerHead = nullptr; // links to global game objects TArray> CorpseQueue; diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 3a267c8162..ce26ff39c7 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -990,7 +990,8 @@ void FLevelLocals::Serialize(FSerializer &arc, bool hubload) ("scrolls", Scrolls) ("automap", automap) ("interpolator", interpolator) - ("frozenstate", frozenstate); + ("frozenstate", frozenstate) + ("visualthinkerhead", VisualThinkerHead); // Hub transitions must keep the current total time diff --git a/src/playsim/dthinker.cpp b/src/playsim/dthinker.cpp index e843847520..51cf3a6703 100644 --- a/src/playsim/dthinker.cpp +++ b/src/playsim/dthinker.cpp @@ -810,11 +810,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DThinker, ChangeStatNum, ChangeStatNum) PARAM_SELF_PROLOGUE(DThinker); PARAM_INT(stat); - // do not allow ZScript to reposition thinkers in or out of particle ticking. - if (stat != STAT_VISUALTHINKER && !dynamic_cast(self)) - { - ChangeStatNum(self, stat); - } + ChangeStatNum(self, stat); return 0; } diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index a2d42f7c57..af8514698b 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -214,15 +214,13 @@ void P_FindParticleSubsectors (FLevelLocals *Level) { Level->subsectors[i].sprites.Clear(); } - // [MC] Not too happy about using an iterator for this but I can't think of another way to handle it. - // At least it's on its own statnum for maximum efficiency. - auto it = Level->GetThinkerIterator(NAME_None, STAT_VISUALTHINKER); - DVisualThinker* sp; - while (sp = it.Next()) + auto sp = Level->VisualThinkerHead; + while (sp != nullptr) { if (!sp->PT.subsector) sp->PT.subsector = Level->PointInRenderSubsector(sp->PT.Pos); sp->PT.subsector->sprites.Push(sp); + sp = sp->GetNext(); } // End VisualThinker hitching. Now onto the particles. if (Level->ParticlesInSubsec.Size() < Level->subsectors.Size()) @@ -1007,26 +1005,38 @@ void DVisualThinker::Construct() cursector = nullptr; PT.color = 0xffffff; AnimatedTexture.SetNull(); -} -DVisualThinker::DVisualThinker() -{ - Construct(); + _prev = _next = nullptr; + if (Level->VisualThinkerHead != nullptr) + { + Level->VisualThinkerHead->_prev = this; + _next = Level->VisualThinkerHead; + } + Level->VisualThinkerHead = this; } void DVisualThinker::OnDestroy() { + if (_prev != nullptr) + _prev->_next = _next; + if (_next != nullptr) + _next->_prev = _prev; + if (Level->VisualThinkerHead == this) + Level->VisualThinkerHead = _next; + PT.alpha = 0.0; // stops all rendering. Super::OnDestroy(); } +DVisualThinker* DVisualThinker::GetNext() const +{ + return _next; +} + DVisualThinker* DVisualThinker::NewVisualThinker(FLevelLocals* Level, PClass* type) { if (type == nullptr) - return nullptr; - else if (type->bAbstract) { - Printf("Attempt to spawn an instance of abstract VisualThinker class %s\n", type->TypeName.GetChars()); return nullptr; } else if (!type->IsDescendantOf(RUNTIME_CLASS(DVisualThinker))) @@ -1034,8 +1044,13 @@ DVisualThinker* DVisualThinker::NewVisualThinker(FLevelLocals* Level, PClass* ty Printf("Attempt to spawn class not inherent to VisualThinker: %s\n", type->TypeName.GetChars()); return nullptr; } + else if (type->bAbstract) + { + Printf("Attempt to spawn an instance of abstract VisualThinker class %s\n", type->TypeName.GetChars()); + return nullptr; + } - DVisualThinker *zs = static_cast(Level->CreateThinker(type, STAT_VISUALTHINKER)); + auto zs = static_cast(Level->CreateThinker(type, DVisualThinker::DEFAULT_STAT)); zs->Construct(); return zs; } @@ -1284,7 +1299,7 @@ void DVisualThinker::Serialize(FSerializer& arc) { Super::Serialize(arc); - arc ("pos", PT.Pos) + arc("pos", PT.Pos) ("vel", PT.Vel) ("prev", Prev) ("scale", Scale) @@ -1300,7 +1315,9 @@ void DVisualThinker::Serialize(FSerializer& arc) ("lightlevel", LightLevel) ("animData", PT.animData) ("flags", PT.flags) - ("visualThinkerFlags", flags); + ("visualThinkerFlags", flags) + ("next", _next) + ("prev", _prev); if(arc.isReading()) { diff --git a/src/playsim/p_visualthinker.h b/src/playsim/p_visualthinker.h index d4b1e262dd..9fb5eae65c 100644 --- a/src/playsim/p_visualthinker.h +++ b/src/playsim/p_visualthinker.h @@ -26,7 +26,11 @@ class DVisualThinker : public DThinker { DECLARE_CLASS(DVisualThinker, DThinker); void UpdateSector(subsector_t * newSubsector); + + DVisualThinker* _next, * _prev; public: + static const int DEFAULT_STAT = STAT_VISUALTHINKER; + DVector3 Prev; DVector2 Scale, Offset; @@ -41,9 +45,9 @@ class DVisualThinker : public DThinker // internal only variables particle_t PT; - DVisualThinker(); void Construct(); void OnDestroy() override; + DVisualThinker* GetNext() const; static DVisualThinker* NewVisualThinker(FLevelLocals* Level, PClass* type); void SetTranslation(FName trname); diff --git a/wadsrc/static/zscript/visualthinker.zs b/wadsrc/static/zscript/visualthinker.zs index 45b32865cb..2b6d9a8428 100644 --- a/wadsrc/static/zscript/visualthinker.zs +++ b/wadsrc/static/zscript/visualthinker.zs @@ -33,7 +33,7 @@ Class VisualThinker : Thinker native native protected void UpdateSector(); // needs to be called if the thinker is set to a non-ticking statnum and the position is modified (or if Tick is overriden and doesn't call Super.Tick()) native protected void UpdateSpriteInfo(); // needs to be called every time the texture is updated if the thinker uses SPF_LOCAL_ANIM and is set to a non-ticking statnum (or if Tick is overriden and doesn't call Super.Tick()) - static VisualThinker Spawn(Class type, TextureID tex, Vector3 pos, Vector3 vel, double alpha = 1.0, int flags = 0, + static VisualThinker Spawn(Class type, TextureID tex, Vector3 pos, Vector3 vel = (0,0,0), double alpha = 1.0, int flags = 0, double roll = 0.0, Vector2 scale = (1,1), Vector2 offset = (0,0), int style = STYLE_Normal, TranslationID trans = 0, int VisualThinkerFlags = 0) { if (!Level) return null; From f5bf1d049717db315cd2e5c78631566e81b63c5c Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Mon, 13 Jan 2025 11:46:20 +0800 Subject: [PATCH 31/34] Exported thing activation function --- src/playsim/p_lnspec.h | 2 +- src/playsim/p_map.cpp | 10 +++++++++- wadsrc/static/zscript/actors/actor.zs | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/playsim/p_lnspec.h b/src/playsim/p_lnspec.h index 7072e31e53..1adba82834 100644 --- a/src/playsim/p_lnspec.h +++ b/src/playsim/p_lnspec.h @@ -219,7 +219,7 @@ static inline bool P_IsACSSpecial(int specnum) FLineSpecial *P_GetLineSpecialInfo(int num); int P_GetMaxLineSpecial(); int P_FindLineSpecial (const char *string, int *min_args=NULL, int *max_args=NULL); -bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death=false); +int P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death=false); int P_ExecuteSpecial( FLevelLocals *lev, int num, diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index ef5438afdf..c4b4c96ebc 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -7211,7 +7211,7 @@ static void SpawnDeepSplash(AActor *t1, const FTraceResults &trace, AActor *puff // //============================================================================= -bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death) +int P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death) { bool res = false; @@ -7267,3 +7267,11 @@ bool P_ActivateThingSpecial(AActor * thing, AActor * trigger, bool death) // Returns the result return res; } + +DEFINE_ACTION_FUNCTION_NATIVE(AActor, ActivateSpecial, P_ActivateThingSpecial) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT_NOT_NULL(activator, AActor); + PARAM_BOOL(death); + ACTION_RETURN_BOOL(P_ActivateThingSpecial(self, activator, death)); +} diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index e0633d599b..320b2e554c 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -690,6 +690,7 @@ class Actor : Thinker native native clearscope static int ApplyDamageFactors(class itemcls, Name damagetype, int damage, int defdamage); native void RemoveFromHash(); native void ChangeTid(int newtid); + native bool ActivateSpecial(Actor activator, bool death = false); deprecated("3.8", "Use Level.FindUniqueTid() instead") static int FindUniqueTid(int start = 0, int limit = 0) { return level.FindUniqueTid(start, limit); From dad8e4719c4035dd26f0f1aefe0f41b7a6db3c7d Mon Sep 17 00:00:00 2001 From: Boondorl Date: Tue, 14 Jan 2025 07:32:25 -0500 Subject: [PATCH 32/34] Don't create thing iterator if THRUACTORS is set when moving --- src/playsim/p_map.cpp | 81 ++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index c4b4c96ebc..b3e052c81f 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -1880,52 +1880,55 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo FBoundingBox box(pos.X, pos.Y, thing->radius); FPortalGroupArray pcheck; - FMultiBlockThingsIterator it2(pcheck, thing->Level, pos.X, pos.Y, thing->Z(), thing->Height, thing->radius, false, newsec); - FMultiBlockThingsIterator::CheckResult tcres; if (!(thing->flags2 & MF2_THRUACTORS)) - while ((it2.Next(&tcres))) - { - if (!PIT_CheckThing(it2, tcres, it2.Box(), tm)) - { // [RH] If a thing can be stepped up on, we need to continue checking - // other things in the blocks and see if we hit something that is - // definitely blocking. Otherwise, we need to check the lines, or we - // could end up stuck inside a wall. - AActor *BlockingMobj = thing->BlockingMobj; - - // If this blocks through a restricted line portal, it will always completely block. - if (BlockingMobj == NULL || (thing->Level->i_compatflags & COMPATF_NO_PASSMOBJ) || (tcres.portalflags & FFCF_RESTRICTEDPORTAL)) - { // Thing slammed into something; don't let it move now. - thing->Height = realHeight; - return false; - } - else if (!BlockingMobj->player && !(thing->flags & (MF_FLOAT | MF_MISSILE | MF_SKULLFLY)) && - BlockingMobj->Top() - thing->Z() <= thing->MaxStepHeight) - { - if (thingblocker == NULL || - BlockingMobj->Z() > thingblocker->Z()) + { + FMultiBlockThingsIterator it2(pcheck, thing->Level, pos.X, pos.Y, thing->Z(), thing->Height, thing->radius, false, newsec); + FMultiBlockThingsIterator::CheckResult tcres; + + while ((it2.Next(&tcres))) + { + if (!PIT_CheckThing(it2, tcres, it2.Box(), tm)) + { // [RH] If a thing can be stepped up on, we need to continue checking + // other things in the blocks and see if we hit something that is + // definitely blocking. Otherwise, we need to check the lines, or we + // could end up stuck inside a wall. + AActor* BlockingMobj = thing->BlockingMobj; + + // If this blocks through a restricted line portal, it will always completely block. + if (BlockingMobj == NULL || (thing->Level->i_compatflags & COMPATF_NO_PASSMOBJ) || (tcres.portalflags & FFCF_RESTRICTEDPORTAL)) + { // Thing slammed into something; don't let it move now. + thing->Height = realHeight; + return false; + } + else if (!BlockingMobj->player && !(thing->flags & (MF_FLOAT | MF_MISSILE | MF_SKULLFLY)) && + BlockingMobj->Top() - thing->Z() <= thing->MaxStepHeight) { - thingblocker = BlockingMobj; + if (thingblocker == NULL || + BlockingMobj->Z() > thingblocker->Z()) + { + thingblocker = BlockingMobj; + } + thing->BlockingMobj = NULL; } - thing->BlockingMobj = NULL; - } - else if (thing->player && - thing->Top() - BlockingMobj->Z() <= thing->MaxStepHeight) - { - if (thingblocker) - { // There is something to step up on. Return this thing as - // the blocker so that we don't step up. + else if (thing->player && + thing->Top() - BlockingMobj->Z() <= thing->MaxStepHeight) + { + if (thingblocker) + { // There is something to step up on. Return this thing as + // the blocker so that we don't step up. + thing->Height = realHeight; + return false; + } + // Nothing is blocking us, but this actor potentially could + // if there is something else to step on. + thing->BlockingMobj = NULL; + } + else + { // Definitely blocking thing->Height = realHeight; return false; } - // Nothing is blocking us, but this actor potentially could - // if there is something else to step on. - thing->BlockingMobj = NULL; - } - else - { // Definitely blocking - thing->Height = realHeight; - return false; } } } From a1460e88af6aa8bf59c19c766f4063088c101d72 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 17 Jan 2025 14:38:25 -0500 Subject: [PATCH 33/34] Added S_StartSoundAt Allows for positional sounds that aren't attached to any Actor. --- src/sound/s_doomsound.cpp | 25 ++++++++++++++++++++++++- wadsrc/static/zscript/doombase.zs | 1 + 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/sound/s_doomsound.cpp b/src/sound/s_doomsound.cpp index 749b1f5e79..525bb9b54b 100644 --- a/src/sound/s_doomsound.cpp +++ b/src/sound/s_doomsound.cpp @@ -379,7 +379,7 @@ void S_InitData() void S_SoundPitch(int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation, float pitch, float startTime) { - soundEngine->StartSound(SOURCE_None, nullptr, nullptr, channel, flags, sound_id, volume, attenuation, 0, pitch); + soundEngine->StartSound(SOURCE_None, nullptr, nullptr, channel, flags, sound_id, volume, attenuation, nullptr, pitch, startTime); } void S_Sound(int channel, EChanFlags flags, FSoundID sound_id, float volume, float attenuation) @@ -414,6 +414,29 @@ DEFINE_ACTION_FUNCTION(DObject, S_StartSound) return 0; } +static void S_StartSoundAt(double x, double y, double z, int sound_id, int channel, int flags, double volume, double attenuation, double pitch, double startTime) +{ + FVector3 pos = { (float)x, (float)z, (float)y }; + soundEngine->StartSound(SOURCE_Unattached, nullptr, &pos, channel, EChanFlags::FromInt(flags), FSoundID::fromInt(sound_id), (float)volume, (float)attenuation, nullptr, (float)pitch, (float)startTime); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, S_StartSoundAt, S_StartSoundAt) +{ + PARAM_PROLOGUE; + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(z); + PARAM_INT(id); + PARAM_INT(channel); + PARAM_INT(flags); + PARAM_FLOAT(volume); + PARAM_FLOAT(attn); + PARAM_FLOAT(pitch); + PARAM_FLOAT(startTime); + S_StartSoundAt(x, y, z, id, channel, flags, volume, attn, pitch, startTime); + return 0; +} + //========================================================================== // diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index 7751e76cf6..bb76cfb657 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -132,6 +132,7 @@ extend class Object } deprecated("4.3", "Use S_StartSound() instead") native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM, float pitch = 0.0, float startTime = 0.0); native static void S_StartSound (Sound sound_id, int channel, int flags = 0, float volume = 1, float attenuation = ATTN_NORM, float pitch = 0.0, float startTime = 0.0); + native static void S_StartSoundAt(Vector3 pos, Sound sound_id, int channel, int flags = 0, double volume = 1, double attenuation = ATTN_NORM, double pitch = 0.0, double startTime = 0.0); native static void S_PauseSound (bool notmusic, bool notsfx); native static void S_ResumeSound (bool notsfx); native static bool S_ChangeMusic(String music_name, int order = 0, bool looping = true, bool force = false); From 7b30f9350cfe8b0c15ca35cc080983eafdc7c8e6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 19 Jan 2025 13:19:26 +0100 Subject: [PATCH 34/34] fix automap display for keys that were altered by Dehacked. --- src/am_map.cpp | 9 ++++++++- src/gamedata/a_keys.cpp | 10 ++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index c547884b2e..ec63817549 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -2910,11 +2910,18 @@ void DAutomap::drawKeys () mpoint_t p; DAngle angle; - auto it = Level->GetThinkerIterator(NAME_Key); + auto it = Level->GetThinkerIterator(NAME_Inventory); AActor *key; while ((key = it.Next()) != nullptr) { + auto cls = key->GetClass(); + if (cls->IsDescendantOf(NAME_DehackedPickup)) + { + cls = cls->ActorInfo()->Replacee; + } + if (!cls->IsDescendantOf(NAME_Key)) continue; + DVector3 pos = key->PosRelative(MapPortalGroup); p.x = pos.X; p.y = pos.Y; diff --git a/src/gamedata/a_keys.cpp b/src/gamedata/a_keys.cpp index 32f680a423..369f9c5ed1 100644 --- a/src/gamedata/a_keys.cpp +++ b/src/gamedata/a_keys.cpp @@ -62,6 +62,16 @@ struct OneKey // P_GetMapColorForKey() checks the key directly if (owner->IsA(key) || owner->GetSpecies() == key->TypeName) return true; + if (owner->IsKindOf(NAME_DehackedPickup)) + { + auto cls = owner->GetClass()->ActorInfo()->Replacee; + if (cls == key || owner->Species == key->TypeName) + { + return true; + } + } + + // Other calls check an actor that may have a key in its inventory. for (AActor *item = owner->Inventory; item != NULL; item = item->Inventory) {