The files for Val-Kaizer use the same SZH compression format, and images use the same "type 0" MSV format as Guynarock 1, so the tools developed for the SGS.COM games are able to be reused here. Rather than the SIL format for script files, the scripts are just plain txt files compressed to SZH. After decompression, they are easy to read and edit in a text editor.
The game's script files, VT_0, VT_A, VT_B, and VT_C, use a human-readable scripting language interpreted by the game's executable. Each line is a separate command, and it even allows whitespace at the start of the line to indent commands that are inside of a menu or loop. While it improves readability, there is one consideration to take into account, each line can only be 255 bytes long, and that includes any whitespace and the two bytes for the end-of-line character. The game does not check for this when it loads a script file, but if a line exceeds that amount it throws off the calculated memory needed and causes the script to start writing itself out of bounds.
When translating the scripts, the menus and messages will take ASCII as well as full-width characters, but for dialogue boxes the characters are spaced full-width without hacking. The commands and parameters are comma-separated, but this prevents us from using ASCII commas in the in-game text so we changed it to use semicolons instead.
The available commands are as follows:
Command | Parameters | Name | Description |
---|---|---|---|
REM | text | REMark | Remarks are notes in the script file for the creators benefit and do nothing in the actual game. |
GHG | file, position | Graphic display | Displays a graphic on screen. "File" is the name of the graphic file without the ".SZH", and "position" is a number indicating one of a set of positions on screen to display. The possible positions are as follows:
|
CLS | none | CLear Screen | Clears the screen, but retains the frame image. |
MUSPL | file, number | MUSic PLay | Plays the music file indicated. "File" parameter omits the filetype, and |
EFFECT | ## | play sound EFFECT | Plays sound effect number indicated. |
SW | ###,# | Script Wait? | Holds executing next script command by ### cycles? |
MES | text | MESsage | Display the text in the message window. The message window is 5 lines of x characters (2x half-width) with space on the left for nametags y characters in length. The messages will automatically wrap at the end of lines and will wait for input if a 6th line is reached. The following special characters can be used:
|
LBL | number | LaBeL | Sets label to jump to with the GOTO command. |
GOTO | number | GO TO label | Jumps to the corresponding label. |
DO | none | DO loop | Continues execution until LOOP command is reached, then jumps back to DO. |
LOOP | none | do LOOP | Jump back to the previous DO command. |
DOEX | none | DO EXit | Exit the current do loop, jumping to just after the LOOP command. |
CLR | #,# | CLeaR variable | ??? |
LET | variable#, value# | LET var = val | Sets the variable number indicated to the given value. |
INC | variable#, value#,mode | INCrement var | Increments the variable indicated by one to a maximum value. A mode value of "S" is will stop at the maximum value, while a value of "L" will loop back to zero. |
CMSL | menu1/menu2/...* | Case Menu SeLect | Menu command followed by list of menu options separated by / and terminated by *. If there are submenus, they will be separated by * and the option that leads to the submenu will be immediately preceded by fullwidth number corresponding to the section of the submenu options. Options with submenus are displayed in yellow. Submenus will also automatically have a Cancel option to back out. |
CASE | 2-digit number "xy" | CASE submenu x, option y | CMSL line is followed by a series of CASE commands. The number following the CASE corresponds to the menu option selected, first digit being the submenu and second being the option. It executes commands from there until it reaches the CASE from the next option then skips ahead to CMEND and resumes normal execution. |
CMEND | none | Case Menu END | Denotes the end of the current CMSL block. |
IF | variable#, value#, else# | IF var=val | If the variable is equal to the value, continue executing the next line, otherwise skip to the next else# lines. |
MIF | var1#,val1#,var2#,val2#,...,*,else# | Multivariable IF | Like the IF command, but compares multiple variables to their corresponding values. "*" indicates the end of the var/val list before the else# value. |
FP | variable# | ??? | Skips ahead to line indicated by the value of the variable, then jump to FPEND. |
FPEND | none | FP? END | Indicates the end of the FP block. |
PLTALL | #,## | ? | ??? |
SCROLL | # | SCROLL image | Scrolls the loaded image in the view window. |
ANIME | frame# | ANIME frame | Display the indicated animation frame of the current graphic. |
MAZE | maze# | MAZE mode | Switches to Maze game mode and loads maze#. MAP#.DAT files have the map layouts, but they don't correspond to the number in the command and I don't know where the associated events are located, possibly hardcoded into ACSEX.EXE like the nametags and error messages. |
DTSV | scene# | DaTa SaVe | Saves the game progress, unlocking scene select up to scene#. |
ACMLD | filename | ACM LoaD | Loads the next script file from "filename".SZH. |
EOF | none | End Of File | Indicates the end of the script file. |
Unused commands: DORT, LCPRN, ME?, MFP, JMP, GCLS, SPACIAL, NOP
The nametag length is hardcoded to 3 characters. When using single-byte halfwidth, you need to change the 03 to 06 at address 9673 in ACSEX.EXE. The names themselves are located at 19568, with each name preceded by a 4 byte header.
ID | Original | English |
---|---|---|
01 | ルナ | Luna |
02 | VAL | VAL |
03 | マキ | Maki |
04 | ユミ | Yumi |
05 | "レイカ | Reika |
06 | 岬 | Misaki |
07 | 男 | Man |
08 | 女 | Woman |
09 | 女子 | Girl |
0A | 店員 | Clerk |
0B | 所員 | Staff |
0C | 真司 | Shinji |
Menu command length is hardcoded to 7 characters. For single-byte halfwidth, change 07 to 0E at addresses 5570 and 564E in ACSEX.EXE.
the script uses ASCII commas as delimiters, and detects them by comparing them to the value at data pair 1f30. by changing the value at 1f34 (191e4 in ACSEX), can change what character it looks for as the delimiter and free up the ASCII comma for use in MES commands.
While the MES command will display ASCII characters as halfwidth text, the character spacing remains fullwidth. The subroutine used to copy the text to TEXT VRAM is also used elsewhere in the program to move data around in memory, and therefore cant be edited directly without breaking things. In order to have the proper spacing, we need to reproduce the beginning of the subroutine elsewhere in memory up to where it calculates the next cursor position, then jump back into the original subroutine.
original subroutines:
3828:0401 56 push si
57 push di
8bf3 mov si,bx
b80000 mov ax,0000
8bd8 mov bx,ax
8b3e8634 mov di,[3486]
8cd9 mov cx,ds
8ec1 mov es,cx
807dfe07 cmp [di-02],07
7410 jz 0428
877dfc xchg [di-04],di
55 push bp
89268834 mov [3488],sp
ff97e632 call [bx+32e6]
5d pop bp
5f pop di
5e pop si
cb retf
:0b86 8b4502 mov ax,[di+02]
8b5d01 mov bx,[di+01]
8a35 mov dh,[[di]
b200 mov dl,00
80cf80 or bh,80
8b4c02 mov cx,[si+02]
8b7cff mov di,[si-01]
8b7401 mov si,[si+01]
81e700ff and di,ff00
0ba0 81ce0080 or si,8000 this is the value that becomes what is added to the work data
0ba4 d1c1 rol cx,1
d1c0 rol ax,1
0aed or ch,ch
...
tested by inserting alternate subroutine at 3828:bc00:
56 57 8b f3 b8 00 00 8b d8 8b 3e 86 34 8c d9 8e c1 87 7d fc 55 89 26 88 34 e8 04 00 5d 5f 5e cb 8b 45 02 8b 5d 01 8a 35 b2 00 80 cf 80 8b 4c 02 8b 7c ff 8b 74 01 81 e7 00 ff 81 ce 00 40 e9 63 4f
and have that called instead of 3828:0401 at 2a13:9578 (9724? in file replace with 9a00bc). This duplicates 0401 up until the value that needs halved in order to add to 3324
While there is space for the new subroutine in the memory segment the subroutines are in when the program is running, there is no corresponding empty space in the executable file itself. Instead, I tacked on a bit of code at the end of the exe, after everything els is loaded and it updates the segment addresses, to then copy the new subroutine into memory.
At the end of the exe, you can place a subroutine that will itself copy the new subroutine into the segment 3828. jmp to this instead of the jmp at 0103 (replace with e9d823? jmp 24de)
1e push ds
06 push es
56 push si
57 push di
50 push ax
0e push cs
1f pop ds
8b060200 mov ax, [0002]
8ec0 mov es, ax
be0025 mov si, :newsubdata: (2500)
bf00bc mov di, :location: (bc00)
51 push cx
b92100 mov cx, :sublength: (21)
f3a5 repe movsw
59 pop cx
58 pop ax
5f pop di
5e pop si
07 pop es
1f pop ds
2eff2f jmp far cs:[bx]
:newsubdata: goes here
Last problem is when it is loading the exe, it cuts off after 0001D0000. Have to increment 0004 from E8 to E9 to load the next chunk of data.