Cyber Arms Val-Kaizer: ACSEX.EXE technical data

File Formats

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.

Script Files

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:
  • 1: the standard game window screen
  • 2: small cut-in image in top left of game window
  • 3: fullscreen border frame, these images are drawn twice consecutively and persist through the CLS command
  • 4: smaller game window, used for cockpit frame view
  • 6: centered image, used for opening cutscene
  • 7: standard game window, but fades in w/ vertical lines
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:
  • :0 displays nametag for character # indicated. Automatically starts a new line.
  • $00 wait for the number of cycles indicated.
  • @00 change text color, 00-07.
  • ¥ wait for keypress before continuing.
  • ^ skip to a new line.
  • #0 ???
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

Nametags

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 Width

Menu command length is hardcoded to 7 characters. For single-byte halfwidth, change 07 to 0E at addresses 5570 and 564E in ACSEX.EXE.

Script Delimiter

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.

Halfwidth Text Display Hack

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.
	

Back

Home