From a369146fc37f2d9f4b554062b3603d9efb410590 Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Wed, 27 Mar 2024 09:28:12 +0100 Subject: [PATCH 01/14] Added joystick support, Doom2 support, and a little menu to choose between installed wads --- Source/Doom/d_iwad.c | 10 ++--- Source/Doom/d_iwad.h | 2 +- Source/Doom/d_main.c | 72 +++++++++++++++++-------------- Source/Doom/doomgeneric_rad.c | 43 +++++++++++++++---- Source/Doom/i_main.c | 6 +-- Source/Doom/w_file_stdc.c | 4 +- Source/rad_doom.cpp | 81 ++++++++++++++++++++++++++++++++--- Source/rad_doom_hijack.cpp | 24 ++++++++++- 8 files changed, 185 insertions(+), 57 deletions(-) diff --git a/Source/Doom/d_iwad.c b/Source/Doom/d_iwad.c index 74cac56..06a1ed3 100644 --- a/Source/Doom/d_iwad.c +++ b/Source/Doom/d_iwad.c @@ -700,9 +700,7 @@ char *D_TryFindWADByName(char *filename) // should be executed (notably loading PWADs). // -char d1wad[] = "RADDOOM/doom1.wad"; - -char *D_FindIWAD(int mask, GameMission_t *mission) +char *D_FindIWAD(int mask, GameMission_t *mission, char *wadLocation) { char *result; char *iwadfile; @@ -723,9 +721,9 @@ char *D_FindIWAD(int mask, GameMission_t *mission) { // Search through IWAD dirs for an IWAD with the given name. - iwadfile = d1wad; - - result = D_FindWADByName( "RADDOOM/doom1.wad" ); + iwadfile = wadLocation; + + result = D_FindWADByName( iwadfile ); if (result == NULL) { diff --git a/Source/Doom/d_iwad.h b/Source/Doom/d_iwad.h index 91a804f..b2ab6e1 100644 --- a/Source/Doom/d_iwad.h +++ b/Source/Doom/d_iwad.h @@ -41,7 +41,7 @@ typedef struct char *D_FindWADByName(char *filename); char *D_TryFindWADByName(char *filename); -char *D_FindIWAD(int mask, GameMission_t *mission); +char *D_FindIWAD(int mask, GameMission_t *mission, char *wadLocation); const iwad_t **D_FindAllIWADs(int mask); char *D_SaveGameIWADName(GameMission_t gamemission); char *D_SuggestIWADName(GameMission_t mission, GameMode_t mode); diff --git a/Source/Doom/d_main.c b/Source/Doom/d_main.c index 4e6dba9..ef71dae 100644 --- a/Source/Doom/d_main.c +++ b/Source/Doom/d_main.c @@ -788,7 +788,7 @@ void D_IdentifyVersion(void) // detecting it based on the filename. Valid values are: "doom2", // "tnt" and "plutonia". // - p = M_CheckParmWithArgs("-pack", 1); + p = 0; //M_CheckParmWithArgs("-pack", 1); if (p > 0) { SetMissionForPackName(myargv[p + 1]); @@ -1157,7 +1157,7 @@ static void LoadIwadDeh(void) // // D_DoomMain // -void D_DoomMain (void) +void D_DoomMain (int doomVersion) { int p; char file[256]; @@ -1360,8 +1360,17 @@ void D_DoomMain (void) I_AtExit(M_SaveDefaults, false); // Find main IWAD file and load it. + char wadLocation[] = "RADDOOM/doom1.wad"; + char wadLocation2[] = "RADDOOM/doom2.wad"; + char wadLocation3[] = "RADDOOM/doom.wad"; + #if 1 - iwadfile = D_FindIWAD(IWAD_MASK_DOOM, &gamemission); + if (doomVersion == 3) + iwadfile = D_FindIWAD(IWAD_MASK_DOOM, &gamemission, wadLocation3); + else if (doomVersion == 2) + iwadfile = D_FindIWAD(IWAD_MASK_DOOM, &gamemission, wadLocation2); + else + iwadfile = D_FindIWAD(IWAD_MASK_DOOM, &gamemission, wadLocation); // None found? @@ -1382,15 +1391,14 @@ extern lumpinfo_t **lumphash; lumphash = NULL; - DEH_printf("W_Init: Init WADfiles.\n"); D_AddFile(iwadfile); - //D_AddFile("RADDOOM/doom1.wad"); #if ORIGCODE numiwadlumps = numlumps; #endif - W_CheckCorrectIWAD(doom); + // This breaks Doom2 support (even when called with doom2) + //W_CheckCorrectIWAD(doom); // Now that we've loaded the IWAD, we can figure out what gamemission // we're playing and which version of Vanilla Doom we need to emulate. @@ -1572,26 +1580,26 @@ lumphash = NULL; // Check for -file in shareware if (modifiedgame) { - // These are the lumps that will be checked in IWAD, - // if any one is not present, execution will be aborted. - char name[23][8]= - { - "e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9", - "e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9", - "dphoof","bfgga0","heada1","cybra1","spida1d1" - }; - int i; - - if ( gamemode == shareware) - I_Error(DEH_String("\nYou cannot -file with the shareware " - "version. Register!")); + // These are the lumps that will be checked in IWAD, + // if any one is not present, execution will be aborted. + char name[23][8]= + { + "e2m1","e2m2","e2m3","e2m4","e2m5","e2m6","e2m7","e2m8","e2m9", + "e3m1","e3m3","e3m3","e3m4","e3m5","e3m6","e3m7","e3m8","e3m9", + "dphoof","bfgga0","heada1","cybra1","spida1d1" + }; + int i; + + if ( gamemode == shareware) + I_Error(DEH_String("\nYou cannot -file with the shareware " + "version. Register!")); - // Check for fake IWAD with right name, - // but w/o all the lumps of the registered version. - if (gamemode == registered) - for (i = 0;i < 23; i++) - if (W_CheckNumForName(name[i])<0) - I_Error(DEH_String("\nThis is not the registered version.")); + // Check for fake IWAD with right name, + // but w/o all the lumps of the registered version. + if (gamemode == registered) + for (i = 0;i < 23; i++) + if (W_CheckNumForName(name[i])<0) + I_Error(DEH_String("\nThis is not the registered version.")); } if (W_CheckNumForName("SS_START") >= 0 @@ -1651,8 +1659,8 @@ lumphash = NULL; if (p) { - startskill = myargv[p+1][0]-'1'; - autostart = true; + startskill = myargv[p+1][0]-'1'; + autostart = true; } //! @@ -1666,9 +1674,9 @@ lumphash = NULL; if (p) { - startepisode = myargv[p+1][0]-'0'; - startmap = 1; - autostart = true; + startepisode = myargv[p+1][0]-'0'; + startmap = 1; + autostart = true; } timelimit = 0; @@ -1685,7 +1693,7 @@ lumphash = NULL; if (p) { - timelimit = atoi(myargv[p+1]); + timelimit = atoi(myargv[p+1]); } //! @@ -1699,7 +1707,7 @@ lumphash = NULL; if (p) { - timelimit = 20; + timelimit = 20; } //! diff --git a/Source/Doom/doomgeneric_rad.c b/Source/Doom/doomgeneric_rad.c index 6584c0b..ad3135a 100644 --- a/Source/Doom/doomgeneric_rad.c +++ b/Source/Doom/doomgeneric_rad.c @@ -48,7 +48,7 @@ #include #include -extern void blitScreenDOOM( uint8_t *koalaData, uint32_t *kbEvents, uint8_t *nEvents, uint8_t *mouseData ); +extern void blitScreenDOOM( uint8_t *koalaData, uint32_t *kbEvents, uint8_t *nEvents, uint8_t *mouseData, uint8_t *joyData, uint32_t *mouseControlActive ); extern void prepareC64(); extern void disableInterrupts(); extern void enableInterrupts(); @@ -951,10 +951,20 @@ int introShowFrame() uint32_t kbEvents[ 16 ]; uint8_t nEvents = 0; uint8_t mouseData[ 4 ]; - blitScreenDOOM( koalaData, kbEvents, &nEvents, mouseData ); + uint8_t joyData[ 5 ]; + blitScreenDOOM( koalaData, kbEvents, &nEvents, mouseData, joyData, &mouseControlActive ); + + if ( nEvents ) { + + for (int i=0; i= 256 ) { + exitKey = showInfo(); + for ( int y = 0; y < 200; y ++ ) { for ( int x = 0; x < 320; x += 2 ) @@ -573,6 +640,8 @@ void doIntro() memset( soundRingBuffer, 0, SOUND_RINGBUF_SIZE ); EnableIRQs(); + + return exitKey; } #endif @@ -612,14 +681,16 @@ void CRAD::Run( void ) sidtimer = new CUserTimer( &m_Interrupt, sidSamplePlayIRQ, this, !true ); sidtimer->Initialize(); + int doomVersion = 1; + #ifdef SHOW_INTRO - doIntro(); + doomVersion = doIntro(); extern void restartIncrementalBlitter(); restartIncrementalBlitter(); #endif - startDoom(); + startDoom(doomVersion); } extern "C" void radMountFileSystem() diff --git a/Source/rad_doom_hijack.cpp b/Source/rad_doom_hijack.cpp index eeb3f13..841b219 100644 --- a/Source/rad_doom_hijack.cpp +++ b/Source/rad_doom_hijack.cpp @@ -429,6 +429,25 @@ u16 getResetVector() return vec; } +void readJoystick(unsigned char *joyData) { + unsigned char joyState; + + // Update the DDR to let the CIA know we want to read the joystick + SPOKE(0xdc02, 0xe0); + + // It takes 2 syncs to be SURE that the register is updated after setting the DDR ( https://www.c64-wiki.com/wiki/Paddle ) + SPEEK(0xdc00, joyState); + SPEEK(0xdc00, joyState); + + // Invert `joyState` since an activation is represented by a 0 + joyState = ~joyState; + + // Directly assign button states to joyData elements using bitwise AND and logical shift right operations. + for (int i = 0; i < 5; ++i) { + joyData[i] = (joyState >> i) & 1; + } +} + void readKeyDoom( unsigned int *kbEvents, unsigned char *nEvents ) { static int firstKeyScan = 1; @@ -557,7 +576,7 @@ void restartIncrementalBlitter() extern "C" void handleMouseUpdate( uint8_t *mouseData ); -extern "C" void blitScreenDOOM( unsigned char *koalaData, unsigned int *kbEvents, unsigned char *nEvents, unsigned char *mouseData ) +extern "C" void blitScreenDOOM( unsigned char *koalaData, unsigned int *kbEvents, unsigned char *nEvents, unsigned char *mouseData, unsigned char *joyData, int *mouseControlActive ) { static u8 fc = 0; register u32 g2; @@ -657,6 +676,9 @@ extern "C" void blitScreenDOOM( unsigned char *koalaData, unsigned int *kbEvents readKeyDoom( kbEvents, nEvents ); + // Read joydata if needed + if (!(*mouseControlActive)) readJoystick( joyData ); + // prepare reading mouse unsigned char tmp02, tmp00; SPEEK( 0xdc02, tmp02 ); From 593918affc6b73cc44be660f376fe75ea59ea164 Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Wed, 27 Mar 2024 09:36:00 +0100 Subject: [PATCH 02/14] clean up --- Source/Doom/d_iwad.c | 2 +- Source/Doom/w_file_stdc.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Doom/d_iwad.c b/Source/Doom/d_iwad.c index 06a1ed3..08d2fe9 100644 --- a/Source/Doom/d_iwad.c +++ b/Source/Doom/d_iwad.c @@ -722,7 +722,7 @@ char *D_FindIWAD(int mask, GameMission_t *mission, char *wadLocation) // Search through IWAD dirs for an IWAD with the given name. iwadfile = wadLocation; - + result = D_FindWADByName( iwadfile ); if (result == NULL) diff --git a/Source/Doom/w_file_stdc.c b/Source/Doom/w_file_stdc.c index 54d7999..48ba95a 100644 --- a/Source/Doom/w_file_stdc.c +++ b/Source/Doom/w_file_stdc.c @@ -30,7 +30,6 @@ typedef struct // This is needed for Doom 2. Even bigger wads will need an even bigger buffer unsigned char filebuffer[ 16 * 1024 * 1024 ];// = NULL; -//unsigned char filebuffer = NULL; extern wad_file_class_t stdc_wad_file; From 1dd8a1e640dfa62d2d150fac517fca0fc9797fba Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Fri, 29 Mar 2024 11:11:44 +0000 Subject: [PATCH 03/14] improved the menu and added support for more wads --- Source/Doom/d_main.c | 14 +-- Source/Doom/doomgeneric_rad.c | 12 +-- Source/Doom/i_main.c | 4 +- Source/Doom/w_file_stdc.c | 4 +- Source/rad_doom.cpp | 180 +++++++++++++++++++++++----------- 5 files changed, 130 insertions(+), 84 deletions(-) diff --git a/Source/Doom/d_main.c b/Source/Doom/d_main.c index ef71dae..d7df68f 100644 --- a/Source/Doom/d_main.c +++ b/Source/Doom/d_main.c @@ -1157,7 +1157,7 @@ static void LoadIwadDeh(void) // // D_DoomMain // -void D_DoomMain (int doomVersion) +void D_DoomMain (char* wadPath) { int p; char file[256]; @@ -1359,18 +1359,8 @@ void D_DoomMain (int doomVersion) // Save configuration at exit. I_AtExit(M_SaveDefaults, false); - // Find main IWAD file and load it. - char wadLocation[] = "RADDOOM/doom1.wad"; - char wadLocation2[] = "RADDOOM/doom2.wad"; - char wadLocation3[] = "RADDOOM/doom.wad"; - #if 1 - if (doomVersion == 3) - iwadfile = D_FindIWAD(IWAD_MASK_DOOM, &gamemission, wadLocation3); - else if (doomVersion == 2) - iwadfile = D_FindIWAD(IWAD_MASK_DOOM, &gamemission, wadLocation2); - else - iwadfile = D_FindIWAD(IWAD_MASK_DOOM, &gamemission, wadLocation); + iwadfile = D_FindIWAD(IWAD_MASK_DOOM, &gamemission, wadPath); // None found? diff --git a/Source/Doom/doomgeneric_rad.c b/Source/Doom/doomgeneric_rad.c index ad3135a..94c02e9 100644 --- a/Source/Doom/doomgeneric_rad.c +++ b/Source/Doom/doomgeneric_rad.c @@ -955,15 +955,9 @@ int introShowFrame() blitScreenDOOM( koalaData, kbEvents, &nEvents, mouseData, joyData, &mouseControlActive ); if ( nEvents ) { - - for (int i=0; i= 256 ) { - exitKey = showInfo(); + wadPath = showInfo(); for ( int y = 0; y < 200; y ++ ) { @@ -641,7 +703,7 @@ int doIntro() EnableIRQs(); - return exitKey; + return wadPath; } #endif @@ -681,16 +743,16 @@ void CRAD::Run( void ) sidtimer = new CUserTimer( &m_Interrupt, sidSamplePlayIRQ, this, !true ); sidtimer->Initialize(); - int doomVersion = 1; + char* wadPath = "RADDOOM/DOOM1.WAD"; #ifdef SHOW_INTRO - doomVersion = doIntro(); + wadPath = doIntro(); extern void restartIncrementalBlitter(); restartIncrementalBlitter(); #endif - startDoom(doomVersion); + startDoom(wadPath); } extern "C" void radMountFileSystem() From 60f8a321338f6325f86d56f17b41f759b3b5a941 Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Fri, 29 Mar 2024 15:27:33 +0000 Subject: [PATCH 04/14] menu improvements --- Source/rad_doom.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/rad_doom.cpp b/Source/rad_doom.cpp index 8fc0796..889e28b 100644 --- a/Source/rad_doom.cpp +++ b/Source/rad_doom.cpp @@ -291,14 +291,14 @@ void _printC64( const char *t, int x, int y, unsigned int color = 0xffffff) { // Creates the black outline int ofs[9][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}, {0, 0}}; for (int p = 0; p < 9; p++) { - uint32_t color1 = color; - uint32_t color2 = 0x5f5f5f; + uint32_t _color = color; + + if (p != 8) _color = 0; // Black outline - if (p != 8) color1 = color2 = 0; x += ofs[p][0]; y += ofs[p][1]; - printC64(t, x, y, color2); + printC64(t, x, y, _color); } } @@ -351,21 +351,21 @@ char* showInfo() { {"SD:RADDOOM/strife1.wad", "Strife", 0, "", false} }; - char nextMenuKey = 49; // ASCII '1' + char nextMenuKey = 65; // ASCII 'A' // Check if files exist and prepare menu lines for (int i = 0; i < sizeof(items) / sizeof(items[0]); i++) { items[i].exists = M_FileExists(items[i].path); if (items[i].exists) { items[i].key = nextMenuKey++; - sprintf(items[i].menuLine, "%d.) %s", items[i].key - 48, items[i].name); + sprintf(items[i].menuLine, "%c.) %s", items[i].key, items[i].name); } } uint64_t curTick = GetuSec(); char debug[30]; char lastKeyPressed = 0; - sprintf(debug, "debug: %d", lastKeyPressed); + sprintf(debug, "pressed: %c", lastKeyPressed); while (1) { int x = 4, y = 10, spacing = 10; @@ -373,7 +373,7 @@ char* showInfo() { bool noWads = true; for (int i = 0; i < sizeof(items) / sizeof(items[0]); i++) { if (items[i].exists) { - _printC64(items[i].menuLine, x, y); y += spacing; + _printC64(items[i].menuLine, x, y, (i%2) ? 0x0000FF : 0xFFFFFF); y += spacing; noWads = false; } } @@ -400,7 +400,7 @@ char* showInfo() { } lastKeyPressed = key; - sprintf(debug, "debug: %d", lastKeyPressed); + //sprintf(debug, "pressed: %c", lastKeyPressed); } return ""; From c443083767ea9a9ec142317aeeab67b6348aa56a Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Fri, 29 Mar 2024 15:52:04 +0000 Subject: [PATCH 05/14] clears screen when menu done --- Source/rad_doom.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/rad_doom.cpp b/Source/rad_doom.cpp index 889e28b..6779b0e 100644 --- a/Source/rad_doom.cpp +++ b/Source/rad_doom.cpp @@ -395,6 +395,11 @@ char* showInfo() { char key = (*functionAddress[1])(); for (int i = 0; i < sizeof(items) / sizeof(items[0]); i++) { if (key == items[i].key && items[i].exists) { + + // Clear screen before we return; + extern unsigned int *DG_ScreenBuffer; + memset( DG_ScreenBuffer, 0, 320 * 200 * 4 ); + return items[i].path + 3; // Omit 'SD:' } } From 2f0bf9c64a803d99cb217f61c0f4423b7c44a83d Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Fri, 29 Mar 2024 16:23:09 +0000 Subject: [PATCH 06/14] Stops sounds when menu shows --- Source/rad_doom.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/rad_doom.cpp b/Source/rad_doom.cpp index 6779b0e..06fdf81 100644 --- a/Source/rad_doom.cpp +++ b/Source/rad_doom.cpp @@ -676,6 +676,8 @@ char* doIntro() if ( fadeOut >= 256 ) { + // Stop sounds here + memset( soundRingBuffer, 0, SOUND_RINGBUF_SIZE ); wadPath = showInfo(); for ( int y = 0; y < 200; y ++ ) @@ -704,7 +706,7 @@ char* doIntro() introFC ++; } - memset( soundRingBuffer, 0, SOUND_RINGBUF_SIZE ); + //memset( soundRingBuffer, 0, SOUND_RINGBUF_SIZE ); EnableIRQs(); From 822f8d9231e3f8f6abb6e93e8a0db02fcd6df5dc Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Sat, 30 Mar 2024 23:18:27 +0000 Subject: [PATCH 07/14] 1 only wad = run that, small fixes and debug/error log --- Source/Doom/i_system.c | 29 ++++++++++++++++++++++++++ Source/rad_doom.cpp | 46 ++++++++++++++++++++++++++++++++---------- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/Source/Doom/i_system.c b/Source/Doom/i_system.c index 907ad7b..cae5a3d 100644 --- a/Source/Doom/i_system.c +++ b/Source/Doom/i_system.c @@ -354,6 +354,31 @@ static int ZenityErrorBox(char *message) // I_Error // +void vfdebug(const char* format, va_list args) { + char* filePath = "SD:debug.txt"; + FILE* file = fopen(filePath, "a"); + if (file == NULL) return; + + // Use vfprintf to write the formatted string to the file + vfprintf(file, format, args); + + // Optionally add a newline after appending the formatted string + fputc('\n', file); + + // Close the file + fclose(file); +} + +void fdebug(const char* format, ...) { + va_list args; + va_start(args, format); + + vfdebug(format, args); + + va_end(args); +} + + static boolean already_quitting = false; void I_Error (char *error, ...) @@ -377,6 +402,10 @@ void I_Error (char *error, ...) // Message first. va_start(argptr, error); + + // helps with logging any errors seen (if any) + vfdebug(error, argptr); + //fprintf(stderr, "\nError: "); vfprintf(stderr, error, argptr); fprintf(stderr, "\n\n"); diff --git a/Source/rad_doom.cpp b/Source/rad_doom.cpp index 06fdf81..6a6885d 100644 --- a/Source/rad_doom.cpp +++ b/Source/rad_doom.cpp @@ -274,7 +274,7 @@ const uint8_t ditherMatrix4x4_line[ 4 * 4 ] = { 8, 12, 10, 14, 3, 7, 1, 5, 11, 15, 9, 13 }; - + extern int palette_pepto[ 16 ][ 3 ]; extern "C" int (*functionAddress[]) (void); @@ -329,6 +329,23 @@ typedef struct { bool exists; // Flag indicating whether the file exists or not } MenuItem; +const unsigned int BLACK = 0x000000; +const unsigned int WHITE = 0xFFFFFF; +const unsigned int RED = 0x68372B; +const unsigned int CYAN = 0x70A4B2; +const unsigned int PURPLE = 0x6F3D86; +const unsigned int GREEN = 0x588D43; +const unsigned int BLUE = 0x352879; +const unsigned int YELLOW = 0xB8C76F; +const unsigned int ORANGE = 0x6F4F25; +const unsigned int BROWN = 0x433900; +const unsigned int PINK = 0x9A6759; +const unsigned int DARKGREY = 0x444444; +const unsigned int GREY = 0x6C6C6C; +const unsigned int LIGHTGREEN = 0x9AD284; +const unsigned int LIGHTBLUE = 0x6C5EB5; +const unsigned int LIGHTGREY = 0x959595; + char* showInfo() { // Init charset charset = font_bin; @@ -351,40 +368,47 @@ char* showInfo() { {"SD:RADDOOM/strife1.wad", "Strife", 0, "", false} }; + char nextMenuKey = 65; // ASCII 'A' // Check if files exist and prepare menu lines - for (int i = 0; i < sizeof(items) / sizeof(items[0]); i++) { + int _i = -1; + int numItems = sizeof(items) / sizeof(items[0]); + for (int i = 0; i < numItems; i++) { items[i].exists = M_FileExists(items[i].path); if (items[i].exists) { items[i].key = nextMenuKey++; sprintf(items[i].menuLine, "%c.) %s", items[i].key, items[i].name); + _i = i; // store index of last found wad } } + // Only one wad found .. use that one + if (nextMenuKey == 66) return items[_i].path + 3; // Omit 'SD:' + uint64_t curTick = GetuSec(); char debug[30]; char lastKeyPressed = 0; sprintf(debug, "pressed: %c", lastKeyPressed); while (1) { + printC64("ditlew", 110, 180, DARKGREY); + int x = 4, y = 10, spacing = 10; - bool noWads = true; - for (int i = 0; i < sizeof(items) / sizeof(items[0]); i++) { + for (int i = 0; i < numItems; i++) { if (items[i].exists) { - _printC64(items[i].menuLine, x, y, (i%2) ? 0x0000FF : 0xFFFFFF); y += spacing; - noWads = false; + _printC64(items[i].menuLine, x, y, (items[i].key % 2) ? WHITE : BLUE); y += spacing; } } - if (noWads) { + if (_i == -1) { _printC64("No wads found :(", x, y); y += spacing; } - if (lastKeyPressed) { - _printC64(debug, x, y); y += spacing; - } + // if (lastKeyPressed) { + // _printC64(debug, x, y); y += spacing; + // } // oh no, we're faster than 50 Hz, better wait :) uint64_t waitStart = curTick; @@ -405,7 +429,7 @@ char* showInfo() { } lastKeyPressed = key; - //sprintf(debug, "pressed: %c", lastKeyPressed); + sprintf(debug, "pressed: %c", lastKeyPressed); } return ""; From 56922e844ebe0f34d19bd454ab1b8387caecefa0 Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Sun, 31 Mar 2024 22:11:37 +0000 Subject: [PATCH 08/14] small bug fixes --- Source/Doom/d_main.c | 3 +- Source/Doom/i_main.c | 2 +- Source/rad_doom.cpp | 121 ++++++++++++++++++------------------------- 3 files changed, 51 insertions(+), 75 deletions(-) diff --git a/Source/Doom/d_main.c b/Source/Doom/d_main.c index d7df68f..f720866 100644 --- a/Source/Doom/d_main.c +++ b/Source/Doom/d_main.c @@ -1387,8 +1387,7 @@ lumphash = NULL; numiwadlumps = numlumps; #endif - // This breaks Doom2 support (even when called with doom2) - //W_CheckCorrectIWAD(doom); + W_CheckCorrectIWAD(doom); // Now that we've loaded the IWAD, we can figure out what gamemission // we're playing and which version of Vanilla Doom we need to emulate. diff --git a/Source/Doom/i_main.c b/Source/Doom/i_main.c index 699f51f..3c4a4c9 100644 --- a/Source/Doom/i_main.c +++ b/Source/Doom/i_main.c @@ -31,7 +31,7 @@ // calls all startup code, parses command line options. // -void D_DoomMain (int doomVersion); +void D_DoomMain (char* wadPath); void M_FindResponseFile(void); diff --git a/Source/rad_doom.cpp b/Source/rad_doom.cpp index 6a6885d..28b4118 100644 --- a/Source/rad_doom.cpp +++ b/Source/rad_doom.cpp @@ -287,39 +287,18 @@ extern "C" { boolean M_FileExists(char *filename); } extern uint8_t font_bin[ 4096 ]; extern uint8_t *charset; -void _printC64( const char *t, int x, int y, unsigned int color = 0xffffff) { +void _printC64( const char *t, int x, int y, unsigned int color = 0xffffff, unsigned int outline_color = 0x0) { // Creates the black outline int ofs[9][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}, {0, 0}}; for (int p = 0; p < 9; p++) { uint32_t _color = color; - if (p != 8) _color = 0; // Black outline + if (p != 8) _color = outline_color; // Black outline - x += ofs[p][0]; - y += ofs[p][1]; - - printC64(t, x, y, _color); + printC64(t, x + ofs[p][0], y + ofs[p][1], _color); } } -/* - { "doom2.wad", doom2, commercial, "Doom II" }, - { "plutonia.wad", pack_plut, commercial, "Final Doom: Plutonia Experiment" }, - { "tnt.wad", pack_tnt, commercial, "Final Doom: TNT: Evilution" }, - { "doom.wad", doom, retail, "Doom" }, - { "DOOM1.WAD", doom, shareware, "Doom Shareware" }, - { "chex.wad", pack_chex, shareware, "Chex Quest" }, - { "hacx.wad", pack_hacx, commercial, "Hacx" }, - { "freedm.wad", doom2, commercial, "FreeDM" }, - { "freedoom2.wad", doom2, commercial, "Freedoom: Phase 2" }, - { "freedoom1.wad", doom, retail, "Freedoom: Phase 1" }, - { "heretic.wad", heretic, retail, "Heretic" }, - { "heretic1.wad", heretic, shareware, "Heretic Shareware" }, - { "hexen.wad", hexen, commercial, "Hexen" }, - //{ "strife0.wad", strife, commercial, "Strife" }, // haleyjd: STRIFE-FIXME - { "strife1.wad", strife, commercial, "Strife" }, -*/ - // Menu item structure typedef struct { char* path; @@ -329,46 +308,45 @@ typedef struct { bool exists; // Flag indicating whether the file exists or not } MenuItem; -const unsigned int BLACK = 0x000000; -const unsigned int WHITE = 0xFFFFFF; -const unsigned int RED = 0x68372B; -const unsigned int CYAN = 0x70A4B2; -const unsigned int PURPLE = 0x6F3D86; -const unsigned int GREEN = 0x588D43; -const unsigned int BLUE = 0x352879; -const unsigned int YELLOW = 0xB8C76F; -const unsigned int ORANGE = 0x6F4F25; -const unsigned int BROWN = 0x433900; -const unsigned int PINK = 0x9A6759; -const unsigned int DARKGREY = 0x444444; -const unsigned int GREY = 0x6C6C6C; -const unsigned int LIGHTGREEN = 0x9AD284; -const unsigned int LIGHTBLUE = 0x6C5EB5; -const unsigned int LIGHTGREY = 0x959595; - -char* showInfo() { +const unsigned int BLACK = 0x000000; // 0 +const unsigned int WHITE = 0xFFFFFF; // 1 +const unsigned int RED = 0x68372B; // 2 +const unsigned int CYAN = 0x70A4B2; // 3 +const unsigned int PURPLE = 0x6F3D86; // 4 +const unsigned int GREEN = 0x588D43; // 5 +const unsigned int BLUE = 0x352879; // 6 +const unsigned int YELLOW = 0xB8C76F; // 7 +const unsigned int ORANGE = 0x6F4F25; // 8 +const unsigned int BROWN = 0x433900; // 9 +const unsigned int PINK = 0x9A6759; // 10 +const unsigned int DARKGREY = 0x444444; // 11 +const unsigned int GREY = 0x6C6C6C; // 12 +const unsigned int LIGHTGREEN = 0x9AD284; // 13 +const unsigned int LIGHTBLUE = 0x6C5EB5; // 14 +const unsigned int LIGHTGREY = 0x959595; // 15 + +// All the WADS supported by doomgeneric .. not sure all works with RAD yet +MenuItem items[] = { + {"SD:RADDOOM/DOOM.WAD", "Doom SW", 0, "", false}, + {"SD:RADDOOM/DOOM1.WAD", "Doom", 0, "", false}, + {"SD:RADDOOM/DOOM2.WAD", "DoomII", 0, "", false}, + {"SD:RADDOOM/plutonia.wad", "FDoom P.E.", 0, "", false}, + {"SD:RADDOOM/tnt.wad", "FDoom TNT E.", 0, "", false}, + {"SD:RADDOOM/chex.wad", "Chex Quest", 0, "", false}, + {"SD:RADDOOM/hacx.wad", "Hacx", 0, "", false}, + {"SD:RADDOOM/freedm.wad", "FreeDM", 0, "", false}, + {"SD:RADDOOM/freedoom1.wad", "Freedoom P1", 0, "", false}, + {"SD:RADDOOM/freedoom2.wad", "Freedoom P2", 0, "", false} +}; + + +int showInfo() { + extern unsigned int *DG_ScreenBuffer; + memset( DG_ScreenBuffer, 11, 320 * 200 * 4 ); + // Init charset charset = font_bin; - // All the WADS supported by doomgeneric .. not sure all works with RAD yet - MenuItem items[] = { - {"SD:RADDOOM/DOOM.WAD", "Doom SW", 0, "", false}, - {"SD:RADDOOM/DOOM1.WAD", "Doom", 0, "", false}, - {"SD:RADDOOM/DOOM2.WAD", "DoomII", 0, "", false}, - {"SD:RADDOOM/plutonia.wad", "FDoom P.E.", 0, "", false}, - {"SD:RADDOOM/tnt.wad", "FDoom TNT E.", 0, "", false}, - {"SD:RADDOOM/chex.wad", "Chex Quest", 0, "", false}, - {"SD:RADDOOM/hacx.wad", "Hacx", 0, "", false}, - {"SD:RADDOOM/freedm.wad", "FreeDM", 0, "", false}, - {"SD:RADDOOM/freedoom1.wad", "Freedoom P1", 0, "", false}, - {"SD:RADDOOM/freedoom2.wad", "Freedoom P2", 0, "", false}, - {"SD:RADDOOM/heretic.wad", "Heretic", 0, "", false}, - {"SD:RADDOOM/heretic1.wad", "Heretic SW", 0, "", false}, - {"SD:RADDOOM/hexen.wad", "Hexen", 0, "", false}, - {"SD:RADDOOM/strife1.wad", "Strife", 0, "", false} - }; - - char nextMenuKey = 65; // ASCII 'A' // Check if files exist and prepare menu lines @@ -384,7 +362,7 @@ char* showInfo() { } // Only one wad found .. use that one - if (nextMenuKey == 66) return items[_i].path + 3; // Omit 'SD:' + if (nextMenuKey == 66) return _i; uint64_t curTick = GetuSec(); char debug[30]; @@ -421,10 +399,9 @@ char* showInfo() { if (key == items[i].key && items[i].exists) { // Clear screen before we return; - extern unsigned int *DG_ScreenBuffer; memset( DG_ScreenBuffer, 0, 320 * 200 * 4 ); - return items[i].path + 3; // Omit 'SD:' + return i; } } @@ -432,12 +409,12 @@ char* showInfo() { sprintf(debug, "pressed: %c", lastKeyPressed); } - return ""; + return 0; } -char* doIntro() +int doIntro() { - char* wadPath = "RADDOOM/DOOM1.WAD"; // default to doom sw + int itemIndex = 0; wavMemory = new u8[ 8192 * 1024 ]; @@ -702,7 +679,7 @@ char* doIntro() { // Stop sounds here memset( soundRingBuffer, 0, SOUND_RINGBUF_SIZE ); - wadPath = showInfo(); + itemIndex = showInfo(); for ( int y = 0; y < 200; y ++ ) { @@ -734,7 +711,7 @@ char* doIntro() EnableIRQs(); - return wadPath; + return itemIndex; } #endif @@ -774,16 +751,16 @@ void CRAD::Run( void ) sidtimer = new CUserTimer( &m_Interrupt, sidSamplePlayIRQ, this, !true ); sidtimer->Initialize(); - char* wadPath = "RADDOOM/DOOM1.WAD"; + int itemIndex = 0; #ifdef SHOW_INTRO - wadPath = doIntro(); + itemIndex = doIntro(); extern void restartIncrementalBlitter(); restartIncrementalBlitter(); #endif - startDoom(wadPath); + startDoom(items[itemIndex].path + 3); // Omit SD: } extern "C" void radMountFileSystem() From a6da0aa5ffb52458dde858da8a0b5c348fd55517 Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Tue, 9 Apr 2024 20:32:32 +0000 Subject: [PATCH 09/14] Press 'u' to have a C64 friendly UI when playing --- Source/Doom/d_main.c | 3 + Source/Doom/doomgeneric_rad.c | 229 ++++++++++++++++++++++++++++++++++ Source/Doom/g_game.c | 10 +- Source/Doom/st_stuff.c | 29 ++++- 4 files changed, 265 insertions(+), 6 deletions(-) diff --git a/Source/Doom/d_main.c b/Source/Doom/d_main.c index f720866..2cc35cd 100644 --- a/Source/Doom/d_main.c +++ b/Source/Doom/d_main.c @@ -573,6 +573,9 @@ void D_DoAdvanceDemo (void) break; } + // Let the c64UI know of the new state + setGameState(gamestate); + // The Doom 3: BFG Edition version of doom2.wad does not have a // TITLETPIC lump. Use INTERPIC instead as a workaround. if (bfgedition && !strcasecmp(pagename, "TITLEPIC") diff --git a/Source/Doom/doomgeneric_rad.c b/Source/Doom/doomgeneric_rad.c index 94c02e9..f193e2b 100644 --- a/Source/Doom/doomgeneric_rad.c +++ b/Source/Doom/doomgeneric_rad.c @@ -158,6 +158,7 @@ void setDisplayPreset( int p ) } static int mouseControlActive = 0; +static boolean c64UIActivated = false; #define VK_F1 133 #define VK_F3 134 @@ -289,6 +290,9 @@ int mouseMaxVal[ 2 ] = { 0, 0 }; int mouseLastVal[ 2 ]; uint8_t mouseFirstPos = 1; +// Used when flipping in and out of c64 UI mode +extern void R_SetViewSize( int blocks, int detail ); + static void addKeyToQueue( int pressed, uint8_t keyCode ) { uint8_t key = convertToDoomKey( keyCode ); @@ -334,6 +338,12 @@ static void addKeyToQueue( int pressed, uint8_t keyCode ) alternatePattern = 1 - alternatePattern; displayStatus = 100; displayPreset = 0; return; + case 'U': case 'u': + c64UIActivated = !c64UIActivated; + // Ignores prev state and switches between full size and nearly fullsize (both in hq) + R_SetViewSize((c64UIActivated) ? 11 : 10, 0); + return; + /* case 'F': case 'f': testVal = max( 0, (int)testVal - 1 ); displayStatus = 100; return; @@ -1002,6 +1012,156 @@ void printC64( const char *t, int x_, int y, uint32_t color ) } } +// These will only be correct at brightness 12 +const unsigned int BLACK = 0x000000; // 0 +const unsigned int WHITE = 0xFFFFFF; // 1 +const unsigned int RED = 0x68372B; // 2 +const unsigned int CYAN = 0x70A4B2; // 3 +const unsigned int PURPLE = 0x6F3D86; // 4 +const unsigned int GREEN = 0x588D43; // 5 +const unsigned int BLUE = 0x352879; // 6 +const unsigned int YELLOW = 0xB8C76F; // 7 +const unsigned int ORANGE = 0x6F4F25; // 8 +const unsigned int BROWN = 0x433900; // 9 +const unsigned int PINK = 0x9A6759; // 10 +const unsigned int DARKGREY = 0x444444; // 11 +const unsigned int GREY = 0x6C6C6C; // 12 +const unsigned int LIGHTGREEN = 0x9AD284; // 13 +const unsigned int LIGHTBLUE = 0x6C5EB5; // 14 +const unsigned int LIGHTGREY = 0x959595; // 15 + +void c64Print( const char *t, int x, int y, unsigned int color, boolean outlined) { + + if (outlined) { + // Creates the black outline + int ofs[8][2] = { {-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1} }; + for (int p = 0; p < 8; p++) + printC64(t, x + ofs[p][0], y + ofs[p][1], BLACK); + } + + printC64(t, x, y, color); +} + +void c64PrintScaled( const char *t, int x_, int y, uint32_t color, int scale_x, int scale_y ) +{ + scale_x = max(1,scale_x); + scale_y = max(1,scale_y); + + int len = strlen( t ); + + for ( int i = 0; i < len; i++ ) + { + uint8_t c = t[ i ]; + int x = x_ + i * 8; + + if ( c == '@' ) + c = 0; + else if ( c == '_' ) + c = 100; + else if ( ( c >= 'a' ) && ( c <= 'z' ) ) + c = c + 1 - 'a'; + + if ( c != 32 && c != ( 32 + 128 ) ) + { + for ( int b = 0; b < 8; b++ ) + { + uint8_t v = charset[ 2048 + c * 8 + b ]; + + for ( int p = 0; p < 7; p++ ) + { + if ( v & 128 ) + { + // Calculate indices for both pixels in each double-height pair + int index1 = (x+p) * scale_x + (y+b * scale_y) * 320; + int index2 = index1 + 320; + + for (int sx=0; sx= 64000) return; // Larger than 320x200 is no go + DG_ScreenBuffer[index] = color; +} + + +// DD: Tbh .. this is ugly +boolean alive = false; + +uint8_t ammo = 0; +uint8_t health = 0; +uint8_t armor = 0; + +uint8_t a_ammo[4] = { 0,0,0,0 }; +uint8_t a_ammoMax[4] = { 0,0,0,0 }; + +boolean a_arms[6] = { 0,0,0,0,0,0,0 }; +boolean a_cards[6] = { 0,0,0,0,0,0,0 }; + +uint8_t gameState = 1; // intermission + +// DD: Tbh .. this is ugly too +void updateNumbers( boolean _alive, int _ammo, int _health, int _armor, int _ammo1, int _ammo_max1, int _ammo2, int _ammo_max2, int _ammo3, int _ammo_max3, int _ammo4, int _ammo_max4, boolean* _arms, boolean* _cards) +{ + alive = _alive; + ammo = _ammo; + health = _health; + armor = _armor; + + a_ammo[0] = _ammo1; + a_ammo[1] = _ammo2; + a_ammo[2] = _ammo3; + a_ammo[3] = _ammo4; + + a_ammoMax[0] = _ammo_max1; + a_ammoMax[1] = _ammo_max2; + a_ammoMax[2] = _ammo_max3; + a_ammoMax[3] = _ammo_max4; + + for (int i = 0; _arms != NULL && i < 6; i ++) + a_arms[i] = _arms[i+1] ? true : false; + + for (int i = 0; _cards != NULL && i < 6; i ++) + a_cards[i] = _cards[i] ? true : false; +} + +void setGameState(uint8_t state) { + gameState = state; +} + uint64_t endLastFrame = -1; extern uint64_t GetuSec(); @@ -1083,6 +1243,75 @@ void DG_DrawFrame() s_KeyQueueReadIndex = 0; } + // DD: Show the c64 UI if alive, activate and we aren't between levels + if (alive && gameState != 1 && c64UIActivated) { + + int ammoWidth = 42; + int ammoWidth1 = max(0, min(ammoWidth, (ammoWidth * a_ammo[0]) / a_ammoMax[0])); + int ammoWidth2 = max(0, min(ammoWidth, (ammoWidth * a_ammo[1]) / a_ammoMax[1])); + int ammoWidth3 = max(0, min(ammoWidth, (ammoWidth * a_ammo[2]) / a_ammoMax[2])); + int ammoWidth4 = max(0, min(ammoWidth, (ammoWidth * a_ammo[4]) / a_ammoMax[3])); + + c64Fill(272, 170, ammoWidth1, 6, GREEN); + c64Fill(272, 177, ammoWidth2, 6, GREEN); + c64Fill(272, 184, ammoWidth3, 6, GREEN); + c64Fill(272, 191, ammoWidth4, 6, GREEN); + + c64Fill(110, 172, 6, 6, (a_arms[0]) ? GREEN : DARKGREY); + c64Fill(122, 172, 6, 6, (a_arms[1]) ? GREEN : DARKGREY); + c64Fill(134, 172, 6, 6, (a_arms[2]) ? GREEN : DARKGREY); + c64Fill(110, 182, 6, 6, (a_arms[3]) ? GREEN : DARKGREY); + c64Fill(122, 182, 6, 6, (a_arms[4]) ? GREEN : DARKGREY); + c64Fill(134, 182, 6, 6, (a_arms[5]) ? GREEN : DARKGREY); + + int yellowColor = (brightnessScale >= 17) ? PINK : YELLOW; + + c64Fill(238, 171, 8, 6, (a_cards[0] || a_cards[3]) ? BLUE : DARKGREY); + c64Fill(238, 181, 8, 6, (a_cards[1] || a_cards[4]) ? yellowColor : DARKGREY); + c64Fill(238, 191, 8, 6, (a_cards[2] || a_cards[5]) ? RED : DARKGREY); + +#ifdef FALSE + // Testing the colors + c64Fill(0, 0, 10, 10, BLACK); + c64Fill(0, 10, 10, 10, WHITE); + c64Fill(0, 20, 10, 10, RED); + c64Fill(0, 30, 10, 10, CYAN); + c64Fill(0, 40, 10, 10, PURPLE); + c64Fill(0, 50, 10, 10, GREEN); + c64Fill(0, 60, 10, 10, BLUE); + c64Fill(0, 70, 10, 10, YELLOW); + c64Fill(10, 0, 10, 10, ORANGE); + c64Fill(10, 10, 10, 10, BROWN); + c64Fill(10, 20, 10, 10, PINK); + c64Fill(10, 30, 10, 10, DARKGREY); + c64Fill(10, 40, 10, 10, GREY); + c64Fill(10, 50, 10, 10, LIGHTGREEN); + c64Fill(10, 60, 10, 10, LIGHTBLUE); + c64Fill(10, 70, 10, 10, LIGHTGREY); +#endif + + // Just for testing scaling + // _printC64_Adv("D", 2, 2, WHITE, 4, 4); // White + + if (ammo < 1000) { + char s1[30]; + sprintf(s1,"%3d", ammo); + c64PrintAvd(s1, 0, 171, RED, true, 2, 2); + } + + if (health < 1000) { + char s2[30]; + sprintf(s2,"%3d", health); + c64PrintAvd(s2, 28, 171, RED, true, 2, 2); + } + + if (armor < 1000) { + char s3[30]; + sprintf(s3,"%3d", armor); + c64PrintAvd(s3, 92, 171, RED, true, 2, 2); + } + } + // print static text int ofs[9][2]={ {-1,-1}, {-1,0},{-1,1}, {0,-1}, {0,1}, {1,-1},{1,0},{1,1},{0,0}}; if ( displayHelp ) diff --git a/Source/Doom/g_game.c b/Source/Doom/g_game.c index 9954d78..1798b37 100644 --- a/Source/Doom/g_game.c +++ b/Source/Doom/g_game.c @@ -596,6 +596,7 @@ void G_BuildTiccmd (ticcmd_t* cmd, int maketic) } } +extern void setGameState( unsigned char state); // // G_DoLoadLevel @@ -642,7 +643,8 @@ void G_DoLoadLevel (void) if (wipegamestate == GS_LEVEL) wipegamestate = -1; // force a wipe - gamestate = GS_LEVEL; + gamestate = GS_LEVEL; + setGameState(gamestate); for (i=0 ; iplayerstate == PST_LIVE), + *w_ready.num, *w_health.n.num, *w_armor.n.num, + *w_ammo[0].num, *w_maxammo[0].num, + *w_ammo[1].num, *w_maxammo[1].num, + *w_ammo[2].num, *w_maxammo[2].num, + *w_ammo[3].num, *w_maxammo[3].num, + &plyr->weaponowned, + &plyr->cards + ); + STlib_updateNum(&w_ready, refresh); for (i=0;i<4;i++) { - STlib_updateNum(&w_ammo[i], refresh); - STlib_updateNum(&w_maxammo[i], refresh); + STlib_updateNum(&w_ammo[i], refresh); + STlib_updateNum(&w_maxammo[i], refresh); } STlib_updatePercent(&w_health, refresh); @@ -1022,12 +1035,12 @@ void ST_drawWidgets(boolean refresh) STlib_updateBinIcon(&w_armsbg, refresh); for (i=0;i<6;i++) - STlib_updateMultIcon(&w_arms[i], refresh); + STlib_updateMultIcon(&w_arms[i], refresh); STlib_updateMultIcon(&w_faces, refresh); for (i=0;i<3;i++) - STlib_updateMultIcon(&w_keyboxes[i], refresh); + STlib_updateMultIcon(&w_keyboxes[i], refresh); STlib_updateNum(&w_frags, refresh); @@ -1400,6 +1413,14 @@ void ST_Start (void) void ST_Stop (void) { + updateNumbers(false, + 0,0,0, + 0,0,0,0, + 0,0,0,0, + NULL, + NULL + ); + if (st_stopped) return; From 4cb3f53d0a259ccbd328aad4508dcba7231a7819 Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Wed, 10 Apr 2024 20:07:21 +0000 Subject: [PATCH 10/14] Added a little menu animation --- Source/Doom/doomgeneric_rad.c | 6 ++- Source/rad_doom.cpp | 86 +++++++++++++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/Source/Doom/doomgeneric_rad.c b/Source/Doom/doomgeneric_rad.c index f193e2b..cd2b01c 100644 --- a/Source/Doom/doomgeneric_rad.c +++ b/Source/Doom/doomgeneric_rad.c @@ -130,6 +130,10 @@ static int displayHelp = 0; static int flickerMode = 0; static int16_t brightnessScale = 20; +void setBrightness(uint8_t level) { + brightnessScale = level; +} + void setDisplayPreset( int p ) { switch ( p ) @@ -975,7 +979,7 @@ int introShowFrame() int (*functionAddress[]) (void) = { introPrepare, - introShowFrame, + introShowFrame }; diff --git a/Source/rad_doom.cpp b/Source/rad_doom.cpp index 28b4118..6b9ae7e 100644 --- a/Source/rad_doom.cpp +++ b/Source/rad_doom.cpp @@ -38,6 +38,7 @@ #include "linux/kernel.h" #include "config.h" #include +#include #include #include #include @@ -325,6 +326,28 @@ const unsigned int LIGHTGREEN = 0x9AD284; // 13 const unsigned int LIGHTBLUE = 0x6C5EB5; // 14 const unsigned int LIGHTGREY = 0x959595; // 15 + + +// Ensure we dont go out of buffer +inline void setPixel(int index, uint32_t color) { + extern unsigned int *DG_ScreenBuffer; + + if (index >= 64000) return; // Larger than 320x200 is no go + DG_ScreenBuffer[index] = color; +} + +void c64Fill(int x, int y, int width, int height, uint32_t color) { + // DD: Wonder if a menset per row would be faster here .. + for (int row = 0; row < height; row++) { + for (int col = 0; col < width; col++) { + // Calculate the index in the DG_ScreenBuffer for each pixel in the square + int index = (x + col) + (y + row) * 320; // Assuming the screen is 320 pixels wide + + setPixel(index, color); + } + } +} + // All the WADS supported by doomgeneric .. not sure all works with RAD yet MenuItem items[] = { {"SD:RADDOOM/DOOM.WAD", "Doom SW", 0, "", false}, @@ -339,10 +362,52 @@ MenuItem items[] = { {"SD:RADDOOM/freedoom2.wad", "Freedoom P2", 0, "", false} }; +const u_int8_t _FSIZE = 10; +const u_int8_t _WIDTH = 320 / _FSIZE; +const u_int8_t _HEIGHT = 200 / _FSIZE; + +// Flames buffer +unsigned int FLAMES[_WIDTH * _HEIGHT]; + +void generateFlamesBase() { + for (int x = 0; x < _WIDTH; ++x) { + FLAMES[(_HEIGHT - 1) * _WIDTH + x] = WHITE; + } +} + +void updateFlames() { + for (int y = 0; y < _HEIGHT - 1; ++y) { + for (int x = 0; x < _WIDTH; ++x) { + int sameColorNeighbors = 0; + unsigned int belowColor = FLAMES[(y + 1) * _WIDTH + x]; + + if (x > 0 && FLAMES[y * _WIDTH + (x - 1)] == belowColor) sameColorNeighbors++; + if (x < _WIDTH - 1 && FLAMES[y * _WIDTH + (x + 1)] == belowColor) sameColorNeighbors++; + + float transitionChance = (float)rand() / RAND_MAX - 0.1f * sameColorNeighbors; + + if (belowColor == WHITE && transitionChance < 0.6f) { + FLAMES[y * _WIDTH + x] = YELLOW; + } else if (belowColor == YELLOW && transitionChance < 0.6f) { + FLAMES[y * _WIDTH + x] = ORANGE; + } else if (belowColor == ORANGE && transitionChance < 0.6f) { + FLAMES[y * _WIDTH + x] = RED; + } else if (belowColor == RED && transitionChance < 0.6f) { + FLAMES[y * _WIDTH + x] = BLACK; + } else { + FLAMES[y * _WIDTH + x] = belowColor; // Keep the same color if no transition + } + } + } +} + +extern "C" void setBrightness(uint8_t level); int showInfo() { extern unsigned int *DG_ScreenBuffer; - memset( DG_ScreenBuffer, 11, 320 * 200 * 4 ); + setBrightness(12); // Lower the brightness to match the original C64 colors + + memset( DG_ScreenBuffer, BLACK, 320 * 200 * 4 ); // Init charset charset = font_bin; @@ -369,14 +434,26 @@ int showInfo() { char lastKeyPressed = 0; sprintf(debug, "pressed: %c", lastKeyPressed); + srand(0); + generateFlamesBase(); + + u_int16_t fps = 0; while (1) { - printC64("ditlew", 110, 180, DARKGREY); + + // Lower animation speed + if (fps++ % 4 == 0) updateFlames(); + + for (int row=0; row < _HEIGHT; row ++) + for (int col=0; col < _WIDTH; col ++) + c64Fill(col * _FSIZE, row * _FSIZE, _FSIZE, _FSIZE, FLAMES[row * _WIDTH + col]); + + printC64("ditlew", 110, 182, BLACK); int x = 4, y = 10, spacing = 10; for (int i = 0; i < numItems; i++) { if (items[i].exists) { - _printC64(items[i].menuLine, x, y, (items[i].key % 2) ? WHITE : BLUE); y += spacing; + _printC64(items[i].menuLine, x, y, (items[i].key % 2) ? WHITE : CYAN); y += spacing; } } @@ -401,6 +478,7 @@ int showInfo() { // Clear screen before we return; memset( DG_ScreenBuffer, 0, 320 * 200 * 4 ); + setBrightness(20); return i; } } @@ -409,6 +487,8 @@ int showInfo() { sprintf(debug, "pressed: %c", lastKeyPressed); } + setBrightness(20); + return 0; } From 405c824c884586c6660f82523c16211397053536 Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Thu, 11 Apr 2024 21:45:48 +0000 Subject: [PATCH 11/14] fix max ammo UI bug --- Source/Doom/doomgeneric_rad.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/Doom/doomgeneric_rad.c b/Source/Doom/doomgeneric_rad.c index cd2b01c..3659f0a 100644 --- a/Source/Doom/doomgeneric_rad.c +++ b/Source/Doom/doomgeneric_rad.c @@ -1125,17 +1125,17 @@ inline void setPixel(int index, uint32_t color) { // DD: Tbh .. this is ugly boolean alive = false; -uint8_t ammo = 0; -uint8_t health = 0; -uint8_t armor = 0; +uint16_t ammo = 0; +uint16_t health = 0; +uint16_t armor = 0; -uint8_t a_ammo[4] = { 0,0,0,0 }; -uint8_t a_ammoMax[4] = { 0,0,0,0 }; +uint16_t a_ammo[4] = { 0,0,0,0 }; +uint16_t a_ammoMax[4] = { 0,0,0,0 }; boolean a_arms[6] = { 0,0,0,0,0,0,0 }; boolean a_cards[6] = { 0,0,0,0,0,0,0 }; -uint8_t gameState = 1; // intermission +uint8_t gameState = 1; // Intermission // DD: Tbh .. this is ugly too void updateNumbers( boolean _alive, int _ammo, int _health, int _armor, int _ammo1, int _ammo_max1, int _ammo2, int _ammo_max2, int _ammo3, int _ammo_max3, int _ammo4, int _ammo_max4, boolean* _arms, boolean* _cards) From 9e6c3892a4107d7afb7d86f972846cbe6c919950 Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Fri, 12 Apr 2024 15:49:04 +0000 Subject: [PATCH 12/14] Updates to the readme --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5babe6f..3b67d4a 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Welcome to this tech-demo for the **RAD Expansion Unit**. The "RAD" is a Raspberry Pi-powered cartridge/expansion for the C64 and C128 and, for example, can be used to emulate memory expansions (please have a look at its [main page](https://github.com/frntc/RAD)). -In this tech-demo the **RAD replaces the MOS6510/8500/8502-CPU of your C64/C128** and natively runs DOOM on the ARM CPU. The purpose of the demo is to experiment with real-time graphics (on-the-fly color reduction and conversion from RGB-frame buffers), sound streaming to the SID, and using C64 peripherals such as keyboard, mouse and MIDI-interfaces. Note that it is currently set up for **PAL machines only**. +In this tech-demo the **RAD replaces the MOS6510/8500/8502-CPU of your C64/C128** and natively runs DOOM on the ARM CPU. The purpose of the demo is to experiment with real-time graphics (on-the-fly color reduction and conversion from RGB-frame buffers), sound streaming to the SID, and using C64 peripherals such as keyboard, joystick, mouse and MIDI-interfaces. Note that it is currently set up for **PAL machines only**. In short, here is what you can experience: @@ -37,7 +37,7 @@ In short, here is what you can experience: Obviously you need a RAD Expansion Unit (see [project page](https://github.com/frntc/RAD) on how to build and setup one) and a Raspberry Pi 3A+/3B+/Zero 2. To play Doom, first download the release archive of this project and copy it to a FAT-formatted SD-card. -Second, you need to download the "doom1.wad" of the shareware version of Doom (e.g. from [doomwiki.org](https://doomwiki.org/wiki/DOOM1.WAD)) and copy it into the "RADDOOM" folder on the SD-card. +Second, you need to download the "doom1.wad" of the shareware version of Doom (e.g. from [doomwiki.org](https://doomwiki.org/wiki/DOOM1.WAD)) and copy it into the "RADDOOM" folder on the SD-card. If you own a copy of Doom, Doom II, Final Doom: Plutonia Experiment, Final Doom: TNT: Evilution, Chex Quest, FreeDM, Freedoom: Phase 1 + 2, the WAD files from those games should also work. Any errors starting the game will be written into debug.txt on the SD-card. You also need a *sound font* in *.sf2*-format for the built-in MIDI synthesizer which plays via the SID or Digimax (the sound synthesis uses [TinySoundFont](https://github.com/schellingb/TinySoundFont)). This file also has to be copied to the "RADDOOM"-folder and named *"soundfont.sf2"*. One freely available sound font (but there are many others) is the [GeneralUser GS](http://schristiancollins.com/generaluser.php), which is also included in the [mt32pi](https://github.com/dwhinham/mt32-pi) release. mt32pi is a MIDI-synthesizer based on a Raspberry Pi which can be used with MIDI interfaces for the C64/C128. Note that the size of the sound font-file dominates the loading time. @@ -45,8 +45,9 @@ Speaking of MIDI interfaces: external MIDI interfaces will requires a cartridge To **configure the sound output**, check the *config.txt* on the SD-card. In case the RAD needs some timing adjustments, please follow the instructions on the RAD main page and adjust timings first with the standard RAD software. -Pressing *F1* while running Doom shows a help screen, *F3* toggles between mouse (port #2) and keyboard controls. +Pressing *F1* while running Doom shows a help screen, *F3* toggles between mouse (port #2) and keyboard + joystick (also port #2) controls. +Pressing 'u' will toggle an ingame C64/C128 friendly version of the game UI. ## Technical Details From 92692e80346ffdcbdbed6fb0895b88ef2b37df59 Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Fri, 12 Apr 2024 15:56:42 +0000 Subject: [PATCH 13/14] Help updated --- README.md | 2 +- Source/Doom/doomgeneric_rad.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b67d4a..07525b8 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ To **configure the sound output**, check the *config.txt* on the SD-card. In cas Pressing *F1* while running Doom shows a help screen, *F3* toggles between mouse (port #2) and keyboard + joystick (also port #2) controls. -Pressing 'u' will toggle an ingame C64/C128 friendly version of the game UI. +Pressing 'U' will toggle a C64/C128 friendly version of the ingame UI / HUD. ## Technical Details diff --git a/Source/Doom/doomgeneric_rad.c b/Source/Doom/doomgeneric_rad.c index 3659f0a..820049b 100644 --- a/Source/Doom/doomgeneric_rad.c +++ b/Source/Doom/doomgeneric_rad.c @@ -1356,6 +1356,7 @@ void DG_DrawFrame() printC64( "brightness ... E,D ", x, y, color2 ); y += spacing; printC64( "shuffle ...... F ", x, y, color2 ); y += spacing; printC64( "presets ...... R ", x, y, color2 ); y += spacing; + printC64( "C= HUD ....... U ", x, y, color2 ); y += spacing; printC64( "show config .. F5 ", x, y, color2 ); y += spacing; if ( mouseControlActive ) From 6dc83fe7bb8c7a5eed73e03fd56b50cd932d59c4 Mon Sep 17 00:00:00 2001 From: Daniel Ditlev Date: Fri, 12 Apr 2024 16:13:27 +0000 Subject: [PATCH 14/14] updated help screen --- Source/Doom/doomgeneric_rad.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Doom/doomgeneric_rad.c b/Source/Doom/doomgeneric_rad.c index 820049b..fe390b7 100644 --- a/Source/Doom/doomgeneric_rad.c +++ b/Source/Doom/doomgeneric_rad.c @@ -1330,7 +1330,7 @@ void DG_DrawFrame() uint32_t color = 0xffffff; uint32_t color2 = 0x5f5f5f; int x = 4, spacing = 10; - int y = 10; + int y = 5; if ( p != 8 ) color = color2 = 0; x += ofs[ p ][ 0 ]; @@ -1340,7 +1340,8 @@ void DG_DrawFrame() if ( !mouseControlActive ) { printC64( "12345... I ", x, y, color ); y += spacing; - printC64( " JKL ", x, y, color ); y += spacing; y += spacing; y += spacing; + printC64( " JKL ", x, y, color ); y += spacing; + printC64( " or JOY2 ", x, y, color ); y += spacing; y += spacing; printC64( " C= SHIFT ZX ", x, y, color ); y += spacing; } else { @@ -1360,7 +1361,7 @@ void DG_DrawFrame() printC64( "show config .. F5 ", x, y, color2 ); y += spacing; if ( mouseControlActive ) - { printC64( "keyboard ..... F3 ", x, y, color2 ); y += spacing; } else + { printC64( "keyboard + JOY F3 ", x, y, color2 ); y += spacing; } else { printC64( "mouse ........ F3 ", x, y, color2 ); y += spacing; } } } else