File select menu printing + Customizable Y printing - Missing Alphabet's cursoring (#59)

* Feature/fileselect (#58)

* Start file select notes

* Blank out file select tileset template

* Preliminary string printing

Had to change the signature of the base
print_chr function because the file select
screen uses a lot of non-standard memory
layouts. For example, the tilemap has a
variable width instead of the standard 32
tiles.

* Include string data in linker script

* Update notes

* Print the full array

* Add external calls

* Add FILE_SELECT struct

* Add format_file_string

* Widen main file select window

* Format full text speed string

* Add build badges to readme

* Oops on the master badge link

* Update README

* Fix file select not showing any info because of wrong palette.

* Make it so before printing the tiles are properly cleared

* Commit for the day. Missing Delete and Copy from File Select menu

* Add Delete and Copy

Also document all windows for future

* Setup basic alphabet - Need cursoring

* Add support for not-multiple-of-8-Ys to print_character_with_callback

* Add support to extra Y tile if and only if it's needed to print_character_with_callback

* Improve cursoring for new Y

* Add summary support
This commit is contained in:
Lorenzooone 2019-08-08 21:07:24 +02:00 committed by jeffman
parent 0379bee7f5
commit 9018780401
14 changed files with 796 additions and 28 deletions

View File

@ -27,7 +27,7 @@ A few years after that, I tried it again from scratch with the intent of having
This project aims to both complete the VWF codebase and to provide a tool for translating the game's dialogue. My new intent is to bring the hack to a state where I can just sit down and translate text efficiently in my spare time with a graphical tool. Not only that, but having such a tool means that other people can contribute! This project aims to both complete the VWF codebase and to provide a tool for translating the game's dialogue. My new intent is to bring the hack to a state where I can just sit down and translate text efficiently in my spare time with a graphical tool. Not only that, but having such a tool means that other people can contribute!
## Screenshots ## Screenshots
![](./screenshots/itshappening2.png) ![](./screenshots/itshappening4.png) ![](./screenshots/itshappening5.png) ![](./screenshots/m2-status2.png) ![](./screenshots/itshappening2.png) ![](./screenshots/itshappening4.png) ![](./screenshots/itshappening5.png) ![](./screenshots/m2-status2.png) ![](./screenshots/m2-battle-slugs.png) ![](./screenshots/m2-fileselect.png)
# Building # Building
@ -52,7 +52,7 @@ This project aims to both complete the VWF codebase and to provide a tool for tr
- Windows: grab the latest release [here](https://github.com/Kingcom/armips/releases) and copy the executable to `bin/armips.exe`. - Windows: grab the latest release [here](https://github.com/Kingcom/armips/releases) and copy the executable to `bin/armips.exe`.
- Linux: follow the [README](https://github.com/Kingcom/armips/blob/master/Readme.md) to build `armips` and copy the executable to `bin/armips`. - Linux: follow the [README](https://github.com/Kingcom/armips/blob/master/Readme.md) to build `armips` and copy the executable to `bin/armips`.
2. Building the ROM 2. Building the ROM
1. Run `build.ps1` (like in Step 4). 1. Run `build.ps1`.
2. The default compiled ROM is copied to `bin/m12.gba`. 2. The default compiled ROM is copied to `bin/m12.gba`.
3. (Optional) Build the GUI script tool: 3. (Optional) Build the GUI script tool:
1. `dotnet build tools/ScriptTool` (don't set the output directory) 1. `dotnet build tools/ScriptTool` (don't set the output directory)

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -22,7 +22,9 @@ int get_tile_number(int x, int y)
{ {
x--; x--;
y--; y--;
return m2_coord_table[x + ((y >> 1) * 28)] + (y & 1) * 32; if(y > 0xF)
y = 0xE + (y & 1);
return m2_coord_table[x + ((y >> 1) * 28)] + (y & 1) * 32; //This is... Very not suited for tilemaps of variable width, which can have more than 0x10 tiles vertically.
} }
int get_tile_number_with_offset(int x, int y) int get_tile_number_with_offset(int x, int y)
@ -52,14 +54,107 @@ byte reduce_bit_depth(int row, int foreground)
return lower | (upper << 4); return lower | (upper << 4);
} }
void print_file_string(int x, int y, int length, byte *str, int unknown) // x,y: tile coordinates
void clear_tile_file(int x, int y, int pixels, int tile_offset_file)
{ {
int *tilesetBasePtr = (int *)(0x82B79B4 + (unknown * 20)); // Clear pixels
int tileIndex = get_tile_number(x, y) + tile_offset_file;
if(((tileIndex << 3) != (0xC9C0 >> 2)) && ((tileIndex << 3) != (0xC9E0 >> 2)))
cpufastset(&pixels, &vram[tileIndex * 8], CPUFASTSET_FILL | 8);
}
// x,y: tile coordinates
void clear_rect_file(int x, int y, int width, int height, int pixels, int tile_offset_file, unsigned short *tilesetDestPtr)
{
for (int tileY = 0; tileY < height; tileY++)
{
for (int tileX = 0; tileX < width; tileX++)
{
if((tilesetDestPtr[x + tileX + ((y + tileY) * width)] & 0x3FF) != 0x95)
clear_tile_file(x + tileX, y + tileY, pixels, tile_offset_file);
else
break;
}
}
}
void wrapper_file_string(int x, int y, int length, byte *str, int window_selector)
{
m2_cstm_last_printed[0] = window_selector; //First time setup
print_file_string(x, y, length, str, window_selector, 0);
}
void wrapper_delete_string(int x, int y, int length, byte *str, int window_selector)
{
print_file_string(x, y, length, str - 0x20 + 0x40 - 0x15, window_selector, 0x6000);
}
void wrapper_name_string(int x, int y, int length, byte *str, int window_selector)
{
char String[length];
for(int i = 0; i < length; i++)
{
if(str[i] == 0xFD)
String[i] = 0x70;
else if(str[i] == 0xF1)
String[i] = 0x53;
else
String[i] = str[i];
}
print_file_string(x, y, length, String, window_selector, 0x7800);
}
void wrapper_name_summary_string(int x, int y, int length, byte *str, int window_selector)
{
char String[length];
for(int i = 0; i < length; i++)
String[i] = str[i];
print_file_string(x, y, length, String, window_selector, 0x2800);
}
int count_pixels(byte *str, int length)
{
int pixels = 0;
for(int i = 0; i < length; i++)
if((str[i] != 0xFF) && (str[i] != 0xFE)) //The latter one is not really needed
pixels += (m2_widths_table[0][decode_character(str[i])] & 0xFF);
int tiles = pixels >> 3;
if((pixels & 7) != 0)
tiles +=1;
return tiles;
}
void wrapper_copy_string(int x, int y, int length, byte *str, int window_selector)
{
print_file_string(x, y, length, str, window_selector, 0x6000);
}
void clearArr(int x, int y, int width, unsigned short *tilesetDestPtr)
{
for(int i = x; i < width - 2; i++)
{
if((tilesetDestPtr[i + (y * width)] & 0x3FF) != 0x95)
{
tilesetDestPtr[i + (y * width)] = 0x13F;
tilesetDestPtr[i + ((y+1) * width)] = 0x13F;
}
else
break;
}
}
void print_file_string(int x, int y, int length, byte *str, int window_selector, int offset)
{
int *tilesetBasePtr = (int *)(0x82B79B4 + (window_selector * 20));
int width = tilesetBasePtr[2]; int width = tilesetBasePtr[2];
unsigned short *tilesetDestPtr = (unsigned short *)(tilesetBasePtr[0]); unsigned short *tilesetDestPtr = (unsigned short *)(tilesetBasePtr[0]);
clearArr(x, y, width, tilesetDestPtr); //Cleans all of the arrangements this line could ever use
int pixelX = x * 8; int pixelX = x * 8;
int pixelY = y * 8; int pixelY = (y * 8) + 3;
int realmask = *palette_mask;
*palette_mask = 0; //File select is special and changes its palette_mask on the fly.
clear_rect_file(x, y, width, 2, 0x11111111, 0x400 + (offset >> 5), tilesetDestPtr); //Clean the rectangle before printing
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
{ {
@ -93,15 +188,500 @@ void print_file_string(int x, int y, int length, byte *str, int unknown)
pixelY, pixelY,
0, 0,
9, 9,
vram + 0x2000, vram + 0x2000 + (offset >> 2),
&get_tile_number, &get_tile_number,
tilesetDestPtr, tilesetDestPtr,
width); width,
(offset >>5));
pixelX += pixels; pixelX += pixels;
} }
*palette_mask = realmask;
} }
void format_options_cc(char String[], int *index, byte cmd)
{
String[(*index)++] = 0xFE;
String[(*index)++] = cmd;
}
void options_setup(char String[])
{
int index = 0;
char Continue[] = "Continue";
for(int i = 0; i < (sizeof(Continue) -1); i++)
String[index++] = encode_ascii(Continue[i]);
// Re-position
format_options_cc(String, &index, CUSTOMCC_SET_X);
String[index++] = 64;
char Copy[] = "Copy";
for(int i = 0; i < (sizeof(Copy) -1); i++)
String[index++] = encode_ascii(Copy[i]);
// Re-position
format_options_cc(String, &index, CUSTOMCC_SET_X);
String[index++] = 97;
char Delete[] = "Delete";
for(int i = 0; i < (sizeof(Delete) -1); i++)
String[index++] = encode_ascii(Delete[i]);
// Re-position
format_options_cc(String, &index, CUSTOMCC_SET_X);
String[index++] = 137;
char Setup[] = "Set Up";
for(int i = 0; i < (sizeof(Setup) -1); i++)
String[index++] = encode_ascii(Setup[i]);
//END
String[index++] = 0xFF;
}
void text_speed_setup(char String[], int selector)
{
int index = 0;
char Text_Speed[] = "Please select text speed.";
char Medium[] = "Medium";
char Fast[] = "Fast";
char Slow[] = "Slow";
switch(selector)
{
case 0:
for(int i = 0; i < (sizeof(Text_Speed) -1); i++)
String[index++] = encode_ascii(Text_Speed[i]);
break;
case 1:
for(int i = 0; i < (sizeof(Fast) -1); i++)
String[index++] = encode_ascii(Fast[i]);
break;
case 2:
for(int i = 0; i < (sizeof(Medium) -1); i++)
String[index++] = encode_ascii(Medium[i]);
break;
default:
for(int i = 0; i < (sizeof(Slow) -1); i++)
String[index++] = encode_ascii(Slow[i]);
break;
}
//END
String[index++] = 0xFF;
}
void delete_setup(char String[], int selector)
{
int index = 0;
char Delete[] = "Are you sure you want to delete?";
char No[] = "No";
char Yes[] = "Yes";
switch(selector)
{
case 0:
for(int i = 0; i < (sizeof(Delete) -1); i++)
String[index++] = encode_ascii(Delete[i]);
break;
case 1:
for(int i = 0; i < (sizeof(No) -1); i++)
String[index++] = encode_ascii(No[i]);
break;
default:
for(int i = 0; i < (sizeof(Yes) -1); i++)
String[index++] = encode_ascii(Yes[i]);
break;
}
//END
String[index++] = 0xFF;
}
void text_flavour_setup(char String[], int selector)
{
int index = 0;
char Text_Flavour_1[] = "Which style of windows";
char Text_Flavour_2[] = "do you prefer?";
char Plain[] = "Plain flavor";
char Mint[] = "Mint flavor";
char Strawberry[] = "Strawberry flavor";
char Banana[] = "Banana flavor";
char Peanut[] = "Peanut flavor";
switch(selector)
{
case 0:
for(int i = 0; i < (sizeof(Text_Flavour_1) -1); i++)
String[index++] = encode_ascii(Text_Flavour_1[i]);
break;
case 1:
for(int i = 0; i < (sizeof(Text_Flavour_2) -1); i++)
String[index++] = encode_ascii(Text_Flavour_2[i]);
break;
case 2:
for(int i = 0; i < (sizeof(Plain) -1); i++)
String[index++] = encode_ascii(Plain[i]);
break;
case 3:
for(int i = 0; i < (sizeof(Mint) -1); i++)
String[index++] = encode_ascii(Mint[i]);
break;
case 4:
for(int i = 0; i < (sizeof(Strawberry) -1); i++)
String[index++] = encode_ascii(Strawberry[i]);
break;
case 5:
for(int i = 0; i < (sizeof(Banana) -1); i++)
String[index++] = encode_ascii(Banana[i]);
break;
default:
for(int i = 0; i < (sizeof(Peanut) -1); i++)
String[index++] = encode_ascii(Peanut[i]);
break;
}
//END
String[index++] = 0xFF;
}
void description_setup(char String[], int selector)
{
int index = 0;
char Ness[] = "Please name him.";
char Paula[] = "Name her, too.";
char Jeff[] = "Name your friend.";
char Poo[] = "Name another friend.";
char King[] = "Name your pet.";
char FavFood[] = "Favorite homemade food?";
char FavThing[] = "What's your favorite thing?";
switch(selector)
{
case 3:
for(int i = 0; i < (sizeof(Ness) -1); i++)
String[index++] = encode_ascii(Ness[i]);
break;
case 4:
for(int i = 0; i < (sizeof(Paula) -1); i++)
String[index++] = encode_ascii(Paula[i]);
break;
case 5:
for(int i = 0; i < (sizeof(Jeff) -1); i++)
String[index++] = encode_ascii(Jeff[i]);
break;
case 6:
for(int i = 0; i < (sizeof(Poo) -1); i++)
String[index++] = encode_ascii(Poo[i]);
break;
case 7:
for(int i = 0; i < (sizeof(King) -1); i++)
String[index++] = encode_ascii(King[i]);
break;
case 8:
for(int i = 0; i < (sizeof(FavFood) -1); i++)
String[index++] = encode_ascii(FavFood[i]);
break;
default:
for(int i = 0; i < (sizeof(FavThing) -1); i++)
String[index++] = encode_ascii(FavThing[i]);
break;
}
//END
String[index++] = 0xFF;
}
void copy_setup(char String[])
{
int index = 0;
char Copy[] = "Copy to where?";
for(int i = 0; i < (sizeof(Copy) -1); i++)
String[index++] = encode_ascii(Copy[i]);
//END
String[index++] = 0xFF;
}
void letterSetup(char String[], int selector, bool capital, int *index)
{
char base = capital ? 'A' : 'a';
int value = 9 - (selector >> 1);
for(int i = 0; i < value; i++)
{
String[(*index)++] = encode_ascii(base + i + (selector * 9));
// Re-position
format_options_cc(String, &(*index), CUSTOMCC_SET_X);
if(i != value -1)
String[(*index)++] = (2 * (i + 2)) << 3;
else
String[(*index)++] = (24) << 3;
}
switch(selector)
{
case 0:
String[(*index)++] = 93;
// Re-position
format_options_cc(String, &(*index), CUSTOMCC_SET_X);
String[(*index)++] = (26) << 3;
String[(*index)++] = 83;
break;
case 1:
String[(*index)++] = 87;
// Re-position
format_options_cc(String, &(*index), CUSTOMCC_SET_X);
String[(*index)++] = (26) << 3;
String[(*index)++] = 174;
break;
default:
String[(*index)++] = 94;
// Re-position
format_options_cc(String, &(*index), CUSTOMCC_SET_X);
String[(*index)++] = (26) << 3;
String[(*index)++] = 95;
break;
}
}
void numbersSetup(char String[], int *index)
{
char base = '0';
for(int i = 0; i < 10; i++)
{
String[(*index)++] = encode_ascii(base + i);
// Re-position
format_options_cc(String, &(*index), CUSTOMCC_SET_X);
if(i != 9)
String[(*index)++] = (2 * (i + 2)) << 3;
else
String[(*index)++] = (24) << 3;
}
String[(*index)++] = 81;
// Re-position
format_options_cc(String, &(*index), CUSTOMCC_SET_X);
String[(*index)++] = (26) << 3;
String[(*index)++] = 0xAC;
}
void alphabet_setup(char String[], int selector, bool capital)
{
int index = 0;
char Capital[] = "CAPITAL";
char Small[] = "small";
char DontCare[] = "Don't Care";
char Backspace[] = "Backspace";
char Ok[] = "OK";
switch(selector)
{
case 0:
case 1:
case 2:
letterSetup(String, selector, capital, &index);
break;
case 3:
numbersSetup(String, &index);
break;
case 4:
for(int i = 0; i < (sizeof(Capital) -1); i++)
String[index++] = encode_ascii(Capital[i]);
//Re-position
format_options_cc(String, &index, CUSTOMCC_SET_X);
String[index++] = (9) << 3;
for(int i = 0; i < (sizeof(Small) -1); i++)
String[index++] = encode_ascii(Small[i]);
//Re-position
format_options_cc(String, &index, CUSTOMCC_SET_X);
String[index++] = (24) << 3;
String[index++] = 111;
// Re-position
format_options_cc(String, &index, CUSTOMCC_SET_X);
String[index++] = (26) << 3;
String[index++] = 0xAF;
break;
default:
for(int i = 0; i < (sizeof(DontCare) -1); i++)
String[index++] = encode_ascii(DontCare[i]);
//Re-position
format_options_cc(String, &index, CUSTOMCC_SET_X);
String[index++] = (19) << 3;
for(int i = 0; i < (sizeof(Backspace) -1); i++)
String[index++] = encode_ascii(Backspace[i]);
//Re-position
format_options_cc(String, &index, CUSTOMCC_SET_X);
String[index++] = (27) << 3;
for(int i = 0; i < (sizeof(Ok) -1); i++)
String[index++] = encode_ascii(Ok[i]);
break;
}
//END
String[index++] = 0xFF;
}
void summary_setup(char String[], int selector)
{
int index = 0;
char FavFood[] = "Favorite food:";
char FavThing[] = "Coolest thing:";
char AreYouSure[] = "Are you sure?";
char Yep[] = "Yep";
char Nope[] = "Nope";
switch(selector)
{
case 0:
for(int i = 0; i < (sizeof(FavFood) -1); i++)
String[index++] = encode_ascii(FavFood[i]);
break;
case 1:
for(int i = 0; i < (sizeof(FavThing) -1); i++)
String[index++] = encode_ascii(FavThing[i]);
break;
default:
for(int i = 0; i < (sizeof(AreYouSure) -1); i++)
String[index++] = encode_ascii(AreYouSure[i]);
//Re-position
format_options_cc(String, &index, CUSTOMCC_SET_X);
String[index++] = (0x10) << 3;
for(int i = 0; i < (sizeof(Yep) -1); i++)
String[index++] = encode_ascii(Yep[i]);
//Re-position
format_options_cc(String, &index, CUSTOMCC_SET_X);
String[index++] = (0x14) << 3;
for(int i = 0; i < (sizeof(Nope) -1); i++)
String[index++] = encode_ascii(Nope[i]);
break;
}
//END
String[index++] = 0xFF;
}
void print_windows(int window_selector)
{
char String[64];
int offset = 0;
switch(window_selector)
{
case 0x10: //Delete
offset = 0x6000;
delete_setup(String, 0);
print_file_string(1, 1, 0x40, String, window_selector, offset);
delete_setup(String, 1);
print_file_string(2, 5, 0x40, String, window_selector, offset);
delete_setup(String, 2);
print_file_string(2, 7, 0x40, String, window_selector, offset);
m2_cstm_last_printed[0] = window_selector | (m2_cstm_last_printed[0] & 0x20);
break;
case 0xE: //Options
offset = 0x1800;
options_setup(String);
print_file_string(2, 1, 0x40, String, window_selector, offset);
m2_cstm_last_printed[0] = window_selector | (m2_cstm_last_printed[0] & 0x20);
break;
case 1: //Text Speed
if(((m2_cstm_last_printed[0] & 0x1F) != 2) && ((m2_cstm_last_printed[0] & 0x1F) != 1)) //If Text Flavour is printed, then this is too. No need to reprint. Avoids tearing
{
offset = 0x6000;
text_speed_setup(String, 0);
print_file_string(1, 1, 0x40, String, window_selector, offset);
text_speed_setup(String, 1);
print_file_string(2, 3, 0x40, String, window_selector, offset);
text_speed_setup(String, 2);
print_file_string(2, 5, 0x40, String, window_selector, offset);
text_speed_setup(String, 3);
print_file_string(2, 7, 0x40, String, window_selector, offset);
m2_cstm_last_printed[0] = window_selector | (m2_cstm_last_printed[0] & 0x20);
}
break;
case 0x2: //Text Flavour
if((m2_cstm_last_printed[0] & 0x1F) != 2){
offset = 0x2800;
text_flavour_setup(String, 0);
print_file_string(1, 1, 0x40, String, window_selector, offset);
text_flavour_setup(String, 1);
print_file_string(1, 3, 0x40, String, window_selector, offset);
text_flavour_setup(String, 2);
print_file_string(2, 5, 0x40, String, window_selector, offset);
text_flavour_setup(String, 3);
print_file_string(2, 7, 0x40, String, window_selector, offset);
text_flavour_setup(String, 4);
print_file_string(2, 9, 0x40, String, window_selector, offset);
text_flavour_setup(String, 5);
print_file_string(2, 11, 0x40, String, window_selector, offset);
text_flavour_setup(String, 6);
print_file_string(2, 13, 0x40, String, window_selector, offset);
m2_cstm_last_printed[0] = window_selector; //Set the alphabet bit to 0.
}
break;
case 0xF: //Copy
offset = 0x6000;
copy_setup(String);
print_file_string(1, 1, 0x40, String, window_selector, offset);
break;
case 0x3: //Ness' name + description
case 0x4: //Paula's name + description
case 0x5: //Jeff's name + description
case 0x6: //Poo's name + description
case 0x7: //King's name + description
case 0x8: //FavFood's name + description
case 0x9: //FavThing's name + description
if((m2_cstm_last_printed[0] & 0x1F) != window_selector){
offset = 0x1800;
description_setup(String, window_selector);
print_file_string(9, 1, 0x40, String, window_selector, offset);
m2_cstm_last_printed[0] = window_selector | (m2_cstm_last_printed[0] & 0x20);
}
break;
case 0xA: //Alphabet 1
if((m2_cstm_last_printed[0] & 0x20) == 0) //Print this once and stop
{
//Main thing
offset = 0x2800;
alphabet_setup(String, 0, true);
print_file_string(2, 1, 0x40, String, window_selector, offset);
alphabet_setup(String, 1, true);
print_file_string(2, 3, 0x40, String, window_selector, offset);
alphabet_setup(String, 2, true);
print_file_string(2, 5, 0x40, String, window_selector, offset);
alphabet_setup(String, 3, true);
print_file_string(2, 7, 0x40, String, window_selector, offset);
alphabet_setup(String, 4, true);
print_file_string(2, 9, 0x40, String, window_selector, offset);
alphabet_setup(String, 5, true);
print_file_string(2, 13, 0x40, String, window_selector, offset);
m2_cstm_last_printed[0] = (m2_cstm_last_printed[0] & 0x1F) | 0x20; //Printed flag
}
break;
case 0xB: //Alphabet 2
if((m2_cstm_last_printed[0] & 0x40) == 0) //Print this once and stop
{
//Main thing
offset = 0x2800;
alphabet_setup(String, 0, false);
print_file_string(2, 1, 0x40, String, window_selector, offset);
alphabet_setup(String, 1, false);
print_file_string(2, 3, 0x40, String, window_selector, offset);
alphabet_setup(String, 2, false);
print_file_string(2, 5, 0x40, String, window_selector, offset);
alphabet_setup(String, 3, false);
print_file_string(2, 7, 0x40, String, window_selector, offset);
alphabet_setup(String, 4, true);
print_file_string(2, 9, 0x40, String, window_selector, offset);
alphabet_setup(String, 5, true);
print_file_string(2, 13, 0x40, String, window_selector, offset);
m2_cstm_last_printed[0] = (m2_cstm_last_printed[0] & 0x1F) | 0x40; //Printed flag
}
break;
case 0xC: //Alphabet 3 - Won't use
break;
case 0xD: //Is this okay? Yes No
offset = 0x2800;
summary_setup(String, 0);
print_file_string(0xC, 5, 0x40, String, window_selector, offset);
summary_setup(String, 1);
print_file_string(0xC, 0xB, 0x40, String, window_selector, offset);
summary_setup(String, 2);
print_file_string(0x1, 0x11, 0x40, String, window_selector, offset);
m2_cstm_last_printed[0] = window_selector; //Set the alphabet bit to 0.
break;
default: //File select string, already printed
break;
}
}
void format_file_cc(FILE_SELECT *file, int *index, byte cmd) void format_file_cc(FILE_SELECT *file, int *index, byte cmd)
{ {
file->formatted_str[(*index)++] = 0xFE; file->formatted_str[(*index)++] = 0xFE;
@ -185,6 +765,39 @@ void format_file_string(FILE_SELECT *file)
file->formatted_str[index++] = encode_ascii(speedStr[i]); file->formatted_str[index++] = encode_ascii(speedStr[i]);
file->formatted_str[index++] = 0xFF; file->formatted_str[index++] = 0xFF;
//Delete part
index = (0x40 - 0x15); //Maximum length of this is 0x15 with the 0xFF. The strings do not collide... By 1 byte. If you were to remove this string's end (which you could), it would be by 2 bytes.
file->formatted_str[index++] = (byte)(slot + ZERO);
file->formatted_str[index++] = encode_ascii(':');
file->formatted_str[index++] = encode_ascii(' ');
// Name
for (int i = 0; i < 5; i++)
{
byte name_chr = file->ness_name[i];
if (name_chr != 0xFF)
file->formatted_str[index++] = name_chr;
else
file->formatted_str[index++] = encode_ascii(' ');
}
// Re-position
format_file_cc(file, &index, CUSTOMCC_SET_X);
file->formatted_str[index++] = 72;
for (int i = 0; i < (sizeof(levelStr) - 1); i++)
file->formatted_str[index++] = encode_ascii(levelStr[i]);
if (tens > 0)
file->formatted_str[index++] = tens + ZERO;
file->formatted_str[index++] = ones + ZERO;
file->formatted_str[index++] = 0xFF;
} }
byte print_character(byte chr, int x, int y) byte print_character(byte chr, int x, int y)
@ -208,12 +821,12 @@ byte print_character_formatted(byte chr, int x, int y, int font, int foreground)
return 8; return 8;
} }
return print_character_with_callback(chr, x, y, font, foreground, vram, &get_tile_number_with_offset, *tilemap_pointer, 32); return print_character_with_callback(chr, x, y, font, foreground, vram, &get_tile_number_with_offset, *tilemap_pointer, 32, 0);
} }
byte print_character_to_ram(byte chr, int *dest, int xOffset, int font, int foreground) byte print_character_to_ram(byte chr, int *dest, int xOffset, int font, int foreground)
{ {
return print_character_with_callback(chr, xOffset, 0, font, foreground, dest, &get_tile_number_grid, NULL, 32); return print_character_with_callback(chr, xOffset, 0, font, foreground, dest, &get_tile_number_grid, NULL, 32, 0);
} }
// Prints a special tile. Pixels are copied to the VWF buffer. // Prints a special tile. Pixels are copied to the VWF buffer.
@ -251,7 +864,7 @@ void map_tile(unsigned short tile, int x, int y)
} }
byte print_character_with_callback(byte chr, int x, int y, int font, int foreground, byte print_character_with_callback(byte chr, int x, int y, int font, int foreground,
int *dest, int (*getTileCallback)(int, int), unsigned short *tilemapPtr, int tilemapWidth) int *dest, int (*getTileCallback)(int, int), unsigned short *tilemapPtr, int tilemapWidth, int tilemapOffset)
{ {
int tileWidth = m2_font_widths[font]; int tileWidth = m2_font_widths[font];
int tileHeight = m2_font_heights[font]; int tileHeight = m2_font_heights[font];
@ -266,6 +879,8 @@ byte print_character_with_callback(byte chr, int x, int y, int font, int foregro
int tileX = x >> 3; int tileX = x >> 3;
int tileY = y >> 3; int tileY = y >> 3;
int offsetY = y & 7;
for (int dTileY = 0; dTileY < tileHeight; dTileY++) // dest tile Y for (int dTileY = 0; dTileY < tileHeight; dTileY++) // dest tile Y
{ {
int dTileX = 0; int dTileX = 0;
@ -275,45 +890,71 @@ byte print_character_with_callback(byte chr, int x, int y, int font, int foregro
{ {
// Glue the leftmost part of the glyph onto the rightmost part of the canvas // Glue the leftmost part of the glyph onto the rightmost part of the canvas
int tileIndex = getTileCallback(tileX + dTileX, tileY + dTileY); //get_tile_number(tileX + dTileX, tileY + dTileY) + tileOffset; int tileIndex = getTileCallback(tileX + dTileX, tileY + dTileY); //get_tile_number(tileX + dTileX, tileY + dTileY) + tileOffset;
bool availableSwap = (dTileY != (tileHeight - 1));
int realTileIndex = tileIndex;
bool useful = false; //Maybe we go over the maximum tile height, let's make sure the extra tile is properly set IF it's useful
for (int row = 0; row < 8; row++) for (int row = 0; row < 8; row++)
{ {
int canvasRow = dest[(tileIndex * 8) + row]; int canvasRow = dest[(realTileIndex * 8) + ((row + offsetY) & 7)];
byte glyphRow = glyphRows[row + (dTileY * 8 * tileWidth) + (dTileX * 8)] & ((1 << leftPortionWidth) - 1); byte glyphRow = glyphRows[row + (dTileY * 8 * tileWidth) + (dTileX * 8)] & ((1 << leftPortionWidth) - 1);
glyphRow <<= (8 - leftPortionWidth); glyphRow <<= (8 - leftPortionWidth);
int expandedGlyphRow = expand_bit_depth(glyphRow, foreground); int expandedGlyphRow = expand_bit_depth(glyphRow, foreground);
int expandedGlyphRowMask = ~expand_bit_depth(glyphRow, 0xF); int expandedGlyphRowMask = ~expand_bit_depth(glyphRow, 0xF);
int tmpCanvasRow = canvasRow;
canvasRow &= expandedGlyphRowMask; canvasRow &= expandedGlyphRowMask;
canvasRow |= expandedGlyphRow; canvasRow |= expandedGlyphRow;
dest[(tileIndex * 8) + row] = canvasRow; if(!availableSwap && ((row + offsetY) >> 3) == 1 && canvasRow != tmpCanvasRow) //This changed the canvas, then it's useful... IF it's the extra vertical tile
useful = true;
dest[(realTileIndex * 8) + ((row + offsetY) & 7)] = canvasRow;
if(offsetY != 0 && ((row + offsetY) == 7))
realTileIndex = getTileCallback(tileX + dTileX, tileY + dTileY + 1);
} }
if (tilemapPtr != NULL) if (tilemapPtr != NULL)
tilemapPtr[tileX + dTileX + ((tileY + dTileY) * tilemapWidth)] = paletteMask | tileIndex; {
tilemapPtr[tileX + dTileX + ((tileY + dTileY) * tilemapWidth)] = paletteMask | (tileIndex + tilemapOffset);
if(useful)
tilemapPtr[tileX + dTileX + ((tileY + dTileY + 1) * tilemapWidth)] = paletteMask | (realTileIndex + tilemapOffset);
}
if (renderedWidth - leftPortionWidth > 0 && leftPortionWidth < 8) if (renderedWidth - leftPortionWidth > 0 && leftPortionWidth < 8)
{ {
// Glue the rightmost part of the glyph onto the leftmost part of the next tile // Glue the rightmost part of the glyph onto the leftmost part of the next tile
// on the canvas // on the canvas
tileIndex = getTileCallback(tileX + dTileX + 1, tileY + dTileY); //get_tile_number(tileX + dTileX + 1, tileY + dTileY) + tileOffset; tileIndex = getTileCallback(tileX + dTileX + 1, tileY + dTileY); //get_tile_number(tileX + dTileX + 1, tileY + dTileY) + tileOffset;
availableSwap = (dTileY != (tileHeight - 1));
realTileIndex = tileIndex;
useful = false; //Maybe we go over the maximum tile height, let's make sure the extra tile is properly set IF it's useful
for (int row = 0; row < 8; row++) for (int row = 0; row < 8; row++)
{ {
int canvasRow = dest[(tileIndex * 8) + row]; int canvasRow = dest[(realTileIndex * 8) + ((row + offsetY) & 7)];
byte glyphRow = glyphRows[row + (dTileY * 8 * tileWidth) + (dTileX * 8)] >> leftPortionWidth; byte glyphRow = glyphRows[row + (dTileY * 8 * tileWidth) + (dTileX * 8)] >> leftPortionWidth;
int expandedGlyphRow = expand_bit_depth(glyphRow, foreground); int expandedGlyphRow = expand_bit_depth(glyphRow, foreground);
int expandedGlyphRowMask = ~expand_bit_depth(glyphRow, 0xF); int expandedGlyphRowMask = ~expand_bit_depth(glyphRow, 0xF);
int tmpCanvasRow = canvasRow;
canvasRow &= expandedGlyphRowMask; canvasRow &= expandedGlyphRowMask;
canvasRow |= expandedGlyphRow; canvasRow |= expandedGlyphRow;
dest[(tileIndex * 8) + row] = canvasRow; if(!availableSwap && ((row + offsetY) >> 3) == 1 && canvasRow != tmpCanvasRow) //This changed the canvas, then it's useful... IF it's the extra vertical tile
useful = true;
dest[(realTileIndex * 8) + ((row + offsetY) & 7)] = canvasRow;
if(offsetY != 0 && ((row + offsetY) == 7))
realTileIndex = getTileCallback(tileX + dTileX + 1, tileY + dTileY + 1);
} }
if (tilemapPtr != NULL) if (tilemapPtr != NULL)
tilemapPtr[tileX + dTileX + 1 + ((tileY + dTileY) * tilemapWidth)] = paletteMask | tileIndex; {
tilemapPtr[tileX + dTileX + 1 + ((tileY + dTileY) * tilemapWidth)] = paletteMask | (tileIndex + tilemapOffset);
if(useful)
tilemapPtr[tileX + dTileX + 1 + ((tileY + dTileY + 1) * tilemapWidth)] = paletteMask | (realTileIndex + tilemapOffset);
}
} }
renderedWidth -= 8; renderedWidth -= 8;

View File

@ -28,6 +28,7 @@
byte decode_character(byte chr); byte decode_character(byte chr);
byte encode_ascii(char chr); byte encode_ascii(char chr);
int get_tile_number(int x, int y); int get_tile_number(int x, int y);
int count_pixels(byte *str, int length);
int expand_bit_depth(byte row, int foreground); int expand_bit_depth(byte row, int foreground);
byte reduce_bit_depth(int row, int foreground); byte reduce_bit_depth(int row, int foreground);
byte print_character(byte chr, int x, int y); byte print_character(byte chr, int x, int y);
@ -37,7 +38,7 @@ void print_special_character(int tile, int x, int y);
void map_special_character(unsigned short tile, int x, int y); void map_special_character(unsigned short tile, int x, int y);
void map_tile(unsigned short tile, int x, int y); void map_tile(unsigned short tile, int x, int y);
byte print_character_with_callback(byte chr, int x, int y, int font, int foreground, byte print_character_with_callback(byte chr, int x, int y, int font, int foreground,
int *dest, int (*getTileCallback)(int, int), unsigned short *tilemapPtr, int tilemapWidth); int *dest, int (*getTileCallback)(int, int), unsigned short *tilemapPtr, int tilemapWidth, int tilemapOffset);
byte print_character_to_ram(byte chr, int *dest, int xOffset, int font, int foreground); byte print_character_to_ram(byte chr, int *dest, int xOffset, int font, int foreground);
int print_window_header_string(int *dest, byte *str, int x, int y); int print_window_header_string(int *dest, byte *str, int x, int y);
void clear_window_header(int *dest, int length, int x, int y); void clear_window_header(int *dest, int length, int x, int y);
@ -67,7 +68,8 @@ void print_number_menu_current(byte digit, WINDOW* window);
void clear_number_menu(WINDOW* window); void clear_number_menu(WINDOW* window);
void format_cash_window(int value, int padding, byte* str); void format_cash_window(int value, int padding, byte* str);
void handle_first_window(WINDOW* window); void handle_first_window(WINDOW* window);
void print_file_string(int x, int y, int length, byte *str, int unknown); void print_file_string(int x, int y, int length, byte *str, int window_selector, int offset);
void wrapper_file_string(int x, int y, int length, byte *str, int window_selector);
void format_file_string(FILE_SELECT *file); void format_file_string(FILE_SELECT *file);
extern unsigned short m2_coord_table[]; extern unsigned short m2_coord_table[];
@ -81,6 +83,7 @@ extern byte m12_other_str5[];
extern byte m12_other_str6[]; extern byte m12_other_str6[];
extern byte m12_other_str7[]; extern byte m12_other_str7[];
extern byte m12_other_str8[]; extern byte m12_other_str8[];
extern byte m2_cstm_last_printed[];
extern void cpufastset(void *source, void *dest, int mode); extern void cpufastset(void *source, void *dest, int mode);
extern byte* m2_strlookup(int *offset_table, byte *strings, int index); extern byte* m2_strlookup(int *offset_table, byte *strings, int index);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1036,7 +1036,7 @@ nop
//Naming screen name length //Naming screen name length
.org 0x8004F54 :: mov r2,#5 //Ness .org 0x8004F54 :: mov r2,#5 //Ness
.org 0x8004F78 :: mov r0,#5 //Paula .org 0x8004F78 :: mov r0,#5 :: str r0,[sp,#0x18] :: bl _4f7c_window_selector //Paula
.org 0x8004F9C :: mov r0,#5 //Jeff .org 0x8004F9C :: mov r0,#5 //Jeff
.org 0x8004FC0 :: mov r1,#5 //Poo .org 0x8004FC0 :: mov r1,#5 //Poo
@ -1054,7 +1054,9 @@ nop
// Main file select window resize // Main file select window resize
.org 0x82B79BC :: dw 0x1C // new window width .org 0x82B79BC :: dw 0x1C // new window width
.org 0x8003998 :: mov r0,1 // new window x .org 0x8003998 :: mov r0,1 // new window x
.org 0x8003A04 :: mov r1,1 .org 0x8003F92 :: mov r0,1
.org 0x80053DC :: mov r0,1
.org 0x8003A04 :: mov r0,1
.org 0x8003B40 :: mov r0,0x10 // new cursor x .org 0x8003B40 :: mov r0,0x10 // new cursor x
.org 0x86DB070 :: .incbin "data/m2-fileselect-template.bin" .org 0x86DB070 :: .incbin "data/m2-fileselect-template.bin"
@ -1066,12 +1068,79 @@ nop
.org 0x8002284 :: bl format_file_string .org 0x8002284 :: bl format_file_string
// Printing // Printing
.org 0x80038CC :: mov r2,0x40 :: bl print_file_string .org 0x80038CC :: mov r2,0x40 :: bl wrapper_file_string
.org 0x80038DE :: mov r2,0x40 :: bl print_file_string .org 0x80038DE :: mov r2,0x40 :: bl wrapper_file_string
.org 0x80038F2 :: mov r2,0x40 :: bl print_file_string .org 0x80038F2 :: mov r2,0x40 :: bl wrapper_file_string
// Bump file select cursor up by 3 pixels // Bump file select cursor up by 3 pixels - Not needed now that the text is 3 pixels lower
.org 0x8003844 :: add r0,r5,1 //.org 0x8003844 :: add r0,r5,1
// File select options
.org 0x8004092 :: bl _4092_print_window //Printing
.org 0x80041D4 :: bl _41D4_cursor_X //New cursor's X
//Text Speed options
.org 0x8003BBC :: bl _4092_print_window //Printing
.org 0x8003FA2 :: bl _4092_print_window
.org 0x82B79D0 :: dw 0x10 //new window width
.org 0x86DB0FC :: .incbin "data/m2-textspeed-template.bin"
//Text Flavour options
.org 0x8003D8A :: bl _4092_print_window //Printing
.org 0x8003D86 :: mov r1,#4 //new window Y
.org 0x8003DB6 :: mov r1,#4
.org 0x8003E0C :: mov r1,#4
.org 0x8003E8C :: mov r1,#4
.org 0x8003EF8 :: mov r1,#4
.org 0x80053F2 :: mov r1,#4
.org 0x82B79E4 :: dw 0xF //new window width
.org 0x82B79E8 :: dw 0x10 //new window height
.org 0x86DB1F8 :: .incbin "data/m2-flavour-template.bin"
//Delete
.org 0x8004410 :: mov r1,#3 :: mov r2,#0x15 :: bl wrapper_delete_string
.org 0x800441E :: bl _4092_print_window //Printing
.org 0x82B7AFC :: dw 0x15 //new window width
.org 0x86DBE8C :: .incbin "data/m2-delete-template.bin"
//Copy
.org 0x8004294 :: bl _4298_print_window //Printing - 1 slot available
.org 0x80042BA :: bl _4092_print_window //Printing - 2 slots available
.org 0x8004268 :: mov r2,#0x2 :: bl wrapper_copy_string
//Descriptions and Names
.org 0x8004ED2 :: bl wrapper_name_string //Printing names
.org 0x8004EDC :: bl _4092_print_window //Printing descriptions
.org 0x86DB2B8 :: .incbin "data/m2-descriptions-template.bin"
.org 0x82B7A00 :: dw 0x86DB2B8 //Point all the descriptions + names to the same template
.org 0x82B7A14 :: dw 0x86DB2B8
.org 0x82B7A28 :: dw 0x86DB2B8
.org 0x82B7A3C :: dw 0x86DB2B8
.org 0x82B7A50 :: dw 0x86DB2B8
.org 0x82B7A64 :: dw 0x86DB2B8
//Alphabets
.org 0x80051A4 :: bl _4092_print_window //Printing
.org 0x8004EA2 :: bl _4092_print_window //Printing
.org 0x82B7A8C :: dw 0x86DB5C4
.org 0x86DB5C4 :: .incbin "data/m2-alphabet-template.bin"
//Summary
.org 0x80055B0 :: bl _4092_print_window //Printing
.org 0x80054F2 :: mov r2,#5 :: bl wrapper_name_summary_string //Printing Ness' name
.org 0x8005502 :: mov r2,#5 :: bl wrapper_name_summary_string //Printing Paula's name
.org 0x8005512 :: mov r2,#5 :: bl wrapper_name_summary_string //Printing Jeff's name
.org 0x8005522 :: mov r2,#5 :: bl wrapper_name_summary_string //Printing Poo's name
.org 0x800555C :: nop :: nop //Sends to a bunch of 0xFF
.org 0x800556A :: nop :: nop //Sends to a bunch of 0xFF
.org 0x8005530 :: mov r0,#0x11 //New x for King's name
.org 0x8005536 :: bl wrapper_name_summary_string //Printing King's name
.org 0x8005578 :: bl count_pixels :: mov r2,#6 :: mov r4,#0x17 :: sub r0,r4,r0 //Count length of Food's name in tiles
.org 0x8005588 :: bl wrapper_name_summary_string //Printing Food's name
.org 0x8005596 :: bl count_pixels :: mov r2,#6 :: sub r4,r4,r0 //Count length of Food's name in tiles
.org 0x80055A6 :: bl wrapper_name_summary_string //Printing Thing's name
.org 0x80056F0 :: add r0,#0x90 //New cursor's X
.org 0x86DBC6C :: .incbin "data/m2-summary-template.bin"
//============================================================================== //==============================================================================
// Data files // Data files

View File

@ -1581,3 +1581,58 @@ bl 0x80BD7F8 //Copies old arrangements, this includes the highlight
pop {r5,pc} pop {r5,pc}
.pool .pool
//==============================================================================
_4092_print_window:
push {lr}
push {r0-r4}
mov r0,r2
bl print_windows
pop {r0-r4}
bl 0x800341C
pop {pc}
//==============================================================================
_4298_print_window:
push {lr}
push {r0-r4}
ldr r0,[sp,#0x20]
bl print_windows
pop {r0-r4}
mov r2,#0
mov r3,#0
pop {pc}
//==============================================================================
_41D4_cursor_X:
push {lr}
cmp r0,#1
bne @@next1
mov r0,#5
b @@end
@@next1:
cmp r0,#6
bne @@next2
mov r0,#11
b @@end
@@next2:
cmp r0,#11
bne @@next3
mov r0,#15
b @@end
@@next3:
mov r0,#20
@@end:
lsl r0,r0,#3
pop {pc}
//==============================================================================
_4f7c_window_selector:
push {lr}
mov r0,#4
mov r10,r0
ldr r1,=#0x82B7FF8
pop {pc}
.pool