ty
tyuuyt
This commit is contained in:
parent
7c58e46fc4
commit
dd88ecddc1
22
.vscode/c_cpp_properties.json
vendored
22
.vscode/c_cpp_properties.json
vendored
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "Win32",
|
|
||||||
"includePath": [
|
|
||||||
"${workspaceFolder}/**",
|
|
||||||
"${workspaceFolder}/source/fumoengine/input"
|
|
||||||
],
|
|
||||||
"defines": [
|
|
||||||
"_DEBUG",
|
|
||||||
"UNICODE",
|
|
||||||
"_UNICODE"
|
|
||||||
],
|
|
||||||
"windowsSdkVersion": "10.0.22000.0",
|
|
||||||
"compilerPath": "C:/mingw64/bin/gcc.exe",
|
|
||||||
"cStandard": "c17",
|
|
||||||
"cppStandard": "c++17",
|
|
||||||
"intelliSenseMode": "windows-gcc-x64"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 4
|
|
||||||
}
|
|
63
.vscode/settings.json
vendored
63
.vscode/settings.json
vendored
|
@ -1,63 +0,0 @@
|
||||||
{
|
|
||||||
"files.associations": {
|
|
||||||
"pthread.h": "c",
|
|
||||||
"fumotris.h": "c",
|
|
||||||
"string.h": "c",
|
|
||||||
"input.h": "c",
|
|
||||||
"stdint.h": "c",
|
|
||||||
"iso646.h": "c",
|
|
||||||
"win.h": "c",
|
|
||||||
"array": "cpp",
|
|
||||||
"deque": "cpp",
|
|
||||||
"string": "cpp",
|
|
||||||
"unordered_map": "cpp",
|
|
||||||
"vector": "cpp",
|
|
||||||
"string_view": "cpp",
|
|
||||||
"atomic": "cpp",
|
|
||||||
"bit": "cpp",
|
|
||||||
"*.tcc": "cpp",
|
|
||||||
"cctype": "cpp",
|
|
||||||
"clocale": "cpp",
|
|
||||||
"cmath": "cpp",
|
|
||||||
"compare": "cpp",
|
|
||||||
"concepts": "cpp",
|
|
||||||
"cstdarg": "cpp",
|
|
||||||
"cstddef": "cpp",
|
|
||||||
"cstdint": "cpp",
|
|
||||||
"cstdio": "cpp",
|
|
||||||
"cstdlib": "cpp",
|
|
||||||
"cwchar": "cpp",
|
|
||||||
"cwctype": "cpp",
|
|
||||||
"exception": "cpp",
|
|
||||||
"algorithm": "cpp",
|
|
||||||
"functional": "cpp",
|
|
||||||
"iterator": "cpp",
|
|
||||||
"memory": "cpp",
|
|
||||||
"memory_resource": "cpp",
|
|
||||||
"numeric": "cpp",
|
|
||||||
"optional": "cpp",
|
|
||||||
"random": "cpp",
|
|
||||||
"system_error": "cpp",
|
|
||||||
"tuple": "cpp",
|
|
||||||
"type_traits": "cpp",
|
|
||||||
"utility": "cpp",
|
|
||||||
"initializer_list": "cpp",
|
|
||||||
"iosfwd": "cpp",
|
|
||||||
"limits": "cpp",
|
|
||||||
"new": "cpp",
|
|
||||||
"numbers": "cpp",
|
|
||||||
"ostream": "cpp",
|
|
||||||
"stdexcept": "cpp",
|
|
||||||
"streambuf": "cpp",
|
|
||||||
"typeinfo": "cpp",
|
|
||||||
"execution": "cpp",
|
|
||||||
"stdbool.h": "c",
|
|
||||||
"gametime.h": "c",
|
|
||||||
"stdlib.h": "c",
|
|
||||||
"stdio.h": "c",
|
|
||||||
"platform.h": "c",
|
|
||||||
"ringbuffer.h": "c",
|
|
||||||
"fumoengine.h": "c",
|
|
||||||
"fumocommon.h": "c"
|
|
||||||
}
|
|
||||||
}
|
|
193
build.py
193
build.py
|
@ -1,94 +1,139 @@
|
||||||
import os, sys
|
import hashlib
|
||||||
import json, hashlib
|
import json
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
def walk_source(path):
|
GCC = "gcc"
|
||||||
source_paths = []
|
ARGS = "-fdiagnostics-color -pthread -Wall -std=c17 -pedantic"
|
||||||
subdirs = []
|
|
||||||
|
|
||||||
for dirpath, dirnames, filenames in os.walk(path):
|
|
||||||
source_paths += [os.path.join(dirpath, f) for f in filenames if f.endswith(".c")]
|
|
||||||
subdirs.append(dirpath)
|
|
||||||
|
|
||||||
return (source_paths, subdirs)
|
|
||||||
|
|
||||||
|
|
||||||
def get_checksums(source_files):
|
SOURCE_DIR = Path("source/")
|
||||||
checksums = {}
|
OBJECT_DIR = Path("objects/")
|
||||||
|
OUTPUT = Path("debug")
|
||||||
for path in source_files:
|
|
||||||
with open(path, "rb") as source_file:
|
|
||||||
source = source_file.read()
|
|
||||||
|
|
||||||
checksum = hashlib.md5(source).hexdigest()
|
|
||||||
checksums[path] = checksum
|
|
||||||
|
|
||||||
return checksums
|
|
||||||
|
|
||||||
|
|
||||||
def read_checksum_file():
|
CHECKSUMS = Path("checksums.txt")
|
||||||
checksums = {}
|
ERRORS = Path("errors.txt")
|
||||||
|
|
||||||
if not os.path.exists("checksums.txt"):
|
|
||||||
return checksums
|
|
||||||
|
|
||||||
with open("checksums.txt", "rb") as checksum_file:
|
|
||||||
checksums = json.loads(checksum_file.read())
|
|
||||||
|
|
||||||
return checksums
|
|
||||||
|
|
||||||
|
|
||||||
def write_checksum_file(checksums):
|
def disk_scan_chksms(sources: list[Path]) -> list[str]:
|
||||||
with open("checksums.txt", "w+") as checksum_file:
|
chksms: list[str] = []
|
||||||
checksum_file.write(json.dumps(checksums))
|
|
||||||
|
for source in sources:
|
||||||
|
with open(source, "rb") as file:
|
||||||
|
raw = file.read()
|
||||||
|
chksms.append(hashlib.md5(raw).hexdigest())
|
||||||
|
|
||||||
|
return chksms
|
||||||
|
|
||||||
|
|
||||||
def get_object_names(path):
|
def disk_read_chksms(txt: Path) -> tuple[list[Path], list[str]]:
|
||||||
object_names = []
|
sources: list[Path]
|
||||||
|
chksms: list[str]
|
||||||
|
|
||||||
for file in os.listdir(path):
|
if not txt.exists():
|
||||||
if os.path.isfile(os.path.join(path, file)):
|
return ([], [])
|
||||||
name = os.path.splitext(os.path.basename(file))[0]
|
|
||||||
|
|
||||||
object_names.append(name)
|
with open(txt, "rb") as file:
|
||||||
|
zipped: dict[str, str] = json.loads(file.read())
|
||||||
|
|
||||||
return object_names
|
sources, chksms = [Path(key) for key in zipped.keys()], zipped.values()
|
||||||
|
|
||||||
|
return (sources, chksms)
|
||||||
|
|
||||||
|
|
||||||
def build(source_path, obj_path, out_path, recompile = False):
|
def disk_write_chksms(txt: Path, sources: list[Path], chksms: list[str]) -> None:
|
||||||
source_paths, subdirs = walk_source(source_path)
|
zipped = {str(source): chksm for source, chksm in zip(sources, chksms)}
|
||||||
|
|
||||||
if recompile:
|
with open(txt, "w+") as file:
|
||||||
result = os.system(f"gcc {' '.join(source_paths)} -I {' -I '.join(subdirs)} -o {out_path} -pthread -Wall -std=c17 -pedantic")
|
file.write(json.dumps(zipped))
|
||||||
print(result)
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
checksums_before = read_checksum_file()
|
def filter_chksms(sources, chksms, old_chksms) -> list[Path]:
|
||||||
checksums_now = get_checksums(source_paths)
|
difs = set(chksms).difference(old_chksms)
|
||||||
|
return [sources[chksms.index(dif)] for dif in difs]
|
||||||
object_names = get_object_names(obj_path)
|
|
||||||
compile_list = []
|
|
||||||
|
|
||||||
for path in checksums_now:
|
|
||||||
name = os.path.splitext(os.path.basename(path))[0]
|
|
||||||
|
|
||||||
if path not in checksums_before or checksums_before[path] != checksums_now[path] or name not in object_names:
|
|
||||||
compile_list.append(path)
|
|
||||||
|
|
||||||
if name in object_names:
|
|
||||||
object_names.remove(name)
|
|
||||||
|
|
||||||
for object_name in object_names:
|
|
||||||
os.remove(f"{obj_path}\\{object_name}.o")
|
|
||||||
|
|
||||||
for path in compile_list:
|
|
||||||
name = os.path.splitext(os.path.basename(path))[0]
|
|
||||||
|
|
||||||
os.system(f"gcc -c {path} -I {' -I '.join(subdirs)} -o {obj_path}\\{name}.o -pthread -Wall -std=c17 -pedantic")
|
|
||||||
|
|
||||||
write_checksum_file(checksums_now)
|
|
||||||
print(os.system(f"gcc {obj_path}\\*.o -o {out_path} -pthread -Wall -std=c17 -pedantic -g"))
|
|
||||||
|
|
||||||
|
|
||||||
build(sys.argv[1], sys.argv[2], sys.argv[3], True)
|
def scan_sources(source_dir: Path) -> tuple[list[Path], list[Path]]:
|
||||||
|
sources = [source for source in source_dir.rglob("*.c")]
|
||||||
|
chksms = disk_scan_chksms(sources)
|
||||||
|
|
||||||
|
old_sources, old_chksms = disk_read_chksms(CHECKSUMS)
|
||||||
|
updated_sources = filter_chksms(sources, chksms, old_chksms)
|
||||||
|
|
||||||
|
disk_write_chksms(CHECKSUMS, sources, chksms)
|
||||||
|
return (updated_sources, sources)
|
||||||
|
|
||||||
|
|
||||||
|
def clean_objects(object_dir: Path, sources: list[Path]) -> None:
|
||||||
|
objects: list[Path] = [object for object in object_dir.rglob("*.o")]
|
||||||
|
|
||||||
|
object_stems = [object.stem for object in objects]
|
||||||
|
source_stems = [source.stem for source in sources]
|
||||||
|
|
||||||
|
for stem in set(object_stems).difference(source_stems):
|
||||||
|
objects[object_stems.index(stem)].unlink()
|
||||||
|
|
||||||
|
|
||||||
|
def compile(source: Path, includes: list[Path], object_dir: Path):
|
||||||
|
include_arg: str = " ".join(f"-I {dir}" for dir in includes)
|
||||||
|
output: Path = object_dir / source.with_suffix(".o").name
|
||||||
|
|
||||||
|
args = f"{GCC} -c {source} {ARGS} {include_arg} -o {output}"
|
||||||
|
|
||||||
|
return subprocess.Popen(args, stderr=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
|
def disk_read_errors(txt: Path) -> dict[str, str]:
|
||||||
|
if not txt.exists():
|
||||||
|
return {}
|
||||||
|
|
||||||
|
with open(txt, "rb") as file:
|
||||||
|
return json.loads(file.read())
|
||||||
|
|
||||||
|
|
||||||
|
def disk_write_errors(txt: Path, errs: dict[str, str]):
|
||||||
|
with open(txt, "w+") as file:
|
||||||
|
file.write(json.dumps(errs))
|
||||||
|
|
||||||
|
|
||||||
|
def wait_compile_tasks(tasks, updated_sources) -> dict[str, str]:
|
||||||
|
errors = disk_read_errors(ERRORS)
|
||||||
|
|
||||||
|
for task, source in zip(tasks, updated_sources):
|
||||||
|
out, err = task.communicate()
|
||||||
|
if err:
|
||||||
|
errors[str(source)] = err.decode("utf-8")
|
||||||
|
else:
|
||||||
|
errors[str(source)] = False
|
||||||
|
|
||||||
|
disk_write_errors(ERRORS, errors)
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def link(object_dir: Path, output: Path) -> None:
|
||||||
|
subprocess.run(f"{GCC} -g {object_dir}/*.o {ARGS} -o {output}")
|
||||||
|
|
||||||
|
|
||||||
|
def build(source_dir: Path, object_dir: Path, output: Path):
|
||||||
|
updated_sources, all_sources = scan_sources(source_dir)
|
||||||
|
includes = [path for path in source_dir.rglob("*") if path.is_dir()]
|
||||||
|
|
||||||
|
|
||||||
|
tasks = []
|
||||||
|
for source in updated_sources:
|
||||||
|
tasks.append(compile(source, includes, object_dir))
|
||||||
|
|
||||||
|
errors = wait_compile_tasks(tasks, updated_sources).values()
|
||||||
|
|
||||||
|
print("\n".join(err for err in errors if err is not False).strip("\n"))
|
||||||
|
|
||||||
|
|
||||||
|
clean_objects(object_dir, all_sources)
|
||||||
|
link(object_dir, output)
|
||||||
|
print(f"Compiled: {len(updated_sources)} Linked: {len(all_sources)}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
build(SOURCE_DIR, OBJECT_DIR, OUTPUT)
|
|
@ -1 +1 @@
|
||||||
{"source\\main.c": "82d4037af47edc6a1ef16f061e8980c2", "source\\game\\gametime.c": "40eedcb0dd0e0ebd42a09860aeb24517", "source\\game\\tetr.c": "fee38bad904b2053644fddf0ba08cd5e", "source\\io\\ctrl.c": "a838d22152710a4be156b5c90c41863c", "source\\io\\input.c": "aca98b0ac5983206b3fad774dc4d6146", "source\\io\\term.c": "b8fa47ec18810973c2123e7ec3a3cec6", "source\\io\\platforms\\win.c": "5f8d684bbaae885edf7505a1d90d91e8", "source\\io\\platforms\\winhandler.c": "b0c21fa0370350172987a3ec39be1d20"}
|
{"source\\fumoengine\\fumocommon.c": "3253ec40842eaf2b65cca13826e35118", "source\\fumoengine\\fumoengine.c": "e6c26dc323b01d0b8c2e7e2f64833eb7", "source\\fumoengine\\include\\dictionary.c": "aa85678a01e035d45c9f59b6fe917beb", "source\\fumoengine\\include\\event.c": "71e6818ecf285293cf01c791f13c4d00", "source\\fumoengine\\include\\ringbuffer.c": "306556649cea951ef769cdfc5ae2b60d", "source\\fumoengine\\include\\vector.c": "67e0cf60c3a359e6e8c8eb46e01e8513", "source\\fumoengine\\input\\ctrl.c": "87dbff7e38fc406cbf309717e63665ed", "source\\fumoengine\\input\\input.c": "5a57ebd313fc2fc0246a95ce6641e5e8", "source\\fumoengine\\input\\platforms\\parseinput.c": "c1562355adcec7d0dcb0a81e8d7ffcca", "source\\fumoengine\\input\\platforms\\win.c": "2014fc5cdb4c8770f510a63db779f8bf", "source\\fumoengine\\terminal\\terminal.c": "c213e73df14b8d5ebcf5f25d221c3fe6", "source\\fumotris\\fumotris.c": "defad533a34d69352e728dbda3306a79", "source\\fumotris\\tetr.c": "09dcf3a7119ccabe0cb69c0a8fd688e9"}
|
1
errors.txt
Normal file
1
errors.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"source\\fumoengine\\input\\platforms\\parseinput.c": false, "source\\fumoengine\\terminal\\terminal.c": false, "source\\fumoengine\\fumoengine.c": "In file included from \u001b[01m\u001b[Ksource\\fumoengine\\fumoengine.h:7\u001b[m\u001b[K,\n from \u001b[01m\u001b[Ksource\\fumoengine\\fumoengine.c:1\u001b[m\u001b[K:\n\u001b[01m\u001b[Ksource\\fumoengine\\include/vector.h:25:2:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kexpected '\u001b[01m\u001b[K;\u001b[m\u001b[K' before '\u001b[01m\u001b[K_Bool\u001b[m\u001b[K'\n 25 | g\n | \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n | \u001b[32m\u001b[K;\u001b[m\u001b[K\n", "source\\fumoengine\\include\\vector.c": "In file included from \u001b[01m\u001b[Ksource\\fumoengine\\include\\vector.c:1\u001b[m\u001b[K:\n\u001b[01m\u001b[Ksource\\fumoengine\\include\\vector.h:25:2:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kexpected '\u001b[01m\u001b[K;\u001b[m\u001b[K' before '\u001b[01m\u001b[K_Bool\u001b[m\u001b[K'\n 25 | g\n | \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n | \u001b[32m\u001b[K;\u001b[m\u001b[K\n", "source\\fumoengine\\include\\event.c": false, "source\\fumoengine\\fumocommon.c": false, "source\\fumoengine\\include\\ringbuffer.c": false, "source\\fumoengine\\input\\platforms\\win.c": false, "source\\fumotris\\fumotris.c": "In file included from \u001b[01m\u001b[Ksource\\fumoengine/fumoengine.h:7\u001b[m\u001b[K,\n from \u001b[01m\u001b[Ksource\\fumotris\\fumotris.h:2\u001b[m\u001b[K,\n from \u001b[01m\u001b[Ksource\\fumotris\\fumotris.c:1\u001b[m\u001b[K:\n\u001b[01m\u001b[Ksource\\fumoengine\\include/vector.h:25:2:\u001b[m\u001b[K \u001b[01;31m\u001b[Kerror: \u001b[m\u001b[Kexpected '\u001b[01m\u001b[K;\u001b[m\u001b[K' before '\u001b[01m\u001b[K_Bool\u001b[m\u001b[K'\n 25 | g\n | \u001b[01;31m\u001b[K^\u001b[m\u001b[K\n | \u001b[32m\u001b[K;\u001b[m\u001b[K\n", "source\\fumotris\\tetr.c": false, "source\\fumoengine\\input\\input.c": false, "source\\fumoengine\\input\\ctrl.c": false, "source\\fumoengine\\include\\dictionary.c": false}
|
BIN
objects/ctrl.o
BIN
objects/ctrl.o
Binary file not shown.
BIN
objects/dictionary.o
Normal file
BIN
objects/dictionary.o
Normal file
Binary file not shown.
BIN
objects/event.o
Normal file
BIN
objects/event.o
Normal file
Binary file not shown.
BIN
objects/fumocommon.o
Normal file
BIN
objects/fumocommon.o
Normal file
Binary file not shown.
BIN
objects/fumoengine.o
Normal file
BIN
objects/fumoengine.o
Normal file
Binary file not shown.
BIN
objects/fumotris.o
Normal file
BIN
objects/fumotris.o
Normal file
Binary file not shown.
Binary file not shown.
BIN
objects/input.o
BIN
objects/input.o
Binary file not shown.
BIN
objects/main.o
BIN
objects/main.o
Binary file not shown.
BIN
objects/parseinput.o
Normal file
BIN
objects/parseinput.o
Normal file
Binary file not shown.
BIN
objects/ringbuffer.o
Normal file
BIN
objects/ringbuffer.o
Normal file
Binary file not shown.
BIN
objects/term.o
BIN
objects/term.o
Binary file not shown.
BIN
objects/terminal.o
Normal file
BIN
objects/terminal.o
Normal file
Binary file not shown.
BIN
objects/tetr.o
BIN
objects/tetr.o
Binary file not shown.
BIN
objects/vector.o
Normal file
BIN
objects/vector.o
Normal file
Binary file not shown.
BIN
objects/win.o
BIN
objects/win.o
Binary file not shown.
Binary file not shown.
|
@ -32,44 +32,36 @@ void FreeController(struct Controller *ctrl)
|
||||||
FreeDictionary(&ctrl->binds);
|
FreeDictionary(&ctrl->binds);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 hash_bind(u16f bind, u16f type)
|
u32 hash_bind(u16f code, u16f type)
|
||||||
{
|
{
|
||||||
return bind + (type << 16);
|
return code | (type << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InputAxis *ControllerMap(
|
bool ControllerBind(struct Controller *ctrl, u16 control, u16 code, u16 type)
|
||||||
struct Controller *ctrl,
|
{
|
||||||
struct ControlMapping *map
|
u32 hash = hash_bind(code, type);
|
||||||
) {
|
|
||||||
struct InputAxis *axis = &ctrl->axes[map->code];
|
|
||||||
|
|
||||||
u32 hash = hash_bind(map->bind, map->type);
|
struct InputAxis *axis = &ctrl->axes[control];
|
||||||
struct InputAxis **bind = DictionarySet(BIND_T, &ctrl->binds, hash, axis);
|
struct InputAxis **bind = DictionarySet(BIND_T, &ctrl->binds, hash, axis);
|
||||||
|
|
||||||
if (bind == nullptr) {
|
if (bind == nullptr)
|
||||||
printf("whar");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
*bind = axis;
|
|
||||||
axis->type = map->type;
|
|
||||||
|
|
||||||
return axis;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ControllerMapMulti(
|
|
||||||
struct Controller *ctrl,
|
|
||||||
usize n,
|
|
||||||
struct ControlMapping *maps,
|
|
||||||
struct InputAxis **binds
|
|
||||||
) {
|
|
||||||
for (usize i = 0; i < n; i++) {
|
|
||||||
struct InputAxis *axis = ControllerMap(ctrl, maps + i);
|
|
||||||
|
|
||||||
if (axis == nullptr)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
binds[i] = axis;
|
*bind = axis;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ControllerBindMulti(
|
||||||
|
struct Controller *ctrl,
|
||||||
|
usize n,
|
||||||
|
u16 *controls,
|
||||||
|
u16 *codes,
|
||||||
|
u16 *types
|
||||||
|
) {
|
||||||
|
for (usize i = 0; i < n; i++) {
|
||||||
|
if (!ControllerBind(ctrl, controls[i], codes[i], types[i]))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -81,7 +73,7 @@ void dispatch_update(struct InputAxis *axis, struct InputRecord *rec)
|
||||||
axis->is_down = true;
|
axis->is_down = true;
|
||||||
axis->is_held = true;
|
axis->is_held = true;
|
||||||
axis->last_pressed = rec->time;
|
axis->last_pressed = rec->time;
|
||||||
} else if (rec->is_up) {
|
} else {
|
||||||
axis->is_up = true;
|
axis->is_up = true;
|
||||||
axis->is_held = false;
|
axis->is_held = false;
|
||||||
axis->last_released = rec->time;
|
axis->last_released = rec->time;
|
||||||
|
@ -104,7 +96,7 @@ void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs)
|
||||||
for (usize i = 0; i < recs->head.len; i++) {
|
for (usize i = 0; i < recs->head.len; i++) {
|
||||||
struct InputRecord *rec = recs->buf + i;
|
struct InputRecord *rec = recs->buf + i;
|
||||||
|
|
||||||
u32 hash = hash_bind(rec->bind, rec->type);
|
u32 hash = hash_bind(rec->code, rec->type);
|
||||||
struct InputAxis *axis = DictionaryFind(BIND_T, &ctrl->binds, hash);
|
struct InputAxis *axis = DictionaryFind(BIND_T, &ctrl->binds, hash);
|
||||||
|
|
||||||
if (axis == nullptr)
|
if (axis == nullptr)
|
||||||
|
|
|
@ -4,30 +4,6 @@
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
|
||||||
|
|
||||||
struct ControlMapping {
|
|
||||||
u16 code;
|
|
||||||
u16 bind;
|
|
||||||
u16 type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct InputAxis {
|
|
||||||
nsec last_pressed;
|
|
||||||
nsec last_released;
|
|
||||||
|
|
||||||
union {
|
|
||||||
struct Button but;
|
|
||||||
struct Axis axis;
|
|
||||||
struct Joystick js;
|
|
||||||
union InputData data;
|
|
||||||
};
|
|
||||||
|
|
||||||
u16 type;
|
|
||||||
|
|
||||||
bool is_down;
|
|
||||||
bool is_held;
|
|
||||||
bool is_up;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Controller {
|
struct Controller {
|
||||||
struct InputAxis *pending[IO_BUF_SIZE];
|
struct InputAxis *pending[IO_BUF_SIZE];
|
||||||
usize pending_len;
|
usize pending_len;
|
||||||
|
@ -43,16 +19,14 @@ bool CreateController(struct Controller *ctrl);
|
||||||
|
|
||||||
void FreeController(struct Controller *ctrl);
|
void FreeController(struct Controller *ctrl);
|
||||||
|
|
||||||
struct InputAxis *ControllerMap(
|
bool ControllerBind(struct Controller *ctrl, u16 control, u16 code, u16 type);
|
||||||
struct Controller *ctrl,
|
|
||||||
struct ControlMapping *map
|
|
||||||
);
|
|
||||||
|
|
||||||
bool ControllerMapMulti(
|
bool ControllerBindMulti(
|
||||||
struct Controller *ctrl,
|
struct Controller *ctrl,
|
||||||
usize n,
|
usize n,
|
||||||
struct ControlMapping *maps,
|
u16 *controls,
|
||||||
struct InputAxis **axis_ptrs
|
u16 *codes,
|
||||||
|
u16 *types
|
||||||
);
|
);
|
||||||
|
|
||||||
void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs);
|
void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs);
|
||||||
|
|
|
@ -33,22 +33,28 @@ struct Joystick {
|
||||||
};
|
};
|
||||||
|
|
||||||
union InputData {
|
union InputData {
|
||||||
struct Button input_but;
|
struct Button but;
|
||||||
struct Axis input_axis;
|
struct Axis axis;
|
||||||
struct Joystick input_js;
|
struct Joystick js;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InputRecord {
|
struct InputRecord {
|
||||||
nsec time;
|
nsec time;
|
||||||
|
|
||||||
union {
|
|
||||||
struct Button but;
|
|
||||||
struct Axis axis;
|
|
||||||
struct Joystick js;
|
|
||||||
union InputData data;
|
union InputData data;
|
||||||
|
|
||||||
|
u16 code;
|
||||||
|
u16 type;
|
||||||
|
|
||||||
|
bool is_down;
|
||||||
};
|
};
|
||||||
|
|
||||||
u16 bind;
|
struct InputAxis {
|
||||||
|
nsec last_pressed;
|
||||||
|
nsec last_released;
|
||||||
|
|
||||||
|
union InputData data;
|
||||||
|
|
||||||
u16 type;
|
u16 type;
|
||||||
|
|
||||||
bool is_down;
|
bool is_down;
|
||||||
|
|
|
@ -1,30 +1,29 @@
|
||||||
#include "parseinput.h"
|
#include "parseinput.h"
|
||||||
|
|
||||||
|
|
||||||
void ReadButton(struct InputRecord *rec, u16f bind, bool is_down)
|
void ReadButton(struct InputRecord *rec, u16f code, bool is_down)
|
||||||
{
|
{
|
||||||
rec->bind = bind;
|
rec->code = code;
|
||||||
rec->type = BUTTON;
|
rec->type = BUTTON;
|
||||||
|
|
||||||
rec->is_down = is_down;
|
rec->is_down = is_down;
|
||||||
rec->is_up = !is_down;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadAxis(struct InputRecord *rec, u16f bind, u64 value)
|
void ReadAxis(struct InputRecord *rec, u16f code, u64 value)
|
||||||
{
|
{
|
||||||
rec->bind = bind;
|
rec->code = code;
|
||||||
rec->type = AXIS;
|
rec->type = AXIS;
|
||||||
|
|
||||||
rec->axis.value = value;
|
rec->data.axis.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadJoystick(struct InputRecord *rec, u16f bind, i32 x, i32 y)
|
void ReadJoystick(struct InputRecord *rec, u16f code, i32 x, i32 y)
|
||||||
{
|
{
|
||||||
rec->bind = bind;
|
rec->code = code;
|
||||||
rec->type = JOYSTICK;
|
rec->type = JOYSTICK;
|
||||||
|
|
||||||
rec->js.x = x;
|
rec->data.js.x = x;
|
||||||
rec->js.y = y;
|
rec->data.js.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t UCS2ToUTF8(char *buf, u16f ucs2)
|
size_t UCS2ToUTF8(char *buf, u16f ucs2)
|
||||||
|
@ -40,8 +39,10 @@ size_t UCS2ToUTF8(char *buf, u16f ucs2)
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
buf[0] = 0xE0 + (ucs2 >> 12);
|
buf[0] = 0xE0 + (ucs2 >> 12);
|
||||||
buf[1] = 0x80 + ((ucs2 >> 6) & 0x3F);
|
buf[1] = 0x80 + ((ucs2 >> 6) & 0x3F);
|
||||||
buf[2] = 0x80 + (ucs2 & 0x3F);
|
buf[2] = 0x80 + (ucs2 & 0x3F);
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
}
|
|
@ -2,9 +2,6 @@
|
||||||
|
|
||||||
|
|
||||||
struct Fumotris {
|
struct Fumotris {
|
||||||
struct ControlMapping mappings[BINDS_N];
|
|
||||||
struct InputAxis *input[BINDS_N];
|
|
||||||
|
|
||||||
struct TetrMap board;
|
struct TetrMap board;
|
||||||
struct TetrMap piece;
|
struct TetrMap piece;
|
||||||
};
|
};
|
||||||
|
@ -15,7 +12,7 @@ void FumotrisStart(void *inst_arg, void *game_arg)
|
||||||
struct FumoInstance *inst = inst_arg;
|
struct FumoInstance *inst = inst_arg;
|
||||||
struct Fumotris *game = game_arg;
|
struct Fumotris *game = game_arg;
|
||||||
|
|
||||||
ControllerMapMulti(&inst->ctrl, BINDS_N, game->mappings, game->input);
|
ControllerBindMulti(&inst->ctrl, BINDS_N, controls_g, codes_g, types_g);
|
||||||
|
|
||||||
CreateTetrMap(&game->board, 10, 10);
|
CreateTetrMap(&game->board, 10, 10);
|
||||||
CreateTetrMap(&game->piece, 3, 3);
|
CreateTetrMap(&game->piece, 3, 3);
|
||||||
|
@ -27,9 +24,10 @@ void FumotrisUpdate(void *inst_arg, void *game_arg)
|
||||||
struct FumoInstance *inst = inst_arg;
|
struct FumoInstance *inst = inst_arg;
|
||||||
struct Fumotris *game = game_arg;
|
struct Fumotris *game = game_arg;
|
||||||
|
|
||||||
if (game->input[LEFT]->is_down)
|
if (inst->ctrl.axes[LEFT].is_down)
|
||||||
game->piece.x -= 1;
|
game->piece.x -= 1;
|
||||||
if (game->input[RIGHT]->is_down)
|
|
||||||
|
if (inst->ctrl.axes[RIGHT].is_down)
|
||||||
game->piece.x += 1;
|
game->piece.x += 1;
|
||||||
|
|
||||||
TetrMapDraw(&game->board, &inst->term);
|
TetrMapDraw(&game->board, &inst->term);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#define BINDS_N 12
|
#define BINDS_N 12
|
||||||
|
|
||||||
|
|
||||||
enum FumotrisCode {
|
enum FumotrisControls {
|
||||||
LEFT,
|
LEFT,
|
||||||
RIGHT,
|
RIGHT,
|
||||||
SOFT_DROP,
|
SOFT_DROP,
|
||||||
|
@ -15,64 +15,102 @@ enum FumotrisCode {
|
||||||
ROTATE_180,
|
ROTATE_180,
|
||||||
SWAP,
|
SWAP,
|
||||||
ESC,
|
ESC,
|
||||||
|
|
||||||
VSCROLL,
|
VSCROLL,
|
||||||
HSCROLL,
|
HSCROLL,
|
||||||
|
|
||||||
MOUSE
|
MOUSE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct ControlMapping mappings_global[BINDS_N] = {
|
u16 controls_g[BINDS_N] = {
|
||||||
{ LEFT, 0x25, BUTTON },
|
LEFT,
|
||||||
{ RIGHT, 0x27, BUTTON },
|
RIGHT,
|
||||||
{ SOFT_DROP, 0x28, BUTTON },
|
SOFT_DROP,
|
||||||
{ HARD_DROP, 0x20, BUTTON },
|
HARD_DROP,
|
||||||
{ ROTATE_CCW, 'Z', BUTTON },
|
ROTATE_CCW,
|
||||||
{ ROTATE_CW, 'X', BUTTON },
|
ROTATE_CW,
|
||||||
{ ROTATE_180, 'A', BUTTON },
|
ROTATE_180,
|
||||||
{ SWAP, 'C', BUTTON },
|
SWAP,
|
||||||
{ ESC, 0x1B, BUTTON },
|
ESC,
|
||||||
{ VSCROLL, 0, AXIS },
|
|
||||||
{ HSCROLL, 1, AXIS },
|
VSCROLL,
|
||||||
{ MOUSE, 0, JOYSTICK }
|
HSCROLL,
|
||||||
|
|
||||||
|
MOUSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8 I[16] = {
|
u16 codes_g[BINDS_N] = {
|
||||||
|
0x25,
|
||||||
|
0x27,
|
||||||
|
0x28,
|
||||||
|
0x20,
|
||||||
|
'Z',
|
||||||
|
'X',
|
||||||
|
'A',
|
||||||
|
'C',
|
||||||
|
0x1B,
|
||||||
|
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
u16 types_g[BINDS_N] = {
|
||||||
|
BUTTON,
|
||||||
|
BUTTON,
|
||||||
|
BUTTON,
|
||||||
|
BUTTON,
|
||||||
|
BUTTON,
|
||||||
|
BUTTON,
|
||||||
|
BUTTON,
|
||||||
|
BUTTON,
|
||||||
|
BUTTON,
|
||||||
|
|
||||||
|
AXIS,
|
||||||
|
AXIS,
|
||||||
|
|
||||||
|
JOYSTICK
|
||||||
|
};
|
||||||
|
|
||||||
|
u8 I[16] = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
1, 1, 1, 1,
|
1, 1, 1, 1,
|
||||||
0, 0, 0, 0
|
0, 0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8 O[4] = {
|
u8 O[4] = {
|
||||||
1, 1,
|
1, 1,
|
||||||
1, 1
|
1, 1
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8 T[9] = {
|
u8 T[9] = {
|
||||||
0, 1, 0,
|
0, 1, 0,
|
||||||
1, 1, 1,
|
1, 1, 1,
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8 S[9] = {
|
u8 S[9] = {
|
||||||
0, 1, 1,
|
0, 1, 1,
|
||||||
1, 1, 0,
|
1, 1, 0,
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8 Z[9] = {
|
u8 Z[9] = {
|
||||||
1, 1, 0,
|
1, 1, 0,
|
||||||
0, 1, 1,
|
0, 1, 1,
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8 J[9] = {
|
u8 J[9] = {
|
||||||
1, 0, 0,
|
1, 0, 0,
|
||||||
1, 1, 1,
|
1, 1, 1,
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8 L[9] = {
|
u8 L[9] = {
|
||||||
0, 0, 1,
|
0, 0, 1,
|
||||||
1, 1, 1,
|
1, 1, 1,
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
|
|
Loading…
Reference in a new issue