From bfb74ec39e703719d75ce0e687716d1fd226c6f8 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 23 May 2014 20:04:42 +0100 Subject: [PATCH] add string format and SDL get audio devices --- src/audio.c | 43 ++ src/audio.h | 12 + src/date.h | 1 + src/rct2.c | 4 + src/string_ids.c | 1369 +++++++++++++++++++++++++++++++++++++++++- src/string_ids.h | 26 +- src/util.c | 16 +- src/util.h | 2 + src/window_options.c | 33 +- 9 files changed, 1473 insertions(+), 33 deletions(-) diff --git a/src/audio.c b/src/audio.c index 20925d1a25..ca3f86f604 100644 --- a/src/audio.c +++ b/src/audio.c @@ -18,10 +18,53 @@ * along with this program. If not, see . *****************************************************************************/ +#include #include "audio.h" #include "addresses.h" #include "rct2.h" +int gAudioDeviceCount; +audio_device *gAudioDevices = NULL; + +void audio_init(int i) +{ + if (SDL_Init(SDL_INIT_AUDIO) < 0) { + RCT2_ERROR("SDL_Init %s", SDL_GetError()); + exit(-1); + } +} + +void audio_quit() +{ + SDL_QuitSubSystem(SDL_INIT_AUDIO); +} + +/** + * Populates audio devices. + */ +void audio_get_devices() +{ + int i; + + if (gAudioDevices != NULL) + free(gAudioDevices); + + gAudioDeviceCount = SDL_GetNumAudioDevices(SDL_FALSE); + if (gAudioDeviceCount > 0) { + gAudioDeviceCount++; + gAudioDevices = malloc(gAudioDeviceCount * sizeof(audio_device)); + + strcpy(gAudioDevices[0].name, "Default sound device"); + for (i = 1; i < gAudioDeviceCount; i++) { + const char *utf8_name = SDL_GetAudioDeviceName(i - 1, SDL_FALSE); + if (utf8_name == NULL) + utf8_name = "(UNKNOWN)"; + + strcpy(gAudioDevices[i].name, utf8_name); + } + } +} + void get_dsound_devices() { RCT2_CALLPROC(0x0040502E); diff --git a/src/audio.h b/src/audio.h index 2f5f9981ae..52a51c2cee 100644 --- a/src/audio.h +++ b/src/audio.h @@ -21,6 +21,18 @@ #ifndef _AUDIO_H_ #define _AUDIO_H_ +typedef struct { + char name[256]; +} audio_device; + +extern int gAudioDeviceCount; +extern audio_device *gAudioDevices; + +void audio_init(); +void audio_quit(); +void audio_get_devices(); + + #include /** diff --git a/src/date.h b/src/date.h index 23eae8cdc9..0fef3dde69 100644 --- a/src/date.h +++ b/src/date.h @@ -39,6 +39,7 @@ enum { extern const sint16 days_in_month[MONTH_COUNT]; int date_get_month(int months); +int date_get_year(int months); int date_get_total_months(int month, int year); void date_reset(); diff --git a/src/rct2.c b/src/rct2.c index 0fb90244b0..a8ab8ea254 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -29,6 +29,7 @@ #include #include #include "addresses.h" +#include "audio.h" #include "climate.h" #include "config.h" #include "date.h" @@ -76,6 +77,9 @@ __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInsta RCT2_GLOBAL(0x01423A08, HINSTANCE) = hInstance; RCT2_GLOBAL(RCT2_ADDRESS_CMDLINE, LPSTR) = lpCmdLine; get_system_info(); + + audio_init(); + audio_get_devices(); RCT2_CALLPROC(0x0040502E); // get_dsound_devices() config_init(); diff --git a/src/string_ids.c b/src/string_ids.c index 331bb7537b..78c380760f 100644 --- a/src/string_ids.c +++ b/src/string_ids.c @@ -19,9 +19,1363 @@ *****************************************************************************/ #include +#include #include "addresses.h" +#include "date.h" #include "rct2.h" #include "string_ids.h" +#include "util.h" + +// TODO Store real names in a data file. +#pragma region Real names + +const char *real_names[] = { + "Aaron", + "Abdul", + "Abraham", + "Abu", + "Adam", + "Adrian", + "Adriane", + "Aileen", + "Aisha", + "Akiko", + "Akira", + "Al", + "Ali", + "Alan", + "Alana", + "Albert", + "Alberta", + "Alec", + "Alesia", + "Alex", + "Alexa", + "Alexander", + "Alexandra", + "Alexis", + "Alf", + "Alfonso", + "Alfred", + "Alice", + "Alicia", + "Alison", + "Alistair", + "Allan", + "Allen", + "Allison", + "Allister", + "Alma", + "Alvin", + "Alyson", + "Amanda", + "Amber", + "Amilio", + "Amos", + "Amy", + "Ana", + "Anabel", + "Anastasia", + "Andie", + "Andrea", + "Andres", + "Andrew", + "Andy", + "Angel", + "Angela", + "Angelica", + "Angie", + "Angus", + "Anika", + "Ann", + "Anna", + "Anne", + "Annette", + "Annie", + "Annika", + "Anthony", + "Anton", + "Antonio", + "April", + "Archer", + "Archie", + "Arlene", + "Arnie", + "Arnold", + "Art", + "Arthur", + "Asaf", + "Ashley", + "Astrid", + "Aubrey", + "Austin", + "Austine", + "Avon", + "Avril", + "Axel", + "Aziz", + "Bailey", + "Barbara", + "Barney", + "Barry", + "Bart", + "Barton", + "Baxter", + "Beck", + "Becket", + "Becky", + "Belinda", + "Bella", + "Belle", + "Ben", + "Benjamin", + "Benny", + "Bernadette", + "Bernard", + "Bernice", + "Bess", + "Beth", + "Bethany", + "Bette", + "Betty", + "Bernard", + "Bernardette", + "Bernice", + "Berty", + "Bev", + "Beverly", + "Beverley", + "Bianca", + "Bill", + "Billie", + "Billy", + "Bjorn", + "Blaire", + "Blake", + "Blanche", + "Bo", + "Bob", + "Bobbie", + "Bobby", + "Bonnie", + "Boris", + "Brad", + "Bradley", + "Brady", + "Brandi", + "Brandon", + "Brandy", + "Brenda", + "Brendan", + "Brendon", + "Brent", + "Brett", + "Brian", + "Bridgit", + "Brigitte", + "Britney", + "Bruce", + "Bruno", + "Brutus", + "Bryan", + "Buck", + "Bucky", + "Bug", + "Burton", + "Byron", + "Cailin", + "Caitlyn", + "Cal", + "Caley", + "Callum", + "Calvin", + "Cameron", + "Camille", + "Campbell", + "Candy", + "Carl", + "Carla", + "Carlene", + "Carlos", + "Carmela", + "Carmen", + "Carol", + "Carole", + "Caroline", + "Carolyn", + "Carrie", + "Casey", + "Cassandra", + "Cassey", + "Cassie", + "Catherina", + "Catherine", + "Cathy", + "Caz", + "Cecelia", + "Cecil", + "Cecille", + "Ceilidh", + "Celeste", + "Chad", + "Charlene", + "Charles", + "Charlie", + "Charlotte", + "Chelsea", + "Cher", + "Cheri", + "Cheryll", + "Chip", + "Chloe", + "Chris", + "Christel", + "Christian", + "Christie", + "Christina", + "Christine", + "Christopher", + "Chuck", + "Cindy", + "Clark", + "Clair", + "Claire", + "Clara", + "Clarabell", + "Claude", + "Claudette", + "Claudia", + "Clayton", + "Cliff", + "Clifford", + "Clint", + "Clive", + "Clyde", + "Codey", + "Cody", + "Colin", + "Colleen", + "Connie", + "Coral", + "Corina", + "Craig", + "Curtis", + "Cynthia", + "Cyril", + "Darby", + "Daisy", + "Dale", + "Damien", + "Damon", + "Dan", + "Dana", + "Daniel", + "Danielle", + "Danni", + "Danny", + "Daphne", + "Darla", + "Darlene", + "Darrell", + "Darren", + "Darryl", + "Dave", + "David", + "Davie", + "Davis", + "Dawn", + "Dean", + "Debbie", + "Debby", + "Deborah", + "Debra", + "Debs", + "Deidre", + "Delores", + "Denise", + "Dennis", + "Denzel", + "Derek", + "Desmond", + "Diana", + "Diane", + "Dianna", + "Dick", + "Dillon", + "Dina", + "Dominic", + "Dominik", + "Don", + "Donald", + "Donna", + "Donovan", + "Doreen", + "Doris", + "Dorothy", + "Doug", + "Dougal", + "Douglas", + "Doyle", + "Drew", + "Duane", + "Dudley", + "Duncan", + "Dwight", + "Dylan", + "Earl", + "Ed", + "Eddie", + "Edgar", + "Edith", + "Edmond", + "Edward", + "Edwin", + "Edwina", + "Eileen", + "Elaine", + "Elina", + "Elisa", + "Elisabeth", + "Eliza", + "Elizabeth", + "Ella", + "Ellen", + "Elmer", + "Elsie", + "Emile", + "Emilio", + "Emily", + "Emma", + "Emmett", + "Enrique", + "Eric", + "Erica", + "Ericka", + "Erik", + "Erika", + "Erin", + "Erinn", + "Ernest", + "Esmeralda", + "Esta", + "Estella", + "Esther", + "Ethan", + "Eugene", + "Eva", + "Evan", + "Eve", + "Evelyn", + "Everett", + "Felix", + "Fabio", + "Falicia", + "Farah", + "Felicity", + "Fernando", + "Fergus", + "Fidelia", + "Finlay", + "Fiona", + "Fletcher", + "Flora", + "Florence", + "Floyd", + "Fly", + "Frances", + "Francesca", + "Francis", + "Francisco", + "Frank", + "Franklin", + "Franky", + "Fraser", + "Fred", + "Freda", + "Freddy", + "Fuzz", + "Gabriel", + "Gabriela", + "Gail", + "Garrett", + "Garth", + "Gary", + "Gavin", + "Gayle", + "Gene", + "Genevieve", + "Geoff", + "Geoffrey", + "George", + "Gerald", + "Geraldine", + "Gerard", + "Geri", + "Gerry", + "Gilbert", + "Gillian", + "Gina", + "Ginger", + "Giuseppe", + "Gladys", + "Glen", + "Glenda", + "Glenn", + "Gloria", + "Glyne", + "Goldie", + "Gordon", + "Grace", + "Graeme", + "Graham", + "Grant", + "Grayson", + "Greg", + "Gregor", + "Gregory", + "Gretchen", + "Gus", + "Guy", + "Gwen", + "Gwendoline", + "Hadrian", + "Hamish", + "Hank", + "Hannah", + "Hans", + "Harley", + "Harold", + "Harry", + "Harvey", + "Haseem", + "Hayley", + "Hazel", + "Heather", + "Hector", + "Heidi", + "Helen", + "Helena", + "Henri", + "Henry", + "Herbert", + "Herbie", + "Hermann", + "Hilda", + "Hollie", + "Holly", + "Homer", + "Horace", + "Howard", + "Hugh", + "Hugo", + "Iain", + "Ian", + "Imani", + "Imelda", + "Imran", + "Ingrid", + "Irene", + "Irma", + "Irving", + "Isaac", + "Isabella", + "Isabelle", + "Ishan", + "Isla", + "Ivan", + "Ivanna", + "Ivy", + "Izola", + "Jack", + "Jacque", + "Jacqueline", + "Jacqui", + "Jake", + "Jakob", + "James", + "Jacob", + "Jan", + "Janet", + "Jane", + "Janice", + "Jason", + "Jasper", + "Jay", + "Jayne", + "Jean", + "Jeanette", + "Jeff", + "Jeffrey", + "Jennifer", + "Jenny", + "Jeremy", + "Jerry", + "Jesse", + "Jessica", + "Jessie", + "Jessy", + "Jill", + "Jillian", + "Jim", + "Jimbo", + "Jimmy", + "Jo", + "Joan", + "Joann", + "Joanne", + "Jock", + "Jodi", + "Joe", + "Joel", + "Joelyn", + "Joey", + "Johan", + "John", + "Johnathan", + "Johnnie", + "Johnny", + "Jolynn", + "Jon", + "Jonah", + "Jonas", + "Jonathan", + "Joni", + "Jonny", + "Jordan", + "Jorge", + "Jose", + "Joseph", + "Josephine", + "Josh", + "Joshua", + "Joyce", + "Juan", + "Juana", + "Juanita", + "Judge", + "Judie", + "Judith", + "Judy", + "Julia", + "Julian", + "Julie", + "Juliette", + "Julio", + "Julius", + "June", + "Justin", + "Kaley", + "Kaitlyn", + "Kandice", + "Kara", + "Kareen", + "Karen", + "Karl", + "Karolyne", + "Karri", + "Kate", + "Katelyn", + "Katey", + "Kathy", + "Katherine", + "Kathie", + "Kathleen", + "Kathryn", + "Katie", + "Katrina", + "Katy", + "Katya", + "Kay", + "Keiko", + "Keith", + "Kelly", + "Kelsey", + "Ken", + "Kenneth", + "Kenny", + "Kerry", + "Kev", + "Kevin", + "Kieran", + "Kim", + "Kimberly", + "Kiriaki", + "Kirk", + "Klaus", + "Kris", + "Krista", + "Kristian", + "Kristy", + "Kurt", + "Kurtis", + "Kyle", + "Kylie", + "Laila", + "Lana", + "Lance", + "Larry", + "Lasse", + "Latisha", + "Laura", + "Lauren", + "Lauryn", + "Laurie", + "Lawrence", + "Leah", + "Lee", + "Leigh", + "Len", + "Lena", + "Lenore", + "Leo", + "Leon", + "Leonard", + "Leonardo", + "Leone", + "Leroy", + "Les", + "Leslie", + "Lesley", + "Lester", + "Lewis", + "Liam", + "Lillian", + "Lilly", + "Lily", + "Linda", + "Lindsay", + "Lindsey", + "Lisa", + "Lita", + "Logan", + "Lone", + "Loren", + "Loretta", + "Lori", + "Lorraine", + "Lottie", + "Louis", + "Louise", + "Lowell", + "Lucas", + "Lucy", + "Luis", + "Luke", + "Luther", + "Lydia", + "Lynn", + "Lynne", + "Lyssa", + "Mabel", + "Madeline", + "Maggie", + "Magnus", + "Mahamed", + "Malcolm", + "Mandy", + "Manuel", + "Marc", + "Marcela", + "Marci", + "Marcia", + "Marco", + "Marcus", + "Marcy", + "Margaret", + "Margarita", + "Maria", + "Mariah", + "Marian", + "Marianna", + "Marie", + "Marilyn", + "Marina", + "Marion", + "Marisa", + "Marissa", + "Marjorie", + "Mark", + "Markus", + "Marlene", + "Marlin", + "Marlon", + "Marshall", + "Martha", + "Martin", + "Martyn", + "Marvin", + "Mary", + "Mathew", + "Matt", + "Matthew", + "Maude", + "Maureen", + "Maurice", + "Mauricio", + "Mavis", + "Max", + "Maxine", + "May", + "Megan", + "Meghan", + "Mel", + "Melanie", + "Melany", + "Melinda", + "Melissa", + "Melody", + "Melvin", + "Mervin", + "Mhairi", + "Mia", + "Michael", + "Michelle", + "Mick", + "Mickey", + "Miguel", + "Mikael", + "Mike", + "Mikey", + "Miki", + "Mikko", + "Mildred", + "Millie", + "Milly", + "Milton", + "Miranda", + "Miriam", + "Mirriam", + "Mitchell", + "Mo", + "Molly", + "Monica", + "Monique", + "Monty", + "Morgan", + "Morten", + "Moses", + "Morris", + "Muriel", + "Murphy", + "Murray", + "Mustafa", + "Myles", + "Myrissa", + "Myrtle", + "Nadine", + "Nancy", + "Nanette", + "Naomi", + "Natalia", + "Natalie", + "Natasha", + "Nathan", + "Nathaniel", + "Neil", + "Nellie", + "Nelly", + "Nelson", + "Neville", + "Nicholas", + "Nichole", + "Nick", + "Nico", + "Nicola", + "Nicolas", + "Nicole", + "Nigel", + "Nikia", + "Nikki", + "Nina", + "Noah", + "Noel", + "Norma", + "Norman", + "Norris", + "Norvall", + "Olga", + "Olive", + "Oliver", + "Ollie", + "Omar", + "Oona", + "Orve", + "Orville", + "Oscar", + "Otto", + "Owen", + "Paisley", + "Pam", + "Pamela", + "Pandora", + "Pat", + "Patricia", + "Patrick", + "Patty", + "Paul", + "Paula", + "Pauline", + "Pedro", + "Peggy", + "Penelope", + "Penny", + "Perry", + "Pete", + "Peter", + "Phil", + "Philip", + "Phillip", + "Phyllis", + "Polly", + "Preston", + "Qasim", + "Quentin", + "Quinn", + "Rachel", + "Rae", + "Rafael", + "Raj", + "Raja", + "Ralph", + "Ramon", + "Randal", + "Rashid", + "Raquel", + "Raul", + "Ray", + "Raymond", + "Raymondo", + "Rebecca", + "Reg", + "Regina", + "Reginald", + "Reinhold", + "Rene", + "Reuben", + "Rex", + "Rhonda", + "Richard", + "Rick", + "Ricky", + "Rita", + "Robb", + "Robert", + "Roberta", + "Robin", + "Robina", + "Robyn", + "Robynne", + "Rock", + "Rockie", + "Rod", + "Rodney", + "Rodrigo", + "Roland", + "Rolf", + "Romeo", + "Ronald", + "Ronan", + "Ronnie", + "Roger", + "Rosalind", + "Rosanna", + "Rosanned", + "Rose", + "Rosemary", + "Rosetta", + "Rosie", + "Ross", + "Roxanne", + "Roy", + "Russell", + "Rosty", + "Ruben", + "Ruby", + "Ruth", + "Ryan", + "Sabrina", + "Sadie", + "Sally", + "Sam", + "Samantha", + "Sammy", + "Samuel", + "Sandra", + "Sandy", + "Sara", + "Sarah", + "Sasha", + "Saul", + "Scot", + "Scott", + "Sean", + "Sebastian", + "Sergio", + "Shakira", + "Shannon", + "Shari", + "Sharnell", + "Sharon", + "Sharyn", + "Shawn", + "Shelby", + "Shelley", + "Sherene", + "Sheri", + "Sherman", + "Sherry", + "Shirley", + "Sheryl", + "Shivani", + "Shona", + "Sian", + "Sid", + "Sidney", + "Simon", + "Sindy", + "Sinead", + "Sofia", + "Sonny", + "Sonja", + "Sonya", + "Sophia", + "Sophie", + "Spencer", + "Stacey", + "Stan", + "Stanley", + "Stefan", + "Stephen", + "Stephanie", + "Steve", + "Steven", + "Stewart", + "Stuart", + "Sue", + "Suki", + "Susan", + "Susana", + "Susanne", + "Susie", + "Suzanne", + "Sven", + "Sylvester", + "Sylvia", + "Tabatha", + "Tamara", + "Tammie", + "Tamsin", + "Tania", + "Tanya", + "Tara", + "Taylor", + "Ted", + "Teresa", + "Terrance", + "Terry", + "Tess", + "Tessa", + "Tex", + "Thelma", + "Theodore", + "Theresa", + "Thomas", + "Tiffany", + "Tiger", + "Tiko", + "Tillie", + "Tim", + "Timmy", + "Timothy", + "Tina", + "Toby", + "Todd", + "Tom", + "Tomaki", + "Tommy", + "Tonia", + "Tonie", + "Tony", + "Tracy", + "Travis", + "Trevor", + "Tricia", + "Trixie", + "Troy", + "Tucker", + "Tyler", + "Tyson", + "Ulysses", + "Uri", + "Val", + "Valerie", + "Vanessa", + "Vani", + "Vaughn", + "Velma", + "Vernon", + "Veronica", + "Vicki", + "Vicky", + "Victor", + "Victoria", + "Vijay", + "Vince", + "Vincent", + "Vinnie", + "Virginia", + "Viv", + "Vivian", + "Viviene", + "Wally", + "Walt", + "Walter", + "Walton", + "Wanda", + "Warren", + "Wayne", + "Wendell", + "Wendy", + "Wes", + "Wesley", + "Whitney", + "Will", + "William", + "Willie", + "Willis", + "Wilson", + "Winston", + "Wyatt", + "Xavier", + "Yasmin", + "Yogi", + "Ysabel", + "Yvonne", + "Zachary", + "Zachery", + "Zola" +}; + +#pragma endregion + +char real_name_initials[] = { + 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W' +}; + +void format_string_part_from_raw(char **dest, const char *src, char **args); +void format_string_part(char **dest, rct_string_id format, char **args); + +const char *get_string(rct_string_id id) +{ + return RCT2_ADDRESS(0x009BF2D4, const char*)[id]; +} + +void format_integer(char **dest, int value) +{ + int digit; + char *dst = *dest; + char *finish; + char tmp; + + // Negative sign + if (value < 0) { + *dst++ = '-'; + value = -value; + } + + *dest = dst; + + // Right to left + while (value > 0) { + digit = value % 10; + value /= 10; + + *dst++ = '0' + digit; + } + finish = dst; + + // Reverse string + dst--; + while (*dest < dst) { + tmp = **dest; + **dest = *dst; + *dst = tmp; + (*dest)++; + dst--; + } + *dest = finish; +} + +void format_comma_seperated_integer(char **dest, int value) +{ + int digit, groupIndex; + char *dst = *dest; + char *finish; + char tmp; + + // Negative sign + if (value < 0) { + *dst++ = '-'; + value = -value; + } + + *dest = dst; + + // Groups of three digits, right to left + groupIndex = 0; + while (value > 0) { + // Append group seperator + if (groupIndex == 3) { + groupIndex = 0; + *dst++ = ','; + } + + digit = value % 10; + value /= 10; + + *dst++ = '0' + digit; + groupIndex++; + } + finish = dst; + + // Reverse string + dst--; + while (*dest < dst) { + tmp = **dest; + **dest = *dst; + *dst = tmp; + (*dest)++; + dst--; + } + *dest = finish; +} + +void format_string_code(unsigned char format_code, char **dest, char **args) +{ + int value; + + switch (format_code) { + case FORMAT_COMMA32: + // Pop argument + value = *((sint32*)*args); + *args += 4; + + format_comma_seperated_integer(dest, value); + break; + case FORMAT_INT32: + // Pop argument + value = *((sint32*)*args); + *args += 4; + + format_integer(dest, value); + break; + case FORMAT_COMMA2DP32: + // Pop argument + value = *((sint32*)*args); + *args += 4; + + // TODO + printf("TODO: FORMAT_COMMA2DP32\n"); + break; + case FORMAT_COMMA16: + // Pop argument + value = *((sint16*)*args); + *args += 2; + + format_comma_seperated_integer(dest, value); + break; + case FORMAT_UINT16: + // Pop argument + value = *((uint16*)*args); + *args += 2; + + format_integer(dest, value); + break; + case FORMAT_CURRENCY2DP: + // Pop argument + value = *((sint32*)*args); + *args += 4; + + // TODO + printf("TODO: FORMAT_CURRENCY2DP\n"); + break; + case FORMAT_CURRENCY: + // Pop argument + value = *((sint32*)*args); + *args += 4; + + // TODO + printf("TODO: FORMAT_CURRENCY\n"); + break; + case FORMAT_STRINGID: + case FORMAT_STRINGID2: + // Pop argument + value = *((uint16*)*args); + *args += 2; + + format_string_part(dest, value, args); + break; + case FORMAT_STRING: + // Pop argument + value = *((uint32*)*args); + *args += 4; + + strcpy(*dest, (char*)value); + *dest += strlen(*dest); + break; + case FORMAT_MONTHYEAR: + // Pop argument + value = *((uint16*)*args); + *args += 2; + + uint16 dateArgs[] = { date_get_year(value), date_get_month(value) }; + char formatString[] = "?, Year ?"; + formatString[0] = FORMAT_MONTH; + formatString[8] = FORMAT_COMMA16; + format_string_part_from_raw(dest, formatString, (char**)&dateArgs); + break; + case FORMAT_MONTH: + // Pop argument + value = *((uint16*)*args); + *args += 2; + + strcpy(*dest, get_string(STR_MONTH_MARCH + date_get_month(value))); + *dest += strlen(*dest); + break; + case FORMAT_VELOCITY: + // Pop argument + value = *((sint16*)*args); + *args += 2; + + if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, uint8)) { + format_comma_seperated_integer(dest, mph_to_kmph(value)); + strcat(*dest, "kmh"); + *dest += strlen(*dest); + } else { + format_comma_seperated_integer(dest, value); + strcat(*dest, "mph"); + *dest += strlen(*dest); + } + break; + case FORMAT_POP16: + *args += 2; + break; + case FORMAT_PUSH16: + *args -= 2; + break; + case FORMAT_DURATION: + // Pop argument + value = *((uint16*)*args); + *args += 2; + + if (value / 60 > 0) { + format_integer(dest, value / 60); + strcpy(*dest, value / 60 == 1 ? "min:" : "mins:"); + *dest += strlen(*dest); + } + + format_integer(dest, value % 60); + strcpy(*dest, value % 60 == 1 ? "sec:" : "secs:"); + *dest += strlen(*dest); + break; + case FORMAT_REALTIME: + // Pop argument + value = *((uint16*)*args); + *args += 2; + + if (value / 60 > 0) { + format_integer(dest, value / 60); + strcpy(*dest, value / 60 == 1 ? "hour:" : "hours:"); + *dest += strlen(*dest); + } + + format_integer(dest, value % 60); + strcpy(*dest, value % 60 == 1 ? "min:" : "mins:"); + *dest += strlen(*dest); + break; + case FORMAT_LENGTH: + // Pop argument + value = *((sint16*)*args); + *args += 2; + + if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, uint8)) { + format_comma_seperated_integer(dest, value); + strcat(*dest, "m"); + *dest += strlen(*dest); + } else { + format_comma_seperated_integer(dest, metres_to_feet(value)); + strcat(*dest, "ft"); + *dest += strlen(*dest); + } + break; + case FORMAT_SPRITE: + // Pop argument + value = *((uint32*)*args); + *args += 4; + + *(*dest)++ = 23; + *((uint32*)(*dest)) = value; + *dest += 4; + break; + } +} + +void format_string_part_from_raw(char **dest, const char *src, char **args) +{ + unsigned char code; + while (1) { + code = *src++; + if (code < ' ') { + if (code == 0) { + *(*dest)++ = code; + break; + } else if (code <= 4) { + *(*dest)++ = code; + *(*dest)++ = *src++; + } else if (code <= 16) { + *(*dest)++ = code; + } else if (code <= 22) { + *(*dest)++ = code; + *(*dest)++ = *src++; + *(*dest)++ = *src++; + *(*dest)++ = *src++; + *(*dest)++ = *src++; + } else { + *(*dest)++ = code; + } + } else if (code <= 'z') { + *(*dest)++ = code; + } else if (code < 142) { + format_string_code(code, dest, args); + } else { + *(*dest)++ = code; + } + } +} + +void format_string_part(char **dest, rct_string_id format, char **args) +{ + if (format < 0x8000) { + // Language string + format_string_part_from_raw(dest, get_string(format), args); + } else if (format < 0x9000) { + // Custom string + format -= 0x8000; + // args += (format & 0xC00) >> 9; + format &= ~0xC00; + strcpy(*dest, RCT2_ADDRESS(0x135A8F4 + (format * 32), char)); + } else if (format < 0xE000) { + // Real name + format -= -0xA000; + sprintf(*dest, "%s %c.", + real_names[format % countof(real_names)], + real_name_initials[(format >> 10) % countof(real_name_initials)] + ); + } else { + // ? + RCT2_CALLPROC_EBPSAFE(RCT2_ADDRESS(0x0095AFB8, uint32)[format]); + } +} /** * Writes a formatted string to a buffer. @@ -32,7 +1386,8 @@ */ void format_string(char *dest, rct_string_id format, void *args) { - RCT2_CALLPROC_X(0x006C2555, format, 0, (int)args, 0, 0, (int)dest, 0); + // RCT2_CALLPROC_X(0x006C2555, format, 0, (int)args, 0, 0, (int)dest, 0); + format_string_part(&dest, format, (char**)&args); } void generate_string_file() @@ -61,14 +1416,24 @@ void generate_string_file() case 11: fputs("{OUTLINE}", f); break; case 34: fputs("{ENDQUOTES}", f); break; + case 123: fputs("{COMMA32}", f); break; + case 124: fputs("{INT32}", f); break; case 125: fputs("{COMMA2DP32}", f); break; case 126: fputs("{COMMA16}", f); break; + case 127: fputs("{UINT16}", f); break; case 128: fputs("{CURRENCY2DP}", f); break; case 129: fputs("{CURRENCY}", f); break; - case 130: fputs("{STRING}", f); break; + case 130: fputs("{STRINGID}", f); break; + case 131: fputs("{STRINGID2}", f); break; + case 132: fputs("{STRING}", f); break; case 133: fputs("{MONTHYEAR}", f); break; + case 134: fputs("{MONTH}", f); break; case 135: fputs("{VELOCITY}", f); break; + case 136: fputs("{POP16}", f); break; + case 137: fputs("{PUSH16}", f); break; + case 138: fputs("{DURATION}", f); break; + case 139: fputs("{REALTIME}", f); break; case 140: fputs("{LENGTH}", f); break; case 141: fputs("{SPRITE}", f); break; diff --git a/src/string_ids.h b/src/string_ids.h index 76ce106940..928f7024dd 100644 --- a/src/string_ids.h +++ b/src/string_ids.h @@ -28,6 +28,7 @@ void generate_string_file(); void reset_saved_strings(); enum { + // Font format codes FORMAT_TINYFONT = 7, FORMAT_BIGFONT, FORMAT_MEDIUMFONT, @@ -35,19 +36,31 @@ enum { FORMAT_OUTLINE, + // Non ascii-characters FORMAT_ENDQUOTES = 34, + // Argument format codes FORMAT_COMMA32 = 123, - FORMAT_COMMA2DP32 = 125, + FORMAT_INT32, + FORMAT_COMMA2DP32, FORMAT_COMMA16, - FORMAT_CURRENCY2DP = 128, + FORMAT_UINT16, + FORMAT_CURRENCY2DP, FORMAT_CURRENCY, + FORMAT_STRINGID, + FORMAT_STRINGID2, FORMAT_STRING, - FORMAT_MONTHYEAR = 133, - FORMAT_VELOCITY = 135, - FORMAT_LENGTH = 140, - FORMAT_SPRITE = 141, + FORMAT_MONTHYEAR, + FORMAT_MONTH, + FORMAT_VELOCITY, + FORMAT_POP16, + FORMAT_PUSH16, + FORMAT_DURATION, + FORMAT_REALTIME, + FORMAT_LENGTH, + FORMAT_SPRITE, + // Colour format codes FORMAT_BLACK = 142, FORMAT_GREY, FORMAT_WHITE, @@ -63,6 +76,7 @@ enum { FORMAT_PEARLAQUA, FORMAT_PALESILVER, + // Extra non-ascii characters FORMAT_AMINUSCULE = 159, FORMAT_UP, FORMAT_POUND = 163, diff --git a/src/util.c b/src/util.c index f330745a4d..6a151248c8 100644 --- a/src/util.c +++ b/src/util.c @@ -23,6 +23,20 @@ int squaredmetres_to_squaredfeet(int squaredMetres) { // 1 metre squared = 10.7639104 feet squared - // how it is done in RCT2 + // RCT2 approximates as 11 return squaredMetres * 11; } + +int metres_to_feet(int metres) +{ + // 1 metre = 3.2808399 feet + // RCT2 approximates as 3.28125 + return (metres * 840) / 256; +} + +int mph_to_kmph(int mph) +{ + // 1 mph = 1.60934 kmph + // RCT2 approximates as 1.609375 + return (mph * 1648) / 1024; +} \ No newline at end of file diff --git a/src/util.h b/src/util.h index e2c230ebdb..c93ac1cc69 100644 --- a/src/util.h +++ b/src/util.h @@ -22,5 +22,7 @@ #define _UTIL_H_ int squaredmetres_to_squaredfeet(int squaredMetres); +int metres_to_feet(int metres); +int mph_to_kmph(int mph); #endif diff --git a/src/window_options.c b/src/window_options.c index 8206d69532..fbb9897940 100644 --- a/src/window_options.c +++ b/src/window_options.c @@ -283,7 +283,6 @@ static void window_options_mouseup() static void window_options_mousedown() { int num_items, i; - sint64 device; short widgetIndex; rct_window *w; rct_widget *widget; @@ -305,22 +304,14 @@ static void window_options_mousedown() switch (widgetIndex) { case WIDX_SOUND_DROPDOWN: - num_items = RCT2_GLOBAL(RCT2_ADDRESS_NUM_DSOUND_DEVICES, uint32); - if (num_items == 0) - break; - - window_options_draw_dropdown_box(w, widget, num_items); + window_options_draw_dropdown_box(w, widget, gAudioDeviceCount); // populate the list with the sound devices - device = RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES, sint32) + 0x10; - - for (i = 0; i < num_items; i++) { + for (i = 0; i < gAudioDeviceCount; i++) { gDropdownItemsFormat[i] = 1142; - gDropdownItemsArgs[i] = 1170 | (device << 16); - device += 0x210; + gDropdownItemsArgs[i] = 1170 | ((uint64)gAudioDevices[i].name << 16); } gDropdownItemsChecked |= (1 << RCT2_GLOBAL(0x9AF280, uint32)); - break; case WIDX_HEIGHT_LABELS_DROPDOWN: window_options_draw_dropdown_box(w, widget, 2); @@ -380,7 +371,7 @@ static void window_options_mousedown() break; case WIDX_RESOLUTION_DROPDOWN: - RCT2_CALLPROC_EBPSAFE(0x006BB2AF); + // RCT2_CALLPROC_EBPSAFE(0x006BB2AF); break; case WIDX_TEMPERATURE_DROPDOWN: window_options_draw_dropdown_box(w, widget, 2); @@ -522,25 +513,19 @@ static void window_options_update(rct_window *w) __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); #endif - - sint32 format_args = RCT2_GLOBAL(0x009AF280, sint32); + sint32 currentSoundDevice = RCT2_GLOBAL(0x009AF280, sint32); // sound devices - if (format_args == -1 || RCT2_GLOBAL(RCT2_ADDRESS_NUM_DSOUND_DEVICES, sint32) == 0) { + if (currentSoundDevice == -1 || gAudioDeviceCount == 0) { RCT2_GLOBAL(0x013CE952, uint16) = STR_SOUND_NONE; } else { - format_args = RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES, uint32) + format_args * 0x210 + 16; RCT2_GLOBAL(0x013CE952, uint16) = 1170; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = format_args; + RCT2_GLOBAL(0x013CE952 + 2, uint32) = (uint32)gAudioDevices[currentSoundDevice].name; } // height: units/real values - if ((RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS)) - format_args = STR_UNITS; - else - format_args = STR_REAL_VALUES; - - RCT2_GLOBAL(0x013CE952 + 6, uint16) = (uint16)format_args; + RCT2_GLOBAL(0x013CE952 + 6, uint16) = ((RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS)) ? + STR_UNITS : STR_REAL_VALUES; // music: on/off RCT2_GLOBAL(0x013CE952 + 8, uint16) = STR_OFF +