Coder Social home page Coder Social logo

issotm / fortissimo Goto Github PK

View Code? Open in Web Editor NEW
18.0 3.0 1.0 313 KB

A speed-and size-focused Game Boy music driver, drop-in replacement for hUGEDriver ~ Try the demo!

Home Page: http://eldred.fr/fortISSimO/

License: Other

Assembly 42.12% C 1.08% Rust 42.36% Shell 0.17% JavaScript 14.26%
chiptune chiptune-player game-boy game-boy-color game-boy-development hugetracker

fortissimo's Introduction

Hi!

The name's Eldred, Eldred Habert.

I mainly deal with lower-level stuff, and making tools to help others make great stuff out of them. I'm a regular over at gbdev, if you're interested in making a game on a retro platform for fun, this might be worth checking out!

I'm the main maintainer of RGBDS, the main toolchain for programming on the Game Boy. If you're interested in contributing, we have some beginner-friendly tasks!

I have a Game Boy programming tutorial in progress; if you'd be interested in translating it, you can help! Please open an issue to let me know, and we can get started :)

Thanks for stopping by, have fun on the rest of your browsing journey o/

fortissimo's People

Contributors

dependabot[bot] avatar eievui5 avatar issotm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

papielguapo

fortissimo's Issues

Pattern break breaks to the same pattern

Pattern break Dxx seems to under fO, jump to the specified row on the pattern it's already playing. Under hD, it skips to the next pattern (unless overridden using a Bxx command).

Set tempo problem

There seems to be something not quite right with Fxx Set Tempo. For example, playing the first pattern of the sample song The Murderous Funk Machine (intro), it has a discrepancy. I've attached recordings displaying the difference, with the first channel isolated.

funk.zip

Arpeggio problem

Arpeggios do not seem to work. I've included a sample module, and recordings of each driver.

arp.zip

Unmuting a channel may still yield a corrupted sound

When a channel is unmuted, the driver refrains from using it until a note is next played. The reason is that FX might write to the channel while NRxy still contain leftover values, but not the song's; this would produce corrupt sounds. When a note is played, all NRxy registers are initialised, avoiding the issue.

However, the current condition is wrong: all registers may not be written if a note is played, only if an instrument is specified on that cell as well.

fortISSimO/fortISSimO.asm

Lines 530 to 541 in 91287de

ldh a, [hUGE_AllowedChannels]
or e
ldh [hUGE_AllowedChannels], a
; Let's roll!
push de ; Save the note index for later.
; First, apply the instrument.
ld a, [hli]
inc hl
assert whUGEch1.instrAndFX + 2 == whUGEch1.subPattern
and $F0 ; Keep the instrument bits.
jr z, .noInstr

fortISSimO/fortISSimO.asm

Lines 629 to 637 in 91287de

ldh a, [hUGE_AllowedChannels]
or hUGE_CH3_MASK
ldh [hUGE_AllowedChannels], a
; First, apply the instrument.
ld a, [whUGEch3.instrAndFX]
and $F0 ; Keep the instrument bits.
ld hl, whUGEch3.ctrlMask
jr z, .noWaveInstr

fortISSimO/fortISSimO.asm

Lines 715 to 723 in 91287de

ldh a, [hUGE_AllowedChannels]
or hUGE_CH4_MASK
ldh [hUGE_AllowedChannels], a
; First, apply the instrument.
ld a, [whUGEch4.instrAndFX]
and $F0 ; Keep the instrument bits.
ld hl, whUGEch4.ctrlMask
jr z, .noNoiseInstr

This would require moving the AllowedChannels write inside of the "instrument writes" block. Preferably early, as e (the channel mask) eventually gets overwritten from register pressure.

Allow disabling teNOR's optimisation passes

This should be relatively easy:

  1. Add a new option (in main.rs); I'm thinking something like -O -trim_patterns,+prune_instruments. (-O is a common "optimisation" flag, e.g. in C compilers.) The argument would be a comma-separated list of pass toggles, with the + or - prefix indicating whether to enable or disable the pass.
  2. For each pass, if it's disabled, then replace it with a dummy operation that doesn't perform any optimisations. (For example, the "row overlap" pass would instead return some arbitrary order, and no overlap.)

Rationale

This would be useful for people doing tricks with the song data (e.g. using routines to manipulate the song pointer).

Error: Unable to parse a UGE song from "....": There was an error parsing the UGE file!

Attached song works fine in hUGETracker 1.0.1, but trying to parse it with teNOR-v1.0.0-x86_64 throws an error:

Error: Unable to parse a UGE song from "Prologue_test_new05a.uge": There was an error parsing the UGE file!
        (0x6001 bytes into the data) Length out of range (000000e3)
        (0x5efd bytes into the data) parsing v3 instrument from here
        (0x542b bytes into the data) Error in parser "Count"
        (0x542b bytes into the data) parsing v3 instrument bank from here
        (0x304  bytes into the data) parsing v3 instr collection from here
        (0x4    bytes into the data) parsing v6 song from here
(Either the file is corrupted, or our UGE parser has a bug. If the latter, please attach your UGE file and the above in your bug report!)

Prologue_test_new05.zip

Add "fixed mode" subpatterns

This has been requested by a few people: allow "absolute" offsets in subpatterns.

Proposed implementation: repurpose a FX otherwise incompatible with subpatterns, that would signal the offset must instead be interpreted as a note ID. Possibly, make the FX param be an additional offset to add to that note's period?

Optimise generated song format

Look for ; TODO: have tracker do this comments (or similar, the regex TODO.+tracker should find them all). These mark computations that can be done statically, which would not only save some cycles, but also some bytes in the especially "jr-tight" FX code.

@SuperDisk has commented that the textual output format is not to be changed, for "debuggability" purposes (fair enough); however, the binary format can be modified.

Fortunately, macros can give us the best of both worlds:

MACRO dn ;; (note, instr, effect)
db (\1 | ((\2 & %00010000) << 3))
db (((\2 << 4) & $FF) | (\3 >> 8))
db LOW(\3)
ENDM

#define DN(A, B, C) (unsigned char)(A | ((B & 0x10) << 3)),(unsigned char)(((B << 4) & 0xFF) | (C >> 8)),(unsigned char)(C & 0xFF)

This is trivial on the RGBDS side, since the macro can be essentially as complex as we want (though keeping the complexity low is preferable), but more annoying on the C side, since the macro has to be expressions—and unlike 🦀, we can't really do conditionals besides ternaries, likely turning that macro into ternary soup in the long run.

A possibility for the C thing is to "pre-process" that C file (from a more maintainable hUGEDriver.h.in). This however complicates the integration process slightly, though we can instead rely on releases for this. Maybe.

Split "cell catalog" between "main grid" and subpatterns

Note

Help is wanted because I do not have the motivation to implement this; I am however willing to provide guidance to anyone having that motivation. Feel free to contact me.

Context / Motivation

Currently, the biggest problem with using fO over hD is the dreaded Error: The song has NNN unique cells, the max is 256! error.

In the interest of size, fO collects cells (note+instr+FX) into a "catalog", and stores cells as indices into this catalog; in the interest of size and speed (again), those indices are single bytes, which inherently forbid more than 256 entries in the "catalog".

Implementation

A way to relax the limitation is to split the catalog in two1: one for the "main grid", and one for subpatterns. Then the limitation only applies to each one individually, which should be productive considering that typical cells for patterns and subpatterns are quite different.

As far as fO itself is concerned, this is really simple: duplicate the pointer to .cellCatalog, and change the variable being loaded from in TickSubpattern.

Issues

Song export

First off, teNOR currently assumes that it can compute the "overlap" optimisation by comparing the cells themselves; this wouldn't become true anymore, because nothing guarantees a given cell would have the same ID across both catalogs.

Therefore, cells should instead be compared via some kind of IDs, of three kinds: shared, main only, and subpattern only. Then, the shared cells would get the same indices across both catalogs (so the first few, for simplicity).

Output size

There is also a size problem: there is already somewhat considerable padding within a cell catalog2, and splitting the catalog in two like that would multiply the padding by 2.5!

This could be mitigated by fusing the two catalogs like they currently are if that's possible; then both labels are identical, and only a single header byte is wasted—but that increases the implementation's complexity significantly.

Footnotes

  1. Other options have been considered for splitting, such as one catalog per channel; but these are very impractical to implement, at least with fO in its current form.

  2. The size of the catalog is 512 + nb_cells bytes, which can be a lot compared to the theoretical minimum size of 3 × nb_cells.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.