diff --git a/CGDOOM-minisdk/CGDOOM/platform.h b/CGDOOM-minisdk/CGDOOM/platform.h index e7d0622..0dae04d 100644 --- a/CGDOOM-minisdk/CGDOOM/platform.h +++ b/CGDOOM-minisdk/CGDOOM/platform.h @@ -73,4 +73,12 @@ #define ASSERT(x) #define InitFlashSimu(filename) +/* Description of a WAD file selectable by user. */ +typedef struct +{ + char name[16]; + uint16_t path[23]; + int size; +} WADFileInfo; + #endif //#ifndef PLATFORM_H diff --git a/cgdoom/cgdoom-ui.c b/cgdoom/cgdoom-ui.c index 1a6117c..0b59283 100644 --- a/cgdoom/cgdoom-ui.c +++ b/cgdoom/cgdoom-ui.c @@ -1,4 +1,5 @@ #include "cgdoom-ui.h" +#include /* gint's font in a PrizmSDK-friendly (though ugly) form */ static uint8_t const font_width[96] = { @@ -68,7 +69,7 @@ static void Font_RenderChar(int *x, int y, int c, int fg) for(int dy = 0; dy < 11; dy++) for(int dx = 0; dx < font_width[g]; dx++) { - int b = font_glyphs[offset + (bit >> 5)] & (0x80000000 >> (bit & 31)); + int b = font_glyphs[offset + (bit>>5)] & (0x80000000 >> (bit&31)); if (b) Bdisp_SetPoint_VRAM(*x+dx, y+dy, fg); bit++; @@ -89,13 +90,7 @@ static int Font_StringLength(char const *text) return w - 1; } -enum { - UI_LEFT = 0, - UI_CENTER = 1, - UI_RIGHT = 2, -}; - -void UI_Print(int x, int y, char const *text, int fg, int align) +void UI_Print(int x, int y, int fg, int align, char const *text) { if(align == UI_CENTER) x -= (Font_StringLength(text) + 1) / 2; @@ -106,6 +101,21 @@ void UI_Print(int x, int y, char const *text, int fg, int align) Font_RenderChar(&x, y, text[i], fg); } +void UI_Vprintf(int x, int y, int fg, int align, char const *fmt, va_list args) +{ + char str[256]; + vsprintf(str, fmt, args); + UI_Print(x, y, fg, align, str); +} + +void UI_Printf(int x, int y, int fg, int align, char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + UI_Vprintf(x, y, fg, align, fmt, args); + va_end(args); +} + void UI_AreaReverse(int x1, int y1, int x2, int y2) { uint16_t *VRAM = (uint16_t *)GetVRAMAddress() + WIDTH * y1; @@ -131,59 +141,6 @@ void UI_Checkbox(int x, int y, int checked) } } -int UI_Main(char const wad_files[][32], int wad_file_count, int *dev_info) -{ - int key=0, cursor=0; - - while(key != KEY_CTRL_EXIT) - { - int l=60, r=WIDTH-l, y=34, cursor_max=0, play_max=0; - - Bdisp_AllClr_VRAM(); - UI_Print(WIDTH / 2, 12, "CGDOOM for fx-CG 50 and Graph 90+E", - 0x0000, UI_CENTER); - - for(int i = 0; i < wad_file_count; i++) - { - char const *action = "Play other WAD"; - if(!strcmp(wad_files[i], "doom.wad")) - action = "Play DOOM"; - else if(!strcmp(wad_files[i], "doomu.wad")) - action = "Play Ultimate DOOM"; - - char name[34] = ""; - strcat(name, "("); - strcat(name, wad_files[i]); - strcat(name, ")"); - - UI_Print(l, y, action, 0x0000, UI_LEFT); - UI_Print(r, y, name, 0x0000, UI_RIGHT); - y += 14; - } - play_max = cursor_max = wad_file_count; - - UI_Print(l, y, "Developer info:", 0x0000, UI_LEFT); - UI_Checkbox(r-7, y+1, *dev_info); - y += 14; - cursor_max++; - - UI_AreaReverse(0, 32+14*cursor, WIDTH-1, 32+14*cursor+13); - Bdisp_PutDisp_DD(); - - GetKey(&key); - if(key == KEY_CTRL_UP && cursor > 0) - cursor--; - if(key == KEY_CTRL_DOWN && cursor < cursor_max - 1) - cursor++; - if(key == KEY_CTRL_EXE && cursor < play_max) - return cursor; - if(key == KEY_CTRL_EXE && cursor == cursor_max - 1) - *dev_info ^= 1; - } - - return -1; -} - void UI_FileMappingProgressBar(int size_mapped, int size_total) { const int w=192, h=5; @@ -201,3 +158,130 @@ void UI_FileMappingProgressBar(int size_mapped, int size_total) } Bdisp_PutDisp_DD(); } + +/* Layout functions. */ + +#define LAYOUT_LEFT 40 +#define LAYOUT_RIGHT (WIDTH-40) + +void Layout_Init(Layout *l) +{ + l->focus = -1; + Layout_StartFrame(l); +} + +void Layout_StartFrame(Layout *l) +{ + l->focus_count = 0; + l->y = 12; +} + +void Layout_EndFrame(Layout *l) +{ + if(l->focus < 0) + return; + int y = l->focus_y[l->focus]; + UI_AreaReverse(0, y, WIDTH-1, y+13); +} + +static void Layout_AddFocus(Layout *l) +{ + if(l->focus < 0) + l->focus = 0; + if(l->focus_count >= 16) + return; + l->focus_y[l->focus_count++] = l->y - 2; +} + +void Layout_CenteredText(Layout *l, const char *text) +{ + UI_Print(WIDTH / 2, l->y, 0x0000, UI_CENTER, text); + l->y += 14; +} + +void Layout_Text(Layout *l, const char *label, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Layout_AddFocus(l); + UI_Print(LAYOUT_LEFT, l->y, 0x0000, UI_LEFT, label); + UI_Vprintf(LAYOUT_RIGHT, l->y, 0x0000, UI_RIGHT, fmt, args); + l->y += 14; + va_end(args); +} + +void Layout_Checkbox(Layout *l, const char *label, int checked) +{ + Layout_AddFocus(l); + UI_Print(LAYOUT_LEFT, l->y, 0x0000, UI_LEFT, label); + UI_Checkbox(LAYOUT_RIGHT-7, l->y+1, checked); + l->y += 14; +} + +void Layout_Spacing(Layout *l, int spacing) +{ + l->y += spacing; +} + +int Layout_Event(Layout *l, int key) +{ + if(key == KEY_CTRL_UP) + { + l->focus--; + if(l->focus < 0) + l->focus += l->focus_count; + return 1; + } + if(key == KEY_CTRL_DOWN) + { + l->focus++; + if(l->focus >= l->focus_count) + l->focus -= l->focus_count; + return 1; + } + return 0; +} + +int UI_Main(WADFileInfo *wads, int wad_count, int *dev_info) +{ + Layout l; + Layout_Init(&l); + + while(1) + { + Bdisp_AllClr_VRAM(); + Layout_StartFrame(&l); + Layout_CenteredText(&l, "CGDOOM for fx-CG 50 and Graph 90+E"); + Layout_Spacing(&l, 12); + + for(int i = 0; i < wad_count; i++) + { + char const *action = "Play other WAD"; + if(!strcmp(wads[i].name, "doom.wad")) + action = "Play DOOM"; + else if(!strcmp(wads[i].name, "doomu.wad")) + action = "Play Ultimate DOOM"; + + Layout_Text(&l, action, "%s (%d.%dM)", + wads[i].name, wads[i].size / 1000000, + (wads[i].size % 1000000) / 100000); + } + + Layout_Spacing(&l, 12); + Layout_Checkbox(&l, "Developer info:", *dev_info); + Layout_EndFrame(&l); + Bdisp_PutDisp_DD(); + + int key; + GetKey(&key); + if(Layout_Event(&l, key)) + continue; + + if(key == KEY_CTRL_EXE && l.focus < wad_count) + return l.focus; + if(key == KEY_CTRL_EXE && l.focus == l.focus_count - 1) + *dev_info ^= 1; + } + + return -1; +} diff --git a/cgdoom/cgdoom-ui.h b/cgdoom/cgdoom-ui.h index b507640..118c42c 100644 --- a/cgdoom/cgdoom-ui.h +++ b/cgdoom/cgdoom-ui.h @@ -2,11 +2,53 @@ #define CGDOOM_UI_H #include "platform.h" +#include -/* Show the program's main screen; returns index of selected WAD file. */ -int UI_Main(char const wad_files[][32], int wad_file_count, int *dev_info); +/* Basic rendering functions. */ -/* Show a progress bar of file mapping. */ +enum { + UI_LEFT = 0, + UI_CENTER = 1, + UI_RIGHT = 2, +}; + +/* Show a progress bar of file mapping at the bottom of the screen. */ void UI_FileMappingProgressBar(int size_mapped, int size_total); +/* Print text with a cleaner font. */ +void UI_Print(int x, int y, int fg, int halign, char const *text); +/* Like UI_Print, but applies printf() formatting. */ +void UI_Printf(int x, int y, int fg, int halign, char const *fmt, ...); +void UI_Vprintf(int x, int y, int fg, int halign, char const *fmt, va_list args); + +/* A simple immediate-mode layout system. */ + +typedef struct +{ + int y, focus, focus_count; + int16_t focus_y[16]; +} Layout; + +void Layout_Init(Layout *l); + +void Layout_StartFrame(Layout *l); +void Layout_EndFrame(Layout *l); + +/* Add a centered text. */ +void Layout_CenteredText(Layout *l, const char *text); +/* Add a labeled field with printf-formatted contents. */ +void Layout_Text(Layout *l, const char *label, const char *fmt, ...); +/* Add a checkbox. */ +void Layout_Checkbox(Layout *l, const char *label, int checked); +/* Add spacing. */ +void Layout_Spacing(Layout *l, int spacing); + +/* Handle a key press; returns non-zero if event is caught. */ +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(WADFileInfo *wads, int wad_count, int *dev_info); + #endif /* CGDOOM_UI_H */ diff --git a/cgdoom/cgdoom.c b/cgdoom/cgdoom.c index 1031045..a0a8897 100644 --- a/cgdoom/cgdoom.c +++ b/cgdoom/cgdoom.c @@ -318,6 +318,7 @@ typedef struct }FileMapping; +/* Bfile's file info structure returned by filesystem search functions. */ typedef struct { unsigned short id, type; @@ -334,9 +335,9 @@ void ResetData(FileMapping *pMap) } /* Find WAD files in the filesystem. */ -int FindWADs(char filenames[][32], int max) +int FindWADs(WADFileInfo *files, int max) { - uint16_t path[32]; + uint16_t path[16]; Bfile_FileInfo info; int sd, rc, total=0; @@ -344,7 +345,10 @@ int FindWADs(char filenames[][32], int max) while(rc != -16 && total < max) { - Bfile_NameToStr_ncpy(filenames[total], path, 32); + memcpy(files[total].path, u"\\\\fls0\\", 14); + memcpy(files[total].path+7, path, 16*2); + Bfile_NameToStr_ncpy(files[total].name, path, 16); + files[total].size = info.fsize; total++; rc = Bfile_FindNext(sd, path, &info); @@ -376,6 +380,10 @@ int Flash_ReadFile(void *buf, int size, int readpos) static FileMapping *gpWADMap = 0; static SectorIndexInfo *gIndex = NULL; +/* Developer info */ +static int gDevFragments = 0; +static int gDevIndexHits = 0; + /* Read next sector from file, while caching into a buffer. */ const void *ReadNextSector(FileAccessCache *fc, int *size) { @@ -438,13 +446,17 @@ int FindSectorInFlash(const void *buf, int size) typeof(&memcmp) memcmp_fun = &memcmp; if(size == FLASH_PAGE_SIZE) memcmp_fun = &CGD_sector_memcmp; + gDevFragments++; + #ifdef FLASH_INDEX /* If an index has been built, search in it */ int lo, hi; IndexSearchSector(gIndex, buf, &lo, &hi); for(int i = lo; i < hi; i++) { - if(!memcmp_fun(buf, gIndex[i].sector, size)) + if(!memcmp_fun(buf, gIndex[i].sector, size)) { + gDevIndexHits++; return (gIndex[i].sector - FLASH_START) / FLASH_PAGE_SIZE; + } } #endif @@ -602,17 +614,14 @@ int main(void){ EnableColor(1); EnableStatusArea(3); - char wad_files[16][32]; - int wad_file_count = FindWADs(wad_files, 16); - uint16_t wad_path[39] = u"\\\\fls0\\"; + WADFileInfo wads[16]; + int wad_count = FindWADs(wads, 16); int dev_info = 0; - int choice = UI_Main(wad_files, wad_file_count, &dev_info); + int choice = UI_Main(wads, wad_count, &dev_info); if(choice < 0) return 1; - Bfile_StrToName_ncpy(wad_path+7, wad_files[choice], 32); - unsigned tmp=((unsigned)getSecondaryVramAddress()+3)&(~3); SaveVRAMBuffer = (unsigned char*)tmp; /* Graph 90+E: RAM starts at 0x0c000000 in physical memory */ @@ -622,7 +631,7 @@ int main(void){ /* Setup access to WAD file */ #ifdef CGDOOM_WAD_BFILE - gWADfd = Bfile_OpenFile_OS(wad_path, 0, 0); + gWADfd = Bfile_OpenFile_OS(wads[choice].path, 0, 0); #else #ifdef FLASH_INDEX /* Index most likely flash sectors into a sorted array, so that sectors @@ -640,7 +649,7 @@ int main(void){ gpWADMap = (FileMapping *)(SaveVRAMBuffer + 2*65536); ASSERT(2*65536 + sizeof(FileMapping) < SAVE_VRAM_SIZE); - int fd = Bfile_OpenFile_OS(wad_path,0,0); + int fd = Bfile_OpenFile_OS(wads[choice].path,0,0); int size = CreateFileMapping(fd, gpWADMap); Bfile_CloseFile_OS(fd); UI_FileMappingProgressBar(1, 1); @@ -657,6 +666,18 @@ int main(void){ I_Error ("File too fragmented"); return 1; } + else if(dev_info) { + Layout l; + Layout_Init(&l); + Bdisp_AllClr_VRAM(); + Layout_CenteredText(&l, "Developer info"); + Layout_Text(&l, "Fragments:", "%d", gDevFragments); + Layout_Text(&l, "Index hits:", "%d (%d%%)", gDevIndexHits, + (gDevIndexHits * 100 / gDevFragments)); + Bdisp_PutDisp_DD(); + int key; + GetKey(&key); + } #endif memset(VRAM,0,WIDTH*HEIGHT*2); diff --git a/cgdoom/os.h b/cgdoom/os.h index e9b1a4f..8b20663 100644 --- a/cgdoom/os.h +++ b/cgdoom/os.h @@ -40,7 +40,6 @@ void I_ErrorI(const char *str, int i1, int i2, int i3, int i4); #define strnicmp 22 #define strncmp 27 #define strcmp 33 -#define sprintf 212 //return ptr to flash int FindInFlash(const void **buf, int size, int readpos);