mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	Compare commits
	
		
			22 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 75fabf3202 | ||
|  | 83c9da6fbb | ||
|  | 283bf244c4 | ||
|  | ccb0495a06 | ||
|  | ac5afca619 | ||
|  | e49673329d | ||
|  | 07ebed83bf | ||
|  | 1def87fdc3 | ||
|  | d91fed7dd4 | ||
|  | 5f2f7e70ef | ||
|  | 83432beff6 | ||
|  | 979b550178 | ||
|  | 9062a531f3 | ||
|  | e2a6fbcf3c | ||
|  | ec16931f3a | ||
|  | 0ec0ca7495 | ||
|  | 51fa7c9371 | ||
|  | 6c69f10fe7 | ||
|  | 206e85a356 | ||
|  | 8d7dd4867b | ||
|  | d1524f78fb | ||
|  | b26735d520 | 
							
								
								
									
										4
									
								
								.github/workflows/ccpp.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/ccpp.yml
									
									
									
									
										vendored
									
									
								
							| @@ -70,7 +70,9 @@ jobs: | ||||
|       uses: actions/upload-artifact@v4 | ||||
|       with: | ||||
|         name: ${{ github.event.repository.name }}.${{ github.sha }}.fluxengine.${{ runner.arch }}.pkg | ||||
|         path: fluxengine/FluxEngine.pkg | ||||
|         path: | | ||||
|           fluxengine/FluxEngine.pkg | ||||
|           fluxengine/FluxEngine.app.zip | ||||
|  | ||||
|   build-windows: | ||||
|     runs-on: windows-latest | ||||
|   | ||||
							
								
								
									
										3
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -99,6 +99,7 @@ jobs: | ||||
|       run: | | ||||
|         gmake | ||||
|         mv FluxEngine.pkg FluxEngine-${{ runner.arch }}.pkg | ||||
|         mv FluxEngine.app.zip FluxEngine-${{ runner.arch }}.app.zip | ||||
|  | ||||
|     - name: tag | ||||
|       uses: EndBug/latest-tag@latest | ||||
| @@ -115,6 +116,7 @@ jobs: | ||||
|         tag: dev | ||||
|         assets: |  | ||||
|           FluxEngine-${{ runner.arch }}.pkg | ||||
|           FluxEngine-${{ runner.arch }}.app.zip | ||||
|         fail-if-no-assets: false | ||||
|  | ||||
|     - name: release | ||||
| @@ -123,6 +125,7 @@ jobs: | ||||
|         name: Development build ${{ env.RELEASE_DATE }} | ||||
|         files: | | ||||
|           FluxEngine-${{ runner.arch }}.pkg | ||||
|           FluxEngine-${{ runner.arch }}.app.zip | ||||
|         tag_name: dev | ||||
|       env: | ||||
|         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||
|   | ||||
							
								
								
									
										3
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Makefile
									
									
									
									
									
								
							| @@ -26,7 +26,8 @@ ifeq ($(BUILDTYPE),windows) | ||||
| else | ||||
| 	CC = gcc | ||||
| 	CXX = g++ -std=c++20 | ||||
| 	CFLAGS = -g -O3 \ | ||||
| 	CFLAGS = -g -O3 | ||||
| 	CXXFLAGS += \ | ||||
| 		-Wno-deprecated-enum-float-conversion \ | ||||
| 		-Wno-deprecated-enum-enum-conversion | ||||
| 	LDFLAGS = | ||||
|   | ||||
| @@ -268,6 +268,10 @@ written by Dave Koelle, taken from | ||||
| https://web.archive.org/web/20210207124255/davekoelle.com/alphanum.html. It is | ||||
| MIT licensed. Please see the source for the full text. | ||||
|  | ||||
| As an exception, `dep/imgui` contains a partial copy of the Dear Imgui package, | ||||
| written by Omar Cornut, taken from https://github.com/WerWolv/ImHex. It is MIT | ||||
| licensed. Please see the contents of the directory for the full text. | ||||
|  | ||||
| __Important:__ Because of all these exceptions, if you distribute the | ||||
| FluxEngine package as a whole, you must comply with the terms of _all_ of the | ||||
| licensing terms. This means that __effectively the FluxEngine package is | ||||
|   | ||||
							
								
								
									
										33
									
								
								build.py
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								build.py
									
									
									
									
									
								
							| @@ -8,8 +8,9 @@ import config | ||||
| import re | ||||
|  | ||||
| # Hack for building on Fedora/WSL; executables get the .exe extension, | ||||
| # build the build system detects it as Linux. | ||||
| # but the build system detects it as Linux. | ||||
| import build.toolchain | ||||
|  | ||||
| toolchain.Toolchain.EXE = "$(EXT)" | ||||
|  | ||||
| package(name="protobuf_lib", package="protobuf") | ||||
| @@ -27,7 +28,7 @@ else: | ||||
|         ("acorndfs", "", "--200"), | ||||
|         ("agat", "", ""), | ||||
|         ("amiga", "", ""), | ||||
|         ("apple2", "", "--140 40track_drive"), | ||||
|         ("apple2", "", "--140 --drivetype=40"), | ||||
|         ("atarist", "", "--360"), | ||||
|         ("atarist", "", "--370"), | ||||
|         ("atarist", "", "--400"), | ||||
| @@ -37,17 +38,17 @@ else: | ||||
|         ("atarist", "", "--800"), | ||||
|         ("atarist", "", "--820"), | ||||
|         ("bk", "", ""), | ||||
|         ("brother", "", "--120 40track_drive"), | ||||
|         ("brother", "", "--120 --drivetype=40"), | ||||
|         ("brother", "", "--240"), | ||||
|         ( | ||||
|             "commodore", | ||||
|             "scripts/commodore1541_test.textpb", | ||||
|             "--171 40track_drive", | ||||
|             "--171 --drivetype=40", | ||||
|         ), | ||||
|         ( | ||||
|             "commodore", | ||||
|             "scripts/commodore1541_test.textpb", | ||||
|             "--192 40track_drive", | ||||
|             "--192 --drivetype=40", | ||||
|         ), | ||||
|         ("commodore", "", "--800"), | ||||
|         ("commodore", "", "--1620"), | ||||
| @@ -59,17 +60,17 @@ else: | ||||
|         ("ibm", "", "--1232"), | ||||
|         ("ibm", "", "--1440"), | ||||
|         ("ibm", "", "--1680"), | ||||
|         ("ibm", "", "--180 40track_drive"), | ||||
|         ("ibm", "", "--160 40track_drive"), | ||||
|         ("ibm", "", "--320 40track_drive"), | ||||
|         ("ibm", "", "--360 40track_drive"), | ||||
|         ("ibm", "", "--180 --drivetype=40"), | ||||
|         ("ibm", "", "--160 --drivetype=40"), | ||||
|         ("ibm", "", "--320 --drivetype=40"), | ||||
|         ("ibm", "", "--360 --drivetype=40"), | ||||
|         ("ibm", "", "--720_96"), | ||||
|         ("ibm", "", "--720_135"), | ||||
|         ("mac", "scripts/mac400_test.textpb", "--400"), | ||||
|         ("mac", "scripts/mac800_test.textpb", "--800"), | ||||
|         ("n88basic", "", ""), | ||||
|         ("rx50", "", ""), | ||||
|         ("tartu", "", "--390 40track_drive"), | ||||
|         ("tartu", "", "--390 --drivetype=40"), | ||||
|         ("tartu", "", "--780"), | ||||
|         ("tids990", "", ""), | ||||
|         ("victor9k", "", "--612"), | ||||
| @@ -92,7 +93,7 @@ else: | ||||
|                     + c[1] | ||||
|                     + "' '" | ||||
|                     + c[2] | ||||
|                     + "' $(dir $[outs[0]]) > /dev/null" | ||||
|                     + "' $[dirname(filenameof(outs[0]))] > /dev/null" | ||||
|                 ], | ||||
|                 label="CORPUSTEST", | ||||
|             ) | ||||
| @@ -104,10 +105,18 @@ export( | ||||
|     items={ | ||||
|         "fluxengine$(EXT)": "src+fluxengine", | ||||
|         "fluxengine-gui$(EXT)": "src/gui", | ||||
|         "fluxengine-gui2$(EXT)": "src/gui2", | ||||
|         "brother120tool$(EXT)": "tools+brother120tool", | ||||
|         "brother240tool$(EXT)": "tools+brother240tool", | ||||
|         "upgrade-flux-file$(EXT)": "tools+upgrade-flux-file", | ||||
|     } | ||||
|     | ({"FluxEngine.pkg": "src/gui+fluxengine_pkg"} if config.osx else {}), | ||||
|     | ( | ||||
|         { | ||||
|             "FluxEngine.pkg": "src/gui+fluxengine_pkg", | ||||
|             "FluxEngine.app.zip": "src/gui+fluxengine_app_zip", | ||||
|         } | ||||
|         if config.osx | ||||
|         else {} | ||||
|     ), | ||||
|     deps=["tests", "src/formats+docs", "scripts+mkdocindex"] + corpustests, | ||||
| ) | ||||
|   | ||||
							
								
								
									
										69
									
								
								build/ab.mk
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								build/ab.mk
									
									
									
									
									
								
							| @@ -15,16 +15,17 @@ HOSTCC ?= gcc | ||||
| HOSTCXX ?= g++ | ||||
| HOSTAR ?= ar | ||||
| HOSTCFLAGS ?= -g -Og | ||||
| HOSTCXXFLAGS ?= $(HOSTCFLAGS) | ||||
| HOSTLDFLAGS ?= -g | ||||
|  | ||||
| CC ?= $(HOSTCC) | ||||
| CXX ?= $(HOSTCXX) | ||||
| AR ?= $(HOSTAR) | ||||
| CFLAGS ?= $(HOSTCFLAGS) | ||||
| CXXFLAGS ?= $(CFLAGS) | ||||
| LDFLAGS ?= $(HOSTLDFLAGS) | ||||
|  | ||||
| export PKG_CONFIG | ||||
| export HOST_PKG_CONFIG | ||||
| NINJA ?= ninja | ||||
|  | ||||
| ifdef VERBOSE | ||||
| 	hide = | ||||
| @@ -63,37 +64,33 @@ EXT ?= | ||||
|  | ||||
| CWD=$(shell pwd) | ||||
|  | ||||
| ifeq ($(AB_ENABLE_PROGRESS_INFO),true) | ||||
| 	ifeq ($(PROGRESSINFO),) | ||||
| 	# The first make invocation here has to have its output discarded or else it | ||||
| 	# produces spurious 'Leaving directory' messages... don't know why. | ||||
| 	rulecount := $(strip $(shell $(MAKE) --no-print-directory -q $(OBJ)/build.mk PROGRESSINFO=1 > /dev/null \ | ||||
| 		&& $(MAKE) --no-print-directory -n $(MAKECMDGOALS) PROGRESSINFO=XXXPROGRESSINFOXXX | grep XXXPROGRESSINFOXXX | wc -l)) | ||||
| 	ruleindex := 1 | ||||
| 	PROGRESSINFO = "[$(ruleindex)/$(rulecount)]$(eval ruleindex := $(shell expr $(ruleindex) + 1)) " | ||||
| 	endif | ||||
| else | ||||
| 	PROGRESSINFO = "" | ||||
| endif | ||||
| define newline | ||||
|  | ||||
| PKG_CONFIG_HASHES = $(OBJ)/.pkg-config-hashes/target-$(word 1, $(shell $(PKG_CONFIG) --list-all | md5sum)) | ||||
| HOST_PKG_CONFIG_HASHES = $(OBJ)/.pkg-config-hashes/host-$(word 1, $(shell $(HOST_PKG_CONFIG) --list-all | md5sum)) | ||||
|  | ||||
| $(OBJ)/build.mk : $(PKG_CONFIG_HASHES) $(HOST_PKG_CONFIG_HASHES) | ||||
| $(PKG_CONFIG_HASHES) $(HOST_PKG_CONFIG_HASHES) &: | ||||
| 	$(hide) rm -rf $(OBJ)/.pkg-config-hashes | ||||
| 	$(hide) mkdir -p $(OBJ)/.pkg-config-hashes | ||||
| 	$(hide) touch $(PKG_CONFIG_HASHES) $(HOST_PKG_CONFIG_HASHES) | ||||
| endef | ||||
|  | ||||
| include $(OBJ)/build.mk | ||||
| define check_for_command | ||||
|   $(shell command -v $1 >/dev/null || (echo "Required command '$1' missing" >/dev/stderr && kill $$PPID)) | ||||
| endef | ||||
|  | ||||
| ifeq ($(OSX),yes) | ||||
| 	MAKEFLAGS += -r -j$(shell sysctl -n hw.logicalcpu) | ||||
| else | ||||
| 	MAKEFLAGS += -r -j$(shell nproc) | ||||
| endif | ||||
| $(call check_for_command,ninja) | ||||
| $(call check_for_command,cmp) | ||||
| $(call check_for_command,$(PYTHON)) | ||||
|  | ||||
| .DELETE_ON_ERROR: | ||||
| pkg-config-hash = $(shell ($(PKG_CONFIG) --list-all && $(HOST_PKG_CONFIG) --list-all) | md5sum) | ||||
| build-files = $(shell find . -name .obj -prune -o \( -name 'build.py' -a -type f \) -print) $(wildcard build/*.py) $(wildcard config.py) | ||||
| build-file-timestamps = $(shell ls -l $(build-files) | md5sum) | ||||
|  | ||||
| # Wipe the build file (forcing a regeneration) if the make environment is different. | ||||
| # (Conveniently, this includes the pkg-config hash calculated above.) | ||||
|  | ||||
| ignored-variables = MAKE_RESTARTS .VARIABLES MAKECMDGOALS MAKEFLAGS MFLAGS | ||||
| $(shell mkdir -p $(OBJ)) | ||||
| $(file >$(OBJ)/newvars.txt,$(foreach v,$(filter-out $(ignored-variables),$(.VARIABLES)),$(v)=$($(v))$(newline))) | ||||
| $(shell touch $(OBJ)/vars.txt) | ||||
| #$(shell diff -u $(OBJ)/vars.txt $(OBJ)/newvars.txt > /dev/stderr) | ||||
| $(shell cmp -s $(OBJ)/newvars.txt $(OBJ)/vars.txt || (rm -f $(OBJ)/build.ninja && echo "Environment changed --- regenerating" > /dev/stderr)) | ||||
| $(shell mv $(OBJ)/newvars.txt $(OBJ)/vars.txt) | ||||
|  | ||||
| .PHONY: update-ab | ||||
| update-ab: | ||||
| @@ -108,9 +105,15 @@ clean:: | ||||
| 	$(hide) rm -rf $(OBJ) | ||||
|  | ||||
| export PYTHONHASHSEED = 1 | ||||
| build-files = $(shell find . -name 'build.py') $(wildcard build/*.py) $(wildcard config.py) | ||||
| $(OBJ)/build.mk: Makefile $(build-files) build/ab.mk | ||||
| $(OBJ)/build.ninja $(OBJ)/build.targets &: | ||||
| 	@echo "AB" | ||||
| 	@mkdir -p $(OBJ) | ||||
| 	$(hide) $(PYTHON) -X pycache_prefix=$(OBJ)/__pycache__ build/ab.py -o $@ build.py \ | ||||
| 		|| rm -f $@ | ||||
| 	$(hide) $(PYTHON) -X pycache_prefix=$(OBJ)/__pycache__ build/ab.py \ | ||||
| 		-o $(OBJ) build.py \ | ||||
| 		-v $(OBJ)/vars.txt \ | ||||
| 		|| (rm -f $@ && false) | ||||
|  | ||||
| include $(OBJ)/build.targets | ||||
| .PHONY: $(ninja-targets) | ||||
| $(ninja-targets) &: $(OBJ)/build.ninja | ||||
| 	@echo "NINJA" | ||||
| 	+$(hide) $(NINJA) -f $(OBJ)/build.ninja $@ | ||||
|   | ||||
							
								
								
									
										244
									
								
								build/ab.py
									
									
									
									
									
								
							
							
						
						
									
										244
									
								
								build/ab.py
									
									
									
									
									
								
							| @@ -1,36 +1,32 @@ | ||||
| from collections import namedtuple | ||||
| from copy import copy | ||||
| from importlib.machinery import SourceFileLoader, PathFinder, ModuleSpec | ||||
| from os.path import * | ||||
| from pathlib import Path | ||||
| from typing import Iterable | ||||
| import argparse | ||||
| import ast | ||||
| import builtins | ||||
| from copy import copy | ||||
| import functools | ||||
| import hashlib | ||||
| import importlib | ||||
| import importlib.util | ||||
| from importlib.machinery import ( | ||||
|     SourceFileLoader, | ||||
|     PathFinder, | ||||
|     ModuleSpec, | ||||
| ) | ||||
| import inspect | ||||
| import os | ||||
| import re | ||||
| import string | ||||
| import sys | ||||
| import hashlib | ||||
| import re | ||||
| import ast | ||||
| from collections import namedtuple | ||||
| import types | ||||
|  | ||||
| VERBOSE_MK_FILE = False | ||||
| VERBOSE_NINJA_FILE = False | ||||
|  | ||||
| verbose = False | ||||
| quiet = False | ||||
| cwdStack = [""] | ||||
| targets = {} | ||||
| unmaterialisedTargets = {}  # dict, not set, to get consistent ordering | ||||
| materialisingStack = [] | ||||
| defaultGlobals = {} | ||||
| globalId = 1 | ||||
| wordCache = {} | ||||
| outputTargets = set() | ||||
|  | ||||
| RE_FORMAT_SPEC = re.compile( | ||||
|     r"(?:(?P<fill>[\s\S])?(?P<align>[<>=^]))?" | ||||
| @@ -52,6 +48,15 @@ sys.path += ["."] | ||||
| old_import = builtins.__import__ | ||||
|  | ||||
|  | ||||
| class Environment(types.SimpleNamespace): | ||||
|     def setdefault(self, name, value): | ||||
|         if not hasattr(self, name): | ||||
|             setattr(self, name, value) | ||||
|  | ||||
|  | ||||
| G = Environment() | ||||
|  | ||||
|  | ||||
| class PathFinderImpl(PathFinder): | ||||
|     def find_spec(self, fullname, path, target=None): | ||||
|         # The second test here is needed for Python 3.9. | ||||
| @@ -103,26 +108,71 @@ def error(message): | ||||
|  | ||||
|  | ||||
| class BracketedFormatter(string.Formatter): | ||||
|     def __init__(self, op, cl): | ||||
|         self.op = op | ||||
|         self.cl = cl | ||||
|  | ||||
|     def _undo_escaped_dollar(self, s): | ||||
|         return s.replace(f"$${self.op}", f"${self.op}") | ||||
|  | ||||
|     def parse(self, format_string): | ||||
|         while format_string: | ||||
|             left, *right = format_string.split("$[", 1) | ||||
|             if not right: | ||||
|                 yield (left, None, None, None) | ||||
|             m = re.search(f"(?:[^$]|^)()\\$\\{self.op}()", format_string) | ||||
|             if not m: | ||||
|                 yield ( | ||||
|                     self._undo_escaped_dollar(format_string), | ||||
|                     None, | ||||
|                     None, | ||||
|                     None, | ||||
|                 ) | ||||
|                 break | ||||
|             right = right[0] | ||||
|             left = format_string[: m.start(1)] | ||||
|             right = format_string[m.end(2) :] | ||||
|  | ||||
|             offset = len(right) + 1 | ||||
|             try: | ||||
|                 ast.parse(right) | ||||
|             except SyntaxError as e: | ||||
|                 if not str(e).startswith("unmatched ']'"): | ||||
|                 if not str(e).startswith(f"unmatched '{self.cl}'"): | ||||
|                     raise e | ||||
|                 offset = e.offset | ||||
|  | ||||
|             expr = right[0 : offset - 1] | ||||
|             format_string = right[offset:] | ||||
|  | ||||
|             yield (left if left else None, expr, None, None) | ||||
|             yield ( | ||||
|                 self._undo_escaped_dollar(left) if left else None, | ||||
|                 expr, | ||||
|                 None, | ||||
|                 None, | ||||
|             ) | ||||
|  | ||||
|  | ||||
| class GlobalFormatter(BracketedFormatter): | ||||
|     def __init__(self): | ||||
|         super().__init__("(", ")") | ||||
|  | ||||
|     def get_field(self, name, a1, a2): | ||||
|         return ( | ||||
|             getattr(G, name), | ||||
|             False, | ||||
|         ) | ||||
|  | ||||
|     def format_field(self, value, format_spec): | ||||
|         if not value: | ||||
|             return "" | ||||
|         return str(value) | ||||
|  | ||||
|  | ||||
| globalFormatter = GlobalFormatter() | ||||
|  | ||||
|  | ||||
| def substituteGlobalVariables(value): | ||||
|     while True: | ||||
|         oldValue = value | ||||
|         value = globalFormatter.format(value) | ||||
|         if value == oldValue: | ||||
|             return value | ||||
|  | ||||
|  | ||||
| def Rule(func): | ||||
| @@ -187,12 +237,10 @@ def _isiterable(xs): | ||||
|  | ||||
| class Target: | ||||
|     def __init__(self, cwd, name): | ||||
|         if verbose: | ||||
|             print("rule('%s', cwd='%s'" % (name, cwd)) | ||||
|         self.name = name | ||||
|         self.localname = self.name.rsplit("+")[-1] | ||||
|         self.traits = set() | ||||
|         self.dir = join("$(OBJ)", name) | ||||
|         self.dir = join(G.OBJ, name) | ||||
|         self.ins = [] | ||||
|         self.outs = [] | ||||
|         self.deps = [] | ||||
| @@ -213,6 +261,9 @@ class Target: | ||||
|  | ||||
|     def templateexpand(selfi, s): | ||||
|         class Formatter(BracketedFormatter): | ||||
|             def __init__(self): | ||||
|                 super().__init__("[", "]") | ||||
|  | ||||
|             def get_field(self, name, a1, a2): | ||||
|                 return ( | ||||
|                     eval(name, selfi.callback.__globals__, selfi.args), | ||||
| @@ -232,7 +283,8 @@ class Target: | ||||
|                     [selfi.templateexpand(f) for f in filenamesof(value)] | ||||
|                 ) | ||||
|  | ||||
|         return Formatter().format(s) | ||||
|         s = Formatter().format(s) | ||||
|         return substituteGlobalVariables(s) | ||||
|  | ||||
|     def materialise(self, replacing=False): | ||||
|         if self not in unmaterialisedTargets: | ||||
| @@ -341,10 +393,10 @@ def targetof(value, cwd=None): | ||||
|             elif value.startswith("./"): | ||||
|                 value = normpath(join(cwd, value)) | ||||
|         # Explicit directories are always raw files. | ||||
|         elif value.endswith("/"): | ||||
|         if value.endswith("/"): | ||||
|             return _filetarget(value, cwd) | ||||
|         # Anything starting with a variable expansion is always a raw file. | ||||
|         elif value.startswith("$"): | ||||
|         # Anything in .obj is a raw file. | ||||
|         elif value.startswith(outputdir) or value.startswith(G.OBJ): | ||||
|             return _filetarget(value, cwd) | ||||
|  | ||||
|         # If this is not a rule lookup... | ||||
| @@ -467,78 +519,67 @@ def emit(*args, into=None): | ||||
|     if into is not None: | ||||
|         into += [s] | ||||
|     else: | ||||
|         outputFp.write(s) | ||||
|         ninjaFp.write(s) | ||||
|  | ||||
|  | ||||
| def shell(*args): | ||||
|     s = "".join(args) + "\n" | ||||
|     shellFp.write(s) | ||||
|  | ||||
|  | ||||
| def emit_rule(self, ins, outs, cmds=[], label=None): | ||||
|     name = self.name | ||||
|     fins_list = filenamesof(ins) | ||||
|     fins = set(fins_list) | ||||
|     fouts = filenamesof(outs) | ||||
|     nonobjs = [f for f in fouts if not f.startswith("$(OBJ)")] | ||||
|     fins = [self.templateexpand(f) for f in set(filenamesof(ins))] | ||||
|     fouts = [self.templateexpand(f) for f in filenamesof(outs)] | ||||
|  | ||||
|     global outputTargets | ||||
|     outputTargets.update(fouts) | ||||
|     outputTargets.add(name) | ||||
|  | ||||
|     emit("") | ||||
|     if VERBOSE_MK_FILE: | ||||
|     if VERBOSE_NINJA_FILE: | ||||
|         for k, v in self.args.items(): | ||||
|             emit(f"# {k} = {v}") | ||||
|  | ||||
|     lines = [] | ||||
|     if nonobjs: | ||||
|         emit("clean::", into=lines) | ||||
|         emit("\t$(hide) rm -f", *nonobjs, into=lines) | ||||
|  | ||||
|     hashable = cmds + fins_list + fouts | ||||
|     hash = hashlib.sha1(bytes("\n".join(hashable), "utf-8")).hexdigest() | ||||
|     hashfile = join(self.dir, f"hash_{hash}") | ||||
|  | ||||
|     global globalId | ||||
|     emit(".PHONY:", name, into=lines) | ||||
|     if outs: | ||||
|         outsn = globalId | ||||
|         globalId = globalId + 1 | ||||
|         insn = globalId | ||||
|         globalId = globalId + 1 | ||||
|  | ||||
|         emit(f"OUTS_{outsn}", "=", *fouts, into=lines) | ||||
|         emit(f"INS_{insn}", "=", *fins, into=lines) | ||||
|         emit(name, ":", f"$(OUTS_{outsn})", into=lines) | ||||
|         emit(hashfile, ":", into=lines) | ||||
|         emit(f"\t@mkdir -p {self.dir}", into=lines) | ||||
|         emit(f"\t@touch {hashfile}", into=lines) | ||||
|         emit( | ||||
|             f"$(OUTS_{outsn})", | ||||
|             "&:" if len(fouts) > 1 else ":", | ||||
|             f"$(INS_{insn})", | ||||
|             hashfile, | ||||
|             into=lines, | ||||
|         ) | ||||
|  | ||||
|         if label: | ||||
|             emit("\t$(hide)", "$(ECHO) $(PROGRESSINFO)" + label, into=lines) | ||||
|         os.makedirs(self.dir, exist_ok=True) | ||||
|         rule = [] | ||||
|  | ||||
|         sandbox = join(self.dir, "sandbox") | ||||
|         emit("\t$(hide)", f"rm -rf {sandbox}", into=lines) | ||||
|         emit(f"rm -rf {sandbox}", into=rule) | ||||
|         emit( | ||||
|             "\t$(hide)", | ||||
|             "$(PYTHON) build/_sandbox.py --link -s", | ||||
|             sandbox, | ||||
|             f"$(INS_{insn})", | ||||
|             into=lines, | ||||
|             f"{G.PYTHON} build/_sandbox.py --link -s", sandbox, *fins, into=rule | ||||
|         ) | ||||
|         for c in cmds: | ||||
|             emit(f"\t$(hide) cd {sandbox} && (", c, ")", into=lines) | ||||
|             emit(f"(cd {sandbox} &&", c, ")", into=rule) | ||||
|         emit( | ||||
|             "\t$(hide)", | ||||
|             "$(PYTHON) build/_sandbox.py --export -s", | ||||
|             f"{G.PYTHON} build/_sandbox.py --export -s", | ||||
|             sandbox, | ||||
|             f"$(OUTS_{outsn})", | ||||
|             into=lines, | ||||
|             *fouts, | ||||
|             into=rule, | ||||
|         ) | ||||
|  | ||||
|         ruletext = "".join(rule) | ||||
|         if len(ruletext) > 7000: | ||||
|             rulehash = hashlib.sha1(ruletext.encode()).hexdigest() | ||||
|  | ||||
|             rulef = join(self.dir, f"rule-{rulehash}.sh") | ||||
|             with open(rulef, "wt") as fp: | ||||
|                 fp.write(ruletext) | ||||
|  | ||||
|             emit("build", *fouts, ":rule", *fins, rulef) | ||||
|             emit(" command=sh", rulef) | ||||
|         else: | ||||
|             emit("build", *fouts, ":rule", *fins) | ||||
|             emit(" command=", "&&".join([s.strip() for s in rule])) | ||||
|         if label: | ||||
|             emit(" description=", label) | ||||
|         emit("build", name, ":phony", *fouts) | ||||
|  | ||||
|     else: | ||||
|         assert len(cmds) == 0, "rules with no outputs cannot have commands" | ||||
|         emit(name, ":", *fins, into=lines) | ||||
|         emit("build", name, ":phony", *fins) | ||||
|  | ||||
|     outputFp.write("".join(lines)) | ||||
|     emit("") | ||||
|  | ||||
|  | ||||
| @@ -585,47 +626,65 @@ def export(self, name=None, items: TargetsMap = {}, deps: Targets = []): | ||||
|         dest = self.targetof(dest) | ||||
|         outs += [dest] | ||||
|  | ||||
|         destf = filenameof(dest) | ||||
|         destf = self.templateexpand(filenameof(dest)) | ||||
|         outputTargets.update([destf]) | ||||
|  | ||||
|         srcs = filenamesof([src]) | ||||
|         assert ( | ||||
|             len(srcs) == 1 | ||||
|         ), "a dependency of an exported file must have exactly one output file" | ||||
|         srcf = self.templateexpand(srcs[0]) | ||||
|  | ||||
|         subrule = simplerule( | ||||
|             name=f"{self.localname}/{destf}", | ||||
|             cwd=self.cwd, | ||||
|             ins=[srcs[0]], | ||||
|             outs=[destf], | ||||
|             commands=["$(CP) -H %s %s" % (srcs[0], destf)], | ||||
|             label="", | ||||
|             commands=["$(CP) -H %s %s" % (srcf, destf)], | ||||
|             label="EXPORT", | ||||
|         ) | ||||
|         subrule.materialise() | ||||
|  | ||||
|     self.ins = [] | ||||
|     self.outs = deps + outs | ||||
|     outputTargets.add(name) | ||||
|  | ||||
|     emit("") | ||||
|     emit(".PHONY:", name) | ||||
|     emit(name, ":", *filenamesof(outs + deps)) | ||||
|     emit( | ||||
|         "build", | ||||
|         name, | ||||
|         ":phony", | ||||
|         *[self.templateexpand(f) for f in filenamesof(outs + deps)], | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def main(): | ||||
|     parser = argparse.ArgumentParser() | ||||
|     parser.add_argument("-v", "--verbose", action="store_true") | ||||
|     parser.add_argument("-q", "--quiet", action="store_true") | ||||
|     parser.add_argument("-o", "--output") | ||||
|     parser.add_argument("-v", "--varfile") | ||||
|     parser.add_argument("-o", "--outputdir") | ||||
|     parser.add_argument("-D", "--define", action="append", default=[]) | ||||
|     parser.add_argument("files", nargs="+") | ||||
|     args = parser.parse_args() | ||||
|  | ||||
|     global verbose | ||||
|     verbose = args.verbose | ||||
|  | ||||
|     global quiet | ||||
|     quiet = args.quiet | ||||
|  | ||||
|     global outputFp | ||||
|     outputFp = open(args.output, "wt") | ||||
|     vardefs = args.define | ||||
|     if args.varfile: | ||||
|         with open(args.varfile, "rt") as fp: | ||||
|             vardefs = vardefs + list(fp) | ||||
|  | ||||
|     for line in vardefs: | ||||
|         if "=" in line: | ||||
|             name, value = line.split("=", 1) | ||||
|             G.setdefault(name.strip(), value.strip()) | ||||
|  | ||||
|     global ninjaFp, shellFp, outputdir | ||||
|     outputdir = args.outputdir | ||||
|     G.setdefault("OBJ", outputdir) | ||||
|     ninjaFp = open(outputdir + "/build.ninja", "wt") | ||||
|     ninjaFp.write(f"include build/ab.ninja\n") | ||||
|  | ||||
|     for k in ["Rule"]: | ||||
|         defaultGlobals[k] = globals()[k] | ||||
| @@ -640,7 +699,10 @@ def main(): | ||||
|     while unmaterialisedTargets: | ||||
|         t = next(iter(unmaterialisedTargets)) | ||||
|         t.materialise() | ||||
|     emit("AB_LOADED = 1\n") | ||||
|  | ||||
|     with open(outputdir + "/build.targets", "wt") as fp: | ||||
|         fp.write("ninja-targets =") | ||||
|         fp.write(substituteGlobalVariables(" ".join(outputTargets))) | ||||
|  | ||||
|  | ||||
| main() | ||||
|   | ||||
							
								
								
									
										55
									
								
								build/c.py
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								build/c.py
									
									
									
									
									
								
							| @@ -7,23 +7,22 @@ from build.ab import ( | ||||
|     flatten, | ||||
|     simplerule, | ||||
|     emit, | ||||
|     G, | ||||
| ) | ||||
| from build.utils import filenamesmatchingof, stripext, collectattrs | ||||
| from build.utils import stripext, collectattrs | ||||
| from build.toolchain import Toolchain, HostToolchain | ||||
| from os.path import * | ||||
|  | ||||
| emit( | ||||
|     """ | ||||
| ifeq ($(OSX),no) | ||||
| STARTGROUP ?= -Wl,--start-group | ||||
| ENDGROUP ?= -Wl,--end-group | ||||
| endif | ||||
| """ | ||||
| ) | ||||
| if G.OSX != "yes": | ||||
|     G.STARTGROUP = "-Wl,--start-group" | ||||
|     G.ENDGROUP = "-Wl,--end-group" | ||||
| else: | ||||
|     G.STARTGROUP = "" | ||||
|     G.ENDGROUP = "" | ||||
|  | ||||
| Toolchain.CC = ["$(CC) -c -o $[outs[0]] $[ins[0]] $(CFLAGS) $[cflags]"] | ||||
| Toolchain.CPP = ["$(CC) -E -P -o $[outs] $[cflags] -x c $[ins]"] | ||||
| Toolchain.CXX = ["$(CXX) -c -o $[outs[0]] $[ins[0]] $(CFLAGS) $[cflags]"] | ||||
| Toolchain.CXX = ["$(CXX) -c -o $[outs[0]] $[ins[0]] $(CXXFLAGS) $[cflags]"] | ||||
| Toolchain.AR = ["$(AR) cqs $[outs[0]] $[ins]"] | ||||
| Toolchain.ARXX = ["$(AR) cqs $[outs[0]] $[ins]"] | ||||
| Toolchain.CLINK = [ | ||||
| @@ -70,13 +69,9 @@ def _toolchain_find_header_targets(deps, initial=[]): | ||||
| Toolchain.find_c_header_targets = _toolchain_find_header_targets | ||||
|  | ||||
|  | ||||
| HostToolchain.CC = [ | ||||
|     "$(HOSTCC) -c -o $[outs[0]] $[ins[0]] $(HOSTCFLAGS) $[cflags]" | ||||
| ] | ||||
| HostToolchain.CC = ["$(HOSTCC) -c -o $[outs[0]] $[ins[0]] $(HOSTCFLAGS) $[cflags]"] | ||||
| HostToolchain.CPP = ["$(HOSTCC) -E -P -o $[outs] $[cflags] -x c $[ins]"] | ||||
| HostToolchain.CXX = [ | ||||
|     "$(HOSTCXX) -c -o $[outs[0]] $[ins[0]] $(HOSTCFLAGS) $[cflags]" | ||||
| ] | ||||
| HostToolchain.CXX = ["$(HOSTCXX) -c -o $[outs[0]] $[ins[0]] $(HOSTCFLAGS) $[cflags]"] | ||||
| HostToolchain.AR = ["$(HOSTAR) cqs $[outs[0]] $[ins]"] | ||||
| HostToolchain.ARXX = ["$(HOSTAR) cqs $[outs[0]] $[ins]"] | ||||
| HostToolchain.CLINK = [ | ||||
| @@ -102,9 +97,7 @@ def _indirect(deps, name): | ||||
|     return r | ||||
|  | ||||
|  | ||||
| def cfileimpl( | ||||
|     self, name, srcs, deps, suffix, commands, label, toolchain, cflags | ||||
| ): | ||||
| def cfileimpl(self, name, srcs, deps, suffix, commands, label, toolchain, cflags): | ||||
|     outleaf = "=" + stripext(basename(filenameof(srcs[0]))) + suffix | ||||
|  | ||||
|     hdr_deps = toolchain.find_c_header_targets(deps) | ||||
| @@ -114,9 +107,7 @@ def cfileimpl( | ||||
|         if ("cheader_deps" not in d.args) and ("clibrary_deps" not in d.args) | ||||
|     ] | ||||
|     hdr_files = collectattrs(targets=hdr_deps, name="cheader_files") | ||||
|     cflags = collectattrs( | ||||
|         targets=hdr_deps, name="caller_cflags", initial=cflags | ||||
|     ) | ||||
|     cflags = collectattrs(targets=hdr_deps, name="caller_cflags", initial=cflags) | ||||
|  | ||||
|     t = simplerule( | ||||
|         replaces=self, | ||||
| @@ -194,7 +185,7 @@ def findsources(self, srcs, deps, cflags, filerule, toolchain, cwd): | ||||
|     for s in flatten(srcs): | ||||
|         objs += [ | ||||
|             filerule( | ||||
|                 name=join(self.localname, _removeprefix(f, "$(OBJ)/")), | ||||
|                 name=join(self.localname, _removeprefix(f, G.OBJ + "/")), | ||||
|                 srcs=[f], | ||||
|                 deps=deps, | ||||
|                 cflags=sorted(set(cflags)), | ||||
| @@ -239,9 +230,7 @@ def libraryimpl( | ||||
|         i = 0 | ||||
|         for dest, src in hdrs.items(): | ||||
|             s = filenamesof([src]) | ||||
|             assert ( | ||||
|                 len(s) == 1 | ||||
|             ), "the target of a header must return exactly one file" | ||||
|             assert len(s) == 1, "the target of a header must return exactly one file" | ||||
|  | ||||
|             cs += [f"$(CP) $[ins[{i}]] $[outs[{i}]]"] | ||||
|             outs += ["=" + dest] | ||||
| @@ -431,20 +420,16 @@ def programimpl( | ||||
|     label, | ||||
|     filerule, | ||||
| ): | ||||
|     cfiles = findsources( | ||||
|         self, srcs, deps, cflags, filerule, toolchain, self.cwd | ||||
|     ) | ||||
|     cfiles = findsources(self, srcs, deps, cflags, filerule, toolchain, self.cwd) | ||||
|  | ||||
|     lib_deps = toolchain.find_c_library_targets(deps) | ||||
|     libs = collectattrs(targets=lib_deps, name="clibrary_files") | ||||
|     ldflags = collectattrs( | ||||
|         targets=lib_deps, name="caller_ldflags", initial=ldflags | ||||
|     ) | ||||
|     ldflags = collectattrs(targets=lib_deps, name="caller_ldflags", initial=ldflags) | ||||
|  | ||||
|     simplerule( | ||||
|         replaces=self, | ||||
|         ins=cfiles + libs, | ||||
|         outs=[f"={self.localname}{toolchain.EXE}"], | ||||
|         outs=[f"={self.localname}$(EXT)"], | ||||
|         deps=deps, | ||||
|         label=label, | ||||
|         commands=commands, | ||||
| @@ -558,9 +543,7 @@ def hostcxxprogram( | ||||
|  | ||||
| def _cppfileimpl(self, name, srcs, deps, cflags, toolchain): | ||||
|     hdr_deps = _indirect(deps, "cheader_deps") | ||||
|     cflags = collectattrs( | ||||
|         targets=hdr_deps, name="caller_cflags", initial=cflags | ||||
|     ) | ||||
|     cflags = collectattrs(targets=hdr_deps, name="caller_cflags", initial=cflags) | ||||
|  | ||||
|     simplerule( | ||||
|         replaces=self, | ||||
|   | ||||
							
								
								
									
										10
									
								
								build/pkg.py
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								build/pkg.py
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| from build.ab import Rule, Target | ||||
| from build.ab import Rule, Target, G | ||||
| import os | ||||
| import subprocess | ||||
|  | ||||
| @@ -31,8 +31,8 @@ class _PkgConfig: | ||||
|         return self.package_properties[p] | ||||
|  | ||||
|  | ||||
| TargetPkgConfig = _PkgConfig(os.getenv("PKG_CONFIG")) | ||||
| HostPkgConfig = _PkgConfig(os.getenv("HOST_PKG_CONFIG")) | ||||
| TargetPkgConfig = _PkgConfig(G.PKG_CONFIG) | ||||
| HostPkgConfig = _PkgConfig(G.HOST_PKG_CONFIG) | ||||
|  | ||||
|  | ||||
| def _package(self, name, package, fallback, pkgconfig): | ||||
| @@ -49,9 +49,7 @@ def _package(self, name, package, fallback, pkgconfig): | ||||
|         self.traits.update({"clibrary", "cxxlibrary"}) | ||||
|         return | ||||
|  | ||||
|     assert ( | ||||
|         fallback | ||||
|     ), f"Required package '{package}' not installed when materialising target '$[name]'" | ||||
|     assert fallback, f"Required package '{package}' not installed" | ||||
|  | ||||
|     if "cheader_deps" in fallback.args: | ||||
|         self.args["cheader_deps"] = fallback.args["cheader_deps"] | ||||
|   | ||||
| @@ -1,14 +1,10 @@ | ||||
| from build.ab import Rule, Targets, emit, simplerule, filenamesof | ||||
| from build.ab import Rule, Targets, emit, simplerule, filenamesof, G | ||||
| from build.utils import filenamesmatchingof, collectattrs | ||||
| from os.path import join, abspath, dirname, relpath | ||||
| from build.pkg import has_package | ||||
|  | ||||
| emit( | ||||
|     """ | ||||
| PROTOC ?= protoc | ||||
| HOSTPROTOC ?= protoc | ||||
| """ | ||||
| ) | ||||
| G.setdefault("PROTOC", "protoc") | ||||
| G.setdefault("HOSTPROTOC", "hostprotoc") | ||||
|  | ||||
| assert has_package("protobuf"), "required package 'protobuf' not installed" | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,5 @@ | ||||
| import platform | ||||
|  | ||||
| _is_windows = (platform.system() == "Windows") | ||||
|  | ||||
| class Toolchain: | ||||
|     PREFIX = "" | ||||
|     EXE = ".exe" if _is_windows else "" | ||||
|  | ||||
|  | ||||
| class HostToolchain(Toolchain): | ||||
|   | ||||
| @@ -11,6 +11,7 @@ from build.ab import ( | ||||
| from os.path import relpath, splitext, join, basename, isfile | ||||
| from glob import iglob | ||||
| import fnmatch | ||||
| import subprocess | ||||
|  | ||||
|  | ||||
| def filenamesmatchingof(xs, pattern): | ||||
| @@ -51,6 +52,11 @@ def itemsof(pattern, root=None, cwd=None): | ||||
|     return result | ||||
|  | ||||
|  | ||||
| def shell(args): | ||||
|     r = subprocess.check_output(args) | ||||
|     return r.decode("utf-8").strip() | ||||
|  | ||||
|  | ||||
| @Rule | ||||
| def objectify(self, name, src: Target, symbol): | ||||
|     simplerule( | ||||
|   | ||||
| @@ -7,9 +7,7 @@ from build.ab import ( | ||||
|  | ||||
|  | ||||
| @Rule | ||||
| def zip( | ||||
|     self, name, flags="", items: TargetsMap = {}, extension="zip", label="ZIP" | ||||
| ): | ||||
| def zip(self, name, flags="", items: TargetsMap = {}, extension="zip", label="ZIP"): | ||||
|     cs = ["$(PYTHON) build/_zip.py -z $[outs]"] | ||||
|  | ||||
|     ins = [] | ||||
|   | ||||
							
								
								
									
										21
									
								
								dep/imgui/LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								dep/imgui/LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| The MIT License (MIT) | ||||
|  | ||||
| Copyright (c) 2014-2025 Omar Cornut | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
							
								
								
									
										1006
									
								
								dep/imgui/backends/imgui_impl_glfw.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1006
									
								
								dep/imgui/backends/imgui_impl_glfw.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										70
									
								
								dep/imgui/backends/imgui_impl_glfw.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								dep/imgui/backends/imgui_impl_glfw.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| // dear imgui: Platform Backend for GLFW | ||||
| // This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..) | ||||
| // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) | ||||
|  | ||||
| // Implemented features: | ||||
| //  [X] Platform: Clipboard support. | ||||
| //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only). | ||||
| //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5] | ||||
| //  [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. | ||||
| //  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. | ||||
| //  [X] Multiple Dear ImGui contexts support. | ||||
| // Missing features or Issues: | ||||
| //  [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround. | ||||
| //  [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors. | ||||
|  | ||||
| // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. | ||||
| // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | ||||
| // Learn about Dear ImGui: | ||||
| // - FAQ                  https://dearimgui.com/faq | ||||
| // - Getting Started      https://dearimgui.com/getting-started | ||||
| // - Documentation        https://dearimgui.com/docs (same as your local docs/ folder). | ||||
| // - Introduction, links and more at the top of imgui.cpp | ||||
|  | ||||
| #pragma once | ||||
| #include "imgui.h"      // IMGUI_IMPL_API | ||||
| #ifndef IMGUI_DISABLE | ||||
|  | ||||
| struct GLFWwindow; | ||||
| struct GLFWmonitor; | ||||
|  | ||||
| // Follow "Getting Started" link and check examples/ folder to learn about using backends! | ||||
| IMGUI_IMPL_API bool     ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks); | ||||
| IMGUI_IMPL_API bool     ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks); | ||||
| IMGUI_IMPL_API bool     ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_Shutdown(); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_NewFrame(); | ||||
|  | ||||
| // Emscripten related initialization phase methods (call after ImGui_ImplGlfw_InitForOpenGL) | ||||
| #ifdef __EMSCRIPTEN__ | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector); | ||||
| //static inline void    ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { ImGui_ImplGlfw_InstallEmscriptenCallbacks(nullptr, canvas_selector); } } // Renamed in 1.91.0 | ||||
| #endif | ||||
|  | ||||
| // GLFW callbacks install | ||||
| // - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any. | ||||
| // - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks. | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window); | ||||
|  | ||||
| // GFLW callbacks options: | ||||
| // - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user) | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows); | ||||
|  | ||||
| // GLFW callbacks (individual callbacks to call yourself if you didn't install callbacks) | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused);        // Since 1.84 | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered);        // Since 1.84 | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y);   // Since 1.87 | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event); | ||||
|  | ||||
| // GLFW helpers | ||||
| IMGUI_IMPL_API void     ImGui_ImplGlfw_Sleep(int milliseconds); | ||||
| IMGUI_IMPL_API float    ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window); | ||||
| IMGUI_IMPL_API float    ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor); | ||||
|  | ||||
|  | ||||
| #endif // #ifndef IMGUI_DISABLE | ||||
							
								
								
									
										1050
									
								
								dep/imgui/backends/imgui_impl_opengl3.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1050
									
								
								dep/imgui/backends/imgui_impl_opengl3.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										68
									
								
								dep/imgui/backends/imgui_impl_opengl3.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								dep/imgui/backends/imgui_impl_opengl3.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| // dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline | ||||
| // - Desktop GL: 2.x 3.x 4.x | ||||
| // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) | ||||
| // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) | ||||
|  | ||||
| // Implemented features: | ||||
| //  [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef! | ||||
| //  [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!] | ||||
| //  [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures). | ||||
|  | ||||
| // About WebGL/ES: | ||||
| // - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES. | ||||
| // - This is done automatically on iOS, Android and Emscripten targets. | ||||
| // - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h. | ||||
|  | ||||
| // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. | ||||
| // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. | ||||
| // Learn about Dear ImGui: | ||||
| // - FAQ                  https://dearimgui.com/faq | ||||
| // - Getting Started      https://dearimgui.com/getting-started | ||||
| // - Documentation        https://dearimgui.com/docs (same as your local docs/ folder). | ||||
| // - Introduction, links and more at the top of imgui.cpp | ||||
|  | ||||
| // About GLSL version: | ||||
| //  The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string. | ||||
| //  On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es" | ||||
| //  Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp. | ||||
|  | ||||
| #pragma once | ||||
| #include "imgui.h"      // IMGUI_IMPL_API | ||||
| #ifndef IMGUI_DISABLE | ||||
|  | ||||
| // Follow "Getting Started" link and check examples/ folder to learn about using backends! | ||||
| IMGUI_IMPL_API bool     ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr); | ||||
| IMGUI_IMPL_API void     ImGui_ImplOpenGL3_Shutdown(); | ||||
| IMGUI_IMPL_API void     ImGui_ImplOpenGL3_NewFrame(); | ||||
| IMGUI_IMPL_API void     ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); | ||||
|  | ||||
| // (Optional) Called by Init/NewFrame/Shutdown | ||||
| IMGUI_IMPL_API bool     ImGui_ImplOpenGL3_CreateDeviceObjects(); | ||||
| IMGUI_IMPL_API void     ImGui_ImplOpenGL3_DestroyDeviceObjects(); | ||||
|  | ||||
| // (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually. | ||||
| IMGUI_IMPL_API void     ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex); | ||||
|  | ||||
| // Configuration flags to add in your imconfig file: | ||||
| //#define IMGUI_IMPL_OPENGL_ES2     // Enable ES 2 (Auto-detected on Emscripten) | ||||
| //#define IMGUI_IMPL_OPENGL_ES3     // Enable ES 3 (Auto-detected on iOS/Android) | ||||
|  | ||||
| // You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. | ||||
| #if !defined(IMGUI_IMPL_OPENGL_ES2) \ | ||||
|  && !defined(IMGUI_IMPL_OPENGL_ES3) | ||||
|  | ||||
| // Try to detect GLES on matching platforms | ||||
| #if defined(__APPLE__) | ||||
| #include <TargetConditionals.h> | ||||
| #endif | ||||
| #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__)) | ||||
| #define IMGUI_IMPL_OPENGL_ES3               // iOS, Android  -> GL ES 3, "#version 300 es" | ||||
| #elif defined(__EMSCRIPTEN__) || defined(__amigaos4__) | ||||
| #define IMGUI_IMPL_OPENGL_ES2               // Emscripten    -> GL ES 2, "#version 100" | ||||
| #else | ||||
| // Otherwise imgui_impl_opengl3_loader.h will be used. | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #endif // #ifndef IMGUI_DISABLE | ||||
							
								
								
									
										929
									
								
								dep/imgui/backends/imgui_impl_opengl3_loader.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										929
									
								
								dep/imgui/backends/imgui_impl_opengl3_loader.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,929 @@ | ||||
| //----------------------------------------------------------------------------- | ||||
| // About imgui_impl_opengl3_loader.h: | ||||
| // | ||||
| // We embed our own OpenGL loader to not require user to provide their own or to have to use ours, | ||||
| // which proved to be endless problems for users. | ||||
| // Our loader is custom-generated, based on gl3w but automatically filtered to only include | ||||
| // enums/functions that we use in our imgui_impl_opengl3.cpp source file in order to be small. | ||||
| // | ||||
| // YOU SHOULD NOT NEED TO INCLUDE/USE THIS DIRECTLY. THIS IS USED BY imgui_impl_opengl3.cpp ONLY. | ||||
| // THE REST OF YOUR APP SHOULD USE A DIFFERENT GL LOADER: ANY GL LOADER OF YOUR CHOICE. | ||||
| // | ||||
| // IF YOU GET BUILD ERRORS IN THIS FILE (commonly macro redefinitions or function redefinitions): | ||||
| // IT LIKELY MEANS THAT YOU ARE BUILDING 'imgui_impl_opengl3.cpp' OR INCLUDING 'imgui_impl_opengl3_loader.h' | ||||
| // IN THE SAME COMPILATION UNIT AS ONE OF YOUR FILE WHICH IS USING A THIRD-PARTY OPENGL LOADER. | ||||
| // (e.g. COULD HAPPEN IF YOU ARE DOING A UNITY/JUMBO BUILD, OR INCLUDING .CPP FILES FROM OTHERS) | ||||
| // YOU SHOULD NOT BUILD BOTH IN THE SAME COMPILATION UNIT. | ||||
| // BUT IF YOU REALLY WANT TO, you can '#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM' and imgui_impl_opengl3.cpp | ||||
| // WILL NOT BE USING OUR LOADER, AND INSTEAD EXPECT ANOTHER/YOUR LOADER TO BE AVAILABLE IN THE COMPILATION UNIT. | ||||
| // | ||||
| // Regenerate with: | ||||
| //   python3 gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt | ||||
| // | ||||
| // More info: | ||||
| //   https://github.com/dearimgui/gl3w_stripped | ||||
| //   https://github.com/ocornut/imgui/issues/4445 | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /* | ||||
|  * This file was generated with gl3w_gen.py, part of imgl3w | ||||
|  * (hosted at https://github.com/dearimgui/gl3w_stripped) | ||||
|  * | ||||
|  * This is free and unencumbered software released into the public domain. | ||||
|  * | ||||
|  * Anyone is free to copy, modify, publish, use, compile, sell, or | ||||
|  * distribute this software, either in source code form or as a compiled | ||||
|  * binary, for any purpose, commercial or non-commercial, and by any | ||||
|  * means. | ||||
|  * | ||||
|  * In jurisdictions that recognize copyright laws, the author or authors | ||||
|  * of this software dedicate any and all copyright interest in the | ||||
|  * software to the public domain. We make this dedication for the benefit | ||||
|  * of the public at large and to the detriment of our heirs and | ||||
|  * successors. We intend this dedication to be an overt act of | ||||
|  * relinquishment in perpetuity of all present and future rights to this | ||||
|  * software under copyright law. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
|  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||||
|  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||||
|  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||||
|  * OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #ifndef __gl3w_h_ | ||||
| #define __gl3w_h_ | ||||
|  | ||||
| // Adapted from KHR/khrplatform.h to avoid including entire file. | ||||
| #ifndef __khrplatform_h_ | ||||
| typedef          float         khronos_float_t; | ||||
| typedef signed   char          khronos_int8_t; | ||||
| typedef unsigned char          khronos_uint8_t; | ||||
| typedef signed   short int     khronos_int16_t; | ||||
| typedef unsigned short int     khronos_uint16_t; | ||||
| #ifdef _WIN64 | ||||
| typedef signed   long long int khronos_intptr_t; | ||||
| typedef signed   long long int khronos_ssize_t; | ||||
| #else | ||||
| typedef signed   long  int     khronos_intptr_t; | ||||
| typedef signed   long  int     khronos_ssize_t; | ||||
| #endif | ||||
|  | ||||
| #if defined(_MSC_VER) && !defined(__clang__) | ||||
| typedef signed   __int64       khronos_int64_t; | ||||
| typedef unsigned __int64       khronos_uint64_t; | ||||
| #elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100) | ||||
| #include <stdint.h> | ||||
| typedef          int64_t       khronos_int64_t; | ||||
| typedef          uint64_t      khronos_uint64_t; | ||||
| #else | ||||
| typedef signed   long long     khronos_int64_t; | ||||
| typedef unsigned long long     khronos_uint64_t; | ||||
| #endif | ||||
| #endif  // __khrplatform_h_ | ||||
|  | ||||
| #ifndef __gl_glcorearb_h_ | ||||
| #define __gl_glcorearb_h_ 1 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| /* | ||||
| ** Copyright 2013-2020 The Khronos Group Inc. | ||||
| ** SPDX-License-Identifier: MIT | ||||
| ** | ||||
| ** This header is generated from the Khronos OpenGL / OpenGL ES XML | ||||
| ** API Registry. The current version of the Registry, generator scripts | ||||
| ** used to make the header, and the header can be found at | ||||
| **   https://github.com/KhronosGroup/OpenGL-Registry | ||||
| */ | ||||
| #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) | ||||
| #ifndef WIN32_LEAN_AND_MEAN | ||||
| #define WIN32_LEAN_AND_MEAN 1 | ||||
| #endif | ||||
| #include <windows.h> | ||||
| #endif | ||||
| #ifndef APIENTRY | ||||
| #define APIENTRY | ||||
| #endif | ||||
| #ifndef APIENTRYP | ||||
| #define APIENTRYP APIENTRY * | ||||
| #endif | ||||
| #ifndef GLAPI | ||||
| #define GLAPI extern | ||||
| #endif | ||||
| /* glcorearb.h is for use with OpenGL core profile implementations. | ||||
| ** It should should be placed in the same directory as gl.h and | ||||
| ** included as <GL/glcorearb.h>. | ||||
| ** | ||||
| ** glcorearb.h includes only APIs in the latest OpenGL core profile | ||||
| ** implementation together with APIs in newer ARB extensions which  | ||||
| ** can be supported by the core profile. It does not, and never will | ||||
| ** include functionality removed from the core profile, such as | ||||
| ** fixed-function vertex and fragment processing. | ||||
| ** | ||||
| ** Do not #include both <GL/glcorearb.h> and either of <GL/gl.h> or | ||||
| ** <GL/glext.h> in the same source file. | ||||
| */ | ||||
| /* Generated C header for: | ||||
|  * API: gl | ||||
|  * Profile: core | ||||
|  * Versions considered: .* | ||||
|  * Versions emitted: .* | ||||
|  * Default extensions included: glcore | ||||
|  * Additional extensions included: _nomatch_^ | ||||
|  * Extensions removed: _nomatch_^ | ||||
|  */ | ||||
| #ifndef GL_VERSION_1_0 | ||||
| typedef void GLvoid; | ||||
| typedef unsigned int GLenum; | ||||
|  | ||||
| typedef khronos_float_t GLfloat; | ||||
| typedef int GLint; | ||||
| typedef int GLsizei; | ||||
| typedef unsigned int GLbitfield; | ||||
| typedef double GLdouble; | ||||
| typedef unsigned int GLuint; | ||||
| typedef unsigned char GLboolean; | ||||
| typedef khronos_uint8_t GLubyte; | ||||
| #define GL_COLOR_BUFFER_BIT               0x00004000 | ||||
| #define GL_FALSE                          0 | ||||
| #define GL_TRUE                           1 | ||||
| #define GL_TRIANGLES                      0x0004 | ||||
| #define GL_ONE                            1 | ||||
| #define GL_SRC_ALPHA                      0x0302 | ||||
| #define GL_ONE_MINUS_SRC_ALPHA            0x0303 | ||||
| #define GL_FRONT                          0x0404 | ||||
| #define GL_BACK                           0x0405 | ||||
| #define GL_FRONT_AND_BACK                 0x0408 | ||||
| #define GL_POLYGON_MODE                   0x0B40 | ||||
| #define GL_CULL_FACE                      0x0B44 | ||||
| #define GL_DEPTH_TEST                     0x0B71 | ||||
| #define GL_STENCIL_TEST                   0x0B90 | ||||
| #define GL_VIEWPORT                       0x0BA2 | ||||
| #define GL_BLEND                          0x0BE2 | ||||
| #define GL_SCISSOR_BOX                    0x0C10 | ||||
| #define GL_SCISSOR_TEST                   0x0C11 | ||||
| #define GL_UNPACK_ROW_LENGTH              0x0CF2 | ||||
| #define GL_UNPACK_ALIGNMENT               0x0CF5 | ||||
| #define GL_PACK_ALIGNMENT                 0x0D05 | ||||
| #define GL_MAX_TEXTURE_SIZE               0x0D33 | ||||
| #define GL_TEXTURE_2D                     0x0DE1 | ||||
| #define GL_UNSIGNED_BYTE                  0x1401 | ||||
| #define GL_UNSIGNED_SHORT                 0x1403 | ||||
| #define GL_UNSIGNED_INT                   0x1405 | ||||
| #define GL_FLOAT                          0x1406 | ||||
| #define GL_RGBA                           0x1908 | ||||
| #define GL_FILL                           0x1B02 | ||||
| #define GL_VENDOR                         0x1F00 | ||||
| #define GL_RENDERER                       0x1F01 | ||||
| #define GL_VERSION                        0x1F02 | ||||
| #define GL_EXTENSIONS                     0x1F03 | ||||
| #define GL_LINEAR                         0x2601 | ||||
| #define GL_TEXTURE_MAG_FILTER             0x2800 | ||||
| #define GL_TEXTURE_MIN_FILTER             0x2801 | ||||
| #define GL_TEXTURE_WRAP_S                 0x2802 | ||||
| #define GL_TEXTURE_WRAP_T                 0x2803 | ||||
| #define GL_REPEAT                         0x2901 | ||||
| typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode); | ||||
| typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height); | ||||
| typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); | ||||
| typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); | ||||
| typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask); | ||||
| typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); | ||||
| typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap); | ||||
| typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap); | ||||
| typedef void (APIENTRYP PFNGLFLUSHPROC) (void); | ||||
| typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param); | ||||
| typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); | ||||
| typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void); | ||||
| typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data); | ||||
| typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGPROC) (GLenum name); | ||||
| typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC) (GLenum cap); | ||||
| typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); | ||||
| #ifdef GL_GLEXT_PROTOTYPES | ||||
| GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode); | ||||
| GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); | ||||
| GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); | ||||
| GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); | ||||
| GLAPI void APIENTRY glClear (GLbitfield mask); | ||||
| GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); | ||||
| GLAPI void APIENTRY glDisable (GLenum cap); | ||||
| GLAPI void APIENTRY glEnable (GLenum cap); | ||||
| GLAPI void APIENTRY glFlush (void); | ||||
| GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param); | ||||
| GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); | ||||
| GLAPI GLenum APIENTRY glGetError (void); | ||||
| GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *data); | ||||
| GLAPI const GLubyte *APIENTRY glGetString (GLenum name); | ||||
| GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap); | ||||
| GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); | ||||
| #endif | ||||
| #endif /* GL_VERSION_1_0 */ | ||||
| #ifndef GL_VERSION_1_1 | ||||
| typedef khronos_float_t GLclampf; | ||||
| typedef double GLclampd; | ||||
| #define GL_TEXTURE_BINDING_2D             0x8069 | ||||
| typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices); | ||||
| typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); | ||||
| typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture); | ||||
| typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures); | ||||
| typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures); | ||||
| #ifdef GL_GLEXT_PROTOTYPES | ||||
| GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); | ||||
| GLAPI void APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); | ||||
| GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture); | ||||
| GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); | ||||
| GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures); | ||||
| #endif | ||||
| #endif /* GL_VERSION_1_1 */ | ||||
| #ifndef GL_VERSION_1_2 | ||||
| #define GL_CLAMP_TO_EDGE                  0x812F | ||||
| #endif /* GL_VERSION_1_2 */ | ||||
| #ifndef GL_VERSION_1_3 | ||||
| #define GL_TEXTURE0                       0x84C0 | ||||
| #define GL_ACTIVE_TEXTURE                 0x84E0 | ||||
| typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); | ||||
| #ifdef GL_GLEXT_PROTOTYPES | ||||
| GLAPI void APIENTRY glActiveTexture (GLenum texture); | ||||
| #endif | ||||
| #endif /* GL_VERSION_1_3 */ | ||||
| #ifndef GL_VERSION_1_4 | ||||
| #define GL_BLEND_DST_RGB                  0x80C8 | ||||
| #define GL_BLEND_SRC_RGB                  0x80C9 | ||||
| #define GL_BLEND_DST_ALPHA                0x80CA | ||||
| #define GL_BLEND_SRC_ALPHA                0x80CB | ||||
| #define GL_FUNC_ADD                       0x8006 | ||||
| typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); | ||||
| typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode); | ||||
| #ifdef GL_GLEXT_PROTOTYPES | ||||
| GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); | ||||
| GLAPI void APIENTRY glBlendEquation (GLenum mode); | ||||
| #endif | ||||
| #endif /* GL_VERSION_1_4 */ | ||||
| #ifndef GL_VERSION_1_5 | ||||
| typedef khronos_ssize_t GLsizeiptr; | ||||
| typedef khronos_intptr_t GLintptr; | ||||
| #define GL_ARRAY_BUFFER                   0x8892 | ||||
| #define GL_ELEMENT_ARRAY_BUFFER           0x8893 | ||||
| #define GL_ARRAY_BUFFER_BINDING           0x8894 | ||||
| #define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895 | ||||
| #define GL_STREAM_DRAW                    0x88E0 | ||||
| typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); | ||||
| typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); | ||||
| typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); | ||||
| typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage); | ||||
| typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); | ||||
| #ifdef GL_GLEXT_PROTOTYPES | ||||
| GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer); | ||||
| GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); | ||||
| GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); | ||||
| GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); | ||||
| GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); | ||||
| #endif | ||||
| #endif /* GL_VERSION_1_5 */ | ||||
| #ifndef GL_VERSION_2_0 | ||||
| typedef char GLchar; | ||||
| typedef khronos_int16_t GLshort; | ||||
| typedef khronos_int8_t GLbyte; | ||||
| typedef khronos_uint16_t GLushort; | ||||
| #define GL_BLEND_EQUATION_RGB             0x8009 | ||||
| #define GL_VERTEX_ATTRIB_ARRAY_ENABLED    0x8622 | ||||
| #define GL_VERTEX_ATTRIB_ARRAY_SIZE       0x8623 | ||||
| #define GL_VERTEX_ATTRIB_ARRAY_STRIDE     0x8624 | ||||
| #define GL_VERTEX_ATTRIB_ARRAY_TYPE       0x8625 | ||||
| #define GL_VERTEX_ATTRIB_ARRAY_POINTER    0x8645 | ||||
| #define GL_BLEND_EQUATION_ALPHA           0x883D | ||||
| #define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A | ||||
| #define GL_FRAGMENT_SHADER                0x8B30 | ||||
| #define GL_VERTEX_SHADER                  0x8B31 | ||||
| #define GL_COMPILE_STATUS                 0x8B81 | ||||
| #define GL_LINK_STATUS                    0x8B82 | ||||
| #define GL_INFO_LOG_LENGTH                0x8B84 | ||||
| #define GL_CURRENT_PROGRAM                0x8B8D | ||||
| #define GL_UPPER_LEFT                     0x8CA2 | ||||
| typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); | ||||
| typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); | ||||
| typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader); | ||||
| typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void); | ||||
| typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); | ||||
| typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); | ||||
| typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); | ||||
| typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); | ||||
| typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); | ||||
| typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); | ||||
| typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); | ||||
| typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); | ||||
| typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); | ||||
| typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); | ||||
| typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); | ||||
| typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); | ||||
| typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); | ||||
| typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer); | ||||
| typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program); | ||||
| typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); | ||||
| typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); | ||||
| typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); | ||||
| typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); | ||||
| typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); | ||||
| typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); | ||||
| #ifdef GL_GLEXT_PROTOTYPES | ||||
| GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); | ||||
| GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader); | ||||
| GLAPI void APIENTRY glCompileShader (GLuint shader); | ||||
| GLAPI GLuint APIENTRY glCreateProgram (void); | ||||
| GLAPI GLuint APIENTRY glCreateShader (GLenum type); | ||||
| GLAPI void APIENTRY glDeleteProgram (GLuint program); | ||||
| GLAPI void APIENTRY glDeleteShader (GLuint shader); | ||||
| GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader); | ||||
| GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index); | ||||
| GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index); | ||||
| GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); | ||||
| GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); | ||||
| GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); | ||||
| GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); | ||||
| GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); | ||||
| GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); | ||||
| GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); | ||||
| GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer); | ||||
| GLAPI GLboolean APIENTRY glIsProgram (GLuint program); | ||||
| GLAPI void APIENTRY glLinkProgram (GLuint program); | ||||
| GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); | ||||
| GLAPI void APIENTRY glUseProgram (GLuint program); | ||||
| GLAPI void APIENTRY glUniform1i (GLint location, GLint v0); | ||||
| GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); | ||||
| GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); | ||||
| #endif | ||||
| #endif /* GL_VERSION_2_0 */ | ||||
| #ifndef GL_VERSION_2_1 | ||||
| #define GL_PIXEL_UNPACK_BUFFER            0x88EC | ||||
| #define GL_PIXEL_UNPACK_BUFFER_BINDING    0x88EF | ||||
| #endif /* GL_VERSION_2_1 */ | ||||
| #ifndef GL_VERSION_3_0 | ||||
| typedef khronos_uint16_t GLhalf; | ||||
| #define GL_MAJOR_VERSION                  0x821B | ||||
| #define GL_MINOR_VERSION                  0x821C | ||||
| #define GL_NUM_EXTENSIONS                 0x821D | ||||
| #define GL_FRAMEBUFFER_SRGB               0x8DB9 | ||||
| #define GL_VERTEX_ARRAY_BINDING           0x85B5 | ||||
| typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data); | ||||
| typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data); | ||||
| typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index); | ||||
| typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array); | ||||
| typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); | ||||
| typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); | ||||
| #ifdef GL_GLEXT_PROTOTYPES | ||||
| GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index); | ||||
| GLAPI void APIENTRY glBindVertexArray (GLuint array); | ||||
| GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays); | ||||
| GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays); | ||||
| #endif | ||||
| #endif /* GL_VERSION_3_0 */ | ||||
| #ifndef GL_VERSION_3_1 | ||||
| #define GL_VERSION_3_1 1 | ||||
| #define GL_PRIMITIVE_RESTART              0x8F9D | ||||
| #endif /* GL_VERSION_3_1 */ | ||||
| #ifndef GL_VERSION_3_2 | ||||
| #define GL_VERSION_3_2 1 | ||||
| typedef struct __GLsync *GLsync; | ||||
| typedef khronos_uint64_t GLuint64; | ||||
| typedef khronos_int64_t GLint64; | ||||
| #define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 | ||||
| #define GL_CONTEXT_PROFILE_MASK           0x9126 | ||||
| typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); | ||||
| typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data); | ||||
| #ifdef GL_GLEXT_PROTOTYPES | ||||
| GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); | ||||
| #endif | ||||
| #endif /* GL_VERSION_3_2 */ | ||||
| #ifndef GL_VERSION_3_3 | ||||
| #define GL_VERSION_3_3 1 | ||||
| #define GL_SAMPLER_BINDING                0x8919 | ||||
| typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); | ||||
| #ifdef GL_GLEXT_PROTOTYPES | ||||
| GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler); | ||||
| #endif | ||||
| #endif /* GL_VERSION_3_3 */ | ||||
| #ifndef GL_VERSION_4_1 | ||||
| typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data); | ||||
| typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data); | ||||
| #endif /* GL_VERSION_4_1 */ | ||||
| #ifndef GL_VERSION_4_3 | ||||
| typedef void (APIENTRY  *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); | ||||
| #endif /* GL_VERSION_4_3 */ | ||||
| #ifndef GL_VERSION_4_5 | ||||
| #define GL_CLIP_ORIGIN                    0x935C | ||||
| typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param); | ||||
| typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param); | ||||
| #endif /* GL_VERSION_4_5 */ | ||||
| #ifndef GL_ARB_bindless_texture | ||||
| typedef khronos_uint64_t GLuint64EXT; | ||||
| #endif /* GL_ARB_bindless_texture */ | ||||
| #ifndef GL_ARB_cl_event | ||||
| struct _cl_context; | ||||
| struct _cl_event; | ||||
| #endif /* GL_ARB_cl_event */ | ||||
| #ifndef GL_ARB_clip_control | ||||
| #define GL_ARB_clip_control 1 | ||||
| #endif /* GL_ARB_clip_control */ | ||||
| #ifndef GL_ARB_debug_output | ||||
| typedef void (APIENTRY  *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); | ||||
| #endif /* GL_ARB_debug_output */ | ||||
| #ifndef GL_EXT_EGL_image_storage | ||||
| typedef void *GLeglImageOES; | ||||
| #endif /* GL_EXT_EGL_image_storage */ | ||||
| #ifndef GL_EXT_direct_state_access | ||||
| typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params); | ||||
| typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params); | ||||
| typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params); | ||||
| typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param); | ||||
| typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param); | ||||
| #endif /* GL_EXT_direct_state_access */ | ||||
| #ifndef GL_NV_draw_vulkan_image | ||||
| typedef void (APIENTRY  *GLVULKANPROCNV)(void); | ||||
| #endif /* GL_NV_draw_vulkan_image */ | ||||
| #ifndef GL_NV_gpu_shader5 | ||||
| typedef khronos_int64_t GLint64EXT; | ||||
| #endif /* GL_NV_gpu_shader5 */ | ||||
| #ifndef GL_NV_vertex_buffer_unified_memory | ||||
| typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result); | ||||
| #endif /* GL_NV_vertex_buffer_unified_memory */ | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #ifndef GL3W_API | ||||
| #define GL3W_API | ||||
| #endif | ||||
|  | ||||
| #ifndef __gl_h_ | ||||
| #define __gl_h_ | ||||
| #endif | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| #define GL3W_OK 0 | ||||
| #define GL3W_ERROR_INIT -1 | ||||
| #define GL3W_ERROR_LIBRARY_OPEN -2 | ||||
| #define GL3W_ERROR_OPENGL_VERSION -3 | ||||
|  | ||||
| typedef void (*GL3WglProc)(void); | ||||
| typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc); | ||||
|  | ||||
| /* gl3w api */ | ||||
| GL3W_API int imgl3wInit(void); | ||||
| GL3W_API int imgl3wInit2(GL3WGetProcAddressProc proc); | ||||
| GL3W_API void imgl3wShutdown(void); | ||||
| GL3W_API int imgl3wIsSupported(int major, int minor); | ||||
| GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc); | ||||
|  | ||||
| /* gl3w internal state */ | ||||
| union ImGL3WProcs { | ||||
|     GL3WglProc ptr[60]; | ||||
|     struct { | ||||
|         PFNGLACTIVETEXTUREPROC            ActiveTexture; | ||||
|         PFNGLATTACHSHADERPROC             AttachShader; | ||||
|         PFNGLBINDBUFFERPROC               BindBuffer; | ||||
|         PFNGLBINDSAMPLERPROC              BindSampler; | ||||
|         PFNGLBINDTEXTUREPROC              BindTexture; | ||||
|         PFNGLBINDVERTEXARRAYPROC          BindVertexArray; | ||||
|         PFNGLBLENDEQUATIONPROC            BlendEquation; | ||||
|         PFNGLBLENDEQUATIONSEPARATEPROC    BlendEquationSeparate; | ||||
|         PFNGLBLENDFUNCSEPARATEPROC        BlendFuncSeparate; | ||||
|         PFNGLBUFFERDATAPROC               BufferData; | ||||
|         PFNGLBUFFERSUBDATAPROC            BufferSubData; | ||||
|         PFNGLCLEARPROC                    Clear; | ||||
|         PFNGLCLEARCOLORPROC               ClearColor; | ||||
|         PFNGLCOMPILESHADERPROC            CompileShader; | ||||
|         PFNGLCREATEPROGRAMPROC            CreateProgram; | ||||
|         PFNGLCREATESHADERPROC             CreateShader; | ||||
|         PFNGLDELETEBUFFERSPROC            DeleteBuffers; | ||||
|         PFNGLDELETEPROGRAMPROC            DeleteProgram; | ||||
|         PFNGLDELETESHADERPROC             DeleteShader; | ||||
|         PFNGLDELETETEXTURESPROC           DeleteTextures; | ||||
|         PFNGLDELETEVERTEXARRAYSPROC       DeleteVertexArrays; | ||||
|         PFNGLDETACHSHADERPROC             DetachShader; | ||||
|         PFNGLDISABLEPROC                  Disable; | ||||
|         PFNGLDISABLEVERTEXATTRIBARRAYPROC DisableVertexAttribArray; | ||||
|         PFNGLDRAWELEMENTSPROC             DrawElements; | ||||
|         PFNGLDRAWELEMENTSBASEVERTEXPROC   DrawElementsBaseVertex; | ||||
|         PFNGLENABLEPROC                   Enable; | ||||
|         PFNGLENABLEVERTEXATTRIBARRAYPROC  EnableVertexAttribArray; | ||||
|         PFNGLFLUSHPROC                    Flush; | ||||
|         PFNGLGENBUFFERSPROC               GenBuffers; | ||||
|         PFNGLGENTEXTURESPROC              GenTextures; | ||||
|         PFNGLGENVERTEXARRAYSPROC          GenVertexArrays; | ||||
|         PFNGLGETATTRIBLOCATIONPROC        GetAttribLocation; | ||||
|         PFNGLGETERRORPROC                 GetError; | ||||
|         PFNGLGETINTEGERVPROC              GetIntegerv; | ||||
|         PFNGLGETPROGRAMINFOLOGPROC        GetProgramInfoLog; | ||||
|         PFNGLGETPROGRAMIVPROC             GetProgramiv; | ||||
|         PFNGLGETSHADERINFOLOGPROC         GetShaderInfoLog; | ||||
|         PFNGLGETSHADERIVPROC              GetShaderiv; | ||||
|         PFNGLGETSTRINGPROC                GetString; | ||||
|         PFNGLGETSTRINGIPROC               GetStringi; | ||||
|         PFNGLGETUNIFORMLOCATIONPROC       GetUniformLocation; | ||||
|         PFNGLGETVERTEXATTRIBPOINTERVPROC  GetVertexAttribPointerv; | ||||
|         PFNGLGETVERTEXATTRIBIVPROC        GetVertexAttribiv; | ||||
|         PFNGLISENABLEDPROC                IsEnabled; | ||||
|         PFNGLISPROGRAMPROC                IsProgram; | ||||
|         PFNGLLINKPROGRAMPROC              LinkProgram; | ||||
|         PFNGLPIXELSTOREIPROC              PixelStorei; | ||||
|         PFNGLPOLYGONMODEPROC              PolygonMode; | ||||
|         PFNGLREADPIXELSPROC               ReadPixels; | ||||
|         PFNGLSCISSORPROC                  Scissor; | ||||
|         PFNGLSHADERSOURCEPROC             ShaderSource; | ||||
|         PFNGLTEXIMAGE2DPROC               TexImage2D; | ||||
|         PFNGLTEXPARAMETERIPROC            TexParameteri; | ||||
|         PFNGLTEXSUBIMAGE2DPROC            TexSubImage2D; | ||||
|         PFNGLUNIFORM1IPROC                Uniform1i; | ||||
|         PFNGLUNIFORMMATRIX4FVPROC         UniformMatrix4fv; | ||||
|         PFNGLUSEPROGRAMPROC               UseProgram; | ||||
|         PFNGLVERTEXATTRIBPOINTERPROC      VertexAttribPointer; | ||||
|         PFNGLVIEWPORTPROC                 Viewport; | ||||
|     } gl; | ||||
| }; | ||||
|  | ||||
| GL3W_API extern union ImGL3WProcs imgl3wProcs; | ||||
|  | ||||
| /* OpenGL functions */ | ||||
| #define glActiveTexture                   imgl3wProcs.gl.ActiveTexture | ||||
| #define glAttachShader                    imgl3wProcs.gl.AttachShader | ||||
| #define glBindBuffer                      imgl3wProcs.gl.BindBuffer | ||||
| #define glBindSampler                     imgl3wProcs.gl.BindSampler | ||||
| #define glBindTexture                     imgl3wProcs.gl.BindTexture | ||||
| #define glBindVertexArray                 imgl3wProcs.gl.BindVertexArray | ||||
| #define glBlendEquation                   imgl3wProcs.gl.BlendEquation | ||||
| #define glBlendEquationSeparate           imgl3wProcs.gl.BlendEquationSeparate | ||||
| #define glBlendFuncSeparate               imgl3wProcs.gl.BlendFuncSeparate | ||||
| #define glBufferData                      imgl3wProcs.gl.BufferData | ||||
| #define glBufferSubData                   imgl3wProcs.gl.BufferSubData | ||||
| #define glClear                           imgl3wProcs.gl.Clear | ||||
| #define glClearColor                      imgl3wProcs.gl.ClearColor | ||||
| #define glCompileShader                   imgl3wProcs.gl.CompileShader | ||||
| #define glCreateProgram                   imgl3wProcs.gl.CreateProgram | ||||
| #define glCreateShader                    imgl3wProcs.gl.CreateShader | ||||
| #define glDeleteBuffers                   imgl3wProcs.gl.DeleteBuffers | ||||
| #define glDeleteProgram                   imgl3wProcs.gl.DeleteProgram | ||||
| #define glDeleteShader                    imgl3wProcs.gl.DeleteShader | ||||
| #define glDeleteTextures                  imgl3wProcs.gl.DeleteTextures | ||||
| #define glDeleteVertexArrays              imgl3wProcs.gl.DeleteVertexArrays | ||||
| #define glDetachShader                    imgl3wProcs.gl.DetachShader | ||||
| #define glDisable                         imgl3wProcs.gl.Disable | ||||
| #define glDisableVertexAttribArray        imgl3wProcs.gl.DisableVertexAttribArray | ||||
| #define glDrawElements                    imgl3wProcs.gl.DrawElements | ||||
| #define glDrawElementsBaseVertex          imgl3wProcs.gl.DrawElementsBaseVertex | ||||
| #define glEnable                          imgl3wProcs.gl.Enable | ||||
| #define glEnableVertexAttribArray         imgl3wProcs.gl.EnableVertexAttribArray | ||||
| #define glFlush                           imgl3wProcs.gl.Flush | ||||
| #define glGenBuffers                      imgl3wProcs.gl.GenBuffers | ||||
| #define glGenTextures                     imgl3wProcs.gl.GenTextures | ||||
| #define glGenVertexArrays                 imgl3wProcs.gl.GenVertexArrays | ||||
| #define glGetAttribLocation               imgl3wProcs.gl.GetAttribLocation | ||||
| #define glGetError                        imgl3wProcs.gl.GetError | ||||
| #define glGetIntegerv                     imgl3wProcs.gl.GetIntegerv | ||||
| #define glGetProgramInfoLog               imgl3wProcs.gl.GetProgramInfoLog | ||||
| #define glGetProgramiv                    imgl3wProcs.gl.GetProgramiv | ||||
| #define glGetShaderInfoLog                imgl3wProcs.gl.GetShaderInfoLog | ||||
| #define glGetShaderiv                     imgl3wProcs.gl.GetShaderiv | ||||
| #define glGetString                       imgl3wProcs.gl.GetString | ||||
| #define glGetStringi                      imgl3wProcs.gl.GetStringi | ||||
| #define glGetUniformLocation              imgl3wProcs.gl.GetUniformLocation | ||||
| #define glGetVertexAttribPointerv         imgl3wProcs.gl.GetVertexAttribPointerv | ||||
| #define glGetVertexAttribiv               imgl3wProcs.gl.GetVertexAttribiv | ||||
| #define glIsEnabled                       imgl3wProcs.gl.IsEnabled | ||||
| #define glIsProgram                       imgl3wProcs.gl.IsProgram | ||||
| #define glLinkProgram                     imgl3wProcs.gl.LinkProgram | ||||
| #define glPixelStorei                     imgl3wProcs.gl.PixelStorei | ||||
| #define glPolygonMode                     imgl3wProcs.gl.PolygonMode | ||||
| #define glReadPixels                      imgl3wProcs.gl.ReadPixels | ||||
| #define glScissor                         imgl3wProcs.gl.Scissor | ||||
| #define glShaderSource                    imgl3wProcs.gl.ShaderSource | ||||
| #define glTexImage2D                      imgl3wProcs.gl.TexImage2D | ||||
| #define glTexParameteri                   imgl3wProcs.gl.TexParameteri | ||||
| #define glTexSubImage2D                   imgl3wProcs.gl.TexSubImage2D | ||||
| #define glUniform1i                       imgl3wProcs.gl.Uniform1i | ||||
| #define glUniformMatrix4fv                imgl3wProcs.gl.UniformMatrix4fv | ||||
| #define glUseProgram                      imgl3wProcs.gl.UseProgram | ||||
| #define glVertexAttribPointer             imgl3wProcs.gl.VertexAttribPointer | ||||
| #define glViewport                        imgl3wProcs.gl.Viewport | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #ifdef IMGL3W_IMPL | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #define GL3W_ARRAY_SIZE(x)  (sizeof(x) / sizeof((x)[0])) | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| #ifndef WIN32_LEAN_AND_MEAN | ||||
| #define WIN32_LEAN_AND_MEAN 1 | ||||
| #endif | ||||
| #include <windows.h> | ||||
|  | ||||
| static HMODULE libgl = NULL; | ||||
| typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR); | ||||
| static GL3WglGetProcAddr wgl_get_proc_address; | ||||
|  | ||||
| static int open_libgl(void) | ||||
| { | ||||
|     libgl = LoadLibraryA("opengl32.dll"); | ||||
|     if (!libgl) | ||||
|         return GL3W_ERROR_LIBRARY_OPEN; | ||||
|     wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress"); | ||||
|     return GL3W_OK; | ||||
| } | ||||
|  | ||||
| static void close_libgl(void) { FreeLibrary(libgl); libgl = NULL; } | ||||
| static GL3WglProc get_proc(const char *proc) | ||||
| { | ||||
|     GL3WglProc res; | ||||
|     res = (GL3WglProc)wgl_get_proc_address(proc); | ||||
|     if (!res) | ||||
|         res = (GL3WglProc)GetProcAddress(libgl, proc); | ||||
|     return res; | ||||
| } | ||||
| #elif defined(__APPLE__) | ||||
| #include <dlfcn.h> | ||||
|  | ||||
| static void *libgl = NULL; | ||||
| static int open_libgl(void) | ||||
| { | ||||
|     libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL); | ||||
|     if (!libgl) | ||||
|         return GL3W_ERROR_LIBRARY_OPEN; | ||||
|     return GL3W_OK; | ||||
| } | ||||
|  | ||||
| static void close_libgl(void) { dlclose(libgl); libgl = NULL; } | ||||
|  | ||||
| static GL3WglProc get_proc(const char *proc) | ||||
| { | ||||
|     GL3WglProc res; | ||||
|     *(void **)(&res) = dlsym(libgl, proc); | ||||
|     return res; | ||||
| } | ||||
| #else | ||||
| #include <dlfcn.h> | ||||
|  | ||||
| static void* libgl;  // OpenGL library | ||||
| static void* libglx;  // GLX library | ||||
| static void* libegl;  // EGL library | ||||
| static GL3WGetProcAddressProc gl_get_proc_address; | ||||
|  | ||||
| static void close_libgl(void) | ||||
| { | ||||
|     if (libgl) { | ||||
|         dlclose(libgl); | ||||
|         libgl = NULL; | ||||
|     } | ||||
|     if (libegl) { | ||||
|         dlclose(libegl); | ||||
|         libegl = NULL; | ||||
|     } | ||||
|     if (libglx) { | ||||
|         dlclose(libglx); | ||||
|         libglx = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int is_library_loaded(const char* name, void** lib) | ||||
| { | ||||
|     *lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); | ||||
|     return *lib != NULL; | ||||
| } | ||||
|  | ||||
| static int open_libs(void) | ||||
| { | ||||
|     // On Linux we have two APIs to get process addresses: EGL and GLX. | ||||
|     // EGL is supported under both X11 and Wayland, whereas GLX is X11-specific. | ||||
|  | ||||
|     libgl = NULL; | ||||
|     libegl = NULL; | ||||
|     libglx = NULL; | ||||
|  | ||||
|     // First check what's already loaded, the windowing library might have | ||||
|     // already loaded either EGL or GLX and we want to use the same one. | ||||
|  | ||||
|     if (is_library_loaded("libEGL.so.1", &libegl) || | ||||
|         is_library_loaded("libGLX.so.0", &libglx)) { | ||||
|         libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL); | ||||
|         if (libgl) | ||||
|             return GL3W_OK; | ||||
|         else | ||||
|             close_libgl(); | ||||
|     } | ||||
|  | ||||
|     if (is_library_loaded("libGL.so", &libgl)) | ||||
|         return GL3W_OK; | ||||
|     if (is_library_loaded("libGL.so.1", &libgl)) | ||||
|         return GL3W_OK; | ||||
|     if (is_library_loaded("libGL.so.3", &libgl)) | ||||
|         return GL3W_OK; | ||||
|  | ||||
|     // Neither is already loaded, so we have to load one.  Try EGL first | ||||
|     // because it is supported under both X11 and Wayland. | ||||
|  | ||||
|     // Load OpenGL + EGL | ||||
|     libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL); | ||||
|     libegl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL); | ||||
|     if (libgl && libegl) | ||||
|         return GL3W_OK; | ||||
|     else | ||||
|         close_libgl(); | ||||
|  | ||||
|     // Fall back to legacy libGL, which includes GLX | ||||
|     // While most systems use libGL.so.1, NetBSD seems to use that libGL.so.3. See https://github.com/ocornut/imgui/issues/6983 | ||||
|     libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL); | ||||
|     if (!libgl) | ||||
|         libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL); | ||||
|     if (!libgl) | ||||
|         libgl = dlopen("libGL.so.3", RTLD_LAZY | RTLD_LOCAL); | ||||
|  | ||||
|     if (libgl) | ||||
|         return GL3W_OK; | ||||
|  | ||||
|     return GL3W_ERROR_LIBRARY_OPEN; | ||||
| } | ||||
|  | ||||
| static int open_libgl(void) | ||||
| { | ||||
|     int res = open_libs(); | ||||
|     if (res) | ||||
|         return res; | ||||
|  | ||||
|     if (libegl) | ||||
|         *(void**)(&gl_get_proc_address) = dlsym(libegl, "eglGetProcAddress"); | ||||
|     else if (libglx) | ||||
|         *(void**)(&gl_get_proc_address) = dlsym(libglx, "glXGetProcAddressARB"); | ||||
|     else | ||||
|         *(void**)(&gl_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB"); | ||||
|  | ||||
|     if (!gl_get_proc_address) { | ||||
|         close_libgl(); | ||||
|         return GL3W_ERROR_LIBRARY_OPEN; | ||||
|     } | ||||
|  | ||||
|     return GL3W_OK; | ||||
| } | ||||
|  | ||||
| static GL3WglProc get_proc(const char* proc) | ||||
| { | ||||
|     GL3WglProc res = NULL; | ||||
|  | ||||
|     // Before EGL version 1.5, eglGetProcAddress doesn't support querying core | ||||
|     // functions and may return a dummy function if we try, so try to load the | ||||
|     // function from the GL library directly first. | ||||
|     if (libegl) | ||||
|         *(void**)(&res) = dlsym(libgl, proc); | ||||
|  | ||||
|     if (!res) | ||||
|         res = gl_get_proc_address(proc); | ||||
|  | ||||
|     if (!libegl && !res) | ||||
|         *(void**)(&res) = dlsym(libgl, proc); | ||||
|  | ||||
|     return res; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static struct { int major, minor; } version; | ||||
|  | ||||
| static int parse_version(void) | ||||
| { | ||||
|     if (!glGetIntegerv) | ||||
|         return GL3W_ERROR_INIT; | ||||
|     glGetIntegerv(GL_MAJOR_VERSION, &version.major); | ||||
|     glGetIntegerv(GL_MINOR_VERSION, &version.minor); | ||||
|     if (version.major == 0 && version.minor == 0) | ||||
|     { | ||||
|         // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>" | ||||
|         if (const char* gl_version = (const char*)glGetString(GL_VERSION)) | ||||
|             sscanf(gl_version, "%d.%d", &version.major, &version.minor); | ||||
|     } | ||||
|     if (version.major < 2) | ||||
|         return GL3W_ERROR_OPENGL_VERSION; | ||||
|     return GL3W_OK; | ||||
| } | ||||
|  | ||||
| static void load_procs(GL3WGetProcAddressProc proc); | ||||
|  | ||||
| int imgl3wInit(void) | ||||
| { | ||||
|     int res = open_libgl(); | ||||
|     if (res) | ||||
|         return res; | ||||
|     atexit(close_libgl); | ||||
|     return imgl3wInit2(get_proc); | ||||
| } | ||||
|  | ||||
| int imgl3wInit2(GL3WGetProcAddressProc proc) | ||||
| { | ||||
|     load_procs(proc); | ||||
|     return parse_version(); | ||||
| } | ||||
|  | ||||
| void imgl3wShutdown(void) | ||||
| { | ||||
|     close_libgl(); | ||||
| } | ||||
|  | ||||
| int imgl3wIsSupported(int major, int minor) | ||||
| { | ||||
|     if (major < 2) | ||||
|         return 0; | ||||
|     if (version.major == major) | ||||
|         return version.minor >= minor; | ||||
|     return version.major >= major; | ||||
| } | ||||
|  | ||||
| GL3WglProc imgl3wGetProcAddress(const char *proc) { return get_proc(proc); } | ||||
|  | ||||
| static const char *proc_names[] = { | ||||
|     "glActiveTexture", | ||||
|     "glAttachShader", | ||||
|     "glBindBuffer", | ||||
|     "glBindSampler", | ||||
|     "glBindTexture", | ||||
|     "glBindVertexArray", | ||||
|     "glBlendEquation", | ||||
|     "glBlendEquationSeparate", | ||||
|     "glBlendFuncSeparate", | ||||
|     "glBufferData", | ||||
|     "glBufferSubData", | ||||
|     "glClear", | ||||
|     "glClearColor", | ||||
|     "glCompileShader", | ||||
|     "glCreateProgram", | ||||
|     "glCreateShader", | ||||
|     "glDeleteBuffers", | ||||
|     "glDeleteProgram", | ||||
|     "glDeleteShader", | ||||
|     "glDeleteTextures", | ||||
|     "glDeleteVertexArrays", | ||||
|     "glDetachShader", | ||||
|     "glDisable", | ||||
|     "glDisableVertexAttribArray", | ||||
|     "glDrawElements", | ||||
|     "glDrawElementsBaseVertex", | ||||
|     "glEnable", | ||||
|     "glEnableVertexAttribArray", | ||||
|     "glFlush", | ||||
|     "glGenBuffers", | ||||
|     "glGenTextures", | ||||
|     "glGenVertexArrays", | ||||
|     "glGetAttribLocation", | ||||
|     "glGetError", | ||||
|     "glGetIntegerv", | ||||
|     "glGetProgramInfoLog", | ||||
|     "glGetProgramiv", | ||||
|     "glGetShaderInfoLog", | ||||
|     "glGetShaderiv", | ||||
|     "glGetString", | ||||
|     "glGetStringi", | ||||
|     "glGetUniformLocation", | ||||
|     "glGetVertexAttribPointerv", | ||||
|     "glGetVertexAttribiv", | ||||
|     "glIsEnabled", | ||||
|     "glIsProgram", | ||||
|     "glLinkProgram", | ||||
|     "glPixelStorei", | ||||
|     "glPolygonMode", | ||||
|     "glReadPixels", | ||||
|     "glScissor", | ||||
|     "glShaderSource", | ||||
|     "glTexImage2D", | ||||
|     "glTexParameteri", | ||||
|     "glTexSubImage2D", | ||||
|     "glUniform1i", | ||||
|     "glUniformMatrix4fv", | ||||
|     "glUseProgram", | ||||
|     "glVertexAttribPointer", | ||||
|     "glViewport", | ||||
| }; | ||||
|  | ||||
| GL3W_API union ImGL3WProcs imgl3wProcs; | ||||
|  | ||||
| static void load_procs(GL3WGetProcAddressProc proc) | ||||
| { | ||||
|     size_t i; | ||||
|     for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++) | ||||
|         imgl3wProcs.ptr[i] = proc(proc_names[i]); | ||||
| } | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
							
								
								
									
										32
									
								
								dep/imgui/build.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								dep/imgui/build.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| from build.c import cxxlibrary | ||||
| from build.pkg import package | ||||
|  | ||||
| package(name="libglfw", package="glfw3") | ||||
| package(name="libopengl", package="opengl") | ||||
|  | ||||
| cxxlibrary( | ||||
|     name="imgui", | ||||
|     srcs=[ | ||||
|         "./backends/imgui_impl_glfw.cpp", | ||||
|         "./backends/imgui_impl_glfw.h", | ||||
|         "./backends/imgui_impl_opengl3.cpp", | ||||
|         "./backends/imgui_impl_opengl3.h", | ||||
|         "./backends/imgui_impl_opengl3_loader.h", | ||||
|         "./imgui.cpp", | ||||
|         "./imgui_demo.cpp", | ||||
|         "./imgui_draw.cpp", | ||||
|         "./imgui_internal.h", | ||||
|         "./imgui_tables.cpp", | ||||
|         "./imgui_widgets.cpp", | ||||
|         "./imstb_rectpack.h", | ||||
|         "./imstb_textedit.h", | ||||
|         "./imstb_truetype.h", | ||||
|     ], | ||||
|     hdrs={ | ||||
|         "imconfig.h": "./imconfig.h", | ||||
|         "imgui.h": "./imgui.h", | ||||
|         "imgui_impl_glfw.h": "./backends/imgui_impl_glfw.h", | ||||
|         "imgui_impl_opengl3.h": "./backends/imgui_impl_opengl3.h", | ||||
|     }, | ||||
|     deps=[".+libglfw", ".+libopengl"], | ||||
| ) | ||||
							
								
								
									
										145
									
								
								dep/imgui/imconfig.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								dep/imgui/imconfig.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| //----------------------------------------------------------------------------- | ||||
| // DEAR IMGUI COMPILE-TIME OPTIONS | ||||
| // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. | ||||
| // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. | ||||
| //----------------------------------------------------------------------------- | ||||
| // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it) | ||||
| // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. | ||||
| //----------------------------------------------------------------------------- | ||||
| // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp | ||||
| // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. | ||||
| // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. | ||||
| // Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using. | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| //---- Define assertion handler. Defaults to calling assert(). | ||||
| // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. | ||||
| //#define IM_ASSERT(_EXPR)  MyAssert(_EXPR) | ||||
| //#define IM_ASSERT(_EXPR)  ((void)(_EXPR))     // Disable asserts | ||||
|  | ||||
| //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows | ||||
| // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. | ||||
| // - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() | ||||
| //   for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. | ||||
| //#define IMGUI_API __declspec(dllexport)                   // MSVC Windows: DLL export | ||||
| //#define IMGUI_API __declspec(dllimport)                   // MSVC Windows: DLL import | ||||
| //#define IMGUI_API __attribute__((visibility("default")))  // GCC/Clang: override visibility when set is hidden | ||||
|  | ||||
| //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names. | ||||
| //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS | ||||
|  | ||||
| //---- Disable all of Dear ImGui or don't implement standard windows/tools. | ||||
| // It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp. | ||||
| //#define IMGUI_DISABLE                                     // Disable everything: all headers and source files will be empty. | ||||
| //#define IMGUI_DISABLE_DEMO_WINDOWS                        // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. | ||||
| //#define IMGUI_DISABLE_DEBUG_TOOLS                         // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty. | ||||
|  | ||||
| //---- Don't implement some functions to reduce linkage requirements. | ||||
| //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS   // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) | ||||
| //#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS          // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW) | ||||
| //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS         // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) | ||||
| //#define IMGUI_DISABLE_WIN32_FUNCTIONS                     // [Win32] Won't use and link with any Win32 function (clipboard, IME). | ||||
| //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS      // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). | ||||
| //#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS             // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")). | ||||
| //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS            // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) | ||||
| //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS              // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. | ||||
| //#define IMGUI_DISABLE_FILE_FUNCTIONS                      // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) | ||||
| //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS              // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. | ||||
| //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS                  // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). | ||||
| //#define IMGUI_DISABLE_DEFAULT_FONT                        // Disable default embedded font (ProggyClean.ttf), remove ~9.5 KB from output binary. AddFontDefault() will assert. | ||||
| //#define IMGUI_DISABLE_SSE                                 // Disable use of SSE intrinsics even if available | ||||
|  | ||||
| //---- Enable Test Engine / Automation features. | ||||
| //#define IMGUI_ENABLE_TEST_ENGINE                          // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details. | ||||
|  | ||||
| //---- Include imgui_user.h at the end of imgui.h as a convenience | ||||
| // May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included. | ||||
| //#define IMGUI_INCLUDE_IMGUI_USER_H | ||||
| //#define IMGUI_USER_H_FILENAME         "my_folder/my_imgui_user.h" | ||||
|  | ||||
| //---- Pack vertex colors as BGRA8 instead of RGBA8 (to avoid converting from one to another). Need dedicated backend support. | ||||
| //#define IMGUI_USE_BGRA_PACKED_COLOR | ||||
|  | ||||
| //---- Use legacy CRC32-adler tables (used before 1.91.6), in order to preserve old .ini data that you cannot afford to invalidate. | ||||
| //#define IMGUI_USE_LEGACY_CRC32_ADLER | ||||
|  | ||||
| //---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) | ||||
| //#define IMGUI_USE_WCHAR32 | ||||
|  | ||||
| //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version | ||||
| // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. | ||||
| //#define IMGUI_STB_TRUETYPE_FILENAME   "my_folder/stb_truetype.h" | ||||
| //#define IMGUI_STB_RECT_PACK_FILENAME  "my_folder/stb_rect_pack.h" | ||||
| //#define IMGUI_STB_SPRINTF_FILENAME    "my_folder/stb_sprintf.h"    // only used if IMGUI_USE_STB_SPRINTF is defined. | ||||
| //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION | ||||
| //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION | ||||
| //#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION                   // only disabled if IMGUI_USE_STB_SPRINTF is defined. | ||||
|  | ||||
| //---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) | ||||
| // Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h. | ||||
| //#define IMGUI_USE_STB_SPRINTF | ||||
|  | ||||
| //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) | ||||
| // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). | ||||
| // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. | ||||
| //#define IMGUI_ENABLE_FREETYPE | ||||
|  | ||||
| //---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT) | ||||
| // Only works in combination with IMGUI_ENABLE_FREETYPE. | ||||
| // - plutosvg is currently easier to install, as e.g. it is part of vcpkg. It will support more fonts and may load them faster. See misc/freetype/README for instructions. | ||||
| // - Both require headers to be available in the include path + program to be linked with the library code (not provided). | ||||
| // - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement) | ||||
| //#define IMGUI_ENABLE_FREETYPE_PLUTOSVG | ||||
| //#define IMGUI_ENABLE_FREETYPE_LUNASVG | ||||
|  | ||||
| //---- Use stb_truetype to build and rasterize the font atlas (default) | ||||
| // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. | ||||
| //#define IMGUI_ENABLE_STB_TRUETYPE | ||||
|  | ||||
| //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. | ||||
| // This will be inlined as part of ImVec2 and ImVec4 class declarations. | ||||
| /* | ||||
| #define IM_VEC2_CLASS_EXTRA                                                     \ | ||||
|         constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {}                   \ | ||||
|         operator MyVec2() const { return MyVec2(x,y); } | ||||
|  | ||||
| #define IM_VEC4_CLASS_EXTRA                                                     \ | ||||
|         constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {}   \ | ||||
|         operator MyVec4() const { return MyVec4(x,y,z,w); } | ||||
| */ | ||||
| //---- ...Or use Dear ImGui's own very basic math operators. | ||||
| //#define IMGUI_DEFINE_MATH_OPERATORS | ||||
|  | ||||
| //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. | ||||
| // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). | ||||
| // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. | ||||
| // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. | ||||
| //#define ImDrawIdx unsigned int | ||||
|  | ||||
| //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) | ||||
| //struct ImDrawList; | ||||
| //struct ImDrawCmd; | ||||
| //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); | ||||
| //#define ImDrawCallback MyImDrawCallback | ||||
|  | ||||
| //---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase) | ||||
| // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) | ||||
| //#define IM_DEBUG_BREAK  IM_ASSERT(0) | ||||
| //#define IM_DEBUG_BREAK  __debugbreak() | ||||
|  | ||||
| //---- Debug Tools: Enable highlight ID conflicts _before_ hovering items. When io.ConfigDebugHighlightIdConflicts is set. | ||||
| // (THIS WILL SLOW DOWN DEAR IMGUI. Only use occasionally and disable after use) | ||||
| //#define IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS | ||||
|  | ||||
| //---- Debug Tools: Enable slower asserts | ||||
| //#define IMGUI_DEBUG_PARANOID | ||||
|  | ||||
| //---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files) | ||||
| /* | ||||
| namespace ImGui | ||||
| { | ||||
|     void MyFunction(const char* name, MyMatrix44* mtx); | ||||
| } | ||||
| */ | ||||
							
								
								
									
										23757
									
								
								dep/imgui/imgui.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23757
									
								
								dep/imgui/imgui.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4396
									
								
								dep/imgui/imgui.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4396
									
								
								dep/imgui/imgui.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										11146
									
								
								dep/imgui/imgui_demo.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11146
									
								
								dep/imgui/imgui_demo.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										6331
									
								
								dep/imgui/imgui_draw.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6331
									
								
								dep/imgui/imgui_draw.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4208
									
								
								dep/imgui/imgui_internal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4208
									
								
								dep/imgui/imgui_internal.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4562
									
								
								dep/imgui/imgui_tables.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4562
									
								
								dep/imgui/imgui_tables.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										10757
									
								
								dep/imgui/imgui_widgets.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10757
									
								
								dep/imgui/imgui_widgets.cpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										627
									
								
								dep/imgui/imstb_rectpack.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										627
									
								
								dep/imgui/imstb_rectpack.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,627 @@ | ||||
| // [DEAR IMGUI] | ||||
| // This is a slightly modified version of stb_rect_pack.h 1.01. | ||||
| // Grep for [DEAR IMGUI] to find the changes. | ||||
| //  | ||||
| // stb_rect_pack.h - v1.01 - public domain - rectangle packing | ||||
| // Sean Barrett 2014 | ||||
| // | ||||
| // Useful for e.g. packing rectangular textures into an atlas. | ||||
| // Does not do rotation. | ||||
| // | ||||
| // Before #including, | ||||
| // | ||||
| //    #define STB_RECT_PACK_IMPLEMENTATION | ||||
| // | ||||
| // in the file that you want to have the implementation. | ||||
| // | ||||
| // Not necessarily the awesomest packing method, but better than | ||||
| // the totally naive one in stb_truetype (which is primarily what | ||||
| // this is meant to replace). | ||||
| // | ||||
| // Has only had a few tests run, may have issues. | ||||
| // | ||||
| // More docs to come. | ||||
| // | ||||
| // No memory allocations; uses qsort() and assert() from stdlib. | ||||
| // Can override those by defining STBRP_SORT and STBRP_ASSERT. | ||||
| // | ||||
| // This library currently uses the Skyline Bottom-Left algorithm. | ||||
| // | ||||
| // Please note: better rectangle packers are welcome! Please | ||||
| // implement them to the same API, but with a different init | ||||
| // function. | ||||
| // | ||||
| // Credits | ||||
| // | ||||
| //  Library | ||||
| //    Sean Barrett | ||||
| //  Minor features | ||||
| //    Martins Mozeiko | ||||
| //    github:IntellectualKitty | ||||
| // | ||||
| //  Bugfixes / warning fixes | ||||
| //    Jeremy Jaussaud | ||||
| //    Fabian Giesen | ||||
| // | ||||
| // Version history: | ||||
| // | ||||
| //     1.01  (2021-07-11)  always use large rect mode, expose STBRP__MAXVAL in public section | ||||
| //     1.00  (2019-02-25)  avoid small space waste; gracefully fail too-wide rectangles | ||||
| //     0.99  (2019-02-07)  warning fixes | ||||
| //     0.11  (2017-03-03)  return packing success/fail result | ||||
| //     0.10  (2016-10-25)  remove cast-away-const to avoid warnings | ||||
| //     0.09  (2016-08-27)  fix compiler warnings | ||||
| //     0.08  (2015-09-13)  really fix bug with empty rects (w=0 or h=0) | ||||
| //     0.07  (2015-09-13)  fix bug with empty rects (w=0 or h=0) | ||||
| //     0.06  (2015-04-15)  added STBRP_SORT to allow replacing qsort | ||||
| //     0.05:  added STBRP_ASSERT to allow replacing assert | ||||
| //     0.04:  fixed minor bug in STBRP_LARGE_RECTS support | ||||
| //     0.01:  initial release | ||||
| // | ||||
| // LICENSE | ||||
| // | ||||
| //   See end of file for license information. | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
| // | ||||
| //       INCLUDE SECTION | ||||
| // | ||||
|  | ||||
| #ifndef STB_INCLUDE_STB_RECT_PACK_H | ||||
| #define STB_INCLUDE_STB_RECT_PACK_H | ||||
|  | ||||
| #define STB_RECT_PACK_VERSION  1 | ||||
|  | ||||
| #ifdef STBRP_STATIC | ||||
| #define STBRP_DEF static | ||||
| #else | ||||
| #define STBRP_DEF extern | ||||
| #endif | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| typedef struct stbrp_context stbrp_context; | ||||
| typedef struct stbrp_node    stbrp_node; | ||||
| typedef struct stbrp_rect    stbrp_rect; | ||||
|  | ||||
| typedef int            stbrp_coord; | ||||
|  | ||||
| #define STBRP__MAXVAL  0x7fffffff | ||||
| // Mostly for internal use, but this is the maximum supported coordinate value. | ||||
|  | ||||
| STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); | ||||
| // Assign packed locations to rectangles. The rectangles are of type | ||||
| // 'stbrp_rect' defined below, stored in the array 'rects', and there | ||||
| // are 'num_rects' many of them. | ||||
| // | ||||
| // Rectangles which are successfully packed have the 'was_packed' flag | ||||
| // set to a non-zero value and 'x' and 'y' store the minimum location | ||||
| // on each axis (i.e. bottom-left in cartesian coordinates, top-left | ||||
| // if you imagine y increasing downwards). Rectangles which do not fit | ||||
| // have the 'was_packed' flag set to 0. | ||||
| // | ||||
| // You should not try to access the 'rects' array from another thread | ||||
| // while this function is running, as the function temporarily reorders | ||||
| // the array while it executes. | ||||
| // | ||||
| // To pack into another rectangle, you need to call stbrp_init_target | ||||
| // again. To continue packing into the same rectangle, you can call | ||||
| // this function again. Calling this multiple times with multiple rect | ||||
| // arrays will probably produce worse packing results than calling it | ||||
| // a single time with the full rectangle array, but the option is | ||||
| // available. | ||||
| // | ||||
| // The function returns 1 if all of the rectangles were successfully | ||||
| // packed and 0 otherwise. | ||||
|  | ||||
| struct stbrp_rect | ||||
| { | ||||
|    // reserved for your use: | ||||
|    int            id; | ||||
|  | ||||
|    // input: | ||||
|    stbrp_coord    w, h; | ||||
|  | ||||
|    // output: | ||||
|    stbrp_coord    x, y; | ||||
|    int            was_packed;  // non-zero if valid packing | ||||
|  | ||||
| }; // 16 bytes, nominally | ||||
|  | ||||
|  | ||||
| STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); | ||||
| // Initialize a rectangle packer to: | ||||
| //    pack a rectangle that is 'width' by 'height' in dimensions | ||||
| //    using temporary storage provided by the array 'nodes', which is 'num_nodes' long | ||||
| // | ||||
| // You must call this function every time you start packing into a new target. | ||||
| // | ||||
| // There is no "shutdown" function. The 'nodes' memory must stay valid for | ||||
| // the following stbrp_pack_rects() call (or calls), but can be freed after | ||||
| // the call (or calls) finish. | ||||
| // | ||||
| // Note: to guarantee best results, either: | ||||
| //       1. make sure 'num_nodes' >= 'width' | ||||
| //   or  2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' | ||||
| // | ||||
| // If you don't do either of the above things, widths will be quantized to multiples | ||||
| // of small integers to guarantee the algorithm doesn't run out of temporary storage. | ||||
| // | ||||
| // If you do #2, then the non-quantized algorithm will be used, but the algorithm | ||||
| // may run out of temporary storage and be unable to pack some rectangles. | ||||
|  | ||||
| STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); | ||||
| // Optionally call this function after init but before doing any packing to | ||||
| // change the handling of the out-of-temp-memory scenario, described above. | ||||
| // If you call init again, this will be reset to the default (false). | ||||
|  | ||||
|  | ||||
| STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); | ||||
| // Optionally select which packing heuristic the library should use. Different | ||||
| // heuristics will produce better/worse results for different data sets. | ||||
| // If you call init again, this will be reset to the default. | ||||
|  | ||||
| enum | ||||
| { | ||||
|    STBRP_HEURISTIC_Skyline_default=0, | ||||
|    STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, | ||||
|    STBRP_HEURISTIC_Skyline_BF_sortHeight | ||||
| }; | ||||
|  | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
| // | ||||
| // the details of the following structures don't matter to you, but they must | ||||
| // be visible so you can handle the memory allocations for them | ||||
|  | ||||
| struct stbrp_node | ||||
| { | ||||
|    stbrp_coord  x,y; | ||||
|    stbrp_node  *next; | ||||
| }; | ||||
|  | ||||
| struct stbrp_context | ||||
| { | ||||
|    int width; | ||||
|    int height; | ||||
|    int align; | ||||
|    int init_mode; | ||||
|    int heuristic; | ||||
|    int num_nodes; | ||||
|    stbrp_node *active_head; | ||||
|    stbrp_node *free_head; | ||||
|    stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' | ||||
| }; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|  | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
| // | ||||
| //     IMPLEMENTATION SECTION | ||||
| // | ||||
|  | ||||
| #ifdef STB_RECT_PACK_IMPLEMENTATION | ||||
| #ifndef STBRP_SORT | ||||
| #include <stdlib.h> | ||||
| #define STBRP_SORT qsort | ||||
| #endif | ||||
|  | ||||
| #ifndef STBRP_ASSERT | ||||
| #include <assert.h> | ||||
| #define STBRP_ASSERT assert | ||||
| #endif | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| #define STBRP__NOTUSED(v)  (void)(v) | ||||
| #define STBRP__CDECL       __cdecl | ||||
| #else | ||||
| #define STBRP__NOTUSED(v)  (void)sizeof(v) | ||||
| #define STBRP__CDECL | ||||
| #endif | ||||
|  | ||||
| enum | ||||
| { | ||||
|    STBRP__INIT_skyline = 1 | ||||
| }; | ||||
|  | ||||
| STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) | ||||
| { | ||||
|    switch (context->init_mode) { | ||||
|       case STBRP__INIT_skyline: | ||||
|          STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); | ||||
|          context->heuristic = heuristic; | ||||
|          break; | ||||
|       default: | ||||
|          STBRP_ASSERT(0); | ||||
|    } | ||||
| } | ||||
|  | ||||
| STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) | ||||
| { | ||||
|    if (allow_out_of_mem) | ||||
|       // if it's ok to run out of memory, then don't bother aligning them; | ||||
|       // this gives better packing, but may fail due to OOM (even though | ||||
|       // the rectangles easily fit). @TODO a smarter approach would be to only | ||||
|       // quantize once we've hit OOM, then we could get rid of this parameter. | ||||
|       context->align = 1; | ||||
|    else { | ||||
|       // if it's not ok to run out of memory, then quantize the widths | ||||
|       // so that num_nodes is always enough nodes. | ||||
|       // | ||||
|       // I.e. num_nodes * align >= width | ||||
|       //                  align >= width / num_nodes | ||||
|       //                  align = ceil(width/num_nodes) | ||||
|  | ||||
|       context->align = (context->width + context->num_nodes-1) / context->num_nodes; | ||||
|    } | ||||
| } | ||||
|  | ||||
| STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) | ||||
| { | ||||
|    int i; | ||||
|  | ||||
|    for (i=0; i < num_nodes-1; ++i) | ||||
|       nodes[i].next = &nodes[i+1]; | ||||
|    nodes[i].next = NULL; | ||||
|    context->init_mode = STBRP__INIT_skyline; | ||||
|    context->heuristic = STBRP_HEURISTIC_Skyline_default; | ||||
|    context->free_head = &nodes[0]; | ||||
|    context->active_head = &context->extra[0]; | ||||
|    context->width = width; | ||||
|    context->height = height; | ||||
|    context->num_nodes = num_nodes; | ||||
|    stbrp_setup_allow_out_of_mem(context, 0); | ||||
|  | ||||
|    // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) | ||||
|    context->extra[0].x = 0; | ||||
|    context->extra[0].y = 0; | ||||
|    context->extra[0].next = &context->extra[1]; | ||||
|    context->extra[1].x = (stbrp_coord) width; | ||||
|    context->extra[1].y = (1<<30); | ||||
|    context->extra[1].next = NULL; | ||||
| } | ||||
|  | ||||
| // find minimum y position if it starts at x1 | ||||
| static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) | ||||
| { | ||||
|    stbrp_node *node = first; | ||||
|    int x1 = x0 + width; | ||||
|    int min_y, visited_width, waste_area; | ||||
|  | ||||
|    STBRP__NOTUSED(c); | ||||
|  | ||||
|    STBRP_ASSERT(first->x <= x0); | ||||
|  | ||||
|    #if 0 | ||||
|    // skip in case we're past the node | ||||
|    while (node->next->x <= x0) | ||||
|       ++node; | ||||
|    #else | ||||
|    STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency | ||||
|    #endif | ||||
|  | ||||
|    STBRP_ASSERT(node->x <= x0); | ||||
|  | ||||
|    min_y = 0; | ||||
|    waste_area = 0; | ||||
|    visited_width = 0; | ||||
|    while (node->x < x1) { | ||||
|       if (node->y > min_y) { | ||||
|          // raise min_y higher. | ||||
|          // we've accounted for all waste up to min_y, | ||||
|          // but we'll now add more waste for everything we've visted | ||||
|          waste_area += visited_width * (node->y - min_y); | ||||
|          min_y = node->y; | ||||
|          // the first time through, visited_width might be reduced | ||||
|          if (node->x < x0) | ||||
|             visited_width += node->next->x - x0; | ||||
|          else | ||||
|             visited_width += node->next->x - node->x; | ||||
|       } else { | ||||
|          // add waste area | ||||
|          int under_width = node->next->x - node->x; | ||||
|          if (under_width + visited_width > width) | ||||
|             under_width = width - visited_width; | ||||
|          waste_area += under_width * (min_y - node->y); | ||||
|          visited_width += under_width; | ||||
|       } | ||||
|       node = node->next; | ||||
|    } | ||||
|  | ||||
|    *pwaste = waste_area; | ||||
|    return min_y; | ||||
| } | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|    int x,y; | ||||
|    stbrp_node **prev_link; | ||||
| } stbrp__findresult; | ||||
|  | ||||
| static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) | ||||
| { | ||||
|    int best_waste = (1<<30), best_x, best_y = (1 << 30); | ||||
|    stbrp__findresult fr; | ||||
|    stbrp_node **prev, *node, *tail, **best = NULL; | ||||
|  | ||||
|    // align to multiple of c->align | ||||
|    width = (width + c->align - 1); | ||||
|    width -= width % c->align; | ||||
|    STBRP_ASSERT(width % c->align == 0); | ||||
|  | ||||
|    // if it can't possibly fit, bail immediately | ||||
|    if (width > c->width || height > c->height) { | ||||
|       fr.prev_link = NULL; | ||||
|       fr.x = fr.y = 0; | ||||
|       return fr; | ||||
|    } | ||||
|  | ||||
|    node = c->active_head; | ||||
|    prev = &c->active_head; | ||||
|    while (node->x + width <= c->width) { | ||||
|       int y,waste; | ||||
|       y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); | ||||
|       if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL | ||||
|          // bottom left | ||||
|          if (y < best_y) { | ||||
|             best_y = y; | ||||
|             best = prev; | ||||
|          } | ||||
|       } else { | ||||
|          // best-fit | ||||
|          if (y + height <= c->height) { | ||||
|             // can only use it if it first vertically | ||||
|             if (y < best_y || (y == best_y && waste < best_waste)) { | ||||
|                best_y = y; | ||||
|                best_waste = waste; | ||||
|                best = prev; | ||||
|             } | ||||
|          } | ||||
|       } | ||||
|       prev = &node->next; | ||||
|       node = node->next; | ||||
|    } | ||||
|  | ||||
|    best_x = (best == NULL) ? 0 : (*best)->x; | ||||
|  | ||||
|    // if doing best-fit (BF), we also have to try aligning right edge to each node position | ||||
|    // | ||||
|    // e.g, if fitting | ||||
|    // | ||||
|    //     ____________________ | ||||
|    //    |____________________| | ||||
|    // | ||||
|    //            into | ||||
|    // | ||||
|    //   |                         | | ||||
|    //   |             ____________| | ||||
|    //   |____________| | ||||
|    // | ||||
|    // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned | ||||
|    // | ||||
|    // This makes BF take about 2x the time | ||||
|  | ||||
|    if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { | ||||
|       tail = c->active_head; | ||||
|       node = c->active_head; | ||||
|       prev = &c->active_head; | ||||
|       // find first node that's admissible | ||||
|       while (tail->x < width) | ||||
|          tail = tail->next; | ||||
|       while (tail) { | ||||
|          int xpos = tail->x - width; | ||||
|          int y,waste; | ||||
|          STBRP_ASSERT(xpos >= 0); | ||||
|          // find the left position that matches this | ||||
|          while (node->next->x <= xpos) { | ||||
|             prev = &node->next; | ||||
|             node = node->next; | ||||
|          } | ||||
|          STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); | ||||
|          y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); | ||||
|          if (y + height <= c->height) { | ||||
|             if (y <= best_y) { | ||||
|                if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { | ||||
|                   best_x = xpos; | ||||
|                   //STBRP_ASSERT(y <= best_y); [DEAR IMGUI] | ||||
|                   best_y = y; | ||||
|                   best_waste = waste; | ||||
|                   best = prev; | ||||
|                } | ||||
|             } | ||||
|          } | ||||
|          tail = tail->next; | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    fr.prev_link = best; | ||||
|    fr.x = best_x; | ||||
|    fr.y = best_y; | ||||
|    return fr; | ||||
| } | ||||
|  | ||||
| static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) | ||||
| { | ||||
|    // find best position according to heuristic | ||||
|    stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); | ||||
|    stbrp_node *node, *cur; | ||||
|  | ||||
|    // bail if: | ||||
|    //    1. it failed | ||||
|    //    2. the best node doesn't fit (we don't always check this) | ||||
|    //    3. we're out of memory | ||||
|    if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { | ||||
|       res.prev_link = NULL; | ||||
|       return res; | ||||
|    } | ||||
|  | ||||
|    // on success, create new node | ||||
|    node = context->free_head; | ||||
|    node->x = (stbrp_coord) res.x; | ||||
|    node->y = (stbrp_coord) (res.y + height); | ||||
|  | ||||
|    context->free_head = node->next; | ||||
|  | ||||
|    // insert the new node into the right starting point, and | ||||
|    // let 'cur' point to the remaining nodes needing to be | ||||
|    // stiched back in | ||||
|  | ||||
|    cur = *res.prev_link; | ||||
|    if (cur->x < res.x) { | ||||
|       // preserve the existing one, so start testing with the next one | ||||
|       stbrp_node *next = cur->next; | ||||
|       cur->next = node; | ||||
|       cur = next; | ||||
|    } else { | ||||
|       *res.prev_link = node; | ||||
|    } | ||||
|  | ||||
|    // from here, traverse cur and free the nodes, until we get to one | ||||
|    // that shouldn't be freed | ||||
|    while (cur->next && cur->next->x <= res.x + width) { | ||||
|       stbrp_node *next = cur->next; | ||||
|       // move the current node to the free list | ||||
|       cur->next = context->free_head; | ||||
|       context->free_head = cur; | ||||
|       cur = next; | ||||
|    } | ||||
|  | ||||
|    // stitch the list back in | ||||
|    node->next = cur; | ||||
|  | ||||
|    if (cur->x < res.x + width) | ||||
|       cur->x = (stbrp_coord) (res.x + width); | ||||
|  | ||||
| #ifdef _DEBUG | ||||
|    cur = context->active_head; | ||||
|    while (cur->x < context->width) { | ||||
|       STBRP_ASSERT(cur->x < cur->next->x); | ||||
|       cur = cur->next; | ||||
|    } | ||||
|    STBRP_ASSERT(cur->next == NULL); | ||||
|  | ||||
|    { | ||||
|       int count=0; | ||||
|       cur = context->active_head; | ||||
|       while (cur) { | ||||
|          cur = cur->next; | ||||
|          ++count; | ||||
|       } | ||||
|       cur = context->free_head; | ||||
|       while (cur) { | ||||
|          cur = cur->next; | ||||
|          ++count; | ||||
|       } | ||||
|       STBRP_ASSERT(count == context->num_nodes+2); | ||||
|    } | ||||
| #endif | ||||
|  | ||||
|    return res; | ||||
| } | ||||
|  | ||||
| static int STBRP__CDECL rect_height_compare(const void *a, const void *b) | ||||
| { | ||||
|    const stbrp_rect *p = (const stbrp_rect *) a; | ||||
|    const stbrp_rect *q = (const stbrp_rect *) b; | ||||
|    if (p->h > q->h) | ||||
|       return -1; | ||||
|    if (p->h < q->h) | ||||
|       return  1; | ||||
|    return (p->w > q->w) ? -1 : (p->w < q->w); | ||||
| } | ||||
|  | ||||
| static int STBRP__CDECL rect_original_order(const void *a, const void *b) | ||||
| { | ||||
|    const stbrp_rect *p = (const stbrp_rect *) a; | ||||
|    const stbrp_rect *q = (const stbrp_rect *) b; | ||||
|    return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); | ||||
| } | ||||
|  | ||||
| STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) | ||||
| { | ||||
|    int i, all_rects_packed = 1; | ||||
|  | ||||
|    // we use the 'was_packed' field internally to allow sorting/unsorting | ||||
|    for (i=0; i < num_rects; ++i) { | ||||
|       rects[i].was_packed = i; | ||||
|    } | ||||
|  | ||||
|    // sort according to heuristic | ||||
|    STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); | ||||
|  | ||||
|    for (i=0; i < num_rects; ++i) { | ||||
|       if (rects[i].w == 0 || rects[i].h == 0) { | ||||
|          rects[i].x = rects[i].y = 0;  // empty rect needs no space | ||||
|       } else { | ||||
|          stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); | ||||
|          if (fr.prev_link) { | ||||
|             rects[i].x = (stbrp_coord) fr.x; | ||||
|             rects[i].y = (stbrp_coord) fr.y; | ||||
|          } else { | ||||
|             rects[i].x = rects[i].y = STBRP__MAXVAL; | ||||
|          } | ||||
|       } | ||||
|    } | ||||
|  | ||||
|    // unsort | ||||
|    STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); | ||||
|  | ||||
|    // set was_packed flags and all_rects_packed status | ||||
|    for (i=0; i < num_rects; ++i) { | ||||
|       rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); | ||||
|       if (!rects[i].was_packed) | ||||
|          all_rects_packed = 0; | ||||
|    } | ||||
|  | ||||
|    // return the all_rects_packed status | ||||
|    return all_rects_packed; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* | ||||
| ------------------------------------------------------------------------------ | ||||
| This software is available under 2 licenses -- choose whichever you prefer. | ||||
| ------------------------------------------------------------------------------ | ||||
| ALTERNATIVE A - MIT License | ||||
| Copyright (c) 2017 Sean Barrett | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy of | ||||
| this software and associated documentation files (the "Software"), to deal in | ||||
| the Software without restriction, including without limitation the rights to | ||||
| use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||||
| of the Software, and to permit persons to whom the Software is furnished to do | ||||
| so, subject to the following conditions: | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
| ------------------------------------------------------------------------------ | ||||
| ALTERNATIVE B - Public Domain (www.unlicense.org) | ||||
| This is free and unencumbered software released into the public domain. | ||||
| Anyone is free to copy, modify, publish, use, compile, sell, or distribute this | ||||
| software, either in source code form or as a compiled binary, for any purpose, | ||||
| commercial or non-commercial, and by any means. | ||||
| In jurisdictions that recognize copyright laws, the author or authors of this | ||||
| software dedicate any and all copyright interest in the software to the public | ||||
| domain. We make this dedication for the benefit of the public at large and to | ||||
| the detriment of our heirs and successors. We intend this dedication to be an | ||||
| overt act of relinquishment in perpetuity of all present and future rights to | ||||
| this software under copyright law. | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||||
| ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
| ------------------------------------------------------------------------------ | ||||
| */ | ||||
							
								
								
									
										1488
									
								
								dep/imgui/imstb_textedit.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1488
									
								
								dep/imgui/imstb_textedit.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5085
									
								
								dep/imgui/imstb_truetype.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5085
									
								
								dep/imgui/imstb_truetype.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,15 +0,0 @@ | ||||
| 40track_drive | ||||
| ==== | ||||
| ## Adjust configuration for a 40-track drive | ||||
| <!-- This file is automatically generated. Do not edit. --> | ||||
|  | ||||
| This is an extension profile; adding this to the command line will configure | ||||
| FluxEngine to read from 40-track, 48tpi 5.25" drives. You have to tell it because there is | ||||
| no way to detect this automatically. | ||||
|  | ||||
| For example: | ||||
|  | ||||
| ``` | ||||
| fluxengine read ibm --180 40track_drive | ||||
| ``` | ||||
|  | ||||
| @@ -31,9 +31,9 @@ they might require nudging as the side order can't be reliably autodetected. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read acornadfs --160 -s drive:0 -o acornadfs.img` | ||||
|   - `fluxengine read acornadfs --320 -s drive:0 -o acornadfs.img` | ||||
|   - `fluxengine read acornadfs --640 -s drive:0 -o acornadfs.img` | ||||
|   - `fluxengine read acornadfs --800 -s drive:0 -o acornadfs.img` | ||||
|   - `fluxengine read acornadfs --1600 -s drive:0 -o acornadfs.img` | ||||
|   - `fluxengine read -c acornadfs --160 -s drive:0 -o acornadfs.img` | ||||
|   - `fluxengine read -c acornadfs --320 -s drive:0 -o acornadfs.img` | ||||
|   - `fluxengine read -c acornadfs --640 -s drive:0 -o acornadfs.img` | ||||
|   - `fluxengine read -c acornadfs --800 -s drive:0 -o acornadfs.img` | ||||
|   - `fluxengine read -c acornadfs --1600 -s drive:0 -o acornadfs.img` | ||||
|  | ||||
|   | ||||
| @@ -24,13 +24,13 @@ requires a bit of fiddling as they have the same tracks on twice. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read acorndfs --100 -s drive:0 -o acorndfs.img` | ||||
|   - `fluxengine read acorndfs --200 -s drive:0 -o acorndfs.img` | ||||
|   - `fluxengine read -c acorndfs --100 -s drive:0 -o acorndfs.img` | ||||
|   - `fluxengine read -c acorndfs --200 -s drive:0 -o acorndfs.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write acorndfs --100 -d drive:0 -i acorndfs.img` | ||||
|   - `fluxengine write acorndfs --200 -d drive:0 -i acorndfs.img` | ||||
|   - `fluxengine write -c acorndfs --100 -d drive:0 -i acorndfs.img` | ||||
|   - `fluxengine write -c acorndfs --200 -d drive:0 -i acorndfs.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -37,7 +37,7 @@ based on what looks right. If anyone knows _anything_ about these disks, | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read aeslanier -s drive:0 -o aeslanier.img` | ||||
|   - `fluxengine read -c aeslanier -s drive:0 -o aeslanier.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -20,11 +20,11 @@ profile. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read agat -s drive:0 -o agat.img` | ||||
|   - `fluxengine read -c agat -s drive:0 -o agat.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write agat -d drive:0 -i agat.img` | ||||
|   - `fluxengine write -c agat -d drive:0 -i agat.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -26,11 +26,11 @@ distinctly subpar and not particularly good at detecting errors. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read amiga -s drive:0 -o amiga.adf` | ||||
|   - `fluxengine read -c amiga -s drive:0 -o amiga.adf` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write amiga -d drive:0 -i amiga.adf` | ||||
|   - `fluxengine write -c amiga -d drive:0 -i amiga.adf` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -43,8 +43,8 @@ kayinfo.lbr | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read ampro --400 -s drive:0 -o ampro.img` | ||||
|   - `fluxengine read ampro --800 -s drive:0 -o ampro.img` | ||||
|   - `fluxengine read -c ampro --400 -s drive:0 -o ampro.img` | ||||
|   - `fluxengine read -c ampro --800 -s drive:0 -o ampro.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -58,13 +58,13 @@ volume. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read apple2 --140 -s drive:0 -o apple2.img` | ||||
|   - `fluxengine read apple2 --640 -s drive:0 -o apple2.img` | ||||
|   - `fluxengine read -c apple2 --140 -s drive:0 -o apple2.img` | ||||
|   - `fluxengine read -c apple2 --640 -s drive:0 -o apple2.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write apple2 --140 -d drive:0 -i apple2.img` | ||||
|   - `fluxengine write apple2 --640 -d drive:0 -i apple2.img` | ||||
|   - `fluxengine write -c apple2 --140 -d drive:0 -i apple2.img` | ||||
|   - `fluxengine write -c apple2 --640 -d drive:0 -i apple2.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -1,16 +0,0 @@ | ||||
| apple2_drive | ||||
| ==== | ||||
| ## Adjust configuration for a 40-track Apple II drive | ||||
| <!-- This file is automatically generated. Do not edit. --> | ||||
|  | ||||
| This is an extension profile; adding this to the command line will configure | ||||
| FluxEngine to adjust the pinout and track spacing to work with an Apple II | ||||
| drive.  This only works on Greaseweazle hardware and requires a custom | ||||
| connector. | ||||
|  | ||||
| For example: | ||||
|  | ||||
| ``` | ||||
| fluxengine read apple2 --160 apple2_drive | ||||
| ``` | ||||
|  | ||||
| @@ -29,25 +29,25 @@ Be aware that many PC drives (including mine) won't do the 82 track formats. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read atarist --360 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read atarist --370 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read atarist --400 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read atarist --410 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read atarist --720 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read atarist --740 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read atarist --800 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read atarist --820 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read -c atarist --360 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read -c atarist --370 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read -c atarist --400 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read -c atarist --410 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read -c atarist --720 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read -c atarist --740 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read -c atarist --800 -s drive:0 -o atarist.img` | ||||
|   - `fluxengine read -c atarist --820 -s drive:0 -o atarist.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write atarist --360 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write atarist --370 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write atarist --400 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write atarist --410 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write atarist --720 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write atarist --740 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write atarist --800 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write atarist --820 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write -c atarist --360 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write -c atarist --370 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write -c atarist --400 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write -c atarist --410 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write -c atarist --720 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write -c atarist --740 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write -c atarist --800 -d drive:0 -i atarist.img` | ||||
|   - `fluxengine write -c atarist --820 -d drive:0 -i atarist.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -22,9 +22,9 @@ on what was available at the time, with the same format on both. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read bk -s drive:0 -o bk800.img` | ||||
|   - `fluxengine read -c bk -s drive:0 -o bk800.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write bk -d drive:0 -i bk800.img` | ||||
|   - `fluxengine write -c bk -d drive:0 -i bk800.img` | ||||
|  | ||||
|   | ||||
| @@ -44,13 +44,13 @@ investigate. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read brother --120 -s drive:0 -o brother.img` | ||||
|   - `fluxengine read brother --240 -s drive:0 -o brother.img` | ||||
|   - `fluxengine read -c brother --120 -s drive:0 -o brother.img` | ||||
|   - `fluxengine read -c brother --240 -s drive:0 -o brother.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write brother --120 -d drive:0 -i brother.img` | ||||
|   - `fluxengine write brother --240 -d drive:0 -i brother.img` | ||||
|   - `fluxengine write -c brother --120 -d drive:0 -i brother.img` | ||||
|   - `fluxengine write -c brother --240 -d drive:0 -i brother.img` | ||||
|  | ||||
| Dealing with misaligned disks | ||||
| ----------------------------- | ||||
|   | ||||
| @@ -54,18 +54,18 @@ A CMD FD2000 disk (a popular third-party Commodore disk drive) | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read commodore --171 -s drive:0 -o commodore.d64` | ||||
|   - `fluxengine read commodore --192 -s drive:0 -o commodore.d64` | ||||
|   - `fluxengine read commodore --800 -s drive:0 -o commodore.d64` | ||||
|   - `fluxengine read commodore --1042 -s drive:0 -o commodore.d64` | ||||
|   - `fluxengine read commodore --1620 -s drive:0 -o commodore.d64` | ||||
|   - `fluxengine read -c commodore --171 -s drive:0 -o commodore.d64` | ||||
|   - `fluxengine read -c commodore --192 -s drive:0 -o commodore.d64` | ||||
|   - `fluxengine read -c commodore --800 -s drive:0 -o commodore.d64` | ||||
|   - `fluxengine read -c commodore --1042 -s drive:0 -o commodore.d64` | ||||
|   - `fluxengine read -c commodore --1620 -s drive:0 -o commodore.d64` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write commodore --171 -d drive:0 -i commodore.d64` | ||||
|   - `fluxengine write commodore --192 -d drive:0 -i commodore.d64` | ||||
|   - `fluxengine write commodore --800 -d drive:0 -i commodore.d64` | ||||
|   - `fluxengine write commodore --1620 -d drive:0 -i commodore.d64` | ||||
|   - `fluxengine write -c commodore --171 -d drive:0 -i commodore.d64` | ||||
|   - `fluxengine write -c commodore --192 -d drive:0 -i commodore.d64` | ||||
|   - `fluxengine write -c commodore --800 -d drive:0 -i commodore.d64` | ||||
|   - `fluxengine write -c commodore --1620 -d drive:0 -i commodore.d64` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -33,7 +33,7 @@ images. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read eco1 -s drive:0 -o eco1.img` | ||||
|   - `fluxengine read -c eco1 -s drive:0 -o eco1.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -15,5 +15,5 @@ format itself is yet another IBM scheme variant. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read epsonpf10 -s drive:0 -o epsonpf10.img` | ||||
|   - `fluxengine read -c epsonpf10 -s drive:0 -o epsonpf10.img` | ||||
|  | ||||
|   | ||||
| @@ -36,7 +36,7 @@ touch](https://github.com/davidgiven/fluxengine/issues/new). | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read f85 -s drive:0 -o f85.img` | ||||
|   - `fluxengine read -c f85 -s drive:0 -o f85.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -30,7 +30,7 @@ I don't have access to one of those disks. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read fb100 -s drive:0 -o fb100.img` | ||||
|   - `fluxengine read -c fb100 -s drive:0 -o fb100.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -23,17 +23,17 @@ encoding scheme. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read hplif --264 -s drive:0 -o hplif.img` | ||||
|   - `fluxengine read hplif --608 -s drive:0 -o hplif.img` | ||||
|   - `fluxengine read hplif --616 -s drive:0 -o hplif.img` | ||||
|   - `fluxengine read hplif --770 -s drive:0 -o hplif.img` | ||||
|   - `fluxengine read -c hplif --264 -s drive:0 -o hplif.img` | ||||
|   - `fluxengine read -c hplif --608 -s drive:0 -o hplif.img` | ||||
|   - `fluxengine read -c hplif --616 -s drive:0 -o hplif.img` | ||||
|   - `fluxengine read -c hplif --770 -s drive:0 -o hplif.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write hplif --264 -d drive:0 -i hplif.img` | ||||
|   - `fluxengine write hplif --608 -d drive:0 -i hplif.img` | ||||
|   - `fluxengine write hplif --616 -d drive:0 -i hplif.img` | ||||
|   - `fluxengine write hplif --770 -d drive:0 -i hplif.img` | ||||
|   - `fluxengine write -c hplif --264 -d drive:0 -i hplif.img` | ||||
|   - `fluxengine write -c hplif --608 -d drive:0 -i hplif.img` | ||||
|   - `fluxengine write -c hplif --616 -d drive:0 -i hplif.img` | ||||
|   - `fluxengine write -c hplif --770 -d drive:0 -i hplif.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -55,30 +55,30 @@ image format. FluxEngine will use these parameters. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read ibm --auto -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read ibm --160 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read ibm --180 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read ibm --320 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read ibm --360 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read ibm --720_96 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read ibm --720_135 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read ibm --1200 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read ibm --1232 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read ibm --1440 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read ibm --1680 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read -c ibm --auto -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read -c ibm --160 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read -c ibm --180 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read -c ibm --320 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read -c ibm --360 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read -c ibm --720_96 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read -c ibm --720_135 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read -c ibm --1200 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read -c ibm --1232 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read -c ibm --1440 -s drive:0 -o ibm.img` | ||||
|   - `fluxengine read -c ibm --1680 -s drive:0 -o ibm.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write ibm --160 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write ibm --180 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write ibm --320 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write ibm --360 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write ibm --720_96 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write ibm --720_135 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write ibm --1200 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write ibm --1232 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write ibm --1440 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write ibm --1680 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write -c ibm --160 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write -c ibm --180 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write -c ibm --320 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write -c ibm --360 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write -c ibm --720_96 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write -c ibm --720_135 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write -c ibm --1200 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write -c ibm --1232 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write -c ibm --1440 -d drive:0 -i ibm.img` | ||||
|   - `fluxengine write -c ibm --1680 -d drive:0 -i ibm.img` | ||||
|  | ||||
| Mixed-format disks | ||||
| ------------------ | ||||
|   | ||||
| @@ -15,5 +15,5 @@ track! Other than that it's another IBM scheme variation. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read icl30 -s drive:0 -o icl30.img` | ||||
|   - `fluxengine read -c icl30 -s drive:0 -o icl30.img` | ||||
|  | ||||
|   | ||||
| @@ -47,13 +47,13 @@ standard for disk images is to omit it. If you want them, specify that you want | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read mac --400 -s drive:0 -o mac.dsk` | ||||
|   - `fluxengine read mac --800 -s drive:0 -o mac.dsk` | ||||
|   - `fluxengine read -c mac --400 -s drive:0 -o mac.dsk` | ||||
|   - `fluxengine read -c mac --800 -s drive:0 -o mac.dsk` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write mac --400 -d drive:0 -i mac.dsk` | ||||
|   - `fluxengine write mac --800 -d drive:0 -i mac.dsk` | ||||
|   - `fluxengine write -c mac --400 -d drive:0 -i mac.dsk` | ||||
|   - `fluxengine write -c mac --800 -d drive:0 -i mac.dsk` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -63,11 +63,11 @@ need to apply extra options to change the format if desired. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read micropolis -s drive:0 -o micropolis.img` | ||||
|   - `fluxengine read -c micropolis -s drive:0 -o micropolis.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write micropolis -d drive:0 -i micropolis.img` | ||||
|   - `fluxengine write -c micropolis -d drive:0 -i micropolis.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -52,10 +52,10 @@ Words are all stored little-endian. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read mx --110 -s drive:0 -o mx.img` | ||||
|   - `fluxengine read mx --220ds -s drive:0 -o mx.img` | ||||
|   - `fluxengine read mx --220ss -s drive:0 -o mx.img` | ||||
|   - `fluxengine read mx --440 -s drive:0 -o mx.img` | ||||
|   - `fluxengine read -c mx --110 -s drive:0 -o mx.img` | ||||
|   - `fluxengine read -c mx --220ds -s drive:0 -o mx.img` | ||||
|   - `fluxengine read -c mx --220ss -s drive:0 -o mx.img` | ||||
|   - `fluxengine read -c mx --440 -s drive:0 -o mx.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -18,9 +18,9 @@ boot ROM could only read single density data.) | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read n88basic -s drive:0 -o n88basic.img` | ||||
|   - `fluxengine read -c n88basic -s drive:0 -o n88basic.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write n88basic -d drive:0 -i n88basic.img` | ||||
|   - `fluxengine write -c n88basic -d drive:0 -i n88basic.img` | ||||
|  | ||||
|   | ||||
| @@ -31,15 +31,15 @@ equivalent to .img images. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read northstar --87 -s drive:0 -o northstar.nsi` | ||||
|   - `fluxengine read northstar --175 -s drive:0 -o northstar.nsi` | ||||
|   - `fluxengine read northstar --350 -s drive:0 -o northstar.nsi` | ||||
|   - `fluxengine read -c northstar --87 -s drive:0 -o northstar.nsi` | ||||
|   - `fluxengine read -c northstar --175 -s drive:0 -o northstar.nsi` | ||||
|   - `fluxengine read -c northstar --350 -s drive:0 -o northstar.nsi` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write northstar --87 -d drive:0 -i northstar.nsi` | ||||
|   - `fluxengine write northstar --175 -d drive:0 -i northstar.nsi` | ||||
|   - `fluxengine write northstar --350 -d drive:0 -i northstar.nsi` | ||||
|   - `fluxengine write -c northstar --87 -d drive:0 -i northstar.nsi` | ||||
|   - `fluxengine write -c northstar --175 -d drive:0 -i northstar.nsi` | ||||
|   - `fluxengine write -c northstar --350 -d drive:0 -i northstar.nsi` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -24,9 +24,9 @@ and, oddly, swapped sides. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read psos -s drive:0 -o pme.img` | ||||
|   - `fluxengine read -c psos -s drive:0 -o pme.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write psos -d drive:0 -i pme.img` | ||||
|   - `fluxengine write -c psos -d drive:0 -i pme.img` | ||||
|  | ||||
|   | ||||
| @@ -40,9 +40,9 @@ for assistance with this! | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read rolandd20 -s drive:0 -o rolandd20.img` | ||||
|   - `fluxengine read -c rolandd20 -s drive:0 -o rolandd20.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write rolandd20 -d drive:0 -i rolandd20.img` | ||||
|   - `fluxengine write -c rolandd20 -d drive:0 -i rolandd20.img` | ||||
|  | ||||
|   | ||||
| @@ -15,9 +15,9 @@ vanilla single-sided IBM scheme variation. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read rx50 -s drive:0 -o rx50.img` | ||||
|   - `fluxengine read -c rx50 -s drive:0 -o rx50.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write rx50 -d drive:0 -i rx50.img` | ||||
|   - `fluxengine write -c rx50 -d drive:0 -i rx50.img` | ||||
|  | ||||
|   | ||||
| @@ -1,15 +0,0 @@ | ||||
| shugart_drive | ||||
| ==== | ||||
| ## Adjust configuration for a Shugart drive | ||||
| <!-- This file is automatically generated. Do not edit. --> | ||||
|  | ||||
| This is an extension profile; adding this to the command line will configure | ||||
| FluxEngine to adjust the pinout to work with a Shugart drive. This only works | ||||
| on Greaseweazle hardware. | ||||
|  | ||||
| For example: | ||||
|  | ||||
| ``` | ||||
| fluxengine read ibm --720 shugart_drive | ||||
| ``` | ||||
|  | ||||
| @@ -26,7 +26,7 @@ this is completely correct, so don't trust it! | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read smaky6 -s drive:0 -o smaky6.img` | ||||
|   - `fluxengine read -c smaky6 -s drive:0 -o smaky6.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -34,13 +34,13 @@ FluxEngine supports reading and writing Tartu disks with CP/M filesystem access. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read tartu --390 -s drive:0 -o tartu.img` | ||||
|   - `fluxengine read tartu --780 -s drive:0 -o tartu.img` | ||||
|   - `fluxengine read -c tartu --390 -s drive:0 -o tartu.img` | ||||
|   - `fluxengine read -c tartu --780 -s drive:0 -o tartu.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write tartu --390 -d drive:0 -i tartu.img` | ||||
|   - `fluxengine write tartu --780 -d drive:0 -i tartu.img` | ||||
|   - `fluxengine write -c tartu --390 -d drive:0 -i tartu.img` | ||||
|   - `fluxengine write -c tartu --780 -d drive:0 -i tartu.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -26,11 +26,11 @@ FluxEngine will read and write these (but only the DSDD MFM variant). | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read tids990 -s drive:0 -o tids990.img` | ||||
|   - `fluxengine read -c tids990 -s drive:0 -o tids990.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write tids990 -d drive:0 -i tids990.img` | ||||
|   - `fluxengine write -c tids990 -d drive:0 -i tids990.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -20,8 +20,8 @@ on the precise format. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read tiki --90 -s drive:0 -o tiki.img` | ||||
|   - `fluxengine read tiki --200 -s drive:0 -o tiki.img` | ||||
|   - `fluxengine read tiki --400 -s drive:0 -o tiki.img` | ||||
|   - `fluxengine read tiki --800 -s drive:0 -o tiki.img` | ||||
|   - `fluxengine read -c tiki --90 -s drive:0 -o tiki.img` | ||||
|   - `fluxengine read -c tiki --200 -s drive:0 -o tiki.img` | ||||
|   - `fluxengine read -c tiki --400 -s drive:0 -o tiki.img` | ||||
|   - `fluxengine read -c tiki --800 -s drive:0 -o tiki.img` | ||||
|  | ||||
|   | ||||
| @@ -46,13 +46,13 @@ FluxEngine can read and write both the single-sided and double-sided variants. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read victor9k --612 -s drive:0 -o victor9k.img` | ||||
|   - `fluxengine read victor9k --1224 -s drive:0 -o victor9k.img` | ||||
|   - `fluxengine read -c victor9k --612 -s drive:0 -o victor9k.img` | ||||
|   - `fluxengine read -c victor9k --1224 -s drive:0 -o victor9k.img` | ||||
|  | ||||
| To write: | ||||
|  | ||||
|   - `fluxengine write victor9k --612 -d drive:0 -i victor9k.img` | ||||
|   - `fluxengine write victor9k --1224 -d drive:0 -i victor9k.img` | ||||
|   - `fluxengine write -c victor9k --612 -d drive:0 -i victor9k.img` | ||||
|   - `fluxengine write -c victor9k --1224 -d drive:0 -i victor9k.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -31,7 +31,7 @@ system. | ||||
|  | ||||
| To read: | ||||
|  | ||||
|   - `fluxengine read zilogmcz -s drive:0 -o zilogmcz.img` | ||||
|   - `fluxengine read -c zilogmcz -s drive:0 -o zilogmcz.img` | ||||
|  | ||||
| ## References | ||||
|  | ||||
|   | ||||
| @@ -36,10 +36,10 @@ Forty track formats on a forty track drive | ||||
| ------------------------------------------ | ||||
|  | ||||
| If you actually have a forty track drive, you need to tell FluxEngine. This is | ||||
| done by adding the special profile `40track_drive`: | ||||
| done by adding `--drivetype=40`: | ||||
|  | ||||
| ``` | ||||
| fluxengine write ibm --360 40track_drive -i image.img -d drive:0 | ||||
| fluxengine write -c ibm --360 --drivetype=40 -i image.img -d drive:0 | ||||
| ``` | ||||
|  | ||||
| It should then Just Work. This is supported by both FluxEngine and Greaseweazle | ||||
| @@ -47,24 +47,6 @@ hardware. | ||||
|  | ||||
| Obviously you can't write an eighty-track format using a forty-track drive! | ||||
|  | ||||
| Apple II drives | ||||
| --------------- | ||||
|  | ||||
| The Apple II had special drives which supported microstepping: when commanded | ||||
| to move the head, then instead of moving in single-track steps as is done in | ||||
| most other drives, the Apple II drive would move in quarter-track steps. This | ||||
| allowed much less precise head alignment, as small errors could be corrected in | ||||
| software. (The Brother word processor drives were similar.) The bus interface | ||||
| is different from normal PC drives. | ||||
|  | ||||
| The FluxEngine client supports these with the `apple2_drive` profile: | ||||
|  | ||||
| ``` | ||||
| fluxengine write apple2 apple2_drive -i image.img -d drive:0 | ||||
| ``` | ||||
|  | ||||
| This is supported only by Greaseweazle hardware. | ||||
|  | ||||
| Shugart drives | ||||
| -------------- | ||||
|  | ||||
| @@ -77,14 +59,32 @@ the drives must be jumpered to configure them. This was mostly used by older | ||||
| 3.5" drives, such as those on the Atari ST. [the How It Works | ||||
| page](technical.md) for the pinout. | ||||
|  | ||||
| The FluxEngine client supports these with the `shugart_drive` profile: | ||||
| The FluxEngine client supports these with `--bus=shugart`: | ||||
|  | ||||
| ``` | ||||
| fluxengine write atarist720 shugart_drive -i image.img -d drive:0 | ||||
| fluxengine write -c atarist720 --bus=shugart -i image.img -d drive:0 | ||||
| ``` | ||||
|  | ||||
| (If you have a 40-track Shugart drive, use _both_ `shugart_drive` and | ||||
| `40track_drive`.) | ||||
| (If you have a 40-track Shugart drive, use _both_ `--bus=shugart` and | ||||
| `--drivetype=40`.) | ||||
|  | ||||
| This is supported only by Greaseweazle hardware. | ||||
|  | ||||
| Apple II drives | ||||
| --------------- | ||||
|  | ||||
| The Apple II had special drives which supported microstepping: when commanded | ||||
| to move the head, then instead of moving in single-track steps as is done in | ||||
| most other drives, the Apple II drive would move in quarter-track steps. This | ||||
| allowed much less precise head alignment, as small errors could be corrected in | ||||
| software. (The Brother word processor drives were similar.) The bus interface | ||||
| is different from normal PC drives. | ||||
|  | ||||
| The FluxEngine client supports these with `--drivetype=160 --bus=appleii`. | ||||
|  | ||||
| ``` | ||||
| fluxengine write -c apple2 --drivetype=160 --bus=appleii -i image.img -d drive:0 | ||||
| ``` | ||||
|  | ||||
| This is supported only by Greaseweazle hardware. | ||||
|  | ||||
|   | ||||
							
								
								
									
										48
									
								
								doc/using.md
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								doc/using.md
									
									
									
									
									
								
							| @@ -15,7 +15,7 @@ If possible, try using the GUI, which should provide simplified access for most | ||||
| common operations. | ||||
|  | ||||
| <div style="text-align: center"> | ||||
| <a href="doc/screenshot-details.png"><img src="doc/screenshot-details.png" style="width:60%" alt="screenshot of the GUI in action"></a> | ||||
| <a href="screenshot-details.png"><img src="screenshot-details.png" style="width:60%" alt="screenshot of the GUI in action"></a> | ||||
| </div> | ||||
|  | ||||
| ### Core concepts | ||||
| @@ -82,16 +82,16 @@ Here are some sample invocations: | ||||
| ``` | ||||
| # Read an PC 1440kB disk, producing a disk image with the default name | ||||
| # (ibm.img) | ||||
| $ fluxengine read ibm --1440 | ||||
| $ fluxengine read -c ibm --1440 | ||||
|  | ||||
| # Write a PC 1440kB disk to drive 1 | ||||
| $ fluxengine write ibm --1440 -i image.img -d drive:1 | ||||
| $ fluxengine write -c ibm --1440 -i image.img -d drive:1 | ||||
|  | ||||
| # Read a Eco1 CP/M disk, making a copy of the flux into a file | ||||
| $ fluxengine read eco1 --copy-flux-to copy.flux -o eco1.ldbs | ||||
| $ fluxengine read -c eco1 --copy-flux-to copy.flux -o eco1.ldbs | ||||
|  | ||||
| # Rerun the decode from the flux file, tweaking the parameters | ||||
| $ fluxengine read eco1 -s copy.flux -o eco1.ldbs --cylinders=1 | ||||
| $ fluxengine read -c eco1 -s copy.flux -o eco1.ldbs --cylinders=1 | ||||
| ``` | ||||
|  | ||||
| ### Configuration | ||||
| @@ -108,13 +108,13 @@ encoder { | ||||
|     } | ||||
|   } | ||||
| } | ||||
| $ fluxengine write ibm --1440 config.textpb -i image.img | ||||
| $ fluxengine write -c ibm --1440 -c config.textpb -i image.img | ||||
| ``` | ||||
|  | ||||
| ...or you can specify them on the command line: | ||||
|  | ||||
| ``` | ||||
| $ fluxengine write ibm --1440 -i image.img --encoder.ibm.trackdata.emit_iam=false | ||||
| $ fluxengine write -c ibm --1440 -i image.img --encoder.ibm.trackdata.emit_iam=false | ||||
| ``` | ||||
|  | ||||
| Both the above invocations are equivalent. The text files use [Google's | ||||
| @@ -128,7 +128,7 @@ files as you wish; they are all merged left to right.  You can see all these | ||||
| settings by doing: | ||||
|  | ||||
| ``` | ||||
| $ fluxengine write ibm --1440 --config | ||||
| $ fluxengine write -c ibm --1440 --show-config | ||||
| ``` | ||||
|  | ||||
| The `--config` option will cause the current configuration to be dumped to the | ||||
| @@ -146,40 +146,26 @@ different task. Run each one with `--help` to get a full list of | ||||
| (non-configuration-setting) options; this describes only basic usage of the | ||||
| more common tools. | ||||
|  | ||||
|   - `fluxengine read <profile> <options> -s <flux source> -o <image output>` | ||||
|   - `fluxengine read -c <profile> <options> -s <flux source> -o <image output>` | ||||
|  | ||||
|     Reads flux (possibly from a disk) and decodes it into a file system image. | ||||
|     `<profile>` is a reference to an internal input configuration file | ||||
|     describing the format. `<options>` may be any combination of options | ||||
|     defined by the profile. | ||||
|  | ||||
|   - `fluxengine write <profile> -i <image input> -d <flux destination>` | ||||
|   - `fluxengine write -c <profile> -i <image input> -d <flux destination>` | ||||
|  | ||||
|     Reads a filesystem image and encodes it into flux (possibly writing to a | ||||
|     disk). `<profile>` is a reference to an internal output configuration file | ||||
|     describing the format. | ||||
|  | ||||
|   - `fluxengine rawread -s <flux source> -d <flux destination>` | ||||
|  | ||||
|     Reads flux (possibly from a disk) and writes it to a flux file without doing | ||||
|     any decoding. You can specify a profile if you want to read a subset of the | ||||
|     disk. | ||||
|  | ||||
|   - `fluxengine rawwrite -s <flux source> -d <flux destination>` | ||||
|  | ||||
|     Reads flux from a file and writes it (possibly to a disk) without doing any | ||||
|     encoding. You can specify a profile if you want to write a subset of the | ||||
|     disk. | ||||
|  | ||||
|   - `fluxengine merge -s <fluxfile> -s <fluxfile...> -d <fluxfile` | ||||
|  | ||||
|     Merges data from multiple flux files together. This is useful if you have | ||||
|     several reads from an unreliable disk where each read has a different set | ||||
|     of good sectors. By merging the flux files, you get to combine all the | ||||
|     data. Don't use this on reads of different disks, for obvious results! Note | ||||
|     that this works on flux files, not on flux sources. | ||||
|  | ||||
|   - `fluxengine inspect -s <flux source> -c <cylinder> -h <head> -B` | ||||
|   - `fluxengine inspect -s <flux source> -t <track> -h <head> -B` | ||||
|  | ||||
|     Reads flux (possibly from a disk) and does various analyses of it to try and | ||||
|     detect the clock rate, display raw flux information, examine the underlying | ||||
| @@ -198,14 +184,8 @@ more common tools. | ||||
|  | ||||
| There are other tools; try `fluxengine --help`. | ||||
|  | ||||
| **Important note on `rawread` and `rawwrite`:** You can't use these tools to | ||||
| **Important note on `rawwrite`:** You can't use theis tool to | ||||
| copy disks, in most circumstances. See [the FAQ](faq.md) for more information. | ||||
| Also, `rawread` is not guaranteed to read correctly. Floppy disks are | ||||
| fundamentally unreliable, and random bit errors may occur at any time; these | ||||
| can only be detected by performing a decode and verifying the checksums on the | ||||
| sectors. To perform a correct read, it's recommended to do `fluxengine read` | ||||
| with the `--copy-flux-to` option, to perform a decode to a filesystem image | ||||
| while also writing to a flux file. | ||||
|  | ||||
| ### Flux sources and destinations | ||||
|  | ||||
| @@ -489,7 +469,7 @@ containing valuable historical data, and you want to read them. | ||||
| Typically I do this: | ||||
|  | ||||
| ``` | ||||
| $ fluxengine read brother240 -s drive:0 -o brother.img --copy-flux-to=brother.flux --decoder.write_csv_to=brother.csv | ||||
| $ fluxengine read -c brother240 -s drive:0 -o brother.img --copy-flux-to=brother.flux --decoder.write_csv_to=brother.csv | ||||
| ``` | ||||
|  | ||||
| This will read the disk in drive 0 and write out an information CSV file. It'll | ||||
| @@ -499,7 +479,7 @@ settings, I can rerun the decode without having to physically touch the disk | ||||
| like this: | ||||
|  | ||||
| ``` | ||||
| $ fluxengine read brother -s brother.flux -o brother.img --decoder.write_csv_to=brother.csv | ||||
| $ fluxengine read -c brother -s brother.flux -o brother.img --decoder.write_csv_to=brother.csv | ||||
| ``` | ||||
|  | ||||
| Apart from being drastically faster, this avoids touching the (potentially | ||||
|   | ||||
| @@ -4,6 +4,7 @@ from build.c import clibrary | ||||
| from build.zip import zip | ||||
| from glob import glob | ||||
| from os.path import * | ||||
| import config | ||||
|  | ||||
| icons = ["fluxfile", "hardware", "icon", "imagefile"] | ||||
|  | ||||
| @@ -17,37 +18,37 @@ clibrary( | ||||
|     }, | ||||
| ) | ||||
|  | ||||
| simplerule( | ||||
|     name="fluxengine_icns", | ||||
|     ins=["./icon.png"], | ||||
|     outs=["=fluxengine.icns"], | ||||
|     commands=[ | ||||
|         "mkdir -p fluxengine.iconset", | ||||
|         "sips -z 64 64 $[ins[0]] --out fluxengine.iconset/icon_32x32@2x.png > /dev/null", | ||||
|         "iconutil -c icns -o $[outs[0]] fluxengine.iconset", | ||||
|     ], | ||||
|     label="ICONSET", | ||||
| ) | ||||
|  | ||||
| simplerule( | ||||
|     name="fluxengine_ico", | ||||
|     ins=["./icon.png"], | ||||
|     outs=["=fluxengine.ico"], | ||||
|     commands=["png2ico $[outs[0]] $[ins[0]]"], | ||||
|     label="MAKEICON", | ||||
| ) | ||||
|  | ||||
| template_files = [ | ||||
|     f | ||||
|     for f in glob( | ||||
|         "**", recursive=True, root_dir="extras/FluxEngine.app.template" | ||||
| if config.osx: | ||||
|     simplerule( | ||||
|         name="fluxengine_icns", | ||||
|         ins=["./icon.png"], | ||||
|         outs=["=fluxengine.icns"], | ||||
|         commands=[ | ||||
|             "mkdir -p fluxengine.iconset", | ||||
|             "sips -z 64 64 $[ins[0]] --out fluxengine.iconset/icon_32x32@2x.png > /dev/null", | ||||
|             "iconutil -c icns -o $[outs[0]] fluxengine.iconset", | ||||
|         ], | ||||
|         label="ICONSET", | ||||
|     ) | ||||
|  | ||||
|     template_files = [ | ||||
|         f | ||||
|         for f in glob("**", recursive=True, root_dir="extras/FluxEngine.app.template") | ||||
|         if isfile(join("extras/FluxEngine.app.template", f)) | ||||
|     ] | ||||
|     zip( | ||||
|         name="fluxengine_template", | ||||
|         items={ | ||||
|             join("FluxEngine.app", k): join("extras/FluxEngine.app.template", k) | ||||
|             for k in template_files | ||||
|         }, | ||||
|     ) | ||||
|  | ||||
| if config.windows: | ||||
|     simplerule( | ||||
|         name="fluxengine_ico", | ||||
|         ins=["./icon.png"], | ||||
|         outs=["=fluxengine.ico"], | ||||
|         commands=["png2ico $[outs[0]] $[ins[0]]"], | ||||
|         label="MAKEICON", | ||||
|     ) | ||||
|     if isfile(join("extras/FluxEngine.app.template", f)) | ||||
| ] | ||||
| zip( | ||||
|     name="fluxengine_template", | ||||
|     items={ | ||||
|         join("FluxEngine.app", k): join("extras/FluxEngine.app.template", k) | ||||
|         for k in template_files | ||||
|     }, | ||||
| ) | ||||
|   | ||||
| @@ -741,38 +741,3 @@ void readDiskCommand( | ||||
|             *diskflux->image, globalConfig()->decoder().write_csv_to()); | ||||
|     writer.writeImage(*diskflux->image); | ||||
| } | ||||
|  | ||||
| void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink) | ||||
| { | ||||
|     log(BeginOperationLogMessage{"Performing raw read of disk"}); | ||||
|  | ||||
|     if (fluxsource.isHardware() || fluxsink.isHardware()) | ||||
|         measureDiskRotation(); | ||||
|     auto physicalLocations = Layout::computePhysicalLocations(); | ||||
|     unsigned index = 0; | ||||
|     for (const auto& physicalLocation : physicalLocations) | ||||
|     { | ||||
|         log(OperationProgressLogMessage{ | ||||
|             index * 100 / (int)physicalLocations.size()}); | ||||
|         index++; | ||||
|  | ||||
|         testForEmergencyStop(); | ||||
|         auto trackInfo = Layout::getLayoutOfTrackPhysical( | ||||
|             physicalLocation.cylinder, physicalLocation.head); | ||||
|         auto fluxSourceIterator = fluxsource.readFlux( | ||||
|             trackInfo->physicalTrack, trackInfo->physicalSide); | ||||
|  | ||||
|         log(BeginReadOperationLogMessage{ | ||||
|             trackInfo->physicalTrack, trackInfo->physicalSide}); | ||||
|         auto fluxmap = fluxSourceIterator->next(); | ||||
|         log(EndReadOperationLogMessage()); | ||||
|         log("{0} ms in {1} bytes", | ||||
|             (int)(fluxmap->duration() / 1e6), | ||||
|             fluxmap->bytes()); | ||||
|  | ||||
|         fluxsink.writeFlux( | ||||
|             trackInfo->physicalTrack, trackInfo->physicalSide, *fluxmap); | ||||
|     } | ||||
|  | ||||
|     log(EndOperationLogMessage{"Raw read complete"}); | ||||
| } | ||||
|   | ||||
| @@ -111,6 +111,5 @@ extern std::shared_ptr<const DiskFlux> readDiskCommand( | ||||
|     FluxSource& fluxsource, Decoder& decoder); | ||||
| extern void readDiskCommand( | ||||
|     FluxSource& source, Decoder& decoder, ImageWriter& writer); | ||||
| extern void rawReadDiskCommand(FluxSource& source, FluxSink& sink); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| #include "lib/core/utils.h" | ||||
| #include <fstream> | ||||
| #include <google/protobuf/text_format.h> | ||||
| #include <fmt/ranges.h> | ||||
|  | ||||
| static Config config; | ||||
|  | ||||
| @@ -181,35 +182,8 @@ ConfigProto* Config::combined() | ||||
|     { | ||||
|         _combinedConfig = _baseConfig; | ||||
|  | ||||
|         /* First apply any standalone options. */ | ||||
|  | ||||
|         std::set<std::string> options = _appliedOptions; | ||||
|         for (const auto& option : _baseConfig.option()) | ||||
|         { | ||||
|             if (options.find(option.name()) != options.end()) | ||||
|             { | ||||
|                 _combinedConfig.MergeFrom(option.config()); | ||||
|                 options.erase(option.name()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* Then apply any group options. */ | ||||
|  | ||||
|         for (auto& group : _baseConfig.option_group()) | ||||
|         { | ||||
|             const OptionProto* selectedOption = &*group.option().begin(); | ||||
|  | ||||
|             for (auto& option : group.option()) | ||||
|             { | ||||
|                 if (options.find(option.name()) != options.end()) | ||||
|                 { | ||||
|                     selectedOption = &option; | ||||
|                     options.erase(option.name()); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             _combinedConfig.MergeFrom(selectedOption->config()); | ||||
|         } | ||||
|         for (const auto& optionInfo : _appliedOptions) | ||||
|             _combinedConfig.MergeFrom(optionInfo.option->config()); | ||||
|  | ||||
|         /* Add in the user overrides. */ | ||||
|  | ||||
| @@ -241,51 +215,27 @@ std::vector<std::string> Config::validate() | ||||
| { | ||||
|     std::vector<std::string> results; | ||||
|  | ||||
|     std::set<std::string> optionNames = _appliedOptions; | ||||
|     std::set<const OptionProto*> appliedOptions; | ||||
|     for (const auto& option : _baseConfig.option()) | ||||
|     { | ||||
|         if (optionNames.find(option.name()) != optionNames.end()) | ||||
|     /* Ensure that only one item in each group is set. */ | ||||
|  | ||||
|     std::map<const OptionGroupProto*, const OptionProto*> optionsByGroup; | ||||
|     for (auto [group, option, hasArgument] : _appliedOptions) | ||||
|         if (group) | ||||
|         { | ||||
|             appliedOptions.insert(&option); | ||||
|             optionNames.erase(option.name()); | ||||
|             auto& o = optionsByGroup[group]; | ||||
|             if (o) | ||||
|                 results.push_back( | ||||
|                     fmt::format("multiple mutually exclusive values set for " | ||||
|                                 "group '{}': valid values are: {}", | ||||
|                         group->comment(), | ||||
|                         fmt::join(std::views::transform( | ||||
|                                       group->option(), &OptionProto::name), | ||||
|                             ", "))); | ||||
|             o = option; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Then apply any group options. */ | ||||
|  | ||||
|     for (auto& group : _baseConfig.option_group()) | ||||
|     { | ||||
|         int count = 0; | ||||
|  | ||||
|         for (auto& option : group.option()) | ||||
|         { | ||||
|             if (optionNames.find(option.name()) != optionNames.end()) | ||||
|             { | ||||
|                 optionNames.erase(option.name()); | ||||
|                 appliedOptions.insert(&option); | ||||
|  | ||||
|                 count++; | ||||
|                 if (count == 2) | ||||
|                     results.push_back( | ||||
|                         fmt::format("multiple mutually exclusive options set " | ||||
|                                     "for group '{}'", | ||||
|                             group.comment())); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Check for unknown options. */ | ||||
|  | ||||
|     if (!optionNames.empty()) | ||||
|     { | ||||
|         for (auto& name : optionNames) | ||||
|             results.push_back(fmt::format("'{}' is not a known option", name)); | ||||
|     } | ||||
|  | ||||
|     /* Check option requirements. */ | ||||
|  | ||||
|     for (auto& option : appliedOptions) | ||||
|     for (auto [group, option, hasArgument] : _appliedOptions) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
| @@ -360,11 +310,12 @@ void Config::readBaseConfig(std::string data) | ||||
|         error("couldn't load external config proto"); | ||||
| } | ||||
|  | ||||
| const OptionProto& Config::findOption(const std::string& optionName) | ||||
| Config::OptionInfo Config::findOption( | ||||
|     const std::string& name, const std::string value) | ||||
| { | ||||
|     const OptionProto* found = nullptr; | ||||
|  | ||||
|     auto searchOptionList = [&](auto& optionList) | ||||
|     auto searchOptionList = [&](auto& optionList, const std::string& optionName) | ||||
|     { | ||||
|         for (const auto& option : optionList) | ||||
|         { | ||||
| @@ -377,17 +328,39 @@ const OptionProto& Config::findOption(const std::string& optionName) | ||||
|         return false; | ||||
|     }; | ||||
|  | ||||
|     if (searchOptionList(base()->option())) | ||||
|         return *found; | ||||
|     /* First look for any group names which match. */ | ||||
|  | ||||
|     if (!value.empty()) | ||||
|         for (const auto& optionGroup : base()->option_group()) | ||||
|             if (optionGroup.name() == name) | ||||
|             { | ||||
|                 /* The option must therefore be one of these. */ | ||||
|  | ||||
|                 if (searchOptionList(optionGroup.option(), value)) | ||||
|                     return {&optionGroup, found, true}; | ||||
|  | ||||
|                 throw OptionNotFoundException(fmt::format( | ||||
|                     "value {} is not valid for option {}; valid values are: {}", | ||||
|                     value, | ||||
|                     name, | ||||
|                     fmt::join(std::views::transform( | ||||
|                                   optionGroup.option(), &OptionProto::name), | ||||
|                         ", "))); | ||||
|             } | ||||
|  | ||||
|     /* Now search for individual options. */ | ||||
|  | ||||
|     if (searchOptionList(base()->option(), name)) | ||||
|         return {nullptr, found, false}; | ||||
|  | ||||
|     for (const auto& optionGroup : base()->option_group()) | ||||
|     { | ||||
|         if (searchOptionList(optionGroup.option())) | ||||
|             return *found; | ||||
|         if (optionGroup.name().empty()) | ||||
|             if (searchOptionList(optionGroup.option(), name)) | ||||
|                 return {nullptr, found, false}; | ||||
|     } | ||||
|  | ||||
|     throw OptionNotFoundException( | ||||
|         fmt::format("option {} not found", optionName)); | ||||
|     throw OptionNotFoundException(fmt::format("option {} not found", name)); | ||||
| } | ||||
|  | ||||
| void Config::checkOptionValid(const OptionProto& option) | ||||
| @@ -445,22 +418,20 @@ bool Config::isOptionValid(const OptionProto& option) | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool Config::isOptionValid(std::string option) | ||||
| { | ||||
|     return isOptionValid(findOption(option)); | ||||
| } | ||||
|  | ||||
| void Config::applyOption(const OptionProto& option) | ||||
| void Config::applyOption(const OptionInfo& optionInfo) | ||||
| { | ||||
|     auto* option = optionInfo.option; | ||||
|     log(OptionLogMessage{ | ||||
|         option.has_message() ? option.message() : option.comment()}); | ||||
|         option->has_message() ? option->message() : option->comment()}); | ||||
|  | ||||
|     _appliedOptions.insert(option.name()); | ||||
|     _appliedOptions.insert(optionInfo); | ||||
| } | ||||
|  | ||||
| void Config::applyOption(std::string option) | ||||
| bool Config::applyOption(const std::string& name, const std::string value) | ||||
| { | ||||
|     applyOption(findOption(option)); | ||||
|     auto optionInfo = findOption(name, value); | ||||
|     applyOption(optionInfo); | ||||
|     return optionInfo.usesValue; | ||||
| } | ||||
|  | ||||
| void Config::clearOptions() | ||||
|   | ||||
| @@ -66,6 +66,18 @@ struct FluxConstructor | ||||
|  | ||||
| class Config | ||||
| { | ||||
| private: | ||||
|     struct OptionInfo | ||||
|     { | ||||
|         bool operator==(const OptionInfo& other) const = default; | ||||
|         std::strong_ordering operator<=>( | ||||
|             const OptionInfo& other) const = default; | ||||
|  | ||||
|         const OptionGroupProto* group; | ||||
|         const OptionProto* option; | ||||
|         bool usesValue; | ||||
|     }; | ||||
|  | ||||
| public: | ||||
|     /* Direct access to the various proto layers. */ | ||||
|  | ||||
| @@ -124,12 +136,12 @@ public: | ||||
|     /* Option management: look up an option by name, determine whether an option | ||||
|      * is valid, and apply an option. */ | ||||
|  | ||||
|     const OptionProto& findOption(const std::string& option); | ||||
|     OptionInfo findOption( | ||||
|         const std::string& name, const std::string value = ""); | ||||
|     void checkOptionValid(const OptionProto& option); | ||||
|     bool isOptionValid(const OptionProto& option); | ||||
|     bool isOptionValid(std::string option); | ||||
|     void applyOption(const OptionProto& option); | ||||
|     void applyOption(std::string option); | ||||
|     void applyOption(const OptionInfo& optionInfo); | ||||
|     bool applyOption(const std::string& name, const std::string value = ""); | ||||
|     void clearOptions(); | ||||
|  | ||||
|     /* Adjust overall inputs and outputs. */ | ||||
| @@ -165,7 +177,7 @@ private: | ||||
|     ConfigProto _baseConfig; | ||||
|     ConfigProto _overridesConfig; | ||||
|     ConfigProto _combinedConfig; | ||||
|     std::set<std::string> _appliedOptions; | ||||
|     std::set<OptionInfo> _appliedOptions; | ||||
|     bool _configValid; | ||||
|  | ||||
|     FluxSourceProto _verificationFluxSourceProto; | ||||
|   | ||||
| @@ -73,5 +73,6 @@ message OptionProto | ||||
| message OptionGroupProto | ||||
| { | ||||
|     optional string comment = 1 [(help) = "help text for option group"]; | ||||
|     repeated OptionProto option = 2; | ||||
|     optional string name = 2 [(help) = "option group name"]; | ||||
|     repeated OptionProto option = 3; | ||||
| } | ||||
|   | ||||
| @@ -13,17 +13,23 @@ static std::vector<Flag*> all_flags; | ||||
| static std::map<const std::string, Flag*> flags_by_name; | ||||
|  | ||||
| static void doHelp(); | ||||
| static void doLoadConfig(const std::string& filename); | ||||
| static void doShowConfig(); | ||||
| static void doDoc(); | ||||
|  | ||||
| static FlagGroup helpGroup; | ||||
| static ActionFlag helpFlag = ActionFlag({"--help"}, "Shows the help.", doHelp); | ||||
|  | ||||
| static ActionFlag showConfigFlag = ActionFlag({"--config", "-C"}, | ||||
| static FlagGroup configGroup; | ||||
| static ActionFlag loadConfigFlag({"--config", "-c"}, | ||||
|     "Reads an internal or external configuration file.", | ||||
|     doLoadConfig); | ||||
|  | ||||
| static ActionFlag showConfigFlag({"--show-config", "-C"}, | ||||
|     "Shows the currently set configuration and halts.", | ||||
|     doShowConfig); | ||||
|  | ||||
| static ActionFlag docFlag = ActionFlag( | ||||
| static ActionFlag docFlag( | ||||
|     {"--doc"}, "Shows the available configuration options and halts.", doDoc); | ||||
|  | ||||
| FlagGroup::FlagGroup() | ||||
| @@ -152,7 +158,7 @@ std::vector<std::string> FlagGroup::parseFlagsWithFilenames(int argc, | ||||
|                         index += usesthat; | ||||
|                     } | ||||
|                     else | ||||
|                         globalConfig().applyOption(path); | ||||
|                         usesthat = globalConfig().applyOption(path, value); | ||||
|                 } | ||||
|                 else | ||||
|                     error("unrecognised flag '-{}'; try --help", key); | ||||
| @@ -182,17 +188,17 @@ void FlagGroup::parseFlags(int argc, | ||||
|             "non-option parameter '{}' seen (try --help)", *filenames.begin()); | ||||
| } | ||||
|  | ||||
| static void doLoadConfig(const std::string& filename) | ||||
| { | ||||
|     globalConfig().readBaseConfigFile(filename); | ||||
| } | ||||
|  | ||||
| void FlagGroup::parseFlagsWithConfigFiles(int argc, | ||||
|     const char* argv[], | ||||
|     const std::map<std::string, const ConfigProto*>& configFiles) | ||||
| { | ||||
|     parseFlags(argc, | ||||
|         argv, | ||||
|         [&](const auto& filename) | ||||
|         { | ||||
|             globalConfig().readBaseConfigFile(filename); | ||||
|             return true; | ||||
|         }); | ||||
|     globalConfig().readBaseConfigFile("_global_options"); | ||||
|     FlagGroup({this, &configGroup}).parseFlags(argc, argv); | ||||
| } | ||||
|  | ||||
| void FlagGroup::checkInitialised() const | ||||
|   | ||||
| @@ -83,13 +83,23 @@ public: | ||||
|         const std::string helptext, | ||||
|         std::function<void(void)> callback): | ||||
|         Flag(names, helptext), | ||||
|         _callback(callback) | ||||
|         _voidCallback(callback), | ||||
|         _hasArgument(false) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     ActionFlag(const std::vector<std::string>& names, | ||||
|         const std::string helptext, | ||||
|         std::function<void(const std::string&)> callback): | ||||
|         Flag(names, helptext), | ||||
|         _callback(callback), | ||||
|         _hasArgument(true) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     bool hasArgument() const override | ||||
|     { | ||||
|         return false; | ||||
|         return _hasArgument; | ||||
|     } | ||||
|  | ||||
|     const std::string defaultValueAsString() const override | ||||
| @@ -99,11 +109,16 @@ public: | ||||
|  | ||||
|     void set(const std::string& value) override | ||||
|     { | ||||
|         _callback(); | ||||
|         if (_hasArgument) | ||||
|             _callback(value); | ||||
|         else | ||||
|             _voidCallback(); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     const std::function<void(void)> _callback; | ||||
|     const std::function<void(const std::string&)> _callback; | ||||
|     const std::function<void(void)> _voidCallback; | ||||
|     bool _hasArgument; | ||||
| }; | ||||
|  | ||||
| class SettableFlag : public Flag | ||||
|   | ||||
| @@ -439,7 +439,7 @@ std::string ProtoField::get() const | ||||
|             case google::protobuf::FieldDescriptor::TYPE_ENUM: | ||||
|             { | ||||
|                 const auto* enumvalue = reflection->GetEnum(*_message, _field); | ||||
|                 return enumvalue->name(); | ||||
|                 return (std::string)enumvalue->name(); | ||||
|             } | ||||
|  | ||||
|             case google::protobuf::FieldDescriptor::TYPE_MESSAGE: | ||||
| @@ -534,7 +534,7 @@ findAllPossibleProtoFields(const google::protobuf::Descriptor* descriptor) | ||||
|         for (int i = 0; i < d->field_count(); i++) | ||||
|         { | ||||
|             const google::protobuf::FieldDescriptor* f = d->field(i); | ||||
|             std::string n = s + f->name(); | ||||
|             std::string n = s + (std::string)f->name(); | ||||
|  | ||||
|             if (f->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) | ||||
|                 n += "[]"; | ||||
|   | ||||
| @@ -14,10 +14,10 @@ destfile=$dir/dest.img | ||||
|  | ||||
| dd if=/dev/urandom of=$srcfile bs=1048576 count=2 2>&1 | ||||
|  | ||||
| echo $fluxengine write $format -i $srcfile -d $fluxfile --drive.rotational_period_ms=200 $flags | ||||
| $fluxengine write $format -i $srcfile -d $fluxfile --drive.rotational_period_ms=200 $flags | ||||
| echo $fluxengine read $format -s $fluxfile -o $destfile --drive.rotational_period_ms=200 $flags | ||||
| $fluxengine read $format -s $fluxfile -o $destfile --drive.rotational_period_ms=200 $flags | ||||
| echo $fluxengine write -c $format -i $srcfile -d $fluxfile --drive.rotational_period_ms=200 $flags | ||||
| $fluxengine write -c $format -i $srcfile -d $fluxfile --drive.rotational_period_ms=200 $flags | ||||
| echo $fluxengine read -c $format -s $fluxfile -o $destfile --drive.rotational_period_ms=200 $flags | ||||
| $fluxengine read -c $format -s $fluxfile -o $destfile --drive.rotational_period_ms=200 $flags | ||||
| if [ ! -s $destfile ]; then | ||||
| 	echo "Zero length output file!" >&2 | ||||
| 	exit 1 | ||||
|   | ||||
| @@ -28,7 +28,7 @@ static void addExample(std::vector<std::string>& examples, | ||||
|     else | ||||
|         return; | ||||
|  | ||||
|     r += fmt::format(" {}", name); | ||||
|     r += fmt::format(" -c {}", name); | ||||
|     if (format) | ||||
|         r += fmt::format(" --{}", format->name()); | ||||
|  | ||||
|   | ||||
| @@ -19,7 +19,7 @@ static std::string supportStatus(SupportStatus status) | ||||
|             return ""; | ||||
|     } | ||||
|  | ||||
| 	return ""; | ||||
|     return ""; | ||||
| } | ||||
|  | ||||
| int main(int argc, const char* argv[]) | ||||
| @@ -43,7 +43,9 @@ int main(int argc, const char* argv[]) | ||||
|             { | ||||
|                 const auto* descriptor = | ||||
|                     FilesystemProto::FilesystemType_descriptor(); | ||||
|                 auto name = descriptor->FindValueByNumber(fs.type())->name(); | ||||
|                 auto name = | ||||
|                     (std::string)descriptor->FindValueByNumber(fs.type()) | ||||
|                         ->name(); | ||||
|  | ||||
|                 filesystems.insert(name); | ||||
|             } | ||||
|   | ||||
| @@ -19,11 +19,9 @@ cxxprogram( | ||||
|         "./fe-getfileinfo.cc", | ||||
|         "./fe-inspect.cc", | ||||
|         "./fe-ls.cc", | ||||
|         "./fe-merge.cc", | ||||
|         "./fe-mkdir.cc", | ||||
|         "./fe-mv.cc", | ||||
|         "./fe-putfile.cc", | ||||
|         "./fe-rawread.cc", | ||||
|         "./fe-rawwrite.cc", | ||||
|         "./fe-read.cc", | ||||
|         "./fe-rm.cc", | ||||
|   | ||||
| @@ -22,9 +22,7 @@ static StringFlag destFlux({"--dest", "-d"}, | ||||
|         globalConfig().setFluxSink(value); | ||||
|     }); | ||||
|  | ||||
| static IntFlag destTrack({"--cylinder", "-c"}, "track to write to", 0); | ||||
|  | ||||
| static IntFlag destHead({"--head", "-h"}, "head to write to", 0); | ||||
| static StringFlag destTracks({"--tracks", "-t"}, "tracks to write to", "c0h0"); | ||||
|  | ||||
| static DoubleFlag minInterval( | ||||
|     {"--min-interval-us"}, "Minimum pulse interval", 2.0); | ||||
| @@ -251,11 +249,14 @@ int mainAnalyseDriveResponse(int argc, const char* argv[]) | ||||
|  | ||||
|     if (globalConfig()->flux_sink().type() != FLUXTYPE_DRIVE) | ||||
|         error("this only makes sense with a real disk drive"); | ||||
|     auto tracks = parseCylinderHeadsString(destTracks); | ||||
|     if (tracks.size() != 1) | ||||
|         error("you must specify exactly one track"); | ||||
|  | ||||
|     usbSetDrive(globalConfig()->drive().drive(), | ||||
|         globalConfig()->drive().high_density(), | ||||
|         globalConfig()->drive().index_mode()); | ||||
|     usbSeek(destTrack); | ||||
|     usbSeek(tracks[0].cylinder); | ||||
|  | ||||
|     std::cout << "Measuring rotational speed...\n"; | ||||
|     nanoseconds_t period = usbGetRotationalPeriod(0); | ||||
| @@ -291,12 +292,12 @@ int mainAnalyseDriveResponse(int argc, const char* argv[]) | ||||
|                 outFluxmap.appendPulse(); | ||||
|             } | ||||
|  | ||||
|             usbWrite(destHead, outFluxmap.rawBytes(), 0); | ||||
|             usbWrite(tracks[0].head, outFluxmap.rawBytes(), 0); | ||||
|  | ||||
|             /* Read the test pattern in again. */ | ||||
|  | ||||
|             Fluxmap inFluxmap; | ||||
|             inFluxmap.appendBytes(usbRead(destHead, true, period, 0)); | ||||
|             inFluxmap.appendBytes(usbRead(tracks[0].head, true, period, 0)); | ||||
|  | ||||
|             /* Compute histogram. */ | ||||
|  | ||||
|   | ||||
| @@ -21,9 +21,7 @@ static StringFlag sourceFlux({"--source", "-s"}, | ||||
|         globalConfig().setFluxSource(value); | ||||
|     }); | ||||
|  | ||||
| static IntFlag trackFlag({"--cylinder", "-c"}, "Track to read.", 0); | ||||
|  | ||||
| static IntFlag headFlag({"--head", "-h"}, "Head to read.", 0); | ||||
| static StringFlag destTracks({"--tracks", "-t"}, "tracks to write to", "c0h0"); | ||||
|  | ||||
| static SettableFlag dumpFluxFlag( | ||||
|     {"--dump-flux", "-F"}, "Dump raw magnetic disk flux."); | ||||
| @@ -135,7 +133,10 @@ int mainInspect(int argc, const char* argv[]) | ||||
|     flags.parseFlagsWithConfigFiles(argc, argv, {}); | ||||
|  | ||||
|     auto fluxSource = FluxSource::create(globalConfig()); | ||||
|     const auto fluxmap = fluxSource->readFlux(trackFlag, headFlag)->next(); | ||||
|     auto tracks = parseCylinderHeadsString(destTracks); | ||||
|     if (tracks.size() != 1) | ||||
|         error("you must specify exactly one track"); | ||||
|     const auto fluxmap = fluxSource->readFlux(tracks[0])->next(); | ||||
|  | ||||
|     std::cout << fmt::format("0x{:x} bytes of data in {:.3f}ms\n", | ||||
|         fluxmap->bytes(), | ||||
|   | ||||
| @@ -1,64 +0,0 @@ | ||||
| #include "lib/core/globals.h" | ||||
| #include "lib/config/flags.h" | ||||
| #include "lib/data/fluxmap.h" | ||||
| #include "lib/data/sector.h" | ||||
| #include "lib/config/proto.h" | ||||
| #include "lib/data/flux.h" | ||||
| #include "lib/external/fl2.h" | ||||
| #include "lib/external/fl2.pb.h" | ||||
| #include "src/fluxengine.h" | ||||
| #include <fstream> | ||||
|  | ||||
| static FlagGroup flags; | ||||
|  | ||||
| static std::vector<std::string> inputFluxFiles; | ||||
|  | ||||
| static StringFlag sourceFlux({"-s", "--source"}, | ||||
|     "flux file to read from (repeatable)", | ||||
|     "", | ||||
|     [](const auto& value) | ||||
|     { | ||||
|         inputFluxFiles.push_back(value); | ||||
|     }); | ||||
|  | ||||
| static StringFlag destFlux( | ||||
|     {"-d", "--dest"}, "destination flux file to write to", ""); | ||||
|  | ||||
| int mainMerge(int argc, const char* argv[]) | ||||
| { | ||||
|     flags.parseFlags(argc, argv); | ||||
|  | ||||
|     if (inputFluxFiles.empty()) | ||||
|         error("you must specify at least one input flux file (with -s)"); | ||||
|     if (destFlux.get() == "") | ||||
|         error("you must specify an output flux file (with -d)"); | ||||
|  | ||||
|     std::map<std::pair<int, int>, TrackFluxProto> data; | ||||
|     for (const auto& s : inputFluxFiles) | ||||
|     { | ||||
|         fmt::print("Reading {}...\n", s); | ||||
|         FluxFileProto f = loadFl2File(s); | ||||
|  | ||||
|         for (auto& trackflux : f.track()) | ||||
|         { | ||||
|             auto key = std::make_pair(trackflux.track(), trackflux.head()); | ||||
|             auto i = data.find(key); | ||||
|             if (i == data.end()) | ||||
|                 data[key] = trackflux; | ||||
|             else | ||||
|             { | ||||
|                 for (auto flux : trackflux.flux()) | ||||
|                     i->second.add_flux(flux); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     FluxFileProto proto; | ||||
|     for (auto& i : data) | ||||
|         *proto.add_track() = i.second; | ||||
|  | ||||
|     fmt::print("Writing {}...\n", destFlux.get()); | ||||
|     saveFl2File(destFlux.get(), proto); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
| @@ -1,52 +0,0 @@ | ||||
| #include "lib/core/globals.h" | ||||
| #include "lib/config/config.h" | ||||
| #include "lib/config/flags.h" | ||||
| #include "lib/algorithms/readerwriter.h" | ||||
| #include "lib/data/fluxmap.h" | ||||
| #include "lib/decoders/decoders.h" | ||||
| #include "lib/data/sector.h" | ||||
| #include "lib/config/proto.h" | ||||
| #include "lib/fluxsink/fluxsink.h" | ||||
| #include "lib/fluxsource/fluxsource.h" | ||||
| #include "lib/imagewriter/imagewriter.h" | ||||
| #include "fluxengine.h" | ||||
| #include <google/protobuf/text_format.h> | ||||
| #include <fstream> | ||||
|  | ||||
| static FlagGroup flags; | ||||
|  | ||||
| static StringFlag sourceFlux({"-s", "--source"}, | ||||
|     "flux file to read from", | ||||
|     "", | ||||
|     [](const auto& value) | ||||
|     { | ||||
|         globalConfig().setFluxSource(value); | ||||
|     }); | ||||
|  | ||||
| static StringFlag destFlux({"-d", "--dest"}, | ||||
|     "destination flux file to write to", | ||||
|     "", | ||||
|     [](const auto& value) | ||||
|     { | ||||
|         globalConfig().setFluxSink(value); | ||||
|     }); | ||||
|  | ||||
| int mainRawRead(int argc, const char* argv[]) | ||||
| { | ||||
|     globalConfig().overrides()->set_tracks("0-79"); | ||||
|  | ||||
|     if (argc == 1) | ||||
|         showProfiles("rawread", formats); | ||||
|     globalConfig().overrides()->mutable_flux_source()->set_type(FLUXTYPE_DRIVE); | ||||
|     flags.parseFlagsWithConfigFiles(argc, argv, formats); | ||||
|  | ||||
|     if (globalConfig()->flux_sink().type() == FLUXTYPE_DRIVE) | ||||
|         error("you can't use rawread to write to hardware"); | ||||
|  | ||||
|     auto fluxSource = FluxSource::create(globalConfig()); | ||||
|     auto fluxSink = FluxSink::create(globalConfig()); | ||||
|  | ||||
|     rawReadDiskCommand(*fluxSource, *fluxSink); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
| @@ -16,7 +16,7 @@ static StringFlag sourceFlux({"-s", "--source"}, | ||||
|         globalConfig().setFluxSource(value); | ||||
|     }); | ||||
|  | ||||
| static IntFlag track({"--cylinder", "-c"}, "track to seek to", 0); | ||||
| static IntFlag track({"--cylinder", "-t"}, "track to seek to", 0); | ||||
|  | ||||
| extern const std::map<std::string, std::string> readables; | ||||
|  | ||||
|   | ||||
| @@ -16,11 +16,9 @@ extern command_cb mainGetFile; | ||||
| extern command_cb mainGetFileInfo; | ||||
| extern command_cb mainInspect; | ||||
| extern command_cb mainLs; | ||||
| extern command_cb mainMerge; | ||||
| extern command_cb mainMkDir; | ||||
| extern command_cb mainMv; | ||||
| extern command_cb mainPutFile; | ||||
| extern command_cb mainRawRead; | ||||
| extern command_cb mainRawWrite; | ||||
| extern command_cb mainRead; | ||||
| extern command_cb mainRm; | ||||
| @@ -51,10 +49,8 @@ static std::vector<Command> commands = | ||||
|     { "write",             mainWrite,             "Writes a sector image to a disk.", }, | ||||
| 	{ "fluxfile",          mainFluxfile,          "Flux file manipulation operations.", }, | ||||
| 	{ "format",            mainFormat,            "Format a disk and make a file system on it.", }, | ||||
| 	{ "rawread",           mainRawRead,           "Reads raw flux from a disk. Warning: you can't use this to copy disks.", }, | ||||
|     { "rawwrite",          mainRawWrite,          "Writes a flux file to a disk. Warning: you can't use this to copy disks.", }, | ||||
|     { "convert",           mainConvert,           "Converts a flux file from one format to another.", }, | ||||
| 	{ "merge",             mainMerge,             "Merge together multiple flux files.", }, | ||||
| 	{ "getdiskinfo",       mainGetDiskInfo,       "Read volume metadata off a disk (or image).", }, | ||||
| 	{ "ls",                mainLs,                "Show files on disk (or image).", }, | ||||
| 	{ "mv",                mainMv,                "Rename a file on a disk (or image).", }, | ||||
|   | ||||
| @@ -1,22 +0,0 @@ | ||||
| comment: 'Adjust configuration for a 40-track drive' | ||||
| is_extension: true | ||||
|  | ||||
| documentation: | ||||
| <<< | ||||
| This is an extension profile; adding this to the command line will configure | ||||
| FluxEngine to read from 40-track, 48tpi 5.25" drives. You have to tell it because there is | ||||
| no way to detect this automatically. | ||||
|  | ||||
| For example: | ||||
|  | ||||
| ``` | ||||
| fluxengine read ibm --180 40track_drive | ||||
| ``` | ||||
| >>> | ||||
|  | ||||
| drive { | ||||
|     tracks: "c0-40h0-1" | ||||
|     drive_type: DRIVETYPE_40TRACK | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										77
									
								
								src/formats/_global_options.textpb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/formats/_global_options.textpb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| comment: 'Options which can be applied everywhere.' | ||||
| is_extension: true | ||||
|  | ||||
| option_group { | ||||
| 	comment: "Drive type" | ||||
|     name: "drivetype" | ||||
|  | ||||
| 	option { | ||||
| 		name: "80" | ||||
| 		comment: '80 track drive' | ||||
|         set_by_default: true | ||||
|  | ||||
| 		config { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	option { | ||||
| 		name: "40" | ||||
| 		comment: '40 track drive' | ||||
|  | ||||
| 		config { | ||||
|             drive { | ||||
|                 tracks: "c0-40h0-1" | ||||
|                 drive_type: DRIVETYPE_40TRACK | ||||
|             } | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	option { | ||||
| 		name: "160" | ||||
| 		comment: '160 track Apple II drive' | ||||
|  | ||||
| 		config { | ||||
|             drive { | ||||
|                 tracks: "c0-159h0" | ||||
|                 drive_type: DRIVETYPE_APPLE2 | ||||
|             } | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| option_group { | ||||
|     comment: 'Bus interface' | ||||
|     name: "bus" | ||||
|  | ||||
| 	option { | ||||
| 		name: "pc" | ||||
| 		comment: 'PC drive interface' | ||||
|         set_by_default: true | ||||
|     } | ||||
|  | ||||
| 	option { | ||||
| 		name: "shugart" | ||||
| 		comment: 'Shugart bus interface (only on Greaseweazle)' | ||||
|  | ||||
| 		config { | ||||
|             usb { | ||||
|                 greaseweazle { | ||||
|                     bus_type: SHUGART | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	option { | ||||
| 		name: "appleii" | ||||
| 		comment: 'Apple II bus interface (only on Greaseweazle)' | ||||
|  | ||||
| 		config { | ||||
|             usb { | ||||
|                 greaseweazle { | ||||
|                     bus_type: APPLE2 | ||||
|                 } | ||||
|             } | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,29 +0,0 @@ | ||||
| comment: 'Adjust configuration for a 40-track Apple II drive' | ||||
| is_extension: true | ||||
|  | ||||
| documentation: | ||||
| <<< | ||||
| This is an extension profile; adding this to the command line will configure | ||||
| FluxEngine to adjust the pinout and track spacing to work with an Apple II | ||||
| drive.  This only works on Greaseweazle hardware and requires a custom | ||||
| connector. | ||||
|  | ||||
| For example: | ||||
|  | ||||
| ``` | ||||
| fluxengine read apple2 --160 apple2_drive | ||||
| ``` | ||||
| >>> | ||||
|  | ||||
| usb { | ||||
|     greaseweazle { | ||||
|         bus_type: APPLE2 | ||||
|     } | ||||
| } | ||||
|  | ||||
| drive { | ||||
|     tracks: "c0-159h0" | ||||
|     drive_type: DRIVETYPE_APPLE2 | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -3,14 +3,13 @@ from build.c import cxxlibrary | ||||
| from scripts.build import protoencode | ||||
|  | ||||
| formats = [ | ||||
|     "40track_drive", | ||||
|     "_global_options", | ||||
|     "acornadfs", | ||||
|     "acorndfs", | ||||
|     "aeslanier", | ||||
|     "agat", | ||||
|     "amiga", | ||||
|     "ampro", | ||||
|     "apple2_drive", | ||||
|     "apple2", | ||||
|     "atarist", | ||||
|     "bk", | ||||
| @@ -33,7 +32,6 @@ formats = [ | ||||
|     "psos", | ||||
|     "rolandd20", | ||||
|     "rx50", | ||||
|     "shugart_drive", | ||||
|     "smaky6", | ||||
|     "tartu", | ||||
|     "ti99", | ||||
|   | ||||
| @@ -1,22 +0,0 @@ | ||||
| comment: 'Adjust configuration for a Shugart drive' | ||||
| is_extension: true | ||||
|  | ||||
| documentation: | ||||
| <<< | ||||
| This is an extension profile; adding this to the command line will configure | ||||
| FluxEngine to adjust the pinout to work with a Shugart drive. This only works | ||||
| on Greaseweazle hardware. | ||||
|  | ||||
| For example: | ||||
|  | ||||
| ``` | ||||
| fluxengine read ibm --720 shugart_drive | ||||
| ``` | ||||
| >>> | ||||
|  | ||||
| usb { | ||||
|     greaseweazle { | ||||
|         bus_type: SHUGART | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -1,19 +1,25 @@ | ||||
| from build.ab import emit, simplerule | ||||
| from build.ab import simplerule, G | ||||
| from build.c import cxxprogram | ||||
| from build.utils import shell | ||||
| from glob import glob | ||||
| import config | ||||
| import shutil | ||||
| import subprocess | ||||
|  | ||||
| emit( | ||||
|     """ | ||||
| WX_CONFIG ?= wx-config | ||||
| ifneq ($(strip $(shell command -v $(WX_CONFIG) >/dev/null 2>&1; echo $$?)),0) | ||||
| WX_CFLAGS = $(error Required binary 'wx-config' not found.) | ||||
| WX_LDFLAGS = $(error Required binary 'wx-config' not found.) | ||||
| else | ||||
| WX_CFLAGS := $(shell $(WX_CONFIG) --cxxflags base adv aui richtext core) | ||||
| WX_LDFLAGS := $(shell $(WX_CONFIG) --libs base adv aui richtext core) | ||||
| endif | ||||
| """ | ||||
| G.setdefault("WX_CONFIG", "wx-config") | ||||
| assert shutil.which(G.WX_CONFIG), "Required binary 'wx-config' not found" | ||||
|  | ||||
| G.setdefault( | ||||
|     "WX_CFLAGS", | ||||
|     shell( | ||||
|         [G.WX_CONFIG, "--cxxflags", "base", "adv", "aui", "richtext", "core"] | ||||
|     ), | ||||
| ) | ||||
| G.setdefault( | ||||
|     "WX_LDFLAGS", | ||||
|     shell( | ||||
|         [G.WX_CONFIG, "--libs", "base", "adv", "aui", "richtext", "core"] | ||||
|     ) | ||||
| ) | ||||
|  | ||||
| extrasrcs = ["./layout.cpp"] | ||||
| @@ -57,13 +63,13 @@ cxxprogram( | ||||
|  | ||||
| if config.osx: | ||||
|     simplerule( | ||||
|         name="fluxengine_pkg", | ||||
|         name="fluxengine_app_zip", | ||||
|         ins=[ | ||||
|             ".+gui", | ||||
|             "extras+fluxengine_icns", | ||||
|             "extras+fluxengine_template", | ||||
|         ], | ||||
|         outs=["=FluxEngine.pkg"], | ||||
|         outs=["=FluxEngine.app.zip"], | ||||
|         commands=[ | ||||
|             "rm -rf $[outs[0]]", | ||||
|             "unzip -q $[ins[2]]",  # creates FluxEngine.app | ||||
| @@ -79,7 +85,20 @@ if config.osx: | ||||
|             "cp $$(brew --prefix abseil)/LICENSE FluxEngine.app/Contents/libs/abseil.txt", | ||||
|             "cp $$(brew --prefix libtiff)/LICENSE.md FluxEngine.app/Contents/libs/libtiff.txt", | ||||
|             "cp $$(brew --prefix zstd)/LICENSE FluxEngine.app/Contents/libs/zstd.txt", | ||||
|             "pkgbuild --quiet --install-location /Applications --component FluxEngine.app $[outs[0]]", | ||||
|             "zip -rq $[outs[0]] FluxEngine.app", | ||||
|         ], | ||||
|         label="MKAPP", | ||||
|     ) | ||||
|  | ||||
|     simplerule( | ||||
|         name="fluxengine_pkg", | ||||
|         ins=[ | ||||
|             ".+fluxengine_app_zip", | ||||
|         ], | ||||
|         outs=["=FluxEngine.pkg"], | ||||
|         commands=[ | ||||
|             "unzip -q $[ins[0]]", | ||||
|             "pkgbuild --quiet --install-location /Applications --component FluxEngine.app $[outs[0]]", | ||||
|         ], | ||||
|         label="MKPKG", | ||||
|     ) | ||||
|   | ||||
							
								
								
									
										31
									
								
								src/gui2/build.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/gui2/build.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| from build.ab import emit, simplerule | ||||
| from build.c import cxxprogram | ||||
| from glob import glob | ||||
| import config | ||||
|  | ||||
| cxxprogram( | ||||
|     name="gui2", | ||||
|     srcs=glob("src/gui2/*.cc") + glob("src/gui2/*.h"), | ||||
|     cflags=[], | ||||
|     ldflags=[], | ||||
|     deps=[ | ||||
|         "lib/external+fl2_proto_lib", | ||||
|         "+protocol", | ||||
|         "dep/adflib", | ||||
|         "dep/fatfs", | ||||
|         "dep/hfsutils", | ||||
|         "dep/libusbp", | ||||
|         "dep/imgui", | ||||
|         "extras+icons", | ||||
|         "lib/core", | ||||
|         "lib/data", | ||||
|         "lib/vfs", | ||||
|         "lib/config", | ||||
|         "arch", | ||||
|         "src/formats", | ||||
|         "src/gui/drivetypes", | ||||
|         "+z_lib", | ||||
|         "+fmt_lib", | ||||
|         "+protobuf_lib", | ||||
|     ], | ||||
| ) | ||||
							
								
								
									
										28
									
								
								src/gui2/globals.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/gui2/globals.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "lib/core/globals.h" | ||||
| #include <semaphore> | ||||
|  | ||||
| typedef std::function<void(void)> CB; | ||||
|  | ||||
| extern void runOnAppThread(CB cb); | ||||
| extern void runOnUiThread(CB cb); | ||||
|  | ||||
| template <typename T> | ||||
| T runOnUiThread(std::function<void(T)> cb) | ||||
| { | ||||
|     T result; | ||||
|     std::binary_semaphore sem; | ||||
|     runOnUiThread( | ||||
|         [&]() | ||||
|         { | ||||
|             result = cb(); | ||||
|             sem.release(); | ||||
|         }); | ||||
|     sem.acquire(); | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| extern void guiInit(); | ||||
| extern void guiLoop(CB each); | ||||
| extern void guiShutdown(); | ||||
							
								
								
									
										178
									
								
								src/gui2/gui.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								src/gui2/gui.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| #include "globals.h" | ||||
| #include "imgui.h" | ||||
| #include "imgui_impl_glfw.h" | ||||
| #include "imgui_impl_opengl3.h" | ||||
| #define GL_SILENCE_DEPRECATION | ||||
| #if defined(IMGUI_IMPL_OPENGL_ES2) | ||||
| #include <GLES2/gl2.h> | ||||
| #endif | ||||
| #include <GLFW/glfw3.h> | ||||
|  | ||||
| static GLFWwindow* window; | ||||
|  | ||||
| static void glfw_error_callback(int error, const char* description) | ||||
| { | ||||
|     fprintf(stderr, "GLFW Error %d: %s\n", error, description); | ||||
| } | ||||
|  | ||||
| void guiInit() | ||||
| { | ||||
|     glfwSetErrorCallback(glfw_error_callback); | ||||
|     if (!glfwInit()) | ||||
|         error("failed to initialise GLFW"); | ||||
|  | ||||
|     // Decide GL+GLSL versions | ||||
| #if defined(IMGUI_IMPL_OPENGL_ES2) | ||||
|     // GL ES 2.0 + GLSL 100 (WebGL 1.0) | ||||
|     const char* glsl_version = "#version 100"; | ||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); | ||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); | ||||
|     glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); | ||||
| #elif defined(IMGUI_IMPL_OPENGL_ES3) | ||||
|     // GL ES 3.0 + GLSL 300 es (WebGL 2.0) | ||||
|     const char* glsl_version = "#version 300 es"; | ||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | ||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); | ||||
|     glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); | ||||
| #elif defined(__APPLE__) | ||||
|     // GL 3.2 + GLSL 150 | ||||
|     const char* glsl_version = "#version 150"; | ||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | ||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); | ||||
|     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 3.2+ only | ||||
|     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);            // Required on Mac | ||||
| #else | ||||
|     // GL 3.0 + GLSL 130 | ||||
|     const char* glsl_version = "#version 130"; | ||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | ||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); | ||||
|     //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 3.2+ only | ||||
|     //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);            // 3.0+ only | ||||
| #endif | ||||
|  | ||||
|     // Create window with graphics context | ||||
|     float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only | ||||
|     window = glfwCreateWindow((int)(1280 * main_scale), (int)(800 * main_scale), "FluxEngine", nullptr, nullptr); | ||||
|     if (window == nullptr) | ||||
|         error("GLFW window creation failure"); | ||||
|     glfwMakeContextCurrent(window); | ||||
|     glfwSwapInterval(1); // Enable vsync | ||||
|  | ||||
|     // Setup Dear ImGui context | ||||
|     IMGUI_CHECKVERSION(); | ||||
|     ImGui::CreateContext(); | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|     io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls | ||||
|     io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; | ||||
|  | ||||
|     // Setup Dear ImGui style | ||||
|     ImGui::StyleColorsDark(); | ||||
|     //ImGui::StyleColorsLight(); | ||||
|  | ||||
|     // Setup scaling | ||||
|     ImGuiStyle& style = ImGui::GetStyle(); | ||||
|     style.ScaleAllSizes(main_scale);        // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again) | ||||
|     style.FontScaleDpi = main_scale;        // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose) | ||||
|  | ||||
|     // Setup Platform/Renderer backends | ||||
|     ImGui_ImplGlfw_InitForOpenGL(window, true); | ||||
|     ImGui_ImplOpenGL3_Init(glsl_version); | ||||
|  | ||||
|     // Load Fonts | ||||
|     // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. | ||||
|     // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. | ||||
|     // - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). | ||||
|     // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering. | ||||
|     // - Read 'docs/FONTS.md' for more instructions and details. If you like the default font but want it to scale better, consider using the 'ProggyVector' from the same author! | ||||
|     // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! | ||||
|     // - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details. | ||||
|     //style.FontSizeBase = 20.0f; | ||||
|     //io.Fonts->AddFontDefault(); | ||||
|     //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf"); | ||||
|     //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf"); | ||||
|     //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf"); | ||||
|     //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf"); | ||||
|     //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf"); | ||||
|     //IM_ASSERT(font != nullptr); | ||||
| } | ||||
|  | ||||
| void guiLoop(CB each) | ||||
| { | ||||
|     ImGuiIO& io = ImGui::GetIO(); | ||||
|  | ||||
|     // Our state | ||||
|     bool show_another_window = false; | ||||
|     ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); | ||||
|  | ||||
|     while (!glfwWindowShouldClose(window)) | ||||
|     { | ||||
|         glfwPollEvents(); | ||||
|         if (glfwGetWindowAttrib(window, GLFW_ICONIFIED) != 0) | ||||
|         { | ||||
|             ImGui_ImplGlfw_Sleep(10); | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         // Start the Dear ImGui frame | ||||
|         ImGui_ImplOpenGL3_NewFrame(); | ||||
|         ImGui_ImplGlfw_NewFrame(); | ||||
|          | ||||
|         ImGui::NewFrame(); | ||||
|         ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport()); | ||||
|  | ||||
|         each(); | ||||
|  | ||||
|         { | ||||
|             static float f = 0.0f; | ||||
|             static int counter = 0; | ||||
|  | ||||
|             ImGui::Begin("Hello, world!");                          // Create a window called "Hello, world!" and append into it. | ||||
|  | ||||
|             ImGui::Text("This is some useful text.");               // Display some text (you can use a format strings too) | ||||
|             ImGui::Checkbox("Another Window", &show_another_window); | ||||
|  | ||||
|             ImGui::SliderFloat("float", &f, 0.0f, 1.0f);            // Edit 1 float using a slider from 0.0f to 1.0f | ||||
|             ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color | ||||
|  | ||||
|             if (ImGui::Button("Button"))                            // Buttons return true when clicked (most widgets return true when edited/activated) | ||||
|                 counter++; | ||||
|             ImGui::SameLine(); | ||||
|             ImGui::Text("counter = %d", counter); | ||||
|  | ||||
|             ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); | ||||
|             ImGui::End(); | ||||
|         } | ||||
|  | ||||
|         // 3. Show another simple window. | ||||
|         if (show_another_window) | ||||
|         { | ||||
|             ImGui::Begin("Another Window", &show_another_window);   // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) | ||||
|             ImGui::Text("Hello from another window!"); | ||||
|             if (ImGui::Button("Close Me")) | ||||
|                 show_another_window = false; | ||||
|             ImGui::End(); | ||||
|         } | ||||
|  | ||||
|         // Rendering | ||||
|         ImGui::Render(); | ||||
|         int display_w, display_h; | ||||
|         glfwGetFramebufferSize(window, &display_w, &display_h); | ||||
|         glViewport(0, 0, display_w, display_h); | ||||
|         glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); | ||||
|         glClear(GL_COLOR_BUFFER_BIT); | ||||
|         ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); | ||||
|  | ||||
|         glfwSwapBuffers(window); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void guiShutdown() | ||||
| { | ||||
|     ImGui_ImplOpenGL3_Shutdown(); | ||||
|     ImGui_ImplGlfw_Shutdown(); | ||||
|     ImGui::DestroyContext(); | ||||
|  | ||||
|     glfwDestroyWindow(window); | ||||
|     glfwTerminate(); | ||||
| } | ||||
|  | ||||
							
								
								
									
										75
									
								
								src/gui2/main.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/gui2/main.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| #include "globals.h" | ||||
| #include <mutex> | ||||
| #include <thread> | ||||
|  | ||||
| static std::mutex queueMutex; | ||||
| static std::counting_semaphore<INT_MAX> appThreadSize(0); | ||||
| static std::deque<CB> appThreadQueue; | ||||
| static std::deque<CB> uiThreadQueue; | ||||
| static bool appThreadShouldExit = false; /* app thread only */ | ||||
|  | ||||
| void runOnAppThread(CB cb) | ||||
| { | ||||
|     std::lock_guard<std::mutex> guard(queueMutex); | ||||
|     appThreadQueue.push_back(cb); | ||||
|     appThreadSize.release(); | ||||
| } | ||||
|  | ||||
| void runOnUiThread(CB cb) | ||||
| { | ||||
|     std::lock_guard<std::mutex> guard(queueMutex); | ||||
|     uiThreadQueue.push_back(cb); | ||||
| } | ||||
|  | ||||
| static CB atomicallyPopFromQueue(std::deque<CB>& queue) | ||||
| { | ||||
|     CB cb; | ||||
|     std::lock_guard<std::mutex> guard(queueMutex); | ||||
|     if (!queue.empty()) | ||||
|     { | ||||
|         cb = queue.front(); | ||||
|         queue.pop_front(); | ||||
|     } | ||||
|     return cb; | ||||
| } | ||||
|  | ||||
| static void appThreadMain(void) | ||||
| { | ||||
|     while (!appThreadShouldExit) | ||||
|     { | ||||
|         appThreadSize.acquire(); | ||||
|  | ||||
|         CB cb = atomicallyPopFromQueue(appThreadQueue); | ||||
|         cb(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| int main(int argc, const char* argv[]) | ||||
| { | ||||
|     guiInit(); | ||||
|  | ||||
|     std::thread appThread(appThreadMain); | ||||
|  | ||||
|     guiLoop( | ||||
|         []() | ||||
|         { | ||||
|             for (;;) | ||||
|             { | ||||
|                 CB cb = atomicallyPopFromQueue(uiThreadQueue); | ||||
|                 if (!cb) | ||||
|                     break; | ||||
|                 cb(); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|     runOnAppThread( | ||||
|         []() | ||||
|         { | ||||
|             appThreadShouldExit = true; | ||||
|         }); | ||||
|     appThread.join(); | ||||
|  | ||||
|     guiShutdown(); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										6
									
								
								src/gui2/view.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/gui2/view.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| #pragma once | ||||
|  | ||||
| class View | ||||
| { | ||||
| public: | ||||
|      | ||||
| @@ -55,14 +55,14 @@ static void test_option_validity() | ||||
|         } | ||||
| 	)M"); | ||||
|  | ||||
|     AssertThat( | ||||
|         globalConfig().isOptionValid(globalConfig().findOption("option1")), | ||||
|     AssertThat(globalConfig().isOptionValid( | ||||
|                    *globalConfig().findOption("option1").option), | ||||
|         Equals(true)); | ||||
|     AssertThat( | ||||
|         globalConfig().isOptionValid(globalConfig().findOption("option2")), | ||||
|     AssertThat(globalConfig().isOptionValid( | ||||
|                    *globalConfig().findOption("option2").option), | ||||
|         Equals(false)); | ||||
|     AssertThat( | ||||
|         globalConfig().isOptionValid(globalConfig().findOption("option3")), | ||||
|     AssertThat(globalConfig().isOptionValid( | ||||
|                    *globalConfig().findOption("option3").option), | ||||
|         Equals(true)); | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user