8000 Tags · cv/kananeko · GitHub
[go: up one dir, main page]

Skip to content

Tags

Tags

v1.5.5

Toggle v1.5.5's commit message

Unverified

This user has not yet uploaded their public signing key.
perf: test for 0 with OR A instead of CP 0

OR A sets Z like CP 0 in a byte less; only the N flag differs, and only DAA
reads it (the game has none). compare, ifEquals, ifNotEquals and dispatch
now use it for 0, as do the seven CP 0s written out in the game. Two of
those followed a DEC that had already set Z, so they're gone. 30 bytes
saved: 30,725 bytes, 1,707 free.

v1.5.4

Toggle v1.5.4's commit message

Unverified

This user has not yet uploaded their public signing key.
feat(asm): typed state dispatch and helpers for common sequences

Branching on a variable now goes through helpers that know its enum:
- dispatch(MEM.KANA_STATE, KanaState, { IDLE: 'ret', AWAITING: 'continue',
  ... }) needs a case for every value, from the variable's own enum, so a
  new state can't go unhandled. The kana and dialogue update routines and
  the kana mode check use it.
- compare, ifEquals and ifNotEquals only take values of the variable's kind
  (28 sites).

Common sequences got names:
- incByte, decByte, copyByte (byteOf-checked), copyWord: 24 sites;
- tableEntry(table, stride) and addAToHl for table lookups: 7 sites;
- pressed, held, ifPressed and ifHeld for the buttons: 6 sites.

The two state dispatches no longer test the state that carries on, which
frees 9 bytes (30,755 bytes, 1,677 free). Everything else assembles to the
same bytes. Also corrects joypad.ts's header, which still gave the variables'
old addresses.

rom-fddb5fe3f852

Toggle rom-fddb5fe3f852's commit message

Unverified

This user has not yet uploaded their public signing key.
feat(asm): routine arguments in contracts, called with invoke

A contract now says which registers a routine takes (in), and the build checks
it: a routine that reads a register before setting it must take it, and one
it takes must be read. Routines with arguments are called with invoke, which
needs exactly those arguments, so a forgotten one is a type error:

  ...invoke(CAT_PLACE, { b: spot.x, c: spot.y })
  ...invoke(VRAM_PUT, { a: 'a', hl: 'hl' })   // already in place

A plain call() to such a routine no longer type-checks. The 30 routines that
take arguments got their in lists from the new inference in npm run
contracts, and all 48 calls to them use invoke. The ROM is byte-identical.

Knowing the arguments also tightened the clobber check: a register a later
call takes must survive the calls before it. That showed five contracts
listed a result as clobbered: pass_tile (A), practice_pick (A), table_find
(DE), question_copy (DE) and draw_tiles (HL) now declare them as outputs.

Inputs are worked out without counting a routine's outputs as needed at RET,
so an output set on only some paths (table_find's DE) isn't taken for an
argument. F is left out: flag inputs aren't tracked.

rom-f3ae11941c1e

Toggle rom-f3ae11941c1e's commit message

Unverified

This user has not yet uploaded their public signing key.
style: sort imports with eslint-plugin-simple-import-sort

Every file ordered its imports its own way. The new lint rule (fixable with
eslint --fix) sorts them: packages and the @asm/@GAMe aliases first, then
relative imports, with the names inside each one sorted too. The change is
mechanical; the ROM is byte-identical and the site's tests pass.

rom-f2cd45e6bce6

Toggle rom-f2cd45e6bce6's commit message

Unverified

This user has not yet uploaded their public signing key.
feat(asm): typed state dispatch and helpers for common sequences

Branching on a variable now goes through helpers that know its enum:
- dispatch(MEM.KANA_STATE, KanaState, { IDLE: 'ret', AWAITING: 'continue',
  ... }) needs a case for every value, from the variable's own enum, so a
  new state can't go unhandled. The kana and dialogue update routines and
  the kana mode check use it.
- compare, ifEquals and ifNotEquals only take values of the variable's kind
  (28 sites).

Common sequences got names:
- incByte, decByte, copyByte (byteOf-checked), copyWord: 24 sites;
- tableEntry(table, stride) and addAToHl for table lookups: 7 sites;
- pressed, held, ifPressed and ifHeld for the buttons: 6 sites.

The two state dispatches no longer test the state that carries on, which
frees 9 bytes (30,755 bytes, 1,677 free). Everything else assembles to the
same bytes. Also corrects joypad.ts's header, which still gave the variables'
old addresses.

rom-aa8ebf1aaa65

Toggle rom-aa8ebf1aaa65's commit message

Unverified

This user has not yet uploaded their public signing key.
perf: test for 0 with OR A instead of CP 0

OR A sets Z like CP 0 in a byte less; only the N flag differs, and only DAA
reads it (the game has none). compare, ifEquals, ifNotEquals and dispatch
now use it for 0, as do the seven CP 0s written out in the game. Two of
those followed a DEC that had already set Z, so they're gone. 30 bytes
saved: 30,725 bytes, 1,707 free.

rom-5693bfa928fe

Toggle rom-5693bfa928fe's commit message

Unverified

This user has not yet uploaded their public signing key.
refactor: write the framework's macros with mnemonics and trim exports

- src/asm/macros.ts and flow.ts used the encoding layer (ld_a_nn, jr_cc,
  ld_rr_nn...): 109 calls now use the same mnemonics as the game code, so the
  framework reads like what it helps write. Doc comments that named the old
  functions are updated too.
- 75 exports in src/game that nothing else uses are now private: the builders
  each module wires up itself (buildCatRoutines, buildChartData...), constants
  and types only their own file needs.
- 16 u16() wrappers around a register pair's value are gone: ld() and
  invoke() take a plain number for a pair.

The ROM is byte-identical.

rom-3da13102afb2

Toggle rom-3da13102afb2's commit message

Unverified

This user has not yet uploaded their public signing key.
refactor(game): split main.ts into title, results, rounds and boot

main.ts held the title screen, the result screens, the round routines, boot
and the game flow in 864 lines. Each now lives with what it's about:
- title.ts: the logo, the menu and the START prompt (titleModule);
- results.ts: the ending and game-over screens, with the stamps (resultsModule);
- rounds.ts: the routines that find and play a scene's rounds, next to the
  data they read (roundsModule), plus engineLoop and resetRunState;
- boot.ts: the CPU, RAM and font setup, and the font's tiles (fontModule).

main.ts (386 lines) keeps the game flow, the scenes module and the list of
modules. Data moved to the modules that use it: the chart's, title's and
result screens' palette sets, the speed round's questions (practice), and the
dialogue dictionary (dialogueModule now takes the codec).

Moving the code alone left the ROM byte-identical. Moving the data changed
its order, so the layout changed, but not the size (30,755 bytes).

v1.5.3

Toggle v1.5.3's commit message

Unverified

This user has not yet uploaded their public signing key.
feat(asm): record layouts declared once

src/asm/struct.ts: struct(name, { field: word() | byte() }) gives each field's offset, the record size, encode() for its ROM data and decode() for tests. FieldsOf picks out fields of one kind, so code that reads a word field can't be handed a byte field.

The scene table entry, a sound voice's state and an OAM entry use it. sceneWord()/sceneByte() take only fields of their kind, buildSceneTable() encodes entries with SCENE_ENTRY, and a ROM test now decodes each scene's entry and checks it points at that scene's data.

The ROM is byte-identical to the previous commit.

v1.5.2

Toggle v1.5.2's commit message

Unverified

This user has not yet uploaded their public signing key.
feat(asm): one function per mnemonic, with type-checked operands

src/asm/sm83.ts writes instructions the way the assembly reads: ld('a', [MEM.X]), ld(['hl+'], 'a'), ld('hl', TABLE), cp(3), add('hl', 'de'), inc(['hl']), jr('nz', LOOP), call('c', X), ret('z'). Brackets mean memory, as parentheses do in assembly.

Overloads only allow forms the CPU has: ld('b', [MEM.X]) and ld(['hl'], ['hl']) are type errors, and immediates are typed Imm, which excludes addresses, so ld('a', MEM.X) without brackets doesn't compile either. Immediates take plain numbers and are range-checked, so the game no longer needs u8() around them. ops.ts stays as the encoding layer under it (and gains CALL cc,nn).

All the game code and tests move to it: 1564 instructions in 24 files, replacing 13 ld_* variants and the _r/_n pairs of each ALU instruction. The README gets a short guide to writing game code.

The ROM is byte-identical.
0