diff --git a/CGDOOM_SELECTED.png b/CGDOOM_SELECTED.png deleted file mode 100644 index 2423e6c..0000000 Binary files a/CGDOOM_SELECTED.png and /dev/null differ diff --git a/CGDOOM_UNSELECTED.png b/CGDOOM_UNSELECTED.png deleted file mode 100644 index 0426681..0000000 Binary files a/CGDOOM_UNSELECTED.png and /dev/null differ diff --git a/Makefile b/Makefile index fc71297..c776748 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ all: all-cg all-cg: $(NAME).g3a $(NAME).g3a: build-cg/$(NAME).bin - mkg3a -n : -i uns:CGDOOM_UNSELECTED.png -i sel:CGDOOM_SELECTED.png $< $@ + mkg3a -n CGDoom -i uns:icon-uns.png -i sel:icon-sel.png $< $@ build-cg/%.s.o: cgdoom/%.s | build-cg/ $(CG_CC) $(CG_CFLAGS) -c $< -o $@ diff --git a/cgdoom/cgdoom-frag.c b/cgdoom/cgdoom-frag.c index dd2c250..120a2d0 100644 --- a/cgdoom/cgdoom-frag.c +++ b/cgdoom/cgdoom-frag.c @@ -3,12 +3,12 @@ #include "os.h" #include "w_wad.h" -int CGD_Frag_Map(const char *lumpname, CGD_Frag *frag) +int CGD_Frag_Map(const char *lumpname, CGDoom_Frag *frag) { int lump = W_CheckNumForName(lumpname); if(lump < 0) return 1; - if(CGD_WADMethod == CGDOOM_WAD_BFILE) + if(CGD_Options.WADMethod == CGDOOM_WAD_BFILE) return 1; lumpinfo_t *l = &lumpinfo[lump]; @@ -16,7 +16,7 @@ int CGD_Frag_Map(const char *lumpname, CGD_Frag *frag) int position = l->position; int f = 0; - while(f < CGD_FRAG_ESTIMATE && size > 0) { + while(f < CGDOOM_FRAG_ESTIMATE && size > 0) { int found = FindInFlash(&frag->data[f], size, position); frag->size[f] = found; @@ -26,7 +26,7 @@ int CGD_Frag_Map(const char *lumpname, CGD_Frag *frag) } if(size) { - I_Error("CGD_Frag_Map: failed on '%s' (size=%d, offset=%d), could only" + I_Error("CGDoom_Frag_Map: failed on '%s' (size=%d, offset=%d), could only" " obtain %d", lumpname, l->size, l->position, l->size - size); return 1; } @@ -35,7 +35,7 @@ int CGD_Frag_Map(const char *lumpname, CGD_Frag *frag) return 0; } -uint8_t CGD_Frag_u8(CGD_Frag const *frag, int offset) +uint8_t CGD_Frag_u8(CGDoom_Frag const *frag, int offset) { int f = 0; while(frag->size[f] != 0 && offset >= frag->size[f]) { @@ -50,7 +50,7 @@ uint8_t CGD_Frag_u8(CGD_Frag const *frag, int offset) return data[offset]; } -short CGD_Frag_i16LE(CGD_Frag const *frag, int offset) +short CGD_Frag_i16LE(CGDoom_Frag const *frag, int offset) { uint8_t b1 = CGD_Frag_u8(frag, offset); uint8_t b2 = CGD_Frag_u8(frag, offset + 1); @@ -58,7 +58,7 @@ short CGD_Frag_i16LE(CGD_Frag const *frag, int offset) return (b2 << 8) | b1; } -int CGD_Frag_i32LE(CGD_Frag const *frag, int offset) +int CGD_Frag_i32LE(CGDoom_Frag const *frag, int offset) { uint8_t b1 = CGD_Frag_u8(frag, offset); uint8_t b2 = CGD_Frag_u8(frag, offset + 1); diff --git a/cgdoom/cgdoom-frag.h b/cgdoom/cgdoom-frag.h index a7ba47a..22df947 100644 --- a/cgdoom/cgdoom-frag.h +++ b/cgdoom/cgdoom-frag.h @@ -25,20 +25,22 @@ This interface exists just in case it is be useful for other lumps. */ /* Maximum number of fragments that we expect in a lump (+1 for terminator) */ -#define CGD_FRAG_ESTIMATE 33 +#define CGDOOM_FRAG_ESTIMATE 33 /* Fragmented lump lookup table */ -typedef struct { - const void *data[CGD_FRAG_ESTIMATE]; - int size[CGD_FRAG_ESTIMATE+1]; -} CGD_Frag; +typedef struct +{ + const void *data[CGDOOM_FRAG_ESTIMATE]; + int size[CGDOOM_FRAG_ESTIMATE+1]; + +} CGDoom_Frag; /* Compute the lookup table for a lump; if successful, returns 0 */ -int CGD_Frag_Map(const char *lumpname, CGD_Frag *frag); +int CGD_Frag_Map(const char *lumpname, CGDoom_Frag *frag); /* Read different types within the lump */ -uint8_t CGD_Frag_u8(CGD_Frag const *frag, int offset); -short CGD_Frag_i16LE(CGD_Frag const *frag, int offset); -int CGD_Frag_i32LE(CGD_Frag const *frag, int offset); +uint8_t CGD_Frag_u8(CGDoom_Frag const *frag, int offset); +short CGD_Frag_i16LE(CGDoom_Frag const *frag, int offset); +int CGD_Frag_i32LE(CGDoom_Frag const *frag, int offset); #endif /* CGDOOM_FRAG_H */ diff --git a/cgdoom/cgdoom-kbd.c b/cgdoom/cgdoom-kbd.c index d58e050..9f3924c 100644 --- a/cgdoom/cgdoom-kbd.c +++ b/cgdoom/cgdoom-kbd.c @@ -2,41 +2,45 @@ #include "cgdoom-kbd.h" #include "doomdef.h" -/* Dynamic keymap */ -uint16_t CGD_Keymap[] = { - KEY_LEFTARROW, -1, - KEY_RIGHTARROW, -1, - KEY_UPARROW, -1, - KEY_DOWNARROW, -1, - ' ', -1, /* Open doors etc */ - KEY_RCTRL, -1, /* Shoot */ - '1', -1, - '2', -1, - '3', -1, - '4', -1, - '5', -1, - '6', -1, - '7', -1, - KEY_TAB, -1, - KEY_PAUSE, -1, - KEY_SLEFTARROW, -1, - KEY_SRIGHTARROW, -1, - KEY_RSHIFT, -1, /* Speed toggle */ +//--- +// Keymaps +//--- + +/* List of Doom keys in their order of assignment in keymaps */ +int16_t CGD_KeymapEntries[CGDOOM_KEYMAP_SIZE] = { + KEY_LEFTARROW, + KEY_RIGHTARROW, + KEY_UPARROW, + KEY_DOWNARROW, + ' ', /* Open doors etc */ + KEY_RCTRL, /* Shoot */ + '1', + '2', + '3', + '4', + '5', + '6', + '7', + KEY_TAB, + KEY_PAUSE, + KEY_SLEFTARROW, + KEY_SRIGHTARROW, + KEY_RSHIFT, /* Speed toggle */ + /* Special CGDoom keys */ - SKEY_DECVP, -1, - SKEY_INCVP, -1, - SKEY_CHEAT, -1, - SKEY_NOCLIP, -1, - SKEY_GAMMA, -1, - SKEY_FREEMEM, -1, - SKEY_FPSCOUNTER, -1, - SKEY_FRAMESKIP, -1, - SKEY_PROFILER, -1, - 0, + SKEY_DECVP, + SKEY_INCVP, + SKEY_CHEAT, + SKEY_NOCLIP, + SKEY_GAMMA, + SKEY_FREEMEM, + SKEY_FPSCOUNTER, + SKEY_FRAMESKIP, + SKEY_PROFILER, }; -/* Default keymap: CGDoom 0.3 */ -const uint16_t CGD_Keymap_CGDoom_0_3[] = { +/* Default keymap: CGDoom 0.03 */ +const CGDoom_Keymap CGD_Keymap_CGDoom_0_03 = { KEYCODE_LEFT, KEYCODE_RIGHT, KEYCODE_UP, @@ -64,10 +68,9 @@ const uint16_t CGD_Keymap_CGDoom_0_3[] = { KEYCODE_LEFTP, KEYCODE_VARS, KEYCODE_RIGHTP, - 0, }; /* Default keymap: thumbs only */ -const uint16_t CGD_Keymap_ThumbsOnly[] = { +const CGDoom_Keymap CGD_Keymap_ThumbsOnly = { KEYCODE_LEFT, KEYCODE_RIGHT, KEYCODE_UP, @@ -95,10 +98,9 @@ const uint16_t CGD_Keymap_ThumbsOnly[] = { KEYCODE_LEFTP, KEYCODE_VARS, KEYCODE_RIGHTP, - 0, }; /* Default keymap: full-hands */ -const uint16_t CGD_Keymap_FullHands[] = { +const CGDoom_Keymap CGD_Keymap_FullHands = { KEYCODE_F5, KEYCODE_F6, KEYCODE_OPTN, @@ -126,14 +128,31 @@ const uint16_t CGD_Keymap_FullHands[] = { KEYCODE_LEFTP, KEYCODE_SIN, KEYCODE_RIGHTP, - 0, }; -/* Current keyboard state. */ -static CGD_KeyboardState st_prev={0}, st_now={0}; +void CGD_CopyKeymap(CGDoom_Keymap dest, const CGDoom_Keymap src) +{ + memcpy(dest, src, sizeof(CGDoom_Keymap)); +} + +static int DecodeKeymap(const CGDoom_Keymap map, int key) +{ + for(int i = 0; i < CGDOOM_KEYMAP_SIZE; i++) { + if(CGD_KeymapEntries[i] == key) + return map[i]; + } + return -1; +} + +//--- +// Physical keyboard driver +//--- + +static CGDoom_KeyboardState st_prev = { 0 }; +static CGDoom_KeyboardState st_now = { 0 }; #ifndef CG_EMULATOR -void CGD_ScanKeyboard(CGD_KeyboardState state) +void CGD_ScanKeyboard(CGDoom_KeyboardState state) { volatile uint16_t *KEYSC = (void *)0xa44b0000; uint16_t *array = (void *)state; @@ -141,25 +160,38 @@ void CGD_ScanKeyboard(CGD_KeyboardState state) } #endif -void CGD_LoadKeymap(const uint16_t *template) +int KeycodeDown(CGDoom_KeyboardState state, int code) { - for(int i = 0; CGD_Keymap[2*i] != 0; i++) { - CGD_Keymap[2*i+1] = template[i]; - } + if(code < 0) return 0; + int row = (code >> 4) ^ 1; + int col = 0x80 >> (code & 0x7); + return (state[row] & col) != 0; } -static int DecodeKeymap(uint16_t *map, int key) +int CGD_PRGM_Getkey(void) { - for(int i = 0; map[2*i] != 0; i++) { - if(map[2*i] == key) - return map[2*i+1]; + CGDoom_KeyboardState st; + CGD_ScanKeyboard(st); + + for(int code_y = 9; code_y >= 1; code_y--) { + for(int code_x = 1; code_x <= 6 - (code_y < 5); code_x++) { + int code = (code_y << 4) | code_x; + if(code == 0x45) code = KEYCODE_ACON; + + if(KeycodeDown(st, code)) + return code; + } } return -1; } +//--- +// Doom keys +//--- + static int DoomKeyToKeycode(int key) { - int code = DecodeKeymap(CGD_Keymap, key); + int code = DecodeKeymap(CGD_Options.Keymap, key); if(code != -1) return code; @@ -215,15 +247,7 @@ static int DoomKeyToKeycode(int key) } } -static int KeycodeDown(CGD_KeyboardState state, int code) -{ - if(code < 0) return 0; - int row = (code >> 4) ^ 1; - int col = 0x80 >> (code & 0x7); - return (state[row] & col) != 0; -} - -static int KeyDown(CGD_KeyboardState state, int key) +static int KeyDown(CGDoom_KeyboardState state, int key) { int code = DoomKeyToKeycode(key); @@ -236,18 +260,18 @@ static int KeyDown(CGD_KeyboardState state, int key) return KeycodeDown(state, code); } -void UpdateKeyboardState(void) +void CGD_UpdateKeyboardState(void) { memcpy(st_prev, st_now, sizeof st_now); CGD_ScanKeyboard(st_now); } -int KeyWasJustPressed(int key) +int CGD_KeyWasJustPressed(int key) { return !KeyDown(st_prev, key) && KeyDown(st_now, key); } -int KeyWasJustReleased(int key) +int CGD_KeyWasJustReleased(int key) { return KeyDown(st_prev, key) && !KeyDown(st_now, key); } @@ -283,7 +307,7 @@ static const char *KeyName(int key, const char * const *names) { if(key == KEYCODE_ACON) key = 0x45; - if(key < 0) + if(key <= 0) key = 0x46; int row = 9 - (key >> 4); @@ -367,7 +391,7 @@ const char *CGD_DoomKey_DisplayName(int key) if(doomkeys[i].key == key) return doomkeys[i].display_name; } - return NULL; + return "(None)"; } const char *CGD_DoomKey_TechnicalName(int key) @@ -376,7 +400,7 @@ const char *CGD_DoomKey_TechnicalName(int key) if(doomkeys[i].key == key) return doomkeys[i].technical_name; } - return NULL; + return "NONE"; } int CGD_DoomKey_FromTechnicalName(const char *name, int length) @@ -390,24 +414,3 @@ int CGD_DoomKey_FromTechnicalName(const char *name, int length) } return -1; } - -//--- -// Direct keyboard functions -//--- - -int CGD_PRGM_Getkey(void) -{ - CGD_KeyboardState st; - CGD_ScanKeyboard(st); - - for(int code_y = 9; code_y >= 1; code_y--) { - for(int code_x = 1; code_x <= 6 - (code_y < 5); code_x++) { - int code = (code_y << 4) | code_x; - if(code == 0x45) code = KEYCODE_ACON; - - if(KeycodeDown(st, code)) - return code; - } - } - return -1; -} diff --git a/cgdoom/cgdoom-kbd.h b/cgdoom/cgdoom-kbd.h index 6a7d422..75e3ff2 100644 --- a/cgdoom/cgdoom-kbd.h +++ b/cgdoom/cgdoom-kbd.h @@ -8,33 +8,35 @@ driver adapter from gint's. The following matrix codes identify all keys on the keyboard. The PC build maps a subset of them to PC keys. + Each keymap is an array of keycodes, each either -1 (unbound) or a valid + enumerated KEYCODE_X value (see below). The meaning of each entry is + indicated by the array CGD_KeymapEntries which is an array of Doom keys. + CGDoom also defines symbolic keys other than Doom's. The particular encoding used by Doom for keys is quite unclear to me (ASCII characters and the like) and not necessarily suitable for the calculator, so this module also handles input configuration. */ -/* Copy of the keyboard state, one byte per row */ -typedef uint8_t CGD_KeyboardState[12] __attribute__((aligned(2))); +#include -/* Keyboard scanning function (very short), uses either the KEYSC or SDL */ -void CGD_ScanKeyboard(CGD_KeyboardState state); +//--- +// Keymaps +//--- -/* Default keymaps for use in UI code */ -extern const uint16_t CGD_Keymap_CGDoom_0_3[]; -extern const uint16_t CGD_Keymap_ThumbsOnly[]; -extern const uint16_t CGD_Keymap_FullHands[]; +#define CGDOOM_KEYMAP_SIZE 27 -/* Dynamic keymap (the format is slightly different, see cgdoom-kbd.c) */ -extern uint16_t CGD_Keymap[]; +/* Array of Doom keys indicating the meaning of keymap indices. */ +extern int16_t CGD_KeymapEntries[CGDOOM_KEYMAP_SIZE]; +/* Type of custom keymaps */ +typedef int16_t CGDoom_Keymap[CGDOOM_KEYMAP_SIZE]; -/* Load a default keymap */ -void CGD_LoadKeymap(const uint16_t *template); +/* Default keymaps (selectable in the main menu) */ +extern const CGDoom_Keymap CGD_Keymap_CGDoom_0_03; +extern const CGDoom_Keymap CGD_Keymap_ThumbsOnly; +extern const CGDoom_Keymap CGD_Keymap_FullHands; -/* Key name from matrix code */ -const char *CGD_KeyName(int keycode); - -/* PRGM_Getkey() but with the direct driver */ -int CGD_PRGM_Getkey(void); +/* Load/copy a keymap. */ +void CGD_CopyKeymap(CGDoom_Keymap dest, const CGDoom_Keymap src); //--- // Doom keys @@ -60,10 +62,33 @@ const char *CGD_DoomKey_TechnicalName(int key); /* Key from technical name */ int CGD_DoomKey_FromTechnicalName(const char *technical_name, int length); +/* Scan keyboard (the previous state is also retained). */ +void CGD_UpdateKeyboardState(void); + +/* Check if a Doom key has just been pressed, or released. */ +int CGD_KeyWasJustPressed(int key); +int CGD_KeyWasJustReleased(int key); + //--- -// Physical keys +// Physical keyboard driver //--- +/* Copy of the keyboard state, one byte per row */ +typedef uint8_t CGDoom_KeyboardState[12] __attribute__((aligned(2))); + +/* Keyboard scanning function (very short), uses either the KEYSC or SDL */ +void CGD_ScanKeyboard(CGDoom_KeyboardState state); + +/* PRGM_Getkey() but with the direct driver. */ +int CGD_PRGM_Getkey(void); + +/* Display name for a key (eg. "x^2") */ +const char *CGD_PhysicalKey_DisplayName(int key); +/* Technical name for a key (eg. "SQUARE") */ +const char *CGD_PhysicalKey_TechnicalName(int key); +/* Key from technical name */ +int CGD_PhysicalKey_FromTechnicalName(const char *technical_name, int length); + /* Matrix codes generated by the keyboard driver. */ #define KEYCODE_F1 0x91 #define KEYCODE_F2 0x92 @@ -116,11 +141,4 @@ int CGD_DoomKey_FromTechnicalName(const char *technical_name, int length); #define KEYCODE_EXE 0x15 #define KEYCODE_ACON 0x07 -/* Display name for a key (eg. "x^2") */ -const char *CGD_PhysicalKey_DisplayName(int key); -/* Technical name for a key (eg. "SQUARE") */ -const char *CGD_PhysicalKey_TechnicalName(int key); -/* Key from technical name */ -int CGD_PhysicalKey_FromTechnicalName(const char *technical_name, int length); - #endif /* CGDOOM_KBD_H */ diff --git a/cgdoom/cgdoom-ui.c b/cgdoom/cgdoom-ui.c index 8159788..cc48600 100644 --- a/cgdoom/cgdoom-ui.c +++ b/cgdoom/cgdoom-ui.c @@ -392,7 +392,7 @@ int Layout_Event(Layout *l, int key) return 0; } -void UI_AdvancedOptions(int *dev_info, int *use_mmap, int *trustunaligned) +void UI_AdvancedOptions(CGDoom_Options *o) { Layout l; Layout_Init(&l); @@ -404,15 +404,18 @@ void UI_AdvancedOptions(int *dev_info, int *use_mmap, int *trustunaligned) Layout_CenteredText(&l, "CGDoom: Advanced options"); Layout_Spacing(&l, 10); - Layout_Checkbox(&l, "Developer info:", dev_info); + Layout_Checkbox(&l, "Developer info:", &o->DeveloperInfo); Layout_Subtext(&l, "Start/end screens with statistics."); Layout_Spacing(&l, 10); - Layout_Checkbox(&l, "Map file to memory:", use_mmap); - Layout_Subtext(&l, "Much faster than BFile."); + int i_wad = Layout_Text(&l, "WAD file access method:", "%s", + o->WADMethod == CGDOOM_WAD_BFILE ? "< BFile" : + o->WADMethod == CGDOOM_WAD_MMAP ? "Memory map >" : + "?"); + Layout_Subtext(&l, "Mapping is much faster."); Layout_Spacing(&l, 10); - Layout_Checkbox(&l, "Trust unaligned lumps", trustunaligned); + Layout_Checkbox(&l, "Trust unaligned lumps", &o->TrustUnalignedLumps); Layout_Subtext(&l, "Faster; if System ERROR, report a bug!"); Layout_EndFrame(&l); @@ -423,21 +426,26 @@ void UI_AdvancedOptions(int *dev_info, int *use_mmap, int *trustunaligned) if(Layout_Event(&l, key)) { } + else if(key == KEY_CTRL_RIGHT && l.focus == i_wad) { + o->WADMethod = CGDOOM_WAD_BFILE; + } + else if(key == KEY_CTRL_LEFT && l.focus == i_wad) { + o->WADMethod = CGDOOM_WAD_MMAP; + } else if(key == KEY_CTRL_EXIT) { break; } } } -void UI_Controls(void) +void UI_Controls(CGDoom_Keymap map) { int focus_x=0, focus_y=-1; int dflt = 0; int editing = -1; - uint16_t saved_keymap[28] = { 0 }; - for(int i = 0; CGD_Keymap[2*i] != 0; i++) - saved_keymap[i] = CGD_Keymap[2*i+1]; + CGDoom_Keymap saved_map; + CGD_CopyKeymap(saved_map, map); while(1) { Bdisp_AllClr_VRAM(); @@ -450,13 +458,13 @@ void UI_Controls(void) if(focus_y == -1) UI_AreaReverse(0, 10-2, WIDTH-1, 10+11); - for(int i = 0; CGD_Keymap[2*i] != 0; i++) { + for(int i = 0; i < CGDOOM_KEYMAP_SIZE; i++) { int x1 = (i < 14) ? LAYOUT_LEFT - 20 : WIDTH/2 + 15; int x2 = (i < 14) ? WIDTH/2 - 15 : LAYOUT_RIGHT + 20; int y = 29 + 12 * (i % 14); /* Skip a row before special keys */ - if(CGD_Keymap[2*i] >= 0x100) + if(CGD_KeymapEntries[i] >= 0x100) y += 12; if(editing == i) { @@ -464,9 +472,9 @@ void UI_Controls(void) } else { UI_Printf(x1, y, 0x0000, UI_LEFT, "%s", - CGD_DoomKey_DisplayName(CGD_Keymap[2*i])); + CGD_DoomKey_DisplayName(CGD_KeymapEntries[i])); UI_Printf(x2, y, 0x0000, UI_RIGHT, "%s", - CGD_PhysicalKey_DisplayName(CGD_Keymap[2*i+1])); + CGD_PhysicalKey_DisplayName(map[i])); } if(focus_y >= 0 && 14 * focus_x + focus_y == i) @@ -487,7 +495,7 @@ void UI_Controls(void) while(CGD_PRGM_Getkey() != -1) {} /* Wait for a new key to be pressed */ while((key = CGD_PRGM_Getkey()) == -1) {} - CGD_Keymap[2*editing+1] = key; + map[editing] = key; editing = -1; /* Unbuffer that key so GetKey() won't return it again */ @@ -502,7 +510,7 @@ void UI_Controls(void) if(key == KEY_CTRL_F1) break; if(key == KEY_CTRL_F6) { - CGD_LoadKeymap(saved_keymap); + CGD_CopyKeymap(map, saved_map); break; } /* Default selection */ @@ -512,11 +520,11 @@ void UI_Controls(void) dflt++; else if(key == KEY_CTRL_EXE && focus_y == -1) { if(dflt == 0) - CGD_LoadKeymap(CGD_Keymap_ThumbsOnly); + CGD_CopyKeymap(map, CGD_Keymap_ThumbsOnly); else if(dflt == 1) - CGD_LoadKeymap(CGD_Keymap_FullHands); + CGD_CopyKeymap(map, CGD_Keymap_FullHands); else if(dflt == 2) - CGD_LoadKeymap(CGD_Keymap_CGDoom_0_3); + CGD_CopyKeymap(map, CGD_Keymap_CGDoom_0_03); } /* Focus movement */ else if(key == KEY_CTRL_UP && focus_y >= 0) @@ -536,18 +544,21 @@ void UI_Controls(void) editing = 14 * focus_x + focus_y; } else if(key == KEY_CTRL_DEL && focus_y >= 0) { - CGD_Keymap[2*(14*focus_x + focus_y)+1] = -1; + map[14*focus_x + focus_y] = -1; } } } -int UI_Main(CGD_WADFileInfo *wads, int wad_count, int *dev_info, int *use_mmap, - int *startmap, int *startepisode, int *trustunaligned, - int *autostart, int *enabledemos, int *enable2MBline, int *recorddemo) +int UI_Main(CGDoom_FileInfo *wads, int wad_count, CGDoom_Options *o, + int *startmap, int *startepisode, int *recorddemo, + int allow_experimental_memory) { Layout l; Layout_Init(&l); + enum { TS_SKIP, TS_NODEMOS, TS_FULL }; + int title = o->AutoStart ? TS_SKIP : o->EnableDemos ? TS_FULL : TS_NODEMOS; + while(1) { Bdisp_AllClr_VRAM(); @@ -582,12 +593,15 @@ int UI_Main(CGD_WADFileInfo *wads, int wad_count, int *dev_info, int *use_mmap, Layout_Integer(&l, "Start at episode:", startepisode); Layout_Integer(&l, "Start at map:", startmap); int i_title = Layout_Text(&l, "Title screen:", - *autostart ? "Skip" : - !*enabledemos ? "No demos" : "Full"); + title == TS_SKIP ? "Skip >" : + title == TS_NODEMOS ? "< No demos >" : + title == TS_FULL ? "< Full" : + "?"); Layout_Spacing(&l, 10); - if(enable2MBline) - Layout_Checkbox(&l, "Use experimental RAM:", enable2MBline); + if(allow_experimental_memory) + Layout_Checkbox(&l, "Use experimental RAM:", + &o->EnableExperimentalMemory); int i_demo = Layout_Text(&l, "Record demo:", (*recorddemo < 0) ? "None" : "DEMO%02d.lmp", *recorddemo); int i_controls = Layout_Text(&l, "Customize controls...", ""); @@ -602,25 +616,21 @@ int UI_Main(CGD_WADFileInfo *wads, int wad_count, int *dev_info, int *use_mmap, /* Set autostart when changing starting episode/map */ int startparam = (l.focus == wad_count || l.focus == wad_count+1); int changekey = (key == KEY_CTRL_EXE || key == KEY_CTRL_LEFT || - key == KEY_CTRL_RIGHT); + key == KEY_CTRL_RIGHT); if(startparam && changekey) - *autostart = 1; + title = TS_SKIP; } /* Title screen options */ - else if(key == KEY_CTRL_EXE && l.focus == i_title) { - if (!*autostart && *enabledemos) - *autostart = 1; - else if (!*autostart) - *enabledemos = 1; - else - *autostart = 0, *enabledemos = 0; - } + else if(key == KEY_CTRL_LEFT && l.focus == i_title) + title -= (title > TS_SKIP); + else if(key == KEY_CTRL_RIGHT && l.focus == i_title) + title += (title < TS_FULL); /* Submenus */ else if(key == KEY_CTRL_EXE && l.focus == i_controls) { - UI_Controls(); + UI_Controls(o->Keymap); } else if(key == KEY_CTRL_EXE && l.focus == i_advanced) { - UI_AdvancedOptions(dev_info, use_mmap, trustunaligned); + UI_AdvancedOptions(o); } /* Select demo file to save */ else if(key == KEY_CTRL_LEFT && l.focus == i_demo) { @@ -638,6 +648,9 @@ int UI_Main(CGD_WADFileInfo *wads, int wad_count, int *dev_info, int *use_mmap, *startmap = 1; if(*startepisode < 1) *startepisode = 1; + + o->AutoStart = (title == TS_SKIP); + o->EnableDemos = (title == TS_FULL); } return -1; @@ -702,7 +715,7 @@ void UI_Error(const char *fmt, va_list args) GetKey(&key); } -void UI_DelayedWrites(CGD_DelayedFileWrite const *dfw, int count, +void UI_DelayedWrites(CGDoom_DelayedFileWrite const *dfw, int count, int current_file, int current_file_done) { int total = 0; diff --git a/cgdoom/cgdoom-ui.h b/cgdoom/cgdoom-ui.h index 670fd22..5d4e570 100644 --- a/cgdoom/cgdoom-ui.h +++ b/cgdoom/cgdoom-ui.h @@ -2,6 +2,7 @@ #define CGDOOM_UI_H #include "cgdoom.h" + #include #include @@ -63,23 +64,19 @@ int Layout_Event(Layout *l, int key); /* Larger-scale functions. */ /* Show the program's main screen; returns index of selected WAD file. */ -int UI_Main(CGD_WADFileInfo *wads, int wad_count, - int *dev_info, /* Enable technical detail screens */ - int *use_mmap, /* Map file to memory (as opposed to using Bfile) */ - int *startmap, /* Warp to this map */ - int *startepisode, /* Warp to this episode */ - int *trustunaligned, /* Trust unaligned lumps */ - int *autostart, /* Skip title screen, straight to gameplay */ - int *enabledemos, /* Enable demos on the title screen */ - int *enable2MBline, /* Enable memory past the 2MB line */ - int *recorddemo /* Number of demo to record (-1 for none) */ +int UI_Main(CGDoom_FileInfo *wads, int wad_count, + CGDoom_Options *options, + int *startmap, /* Warp to this map (autostart only) */ + int *startepisode, /* Warp to this episode (autostart only) */ + int *recorddemo, /* Number of demo to record (-1 for none) */ + int allow_2MBline /* Allow setting the experimental RAM option */ ); /* Show an error with custom formatting. */ void UI_Error(const char *fmt, va_list args); /* Show a file save with a progress bar. */ -void UI_DelayedWrites(CGD_DelayedFileWrite const *dfw, int count, +void UI_DelayedWrites(CGDoom_DelayedFileWrite const *dfw, int count, int current_file, int current_amount); #endif /* CGDOOM_UI_H */ diff --git a/cgdoom/cgdoom.c b/cgdoom/cgdoom.c index 9881166..6a5119f 100644 --- a/cgdoom/cgdoom.c +++ b/cgdoom/cgdoom.c @@ -38,8 +38,8 @@ void *CGD_realloc(void *p, int size) return realloc(p, size); } -unsigned short *VRAM; -unsigned char *SaveVRAMBuffer; +uint16_t *VRAM; +uint16_t *SecondaryVRAM; unsigned char *SystemStack; int strnicmp(const char *s1,const char *s2,int count) @@ -112,8 +112,6 @@ typedef struct { int miTotalLength; } FileMapping; -/* WAD file access method. */ -int CGD_WADMethod = CGDOOM_WAD_MMAP; /* File descriptor to WAD, used in Flash_ReadFile calls. (CGDOOM_WAD_BFILE) */ static int gWADfd = -1; /* Memory map of WAD file. (CGDOOM_WAD_MMAP) */ @@ -121,9 +119,11 @@ static FileMapping gWADMap; /* Index of most likely sectors for fragment search. (CGDOOM_WAD_MMAP) */ static SectorIndexInfo *gIndex = NULL; +CGDoom_Options CGD_Options; +CGDoom_Perf CGD_Perf; +CGDoom_Stats CGD_Stats; + /* Global options */ -int CGD_TrustUnalignedLumps = 1; -int CGD_EnableDemos = 0; int CGD_SingleEpisodeUltimate = 0; int CGD_2MBLineMemory = 0; int CGD_Frameskip = 1; @@ -131,12 +131,7 @@ const char *CGD_WADFileName = NULL; const char *CGD_RecordDemoName = NULL; /* Delayed file accesses */ -CGD_DelayedFileWrite CGD_DelayedSaves[CGD_DELAYEDSAVES_COUNT] = { 0 }; - -/* Performance counters */ -struct CGD_Perf CGD_Perf; -/* Developer statistics */ -struct CGD_Stats CGD_Stats; +CGDoom_DelayedFileWrite CGD_DelayedSaves[CGD_DELAYEDSAVES_COUNT] = { 0 }; #ifndef CG_EMULATOR @@ -326,7 +321,7 @@ int FindFragmentInMap(FileMapping *map, int sector_number) int FindInFlash(const void **buf, int size, int readpos) { - if(CGD_WADMethod == CGDOOM_WAD_BFILE) + if(CGD_Options.WADMethod == CGDOOM_WAD_BFILE) return 0; ASSERT(readpos >= 0); @@ -378,7 +373,7 @@ void abort(void){ int Flash_ReadFile(void *buf, int size, int readpos) { - if(CGD_WADMethod == CGDOOM_WAD_BFILE) + if(CGD_Options.WADMethod == CGDOOM_WAD_BFILE) return Bfile_ReadFile_OS(gWADfd, buf, size, readpos); const void *pSrc; @@ -401,7 +396,7 @@ int Flash_ReadFile(void *buf, int size, int readpos) } /* Find WAD files in the filesystem. */ -int FindWADs(CGD_WADFileInfo *files, int max) +int FindWADs(CGDoom_FileInfo *files, int max) { uint16_t path[32]; Bfile_FileInfo info; @@ -426,7 +421,7 @@ int FindWADs(CGD_WADFileInfo *files, int max) static void DelayedWriteFile(int i) { - CGD_DelayedFileWrite const *dfw = &CGD_DelayedSaves[i]; + CGDoom_DelayedFileWrite const *dfw = &CGD_DelayedSaves[i]; uint16_t fc_path[100] = u"\\\\fls0\\"; int j=7, rc, fd; @@ -470,35 +465,46 @@ static void DelayedWriteFile(int i) Bfile_CloseFile_OS(fd); } -static void SaveSettings(int dev_info, int autostart) +//--- +// Setting save/load +//--- + +static void SaveSettings(const CGDoom_Options *o) { char *out_start = (char *)CGDOOM_SCREENS_BASE; char *out = out_start; /* Version identifcation (just in case something goes wrong) */ - out += sprintf(out, "Version=%d\n", SETTINGS_FILE_VERSION); + out += sprintf(out, "Version=%d\n", CGDOOM_SETTINGS_FILE_VERSION); /* Settings */ out += sprintf(out, "WADMethod=%s\n", - CGD_WADMethod == CGDOOM_WAD_BFILE ? "BFILE" : "MMAP"); - out += sprintf(out, "DeveloperInfo=%d\n", dev_info); - out += sprintf(out, "TrustUnalignedLumps=%d\n", CGD_TrustUnalignedLumps); - out += sprintf(out, "EnableDemos=%d\n", CGD_EnableDemos); - out += sprintf(out, "Autostart=%d\n", autostart); - out += sprintf(out, "ExperimentalMemory=%d\n", CGD_2MBLineMemory != 0); + o->WADMethod == CGDOOM_WAD_BFILE ? "BFILE" : + o->WADMethod == CGDOOM_WAD_MMAP ? "MMAP" : + "?"); + out += sprintf(out, "DeveloperInfo=%d\n", + o->DeveloperInfo); + out += sprintf(out, "TrustUnalignedLumps=%d\n", + o->TrustUnalignedLumps); + out += sprintf(out, "EnableDemos=%d\n", + o->EnableDemos); + out += sprintf(out, "Autostart=%d\n", + o->AutoStart); + out += sprintf(out, "ExperimentalMemory=%d\n", + o->EnableExperimentalMemory); /* Keyboard layout */ - for(int i = 0; CGD_Keymap[2*i] != 0; i++) { + for(int i = 0; i < CGDOOM_KEYMAP_SIZE; i++) { out += sprintf(out, "Keymap.%s=%s\n", - CGD_DoomKey_TechnicalName(CGD_Keymap[2*i]), - CGD_PhysicalKey_TechnicalName(CGD_Keymap[2*i+1])); + CGD_DoomKey_TechnicalName(CGD_KeymapEntries[i]), + CGD_PhysicalKey_TechnicalName(o->Keymap[i])); } M_WriteFile("CGDoom.cfg", out_start, out - out_start); memset(out_start, 0xff, out - out_start); } -static void LoadSettings(int *dev_info, int *autostart) +static void LoadSettings(CGDoom_Options *o) { char *buffer = (char *)CGDOOM_SCREENS_BASE; int length = M_ReadFile("CGDoom.cfg", (byte **)&buffer, 0); @@ -523,14 +529,15 @@ static void LoadSettings(int *dev_info, int *autostart) if(!strncmp(line, "Version", eq-line)) { int version = atoi(value); - if(version != SETTINGS_FILE_VERSION) return; + if(version != CGDOOM_SETTINGS_FILE_VERSION) + return; } else if(!strncmp(line, "WADMethod", eq-line)) { if(!strncmp(value, "BFILE", 5)) - CGD_WADMethod = CGDOOM_WAD_BFILE; + o->WADMethod = CGDOOM_WAD_BFILE; else if(!strncmp(value, "MMAP", 4)) - CGD_WADMethod = CGDOOM_WAD_MMAP; + o->WADMethod = CGDOOM_WAD_MMAP; } else if(!strncmp(line, "Keymap.", 7)) { @@ -538,9 +545,9 @@ static void LoadSettings(int *dev_info, int *autostart) int k2 = CGD_PhysicalKey_FromTechnicalName(value,nextline-value-1); if(k1 > 0 && k2 >= 0) { - for(int i = 0; CGD_Keymap[2*i] != 0; i++) { - if(CGD_Keymap[2*i] == k1) { - CGD_Keymap[2*i+1] = k2; + for(int i = 0; i < CGDOOM_KEYMAP_SIZE; i++) { + if(CGD_KeymapEntries[i] == k1) { + o->Keymap[i] = k2; break; } } @@ -548,32 +555,38 @@ static void LoadSettings(int *dev_info, int *autostart) } else if(!strncmp(line, "DeveloperInfo", eq-line)) - *dev_info = atoi(value); + o->DeveloperInfo = atoi(value); else if(!strncmp(line, "TrustUnalignedLumps", eq-line)) - CGD_TrustUnalignedLumps = atoi(value); + o->TrustUnalignedLumps = atoi(value); else if(!strncmp(line, "EnableDemos", eq-line)) - CGD_EnableDemos = atoi(value); + o->EnableDemos = atoi(value); else if(!strncmp(line, "Autostart", eq-line)) - *autostart = atoi(value); + o->AutoStart = atoi(value); else if(!strncmp(line, "ExperimentalMemory", eq-line)) - CGD_2MBLineMemory = atoi(value); + o->EnableExperimentalMemory = atoi(value); } } -/////////////////////////////////////////////////////////////////////////////////////////////////// +static int SettingsChanged(const CGDoom_Options *before, + const CGDoom_Options *after) +{ + return memcmp(before, after, sizeof *before) != 0; +} + +//--- +// Main function +//--- + int main(void) { - extern boolean autostart; - int autostart_ = 0; - startmap = 1; - startepisode = 1; + //--- + // First configuration step + //--- VRAM = (void *)GetVRAMAddress(); - uintptr_t secondary_vram = ((uintptr_t)GetSecondaryVRAMAddress() + 3) & -4; - SaveVRAMBuffer = (void *)secondary_vram; - - int time, ms_index=0, ms_mmap=0; + uintptr_t vram2 = ((uintptr_t)GetSecondaryVRAMAddress() + 3) & -4; + SecondaryVRAM = (void *)vram2; EnableColor(1); EnableStatusArea(3); @@ -582,41 +595,82 @@ int main(void) prof_init(); - CGD_WADFileInfo wads[16]; - int wad_count = FindWADs(wads, 16); - - int dev_info = 0; - int recorddemo = -1; - - /* Set initial keyboard layout to thumbs-only */ - CGD_LoadKeymap(CGD_Keymap_ThumbsOnly); - - /* Load settings from file if there is one */ - LoadSettings(&dev_info, &autostart_); - - /* Allow the user to use memory past the 2 MB line on known OS versions */ - int *enable_2MBline=NULL; + /* Allow the user to use memory past the 2 MB line on tested OS versions */ + int allow_experimental_RAM = 0; char const *osv = GetOSVersion(); if(!strncmp(osv, "03.", 3) && osv[3] <= '6') // 3.60 or earlier - enable_2MBline = &CGD_2MBLineMemory; + allow_experimental_RAM = 1; else - CGD_2MBLineMemory = 0; + CGD_Options.EnableExperimentalMemory = 0; - int choice = UI_Main(wads, wad_count, &dev_info, &CGD_WADMethod, - &startmap, &startepisode, &CGD_TrustUnalignedLumps, &autostart_, - &CGD_EnableDemos, enable_2MBline, &recorddemo); + //--- + // Load default and saved options + //--- + + CGDoom_Options o = { + .DeveloperInfo = 0, + .WADMethod = CGDOOM_WAD_MMAP, + .TrustUnalignedLumps = 1, + .AutoStart = 0, + .EnableDemos = 0, + .EnableExperimentalMemory = 0, + }; + CGD_CopyKeymap(o.Keymap, CGD_Keymap_ThumbsOnly); + + /* Override with settings read from file if there is one */ + LoadSettings(&o); + + /* Keep o so we can later look for changes and resave them */ + memcpy(&CGD_Options, &o, sizeof o); + + /* Offer to start at E1M1 if skipping the title screen */ + extern int startmap; + extern int startepisode; + startmap = 1; + startepisode = 1; + /* Don't record demos by default */ + int recorddemo = -1; + + //--- + // Run main menu and apply settings + //--- + + /* Look for WAD files at the root of the filesystem */ + CGDoom_FileInfo wads[16]; + int wad_count = FindWADs(wads, 16); + + int choice = UI_Main(wads, wad_count, &CGD_Options, + &startmap, &startepisode, &recorddemo, allow_experimental_RAM); if(choice < 0) return 1; - autostart = autostart_; - - /* Parameters unavailable on the SDL2 build */ + /* Override parameters unavailable on the SDL2 build */ #ifdef CG_EMULATOR - CGD_WADMethod = CGDOOM_WAD_BFILE; - CGD_TrustUnalignedLumps = 0; - CGD_2MBLineMemory = 0; + CGD_Options.WADMethod = CGDOOM_WAD_BFILE; + CGD_Options.TrustUnalignedLumps = 0; + CGD_Options.EnableExperimentalMemory = 0; #endif + /* Apply settings to Doom variables */ + extern boolean autostart; + autostart = CGD_Options.AutoStart; + + /* Determine how much RAM is zeroed out at 2 MB */ + if(CGD_Options.EnableExperimentalMemory) + CGD_2MBLineMemory = FindZeroedMemory((void *)0xac200000); + else + CGD_2MBLineMemory = 0; + + /* Save settings for the next load */ + if(SettingsChanged(&o, &CGD_Options)) + SaveSettings(&CGD_Options); + + //--- + // Second configuration step + //--- + + void *PRAM0_alloc_start = PRAM0_START; + /* Override version detection for single-episode Ultimate Doom WADs */ if (!strcmp(wads[choice].name, "doomu1.wad")) CGD_SingleEpisodeUltimate = 1; @@ -627,26 +681,22 @@ int main(void) if (!strcmp(wads[choice].name, "doomu4.wad")) CGD_SingleEpisodeUltimate = 4; - /* fx-CG 50 / Graph 90+E: RAM starts at 0x0c000000 in physical memory */ - SystemStack = (void *)0xac0f0000; - - /* Determine how much RAM is zeroed out at 2 MB */ - if(CGD_2MBLineMemory) - CGD_2MBLineMemory = FindZeroedMemory((void *)0xac200000); - - void *PRAM0_alloc_start = PRAM0_START; - /* Remember WAD file name for saves and loads */ static char wad_name[32] = { 0 }; for (int i = 0; wads[choice].name[i] != '.'; i++) wad_name[i] = wads[choice].name[i]; CGD_WADFileName = wad_name; - /* Save settings for the next load */ - SaveSettings(dev_info, autostart_); + /* fx-CG 50 / Graph 90+E: RAM starts at 0x0c000000 in physical memory */ + SystemStack = (void *)0xac0f0000; - /* Setup access to WAD file */ - if(CGD_WADMethod == CGDOOM_WAD_BFILE) + //--- + // Setup access to the WAD file + //--- + + int time, ms_index=0, ms_mmap=0; + + if(CGD_Options.WADMethod == CGDOOM_WAD_BFILE) { gWADfd = Bfile_OpenFile_OS(wads[choice].path, 0, 0); } @@ -688,7 +738,7 @@ int main(void) I_Error ("File too fragmented"); return 1; } - else if(dev_info) { + else if(CGD_Options.DeveloperInfo) { Layout l; Layout_Init(&l); Bdisp_AllClr_VRAM(); @@ -730,12 +780,12 @@ int main(void) Bfile_CloseFile_OS(gWADfd); for(int i = 0; i < CGD_DELAYEDSAVES_COUNT; i++) { - CGD_DelayedFileWrite *dfw = &CGD_DelayedSaves[i]; + CGDoom_DelayedFileWrite *dfw = &CGD_DelayedSaves[i]; if(dfw->data != NULL) DelayedWriteFile(i); } - if(dev_info) { + if(CGD_Options.DeveloperInfo) { Layout l; Layout_Init(&l); Bdisp_AllClr_VRAM(); diff --git a/cgdoom/cgdoom.h b/cgdoom/cgdoom.h index 4a33d13..bd921db 100644 --- a/cgdoom/cgdoom.h +++ b/cgdoom/cgdoom.h @@ -1,34 +1,52 @@ #ifndef CGDOOM_H #define CGDOOM_H +#include "cgdoom-kbd.h" #include "platform.h" #include "libprof.h" #include -// CGDoom-specific definitions that cover both calculator and native builds. +//--- +// Memory layout +//--- -#define SETTINGS_FILE_VERSION 1 - -/* VRAM pointer and size */ +/* Size of VRAM buffers */ +#define WIDTH 384 +#define HEIGHT 216 +/* Main and secondary VRAMs (both supplied by the OS) */ extern uint16_t *VRAM; -#define WIDTH 384 -#define HEIGHT 216 +extern uint16_t *SecondaryVRAM; -/* Description of a WAD file selectable by user. */ +//--- +// Filesystem +//--- + +/* Description of a WAD or demo file selectable by user. */ typedef struct { char name[32]; uint16_t path[7+32]; int size; -} CGD_WADFileInfo; -/* Description of a file write that has been delated. */ +} CGDoom_FileInfo; + +/* Description of a file write that has been delayed. */ typedef struct { char filename[32]; const void *data; int size; -} CGD_DelayedFileWrite; + +} CGDoom_DelayedFileWrite; + +/* IDs for delayed saves */ +enum { + CGD_DELAYEDSAVES_SAVES = 0, /* 6 entries */ + CGD_DELAYEDSAVES_DEMO = 6, + CGD_DELAYEDSAVES_COUNT, +}; +/* Save Game operations delayed until closing the add-in (one per save) */ +extern CGDoom_DelayedFileWrite CGD_DelayedSaves[CGD_DELAYEDSAVES_COUNT]; /* File access method (numbering is used in checkbox; keep as is) */ enum { @@ -43,56 +61,53 @@ enum { /* Delay file saves until exit to avoid quitting immediately */ #define CGDOOM_DELAY_SAVES -/* CGDoom statistics */ -extern struct CGD_Perf CGD_Perf; -extern struct CGD_Stats CGD_Stats; +//--- +// CGDoom options +//--- -// CGDoom options (some more are specified in platform.h) +/* The settings file is text-based and probably doesn't ever need to change + even if settings are added or removed. This is just in case. */ +#define CGDOOM_SETTINGS_FILE_VERSION 1 + +typedef struct { + /* Enable technical detail screens. These screens are shown at the start + and end of the game and display some statistics and debug data. */ + int DeveloperInfo; + /* File access method (see above). */ + int WADMethod; + /* Whether to trust unaligned lumps. If this is set, all non-fragmented + lumps will be accessed from ROM. Otherwise, lumps that are not 4-aligned + will be loaded to the heap even if they are available. This option is + relevant only if WADMethod == CGDOOM_WAD_MMAP. */ + int TrustUnalignedLumps; + /* Skip title screen and get straight to gameplay. */ + int AutoStart; + /* Enable demos in the title screen (most are for previous versions of + the engine and just look bad). */ + int EnableDemos; + /* Enable the use of experimental memory. */ + int EnableExperimentalMemory; + /* Custom controls. */ + CGDoom_Keymap Keymap; + +} CGDoom_Options; + +extern CGDoom_Options CGD_Options; + +// CGDoom settings that affect the game -/* File access method */ -extern int CGD_WADMethod; -/* Enable demos in the title screen (most are incompatible and look bad) */ -extern int CGD_EnableDemos; /* The selected WAD is a split Ultimate Doom WAD with a single episode (this exists on the fx-CG 50 and is incorrectly detected by normal logic) */ extern int CGD_SingleEpisodeUltimate; /* Skip this amount of frames after every rendered frame (default 1) */ extern int CGD_Frameskip; -/* Whether to trust unaligned lumps. If this is set, all non-fragmented lumps - will be accessed from ROM. Otherwise, lumps that are not 4-aligned will be - loaded to the heap even if they are available. (CGDOOM_WAD_MMAP) */ -extern int CGD_TrustUnalignedLumps; - -// Global variables interfacing with Doom itself. - -/* Map and episode to start at when loading the game. */ -extern int startmap, startepisode; -/* WAD file name (without .wad), used to avoid save file conflicts */ +/* WAD file name (without .wad), used to name save and demo files */ extern const char *CGD_WADFileName; /* Name of record demo file */ extern const char *CGD_RecordDemoName; -/* IDs for delayed saves */ -enum { - CGD_DELAYEDSAVES_SAVES = 0, /* 6 entries */ - CGD_DELAYEDSAVES_DEMO = 6, - CGD_DELAYEDSAVES_COUNT, -}; -/* Save Game operations delayed until closing the add-in (one per save) */ -extern CGD_DelayedFileWrite CGD_DelayedSaves[CGD_DELAYEDSAVES_COUNT]; - - -// Keyboard interface. - -// Scan keyboard (the previous state is also retained). -void UpdateKeyboardState(void); - -// Check if a Doom key has just been pressed, or released. -int KeyWasJustPressed(int key); -int KeyWasJustReleased(int key); - //--- -// Control systems +// Control functions (mapped to special keys) //--- void CGD_Cheat(); @@ -106,16 +121,23 @@ void CGD_ProfilerResults(); // Performance metrics //--- -struct CGD_Perf +typedef struct { prof_t DynamicAllocation; prof_t GraphicsRendering; prof_t DisplayInterface; prof_t LumpLoading; prof_t UnalignedLumpLoading; -}; -struct CGD_Stats +} CGDoom_Perf; + +extern CGDoom_Perf CGD_Perf; + +//--- +// Game and debugging statistics +//--- + +typedef struct { /* Fragments in the WAD file */ int WADFragments; @@ -137,6 +159,9 @@ struct CGD_Stats uint64_t LumpsLoadedTotal; uint64_t LumpsReferencedTotal; uint64_t UnalignedLumpsLoadedTotal; -}; + +} CGDoom_Stats; + +extern CGDoom_Stats CGD_Stats; #endif /* CGDOOM_H */ diff --git a/cgdoom/d_main.c b/cgdoom/d_main.c index 17e7bee..f3d1154 100644 --- a/cgdoom/d_main.c +++ b/cgdoom/d_main.c @@ -258,9 +258,6 @@ extern boolean demorecording; void D_DoomLoop (void) { - if (demorecording) - G_BeginRecording (); - I_InitGraphics (); while (!fuck) @@ -398,7 +395,7 @@ void D_DoAdvanceDemo (void) } /* CGDoom: Skip demos on option (often incompatible) */ - if (gameaction == ga_playdemo && !CGD_EnableDemos) { + if (gameaction == ga_playdemo && !CGD_Options.EnableDemos) { D_DoAdvanceDemo(); } } diff --git a/cgdoom/g_game.c b/cgdoom/g_game.c index ff2986b..b65fa3e 100644 --- a/cgdoom/g_game.c +++ b/cgdoom/g_game.c @@ -1069,7 +1069,7 @@ boolean G_DoSaveGame (void) #endif int n = CGD_DELAYEDSAVES_SAVES + savegameslot; - CGD_DelayedFileWrite *dfw = &CGD_DelayedSaves[n]; + CGDoom_DelayedFileWrite *dfw = &CGD_DelayedSaves[n]; /* Allocate memory to hold the data while delaying */ if (!save_now) { @@ -1135,6 +1135,9 @@ void G_DoNewGame (void) consoleplayer = 0; G_InitNew (d_skill, d_episode, d_map); gameaction = ga_nothing; + + if (demorecording) + G_BeginRecording (); } // The sky texture to be used instead of the F_SKY1 dummy. @@ -1436,7 +1439,7 @@ boolean G_CheckDemoStatus (void) if (demorecording) { *demo_p++ = DEMOMARKER; - CGD_DelayedFileWrite *dfw = &CGD_DelayedSaves[CGD_DELAYEDSAVES_DEMO]; + CGDoom_DelayedFileWrite *dfw = &CGD_DelayedSaves[CGD_DELAYEDSAVES_DEMO]; strcpy(dfw->filename, demoname); dfw->data = demobuffer; dfw->size = demo_p - demobuffer; diff --git a/cgdoom/i_system.c b/cgdoom/i_system.c index 8e7ce70..9426aee 100644 --- a/cgdoom/i_system.c +++ b/cgdoom/i_system.c @@ -99,7 +99,7 @@ byte* I_ZoneBase (int* size, int i) /* Secondary VRAM (screen buffers being in the main VRAM because we're doing direct access so we don't need Bdisp_PutDisp_DD() */ *size = 384 * 216 * 2; - return SaveVRAMBuffer; + return (void *)SecondaryVRAM; } #endif return NULL; @@ -290,26 +290,26 @@ void I_StartTic (void) /* This variable is set in m_menu.c while typing save file names */ extern int saveStringEnter; - UpdateKeyboardState(); + CGD_UpdateKeyboardState(); if(!saveStringEnter) { /* Capture events for special keys */ - if(KeyWasJustPressed(SKEY_CHEAT)) + if(CGD_KeyWasJustPressed(SKEY_CHEAT)) CGD_Cheat(); - if(KeyWasJustPressed(SKEY_DECVP)) + if(CGD_KeyWasJustPressed(SKEY_DECVP)) R_SetViewSizeChange(-1); - if(KeyWasJustPressed(SKEY_INCVP)) + if(CGD_KeyWasJustPressed(SKEY_INCVP)) R_SetViewSizeChange(1); - if(KeyWasJustPressed(SKEY_NOCLIP)) + if(CGD_KeyWasJustPressed(SKEY_NOCLIP)) CGD_SwitchClip(); - if(KeyWasJustPressed(SKEY_GAMMA)) + if(CGD_KeyWasJustPressed(SKEY_GAMMA)) CGD_CycleGamma(); - if(KeyWasJustPressed(SKEY_FREEMEM)) + if(CGD_KeyWasJustPressed(SKEY_FREEMEM)) CGD_FreeMem(); - if(KeyWasJustPressed(SKEY_FPSCOUNTER)) + if(CGD_KeyWasJustPressed(SKEY_FPSCOUNTER)) fpscounteractive = !fpscounteractive; - if(KeyWasJustPressed(SKEY_FRAMESKIP)) + if(CGD_KeyWasJustPressed(SKEY_FRAMESKIP)) CGD_CycleFrameskip(); } @@ -320,7 +320,7 @@ void I_StartTic (void) /* Number of ticks left before reporting results */ static int profiler_ticks = -1; - if (!saveStringEnter && KeyWasJustPressed(SKEY_PROFILER)) { + if (!saveStringEnter && CGD_KeyWasJustPressed(SKEY_PROFILER)) { prof_t *counters = (prof_t *)&CGD_Perf; for(int i = 0; i < sizeof CGD_Perf / sizeof (prof_t); i++) { counters[i] = prof_make(); @@ -364,9 +364,9 @@ void I_StartTic (void) for(int i = 0; keys[i]; i++) { event_t e; - if(KeyWasJustPressed(keys[i])) + if(CGD_KeyWasJustPressed((uint8_t)keys[i])) e.type = ev_keydown; - else if(KeyWasJustReleased(keys[i])) + else if(CGD_KeyWasJustReleased((uint8_t)keys[i])) e.type = ev_keyup; else continue; diff --git a/cgdoom/os.h b/cgdoom/os.h index 2b12bed..9f777bc 100644 --- a/cgdoom/os.h +++ b/cgdoom/os.h @@ -3,9 +3,6 @@ #define SYSTEM_STACK_SAFE (64*1024) #define USER_STACK_SAFE (32*1024) -// SaveVRAMBuffer (384*216*2 bytes) -extern unsigned char *SaveVRAMBuffer; - // system stack (512 kB). #define SYSTEM_STACK_SIZE (512*1024-SYSTEM_STACK_SAFE) extern unsigned char *SystemStack; diff --git a/cgdoom/v_video.c b/cgdoom/v_video.c index f8de4f1..a78c3e5 100644 --- a/cgdoom/v_video.c +++ b/cgdoom/v_video.c @@ -252,7 +252,7 @@ void V_DrawPatch(int x,int y,int scrn,const patch_t* patch) // void V_DrawFullscreenPatchFragmented(int scrn, const char *lumpname) { - CGD_Frag patch; + CGDoom_Frag patch; if (CGD_Frag_Map(lumpname, &patch)) { V_DrawPatch(0, 0, scrn, W_CacheLumpNamePatch(lumpname, PU_CACHE)); return; diff --git a/cgdoom/w_wad.c b/cgdoom/w_wad.c index 37f6119..35254c4 100644 --- a/cgdoom/w_wad.c +++ b/cgdoom/w_wad.c @@ -296,11 +296,10 @@ void * W_ReadLumpWithZ_Malloc(int lump,int tag,int iEnableFlash) int full = (c == lumpinfo[lump].size); int aligned = (((uintptr_t)lumpcache[lump] & 1) == 0); - if(CGD_TrustUnalignedLumps) + if(CGD_Options.TrustUnalignedLumps) aligned = 1; /* Record statistics on loading unaligned but full lumps */ - extern struct CGD_Stats CGD_Stats; if(full && !aligned) { CGD_Stats.UnalignedLumpsLoaded++; CGD_Stats.UnalignedLumpsLoadedTotal += lumpinfo[lump].size; diff --git a/icon-sel.png b/icon-sel.png new file mode 100644 index 0000000..a1e5247 Binary files /dev/null and b/icon-sel.png differ diff --git a/icon-uns.png b/icon-uns.png new file mode 100644 index 0000000..19e0cd7 Binary files /dev/null and b/icon-uns.png differ diff --git a/icon.xcf b/icon.xcf new file mode 100644 index 0000000..93d5e04 Binary files /dev/null and b/icon.xcf differ diff --git a/src-cg/platform.h b/src-cg/platform.h index 10e41da..4c1127e 100644 --- a/src-cg/platform.h +++ b/src-cg/platform.h @@ -72,7 +72,7 @@ ((uint32_t)GetVRAMAddress() & 0x1fffffff) | 0x80000000 \ )) #else -# define CGDOOM_SCREENS_BASE SaveVRAMBuffer +# define CGDOOM_SCREENS_BASE SecondaryVRAM #endif /* Amount of extra memory past the 2 MB line that we deem safe to access. */ diff --git a/src-sdl2/emul.c b/src-sdl2/emul.c index 0c6c568..0bf15d5 100644 --- a/src-sdl2/emul.c +++ b/src-sdl2/emul.c @@ -1,8 +1,13 @@ #include "cgdoom.h" +#include "cgdoom-kbd.h" #include "platform.h" + +#include "doomdef.h" #include "i_system.h" + #include #include +#include #include SDL_Window *window = NULL; @@ -97,6 +102,98 @@ void Bdisp_AllClr_VRAM(void) /* Keyboard system emulation. */ +static int MatrixCodeToPCKey(int key) +{ + switch(key) + { + case KEYCODE_F1: return SDL_SCANCODE_F1; + case KEYCODE_F2: return SDL_SCANCODE_F2; + case KEYCODE_F3: return SDL_SCANCODE_F3; + case KEYCODE_F4: return SDL_SCANCODE_F4; + case KEYCODE_F5: return SDL_SCANCODE_F5; + case KEYCODE_F6: return SDL_SCANCODE_F6; + + case KEYCODE_UP: return SDL_SCANCODE_UP; + case KEYCODE_RIGHT: return SDL_SCANCODE_RIGHT; + case KEYCODE_DOWN: return SDL_SCANCODE_DOWN; + case KEYCODE_LEFT: return SDL_SCANCODE_LEFT; + + case KEYCODE_SHIFT: return SDL_SCANCODE_Q; + case KEYCODE_OPTN: return SDL_SCANCODE_W; + case KEYCODE_VARS: return SDL_SCANCODE_E; + case KEYCODE_MENU: return SDL_SCANCODE_R; + + case KEYCODE_ALPHA: return SDL_SCANCODE_A; + case KEYCODE_SQUARE: return SDL_SCANCODE_S; + case KEYCODE_POWER: return SDL_SCANCODE_D; + case KEYCODE_EXIT: return SDL_SCANCODE_F; + + case KEYCODE_XOT: return SDL_SCANCODE_T; + case KEYCODE_LOG: return SDL_SCANCODE_Y; + case KEYCODE_LN: return SDL_SCANCODE_U; + case KEYCODE_SIN: return SDL_SCANCODE_I; + case KEYCODE_COS: return SDL_SCANCODE_O; + case KEYCODE_TAN: return SDL_SCANCODE_P; + + case KEYCODE_FRAC: return SDL_SCANCODE_G; + case KEYCODE_FD: return SDL_SCANCODE_H; + case KEYCODE_LEFTP: return SDL_SCANCODE_J; + case KEYCODE_RIGHTP: return SDL_SCANCODE_K; + case KEYCODE_COMMA: return SDL_SCANCODE_L; + case KEYCODE_ARROW: return SDL_SCANCODE_SEMICOLON; + + case KEYCODE_1: return SDL_SCANCODE_1; + case KEYCODE_2: return SDL_SCANCODE_2; + case KEYCODE_3: return SDL_SCANCODE_3; + case KEYCODE_4: return SDL_SCANCODE_4; + case KEYCODE_5: return SDL_SCANCODE_5; + case KEYCODE_6: return SDL_SCANCODE_6; + case KEYCODE_7: return SDL_SCANCODE_7; + case KEYCODE_8: return SDL_SCANCODE_8; + case KEYCODE_9: return SDL_SCANCODE_9; + case KEYCODE_0: return SDL_SCANCODE_0; + + case KEYCODE_DEL: return SDL_SCANCODE_BACKSPACE; + case KEYCODE_ACON: return SDL_SCANCODE_ESCAPE; + + case KEYCODE_MUL: return SDL_SCANCODE_LEFTBRACKET; + case KEYCODE_DIV: return SDL_SCANCODE_RIGHTBRACKET; + + case KEYCODE_PLUS: return SDL_SCANCODE_MINUS; + case KEYCODE_MINUS: return SDL_SCANCODE_EQUALS; + + case KEYCODE_DOT: return -1; + case KEYCODE_EXP: return -1; + case KEYCODE_NEG: return -1; + + case KEYCODE_EXE: return SDL_SCANCODE_RETURN; + + default: return -1; + } +} + +void CGD_ScanKeyboard(CGDoom_KeyboardState state) +{ + SDL_Event e; + while(SDL_PollEvent(&e)) {} + + int length; + const Uint8 *sdl_state = SDL_GetKeyboardState(&length); + + for(int row = 0; row < 12; row++) { + for(int col = 0; col < 8; col++) { + int matrix_code = (row << 4) | col; + int index = row ^ 1; + int pattern = (0x80 >> col); + + int scancode = MatrixCodeToPCKey(matrix_code); + state[index] &= ~pattern; + if(scancode >= 0 && scancode < length && sdl_state[scancode]) + state[index] |= pattern; + } + } +} + int PRGM_GetKey(void) { // TODO: PRGM_GetKey() @@ -127,6 +224,12 @@ void GetKey(int *key) case SDLK_DOWN: *key = KEY_CTRL_DOWN; break; case SDLK_LEFT: *key = KEY_CTRL_LEFT; break; case SDLK_RETURN: *key = KEY_CTRL_EXE; break; + case SDLK_F1: *key = KEY_CTRL_F1; break; + case SDLK_F2: *key = KEY_CTRL_F2; break; + case SDLK_F3: *key = KEY_CTRL_F3; break; + case SDLK_F4: *key = KEY_CTRL_F4; break; + case SDLK_F5: *key = KEY_CTRL_F5; break; + case SDLK_F6: *key = KEY_CTRL_F6; break; default: if(sym >= '0' && sym <= '9') *key = sym; diff --git a/src-sdl2/keyboard.c b/src-sdl2/keyboard.c deleted file mode 100644 index eb23243..0000000 --- a/src-sdl2/keyboard.c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include - -#include "cgdoom.h" -#include "cgdoom-kbd.h" -#include "doomdef.h" - -/* Mapping of calculator matrix codes on the PC keyboard */ -static int MatrixCodeToPCKey(int key) -{ - switch(key) - { - case KEYCODE_F1: return SDL_SCANCODE_F1; - case KEYCODE_F2: return SDL_SCANCODE_F2; - case KEYCODE_F3: return SDL_SCANCODE_F3; - case KEYCODE_F4: return SDL_SCANCODE_F4; - case KEYCODE_F5: return SDL_SCANCODE_F5; - case KEYCODE_F6: return SDL_SCANCODE_F6; - - case KEYCODE_UP: return SDL_SCANCODE_UP; - case KEYCODE_RIGHT: return SDL_SCANCODE_RIGHT; - case KEYCODE_DOWN: return SDL_SCANCODE_DOWN; - case KEYCODE_LEFT: return SDL_SCANCODE_LEFT; - - case KEYCODE_SHIFT: return SDL_SCANCODE_Q; - case KEYCODE_OPTN: return SDL_SCANCODE_W; - case KEYCODE_VARS: return SDL_SCANCODE_E; - case KEYCODE_MENU: return SDL_SCANCODE_R; - - case KEYCODE_ALPHA: return SDL_SCANCODE_A; - case KEYCODE_SQUARE: return SDL_SCANCODE_S; - case KEYCODE_POWER: return SDL_SCANCODE_D; - case KEYCODE_EXIT: return SDL_SCANCODE_F; - - case KEYCODE_XOT: return SDL_SCANCODE_T; - case KEYCODE_LOG: return SDL_SCANCODE_Y; - case KEYCODE_LN: return SDL_SCANCODE_U; - case KEYCODE_SIN: return SDL_SCANCODE_I; - case KEYCODE_COS: return SDL_SCANCODE_O; - case KEYCODE_TAN: return SDL_SCANCODE_P; - - case KEYCODE_FRAC: return SDL_SCANCODE_G; - case KEYCODE_FD: return SDL_SCANCODE_H; - case KEYCODE_LEFTP: return SDL_SCANCODE_J; - case KEYCODE_RIGHTP: return SDL_SCANCODE_K; - case KEYCODE_COMMA: return SDL_SCANCODE_L; - case KEYCODE_ARROW: return SDL_SCANCODE_SEMICOLON; - - case KEYCODE_1: return SDL_SCANCODE_1; - case KEYCODE_2: return SDL_SCANCODE_2; - case KEYCODE_3: return SDL_SCANCODE_3; - case KEYCODE_4: return SDL_SCANCODE_4; - case KEYCODE_5: return SDL_SCANCODE_5; - case KEYCODE_6: return SDL_SCANCODE_6; - case KEYCODE_7: return SDL_SCANCODE_7; - case KEYCODE_8: return SDL_SCANCODE_8; - case KEYCODE_9: return SDL_SCANCODE_9; - case KEYCODE_0: return SDL_SCANCODE_0; - - case KEYCODE_DEL: return SDL_SCANCODE_BACKSPACE; - case KEYCODE_ACON: return SDL_SCANCODE_ESCAPE; - - case KEYCODE_MUL: return SDL_SCANCODE_LEFTBRACKET; - case KEYCODE_DIV: return SDL_SCANCODE_RIGHTBRACKET; - - case KEYCODE_PLUS: return SDL_SCANCODE_MINUS; - case KEYCODE_MINUS: return SDL_SCANCODE_EQUALS; - - case KEYCODE_DOT: return -1; - case KEYCODE_EXP: return -1; - case KEYCODE_NEG: return -1; - - case KEYCODE_EXE: return SDL_SCANCODE_RETURN; - - default: return -1; - } -} - -void CGD_ScanKeyboard(CGD_KeyboardState state) -{ - SDL_Event e; - while(SDL_PollEvent(&e)) {} - - int length; - const Uint8 *sdl_state = SDL_GetKeyboardState(&length); - - for(int row = 0; row < 12; row++) { - for(int col = 0; col < 8; col++) { - int matrix_code = (row << 4) | col; - int index = row ^ 1; - int pattern = (0x80 >> col); - - int scancode = MatrixCodeToPCKey(matrix_code); - state[index] &= ~pattern; - if(scancode >= 0 && scancode < length && sdl_state[scancode]) - state[index] |= pattern; - } - } -} diff --git a/src-sdl2/platform.h b/src-sdl2/platform.h index 389651a..6d5e7ec 100644 --- a/src-sdl2/platform.h +++ b/src-sdl2/platform.h @@ -16,7 +16,7 @@ extern char _PRAM0[160*1024]; #define PRAM0_START ((void *)_PRAM0) #define PRAM0_END ((void *)_PRAM0 + sizeof _PRAM0) -#define CGDOOM_SCREENS_BASE SaveVRAMBuffer +#define CGDOOM_SCREENS_BASE (void *)SecondaryVRAM //--- // fx-CG-specific functions not defined on emulator