diff --git a/Makefile b/Makefile index fb5c97f..515a154 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,3 @@ - # makefile to fail if any command in pipe is failed. SHELL = /bin/bash -o pipefail @@ -9,8 +8,15 @@ CC = $(BASE)-gcc LD = $(CC) STRIP = $(BASE)-strip +ifeq ($(V),1) + Q := +else + Q := @ +endif + INCLUDE = -I./ -INCLUDE = -I./support/minimig +INCLUDE += -I./support/minimig +INCLUDE += -I./lib/libco PRJ = MiSTer SRC = $(wildcard *.c) @@ -21,46 +27,48 @@ ARCHIE_SRC = $(wildcard ./support/archie/*.cpp) ST_SRC = $(wildcard ./support/st/*.cpp) X86_SRC = $(wildcard ./support/x86/*.cpp) SNES_SRC = $(wildcard ./support/snes/*.cpp) +LIBCO_SRC = lib/libco/arm.c VPATH = ./:./support/minimig:./support/sharpmz:./support/archie:./support/st:./support/x86:./support/snes -OBJ = $(SRC:.c=.o) $(SRC2:.cpp=.o) $(MINIMIG_SRC:.cpp=.o) $(SHARPMZ_SRC:.cpp=.o) $(ARCHIE_SRC:.cpp=.o) $(ST_SRC:.cpp=.o) $(X86_SRC:.cpp=.o) $(SNES_SRC:.cpp=.o) -DEP = $(SRC:.c=.d) $(SRC2:.cpp=.d) $(MINIMIG_SRC:.cpp=.d) $(SHARPMZ_SRC:.cpp=.d) $(ARCHIE_SRC:.cpp=.d) $(ST_SRC:.cpp=.d) $(X86_SRC:.cpp=.d) $(SNES_SRC:.cpp=.d) +OBJ = $(SRC:.c=.c.o) $(SRC2:.cpp=.cpp.o) $(MINIMIG_SRC:.cpp=.cpp.o) $(SHARPMZ_SRC:.cpp=.cpp.o) $(ARCHIE_SRC:.cpp=.cpp.o) $(ST_SRC:.cpp=.cpp.o) $(X86_SRC:.cpp=.cpp.o) $(SNES_SRC:.cpp=.cpp.o) $(LIBCO_SRC:.c=.c.o) +DEP = $(SRC:.c=.cpp.d) $(SRC2:.cpp=.cpp.d) $(MINIMIG_SRC:.cpp=.cpp.d) $(SHARPMZ_SRC:.cpp=.cpp.d) $(ARCHIE_SRC:.cpp=.cpp.d) $(ST_SRC:.cpp=.cpp.d) $(X86_SRC:.cpp=.cpp.d) $(SNES_SRC:.cpp=.cpp.d) $(LIBCO_SRC:.c=.c.d) -DFLAGS = $(INCLUDE) -CFLAGS = $(DFLAGS) -Wall -Wextra -c -O3 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -DVDATE=\"`date +"%y%m%d"`\" +DFLAGS = $(INCLUDE) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -DVDATE=\"`date +"%y%m%d"`\" +CFLAGS = $(DFLAGS) -Wall -Wextra -Wno-strict-aliasing -c -O3 LFLAGS = -lc -lstdc++ -lrt $(PRJ): $(OBJ) - @$(info $@) - @$(LD) -o $@ $+ $(LFLAGS) - @cp $@ $@.elf - @$(STRIP) $@ + $(Q)$(info $@) + $(Q)$(LD) -o $@ $+ $(LFLAGS) + $(Q)cp $@ $@.elf + $(Q)$(STRIP) $@ clean: - rm -f *.d *.o *.elf *.map *.lst *.bak *.rej *.org *.user *~ $(PRJ) - rm -rf obj .vs DTAR* x64 + $(Q)rm -f *.elf *.map *.lst *.user *~ $(PRJ) + $(Q)rm -rf obj .vs DTAR* x64 + $(Q)find . \( -name '*.o' -o -name '*.d' -o -name '*.bak' -o -name '*.rej' -o -name '*.org' \) -exec rm -f {} \; cleanall: - rm -rf *.d *.o *.elf *.map *.lst *.bak *.rej *.org *.user *~ $(PRJ) - rm -rf obj .vs DTAR* x64 - find . -name '*.o' -delete - find . -name '*.d' -delete + $(Q)rm -rf $(OBJ) $(DEP) *.elf *.map *.lst *.bak *.rej *.org *.user *~ $(PRJ) + $(Q)rm -rf obj .vs DTAR* x64 + $(Q)find . -name '*.o' -delete + $(Q)find . -name '*.d' -delete -%.o: %.c - @$(info $<) - @$(CC) $(CFLAGS) -std=gnu99 -o $@ -c $< 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):\([0-9]\+\):/\1(\2,\ \3):/g' +%.c.o: %.c + $(Q)$(info $<) + $(Q)$(CC) $(CFLAGS) -std=gnu99 -o $@ -c $< 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):\([0-9]\+\):/\1(\2,\ \3):/g' -%.o: %.cpp - @$(info $<) - @$(CC) $(CFLAGS) -std=gnu++14 -o $@ -c $< 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):\([0-9]\+\):/\1(\2,\ \3):/g' +%.cpp.o: %.cpp + $(Q)$(info $<) + $(Q)$(CC) $(CFLAGS) -std=gnu++14 -o $@ -c $< 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):\([0-9]\+\):/\1(\2,\ \3):/g' -include $(DEP) -%.d: %.c - @$(CC) $(DFLAGS) -MM $< -MT $@ -MT $*.o -MF $@ 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):\([0-9]\+\):/\1(\2,\ \3):/g' +%.c.d: %.c + $(Q)$(CC) $(DFLAGS) -MM $< -MT $@ -MT $*.c.o -MF $@ 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):\([0-9]\+\):/\1(\2,\ \3):/g' -%.d: %.cpp - @$(CC) $(DFLAGS) -MM $< -MT $@ -MT $*.o -MF $@ 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):\([0-9]\+\):/\1(\2,\ \3):/g' +%.cpp.d: %.cpp + $(Q)$(CC) $(DFLAGS) -MM $< -MT $@ -MT $*.cpp.o -MF $@ 2>&1 | sed -e 's/\(.[a-zA-Z]\+\):\([0-9]\+\):\([0-9]\+\):/\1(\2,\ \3):/g' # Ensure correct time stamp -main.o: $(filter-out main.o, $(OBJ)) +main.cpp.o: $(filter-out main.cpp.o, $(OBJ)) diff --git a/MiSTer.vcxproj b/MiSTer.vcxproj index 941417f..3518958 100644 --- a/MiSTer.vcxproj +++ b/MiSTer.vcxproj @@ -29,12 +29,16 @@ git.lnk ./build.sh MiSTer git.lnk ./clean.sh - WIN32;VDATE="000000";_FILE_OFFSET_BITS=64;_LARGEFILE64_SOURCE;$(NMakePreprocessorDefinitions) - c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\libc\usr\include;$(NMakeIncludeSearchPath) + __arm__;__GNUC__;__USE_GNU ;_GNU_SOURCE;VDATE="000000";_FILE_OFFSET_BITS=64;_LARGEFILE64_SOURCE;$(NMakePreprocessorDefinitions) + c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\libc\usr\include;c:\Work\Git\opt\gcc54\lib\gcc\arm-linux-gnueabihf\5.4.1\include;c:\Work\Git\opt\gcc54\arm-linux-gnueabihf\include\c++\5.4.1;$(NMakeIncludeSearchPath);lib\libco $(TEMP) $(TEMP) + + + + @@ -53,9 +57,12 @@ + + + @@ -88,9 +95,12 @@ + + + diff --git a/MiSTer.vcxproj.filters b/MiSTer.vcxproj.filters index 3b13493..ae40f58 100644 --- a/MiSTer.vcxproj.filters +++ b/MiSTer.vcxproj.filters @@ -9,6 +9,12 @@ {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd + + {0c4bf53d-7986-4434-bbd2-734da3553be9} + + + {da657dc9-d7b4-417e-b916-6543cf17b67e} + @@ -94,6 +100,15 @@ Source Files + + Source Files\lib + + + Source Files\lib + + + Source Files + @@ -201,5 +216,14 @@ Header Files + + Header Files\lib + + + Header Files\lib + + + Header Files + \ No newline at end of file diff --git a/file_io.cpp b/file_io.cpp index 502d8d7..542cfc9 100644 --- a/file_io.cpp +++ b/file_io.cpp @@ -22,9 +22,12 @@ #include "user_io.h" #include "cfg.h" #include "input.h" +#include "scheduler.h" typedef std::vector DirentVector; +static const size_t YieldIterations = 128; + DirentVector DirItem; int iSelectedEntry = 0; // selected entry index int iFirstEntry = 0; @@ -520,6 +523,11 @@ struct DirentComp { bool operator()(const dirent& de1, const dirent& de2) { + if (++iterations % YieldIterations == 0) + { + scheduler_yield(); + } + if ((de1.d_type == DT_DIR) && !strcmp(de1.d_name, "..")) return true; if ((de2.d_type == DT_DIR) && !strcmp(de2.d_name, "..")) return false; @@ -545,6 +553,8 @@ struct DirentComp return strcasecmp(de1.d_name, de2.d_name) < 0; } + + size_t iterations = 0; }; static int get_stmode(const char *path) @@ -635,8 +645,13 @@ int ScanDirectory(char* path, int mode, const char *extension, int options, cons } struct dirent *de; - while((de = readdir(d))) + for (size_t i = 0; (de = readdir(d)); i++) { + if (0 < i && i % YieldIterations == 0) + { + scheduler_yield(); + } + if (de->d_type == DT_DIR) { if (!strcmp(de->d_name, ".")) continue; diff --git a/input.cpp b/input.cpp index 0ec2fbf..7e86fe5 100644 --- a/input.cpp +++ b/input.cpp @@ -17,6 +17,7 @@ #include "errno.h" #define NUMDEV 10 +#define NUMPLAYERS 6 static int ev2amiga[] = { @@ -970,24 +971,24 @@ uint32_t get_key_mod() typedef struct { uint16_t vid, pid; - char led; - char last_x, last_y; // last x & y axis bitmasks for each alternative directional control scheme (DPAD, Analog pad etc.) + uint8_t led; + uint8_t last_x, last_y; // last x & y axis bitmasks for each alternative directional control scheme (DPAD, Analog pad etc.) - char has_map; + uint8_t num; + uint8_t has_map; uint32_t map[32]; - char has_mmap; + uint8_t has_mmap; uint32_t mmap[32]; uint16_t jkmap[1024]; - char has_kbdmap; + uint8_t has_kbdmap; uint8_t kbdmap[256]; int accx, accy; } devInput; static devInput input[NUMDEV] = {}; -static int first_joystick = -1; int mfd = -1; int mwd = -1; @@ -1190,8 +1191,8 @@ void finish_map_setting(int dismiss) } else { - if (dismiss) input[mapping_dev].has_map = 0; - else FileSaveConfig(get_map_name(mapping_dev, 0), &input[mapping_dev].map, sizeof(input[mapping_dev].map)); + for (int i = 0; i < NUMDEV; i++) input[i].has_map = 0; + if (!dismiss) FileSaveConfig(get_map_name(mapping_dev, 0), &input[mapping_dev].map, sizeof(input[mapping_dev].map)); if (is_menu_core()) input[mapping_dev].has_mmap = 0; } } @@ -1281,10 +1282,10 @@ static int keyrah_trans(int key, int press) static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int dev); static int kbd_toggle = 0; -static uint16_t joy[2] = { 0 }, joy_prev[2] = { 0 }; -static uint16_t autofire[2] = { 0 }; -static uint16_t autofirecodes[2][16] = { 0 }; -static int af_delay[2] = { 50, 50 }; +static uint16_t joy[NUMPLAYERS] = {}, joy_prev[NUMPLAYERS] = {}; +static uint16_t autofire[NUMPLAYERS] = {}; +static uint16_t autofirecodes[NUMPLAYERS][16] = {}; +static int af_delay[NUMPLAYERS] = {}; static unsigned char mouse_btn = 0; static int mouse_emu = 0; @@ -1295,88 +1296,92 @@ static int mouse_emu_y = 0; static uint32_t mouse_timer = 0; -static void joy_digital(int num, uint16_t mask, uint16_t code, char press, int bnum) +static void joy_digital(int jnum, uint16_t mask, uint16_t code, char press, int bnum) { static char str[128]; - static uint16_t lastcode[2], lastmask[2]; + static uint16_t lastcode[NUMPLAYERS], lastmask[NUMPLAYERS]; + int num = jnum - 1; - if (num < 2) + if (num < NUMPLAYERS) { - if (bnum != 17 && bnum != 16) + if (jnum) { - if (press) - { - lastcode[num] = code; - lastmask[num] = mask; - } - else - { - lastcode[num] = 0; - lastmask[num] = 0; - } - } - else if (!user_io_osd_is_visible()) - { - if (lastcode[num]) + if (bnum != 17 && bnum != 16) { if (press) { - int found = 0; - int zero = -1; - for (int i = 0; i < 16; i++) + lastcode[num] = code; + lastmask[num] = mask; + } + else + { + lastcode[num] = 0; + lastmask[num] = 0; + } + } + else if (!user_io_osd_is_visible()) + { + if (lastcode[num]) + { + if (press) { - if (!autofirecodes[num][i]) zero = i; - if (autofirecodes[num][i] == lastcode[num]) + int found = 0; + int zero = -1; + for (int i = 0; i < 16; i++) { - found = 1; - autofirecodes[num][i] = 0; - break; + if (!autofirecodes[num][i]) zero = i; + if (autofirecodes[num][i] == lastcode[num]) + { + found = 1; + autofirecodes[num][i] = 0; + break; + } + } + + if (!found && zero >= 0) autofirecodes[num][zero] = lastcode[num]; + autofire[num] = !found ? autofire[num] | lastmask[num] : autofire[num] & ~lastmask[num]; + + if (hasAPI1_5()) + { + if (!found) sprintf(str, "Auto fire: %d ms", af_delay[num] * 2); + else sprintf(str, "Auto fire: OFF"); + Info(str); + } + else InfoMessage((!found) ? "\n\n Auto fire\n ON" : + "\n\n Auto fire\n OFF"); + } + return; + } + else if (joy[num] & 0xF) + { + if (press) + { + if (joy[num] & 9) + { + af_delay[num] += 25 << ((joy[num] & 1) ? 1 : 0); + if (af_delay[num] > 500) af_delay[num] = 500; + } + else + { + af_delay[num] -= 25 << ((joy[num] & 2) ? 1 : 0); + if (af_delay[num] < 25) af_delay[num] = 25; + } + + static char str[256]; + + if (hasAPI1_5()) + { + sprintf(str, "Auto fire period: %d ms", af_delay[num] * 2); + Info(str); + } + else + { + sprintf(str, "\n\n Auto fire period\n %dms", af_delay[num] * 2); + InfoMessage(str); } } - - if (!found && zero >= 0) autofirecodes[num][zero] = lastcode[num]; - autofire[num] = !found ? autofire[num] | lastmask[num] : autofire[num] & ~lastmask[num]; - - if (hasAPI1_5()) - { - if (!found) sprintf(str, "Auto fire: %d ms", af_delay[num] * 2); - else sprintf(str, "Auto fire: OFF"); - Info(str); - } - else InfoMessage((!found) ? "\n\n Auto fire\n ON" : - "\n\n Auto fire\n OFF"); + return; } - return; - } - else if(joy[num] &0xF) - { - if (press) - { - if (joy[num] & 9) - { - af_delay[num] += 25 << ((joy[num] & 1) ? 1 : 0); - if (af_delay[num] > 500) af_delay[num] = 500; - } - else - { - af_delay[num] -= 25 << ((joy[num] & 2) ? 1 : 0); - if (af_delay[num] < 25) af_delay[num] = 25; - } - - static char str[256]; - - if (hasAPI1_5()) - { - sprintf(str, "Auto fire period: %d ms", af_delay[num] * 2); - Info(str); - } - else - { - sprintf(str, "\n\n Auto fire period\n %dms", af_delay[num] * 2); - InfoMessage(str); - } - } - return; } } @@ -1447,7 +1452,7 @@ static void joy_digital(int num, uint16_t mask, uint16_t code, char press, int b input_cb(&ev, 0, 0); } - else + else if(jnum) { if (press) joy[num] |= mask; else joy[num] &= ~mask; @@ -1465,10 +1470,11 @@ static void joy_digital(int num, uint16_t mask, uint16_t code, char press, int b static void joy_analog(int num, int axis, int offset) { - static int pos[2][2] = { 0 }; + static int pos[NUMPLAYERS][2] = {}; - if (num < 2) + if (num > 0 && num < NUMPLAYERS+1) { + num--; pos[num][axis] = offset; user_io_analog_joystick(num, (char)(pos[num][0]), (char)(pos[num][1])); } @@ -1545,8 +1551,9 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int input[dev].map[13] = 0; input[dev].map[14] = 0; input[dev].map[15] = 0; + input[dev].has_map++; } - input[dev].has_map = 1; + input[dev].has_map++; } if (!input[dev].has_mmap) @@ -1651,7 +1658,24 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int //joystick buttons, digital directions if (ev->code >= 256) { - if (first_joystick < 0) first_joystick = dev; + if (!input[dev].num) + { + for (uint8_t num = 1; num < NUMDEV + 1; num++) + { + int found = 0; + for (int i = 0; i < NUMDEV; i++) + { + found = (input[i].num == num); + if (found) break; + } + + if (!found) + { + input[dev].num = num; + break; + } + } + } if (user_io_osd_is_visible()) { @@ -1711,11 +1735,16 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int { if (ev->code == input[dev].map[i]) { - if (ev->value <= 1) joy_digital((first_joystick == dev) ? 0 : 1, 1 << i, 0, ev->value, i); + if (ev->value <= 1) joy_digital(input[dev].num, 1 << i, 0, ev->value, i); return; } } } + else if (input[dev].has_map == 2) + { + if (ev->value == 1) joy_digital(0, 0, 0, 3, 17); + return; + } else { for (int i = 0; i <= 15; i++) @@ -1723,7 +1752,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int if (ev->code == input[dev].map[i]) { if (i <= 3 && origcode == ev->code) origcode = 0; // prevent autofire for original dpad - if (ev->value <= 1) joy_digital((first_joystick == dev) ? 0 : 1, 1 << i, origcode, ev->value, i); + if (ev->value <= 1) joy_digital(input[dev].num, 1 << i, origcode, ev->value, i); return; } } @@ -1733,7 +1762,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int if (ev->code == input[dev].mmap[i]) { if (origcode == ev->code) origcode = 0; // prevent autofire for original dpad - if (ev->value <= 1) joy_digital((first_joystick == dev) ? 0 : 1, 1 << (i - 8), origcode, ev->value, i - 8); + if (ev->value <= 1) joy_digital(input[dev].num, 1 << (i - 8), origcode, ev->value, i - 8); return; } } @@ -1741,7 +1770,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int if (ev->code == input[dev].mmap[17]) { - if (ev->value <= 1) joy_digital((first_joystick == dev) ? 0 : 1, 0, 0, ev->value, 17); + if (ev->value <= 1) joy_digital(input[dev].num, 0, 0, ev->value, 17); return; } @@ -1805,7 +1834,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int if (ev->code == input[dev].map[i]) { if (i <= 3 && origcode == ev->code) origcode = 0; // prevent autofire for original dpad - if (ev->value <= 1) joy_digital((user_io_get_kbdemu() == EMU_JOY0) ? 0 : 1, 1 << i, origcode, ev->value, i); + if (ev->value <= 1) joy_digital((user_io_get_kbdemu() == EMU_JOY0) ? 1 : 2, 1 << i, origcode, ev->value, i); return; } } @@ -1813,7 +1842,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int if (ev->code == input[dev].mmap[16]) { - if (ev->value <= 1) joy_digital((user_io_get_kbdemu() == EMU_JOY0) ? 0 : 1, 0, 0, ev->value, 16); + if (ev->value <= 1) joy_digital((user_io_get_kbdemu() == EMU_JOY0) ? 1 : 2, 0, 0, ev->value, 16); return; } } @@ -1914,7 +1943,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int else { // skip if first joystick is not defined. - if (first_joystick < 0) break; + if (!input[dev].num) break; // TODO: // 1) add analog axis mapping @@ -1925,7 +1954,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int int offset = 0; if (value < 127 || value>129) offset = value - 128; //printf("analog_x = %d\n", offset); - joy_analog((first_joystick == dev) ? 0 : 1, 0, offset); + joy_analog(input[dev].num, 0, offset); return; } @@ -1934,7 +1963,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int int offset = 0; if (value < 127 || value>129) offset = value - 128; //printf("analog_y = %d\n", offset); - joy_analog((first_joystick == dev) ? 0 : 1, 1, offset); + joy_analog(input[dev].num, 1, offset); return; } } @@ -2095,12 +2124,12 @@ int input_test(int getchar) { //keyboard, buttons case EV_KEY: - printf("Input event: type=EV_KEY, code=%d(0x%x), value=%d\n", ev.code, ev.code, ev.value); + printf("Input event: type=EV_KEY, code=%d(0x%x), value=%d, jnum=%d, ID:%04x:%04x\n", ev.code, ev.code, ev.value, input[i].num, input[i].vid, input[i].pid); break; //mouse case EV_REL: - printf("Input event: type=EV_REL, Axis=%d, Offset:=%d\n", ev.code, ev.value); + printf("Input event: type=EV_REL, Axis=%d, Offset:=%d, jnum=%d, ID:%04x:%04x\n", ev.code, ev.value, input[i].num, input[i].vid, input[i].pid); break; case EV_SYN: @@ -2122,7 +2151,7 @@ int input_test(int getchar) if (input[i].vid == 0x0079 && input[i].pid == 0x0006) { if (ev.code == 2) break; } - printf("Input event: type=EV_ABS, Axis=%d, Offset:=%d.", ev.code, ev.value); + printf("Input event: type=EV_ABS, Axis=%d, Offset:=%d, jnum=%d, ID:%04x:%04x.", ev.code, ev.value, input[i].num, input[i].vid, input[i].pid); printf(" ABS_INFO: min = %d max = %d", absinfo.minimum, absinfo.maximum); if (absinfo.fuzz) printf(" fuzz = %d", absinfo.fuzz); if (absinfo.resolution) printf(" res = %d", absinfo.resolution); @@ -2130,7 +2159,7 @@ int input_test(int getchar) break; default: - printf("Input event: type=%d, code=%d(0x%x), value=%d(0x%x)\n", ev.type, ev.code, ev.code, ev.value, ev.value); + printf("Input event: type=%d, code=%d(0x%x), value=%d(0x%x), jnum=%d, ID:%04x:%04x\n", ev.type, ev.code, ev.code, ev.value, ev.value, input[i].num, input[i].vid, input[i].pid); } } @@ -2159,8 +2188,9 @@ int input_test(int getchar) uint16_t base_axis = !user_io_get_joy_transl() ? 0 : ~ev.code; uint16_t extra_axis = 2; - if (input[i].vid == 0x0079 && input[i].pid == 0x0006) extra_axis = 0; // AliExpress USB encoder PCB floods axis 2 if (input[i].vid == 0x045e && input[i].pid == 0x028e) extra_axis = 3; // 8BitDo Retro Receiver + if (input[i].vid == 0x046d && input[i].pid == 0xc21f) extra_axis = 3; // Logitech F710 + if (input[i].vid == 0x0079 && input[i].pid == 0x0006) extra_axis = 0; // AliExpress USB encoder PCB floods axis 2 if(ev.code == base_axis || ev.code == extra_axis || ev.code == 16) // x { @@ -2178,10 +2208,11 @@ int input_test(int getchar) } base_axis = !user_io_get_joy_transl() ? 1 : ~ev.code; - if (input[i].vid == 0x0079 && input[i].pid == 0x0006) base_axis = 3; // AliExpress USB encoder PCB extra_axis = 5; if (input[i].vid == 0x045e && input[i].pid == 0x028e) extra_axis = 4; // 8BitDo Retro Receiver + if (input[i].vid == 0x046d && input[i].pid == 0xc21f) extra_axis = 4; // Logitech F710 + if (input[i].vid == 0x0079 && input[i].pid == 0x0006) extra_axis = 3; // AliExpress USB encoder PCB if (ev.code == base_axis || ev.code == extra_axis || ev.code == 17) // y { @@ -2201,7 +2232,8 @@ int input_test(int getchar) } } - if (input[i].vid == 0x045e && input[i].pid == 0x028e) // 8BitDo Retro Receiver + if ((input[i].vid == 0x045e && input[i].pid == 0x028e) || // 8BitDo Retro Receiver + (input[i].vid == 0x046d && input[i].pid == 0xc21f)) // Logitech F710 { ev.type = EV_KEY; if (ev.code == 2) @@ -2265,8 +2297,8 @@ int input_test(int getchar) int input_poll(int getchar) { - static int af[2] = { 0 }; - static uint32_t time[2] = { 0 }; + static int af[NUMPLAYERS] = {}; + static uint32_t time[NUMPLAYERS] = {}; int ret = input_test(getchar); if (getchar) return ret; @@ -2298,8 +2330,10 @@ int input_poll(int getchar) if (!mouse_emu_x && !mouse_emu_y) mouse_timer = 0; - for (int i = 0; i < 2; i++) + for (int i = 0; i < NUMPLAYERS; i++) { + if (!af_delay[i]) af_delay[i] = 50; + if (!time[i]) time[i] = GetTimer(af_delay[i]); int send = 0; diff --git a/lib/libco/amd64.c b/lib/libco/amd64.c new file mode 100644 index 0000000..235708a --- /dev/null +++ b/lib/libco/amd64.c @@ -0,0 +1,160 @@ +/* + libco.amd64 (2016-09-14) + author: byuu + license: public domain +*/ + +#define LIBCO_C +#include "libco.h" +#include "settings.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static thread_local long long co_active_buffer[64]; +static thread_local cothread_t co_active_handle = 0; +static void (*co_swap)(cothread_t, cothread_t) = 0; + +#ifdef LIBCO_MPROTECT + alignas(4096) +#else + section(text) +#endif +#ifdef _WIN32 + /* ABI: Win64 */ + static const unsigned char co_swap_function[4096] = { + 0x48, 0x89, 0x22, /* mov [rdx],rsp */ + 0x48, 0x8b, 0x21, /* mov rsp,[rcx] */ + 0x58, /* pop rax */ + 0x48, 0x89, 0x6a, 0x08, /* mov [rdx+ 8],rbp */ + 0x48, 0x89, 0x72, 0x10, /* mov [rdx+16],rsi */ + 0x48, 0x89, 0x7a, 0x18, /* mov [rdx+24],rdi */ + 0x48, 0x89, 0x5a, 0x20, /* mov [rdx+32],rbx */ + 0x4c, 0x89, 0x62, 0x28, /* mov [rdx+40],r12 */ + 0x4c, 0x89, 0x6a, 0x30, /* mov [rdx+48],r13 */ + 0x4c, 0x89, 0x72, 0x38, /* mov [rdx+56],r14 */ + 0x4c, 0x89, 0x7a, 0x40, /* mov [rdx+64],r15 */ + #if !defined(LIBCO_NO_SSE) + 0x0f, 0x29, 0x72, 0x50, /* movaps [rdx+ 80],xmm6 */ + 0x0f, 0x29, 0x7a, 0x60, /* movaps [rdx+ 96],xmm7 */ + 0x44, 0x0f, 0x29, 0x42, 0x70, /* movaps [rdx+112],xmm8 */ + 0x48, 0x83, 0xc2, 0x70, /* add rdx,112 */ + 0x44, 0x0f, 0x29, 0x4a, 0x10, /* movaps [rdx+ 16],xmm9 */ + 0x44, 0x0f, 0x29, 0x52, 0x20, /* movaps [rdx+ 32],xmm10 */ + 0x44, 0x0f, 0x29, 0x5a, 0x30, /* movaps [rdx+ 48],xmm11 */ + 0x44, 0x0f, 0x29, 0x62, 0x40, /* movaps [rdx+ 64],xmm12 */ + 0x44, 0x0f, 0x29, 0x6a, 0x50, /* movaps [rdx+ 80],xmm13 */ + 0x44, 0x0f, 0x29, 0x72, 0x60, /* movaps [rdx+ 96],xmm14 */ + 0x44, 0x0f, 0x29, 0x7a, 0x70, /* movaps [rdx+112],xmm15 */ + #endif + 0x48, 0x8b, 0x69, 0x08, /* mov rbp,[rcx+ 8] */ + 0x48, 0x8b, 0x71, 0x10, /* mov rsi,[rcx+16] */ + 0x48, 0x8b, 0x79, 0x18, /* mov rdi,[rcx+24] */ + 0x48, 0x8b, 0x59, 0x20, /* mov rbx,[rcx+32] */ + 0x4c, 0x8b, 0x61, 0x28, /* mov r12,[rcx+40] */ + 0x4c, 0x8b, 0x69, 0x30, /* mov r13,[rcx+48] */ + 0x4c, 0x8b, 0x71, 0x38, /* mov r14,[rcx+56] */ + 0x4c, 0x8b, 0x79, 0x40, /* mov r15,[rcx+64] */ + #if !defined(LIBCO_NO_SSE) + 0x0f, 0x28, 0x71, 0x50, /* movaps xmm6, [rcx+ 80] */ + 0x0f, 0x28, 0x79, 0x60, /* movaps xmm7, [rcx+ 96] */ + 0x44, 0x0f, 0x28, 0x41, 0x70, /* movaps xmm8, [rcx+112] */ + 0x48, 0x83, 0xc1, 0x70, /* add rcx,112 */ + 0x44, 0x0f, 0x28, 0x49, 0x10, /* movaps xmm9, [rcx+ 16] */ + 0x44, 0x0f, 0x28, 0x51, 0x20, /* movaps xmm10,[rcx+ 32] */ + 0x44, 0x0f, 0x28, 0x59, 0x30, /* movaps xmm11,[rcx+ 48] */ + 0x44, 0x0f, 0x28, 0x61, 0x40, /* movaps xmm12,[rcx+ 64] */ + 0x44, 0x0f, 0x28, 0x69, 0x50, /* movaps xmm13,[rcx+ 80] */ + 0x44, 0x0f, 0x28, 0x71, 0x60, /* movaps xmm14,[rcx+ 96] */ + 0x44, 0x0f, 0x28, 0x79, 0x70, /* movaps xmm15,[rcx+112] */ + #endif + 0xff, 0xe0, /* jmp rax */ + }; + + #include + + static void co_init() { + #ifdef LIBCO_MPROTECT + DWORD old_privileges; + VirtualProtect((void*)co_swap_function, sizeof co_swap_function, PAGE_EXECUTE_READ, &old_privileges); + #endif + } +#else + /* ABI: SystemV */ + static const unsigned char co_swap_function[4096] = { + 0x48, 0x89, 0x26, /* mov [rsi],rsp */ + 0x48, 0x8b, 0x27, /* mov rsp,[rdi] */ + 0x58, /* pop rax */ + 0x48, 0x89, 0x6e, 0x08, /* mov [rsi+ 8],rbp */ + 0x48, 0x89, 0x5e, 0x10, /* mov [rsi+16],rbx */ + 0x4c, 0x89, 0x66, 0x18, /* mov [rsi+24],r12 */ + 0x4c, 0x89, 0x6e, 0x20, /* mov [rsi+32],r13 */ + 0x4c, 0x89, 0x76, 0x28, /* mov [rsi+40],r14 */ + 0x4c, 0x89, 0x7e, 0x30, /* mov [rsi+48],r15 */ + 0x48, 0x8b, 0x6f, 0x08, /* mov rbp,[rdi+ 8] */ + 0x48, 0x8b, 0x5f, 0x10, /* mov rbx,[rdi+16] */ + 0x4c, 0x8b, 0x67, 0x18, /* mov r12,[rdi+24] */ + 0x4c, 0x8b, 0x6f, 0x20, /* mov r13,[rdi+32] */ + 0x4c, 0x8b, 0x77, 0x28, /* mov r14,[rdi+40] */ + 0x4c, 0x8b, 0x7f, 0x30, /* mov r15,[rdi+48] */ + 0xff, 0xe0, /* jmp rax */ + }; + + #include + #include + + static void co_init() { + #ifdef LIBCO_MPROTECT + unsigned long long addr = (unsigned long long)co_swap_function; + unsigned long long base = addr - (addr % sysconf(_SC_PAGESIZE)); + unsigned long long size = (addr - base) + sizeof co_swap_function; + mprotect((void*)base, size, PROT_READ | PROT_EXEC); + #endif + } +#endif + +static void crash() { + assert(0); /* called only if cothread_t entrypoint returns */ +} + +cothread_t co_active() { + if(!co_active_handle) co_active_handle = &co_active_buffer; + return co_active_handle; +} + +cothread_t co_create(unsigned int size, void (*entrypoint)(void)) { + cothread_t handle; + if(!co_swap) { + co_init(); + co_swap = (void (*)(cothread_t, cothread_t))co_swap_function; + } + if(!co_active_handle) co_active_handle = &co_active_buffer; + size += 512; /* allocate additional space for storage */ + size &= ~15; /* align stack to 16-byte boundary */ + + if(handle = (cothread_t)malloc(size)) { + long long *p = (long long*)((char*)handle + size); /* seek to top of stack */ + *--p = (long long)crash; /* crash if entrypoint returns */ + *--p = (long long)entrypoint; /* start of function */ + *(long long*)handle = (long long)p; /* stack pointer */ + } + + return handle; +} + +void co_delete(cothread_t handle) { + free(handle); +} + +void co_switch(cothread_t handle) { + register cothread_t co_previous_handle = co_active_handle; + co_swap(co_active_handle = handle, co_previous_handle); +} + +#ifdef __cplusplus +} +#endif diff --git a/lib/libco/arm.c b/lib/libco/arm.c new file mode 100644 index 0000000..e7c57b4 --- /dev/null +++ b/lib/libco/arm.c @@ -0,0 +1,79 @@ +/* + libco.arm (2016-09-14) + author: byuu + license: public domain +*/ + +#define LIBCO_C +#include "libco.h" +#include "settings.h" + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static thread_local unsigned long co_active_buffer[64]; +static thread_local cothread_t co_active_handle = 0; +static void (*co_swap)(cothread_t, cothread_t) = 0; + +#ifdef LIBCO_MPROTECT + alignas(4096) +#else + section(text) +#endif +static const unsigned long co_swap_function[1024] = { + 0xe8a16ff0, /* stmia r1!, {r4-r11,sp,lr} */ + 0xe8b0aff0, /* ldmia r0!, {r4-r11,sp,pc} */ + 0xe12fff1e, /* bx lr */ +}; + +static void co_init() { + #ifdef LIBCO_MPROTECT + unsigned long addr = (unsigned long)co_swap_function; + unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE)); + unsigned long size = (addr - base) + sizeof co_swap_function; + mprotect((void*)base, size, PROT_READ | PROT_EXEC); + #endif +} + +cothread_t co_active() { + if(!co_active_handle) co_active_handle = &co_active_buffer; + return co_active_handle; +} + +cothread_t co_create(unsigned int size, void (*entrypoint)(void)) { + unsigned long* handle = 0; + if(!co_swap) { + co_init(); + co_swap = (void (*)(cothread_t, cothread_t))co_swap_function; + } + if(!co_active_handle) co_active_handle = &co_active_buffer; + size += 256; + size &= ~15; + + if((handle = (unsigned long*)malloc(size))) { + unsigned long* p = (unsigned long*)((unsigned char*)handle + size); + handle[8] = (unsigned long)p; + handle[9] = (unsigned long)entrypoint; + } + + return handle; +} + +void co_delete(cothread_t handle) { + free(handle); +} + +void co_switch(cothread_t handle) { + cothread_t co_previous_handle = co_active_handle; + co_swap(co_active_handle = handle, co_previous_handle); +} + +#ifdef __cplusplus +} +#endif diff --git a/lib/libco/doc/style.css b/lib/libco/doc/style.css new file mode 100644 index 0000000..5181afd --- /dev/null +++ b/lib/libco/doc/style.css @@ -0,0 +1,8 @@ +body { + background: #333; + color: #fff; +} + +code { + background: #444; +} diff --git a/lib/libco/doc/targets.html b/lib/libco/doc/targets.html new file mode 100644 index 0000000..d6211a1 --- /dev/null +++ b/lib/libco/doc/targets.html @@ -0,0 +1,89 @@ + + + + + + + +Supported targets:

+ +Note that supported targets are only those that have been tested and confirmed +working. It is quite possible that libco will work on more processors, compilers +and operating systems than those listed below. +
+ +libco.x86
+Overhead: ~5x
+Supported processor(s): 32-bit x86
+Supported compiler(s): any
+Supported operating system(s):
    +
  • Windows
  • +
  • Mac OS X
  • +
  • Linux
  • +
  • BSD
  • +
+
+ +libco.amd64
+Overhead: ~10x (Windows), ~6x (all other platforms)
+Supported processor(s): 64-bit amd64
+Supported compiler(s): any
+Supported operating system(s):
    +
  • Windows
  • +
  • Mac OS X
  • +
  • Linux
  • +
  • BSD
  • +
+
+ +libco.ppc
+Overhead: ~20x
+Supported processor(s): 32-bit PowerPC, 64-bit PowerPC
+Supported compiler(s): GNU GCC
+Supported operating system(s):
    +
+
  • Mac OS X
  • +
  • Linux
  • +
  • BSD
  • +
  • Playstation 3
  • + +
    + +Note: this module contains compiler flags to enable/disable FPU and Altivec +support. + +
    + +libco.fiber
    +Overhead: ~15x
    +Supported processor(s): Processor independent
    +Supported compiler(s): any
    +Supported operating system(s):
      +
    • Windows
    • +
    +
    + +libco.sjlj
    +Overhead: ~30x
    +Supported processor(s): Processor independent
    +Supported compiler(s): any
    +Supported operating system(s):
      +
    • Mac OS X
    • +
    • Linux
    • +
    • BSD
    • +
    • Solaris
    • +
    +
    + +libco.ucontext
    +Overhead: ~300x
    +Supported processor(s): Processor independent
    +Supported compiler(s): any
    +Supported operating system(s):
      +
    • Linux
    • +
    • BSD
    • +
    +
    + + + diff --git a/lib/libco/doc/usage.html b/lib/libco/doc/usage.html new file mode 100644 index 0000000..3f0d81c --- /dev/null +++ b/lib/libco/doc/usage.html @@ -0,0 +1,107 @@ + + + + + + + +License:

    +libco is released to the public domain. +
    + +Contact:

    +At present, you may contact me at setsunakun0 at hotmail dot com.
    +I am interested in knowing of any projects that make use of this library, +though this is only a courtesy. +
    + +Foreword:

    +libco is a cross-platform, public domain implementation of +cooperative-multithreading; a feature that is sorely lacking +from the ISO C/C++ standard.
    +The library is designed for maximum speed and portability, and +not for safety or features. If safety or extra functionality is desired, +a wrapper API can easily be written to encapsulate all library functions.
    +Behavior of executing operations that are listed as not permitted +below result in undefined behavior. They may work anyway, they +may cause undesired / unknown behavior, or they may crash the +program entirely.
    +The goal of this library was to simplify the base API as much as possible, +implementing only that which cannot be implemented using pure C. Additional +functionality after this would only complicate ports of this library to new +platforms. +
    + +Porting:

    +This document is included as a reference for porting libco. Please submit any +ports you create to me, so that libco can become more useful. Please note that +since libco is public domain, you must submit your code as a work of the +public domain in order for it to be included in the official distribution. +Full credit will be given in the source code of the official release. Please +do not bother submitting code to me under any other license -- including GPL, +LGPL, BSD or CC -- I am not interested in creating a library with multiple +different licenses depending on which targets are used. +
    + +Synopsis:

    + +typedef void* cothread_t;
    +
    +cothread_t co_active();
    +cothread_t co_create(unsigned int heapsize, void (*coentry)(void));
    +void       co_delete(cothread_t cothread);
    +void       co_switch(cothread_t cothread);
    +
    +
    + +Usage: +
    + +typedef void* cothread_t;

    +Handle to cothread.
    +Handle must be of type void*.
    +A value of null (0) indicates an uninitialized or invalid +handle, whereas a non-zero value indicates a valid handle. +
    + +cothread_t co_active();

    +Return handle to current cothread. Always returns a valid handle, even when +called from the main program thread. +
    + +cothread_t co_create(unsigned int heapsize, void (*coentry)(void));

    +Create new cothread.
    +Heapsize is the amount of memory allocated for the cothread stack, specified +in bytes. This is unfortunately impossible to make fully portable. It is +recommended to specify sizes using `n * sizeof(void*)'. It is better to err +on the side of caution and allocate more memory than will be needed to ensure +compatibility with other platforms, within reason. A typical heapsize for a +32-bit architecture is ~1MB.
    +When the new cothread is first called, program execution jumps to coentry. +This function does not take any arguments, due to portability issues with +passing function arguments. However, arguments can be simulated by the use +of global variables, which can be set before the first call to each cothread.
    +coentry() must not return, and should end with an appropriate co_switch() +statement. Behavior is undefined if entry point returns normally.
    +Library is responsible for allocating cothread stack memory, to free +the user from needing to allocate special memory capable of being used +as program stack memory on platforms where this is required.
    +User is always responsible for deleting cothreads with co_delete().
    +Return value of null (0) indicates cothread creation failed. +
    + +void co_delete(cothread_t cothread);

    +Delete specified cothread.
    +Null (0) or invalid cothread handle is not allowed.
    +Passing handle of active cothread to this function is not allowed.
    +Passing handle of primary cothread is not allowed. +
    + +void co_switch(cothread_t cothread);

    +Switch to specified cothread.
    +Null (0) or invalid cothread handle is not allowed.
    +Passing handle of active cothread to this function is not allowed. +
    + + + diff --git a/lib/libco/fiber.c b/lib/libco/fiber.c new file mode 100644 index 0000000..f2c5b72 --- /dev/null +++ b/lib/libco/fiber.c @@ -0,0 +1,51 @@ +/* + libco.win (2008-01-28) + authors: Nach, byuu + license: public domain +*/ + +#define LIBCO_C +#include "libco.h" + +#define WINVER 0x0400 +#define _WIN32_WINNT 0x0400 +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static thread_local cothread_t co_active_ = 0; + +static void __stdcall co_thunk(void* coentry) { + ((void (*)(void))coentry)(); +} + +cothread_t co_active() { + if(!co_active_) { + ConvertThreadToFiber(0); + co_active_ = GetCurrentFiber(); + } + return co_active_; +} + +cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) { + if(!co_active_) { + ConvertThreadToFiber(0); + co_active_ = GetCurrentFiber(); + } + return (cothread_t)CreateFiber(heapsize, co_thunk, (void*)coentry); +} + +void co_delete(cothread_t cothread) { + DeleteFiber(cothread); +} + +void co_switch(cothread_t cothread) { + co_active_ = cothread; + SwitchToFiber(cothread); +} + +#ifdef __cplusplus +} +#endif diff --git a/lib/libco/libco.c b/lib/libco/libco.c new file mode 100644 index 0000000..13eb237 --- /dev/null +++ b/lib/libco/libco.c @@ -0,0 +1,34 @@ +/* + libco + license: public domain +*/ + +#if defined(__clang__) + #pragma clang diagnostic ignored "-Wparentheses" +#endif + +#if defined(__clang__) || defined(__GNUC__) + #if defined(__i386__) + #include "x86.c" + #elif defined(__amd64__) + #include "amd64.c" + #elif defined(__arm__) + #include "arm.c" + #elif defined(_ARCH_PPC) + #include "ppc.c" + #elif defined(_WIN32) + #include "fiber.c" + #else + #include "sjlj.c" + #endif +#elif defined(_MSC_VER) + #if defined(_M_IX86) + #include "x86.c" + #elif defined(_M_AMD64) + #include "amd64.c" + #else + #include "fiber.c" + #endif +#else + #error "libco: unsupported processor, compiler or operating system" +#endif diff --git a/lib/libco/libco.h b/lib/libco/libco.h new file mode 100644 index 0000000..792df0b --- /dev/null +++ b/lib/libco/libco.h @@ -0,0 +1,26 @@ +/* + libco v18 (2016-09-14) + author: byuu + license: public domain +*/ + +#ifndef LIBCO_H +#define LIBCO_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* cothread_t; + +cothread_t co_active(); +cothread_t co_create(unsigned int, void (*)(void)); +void co_delete(cothread_t); +void co_switch(cothread_t); + +#ifdef __cplusplus +} +#endif + +/* ifndef LIBCO_H */ +#endif diff --git a/lib/libco/ppc.c b/lib/libco/ppc.c new file mode 100644 index 0000000..efec3aa --- /dev/null +++ b/lib/libco/ppc.c @@ -0,0 +1,367 @@ +/* + libco.ppc (2016-09-14) + author: blargg + license: public domain +*/ + +#define LIBCO_C +#include "libco.h" +#include "settings.h" + +#include +#include +#include + +#if LIBCO_MPROTECT + #include + #include +#endif + +/* state format (offsets in 32-bit words) + + +0 pointer to swap code + rest of function descriptor for entry function + +8 PC ++10 SP + special registers + GPRs + FPRs + VRs + stack +*/ + +enum { state_size = 1024 }; +enum { above_stack = 2048 }; +enum { stack_align = 256 }; + +static thread_local cothread_t co_active_handle = 0; + +/* determine environment */ + +#define LIBCO_PPC64 (_ARCH_PPC64 || __PPC64__ || __ppc64__ || __powerpc64__) + +/* whether function calls are indirect through a descriptor, or are directly to function */ +#ifndef LIBCO_PPCDESC + #if !_CALL_SYSV && (_CALL_AIX || _CALL_AIXDESC || LIBCO_PPC64) + #define LIBCO_PPCDESC 1 + #endif +#endif + +#ifdef LIBCO_MPROTECT + alignas(4096) +#else + section(text) +#endif +static const uint32_t libco_ppc_code[1024] = { + #if LIBCO_PPC64 + 0x7d000026, /* mfcr r8 */ + 0xf8240028, /* std r1,40(r4) */ + 0x7d2802a6, /* mflr r9 */ + 0xf9c40048, /* std r14,72(r4) */ + 0xf9e40050, /* std r15,80(r4) */ + 0xfa040058, /* std r16,88(r4) */ + 0xfa240060, /* std r17,96(r4) */ + 0xfa440068, /* std r18,104(r4) */ + 0xfa640070, /* std r19,112(r4) */ + 0xfa840078, /* std r20,120(r4) */ + 0xfaa40080, /* std r21,128(r4) */ + 0xfac40088, /* std r22,136(r4) */ + 0xfae40090, /* std r23,144(r4) */ + 0xfb040098, /* std r24,152(r4) */ + 0xfb2400a0, /* std r25,160(r4) */ + 0xfb4400a8, /* std r26,168(r4) */ + 0xfb6400b0, /* std r27,176(r4) */ + 0xfb8400b8, /* std r28,184(r4) */ + 0xfba400c0, /* std r29,192(r4) */ + 0xfbc400c8, /* std r30,200(r4) */ + 0xfbe400d0, /* std r31,208(r4) */ + 0xf9240020, /* std r9,32(r4) */ + 0xe8e30020, /* ld r7,32(r3) */ + 0xe8230028, /* ld r1,40(r3) */ + 0x48000009, /* bl 1 */ + 0x7fe00008, /* trap */ + 0x91040030, /*1:stw r8,48(r4) */ + 0x80c30030, /* lwz r6,48(r3) */ + 0x7ce903a6, /* mtctr r7 */ + 0xe9c30048, /* ld r14,72(r3) */ + 0xe9e30050, /* ld r15,80(r3) */ + 0xea030058, /* ld r16,88(r3) */ + 0xea230060, /* ld r17,96(r3) */ + 0xea430068, /* ld r18,104(r3) */ + 0xea630070, /* ld r19,112(r3) */ + 0xea830078, /* ld r20,120(r3) */ + 0xeaa30080, /* ld r21,128(r3) */ + 0xeac30088, /* ld r22,136(r3) */ + 0xeae30090, /* ld r23,144(r3) */ + 0xeb030098, /* ld r24,152(r3) */ + 0xeb2300a0, /* ld r25,160(r3) */ + 0xeb4300a8, /* ld r26,168(r3) */ + 0xeb6300b0, /* ld r27,176(r3) */ + 0xeb8300b8, /* ld r28,184(r3) */ + 0xeba300c0, /* ld r29,192(r3) */ + 0xebc300c8, /* ld r30,200(r3) */ + 0xebe300d0, /* ld r31,208(r3) */ + 0x7ccff120, /* mtcr r6 */ + #else + 0x7d000026, /* mfcr r8 */ + 0x90240028, /* stw r1,40(r4) */ + 0x7d2802a6, /* mflr r9 */ + 0x91a4003c, /* stw r13,60(r4) */ + 0x91c40040, /* stw r14,64(r4) */ + 0x91e40044, /* stw r15,68(r4) */ + 0x92040048, /* stw r16,72(r4) */ + 0x9224004c, /* stw r17,76(r4) */ + 0x92440050, /* stw r18,80(r4) */ + 0x92640054, /* stw r19,84(r4) */ + 0x92840058, /* stw r20,88(r4) */ + 0x92a4005c, /* stw r21,92(r4) */ + 0x92c40060, /* stw r22,96(r4) */ + 0x92e40064, /* stw r23,100(r4) */ + 0x93040068, /* stw r24,104(r4) */ + 0x9324006c, /* stw r25,108(r4) */ + 0x93440070, /* stw r26,112(r4) */ + 0x93640074, /* stw r27,116(r4) */ + 0x93840078, /* stw r28,120(r4) */ + 0x93a4007c, /* stw r29,124(r4) */ + 0x93c40080, /* stw r30,128(r4) */ + 0x93e40084, /* stw r31,132(r4) */ + 0x91240020, /* stw r9,32(r4) */ + 0x80e30020, /* lwz r7,32(r3) */ + 0x80230028, /* lwz r1,40(r3) */ + 0x48000009, /* bl 1 */ + 0x7fe00008, /* trap */ + 0x91040030, /*1:stw r8,48(r4) */ + 0x80c30030, /* lwz r6,48(r3) */ + 0x7ce903a6, /* mtctr r7 */ + 0x81a3003c, /* lwz r13,60(r3) */ + 0x81c30040, /* lwz r14,64(r3) */ + 0x81e30044, /* lwz r15,68(r3) */ + 0x82030048, /* lwz r16,72(r3) */ + 0x8223004c, /* lwz r17,76(r3) */ + 0x82430050, /* lwz r18,80(r3) */ + 0x82630054, /* lwz r19,84(r3) */ + 0x82830058, /* lwz r20,88(r3) */ + 0x82a3005c, /* lwz r21,92(r3) */ + 0x82c30060, /* lwz r22,96(r3) */ + 0x82e30064, /* lwz r23,100(r3) */ + 0x83030068, /* lwz r24,104(r3) */ + 0x8323006c, /* lwz r25,108(r3) */ + 0x83430070, /* lwz r26,112(r3) */ + 0x83630074, /* lwz r27,116(r3) */ + 0x83830078, /* lwz r28,120(r3) */ + 0x83a3007c, /* lwz r29,124(r3) */ + 0x83c30080, /* lwz r30,128(r3) */ + 0x83e30084, /* lwz r31,132(r3) */ + 0x7ccff120, /* mtcr r6 */ + #endif + + #ifndef LIBCO_PPC_NOFP + 0xd9c400e0, /* stfd f14,224(r4) */ + 0xd9e400e8, /* stfd f15,232(r4) */ + 0xda0400f0, /* stfd f16,240(r4) */ + 0xda2400f8, /* stfd f17,248(r4) */ + 0xda440100, /* stfd f18,256(r4) */ + 0xda640108, /* stfd f19,264(r4) */ + 0xda840110, /* stfd f20,272(r4) */ + 0xdaa40118, /* stfd f21,280(r4) */ + 0xdac40120, /* stfd f22,288(r4) */ + 0xdae40128, /* stfd f23,296(r4) */ + 0xdb040130, /* stfd f24,304(r4) */ + 0xdb240138, /* stfd f25,312(r4) */ + 0xdb440140, /* stfd f26,320(r4) */ + 0xdb640148, /* stfd f27,328(r4) */ + 0xdb840150, /* stfd f28,336(r4) */ + 0xdba40158, /* stfd f29,344(r4) */ + 0xdbc40160, /* stfd f30,352(r4) */ + 0xdbe40168, /* stfd f31,360(r4) */ + 0xc9c300e0, /* lfd f14,224(r3) */ + 0xc9e300e8, /* lfd f15,232(r3) */ + 0xca0300f0, /* lfd f16,240(r3) */ + 0xca2300f8, /* lfd f17,248(r3) */ + 0xca430100, /* lfd f18,256(r3) */ + 0xca630108, /* lfd f19,264(r3) */ + 0xca830110, /* lfd f20,272(r3) */ + 0xcaa30118, /* lfd f21,280(r3) */ + 0xcac30120, /* lfd f22,288(r3) */ + 0xcae30128, /* lfd f23,296(r3) */ + 0xcb030130, /* lfd f24,304(r3) */ + 0xcb230138, /* lfd f25,312(r3) */ + 0xcb430140, /* lfd f26,320(r3) */ + 0xcb630148, /* lfd f27,328(r3) */ + 0xcb830150, /* lfd f28,336(r3) */ + 0xcba30158, /* lfd f29,344(r3) */ + 0xcbc30160, /* lfd f30,352(r3) */ + 0xcbe30168, /* lfd f31,360(r3) */ + #endif + + #ifdef __ALTIVEC__ + 0x7ca042a6, /* mfvrsave r5 */ + 0x39040180, /* addi r8,r4,384 */ + 0x39240190, /* addi r9,r4,400 */ + 0x70a00fff, /* andi. r0,r5,4095 */ + 0x90a40034, /* stw r5,52(r4) */ + 0x4182005c, /* beq- 2 */ + 0x7e8041ce, /* stvx v20,r0,r8 */ + 0x39080020, /* addi r8,r8,32 */ + 0x7ea049ce, /* stvx v21,r0,r9 */ + 0x39290020, /* addi r9,r9,32 */ + 0x7ec041ce, /* stvx v22,r0,r8 */ + 0x39080020, /* addi r8,r8,32 */ + 0x7ee049ce, /* stvx v23,r0,r9 */ + 0x39290020, /* addi r9,r9,32 */ + 0x7f0041ce, /* stvx v24,r0,r8 */ + 0x39080020, /* addi r8,r8,32 */ + 0x7f2049ce, /* stvx v25,r0,r9 */ + 0x39290020, /* addi r9,r9,32 */ + 0x7f4041ce, /* stvx v26,r0,r8 */ + 0x39080020, /* addi r8,r8,32 */ + 0x7f6049ce, /* stvx v27,r0,r9 */ + 0x39290020, /* addi r9,r9,32 */ + 0x7f8041ce, /* stvx v28,r0,r8 */ + 0x39080020, /* addi r8,r8,32 */ + 0x7fa049ce, /* stvx v29,r0,r9 */ + 0x39290020, /* addi r9,r9,32 */ + 0x7fc041ce, /* stvx v30,r0,r8 */ + 0x7fe049ce, /* stvx v31,r0,r9 */ + 0x80a30034, /*2:lwz r5,52(r3) */ + 0x39030180, /* addi r8,r3,384 */ + 0x39230190, /* addi r9,r3,400 */ + 0x70a00fff, /* andi. r0,r5,4095 */ + 0x7ca043a6, /* mtvrsave r5 */ + 0x4d820420, /* beqctr */ + 0x7e8040ce, /* lvx v20,r0,r8 */ + 0x39080020, /* addi r8,r8,32 */ + 0x7ea048ce, /* lvx v21,r0,r9 */ + 0x39290020, /* addi r9,r9,32 */ + 0x7ec040ce, /* lvx v22,r0,r8 */ + 0x39080020, /* addi r8,r8,32 */ + 0x7ee048ce, /* lvx v23,r0,r9 */ + 0x39290020, /* addi r9,r9,32 */ + 0x7f0040ce, /* lvx v24,r0,r8 */ + 0x39080020, /* addi r8,r8,32 */ + 0x7f2048ce, /* lvx v25,r0,r9 */ + 0x39290020, /* addi r9,r9,32 */ + 0x7f4040ce, /* lvx v26,r0,r8 */ + 0x39080020, /* addi r8,r8,32 */ + 0x7f6048ce, /* lvx v27,r0,r9 */ + 0x39290020, /* addi r9,r9,32 */ + 0x7f8040ce, /* lvx v28,r0,r8 */ + 0x39080020, /* addi r8,r8,32 */ + 0x7fa048ce, /* lvx v29,r0,r9 */ + 0x39290020, /* addi r9,r9,32 */ + 0x7fc040ce, /* lvx v30,r0,r8 */ + 0x7fe048ce, /* lvx v31,r0,r9 */ + #endif + + 0x4e800420, /* bctr */ +}; + +#if LIBCO_PPCDESC + /* function call goes through indirect descriptor */ + #define CO_SWAP_ASM(x, y) ((void (*)(cothread_t, cothread_t))(uintptr_t)x)(x, y) +#else + /* function call goes directly to code */ + #define CO_SWAP_ASM(x, y) ((void (*)(cothread_t, cothread_t))(uintptr_t)libco_ppc_code)(x, y) +#endif + +static uint32_t* co_create_(unsigned size, uintptr_t entry) { + (void)entry; + + uint32_t* t = (uint32_t*)malloc(size); + + #if LIBCO_PPCDESC + if(t) { + memcpy(t, (void*)entry, sizeof(void*) * 3); /* copy entry's descriptor */ + *(const void**)t = libco_ppc_code; /* set function pointer to swap routine */ + } + #endif + + return t; +} + +cothread_t co_create(unsigned int size, void (*entry_)(void)) { + uintptr_t entry = (uintptr_t)entry_; + uint32_t* t = 0; + + /* be sure main thread was successfully allocated */ + if(co_active()) { + size += state_size + above_stack + stack_align; + t = co_create_(size, entry); + } + + if(t) { + uintptr_t sp; + int shift; + + /* save current registers into new thread, so that any special ones will have proper values when thread is begun */ + CO_SWAP_ASM(t, t); + + #if LIBCO_PPCDESC + entry = (uintptr_t)*(void**)entry; /* get real address */ + #endif + + /* put stack near end of block, and align */ + sp = (uintptr_t)t + size - above_stack; + sp -= sp % stack_align; + + /* on PPC32, we save and restore GPRs as 32 bits. for PPC64, we + save and restore them as 64 bits, regardless of the size the ABI + uses. so, we manually write pointers at the proper size. we always + save and restore at the same address, and since PPC is big-endian, + we must put the low byte first on PPC32. */ + + /* if uintptr_t is 32 bits, >>32 is undefined behavior, + so we do two shifts and don't have to care how many bits uintptr_t is. */ + #if LIBCO_PPC64 + shift = 16; + #else + shift = 0; + #endif + + /* set up so entry will be called on next swap */ + t[ 8] = (uint32_t)(entry >> shift >> shift); + t[ 9] = (uint32_t)entry; + + t[10] = (uint32_t)(sp >> shift >> shift); + t[11] = (uint32_t)sp; + } + + return t; +} + +void co_delete(cothread_t t) { + free(t); +} + +static void co_init_(void) { + #if LIBCO_MPROTECT + long page_size = sysconf(_SC_PAGESIZE); + if(page_size > 0) { + uintptr_t align = page_size; + uintptr_t begin = (uintptr_t)libco_ppc_code; + uintptr_t end = begin + sizeof libco_ppc_code; + + /* align beginning and end */ + end += align - 1; + end -= end % align; + begin -= begin % align; + + mprotect((void*)begin, end - begin, PROT_READ | PROT_EXEC); + } + #endif + + co_active_handle = co_create_(state_size, (uintptr_t)&co_switch); +} + +cothread_t co_active() { + if(!co_active_handle) co_init_(); + + return co_active_handle; +} + +void co_switch(cothread_t t) { + cothread_t old = co_active_handle; + co_active_handle = t; + + CO_SWAP_ASM(t, old); +} diff --git a/lib/libco/settings.h b/lib/libco/settings.h new file mode 100644 index 0000000..b419683 --- /dev/null +++ b/lib/libco/settings.h @@ -0,0 +1,36 @@ +#ifdef LIBCO_C + +/*[amd64, arm, ppc, x86]: + by default, co_swap_function is marked as a text (code) section + if not supported, uncomment the below line to use mprotect instead */ +/* #define LIBCO_MPROTECT */ + +/*[amd64]: + Win64 only: provides a substantial speed-up, but will thrash XMM regs + do not use this unless you are certain your application won't use SSE */ +/* #define LIBCO_NO_SSE */ + +#ifdef LIBCO_C + #ifdef LIBCO_MP + #define thread_local __thread + #else + #define thread_local + #endif +#endif + +#if __STDC_VERSION__ >= 201112L + #ifndef _MSC_VER + #include + #endif +#else + #define alignas(bytes) +#endif + +#ifndef _MSC_VER + #define section(name) __attribute__((section("." #name "#"))) +#else + #define section(name) __declspec(allocate("." #name)) +#endif + +/* ifdef LIBCO_C */ +#endif diff --git a/lib/libco/sjlj.c b/lib/libco/sjlj.c new file mode 100644 index 0000000..dfa0aa4 --- /dev/null +++ b/lib/libco/sjlj.c @@ -0,0 +1,102 @@ +/* + libco.sjlj (2008-01-28) + author: Nach + license: public domain +*/ + +/* + note this was designed for UNIX systems. Based on ideas expressed in a paper by Ralf Engelschall. + for SJLJ on other systems, one would want to rewrite springboard() and co_create() and hack the jmb_buf stack pointer. +*/ + +#define LIBCO_C +#include "libco.h" + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + sigjmp_buf context; + void (*coentry)(void); + void* stack; +} cothread_struct; + +static thread_local cothread_struct co_primary; +static thread_local cothread_struct* creating; +static thread_local cothread_struct* co_running = 0; + +static void springboard(int ignored) { + if(sigsetjmp(creating->context, 0)) { + co_running->coentry(); + } +} + +cothread_t co_active() { + if(!co_running) co_running = &co_primary; + return (cothread_t)co_running; +} + +cothread_t co_create(unsigned int size, void (*coentry)(void)) { + if(!co_running) co_running = &co_primary; + + cothread_struct *thread = (cothread_struct*)malloc(sizeof(cothread_struct)); + if(thread) { + struct sigaction handler; + struct sigaction old_handler; + + stack_t stack; + stack_t old_stack; + + thread->coentry = thread->stack = 0; + + stack.ss_flags = 0; + stack.ss_size = size; + thread->stack = stack.ss_sp = malloc(size); + if(stack.ss_sp && !sigaltstack(&stack, &old_stack)) { + handler.sa_handler = springboard; + handler.sa_flags = SA_ONSTACK; + sigemptyset(&handler.sa_mask); + creating = thread; + + if(!sigaction(SIGUSR1, &handler, &old_handler)) { + if(!raise(SIGUSR1)) { + thread->coentry = coentry; + } + sigaltstack(&old_stack, 0); + sigaction(SIGUSR1, &old_handler, 0); + } + } + + if(thread->coentry != coentry) { + co_delete(thread); + thread = 0; + } + } + + return (cothread_t)thread; +} + +void co_delete(cothread_t cothread) { + if(cothread) { + if(((cothread_struct*)cothread)->stack) { + free(((cothread_struct*)cothread)->stack); + } + free(cothread); + } +} + +void co_switch(cothread_t cothread) { + if(!sigsetjmp(co_running->context, 0)) { + co_running = (cothread_struct*)cothread; + siglongjmp(co_running->context, 1); + } +} + +#ifdef __cplusplus +} +#endif diff --git a/lib/libco/ucontext.c b/lib/libco/ucontext.c new file mode 100644 index 0000000..72ea871 --- /dev/null +++ b/lib/libco/ucontext.c @@ -0,0 +1,69 @@ +/* + libco.ucontext (2008-01-28) + author: Nach + license: public domain +*/ + +/* + WARNING: the overhead of POSIX ucontext is very high, + assembly versions of libco or libco_sjlj should be much faster + + this library only exists for two reasons: + 1: as an initial test for the viability of a ucontext implementation + 2: to demonstrate the power and speed of libco over existing implementations, + such as pth (which defaults to wrapping ucontext on unix targets) + + use this library only as a *last resort* +*/ + +#define LIBCO_C +#include "libco.h" + +#define _BSD_SOURCE +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static thread_local ucontext_t co_primary; +static thread_local ucontext_t* co_running = 0; + +cothread_t co_active() { + if(!co_running) co_running = &co_primary; + return (cothread_t)co_running; +} + +cothread_t co_create(unsigned int heapsize, void (*coentry)(void)) { + if(!co_running) co_running = &co_primary; + ucontext_t* thread = (ucontext_t*)malloc(sizeof(ucontext_t)); + if(thread) { + if((!getcontext(thread) && !(thread->uc_stack.ss_sp = 0)) && (thread->uc_stack.ss_sp = malloc(heapsize))) { + thread->uc_link = co_running; + thread->uc_stack.ss_size = heapsize; + makecontext(thread, coentry, 0); + } else { + co_delete((cothread_t)thread); + thread = 0; + } + } + return (cothread_t)thread; +} + +void co_delete(cothread_t cothread) { + if(cothread) { + if(((ucontext_t*)cothread)->uc_stack.ss_sp) { free(((ucontext_t*)cothread)->uc_stack.ss_sp); } + free(cothread); + } +} + +void co_switch(cothread_t cothread) { + ucontext_t* old_thread = co_running; + co_running = (ucontext_t*)cothread; + swapcontext(old_thread, co_running); +} + +#ifdef __cplusplus +} +#endif diff --git a/lib/libco/x86.c b/lib/libco/x86.c new file mode 100644 index 0000000..def3ac1 --- /dev/null +++ b/lib/libco/x86.c @@ -0,0 +1,114 @@ +/* + libco.x86 (2016-09-14) + author: byuu + license: public domain +*/ + +#define LIBCO_C +#include "libco.h" +#include "settings.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__clang__) || defined(__GNUC__) + #define fastcall __attribute__((fastcall)) +#elif defined(_MSC_VER) + #define fastcall __fastcall +#else + #error "libco: please define fastcall macro" +#endif + +static thread_local long co_active_buffer[64]; +static thread_local cothread_t co_active_handle = 0; +static void (fastcall *co_swap)(cothread_t, cothread_t) = 0; + +#ifdef LIBCO_MPROTECT + alignas(4096) +#else + section(text) +#endif +/* ABI: fastcall */ +static const unsigned char co_swap_function[4096] = { + 0x89, 0x22, /* mov [edx],esp */ + 0x8b, 0x21, /* mov esp,[ecx] */ + 0x58, /* pop eax */ + 0x89, 0x6a, 0x04, /* mov [edx+ 4],ebp */ + 0x89, 0x72, 0x08, /* mov [edx+ 8],esi */ + 0x89, 0x7a, 0x0c, /* mov [edx+12],edi */ + 0x89, 0x5a, 0x10, /* mov [edx+16],ebx */ + 0x8b, 0x69, 0x04, /* mov ebp,[ecx+ 4] */ + 0x8b, 0x71, 0x08, /* mov esi,[ecx+ 8] */ + 0x8b, 0x79, 0x0c, /* mov edi,[ecx+12] */ + 0x8b, 0x59, 0x10, /* mov ebx,[ecx+16] */ + 0xff, 0xe0, /* jmp eax */ +}; + +#ifdef _WIN32 + #include + + static void co_init() { + #ifdef LIBCO_MPROTECT + DWORD old_privileges; + VirtualProtect((void*)co_swap_function, sizeof co_swap_function, PAGE_EXECUTE_READ, &old_privileges); + #endif + } +#else + #include + #include + + static void co_init() { + #ifdef LIBCO_MPROTECT + unsigned long addr = (unsigned long)co_swap_function; + unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE)); + unsigned long size = (addr - base) + sizeof co_swap_function; + mprotect((void*)base, size, PROT_READ | PROT_EXEC); + #endif + } +#endif + +static void crash() { + assert(0); /* called only if cothread_t entrypoint returns */ +} + +cothread_t co_active() { + if(!co_active_handle) co_active_handle = &co_active_buffer; + return co_active_handle; +} + +cothread_t co_create(unsigned int size, void (*entrypoint)(void)) { + cothread_t handle; + if(!co_swap) { + co_init(); + co_swap = (void (fastcall*)(cothread_t, cothread_t))co_swap_function; + } + if(!co_active_handle) co_active_handle = &co_active_buffer; + size += 256; /* allocate additional space for storage */ + size &= ~15; /* align stack to 16-byte boundary */ + + if(handle = (cothread_t)malloc(size)) { + long *p = (long*)((char*)handle + size); /* seek to top of stack */ + *--p = (long)crash; /* crash if entrypoint returns */ + *--p = (long)entrypoint; /* start of function */ + *(long*)handle = (long)p; /* stack pointer */ + } + + return handle; +} + +void co_delete(cothread_t handle) { + free(handle); +} + +void co_switch(cothread_t handle) { + register cothread_t co_previous_handle = co_active_handle; + co_swap(co_active_handle = handle, co_previous_handle); +} + +#ifdef __cplusplus +} +#endif diff --git a/main.cpp b/main.cpp index d0b0ca7..4978076 100644 --- a/main.cpp +++ b/main.cpp @@ -30,27 +30,19 @@ along with this program. If not, see . #include "user_io.h" #include "input.h" #include "fpga_io.h" +#include "scheduler.h" const char *version = "$VER:HPS" VDATE; int main(int argc, char *argv[]) { - /* - //placeholder for CPU1 dedicated process - if (!fork()) - { - cpu_set_t set; - CPU_ZERO(&set); - CPU_SET(1, &set); - sched_setaffinity(0, sizeof(set), &set); - - while (1) - { - sleep(2); - printf("Tick\n"); - } - } - */ + // Always pin main worker process to core #1 as core #0 is the + // hardware interrupt handler in Linux. This reduces idle latency + // in the main loop by about 6-7x. + cpu_set_t set; + CPU_ZERO(&set); + CPU_SET(1, &set); + sched_setaffinity(0, sizeof(set), &set); fpga_io_init(); fpga_gpo_write(0); @@ -75,26 +67,8 @@ int main(int argc, char *argv[]) FindStorage(); user_io_init((argc > 1) ? argv[1] : ""); - while(1) - { - if(!is_fpga_ready(1)) - { - printf("FPGA is not ready. JTAG uploading?\n"); - printf("Waiting for FPGA to be ready...\n"); + scheduler_init(); + scheduler_run(); - //enable reset in advance - fpga_core_reset(1); - - while (!is_fpga_ready(0)) - { - sleep(1); - } - reboot(0); - } - - user_io_poll(); - input_poll(0); - HandleUI(); - } return 0; } diff --git a/menu.cpp b/menu.cpp index 92e8c92..9cf8c1b 100644 --- a/menu.cpp +++ b/menu.cpp @@ -1624,11 +1624,11 @@ void HandleUI(void) case MENU_JOYDIGMAP: helptext = 0; menumask = 1; - OsdSetTitle("Joystick", 0); + OsdSetTitle("Define buttons", 0); menustate = MENU_JOYDIGMAP1; parentstate = MENU_JOYDIGMAP; for (int i = 0; i < OsdGetSize() - 1; i++) OsdWrite(i, "", 0, 0); - OsdWrite(OsdGetSize() - 1, " Cancel", menusub == 0, 0); + OsdWrite(OsdGetSize() - 1, " ESC \x16 Cancel", menusub == 0, 0); break; case MENU_JOYDIGMAP1: @@ -1660,7 +1660,7 @@ void HandleUI(void) OsdWrite(3, s, 0, 0); if (get_map_button()) { - if (get_map_type()) OsdWrite(OsdGetSize() - 1, " finish (SPACE - skip)", menusub == 0, 0); + if (get_map_type()) OsdWrite(OsdGetSize() - 1, " Enter \x16 Finish, Space \x16 Skip", menusub == 0, 0); else OsdWrite(OsdGetSize() - 1, "", 0, 0); sprintf(s, " %s ID: %04x:%04x", get_map_type() ? "Joystick" : "Keyboard", get_map_vid(), get_map_pid()); @@ -3450,6 +3450,16 @@ void HandleUI(void) } } +void open_joystick_setup() +{ + OsdSetSize(16); + menusub = 0; + OsdClear(); + OsdEnable(DISABLE_KEYBOARD); + start_map_setting(joy_bcount ? joy_bcount + 4 : 8); + menustate = MENU_JOYDIGMAP; +} + void ScrollLongName(void) { // this function is called periodically when file selection window is displayed diff --git a/menu.h b/menu.h index 3705abe..d271d3e 100644 --- a/menu.h +++ b/menu.h @@ -1,6 +1,8 @@ #ifndef MENU_H #define MENU_H +#include + // UI strings, used by boot messages extern const char *config_memory_chip_msg[]; extern const char *config_memory_slow_msg[]; @@ -24,4 +26,6 @@ void substrcpy(char *d, char *s, char idx); extern char joy_bnames[12][32]; extern int joy_bcount; +void open_joystick_setup(); + #endif diff --git a/releases/MiSTer_20190108 b/releases/MiSTer_20190108 new file mode 100644 index 0000000..21961e7 Binary files /dev/null and b/releases/MiSTer_20190108 differ diff --git a/scheduler.cpp b/scheduler.cpp new file mode 100644 index 0000000..e504126 --- /dev/null +++ b/scheduler.cpp @@ -0,0 +1,94 @@ +#include "scheduler.h" +#include +#include "libco.h" +#include "menu.h" +#include "user_io.h" +#include "input.h" +#include "fpga_io.h" + +static cothread_t co_scheduler = nullptr; +static cothread_t co_poll = nullptr; +static cothread_t co_ui = nullptr; +static cothread_t co_last = nullptr; + +static void scheduler_wait_fpga_ready(void) +{ + while (!is_fpga_ready(1)) + { + printf("FPGA is not ready. JTAG uploading?\n"); + printf("Waiting for FPGA to be ready...\n"); + + //enable reset in advance + fpga_core_reset(1); + + while (!is_fpga_ready(0)) + { + sleep(1); + } + reboot(0); + } +} + +static void scheduler_co_poll(void) +{ + for (;;) + { + scheduler_wait_fpga_ready(); + + user_io_poll(); + input_poll(0); + + scheduler_yield(); + } +} + +static void scheduler_co_ui(void) +{ + for (;;) + { + HandleUI(); + + scheduler_yield(); + } +} + +static void scheduler_schedule(void) +{ + if (co_last == co_poll) + { + co_last = co_ui; + co_switch(co_ui); + } + else + { + co_last = co_poll; + co_switch(co_poll); + } +} + +void scheduler_init(void) +{ + const unsigned int co_stack_size = 262144 * sizeof(void*); + + co_poll = co_create(co_stack_size, scheduler_co_poll); + co_ui = co_create(co_stack_size, scheduler_co_ui); +} + +void scheduler_run(void) +{ + co_scheduler = co_active(); + + for (;;) + { + scheduler_schedule(); + } + + co_delete(co_ui); + co_delete(co_poll); + co_delete(co_scheduler); +} + +void scheduler_yield(void) +{ + co_switch(co_scheduler); +} diff --git a/scheduler.h b/scheduler.h new file mode 100644 index 0000000..15207fb --- /dev/null +++ b/scheduler.h @@ -0,0 +1,8 @@ +#ifndef SCHEDULER_H +#define SCHEDULER_H + +void scheduler_init(void); +void scheduler_run(void); +void scheduler_yield(void); + +#endif diff --git a/support/archie/archie.cpp b/support/archie/archie.cpp index 1431918..f338e00 100644 --- a/support/archie/archie.cpp +++ b/support/archie/archie.cpp @@ -19,7 +19,7 @@ typedef struct static archie_config_t config; -fileTYPE floppy[MAX_FLOPPY] = { 0 }; +fileTYPE floppy[MAX_FLOPPY] = {}; #define ARCHIE_FILE_TX 0x53 #define ARCHIE_FILE_TX_DAT 0x54 @@ -83,7 +83,7 @@ const char *archie_get_rom_name(void) return p; } -const char *archie_get_floppy_name(char i) +const char *archie_get_floppy_name(int i) { if (!floppy[i].size) return "* no disk *"; @@ -125,7 +125,7 @@ void archie_send_file(unsigned char id, char *name) { archie_debugf("Sending file with id %d", id); - fileTYPE file = { 0 }; + fileTYPE file = {}; if (!FileOpen(&file, name)) return; // prepare transmission of new file @@ -184,7 +184,7 @@ void archie_fdc_set_status(void) DisableFpga(); } -void archie_set_floppy(char i, char *name) +void archie_set_floppy(int i, char *name) { if (!name) { @@ -202,7 +202,7 @@ void archie_set_floppy(char i, char *name) archie_fdc_set_status(); } -char archie_floppy_is_inserted(char i) +char archie_floppy_is_inserted(int i) { return(floppy[i].size != 0); } @@ -264,7 +264,7 @@ static void archie_kbd_reset(void) void archie_init(void) { - char i; + int i; archie_debugf("init"); @@ -301,7 +301,7 @@ void archie_init(void) char fdc_name[] = "Archie/FLOPPY0.ADF"; fdc_name[13] = '0' + i; if (FileOpen(&floppy[i], fdc_name)) - archie_debugf("Inserted floppy %d with %d bytes", i, floppy[i].size); + archie_debugf("Inserted floppy %d with %llu bytes", i, floppy[i].size); else floppy[i].size = 0; } diff --git a/support/archie/archie.h b/support/archie/archie.h index 1f743b3..ddee96e 100644 --- a/support/archie/archie.h +++ b/support/archie/archie.h @@ -8,10 +8,10 @@ void archie_poll(void); void archie_kbd(unsigned short code); void archie_mouse(unsigned char b, int16_t x, int16_t y); const char *archie_get_rom_name(void); -const char *archie_get_floppy_name(char b); +const char *archie_get_floppy_name(int b); void archie_set_rom(char *); -void archie_set_floppy(char i, char *); -char archie_floppy_is_inserted(char i); +void archie_set_floppy(int i, char *); +char archie_floppy_is_inserted(int i); void archie_save_config(void); void archie_set_ar(char i); diff --git a/support/minimig/minimig_boot.cpp b/support/minimig/minimig_boot.cpp index 5b7f3fb..4ef3d01 100644 --- a/support/minimig/minimig_boot.cpp +++ b/support/minimig/minimig_boot.cpp @@ -169,7 +169,7 @@ static void BootClearScreen(int adr, int size) static void BootUploadLogo() { - fileTYPE file = { 0 }; + fileTYPE file = {}; int x, y; int i = 0; int adr; @@ -228,7 +228,7 @@ static void BootUploadLogo() static void BootUploadBall() { - fileTYPE file = { 0 }; + fileTYPE file = {}; int x; int i = 0; int adr; @@ -258,7 +258,7 @@ static void BootUploadBall() static void BootUploadCopper() { - fileTYPE file = { 0 }; + fileTYPE file = {}; int x; int i = 0; int adr; diff --git a/support/minimig/minimig_config.cpp b/support/minimig/minimig_config.cpp index 344e525..af8c11d 100644 --- a/support/minimig/minimig_config.cpp +++ b/support/minimig/minimig_config.cpp @@ -35,7 +35,7 @@ typedef struct unsigned char autofire; } configTYPE_old; -configTYPE config = { 0 }; +configTYPE config = { }; unsigned char romkey[3072]; static void SendFileV2(fileTYPE* file, unsigned char* key, int keysize, int address, int size) @@ -61,7 +61,7 @@ static void SendFileV2(fileTYPE* file, unsigned char* key, int keysize, int addr for (int j = 0; j<512; j++) { buf[j] ^= key[keyidx++]; - if (keyidx >= keysize) keyidx -= keysize; + if ((int)keyidx >= keysize) keyidx -= keysize; } } EnableOsd(); @@ -86,7 +86,7 @@ static void SendFileV2(fileTYPE* file, unsigned char* key, int keysize, int addr static char UploadKickstart(char *name) { - fileTYPE file = { 0 }; + fileTYPE file = {}; int keysize = 0; BootPrint("Checking for Amiga Forever key file:"); @@ -168,7 +168,7 @@ static char UploadKickstart(char *name) static char UploadActionReplay() { - fileTYPE file = { 0 }; + fileTYPE file = {}; if(FileOpen(&file, "Amiga/HRTMON.ROM") || FileOpen(&file, "HRTMON.ROM")) { int adr, data; @@ -378,7 +378,6 @@ unsigned char LoadConfiguration(int num) static const char config_id[] = "MNMGCFG0"; char updatekickstart = 0; char result = 0; - unsigned char key, i; const char *filename = GetConfigurationName(num); @@ -387,7 +386,7 @@ unsigned char LoadConfiguration(int num) if(filename && (size = FileLoadConfig(filename, 0, 0))>0) { BootPrint("Opened configuration file\n"); - printf("Configuration file size: %s, %lu\n", filename, size); + printf("Configuration file size: %s, %d\n", filename, size); if (size == sizeof(config)) { static configTYPE tmpconf; @@ -439,7 +438,7 @@ unsigned char LoadConfiguration(int num) } else printf("Cannot load configuration file\n"); } - else printf("Wrong configuration file size: %lu (expected: %lu)\n", size, sizeof(config)); + else printf("Wrong configuration file size: %d (expected: %u)\n", size, sizeof(config)); } if (!result) { BootPrint("Can not open configuration file!\n"); @@ -502,7 +501,7 @@ void MinimigReset() void SetKickstart(char *name) { - int len = strlen(name); + uint len = strlen(name); if (len > (sizeof(config.kickstart) - 1)) len = sizeof(config.kickstart) - 1; memcpy(config.kickstart, name, len); config.kickstart[len] = 0; diff --git a/support/minimig/minimig_fdd.cpp b/support/minimig/minimig_fdd.cpp index 22f0f08..98aa48e 100644 --- a/support/minimig/minimig_fdd.cpp +++ b/support/minimig/minimig_fdd.cpp @@ -35,7 +35,7 @@ along with this program. If not, see . unsigned char drives = 0; // number of active drives reported by FPGA (may change only during reset) adfTYPE *pdfx; // drive select pointer -adfTYPE df[4] = { 0 }; // drive information structure +adfTYPE df[4] = {}; // drive information structure static uint8_t sector_buffer[512]; @@ -71,13 +71,13 @@ void SendSector(unsigned char *pData, unsigned char sector, unsigned char track, // odd bits of header x = 0x55; checksum[0] = x; - y = track >> 1 & 0x55; + y = (track >> 1) & 0x55; checksum[1] = y; spi_w(B2W(x,y)); - x = sector >> 1 & 0x55; + x = (sector >> 1) & 0x55; checksum[2] = x; - y = 11 - sector >> 1 & 0x55; + y = ((11 - sector) >> 1) & 0x55; checksum[3] = y; spi_w(B2W(x, y)); @@ -90,7 +90,7 @@ void SendSector(unsigned char *pData, unsigned char sector, unsigned char track, x = sector & 0x55; checksum[2] ^= x; - y = 11 - sector & 0x55; + y = (11 - sector) & 0x55; checksum[3] ^= y; spi_w(B2W(x, y)); @@ -135,8 +135,8 @@ void SendSector(unsigned char *pData, unsigned char sector, unsigned char track, p = pData; while (i--) { - x = *p++ >> 1 | 0xAA; - y = *p++ >> 1 | 0xAA; + x = (*p++ >> 1) | 0xAA; + y = (*p++ >> 1) | 0xAA; spi_w(B2W(x, y)); } @@ -166,7 +166,7 @@ void ReadTrack(adfTYPE *drive) unsigned char status; unsigned char track; unsigned short dsksync; - unsigned short dsklen; + //unsigned short dsklen; uint16_t tmp; //unsigned short n; @@ -201,7 +201,7 @@ void ReadTrack(adfTYPE *drive) status = (uint8_t)(tmp>>8); // read request signal track = (uint8_t)tmp; // track number (cylinder & head) dsksync = spi_w(0); // disk sync - dsklen = spi_w(0) & 0x3FFF; // mfm words to transfer + //dsklen = spi_w(0) & 0x3FFF; // mfm words to transfer DisableFpga(); if (track >= drive->tracks) @@ -218,7 +218,7 @@ void ReadTrack(adfTYPE *drive) status = (uint8_t)(tmp >> 8); // read request signal track = (uint8_t)tmp; // track number (cylinder & head) dsksync = spi_w(0); // disk sync - dsklen = spi_w(0) & 0x3FFF; // mfm words to transfer + //dsklen = spi_w(0) & 0x3FFF; // mfm words to transfer if (track >= drive->tracks) track = drive->tracks - 1; @@ -281,7 +281,7 @@ void ReadTrack(adfTYPE *drive) unsigned char FindSync(adfTYPE *drive) // reads data from fifo till it finds sync word or fifo is empty and dma inactive (so no more data is expected) { - unsigned char c1, c2, c3, c4; + unsigned char c1, c2; unsigned short n; uint16_t tmp; @@ -641,7 +641,6 @@ void InsertFloppy(adfTYPE *drive, char* path) return; } - unsigned char i, j; unsigned long tracks; // calculate number of tracks in the ADF image file diff --git a/support/minimig/minimig_hdd.cpp b/support/minimig/minimig_hdd.cpp index 004dfdd..27a1105 100644 --- a/support/minimig/minimig_hdd.cpp +++ b/support/minimig/minimig_hdd.cpp @@ -81,12 +81,12 @@ typedef struct uint16_t sector_count; } hdfTYPE; -static hdfTYPE HDF[4] = { 0 }; +static hdfTYPE HDF[4] = {}; static uint8_t sector_buffer[512]; static void CalcGeometry(hdfTYPE *hdf) { - uint32_t head, cyl, spt; + uint32_t head = 0, cyl = 0, spt = 0; uint32_t sptt[] = { 63, 127, 255, 0 }; uint32_t total = hdf->file.size / 512; for (int i = 0; sptt[i] != 0; i++) @@ -205,7 +205,6 @@ static uint32_t RDBChecksum(uint32_t *p, int set) // if the HDF file doesn't have a RigidDiskBlock, we synthesize one static void FakeRDB(hdfTYPE *hdf) { - int i; // start by clearing the sector buffer memset(sector_buffer, 0, 512); @@ -285,7 +284,8 @@ static void FakeRDB(hdfTYPE *hdf) // builds Identify Device struct static void IdentifyDevice(uint16_t *pBuffer, hdfTYPE *hdf) { - char *p, i, x; + char *p, x; + int i; uint32_t total_sectors = hdf->cylinders * hdf->heads * hdf->sectors; memset(pBuffer, 0, 512); @@ -368,6 +368,7 @@ static void WriteStatus(uint8_t status) static void ATA_Recalibrate(uint8_t* tfr, hdfTYPE *hdf) { // Recalibrate 0x10-0x1F (class 3 command: no data) + (void)hdf; hdd_debugf("IDE%d: Recalibrate", hdf->unit); WriteTaskFile(0, 0, tfr[6] & 0x40 ? 0 : 1, 0, 0, tfr[6] & 0xF0); WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ); @@ -376,6 +377,8 @@ static void ATA_Recalibrate(uint8_t* tfr, hdfTYPE *hdf) static void ATA_Diagnostic(uint8_t* tfr, hdfTYPE *hdf) { // Execute Drive Diagnostic (0x90) + (void)hdf; + (void)tfr; hdd_debugf("IDE: Drive Diagnostic"); WriteTaskFile(1, 0, 0, 0, 0, 0); WriteStatus(IDE_STATUS_END | IDE_STATUS_IRQ); @@ -383,7 +386,6 @@ static void ATA_Diagnostic(uint8_t* tfr, hdfTYPE *hdf) static void ATA_IdentifyDevice(uint8_t* tfr, hdfTYPE *hdf) { - int i; // Identify Device (0xec) hdd_debugf("IDE%d: Identify Device", hdf->unit); IdentifyDevice((uint16_t*)sector_buffer, hdf); @@ -401,6 +403,7 @@ static void ATA_IdentifyDevice(uint8_t* tfr, hdfTYPE *hdf) static void ATA_Initialize(uint8_t* tfr, hdfTYPE *hdf) { // Initialize Device Parameters (0x91) + (void)hdf; hdd_debugf("Initialize Device Parameters"); hdd_debugf("IDE%d: %02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X", hdf->unit, tfr[0], tfr[1], tfr[2], tfr[3], tfr[4], tfr[5], tfr[6], tfr[7]); WriteTaskFile(0, tfr[2], tfr[3], tfr[4], tfr[5], tfr[6]); @@ -535,7 +538,7 @@ static void WriteSector(hdfTYPE *hdf) else { GetRDBGeometry(hdf); - printf("Using new CHS: %u/%u/%u (%lu MB)\n", hdf->cylinders, hdf->heads, hdf->sectors, ((((uint32_t)hdf->cylinders) * hdf->heads * hdf->sectors) >> 11)); + printf("Using new CHS: %u/%u/%u (%llu MB)\n", hdf->cylinders, hdf->heads, hdf->sectors, ((((uint64_t)hdf->cylinders) * hdf->heads * hdf->sectors) >> 11)); } } FileWriteSec(&hdf->file, sector_buffer); @@ -660,6 +663,8 @@ static void ATA_WriteMultiple(uint8_t* tfr, hdfTYPE *hdf) void HandleHDD(uint8_t c1, uint8_t c2) { + (void)c2; + if (c1 & CMD_IDECMD) { uint8_t unit = 0; @@ -727,7 +732,7 @@ uint8_t OpenHardfile(uint8_t unit) SetHardfileGeometry(hdf, !strcasecmp(".hdf", config.hardfile[unit].filename + strlen(config.hardfile[unit].filename) - 4)); printf("size: %llu (%llu MB)\n", hdf->file.size, hdf->file.size >> 20); printf("CHS: %u/%u/%u", hdf->cylinders, hdf->heads, hdf->sectors); - printf(" (%lu MB), ", ((((uint32_t)hdf->cylinders) * hdf->heads * hdf->sectors) >> 11)); + printf(" (%llu MB), ", ((((uint64_t)hdf->cylinders) * hdf->heads * hdf->sectors) >> 11)); printf("Offset: %d\n", hdf->offset); return 1; } @@ -742,7 +747,7 @@ uint8_t OpenHardfile(uint8_t unit) int checkHDF(const char* name, struct RigidDiskBlock **rdb) { - fileTYPE file = { 0 }; + fileTYPE file = {}; *rdb = NULL; if (FileOpenEx(&file, name, O_RDONLY)) diff --git a/support/sharpmz/sharpmz.cpp b/support/sharpmz/sharpmz.cpp index b735b6a..1568bc5 100644 --- a/support/sharpmz/sharpmz.cpp +++ b/support/sharpmz/sharpmz.cpp @@ -253,7 +253,7 @@ int sharpmz_reload_config(short setStatus) // void sharpmz_init(void) { - char i; + int i; sharpmz_debugf("Sharp MZ Series Initialisation"); @@ -1253,7 +1253,7 @@ void sharpmz_set_fdc_rom_enabled(short machineModel, short on, short setStatus) // short sharpmz_get_custom_rom_enabled(short machineModel, short romType) { - short romEnabled; + short romEnabled = 0; machineModel &= 0x07; romType &= 0x07; @@ -1492,7 +1492,7 @@ void sharpmz_send_file(romData_t &image, char *dirPrefix) unsigned int actualReadSize; unsigned long time = GetTimer(0); unsigned short i; - fileTYPE file = { 0 }; + fileTYPE file = {}; // If a prefix is given (ie. core directory), prepend it before use. // @@ -1528,7 +1528,7 @@ void sharpmz_send_file(romData_t &image, char *dirPrefix) sharpmz_debugf("["); for (i = 0; i < image.loadSize; i += actualReadSize) { - if (!(i & 127)) sharpmz_debugf("*"); + if (!(i & 127)) { sharpmz_debugf("*"); } // Work out size of data block to read. int readSize = (image.loadSize - i >= 512 ? 512 : image.loadSize - i); @@ -1574,7 +1574,7 @@ void sharpmz_send_file(romData_t &image, char *dirPrefix) short sharpmz_read_ram(const char *memDumpFile, short bank) { unsigned int actualWriteSize; - fileTYPE file = { 0 }; + fileTYPE file = {}; // Open the memory image debug file for writing. if (!sharpmz_file_write(&file, memDumpFile)) @@ -1585,7 +1585,7 @@ short sharpmz_read_ram(const char *memDumpFile, short bank) // Depending on the bank, or all banks, loop until request is complete. // - for(unsigned int mb=(bank == SHARPMZ_MEMBANK_ALL ? 0 : bank); mb <= (bank == SHARPMZ_MEMBANK_ALL ? SHARPMZ_MEMBANK_MAXBANKS-1 : bank); mb++) + for(unsigned int mb=(bank == SHARPMZ_MEMBANK_ALL ? 0 : bank); mb <= (uint)(bank == SHARPMZ_MEMBANK_ALL ? SHARPMZ_MEMBANK_MAXBANKS-1 : bank); mb++) { // Skip bank 1, as SYSROM spans two physical banks 0 and 1. if(mb == 1) mb = SHARPMZ_MEMBANK_SYSRAM; @@ -1603,7 +1603,7 @@ short sharpmz_read_ram(const char *memDumpFile, short bank) sharpmz_debugf("["); for (unsigned long j = 0; j < MZBANKSIZE[mb] or actualWriteSize == 0; j += actualWriteSize) { - if (!(j & 127)) sharpmz_debugf("*"); + if (!(j & 127)) { sharpmz_debugf("*"); } spi_read(sector_buffer, 512, 0); @@ -1637,7 +1637,7 @@ short sharpmz_read_tape_header(const char *tapeFile) // Handle for the MZF file to be processed. // - fileTYPE file = { 0 }; + fileTYPE file = {}; // Try and open the tape file, exit if it cannot be opened. // @@ -1668,13 +1668,13 @@ short sharpmz_load_tape_to_ram(const char *tapeFile, unsigned char dstCMT) { unsigned int actualReadSize; unsigned long time = GetTimer(0); - char fileName[17]; + //char fileName[17]; //sharpmz_debugf("Sending tape file:%s to emulator ram", tapeFile); // Handle for the MZF file to be processed. // - fileTYPE file = { 0 }; + fileTYPE file = {}; // Try and open the tape file, exit if it cannot be opened. // @@ -1692,10 +1692,12 @@ short sharpmz_load_tape_to_ram(const char *tapeFile, unsigned char dstCMT) // Some sanity checks. // if(tapeHeader.dataType == 0 || tapeHeader.dataType > 5) return(4); + /* for(int i=0; i < 17; i++) { fileName[i] = tapeHeader.fileName[i] == 0x0d ? 0x00 : tapeHeader.fileName[i]; } + */ // Debug output to indicate the file loaded and information about the tape image. // @@ -1756,7 +1758,7 @@ short sharpmz_load_tape_to_ram(const char *tapeFile, unsigned char dstCMT) sharpmz_debugf("["); for (unsigned short i = 0; i < tapeHeader.fileSize; i += actualReadSize) { - if (!(i & 127)) sharpmz_debugf("*"); + if (!(i & 127)) { sharpmz_debugf("*"); } DISKLED_ON; actualReadSize = sharpmz_file_read(&file, sector_buffer, 512); @@ -1865,7 +1867,7 @@ short sharpmz_save_tape_from_cmt(const char *tapeFile) // Handle for the MZF file to be written. // - fileTYPE file = { 0 }; + fileTYPE file = {}; // Read the header, then data, but limit data size to the 'file size' stored in the header. // @@ -1946,6 +1948,7 @@ short sharpmz_save_tape_from_cmt(const char *tapeFile) void sharpmz_select_file(const char* pFileExt, unsigned char Options, char *fs_pFileExt, char chdir, char *SelectedPath) { sharpmz_debugf("pFileExt = %s\n", pFileExt); + (void)chdir; if (strncasecmp(SHARPMZ_CORE_NAME, SelectedPath, strlen(SHARPMZ_CORE_NAME))) strcpy(SelectedPath, SHARPMZ_CORE_NAME); @@ -1991,17 +1994,19 @@ void sharpmz_ui(int idleState, int idle2State, int system static short scrollPos = 0; static short volumeDir = 0; int menuItem; - int subItem; + uint32_t subItem; short romEnabled; short itemCount; char sBuf[40]; char *fileName; + (void)plus; + (void)minus; // Idle2 state (MENU_NONE2) is our main hook, when the HandleUI state machine reaches this state, if the menu key is pressed, // we takeover control in this method. // - if(*menustate == idle2State && menu) + if(*menustate == (uint32_t)idle2State && menu) { OsdSetSize(16); *menusub = 0; diff --git a/support/st/st_ikbd.cpp b/support/st/st_ikbd.cpp index 2ad1f68..ce81c86 100644 --- a/support/st/st_ikbd.cpp +++ b/support/st/st_ikbd.cpp @@ -375,10 +375,11 @@ void ikbd_reset(void) { // process inout from atari core into ikbd void ikbd_handle_input(unsigned char cmd) { // store byte in buffer - ikbd.buffer.byte[ikbd.buffer.size++] = cmd; + unsigned char *byte = ikbd.buffer.byte; + byte[(int)(ikbd.buffer.size++)] = cmd; // check if there's a known command in the buffer - char c; + int c; for (c = 0; ikbd_command_handler[c].length && (ikbd_command_handler[c].code != ikbd.buffer.command.code); c++); @@ -445,7 +446,7 @@ static void ikbd_update_time() void ikbd_poll(void) { #ifdef IKBD_DEBUG static unsigned long xtimer = 0; - static int last_cnt = 0; + static unsigned int last_cnt = 0; if (CheckTimer(xtimer)) { xtimer = GetTimer(2000); if (ikbd.tx_cnt != last_cnt) { @@ -469,7 +470,7 @@ void ikbd_poll(void) { /* --------- joystick ---------- */ if (ikbd.state & IKBD_STATE_JOYSTICK_EVENT_REPORTING) { - char i; + int i; for (i = 0; i<2; i++) { unsigned char state = ikbd.joy[i].state; @@ -599,7 +600,7 @@ void ikbd_keyboard(unsigned char code) { enqueue(code); } -void ikbd_mouse(unsigned char b, char x, char y) { +void ikbd_mouse(unsigned char b, signed char x, signed char y) { // honour reversal of y axis if (ikbd.state & IKBD_STATE_MOUSE_Y_BOTTOM) diff --git a/support/st/st_ikbd.h b/support/st/st_ikbd.h index dcd0cdf..8c1391d 100644 --- a/support/st/st_ikbd.h +++ b/support/st/st_ikbd.h @@ -5,7 +5,7 @@ void ikbd_init(void); void ikbd_poll(void); void ikbd_reset(void); void ikbd_joystick(unsigned char joy, unsigned char map); -void ikbd_mouse(unsigned char buttons, char x, char y); +void ikbd_mouse(unsigned char buttons, signed char x, signed char y); void ikbd_keyboard(unsigned char code); #endif // IKBD_H diff --git a/support/st/st_tos.cpp b/support/st/st_tos.cpp index c0c5ea4..1d9ba66 100644 --- a/support/st/st_tos.cpp +++ b/support/st/st_tos.cpp @@ -36,10 +36,10 @@ static struct { fileTYPE file; unsigned char sides; unsigned char spt; -} fdd_image[2] = { 0 }; +} fdd_image[2] = {}; // one harddisk -fileTYPE hdd_image[2] = { 0 }; +fileTYPE hdd_image[2] = {}; unsigned long hdd_direct = 0; static unsigned char dma_buffer[512]; @@ -66,7 +66,7 @@ static const char *acsi_cmd_name(int cmd) { return cmdname[cmd]; } -void tos_set_video_adjust(char axis, char value) { +void tos_set_video_adjust(int axis, char value) { config.video_adjust[axis] += value; EnableFpga(); @@ -76,7 +76,7 @@ void tos_set_video_adjust(char axis, char value) { DisableFpga(); } -char tos_get_video_adjust(char axis) { +char tos_get_video_adjust(int axis) { return config.video_adjust[axis]; } @@ -105,6 +105,7 @@ static void mist_set_control(unsigned long ctrl) { DisableFpga(); } +/* static void mist_memory_read(char *data, unsigned long words) { EnableFpga(); spi8(MIST_READ_MEMORY); @@ -117,6 +118,7 @@ static void mist_memory_read(char *data, unsigned long words) { DisableFpga(); } +*/ static void mist_memory_write(unsigned char *data, unsigned long words) { EnableFpga(); @@ -162,6 +164,7 @@ void mist_memory_set(char data, unsigned long words) { // enable direct sd card access on acsi0 void tos_set_direct_hdd(char on) { + (void)on; config.sd_direct = 0; tos_debugf("ACSI: disable direct sd access"); @@ -208,12 +211,12 @@ static void handle_acsi(unsigned char *buffer) { if (length == 0) length = 256; if (user_io_dip_switch1()) { - tos_debugf("ACSI: target %d.%d, \"%s\" (%02x)", target, device, acsi_cmd_name(cmd), cmd); + tos_debugf("ACSI: target %u.%u, \"%s\" (%02x)", target, device, acsi_cmd_name(cmd), cmd); tos_debugf("ACSI: lba %lu (%lx), length %u", lba, lba, length); - tos_debugf("DMA: scnt %u, addr %p", scnt, dma_address); + tos_debugf("DMA: scnt %u, addr %X", scnt, dma_address); if (buffer[20] == 0xa5) { - tos_debugf("DMA: fifo %d/%d %x %s", + tos_debugf("DMA: fifo %u/%u %x %s", (buffer[21] >> 4) & 0x0f, buffer[21] & 0x0f, buffer[22], (buffer[2] & 1) ? "OUT" : "IN"); tos_debugf("DMA stat=%x, mode=%x, fdc_irq=%d, acsi_irq=%d", @@ -308,7 +311,7 @@ static void handle_acsi(unsigned char *buffer) { asc[target] = 0x00; } else { - tos_debugf("ACSI: read (%d+%d) exceeds device limits (%d)", + tos_debugf("ACSI: read (%lu+%u) exceeds device limits (%lu)", lba, length, blocks); dma_ack(0x02); asc[target] = 0x21; @@ -348,7 +351,7 @@ static void handle_acsi(unsigned char *buffer) { asc[target] = 0x00; } else { - tos_debugf("ACSI: write (%d+%d) exceeds device limits (%d)", + tos_debugf("ACSI: write (%lu+%u) exceeds device limits (%lu)", lba, length, blocks); dma_ack(0x02); asc[target] = 0x21; @@ -380,7 +383,7 @@ static void handle_acsi(unsigned char *buffer) { case 0x1a: // mode sense if (device == 0) { - tos_debugf("ACSI: mode sense, blocks = %u", blocks); + tos_debugf("ACSI: mode sense, blocks = %lu", blocks); bzero(dma_buffer, 512); dma_buffer[3] = 8; // size of extent descriptor list dma_buffer[5] = blocks >> 16; @@ -430,7 +433,7 @@ static void handle_fdc(unsigned char *buffer) { unsigned char fdc_cmd = buffer[4]; unsigned char fdc_track = buffer[5]; unsigned char fdc_sector = buffer[6]; - unsigned char fdc_data = buffer[7]; + //unsigned char fdc_data = buffer[7]; unsigned char drv_sel = 3 - ((buffer[8] >> 2) & 3); unsigned char drv_side = 1 - ((buffer[8] >> 1) & 1); @@ -450,7 +453,7 @@ static void handle_fdc(unsigned char *buffer) { offset += fdc_sector - 1; if (user_io_dip_switch1()) { - tos_debugf("FDC %s req %d sec (%c, SD:%d, T:%d, S:%d = %d) -> %p", + tos_debugf("FDC %s req %d sec (%c, SD:%d, T:%d, S:%d = %d) -> %X", (fdc_cmd & 0x10) ? "multi" : "single", scnt, 'A' + drv_sel - 1, drv_side, fdc_track, fdc_sector, offset, dma_address); @@ -534,6 +537,7 @@ static void mist_get_dmastate() { #define PLANES 4 static void tos_write(const char *str); +/* static void tos_color_test() { unsigned short buffer[COLORS][PLANES]; @@ -569,6 +573,7 @@ static void tos_color_test() { // for(;;); #endif } +*/ static void tos_write(const char *str) { static int y = 0; @@ -614,7 +619,7 @@ static void tos_clr() { extern unsigned char charfont[256][8]; static void tos_font_load() { - fileTYPE file = { 0 }; + fileTYPE file = {}; if (FileOpen(&file, "SYSTEM.FNT")) { if (file.size == 4096) { int i; @@ -648,7 +653,7 @@ static void tos_font_load() { void tos_load_cartridge(const char *name) { - fileTYPE file = { 0 }; + fileTYPE file = {}; if (name) strncpy(config.cart_img, name, 11); @@ -658,7 +663,7 @@ void tos_load_cartridge(const char *name) int i; unsigned char buffer[512]; - tos_debugf("%s:\n size = %d", config.cart_img, file.size); + tos_debugf("%s:\n size = %llu", config.cart_img, file.size); int blocks = file.size / 512; tos_debugf(" blocks = %d", blocks); @@ -697,7 +702,7 @@ char tos_cartridge_is_inserted() { void tos_upload(const char *name) { - fileTYPE file = { 0 }; + fileTYPE file = {}; // set video offset in fpga tos_set_video_adjust(0, 0); @@ -727,7 +732,7 @@ void tos_upload(const char *name) unsigned long time; unsigned long tos_base = TOS_BASE_ADDRESS_192k; - tos_debugf("TOS.IMG:\n size = %d", file.size); + tos_debugf("TOS.IMG:\n size = %llu", file.size); if (file.size >= 256 * 1024) tos_base = TOS_BASE_ADDRESS_256k; @@ -737,7 +742,7 @@ void tos_upload(const char *name) int blocks = file.size / 512; tos_debugf(" blocks = %d", blocks); - tos_debugf(" address = $%08x", tos_base); + tos_debugf(" address = $%08lx", tos_base); // clear first 16k mist_memory_set_address(0, 16384 / 512, 0); @@ -828,7 +833,7 @@ void tos_upload(const char *name) #endif time = GetTimer(0) - time; - tos_debugf("TOS.IMG uploaded in %lu ms (%d kB/s / %d kBit/s)", + tos_debugf("TOS.IMG uploaded in %lu ms (%llu kB/s / %llu kBit/s)", time >> 20, file.size / (time >> 20), 8 * file.size / (time >> 20)); } @@ -851,9 +856,9 @@ void tos_upload(const char *name) // try to open both floppies int i; for (i = 0; i<2; i++) { - char msg[] = "Found floppy disk image for drive X: "; + //char msg[] = "Found floppy disk image for drive X: "; char name[] = "DISK_A.ST"; - msg[34] = name[5] = 'A' + i; + //msg[34] = name[5] = 'A' + i; tos_insert_disk(i, name); } @@ -889,6 +894,7 @@ void tos_upload(const char *name) mist_set_control(config.system_ctrl); } +/* static unsigned long get_long(char *buffer, int offset) { unsigned long retval = 0; int i; @@ -898,6 +904,7 @@ static unsigned long get_long(char *buffer, int offset) { return retval; } +*/ void tos_poll() { // 1 == button not pressed, 2 = 1 sec exceeded, else timer running @@ -950,9 +957,8 @@ static void nice_name(char *dest, char *src) { static char buffer[17]; // local buffer to assemble file name (8+3+2) -char *tos_get_disk_name(char index) { +char *tos_get_disk_name(int index) { fileTYPE file; - char *c; if (index <= 1) file = fdd_image[index].file; @@ -983,14 +989,14 @@ char *tos_get_cartridge_name() { return buffer; } -char tos_disk_is_inserted(char index) { +char tos_disk_is_inserted(int index) { if (index <= 1) return (fdd_image[index].file.size != 0); return hdd_image[index - 2].size != 0; } -void tos_select_hdd_image(char i, const char *name) +void tos_select_hdd_image(int i, const char *name) { tos_debugf("Select ACSI%c image %s", '0' + i, name); @@ -1015,7 +1021,7 @@ void tos_select_hdd_image(char i, const char *name) mist_set_control(config.system_ctrl); } -void tos_insert_disk(char i, const char *name) +void tos_insert_disk(int i, const char *name) { if (i > 1) { @@ -1136,7 +1142,7 @@ void tos_config_init(void) int size = FileLoadConfig(CONFIG_FILENAME, 0, 0); if (size>0) { - tos_debugf("Configuration file size: %lu (should be %lu)", size, sizeof(tos_config_t)); + tos_debugf("Configuration file size: %u (should be %u)", size, sizeof(tos_config_t)); if (size == sizeof(tos_config_t)) { FileLoadConfig(CONFIG_FILENAME, &config, size); diff --git a/support/st/st_tos.h b/support/st/st_tos.h index 58b0323..89e4357 100644 --- a/support/st/st_tos.h +++ b/support/st/st_tos.h @@ -85,11 +85,11 @@ unsigned long tos_system_ctrl(void); void tos_upload(const char *); void tos_poll(); void tos_update_sysctrl(unsigned long); -char *tos_get_disk_name(char); -char tos_disk_is_inserted(char index); -void tos_insert_disk(char i, const char *name); +char *tos_get_disk_name(int); +char tos_disk_is_inserted(int index); +void tos_insert_disk(int i, const char *name); void tos_eject_all(); -void tos_select_hdd_image(char i, const char *name); +void tos_select_hdd_image(int i, const char *name); void tos_set_direct_hdd(char on); char tos_get_direct_hdd(); void tos_reset(char cold); @@ -98,8 +98,8 @@ char *tos_get_cartridge_name(); char tos_cartridge_is_inserted(); void tos_load_cartridge(const char *); -void tos_set_video_adjust(char axis, char value); -char tos_get_video_adjust(char axis); +void tos_set_video_adjust(int axis, char value); +char tos_get_video_adjust(int axis); void tos_config_init(void); void tos_config_save(void); diff --git a/support/x86/x86.cpp b/support/x86/x86.cpp index aabb4a3..0221352 100644 --- a/support/x86/x86.cpp +++ b/support/x86/x86.cpp @@ -72,6 +72,7 @@ static uint8_t dma_sdio(int status) return res; } +/* static uint32_t dma_get(uint32_t address) { EnableFpga(); @@ -81,6 +82,7 @@ static uint32_t dma_get(uint32_t address) DisableFpga(); return res; } +*/ static void dma_set(uint32_t address, uint32_t data) { @@ -111,7 +113,7 @@ static void dma_rcvbuf(uint32_t address, uint32_t length, uint32_t *data) static int load_bios(const char* name, uint8_t index) { - fileTYPE f = { 0 }; + fileTYPE f = {}; static uint32_t buf[128]; if (!FileOpen(&f, name)) return 0; @@ -155,10 +157,10 @@ static bool floppy_is_2_88m= false; #define CMOS_FDD_TYPE ((floppy_is_2_88m) ? 0x50 : (floppy_is_1_44m || floppy_is_1_68m) ? 0x40 : (floppy_is_720k) ? 0x30 : (floppy_is_1_2m) ? 0x20 : 0x10) -static fileTYPE fdd_image0 = { 0 }; -static fileTYPE fdd_image1 = { 0 }; -static fileTYPE hdd_image0 = { 0 }; -static fileTYPE hdd_image1 = { 0 }; +static fileTYPE fdd_image0 = {}; +static fileTYPE fdd_image1 = {}; +static fileTYPE hdd_image0 = {}; +static fileTYPE hdd_image1 = {}; static bool boot_from_floppy = 1; #define IMG_TYPE_FDD0 0x0800 @@ -210,8 +212,8 @@ static int img_write(uint32_t type, uint32_t lba, void *buf, uint32_t len) #define IOWR(base, reg, value) dma_set(base+(reg<<2), value) static uint32_t cmos[128]; - -void cmos_set(int addr, uint8_t val) +/* +static void cmos_set(uint addr, uint8_t val) { if (addr >= sizeof(cmos)) return; @@ -229,6 +231,7 @@ void cmos_set(int addr, uint8_t val) IOWR(RTC_BASE, 0x2E, cmos[0x2E]); IOWR(RTC_BASE, 0x2F, cmos[0x2F]); } +*/ static int fdd_set(char* filename) { @@ -661,7 +664,7 @@ struct sd_param_t uint32_t bl_cnt; }; -static struct sd_param_t sd_params = { 0 }; +static struct sd_param_t sd_params = {}; void x86_poll() { diff --git a/user_io.cpp b/user_io.cpp index b88b84a..27877b2 100644 --- a/user_io.cpp +++ b/user_io.cpp @@ -609,7 +609,7 @@ int user_io_get_joyswap() void user_io_analog_joystick(unsigned char joystick, char valueX, char valueY) { - uint8_t joy = (!joyswap) ? joystick : joystick ? 0 : 1; + uint8_t joy = (joystick>1 || !joyswap) ? joystick : joystick^1; if (core_type == CORE_TYPE_8BIT) { @@ -626,13 +626,7 @@ void user_io_analog_joystick(unsigned char joystick, char valueX, char valueY) void user_io_digital_joystick(unsigned char joystick, uint16_t map, int newdir) { - uint8_t joy = (!joyswap) ? joystick : joystick ? 0 : 1; - - if (is_minimig()) - { - spi_uio_cmd16(UIO_JOYSTICK0 + joy, map); - return; - } + uint8_t joy = (joystick>1 || !joyswap) ? joystick : joystick ^ 1; // atari ST handles joystick 0 and 1 through the ikbd emulated by the io controller // but only for joystick 1 and 2 @@ -642,8 +636,9 @@ void user_io_digital_joystick(unsigned char joystick, uint16_t map, int newdir) return; } - spi_uio_cmd16(UIO_JOYSTICK0 + joy, map); - if (joy_transl == 1 && newdir) + spi_uio_cmd16((joy < 2) ? (UIO_JOYSTICK0 + joy) : (UIO_JOYSTICK2 + joy - 2), map); + + if (!is_minimig() && joy_transl == 1 && newdir) { user_io_analog_joystick(joystick, (map & 2) ? 128 : (map & 1) ? 127 : 0, (map & 8) ? 128 : (map & 4) ? 127 : 0); } @@ -2473,8 +2468,8 @@ void user_io_kbd(uint16_t key, int press) else { if (is_menu_core()) printf("PS2 code(make)%s for core: %d(0x%X)\n", (code & EXT) ? "(ext)" : "", code & 255, code & 255); - - if ((has_menu() || osd_is_visible || (get_key_mod() & (LALT | RALT | RGUI | LGUI))) && (((key == KEY_F12) && ((!is_x86_core() && !is_archie()) || (get_key_mod() & (RGUI | LGUI)))) || key == KEY_MENU)) menu_key_set(KEY_F12); + if (!osd_is_visible && !is_menu_core() && key == KEY_MENU && press == 3) open_joystick_setup(); + else if ((has_menu() || osd_is_visible || (get_key_mod() & (LALT | RALT | RGUI | LGUI))) && (((key == KEY_F12) && ((!is_x86_core() && !is_archie()) || (get_key_mod() & (RGUI | LGUI)))) || key == KEY_MENU)) menu_key_set(KEY_F12); else if (osd_is_visible) { if (press == 1) menu_key_set(key); @@ -2943,10 +2938,10 @@ static void adjust_vsize(char force) if ((res & 0x8000) && (nres != res || force)) { nres = res; - uint16_t scr_hsize = spi_w(0); - uint16_t scr_vsize = spi_w(0); + uint16_t scr_hsize = spi_w(0); + uint16_t scr_vsize = spi_w(0); DisableIO(); - + printf("\033[1;37mVMODE: resolution: %u x %u, mode: %u\033[0m\n", scr_hsize, scr_vsize, res & 255); static int loaded = 0; @@ -2991,14 +2986,14 @@ static void store_vsize() spi_uio_cmd_cont(UIO_GET_VMODE); uint16_t res = spi_w(0); - uint16_t scr_hsize = spi_w(0); - uint16_t scr_vsize = spi_w(0); - uint16_t scr_hbl_l = spi_w(0); - uint16_t scr_hbl_r = spi_w(0); - uint16_t scr_vbl_t = spi_w(0); - uint16_t scr_vbl_b = spi_w(0); + uint16_t scr_hsize = spi_w(0); + uint16_t scr_vsize = spi_w(0); + uint16_t scr_hbl_l = spi_w(0); + uint16_t scr_hbl_r = spi_w(0); + uint16_t scr_vbl_t = spi_w(0); + uint16_t scr_vbl_b = spi_w(0); DisableIO(); - + printf("\033[1;37mVMODE: store position: [%u-%u, %u-%u]\033[0m\n", scr_hbl_l, scr_hbl_r, scr_vbl_t, scr_vbl_b); uint32_t mode = scr_hsize | (scr_vsize << 12) | ((res & 0xFF) << 24);