This version contains several important bug fixes and a few new features. Please review the list of breaking changes. This release was a little rushed, so issues may arise.
9/22: hotfixes were done. Please download the hotfixed files.
NROM128 support
NESFab can now create 16KB NROM files.
I added this in case anyone wants to participate in the Game Genie Mini Jam.
Anonymous labels
asm fn and fn now accept anonymous labels.
Syntax:
label+amount
label-amount
Where +amount is a number referring to upcoming anonymous labels, and -amount is a number referring to previous anonymous labels.
Example:
label
jmp label-1 // Jump to the previous label
jmp label+1 // Jump to the next label
jmp label+2 // Jumps 2 labels ahead
label
nop
label
Arg-less [] and {}
The [] and {} operator can now be used without an index. In such cases, the index is treated as 0.
Example:
my_array[] = 10 // Equivalent to my_array[0] = 10
Index types: I and II.
There are two new types, I and II. These represent indexes into globally-defined arrays.
Syntax:
I.array
II.array
Where array is the name of a globally-defined array.
Values of I and II store indexes, just like U or UU. However, they also behave like pointers in that you can dereference them using [] or {}.
Example:
vars
UU[10] some_array // Define a global array
fn example()
I.some_array my_index = 5 // Create an index value pointing to the [5] position.
my_index[] = 10 // Equivalent to some_array[5] = 10
Index types reduce the typing involved when working with arrays, but also come with some extra safety.
Feel free to ask in the Discord if you're confused by these.
Stronger type safety on [] and {} (breaking change)
The [] and {} operators now require their index to match type U and UU respectively. Before, implicit conversions were allowed, meaning {} could also accept U and Bool.
Weaker type safety on hardware writes
Hardware writes using the {}() syntax now cast the argument to U in more situations. This allows one to write S values, for example, without an explicit cast.
push / pop optional index argument
For Vec types, you can now push and pop into specific indexes, instead of only the last element.
Syntax:
push(vec, value, index)
pop(vec, index)
+inherit modifier
Adding the +inherit modifier to a struct field allows the owning struct to copy some of its behavior. Specifically, the parent struct will implicitly cast to the inherited field, and the inherited field's own fields will be accessible.
Example:
Struct Bar
U member
struct Foo
Bar bar : +inherit
fn example()
Foo foo = Foo()
Bar bar = foo // Implicit cast
foo.member = 10 // Access Bar members
palette.fab rename: fade_out -> fade_out_custom (breaking change)
The fade_out / fade_in functions were intended to make it easy to define your own fade functions. The problem was, they took up the best names for these functions! Thus, they have been renamed.
lib/metasprite/metasprite.fab
I've added some extra functions to this library file, including ones that use U positions instead of SS.
lib/step_counter.fab
This tiny library file implements a common pattern: counting the number of times NMI was waited on. This is similar to checking nmi_counter, but does not increment on lag frames.
lib/uvec.fab
This library file contains ct functions for manipulating U{} values.