Mother2GbaTranslation/compiled/vwf.c

277 lines
7.7 KiB
C

#include "window.h"
#include "vwf.h"
byte decode_character(byte chr)
{
int c = chr - 0x50;
if ((c < 0) || ((c >= 0x60) && (c < 0x64)) || (c >= 0x6E))
c = QUESTION_MARK;
return c;
}
int get_tile_number(int x, int y)
{
x--;
y--;
return m2_coord_table[x + ((y >> 1) * 28)] + (y & 1) * 32;
}
int get_tile_number_with_offset(int x, int y)
{
return get_tile_number(x, y) + *tile_offset;
}
int get_tile_number_grid(int x, int y)
{
return x + (y * 32);
}
int expand_bit_depth(byte row, int foreground)
{
foreground &= 0xF;
return m2_bits_to_nybbles[row + (foreground * 256)];
}
byte reduce_bit_depth(int row, int foreground)
{
int foregroundRow = row * 0x11111111;
row ^= foregroundRow;
int lower = m2_nybbles_to_bits[row & 0xFFFF];
int upper = m2_nybbles_to_bits[(row >> 16) & 0xFFFF];
return lower | (upper << 4);
}
byte print_character(byte chr, int x, int y, int font, int foreground)
{
// 0x64 to 0x6C (inclusive) is YOU WON
if ((chr >= 0x64) && (chr <= 0x6C))
{
print_special_character(chr + 0xF0, x, y);
return 8;
}
// 0x6D is an arrow ->
else if (chr == 0x6D)
{
print_special_character(0x9D, x, y);
return 8;
}
return print_character_with_callback(chr, x, y, font, foreground, vram, &get_tile_number_with_offset, TRUE);
}
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, FALSE);
}
void print_special_character(int tile, int x, int y)
{
// Special graphics must be tile-aligned
x >>= 3;
y >>= 3;
unsigned short sourceTileIndex = tile + *tile_offset;
unsigned short destTileIndex = get_tile_number(x, y) + *tile_offset;
(*tilemap_pointer)[x + (y * 32)] = destTileIndex | *palette_mask;
(*tilemap_pointer)[x + ((y + 1) * 32)] = (destTileIndex + 32) | *palette_mask;
cpufastset(&vram[sourceTileIndex * 8], &vram[destTileIndex * 8], 8);
cpufastset(&vram[(sourceTileIndex + 32) * 8], &vram[(destTileIndex + 32) * 8], 8);
}
byte print_character_with_callback(byte chr, int x, int y, int font, int foreground,
int *dest, int (*getTileCallback)(int, int), int useTilemap)
{
int tileWidth = m2_font_widths[font];
int tileHeight = m2_font_heights[font];
int widths = m2_widths_table[font][chr];
int paletteMask = *palette_mask;
byte *glyphRows = &m2_font_table[font][chr * tileWidth * tileHeight * 8];
int virtualWidth = widths & 0xFF;
int leftPortionWidth = 8 - (x & 7);
int tileX = x >> 3;
int tileY = y >> 3;
for (int dTileY = 0; dTileY < tileHeight; dTileY++) // dest tile Y
{
int dTileX = 0;
int renderedWidth = widths >> 8;
while (renderedWidth > 0)
{
// 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;
for (int row = 0; row < 8; row++)
{
int canvasRow = dest[(tileIndex * 8) + row];
byte glyphRow = glyphRows[row + (dTileY * 8 * tileWidth) + (dTileX * 8)] & ((1 << leftPortionWidth) - 1);
glyphRow <<= (8 - leftPortionWidth);
int expandedGlyphRow = expand_bit_depth(glyphRow, foreground);
int expandedGlyphRowMask = ~expand_bit_depth(glyphRow, 0xF);
canvasRow &= expandedGlyphRowMask;
canvasRow |= expandedGlyphRow;
dest[(tileIndex * 8) + row] = canvasRow;
}
if (useTilemap)
(*tilemap_pointer)[tileX + dTileX + ((tileY + dTileY) * 32)] = paletteMask | tileIndex;
if (renderedWidth - leftPortionWidth > 0 && leftPortionWidth < 8)
{
// Glue the rightmost part of the glyph onto the leftmost part of the next tile
// on the canvas
tileIndex = getTileCallback(tileX + dTileX + 1, tileY + dTileY); //get_tile_number(tileX + dTileX + 1, tileY + dTileY) + tileOffset;
for (int row = 0; row < 8; row++)
{
int canvasRow = dest[(tileIndex * 8) + row];
byte glyphRow = glyphRows[row + (dTileY * 8 * tileWidth) + (dTileX * 8)] >> leftPortionWidth;
int expandedGlyphRow = expand_bit_depth(glyphRow, foreground);
int expandedGlyphRowMask = ~expand_bit_depth(glyphRow, 0xF);
canvasRow &= expandedGlyphRowMask;
canvasRow |= expandedGlyphRow;
dest[(tileIndex * 8) + row] = canvasRow;
}
if (useTilemap)
(*tilemap_pointer)[tileX + dTileX + 1 + ((tileY + dTileY) * 32)] = paletteMask | tileIndex;
}
renderedWidth -= 8;
dTileX++;
}
}
return virtualWidth;
}
int print_window_header_string(int *dest, byte *str, int x, int y)
{
int pixelX = x & 7;
int *destOffset = dest + ((x & ~7) + (y * 32));
for (;;)
{
byte code = *(str + 1);
if (code == 0xFF)
{
if (*str == 0)
break;
str += 2;
continue;
}
pixelX += print_character_to_ram(decode_character(*str++), destOffset, pixelX, 4, 0xF);
}
return pixelX - (x & 7);
}
void clear_window_header(int *dest)
{
dest += (0x10 + (0x11 * 32)) * 8;
clear_rect_ram(dest, 16, 0x33333333);
}
void weld_entry(WINDOW *window, byte *str)
{
weld_entry_custom(window, str, 0, 0xF);
}
void weld_entry_custom(WINDOW *window, byte *str, int font, int foreground)
{
int chr = decode_character(*str);
int x = window->pixel_x + (window->window_x + window->text_x) * 8;
int y = (window->window_y + window->text_y) * 8;
x += print_character(chr, x, y, font, foreground);
window->pixel_x = x & 7;
window->text_x = (x >> 3) - window->window_x;
}
// Returns: ____XXXX = number of characters printed
// XXXX____ = number of pixels printed
int print_string(byte *str, int x, int y)
{
byte chr;
int initialX = x;
int charCount = 0;
while (str[1] != 0xFF)
{
x += print_character(decode_character(*str++), x, y, 0, 0xF);
charCount++;
}
int totalWidth = x - initialX;
return (charCount & 0xFFFF) | (totalWidth << 16);
}
void clear_tile(int x, int y, int pixels)
{
int tileIndex = get_tile_number(x, y) + *tile_offset;
cpufastset(&pixels, &vram[tileIndex * 8], CPUFASTSET_FILL | 8);
}
void clear_rect(int x, int y, int width, int height, int pixels)
{
for (int tileY = 0; tileY < height; tileY++)
{
for (int tileX = 0; tileX < width; tileX++)
{
clear_tile(x + tileX, y + tileY, pixels);
}
}
}
void clear_rect_ram(int *dest, int tileCount, int pixels)
{
cpufastset(&pixels, dest, CPUFASTSET_FILL | (tileCount * 8));
}
void clear_window(WINDOW *window)
{
clear_rect(window->window_x, window->window_y,
window->window_width, window->window_height,
0x44444444);
}
void print_blankstr(int x, int y, int width)
{
clear_rect(x, y, width, 2, 0x44444444);
}
void copy_tile(int xSource, int ySource, int xDest, int yDest)
{
int sourceTileIndex = get_tile_number(xSource, ySource) + *tile_offset;
int destTileIndex = get_tile_number(xDest, yDest) + *tile_offset;
cpufastset(&vram[sourceTileIndex * 8], &vram[destTileIndex * 8], 8);
}
void copy_tile_up(int x, int y)
{
copy_tile(x, y, x, y - 2);
}
void print_space(WINDOW *window)
{
byte space = 0x50;
weld_entry(window, &space);
}