implement utf8, part 12

This commit is contained in:
IntelOrca 2015-07-29 02:03:34 +01:00
parent 357111a560
commit a9e6f8c3db
9 changed files with 223 additions and 189 deletions

View File

@ -36,6 +36,7 @@
<ClCompile Include="..\src\drawing\line.c" />
<ClCompile Include="..\src\drawing\rain.c" />
<ClCompile Include="..\src\drawing\rect.c" />
<ClCompile Include="..\src\drawing\scrolling_text.c" />
<ClCompile Include="..\src\drawing\sprite.c" />
<ClCompile Include="..\src\drawing\string.c" />
<ClCompile Include="..\src\editor.c" />

View File

@ -498,6 +498,9 @@
<ClCompile Include="..\src\localisation\convert.c">
<Filter>Source\Localisation</Filter>
</ClCompile>
<ClCompile Include="..\src\drawing\scrolling_text.c">
<Filter>Source\Drawing</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\management\award.h">

View File

@ -144,4 +144,8 @@ void redraw_rain();
// unknown
void sub_681DE2(rct_drawpixelinfo *dpi, int x, int y, int image1, int image2);
// scrolling text
void scrolling_text_initialise_bitmaps();
int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrollingMode);
#endif

View File

@ -0,0 +1,161 @@
#include "../addresses.h"
#include "../config.h"
#include "../localisation/localisation.h"
#include "drawing.h"
/* size: 0xA12 */
typedef struct {
rct_string_id string_id; // 0x00
uint32 string_args_0; // 0x02
uint32 string_args_1; // 0x06
uint16 position; // 0x0A
uint16 mode; // 0x0C
uint32 id; // 0x0E
uint8 bitmap[64 * 8 * 5]; // 0x12
} rct_draw_scroll_text;
rct_draw_scroll_text *gDrawScrollTextList = RCT2_ADDRESS(RCT2_ADDRESS_DRAW_SCROLL_LIST, rct_draw_scroll_text);
void scrolling_text_initialise_bitmaps()
{
uint8 drawingSurface[64];
rct_drawpixelinfo dpi = {
.bits = (char*)&drawingSurface,
.x = 0,
.y = 0,
.width = 8,
.height = 8,
.pitch = 0,
.zoom_level = 0
};
for (int i = 0; i < 224; i++) {
memset(drawingSurface, 0, sizeof(drawingSurface));
gfx_draw_sprite(&dpi, i + 0x10D5, -1, 0, 0);
for (int x = 0; x < 8; x++) {
uint8 val = 0;
for (int y = 0; y < 8; y++) {
val >>= 1;
if (dpi.bits[x + y * 8] == 1) {
val |= 0x80;
}
}
RCT2_ADDRESS(RCT2_ADDRESS_CHARACTER_BITMAP, uint8)[i * 8 + x] = val;
}
}
}
/**
*
* rct2: 0x006C42D9
*/
int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrollingMode)
{
rct_drawpixelinfo* dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*);
if (dpi->zoom_level != 0) return 0x626;
RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32)++;
// Find the oldest scroll for use as the newest
uint32 oldestId = 0xFFFFFFFF;
uint8 scrollIndex = 0xFF;
rct_draw_scroll_text* oldestScroll = NULL;
for (int i = 0; i < 32; i++) {
rct_draw_scroll_text *scrollText = &gDrawScrollTextList[i];
if (oldestId >= scrollText->id) {
oldestId = scrollText->id;
scrollIndex = i;
oldestScroll = scrollText;
}
// If exact match return the matching index
if (
scrollText->string_id == stringId &&
scrollText->string_args_0 == RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) &&
scrollText->string_args_1 == RCT2_GLOBAL(0x13CE956, uint32) &&
scrollText->position == scroll &&
scrollText->mode == scrollingMode
) {
scrollText->id = RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32);
return i + 0x606;
}
}
// Setup scrolling text
rct_draw_scroll_text* scrollText = oldestScroll;
scrollText->string_id = stringId;
scrollText->string_args_0 = RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32);
scrollText->string_args_1 = RCT2_GLOBAL(0x13CE956, uint32);
scrollText->position = scroll;
scrollText->mode = scrollingMode;
scrollText->id = RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32_t);
uint8* scrollPixelPointer = scrollText->bitmap;
memset(scrollPixelPointer, 0, 320 * 8);
// Convert string id back into a string for processing
utf8 scrollString[MAX_PATH];
if (gConfigGeneral.upper_case_banners)
format_string_to_upper(scrollString, stringId, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS);
else
format_string(scrollString, stringId, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS);
// Setup character colour from ???
uint32 character = RCT2_GLOBAL(0x13CE959, uint8);
int edi = character & 0x7F;
int offs = 0;
if (character >= 0x80) offs = 2;
uint8 characterColour = RCT2_ADDRESS(0x0141FC47, uint8)[offs + edi * 8];
sint16* scrollingModePositions = RCT2_ADDRESS(RCT2_ADDRESS_SCROLLING_MODE_POSITIONS, uint16_t*)[scrollingMode];
uint8* formatResult = scrollString;
while (true) {
character = utf8_get_next(formatResult, &formatResult);
// If at the end of the string loop back to the start
if (character == 0) {
formatResult = scrollString;
continue;
}
// Set any change in colour
if (character <= FORMAT_COLOUR_CODE_END && character >= FORMAT_COLOUR_CODE_START){
character -= FORMAT_COLOUR_CODE_START;
characterColour = RCT2_GLOBAL(0x009FF048, uint8*)[character * 4];
continue;
}
// If another type of control character ignore
if (character < 32) continue;
// Convert to an indexable character
character = utf8_get_sprite_offset_for_codepoint(character);
uint8 characterWidth = RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH + 448, uint8)[character];
uint8* characterBitmap = &(RCT2_ADDRESS(RCT2_ADDRESS_CHARACTER_BITMAP, uint8)[character * 8]);
for (; characterWidth != 0; characterWidth--, characterBitmap++) {
// Skip any none displayed columns
if (scroll != 0){
scroll--;
continue;
}
sint16 scrollPosition = *scrollingModePositions;
if (scrollPosition == -1) return scrollIndex + 0x606;
if (scrollPosition > -1) {
uint8* dst = &scrollPixelPointer[scrollPosition];
for (uint8 char_bitmap = *characterBitmap; char_bitmap != 0; char_bitmap >>= 1){
if (char_bitmap & 1) *dst = characterColour;
// Jump to next row
dst += 64;
}
}
scrollingModePositions++;
}
}
}

View File

@ -35,6 +35,16 @@ static int _ttfFontOffsetY = 0;
static const int TTFFontSizes[] = { 7, 9, 11, 13 };
enum {
FONT_SIZE_TINY = 2,
FONT_SIZE_SMALL = 0,
FONT_SIZE_MEDIUM = 1,
FONT_SIZE_BIG = 3,
FONT_SIZE_COUNT = 4
};
enum {
FONT_SPRITE_GLYPH_COUNT = 224,
FONT_SPRITE_BASE_TINY = 448,
FONT_SPRITE_BASE_SMALL = 0,
FONT_SPRITE_BASE_MEDIUM = 224,
@ -47,59 +57,30 @@ static uint8 *_spriteFontCharacterWidths = (uint8*)RCT2_ADDRESS_FONT_CHAR_WIDTH;
*
* rct2: 0x006C19AC
*/
void gfx_load_character_widths(){
uint8* char_width_pointer = _spriteFontCharacterWidths;
for (int char_set_offset = 0; char_set_offset < 4*0xE0; char_set_offset+=0xE0){
for (uint8 c = 0; c < 0xE0; c++, char_width_pointer++){
rct_g1_element g1 = g1Elements[c + SPR_CHAR_START + char_set_offset];
int width;
if (char_set_offset == 0xE0*3) width = g1.width + 1;
else width = g1.width - 1;
if (c >= (FORMAT_ARGUMENT_CODE_START - 0x20) && c < (FORMAT_COLOUR_CODE_END - 0x20)){
void gfx_load_character_widths()
{
uint8* pCharacterWidth = _spriteFontCharacterWidths;
for (int fontSize = 0; fontSize < FONT_SIZE_COUNT; fontSize++) {
int glyphOffset = fontSize * FONT_SPRITE_GLYPH_COUNT;
for (uint8 glyphIndex = 0; glyphIndex < FONT_SPRITE_GLYPH_COUNT; glyphIndex++) {
rct_g1_element g1 = g1Elements[glyphIndex + SPR_CHAR_START + glyphOffset];
int width = fontSize == FONT_SIZE_BIG ? g1.width + 1 : g1.width - 1;
if (glyphIndex >= (FORMAT_ARGUMENT_CODE_START - 32) && glyphIndex < (FORMAT_COLOUR_CODE_END - 32)) {
width = 0;
}
*char_width_pointer = (uint8)width;
*pCharacterWidth++ = (uint8)width;
}
}
uint8 drawing_surface[0x40];
rct_drawpixelinfo dpi = {
.bits = (char*)&drawing_surface,
.width = 8,
.height = 8,
.x = 0,
.y = 0,
.pitch = 0,
.zoom_level = 0};
scrolling_text_initialise_bitmaps();
for (int i = 0; i < 0xE0; ++i){
memset(drawing_surface, 0, sizeof(drawing_surface));
gfx_draw_sprite(&dpi, i + 0x10D5, -1, 0, 0);
for (int x = 0; x < 8; ++x){
uint8 val = 0;
for (int y = 0; y < 8; ++y){
val >>= 1;
if (dpi.bits[x + y * 8]==1){
val |= 0x80;
}
}
RCT2_ADDRESS(RCT2_ADDRESS_CHARACTER_BITMAP, uint8)[i * 8 + x] = val;
}
}
for (int i = 0; i < 0x20; ++i){
for (int i = 0; i < 32; i++) {
rct_g1_element* g1 = &g1Elements[0x606 + i];
uint8* unknown_pointer = RCT2_ADDRESS(0x9C3852, uint8) + 0xa12 * i;
uint8* unknown_pointer = RCT2_ADDRESS(0x009C3852, uint8) + 0xA12 * i;
g1->offset = unknown_pointer;
g1->width = 0x40;
g1->height = 0x28;
g1->width = 64;
g1->height = 40;
*((uint16*)unknown_pointer) = 0xFFFF;
*((uint32*)(unknown_pointer + 0x0E)) = 0;
}
@ -782,7 +763,7 @@ bool ttf_initialise()
}
_ttfFontOffsetX = 1;
_ttfFontOffsetY = -3;
_ttfFontOffsetY = -2;
_ttfInitialised = true;
}
return true;
@ -805,6 +786,7 @@ void ttf_dispose()
}
enum {
TEXT_DRAW_FLAG_INSET = 1 << 0,
TEXT_DRAW_FLAG_OUTLINE = 1 << 1,
TEXT_DRAW_FLAG_TTF = 1 << 30,
TEXT_DRAW_FLAG_NO_DRAW = 1 << 31
@ -920,8 +902,10 @@ static void ttf_draw_string_raw_ttf(rct_drawpixelinfo *dpi, const utf8 *text, te
for (int xx = 0; xx < width; xx++) {
if (*src != 0) {
*dst = colour;
if (info->flags & TEXT_DRAW_FLAG_OUTLINE) {
*(dst + width + dstScanSkip + 1) = 0;
if (info->flags & TEXT_DRAW_FLAG_INSET) {
*(dst + width + dstScanSkip + 1) = info->palette[3];
} else if (info->flags & TEXT_DRAW_FLAG_OUTLINE) {
*(dst + width + dstScanSkip + 1) = info->palette[3];
}
}
src++;
@ -953,7 +937,7 @@ static const utf8 *ttf_process_format_code(rct_drawpixelinfo *dpi, const utf8 *t
codepoint = utf8_get_next(text, &nextCh);
switch (codepoint) {
case FORMAT_MOVE_X:
info->x = info->startX + *nextCh++;
info->x = info->startX + (uint8)(*nextCh++);
break;
case FORMAT_ADJUST_PALETTE:
{

View File

@ -990,130 +990,6 @@ void sprite_paint_setup(uint16 eax, uint16 ecx){
}
}
/* size: 0xA12 */
typedef struct{
rct_string_id string_id; // 0x00
uint32 string_args_0; // 0x02
uint32 string_args_1; // 0x06
uint16 position; // 0x0A
uint16 mode; // 0x0C
uint32 id; // 0x0E
uint8 bitmap[64 * 8 * 5];// 0x12
}rct_draw_scroll_text;
/*rct2: 0x006C42D9*/
int scrolling_text_setup(rct_string_id string_id, uint16 scroll, uint16 scrolling_mode)
{
rct_drawpixelinfo* dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*);
if (dpi->zoom_level != 0) return 0x626;
RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32)++;
uint32 oldest_id = 0xFFFFFFFF;
uint8 scroll_index = 0xFF;
rct_draw_scroll_text* oldest_scroll = NULL;
// Find the oldest scroll for use as the newest
for (int i = 0; i < 32; i++)
{
rct_draw_scroll_text* scroll_text = &RCT2_ADDRESS(RCT2_ADDRESS_DRAW_SCROLL_LIST, rct_draw_scroll_text)[i];
if (oldest_id >= scroll_text->id){
oldest_id = scroll_text->id;
scroll_index = i;
oldest_scroll = scroll_text;
}
// If exact match return the matching index
if (scroll_text->string_id == string_id &&
scroll_text->string_args_0 == RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) &&
scroll_text->string_args_1 == RCT2_GLOBAL(0x13CE956, uint32) &&
scroll_text->position == scroll &&
scroll_text->mode == scrolling_mode){
scroll_text->id = RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32);
return i + 0x606;
}
}
// Setup scrolling text
rct_draw_scroll_text* scroll_text = oldest_scroll;
scroll_text->string_id = string_id;
scroll_text->string_args_0 = RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32);
scroll_text->string_args_1 = RCT2_GLOBAL(0x13CE956, uint32);
scroll_text->position = scroll;
scroll_text->mode = scrolling_mode;
scroll_text->id = RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32_t);
uint8* scroll_pixel_pointer = scroll_text->bitmap;
memset(scroll_pixel_pointer, 0, 320 * 8);
// Convert string id back into a string for processing
uint8 scroll_string[MAX_PATH];
if(gConfigGeneral.upper_case_banners)
format_string_to_upper(scroll_string, string_id, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS);
else
format_string(scroll_string, string_id, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS);
// Setup character colour from ???
uint8 character = RCT2_GLOBAL(0x13CE959, uint8);
int edi = character & 0x7F;
int offs = 0;
if (character >= 0x80) offs = 2;
uint8 character_colour = RCT2_ADDRESS(0x0141FC47, uint8)[offs + edi * 8];
sint16* scrolling_mode_positions = RCT2_ADDRESS(RCT2_ADDRESS_SCROLLING_MODE_POSITIONS, uint16_t*)[scrolling_mode];
uint8* format_result = scroll_string;
while (true)
{
character = *format_result++;
// If at the end of the string loop back to the start
if (character == 0){
format_result = scroll_string;
continue;
}
// Set any change in colour
if (character <= FORMAT_COLOUR_CODE_END && character >= FORMAT_COLOUR_CODE_START){
character -= FORMAT_COLOUR_CODE_START;
character_colour = RCT2_GLOBAL(0x9FF048, uint8*)[character * 4];
continue;
}
// If another type of control character ignore
if (character < 0x20) continue;
// Convert to an indexable character
character -= 0x20;
uint8 character_width = RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH + 0x1C0, uint8)[character];
uint8* character_bitmap = &(RCT2_ADDRESS(RCT2_ADDRESS_CHARACTER_BITMAP, uint8)[character * 8]);
for (; character_width != 0;character_width--,character_bitmap++)
{
// Skip any none displayed columns
if (scroll != 0){
scroll--;
continue;
}
sint16 scroll_position = *scrolling_mode_positions;
if (scroll_position == -1) return scroll_index + 0x606;
if (scroll_position > -1)
{
uint8* dst = &scroll_pixel_pointer[scroll_position];
for (uint8 char_bitmap = *character_bitmap; char_bitmap != 0; char_bitmap >>= 1){
if (char_bitmap & 1) *dst = character_colour;
// Jump to next row
dst += 64;
}
}
scrolling_mode_positions++;
}
}
}
/* rct2: 0x006629BC
* returns al
* ebp : image_id

View File

@ -3111,20 +3111,24 @@ rct_track_design *temp_track_get_info(char* path, uint8** preview)
return trackDesign;
}
void window_track_list_format_name(char *dst, const char *src, char colour, char quotes)
void window_track_list_format_name(utf8 *dst, const utf8 *src, int colour, bool quotes)
{
if (colour != 0)
*dst++ = colour;
const utf8 *ch;
int codepoint;
if (quotes != 0)
*dst++ = FORMAT_OPENQUOTES;
while (*src != '.' && *src != 0) {
*dst++ = *src++;
if (colour != 0) {
dst = utf8_write_codepoint(dst, colour);
}
if (quotes != 0)
*dst++ = FORMAT_ENDQUOTES;
if (quotes) dst = utf8_write_codepoint(dst, FORMAT_OPENQUOTES);
ch = src;
while ((codepoint = utf8_get_next(ch, &ch)) != 0) {
if (codepoint == '.') break;
dst = utf8_write_codepoint(dst, codepoint);
}
if (quotes) dst = utf8_write_codepoint(dst, FORMAT_ENDQUOTES);
*dst = 0;
}

View File

@ -512,7 +512,7 @@ int track_is_connected_by_shape(rct_map_element *a, rct_map_element *b);
int sub_6D01B3(uint8 bl, uint8 rideIndex, int x, int y, int z);
int save_track_design(uint8 rideIndex);
int install_track(char* source_path, char* dest_name);
void window_track_list_format_name(char *dst, const char *src, char colour, char quotes);
void window_track_list_format_name(utf8 *dst, const utf8 *src, int colour, bool quotes);
void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
void track_save_reset_scenery();

View File

@ -80,7 +80,8 @@ static uint16 _window_error_num_lines;
*/
void window_error_open(rct_string_id title, rct_string_id message)
{
char *dst, *args;
utf8 *dst;
char *args;
int numLines, fontHeight, x, y, width, height, maxY;
rct_window *w;
@ -89,17 +90,17 @@ void window_error_open(rct_string_id title, rct_string_id message)
args = (char*)0x0013CE952;
// Format the title
*dst++ = FORMAT_BLACK;
dst = utf8_write_codepoint(dst, FORMAT_BLACK);
if (title != (rct_string_id)STR_NONE) {
format_string(dst, title, args);
dst += get_string_size(dst) - 1;
dst = get_string_end(dst);
}
// Format the message
if (message != (rct_string_id)STR_NONE) {
*dst++ = FORMAT_NEWLINE;
dst = utf8_write_codepoint(dst, FORMAT_NEWLINE);
format_string(dst, message, args);
dst += get_string_size(dst) - 1;
dst = get_string_end(dst);
}
log_verbose("show error, %s", _window_error_text + 1);