![]() |
Routines |
| Prev: 74A6 | Up: Map | Next: 7574 |
|
Used by the routine at NARRATE_ACTION.
Takes a 2-byte word reference and writes the letters to a buffer at WORD_BUFFER -- which the disassembly shows as a data block and a message, because it holds whatever was last expanded into it rather than anything the game was built with.
The reference: the low 12 bits are an offset from WORD_INDEX to the entry, and the top 4 bits are flags the tail of the routine acts on. Zero means print nothing. The letters come back out as lowercase ASCII by adding $60 to each 5-bit code.
The loop is where the game states the format's awkward rule itself. It stops on a byte with bit 7 set, except that if only two letters have been emitted it carries on regardless -- because the top bits of the first two bytes are the word's part of speech, so bit 7 there is not a terminator. At exactly three letters it goes back and re-tests the second byte's bit 7 before deciding. A decoder that simply stops at the first bit 7 splits ATTACK into AT and TACK.
|
||||||||
| PRINT_WORD | 74BA | LD E,(HL) | DE = the reference at HL | |||||
| 74BB | INC HL | |||||||
| 74BC | LD A,(HL) | |||||||
| 74BD | INC HL | |||||||
| 74BE | AND $0F | |||||||
| 74C0 | LD D,A | |||||||
|
This entry point is used by the routines at NARRATE_ACTION, RUN_MESSAGE, WORD_AND_END, ARTICLE, PRINT_NOUN, PRINT_SUBJECT, DO_LOOK, PRINT_NAME, EXITS_THROUGH, VISIBLE_EXITS and GOBLIN_RETURNS.
|
||||||||
| PRINT_WORD_DE | 74C1 | LD A,D | Zero prints nothing | |||||
| 74C2 | AND $0F | |||||||
| 74C4 | OR E | |||||||
| 74C5 | RET Z | |||||||
| 74C6 | PUSH HL | |||||||
| 74C7 | PUSH BC | |||||||
| 74C8 | PUSH DE | |||||||
| 74C9 | LD C,D | C = the flag nibble, for later | ||||||
| 74CA | LD A,D | HL = the dictionary entry | ||||||
| 74CB | AND $0F | |||||||
| 74CD | LD D,A | |||||||
| 74CE | LD HL,WORD_INDEX | |||||||
| 74D1 | ADD HL,DE | |||||||
| 74D2 | LD DE,WORD_BUFFER | The letters go into the buffer at WORD_BUFFER | ||||||
| 74D5 | PUSH HL | |||||||
| 74D6 | LD B,$00 | |||||||
| PRINT_WORD_0 | 74D8 | LD A,(HL) | Each letter as lower-case ASCII, counted in B | |||||
| 74D9 | AND $1F | |||||||
| 74DB | JR Z,PRINT_WORD_1 | |||||||
| 74DD | INC B | |||||||
| 74DE | ADD A,$60 | |||||||
| 74E0 | LD (DE),A | |||||||
| 74E1 | INC DE | |||||||
| 74E2 | BIT 7,(HL) | Bit 7 clear: more letters to come | ||||||
| 74E4 | INC HL | |||||||
| 74E5 | JR Z,PRINT_WORD_0 | |||||||
| 74E7 | LD A,B | Bit 7 set after only two letters is part of the class, not the end | ||||||
| 74E8 | CP $02 | |||||||
| 74EA | JR Z,PRINT_WORD_0 | |||||||
| 74EC | CP $03 | After three, look again at the second byte's bit 7 before deciding | ||||||
| 74EE | JR NZ,PRINT_WORD_1 | |||||||
| 74F0 | DEC HL | |||||||
| 74F1 | DEC HL | |||||||
| 74F2 | LD A,(HL) | |||||||
| 74F3 | INC HL | |||||||
| 74F4 | INC HL | |||||||
| 74F5 | BIT 7,A | |||||||
| 74F7 | JR NZ,PRINT_WORD_0 | |||||||
| PRINT_WORD_1 | 74F9 | POP HL | ||||||
| 74FA | LD A,C | Flag nibble $50: never inflect | ||||||
| 74FB | AND $F0 | |||||||
| 74FD | CP $50 | |||||||
| 74FF | JR Z,PRINT_WORD_5 | |||||||
| 7501 | CP $40 | $40: always inflect | ||||||
| 7503 | JR Z,PRINT_WORD_3 | |||||||
| 7505 | CP $10 | $10 agrees with TARGET, anything else with ACTING: zero, no ending | ||||||
| 7507 | LD A,(TARGET) | |||||||
| 750A | JR Z,PRINT_WORD_2 | |||||||
| 750C | LD A,(ACTING) | |||||||
| PRINT_WORD_2 | 750F | AND A | ||||||
| 7510 | JR Z,PRINT_WORD_5 | |||||||
| PRINT_WORD_3 | 7512 | INC HL | The word itself has to allow an ending: bit 7 of its second byte | |||||
| 7513 | BIT 7,(HL) | |||||||
| 7515 | JR Z,PRINT_WORD_5 | |||||||
| 7517 | INC HL | HL = the ending chosen by bits 5-7 of its third byte, in ENDINGS | ||||||
| 7518 | LD A,(HL) | |||||||
| 7519 | AND $E0 | |||||||
| 751B | RRCA | |||||||
| 751C | RRCA | |||||||
| 751D | RRCA | |||||||
| 751E | LD L,A | |||||||
| 751F | LD H,$00 | |||||||
| 7521 | LD BC,ENDINGS | |||||||
| 7524 | ADD HL,BC | |||||||
| 7525 | LD B,$04 | Add up to four characters of it to the buffer | ||||||
| PRINT_WORD_4 | 7527 | LD A,(HL) | ||||||
| 7528 | AND A | |||||||
| 7529 | JR Z,PRINT_WORD_5 | |||||||
| 752B | INC HL | |||||||
| 752C | LD (DE),A | |||||||
| 752D | INC DE | |||||||
| 752E | DJNZ PRINT_WORD_4 | |||||||
| PRINT_WORD_5 | 7530 | LD HL,WORD_BUFFER | B = how many characters there are to print | |||||
| 7533 | EX DE,HL | |||||||
| 7534 | AND A | |||||||
| 7535 | SBC HL,DE | |||||||
| 7537 | LD B,L | |||||||
| 7538 | LD A,(INPUT_STYLE) | A space before the word, when one is wanted | ||||||
| 753B | AND A | |||||||
| 753C | PUSH AF | |||||||
| 753D | JR NZ,PRINT_WORD_6 | |||||||
| 753F | LD A,(MID_LINE) | |||||||
| 7542 | AND A | |||||||
| PRINT_WORD_6 | 7543 | LD A,$20 | ||||||
| 7545 | CALL NZ,PRINT_CHAR | |||||||
| 7548 | POP AF | Start a new line first if the word would not fit on this one | ||||||
| 7549 | LD A,(INPUT_COLUMNS) | |||||||
| 754C | JR NZ,PRINT_WORD_7 | |||||||
| 754E | LD A,(STORY_COLUMNS) | |||||||
| PRINT_WORD_7 | 7551 | LD HL,CAPITAL_NEXT | ||||||
| 7554 | CP B | |||||||
| 7555 | JR NC,PRINT_WORD_8 | |||||||
| 7557 | LD A,(HL) | |||||||
| 7558 | CALL NEW_LINE | |||||||
| 755B | LD (HL),A | |||||||
| PRINT_WORD_8 | 755C | POP DE | ||||||
| 755D | LD A,D | Flag nibble $70 sets CAPITAL_NEXT to 1 | ||||||
| 755E | AND $F0 | |||||||
| 7560 | CP $70 | |||||||
| 7562 | LD A,$01 | |||||||
| 7564 | JR NZ,PRINT_WORD_9 | |||||||
| 7566 | LD (HL),A | |||||||
| PRINT_WORD_9 | 7567 | LD HL,WORD_BUFFER | Print the buffer | |||||
| PRINT_WORD_10 | 756A | LD A,(HL) | ||||||
| 756B | CALL PRINT_CHAR | |||||||
| 756E | INC HL | |||||||
| 756F | DJNZ PRINT_WORD_10 | |||||||
| 7571 | POP BC | |||||||
| 7572 | POP HL | |||||||
| 7573 | RET | |||||||
|
The flags in the top nibble choose whether the word is inflected, and the whole of it is: $40 always adds the suffix, $50 never does, $10 adds it when TARGET is non-zero, and every other value adds it when ACTING is non-zero. Either way the word itself has the final say -- the suffix is only added if bit 7 of its second byte is set, which is what marks an entry as one that can take it.
Measured rather than read off: PRINT_WORD was called directly with each of the sixteen flag values and the buffer read back, then TARGET and ACTING were toggled by hand to test the dispatch. The word at WORD_SHATTER comes out as "shatter" or "shatters" exactly as the rule above predicts in all six cases, the ones at WORD_RECOVER and WORD_ARRIVES inflect the same way, and no word in the indexed list inflects at all -- none of them has that bit set, which fits, since the indexed list is what the parser matches against and nothing is ever printed from it.
ACTING holds who the sentence is about, and zero means the player -- so the test really is subject agreement. Watched across real sentences: while the game narrates you it is zero and no verb inflects, and while it narrates anybody else it holds that character's identifier and the inflectable verbs take their -s. TARGET is a second participant, and flag $10 is how a word is made to agree with that one instead.
The identifiers are not a flag but a character number: TARGET is set to $FF at PARSE_ACTION, loaded from tables at FIRST_TARGET_FAILED and TARGET_NAME elsewhere, and compared against list entries with CP (HL) at EXCEPTED. One turn of narration walked ACTING through a run of consecutive values while repeating the same verb, which is a group of characters being described one after another rather than anything to do with grammar.
|
||||||||
| Prev: 74A6 | Up: Map | Next: 7574 |