Welcome to Data Crystal's new home! Data Crystal is now part of the TCRF family (sort of).
The wiki has recently moved; please report any issues in Discord. Pardon the dust.

Crystal Beans from Dungeon Explorer/Tutorials

From Data Crystal
Jump to navigation Jump to search

Chip tiny.png The following article is a Tutorial for Crystal Beans from Dungeon Explorer.

List of things potentially needing translation

  • 0x00972F: If changing the font ordering put in the digits from 0 to 9. The pointer is hard-coded at 0x0226D7 (16-bits).
  • 0x009739: If using dialog code <CMHP>, put in the string that makes a noun plural. The low byte of the pointer is hard-coded at 0x0228D8 (byte), the high byte at 0x0228DD (byte), the length at 0x0228E2 (byte).
  • 0x009782: Character names. The pointers and lengths are stored at 0x009740.
  • 0x00986C: Yes/No answer string. Pointer and length at 0x009869.
  • 0x009887: Number of players answer string. Pointer and length at 0x009887.
  • 0x035759: Number of players question string. The low byte of the pointer is hard-coded at 0x00F945 (byte), the high byte at 0x00F949 (byte), the bank at 0x00F94D (byte).
  • 0x035775: Continue question string. The low byte of the pointer is hard-coded at 0x009352 (byte), the high byte at 0x009356 (byte), the bank at 0x00935A (byte).
  • 0x0357E5: Place names. Pointers at 0x035791 (16-bits). There may be a need to edit the compressed tilemap for the place name window at 0x0805D5 to allow for longer names.
  • 0x03E79E: Dialog strings. Pointers at 0x03E402 (24-bits).
  • 0x0866A4: Compressed menu and stats graphics.
  • 0x086C48: Compressed class names graphics.
  • 0x08712F: Compressed character names graphics.
  • 0x0DF942: Compressed character selection icon for player 1.
  • 0x0DF9C5: Compressed character selection icon for player 2.
  • 0x0DFA58: Compressed character selection icon for player 3.
  • 0x110BA3: Compressed "Game Over" graphics.
  • 0x17D616: Cutscene strings. Pointers at 0x17D5E4 (16-bits).

Removing the cutscene text compression

The cutscene strings use a simple compression to allow for character numbers between 0 and 511, but if there is no need for more than 256 characters, that compression increases the size of the text.

Assembling the following function at 0x17E200 will remove the need to compress the text when inserting it and will make the game load the text one byte at a time.

GetChar:
  LDY.W   $1CF3           ; (AC F3 1C) load character pointer
  LDA.W   $0000, Y        ; (B9 00 00) load a char
  AND.W   #$00FF          ; (29 FF 00) keep only lower byte
  STA.B   $38             ; (85 38)    store char to print
  INY                     ; (C8)       increment pointer
  STY.W   $1CF3           ; (8C F3 1C) store character pointer
  RTS                     ; (60)

Making the dialog use 1 byte characters

Like above, if there is no need for more than 256 characters, using 2 bytes per character wastes a huge amount of space.

Assembling the following function at 0x22786 will make the game read the text one byte at a time excepted for special codes, nearly doubling the amount of text that can be inserted.

The downside of this function is that the special codes will change values (code 02 will become 01, 04 become 02, 06 become 03, etc). For this reason, if you use this function, make sure to extract the text using textual values for the codes, then you will only need to change the table values when inserting the text.

Another downside is that the first 22 characters become unavailable for printing in dialog strings (the cursors are not affected by this as they are printed directly without being checked for special codes).

CheckChar:
  LDA.B   [$82]           ; (A7 82)       load 1 byte
  CMP.B   #$17            ; (C9 17)       if byte >= 23
  BCS     _normal_char    ; (B0 12)       normal char, jump
  ASL     A               ; (0A)
  TAX                     ; (AA)
  LDA.B   #$01            ; (A9 01)
  JSL.L   $C0870D         ; (22 0D 87 C0) MovePlayerButtonsHeldSleepL(byte numFrameToSleep<A>)
  PEA     _handler_return_here - 1 ; (F4 99 27) push address for RTS to return after the JMP
  JMP     (CodeHandlerJumpTable, X) ; (7C B0 27) jump to special code handler

_handler_return_here:
  BCC     CheckChar       ; (90 EA)       if carry clear, check next byte
  BRA     _locret_227C5   ; (80 11)       else exit function (no printing)

_normal_char:
  LDA.B   [$82]           ; (A7 82)       load 1 byte
  STA.W   $E0             ; (85 E0)       store to CurChar
  LDY.B   #$01            ; (A0 01)
  STZ.W   $E1             ; (64 E1)       clear high byte of CurChar
  LDA.B   #$01            ; (A9 01)       advance 1 bytes
  JSR     $C22D8A         ; (20 8A 2D)    IncStrPtr(byte num<A>)
  JSL.L   $C227C6         ; (22 C6 27 C2) PrintCharAndAdvanceCursor

_locret_227C5:
  RTL                     ; (6B)

CodeHandlerJumpTable:
; the addresses for the non-existing code 00 and 0E points to a RTS instruction
.DW $2785 $2817 $282C $2841 $284B $2860 $2867 $2888 $28A1 $28C1 $28C8
.DW $28F5 $291A $2785 $2957 $298A $2A20 $2A2B $2A41 $2A56 $2A66 $2A71