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.
This commit is contained in:
parent
205e2716dd
commit
fb8cbf7219
3 changed files with 27 additions and 5 deletions
|
|
@ -43,7 +43,7 @@ class ZCpuRestart(ZCpuError):
|
|||
|
||||
class ZCpu:
|
||||
def __init__(
|
||||
self, zmem, zopdecoder, zstack, zobjects, zstring, zstreammanager, zui
|
||||
self, zmem, zopdecoder, zstack, zobjects, zstring, zstreammanager, zui, zlexer
|
||||
):
|
||||
self._memory = zmem
|
||||
self._opdecoder = zopdecoder
|
||||
|
|
@ -52,6 +52,7 @@ class ZCpu:
|
|||
self._string = zstring
|
||||
self._streammanager = zstreammanager
|
||||
self._ui = zui
|
||||
self._lexer = zlexer
|
||||
|
||||
def _get_handler(self, opcode_class, opcode_number):
|
||||
try:
|
||||
|
|
@ -556,8 +557,10 @@ class ZCpu:
|
|||
pass
|
||||
|
||||
def op_verify(self, *args):
|
||||
"""TODO: Write docstring here."""
|
||||
raise ZCpuNotImplemented
|
||||
"""Verify story file checksum. Branch if checksum matches."""
|
||||
expected_checksum = self._memory.read_word(0x1C)
|
||||
actual_checksum = self._memory.generate_checksum()
|
||||
self._branch(expected_checksum == actual_checksum)
|
||||
|
||||
def op_piracy(self, *args):
|
||||
"""TODO: Write docstring here."""
|
||||
|
|
@ -619,9 +622,22 @@ class ZCpu:
|
|||
self._memory[text_buffer_addr + 1 + len(text)] = 0
|
||||
|
||||
# Tokenize if parse buffer provided
|
||||
# Note: ZLexer not yet wired up - tokenization will be added when needed
|
||||
if parse_buffer_addr != 0:
|
||||
pass # TODO: add tokenization when ZLexer is integrated
|
||||
max_words = self._memory[parse_buffer_addr]
|
||||
tokens = self._lexer.parse_input(text)
|
||||
num_words = min(len(tokens), max_words)
|
||||
self._memory[parse_buffer_addr + 1] = num_words
|
||||
offset = 0
|
||||
for i in range(num_words):
|
||||
word_str, dict_addr = tokens[i]
|
||||
# Find word position in text
|
||||
pos = text.find(word_str, offset)
|
||||
word_len = len(word_str)
|
||||
base = parse_buffer_addr + 2 + (i * 4)
|
||||
self._memory.write_word(base, dict_addr)
|
||||
self._memory[base + 2] = word_len
|
||||
self._memory[base + 3] = pos + 1 # 1-indexed from start of text buffer
|
||||
offset = pos + word_len
|
||||
|
||||
def op_sread_v4(self, *args):
|
||||
"""TODO: Write docstring here."""
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
from . import zlogging
|
||||
from .zcpu import ZCpu
|
||||
from .zlexer import ZLexer
|
||||
from .zmemory import ZMemory
|
||||
from .zobjectparser import ZObjectParser
|
||||
from .zopdecoder import ZOpDecoder
|
||||
|
|
@ -33,6 +34,7 @@ class ZMachine:
|
|||
self._opdecoder.program_counter = self._mem.read_word(0x06)
|
||||
self._ui = ui
|
||||
self._stream_manager = ZStreamManager(self._mem, self._ui)
|
||||
self._lexer = ZLexer(self._mem)
|
||||
self._cpu = ZCpu(
|
||||
self._mem,
|
||||
self._opdecoder,
|
||||
|
|
@ -41,6 +43,7 @@ class ZMachine:
|
|||
self._stringfactory,
|
||||
self._stream_manager,
|
||||
self._ui,
|
||||
self._lexer,
|
||||
)
|
||||
|
||||
# --------- Public APIs -----------
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ class ZMachineOpcodeTests(TestCase):
|
|||
Mock(), # string
|
||||
Mock(), # stream manager
|
||||
self.ui,
|
||||
Mock(), # lexer
|
||||
)
|
||||
|
||||
def test_op_nop(self):
|
||||
|
|
@ -356,6 +357,7 @@ class ZMachineObjectOpcodeTests(TestCase):
|
|||
self.string,
|
||||
Mock(), # stream manager
|
||||
self.ui,
|
||||
Mock(), # lexer
|
||||
)
|
||||
|
||||
def test_op_get_sibling_with_sibling(self):
|
||||
|
|
@ -536,6 +538,7 @@ class ZMachineComplexOpcodeTests(TestCase):
|
|||
Mock(), # string
|
||||
Mock(), # stream manager
|
||||
self.ui,
|
||||
Mock(), # lexer
|
||||
)
|
||||
|
||||
def test_op_sread_v3_basic_input(self):
|
||||
|
|
|
|||
Loading…
Reference in a new issue