diff --git a/Makefile b/Makefile index 31fe039..4015594 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,8 @@ TARGET = quest LIBS = -lm -luiohook CC = gcc CFLAGS = -g -Wall +INSTALL_PATH = /usr/local +VERSION = 0.5.0 .PHONY: default all clean @@ -22,3 +24,15 @@ $(TARGET): $(OBJECTS) clean: -rm -f *.o -rm -f $(TARGET) + +install: all + mkdir -p $(DESTDIR)$(INSTALL_PATH)/bin + cp -f $(TARGET) $(DESTDIR)$(INSTALL_PATH)/bin + chmod 755 $(DESTDIR)$(INSTALL_PATH)/bin/$(TARGET) + mkdir -p $(DESTDIR)$(INSTALL_PATH)/share/man/man1 + sed "s/VERSION/$(VERSION)/g" < docs/$(TARGET).1 > $(DESTDIR)$(INSTALL_PATH)/share/man/man1/$(TARGET).1 + chmod 644 $(DESTDIR)$(INSTALL_PATH)/share/man/man1/$(TARGET).1 + +uninstall: + rm -f $(DESTDIR)$(INSTALL_PATH)/bin/$(TARGET)\ + $(DESTDIR)$(INSTALL_PATH)/share/man/man1/$(TARGET).1 diff --git a/README.md b/README.md index 10c175c..3da93c0 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,10 @@ splits after the first use of the split file is currently unsupported. | Keys | Action | | ---- | --------------------- | | `R` | Start | -| `F` | Stop | +| `F` | Stop / Reset | | `E` | Split | | `G` | Undo split | +| `V` | Skip split | | `C` | Close | | `T` | Toggle global hotkeys | diff --git a/docs/quest.1 b/docs/quest.1 new file mode 100644 index 0000000..53352a6 --- /dev/null +++ b/docs/quest.1 @@ -0,0 +1,17 @@ +.TH QUEST 1 quest\-VERSION +.SH NAME +quest \- speedrun timer +.SH SYNOPSIS +.B quest +.IR file +.SH DESCRIPTION +quest provides a timer for timing speedruns of video games, with features +speedrunners expect of such software like splitting the timer between named +segments and displaying comparisons between a known previous time such as +a personal best or world record. +.PP +I/O features such as importing split names from a splits.io run file/exporting +runs to the splits.io generic exchange format and global hotkeys to control the +software while a video game has window focus are also supported. +.SH OPTIONS + diff --git a/src/keys.c b/src/keys.c index 5c8476c..c2257d1 100644 --- a/src/keys.c +++ b/src/keys.c @@ -27,6 +27,8 @@ void dispatch_proc(uiohook_event * const event) { buf = K_HOTKS; if (event->data.keyboard.keycode == km.USPLT) buf = K_USPLT; + if (event->data.keyboard.keycode == km.SKIP) + buf = K_SKIP; write(pipefd[1], &buf, 1); default: break; @@ -50,6 +52,8 @@ int handleInput() hotkeys_enabled = !hotkeys_enabled; if (buf == K_USPLT) unsplit(); + if (buf == K_SKIP) + skip(); if (buf == K_CLOSE) return 1; return 0; diff --git a/src/keys.h b/src/keys.h index 8accd27..9b62865 100644 --- a/src/keys.h +++ b/src/keys.h @@ -12,6 +12,7 @@ #define K_CLOSE 5 #define K_HOTKS 6 #define K_USPLT 7 +#define K_SKIP 8 struct keymap { @@ -22,6 +23,7 @@ struct keymap uint16_t CLOSE; uint16_t HOTKS; uint16_t USPLT; + uint16_t SKIP; }; extern char buf; diff --git a/src/timer.c b/src/timer.c index 49e4568..bd8259a 100644 --- a/src/timer.c +++ b/src/timer.c @@ -50,15 +50,6 @@ void sub_timespec(struct timespec t1, struct timespec t2, struct timespec* td) } } -void reset() -{ - if (!timerActive) - return; - segments[currSeg].isReset = true; - stop(); - currSeg = -1; -} - void start() { if (timerActive || segCount == 0) @@ -73,6 +64,8 @@ void stop() { if (!timerActive) return; + if (currSeg < segCount) + segments[currSeg].isReset = true; timerActive = false; attempts++; if (pastRuns) @@ -88,6 +81,14 @@ void stop() } calculatePB(); saveFile(); + + //Reset state of timer + for(int i = 0; i < segCount; i++) { + segments[i].ms = 0; + segments[i].isSkipped = false; + segments[i].isReset = false; + } + currSeg = 0; } void split() @@ -112,6 +113,16 @@ void tpause() } +void skip() +{ + if (!timerActive) + return; + segments[currSeg].isSkipped = true; + currSeg++; + if (currSeg >= segCount) + stop(); +} + void loadKeymap() { km.START = VC_R; @@ -121,6 +132,7 @@ void loadKeymap() km.CLOSE = VC_C; km.HOTKS = VC_T; km.USPLT = VC_G; + km.SKIP = VC_V; } void ftime(char *timestr, bool withMS, int rms) @@ -176,7 +188,10 @@ void drawSegments() ftime(deltaTime, false, segments[i].ms - pbrun[i].ms); ftime(sgmtTime, false, segments[i].ms - segments[i - 1].ms); ftime(segTime, false, segments[i].ms); - sprintf(data, "%10s%10s%10s%10s", deltaTime, sgmtTime, segTime, segmentTime); + if (segments[i].isSkipped) + sprintf(data, "%10s%10s%10s%10s", zeroStr, zeroStr, zeroStr, segmentTime); + else + sprintf(data, "%10s%10s%10s%10s", deltaTime, sgmtTime, segTime, segmentTime); } rghtPrint(6 + i, w, data); leftPrint(6 + i, w, segments[i].name); @@ -232,6 +247,7 @@ void drawDisplay() drawHLine(5, w); printf("\033[5;3H[dsph]"); if (timerActive) { + drawSegments(); drawCurrentSegment(); struct timespec delta; sub_timespec(timestart, finish, &delta); @@ -254,6 +270,9 @@ void resize(int i) resized = true; } +//This function will find an invalid run if theres only one in the history +//and that run is invalid. Also, runs with skipped segments aren't considered +//valid but should be void calculatePB() { if (attempts == 0) diff --git a/src/timer.h b/src/timer.h index 831236b..f1d68f5 100644 --- a/src/timer.h +++ b/src/timer.h @@ -43,7 +43,7 @@ void stop(); void split(); void tpause(); void unsplit(); -void reset(); +void skip(); void loadKeymap(); void ftime(char *timestr, bool withMS, int ms); int timespecToMS(struct timespec t);