Skip to content

Releases: pubby/nesfab

NESFab 1.5

30 Jul 14:02
Compare
Choose a tag to compare

This update is primarily for bug fixes and optimization tweaks, but contains a few new things.

Clang Support

NESFab seemingly compiles under the clang++ compiler now, meaning it might be possible to compile natively on Mac.

Flash Saves

I've improved support for saving to flash memory, adding a +sector modifier to align data to sectors, and a --sector-size compiler option.

See examples/flash_save to see an example.

NESFab 1.4

25 Apr 21:43
Compare
Choose a tag to compare

This update includes bug fixes and a few features.

MMC5 Support

The mmc5 mapper is now supported, with some initial library code at /lib/mapper/mmc5.fab. NESFab can take advantage of MMC5's multiplication hardware when compiling with --unsafe-bank-switch. The NESFab implementation of MMC5 expects 32K banking to always be used.

See examples/mmc5 to see an example.

Rainbow Mapper Support

The rainbow mapper is now supported, with some initial library code at /lib/mapper/rainbow.fab. The NESFab implementation of Rainbow expects 32K banking to always be used.

See examples/rainbow and examples/wifi to see an example.

Expansion Audio

The PUF music driver now implements expansion audio for MMC5 and Rainbow (modified VRC6).

charmap offsets

You can now include an offset incharmap definitions, which defines the value of the first element:

charmap foo("abc", 8)
: stows /strings

Here, a will have a value of 8.

Logging Library

Miau's Lua logging code was adapted into lib/logging, which provides printf support in emulators like FCEUX and Mesen.

For better support, the language now reserves address $00 for debugging, and addresses $100-$107 can be used for additional information.

NESFab 1.3

09 Dec 03:47
Compare
Choose a tag to compare

This update contains a few features and a few bug fixes.

Legal-only Instructions

Building the compiler with make ISA=legal results in a NESFab executable that only generates legal instructions. As illegal instructions have better performance, the default implementation will remain as-is.

Because this is the first release to support this feature, I've included a nesfab_legal.exe in the Windows release. I haven't decided if future releases will do the same.

Conditional byte blocks

You can now use if and else inside byte blocks, so long as the condition can be checked at compile time. This enables data to be included / excluded based on compile-time knowledge.

asm fn foo() U
: employs
    default
        if SOME_CONSTANT == 1
            lda #10
        else
            lda #32
        sta &return
        rts

The current implementation cannot handle labels inside of conditionals, so watch out for that caveat.

PUF Audio Update

More speeds

A common complaint was that PUF music had to be speed 4 or slower. This update removes that restriction, allowing any speed from 1 to 30, albeit with reduced performance for speeds 1 to 3.

Changeable speeds

You can now use puf.set_speed to change the speed of a song while it is playing. This can be used to hasten the music when gameplay gets tense.

Controller Update

Controller reading has received a small update to support more than 2 players.

--controllers compiler flag

You can now set the --controllers option, used to mark the maximum number of controllers used. This exports a __controllers option in the language, which library code (or your code) can reference.

The default controller reading in lib/nes.fab checks the __controllers option to determine its implementation. For 1 player, it only reads the first controller. For 2 players, it reads both. For 3 and 4 players, it checks for the presence of the NES Four Score adapter. No higher player count is supported yet.

See examples/4_player to see the Four Score used.

Famicom Controller Support

As mentioned, the default controller code can handle the Four Score adapter. Unfortunately, the Japanese Famicom supports many more styles of adapters, which complicates things.

The new file lib/famicom.fab contains a controller reading implementation which handles all of these adapters, including the Four Score. It was based on code written by Miau, shared on the forums. Currently, this implementation does not handle the DPCM error, so the DMC channel should not be used.

SNES Mouse Support

The library file lib/mouse.fab implements SNES mouse support.

Currently, this implementation does not handle the DPCM error, so the DMC channel should not be used.

See examples/mouse to see the SNES Mouse used.

CNROM change

Previously, CNROM was changing banks by writing to an address directly, e.g. {$8000}(my_bank). As this method cannot handle bus conflicts, CNROM was changed to use the state keyword, e.g. state(my_bank).

NESFab 1.2

22 Oct 14:20
Compare
Choose a tag to compare

Overview

Primarily bug fixes, with a few features.

-unroll and +unloop

You can now disable loop unrolling using the -unroll modifier:

for U i = 0; i < 10; i += 1
: -unroll
    {PPUDATA}(0)

You can now force loops to be fully unrolled using the +unloop modifier:

for U i = 0; i < 10; i += 1
: +unloop
    {PPUDATA}(0)

These modifiers are hints. They work most of the time, but there may be a few rare cases where they are ignored.

Donut CHR compression

NESFab now supports Donut compression, which is perhaps the best form of CHR compression. See lib/decompress/donut.fab for the decompressor.

Macro-based geometry.fab

There's now a generic version of lib/math/geometry.fab called lib/math/geometry.macrofab, which lets you change the types and prefixes. The original file remains, for those who prefer simplicity.

NESFab 1.1

18 Sep 03:55
Compare
Choose a tag to compare

Overview

This version contains several prominent bug fixes, and a few small features:

Metasprite library reorganization and animation.fab

I've moved lib/metasprite.fab into its own folder: lib/metasprite/metasprite.fab.
This folder also contains a new library file, animation.fab, which contains code for animating metasprites.

To see this file used in an example, check out examples/animation.

Paired hardware writes (and reads)

Using the following syntax, you can now execute two hardware writes consecutively:

{foo_addr, bar_addr}(foo_value, bar_data)

This syntax ensures that the hardware writes will occur as close together as possible, without any execution happening in-between.

Why is this necessary?

First, it's helpful when writing scrolling code to minimize PPU glitches. With this syntax, there's less concern of timing windows.

More importantly though, it's important when interfacing mappers like MMC3, which require two writes to interface.

Consider the code below which doesn't use this feature:

{$8000}(0)
{$8001}(calc_bank())

NESFab may decide to call the function calc_bank between the the two hardware writes. If this occurs, the first write will be clobbered as calling a function writes to $8000 too.

With a paired write, the problem is avoided, as calc_bank must occur before both of the two writes:

{$8000, $8001}(0, calc_bank())

--ctags Option

The --ctags option can be used to generate a ctags file. When loaded into a text editor, the ctags file can be used to quickly navigate to definitions.

To use ctags in VSCode, install the following extension: https://marketplace.visualstudio.com/items?itemName=jtanx.ctagsx

--ram-init, --sram-init, --vram-init Options

These new compiler flags cause memory to be zero'd out on boot. Although not recommended (it's better to zero-init using code), I've gotten a few requests for these so I've decided to add them.

NESFab 1.0

29 Aug 01:15
Compare
Choose a tag to compare

Overview

This is a milestone. If you're an optimist, you can think of NESFab as going from beta to gold. If you're a pessimist, you can think of it as going from alpha to beta. Either way, 1.0 is a major version bump.

There's a decent amount of bugfixes in this release, along with a few features.

Breaking change: Library reorganization

I've moved various files in thelib/ folder to sub-folders such as lib/math/ and lib/audio/. Also, I've renamed a few files and functions (such as base10 -> base_10 to better match NESFab's naming scheme. My apologies for this, but the 1.0 release seemed like a good time to make these changes.

file Expressions

Previously, the file keyword could only be used in byte blocks. Now, it can be used as an expression to produce values of type U{}.

Function pointers

I've added experimental support for function pointers, but this support is somewhat gimped. Function pointers require functions to be partitioned into sets, and function pointers can only be called from a single thread of execution. Also, for the time being, asm support doesn't exist for function pointers. But there is some support in 1.0.

To see this feature being used, check out examples/fn_ptr/.

--multicart compiler option

The --multicart action53 compiler flag can be used to ensure compatibility with the Action 53 multicart mapper. This is intended to be used for the yearly NESDev competition.

JSON mapfab imports

The mapfab keyword can now import .JSON files exported by MapFab.

32x32 Meta-meta-tiles

The mapfab keyword now supports the mmt_32 target, which generates 32x32 metametatiles.

To see this feature being used, check out examples/meta_meta_tiles/.

More examples

  • examples/platformer/ shows the basics of a platforming game
  • examples/scrolling_8_way/ shows how to achieve 8-way scrolling
  • examples/rope/ shows some interesting rope physics
  • examples/billiards/ shows bouncing ball physics

Patreon

https://patreon.com/Pubby434

NESFab 0.9

04 Aug 08:38
Compare
Choose a tag to compare

Overview

This release is a mix of bug fixes, features, and performance enhancements.

MapFab support and the mapfab keyword

MapFab is a new level editor designed to be used with NESFab. Its data files can be imported into NESFab using the new mapfab keyword:

mapfab(raw, "project.mapfab", "chr", "palette", "metatiles", "level")

This keyword invokes user-defined macros for each definition in the .mapfab file, allowing one to customize how the data is formatted in the game.

The new example examples/mapfab illustrates how this works.

chrrom offsets

You can now have multiple chrrom definitions. An integer following the chrrom keyword specifies what offset the data will go.

chrrom $1000
    (...)

chrrom $0000
    (...)

VEC types

VECs are resizeable arrays that only exist at compile time. Their syntax is similar to regular arrays (TEAs), but their length is not part of their type signature:

ct Int{} my_vec = Int{}(1,2,3,4,5)    // Type{} syntax means VEC

The purpose of VECs is that they let you write compile-time functions that generate or resize arrays. Two new keywords: push and pop were added to facilitate this.

ct fn foo(Int{} in) Int{}
    Int{} out = Int{}()
    for U i = 0; i < len(in); i += 1
        push(out, in{i})
        push(out, in{i})
    return out

Unlike other types arrays, VECs can be multi-dimensional.

Patreon

I've set up a Patreon to help development:

https://patreon.com/Pubby434

NESFab 0.8

27 Jun 18:30
Compare
Choose a tag to compare

Overview

This release is a mix of bug fixes, features, and performance enhancements.

Mapper addition: MMC3 and UNROM

Experimentally, MMC3 and UNROM are now supported. These mappers involve a fixed bank, which requires the use of the +static modifier.

Language addition: read and write

The keywords read and write allow data of arbitrary types to be read/written using pointers.

Language addition: nesfab-dir

The --nesfab-dir option is used to specify the directory of the NESFab installation. This should be used instead of specifying lib files using complicated relative paths.

nesfab-dir = ../../
input = lib/nes.fab
input = lib/palette.fab

Likewise, the NESFAB environment variable can be used to set --nesfab-dir globally.

Language addition: sloppy

The --sloppy compiler flag, and +sloppy / -sloppy modifiers can be used to speed up compilation times at the cost of optimization.

Language addition: SRAM

NESFab now supports mappers with 8KiB of additional cartridge RAM (SRAM), which can be enabled using the option --sram. Variables can be forced to use SRAM using the modifiers +sram and -sram.

Language addition: Private identifiers

Global identifiers prefixed with _ are now private to the file they're in.

fn foo() // not private

fn _bar() // private

Breaking language change: PP and PPP pointers.

CC and CCC pointers now point to ROM data only. To point to either ROM data, or RAM data, new PP and PPP types were introduced.

Breaking library change: pbz.fab and rlz.fab

The decompression functions in these files were changed to return a pointer to the end of their data.

PBZ decompression interface was redesigned to better match the rest of the library. This will break existing code.

NESFab 0.7

13 Jun 04:10
Compare
Choose a tag to compare

Overview

Several important bugfixes in this release. Many thanks to the bug reporters!

Library addition: trig.fab

This file contains routines for a few functions from trigonometry - the ones useful for game dev.

To see this file being used, check out "examples/trig".

NESFab 0.6

01 Jun 20:04
Compare
Choose a tag to compare

Overview

A large number of bug fixes, and a few new optimizations.

Language change to groups

In previous versions of NESFab, each group was either a vars group, a data group, or an omni data group. In 0.6 however, groups can be any combination of these.

For example, the following code is now valid:

vars /my_group
    // ...

data /my_group
    // ...

To implement this change, changes were made to the stows and employs modifiers.

  • stows now puts strings in a regular data block. To put them in an omni data block, use stows omni.
  • employs works as it always does, but one can use employs vars or employs data to employ only those specific blocks of each group.

Library addition: base10.fab

This file contains routines for converting between numbers and a base-10 representation. It is useful if you want to display numbers on the screen.

To see this file being used, check out "examples/counter".

Library addition: palette.fab

This file extends the palette code from "lib/nes.fab", specifically adding routines to fade in and out. In the future, more effects may be added.

To see this file being used, check out "examples/fade".