Commit graph

11 commits

Author SHA1 Message Date
b0fb9b5e2c
Wire op_restore to QuetzalParser and filesystem
Implement V3 restore opcode:
- Add QuetzalParser.load_from_bytes() to parse save data from memory
- Wire op_restore to call filesystem.restore_game() and parse result
- Validate IFhd matches current story (release/serial/checksum)
- Restore dynamic memory, call stack, and program counter
- Branch true on success, false on failure/cancellation

Fix IFF chunk padding bug:
- Add padding byte to odd-length chunks in QuetzalWriter
- Ensures proper chunk alignment for parser compatibility

Add comprehensive tests:
- Branch false when filesystem returns None
- Branch false without zmachine reference
- Branch true on successful restore
- Verify memory state matches saved values
- Handle malformed save data gracefully
2026-02-10 10:13:45 -05:00
a5053e10f2
Wire op_save to QuetzalWriter and filesystem
Implement full save functionality for V3 z-machine:
- Fixed QuetzalWriter._generate_anno_chunk() to return bytes
- Added QuetzalWriter.generate_save_data() to produce IFF container
- Updated QuetzalWriter.write() to use new method and binary mode
- Added zmachine reference to ZCpu for QuetzalWriter access
- Added _program_counter property to ZCpu for Quetzal access
- Implemented op_save to call QuetzalWriter and filesystem
- Updated tests for op_save (success, failure, IFF validation)
- Added filesystem mock to MockUI for testing
- Added _call_stack to MockStackManager for QuetzalWriter

All tests pass. Save now generates valid IFF/FORM/IFZS data with
IFhd, CMem, Stks, and ANNO chunks.
2026-02-10 10:13:45 -05:00
69b1ef8a59
Implement QuetzalWriter CMem and Stks chunk generators
Adds comprehensive test coverage for CMem chunk generation:
- test_cmem_all_unchanged: Empty output when memory unchanged
- test_cmem_single_byte_change: Single byte modification
- test_cmem_multiple_scattered_changes: Multiple changes
- test_cmem_roundtrip_with_parser: Writer/parser integration
- test_cmem_consecutive_zeros: Run-length encoding validation
2026-02-10 10:13:33 -05:00
0c6eadb0da
Implement QuetzalWriter._generate_ifhd_chunk()
The IFhd chunk contains 13 bytes of metadata identifying the story
and current execution state:
- Release number (2 bytes) from header
- Serial number (6 bytes) from header
- Checksum (2 bytes) from header
- Program counter (3 bytes) from CPU state

This allows save files to be validated against the story file.
2026-02-10 09:47:24 -05:00
2ce82e7d87
Add unit tests for op_test, op_verify, and op_get_child
Adds comprehensive test coverage for three newly implemented Z-machine opcodes:

- op_test: Tests bitmap flag checking with all flags set, some missing, zero
  flags, and identical values
- op_verify: Tests checksum verification with matching and mismatched checksums
- op_get_child: Tests getting first child of object with and without children

Also extends MockMemory with generate_checksum() and MockObjectParser with
get_child() to support the new tests.
2026-02-09 21:52:08 -05:00
311a67e80a
Fix bugs found running Zork 1 through hybrid interpreter
Spec fixes: implement op_test (bitwise AND branch), add missing branch
to op_get_child, handle call-to-address-0 as no-op in op_call/_call.
I/O fixes: correct keyboard API (keyboard_input.read_line), non-TTY
fallbacks in trivialzui, stdout flush for immediate output. Graceful
handling of unmapped ZSCII characters. Add instruction trace buffer
for debugging.
2026-02-09 21:36:30 -05:00
fb8cbf7219
Implement op_verify and wire ZLexer into sread for Zork 1
op_verify now performs actual checksum validation against the header
instead of raising NotImplemented. ZLexer is injected into ZCpu and
sread tokenizes input into the parse buffer per the V3 spec.
2026-02-09 20:57:15 -05:00
72dd047b7b
Port 5 complex opcodes to hybrid z-machine interpreter
Implement op_sread (text input), op_save/restore (file I/O stubs),
op_restart (exception-based reset), op_input_stream and op_sound_effect
(no-op stubs). Add ZCpuRestart exception. All implementations follow TDD
with comprehensive unit tests.
2026-02-09 20:44:22 -05:00
c76ee337d3
Port 4 medium opcodes to hybrid z-machine interpreter
Implements op_print_addr, op_print_num, op_ret, and op_show_status following
TDD approach with tests first. Each opcode now properly decodes/prints text,
handles signed numbers, returns from routines, or acts as a no-op as appropriate.
2026-02-09 20:44:22 -05:00
1b9d84f41a
Port 10 object tree opcodes to hybrid z-machine interpreter
Implemented 10 opcodes for object tree manipulation: get_sibling,
test_attr, set_attr, clear_attr, jin, remove_obj, print_obj,
get_prop_addr, get_next_prop, and get_prop_len.

Added 6 supporting methods to ZObjectParser: set_attribute,
clear_attribute, remove_object, get_property_data_address,
get_next_property, and get_property_length.

Fixed bug in insert_object where sibling chain walk never advanced
the prev pointer, potentially causing infinite loops.

Added 16 unit tests with MockObjectParser to verify CPU opcode
behavior. All tests passing.
2026-02-09 20:44:21 -05:00
dcc952d4c5
Port 12 trivial opcodes to hybrid z-machine interpreter 2026-02-09 20:44:21 -05:00