VWF Dialogues
© 2010-2024 RPG Hacker

Screenshot
Screenshot
Screenshot

Table of Contents

  1. Introduction
  2. Getting Started
  3. Basic Functionality
  4. Advanced Functionality
  5. Problem Solving
  6. Known Bugs
  7. Contribute, Report Bugs & Request Features
  8. Version History

Introduction

Welcome to VWF Dialogues! Since you got here by yourself, you most likely already know what this patch does, but let me give you a general overview anyways.

The aim of this patch is to give a useful alternative to SMW’s native text boxes. Unlike Romi's VWF Cutscene Tool (which is great, but has very specific use cases only), this patch was designed around easy event creation, easy customization and compatibility with all kinds of languages. The cost of this is that its useage is slightly more advanced and requires more knowledge. However, as long as you read this manual carefully and are somewhat familiar with custom sprites/custom blocks and Asar patches, you should be fine.

I’ve included a single custom block that utilizes this patch. Originally, I wanted to include more blocks and also a few custom sprites, but I figured that any custom block or custom sprite hosted on SMW Central that displays a native SMW message box should already be compatible with the patch as long as you enable the SMW message box hijack (see section 2). The one block I did include gives a general idea on how to address this patch within your own code. It primarily serves as a sample for people who want to write custom code that interfaces with the patch.

In addition to this, I’ve included a few alternative fonts in case you don’t like the default one. Though keep in mind that the default font features the largest (non-Japanese) character set. If you’re making a hack in any language that isn't English and features any special characters that are not yet in the default font, you will have to draw and add the missing glyphs yourself.

Be aware that by default, this patch applies some modifications to your ROM that seem to be unrelated to the patch itself at first and might have unintended side effects. For example: It automatically expands the ROM's SRAM size to 128 KB since it requires roughly around 20 KB of working RAM that normally aren't available in SMW. For all of those cases, there's usually config options that can be used to disable the respective modifications if desired.

During operation, this patch hides, overwrites, and later restores a large chunk of data in layer 3. It's save to use the patch in levels with layer 3 active, however, the original layer image will become invisible for the duration of the text box, so it might not always be a good idea to do so. The patch also overwrites (and later restores) certain colors from the palette in CGRAM, documented in detail throughout this manual. Because of this, some care needs to be taken on which colors to use inside levels that display text boxes.

Anyways, let’s get started with the first steps of setting up the patch.

Return to Index

Getting Started

In order to make use of this patch, you'll need to have downloaded Asar v1.90 or newer. Older versions of Asar won't work, as the patch was designed specifically around newer Asar features for an improved user experience. As for the patch itself, the very first thing you’ll want to do is to take the entire vwf_dialogues folder and copy it over to your hack’s local patches directory so that you can make modifications to it as needed. If you only want to see the patch in action, without configuring anything or adding custom text, you may go ahead and patch vwf_dialogues.asm to your ROM right now. Otherwise, keep reading.

The patch is structured in a way where all data that is meant to be editable by end users is stored inside the data subdirectory. The most important file here is called vwfconfig.cfg and it contains all the major settings for the patch. Open it up in a text editor of your choice to edit them. Pay special attention to all the comments in this file, as they explain what most of the options do. This manual will only explain some of the more important ones.

The first options you will find are !vwf_var_ram, !vwf_backup_ram and !vwf_gfx_ram as well as !vwf_var_ram_sa1, !vwf_backup_ram_sa1, !vwf_gfx_ram_sa1 and !vwf_palette_backup_ram_sa1 respectively. The first section of variables is used only in non-SA-1 ROMs, with the second one only being used in SA-1 ROMs. These defines configure which areas of RAM VWF Dialogues will use as their working memory. As an average user, you most likely won't ever have to edit any of these. The default settings should work out of the box. Advanced users, who might need more control over their RAM, can make use of them, going by the comments on each define as a rough guide on what they need and how they're being used.

The only thing worth noting is that without further modifications, a non-SA-1 SMW ROM doesn't provide the amount of free RAM VWF Dialogues need. For this reason, the patch uses SRAM as working memory by default. All of the non-SA-1 address defines mentioned above have their default values pointing to areas in SRAM. The patch automatically applies a SRAM expansion patch to make sure enough SRAM is available. This behavior is controlled via the !vwf_patch_sram_expansion setting. Advanced users can set it to false to disable SRAM expansion, but will have to use additional patches that provide alternative areas of free RAM. SA-1 ROMs are unaffected by all this, as the SA-1 chip contains its own large area of RAM, which in the case of SMW is more than enough for this patch to work with.

Now for (occasionally not so) quick explanations on some of the more important settings in the Patch Settings section:

Settings in the Default Settings sections define the default values/behaviors of various patch functions. I won't explain them in detail here, because most are either self-explanatory or will become apparent once the respective functions they relate to are explained.

The Data Includes section becomes relevant once you want to add new assets to the patch. That is: New fonts, new message files, new text box frames etc. New fonts and messages files are added within the vwf_define_data() macro, whereas the vwf_define_frames() macro lets you specify the properties of your text box frames (currently just the palettes). Once again, these settings should become more apparent when their respective functionality is explained.

This covers all of the patch's basic setup. More advanced functionality will be explained in detail later on. Once you're done configuring vwfconfig.cfg, you may go ahead and use Asar to patch vwf_dialogues.asm to your ROM. If everything was set up correctly, Asar's output should look roughly like this: Screenshot If that’s what you get, then the patch was applied successfully. Most of these outputs are just for debugging purposes. You can safely ignore them, unless you're modifying the patch itself or coding some advanced feature that makes use of it.

Return to Index

Basic Functionality

In this section I'll explain all the functionality that is intended for average users of this patch. This includes setting up resources and writing actual message boxes.

Resources (Graphics, Palettes, Fonts...)

VWF Dialogues are designed to be very customizable. This not only includes the dialogue text itself, but also the design of the text box containing it. It's possible to customize all text box frames and backgrounds, as well as all fonts, to your liking, or add new ones entirely. The patch can even switch between them at run-time (though for text box frames and backgrounds, this is only technically supported - no feature is currently provided that makes use of this possibility, so if you want it in your hack, you currently need to write custom code for it). In order to make the most out of these features, you'll have to understand the different types of resources the patch uses, all contained within the data folder. Here's a short summary:

Editing any of these graphics requires a tile editor that supports the 2BPP GB graphics format. In theory, any such tile editor will do, but if you plan to edit (or create) fonts, I highly recommend using a recent version of YY-CHR. You'll want to be using at least v0.99, as older versions lack some features that make editing fonts practicable. For the purpose of this manual, I will assume you're using YY-CHR and will reference it where appropriate.

Text Box Backgrounds

For starters, let's look at background graphics, which are by far the simplest graphics format. Open data/gfx/vwfbgpatterns.bin in YY-CHR and set the graphics format to 2BPP GB. After tweaking palettes a little, you should see something similiar to this: Screenshot Here's what you need to know about background graphics:

That's pretty much all there is to it. To add additional BG patterns to the patch, simply expand the size of vwfbgpatterns.bin by 16 bytes (you can use a hex editor for this) and then draw the new pattern into the newly added empty space in YY-CHR.

Text Box Frames

In order to edit text box frames, open up data/gfx/vwfframes.bin in YY-CHR and set the graphics format to 2BPP GB. Tweak the palettes to your liking, and you should see something like this: Screenshot

Here's a quick rundown of everything you need to know about text box frames:

To add additional text box frames to the patch, simply expand the size of vwfframes.bin by 144 bytes (you can use a hex editor for this) and then draw the new text box frame tiles into the newly added empty space in YY-CHR. Add the palette for this new frame to the bottom of vwf_define_frames().

Fonts

Font are the most complex type of resource supported by the patch. It already comes pre-packaged with four of them ready to use (one with support for Japanese text). If you do want to make your own fonts, there's three different types of resource files you need to know about: A .bin file containing character glyph graphics, an .asm file containing the widths of each character, and a second .asm file containing character-to-glyph mappings. You can find all the pre-packaged fonts in data/fonts. Each folder here contains a vwffont.bin containing the graphics and a vwffont.asm containing the character widths. The only exception is the terra_j font, which contains multiple .bin files, because there isn't enough space in a single font to contain the entire Japanese character set. For all pre-packaged fonts, data/fonts/vwftable.asm can be used as the character-to-glyph mapping file. Here's a list of things to be aware of when working with fonts:

Message Files

Message files are probably this patch's most important resource, as they contain its actual guts: the messages themselves. The patch comes pre-packaged with a single message file at data/vwfmessages.asm. It's unlikely you'll ever have to create a new one. For 99% of use cases, just editing the existing file will be sufficient. There's only a few potential scenarios that I can think of where creating additional message files might be useful or even required:

Anyways, for the few people who have legitimate reasons to create new message files, here's a brief explanation on them. Note that it only covers the format of message files themselves, not on the messages within them. See section Message Format for details on that. That's really all there is to it.

Message Format

Adding new messages to this patch is as simple as adding the following lines to one of your message files (usually data/vwfmessages.asm):

%vwf_message_start(0000)

	%vwf_header()
	
	; Message contents go here.

%vwf_message_end()
The number passed to %vwf_message_start() is the ID of your message. This is what other patches/sprites/blocks use to tell this patch which message to display. It's a four-digit hexadecimal number and must be unique for every message. The easiest way to assure this is to just start from 0000 and increment the ID by 1 for every message you add. In theory, the ID can be any value from 0000 to FFFF, but in practice, because the patch uses 24-bit pointers for messages and they all need to fit into a single bank, the actual maximum is somewhere around 2AAA. This shouldn't be an issue for average users, as this still means the patch supports up to 10922 individual messages.

One thing to be aware of when assigning message IDs is that the patch will automatically generate pointers for every single message. Since the pointers are stored as a simple table that is looked up via the message ID, whenever there's a gap in message IDs the patch needs to fill in that gap via dummy pointers. So if you have a message file that only contains two messages with IDs 0000 and 0100, then the patch will generate dummy pointers for all IDs from 0001 to 00FF. Since this wastes free space, it is advised to avoid gaps in message IDs altogether. The patch will print a warning once it detects a certain number of gaps.

The %vwf_header() always needs to be the first line right after the %vwf_message_start(). This line allows you to override text box settings by passing different arguments to the %vwf_header() macro. More details on that in section Header Settings.

After the header is where you add your text commands. Without any commands, all you'll get is an empty text box. See section Text Commands for a full list of what commands are available.

Putting everything together, here is a simple example of what a full text box might look like:

%vwf_message_start(001A)

	%vwf_header(x_pos(10), y_pos(10), width(5), height(1), text_alignment(TextAlignment.Centered))
	
	!str("What's up, Mario? Hope you have a nice day!")

%vwf_message_end()

Header Settings

When defining your own text boxes, the very first thing you'll want to look at are the header settings. These settings define a number of general properties of your text box, like position, size, sound effects and more. The way this works is by passing optional arguments as function calls to the %vwf_header() macro in your message. Here's an example:

%vwf_header(vwf_x_pos(0), vwf_y_pos(0), vwf_width(15), vwf_height(13))
When any argument is omitted, its value will be pulled from the default values defined in vwfconfig.cfg. For example, when you omit the vwf_x_pos argument, the patch will use the !vwf_default_x_pos define in its place. Providing no arguments at all will automatically replace the header by a shared header containing all the default values, reducing the total size of your message.

Header arguments, like text commands, support short aliases via the !vwf_enable_short_aliases setting. When enabled, the vwf_ prefix on all arguments can be omitted. Example:

%vwf_header(x_pos(0), y_pos(0), width(15), height(13))
What follows is a list of all header arguments along with a brief explanation.

Shared Headers

Shared headers allow you to define a header in one message and then reuse it in arbitrarily many other other messages. This has a few key advantages:

To make use of shared headers, simply replace the
%vwf_header()
line in one of your mesages by
%vwf_shared_header(message_id)
where message_id is the ID of the message whose header you want to reuse. Here is a complete example:
%vwf_message_start(001B)

	%vwf_shared_header(001A)
	
	!str("Hey, Mario! Nice to see you again!")

%vwf_message_end()
Note that you can only point a shared header to a message that has a physical header itself (aka a message that uses %vwf_header() instead of %vwf_shared_header()). While it's technically possible to point shared headers to other shared headers, there's very little use to it over pointing to the origin header directly, and it only runs the risk of causing stack overflows or infinite recursion at run-time, so the patch prevents this use case entirely.

When you try to point a shared header to a message that doesn't have a physical header, you will get an error message similar to the following:

error: (Elabel_not_found): Label 'PhysicalHeader001A' wasn't found. [dw $001A+(PhysicalHeader001A-PhysicalHeader001A)]
The error message is a bit cryptic, because it abuses Asar functionality to work at all. In this example case, it's saying that message 001A doesn't have a physical header, so it's impossible to use it as a shared header via %vwf_shared_header(001A). Fixing this error requires giving either message (001A or the message referencing it) a physical header.

As a special case, using %vwf_header() in a message without any arguments will automatically turn the header into a shared header that points to a built-in message containing all your default header settings. This greatly reduces the size of all messages that only use default settings. If you want to use one of your own headers as a shared header, it thus needs to contain at least a single argument to override any header setting and prevent this automatic replacement.

Text Box Properties

vwf_x_pos()

Usage
vwf_x_pos(x_pos)
Short Aliases
x_pos(x_pos) = vwf_x_pos(x_pos)
Parameters
  • x_pos: number: The X position to use. (min: 0, max: 28)
Specifies the X position of the text box on the screen in 8x8 tile increments. An x_pos of 1 moves the text box one 8x8 tile (=8 pixels) the right, an x_pos of 2 two 8x8 tiles etc. Depending on the size of the text box, the patch might automatically clamp this value down to prevent it from going beyond the screen border.

vwf_y_pos()

Usage
vwf_y_pos(y_pos)
Short Aliases
y_pos(y_pos) = vwf_y_pos(y_pos)
Parameters
  • y_pos: number: The Y position to use. (min: 0, max: 24)
Specifies the Y position of the text box on the screen 8x8 tile increments. A y_pos of 1 moves the text box one 8x8 tile (=8 pixels) down, a y_pos of 2 two 8x8 tiles etc. Depending on the size of the text box, the patch might automatically clamp this value down to prevent it from going beyond the screen border.

vwf_width()

Usage
vwf_width(width)
Short Aliases
width(width) = vwf_width(width)
Parameters
  • width: number: The width to use. (min: 1, max: 15)
Specifies the width of the inside area (aka the text area) of the text box in 16x16 tile increments. A value of 1 means one 16x16 tile (=16 pixels), a value of 2 two 16x16 tiles etc. To get the total width of the entire text box, add two 8x8 tiles for the text box frame to this.

vwf_height()

Usage
vwf_height(height)
Short Aliases
height(height) = vwf_height(height)
Parameters
  • height: number: The height to use. (min: 1, max: 13)
Specifies the height of the inside area (aka the text area) of the text box in 16x16 tile increments. A value of 1 means one 16x16 tile (=16 pixels), a value of 2 two 16x16 tiles etc. To get the total height of the entire text box, add two 8x8 tiles for the text box frame to this.

vwf_text_box_bg_pattern()

Usage
vwf_text_box_bg_pattern(pattern_id)
Short Aliases
text_box_bg_pattern(pattern_id) = vwf_text_box_bg_pattern(pattern_id)
Parameters
  • pattern_id: number: The index of the pattern to use. (min: $00, max: [total number of patterns] - 1)
Overrides the setting for the text box background pattern used by this text box. NOTE: For technical reasons, the patch can't properly bound-check this setting for the maximum value. Going beyond the maximum will produce glitched text box backgrounds.

vwf_text_box_bg_color()

Usage
vwf_text_box_bg_color(color)
Short Aliases
text_box_bg_color(color) = vwf_text_box_bg_color(color)
Parameters
  • color: rgb15-color: The color to use, in RGB15 format.
Overrides the setting for the text box background color used by this text box.

vwf_text_box_frame()

Usage
vwf_text_box_frame(frame_id)
Short Aliases
text_box_frame(frame_id) = vwf_text_box_frame(frame_id)
Parameters
  • frame_id: number: The index of the frame to use. (min: $00, max: [total number of frames] - 1)
Overrides the setting for the text box frame used by this text box. NOTE: For technical reasons, the patch can't properly bound-check this setting for the maximum value. Going beyond the maximum will produce glitched text box frames.

vwf_box_animation()

Usage
vwf_box_animation(animation)
Short Aliases
box_animation(animation) = vwf_box_animation(animation)
BoxAnimation = VWF_BoxAnimation
Parameters
  • animation: VWF_BoxAnimation: The animation to use. Valid values:
    ValueDescription
    VWF_BoxAnimation.NoneDon't display any text box at all (only text will be visible).
    VWF_BoxAnimation.SoEAnimate the text box like in Secret of Evermore (the text box expands top to bottom).
    VWF_BoxAnimation.SoMAnimate the text box like in Secret of Mana (the text box expands from the center to the outside).
    VWF_BoxAnimation.MMZAnimate the text box like in Mega Man Zero (the text box expands from left to right).
    VWF_BoxAnimation.InstantDisplay the entire text box at once, without any animation.
Specifies the animation to play when opening the text box (or hides the text box entirely).

Text Properties

vwf_font()

Usage
vwf_font(font_id)
Short Aliases
font(font_id) = vwf_font(font_id)
Parameters
  • font_id: number: The ID of the font to use. (min: 0, max: [total number of fonts] - 1)
Specifies the font to use for the text box (when not overridden by a text command). Font IDs are based on the order of %vwf_add_font() calls in your vwfconfig.cfg, starting at 0. This setting is ignored when running in 16-bit mode. Note that this setting does not affect the active character mapping table, so if you require different tables for different fonts, you'll have to load them manually via an incsrc. See Fonts for details.

vwf_text_palette()

Usage
vwf_text_palette(palette_id)
Short Aliases
text_palette(palette_id) = vwf_text_palette(palette_id)
Parameters
  • palette_id: number: The ID of the palette to use. (min: 0, max: 7)
Specifies what palette number to use for text, outlines and background of the text box (when not overridden by a text command). This is based on a 2BPP (4-color) palette, meaning each increment moves the palette four colors ahead. Only the first two rows of Lunar Magic's palette are usable, giving you a choice between eight palettes in total. While the text box is open, the patch will overwrite the colors in this palette with whatever colors were specified for the text, outline and background colors. This means you should avoid selecting any palette that is being used for the level graphics and might be visible on the screen when you open the text box. Additionally, you should avoid using the same palette as set for !vwf_frame_palette in vwfconfig.cfg. Doing so would lead to undefined behavior.

vwf_text_color()

Usage
vwf_text_color(color)
Short Aliases
text_color(color) = vwf_text_color(color)
Parameters
  • color: rgb15-color: The color to use, in RGB15 format.
Specifies the text color to use for the text box. In other words, this determines which color gets written to color 2 (the third color) of the palette specified with vwf_text_palette(). You can use the rgb_15() helper function to specify the color via its RGB components.

vwf_outline_color()

Usage
vwf_outline_color(color)
Short Aliases
outline_color(color) = vwf_outline_color(color)
Parameters
  • color: rgb15-color: The color to use, in RGB15 format.
Specifies the outline color to use for the text box. In other words, this determines which color gets written to color 3 (the fourth color) of the palette specified with vwf_text_palette(). You can use the rgb_15() helper function to specify the color via its RGB components.

vwf_space_width()

Usage
vwf_space_width(width)
Short Aliases
space_width(width) = vwf_space_width(width)
Parameters
  • width: number: The width in pixels. (min: 0, max: 15).
Specifies the width of the space character within this text box. It's recommended to use at least 6 to 8 pixels for this, depending on whether the font you use has outlines on both sides (left and right), on just one side, or no outlines at all. The reason for this has to do with the way the vwf_set_text_palette() command works. It can only modify the text palette per 8x8 tile, not per character or word. Using a wide enough space here assures that if you use this command to recolor a word surrounded by spaces, the palette change will never cut into tiles of surrounding words in a visible way.

vwf_text_margin()

Usage
vwf_text_margin(margin)
Short Aliases
text_margin(margin) = vwf_text_margin(margin)
Parameters
  • margin: number: The margin in pixels. (min: 0, max: 15).
Specifies the number of pixels to keep empty at the left and right edges of the text box.

vwf_text_alignment()

Usage
vwf_text_alignment(alignment)
Short Aliases
text_alignment(alignment) = vwf_text_alignment(alignment)
TextAlignment = VWF_TextAlignment
Parameters
  • alignment: VWF_TextAlignment: The text alignment to use. Valid values:
    ValueDescription
    VWF_TextAlignment.LeftThe text is left-aligned.
    VWF_TextAlignment.CenteredThe text is centered.
Specifies the text alignment for this text box.

Speed & Flow Settings

vwf_freeze_game()

Usage
vwf_freeze_game(freeze)
Short Aliases
freeze_game(freeze) = vwf_freeze_game(freeze)
Parameters
  • freeze: boolean: Whether to freeze (true) or not freeze (false) gameplay.

Specifies whether gameplay should freeze while the text box is open. For non-SA-1 ROMs, the general recommendation is to always set this to true, as the patch is too demanding for them to run gameplay at the same time, leading to slowdown. It's recommended to use an SA-1 ROM instead if you want to make use of this feature. It should be fast enough for a dialog not to slow down gameplay.

If you absolutely must use a non-SA-1 ROM, here's a few tips for lessening the impact of slowdown:

  • Make sure all FastROM options of Lunar Magic are enabled. This will notably increase game speed even in non-SA-1 ROMs.
  • Use slower text speeds. Slower text speeds mean there's more frames without any text processing happening between each character, thus lag frames will be more spaced out and less noticable.
  • Use smaller text boxes overall with long wait times at the end. This again helps spacing out lag frames to make them less noticable.
  • Keep the number of sprites on-screen during a text box low.
  • Make use of animation style VWF_BoxAnimation.None, which disables the text box background entirely and makes the patch skip a good chunk of code.

Whenever you do allow gameplay during text boxes, you should try to make sure they close by the time any level transition occurs (like from entering a pipe, touching a goal post or dying). The patch does try to automatically close text boxes to prevent glitches, but there's always a chance for oversights with this feature. You're on the safe side when you only use your text boxes in predictable environments.

vwf_text_speed()

Usage
vwf_text_speed(speed)
Short Aliases
text_speed(speed) = vwf_text_speed(speed)
Parameters
  • speed: number: The number of frames to wait between characters. (min: 0, max: 63).
Specifies the number of frames the text box should wait between displaying each character. This effectively sets the text speed. A value of 0 represents the fastest text speed, a value of 63 the slowest.

vwf_auto_wait()

Usage
vwf_auto_wait(mode)
Short Aliases
auto_wait(mode) = vwf_auto_wait(mode)
AutoWait = VWF_AutoWait
Parameters
  • mode: VWF_AutoWait: The action to perform. Valid values:
    ValueDescription
    VWF_AutoWait.NoneDo "nothing" (just clears the text box and continues).
    VWF_AutoWait.WaitForAAutomatically pause the text box until the A button is pressed, in a similar manner to the %vwf_wait_for_a() text command. Deprecated. Use VWF_AutoWait.WaitForButton instead.
    VWF_AutoWait.WaitForButtonAutomatically pause the text box until the default text box advance button is pressed, in a similar manner to the %vwf_wait_for_button() text command.
    VWF_AutoWait.WaitFrames.1
    VWF_AutoWait.WaitFrames.2
    [...]
    VWF_AutoWait.WaitFrames.255
    Automatically pause the text box for the specified number of frames, before clearing it and continuing.
Specifies the action to take when text exceeds the available space of a text box. Compatibility note: In all pre-macro versions of this patch, due to a programming oversight, the minimum number of frames to wait with the WaitFrames setting was 2 and the maximum was 255, whereas in current versions the supported range is 1 to 255 frames. Keep this in mind if you plan to port text data from an older version to a newer one. Slight adjustments to text box headers might be necessary (you might have to add a frame to all auto-wait settings if frame-perfect timing matters).

vwf_button_speedup()

Usage
vwf_button_speedup(enable)
Short Aliases
button_speedup(enable) = vwf_button_speedup(enable)
Parameters
  • enable: boolean: Whether to enable (true) or disable (false) button-speedup.
Specifies whether the text box supports button-speedup. When enabled, text can be sped-up by holding down the A button. This only applies to text boxes with a text speed setting greater than 0, as all this does is to reduce that setting to 0 while the button is being held down.

vwf_enable_skipping()

Usage
vwf_enable_skipping(enable)
Short Aliases
enable_skipping(enable) = vwf_enable_skipping(enable)
Parameters
  • enable: boolean: Whether to enable (true) or disable (false) skipping.
Specifies whether this text box can be skipped. When enabled, pressing the Start button will immediately move the text pointer forward to the text box's skip location. By default, this is the end of the text box (thus closing it). However, this can be overridden by using the %vwf_set_skip_location() text command within your text box, which will set the skip location to the location of the command. NOTE: This can be done only once per text box. Using the command multiple times within the same text box will generate an error.

Sound Effects

vwf_enable_sfx()

Usage
vwf_enable_sfx(enable)
Short Aliases
enable_sfx(enable) = vwf_enable_sfx(enable)
Parameters
  • enable: boolean: Whether to enable (true) or disable (false) sound effects.
Specifies whether this text box should play sound effects or not. When disabled, all other sound effect settings will be ignored.

vwf_letter_sound()

Usage
vwf_letter_sound(sound_bank, sound_id)
Short Aliases
letter_sound(sound_bank, sound_id) = vwf_letter_sound(sound_bank, sound_id)
Parameters
  • sound_bank: number: The sound bank of the sound to play. Valid values are $1DF9, $1DFA, $1DFB and $1DFC (although using $1DFB is probably a bad idea).
  • sound_id: number: The ID of the sound to play. Valid values depend on the selected sound bank. See the SMW Central RAM Map for details.
Specifies which sound effect to play when the text box displays a character.

vwf_wait_sound()

Usage
vwf_wait_sound(sound_bank, sound_id)
Short Aliases
wait_sound(sound_bank, sound_id) = vwf_wait_sound(sound_bank, sound_id)
Parameters
  • sound_bank: number: The sound bank of the sound to play. Valid values are $1DF9, $1DFA, $1DFB and $1DFC (although using $1DFB is probably a bad idea).
  • sound_id: number: The ID of the sound to play. Valid values depend on the selected sound bank. See the SMW Central RAM Map for details.
Specifies which sound effect to play when the text box waits for an A press (either because of a text command or an auto-wait).

vwf_cursor_sound()

Usage
vwf_cursor_sound(sound_bank, sound_id)
Short Aliases
cursor_sound(sound_bank, sound_id) = vwf_cursor_sound(sound_bank, sound_id)
Parameters
  • sound_bank: number: The sound bank of the sound to play. Valid values are $1DF9, $1DFA, $1DFB and $1DFC (although using $1DFB is probably a bad idea).
  • sound_id: number: The ID of the sound to play. Valid values depend on the selected sound bank. See the SMW Central RAM Map for details.
Specifies which sound effect to play when the cursor of a %vwf_display_options() command moves.

vwf_continue_sound()

Usage
vwf_continue_sound(sound_bank, sound_id)
Short Aliases
continue_sound(sound_bank, sound_id) = vwf_continue_sound(sound_bank, sound_id)
Parameters
  • sound_bank: number: The sound bank of the sound to play. Valid values are $1DF9, $1DFA, $1DFB and $1DFC (although using $1DFB is probably a bad idea).
  • sound_id: number: The ID of the sound to play. Valid values depend on the selected sound bank. See the SMW Central RAM Map for details.
Specifies which sound effect to play when the user presses the A button while the text box is waiting for an A press, or when the user selects an option from a %vwf_display_options() command.

Advanced

vwf_enable_message_asm()

Usage
vwf_enable_message_asm(enable)
Short Aliases
enable_message_asm(enable) = vwf_enable_message_asm(enable)
Parameters
  • enable: boolean: Whether to enable (true) or disable (false) MessageASM.
Specifies whether MessageASM should be enabled for this text box. See section MessageASM for details.

Text Commands

With everything else out of the way, it's time to finally start defining the actual contents of our text boxes. This is done by inserting text commands between a message's %vwf_header() and %vwf_message_end() (see section Message Format for details). These text commands usually take the form of macro calls, but can also be defines when using short aliases. Here's a simple example of a message containing some text commands:

%vwf_message_start(0000)

	%vwf_header()
	
	; One command per line
	%vwf_text("You can write each text command on a separate line like this.")
	%vwf_wait_for_button()
	%vwf_clear()
	
	; Multiple commands on a single line
	%vwf_text("But you can also chain them together on one line via a colon.") : %vwf_wait_for_button() : %vwf_clear()
	
	; These two lines are equivalent, but one uses short aliases, the other doesn't.
	%vwf_text("Hello?") : %vwf_wait_for_button() : %vwf_line_break()
	!str("Hello?") : !press_button : !n

%vwf_message_end()
Some text commands have parameters tagged as "(optional)". This means the respective parameter can be omitted, in which case a default value will be used.

Text Output

%vwf_text()

Usage
%vwf_text(text)
Short Aliases
!text(text) = %vwf_text(text)
!str(text) = %vwf_text(text)
Parameters
  • text: string: The text to output.
This command prints a string of regular text to the text box. Your currently active table file defines how each character maps onto the currently active font to display the respective character. Whenever a text string you print would overflow the available space of the text box, the vwf_auto_wait() header setting defines what action should be taken.

A word of caution: For the implementation of text commands, the patch reserves a certain number of character values. Currently, these are $E6 to $FF when running in 8-bit mode, or $FFE6 to $FFFF when running in 16-bit mode. Trying to print any character with this command that maps onto one of those values (except for $FE, which represents the vwf_space() command) will likely result in bugs. Currently, these characters need to be escaped manually using the vwf_char() command. A future version of the patch might automate this process if possible.

%vwf_char()

Usage
%vwf_char(char)
Short Aliases
!char(char) = %vwf_char(char)
!chr(char) = %vwf_char(char)
Parameters
  • char: character: The character to output.
Prints a single character to the text box. Unlike vwf_text(), this command escapes every character you output and can thus never accidentally map onto another text command, so you can use it to safely print any raw character from a font to the text box.

%vwf_char_at_address()

Usage
%vwf_char_at_address(address)
Short Aliases
!ram_char(address) = %vwf_char_at_address(address)
!ram_chr(address) = %vwf_char_at_address(address)
Parameters
  • address: number: The RAM/ROM address to read.
This command works just like vwf_char(), except the value you pass in is a RAM address. The game will read out that address and interpret whatever value it currently holds as the character to print. An example use case of this could be printing the SMW timer, which has each of its digits stored in separate RAM addresses (note: this particular use case only works with fonts where all digits are the first glyphs in the font - so for example, character value $00 would map onto the 0 digit glyph, $01 on the 1 digit glyph etc.).

%vwf_space()

Usage
%vwf_space()
Short Aliases
!sp = %vwf_space()
!space = %vwf_space()
Prints a single space to the text box and causes the automatic word wrapping processor to run. If the next word no longer fits onto the current line, a line break is automatically inserted. See %vwf_line_break() for details. Note that there's no reason to ever use this command under normal circumstances. The default character to glyph mapping tables included with the patch already map the space character to the %vwf_space() command, so just using the %vwf_text() command is sufficient and will produce automatic line breaks.

%vwf_non_breaking_space()

Usage
%vwf_non_breaking_space()
Short Aliases
!nbsp = %vwf_non_breaking_space()
An alias for %vwf_char(!vwf_nbsp_char), with !vwf_nbsp_char = $00FE. Basically, this prints character $00FE (which usually maps to a space) to the text box as a raw character. The purpose of this command is to print a space without invoking the word wrapping processor, similar to the   HTML entity. Useful when you want to prevent two words from being separated and ending up on two different lines. For example, if you want the name "Super Mario" to always appear on a single line, you can assure that by using this command in place of the space.

%vwf_decimal()

Usage
%vwf_decimal(address, address_size, leading_zeros)
Short Aliases
!dec(address, address_size, leading_zeros) = %vwf_decimal(address, address_size, leading_zeros)
AddressSize = VWF_AddressSize
Parameters
  • address: number: The RAM/ROM address to read.
  • address_size (optional): VWF_AddressSize: The size of the address to read. Default: VWF_AddressSize.8Bit. Valid values:
    ValueDescription
    VWF_AddressSize.8Bit8-bit address.
    VWF_AddressSize.16Bit16-bit address.
  • leading_zeros (optional): boolean: Whether to output leading zeros (true) or not (false). Default: false
Reads out a RAM address and prints its value to the text box as a decimal number. Depending on the address_size parameter, the address is either interpreted to be an 8-bit number (using a single byte) or a 16-bit number (using two bytes). When the leading_zeros parameter is set to true, leading zeros will be printed. Up to three total places for 8-bit numbers and up to five for 16-bit numbers.

%vwf_hex()

Usage
%vwf_hex(address)
Short Aliases
!hex(address) = %vwf_hex(address)
Parameters
  • address: number: The RAM/ROM address to read.
Reads out a RAM address and prints its value to the text box as a hexadecimal number.

Text Properties

%vwf_set_font()

Usage
%vwf_set_font(font_id)
Short Aliases
!font(font_id) = %vwf_set_font(font_id)
Parameters
  • font_id: number: The ID of the font to set.
Sets the currently active font. The same format and restrictions as in the vwf_font() header setting apply.

%vwf_char_offset()

Usage
%vwf_char_offset(offset)
Short Aliases
!char_offset(offset) = %vwf_char_offset(offset)
!chr_offset(offset) = %vwf_char_offset(offset)
Parameters
  • offset: number: The character offset to apply. (min: $0000, max: $FFFF)
Sets a character offset which is added to every single character printed to the text box (default value: $0000). Here's a simple example:
%vwf_char_offset($0010)
%vwf_char($01) : %vwf_char($02) : %vwf_char($03)
Normally, you would expect this to print characters $01, $02 and $03 to the text box, but due to the %vwf_char_offset($0010), what actually gets printed are characters $11, $12 and $13.

The main purpose of this command is to enable the usage of arbitrarily sized fonts. This is especially useful in 16-bit mode, where any of the regular font settings and commands are ignored. Imagine a scenario in which you have one font occupying font slots $00 to $03 (each containing $100 glyphs) and another occupying font slots $04 to $07. Running the patch in 16-bit mode, you could do something like this:
%vwf_text("Hello world!")
%vwf_char_offset($0400)
%vwf_text("Hello world!")
The first "Hello world!" here would be printed with glyphs starting at font slot $00, whereas the second "Hello world!" would be printed with glyphs starting at font slot $04, making it possible to print each of the strings in a different font. In 8-bit mode, this usually wouldn't be necessary, since you could just use %vwf_set_font($04) instead.

%vwf_change_colors()

Usage
%vwf_change_colors(start_color_no, color_values...)
Short Aliases
!edit_pal(start_color_no, color_values...) = %vwf_change_colors(start_color_no, color_values...)
Parameters
  • start_color_no: number: The number of the first color from the palette to overwrite. (min: $00, max: $FF)
  • color_values...: rgb15-color: One or more color values to write to the palette (separated by comma), in RGB15 format.
This command allows you to overwrite colors in the currently active palette. You can overwrite multiple colors at once, starting at start_color_no, by passing in a list of color values. The main purpose of this is to follow it up with a call to %vwf_set_text_palette() to effectively change the text color. Since this command modifies the active palette, using it carelessly will lead to unintended side effects (randomly changing colors on screen). Make sure to only ever overwrite colors that aren't currently visible anywhere on the screen. Once a text box closes, the patch will restore the original state of the palette from before opening any text box. See %vwf_get_color_index_2bpp() for help with specifying start_color_no.

%vwf_set_text_palette()

Usage
%vwf_set_text_palette(palette_index)
Short Aliases
!set_pal(palette_index) = %vwf_set_text_palette(palette_index)
!reset_color = %vwf_set_text_palette(!vwf_default_text_palette)
Parameters
  • palette_index: number: The index of the palette to set. (min: $00, max: $07)
Switches the currently active text palette to another one. Assumes 2BPP color palettes, so a value of $00 will give you the first four colors of Lunar Magic's palette, a value of $01 the second four colors and so on. Also overwrites color $01 of the selected palette (aka the second color) with the currently active text box background color, so the same restrictions apply as for %vwf_change_colors() (in other words, make sure not to overwrite any color currently visible on screen). This command is meant to be paired with %vwf_change_colors() to effectively switch the active text color. Also see vwf_space_width() for some additional pitfalls related to this command.

%vwf_set_text_color()

Usage
%vwf_set_text_color(palette_index, text_color_value)
Short Aliases
!set_color(palette_index, text_color_value) = %vwf_set_text_color(color_no, text_color_value)
Parameters
  • palette_index: number: The index of the 2BPP palette in which to overwrite colors. (min: $00, max: $07)
  • text_color_value: rgb15-color: The text color value to write to the palette, in RGB15 format.
This command is a shorthand way of calling both %vwf_change_colors() and %vwf_set_text_palette() and lets you switch the active text color more easily. It sets the text color (color $02) of palette palette_index to color text_color_value, sets the outline color (color $03) to black, sets the background color (color $01) to the currently active one, and then automatically switches the active text palette to palette_index. All restrictions that apply to %vwf_change_colors() and %vwf_set_text_palette() also apply to this command.

Text Flow

%vwf_line_break()

Usage
%vwf_line_break()
Short Aliases
!n = %vwf_line_break()
!lf = %vwf_line_break()
!break = %vwf_line_break()
!new_line = %vwf_line_break()
Inserts a line break into the text box. If the text has already reached the last line of the text box, the vwf_auto_wait() header setting dictates how to proceed before automatically clearing the text box.

%vwf_clear()

Usage
%vwf_clear()
Short Aliases
!clear = %vwf_clear()
Clears the text box. Following text being printed will start back at the first line of the text box.

%vwf_set_skip_location()

Usage
%vwf_set_skip_location()
Short Aliases
!skip_loc = %vwf_set_skip_location()
When the vwf_enable_skipping() header setting was set to true, this text command can be used to mark the destination of skipping. When pressing the Start button, the text box will immediately jump to the location in the message where this command was used. Can only be used once per message.

%vwf_close()

Usage
%vwf_close()
Short Aliases
!close = %vwf_close()
Closes the text box, restores backed up layer 3 and palette data, and resumes gameplay. It's normally not necessary to call this command explicitly, as each %vwf_message_end() already does so automatically. You only need to use it when you want to close a text box early (for example: from a specific choice of a %vwf_display_options()).

%vwf_wait_for_button()

Usage
%vwf_wait_for_button()
Short Aliases
!press_button = %vwf_wait_for_button()
Pauses the text box until the player presses any of the default text box advance buttons (defined by the !vwf_default_advance_button_mask setting).

%vwf_wait_for_a()

Usage
%vwf_wait_for_a()
Short Aliases
!press_a = %vwf_wait_for_a()
Pauses the text box until the player presses the A button. Deprecated. Use %vwf_wait_for_button() or %vwf_wait_for_custom_button() instead.

%vwf_wait_for_custom_button()

Usage
%vwf_wait_for_custom_button(button_mask)
Short Aliases
!press_custom_button = %vwf_wait_for_custom_button()
ControllerButton = VWF_ControllerButton
Parameters
  • button_mask: VWF_ControllerButton (bit-mask): Defines which buttons can advance the text box. Valid values:
    ValueDescription
    VWF_ControllerButton.AA button.
    VWF_ControllerButton.BB button.
    VWF_ControllerButton.XX button.
    VWF_ControllerButton.YY button.
    VWF_ControllerButton.StartStart button.
    VWF_ControllerButton.SelectSelect button.
    VWF_ControllerButton.LL button.
    VWF_ControllerButton.RR button.
    VWF_ControllerButton.DpadRightD-Pad right.
    VWF_ControllerButton.DpadLeftD-Pad left.
    VWF_ControllerButton.DpadDownD-Pad down.
    VWF_ControllerButton.DpadUpD-Pad up.
Pauses the text box until the player presses any of the buttons defined by the button_mask parameter. Multiple buttons can be specified as a bit-mask by using the | (or) operator. Example:
%vwf_wait_for_custom_button(VWF_ControllerButton.A|VWF_ControllerButton.B)

%vwf_wait_frames()

Usage
%vwf_wait_frames(num_frames)
Short Aliases
!wait_frames(num_frames) = %vwf_wait_frames(num_frames)
Parameters
  • num_frames: number: The number to frames to wait + 1. (min: 0, max: 255)
Pauses the text box for num_frames + 1 frames.

%vwf_set_text_speed()

Usage
%vwf_set_text_speed(speed)
Short Aliases
!set_speed(speed) = %vwf_set_text_speed(speed)
Parameters
  • speed: number: The number to frames to wait between characters + 1. (min: 0, max: 255)
Sets the text rendering speed. The speed is defined as the number of frames to wait between each character being printed.

%vwf_freeze()

Usage
%vwf_freeze()
Short Aliases
!freeze = %vwf_freeze()
!halt = %vwf_freeze()
Freezes the text box entirely. The only way to unfreeze it is to modify the text pointer directly from code. You can use MessageASM to do this. Consider this an advanced function.

%vwf_set_text_pointer()

Usage
%vwf_set_text_pointer(address)
Short Aliases
!jump(address) = %vwf_set_text_pointer(address)
Parameters
  • address: number: The address to set the text pointer to.
Modifies the text pointer (aka the location the patch is currently reading message data from). Can even be pointed to a RAM address (which could be useful for printing user-defined text, like a player name). When doing so, you should make sure the RAM address in question is already filled with the intended text data before the text box is opened. Filling it while the text box is active could lead to the word wrapping processor and the text renderer seeing different data, which could lead to unexpected word wrapping behavior. See vwf_inline() for how to define message data outside the scope of a message.

%vwf_display_message()

Usage
%vwf_display_message(message_no, show_close_anim, show_open_anim)
Short Aliases
!open_message(message_no, show_close_anim, show_open_anim) = %vwf_display_message(message_no, show_close_anim, show_open_anim)
!display_message(message_no, show_close_anim, show_open_anim) = %vwf_display_message(message_no, show_close_anim, show_open_anim)
Parameters
  • message_no: number: The message to display in the new message box. (min: $0000, max: $FFFF)
  • show_close_anim: boolean: Whether to play (true) or don't play (false) the close animation on the old text box. Default: false
  • show_open_anim: boolean: Whether to play (true) or don't play (false) the open animation on the new text box. Default: false
Closes the current text box and immediately opens a new one with another message. When show_open_anim is set to false, certain text box settings (such as selected frame, selected background or selected background color) won't be reloaded. Set it to true if you require them to be reloaded. You can use the VWF_BoxAnimation.Instant animation style on the new text box to make it appear as though it still appears instantaneously.

%vwf_display_options()

Usage
%vwf_display_options(unique_label_name, option_texts...)
Short Aliases
!options(unique_label_name, option_texts...) = %vwf_display_options(unique_label_name, option_texts...)
Parameters
  • unique_label_name: name: A label name identifying this options block. Must be unique per message box. May only contain the following characters:
    abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ _ 0123456789
  • option_texts...: vwf-text: One or more options to display.
Displays a list of options for the player to choose from, and jumps to different parts of the message depending on what selection they made. The label name must be a valid Asar label name and unique within that message. Supports up to 13 options in theory, but in practice, the number of options is limited by the height of your text box, with each line providing room for one option. Options passed to this command should either be %vwf_text() calls, or multiple text commands wrapped into %vwf_wrap() calls. Use the %vwf_set_option_location() command to set the target locations for each option (there must be at least one call to %vwf_set_option_location() per option passed to %vwf_display_options()). The !vwf_default_cursor_space setting in vwfconfig.cfg lets you control the margin in pixels between the cursor and the option text. The !vwf_default_cursor_char setting determines what character to use as the cursor. If you need to override either setting for just a single use of %vwf_display_options(), you can do so by overwriting the respective setting before calling the command and then restoring it to its original value afterwards. Please avoid putting any text commands into option texts that modify the text flow. Generally speaking, using commands from the Text Output, Text Properties or Text Macros categories should be fine, but using anything else will lead to undefined behavior.

%vwf_set_option_location()

Usage
%vwf_set_option_location(options_label_name, option_id)
Short Aliases
!opt_loc(options_label_name, option_id) = %vwf_set_option_location(options_label_name, option_id)
Parameters
  • options_label_name: name: The unique label name of the options block to set the jump location for.
  • option_id: number: The ID of the option to set the jump location for.
Sets the target destination for a specific choice of a %vwf_display_options() command. Upon selecting that choice, the text box will continue at the location where %vwf_set_option_location() was called. The options_label_name parameter must be identical to the unique_label_name passed to %vwf_display_options(). The option_id parameter specifies which choice you're setting the location for, starting at 0. So if you had the following %vwf_display_options() call
%vwf_display_options(MyOptions, %vwf_text("One"), %vwf_text("Two"), %vwf_text("Three"))
then calling
%vwf_set_option_location(MyOptions, 1)
would set the target location of the Two choice.

Gameplay Modifiers

%vwf_play_bgm()

Usage
%vwf_play_bgm(bgm_id)
Short Aliases
!play_bgm(bgm_id) = %vwf_play_bgm(bgm_id)
Parameters
  • bgm_id: number: The ID of the music to play (the value that gets written to $1DFB).
Switches the currently active background music by writing bgm_id to $1DFB. See SMW Central RAM Map for details.

%vwf_setup_teleport_to_level()

Usage
%vwf_setup_teleport_to_level(destination_level, is_midway)
Short Aliases
!teleport_to_level(destination_level, is_midway) = %vwf_setup_teleport_to_level(destination_level, is_midway)
Parameters
  • destination_level: number: The level number to teleport to. (min: $000, max: $1FF)
  • is_midway: boolean: Whether to enter the level at the midway entrance (true) or not (false).
Sets up a teleport to another level that will activate once the text box closes.

%vwf_setup_teleport_to_secondary_entrance()

Usage
%vwf_setup_teleport_to_secondary_entrance(destination_entrance, is_water_level)
Short Aliases
!teleport_to_secondary(destination_entrance, is_water_level) = %vwf_setup_teleport_to_secondary_entrance(destination_entrance, is_water_level)
Parameters
  • destination_entrance: number: The number of the secondary entrance to teleport to. (min: $0000, max: $1FFF)
  • is_water_level: boolean: Whether the destination is a water level (true) or not (false).
Sets up a teleport to a secondary entrance that will activate once the text box closes.

%vwf_setup_exit_to_overworld()

Usage
%vwf_setup_exit_to_overworld(mode)
Short Aliases
!exit_to_ow(mode) = %vwf_setup_exit_to_overworld(mode)
ExitToOwMode = VWF_ExitToOwMode
Parameters
  • mode: VWF_ExitToOwMode: How to exit the level. Valid values:
    ValueDescription
    VWF_ExitToOwMode.NoExitExit the level as if by pressing Start + Select (don't activate a level exit).
    VWF_ExitToOwMode.PrimaryExitActivate the primary level exit.
    VWF_ExitToOwMode.SecondaryExitActivate the secondary level exit.
Sets up an exit to the overworld that will activate once the text box closes.

Text Macros

%vwf_execute_text_macro()

Usage
%vwf_execute_text_macro(macro_name)
Short Aliases
!macro(macro_name) = %vwf_execute_text_macro(macro_name)
Parameters
Executes a previously registered text macro. See Regular Text Macros for details.

%vwf_execute_text_macro_by_indexed_group()

Usage
%vwf_execute_text_macro_by_indexed_group(group_name, index_address)
Short Aliases
!macro_group(group_name, index_address) = %vwf_execute_text_macro_by_indexed_group(group_name, index_address)
Parameters
  • group_name: string: The name of the group to index. That is, the name that was passed to %vwf_start_text_macro_group().
  • index_address: number: The address to use as an index.
Indexes a text macro group with the current value of a RAM address, and executes the resulting text macro. See Text Macro Groups for details.

%vwf_execute_buffered_text_macro()

Usage
%vwf_execute_buffered_text_macro(macro_id)
Short Aliases
!macro_buf(macro_id) = %vwf_execute_buffered_text_macro(macro_id)
Parameters
  • macro_id: number: The ID of the macro to execute. (min: 0, max: !vwf_num_reserved_text_macros-1)
Executes a previously registered buffered text macro. See Buffered Text Macros for details.

Advanced

%vwf_execute_subroutine()

Usage
%vwf_execute_subroutine(address)
Short Aliases
!execute(address) = %vwf_execute_subroutine(address)
!exec(address) = %vwf_execute_subroutine(address)
Parameters
  • address: number: The address of the routine to execute.
Executes an arbitrary code routine. The patch jumps to this routine via a jsl, so it needs to end in an rtl. Feel free to insert your custom routines directly into vwfmessages.asm (but always outside of a %vwf_message_start()/%vwf_message_end() pair, as the patch might interpret it as text data otherwise). NOTE: The routine is only executed once text rendering itself arrives at the location of this command, not whenever the word wrapping processor sees it. This means running any code inside the routine that will affect what text is being rendered (such as modifying the current text pointer) can lead to unexpected results (such as word wrapping in weird places), as the text being rendered might not match with what the word wrapping processor has previously seen.

Helper Functions

This section covers functionality that doesn't really fit into any other category, but can be useful in certain situations. Some helper functions can be used with both header arguments and text commands, others may be be useful when writing code for VWF dialogues. Read the description on each command for hints on how they might be useful.

Colors

rgb_15()

Usage
rgb_15(r, g, b)
Parameters
  • r: number: The value of the red color channel. (min: 0, max: 31)
  • g: number: The value of the green color channel. (min: 0, max: 31)
  • b: number: The value of the blue color channel. (min: 0, max: 31)
Defines a 16-bit color value in RGB15 format by separately specifying the values for the red, green and blue color channels.

rgb_15_from_24()

Usage
rgb_15_from_24(r, g, b)
Parameters
  • r: number: The value of the red color channel. (min: 0, max: 255)
  • g: number: The value of the green color channel. (min: 0, max: 255)
  • b: number: The value of the blue color channel. (min: 0, max: 255)
Defines a 16-bit color value in RGB15 format by separately specifying the values for the red, green and blue color channels as 8-bit values. This is useful since RGB24 (which uses 8-bit color channels) is the most common color format around today, so you can easily take color values from existing apps (like Microsoft Paint) and copy them directly into the patch. Note that not all RGB24 color values are expressible in RGB15, so in a lot of cases, the function will pick the closest matching color.

rgb_15_from_f()

Usage
rgb_15_from_f(r, g, b)
Parameters
  • r: number: The value of the red color channel. (min: 0.0, max: 1.0)
  • g: number: The value of the green color channel. (min: 0.0, max: 1.0)
  • b: number: The value of the blue color channel. (min: 0.0, max: 1.0)
Defines a 16-bit color value in RGB15 format by separately specifying the values for the red, green and blue color channels as decimal values. This is useful in cases where you want to express color channels as a percentage. The function will pick the closest matching color expressible in RGB15 for the given color channel values.

vwf_get_color_index_2bpp()

Usage
vwf_get_color_index_2bpp(palette_index, type)
Short Aliases
!text_color_0 = vwf_get_color_index_2bpp($00, VWF_ColorID.Text)
!text_color_1 = vwf_get_color_index_2bpp($01, VWF_ColorID.Text)
!text_color_2 = vwf_get_color_index_2bpp($02, VWF_ColorID.Text)
!text_color_3 = vwf_get_color_index_2bpp($03, VWF_ColorID.Text)
!text_color_4 = vwf_get_color_index_2bpp($04, VWF_ColorID.Text)
!text_color_5 = vwf_get_color_index_2bpp($05, VWF_ColorID.Text)
!text_color_6 = vwf_get_color_index_2bpp($06, VWF_ColorID.Text)
!text_color_7 = vwf_get_color_index_2bpp($07, VWF_ColorID.Text)

!outline_color_0 = vwf_get_color_index_2bpp($00, VWF_ColorID.Outline)
!outline_color_1 = vwf_get_color_index_2bpp($01, VWF_ColorID.Outline)
!outline_color_2 = vwf_get_color_index_2bpp($02, VWF_ColorID.Outline)
!outline_color_3 = vwf_get_color_index_2bpp($03, VWF_ColorID.Outline)
!outline_color_4 = vwf_get_color_index_2bpp($04, VWF_ColorID.Outline)
!outline_color_5 = vwf_get_color_index_2bpp($05, VWF_ColorID.Outline)
!outline_color_6 = vwf_get_color_index_2bpp($06, VWF_ColorID.Outline)
!outline_color_7 = vwf_get_color_index_2bpp($07, VWF_ColorID.Outline)
Parameters
  • palette_index: number: The index of the palette for which to retrieve a color index. (min: $00, max: $07)
  • type: VWF_ColorID: The type of color to retrieve the index for. Valid values:
    ValueDescription
    VWF_ColorID.TextText color.
    VWF_ColorID.OutlineOutline color.
Takes a desired palette index and a desired color type and returns the correct color index for them. The resulting value can be passed directly to commands like %vwf_change_colors(). The palette_index parameters of this function matches the palette_index parameter of %vwf_set_text_palette().

Text Commands

%vwf_wrap()

Usage
%vwf_wrap(commands...)
Parameters
  • commands...: text-command: The list of text commands to wrap.
Wraps an arbitrary number of text commands so that they can be passed to a macro as a single argument. This can be useful, for example, to pass multiple commands as a single option to %vwf_display_options(). Usage example:
!edit_pal(!text_color_5, rgb_15(6, 31, 6), rgb_15(0, 0, 0))
					
!options(SampleOptions,
	%vwf_wrap( !set_pal($05), !char($00AC), !reset_color, !str(" Bullet Point 1") ),
	%vwf_wrap( !set_pal($05), !char($00AC), !reset_color, !str(" Bullet Point 2") ),
	%vwf_wrap( !set_pal($05), !char($00AC), !reset_color, !str(" Bullet Point 3") ),
	%vwf_wrap( !set_pal($05), !char($00AC), !reset_color, !str(" Bullet Point 4") )
)

Advanced

%vwf_inline()

Usage
%vwf_inline(commands...)
Parameters
  • commands...: text-command: The list of text commands to compile.
Lets you compile text commands outside of messages. Normally, all text command macros throw an error when used outside of a %vwf_message_start()/%vwf_message_end() pair. However, when writing custom code for VWF Dialogues, there can be valid reasons for why you'd need to use commands outside of messages (for example: to create Buffered Text Macros). Wrapping commands into a %vwf_inline() call allows you to do so, by disabling the respective errors.

remap_ram()

Usage
remap_ram(address)
Parameters
  • address: number: The RAM address to remap.
Automatically remaps a RAM address as needed when applying the patch to an SA-1 ROM (and in theory, also a SuperFX ROM). This can be used to create messages that work consistently in both regular ROMs and SA-1 ROMs. In regular ROMs, the function will effectively "do nothing". In SA-1 ROMs, it will automatically remap the RAM address to the correct SA-1 equivalent. Usage example:
; This will turn into $7E0DBF in a regular ROM, but into $003DBF in an SA-1 ROM.
!str("Mario's current coins: ") : !dec(remap_ram($7E0DBF), AddressSize.8Bit, true) : !new_line

Text Macros

Text macros are a system for reusing text pieces (like names or commonly used phrases) in multiple places. This has a couple of advantages:

All text macros need to be registered once (outside of a message) and can then be called via the different Text Macro text commands.

Regular Text Macros

Regular text macros are the simplest form of text macros. They simply wrap an arbitrary number of text commands into a single call. Use the %vwf_register_text_macro() macro to define a regular text macro.

%vwf_register_text_macro()

Usage
%vwf_register_text_macro(unique_macro_name, commands...)
Parameters
  • unique_macro_name: name: The name that identifies this text macro. Must be globally unique. May only contain the following characters:
    abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ _ 0123456789
  • commands...: vwf-text: One or more text commands to wrap in this macro.
Registers a regular text macro. Pass the same unique_macro_name to %vwf_execute_text_macro() to execute this macro in messages.

Here's a simple example to demonstrate the usage of text macros:
%vwf_register_text_macro("Mario", !str("Mario") )
%vwf_register_text_macro("Luigi", !str("Luigi") )

%vwf_message_start(0050)	; Message 104-1

	%vwf_header()
	
	!str("My name is ") : !macro("Mario") : !str(" ") : !macro("Mario")
	!str(", and this here is my brother ") : !macro("Luigi") : !str(" ") : !macro("Mario") : !str("!")
	!press_button
	
%vwf_message_end()
Text macros can also be nested. In other words, you can register text macros that call other, previously registered text macros, which makes them really flexible and powerful.

Text Macro Groups

Text macro groups are a mechanism for assigning previously registered text macros to groups that can then be indexed via RAM addresses. Put another way: Text macro groups provide a means of turning the value of a RAM address into a text string representing that value. There's many potential use cases for this. A very intuitive one would be some kind of inventory system. Imagine your game featured an inventory where the player could collect different items. In RAM, the items would probably be stored as some kind of table, with one byte specifying the type of each item. You could then use text macro groups to turn the value of said byte into the name of that item. To register a text macro group, use the %vwf_start_text_macro_group() and %vwf_end_text_macro_group() macros and insert one or more calls to %vwf_add_text_macro_to_group() inbetween them.

%vwf_start_text_macro_group()

Usage
%vwf_start_text_macro_group(unique_group_name)
Parameters
  • unique_group_name: name: The name that identifies this text macro. Must be globally unique. May only contain the following characters:
    abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ _ 0123456789
Starts a new text macro group. Use the %vwf_add_text_macro_to_group() macro to add text macros to this group. Pass the unique_group_name specified here to %vwf_execute_text_macro_by_indexed_group() to index this group in messages.

%vwf_add_text_macro_to_group()

Usage
%vwf_add_text_macro_to_group(macro_name)
Parameters
  • macro_name: name: The name of the text macro to add to the current text macro group. Must have been previously registered via %vwf_register_text_macro() and match the unique_macro_name parameter passed to it.
Adds a new text macro to the current text macro group. Its index within the group depends on the order of %vwf_add_text_macro_to_group() calls. The first call will be index 0, the second call index 1 and so on.

%vwf_end_text_macro_group()

Usage
%vwf_end_text_macro_group()
Ends the current text macro group.

Here's an advanced example, combining different text macro functionality (regular text macros, text macro groups, nested text macros) in a practical way to create some super handy text macros:
; Registers text macros for Mario's and Luigi's names
%vwf_register_text_macro("MarioName", !str("Mario") )
%vwf_register_text_macro("LuigiName", !str("Luigi") )

; Registers text macros for the different power-up states of Mario and Luigi
%vwf_register_text_macro("SmallPowerup", !str("Small") )
%vwf_register_text_macro("SuperPowerup", !str("Super") )
%vwf_register_text_macro("CapePowerup", !str("Cape") )
%vwf_register_text_macro("FirePowerup", !str("Fire") )

; Adds Mario's and Luigi's names to a new "PlayerName" group.
%vwf_start_text_macro_group("PlayerName")
	%vwf_add_text_macro_to_group("MarioName")
	%vwf_add_text_macro_to_group("LuigiName")
%vwf_end_text_macro_group()

; Adds the different powerup states to a new "PlayerPowerup" group.
%vwf_start_text_macro_group("PlayerPowerup")
	%vwf_add_text_macro_to_group("SmallPowerup")
	%vwf_add_text_macro_to_group("SuperPowerup")
	%vwf_add_text_macro_to_group("CapePowerup")
	%vwf_add_text_macro_to_group("FirePowerup")
%vwf_end_text_macro_group()

; Registers a convenience macro for indexing the "PlayerName" group.
; $7E0DB3 contains the current player ID.
; 0: Mario
; 1: Luigi
; See SMW Central RAM map for details.
%vwf_register_text_macro("CurrentPlayer", !macro_group("PlayerName", remap_ram($7E0DB3)))

; Registers a convenience macro for indexing both the "PlayerName" and the "PlayerPowerup" groups.
; $7E0019 contains the power-up state of the current player.
; 0: None
; 1: Mushroom
; 2: Cape
; 3: Fire Flower
; See SMW Central RAM map for details.
%vwf_register_text_macro("CurrentPlayerWithPowerup", !macro_group("PlayerPowerup", remap_ram($7E0019)), !nbsp, !macro("CurrentPlayer"))


%vwf_message_start(0050)	; Message 104-1

	%vwf_header()
	
	; Let's assume you're currently playing as Luigi and have a Cape power-up. Then this message will read:
	; "Hey, aren't you Luigi? Cape Luigi, to be specific."
	!str("Hey, aren't you ") : !macro("CurrentPlayer") : !str("? ") : !macro("CurrentPlayerWithPowerup") : !str(", to be specific.")
	!press_button
	
%vwf_message_end()

Buffered Text Macros

Buffered text macros function similarly to regular text macros, with the main difference being that they are constructed at runtime and not patched into the ROM. This makes it possible to have dynamic text macros in the game. A classical example for this would be a player name generated from a name entry screen. The name could be stored in a buffered text macro and then displayed via the %vwf_execute_buffered_text_macro() text command.

Consider this an advanced feature, as it requires some coding knowledge to make meaningful use of. To register buffered text macros, call the shared routines VWF_ResetBufferedTextMacros, VWF_BeginBufferedTextMacro, VWF_AddToBufferedTextMacro and VWF_EndBufferedTextMacro (their usage is documented in code right next to them, so I'll skip a detailed documentation here).

See Shared Routines for details.

Return to Index

Advanced Functionality

This section is intended for advanced users only. That is, people who want to write custom resources (sprites, blocks, patches etc.) that make use of the patch or who want to use the patch in some complex ways. In other words: If you aren't a coder, you can most likely just ignore this entire section.

Display Messages From Custom Code

While the VWF Dialogues patch provides a pretty powerful text system for your hack, the only built-in method of actually opening text boxes is via the message box hijack. However, not everyone wants to override SMW's default message boxes with VWF text boxes, and some people may want to display VWF text boxes from other places, like interactive NPCs or story events. In other words: There's a number of good reasons for wanting to open VWF text boxes from your custom code, and luckily, the patch makes this very easy to do.

If you're just an end user, you don't need to bother with any of that. I recommend searching SMW Central instead for resources that already offer support for VWF Dialogues. A popular example would be WYE's NPCs sprites. This section is only relevant to you if you're making your own resources and want to open VWF text boxes from them.

As already mentioned, doing so is thankfully very simple and only requires you to call the VWF_DisplayAMessage shared routine from your own code. See section Shared Routines on details for how to use shared routines. Usage of the routine is documented in code right next to it, but calling it is usually as simple as:

lda.b #MessageNumber
ldx.b #MessageNumber>>8
jsl VWF_DisplayAMessage

MessageASM

MessageASM is an optional feature that allows you to to add code routines to messages. These routines are called every frame as long as a text box with that specific message is open. Think of it as UberASM, but tied to message numbers instead of level numbers. Enabling MessageASM is as simple as setting the vwf_enable_message_asm setting to true and adding a routine called MessageASMXXXX to the code, where XXXX must be the ID of the message for which MessageASM was enabled. This routine can go into your vwfmessages.asm file if desired, but never directly inside a message body. It also must end in an rtl. Here's a simple example:

%vwf_message_start(0050)	; Message 104-1

	%vwf_header(enable_message_asm(true), freeze_game(false))
	
	!str("Something is happening right now!")
	
%vwf_message_end()

MessageASM0050:
	inc remap_ram($19)
	rtl
Since MessageASM can run any code, there's almost no limits for what can be done with it. You can even use it to mess with the patch directly, either by calling shared routines or by accessing a number of useful defines (some of which are detailed below). To list a few examples of what can be achieved, using MessageASM smartly allows you to create custom menus, display character portraits, automatically display a speaker's name at the start of a text box, or move/animate sprites.

Some useful VWF RAM addresses to use with your MessageASM code:

!vwf_message_was_skipped = Is set to a non-zero value when a message has been skipped with the Start button. Otherwise it's zero.

!vwf_skip_message_flag = Is non-zero if the current message is allowed to be skipped.

!vwf_l3_priority_flag = Contains a backup of the layer 3 priority bit before the text box was displayed. Modify this to affect layer 3 once the text box disappears.

!vwf_l3_transparency_flag = Contains a backup of the layer 3 color math settings before the text box was displayed. Modify this to affect layer 3 once the text box disappears.

!vwf_l3_main_screen_flag = Contains a backup of the layer 3 mainscreen setting before the text box was displayed. Modify this to affect layer 3 once the text box disappears.

!vwf_l3_sub_screen_flag = Contains a backup of the layer 3 subscreen setting before the text box was displayed. Modify this to affect layer 3 once the text box disappears.

!vwf_at_start_of_text = Is set to 01 when a text box is cleared, 00 when text parsing begins. Use this to initialize code related to individual text boxes.

Shared Routines

Shared routines are a mechanism for writing routines that can be used by both the VWF Dialogues patch itself, as well as any other resources that want to work with it. The simplest example here would be a routine for displaying a text box, which the patch itself needs for its message box hijack, but which other resources (like an NPC sprite) might also want to call. Currently, the patch uses its own, somewhat ugly implementation for handling shared routines. To do this, it writes a mapping table of routine names and locations into the ROM. A shared .asm file, which reads this table back in, then needs to be included in other resources. There's a few caveats with this solution, so the hope is that a future version of Asar can provide built-in support for shared routines directly and thus remove many of them. Anyways, here's a brief explanation on how to utilize them.

First of all, to use shared routines in another resource, you need to copy the file code/external/vwfsharedroutines.asm next to it. If the resource in question is for a tool that doesn't use Asar 1.90 or newer yet, copy the file code/external/old_asar/vwfsharedroutines.asm instead (confirmed to work in Asar 1.81). Now incsrc the file you copied into your resource. However, since this file reads the locations of routines from ROM, this requires VWF Dialogues to always be patched to it before the other resource. If you plan to release a resource accessing a shared routine, it's a good idea to mention this fact in your Readme. As an additional safety measure, your resource can check for the existence of specific defines, which indicate that a shared routine has been found. Here is a simple example. It demonstrates how to display text boxes from custom code (probably 99% of use cases for shared routines):

incsrc "vwfsharedroutines.asm"
				
if defined("vwf_shared_routine_VWF_DisplayAMessage_exists")
	lda.b #MessageNumber
	ldx.b #MessageNumber>>8
	jsl VWF_DisplayAMessage
else
	; If VWF Dialogues support is optional in your resource,
	; you can leave out this error entirely and do something else here.
	error "VWF_DisplayAMessage shared routine wasn't found - please patch VWF Dialogues to this ROM first."
endif

If any shared routines were found by the other resource, it will print out some information on them automatically, thanks to the vwfsharedroutines.asm include. This makes it easier for end users to see when a resource has been inserted correctly. The addresses here should match the addresses printed by the VWF Dialogues patch itself. Here's an example of what it might look like: Screenshot

To write your own shared routines, or get an overview over all the available ones, open the file vwfroutines.asm. Each call to the %vwf_register_shared_routine() macro here defines one shared routine, with the argument to the macro being the name of the routine. You can jsl to that name either from directly within VWF Dialogues or from your own resources to call the respective routine. The comments above each routine document what they do and how to use them. To add a new routine, simply define it by adding another call to the %vwf_register_shared_routine() macro at the end of vwfroutines.asm, ending in an rtl. However, there's a few pitfalls you need to be aware of:

Return to Index

Problem Solving

This section lists some tips that can help you improve the patch's performance or deal with problems that you might run into while using it. It's a good idea to check it out whenever you're stuck with something.

Better Error Messages

Ever since version 1.3, the VWF Dialogues patch is operated entirely via macros, functions and defines. The intention of this is primarily to improve usability of the patch, by giving end users readable command names instead of magic hex numbers and by having the patch validate command arguments where possible. However, this also has some drawbacks, which come mainly in the relatively unhelpful way that Asar displays error messages. Whenever Asar throws an error, it only prints the bottom-most and top-most entries of the call stack that led to it. In the case of an incorrect argument passed to a text command macro, an error will be generated inside the macro, so that's the location Asar will display. See the example below: Screenshot As you can imagine, this is pretty unhelpful to users of the patch. You will only know what kind of error occurred, but not where. To understand that, you'd need access to a larger part of the error call stack. Thankfully, Asar versions 2.0+ (unreleased as of the writing of this manual) provide a method to get just that. By passing the --full-error-stack command line option to Asar when applying the patch, it will display full call stacks whenever an error or warning occurs. Here is what that looks like in practice: Screenshot As you can see, with this option enabled, Asar still displays the error to you first, but then gives you a full error call stack that shows you where exactly in vwfmessages.asm the offending call can be found (in the case of the screenshot above, line 100). If Asar version 2.0 or higher are available to you, it's recommended to always operate the patch with this option enabled.

Migration

This section attempts to walk you through the process of migrating from older versions of the patch to the current version. This is typically necessary if you have a WIP hack that is already using an older version of VWF Dialogues, but want to use features only found in a newer version.

From Version 1.2 or Earlier

When I originally started refactoring this patch to make use of Asar 1.90 variadic macros, backwards-compatibility with older patch versions was still one of my main goals. I wanted to make it easy for all version 1.2 (or earlier) users of the patch to migrate to version 1.3+. Over time, as I kept adding more and more improvements to 1.3, this goal kept moving further and further out of reach.

Technically speaking, version 1.3 is binary-compatible with messages from version 1.2, but it just includes so many changes to its general format that writing a straight-forward migration guide became too complex of a task for me. Therefore, I made the decision to declare version 1.3 as incompatible with version 1.2.

So what does this mean for you? Well, if you're making a new hack from scratch or working on a hack that has never used VWF Dialogues before, it doesn't really matter. Just use the newest version of the patch that's available. However, if you're working on a hack that's already using an older version of VWF Dialogues, you now basically have two options. Either you stick with the old patch version (and whatever bugs it might have), or you manually port over everything from the old to the new version, which basically involves recreating all your message boxes and resources in the format of the new version.

As I said, there's unfortunately no easy way of migrating to newer patch versions. However, on the positive side, version 1.3 of the patch was designed in a way that makes it a lot easier to extend in the future without breaking compatibility, so once you go through the effort of migrating, you'll hopefully never have to do it again to that degree for newer versions.

From Version 1.3 or Later

To migrate from version 1.3+ to a newer version of the patch, first open the vwfconfig.cfg files of both patch versions. Search the newer version for settings missing in the older version and copy all of them over (a diffing tool could help with finding the differences here). Next, take all the contents of the old patch version's data directory and and copy them into the data directory of the new version, overwriting all existing files.

You should now be able to continue working in the new version of the patch.

Bank Limits

SNES ROMs are stored as banks containing 32768 bytes of memory each. For almost all practical purposes, crossing a bank border with a resource or code is a problem and leads to bugs, so Asar contains built-in checks that detect bank-crossing and throws an error whenever it happens. In the case of VWF Dialogues, the only thing that can potentially cause a bank border to be crossed are resources. Thankfully, this shouldn't be much of a problem with fonts. Since each font only supports 256 glyphs, graphics file should never go above 16384 bytes in size, and width tables will be exponentially smaller than that, so graphics file plus width table should always fit into a single bank. The %vwf_add_font() macro makes use of Asar's freedata command, which automatically puts all fonts into their own banks.

That leaves only message files. Since they grow in size with every single message or piece of text added, they have a very real chance of exceeding the bank size limit. An average hack is unlikely to ever run into this limitation, because 32768 bytes amount to a lot of text. However, if you're creating a particularly text- and story-heavy hack, you might run into this issue eventually. This is what it might look like: Screenshot Thankfully, the fix for this, too, is pretty simple. Just create a new messages file next to the existing one. Let's say vwfmessages2.asm. In vwfconfig.cfg, include this file inside the vwf_define_data macro, like so:

%vwf_add_messages("data/vwfmessages2.asm", "data/fonts/vwftable.asm")
And then simply start moving entire messages from your first vwfmessages.asm file to your second vwfmessages2.asm file until the error goes aways. From here on out, use vwfmessages2.asm whenever adding new messages. When you edit a message in vwfmessages.asm and the error pops up again, move that entire message over to vwfmessages2.asm.

Conflicts With HDMA Effects

This patch makes use of DMA transfers. DMA transfers share their channels with HDMA. This means they will influence any HDMA effects that use the same channels as them. In non-SA-1 ROMs, the DMA transfers in this patch use channel 0 (%00000001) by default. In SA-1 ROMs, they use channel 2 (%00000100). If you experience problems with HDMA effects while a text box is open, you might be able to resolve them by avoiding to use the respective channels in other patches. If that doesn't help or isn't possible, you can also try tweaking the !vwf_main_dma_channel and !vwf_main_dma_channel_sa1 settings to move VWF Dialogues DMAs to a different channel (though this could potentially cause conflicts in other places). Possible channels are 0 to 7. Read an HDMA tutorial for further information on this subject.

Compatibility With Other Patches

The following patches are expected to be compatible:

The following patches require specific settings to work around compatibility issues: The following patches have a few compatibility quirks which can be easily worked around:

Return to Index

Known Bugs

Return to Index

Contribute, Report Bugs & Request Features

Did you find a bug that wasn't listed in the Known Bugs section, or do you have a suggestion or a feature request for the patch? If so, please file an issue on GitHub! (You can also contact me on SMW Central, but filing an issue will make sure your input won't get lost). If you want to contribute to the patch yourself, you can also do so via that repository by submitting a pull request.

Return to Index

Version History

Version 1.4x - 12/31/2024

Contributors:
  • RPG Hacker
  • Hayashi Neru
Changes:
  • Fixed a few incorrect mappings in vwftable.asm.

Version 1.4 - 02/23/2024

Contributors:
  • RPG Hacker
  • Yoshifanatic
Changes:
  • Renamed "VWF Dialogues Patch" to just "VWF Dialogues".
  • Fixed a copy-paste error in manual.
  • Fixed: SA-1 ROMs didn't hide reserve item while a dialog was open.
  • Added a tab to vwftable.asm (it maps to the same character as a space).
  • Fixed: Word-wrapping could break when combining text macros with centered text.
  • Fixed: A bug with how the main screen register was being written could lead to (essentially) random layer priorities. The bug was noticed in a level using level mode 0E, but could have affected other modes as well.
  • Added note on another known bug that was recently discovered.
  • Optimized performance of patch in V-Blank to reduce the chance of graphical bugs occurring from the interaction with other patches.
  • Optimized performance of some VWF core functionality, including text generation.
  • Added new !vwf_backup_duration_in_frames setting, which allows reducing the patch's V-Blank duration in the initialization step at the cost of longer start-up times for text boxes.
  • Reduced the amount of time the patch spends in V-Blank for smaller text boxes during the text box animation phase. This is achieved by only copying enough tiles to VRAM to cover the visible area of the text box (previous versions always copied an entire screen worth of tiles).
  • Added new !vwf_clear_screen_duration_in_frames setting, which can reduce the amount of time the patch spends in V-Blank during text box clears at the cost of extending their duration to multiple frames.
  • Fixed: The patch wrote to the color math register mirror in incorrect ways. In levels using transparent layers, this could lead to layers becoming non-transparent and staying that way even after a text box closed. The bug was noticed in a level using level mode 1E, but could have affected other modes as well.
  • Added the %vwf_wait_for_button() and %vwf_wait_for_custom_button() text commands, the VWF_AutoWait.WaitForButton auto-wait mode, as well as the !vwf_default_advance_button_mask, !vwf_select_choice_button_mask and !vwf_skip_message_button_mask settings, which give finer control over which buttons affect the patch. These features replace the %vwf_wait_for_a() text command and the VWF_AutoWait.WaitForA auto-wait mode, which are now deprecated.
  • The maximum value for the VWF_AutoWait.WaitFrames auto-wait mode has been extended from 254 to 255.
  • Simplified many multiplications in the patch. For most of them, this slightly boosts performance. More importantly, this removes any dependency on the mode 7 registers for multiplication, which avoids a potential rare bug that could be caused by HDMA.
  • Text box properties (background pattern, background color and frame) can now be overridden by message headers. This functionality is available via the vwf_text_box_bg_pattern(), vwf_text_box_bg_color() and vwf_text_box_frame() header settings.
  • Added the rgb_15_from_24() and rgb_15_from_f() helper functions.
  • Implemented shared headers, which provide a means of reusing message headers, reducing the size of a message in the process.
  • Added a version of vwfsharedroutines.asm that's compatible with Asar 1.81 and can be used with NPCs v4.3.
  • Improved compatibility with several status bar replacement patches. Super Status Bar and Sprite Status Bar are confirmed to work out of the box. DKCR Styled Sprite Status Bar also works out of the box and no longer requires its VWF Dialogues compatibility mode to be enabled. SMB3 Status Bar and Minimalist Status Bars both work out of the box, but produce some graphical glitches that can be eliminated by tweaking certain settings in vwfconfig.cfg. Remove Status Bar requires a compatibility setting and needs to be patched before VWF Dialogues. See section Compatibility With Other Patches for further information.

Version 1.32 - 07/12/2023

Contributors:
  • RPG Hacker
Changes:
  • Changed the default setting for !vwf_var_ram_sa1. The old setting pointed to an area within the GFX decompression buffer. Decompressing sufficiently large graphics (like player ExGFX) could cause the patch's memory to be trampled, causing it to malfunction.

Version 1.31 - 07/10/2023

Contributors:
  • RPG Hacker
  • Yoshifanatic
  • Telinc1
Changes:
  • Fixed multiple crashes in the patch when running an SA-1 ROM in latest Snes9x versions (confirmed with at least 1.62), which was caused by attempting to execute BW-RAM.

Version 1.3 - 07/07/2023

Contributors:
  • Yoshifanatic
  • RPG Hacker
Changes:
  • Completely reworked message format. Messages are now constructed via macros/defines instead of magic hex values. The patch now requires Asar 1.90 or higher.
  • Fixed an oversight where various aspects of layer 3 (transparency, priority, main/subscreen status) were not being preserved.
  • Added MessageASM functionality to allow one to run custom code on a per-message basis.
  • Added the ability to modify the text pointer using the start button.
  • Added a text macro system, allowing one to define strings of text/commands to be called at any time in a message.
  • Added an extra step to message initialization that initializes all the VWF variables on message load, not just on title screen load.
  • Added command byte $EB (%vwf_freeze() text command) that forces a textbox to freeze until something modifies the text pointer.
  • Added command bytes $E8 and $E7 for the text macro system and that act like a JSR and RTS to the textbox system, respectively.
  • Added several useful routines that can be called from within messages, such as a text buffering routine.
  • Made it so that the textbox will be forced to close when the screen fades out. The fadeout will also be delayed until the textbox closes.
  • Added some functionality that enables the textbox to close if another message is being set to display
  • Changed the hijack location for initializing the VWF RAM on the title screen from $0086E2 to $0096B4, because the former location was very questionable.
  • Fixed certain incompatibilities with Vitor Vilela's SA-1 Pack Patch v1.30 and up.
  • Adjusted the $EF (teleport) text command to work with secondary entrances $0200-$1FFF, levels using Lunar Magic 3.00 custom level dimensions, and layer 2 horizontal levels.
  • Added a RAM flag that indicates that the text box has just been cleared.
  • Added placeholder text to messages with no content, which makes it easier for players to report them to hack creators.
  • Cut RAM usage in half by optimizing how the text tiles are buffered.
  • Several small code optimizations.
  • Overall patch cleanup - made some places in the patch more readable and more intuitive, using newer Asar features.
  • Fixed several incompatibilities - patch should no work on newest versions of Higan/BSNES, as well as on sd2snes.
  • Changed the way the "freeze sprites" setting works. As a result, the smoke clouds in Yoshi's House can no longer glitch while a dialog box is open.
  • When specifying "wait x frames" for the auto wait header setting, the patch will now wait 1 frame less, giving the setting an effective range of $01 to $FE instead of $02 to $FF.
  • The "display message" command now has an option to play the box creation animation again (which will also reload certain text box settings).
  • Pointer tables for messages are now generated automatically.
  • Hex and decimal number functions no longer require 0123456789ABCDEF to be the first characters in the font, but rather use character mapping table files to determine the correct characters to use.
  • Character mapping table now supports a bunch of special characters, as well as Japanese (both available from Asar 2.0 onwards).
  • Added new character offset command, which allows applying an offset value to every single character being rendered. Useful for creating fonts with a custom number of characters.
  • Fixed: When running in 16-bit mode and displaying a 16-bit decimal number, the thousands digit didn't work and displayed a random character instead.
  • Added a %vwf_setup_exit_to_overworld() text command.
  • Text palette assignment no longer automatically resets whenever the text box is cleared and now only does so when a new message is loaded.

Version 1.2 - 05/03/2018

Contributors:
  • ExE Boss
  • RPG Hacker
  • randomdude999
Changes:
  • Merged changes from the SA-1 converted version.
  • Converted to a hybrid patch.
  • Updated code style to match the rest of RPG Hacker’s patches.
  • Updated the Readme to look good.
  • Fixed a few things in the Readme and updated some of the outdated information.
  • Fixed and improved the Readme and renamed it to manual.
  • Fixed a typo in vwfmessagepointers.asm.
  • Fixed the broken option selection cursor.
  • Fixed issue when using $F4 to display character $FF.
  • Added a RAM flag to allow closing the dialogue mid-message.
  • The SRAM expansion patch won’t accidentally contract the SRAM size.
  • Added a python script for generating a character width table.

Version 1.01 - 07/06/2014

Contributors:
  • Vitor Vilela
Changes:
  • Fixed palette issues with accurate emulators
  • Changed the channel used in DMA transfers to 0.
  • Fixed cursor sometimes not disappearing when moving.

Version 1.0B - 01/16/2012

Contributors:
  • Alcaro
Changes:
  • Converted to Asar format

Version 1.0 - 11/13/2010

Contributors:
  • RPG Hacker
Changes:
  • Initial Release

Return to Index