-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
here goes. releasing current wiz source on github. readme is rushed, …
…and documentation is largely unfinished, but hopefully still something to go by.
- Loading branch information
1 parent
1ebafd3
commit 551bdcd
Showing
262 changed files
with
41,492 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
bin/ | ||
wiz.js | ||
*.d | ||
*.gb | ||
*.gbc | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
ifdef CC | ||
ifdef CXX | ||
HAS_PREDEFINED_CC := 1 | ||
endif | ||
endif | ||
|
||
ifndef PREFIX | ||
PREFIX := /usr/local | ||
endif | ||
|
||
ifeq ($(OS),Windows_NT) | ||
EXE := .exe | ||
LOCATE_COMMAND := where /q | ||
else | ||
EXE := | ||
LOCATE_COMMAND := command -v | ||
endif | ||
|
||
HAS_CC := $(shell $(LOCATE_COMMAND) cc) | ||
HAS_GCC := $(shell $(LOCATE_COMMAND) gcc) | ||
HAS_CLANG := $(shell $(LOCATE_COMMAND) clang) | ||
|
||
ifndef HAS_PREDEFINED_CC | ||
ifdef HAS_CC | ||
CC := cc | ||
CXX := c++ | ||
else ifdef HAS_GCC | ||
CC := gcc | ||
CXX := g++ | ||
else ifdef HAS_CLANG | ||
CC := clang | ||
CXX := clang++ | ||
endif | ||
endif | ||
|
||
WIZ_SRC := src | ||
WIZ_OUT_DIR := bin | ||
|
||
WIZ_H_MATCH := $(wildcard $(WIZ_SRC)/wiz/*.h $(WIZ_SRC)/wiz/ast/*.h $(WIZ_SRC)/wiz/compiler/*.h $(WIZ_SRC)/wiz/parser/*.h $(WIZ_SRC)/wiz/utility/*.h $(WIZ_SRC)/wiz/definition/*.h $(WIZ_SRC)/wiz/platform/*.h $(WIZ_SRC)/wiz/format/*.h) | ||
WIZ_CPP_MATCH := $(wildcard $(WIZ_SRC)/wiz/*.cpp $(WIZ_SRC)/wiz/ast/*.cpp $(WIZ_SRC)/wiz/compiler/*.cpp $(WIZ_SRC)/wiz/parser/*.cpp $(WIZ_SRC)/wiz/utility/*.cpp $(WIZ_SRC)/wiz/definition/*.cpp $(WIZ_SRC)/wiz/platform/*.cpp $(WIZ_SRC)/wiz/format/*.cpp) | ||
WIZ_H_EXCLUDE := | ||
WIZ_CPP_EXCLUDE := | ||
|
||
WIZ_H := $(filter-out $(WIZ_H_EXCLUDE), $(WIZ_H_MATCH)) | ||
WIZ_CPP := $(filter-out $(WIZ_CPP_EXCLUDE), $(WIZ_CPP_MATCH)) | ||
WIZ_O := $(patsubst %.cpp, %.o, $(WIZ_CPP)) | ||
WIZ_DEPS := $(sort $(patsubst %.o, %.d, $(WIZ_O))) | ||
|
||
ifndef PLATFORM | ||
PLATFORM := native | ||
endif | ||
|
||
ifndef CFG | ||
CFG := release | ||
endif | ||
|
||
ifeq ($(PLATFORM),native) | ||
ifeq ($(CFG),release) | ||
CXX_FLAGS := -D_POSIX_SOURCE -O2 -std=c++17 -MMD -Wall -Werror -Wextra -Wold-style-cast -Wnon-virtual-dtor -fno-exceptions | ||
else ifeq ($(CFG),debug) | ||
CXX_FLAGS := -D_POSIX_SOURCE -DWIZ_DEBUG -g -std=c++17 -MMD -Wall -Werror -Wextra -Wold-style-cast -Wnon-virtual-dtor -fno-exceptions | ||
endif | ||
LXXFLAGS := -lm | ||
INCLUDES := -I$(WIZ_SRC) | ||
WIZ := wiz$(EXE) | ||
else ifeq ($(PLATFORM),emcc) | ||
WIZ_PRE_JS := $(WIZ_SRC)/wiz-emscripten/pre-js.js | ||
WIZ := wiz.js | ||
CC := emcc | ||
CXX := em++ | ||
CXX_FLAGS := -Oz -std=c++1z -MMD -Wall -Werror -Wextra -Wold-style-cast -Wnon-virtual-dtor -fno-exceptions | ||
LXXFLAGS := -lm --bind --memory-init-file 0 -s NO_FILESYSTEM=1 -s DISABLE_EXCEPTION_CATCHING=1 --pre-js $(WIZ_PRE_JS) | ||
INCLUDES := -I$(WIZ_SRC) | ||
else | ||
$(error Unknown PLATFORM value "$(PLATFORM)") | ||
endif | ||
|
||
.PHONY: clean all install | ||
|
||
all: $(WIZ_OUT_DIR)/$(WIZ) | ||
|
||
$(WIZ_OUT_DIR): | ||
mkdir $(WIZ_OUT_DIR) | ||
|
||
$(WIZ_O): %.o: %.cpp | ||
$(CXX) $(CXX_FLAGS) -c -o $@ $< $(INCLUDES) | ||
|
||
$(WIZ_OUT_DIR)/$(WIZ): $(WIZ_O) | ||
$(CXX) $(CXX_FLAGS) $^ $(LXXFLAGS) -o $@ | ||
|
||
clean: | ||
rm -f $(WIZ_OUT_DIR)/$(WIZ) $(WIZ_O) $(WIZ_DEPS) | ||
|
||
install: $(WIZ_OUT_DIR)/$(WIZ) | ||
install -d $(DESTDIR)$(PREFIX)/bin/ | ||
install -m 755 $(WIZ_OUT_DIR)/$(WIZ) $(DESTDIR)$(PREFIX)/bin/ | ||
|
||
-include $(WIZ_DEPS) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# Wiz C++ Coding Style Guide | ||
|
||
## Formatting | ||
|
||
- Four spaces for indentation, no tabs allowed. | ||
- Put the opening brace `{` on the same line as the associated control statement or declaration. | ||
- Put spaces between control structure keywords and their parenthesized expression. eg. `if (expr)` | ||
- Almost always prefer to use a brace-delimited block as the body of a control structure, rather than a single statement. | ||
- Spaces before and after binary operators, except for `.` or `->` or `::` | ||
- No space between an indexable term and the brackets `[` ... `]` for an indexing expression. | ||
- No space between a callable term and the parenthesis `(` ... `)` for a function call | ||
- No space between a unary operator and its term. | ||
- No superfluous padding spaces on the inside of parenthesized/bracketed expressions. | ||
- Add parentheses to expressions when the precedence is not immediately clear (bitwise operations, more complicated mixed-logical operations), but leave them off when it is clear (eg. comparisons, basic math) | ||
- For binary operator expressions that span multiple lines, put the operator on the next line. | ||
- Put consecutive closing parens for nested expressions together on the same line preferrably, and on the same line as the last expression in parentheses. | ||
- Constructors can be weird to indent, see existing examples of how constructors and their member initializer lists should be indented. | ||
- When in doubt, look at existing code for examples and try to match the formatting. | ||
|
||
## C++ Usage | ||
|
||
- C++ is not great, but C is even worse, in my opinion. I wanted a language that's easy enough to compile cross-platform (including to the Web), has mature compilers, and good static type safety and explicit memory management (no GC requirement). Rust is really nice but not quite there. D was a fun language to write earlier versions of Wiz, but C++14 does most of what I wanted from D but without requiring GC, and with better portability. Haskell is a great language that I love, but it fails in a lot of ways for writing software tools, so I stuck with C++. | ||
- Don't use `#pragma once` directives. Use the annoying long-winded way with `#ifndef MODULE_H` ... `#define MODULE_H` ... `#endif` include guards instead. | ||
- Don't use C-style casts. Always use `static_cast` or `reinterpret_cast` instead. | ||
- Don't cast away `const` with `const_cast` - rewrite the code to respect the `const` in place, or make the field mutable. | ||
- If a local variable has an initializer or easily deduced type, use `auto` | ||
- If a local variable is bound once and never changed after binding, use `const auto` | ||
- Prefer named locals over needing to comment complex expressions. | ||
- Range-based for is nice, use `auto`/`auto&` or `const auto`/`const auto&` for the iterator variable. | ||
- Prefer `const` versions of `auto` whenever possible. | ||
- If possible, prefer references `&` to pointers `*`, and make them `const` when possible. | ||
- Prefer `Optional<T>` over pointers or `bool` + out-params for nullable value types. | ||
- Prefer `Variant<T, T2, T3, ...>` over subclasses for simple structs that hold data but don't have behaviour. | ||
- If a function does not need to mutate a reference parameter, take it by `const` | ||
- Do not use raw `new` or `malloc` -- prefer `std::unique_ptr` to manage memory, and `std:move` to explicitly transfer ownership. | ||
- If needing a `std::unique_ptr` to an incomplete type, use `FwdUniquePtr`, and implement a `FwdDeleter` for the type in its .cpp file. | ||
- If passing a pointer to some data in a non-owning fashion, use a raw C-style pointer. | ||
- If a function does not need to mutate a pointer, take it by `const` | ||
- If a member function of a class does not modify `this`, it should be marked `const` | ||
- Don't use `std::shared_ptr` | ||
- Don't use `dynamic_cast` and `typeid` expressions or other RAII stuff. | ||
- Prefer `StringView` to `const char*` or `const std::string&` since it handles both. | ||
- Use `std::string` sparingly. Prefer to pass around `StringView` until you need to copy or mutate a string. | ||
- Use `StringPool` to keep a long-lived `StringView` of a character string. | ||
- If possible, pass dynamically-allocated data structures around by reference (const if possible) rather than copy. | ||
- Don't let the unspecified order of argument evaluation for function calls bite you by accidentally relying on specific order to side-effects in the call, eg. `std::move` | ||
- For C functions, use `<cstdio>`, `<cstring>`, etc instead of `<stdio.h>`, `<stddef.h>`, etc, and prefix C identifiers with `std::` unless they're macros. | ||
- Avoid using C functions when there is something better/safer in the C++ libraries. | ||
- Don't use file-scoped `static` functions, use unnamed namespaces instead. | ||
- The codebase targets C++14. C++17-specifics should currently be avoided except for working around valid C++14 code that got deprecated in C++17. | ||
- C++14 doesn't support nice `std::is_same_v<A, B>` etc and there's no support for `inline` variables until C++17, so use `std::is_same<A, B>::value` etc instead. | ||
- C++14 doesn't support `std::invoke_result_t`, but C++17 doesn't support `std::result_of_t`, so be prepared to work around that. | ||
- Avoid implementation inheritance. Pure-`virtual` interface classes are ok. | ||
- Use `override` whenever providing an implementation of a `virtual` method. | ||
- A `class` with only public members should be a `struct` | ||
- Avoid cluttering headers with `#include` directives that aren't needed so that compile-times stay fast(er). If possible, use forward-declared / incomplete types in the .h, and move the `#include` into .cpp. | ||
- Avoid `#define` macros except for very basic conditional compilation stuff, no code-insertion or constants. | ||
- Prefer `enum class` to `enum`. | ||
- Don't mixed signed and unsigned types without casting. | ||
- Avoid implicit casts (except to `bool` which are okay sometimes) | ||
|
||
## AST | ||
|
||
- The AST was designed to be immutable to simplify design and avoid programmer error, and uses unique pointers to ensure that memory ownership is clearly retained. All nodes should be declared `FwdUniquePtr<const T>`. To have a non-owning reference to a node, use a `const T*` variable to hold it, and use `get()` on a unique pointer. | ||
- There are `clone()` functions on the node types to provide an identical (recursive) copy when needed. It can be expensive depending on where it is done, so it's recommended to apply to the smallest section that needs copying. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
namespace vcs { | ||
namespace sync { | ||
var vsync @ 0x00 : u8; | ||
let VSYNC_START = 0x02; | ||
|
||
var vblank @ 0x01 : u8; | ||
let VBLANK_START = 0x02; | ||
let VBLANK_RESET_TRIGGER = 0x40; | ||
let VBLANK_RESET_POTS = 0x80; | ||
|
||
var wsync @ 0x02 : u8; | ||
var rsync @ 0x03 : u8; | ||
} | ||
|
||
namespace audio { | ||
var volumes @ 0x19 : [u8; 2]; | ||
var volume1 @ 0x19 : u8; | ||
var volume2 @ 0x1A : u8; | ||
|
||
var frequencies @ 0x17 : [u8; 2]; | ||
var frequency1 @ 0x17 : u8; | ||
var frequency2 @ 0x18 : u8; | ||
|
||
var tones @ 0x15 : [u8; 2]; | ||
var tone1 @ 0x15 : u8; | ||
var tone2 @ 0x16 : u8; | ||
} | ||
|
||
namespace io { | ||
var pots @ 0x3C : [u8; 4]; | ||
var pot1 @ 0x38 : u8; | ||
var pot2 @ 0x39 : u8; | ||
var pot3 @ 0x3A : u8; | ||
var pot4 @ 0x3B : u8; | ||
|
||
var triggers @ 0x3C : [u8; 2]; | ||
var trigger1 @ 0x3C : u8; | ||
var trigger2 @ 0x3D : u8; | ||
let TRIGGER_JOY_FIRE = 0x80; | ||
|
||
var port_a @ 0x280 : u8; | ||
var port_b @ 0x282 : u8; | ||
var ddr_a @ 0x281 : u8; | ||
var ddr_b @ 0x023 : u8; | ||
|
||
let PORT_A_JOY_UP = 0x10; | ||
let PORT_A_JOY_DOWN = 0x20; | ||
let PORT_A_JOY_LEFT = 0x40; | ||
let PORT_A_JOY_RIGHT = 0x80; | ||
let PORT_A_JOY2_UP = 0x01; | ||
let PORT_A_JOY2_DOWN = 0x02; | ||
let PORT_A_JOY2_LEFT = 0x04; | ||
let PORT_A_JOY2_RIGHT = 0x08; | ||
} | ||
|
||
namespace timer { | ||
var value @ 0x284 : u8; | ||
var stat @ 0x285 : u8; | ||
var set1 @ 0x294 : u8; | ||
var set8 @ 0x295 : u8; | ||
var set64 @ 0x296 : u8; | ||
var set1024 @ 0x297 : u8; | ||
} | ||
|
||
namespace control { | ||
var players @ 0x04 : [u8; 2]; | ||
var player1 @ 0x04 : u8; | ||
var player2 @ 0x05 : u8; | ||
|
||
let PLAYER_SINGLE = 0x00; | ||
let PLAYER_SINGLE_2X = 0x05; | ||
let PLAYER_SINGLE_4X = 0x07; | ||
let PLAYER_DOUBLE_CLOSE = 0x01; | ||
let PLAYER_DOUBLE_MEDIUM = 0x02; | ||
let PLAYER_DOUBLE_FAR = 0x04; | ||
let PLAYER_TRIPLE_CLOSE = 0x03; | ||
let PLAYER_TRIPLE_MEDIUM = 0x06; | ||
let MISSILE_1PX = 0x00; | ||
let MISSILE_2PX = 0x10; | ||
let MISSILE_4PX = 0x20; | ||
let MISSILE_8PX = 0x30; | ||
|
||
var playfield @ 0x0A : u8; | ||
|
||
let FIELD_REFLECT = 0x1; | ||
let FIELD_SCORE = 0x2; | ||
let FIELD_PRIORITY = 0x4; | ||
let BALL_1PX = 0x00; | ||
let BALL_2PX = 0x10; | ||
let BALL_4PX = 0x20; | ||
let BALL_8PX = 0x30; | ||
} | ||
|
||
namespace color { | ||
var players @ 0x06 : [u8; 2]; | ||
var player1 @ 0x06 : u8; | ||
var player2 @ 0x07 : u8; | ||
var fg @ 0x08 : u8; | ||
var bg @ 0x09 : u8; | ||
|
||
let LUMINOSITY_SHIFT = 1; | ||
let LUMINOSITY_MASK = 0x0E; | ||
|
||
let COLOR_SHIFT = 4; | ||
let COLOR_MASK = 0xF0; | ||
|
||
let SECAM_BLACK = 0x0; | ||
let SECAM_BLUE = 0x2; | ||
let SECAM_RED = 0x4; | ||
let SECAM_MAGENTA = 0x6; | ||
let SECAM_GREEN = 0x8; | ||
let SECAM_CYAN = 0xA; | ||
let SECAM_YELLOW = 0xC; | ||
let SECAM_WHITE = 0xE; | ||
|
||
let PAL_GREY = 0x0; | ||
let PAL_YELLOW = 0x2; | ||
let PAL_OLIVE = 0x3; | ||
let PAL_BROWN = 0x4; | ||
let PAL_GREEN = 0x5; | ||
let PAL_RED = 0x6; | ||
let PAL_CYAN = 0x7; | ||
let PAL_MAGENTA = 0x8; | ||
let PAL_LIGHT_BLUE = 0x9; | ||
let PAL_PURPLE = 0xA; | ||
let PAL_SKY_BLUE = 0xB; | ||
let PAL_INDIGO = 0xC; | ||
let PAL_BLUE = 0xD; | ||
|
||
let NTSC_WHITE = 0x0; | ||
let NTSC_YELLOW = 0x1; | ||
let NTSC_ORANGE = 0x2; | ||
let NTSC_RED_ORANGE = 0x3; | ||
let NTSC_RED = 0x4; | ||
let NTSC_MAGENTA = 0x5; | ||
let NTSC_PURPLE = 0x6; | ||
let NTSC_BLUE_PURPLE = 0x7; | ||
let NTSC_BLUE = 0x8; | ||
let NTSC_SKY_BLUE = 0x9; | ||
let NTSC_CYAN = 0xA; | ||
let NTSC_MINT = 0xB; | ||
let NTSC_GREEN = 0xC; | ||
let NTSC_GREEN_YELLOW = 0xD; | ||
let NTSC_OLIVE = 0xE; | ||
let NTSC_BROWN = 0xF; | ||
} | ||
|
||
namespace pattern { | ||
var players @ 0x1B : [u8; 2]; | ||
var player1 @ 0x1B : u8; | ||
var player2 @ 0x1C : u8; | ||
|
||
var missiles @ 0x1D : [u8; 2]; | ||
var missile1 @ 0x1D : u8; | ||
var missile2 @ 0x1E : u8; | ||
let MISSILE_FILL = 0x2; | ||
|
||
var ball @ 0x1F : u8; | ||
let BALL_FILL = 0x2; | ||
|
||
var playfields @ 0x0D : [u8; 3]; | ||
var playfield1 @ 0x0D : u8; | ||
var playfield2 @ 0x0E : u8; | ||
var playfield3 @ 0x0F : u8; | ||
} | ||
|
||
namespace hmove { | ||
var players @ 0x20 : [u8; 2]; | ||
var player1 @ 0x20 : u8; | ||
var player2 @ 0x21 : u8; | ||
var missiles @ 0x22 : [u8; 2]; | ||
var missile1 @ 0x22 : u8; | ||
var missile2 @ 0x23 : u8; | ||
var ball @ 0x24 : u8; | ||
|
||
var apply @ 0x2A : u8; | ||
var clear @ 0x2B : u8; | ||
} | ||
|
||
namespace vdelay { | ||
var players @ 0x25 : [u8; 2]; | ||
var player1 @ 0x25 : u8; | ||
var player2 @ 0x26 : u8; | ||
var ball @ 0x27 : u8; | ||
} | ||
|
||
namespace reflect { | ||
var players @ 0x0B : [u8; 2]; | ||
var player1 @ 0x0B : u8; | ||
var player2 @ 0x0C : u8; | ||
let ENABLE = 0x08; | ||
} | ||
|
||
namespace warp { | ||
var missiles @ 0x28 : [u8; 2]; | ||
var missile1 @ 0x28 : u8; | ||
var missile2 @ 0x29 : u8; | ||
let ENABLE = 0x02; | ||
} | ||
|
||
namespace reset { | ||
var players @ 0x10 : [u8; 2]; | ||
var player1 @ 0x10 : u8; | ||
var player2 @ 0x11 : u8; | ||
var missiles @ 0x12 : [u8; 2]; | ||
var missile1 @ 0x12 : u8; | ||
var missile2 @ 0x13 : u8; | ||
var ball @ 0x14 : u8; | ||
} | ||
|
||
namespace collision { | ||
var clear @ 0x2C : u8; | ||
|
||
var missile1_vs_players @ 0x30 : u8; | ||
var missile2_vs_players @ 0x31 : u8; | ||
var player1_vs_playfield @ 0x32 : u8; | ||
var player2_vs_playfield @ 0x33 : u8; | ||
var missile1_vs_playfield @ 0x34 : u8; | ||
var missile2_vs_playfield @ 0x35 : u8; | ||
var ball_vs_field @ 0x36 : u8; | ||
var pvp_mvm @ 0x37 : u8; | ||
} | ||
} |
Oops, something went wrong.