The current URL is datacrystal.tcrf.net.
Sindibad: Chitei no Daimakyuu/Notes
The following article is a Notes Page for Sindibad: Chitei no Daimakyuu.
Raw Notes on Script Text Sequences Used by Code
- $01.4a51-$4a57: Section 00, tag 01. - $02.622a-$6230: Section 24, tag 13. - Failed to escape. - $02.624e-$6254: Section 24, tag 35. - Frozen monster thaws. - $02.6468-$647d: Character name; Section 25, tag 11. - Person is attacking (shared with $02.68bf, monster is attacking). - $02.64eb-$64f1: Section 25, tag 23. - Person misses (shared with $02.699a, monster misses). - $02.64f3-$6508: Character name; Section 26, tag 08. - Person defends. - $02.65e3-$65f2: Numeric output; Section 25, tag 07. - Combat damage inflicted upon enemy? - May wish to sequence this, from number [hp damage inflicted] to [inflicted] number [hp damage]. - $02.6663-$6669: Section 25, tag 05. - Enemy defeated. - $02.66e4-$66ea: Section 24, tag 26. - Level increased. - $02.670b-$671f: Section 25, tag 00; numeric output; Section 25, tag 12. - Experience gain. - [キャラバンは ] numeric output [ポイントの けいけんちをえた] - Patched version has plurality issues. - $02.6785-$67B5: Section 25, tag 00; gold-amount output; Section 25, tag 19. - Money gain. - [キャラバンは ] gold amount output [を てにいれた] - $02.6829-$683a: Section 25, tag 00; Item name; Section 25, tag 19. - Item gain. - [キャラバンは ] item name [を てにいれた] - $02.68bf-$68cd: Monster name; Section 25, tag 11. - Monster is attacking (shared with $02.6468, person is attacking). - $02.6938-$695d: Character name; Section 25, tag 01; numeric output; Section 25, tag 16. - Person receives damage. - Character name [は ] numeric output [ポイントの きずをおった] - Patched version has line-wrap and plurality issues. - $02.699a-$69a0: Section 25, tag 23. - Monster misses (shared with $02.64eb, person misses). - $02.69a2-$69b7: Character name; Section 25, tag 09. - Person knocked unconscious. - $02.6a25-$6a2c: Section 24, tag 27-28. - Critical hit messages, for both characters and monsters. - $02.6d6a-$6d70: Section 24, tag 25. - Magic sealed when ??? - $02.6da9-$6daf: Section 24, tag 18. - Character doesn't know magic. - $02.6e45-$6e4b: Section 24, tag 01. - Not enough MP. - Many other uses of this one. - $02.6ed3-$6ed9: Section 24, tag 19. - Trying to select an item to use for a character with no inventory. - $02.719a-$71a0: Section 25, tag 10. - Total party wipe, displays in very small text window. - This window, like for $71d2 and $71f6 is $05-$0e-$16-$04 (fourteen characters by one line), but is configured inline, so its geometry should be adjustable without breaking anything else. - $02.71d2-$71d8: Section 25, tag 15. - Enemies destroyed, displays in very small text window. - This window, like for $719a and $71f6 is $05-$0e-$16-$04 (fourteen characters by one line), but is configured inline, so its geometry should be adjustable without breaking anything else. - $02.71f6-$71fc: Section 25, tag 06. - Successfully ran away, displays in a very small text window. - This window, like for $719a and $71d2 is $05-$0e-$16-$04 (fourteen characters by one line), but is configured inline, so its geometry should be adjustable without breaking anything else. - $02.779b-$77a1: Section 25, tag 35. - $02.77aa-$77b0: Section 25, tag 36. - $02.77b9-$77bf: Section 25, tag 38. - $02.77c8-$77ce: Section 25, tag 39. - $02.77dd-$77e3: Section 25, tag 35. - $02.77ec-$77f2: Section 25, tag 37. - $02.77fb-$7801: Section 25, tag 38. - $02.780a-$7810: Section 25, tag 39. - $02.7995-$799b: Section 25, tag 27. - $02.79a8-$79ae: Section 25, tag 28. - $02.79bb-$79c1: Section 25, tag 29. - $02.79ce-$79d4: Section 25, tag 30. - $02.79e1-$79e7: Section 25, tag 31. - $02.7a32-$7a38: Monster name. - $02.7a5d-$7a63: Section 25, tag 27. - $02.7a70-$7a76: Section 25, tag 28. - $02.7a87-$7abd: Section 25, tag 29. - $02.7a90-$7a96: Section 25, tag 30. - $02.7aa7-$7aad: Section 25, tag 30. - $02.7ab0-$7ab6: Section 25, tag 31. - $02.7ae6-$7aec: Spell name. - $02.7b17-$7b1d: Spell name. - $02.7b5e-$7b64: Item name. - $02.7b8f-$7b95: Item name. - $03.601c-$6021: Fragment var. (02, 03, 04) - $03.603e-$6042: Fragment 05. - $03.604d-$6050: Fragment var. (15?) - $03.6075-$607a: Fragment var. (07, 13, 33?) - $03.608a-$608b: Fragment 08. - $03.6090-$6091: Fragment 41. - $03.6096-$6097: Fragment 62. - $03.6850-$6854: Fragment 48. - $03.68a2-$68a6: Fragment 49. - $03.68c7-$68cb: Fragment 08. - $03.6982-$6986: Fragment 75. - $03.69c0-$69c4: Fragment 87. - $03.6baf-$6bb3: Fragment 10. - $03.6bbf-$6bc3: Fragment 09. - $03.6e2b-$6e35: Character name; Fragment 42; Fragment 91, 92, or 93; Fragment 24. - This is not quite right. It's 93; 24 ("MPが たりない" EOL WFI) or name; 42; numeric; {91,92}; 24. - Character name [は ] numeric output [ポイント HPが かいふくした]/[ポイント MPがかいふくした] EOL WFI - Suggest another new tag [ recovered ], numeric output, then rendering " points of HP/MP" with the EOL. - Complication: Fragments 91 and 92 are Section 24, tags 2 and 15, which have references from banks $45 and $47. - Complication: May need to allocate a new fragment ID for this. - If we can't free up an existing fragment, we'll need to relocate $45.70c6 in order to make room. - $03.714e-$7150: Fragment var. (54?) - $03.7197-$71a0: Fragment 93; Fragment 24. - $03.7288-$728c: Fragment 20. - $03.729d-$72b2: Numeric output; Fragment 75; Fragment 17. - This is "<nnn>G になりますが よろしいですか?", used by both merchants and inkeepers for confirming any transaction amount (buying, selling, or taking a room overnight). - We can wedge a prefix fragment in here by changing $03.7298 LDA #$00 / JSR _open_indexed_window to load the fragment id and call _open_display_indexed_message. - Problem: There's not /enough/ room here to have different dialogue per use-case (necessary for natural English), and we need to find a way to determine which use-case actually applies. - There are only two call sites to $03.7298, one of which is via the menuing function pointers. - $03.72d8-$72dc: Fragment 21. - $03.72f5-$72f9: Fragment 22. - $03.73eb-$73ed: Character name. - $03.7455-$745b: Section 26, tag 04. - $03.746a-$7470: Section 26, tag 05. - $03.747f-$7485: Section 26, tag 07. - $03.7535-$7539: Fragment 14. - $03.75f0-$75f4: Fragment 75. - $03.776d-$7773: Section var., tag var. (menu window contents?) - $03.7915-$7918: Fragment var. (11, 32, 39, 52, 59?) - $03.7a92-$7a97: Fragment var. (06, 12, 35, 40, 53, 60?) - Two use-cases for 53 ($35) that may need to be split, and this array ($03.60d0) is duplicated as $45.72e4. - $03.7b74-$7b9b: Character name or item name or spell name; Fragment 42; Fragment var.; Fragment 24. (34, 47, 56, 58, 88, 95?) - $03.7b9d-$7b9f: Fragment var. (unreferenced ??) - $03.7ba8-$7bdb: Character name; Fragment 42; item name or spell name; Fragment 44; Character name; Fragment 43 or fragment 97; Fragment 96; Fragment var.; Fragment 24. (45, 46, 57, 89, 98?) - Name [は ] item-or-spell [を ] name {[に ]|[から](with うけとった only)} {[わたした]|[わたしても いみがない]|[つかった]|[のませた]|[うけとった]} WFI. - [から] [うけとった] is used for Give /from/ an unconscious party member. - $03.7be3-$???: Character name; Fragment 42; ??? (A on entry to $03.7bdd) ??? Multiple entry points, see $03.7c0a. - Entry point $03.7bdd has call sites at $03.6b7b (a=61), $03.6dcf (any of 68, 57, 66, 69, 70, 71, 72, 73), $03.6f24 (a=67, coffee use, something with Omar?), $03.6f37 (a=66, coffee use on self), $03.718f (a=82). - Name [は ] - Fall through to $03.7c0a entry point case for X being 0. - Entry point $03.7c0a has call sites $03.68c1(x=0), $03.6977(x=2). - Only called with A (the variable tag) as 76 ($4c), thus a search result. - X will be either 0 or 2 on entry. If it is 0 there is additional text. - Item-or-spell - [を ] var. - If menu command is not 5 (cast magic), WFI. - $04.6015-$6018: Fragment 00. - $04.62a8-$62ac: Fragment 01. - $04.62bb-$62be: Fragment 00. - $04.7a31-$7a35: Section var., tag var. (map2 weirdness) - $08.7a2e-$7a34: Section 11, tag 18. - $08.7a4a-$7a50: Section 11, tag 19. - $12.7601-$7607: Section 22, tag 02. - $12.768b-$7691: Section 22, tag 60. - $12.7787-$778e: Section 20, tag var. (01-03, in order) - $12.77c1-$77c8: Section 19, tag var. (01-07, in order) - $12.7806-$7839: Section 19, tag var. (10-13, in order) - ??? bank 13 goes here ??? - $43.7847-$784d: Section 25, tag 27. - $43.7881-$7887: Section 25, tag 28. - $43.78bf-$78c5: Section 25, tag 29. - $43.78f4-$78fa: Section 25, tag 30. - $43.7932-$7938: Section 25, tag 30. - $43.7967-$796d: Section 25, tag 31. - $43.7dd0-$7ddf: Monster name; Section 25, tag 02. - $45.71a2-$71ac: Section 00, tag var. ($2f5e + 10?) - $45.72c6-$72cb: Section 28, tag var. - $45.72d6-$72db: Fragment var. (06, 12, 35, 40, 53, 60) - Two use-cases for 53 ($35) that may need to be split, and this array ($45.72e4) is duplicated as $03.60d0. - $45.72eb-$7316: Character name; Section 25, tag 01; spell name; Section 25, tag 03. - $45.7368-$736e: Section 24, tag 01. - $45.739e-$73a4: Section 24, tag 24. - $45.7477-$7487: Character name; Section 25, tag 01; numeric output; Section 24, tag 02. - $45.7489-$7487: Section 24, tag 05. - $45.74ee-$74f4: Section 24, tag 05. - $45.7574-$7597: Character name; Section 25, tag 01; numeric output; Section 24, tag 03. - $45.76a3-$76cd: Monster name; Section 24, tag 08;{numeric output; Section 24, tag 07|Section 24, tag 09}. - $45.76e2-$76e8: Section 24, tag 05. - $45.7741-$775d: Monster name; Section 25, tag 01; numeric output; Section 24, tag 06. - $45.77e3-$77f1: Monster name; Section 24, tag 10. - $45.77f3-$7801: Monster name; Section 24, tag 12. - $45.7804-$7811: Monster name; Section 24, tag 11. - $45.7819-$782b: Character name; Section 25, tag 01 (common fragment, used by $45.7477, $45.7c21, $45.7cab, $45.7d2d, $45.7daf, $45.7e2e) - $45.7865-$7890: Character name; Section 25, tag 01; item name; Section 24, tag 14. - $45.78cb-$78d1: Section 24, tag 05. - $45.7930-$7936: Section 24, tag 33. - $45.795d-$7963: Section 24, tag 34. - $45.7965-$796b: Section 24, tag 20. - $45.7aa6-$7aac: Section 24, tag 21. - $45.7ae0-$7ae6: Section 24, tag 22. - $45.7af5-$7afb: Section 24, tag 23. - $45.7bb9-$7bbf: Section 24, tag 05. - $45.7c21-$7c31: Character name; Section 25, tag 01; numeric output; Section 24, tag 02. - $45.7cab-$7cbb: Character name; Section 25, tag 01; numeric output; Section 24, tag 15. - $45.7d2d-$7d3d: Character name; Section 25, tag 01; numeric output; Section 24, tag 16. - $45.7daf-$7dbf: Character name; Section 25, tag 01; numeric output; Section 24, tag 03. - $45.7e2e-$7e3e: Character name; Section 25, tag 01; numeric output; Section 24, tag 17. - $45.7e8b-$7e91: Section 24, tag 20. - $47.7020-$7024: Fragment 30. - $47.7035-$703e: Fragment 16; Fragment 77. - $47.7087-$708f: Fragment var. (18, 37?) - $47.70a4-$70ac: Fragment var. (23, 38?) - $47.70ec-$70f2: Fragment var. (28, ?, 27, 26, 25?) - $47.7114-$711d: Fragment 84; Fragment 24. - $47.71a7-$71ab: Fragment 81. - $47.7213-$7217: Fragment 79. - $47.7232-$7236: Fragment 80. - $47.7353-$7359: Section 25, tag 32. - $47.7418-$7430: Item-or-spell name; Fragment 42; Item or spell name; Fragment 43; Fragment 94. - $47.75b2-$75b6: Fragment 25. (followed immediately by $47.75be, which has other entry flows) - $47.75be-$75c2: Fragment 36. - $47.75cd-$75d1: Fragment 83. - $47.7630-$7634: Fragment 86. - $47.76cf-$76d5: Section 09, tag 06. - $47.7add-$7b65: Monster name; Section 25, tag 01; spell name; Section 25, tag 03; {Section 24, tag 01|Section 24, tag 24|nothing}. - $47.7c63-$7d2e: Monster name; Section 25, tag 01; numeric output; Section 24, tag 02. - $47.7dbd-$7dd9: Monster name; Section 25, tag 01; numeric output; Section 24, tag 03. - $47.7e96-$7ec4: Character name; Section 24, tag 08; {numeric output; Section 24, tag 07|Section 24, tag 09}. - $47.7f22-$7f34: Character name; Section 24, tag 10. - $47.7f39-$7f4b: Character name; Section 24, tag 12. - $47.7f50-$7f62: Character name; Section 24, tag 13.
Game map encoding
Map data appears to be encoded in terms of 8x8 pixel graphics tiles, rather than 16x16 pixel metatiles. There appear to be three sets of maps, each with their own tileset.
The first map area located includes the Baghdad royal palace and three other areas. It takes up all of bank $42 and the first half of bank $23, as a 256x48 tile array. Areas packed into the same map appear to have a separation of just over half a display width so that the player will be forced to leave the map before an adjacent area becomes visible. The map wraps horizontally, but areas vertically outside the map region are provided from some other source, possibly a fixed tile fill rule.
Map set zero appears to be stored in banks $18-$1f, taking up the entirety of these banks as a 256x256 tile array. This is the world map. Its tileset is in bank $09, and its tile highbyte is $73 (tiles in VRAM $3000-$3fff, palette $7). Palette data appears to be stored in $05.1ce0-$1cff.
Map set one appears to be stored in banks $40-$47, though the second half of every second bank is given to be code and other information rather than map data, therefore a set of four 256x48 stripes out of a 256x256 tile array, aligned to 64-tile boundaries vertically. This is a set of "outdoor" maps, being palaces, cities, towns, oases, and the like. Its tileset is in bank $0a, and its tile highbyte is $13 (tiles in VRAM $3000-$3fff, palette $1). Palette data appears to be stored in $05.1c20-$1c3f.
Map set two appears to be stored in banks $48-$4f, taking up the entirety of these banks as a 256x256 tile array. This is a set of sixteen "cave" or "indoor" maps, aligned as a 4x4 grid of 64x64 tile segments. Its tileset is in bank $0b, and its tile highbyte is $23 (tiles in VRAM $3000-$3fff, palette $2). Palette data appears to be stored in $05.1c40-$1c5f.
Open questions:
- How does the game know that certain tiles cannot be moved onto/through?
- After a move has been input, the tiles that would be moved onto are read back from VRAM and checked against various lists for possible special handling.
- How does the game know that certain tiles cause an exit to the world map, or to another dungeon area?
- See previous question.
Game text encoding
Script data is stored in banks $14-$17.
The font tileset
The font tileset is stored in bank $08, along with bounding-box characters, possibly other graphics, some code, and what looks to be some other data not yet identified.
Tiles run from $6000 to $75ff ($8000 to $85ff as mapped for loading the tile data). Each tile is $20 bytes long, so there are 176 ($b0) tiles in the font set. There is a full set of kana, plus arabic digits, plus majuscule latin characters. No minuscule latin characters, however.
00-0f: あいうえおかきくけこさしすせそ 10-1f: たちつてとなにぬねのはひふへほま 20-2f: みむめもやゆよらりるれろわをんっ 30-3f: ゃゅょアイウエオカキクケコサシス 40-4f: セソタチツテトナニヌネノハヒフヘ 50-5f: ホマミムメモヤユヨラリルレロワヲ 60-6f: ンッャュョァィゥェォー〜゛゜、。 70-7f: 0123456789ABCDEF 80-8f: GHIJKLMNOPQRSTUV 90-9f: WXYZ!?…「」/
and then we start getting into filled arrows, asterisks, hearts, a space (distinct from the 00 spot, which is apparently a placeholder), what might be a sword, probably box-drawing characters, and I'm not sure what else. The actual in-game set might run out at $9f being a space, but doesn't help as far as voiced/plosive marks go (and confirmed, the game script uses through $9f except for $9c, and doesn't use $a0-$f8).
9a: a period. 9b: filled downward triangle. 9c: filled rightward triangle. 9d: asterisk. 9e: heart. 9f: space.
はやくおきなさい (said early in the game) is 1a 24 08 05 07 15 0b 02 by this font layout. That said, voicing and plosive marks are not embedded in this text, they are added by another process, which may not map the lower codes 1:1. But we get a hit at bank $14, offset $008a. And a secondary hit at bank $14, offset $00a7.
00028270 96 96 fd ff fa 70 72 3e 68 59 3d 6c 6a 46 6c 97 |.....pr>hY=ljFl.| 00028280 3e 60 46 6c 4c 6c 61 46 6c 94 1a 24 08 05 07 15 |>`FlLlaFl..$....| 00028290 0b 02 94 98 fd ff fa 70 73 1a 1a 97 3e 60 46 6c |.......ps...>`Fl|
We see, starting at 2828a, 1a 24 08 05 07 15 0b 02 94 98 fd ff fa. This would be はやくおきなさい!」 and fd ff fa (possibly a boundary sequence). We then have 70 73 1a 1a 97, or 03はは「. Something odd there with the digits, but clearly the next bit of script text.
Looking backwards, we find at 28272, fd ff fa 70 72 3e 68 59 3d 6c 6a 46 6c 97, our boundary sequence again and 02シェラサ゛ート゛「, which tells us something about the script encoding: there's logic to recognize $6c and $6d and handle them specially (putting them above the previous character).
Moving onwards, we have 3e 60 46 6c 4c 6c 61 46 6c 94, which decodes as シント゛ハ゛ット゛!, bringing us to 2828a where we started.
There appears to be some sort of pointer table at the start of bank $14, possibly as many as 32 ($20) 16-bit pointers to within the script banks.
Observed commands:
- ff: end of text.
- fe: end of line (move to start of next line).
- fd: wait for input (any button press) with blinking down-triangle prompt.
- fc: re-spread text window?
- fb: section marker(?) (present at the start of every section after the first, in ascending order from 01 to 31, except for 16, 23, and 28.)
- fa: entry start marker (followed by two digits, corresponding to a packed BCD entry ID).
- f9: emit four spaces (seems to appear in a very small area of the script).
Bytes fa and fb appear in the script stream preceding pairs of digits (7x bytes), probably some kind of start marker. Byte fb appears to be used when addressed by the pointer table at the start of bank $14. There is, as yet, no evidence of any semantics associated with byte $fb.
Observed script loci
The "attract sequence" runs through section zero ($14.8040, from $14.0000) for entries 10 through 15 inclusive.
A new game starts with section zero entry 01, drops to a castle scene. Entrance guards are entry 07, attendants at mid-corridor are entry 06, attendants at top of corridor and vizier to left are entry entry 08, king(?) is entry 09, crowned swordsperson to the right of the throne is entry 02, causing a scene change followed by entry 03, then a step south (off the otherwise-inaccessible bed).
This leaves section zero entries 00 (broken, lacks a terminator), 04 ("password is in the wrong"), and 05 ("please enter password"). The only thing saving 05 is that the use of を calls for object rather than location (which would've been に).
How combat works
Combat is divided into rounds, where commands for all party members are input, then party members and monsters take turns performing their designated actions.
The order of turns within a round is controlled by the "SP" (speed) attribute of each character and monster. This is a strict priority order by descending SP value.
For party members, the action is specified at the start of the turn and then interpreted.
- The "attack" command will have no effect if the target monster is killed before the attacking character's turn. The chance of missing depends on the relative SP attributes of the character and target, being 1/4, 1/8, 1/16, or never missing. The chance of a hit being a critical hit is 1/16. Actual damage dealt appears to be determined by the character's AT (attack) attribute and the target's DF (defense) attribute.
- The precise relation of SP attributes to determine each odds bracket for missing is not yet determined.
- The precise relation of AT/DF attributes to determine damage dealt and how this may be affected by a critical hit is not yet determined.
- The "magic" command has not been well investigated yet.
- The "item" command has not been well investigated yet.
- The "defend" command triples a character's DF (defense) attribute, up to a cap of 255, until the end of the round.
- This implies that the slower a character is (acting later in the round, thus not being protected from earlier attacks), and the more DF they have above 85 (one third of the DF cap), the less useful defending is as an action.
The logic for monsters is not well investigated yet, but the AT/DF attribute relation for determining damage is known to be the same as for party members, and there is some monster-specific data that is only non-zero when a monster has MP.
Post-combat Rewards
There are three possible post-combat rewards.
- The first is experience, which is determined by summing the experience rewards of each opponent, with the caveat that if the sum exceeds 255 it is clamped to 250.
- The second is monetary, which is a straight sum from all opponents (this cannot exceed 4000G, given the existing monster data, so 16-bit overflow is not a concern).
- The third is a possible item drop, which only occurs if a party member has an open inventory slot, at least one opponent has a non-zero droppable item id, and the low four bits of an RNG byte are zero (so, a 1/16 chance), in which case the item specified by the leftmost candidate opponent (that is, the leftmost opponent with a non-zero droppable item id) will be dropped.
Monster Data
There are $60 (96) monsters in the game. Sprite layout data is in bank $05, $8000-$8bff, 32 ($20) bytes per monster. Sprite bitmaps are in banks $0f-$11 and loaded to VRAM $3000-$5fff. The monster combat data is in bank $05, $8c00-$907f, 12 ($0c) bytes per monster.
Each monster record contains 12 bytes:
- 0: The name tag, in Section 30.
- 1-2: The hit points (HP), as a little-endian value.
- 3: The magic points (MP).
- 4: The attack power (AT).
- 5: The defense power (DF).
- 6: The speed (SP).
- 7: ??? only ever zero when MP is zero, some evidence that it's high and low nybbles ??
- 8-9: Gold, as a little-endian value.
- 10 ($0a): Experience.
- 11 ($0b): Droppable item ID, in Section 31.
| mon | HP | MP | AT | DF | SP | ?? | Gold | Exp | Item | |-----+------+----+-----+-----+----+-----+------+-----+------| | 01 | 5000 | 0 | 200 | 94 | 40 | $00 | 0 | 0 | 0 | | 02 | 1500 | 30 | 160 | 80 | 35 | $35 | 0 | 50 | 20 | | 03 | 37 | 0 | 24 | 3 | 12 | $00 | 7 | 6 | 25 | | 04 | 99 | 15 | 52 | 12 | 20 | $31 | 29 | 11 | 43 | | 05 | 47 | 15 | 82 | 45 | 25 | $21 | 81 | 9 | 52 | | 06 | 58 | 15 | 30 | 5 | 18 | $d1 | 15 | 6 | 4 | | 07 | 190 | 30 | 108 | 40 | 68 | $89 | 20 | 10 | 4 | | 08 | 260 | 99 | 115 | 65 | 73 | $39 | 0 | 40 | 20 | | 09 | 30 | 15 | 29 | 14 | 28 | $24 | 27 | 7 | 43 | | 10 | 360 | 90 | 98 | 22 | 26 | $a5 | 40 | 14 | 13 | | 11 | 180 | 80 | 105 | 76 | 43 | $d5 | 0 | 25 | 19 | | 12 | 800 | 10 | 150 | 82 | 35 | $1c | 0 | 0 | 0 | | 13 | 59 | 15 | 31 | 8 | 30 | $31 | 19 | 7 | 0 | | 14 | 80 | 15 | 37 | 8 | 21 | $71 | 17 | 8 | 14 | | 15 | 180 | 15 | 82 | 24 | 30 | $71 | 103 | 18 | 0 | | 16 | 24 | 15 | 23 | 6 | 25 | $18 | 17 | 2 | 43 | | 17 | 60 | 15 | 49 | 17 | 60 | $19 | 32 | 10 | 0 | | 18 | 50 | 15 | 90 | 48 | 66 | $45 | 125 | 14 | 36 | | 19 | 24 | 15 | 29 | 17 | 19 | $3c | 80 | 2 | 0 | | 20 | 6 | 0 | 6 | 0 | 4 | $00 | 5 | 1 | 0 | | 21 | 8 | 0 | 7 | 0 | 4 | $00 | 6 | 1 | 0 | | 22 | 43 | 15 | 29 | 11 | 34 | $34 | 0 | 6 | 34 | | 23 | 76 | 15 | 65 | 20 | 22 | $35 | 55 | 9 | 34 | | 24 | 63 | 16 | 0 | 60 | 54 | $f5 | 189 | 25 | 28 | | 25 | 65 | 15 | 34 | 2 | 44 | $29 | 18 | 9 | 43 | | 26 | 100 | 15 | 96 | 37 | 66 | $b9 | 88 | 20 | 44 | | 27 | 44 | 15 | 35 | 12 | 40 | $4c | 19 | 9 | 0 | | 28 | 120 | 15 | 0 | 31 | 50 | $f7 | 96 | 12 | 51 | | 29 | 214 | 40 | 120 | 80 | 80 | $5c | 0 | 45 | 1 | | 30 | 50 | 15 | 19 | 0 | 12 | $41 | 14 | 4 | 2 | | 31 | 10 | 0 | 7 | 1 | 4 | $00 | 6 | 2 | 0 | | 32 | 40 | 15 | 27 | 7 | 14 | $29 | 35 | 9 | 0 | | 33 | 26 | 0 | 12 | 1 | 10 | $00 | 8 | 2 | 3 | | 34 | 211 | 0 | 98 | 49 | 36 | $00 | 2 | 23 | 31 | | 35 | 320 | 0 | 95 | 14 | 36 | $00 | 0 | 10 | 20 | | 36 | 210 | 15 | 77 | 11 | 27 | $35 | 77 | 17 | 27 | | 37 | 66 | 0 | 24 | 0 | 6 | $00 | 15 | 6 | 4 | | 38 | 320 | 35 | 120 | 25 | 34 | $c5 | 10 | 26 | 39 | | 39 | 22 | 15 | 27 | 13 | 7 | $b8 | 18 | 6 | 0 | | 40 | 44 | 15 | 27 | 5 | 8 | $28 | 33 | 2 | 0 | | 41 | 124 | 15 | 78 | 31 | 27 | $68 | 72 | 12 | 0 | | 42 | 50 | 35 | 31 | 8 | 6 | $39 | 1 | 8 | 0 | | 43 | 70 | 35 | 110 | 100 | 50 | $49 | 100 | 40 | 24 | | 44 | 200 | 57 | 93 | 40 | 34 | $a9 | 0 | 15 | 3 | | 45 | 45 | 15 | 26 | 5 | 6 | $28 | 12 | 6 | 13 | | 46 | 90 | 15 | 72 | 30 | 17 | $88 | 83 | 13 | 44 | | 47 | 213 | 15 | 88 | 0 | 27 | $d8 | 95 | 13 | 26 | | 48 | 31 | 45 | 32 | 14 | 18 | $49 | 27 | 5 | 0 | | 49 | 62 | 15 | 41 | 14 | 19 | $89 | 49 | 8 | 41 | | 50 | 500 | 16 | 112 | 0 | 31 | $9c | 80 | 20 | 3 | | 51 | 620 | 15 | 105 | 45 | 28 | $67 | 1000 | 0 | 0 | | 52 | 100 | 33 | 46 | 8 | 38 | $c1 | 11 | 6 | 14 | | 53 | 110 | 15 | 69 | 36 | 22 | $31 | 44 | 5 | 50 | | 54 | 9 | 20 | 8 | 3 | 5 | $19 | 7 | 3 | 2 | | 55 | 49 | 15 | 28 | 6 | 17 | $59 | 40 | 1 | 16 | | 56 | 140 | 15 | 73 | 25 | 27 | $87 | 90 | 11 | 0 | | 57 | 10 | 20 | 9 | 2 | 5 | $19 | 8 | 3 | 43 | | 58 | 130 | 15 | 62 | 14 | 22 | $39 | 31 | 8 | 0 | | 59 | 400 | 77 | 90 | 0 | 36 | $b1 | 0 | 35 | 20 | | 60 | 19 | 20 | 16 | 2 | 10 | $38 | 5 | 4 | 13 | | 61 | 19 | 25 | 23 | 10 | 13 | $48 | 6 | 4 | 33 | | 62 | 42 | 35 | 91 | 91 | 70 | $c8 | 300 | 35 | 45 | | 63 | 70 | 15 | 66 | 40 | 24 | $37 | 64 | 8 | 16 | | 64 | 398 | 48 | 122 | 17 | 37 | $a5 | 87 | 29 | 1 | | 65 | 200 | 15 | 98 | 19 | 31 | $25 | 104 | 27 | 24 | | 66 | 36 | 15 | 21 | 6 | 13 | $38 | 11 | 5 | 50 | | 67 | 60 | 15 | 43 | 8 | 15 | $a8 | 42 | 9 | 2 | | 68 | 170 | 40 | 115 | 53 | 30 | $a8 | 57 | 19 | 3 | | 69 | 34 | 15 | 22 | 6 | 15 | $24 | 14 | 7 | 14 | | 70 | 71 | 15 | 0 | 40 | 27 | $f7 | 104 | 15 | 13 | | 71 | 272 | 24 | 102 | 39 | 36 | $d5 | 46 | 17 | 3 | | 72 | 12 | 0 | 8 | 1 | 6 | $00 | 7 | 2 | 4 | | 73 | 19 | 0 | 26 | 9 | 4 | $00 | 13 | 7 | 3 | | 74 | 75 | 15 | 80 | 6 | 27 | $a7 | 96 | 10 | 0 | | 75 | 50 | 15 | 39 | 10 | 18 | $34 | 11 | 10 | 4 | | 76 | 120 | 15 | 44 | 0 | 19 | $b4 | 23 | 9 | 33 | | 77 | 125 | 25 | 95 | 40 | 30 | $87 | 146 | 17 | 26 | | 78 | 20 | 0 | 13 | 4 | 8 | $00 | 1 | 4 | 49 | | 79 | 60 | 0 | 28 | 5 | 17 | $00 | 9 | 4 | 49 | | 80 | 70 | 0 | 28 | 0 | 16 | $00 | 24 | 3 | 27 | | 81 | 81 | 15 | 28 | 2 | 20 | $3c | 22 | 5 | 0 | | 82 | 18 | 15 | 10 | 6 | 9 | $2c | 5 | 3 | 17 | | 83 | 135 | 15 | 118 | 69 | 36 | $3c | 60 | 25 | 20 | | 84 | 25 | 25 | 27 | 11 | 24 | $29 | 18 | 6 | 21 | | 85 | 30 | 15 | 39 | 21 | 19 | $59 | 36 | 7 | 34 | | 86 | 220 | 15 | 73 | 15 | 22 | $39 | 65 | 14 | 27 | | 87 | 505 | 15 | 130 | 70 | 61 | $49 | 0 | 0 | 0 | | 88 | 350 | 0 | 170 | 80 | 20 | $00 | 0 | 50 | 20 | | 89 | 22 | 15 | 22 | 8 | 12 | $31 | 13 | 2 | 14 | | 90 | 74 | 15 | 35 | 5 | 18 | $31 | 14 | 10 | 21 | | 91 | 270 | 15 | 88 | 0 | 29 | $91 | 161 | 23 | 16 | | 92 | 38 | 15 | 26 | 9 | 14 | $39 | 12 | 3 | 33 | | 93 | 240 | 50 | 108 | 23 | 36 | $e5 | 0 | 20 | 3 | | 94 | 370 | 25 | 111 | 9 | 36 | $ec | 0 | 30 | 20 | | 95 | 500 | 40 | 115 | 0 | 36 | $43 | 0 | 50 | 24 | | 96 | 20 | 37 | 20 | 5 | 24 | $39 | 10 | 4 | 21 |
Tile animation
The world map has two groups of four animated tiles. Each group is split into an upper and lower half which use the same set of bitmaps but run through the same sequence of four frames in opposite directions. These are, apparently, water tiles.
The series of tile images is constructed in two areas of RAM ($2700-$27ff and $2800-$28ff) from tiles $12-$13 and $6d-$6e by $08.7dca, and uploading the successive tile images to VRAM is done by $08.7bf7.
Group A is tiles $12-$13 and $22-$23. Group B is tiles $6d-$6e and $7d-$7e. This has implications for tile layout overall.
- Frame 0:
- Group A:
- Tiles $12-$13: $27c0
- Tiles $22-$23: $2700
- Group B:
- Tiles $6d-$6e: $28c0
- Tiles $7d-$7e: $2800
- Group A:
- Frame 1:
- Group A:
- Tiles $12-$13: $2780
- Tiles $22-$23: $2740
- Group B:
- Tiles $6d-$6e: $2880
- Tiles $7d-$7e: $2840
- Group A:
- Frame 2:
- Group A:
- Tiles $12-$13: $2740
- Tiles $22-$23: $2780
- Group B:
- Tiles $6d-$6e: $2840
- Tiles $7d-$7e: $2880
- Group A:
- Frame 3:
- Group A:
- Tiles $12-$13: $2700
- Tiles $22-$23: $27c0
- Group B:
- Tiles $6d-$6e: $2800
- Tiles $7d-$7e: $28c0
- Group A:
Open questions:
- Why do the group A tiles have an even base tile id, and the group B tiles have an odd base tile id?
- How is the water animation done in the castle/town/oasis maps? Are there other animations as well?
- See $41.7972 for the castle/town/oasis map animation setup.
- Is there any animation on the cave/dungeon maps?
Non-combat Menuing
This is anything to do with message speed selection, password entry, shopkeepers, the non-combat command menu... and at least one case of dialogue-based interaction (though the basics of dialogue-based interaction is handled through another mechanism).
Script fragments
There is a table at $45.7000-70c5 of script section-and-tag pairs, referred to by index within the menuing code. In some cases, these are complete texts, in others they are fragments that are concatenated together with other things such as character names in particular patterns.
$00: section 0, tag 5: "パスワードを いれてください" / password entry request $01: section 0, tag 4: "パスワードが ちがいます!!" / invalid password notice $02: section 21, tag 1: "うちでは ぶきを うっています" EOL / weapon store merchant intro $03: section 21, tag 9: "うちでは よろいや かぶとを うっています" EOL / armor store merchant intro $04: section 21, tag 10: "いらっしゃいませ。 うちは よろずや です" EOL / item store merchant intro $05: section 21, tag 7: "ほかに ごようは?" / merchant, when cancelling from goods list? $06: section 21, tag 2: "どれを かいますか?" / merchant, when showing goods to buy? $07: section 21, tag 20: "おかねが たりないようです" WFI / merchant/inkeeper, not enough money when buying? $08: section 21, tag 4: "だれが もちますか?" / merchant, selecting who is buying an item? $09: section 21, tag 5: "これいじょう にもつを もつのは むりのようですが……" WFI / merchant, inventory full when buying? $0a: section 21, tag 6: "ありがとう ございました" WFI / merchant, post-purchase? $0b: section 21, tag 11: "だれが うりますか?" / merchant, selecting person selling an item? $0c: section 21, tag 12: "どれを うりますか?" / merchant, showing inventory to sell? $0d: section 21, tag 13: "その しなものは うちでは あつかっていません" WFI / merchant, trying to sell a plot-critical item? $0e: section 25, tag 33: "ケルビムは ものを もてない" WFI / ??? trying to sell to Cherubim? $0f: section 21, tag 32: "なにも もっていないようですが……" WFI / merchant, trying to sell from empty inventory? $10: section 21, tag 16: "たびのやど キャラバンサライに ようこそ" EOL / inkeeper intro $11: section 21, tag 17: " になりますが よろしいですか?" / merchant/inkeeper quoting a price $12: section 21, tag 18: "パスワードを みますか?" EOL "それとも バックアップしますか?" / inkeeper, saving, with backup RAM $13: section 21, tag 19: "では また きてください" / ??? $14: section 21, tag 20 (again): "おかねが たりないようです" WFI / merchant/inkeeper, not enough money when buying? $15: section 21, tag 21: "それでは おやすみなさい……" / inkeeper, when you pay to stay overnight $16: section 21, tag 22: "おはようございます おでかけの じかんです" EOL / inkeeper, when you wake in the morning $17: section 21, tag 24: "どのぼうけんに バックアップしますか?" / inkeeper, when selecting a backup file $18: section 25, tag 60: WFI / a wait-for-input prompt $19: section 25, tag 61: "バックアップラムが しょきか されていません" EOL / backup not initialized, pt. 1? $1a: section 25, tag 62: "バックアップラムが いっぱいです" WFI / ??? $1b: section 25, tag 63: "バックアップデータが こわれています" EOL / ??? $1c: section 25, tag 78: "そのぼうけんは つかわれていません" WFI / ??? $1d: section 21, tag 23: "きをつけて…………" / ??? $1e: section 18, tag 10: something the father does and says?? $1f: section 25, tag 32: total party wipe message $20: section 25, tag 70: "だれが そうびしますか?" / "equip" command, selecting person to change equipment $21: section 25, tag 71: "それは そうびできません" WFI / ??? $22: section 25, tag 72: "なにも もっていない" / when using Equip, Use, Give, or Drop for someone with no inventory $23: section 25, tag 73: "どれを そうびしますか?" / ??? $24: section 25, tag 82: "しょきか しますか?" / backup not initialized, pt. 2? $25: section 25, tag 80: "どちらを つかいますか?" / continuing, selecting backup or password $26: section 25, tag 81: "どの ぼうけんから はじめますか?" / continuing, selecting backup file $27: section 25, tag 75: "だれが わたしますか?" / "give" command, selecting person to act $28: section 25, tag 76: "どれを わたしますか?" / "give" command, selecting item to give $29: section 25, tag 77: "だれに わたしますか?" / "give" command, selecting recipient $2a: section 25, tag 83: "は " / fragment ??? $2b: section 25, tag 84: "に " / fragment ??? $2c: section 25, tag 85: "を " / fragment ??? $2d: section 25, tag 21: "わたした" / ??? $2e: section 25, tag 86: "わたしても いみがない" / ??? $2f: section 25, tag 34: "これいじょう ものを もてない" / when giving an item to someone with a full inventory $30: section 25, tag 17: "シンドバッドは あたりを しらべてみた" WFI / using the search command $31: section 25, tag 18: "けれども なにも みつからなかった" WFI / when searching finds nothing $32: section 25, tag 14: "つぼの なかから" / ??? $33: section 25, tag 99: "を とりだした" WFI / fragment ??? $34: section 25, tag 88: "だれが つかいますか?" / "use" and "magic" commands, selecting person to act $35: section 25, tag 87: "どれを つかいますか?" / "use" and "magic" commands, selecting item/spell $36: section 25, tag 97: "だれに つかいますか?" / "use" and "magic" commands, selecting recipient (when appropriate) $37: section 25, tag 90: "の まほう" / fragment ??? $38: section 26, tag 0: "まだ まほうを つかえません" / "magic" command, when someone with no spells is selected $39: section 26, tag 34: "つかった" / ??? $3a: section 25, tag 89: "つかえません" / ??? $3b: section 26, tag 1: "だれが すてますか?" / "drop" command, selecting person to act $3c: section 26, tag 2: "どれを すてますか?" / "drop" command, selecting item to drop $3d: section 26, tag 3: "すてた" / ??? "dropped" $3e: section 26, tag 10: "ほんとうに すてますか?" / ??? "really drop?" $3f: section 25, tag 8: "きりょくが じゅうじつした" EOL / ??? $40: section 26, tag 11: "まりょくが あがった" / ??? $41: section 26, tag 6: "EX" / ??? $42: section 26, tag 12: "のんだ" / ??? $43: section 26, tag 13: "オマールに のませた" / ??? $44: section 26, tag 14: "バツータに わたした" / ??? $45: section 26, tag 15: "マスルールに わたした" / ??? $46: section 26, tag 16: "さいだんに おさめた" / when using Enlil's Ball on the pyramid $47: section 26, tag 17: "ダライオスに わたした" / ??? $48: section 26, tag 18: "だんろに なげこんだ" / ??? $49: section 26, tag 19: "ハサンに わたした" / ??? $4a: section 26, tag 6 (again): " EX" / ??? $4b: section 26, tag 20: "G" / ??? $4c: section 25, tag 13: "みつけた" / when searching finds something, after the item name and tag 85 (indexed $2c) $4d: section 21, tag 33: "きょうは どんな ごようですか?" / all merchants, after intro line $4e: section 26, tag 21: "ですね?" / ??? $4f: section 26, tag 22: "どれを けしますか?" / ??? $50: section 26, tag 23: "よろしいですか?" / ??? $51: section 26, tag 28: "どうしますか?" / ??? $52: section 26, tag 29: "つかった" WFI " しかし とびらは さびついて ひらかなかった" WFI / ??? $53: section 26, tag 30: "しょきかが おわりました" / shown after initializing backup unit? $54: section 21, tag 34: "メモを とってください" / inkeeper, when showing the save password $55: section 1, tag 52: When you give Omar coffee in Baghdad $56: section 26, tag 35: "もじひょうじの はやさを えらんでください" / ??? $57: section 26, tag 39: "…プーン…つぼのなかから くさーい においがしてきた" EOL "みんな いちもくさんに にげだした!!" / searching a particular jar in the ruins of Babylon, sending the party outside $58: section 26, tag 9: "すてられません" / "may not be dropped" from "<item>は may not be dropped" WFI (see $03.7b74) $59: section 26, tag 40: "のませた" / ??? $5a: section 24, tag 2: "ポイント HPが かいふくした" EOL / ??? $5b: section 24, tag 15: "ポイント MPがかいふくした" EOL / ??? $5c: section 24, tag 5: "しかし なにもおこらなかった" EOL / ??? $5d: section 24, tag 1: "MPが たりない" EOL / ??? $5e: section 26, tag 42: "かわった" WFI / "changed/became", from using a "fox leaf/blade", "fox-leafは <item>に changed/became" $5f: section 26, tag 43: "きを うしなっている" / "has lost consciousness", from "<person>は has lost consciousness" WFI (see $03.794a), poss. other uses. $60: section 26, tag 45: EOL / ??? $61: section 26, tag 46: "から" / ??? $62: section 26, tag 47: "うけとった" / ???
These are descriptions for menus that always have the same items and layout, which is most menus.
The pointer array is from $03.6231-$6250, and the data itself runs from $03.6251-$62f0.
Each record consists of a series of script section-and-tag pairs for rendering the elements, a $ff byte to terminate the list, a byte for the number of entries in the menu, the layout template ($03.62f1), and the interaction template ($03.76f1).
- $00: Two items, layout $00, interaction $00. - section 25, tag 40: "はい" - section 25, tag 41: "いいえ" - $01: Two items, layout $00, interaction $00. - Inkeeper menu. - section 25, tag 43: "とまる" (to lodge, to stay (over)) - section 25, tag 42: "きおく" (memory) - $02: Two items, layout $00, interaction $00. - Shopkeeper primary menu. - section 25, tag 45: "ものをかう" (buy things) - section 25, tag 44: "ものをうる" (sell things) - $03: Two items, layout $05, interaction $12 - Save (and load?) mechanism menu. - section 25, tag 52: "バックアップ" (backup) - section 25, tag 51: "パスワード" (password) - $04: Six items, layout $07, interaction $14 - Main non-combat menu. - section 25, tag 66: "そうび" (equip) - section 25, tag 64: "さがす" (search) - section 25, tag 68: "つかう" (use) - section 25, tag 38: "まほう" (magic) - section 25, tag 67: "わたす" (give) - section 25, tag 98: "すてる" (drop) - $05: Three items, layout $06, interaction $13 - Backup file selection menu. - section 25, tag 53: "ぼうけん1 EX" - section 25, tag 54: "ぼうけん2 EX" - section 25, tag 55: "ぼうけん3 EX" - $06: Seven items, layout $09, interaction $1d - Party member status window during "equip" operation. - section 26, tag 31: "AT" - section 26, tag 32: "DF" - section 26, tag 41: "SP" - section 26, tag 04: "HP" - section 26, tag 07: "MAX" - section 26, tag 05: "MP" - section 26, tag 07: "MAX" - $07: Four items, layout $0a, interaction $1e - Caravan status window when opening main menu. - section 26, tag 20: "G" - section 26, tag 33: "LV" - section 26, tag 06: "EX" - section 26, tag 44: "LUP" - $08: Two items, layout $0b, interaction $1f - section 25, tag 40: "はい" - section 25, tag 41: "いいえ" - $09: Two items, layout $05, interaction $12 - section 25, tag 56: "バグワジ" - section 25, tag 57: "ウガンジョ" - $0a: Two items, layout $05, interaction $12 - section 25, tag 58: "バスラ" - section 25, tag 56: "バグワジ" - $0b: Three items, layout $0c, interaction $20 - section 25, tag 58: "バスラ" - section 25, tag 57: "ウガンジョ" - section 25, tag 59: "ヤクシュニー" - $0c: Four items, layout $0d, interaction $22 - ??? poss. asking what to do if the backup RAM is full? - section 26, tag 26: "けす" (erase?) - section 26, tag 27: "やめる" (stop / give up?) - section 26, tag 24: "すすむ" (move ahead / advance?) - section 26, tag 25: "もどる" (return?) - $0d: Three items, layout $01, interaction $02 - Message-speed selection menu (press SELECT). - section 26, tag 36: "はやい" (fast) - section 26, tag 37: "ふつう" - section 26, tag 38: "おそい" (slow) - $0e: Two items, layout $0d, interaction $22 - section 25, tag 40: "はい" - section 25, tag 41: "いいえ" - $0f: Two items, layout $0e, interaction $23 - section 25, tag 40: "はい" - section 25, tag 41: "いいえ"
Menu interaction templates
These are an array of five-byte structures from $03.63ab-$645e. They specify which window geometry to use and the menu cursor behavior (row height, column width, number of rows, and number of columns). There are thirty-six of these, indices from $00 through $23.
Menu layout templates
These are vectors of X,Y coordinate pairs for displaying menu items.
The pointer array is from $03.62f1-$630e, and the data itself runs from $03.630f-$638c.
Window geometries
These are all X,Y,W,H for the window borders. In five cases there are two bytes of additional data, the initial text cursor position as an X,Y pair. In the other cases, the first two bytes of the next record (or next data structure, in the case of the last record) are used as a text cursor position, but presumably overridden by other logic such as the menu layout template.
The pointer array (necessary, as the records are variable size) is from $03.6119-$6172, and the data itself runs from $03.6173-$6230.
Open questions:
- [X] How does the game know when to parse for an initial text cursor position?
- Turns out that it always parses for the initial position. Presumably, then, most of the call sites override that default (which is often read from the top-left coordinates of the next window).
- [ ] How does the game know where to put the initial text cursor position when one is implicitly defined?
00: 01 14 1E 08 02 16 -- shopkeeper/message-speed/menu-result dialogue box 01: 07 01 12 05 09 03 -- password entry message box 02: 14 02 09 03 17 03 -- gold status window? 03: 15 13 0A 06 04: 15 13 0A 08 05: 15 13 0A 0A 06: 18 14 07 05 07: 02 02 0C 08 -- main command menu 08: 14 05 09 05 -- shopkeeper buy/sell/sleep/save/yes/no menu? 09: 14 0A 0A 06 -- right-side 2-character selector? 0a: 14 0A 0A 08 -- right-side 3-character selector? 0b: 14 0A 0A 0A -- right-side 4-character selector? 0c: 02 0A 0A 06 -- left-side 2-character selector? 0d: 02 0A 0A 08 -- left-side 3-character selector? 0e: 02 0A 0A 0A -- left-side 4-character selector? 0f: 01 02 11 04 -- sale item window, one item? 10: 01 02 11 06 -- sale item window, two items? 11: 01 02 11 08 -- sale item window, three items? 12: 01 02 11 0A -- sale item window, four items? 13: 01 02 11 0C -- sale item window, five items? 14: 01 02 11 0E -- sale item window, six items? 15: 01 02 11 10 -- sale item window, seven items? 16: 01 02 11 12 -- sale item window, eight items? 17: 14 05 0A 06 -- backup/password choice box 18: 0A 0B 14 09 19: 08 0A 17 0A 0A 0C 1a: 12 02 0D 04 -- item-select window, one item? 1b: 12 02 0D 06 -- item-select window, two items? 1c: 12 02 0D 08 -- item-select window, three items? 1d: 12 02 0D 0A -- item-select window, four items? 1e: 12 02 0D 0C -- item-select window, five items? 1f: 12 02 0D 0E -- item-select window, six items? 20: 12 02 0D 10 -- item-select window, seven items? 21: 12 02 0D 12 -- item-select window, eight items? 22: 02 0A 0C 0A 23: 02 0A 0C 08 -- gold/experience status window? 24: 02 12 1D 09 -- bottom party status window? 25: 14 05 0A 08 26: 0D 01 14 12 27: 01 09 0C 0A 28: 02 02 0C 12 29: 04 09 1A 12 2a: 04 04 0E 05 06 06 2b: 12 04 0C 05 2c: 14 0D 0A 05
References to banks $40-$4f
In order to expand the ROM and have it work on an everdrive on real hardware, rather than just under emulation (never trust an emulator!), we need to patch every reference to banks $40-$4f to instead point to $20-$2f. But where are all of the references, and how do we know that we got them all?
- Bank $00: No literal references. Possibly one reference at $fbc8, loaded from $2e at $fbc6. - Bank $01: Multiple references. - $444a, $41. - $44b1, $41. - $44bb, $43. - $44c5, $45. - $44cf, $47. - Bank $02: No references. - Bank $03: Multiple references. - $6f48: $45. - $6f9e: $45. - $76e5: $45. - Bank $04: No references. - Banks $05-$06: Appear to be entirely data, no references. - Bank $07: No references. - Bank $08: No references. - Banks $09-$0b: Entirely graphics tile data, no references. - Banks $0c-$11: Unknown. - Bank $12: Dynamic (computed) bank reference at $70ce, no other references. - Bank $13: No references. - Bank $14-$17: Entirely script data, no references. - Banks $18-$1f: Entirely map data, no references. - Bank $40: Entirely map data, no references. - Bank $41: No references. - Bank $42: Entirely map data, no references. - Bank $43: No references. - Bank $44: Entirely map data, no references. - Bank $45: No references. - Bank $46: Entirely map data, no references. - Bank $47: No references. - Banks $48-$4f: Entirely map data, no references.
We have a potential hit in bank $12, at $70ce. It's dynamically computed. And the other hits available for the obvious variable involved are in bank $01: $51eb, $48; $5213, $40; and not $523b, $18. These appear to be map data starting banks.
All TAM instructions in known code areas have been accounted for. Unless there are further code areas not yet discovered, or dynamically created sections of code in RAM not yet known, all of the references to banks $40-$4f have been identified.
Update, 2021-09-20: Called it: $00.f20d dyanmically generates a TAM instruction in ZPage. Actual impact to be determined, as it is buried in what seems to be the audio driver logic. It's largely static to bank $06, but a couple of touchpoints specify a more-dynamic bank ID, yet to be tracked down. A review of the contents of banks $40-$4f strongly suggest that they are not being mapped here.
$00.f67c sets the bank IDs used for the more-dynamic part of the audio driver banking. Looks to be a table of 2-byte structures pointed to by $06.c004, the second byte of which are the bank IDs. So, starting at $06.c8b8, every second byte, until we reach $06.c8f2. All $06 and $07. We're clear on this one.
Possible hacking approaches
- We can possibly load additional font characters, provided that the game doesn't use up the rest of the encoding space for other things. Notably, while all of VRAM $2000-$2fff (8k bytes, 256 tiles) is loaded from bank $08, there are only $b0 (176) tiles with the rest being code.
- While the box drawing and related characters are currently $a0-$af, the escape codes are all $f9-$ff, so the miscellany could probably be moved to overlap those if we need more space.
- We should only need 26 ($1a) more characters (a minuscule font to go with the existing majuscules, digits, and punctuation) or so, and there are $39 accessible spots remaining...
- At $20 bytes/tile, this is $340 contiguous bytes... for just the minuscule set. We also want at least two new punctuation characters, so $380 bytes.
- Bank $00, $fb59-$fff5 is currently believed to be unreferenced junk. This is $49c bytes of prime real estate.
- Another possibility is stitching together the required space from the padding at the ends of multiple banks at the cost of needing more code to load the font.
- And a third possibility is if we stay with an expanded ROM: Just use one of the new banks to store the new font data.
- At $20 bytes/tile, this is $340 contiguous bytes... for just the minuscule set. We also want at least two new punctuation characters, so $380 bytes.
- Patching a secondary font load needs 34 ($22) bytes accessible in bank $00 or $01 (patch the JSR at $01.465b to point to a new routine that starts with the original JSR, then repeats the whole bank map and blit with new parameters, but taking a JMP rather than JSR to the blit routine).
- Or... since everything is fixed parameters, use ST0/ST1/ST2 to set up the write address, ST0 again to select the write data register, and a TIA to do the damage. Comes to 21 ($15) bytes or thereabouts, and that's without...
- Two more angles: First, shorten the transfer length on the original font upload so that we don't need to reinitialize the write address or reselect the data register, meaning that we can go straight to mapping the bank (if that's even needed, the bank might already be mapped) and transferring the data. Second: Rewrite the original load function using STx and TIA, which leaves enough space in situ to map another bank and issue another TIA.
- The actual font constraints are 8x8 pixels, 7 as backdrop, F as upper foreground (top five rows), E as lower foreground (bottom three rows), top row and right column unoccupied.
- We can view this as the top five rows having one plane defined by the character bitmap and the other three planes be FF-fill, and the bottom three rows having one plane defined by the character bitmap, one plane defined by the inverse of the character bitmap, and the other two planes FF-fill.
- I'm thinking of something in Forth where I lay out the bitmap forms as asterisks and either spaces or underscores so that they're trivially interpretable to the eye, and then have something on the backend that turns that into a monochrome bitmap, and then from the monochrome bitmap to the colored tile data in the ROM image.
- Or I could just rip off my existing 8x8 font to start with, redefine the machinery out from under it, reposition the characters within the tiles...
- We may be able to either compress the script text (it is currently entirely uncompressed) or expand the script text storage (it is currently limited to 32k bytes, but is limited to 15 bit indexes).
- The way that read_script_byte is structured, we could possibly relax the 15-bit limit, but this would require knowing how specific bits of script text are found in the first place.
- There will be little-to-no other text in the game, due to how read_script_byte functions (it forces the high part of the address, so it's not possible to reference RAM or a different ROM bank).
- TYA affects NZ, so patch at $00.e7f9. BPL to pick off the high bit. LSR A five times, CLC, ADC #$10 (high bit was set, so this winds up being $14-$17, the existing script banks), TAM #$10, BRA $e81d, and that brings us to $e807. That's ten bytes from the end of the BPL to the start of the BRA, so point the BPL to $e813 and repeat the middle bits with an ADC #$50 to put four new script text banks at $50-$53 ($30-$33 in the file).
- If we run out our expanded 32k region, we have the option of going to a 64k region once we have the entire script prepped for insertion, even if we're still using original text for most of it at that point.
- We might have as much as five bytes of ZPage and $37 bytes of other RAM available to work with, and there are seven ZPage bytes that are already dedicated to the text printer that could possibly be replaced by literals and repurposed (which would also free up a bit of bank $01 code space).
- $13.67db-$67fe requires that finding and displaying script text not clobber $00.W, and this may not be the only case of such.
- The "obvious" approach to expanding the ROM failed, hard. It turns out that three megabit games use "split" ROMs where the first two megabits are mapped linearly, there's a two megabit gap, and then the third megabit is mapped, while basically any other size is mapped linearly until they get to the point where the card itself has bankswitching logic.
- What this means is that expanding the ROM means finding every place that refers to banks in the $40-$4f range, and remapping them to be in the $20-$2f range.
- And, in turn, to make sure that all such places are found, we need a full disassembly of all of the code, and some certainty that we didn't miss any code.
- This has now been largely addressed, with the remaining caveat being that there may yet be undiscovered references to banks $40-$4f.
- All direct instances of TAM instructions have been accounted for, but the audio driver synthesizes a TAM instruction in RAM, so there may be references to $40-$4f buried in the music data.
- This may be obviable if we can compress the final script sufficiently. Or scare up enough odds and ends of space in various banks to be able to produce more contiguous space for script text.
- $12.7170 has a routine to convert binary to packed BCD. It runs from $7185-$71e5. At $71e6-$71f5 it is unpacked and converted to display format. X and Y are both dead at this point, so they may be used.
- TAX / LSR A / LSR A / LSR A / TAY / TXA / LDX highdigits,Y gets us an (over) approximation of the tens digit into X and the original number in A.
- highdigits here is 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 8, 9, 9.
- SEC / SBC tenstable,X leaves us with the tens digit in X, the ones digit in A, C set, and N clear, if and only if our tens digit is correct.
- If our tens digit is wrong, it's too high by one, and A is too low by ten. Also, Carry is clear.
- DEX / ADC #$0A corrects for our overestimate and sets Carry.
- tenstable here is 0, 10, 20, 30, 40, 50, 60, 70, 80, 90.
- twenty-three bytes in data, eighteen bytes in code (there's a BCS/BPL not made explicit above), for a total of fourty-one ($29) bytes. Seven more bytes does the display conversion and gets things into the right registers. Burn two more to link up with the existing tail, or to account for moving the entry point, and we're up to $32 bytes total. Compared to $71f6-$7185 at $71 bytes, that's a savings of 63 ($3f) bytes.
- Can we wedge a new text printer escape for "print this next character on the line above" into the logic, re-using the existing diacritic-handling routine at $00.ece3?
- Because reasons, we'd have to emit the escape, the upper-line character, the lower-line character, the next escape...
- This will lead to the script having a bit of a "shosple colupis" effect.
- Alternately, if we don't do this, we can add diacritics for non-English latinate languages (umlauts, macrons, graves, and acutes).
- The initial palette load routine $01.4667 is atrocious, replacing most of it with a straight TIA should save a lot of space. The question becomes, do any of the RAM side effects matter?
- Simple analysis shows that they don't.
Bugs found in the original game
- If you don't get Hasan's pearl for him in Baghdad, he's still there while he's also in Basra greeting you as an old friend.
- Patch devised and tested, and well marked in case we don't want to use it after all.
- There's a layout glitch with the dialogue when you try to get Enlil's Orb without enough free inventory space.
- This will necessarily be fixed with the new script.
- The RNG initializer sets the low byte twice, and the high byte not at all.
Internal Data for Sindibad: Chitei no Daimakyuu
| |
---|---|