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):
+
+
+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):
+
+
+
+
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);