mirror of
https://github.com/imjasonh/nescript
synced 2026-07-08 17:06:04 +00:00
lang: NES 2.0 headers and u16 struct fields
Implements two items from docs/future-work.md's language-feature gaps:
NES 2.0 header support: `RomBuilder` gains a `header_format` field
and a matching `enable_nes2()` method. When enabled, byte 7 bits 2-3
are set to `10` and bytes 8-15 are populated per the NES 2.0 spec
(submapper, PRG/CHR MSBs, PRG/CHR RAM, timing). The header stays
16 bytes. Programs opt in via `game Foo { header: nes2 }`; the
default remains iNES 1.0 so every committed example ROM is byte
identical. `validate_ines` now detects and reports which format it
parsed.
u16 struct fields: the analyzer's `register_struct` accepts `u16`
fields with a two-byte size and the struct-variable allocator tracks
per-field sizes so the synthesized `pos.x`/`pos.y` globals get the
right address span. IR lowering's `LValue::Field` and
`Expr::FieldAccess` follow the same wide path as u16 globals, and
struct-literal initialization writes both bytes for u16 fields.
Array and nested-struct fields stay rejected with a clearer
message. Existing u8/i8/bool struct programs are unaffected.
https://claude.ai/code/session_01MaNVcDmK9gsspRkdxowQAM
This commit is contained in:
parent
65a63f9a68
commit
33351f8b32
13 changed files with 588 additions and 26 deletions
|
|
@ -4,7 +4,7 @@ mod tests;
|
|||
use crate::asm;
|
||||
use crate::asm::{AddressingMode as AM, Instruction, Opcode::*};
|
||||
use crate::assets::{BackgroundData, MusicData, PaletteData, SfxData};
|
||||
use crate::parser::ast::{Mapper, Mirroring};
|
||||
use crate::parser::ast::{HeaderFormat, Mapper, Mirroring};
|
||||
use crate::rom::RomBuilder;
|
||||
use crate::runtime;
|
||||
|
||||
|
|
@ -12,6 +12,7 @@ use crate::runtime;
|
|||
pub struct Linker {
|
||||
mirroring: Mirroring,
|
||||
mapper: Mapper,
|
||||
header_format: HeaderFormat,
|
||||
}
|
||||
|
||||
/// CHR data for a sprite, placed at a specific tile index in CHR ROM.
|
||||
|
|
@ -115,11 +116,25 @@ impl Linker {
|
|||
Self {
|
||||
mirroring,
|
||||
mapper: Mapper::NROM,
|
||||
header_format: HeaderFormat::Ines1,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_mapper(mirroring: Mirroring, mapper: Mapper) -> Self {
|
||||
Self { mirroring, mapper }
|
||||
Self {
|
||||
mirroring,
|
||||
mapper,
|
||||
header_format: HeaderFormat::Ines1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Opt into the NES 2.0 header format for the emitted ROM.
|
||||
/// Chainable builder method — returns `self` so callers can
|
||||
/// write `Linker::with_mapper(m, p).with_header(HeaderFormat::Nes2)`.
|
||||
#[must_use]
|
||||
pub fn with_header(mut self, header: HeaderFormat) -> Self {
|
||||
self.header_format = header;
|
||||
self
|
||||
}
|
||||
|
||||
/// Link all code sections into a .nes ROM.
|
||||
|
|
@ -454,6 +469,9 @@ impl Linker {
|
|||
// Build ROM
|
||||
let mut builder = RomBuilder::new(self.mirroring);
|
||||
builder.set_mapper(crate::rom::mapper_number(self.mapper));
|
||||
if self.header_format == HeaderFormat::Nes2 {
|
||||
builder.enable_nes2();
|
||||
}
|
||||
|
||||
// Multi-bank layout: each switchable bank is an independent
|
||||
// 16 KB slot whose contents the linker takes verbatim from
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue