diff --git a/data/language/dutch.txt b/data/language/dutch.txt index 45b3a01f41..63e0026614 100644 --- a/data/language/dutch.txt +++ b/data/language/dutch.txt @@ -3493,3 +3493,16 @@ STR_5160 :{MONTH} {STRINGID}, jaar {COMMA16} STR_5161 :{WHITE}Datumnotatie: STR_5162 :Dag/maand/jaar STR_5163 :Maand/dag/jaar +STR_5164 :Twitch-kanaalnaam +STR_5165 :Bezoekers namen van volgers geven +STR_5166 :Geeft bezoekers namen van gebruikers die het Twitch-kanaal volgen. +STR_5167 :Bezoekers met Twitch-volgersnamen volgen in berichtengebied +STR_5168 :Zet het bezoekersvolgsysteem aan voor bezoekers die naar Twitch-volgers zijn genoemd. +STR_5169 :Bezoekers namen van gebruikers in de Twitch-chat geven +STR_5170 :Geeft bezoekers namen van gebruikers in de Twitch-chat. +STR_5171 :Bezoekers met Twitch-chatnamen volgen in berichtengebied +STR_5172 :Zet het bezoekersvolgsysteem aan voor bezoekers die naar Twitch-chatters zijn genoemd. +STR_5173 :Twitch-chat als nieuws weergeven +STR_5174 :Zal chatberichten op Twitch die beginnen met !news in het berichtengebied tonen. +STR_5175 :Voer de naam van je Twitch-kanaal in +STR_5176 :Twitch-integratie inschakelen diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index e553eda52c..ac1fe63f1b 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -2702,7 +2702,7 @@ STR_2696 :Place trees STR_2697 :??? STR_2698 :??? STR_2699 :??? -STR_2700 :Autosave frequency +STR_2700 :Autosave frequency: STR_2701 :Every week STR_2702 :Every 2 weeks STR_2703 :Every month @@ -2740,7 +2740,7 @@ STR_2734 :{COMMA16}mph STR_2735 :{COMMA16}km/h STR_2736 :{MONTH}, Year {COMMA16} STR_2737 :{STRINGID} {MONTH}, Year {COMMA16} -STR_2738 :Title screen music +STR_2738 :Title screen music: STR_2739 :None STR_2740 :RollerCoaster Tycoon 1 STR_2741 :RollerCoaster Tycoon 2 @@ -2779,7 +2779,7 @@ STR_2772 :Faster Gamespeed STR_2773 :Windowed STR_2774 :Fullscreen STR_2775 :Fullscreen (desktop) -STR_2776 :Language +STR_2776 :Language: STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} STR_2779 :Viewport #{COMMA16} @@ -3499,27 +3499,27 @@ STR_5162 :Day/Month/Year STR_5163 :Month/Day/Year STR_5164 :Twitch Channel name STR_5165 :Name peeps after followers -STR_5166 :Will name peeps after channel's Twitch followers +STR_5166 :{SMALLFONT}{BLACK}Will name peeps after channel's Twitch followers STR_5167 :Track follower peeps -STR_5168 :Will turn on tracking information for guests named after channel's Twitch followers +STR_5168 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after channel's Twitch followers STR_5169 :Name peeps after people in Twitch chat -STR_5170 :Will name peeps after people in Twitch chat +STR_5170 :{SMALLFONT}{BLACK}Will name peeps after people in Twitch chat STR_5171 :Track chat peeps -STR_5172 :Will turn on tracking information for guests named after Twitch chat participants +STR_5172 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after Twitch chat participants STR_5173 :Pull Twitch chat as news -STR_5174 :Will use Twitch chat messages preceded by !news for in game notifications +STR_5174 :{SMALLFONT}{BLACK}Will use Twitch chat messages preceded by !news for in game notifications STR_5175 :Input the name of your Twitch channel STR_5176 :Enable Twitch integration -STR_5177 :Colour schemes -STR_5178 :Top Toolbar -STR_5179 :Bottom Toolbar -STR_5180 :Track Editor Bottom Toolbar -STR_5181 :Scenario Editor Bottom Toolbar -STR_5182 :Title Menu Buttons -STR_5183 :Title Exit Button -STR_5184 :Title Options Button -STR_5185 :Title Scenario Selection -STR_5186 :Park Information +STR_5177 :Fullscreen mode: +STR_5178 :{SMALLFONT}{BLACK}Show financial cheats +STR_5179 :{SMALLFONT}{BLACK}Show guest cheats +STR_5180 :{SMALLFONT}{BLACK}Show park cheats +STR_5181 :{SMALLFONT}{BLACK}Show ride cheats +STR_5182 :{INT32} +STR_5183 :Base height +STR_5184 :Enter base height between {COMMA16} and {COMMA16} +STR_5185 :Water level +STR_5186 :Enter water level between {COMMA16} and {COMMA16} STR_5187 :Finances STR_5188 :New Campaign STR_5189 :Research @@ -3577,3 +3577,13 @@ STR_5240 :Enter a name for the colour scheme STR_5241 :Can't change this preset STR_5242 :Preset name already exists STR_5243 :Invalid characters used +STR_5244 :Colour schemes +STR_5245 :Top Toolbar +STR_5246 :Bottom Toolbar +STR_5247 :Track Editor Bottom Toolbar +STR_5248 :Scenario Editor Bottom Toolbar +STR_5249 :Title Menu Buttons +STR_5250 :Title Exit Button +STR_5251 :Title Options Button +STR_5252 :Title Scenario Selection +STR_5253 :Park Information \ No newline at end of file diff --git a/data/language/english_us.txt b/data/language/english_us.txt index 55c8677b3f..19d49ec620 100644 --- a/data/language/english_us.txt +++ b/data/language/english_us.txt @@ -2682,7 +2682,7 @@ STR_2676 :??? STR_2677 :??? STR_2678 :??? STR_2679 :??? -STR_2680 :??? +STR_2680 :All research complete STR_2681 :{MEDIUMFONT}{BLACK}Increases your money by 5,000 STR_2682 :{MEDIUMFONT}{BLACK}Toggle between Free and Paid Entry STR_2683 :{MEDIUMFONT}{BLACK}Increases every peeps happiness to max @@ -3490,7 +3490,7 @@ STR_5150 :Enable debugging tools #Thousands separator STR_5151 :, #Decimals separator -STR_5152 :. +STR_5152 :. STR_5153 :RCT1 color scheme STR_5154 :Hardware display STR_5155 :Allow testing of unfinished tracks @@ -3502,3 +3502,16 @@ STR_5160 :{MONTH} {STRINGID}, Year {COMMA16} STR_5161 :{WHITE}Date Format: STR_5162 :Day/Month/Year STR_5163 :Month/Day/Year +STR_5164 :Twitch Channel name +STR_5165 :Name peeps after followers +STR_5166 :Will name peeps after channel's Twitch followers +STR_5167 :Track follower peeps +STR_5168 :Will turn on tracking information for guests named after channel's Twitch followers +STR_5169 :Name peeps after people in Twitch chat +STR_5170 :Will name peeps after people in Twitch chat +STR_5171 :Track chat peeps +STR_5172 :Will turn on tracking information for guests named after Twitch chat participants +STR_5173 :Pull Twitch chat as news +STR_5174 :Will use Twitch chat messages preceded by !news for in game notifications +STR_5175 :Input the name of your Twitch channel +STR_5176 :Enable Twitch integration diff --git a/data/language/german.txt b/data/language/german.txt index 12ede24bc7..c99a0e3db9 100644 --- a/data/language/german.txt +++ b/data/language/german.txt @@ -564,7 +564,7 @@ STR_0559 : STR_0560 : STR_0561 : STR_0562 : -STR_0563 :Die Fahrgäste sitzen in komfortablen Wagen mit einfachen Beckenhalterungen, in denen Sie gigantische, gemäßigte Gefälle erleben, aber auch viel Zeit oben `in der Luft' verbringen +STR_0563 :Die Fahrgäste sitzen in komfortablen Wagen mit einfachen Beckenhalterungen, in denen sie gigantische, gemäßigte Gefälle erleben, aber auch viel Zeit oben `in der Luft' verbringen STR_0564 :Diese Holzachterbahn ist schnell, rauh, laut und gibt einem das Gefühl, außer Kontrolle zu sein, wobei man häufig `in der Luft' ist STR_0565 :Eine einfache Holzachterbahn mit nur leichten Gefällen und Kurven, bei der die Wagen nur mit Hilfe von seitlichen Führungsrollen und der Schwerkraft auf der Strecke gehalten werden STR_0566 :Voneinander unabhängige Achterbahnwagen rasen auf einer engen Zickzack-Strecke mit scharfen Kurven und kurzen, starken Gefällen @@ -769,7 +769,7 @@ STR_0764 :Besucher {INT32} STR_0765 :Besucher {INT32} STR_0766 :Besucher {INT32} STR_0767 :Besucher {INT32} -STR_0768 :Handwerker {INT32} +STR_0768 :Parkpfleger {INT32} STR_0769 :Mechaniker {INT32} STR_0770 :Aufseher {INT32} STR_0771 :Animateur {INT32} @@ -857,7 +857,7 @@ STR_0852 :{WINDOW_COLOUR_2}Grafik von Simon Foster STR_0853 :{WINDOW_COLOUR_2}Sound und Musik von Allister Brimble STR_0854 :{WINDOW_COLOUR_2}Zusätzliche Sounds aufgenommen von David Ellis STR_0855 :{WINDOW_COLOUR_2}Repräsentation von Jacqui Lyons bei Marjacq Ltd. -STR_0856 :{WINDOW_COLOUR_2}Dank gilt:- +STR_0856 :{WINDOW_COLOUR_2}Dank gilt: STR_0857 :{WINDOW_COLOUR_2}Peter James Adcock, Joe Booth und John Wardley STR_0858 :{WINDOW_COLOUR_2} STR_0859 :{WINDOW_COLOUR_2} @@ -878,8 +878,8 @@ STR_0873 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_0874 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_0875 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_0876 :{BLACK}{DOWN} -STR_0877 :Zu niedrig ! -STR_0878 :Zu hoch ! +STR_0877 :Zu niedrig! +STR_0878 :Zu hoch! STR_0879 :Gelände kann hier nicht tiefer gemacht werden... STR_0880 :Gelände kann hier nicht höher gemacht werden... STR_0881 :Objekt ist im Weg @@ -946,7 +946,7 @@ STR_0941 :Vertikale Flächen entfernen STR_0942 :Bahnen ausblenden STR_0943 :Szenerie ausblenden STR_0944 :Speichern -STR_0945 :Nicht sp. +STR_0945 :Nicht speich. STR_0946 :Abbrechen STR_0947 :Vor dem Laden speichern? STR_0948 :Vor dem Beenden speichern? @@ -1059,13 +1059,13 @@ STR_1054 :{SMALLFONT}{BLACK}Bahn/Attraktion benennen STR_1055 :{SMALLFONT}{BLACK}Person benennen STR_1056 :{SMALLFONT}{BLACK}Mitarbeiter benennen STR_1057 :Name der Bahn/Attraktion -STR_1058 :Neuen Namen für diese Bahn/Attraktion eingeben:- +STR_1058 :Namen für diese Bahn/Attraktion eingeben: STR_1059 :Bahn/Attraktion kann nicht umbenannt werden... STR_1060 :Ungültiger Bahn-/Attraktionsname STR_1061 :Normaler Modus STR_1062 :Durchgängiger Rundenmodus -STR_1063 :Shuttle-Modus (Start bei umgek. Neig.) -STR_1064 :Angetriebener Start +STR_1063 :Shuttle-Modus (Start bei umgekehrter Neigung) +STR_1064 :Angetriebener Start (Station passieren) STR_1065 :Shuttle-Modus STR_1066 :Mietsboot-Modus STR_1067 :Aufwärtsstart @@ -1096,9 +1096,9 @@ STR_1091 :Zirkusmodus STR_1092 :Start nach unten STR_1093 :Schiefes Haus STR_1094 :Freefall-Modus -STR_1095 :Durchgängig. Streckenmodus m. Blockber. -STR_1096 :Angetriebener Start -STR_1097 :Modus mit angetrieb. Start u. Blockber. +STR_1095 :Durchgängiger Streckenmodus mit Blockbereichen +STR_1096 :Angetriebener Start (Station nicht passieren) +STR_1097 :Modus mit angetriebenem Start und Blockbereichen STR_1098 :Geht ans Ende d. {POP16}{STRINGID} STR_1099 :Warten auf Fahrgäste bei {POP16}{STRINGID} STR_1100 :Wartet auf Abfahrt {POP16}{STRINGID} @@ -1149,11 +1149,11 @@ STR_1144 :Eingang für diese Bahn/Attraktion kann nicht gebaut/verschoben wer STR_1145 :Ausgang für diese Bahn/Attraktion kann nicht gebaut/verschoben werden... STR_1146 :Eingang noch nicht gebaut STR_1147 :Ausgang noch nicht gebaut -STR_1148 :Viertellast -STR_1149 :Halblast -STR_1150 :Dreiviertellast -STR_1151 :Volle Last -STR_1152 :Beliebige Last +STR_1148 :Viertelvoll +STR_1149 :Halbvoll +STR_1150 :Dreiviertelvoll +STR_1151 :Voll +STR_1152 :Beliebig STR_1153 :Höhenmarkierungen an Fahrstrecken STR_1154 :Höhenmarkierungen auf dem Gelände STR_1155 :Höhenmarkierungen an Fußwegen @@ -1216,7 +1216,7 @@ STR_1211 :{WINDOW_COLOUR_2}Mindestwartezeit: STR_1212 :{WINDOW_COLOUR_2}Höchstwartezeit: STR_1213 :{SMALLFONT}{BLACK}Wählen Sie die Mindestwartezeit vor der Abfahrt aus STR_1214 :{SMALLFONT}{BLACK}Wählen Sie die Höchstwartezeit vor der Abfahrt aus -STR_1215 :{WINDOW_COLOUR_2}Mit benachb. Stationen synchron. +STR_1215 :{WINDOW_COLOUR_2}Mit benachbarten Stationen synchronisieren STR_1216 :{SMALLFONT}{BLACK}Auswählen, ob Abfahrt mit allen benachbarten Stationen (für `Rennen') synchronisiert werden soll STR_1217 :{COMMA16} Sekunden STR_1218 :{BLACK}{SMALLUP} @@ -1341,14 +1341,14 @@ STR_1336 :{STRINGID} - Station {POP16}{COMMA16} Eingang STR_1337 :{STRINGID} - Ausgang{POP16}{POP16} STR_1338 :{STRINGID} - Station {POP16}{COMMA16} Ausgang STR_1339 :{BLACK}Noch keine Testergebnisse... -STR_1340 :{WINDOW_COLOUR_2}Max. Geschw: {BLACK}{VELOCITY} +STR_1340 :{WINDOW_COLOUR_2}Max. Geschwindigkeit: {BLACK}{VELOCITY} STR_1341 :{WINDOW_COLOUR_2}Fahrtdauer: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} STR_1342 :{DURATION} STR_1343 :{DURATION} / STR_1344 :{WINDOW_COLOUR_2}Fahrtlänge: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} STR_1345 :{LENGTH} STR_1346 :{LENGTH} / -STR_1347 :{WINDOW_COLOUR_2}Durchschn. G.: {BLACK}{VELOCITY} +STR_1347 :{WINDOW_COLOUR_2}Durchschn. Geschwindigkeit: {BLACK}{VELOCITY} STR_1348 :{WINDOW_COLOUR_2}Max. positive vertikale G-Kraft: {BLACK}{COMMA2DP32}G STR_1349 :{WINDOW_COLOUR_2}Max. positive vertikale G-Kraft: {OUTLINE}{RED}{COMMA2DP32}G STR_1350 :{WINDOW_COLOUR_2}Max. negative vertikale G-Kraft: {BLACK}{COMMA2DP32}G @@ -1356,8 +1356,8 @@ STR_1351 :{WINDOW_COLOUR_2}Max. negative vertikale G-Kraft: {OUTLINE}{RED}{CO STR_1352 :{WINDOW_COLOUR_2}Max. seitliche G-Kraft: {BLACK}{COMMA2DP32}G STR_1353 :{WINDOW_COLOUR_2}Max. seitliche G-Kraft: {OUTLINE}{RED}{COMMA2DP32}G STR_1354 :{WINDOW_COLOUR_2}Höchste Fallhöhe: {BLACK}{LENGTH} -STR_1355 :{WINDOW_COLOUR_2}Abf.: {BLACK}{COMMA16} -STR_1356 :{WINDOW_COLOUR_2}Umkehr.: {BLACK}{COMMA16} +STR_1355 :{WINDOW_COLOUR_2}Stürze: {BLACK}{COMMA16} +STR_1356 :{WINDOW_COLOUR_2}Umkehrungen: {BLACK}{COMMA16} STR_1357 :{WINDOW_COLOUR_2}Löcher: {BLACK}{COMMA16} STR_1358 :{WINDOW_COLOUR_2}Gesamtzeit `in der Luft': {BLACK}{COMMA2DP32}Sek. STR_1359 :{WINDOW_COLOUR_2}Wartezeit: {BLACK}{COMMA16} Minute @@ -1432,7 +1432,7 @@ STR_1427 :{WINDOW_COLOUR_2}Besucher: {BLACK}{COMMA32} pro Stunde STR_1428 :{WINDOW_COLOUR_2}Eintrittspreis: STR_1429 :{POP16}{POP16}{POP16}{CURRENCY2DP} STR_1430 :Kostenlos -STR_1431 :Beim Gehen +STR_1431 :Geht STR_1432 :Geht Richtung {STRINGID} STR_1433 :Steht in Schlange für {STRINGID} STR_1434 :Ertrinkt @@ -1454,7 +1454,7 @@ STR_1449 :{SPRITE} {STRINGID}{NEWLINE}({STRINGID}) STR_1450 :{INLINE_SPRITE}{09}{20}{00}{00}{SPRITE} {STRINGID}{NEWLINE}({STRINGID}) STR_1451 :{STRINGID}{NEWLINE}({STRINGID}) STR_1452 :Name des Besuchers -STR_1453 :Namen für diesen Besucher eingeben:- +STR_1453 :Namen für diesen Besucher eingeben: STR_1454 :Besucher kann nicht benannt werden... STR_1455 :Ungültiger Name für Besucher STR_1456 :{WINDOW_COLOUR_2}Ausgegebenes Geld: {BLACK}{CURRENCY2DP} @@ -1693,7 +1693,7 @@ STR_1688 :Grundflächengröße 4 x 1 STR_1689 :Klotzbremsen STR_1690 :{WINDOW_COLOUR_2}{STRINGID}{NEWLINE}{BLACK}{STRINGID} STR_1691 :{WINDOW_COLOUR_2} Kosten: {BLACK}{CURRENCY} -STR_1692 :{WINDOW_COLOUR_2} Kosten: {BLACK}von {CURRENCY} +STR_1692 :{WINDOW_COLOUR_2} Kosten: {BLACK}ab {CURRENCY} STR_1693 :{SMALLFONT}{BLACK}Besucher STR_1694 :{SMALLFONT}{BLACK}Personal STR_1695 :{SMALLFONT}{BLACK}Einkünfte und Kosten @@ -1701,8 +1701,8 @@ STR_1696 :{SMALLFONT}{BLACK}Besucherinformationen STR_1697 :Können nicht in Wartebereich platziert werden STR_1698 :Können nur in Wartebereich platziert werden STR_1699 :Zu viele Leute im Spiel -STR_1700 :Neuen Handwerker einstellen -STR_1701 :Neuen Mechaniker einstellen +STR_1700 :Neuen Parkpfleger einst. +STR_1701 :Neuen Mechaniker einst. STR_1702 :Neuen Aufseher einstellen STR_1703 :Neuen Animateur einstellen STR_1704 :Es kann kein neuer Mitarbeiter eingestellt werden... @@ -1720,10 +1720,10 @@ STR_1715 :{INLINE_SPRITE}{250}{19}{00}{00}{WINDOW_COLOUR_2}Gras mähen STR_1716 :Ungültiger Name für Park STR_1717 :Park kann nicht umbenannt werden... STR_1718 :Parkname -STR_1719 :Geben Sie einen Parknamen ein:- +STR_1719 :Geben Sie einen Parknamen ein: STR_1720 :{SMALLFONT}{BLACK}Park benennen STR_1721 :Park geschlossen -STR_1722 :Park eröffnet +STR_1722 :Park geöffnet STR_1723 :Park kann nicht eröffnet werden... STR_1724 :Park kann nicht geschlossen werden... STR_1725 :Land kann nicht gekauft werden... @@ -1742,7 +1742,7 @@ STR_1737 :{COMMA16} STR_1738 :Rundenanzahl kann nicht geändert werden... STR_1739 :Rennen gewonnen von Besucher {INT32} STR_1740 :Rennen wurde gewonnen von {STRINGID} -STR_1741 :Noch nicht gebaut ! +STR_1741 :Noch nicht gebaut! STR_1742 :{WINDOW_COLOUR_2}Max. Besucherzahl: STR_1743 :{SMALLFONT}{BLACK}Höchstzahl zulässiger Personen zu einem Zeitpunkt bei dieser Bahn STR_1744 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} @@ -1860,11 +1860,11 @@ STR_1855 :{WINDOW_COLOUR_2}Baudatum: Vor {BLACK}{COMMA16} Jahren STR_1856 :{WINDOW_COLOUR_2}Gewinn pro verkaufter Artikel: {BLACK}{CURRENCY2DP} STR_1857 :{WINDOW_COLOUR_2}Verlust pro verkaufter Artikel: {BLACK}{CURRENCY2DP} STR_1858 :{WINDOW_COLOUR_2}Kosten: {BLACK}{CURRENCY} pro Monat -STR_1859 :Handwerker +STR_1859 :Parkpfleger STR_1860 :Mechaniker STR_1861 :Aufseher STR_1862 :Animateur -STR_1863 :Handwerker +STR_1863 :Parkpfleger STR_1864 :Mechaniker STR_1865 :Aufseher STR_1866 :Animateur @@ -1894,7 +1894,7 @@ STR_1889 :{WINDOW_COLOUR_2}Ausfallzeit: {MOVE_X}{255}{BLACK}{COMMA16}% STR_1890 :{SMALLFONT}{BLACK}Auswählen, wie oft ein Mechaniker diese Bahn überprüfen soll STR_1891 :Noch kein {STRINGID} im Park STR_1892 :RollerCoaster Tycoon 2 -STR_1893 :Legen Sie die RollerCoaster Tycoon 2-CD in folgendes Laufwerk ein:- +STR_1893 :Legen Sie die RollerCoaster Tycoon 2-CD in folgendes Laufwerk ein: STR_1894 :{WINDOW_COLOUR_2}{STRINGID} verkauft: {BLACK}{COMMA32} STR_1895 :{SMALLFONT}{BLACK}Neue Bahn/Attraktion bauen STR_1896 :{WINDOW_COLOUR_2}Ausgaben/Einnahmen @@ -1917,7 +1917,7 @@ STR_1912 :{MONTH} STR_1913 :{BLACK}+{CURRENCY2DP} STR_1914 :{BLACK}{CURRENCY2DP} STR_1915 :{RED}{CURRENCY2DP} -STR_1916 :{WINDOW_COLOUR_2}Darleh.: +STR_1916 :{WINDOW_COLOUR_2}Darlehen: STR_1917 :{POP16}{POP16}{POP16}{CURRENCY} STR_1918 :Es können keine weiteren Gelder geliehen werden! STR_1919 :Nicht genügend Geld verfügbar! @@ -2211,7 +2211,7 @@ STR_2206 :Leerer Getränkekarton STR_2207 :Leeres Saftglas STR_2208 :Bratwurst STR_2209 :Leere Schüssel -STR_2210 :{SMALLFONT}{BLACK}Liste der Handwerker im Park anzeigen +STR_2210 :{SMALLFONT}{BLACK}Liste der Parkpfleger im Park anzeigen STR_2211 :{SMALLFONT}{BLACK}Liste der Mechaniker im Park anzeigen STR_2212 :{SMALLFONT}{BLACK}Liste der Aufseher im Park anzeigen STR_2213 :{SMALLFONT}{BLACK}Liste der Animateure im Park anzeigen @@ -2250,8 +2250,8 @@ STR_2245 :Oktober STR_2246 :November STR_2247 :Dezember STR_2248 :Bahn/Attraktion kann nicht abgerissen werden... -STR_2249 :{BABYBLUE}Neue Bahn/Attraktion jetzt verfügbar:-{NEWLINE}{STRINGID} -STR_2250 :{BABYBLUE}Neue/s/r Szenerie/Thema jetzt verfügbar:-{NEWLINE}{STRINGID} +STR_2249 :{BABYBLUE}Neue Bahn/Attraktion jetzt verfügbar:{NEWLINE}{STRINGID} +STR_2250 :{BABYBLUE}Neue Szenerie jetzt verfügbar:{NEWLINE}{STRINGID} STR_2251 :Kann nur auf Wegen gebaut werden! STR_2252 :Kann nur über Wege gebaut werden! STR_2253 :Transportbahnen @@ -2262,8 +2262,8 @@ STR_2257 :Wasserbahnen STR_2258 :Läden & Stände STR_2259 :Szenerie & Thema STR_2260 :Keine Finanzierung -STR_2261 :Mindestfinanzier. -STR_2262 :Normale Finanzier. +STR_2261 :Mindestfinanzierung +STR_2262 :Normale Finanzierung STR_2263 :Höchstfinanzierung STR_2264 :Forschungsfinanzierung STR_2265 :{WINDOW_COLOUR_2}Kosten: {BLACK}{CURRENCY} pro Monat @@ -2312,12 +2312,12 @@ STR_2307 :Entwurf {STRINGID} auswählen STR_2308 :{STRINGID} Streckenentwürfe STR_2309 :Neuen Streckenentwurf installieren STR_2310 :Nach eigenem Entwurf bauen -STR_2311 :{WINDOW_COLOUR_2}Nervenkitzelwert: {BLACK}{COMMA2DP32} (ungef.) -STR_2312 :{WINDOW_COLOUR_2}Intensitätswert: {BLACK}{COMMA2DP32} (ungef.) -STR_2313 :{WINDOW_COLOUR_2}Übelkeitswert: {BLACK}{COMMA2DP32} (ungef.) +STR_2311 :{WINDOW_COLOUR_2}Nervenkitzelwert: {BLACK}{COMMA2DP32} (ungefähr) +STR_2312 :{WINDOW_COLOUR_2}Intensitätswert: {BLACK}{COMMA2DP32} (ungefähr) +STR_2313 :{WINDOW_COLOUR_2}Übelkeitswert: {BLACK}{COMMA2DP32} (ungefähr) STR_2314 :{WINDOW_COLOUR_2}Fahrtlänge: {BLACK}{STRINGID} -STR_2315 :{WINDOW_COLOUR_2}Kosten: {BLACK}ungef. {CURRENCY} -STR_2316 :{WINDOW_COLOUR_2}Erforderl. Platz {BLACK}{COMMA16} x {COMMA16} Blöcke +STR_2315 :{WINDOW_COLOUR_2}Kosten: {BLACK}ungefähr {CURRENCY} +STR_2316 :{WINDOW_COLOUR_2}Erforderlicher Platz: {BLACK}{COMMA16} x {COMMA16} Blöcke STR_2317 :{WINDOW_COLOUR_2}Soundqualität: STR_2318 :Niedrig STR_2319 :Mittel @@ -2354,10 +2354,10 @@ STR_2349 :{WINDOW_COLOUR_2}Lohn: {BLACK}{CURRENCY} pro Monat STR_2350 :{WINDOW_COLOUR_2}Angestellt: {BLACK}{MONTHYEAR} STR_2351 :{WINDOW_COLOUR_2}Gemähte Rasen: {BLACK}{COMMA16} STR_2352 :{WINDOW_COLOUR_2}Bewässerte Beete: {BLACK}{COMMA16} -STR_2353 :{WINDOW_COLOUR_2}Beseit. Abfall: {BLACK}{COMMA16} -STR_2354 :{WINDOW_COLOUR_2}Gel. Mülleimer: {BLACK}{COMMA16} -STR_2355 :{WINDOW_COLOUR_2}Repar. Bahnen: {BLACK}{COMMA16} -STR_2356 :{WINDOW_COLOUR_2}Inspiz. Bahnen: {BLACK}{COMMA16} +STR_2353 :{WINDOW_COLOUR_2}Beseitigter Abfall: {BLACK}{COMMA16} +STR_2354 :{WINDOW_COLOUR_2}Geleerte Mülleimer: {BLACK}{COMMA16} +STR_2355 :{WINDOW_COLOUR_2}Reparierte Bahnen: {BLACK}{COMMA16} +STR_2356 :{WINDOW_COLOUR_2}Inspizierte Bahnen: {BLACK}{COMMA16} STR_2357 :Haus STR_2358 :Einheiten STR_2359 :Echte Werte @@ -2408,8 +2408,8 @@ STR_2403 :Besucherzahl im Park STR_2404 :Monatliche Einkünfte durch Fahrttickets STR_2405 :Bauen Sie 10 Achterb. einer best. Länge STR_2406 :Stellen Sie den Bau von 5 Achterb. fertig -STR_2407 :Darleh. zurückz. u. best. Verkehrsw. err. -STR_2408 :Monatl. Gewinn d. Speisen/Werbeartikel +STR_2407 :Darlehen zurückzahlen und bestimmten Verkehrswert erreichen +STR_2408 :Monatlicher Gewinn durch Speisen/Werbeartikel STR_2409 :{WINDOW_COLOUR_2}Gerade durchgeführte Marketingkampagnen STR_2410 :{BLACK}Keine STR_2411 :{WINDOW_COLOUR_2}Verfügbare Marketingkampagnen @@ -2426,9 +2426,9 @@ STR_2421 :Gratis-{STRINGID} STR_2422 :Werbekampagne für {STRINGID} STR_2423 :Werbekampagne für {STRINGID} STR_2424 :{WINDOW_COLOUR_2}Gutscheine für freien Eintritt in den Park -STR_2425 :{WINDOW_COLOUR_2}Gutscheine für Freifahrt auf best. Bahn -STR_2426 :{WINDOW_COLOUR_2}Gutscheine für halben Eintrittspreis z. Park -STR_2427 :{WINDOW_COLOUR_2}Gutscheine für kostenl. Speise oder Getränk +STR_2425 :{WINDOW_COLOUR_2}Gutscheine für Freifahrt auf bestimmter Bahn +STR_2426 :{WINDOW_COLOUR_2}Gutscheine für halben Eintrittspreis zum Park +STR_2427 :{WINDOW_COLOUR_2}Gutscheine für kostenlose Speise oder Getränk STR_2428 :{WINDOW_COLOUR_2}Werbekampagne für den Park STR_2429 :{WINDOW_COLOUR_2}Werbekampagne für eine bestimmte Bahn STR_2430 :{BLACK}Gutscheine f. freien Eintr. z.{STRINGID} @@ -2483,17 +2483,18 @@ STR_2478 :{SMALLFONT}{BLACK}Geschwindigkeitsdiagramm im Zeitverlauf anzeigen STR_2479 :{SMALLFONT}{BLACK}Höhendiagramm im Zeitverlauf anzeigen STR_2480 :{SMALLFONT}{BLACK}Diagramm der vertikalen Beschleunigung im Zeitverlauf anzeigen STR_2481 :{SMALLFONT}{BLACK}Diagramm der seitlichen Beschleunigung im Zeitverlauf anzeigen -STR_2482 :{SMALLFONT}{BLACK}Gewinn: {CURRENCY} pro Woche, Verkehrswert: {CURRENCY} +STR_2482 :{SMALLFONT}{BLACK}Gewinn: {CURRENCY} pro Woche{NEWLINE}Verkehrswert: {CURRENCY} STR_2483 :{WINDOW_COLOUR_2}Wöchentlicher Gewinn: {BLACK}+{CURRENCY2DP} STR_2484 :{WINDOW_COLOUR_2}Wöchentlicher Gewinn: {RED}{CURRENCY2DP} STR_2485 :Steuerung STR_2486 :Allgemein -STR_2487 :Echte Besuchernamen anzeigen +STR_2487 :`Echte' Besuchernamen anzeigen STR_2488 :{SMALLFONT}{BLACK}Zwischen `echten' Besuchernamen und Besucherzahlen umschalten -STR_2489 :Kürzeltasten... +STR_2489 :Tastenkürzel... STR_2490 :Tastaturkürzel -STR_2491 :Tast. zur. -STR_2492 :{SMALLFONT}{BLACK}Alle Kürzeltasten auf Standardeinstellung zurücksetzen +#new +STR_2491 :Tasten zurücksetzen +STR_2492 :{SMALLFONT}{BLACK}Alle Tastenkürzel auf Standardeinstellung zurücksetzen STR_2493 :Oberstes Fenster schließen STR_2494 :Alle freien Fenster schließen STR_2495 :Baumodus abbrechen @@ -2683,9 +2684,9 @@ STR_2677 :??? STR_2678 :??? STR_2679 :??? STR_2680 :Alle Forschungen beendet -STR_2681 :{MEDIUMFONT}{BLACK}Erhöht ihr Geld um 5.000 -STR_2682 :{MEDIUMFONT}{BLACK}Zwischen freiem und kostenpflichtigem Eintritt umschalten -STR_2683 :{MEDIUMFONT}{BLACK}Erhöht die Glücklichkeit aller Besucher zum Maximum +STR_2681 :{MEDIUMFONT}{BLACK}Erhöht Ihr Geld um 5.000 +STR_2682 :{MEDIUMFONT}{BLACK}Zw. freiem und kostenpfl. Eintritt umsch. +STR_2683 :{MEDIUMFONT}{BLACK}Erhöht das Vergnügen der Besucher maximal STR_2684 :{MEDIUMFONT}{BLACK}Eine große Gruppe von Besuchern tritt ein STR_2685 :Simplex Noise Parameters STR_2686 :{WINDOW_COLOUR_2}Niedrig: @@ -2698,7 +2699,7 @@ STR_2692 :{WINDOW_COLOUR_2}Wasserhöhe: STR_2693 :{WINDOW_COLOUR_2}Terrain: STR_2694 :Generieren STR_2695 :Zufälliges Terrain -STR_2696 :Bäume Platzieren +STR_2696 :Bäume platzieren STR_2697 :??? STR_2698 :??? STR_2699 :??? @@ -2710,9 +2711,9 @@ STR_2704 :Alle 4 Monate STR_2705 :Jedes Jahr STR_2706 :Nie STR_2707 :Neues Fenster -STR_2708 :{WINDOW_COLOUR_1}Sind sie sicher, dass sie {STRINGID} überschreiben möchten? +STR_2708 :{WINDOW_COLOUR_1}Sind Sie sicher, dass Sie {STRINGID} überschreiben möchten? STR_2709 :Überschreiben -STR_2710 :Geben sie den Dateinamen ein. +STR_2710 :Geben Sie den Dateinamen ein: STR_2711 :; STR_2712 := STR_2713 :, @@ -2720,24 +2721,24 @@ STR_2714 :- STR_2715 :. STR_2716 :/ STR_2717 :' -STR_2718 :??? -STR_2719 :??? -STR_2720 :??? -STR_2721 :??? -STR_2722 :??? -STR_2723 :??? -STR_2724 :??? -STR_2725 :??? -STR_2726 :??? -STR_2727 :??? -STR_2728 :??? -STR_2729 :??? -STR_2730 :??? -STR_2731 :??? -STR_2732 :??? -STR_2733 :??? -STR_2734 :??? -STR_2735 :??? +STR_2718 :(Hoch) +STR_2719 :(Neue Datei) +STR_2720 :{UINT16}Sek. +STR_2721 :{UINT16}Sek. +STR_2722 :{UINT16}Min:{UINT16}Sek. +STR_2723 :{UINT16}Min:{UINT16}Sek. +STR_2724 :{UINT16}Min:{UINT16}Sek. +STR_2725 :{UINT16}Min:{UINT16}Sek. +STR_2726 :{UINT16}Min. +STR_2727 :{UINT16}Min. +STR_2728 :{UINT16}Stunde:{UINT16}Min. +STR_2729 :{UINT16}Stunde:{UINT16}Min. +STR_2730 :{UINT16}Stunden:{UINT16}Min. +STR_2731 :{UINT16}Stunden:{UINT16}Min. +STR_2732 :{COMMA16}ft +STR_2733 :{COMMA16}m +STR_2734 :{COMMA16}mph +STR_2735 :{COMMA16}km/h STR_2736 :{MONTH}, Jahr {COMMA16} STR_2737 :{STRINGID} {MONTH}, Jahr {COMMA16} STR_2738 :Musik im Hauptmenü @@ -2745,7 +2746,7 @@ STR_2739 :Keine STR_2740 :RollerCoaster Tycoon 1 STR_2741 :RollerCoaster Tycoon 2 STR_2742 :css50.dat nicht gefunden -STR_2743 :Kopieren sie data\css17.dat aus ihrem RCT1-Verzeichnis nach data\css50.dat in ihrem RCT2-Verzeichnis. +STR_2743 :Kopieren Sie data\css17.dat aus Ihrem RCT1-Verzeichnis nach data\css50.dat in Ihrem RCT2-Verzeichnis. STR_2744 :[ STR_2745 :\ STR_2746 :] @@ -2753,22 +2754,22 @@ STR_2747 :{ENDQUOTES} STR_2748 :Leiste STR_2749 :Mein neues Szenario # New strings used in the cheats window previously these were ??? -STR_2750 :??? -STR_2751 :??? +STR_2750 :Alle Gegenstände nach oben bewegen +STR_2751 :Alle Gegenstände nach unten bewegen STR_2752 :Gras beseitigen STR_2753 :Rasen mähen STR_2754 :Pflanzen gießen -STR_2755 :Vandalismus beseitigen +STR_2755 :Vandalismus bes. STR_2756 :Müll beseitigen -STR_2757 :Schönes Wetter erzwingen -STR_2758 :Gewitter erzwingen -STR_2759 :Zero Clearance +STR_2757 :Schönes Wetter +STR_2758 :Gewitter +STR_2759 :Kein Zwischenraum STR_2760 :+5000 Geld STR_2761 :Bezahlen für Eintritt STR_2762 :Bezahlen für Bahnen STR_2763 :??? STR_2764 :Glückliche Gäste -STR_2765 :Große Menschenmenge +STR_2765 :Große Straßenbahn STR_2766 :Szenario gewinnen STR_2767 :Wetter stoppen STR_2768 :Wetter fortsetzen @@ -2782,61 +2783,61 @@ STR_2775 :Vollbild (Desktop) STR_2776 :Sprache STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} -STR_2779 :??? -STR_2780 :??? +STR_2779 :Ansichtsfenster {COMMA16} +STR_2780 :Extra Ansichtsfenster # End of new strings STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID}{STRINGID} STR_2782 :UMSCHALT + STR_2783 :STRG + STR_2784 :Tastaturkürzel ändern -STR_2785 :{WINDOW_COLOUR_2}Drücken Sie die neue Kürzeltaste für:-{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2785 :{WINDOW_COLOUR_2}Drücken Sie die neue Taste für:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} STR_2786 :{SMALLFONT}{BLACK}Klicken Sie auf die Kürzelbeschreibung, um eine neue Taste auszuwählen STR_2787 :{WINDOW_COLOUR_2}Verkehrswert: {BLACK}{CURRENCY} STR_2788 :{WINDOW_COLOUR_2}Glückwunsch!{NEWLINE}{BLACK}Sie haben Ihr Ziel mit einem Firmenwert von {CURRENCY} erreicht! STR_2789 :{WINDOW_COLOUR_2}Sie haben Ihr Ziel nicht erreicht! STR_2790 :Geben Sie einen Namen in das Szenariodiagramm ein STR_2791 :Namen eingeben -STR_2792 :Geben Sie Ihren Namen für das Szenariodiagramm ein:- +STR_2792 :Geben Sie Ihren Namen für das Szenariodiagramm ein: STR_2793 :{SMALLFONT}(Durchgeführt von {STRINGID}) STR_2794 :{WINDOW_COLOUR_2}Durchgeführt von: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} mit einem Firmenwert von: {BLACK}{CURRENCY} STR_2795 :Sortieren STR_2796 :{SMALLFONT}{BLACK}Sortieren Sie die Bahnliste in die richtige Reihenfolge mit Hilfe der angezeigten Informationsart STR_2797 :Ansicht rollen, wenn Zeiger am Bildschirmrand ist STR_2798 :{SMALLFONT}{BLACK}Wählen Sie aus, ob die Ansicht gerollt werden soll, wenn sich der Mauszeiger am Bildschirmrand befindet -STR_2799 :{SMALLFONT}{BLACK}Steuertastenzuweisungen anzeigen oder ändern +STR_2799 :{SMALLFONT}{BLACK}Tastenkürzel anzeigen oder ändern STR_2800 :{WINDOW_COLOUR_2}Besucher gesammt: {BLACK}{COMMA32} -STR_2801 :{WINDOW_COLOUR_2}Einkünfte durch Eintrittskarten: {BLACK}{CURRENCY2DP} +STR_2801 :{WINDOW_COLOUR_2}Einkünfte d. Eintrittskarten: {BLACK}{CURRENCY2DP} STR_2802 :Karte STR_2803 :{SMALLFONT}{BLACK}Diese Besucher auf Karte hervorheben STR_2804 :{SMALLFONT}{BLACK}Diese Mitarbeiter auf Karte hervorheben STR_2805 :{SMALLFONT}{BLACK}Parkkarte anzeigen -STR_2806 :{RED}Die Besucher beschweren sich über den schrecklichen Zustand der Fußwege in Ihrem Park{NEWLINE}Überprüfen Sie, wo Ihre Handwerker sind, und organisieren Sie sie erforderlichenfalls besser -STR_2807 :{RED}Die Besucher beschweren sich über das Müllaufkommen in Ihrem Park{NEWLINE}Überprüfen Sie, wo Ihre Handwerker sind, und organisieren Sie sie erforderlichenfalls besser +STR_2806 :{RED}Die Besucher beschweren sich über den schrecklichen Zustand der Fußwege in Ihrem Park{NEWLINE}Überprüfen Sie, wo Ihre Parkpfleger sind, und organisieren Sie sie erforderlichenfalls besser +STR_2807 :{RED}Die Besucher beschweren sich über das Müllaufkommen in Ihrem Park{NEWLINE}Überprüfen Sie, wo Ihre Parkpfleger sind, und organisieren Sie sie erforderlichenfalls besser STR_2808 :{RED}Die Besucher beschweren sich über den Vandalismus in Ihrem Park{NEWLINE}Überprüfen Sie, wo Ihre Aufseher sind, und organisieren Sie sie erforderlichenfalls besser STR_2809 :{RED}Die Besucher sind hungrig und können nirgendwo etwas finden, um Speisen zu kaufen STR_2810 :{RED}Die Besucher sind durstig und können nirgendwo etwas finden, um Getränke zu kaufen STR_2811 :{RED}Die Besucher beschweren sich, weil sie die Toiletten in Ihrem Park nicht finden können STR_2812 :{RED}Die Besucher verirren sich oder es kommt zu Staus{NEWLINE}Überprüfen Sie, ob die Anordnung Ihrer Fußwege eventuell verbessert werden muss, damit die Besucher sich zurechtfinden STR_2813 :{RED}Der Eintrittspreis für Ihren Park ist zu hoch!{NEWLINE}Verringern Sie den Eintrittspreis oder verbessern Sie das Parkangebot, um mehr Besucher anzuziehen -STR_2814 :{WINDOW_COLOUR_2}Auszeichnug f. ungepflegtesten Park -STR_2815 :{WINDOW_COLOUR_2}Auszeichnung f. saubersten Park -STR_2816 :{WINDOW_COLOUR_2}Auszeichnung f. Park mit besten Achterbahnen -STR_2817 :{WINDOW_COLOUR_2}Auszeichnung f. Park mit bestem Angebot -STR_2818 :{WINDOW_COLOUR_2}Auszeichnung f. den schönsten Park -STR_2819 :{WINDOW_COLOUR_2}Auszeichnung f. Park m. schlimmst. Ang. -STR_2820 :{WINDOW_COLOUR_2}Auszeichnung f. den sichersten Park -STR_2821 :{WINDOW_COLOUR_2}Auszeichnung f. das beste Personal -STR_2822 :{WINDOW_COLOUR_2}Auszeichnung f. bestes Essen -STR_2823 :{WINDOW_COLOUR_2}Auszeichnung f. schlechtestes Essen -STR_2824 :{WINDOW_COLOUR_2}Auszeichnung f. beste Parktoiletten -STR_2825 :{WINDOW_COLOUR_2}Auszeichnung f. enttäuschendsten Park -STR_2826 :{WINDOW_COLOUR_2}Auszeichnung f. die besten Wasserbahnen -STR_2827 :{WINDOW_COLOUR_2}Auszeichnung f. beste selbstentw. Bahn. -STR_2828 :{WINDOW_COLOUR_2}Auszeichnung f. bunteste Farbschemas -STR_2829 :{WINDOW_COLOUR_2}Auszeichnung f. konfuseste Parkanordn. -STR_2830 :{WINDOW_COLOUR_2}Auszeichnung f. beste gemäßigte Bahn +STR_2814 :{WINDOW_COLOUR_2}Auszeichnung für ungepflegtesten Park +STR_2815 :{WINDOW_COLOUR_2}Auszeichnung für saubersten Park +STR_2816 :{WINDOW_COLOUR_2}Auszeichnung für Park mit den besten Achterbahnen +STR_2817 :{WINDOW_COLOUR_2}Auszeichnung für Park mit bestem Angebot +STR_2818 :{WINDOW_COLOUR_2}Auszeichnung für den schönsten Park +STR_2819 :{WINDOW_COLOUR_2}Auszeichnung für Park mit schlimmstem Angebot +STR_2820 :{WINDOW_COLOUR_2}Auszeichnung für den sichersten Park +STR_2821 :{WINDOW_COLOUR_2}Auszeichnung für das beste Personal +STR_2822 :{WINDOW_COLOUR_2}Auszeichnung für bestes Essen +STR_2823 :{WINDOW_COLOUR_2}Auszeichnung für schlechtestes Essen +STR_2824 :{WINDOW_COLOUR_2}Auszeichnung für beste Parktoiletten +STR_2825 :{WINDOW_COLOUR_2}Auszeichnung für enttäuschendsten Park +STR_2826 :{WINDOW_COLOUR_2}Auszeichnung für die besten Wasserbahnen +STR_2827 :{WINDOW_COLOUR_2}Auszeichnung für beste selbstentwickelte Bahn +STR_2828 :{WINDOW_COLOUR_2}Auszeichnung für bunteste Farbschemas +STR_2829 :{WINDOW_COLOUR_2}Auszeichnung für konfuseste Parkanordnung +STR_2830 :{WINDOW_COLOUR_2}Auszeichnung für beste gemäßigte Bahn STR_2831 :{TOPAZ}Ihr Park hat die Auszeichnung `Ungepflegtester Park des Landes' erhalten! -STR_2832 :{TOPAZ}Ihr Park hat die Auszeichnung `Säuberster Park des Landes' erhalten! +STR_2832 :{TOPAZ}Ihr Park hat die Auszeichnung `Sauberster Park des Landes' erhalten! STR_2833 :{TOPAZ}Ihr Park hat die Auszeichnung `Park mit den besten Achterbahnen' erhalten! STR_2834 :{TOPAZ}Ihr Park hat die Auszeichnung `Park mit dem besten Angebot des Landes' erhalten! STR_2835 :{TOPAZ}Ihr Park hat die Auszeichnung `Schönster Park des Landes' erhalten! @@ -2858,7 +2859,7 @@ STR_2850 :Neuer Streckenentwurf erfolgreich installiert STR_2851 :Szenario bereits installiert STR_2852 :Streckenentwurf bereits installiert STR_2853 :Von der örtlichen Behörde verboten! -STR_2854 :{RED}Besucher gelangen nicht zum Eingang von {STRINGID} !{NEWLINE}Bauen Sie einen Fußweg zum Eingang +STR_2854 :{RED}Besucher gelangen nicht zum Eingang von {STRINGID}!{NEWLINE}Bauen Sie einen Fußweg zum Eingang STR_2855 :{RED}{STRINGID} hat keinen Fußweg, der vom Ausgang wegführt!{NEWLINE}Legen Sie einen Fußweg an, der vom Bahnausgang wegführt STR_2856 :{WINDOW_COLOUR_2}Lehrgang STR_2857 :{WINDOW_COLOUR_2}(Drücken Sie eine Taste oder klicken Sie mit der Maus, um die Kontrolle zu übernehmen) @@ -2982,12 +2983,12 @@ STR_2974 :Alternatives Farbschema 3 STR_2975 :{SMALLFONT}{BLACK}Wählen Sie das Farbschema aus, das geändert oder mit dem eine Bahn gestrichen werden soll STR_2976 :{SMALLFONT}{BLACK}Streichen Sie einen bestimmten Bereich dieser Bahn mit dem ausgewählten Farbschema STR_2977 :Mitarbeitername -STR_2978 :Neuen Namen für diesen Mitarbeiter eingeben:- +STR_2978 :Neuen Namen für diesen Mitarbeiter eingeben: STR_2979 :Dieser Mitarbeiter kann nicht benannt werden... STR_2980 :Zu viele Banner im Spiel STR_2981 :{RED}Kein Zutritt - - STR_2982 :Bannertext -STR_2983 :Neuen Text für diesen Banner eingeben:- +STR_2983 :Neuen Text für diesen Banner eingeben: STR_2984 :Neuer Text für den Banner kann nicht erstellt werden... STR_2985 :Banner STR_2986 :{SMALLFONT}{BLACK}Text auf Banner ändern @@ -2997,7 +2998,7 @@ STR_2989 :{SMALLFONT}{BLACK}Hauptfarbe auswählen STR_2990 :{SMALLFONT}{BLACK}Textfarbe auswählen STR_2991 :Schild STR_2992 :Schildtext -STR_2993 :Neuen Text für dieses Schild eingeben:- +STR_2993 :Neuen Text für dieses Schild eingeben: STR_2994 :{SMALLFONT}{BLACK}Text auf Schild ändern STR_2995 :{SMALLFONT}{BLACK}Dieses Schild abreißen STR_2996 :{BLACK}ABC @@ -3089,7 +3090,7 @@ STR_3081 :Burgeingang (grau) STR_3082 :Burgeingang (braun) STR_3083 :Dschungeleingang STR_3084 :Blockhütteneingang -STR_3085 :Klassischer/Röm. Eingang +STR_3085 :Klassischer/Römischer Eingang STR_3086 :Abstrakter Eingang STR_3087 :Schnee-/Eis-Eingang STR_3088 :Pagodeneingang @@ -3141,7 +3142,7 @@ STR_3133 :Dies kann nicht auf schrägem Untergrund gebaut werden STR_3134 :{RED}(Der Entwurf enthält Szenerie, die nicht verfügbar ist) STR_3135 :{RED}(Fahrzeugentwurf nicht verfügbar - Dies kann sich auf die Bahn-Performance auswirken) STR_3136 :Warnung: Dieser Entwurf wird mit einer alternativen Fahrzeugart gebaut und könnte möglicherweise nicht wie gewünscht funktionieren -STR_3137 :Nahe Szenerie ausw. +STR_3137 :Nahe Szenerie auswählen STR_3138 :Auswahl zurücksetzen STR_3139 :Kabellift funktioniert nicht in diesem Betriebsmodus STR_3140 :Kabellifthügel muss direkt nach der Station beginnen @@ -3260,14 +3261,14 @@ STR_3252 :Max. Darlehensgröße kann nicht weiter erhöht werden! STR_3253 :Max. Darlehensgröße kann nicht weiter reduziert werden! STR_3254 :Zinsrate kann nicht weiter erhöht werden! STR_3255 :Zinsrate kann nicht weiter reduziert werden! -STR_3256 :Weniger aufreg. Bahnen bevorzugt +STR_3256 :Weniger aufregendere Bahnen bevorzugt STR_3257 :{SMALLFONT}{BLACK}Wählen Sie aus, ob die Besucher im Allgemeinen weniger aufregende Bahnen vorziehen STR_3258 :Aufregendere Bahnen bevorzugt STR_3259 :{SMALLFONT}{BLACK}Wählen Sie aus, ob die Besucher im Allgemeinen aufregendere Bahnen vorziehen -STR_3260 :{WINDOW_COLOUR_2}Durchschn. Geld pro Bes.: -STR_3261 :{WINDOW_COLOUR_2}Anfangsvergn. d. Besuch.: -STR_3262 :{WINDOW_COLOUR_2}Anfangshunger d. Besuch.: -STR_3263 :{WINDOW_COLOUR_2}Anfangsdurst d. Besucher: +STR_3260 :{WINDOW_COLOUR_2}Durchschnittliches Geld pro Besucher: +STR_3261 :{WINDOW_COLOUR_2}Anfangsvergnügen der Besucher: +STR_3262 :{WINDOW_COLOUR_2}Anfangshunger der Besucher: +STR_3263 :{WINDOW_COLOUR_2}Anfangsdurst der Besucher: STR_3264 :Dies kann nicht weiter erhöht werden! STR_3265 :Dies kann nicht weiter reduziert werden! STR_3266 :{SMALLFONT}{BLACK}Wählen Sie aus, was der Park für Eintritt und Fahrten verlangt @@ -3283,8 +3284,8 @@ STR_3275 :Höhere Schwierigkeitsstufe für Besuchergewinnung STR_3276 :{SMALLFONT}{BLACK}Machen Sie das Anlocken von Besuchern schwieriger STR_3277 :{WINDOW_COLOUR_2}Kosten für Landkauf: STR_3278 :{WINDOW_COLOUR_2}Kosten für Erwerb v. Baurechten: -STR_3279 :Freier Eintritt/Bez. pro Fahrt -STR_3280 :Bez. f. Eintritt/Gratis fahren +STR_3279 :Freier Eintritt/Bezahlen pro Fahrt +STR_3280 :Bezahlen für Eintritt/Gratis fahren STR_3281 :{WINDOW_COLOUR_2}Eintrittspreis: STR_3282 :{SMALLFONT}{BLACK}Ziel und Parkname auswählen STR_3283 :{SMALLFONT}{BLACK}Bahnen auswählen, die beibehalten werden sollen @@ -3298,7 +3299,7 @@ STR_3290 :Kühl und feucht STR_3291 :Warm STR_3292 :Heiß und trocken STR_3293 :Kalt -STR_3294 :Änderung... +STR_3294 :Ändern... STR_3295 :{SMALLFONT}{BLACK}Namen des Parks ändern STR_3296 :{SMALLFONT}{BLACK}Namen des Szenarios ändern STR_3297 :{SMALLFONT}{BLACK}Detailhinweise zu Park/Szenario ändern @@ -3308,9 +3309,9 @@ STR_3300 :{WINDOW_COLOUR_2}Szenarioname: {BLACK}{STRINGID} STR_3301 :{WINDOW_COLOUR_2}Zieldatum: STR_3302 :{WINDOW_COLOUR_2}{MONTHYEAR} STR_3303 :{WINDOW_COLOUR_2}Besucheranzahl: -STR_3304 :{WINDOW_COLOUR_2}Verkehrsw.: +STR_3304 :{WINDOW_COLOUR_2}Verkehrswert: STR_3305 :{WINDOW_COLOUR_2}Mon. Einkünfte: -STR_3306 :{WINDOW_COLOUR_2}Mon. Gewinn: +STR_3306 :{WINDOW_COLOUR_2}Monatlicher Gewinn: STR_3307 :{WINDOW_COLOUR_2}Mindestlänge: STR_3308 :{WINDOW_COLOUR_2}Nervenkitzelwert: STR_3309 :{WINDOW_COLOUR_2}{COMMA16} @@ -3318,9 +3319,9 @@ STR_3310 :{WINDOW_COLOUR_2}{LENGTH} STR_3311 :{WINDOW_COLOUR_2}{COMMA2DP32} STR_3312 :{WINDOW_COLOUR_2}Bahnen/Attrakt. unter Beibehaltungsauftrag: STR_3313 :Szenarioname -STR_3314 :Namen für Szenario eingeben:- +STR_3314 :Namen für Szenario eingeben: STR_3315 :Park-/Szenariodetails -STR_3316 :Beschreibung für dieses Szenario eingeben:- +STR_3316 :Beschreibung für dieses Szenario eingeben: STR_3317 :Noch keine Details STR_3318 :{SMALLFONT}{BLACK}Wählen Sie aus, in welcher Gruppe dieses Szenario vorkommt STR_3319 :{WINDOW_COLOUR_2}Szenariogruppe: @@ -3355,7 +3356,7 @@ STR_3347 :Bahn ist zu lang, enthält zu viele Elemente oder Szenerie ist zu z STR_3348 :Umbenennen STR_3349 :Löschen STR_3350 :Streckenentwurfsname -STR_3351 :Neuen Namen für diesen Streckenentwurf eingeben:- +STR_3351 :Neuen Namen für diesen Streckenentwurf eingeben: STR_3352 :Streckenentwurf kann nicht umbenannt werden... STR_3353 :Neuer Name enthält ungültige Zeichen STR_3354 :Entweder besteht bereits eine Datei mit diesem Namen oder die Datei ist schreibgeschützt @@ -3368,7 +3369,7 @@ STR_3360 :Warnung! STR_3361 :Zu viele Streckenentwürfe dieser Art - einige werden nicht aufgeführt. STR_3362 :Erzwungenes Software-Buffer-Mixing STR_3363 :{SMALLFONT}{BLACK}Diese Option wählen, falls das Spiel jedesmal kurz anhält sobald Töne gespielt werden oder falls ein Rauschen zu hören ist. -STR_3364 :Fortgeschr. +STR_3364 :Fortgeschritten STR_3365 :{SMALLFONT}{BLACK}Ermöglichen Sie die Auswahl einzelner Szenerieobjekte zusätzlich zu Szeneriegruppen STR_3366 :{BLACK}= Bahn STR_3367 :{BLACK}= Imbissstand @@ -3451,40 +3452,62 @@ STR_3443 :Seite 4 STR_3444 :Seite 5 STR_3445 :Patrouillenbereich festlegen STR_3446 :Patrouillenbereich verwerfen - # New strings, cleaner -STR_5120 :Show finances button on toolbar -STR_5121 :Show research button on toolbar -STR_5122 :Show all vehicles sharing a track/ride type -STR_5123 :Renew rides -STR_5124 :No Six Flags -STR_5125 :All destructable -STR_5126 :Random title music -STR_5127 :{SMALLFONT}{BLACK}Disable land elevation -STR_5128 :Selection size -STR_5129 :Enter selection size between {COMMA16} and {COMMA16} -STR_5130 :Map size -STR_5131 :Enter map size between {COMMA16} and {COMMA16} -STR_5132 :Fix all rides -STR_5133 :{SMALLFONT}{BLACK}Adjust smaller area of land rights -STR_5134 :{SMALLFONT}{BLACK}Adjust larger area of land rights -STR_5135 :{SMALLFONT}{BLACK}Buy land rights and construction rights -STR_5136 :Land rights -STR_5137 :Allow lift hill and launch speeds{NEWLINE}up to {VELOCITY} +STR_5120 :Finanzen in der Symbolleiste anzeigen +STR_5121 :Forschung in der Symbolleiste anzeigen +STR_5122 :Fahrzeuge gleicher Strecke/Bahnart anzeigen +STR_5123 :Bahnen erneuern +STR_5124 :Keine Six Flags +STR_5125 :Alles zerstörbar +STR_5126 :Zufällige Titelmusik +STR_5127 :{SMALLFONT}{BLACK}Höhenanpassung deaktivieren +STR_5128 :Auswahlgröße +STR_5129 :Auswahlgröße zwischen {COMMA16} und {COMMA16} eingeben: +STR_5130 :Kartengröße +STR_5131 :Kartengröße zwischen {COMMA16} und {COMMA16} eingeben: +STR_5132 :Bahnen reparieren +STR_5133 :{SMALLFONT}{BLACK}Kleineren Landbereich anpassen +STR_5134 :{SMALLFONT}{BLACK}Größeren Landbereich anpassen +STR_5135 :{SMALLFONT}{BLACK}Kaufe Land- und Baurechte +STR_5136 :Landrechte +STR_5137 :Erlaube Lifthügel- und Antriebsgeschw.{NEWLINE}bis zu {VELOCITY} STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} STR_5139 :{WHITE}{STRINGID} -STR_5140 :Disable brakes failure -STR_5141 :Disable all breakdowns -STR_5142 :Normal Speed -STR_5143 :Quick Speed -STR_5144 :Fast Speed -STR_5145 :Turbo Speed -STR_5146 :Hyper Speed -STR_5147 :Show cheats button on toolbar -STR_5148 :{SMALLFONT}{BLACK}Change the game speed -STR_5149 :{SMALLFONT}{BLACK}Open the cheats window -STR_5150 :Enable debugging tools -#Thousands separator +STR_5140 :Deaktiviere Bremsenfehlfunktion +STR_5141 :Deaktiviere alle Störungen +STR_5142 :Normale Geschwindigkeit +STR_5143 :Erhöhte Geschwindigkeit +STR_5144 :Hohe Geschwindigkeit +STR_5145 :Sehr Hohe Geschwindigkeit +STR_5146 :Extreme Geschwindigkeit +STR_5147 :Cheats in der Symbolleiste anzeigen +STR_5148 :{SMALLFONT}{BLACK}Spielgeschwindigkeit ändern +STR_5149 :{SMALLFONT}{BLACK}Cheats anzeigen +STR_5150 :Aktiviere Debugging-Tools STR_5151 :. -#Decimal separator STR_5152 :, +STR_5153 :RCT1 Farbschema +STR_5154 :Anzeige über Hardware durchführen +STR_5155 :Testen unfertiger Bahnen erlauben +STR_5156 :{SMALLFONT}{BLACK}Erlaubt das Testen der meisten Bahnarten, selbst wenn die Strecke nicht fertiggestellt ist, das gilt nicht für den Streckenmodus mit Blockbereichen +STR_5157 :Alle Preise freischalten +STR_5158 :Spiel Beenden +STR_5159 :OpenRCT2 Beenden +STR_5160 :{MONTH} {STRINGID}, Jahr {COMMA16} +STR_5161 :{WHITE}Datumsformat: +STR_5162 :Tag/Monat/Jahr +STR_5163 :Monat/Tag/Jahr +STR_5164 :Twitch-Kanalname +STR_5165 :Parkbesucher nach Followern benennen +STR_5166 :Benennt die Parkbesucher nach den Followern des Twitch-Kanals +STR_5167 :Überwache Follower-Parkbesucher +STR_5168 :Überwachungsinformationen zu Parkbesuchern, die nach Twitch-Followern benannt sind, einschalten - (Bei eingeschalteter Überwachung werden Besucheraktivitäten im Nachrichtenbereich angezeigt) +STR_5169 :Parkbesucher nach Twitch-Chatbenutzern benennen +STR_5170 :Benennt die Parkbesucher nach Twitch-Chatbenutzern +STR_5171 :Überwache Chat-Parkbesucher +STR_5172 :Überwachungsinformationen zu Parkbesuchern, die nach Twitch-Chatbenutzern benannt sind, einschalten - (Bei eingeschalteter Überwachung werden Besucheraktivitäten im Nachrichtenbereich angezeigt) +STR_5173 :Erhalte Twitch-Chat als Spielnachrichten +STR_5174 :Benutzt Twitch-Chatnachrichten, welchen !news vorangestellt ist, für Spielbenachrichtigungen +STR_5175 :Name Ihres Twitch-Kanals eingeben: +STR_5176 :Twitch-Integration aktivieren +STR_5177 :Vollbildmodus: diff --git a/distribution/changelog.txt b/distribution/changelog.txt index f8557af5ca..04e303f884 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,5 +1,11 @@ 0.0.2-beta (2015-05-22) ------------------------------------------------------------------------ +- Feature: Show month before day (e.g. March 14th, year 15) +- Feature: Change available object in-game (only available from console) +- Feature: Exit OpenRCT2 to desktop +- Feature: Allow testing of incomplete tracks +- Feature: Twitch integration +- Feature: Hardware display (useful for streaming) - Feature: Allow both types of powered launch (with and without passing the station) for every roller coaster that supported one type in RCT2. - Feature: Localisation of decimal and thousands separators. - Feature: Increase limits for maximum of circuits per roller coaster (20) and people on mazes (64) (up from the old limits of 7 and 16, respectively). diff --git a/projects/openrct2.vcxproj.user b/projects/openrct2.vcxproj.user index 2b27afde74..42ca88b12a 100644 --- a/projects/openrct2.vcxproj.user +++ b/projects/openrct2.vcxproj.user @@ -4,8 +4,7 @@ $(TargetDir) WindowsLocalDebugger $(TargetDir)\openrct2.exe - - + screenshot "C:\GOG Games\RollerCoaster Tycoon 2 Triple Thrill Pack\Scenarios\Six Flags Magic Mountain.SC6" "test.png" 16000 8000 c c 0 0 false diff --git a/src/addresses.h b/src/addresses.h index 4e70688479..962770bc24 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -230,6 +230,10 @@ #define RCT2_ADDRESS_WINDOW_DPI 0x009DEA74 +#define RCT2_ADDRESS_TEXTINPUT_WIDGETINDEX 0x009DEB88 +#define RCT2_ADDRESS_TEXTINPUT_WINDOWNUMBER 0x009DEB8A +#define RCT2_ADDRESS_TEXTINPUT_WINDOWCLASS 0x009DEB8C + #define RCT2_ADDRESS_DSOUND_BUFFERS 0x009E1AB0 #define RCT2_ADDRESS_NUM_DSOUND_DEVICES 0x009E2B88 #define RCT2_ADDRESS_DSOUND_DEVICES 0x009E2B8C diff --git a/src/cmdline.c b/src/cmdline.c index 6779415e3c..013af496f2 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -22,6 +22,7 @@ #include #include "addresses.h" #include "cmdline.h" +#include "interface/screenshot.h" #include "openrct2.h" #include "platform/platform.h" #include "util/util.h" @@ -138,7 +139,8 @@ static int cmdline_for_none(const char **argv, int argc) struct { const char *firstArg; cmdline_action action; } cmdline_table[] = { { "intro", cmdline_for_intro }, { "edit", cmdline_for_edit }, - { "sprite", cmdline_for_sprite } + { "sprite", cmdline_for_sprite }, + { "screenshot", cmdline_for_screenshot } }; static int cmdline_call_action(const char **argv, int argc) diff --git a/src/cmdline_sprite.c b/src/cmdline_sprite.c index 83c2d1b536..d87ce21a9d 100644 --- a/src/cmdline_sprite.c +++ b/src/cmdline_sprite.c @@ -434,7 +434,7 @@ int cmdline_for_sprite(const char **argv, int argc) fprintf(stderr, "Building: %s\n", spriteFilePath); for (int i = 0; fileExists; i++) { - itoa(i, number, 10); + _itoa(i, number, 10); strcpy(imagePath, resourcePath); if (resourceLength == 0 || (resourcePath[resourceLength - 1] != '/' && resourcePath[resourceLength - 1] != '\\')) strcat(imagePath, "/"); diff --git a/src/drawing/drawing.c b/src/drawing/drawing.c index 901af71bdf..b26c79ad60 100644 --- a/src/drawing/drawing.c +++ b/src/drawing/drawing.c @@ -135,7 +135,7 @@ void gfx_draw_pixel(rct_drawpixelinfo *dpi, int x, int y, int colour) */ void gfx_transpose_palette(int pal, unsigned char product) { - rct_g1_element g1 = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[pal]; + rct_g1_element g1 = g1Elements[pal]; int width = g1.width; int x = g1.x_offset; uint8* dest_pointer = (uint8*)&(RCT2_ADDRESS(0x01424680, uint8)[x * 4]); @@ -161,7 +161,7 @@ void load_palette(){ palette = water_type->image_id; } - rct_g1_element g1 = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[palette]; + rct_g1_element g1 = g1Elements[palette]; int width = g1.width; int x = g1.x_offset; uint8* dest_pointer = (uint8*)&(RCT2_ADDRESS(0x01424680, uint8)[x * 4]); @@ -514,7 +514,7 @@ void redraw_peep_and_rain() if (sprite != -1) { sprite = sprite & 0x7FFFF; - rct_g1_element *g1_elements = &RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[sprite]; + rct_g1_element *g1_elements = &g1Elements[sprite]; int left = RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_X, sint16) + g1_elements->x_offset; int top = RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_Y, sint16) + g1_elements->y_offset; int right = left + g1_elements->width; @@ -546,4 +546,4 @@ void redraw_peep_and_rain() } } RCT2_GLOBAL(RCT2_ADDRESS_NO_RAIN_PIXELS, uint32) = 0; -} +} \ No newline at end of file diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h index e258f07654..80f3713e1a 100644 --- a/src/drawing/drawing.h +++ b/src/drawing/drawing.h @@ -64,6 +64,8 @@ extern uint8 text_palette[]; extern int gLastDrawStringX; extern int gLastDrawStringY; +extern rct_g1_element *g1Elements; + // rct_drawpixelinfo* clip_drawpixelinfo(rct_drawpixelinfo* dpi, int left, int width, int top, int height); void gfx_set_dirty_blocks(int left, int top, int right, int bottom); @@ -91,6 +93,7 @@ void gfx_fill_rect_inset(rct_drawpixelinfo* dpi, short left, short top, short ri // sprite int gfx_load_g1(); int gfx_load_g2(); +void sub_68371D(); void gfx_bmp_sprite_to_buffer(uint8* palette_pointer, uint8* unknown_pointer, uint8* source_pointer, uint8* dest_pointer, rct_g1_element* source_image, rct_drawpixelinfo *dest_dpi, int height, int width, int image_type); void gfx_rle_sprite_to_buffer(uint8* source_bits_pointer, uint8* dest_bits_pointer, uint8* palette_pointer, rct_drawpixelinfo *dpi, int image_type, int source_y_start, int height, int source_x_start, int width); void gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 tertiary_colour); diff --git a/src/drawing/rect.c b/src/drawing/rect.c index ac4558dcf1..e5a4b1e483 100644 --- a/src/drawing/rect.c +++ b/src/drawing/rect.c @@ -109,7 +109,7 @@ void gfx_fill_rect(rct_drawpixelinfo *dpi, int left, int top, int right, int bot // Find colour in colour table? uint16 eax = palette_to_g1_offset[(colour & 0xFF)]; - rct_g1_element g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[eax]; + rct_g1_element g1_element = g1Elements[eax]; // Fill the rectangle with the colours from the colour table for (int i = 0; i < height>>dpi->zoom_level; ++i) { @@ -211,7 +211,7 @@ void gfx_fill_rect(rct_drawpixelinfo *dpi, int left, int top, int right, int bot esi = RCT2_GLOBAL(0xEDF828,sint32); esi *= 0x40; left = 0; - esi += (uint32)(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS,rct_g1_element)[right]).offset;//??? + esi += (uint32)g1Elements[right].offset;//??? //Not finished //Start of loop return; diff --git a/src/drawing/sprite.c b/src/drawing/sprite.c index 0f102dd57b..edadd6ece4 100644 --- a/src/drawing/sprite.c +++ b/src/drawing/sprite.c @@ -38,6 +38,8 @@ typedef struct { rct_gx g2; +rct_g1_element *g1Elements = (rct_g1_element*)RCT2_ADDRESS_G1_ELEMENTS; + /** * * rct2: 0x00678998 @@ -50,8 +52,6 @@ int gfx_load_g1() rct_g1_header header; unsigned int i; - rct_g1_element *g1Elements = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element); - file = fopen(get_file_path(PATH_ID_G1), "rb"); if (file != NULL) { if (fread(&header, 8, 1, file) == 1) { @@ -118,6 +118,19 @@ int gfx_load_g2() return 0; } +/** + * This function looks like it initialises the 0x009E3CE4 array which references sprites used for background / palette mixing or + * something. Further investigation is needed. + */ +void sub_68371D() +{ + uint8 **unk_9E3CE4 = (uint8**)0x009E3CE4; + + unk_9E3CE4[0] = NULL; + for (int i = 1; i < 8; i++) + unk_9E3CE4[i] = g1Elements[23199 + i].offset; +} + /** * Copies a sprite onto the buffer. There is no compression used on the sprite * image. @@ -405,7 +418,7 @@ void gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 } uint16 palette_offset = palette_to_g1_offset[palette_ref]; - palette_pointer = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[palette_offset].offset; + palette_pointer = g1Elements[palette_offset].offset; } else if (image_type && !(image_type & IMAGE_TYPE_USE_PALETTE)){ RCT2_GLOBAL(0x9E3CDC, uint32) = 0; @@ -416,9 +429,9 @@ void gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 uint32 secondary_offset = palette_to_g1_offset[(image_id >> 24) & 0x1F]; uint32 tertiary_offset = palette_to_g1_offset[tertiary_colour]; - rct_g1_element* primary_colour = &RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[primary_offset]; - rct_g1_element* secondary_colour = &RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[secondary_offset]; - rct_g1_element* tertiary_colour = &RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[tertiary_offset]; + rct_g1_element* primary_colour = &g1Elements[primary_offset]; + rct_g1_element* secondary_colour = &g1Elements[secondary_offset]; + rct_g1_element* tertiary_colour = &g1Elements[tertiary_offset]; memcpy(palette_pointer + 0xF3, &primary_colour->offset[0xF3], 12); memcpy(palette_pointer + 0xCA, &secondary_colour->offset[0xF3], 12); @@ -437,13 +450,13 @@ void gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 //Top int top_type = (image_id >> 19) & 0x1f; uint32 top_offset = palette_to_g1_offset[top_type]; //RCT2_ADDRESS(0x97FCBC, uint32)[top_type]; - rct_g1_element top_palette = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[top_offset]; + rct_g1_element top_palette = g1Elements[top_offset]; memcpy(palette_pointer + 0xF3, top_palette.offset + 0xF3, 12); //Trousers int trouser_type = (image_id >> 24) & 0x1f; uint32 trouser_offset = palette_to_g1_offset[trouser_type]; //RCT2_ADDRESS(0x97FCBC, uint32)[trouser_type]; - rct_g1_element trouser_palette = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[trouser_offset]; + rct_g1_element trouser_palette = g1Elements[trouser_offset]; memcpy(palette_pointer + 0xCA, trouser_palette.offset + 0xF3, 12); } @@ -469,7 +482,7 @@ void gfx_draw_sprite_palette_set(rct_drawpixelinfo *dpi, int image_id, int x, in rct_g1_element* g1_source; if (image_element < SPR_G2_BEGIN) { - g1_source = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[image_element]); + g1_source = &g1Elements[image_element]; } else { g1_source = &g2.elements[image_element - SPR_G2_BEGIN]; } diff --git a/src/drawing/string.c b/src/drawing/string.c index 746ebfa9c5..b1c417d4ee 100644 --- a/src/drawing/string.c +++ b/src/drawing/string.c @@ -32,7 +32,7 @@ void gfx_load_character_widths(){ uint8* char_width_pointer = RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH, uint8); 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 = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[c + SPR_CHAR_START + char_set_offset]; + rct_g1_element g1 = g1Elements[c + SPR_CHAR_START + char_set_offset]; int width; if (char_set_offset == 0xE0*3) width = g1.width + 1; @@ -75,7 +75,7 @@ void gfx_load_character_widths(){ } for (int i = 0; i < 0x20; ++i){ - rct_g1_element* g1 = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[0x606 + i]); + rct_g1_element* g1 = &g1Elements[0x606 + i]; uint8* unknown_pointer = RCT2_ADDRESS(0x9C3852, uint8) + 0xa12 * i; g1->offset = unknown_pointer; g1->width = 0x40; @@ -138,7 +138,7 @@ int gfx_get_string_width_new_lined(char* buffer){ case 0x10: continue; case FORMAT_INLINE_SPRITE: - g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[*((uint32*)(curr_char + 1)) & 0x7FFFF]; + g1_element = g1Elements[*((uint32*)(curr_char + 1)) & 0x7FFFF]; width += g1_element.width; curr_char += 4; break; @@ -214,7 +214,7 @@ int gfx_get_string_width(char* buffer) case 0x10: continue; case FORMAT_INLINE_SPRITE: - g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[*((uint32*)(curr_char+1))&0x7FFFF]; + g1_element = g1Elements[*((uint32*)(curr_char + 1)) & 0x7FFFF]; width += g1_element.width; curr_char += 4; break; @@ -297,7 +297,7 @@ int gfx_clip_string(char* buffer, int width) case 0x10: continue; case FORMAT_INLINE_SPRITE: - g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[*((uint32*)(curr_char+1))&0x7FFFF]; + g1_element = g1Elements[*((uint32*)(curr_char + 1)) & 0x7FFFF]; clipped_width += g1_element.width; curr_char += 4; continue; @@ -396,7 +396,7 @@ int gfx_wrap_string(char* buffer, int width, int* num_lines, int* font_height) case 0x10: continue; case FORMAT_INLINE_SPRITE: - g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[*((uint32*)(curr_char + 1)) & 0x7FFFF]; + g1_element = g1Elements[*((uint32*)(curr_char + 1)) & 0x7FFFF]; line_width += g1_element.width; curr_char += 4; break; @@ -718,7 +718,7 @@ void colour_char(uint8 colour, uint16* current_font_flags, uint8* palette_pointe int eax; - rct_g1_element g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[0x1332]; + rct_g1_element g1_element = g1Elements[0x1332]; eax = ((uint32*)g1_element.offset)[colour & 0xFF]; if (!(*current_font_flags & 2)) { @@ -896,7 +896,7 @@ void gfx_draw_string(rct_drawpixelinfo *dpi, char *buffer, int colour, int x, in } eax = palette_to_g1_offset[al]; //RCT2_ADDRESS(0x097FCBC, uint32)[al * 4]; - g1_element = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[eax]); + g1_element = &g1Elements[eax]; ebx = g1_element->offset[0xF9] + (1 << 8); if (!(*current_font_flags & 2)) { ebx = ebx & 0xFF; @@ -1008,7 +1008,7 @@ void gfx_draw_string(rct_drawpixelinfo *dpi, char *buffer, int colour, int x, in } uint32 image_id = *((uint32*)(buffer - 3)); uint32 image_offset = image_id & 0x7FFFF; - g1_element = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[image_offset]); + g1_element = &g1Elements[image_offset]; gfx_draw_sprite(dpi, image_id, max_x, max_y, 0); diff --git a/src/editor.c b/src/editor.c index b51cd723f2..ada8445aa8 100644 --- a/src/editor.c +++ b/src/editor.c @@ -598,7 +598,7 @@ static void editor_finalise_main_view() w->saved_view_y -= viewport->view_height >> 1; window_invalidate(w); - sub_69E9A7(); + reset_all_sprite_quadrant_placements(); scenery_set_default_placement_configuration(); window_new_ride_init_vars(); RCT2_GLOBAL(0x009DEB7C, uint16) = 0; diff --git a/src/game.c b/src/game.c index a42b071237..7923bcff6d 100644 --- a/src/game.c +++ b/src/game.c @@ -102,7 +102,7 @@ void update_palette_effects() if ((sint32)water_type != -1) { palette = water_type->image_id; } - rct_g1_element g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[palette]; + rct_g1_element g1_element = g1Elements[palette]; int xoffset = g1_element.x_offset; xoffset = xoffset * 4; for (int i = 0; i < g1_element.width; i++) { @@ -123,7 +123,7 @@ void update_palette_effects() palette = water_type->image_id; } - rct_g1_element g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[palette]; + rct_g1_element g1_element = g1Elements[palette]; int xoffset = g1_element.x_offset; xoffset = xoffset * 4; for (int i = 0; i < g1_element.width; i++) { @@ -148,7 +148,7 @@ void update_palette_effects() if ((sint32)water_type != -1) { p = water_type->var_06; } - rct_g1_element g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[q + p]; + rct_g1_element g1_element = g1Elements[q + p]; uint8* vs = &g1_element.offset[j * 3]; uint8* vd = RCT2_ADDRESS(0x01424A18, uint8); int n = 5; @@ -167,7 +167,7 @@ void update_palette_effects() if ((sint32)water_type != -1) { p = water_type->var_0A; } - g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[q + p]; + g1_element = g1Elements[q + p]; vs = &g1_element.offset[j * 3]; n = 5; for (int i = 0; i < n; i++) { @@ -183,7 +183,7 @@ void update_palette_effects() j = ((uint16)(RCT2_GLOBAL(RCT2_ADDRESS_PALETTE_EFFECT_FRAME_NO, uint32) * -960) * 3) >> 16; p = 1539; - g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[q + p]; + g1_element = g1Elements[q + p]; vs = &g1_element.offset[j * 3]; vd += 12; n = 3; @@ -705,7 +705,7 @@ int game_load_save(const char *path) mainWindow->saved_view_y -= mainWindow->viewport->view_height >> 1; window_invalidate(mainWindow); - sub_69E9A7(); + reset_all_sprite_quadrant_placements(); scenery_set_default_placement_configuration(); window_new_ride_init_vars(); RCT2_GLOBAL(0x009DEB7C, uint16) = 0; @@ -722,8 +722,9 @@ int game_load_save(const char *path) /* * * rct2: 0x0069E9A7 + * Call after a rotation or loading of a save to reset sprite quadrants */ -void sub_69E9A7() +void reset_all_sprite_quadrant_placements() { for (rct_sprite* spr = g_sprite_list; spr < (rct_sprite*)RCT2_ADDRESS_SPRITES_NEXT_INDEX; spr++) if (spr->unknown.sprite_identifier != 0xFF) diff --git a/src/game.h b/src/game.h index 2b2e4cf914..9a07a8dcc1 100644 --- a/src/game.h +++ b/src/game.h @@ -97,7 +97,7 @@ void game_reduce_game_speed(); void game_create_windows(); void game_update(); void game_logic_update(); -void sub_69E9A7(); +void reset_all_sprite_quadrant_placements(); void update_palette_effects(); int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp); diff --git a/src/interface/colour_schemes.c b/src/interface/colour_schemes.c index 59cf1d0fd3..ab6ccb56f1 100644 --- a/src/interface/colour_schemes.c +++ b/src/interface/colour_schemes.c @@ -24,8 +24,8 @@ #include "colour_schemes.h" window_colour_scheme gColourSchemes[] = { - { WC_TOP_TOOLBAR, { 7, 12, 24, 1, 0, 0 }, 4, 5178, "top_toolbar" }, - { WC_BOTTOM_TOOLBAR, { 140, 140, 0, 14, 0, 0 }, 4, 5179, "bottom_toolbar" }, + { WC_TOP_TOOLBAR, { 7, 12, 24, 1, 0, 0 }, 4, 5245, "top_toolbar" }, + { WC_BOTTOM_TOOLBAR, { 140, 140, 0, 14, 0, 0 }, 4, 5246, "bottom_toolbar" }, { WC_RIDE, { 1, 26, 11, 0, 0, 0 }, 3, 5203, "ride" }, { WC_RIDE_CONSTRUCTION, { 24, 24, 24, 0, 0, 0 }, 3, 5199, "ride_construction" }, { WC_RIDE_LIST, { 1, 26, 26, 0, 0, 0 }, 3, 5204, "ride_list" }, @@ -41,12 +41,12 @@ window_colour_scheme gColourSchemes[] = { { WC_GUEST_LIST, { 1, 15, 15, 0, 0, 0 }, 3, 5206, "guest_list" }, { WC_STAFF_LIST, { 1, 4, 4, 0, 0, 0 }, 3, 5208, "staff_list" }, { WC_FIRE_PROMPT, { 154, 0, 0, 0, 0, 0 }, 1, 5225, "staff_fire_prompt" }, - { WC_PARK_INFORMATION, { 1, 19, 19, 0, 0, 0 }, 3, 5186, "park_information" }, + { WC_PARK_INFORMATION, { 1, 19, 19, 0, 0, 0 }, 3, 5253, "park_information" }, { WC_FINANCES, { 1, 19, 19, 0, 0, 0 }, 3, 5187, "finances" }, - { WC_TITLE_MENU, { 140, 140, 140, 0, 0, 0 }, 3, 5182, "title_menu" }, - { WC_TITLE_EXIT, { 140, 140, 140, 0, 0, 0 }, 3, 5183, "title_exit" }, + { WC_TITLE_MENU, { 140, 140, 140, 0, 0, 0 }, 3, 5249, "title_menu" }, + { WC_TITLE_EXIT, { 140, 140, 140, 0, 0, 0 }, 3, 5250, "title_exit" }, { WC_RECENT_NEWS, { 1, 1, 0, 0, 0, 0 }, 3, 5192, "recent_news" }, - { WC_SCENARIO_SELECT, { 1, 26, 26, 0, 0, 0 }, 3, 5185, "scenario_select" }, + { WC_SCENARIO_SELECT, { 1, 26, 26, 0, 0, 0 }, 3, 5252, "scenario_select" }, { WC_TRACK_DESIGN_LIST, { 26, 26, 26, 0, 0, 0 }, 3, 5202, "track_design_list" }, { WC_TRACK_DESIGN_PLACE, { 24, 24, 24, 0, 0, 0 }, 3, 5200, "track_design_place" }, { WC_NEW_CAMPAIGN, { 19, 19, 19, 0, 0, 0 }, 3, 5188, "new_campaign" }, @@ -68,12 +68,12 @@ window_colour_scheme gColourSchemes[] = { { WC_MAPGEN, { 12, 24, 24, 0, 0, 0 }, 3, 5214, "map_generation" }, { WC_LOADSAVE, { 7, 7, 7, 0, 0, 0 }, 3, 5222, "loadsave" }, { WC_LOADSAVE_OVERWRITE_PROMPT, { 154, 0, 0, 0, 0, 0 }, 1, 5227, "loadsave_overwrite_prompt" }, - { WC_TITLE_OPTIONS, { 140, 140, 140, 0, 0, 0 }, 3, 5184, "title_options" }, + { WC_TITLE_OPTIONS, { 140, 140, 140, 0, 0, 0 }, 3, 5251, "title_options" }, { WC_LAND_RIGHTS, { 19, 19, 19, 0, 0, 0 }, 3, 5196, "land_rights" }, { WC_COLOUR_SCHEMES, { 1, 12, 12, 0, 0, 0 }, 3, 5218, "colour_schemes" }, { WC_STAFF, { 1, 4, 4, 0, 0, 0 }, 3, 5207, "staff" }, - { WC_EDITOR_TRACK_BOTTOM_TOOLBAR, { 135, 135, 135, 0, 0, 0 }, 3, 5180, "editor_track_bottom_toolbar" }, - { WC_EDITOR_SCENARIO_BOTTOM_TOOLBAR, { 150, 150, 141, 0, 0, 0 }, 3, 5181, "editor_scenario_bottom_toolbar" }, + { WC_EDITOR_TRACK_BOTTOM_TOOLBAR, { 135, 135, 135, 0, 0, 0 }, 3, 5247, "editor_track_bottom_toolbar" }, + { WC_EDITOR_SCENARIO_BOTTOM_TOOLBAR, { 150, 150, 141, 0, 0, 0 }, 3, 5248, "editor_scenario_bottom_toolbar" }, }; diff --git a/src/interface/screenshot.c b/src/interface/screenshot.c index 13c2c1a571..632c6eaba9 100644 --- a/src/interface/screenshot.c +++ b/src/interface/screenshot.c @@ -25,9 +25,11 @@ #include "../drawing/drawing.h" #include "../game.h" #include "../localisation/localisation.h" +#include "../openrct2.h" #include "../platform/platform.h" #include "../windows/error.h" #include "screenshot.h" +#include "viewport.h" static const char *_screenshot_format_extension[] = { ".bmp", ".png" }; @@ -273,4 +275,174 @@ int screenshot_dump_png() free(png); return index; +} + +bool screenshot_write_png(rct_drawpixelinfo *dpi, const char *path) +{ + unsigned int error; + unsigned char* png; + size_t pngSize; + LodePNGState state; + + lodepng_state_init(&state); + state.info_raw.colortype = LCT_PALETTE; + + // Get image size + int stride = (dpi->width + 3) & ~3; + + for (int i = 0; i < 256; i++) { + unsigned char r, g, b, a = 255; + + b = RCT2_ADDRESS(0x01424680, uint8)[i * 4 + 0]; + g = RCT2_ADDRESS(0x01424680, uint8)[i * 4 + 1]; + r = RCT2_ADDRESS(0x01424680, uint8)[i * 4 + 2]; + + lodepng_palette_add(&state.info_raw, r, g, b, a); + } + + error = lodepng_encode(&png, &pngSize, dpi->bits, stride, dpi->height, &state); + if (error != 0) { + free(png); + return false; + } else { + error = lodepng_save_file(png, pngSize, path); + if (error != 0) { + free(png); + return false; + } + } + + free(png); + return true; +} + +int cmdline_for_screenshot(const char **argv, int argc) +{ + bool giantScreenshot = argc == 5 && _stricmp(argv[2], "giant") == 0; + if (argc != 4 && argc != 8 && !giantScreenshot) { + printf("Usage: openrct2 screenshot [ ]\n"); + printf("Usage: openrct2 screenshot giant \n"); + return -1; + } + + bool customLocation = false; + bool centreMapX = false; + bool centreMapY = false; + int resolutionWidth, resolutionHeight, customX, customY, customZoom, customRotation; + + const char *inputPath = argv[0]; + const char *outputPath = argv[1]; + if (giantScreenshot) { + resolutionWidth = 0; + resolutionHeight = 0; + customLocation = true; + centreMapX = true; + centreMapY = true; + customZoom = atoi(argv[3]); + customRotation = atoi(argv[4]) & 3; + } else { + resolutionWidth = atoi(argv[2]); + resolutionHeight = atoi(argv[3]); + if (argc == 8) { + customLocation = true; + if (argv[4][0] == 'c') + centreMapX = true; + else + customX = atoi(argv[4]); + if (argv[5][0] == 'c') + centreMapY = true; + else + customY = atoi(argv[5]); + + customZoom = atoi(argv[6]); + customRotation = atoi(argv[7]) & 3; + } + } + + gOpenRCT2Headless = true; + if (openrct2_initialise()) { + rct2_open_file(inputPath); + + RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_PLAYING; + + int mapSize = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16); + if (resolutionWidth == 0 || resolutionHeight == 0) { + resolutionWidth = (mapSize * 32 * 2) >> customZoom; + resolutionHeight = (mapSize * 32 * 1) >> customZoom; + + resolutionWidth += 8; + resolutionHeight += 128; + } + + rct_viewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = resolutionWidth; + viewport.height = resolutionHeight; + viewport.view_width = viewport.width; + viewport.view_height = viewport.height; + viewport.var_11 = 0; + viewport.flags = 0; + + if (customLocation) { + if (centreMapX) + customX = (mapSize / 2) * 32 + 16; + if (centreMapY) + customY = (mapSize / 2) * 32 + 16; + + int x, y; + int z = map_element_height(customX, customY) & 0xFFFF; + switch (customRotation) { + case 0: + x = customY - customX; + y = ((customX + customY) / 2) - z; + break; + case 1: + x = -customY - customX; + y = ((-customX + customY) / 2) - z; + break; + case 2: + x = -customY + customX; + y = ((-customX - customY) / 2) - z; + break; + case 3: + x = customY + customX; + y = ((customX - customY) / 2) - z; + break; + } + + viewport.view_x = x - ((viewport.view_width << customZoom) / 2); + viewport.view_y = y - ((viewport.view_height << customZoom) / 2); + viewport.zoom = customZoom; + + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8) = customRotation; + } else { + viewport.view_x = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_X, sint16) - (viewport.view_width / 2); + viewport.view_y = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, sint16) - (viewport.view_height / 2); + viewport.zoom = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION, uint16) & 0xFF; + + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION, uint16) >> 8; + } + + // Ensure sprites appear regardless of rotation + reset_all_sprite_quadrant_placements(); + + rct_drawpixelinfo dpi; + dpi.x = 0; + dpi.y = 0; + dpi.width = resolutionWidth; + dpi.height = resolutionHeight; + dpi.pitch = 0; + dpi.zoom_level = 0; + dpi.bits = malloc(dpi.width * dpi.height); + + viewport_render(&dpi, &viewport, 0, 0, viewport.width, viewport.height); + + screenshot_write_png(&dpi, outputPath); + + free(dpi.bits); + } + openrct2_dispose(); + return 1; } \ No newline at end of file diff --git a/src/interface/screenshot.h b/src/interface/screenshot.h index 2515ebe79d..3b2c8ae6fa 100644 --- a/src/interface/screenshot.h +++ b/src/interface/screenshot.h @@ -24,4 +24,6 @@ void screenshot_check(); int screenshot_dump(); +int cmdline_for_screenshot(const char **argv, int argc); + #endif \ No newline at end of file diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 80b93835be..1ce75b6591 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -88,7 +88,7 @@ void viewport_init_all() // Palette from sprites? d = 0; for (i = 4915; i < 4947; i++) { - g1_element = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[i]); + g1_element = &g1Elements[i]; *((int*)(0x0141FC44 + d)) = *((int*)(&g1_element->offset[0xF5])); *((int*)(0x0141FC48 + d)) = *((int*)(&g1_element->offset[0xF9])); *((int*)(0x0141FD44 + d)) = *((int*)(&g1_element->offset[0xFD])); @@ -112,7 +112,7 @@ void viewport_init_all() RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, sint16) = -1; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, sint16) = 0; RCT2_GLOBAL(0x009DEA50, sint16) = -1; - RCT2_CALLPROC_EBPSAFE(0x006EE3C3); + textinput_cancel(); format_string((char*)0x0141FA44, STR_CANCEL, NULL); format_string((char*)0x0141F944, STR_OK, NULL); } @@ -743,7 +743,7 @@ int sub_0x686806(rct_sprite* sprite, int eax, int image_id, int ecx, int edx){ ps->image_id = image_id; - rct_g1_element *g1Element = &RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[image_id & 0x7FFFF]; + rct_g1_element *g1Element = &g1Elements[image_id & 0x7FFFF]; eax = (eax & 0xFF) + RCT2_GLOBAL(0x9DE568, uint16); ecx = (ecx & 0xFF) + RCT2_GLOBAL(0x9DE56C, uint16); @@ -821,7 +821,7 @@ void sub_0x6736FC(rct_litter* litter, int ebx, int edx){ * Paint Quadrant * rct2: 0x0069E8B0 */ -void sub_0x69E8B0(uint32 eax, uint32 ecx){ +void sub_0x69E8B0(uint16 eax, uint16 ecx){ uint32 _eax = eax, _ecx = ecx; rct_drawpixelinfo* dpi; @@ -1231,36 +1231,42 @@ void sub_68B35F(int ax, int cx) void sub_0x68B6C2(){ rct_drawpixelinfo* dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*); sint16 ax, bx, cx, dx; + uint16 num_vertical_quadrants = 0; + rct_xy16 mapTile; switch (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)){ case 0: - ax = dpi->y; - bx = dpi->x; + mapTile.x = dpi->x & 0xFFE0; + mapTile.y = (dpi->y - 16) & 0xFFE0; + + bx = mapTile.x / 2; + mapTile.x = mapTile.y - bx; + mapTile.y = mapTile.y + bx; - ax -= 16; - bx &= 0xFFE0; - ax &= 0xFFE0; - bx >>= 1; - cx = ax; - ax -= bx; - cx += bx; - ax &= 0xFFE0; - cx &= 0xFFE0; - dx = dpi->height; - dx += 2128; - dx >>= 5; - for (int i = dx; i > 0; --i){ - sub_68B35F(ax, cx); - sub_0x69E8B0(ax, cx); - cx += 0x20; - ax -= 0x20; - sub_0x69E8B0(ax, cx); - ax += 0x20; - sub_68B35F(ax, cx); - sub_0x69E8B0(ax, cx); - ax += 0x20; - cx -= 0x20; - sub_0x69E8B0(ax, cx); - cx += 0x20; + mapTile.x &= 0xFFE0; + mapTile.y &= 0xFFE0; + + num_vertical_quadrants = (dpi->height + 2128) / 32; + + for (; num_vertical_quadrants > 0; --num_vertical_quadrants){ + sub_68B35F(mapTile.x, mapTile.y); + sub_0x69E8B0(mapTile.x, mapTile.y); + + mapTile.x -= 32; + mapTile.y += 32; + + sub_0x69E8B0(mapTile.x, mapTile.y); + + mapTile.x += 32; + + sub_68B35F(mapTile.x, mapTile.y); + sub_0x69E8B0(mapTile.x, mapTile.y); + + mapTile.x += 32; + mapTile.y -= 32; + + sub_0x69E8B0(mapTile.x, mapTile.y); + + mapTile.y += 32; } break; case 1: @@ -1513,8 +1519,8 @@ void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, in left &= bitmask; top &= bitmask; - RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, uint16) = left; - RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_Y, uint16) = top; + RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, sint16) = left; + RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_Y, sint16) = top; RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_WIDTH, uint16) = width; RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_HEIGHT, uint16) = height; @@ -1522,11 +1528,11 @@ void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, in RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_PITCH, uint16) = (dpi->width + dpi->pitch) - width; - int x = (sint16)(left - (sint16)(viewport->view_x & bitmask)); + sint16 x = (sint16)(left - (sint16)(viewport->view_x & bitmask)); x >>= viewport->zoom; x += viewport->x; - int y = (sint16)(top - (sint16)(viewport->view_y & bitmask)); + sint16 y = (sint16)(top - (sint16)(viewport->view_y & bitmask)); y >>= viewport->zoom; y += viewport->y; @@ -1534,16 +1540,16 @@ void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, in RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_BITS_PTR, uint8*) = bits_pointer; rct_drawpixelinfo* dpi2 = RCT2_ADDRESS(RCT2_ADDRESS_VIEWPORT_DPI, rct_drawpixelinfo); - dpi2->y = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_Y, uint16); + dpi2->y = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_Y, sint16); dpi2->height = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_HEIGHT, uint16); dpi2->zoom_level = (uint8)RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_ZOOM, uint16); //Splits the screen into 32 pixel columns and renders them. - for (x = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, uint16) & 0xFFFFFFE0; - x < RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, uint16) + RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_WIDTH, uint16); + for (x = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, sint16) & 0xFFFFFFE0; + x < RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, sint16) + RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_WIDTH, uint16); x += 32){ - int start_x = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, uint16); + int start_x = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, sint16); int width_col = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_WIDTH, uint16); bits_pointer = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_BITS_PTR, uint8*); int pitch = RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_PITCH, uint16); @@ -1609,7 +1615,8 @@ void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, in * viewport: edi */ void sub_688972(int screenX, int screenY, sint16 *x, sint16 *y, rct_viewport **viewport) { - int my_x, my_y, z, interactionType; + sint16 my_x, my_y; + int z, interactionType; rct_viewport *myViewport; get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_TERRAIN, &my_x, &my_y, &interactionType, NULL, &myViewport); if (interactionType == VIEWPORT_INTERACTION_ITEM_NONE) { @@ -1665,9 +1672,9 @@ void screen_pos_to_map_pos(sint16 *x, sint16 *y, int *direction) } } else { if (mod_y < 16) { - my_direction = 0; - } else { my_direction = 1; + } else { + my_direction = 0; } } } @@ -1955,7 +1962,7 @@ void sub_68862C() * mapElement: edx * viewport: edi */ -void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, int *y, int *interactionType, rct_map_element **mapElement, rct_viewport **viewport) +void get_map_coordinates_from_pos(int screenX, int screenY, int flags, sint16 *x, sint16 *y, int *interactionType, rct_map_element **mapElement, rct_viewport **viewport) { RCT2_GLOBAL(0x9AC154, uint16_t) = flags & 0xFFFF; RCT2_GLOBAL(0x9AC148, uint8_t) = 0; @@ -1994,7 +2001,7 @@ void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, i if (viewport != NULL) *viewport = myviewport; } if (interactionType != NULL) *interactionType = RCT2_GLOBAL(0x9AC148, uint8_t); - if (x != NULL) *x = (int)RCT2_GLOBAL(0x9AC14C, int16_t); - if (y != NULL) *y = (int)RCT2_GLOBAL(0x9AC14E, int16_t); + if (x != NULL) *x = RCT2_GLOBAL(0x9AC14C, int16_t); + if (y != NULL) *y = RCT2_GLOBAL(0x9AC14E, int16_t); if (mapElement != NULL) *mapElement = RCT2_GLOBAL(0x9AC150, rct_map_element*); } \ No newline at end of file diff --git a/src/interface/viewport.h b/src/interface/viewport.h index 7bd3d1b23d..7dcf3243fc 100644 --- a/src/interface/viewport.h +++ b/src/interface/viewport.h @@ -113,7 +113,7 @@ void show_construction_rights(); void hide_construction_rights(); void viewport_set_visibility(uint8 mode); -void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, int *y, int *interactionType, rct_map_element **mapElement, rct_viewport **viewport); +void get_map_coordinates_from_pos(int screenX, int screenY, int flags, sint16 *x, sint16 *y, int *interactionType, rct_map_element **mapElement, rct_viewport **viewport); int viewport_interaction_get_item_left(int x, int y, viewport_interaction_info *info); int viewport_interaction_left_over(int x, int y); diff --git a/src/interface/viewport_interaction.c b/src/interface/viewport_interaction.c index 7c131adaae..6d2ac7152f 100644 --- a/src/interface/viewport_interaction.c +++ b/src/interface/viewport_interaction.c @@ -59,7 +59,10 @@ int viewport_interaction_get_item_left(int x, int y, viewport_interaction_info * if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) && s6Info->var_000 != 6) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; - get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_SPRITE & VIEWPORT_INTERACTION_MASK_RIDE & VIEWPORT_INTERACTION_MASK_PARK, &info->x, &info->y, &info->type, &info->mapElement, NULL); + rct_xy16 mapCoord = { 0 }; + get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_SPRITE & VIEWPORT_INTERACTION_MASK_RIDE & VIEWPORT_INTERACTION_MASK_PARK, &mapCoord.x, &mapCoord.y, &info->type, &info->mapElement, NULL); + info->x = mapCoord.x; + info->y = mapCoord.y; mapElement = info->mapElement; sprite = (rct_sprite*)mapElement; @@ -179,7 +182,10 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) && s6Info->var_000 != 6) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; - get_map_coordinates_from_pos(x, y, ~(VIEWPORT_INTERACTION_MASK_TERRAIN & VIEWPORT_INTERACTION_MASK_WATER), &info->x, &info->y, &info->type, &info->mapElement, NULL); + rct_xy16 mapCoord = { 0 }; + get_map_coordinates_from_pos(x, y, ~(VIEWPORT_INTERACTION_MASK_TERRAIN & VIEWPORT_INTERACTION_MASK_WATER), &mapCoord.x, &mapCoord.y, &info->type, &info->mapElement, NULL); + info->x = mapCoord.x; + info->y = mapCoord.y; mapElement = info->mapElement; sprite = (rct_sprite*)mapElement; @@ -566,7 +572,8 @@ static rct_peep *viewport_interaction_get_closest_peep(int x, int y, int maxDist */ void sub_68A15E(int screenX, int screenY, short *x, short *y, int *direction, rct_map_element **mapElement) { - int my_x, my_y, z, interactionType; + sint16 my_x, my_y; + int z, interactionType; rct_map_element *myMapElement; rct_viewport *viewport; get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_TERRAIN & VIEWPORT_INTERACTION_MASK_WATER, &my_x, &my_y, &interactionType, &myMapElement, &viewport); diff --git a/src/interface/window.c b/src/interface/window.c index 335d425add..0c79b4257a 100644 --- a/src/interface/window.c +++ b/src/interface/window.c @@ -1220,7 +1220,7 @@ void window_rotate_camera(rct_window *w) window_invalidate(w); sub_688956(); - sub_69E9A7(); + reset_all_sprite_quadrant_placements(); } /** @@ -2141,3 +2141,34 @@ int window_can_resize(rct_window *w) { return (w->flags & WF_RESIZABLE) && (w->min_width != w->max_width || w->min_height != w->max_height); } + +void window_event_textinput_call(rct_window *w, int widgetIndex, char *text) +{ + RCT2_CALLPROC_X(w->event_handlers[WE_TEXT_INPUT], 0, 0, text != NULL, widgetIndex, (int)w, (int)text, 0); +} + +/** + * + * rct2: 0x006EE3C3 + */ +void textinput_cancel() +{ + rct_window *w; + + // Close the new text input window + window_close_by_class(WC_TEXTINPUT); + + // The following code is only necessary for the old Windows text input dialog. In theory this isn't used anymore, but can + // still be triggered via original code paths. + RCT2_CALLPROC_EBPSAFE(0x0040701D); + if (RCT2_GLOBAL(0x009DEB8C, uint8) != 255) { + RCT2_CALLPROC_EBPSAFE(0x006EE4E2); + w = window_find_by_number( + RCT2_GLOBAL(RCT2_ADDRESS_TEXTINPUT_WINDOWCLASS, rct_windowclass), + RCT2_GLOBAL(RCT2_ADDRESS_TEXTINPUT_WINDOWNUMBER, rct_windownumber) + ); + if (w != NULL) { + window_event_textinput_call(w, RCT2_GLOBAL(RCT2_ADDRESS_TEXTINPUT_WIDGETINDEX, uint16), NULL); + } + } +} \ No newline at end of file diff --git a/src/interface/window.h b/src/interface/window.h index 64ad903235..0434f225c5 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -597,8 +597,10 @@ void window_event_resize_call(rct_window* w); void window_event_mouse_down_call(rct_window* w, int widgetIndex); void window_event_invalidate_call(rct_window* w); void window_event_update_call(rct_window *w); +void window_event_textinput_call(rct_window *w, int widgetIndex, char *text); void sub_6EA73F(); +void textinput_cancel(); void window_move_and_snap(rct_window *w, int newWindowX, int newWindowY, int snapProximity); int window_can_resize(rct_window *w); @@ -666,6 +668,13 @@ int window_can_resize(rct_window *w); #define window_cursor_set_registers(cursorId) \ __asm mov ebx, cursorId + #define window_tooltip_get_registers(w, widgetIndex) \ + __asm mov widgetIndex, ax \ + __asm mov w, esi + + #define window_tooltip_set_registers(value) \ + __asm mov ax, value + #else #define window_get_register(w) \ __asm__ ( "mov %["#w"], esi " : [w] "+m" (w) ); @@ -728,6 +737,13 @@ int window_can_resize(rct_window *w); #define window_cursor_set_registers(cursorId) \ __asm__ ( "mov ebx, %[cursorId] " : [cursorId] "+m" (cursorId) ); + + #define window_tooltip_get_registers(w, widgetIndex) \ + __asm__ ( "mov %["#widgetIndex"], ax " : [widgetIndex] "+m" (widgetIndex) ); \ + __asm__ ( "mov %["#w"], esi " : [w] "+m" (w) ); + + #define window_tooltip_set_registers(value) \ + __asm__ ( "mov ax, %["#value"] " : [value] "+m" (value) ); #endif #endif diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 8a8bf7c6a7..9786f32fc4 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -1422,6 +1422,8 @@ enum { STR_TWITCH_NAME_DESC = 5175, STR_TWITCH_ENABLE = 5176, + STR_FULLSCREEN_MODE = 5177, + // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768 }; diff --git a/src/management/award.c b/src/management/award.c index 90f4d8e719..ccf55a4255 100644 --- a/src/management/award.c +++ b/src/management/award.c @@ -51,6 +51,8 @@ int _awardPositiveMap[] = { POSITIVE, // PARK_AWARD_BEST_GENTLE_RIDES }; +rct_award *gCurrentAwards = (rct_award*)RCT2_ADDRESS_AWARD_LIST; + int award_is_positive(int type) { return _awardPositiveMap[type]; @@ -581,7 +583,7 @@ void award_reset() { int i; for (i = 0; i < MAX_AWARDS; i++) - RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award)[i].time = 0; + gCurrentAwards[i].time = 0; } /** @@ -591,9 +593,6 @@ void award_reset() void award_update_all() { int i, activeAwardTypes, freeAwardEntryIndex; - rct_award *awards; - - awards = RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award); // Only add new awards if park is open if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_OPEN) { @@ -601,8 +600,8 @@ void award_update_all() activeAwardTypes = 0; freeAwardEntryIndex = -1; for (i = 0; i < MAX_AWARDS; i++) { - if (awards[i].time != 0) - activeAwardTypes |= (1 << awards[i].type); + if (gCurrentAwards[i].time != 0) + activeAwardTypes |= (1 << gCurrentAwards[i].type); else if (freeAwardEntryIndex == -1) freeAwardEntryIndex = i; } @@ -618,8 +617,8 @@ void award_update_all() // Check if award is deserved if (award_is_deserved(awardType, activeAwardTypes)) { // Add award - awards[freeAwardEntryIndex].type = awardType; - awards[freeAwardEntryIndex].time = 5; + gCurrentAwards[freeAwardEntryIndex].type = awardType; + gCurrentAwards[freeAwardEntryIndex].time = 5; news_item_add_to_queue(NEWS_ITEM_AWARD, STR_NEWS_ITEM_AWARD_MOST_UNTIDY + awardType, 0); window_invalidate_by_class(WC_PARK_INFORMATION); } @@ -628,7 +627,7 @@ void award_update_all() // Decrease award times for (i = 0; i < MAX_AWARDS; i++) - if (awards[i].time != 0) - if (--awards[i].time == 0) + if (gCurrentAwards[i].time != 0) + if (--gCurrentAwards[i].time == 0) window_invalidate_by_class(WC_PARK_INFORMATION); } diff --git a/src/management/award.h b/src/management/award.h index 8e7c965f50..faab09d43c 100644 --- a/src/management/award.h +++ b/src/management/award.h @@ -51,6 +51,8 @@ enum { #define MAX_AWARDS 4 +extern rct_award *gCurrentAwards; + int award_is_positive(int type); void award_reset(); void award_update_all(); diff --git a/src/object.c b/src/object.c index 7f2be9d177..64414d549f 100644 --- a/src/object.c +++ b/src/object.c @@ -396,7 +396,7 @@ int object_chunk_load_image_directory(uint8_t** chunk) RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32_t) = no_images + image_start_no; - rct_g1_element* g1_dest = &RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[image_start_no]; + rct_g1_element* g1_dest = &g1Elements[image_start_no]; // After length of data is the start of all g1 element structs rct_g1_element* g1_source = (rct_g1_element*)(*chunk); diff --git a/src/openrct2.c b/src/openrct2.c index d51152f05d..a66731d302 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -34,6 +34,9 @@ int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE; char gOpenRCT2StartupActionPath[512] = { 0 }; +// This should probably be changed later and allow a custom selection of things to initialise like SDL_INIT +bool gOpenRCT2Headless = false; + /** If set, will end the OpenRCT2 game loop. Intentially private to this module so that the flag can not be set back to 0. */ int _finished; @@ -108,51 +111,59 @@ static void openrct2_copy_original_user_files_over() openrct2_copy_files_over((char*)RCT2_ADDRESS_LANDSCAPES_PATH, path, ".sc6"); } -/** - * Launches the game, after command line arguments have been parsed and processed. - */ -void openrct2_launch() +bool openrct2_initialise() { char userPath[MAX_PATH]; platform_get_user_directory(userPath, NULL); if (!platform_ensure_directory_exists(userPath)) { log_fatal("Could not create user directory (do you have write access to your documents folder?)"); - return; + return false; } config_set_defaults(); if (!config_open_default()) { if (!config_find_or_browse_install_directory()) { log_fatal("An RCT2 install directory must be specified!"); - return; + return false; } } config_save_default(); // TODO add configuration option to allow multiple instances - if (!platform_lock_single_instance()) { - fprintf(stderr, "OpenRCT2 is already running.\n"); - return; + if (!gOpenRCT2Headless && !platform_lock_single_instance()) { + log_fatal("OpenRCT2 is already running."); + return false; } get_system_info(); - audio_init(); - audio_get_devices(); - get_dsound_devices(); + if (!gOpenRCT2Headless) { + audio_init(); + audio_get_devices(); + get_dsound_devices(); + } language_open(gConfigGeneral.language); http_init(); - if (!rct2_init()) - return; - - openrct2_copy_original_user_files_over(); - - Mixer_Init(NULL); colour_schemes_set_default(); colour_schemes_load_presets(); + if (!rct2_init()) + return false; + + openrct2_copy_original_user_files_over(); + + Mixer_Init(NULL); + return true; +} + +/** + * Launches the game, after command line arguments have been parsed and processed. + */ +void openrct2_launch() +{ + if (openrct2_initialise()) { switch (gOpenRCT2StartupAction) { case STARTUP_ACTION_INTRO: RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) = 8; @@ -176,17 +187,20 @@ void openrct2_launch() } break; } - - log_verbose("begin openrct2 loop"); - openrct2_loop(); - - http_dispose(); - platform_free(); + openrct2_loop(); + } + openrct2_dispose(); // HACK Some threads are still running which causes the game to not terminate. Investigation required! exit(gExitCode); } +void openrct2_dispose() +{ + http_dispose(); + platform_free(); +} + /** * Run the main game loop until the finished flag is set at 40fps (25ms interval). */ @@ -194,6 +208,8 @@ static void openrct2_loop() { uint32 currentTick, ticksElapsed, lastTick = 0; + log_verbose("begin openrct2 loop"); + _finished = 0; do { currentTick = SDL_GetTicks(); diff --git a/src/openrct2.h b/src/openrct2.h index f265c97833..d2452d5389 100644 --- a/src/openrct2.h +++ b/src/openrct2.h @@ -32,8 +32,11 @@ enum { extern int gOpenRCT2StartupAction; extern char gOpenRCT2StartupActionPath[512]; +extern bool gOpenRCT2Headless; +bool openrct2_initialise(); void openrct2_launch(); +void openrct2_dispose(); void openrct2_finish(); #endif \ No newline at end of file diff --git a/src/platform/shared.c b/src/platform/shared.c index 574dfa531e..fcd34e4027 100644 --- a/src/platform/shared.c +++ b/src/platform/shared.c @@ -28,6 +28,7 @@ #include "../interface/keyboard_shortcut.h" #include "../interface/window.h" #include "../input.h" +#include "../openrct2.h" #include "platform.h" typedef void(*update_palette_func)(char*, int, int); @@ -275,7 +276,7 @@ void platform_update_palette(char* colours, int start_index, int num_colours) colours += 4; } - if (!gConfigGeneral.hardware_display) { + if (!gOpenRCT2Headless && !gConfigGeneral.hardware_display) { surface = SDL_GetWindowSurface(gWindow); if (!surface) { log_fatal("SDL_GetWindowSurface failed %s", SDL_GetError()); @@ -525,7 +526,10 @@ static void platform_create_window() SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, 0); platform_load_cursors(); - RCT2_CALLPROC_EBPSAFE(0x0068371D); + + // TODO This should probably be called somewhere else. It has nothing to do with window creation and can be done as soon as + // g1.dat is loaded. + sub_68371D(); // Get window size width = gConfigGeneral.window_width; diff --git a/src/platform/windows.c b/src/platform/windows.c index 8ce7bedd9b..eed058f77b 100644 --- a/src/platform/windows.c +++ b/src/platform/windows.c @@ -80,6 +80,7 @@ __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInsta if (runGame) openrct2_launch(); + exit(gExitCode); return gExitCode; } diff --git a/src/rct2.c b/src/rct2.c index 81dc31e8b5..e900020c60 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -96,8 +96,10 @@ int rct2_init() gfx_load_g1(); gfx_load_g2(); gfx_load_character_widths(); - platform_init(); - audio_init1(); + if (!gOpenRCT2Headless) { + platform_init(); + audio_init1(); + } viewport_init_all(); news_item_init_queue(); get_local_time(); @@ -109,7 +111,8 @@ int rct2_init() sub_6BD3A4(); map_init(150); park_init(); - window_title_menu_open(); + if (!gOpenRCT2Headless) + window_title_menu_open(); date_reset(); climate_reset(CLIMATE_COOL_AND_WET); scenery_set_default_placement_configuration(); @@ -117,10 +120,12 @@ int rct2_init() window_guest_list_init_vars_b(); window_staff_list_init_vars(); - title_load(); + if (!gOpenRCT2Headless) { + title_load(); - gfx_clear(RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo), 10); - RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) = gConfigGeneral.play_intro ? 8 : 255; + gfx_clear(RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo), 10); + RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) = gConfigGeneral.play_intro ? 8 : 255; + } log_verbose("initialising game finished"); return 1; diff --git a/src/ride/station.c b/src/ride/station.c index a35e050c26..c982a44757 100644 --- a/src/ride/station.c +++ b/src/ride/station.c @@ -291,6 +291,10 @@ static void ride_invalidate_station_start(rct_ride *ride, int stationIndex, int y = (ride->station_starts[stationIndex] >> 8) * 32; mapElement = ride_get_station_start_track_element(ride, stationIndex); + // If no station track found return + if (mapElement == NULL) + return; + mapElement->properties.track.sequence &= 0x7F; if (dl != 0) mapElement->properties.track.sequence |= 0x80; diff --git a/src/scenario.c b/src/scenario.c index 69c7742e6d..4fdae3f241 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -248,7 +248,7 @@ int scenario_load_and_play_from_path(const char *path) mainWindow->saved_view_y -= mainWindow->viewport->view_height >> 1; window_invalidate(mainWindow); - sub_69E9A7(); + reset_all_sprite_quadrant_placements(); window_new_ride_init_vars(); // Set the scenario pseduo-random seeds diff --git a/src/title.c b/src/title.c index a747336f5c..411ff5c612 100644 --- a/src/title.c +++ b/src/title.c @@ -203,7 +203,7 @@ static void title_update_showcase() } window_invalidate(w); - sub_69E9A7(); + reset_all_sprite_quadrant_placements(); window_new_ride_init_vars(); sub_684AC3(); scenery_set_default_placement_configuration(); diff --git a/src/windows/banner.c b/src/windows/banner.c index 7739b1dec5..c1daee3ddb 100644 --- a/src/windows/banner.c +++ b/src/windows/banner.c @@ -205,7 +205,7 @@ static void window_banner_mouseup() window_text_input_open(w, WIDX_BANNER_TEXT, 2982, 2983, gBanners[w->number].string_idx, 0, 32); break; case WIDX_BANNER_NO_ENTRY: - RCT2_CALLPROC_EBPSAFE(0x006EE3C3); + textinput_cancel(); banner->flags ^= BANNER_FLAG_NO_ENTRY; window_invalidate(w); diff --git a/src/windows/cheats.c b/src/windows/cheats.c index f12e7eea0e..e17286aa5b 100644 --- a/src/windows/cheats.c +++ b/src/windows/cheats.c @@ -107,10 +107,10 @@ static rct_widget window_cheats_money_widgets[] = { { WWT_CAPTION, 0, 1, WW - 2, 1, 14, 3165, STR_WINDOW_TITLE_TIP}, // title bar { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, 0x338, STR_CLOSE_WINDOW_TIP}, // close x button { WWT_IMGBTN, 1, 0, WW - 1, 43, WH - 1, 0x0FFFFFFFF, 65535}, // tab content panel - { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 2462}, // tab 1 - { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 2462}, // tab 2 - { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, 2462}, // tab 3 - { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, 2462}, // tab 4 + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 5178 }, // tab 1 + { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 5179 }, // tab 2 + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, 5180 }, // tab 3 + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, 5181 }, // tab 4 { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(1), HPL(1), 2760, STR_NONE}, // high money { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(3), HPL(3), 2761, STR_NONE}, //Park Entrance Fee Toggle { WIDGETS_END }, @@ -121,10 +121,10 @@ static rct_widget window_cheats_guests_widgets[] = { { WWT_CAPTION, 0, 1, WW - 2, 1, 14, 3165, STR_WINDOW_TITLE_TIP }, // title bar { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, 0x338, STR_CLOSE_WINDOW_TIP }, // close x button { WWT_IMGBTN, 1, 0, WW - 1, 43, WH - 1, 0x0FFFFFFFF, 65535 }, // tab content panel - { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 2462 }, // tab 1 - { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 2462 }, // tab 2 - { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, 2462 }, // tab 3 - { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, 2462}, // tab 4 + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 5178 }, // tab 1 + { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 5179 }, // tab 2 + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, 5180 }, // tab 3 + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, 5181 }, // tab 4 { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(1), HPL(1), 2764, STR_NONE}, // happy guests { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(3), HPL(3), 2765, STR_NONE}, // large tram { WIDGETS_END }, @@ -136,10 +136,10 @@ static rct_widget window_cheats_misc_widgets[] = { { WWT_CAPTION, 0, 1, WW - 2, 1, 14, 3165, STR_WINDOW_TITLE_TIP }, // title bar { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, 0x338, STR_CLOSE_WINDOW_TIP }, // close x button { WWT_IMGBTN, 1, 0, WW - 1, 43, WH - 1, 0x0FFFFFFFF, 65535 }, // tab content panel - { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 2462 }, // tab 1 - { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 2462 }, // tab 2 - { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, 2462}, // tab 3 - { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, 2462}, // tab 4 + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 5178 }, // tab 1 + { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 5179 }, // tab 2 + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, 5180 }, // tab 3 + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, 5181 }, // tab 4 { WWT_CLOSEBOX, 1, XPL(1), WPL(1), YPL(1), HPL(1), 2767, STR_NONE}, // Freeze climate { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(0), HPL(0), 2769, STR_NONE}, // open / close park { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(1), HPL(1), 2759, STR_NONE}, // Zero Clearance @@ -159,10 +159,10 @@ static rct_widget window_cheats_rides_widgets[] = { { WWT_CAPTION, 0, 1, WW - 2, 1, 14, 3165, STR_WINDOW_TITLE_TIP }, // title bar { WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, 0x338, STR_CLOSE_WINDOW_TIP }, // close x button { WWT_IMGBTN, 1, 0, WW - 1, 43, WH - 1, 0x0FFFFFFFF, 65535 }, // tab content panel - { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 2462 }, // tab 1 - { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 2462 }, // tab 2 - { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, 2462}, // tab 3 - { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, 2462}, // tab 4 + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 5178 }, // tab 1 + { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 5179 }, // tab 2 + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, 5180 }, // tab 3 + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, 5181 }, // tab 4 { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(0), HPL(0), 5123, STR_NONE}, // Renew rides { WWT_CLOSEBOX, 1, XPL(1), WPL(1), YPL(0), HPL(0), 5124, STR_NONE}, // Remove flags { WWT_CLOSEBOX, 1, XPL(1), WPL(1), YPL(1), HPL(1), 5125, STR_NONE}, // Make destructable diff --git a/src/windows/colour_schemes.c b/src/windows/colour_schemes.c index 13e64fffde..ebb3158702 100644 --- a/src/windows/colour_schemes.c +++ b/src/windows/colour_schemes.c @@ -118,7 +118,7 @@ enum WINDOW_STAFF_LIST_WIDGET_IDX { static rct_widget window_colour_schemes_widgets[] = { { WWT_FRAME, 0, 0, 319, 0, 269, 0x0FFFFFFFF, STR_NONE }, // panel / background - { WWT_CAPTION, 0, 1, 318, 1, 14, 5177, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CAPTION, 0, 1, 318, 1, 14, 5244, STR_WINDOW_TITLE_TIP }, // title bar { WWT_CLOSEBOX, 0, 307, 317, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close button { WWT_RESIZE, 1, 0, 319, 43, 269, 0x0FFFFFFFF, STR_NONE }, // tab content panel { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, 5228 }, // main ui tab diff --git a/src/windows/footpath.c b/src/windows/footpath.c index e4d719283b..a7a1c71066 100644 --- a/src/windows/footpath.c +++ b/src/windows/footpath.c @@ -672,7 +672,10 @@ static void window_footpath_set_provisional_path_at_point(int x, int y) map_invalidate_selection_rect(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 2); - get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN, &x, &y, &interactionType, &mapElement, NULL); + rct_xy16 mapCoord = { 0 }; + get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN, &mapCoord.x, &mapCoord.y, &interactionType, &mapElement, NULL); + x = mapCoord.x; + y = mapCoord.y; if (interactionType == VIEWPORT_INTERACTION_ITEM_NONE) { RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0); @@ -759,7 +762,11 @@ static void window_footpath_place_path_at_point(int x, int y) footpath_provisional_update(); - get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN, &x, &y, &interactionType, &mapElement, NULL); + rct_xy16 mapCoord = { 0 }; + get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN, &mapCoord.x, &mapCoord.y, &interactionType, &mapElement, NULL); + x = mapCoord.x; + y = mapCoord.y; + if (interactionType == VIEWPORT_INTERACTION_ITEM_NONE) return; diff --git a/src/windows/game_bottom_toolbar.c b/src/windows/game_bottom_toolbar.c index 869871f3bf..7da22bd3af 100644 --- a/src/windows/game_bottom_toolbar.c +++ b/src/windows/game_bottom_toolbar.c @@ -215,31 +215,20 @@ static void window_game_bottom_toolbar_mouseup() static void window_game_bottom_toolbar_tooltip() { int month, day; - short tool_tip_index; + short widgetIndex, result; rct_window *w; - #ifdef _MSC_VER - __asm mov tool_tip_index, ax - #else - __asm__ ( "mov %[tool_tip_index], ax " : [tool_tip_index] "+m" (tool_tip_index) ); - #endif + window_tooltip_get_registers(w, widgetIndex); - #ifdef _MSC_VER - __asm mov w, esi - #else - __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); - #endif - - - switch (tool_tip_index) { + switch (widgetIndex) { case WIDX_MONEY: RCT2_GLOBAL(0x013CE952, int) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PROFIT, sint32); RCT2_GLOBAL(0x013CE956, int) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, sint32); - tool_tip_index = 0; + result = 0; break; case WIDX_PARK_RATING: RCT2_GLOBAL(0x013CE952, short) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_RATING, sint16); - tool_tip_index = 0; + result = 0; break; case WIDX_DATE: month = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, sint16) & 7; @@ -247,15 +236,11 @@ static void window_game_bottom_toolbar_tooltip() RCT2_GLOBAL(0x013CE952, short) = STR_DATE_DAY_1 + day; RCT2_GLOBAL(0x013CE954, short) = STR_MONTH_MARCH + month; - tool_tip_index = 0; + result = 0; break; } -#ifdef _MSC_VER - __asm mov ax, tool_tip_index -#else - __asm__("mov ax, %[tool_tip_index] " :[tool_tip_index] "+m" (tool_tip_index)); -#endif + window_tooltip_set_registers(result); } /** diff --git a/src/windows/guest.c b/src/windows/guest.c index 58f840a96a..651588b603 100644 --- a/src/windows/guest.c +++ b/src/windows/guest.c @@ -1594,12 +1594,15 @@ void window_guest_rides_tooltip(){ } /* rct2: 0x69784E */ -void window_guest_rides_scroll_get_size(){ +void window_guest_rides_scroll_get_size() +{ rct_window *w; + int width, height; window_get_register(w); - int height = w->no_list_items * 10; + width = 0; + height = w->no_list_items * 10; if (w->selected_list_item != -1){ w->selected_list_item = -1; @@ -1618,17 +1621,7 @@ void window_guest_rides_scroll_get_size(){ window_invalidate(w); } -#ifdef _MSC_VER - __asm mov ecx, 0 -#else - __asm__("mov ecx, 0 "); -#endif - -#ifdef _MSC_VER - __asm mov edx, height -#else - __asm__("mov edx, %[height] " : [height] "+m" (height)); -#endif + window_scrollsize_set_registers(width, height); } /* rct2: 0x006978CC */ diff --git a/src/windows/guest_list.c b/src/windows/guest_list.c index 76ffe41e6f..7bc2dd1d7e 100644 --- a/src/windows/guest_list.c +++ b/src/windows/guest_list.c @@ -419,7 +419,7 @@ static void window_guest_list_update(rct_window *w) */ static void window_guest_list_scrollgetsize() { - int i, y, numGuests, spriteIndex; + int i, y, numGuests, spriteIndex, width, height; rct_window *w; rct_peep *peep; @@ -470,18 +470,10 @@ static void window_guest_list_scrollgetsize() window_invalidate(w); } - #ifdef _MSC_VER - __asm mov ecx, 447 - #else - __asm__ ( "mov ecx, 447 " ); - #endif - - #ifdef _MSC_VER - __asm mov edx, y - #else - __asm__ ( "mov edx, %[y] " : [y] "+m" (y) ); - #endif + width = 447; + height = y; + window_scrollsize_set_registers(width, height); } /** diff --git a/src/windows/install_track.c b/src/windows/install_track.c index d2e465a7c9..f66b8bb8d9 100644 --- a/src/windows/install_track.c +++ b/src/windows/install_track.c @@ -298,7 +298,7 @@ static void window_install_track_paint() uint16 holes, speed, drops, dropHeight, inversions; fixed32_2dp rating; int x, y, colour, gForces, airTime; - rct_g1_element tmpElement, *subsituteElement, *g1Elements = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element); + rct_g1_element tmpElement, *subsituteElement; window_paint_get_registers(w, dpi); diff --git a/src/windows/map.c b/src/windows/map.c index 75099de662..69be2f881e 100644 --- a/src/windows/map.c +++ b/src/windows/map.c @@ -463,15 +463,13 @@ static void window_map_update(rct_window *w) */ static void window_map_scrollgetsize() { + int width, height; + window_map_invalidate(); - #ifdef _MSC_VER - __asm mov ecx, 512 - __asm mov edx, 512 - #else - __asm__ ( "mov ecx, 512 " ); - __asm__ ( "mov edx, 512 " ); - #endif + width = 512; + height = 512; + window_scrollsize_set_registers(width, height); } /** @@ -894,7 +892,7 @@ static void window_map_scrollpaint() gfx_clear(dpi, 0x0A0A0A0A); - g1_element = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element); + g1_element = &g1Elements[0]; pushed_g1_element = *g1_element; g1_element->offset = RCT2_GLOBAL(RCT2_ADDRESS_MAP_IMAGE_DATA, uint8*); diff --git a/src/windows/music_credits.c b/src/windows/music_credits.c index 2c8891308c..4a6f1c9da3 100644 --- a/src/windows/music_credits.c +++ b/src/windows/music_credits.c @@ -130,13 +130,11 @@ static void window_music_credits_mouseup() */ static void window_music_credits_scrollgetsize() { - int y = 560; + int width, height; - #ifdef _MSC_VER - __asm mov edx, y - #else - __asm__("mov edx, %[y] " : [y] "+m" (y)); - #endif + width = 0; + height = 560; + window_scrollsize_set_registers(width, height); } /** diff --git a/src/windows/new_ride.c b/src/windows/new_ride.c index e583dfc830..1cc1aaa236 100644 --- a/src/windows/new_ride.c +++ b/src/windows/new_ride.c @@ -635,27 +635,17 @@ static void window_new_ride_update(rct_window *w) static void window_new_ride_scrollgetsize() { ride_list_item *listItem = (ride_list_item*)0x00F43523; - int scrollWidth, scrollHeight; + int width, height; int count = 0; while (listItem->type != 255 || listItem->entry_index != 255) { count++; listItem++; } - scrollWidth = 0; - scrollHeight = ((count + 4) / 5) * 116; + width = 0; + height = ((count + 4) / 5) * 116; - #ifdef _MSC_VER - __asm mov ecx, scrollWidth - #else - __asm__ ( "mov ecx, %[scrollWidth] " : [scrollWidth] "+m" (scrollWidth) ); - #endif - - #ifdef _MSC_VER - __asm mov edx, scrollHeight - #else - __asm__ ( "mov edx, %[scrollHeight] " : [scrollHeight] "+m" (scrollHeight) ); - #endif + window_scrollsize_set_registers(width, height); } /** diff --git a/src/windows/news.c b/src/windows/news.c index 9c3fff2310..fd93b4edc8 100644 --- a/src/windows/news.c +++ b/src/windows/news.c @@ -184,9 +184,10 @@ static void window_news_update(rct_window *w) */ static void window_news_scrollgetsize() { - int i, height; + int i, width, height; rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); + width = 0; height = 0; for (i = 11; i < 61; i++) { if (newsItems[i].type == NEWS_ITEM_NULL) @@ -195,12 +196,7 @@ static void window_news_scrollgetsize() height += 42; } - #ifdef _MSC_VER - __asm mov edx, height - #else - __asm__ ( "mov edx, %[height] " : [height] "+m" (height) ); - #endif - + window_scrollsize_set_registers(width, height); } /** diff --git a/src/windows/options.c b/src/windows/options.c index 8c14d16218..9829af7465 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -990,10 +990,7 @@ static void window_options_paint() switch (w->page) { case WINDOW_OPTIONS_PAGE_DISPLAY: gfx_draw_string_left(dpi, STR_DISPLAY_RESOLUTION, w, 0, w->x + 10, w->y + window_options_widgets[WIDX_RESOLUTION].top + 1); - - sprintf(buffer, "%c%c%s", FORMAT_MEDIUMFONT, FORMAT_WINDOW_COLOUR_2, "Fullscreen mode:"); - gfx_draw_string(dpi, buffer, 0, w->x + 10, w->y + window_options_widgets[WIDX_FULLSCREEN].top + 1); - + gfx_draw_string_left(dpi, STR_FULLSCREEN_MODE, w, 12, w->x + 10, w->y + window_options_widgets[WIDX_FULLSCREEN].top + 1); gfx_draw_string_left(dpi, STR_CONSTRUCTION_MARKER, w, 0, w->x + 10, w->y + window_options_widgets[WIDX_CONSTRUCTION_MARKER].top + 1); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = (uint32)&gConfigColourSchemes.presets[gCurrentColourSchemePreset].name; diff --git a/src/windows/park.c b/src/windows/park.c index 2169520c78..97baae4c9b 100644 --- a/src/windows/park.c +++ b/src/windows/park.c @@ -812,6 +812,7 @@ static void window_park_entrance_toolupdate() switch (widgetIndex){ case WIDX_BUY_LAND_RIGHTS: + // Create a new version for this instance as scenery_clear is silly for this RCT2_CALLPROC_X(0x0068E213, x, y, 0, widgetIndex, (int)w, 0, 0); RCT2_GLOBAL(0x00F1AD62, uint32) = game_do_command( RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16), @@ -1984,7 +1985,7 @@ static void window_park_awards_paint() count = 0; for (i = 0; i < MAX_AWARDS; i++) { - award = &RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award)[i]; + award = &gCurrentAwards[i]; if (award->time == 0) continue; diff --git a/src/windows/publisher_credits.c b/src/windows/publisher_credits.c index 37896872ce..a517c189a0 100644 --- a/src/windows/publisher_credits.c +++ b/src/windows/publisher_credits.c @@ -130,13 +130,11 @@ static void window_publisher_credits_mouseup() */ static void window_publisher_credits_scrollgetsize() { - int y = 820; + int width, height; -#ifdef _MSC_VER - __asm mov edx, y -#else - __asm__("mov edx, %[y] " : [y] "+m" (y)); -#endif + width = 0; + height = 820; + window_scrollsize_set_registers(width, height); } /** diff --git a/src/windows/ride.c b/src/windows/ride.c index 2adc2ab40d..69a42ee60f 100644 --- a/src/windows/ride.c +++ b/src/windows/ride.c @@ -3565,7 +3565,10 @@ static void window_ride_set_track_colour_scheme(rct_window *w, int x, int y) int interactionType; - get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_RIDE, &x, &y, &interactionType, &mapElement, NULL); + rct_xy16 mapCoord = { 0 }; + get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_RIDE, &mapCoord.x, &mapCoord.y, &interactionType, &mapElement, NULL); + x = mapCoord.x; + y = mapCoord.y; // Get map coordinates from point /*int eax, ebx, ecx, edx, esi, edi, ebp; eax = x; @@ -5081,18 +5084,7 @@ static void window_ride_graphs_scrollgetheight() if (measurement != NULL) width = max(width, measurement->num_items); - // Return size - #ifdef _MSC_VER - __asm mov ecx, width - #else - __asm__ ( "mov ecx, 0 " ); - #endif - - #ifdef _MSC_VER - __asm mov edx, height - #else - __asm__ ( "mov edx, %[height] " : [height] "+m" (height) ); - #endif + window_scrollsize_set_registers(width, height); } /** @@ -5115,12 +5107,12 @@ static void window_ride_graphs_15() static void window_ride_graphs_tooltip() { rct_window *w; - short unused, widgetIndex, result; + short widgetIndex, result; rct_ride *ride; rct_ride_measurement *measurement; rct_string_id stringId; - window_dropdown_get_registers(w, unused, widgetIndex); + window_tooltip_get_registers(w, widgetIndex); result = -1; if (widgetIndex == WIDX_GRAPH) { @@ -5136,11 +5128,7 @@ static void window_ride_graphs_tooltip() } } - #ifdef _MSC_VER - __asm mov ax, result - #else - __asm__ ( "mov ax, %[result] " : [result] "+m" (result) ); - #endif + window_tooltip_set_registers(result); } /** diff --git a/src/windows/ride_list.c b/src/windows/ride_list.c index 3ebbaf96df..eccece57cc 100644 --- a/src/windows/ride_list.c +++ b/src/windows/ride_list.c @@ -308,7 +308,7 @@ static void window_ride_list_update(rct_window *w) */ static void window_ride_list_scrollgetsize() { - int top, height; + int top, width, height; rct_window *w; window_get_register(w); @@ -327,18 +327,8 @@ static void window_ride_list_scrollgetsize() window_invalidate(w); } - #ifdef _MSC_VER - __asm mov ecx, 0 - #else - __asm__ ( "mov ecx, 0 " ); - #endif - - #ifdef _MSC_VER - __asm mov edx, height - #else - __asm__ ( "mov edx, %[height] " : [height] "+m" (height) ); - #endif - + width = 0; + window_scrollsize_set_registers(width, height); } /** diff --git a/src/windows/staff_list.c b/src/windows/staff_list.c index e1d6b6023f..86cad33ca4 100644 --- a/src/windows/staff_list.c +++ b/src/windows/staff_list.c @@ -349,8 +349,9 @@ void window_staff_list_toolabort() { * * rct2: 0x006BDBE6 */ -void window_staff_list_scrollgetsize() { - int spriteIndex; +void window_staff_list_scrollgetsize() +{ + int i, width, height, spriteIndex; rct_peep *peep; rct_window *w; @@ -369,8 +370,8 @@ void window_staff_list_scrollgetsize() { window_invalidate(w); } - int scrollHeight = staffCount * 10; - int i = scrollHeight - window_staff_list_widgets[WIDX_STAFF_LIST_LIST].bottom + window_staff_list_widgets[WIDX_STAFF_LIST_LIST].top + 21; + height = staffCount * 10; + i = height - window_staff_list_widgets[WIDX_STAFF_LIST_LIST].bottom + window_staff_list_widgets[WIDX_STAFF_LIST_LIST].top + 21; if (i < 0) i = 0; if (i < w->scrolls[0].v_top) { @@ -378,17 +379,8 @@ void window_staff_list_scrollgetsize() { window_invalidate(w); } - #ifdef _MSC_VER - __asm mov ecx, 420 - #else - __asm__("mov ecx, 420 "); - #endif - - #ifdef _MSC_VER - __asm mov edx, scrollHeight - #else - __asm__("mov edx, %[scrollHeight] " : [scrollHeight] "+m" (scrollHeight)); - #endif + width = 420; + window_scrollsize_set_registers(width, height); } /** diff --git a/src/windows/text_input.c b/src/windows/text_input.c index d12a5bfe0a..d0b81642a8 100644 --- a/src/windows/text_input.c +++ b/src/windows/text_input.c @@ -240,7 +240,7 @@ static void window_text_input_mouseup(){ // Pass back the text that has been entered. // ecx when zero means text input failed if (calling_w != NULL) - RCT2_CALLPROC_X(calling_w->event_handlers[WE_TEXT_INPUT], 0, 0, 0, calling_widget, (int)calling_w, (int)text_input, 0); + window_event_textinput_call(calling_w, calling_widget, NULL); window_close(w); break; case WIDX_OKAY: @@ -248,7 +248,7 @@ static void window_text_input_mouseup(){ // Pass back the text that has been entered. // ecx when none zero means text input success if (calling_w != NULL) - RCT2_CALLPROC_X(calling_w->event_handlers[WE_TEXT_INPUT], 0, 0, 1, calling_widget, (int)calling_w, (int)text_input, 0); + window_event_textinput_call(calling_w, calling_widget, text_input); window_close(w); } } @@ -340,7 +340,7 @@ static void window_text_input_text(int key, rct_window* w){ // Pass back the text that has been entered. // ecx when none zero means text input success if (calling_w) - RCT2_CALLPROC_X(calling_w->event_handlers[WE_TEXT_INPUT], 0, 0, 1, calling_widget, (int)calling_w, (int)text_input, 0); + window_event_textinput_call(calling_w, calling_widget, text_input); } window_invalidate(w); diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 53b326ef1f..93dfd5e7bc 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -190,12 +190,13 @@ static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_w static void window_scenarioselect_scrollgetsize() { - int i, height; + int i, width, height; rct_window *w; rct_scenario_basic *scenario; window_get_register(w); + width = 0; height = 0; for (i = 0; i < gScenarioListCount; i++) { scenario = &gScenarioList[i]; @@ -205,18 +206,7 @@ static void window_scenarioselect_scrollgetsize() height += 24; } - #ifdef _MSC_VER - __asm mov ecx, 0 - #else - __asm__ ( "mov ecx, 0 " ); - #endif - - #ifdef _MSC_VER - __asm mov edx, height - #else - __asm__ ( "mov edx, %[height] " : [height] "+m" (height) ); - #endif - + window_scrollsize_set_registers(width, height); } /* rct2: 0x6780FE */ diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index 2e6e4174be..522309108e 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -210,6 +210,9 @@ void toggle_land_window(rct_window *topToolbar, int widgetIndex); void toggle_clear_scenery_window(rct_window *topToolbar, int widgetIndex); void toggle_water_window(rct_window *topToolbar, int widgetIndex); +money32 selection_lower_land(uint8 flags); +money32 selection_raise_land(uint8 flags); + static bool _menuDropdownIncludesTwitch; /** @@ -369,8 +372,10 @@ static void window_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widg numItems ); +#ifndef DISABLE_TWITCH if (_menuDropdownIncludesTwitch && gTwitchEnable) gDropdownItemsChecked |= (1 << 10); +#endif break; case WIDX_VIEW_MENU: top_toolbar_init_view_menu(w, widget); @@ -447,9 +452,11 @@ static void window_top_toolbar_dropdown() case DDIDX_EXIT_OPENRCT2: rct2_quit(); break; +#ifndef DISABLE_TWITCH case DDIDX_ENABLE_TWITCH: gTwitchEnable = !gTwitchEnable; break; +#endif } break; case WIDX_VIEW_MENU: @@ -709,7 +716,8 @@ static void repaint_scenery_tool_down(sint16 x, sint16 y, sint16 widgetIndex){ //RCT2_CALLPROC_X(0x6E2CC6, x, y, 0, widgetIndex, 0, 0, 0); //return; // ax, cx, bl - int grid_x, grid_y, type; + sint16 grid_x, grid_y; + int type; // edx rct_map_element* map_element; uint16 flags = @@ -1031,10 +1039,7 @@ void sub_6E1F34(sint16 x, sint16 y, uint16 selected_scenery, sint16* grid_x, sin int interaction_type = 0; rct_map_element* map_element; - int map_x, map_y; - get_map_coordinates_from_pos(x, y, flags, &map_x, &map_y, &interaction_type, &map_element, NULL); - *grid_x = (sint16)map_x; - *grid_y = (sint16)map_y; + get_map_coordinates_from_pos(x, y, flags, grid_x, grid_y, &interaction_type, &map_element, NULL); if (interaction_type == VIEWPORT_INTERACTION_ITEM_NONE) { @@ -1113,10 +1118,7 @@ void sub_6E1F34(sint16 x, sint16 y, uint16 selected_scenery, sint16* grid_x, sin int interaction_type = 0; rct_map_element* map_element; - int map_x, map_y; - get_map_coordinates_from_pos(x, y, flags, &map_x, &map_y, &interaction_type, &map_element, NULL); - *grid_x = (sint16)map_x; - *grid_y = (sint16)map_y; + get_map_coordinates_from_pos(x, y, flags, grid_x, grid_y, &interaction_type, &map_element, NULL); if (interaction_type == VIEWPORT_INTERACTION_ITEM_NONE) { @@ -1264,10 +1266,7 @@ void sub_6E1F34(sint16 x, sint16 y, uint16 selected_scenery, sint16* grid_x, sin int interaction_type = 0; rct_map_element* map_element; - int map_x, map_y; - get_map_coordinates_from_pos(x, y, flags, &map_x, &map_y, &interaction_type, &map_element, NULL); - *grid_x = (sint16)map_x; - *grid_y = (sint16)map_y; + get_map_coordinates_from_pos(x, y, flags, grid_x, grid_y, &interaction_type, &map_element, NULL); if (interaction_type == VIEWPORT_INTERACTION_ITEM_NONE) { @@ -1518,6 +1517,802 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window* w } } +/** +* +* rct2: 0x0068E213 +*/ +void top_toolbar_tool_update_scenery_clear(sint16 x, sint16 y){ + map_invalidate_selection_rect(); + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0); + + rct_xy16 mapTile = { 0 }; + sub_688972(x, y, &mapTile.x, &mapTile.y, NULL); + + if (mapTile.x == (sint16)0x8000){ + if (RCT2_GLOBAL(0x00F1AD62, money32) != MONEY32_UNDEFINED){ + RCT2_GLOBAL(0x00F1AD62, money32) = MONEY32_UNDEFINED; + window_invalidate_by_class(WC_CLEAR_SCENERY); + } + return; + } + + uint8 state_changed = 0; + + if (!(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 0); + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) != 4){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4; + state_changed++; + } + + sint16 tool_size = RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16); + if (tool_size == 0) + tool_size = 1; + + sint16 tool_length = (tool_size - 1) * 32; + + // Move to tool bottom left + mapTile.x -= (tool_size - 1) * 16; + mapTile.y -= (tool_size - 1) * 16; + mapTile.x &= 0xFFE0; + mapTile.y &= 0xFFE0; + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) != mapTile.x){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) = mapTile.x; + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) != mapTile.y){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) = mapTile.y; + state_changed++; + } + + mapTile.x += tool_length; + mapTile.y += tool_length; + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) != mapTile.x){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) = mapTile.x; + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) != mapTile.y){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) = mapTile.y; + state_changed++; + } + + map_invalidate_selection_rect(); + if (!state_changed) + return; + + money32 cost = map_clear_scenery( + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) / 32, + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) / 32, + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) / 32, + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) / 32, + 0); + + if (RCT2_GLOBAL(0x00F1AD62, money32) != cost){ + RCT2_GLOBAL(0x00F1AD62, money32) = cost; + window_invalidate_by_class(WC_CLEAR_SCENERY); + return; + } +} + +/** +* +* rct2: 0x00664280 +*/ +void top_toolbar_tool_update_land(sint16 x, sint16 y){ + map_invalidate_selection_rect(); + + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) == 3){ + if (!(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))) + return; + + money32 lower_cost = selection_lower_land(0); + money32 raise_cost = selection_raise_land(0); + + if (RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, money32) != raise_cost || + RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, money32) != lower_cost){ + RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, money32) = raise_cost; + RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, money32) = lower_cost; + window_invalidate_by_class(WC_LAND); + } + return; + } + + sint16 tool_size = RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16); + rct_xy16 mapTile = { .x = x, .y = y }; + + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0); + if (tool_size == 1){ + int direction; + screen_pos_to_map_pos(&mapTile.x, &mapTile.y, &direction); + + if (mapTile.x == (sint16)0x8000){ + money32 lower_cost = MONEY32_UNDEFINED; + money32 raise_cost = MONEY32_UNDEFINED; + + if (RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, money32) != raise_cost || + RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, money32) != lower_cost){ + RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, money32) = raise_cost; + RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, money32) = lower_cost; + window_invalidate_by_class(WC_LAND); + } + return; + } + + uint8 state_changed = 0; + + if (!(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 0); + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) != direction){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = direction; + state_changed++; + } + + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) != mapTile.x){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) = mapTile.x; + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) != mapTile.y){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) = mapTile.y; + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) != mapTile.x){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) = mapTile.x; + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) != mapTile.y){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) = mapTile.y; + state_changed++; + } + + map_invalidate_selection_rect(); + if (!state_changed) + return; + + money32 lower_cost = selection_lower_land(0); + money32 raise_cost = selection_raise_land(0); + + if (RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, money32) != raise_cost || + RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, money32) != lower_cost){ + RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, money32) = raise_cost; + RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, money32) = lower_cost; + window_invalidate_by_class(WC_LAND); + } + return; + } + + sub_688972(x, y, &mapTile.x, &mapTile.y, NULL); + + if (mapTile.x == (sint16)0x8000){ + money32 lower_cost = MONEY32_UNDEFINED; + money32 raise_cost = MONEY32_UNDEFINED; + + if (RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, money32) != raise_cost || + RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, money32) != lower_cost){ + RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, money32) = raise_cost; + RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, money32) = lower_cost; + window_invalidate_by_class(WC_LAND); + } + return; + } + + uint8 state_changed = 0; + + if (!(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 0); + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) != 4){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4; + state_changed++; + } + + + if (tool_size == 0) + tool_size = 1; + + sint16 tool_length = (tool_size - 1) * 32; + + // Move to tool bottom left + mapTile.x -= (tool_size - 1) * 16; + mapTile.y -= (tool_size - 1) * 16; + mapTile.x &= 0xFFE0; + mapTile.y &= 0xFFE0; + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) != mapTile.x){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) = mapTile.x; + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) != mapTile.y){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) = mapTile.y; + state_changed++; + } + + mapTile.x += tool_length; + mapTile.y += tool_length; + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) != mapTile.x){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) = mapTile.x; + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) != mapTile.y){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) = mapTile.y; + state_changed++; + } + + map_invalidate_selection_rect(); + if (!state_changed) + return; + + money32 lower_cost = selection_lower_land(0); + money32 raise_cost = selection_raise_land(0); + + if (RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, money32) != raise_cost || + RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, money32) != lower_cost){ + RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, money32) = raise_cost; + RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, money32) = lower_cost; + window_invalidate_by_class(WC_LAND); + } +} + +/** +* +* rct2: 0x006E6BDC +*/ +void top_toolbar_tool_update_water(sint16 x, sint16 y){ + map_invalidate_selection_rect(); + + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) == 3){ + if (!(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))) + return; + + money32 lower_cost = lower_water( + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16), + 0); + + money32 raise_cost = raise_water( + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16), + 0); + + if (RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, money32) != raise_cost || + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, money32) != lower_cost){ + RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, money32) = raise_cost; + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, money32) = lower_cost; + window_invalidate_by_class(WC_WATER); + } + return; + } + + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0); + + rct_xy16 mapTile = { 0 }; + int interaction_type = 0; + get_map_coordinates_from_pos( + x, + y, + VIEWPORT_INTERACTION_MASK_TERRAIN & VIEWPORT_INTERACTION_MASK_WATER, + &mapTile.x, + &mapTile.y, + &interaction_type, + NULL, + NULL); + + if (interaction_type == VIEWPORT_INTERACTION_ITEM_NONE){ + if (RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, money32) != MONEY32_UNDEFINED || + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, money32) != MONEY32_UNDEFINED){ + RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, money32) = MONEY32_UNDEFINED; + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, money32) = MONEY32_UNDEFINED; + window_invalidate_by_class(WC_WATER); + } + return; + } + + mapTile.x += 16; + mapTile.y += 16; + + uint8 state_changed = 0; + + if (!(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 0); + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) != 4){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4; + state_changed++; + } + + sint16 tool_size = RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16); + if (tool_size == 0) + tool_size = 1; + + sint16 tool_length = (tool_size - 1) * 32; + + // Move to tool bottom left + mapTile.x -= (tool_size - 1) * 16; + mapTile.y -= (tool_size - 1) * 16; + mapTile.x &= 0xFFE0; + mapTile.y &= 0xFFE0; + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) != mapTile.x){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) = mapTile.x; + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) != mapTile.y){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) = mapTile.y; + state_changed++; + } + + mapTile.x += tool_length; + mapTile.y += tool_length; + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) != mapTile.x){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) = mapTile.x; + state_changed++; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) != mapTile.y){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) = mapTile.y; + state_changed++; + } + + map_invalidate_selection_rect(); + if (!state_changed) + return; + + money32 lower_cost = lower_water( + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16), + 0); + + money32 raise_cost = raise_water( + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16), + 0); + + if (RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, money32) != raise_cost || + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, money32) != lower_cost){ + RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, money32) = raise_cost; + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, money32) = lower_cost; + window_invalidate_by_class(WC_WATER); + } +} + +/* rct2: 0x006E24F6 + * On failure returns MONEY32_UNDEFINED + * On success places ghost scenery and returns cost to place proper + */ +money32 try_place_ghost_scenery(rct_xy16 map_tile, uint32 parameter_1, uint32 parameter_2, uint32 parameter_3, uint16 selected_tab){ + scenery_remove_ghost_tool_placement(); + + uint8 scenery_type = (selected_tab & 0xFF00) >> 8; + uint8 selected_scenery = selected_tab & 0xFF; + money32 cost = 0; + rct_map_element* mapElement; + + switch (scenery_type){ + case 0: + // Small Scenery + //6e252b + cost = game_do_command( + map_tile.x, + parameter_1 | 0x69, + map_tile.y, + parameter_2, + GAME_COMMAND_PLACE_SCENERY, + parameter_3, + RCT2_GLOBAL(0x00F64ED4, sint16)); + + if (cost == MONEY32_UNDEFINED) + return cost; + + RCT2_GLOBAL(0x00F64EC4, sint16) = map_tile.x; + RCT2_GLOBAL(0x00F64EC6, sint16) = map_tile.y; + RCT2_GLOBAL(0x00F64EC0, uint16) = (uint16)(parameter_3 & 0xFFFF); + RCT2_GLOBAL(0x00F64EDA, sint16) = selected_tab; + + mapElement = RCT2_GLOBAL(0x00F64EBC, rct_map_element*); + RCT2_GLOBAL(0x00F64F09, uint8) = mapElement->base_height; + RCT2_GLOBAL(0x00F64F0C, uint8) = mapElement->type; + if (RCT2_GLOBAL(0x00F64F14, uint8) & (1 << 1)){ + viewport_set_visibility(4); + } + else{ + viewport_set_visibility(5); + } + + RCT2_GLOBAL(0x00F64F0D, uint8) |= (1 << 0); + break; + case 1: + // Path Bits + //6e265b + cost = game_do_command( + map_tile.x, + parameter_1 | 0xE9, + map_tile.y, + parameter_2, + GAME_COMMAND_PLACE_PATH, + parameter_3, + 0); + + if (cost == MONEY32_UNDEFINED) + return cost; + + RCT2_GLOBAL(0x00F64EC4, sint16) = map_tile.x; + RCT2_GLOBAL(0x00F64EC6, sint16) = map_tile.y; + RCT2_GLOBAL(0x00F64F09, uint8) = (parameter_2 & 0xFF); + RCT2_GLOBAL(0x00F64F0F, uint8) = ((parameter_1 >> 8) & 0xFF); + RCT2_GLOBAL(0x00F64F10, uint8) = ((parameter_2 >> 8) & 0xFF); + RCT2_GLOBAL(0x00F64EAC, uint32) = parameter_3; + + RCT2_GLOBAL(0x00F64F0D, uint8) |= (1 << 1); + break; + case 2: + // Walls + //6e26b0 + cost = game_do_command( + map_tile.x, + parameter_1 | 0x69, + map_tile.y, + parameter_2, + GAME_COMMAND_41, + RCT2_GLOBAL(0x00F64ED4, uint16), + RCT2_GLOBAL(0x00F64F15, uint16)); + + if (cost == MONEY32_UNDEFINED) + return cost; + + RCT2_GLOBAL(0x00F64EC4, sint16) = map_tile.x; + RCT2_GLOBAL(0x00F64EC6, sint16) = map_tile.y; + RCT2_GLOBAL(0x00F64F11, uint8) = (parameter_2 & 0xFF); + + mapElement = RCT2_GLOBAL(0x00F64EBC, rct_map_element*); + RCT2_GLOBAL(0x00F64F09, uint8) = mapElement->base_height; + + RCT2_GLOBAL(0x00F64F0D, uint8) |= (1 << 2); + break; + case 3: + // Large Scenery + //6e25a7 + cost = game_do_command( + map_tile.x, + parameter_1 | 0x69, + map_tile.y, + parameter_2, + GAME_COMMAND_43, + parameter_3, + RCT2_GLOBAL(0x00F64ED4, uint16)); + + if (cost == MONEY32_UNDEFINED) + return cost; + + RCT2_GLOBAL(0x00F64EC4, sint16) = map_tile.x; + RCT2_GLOBAL(0x00F64EC6, sint16) = map_tile.y; + RCT2_GLOBAL(0x00F64EC0, uint8) = ((parameter_1 >> 8) & 0xFF); + + mapElement = RCT2_GLOBAL(0x00F64EBC, rct_map_element*); + RCT2_GLOBAL(0x00F64F09, uint8) = mapElement->base_height; + + if (RCT2_GLOBAL(0x00F64F14, uint8) & (1 << 1)){ + viewport_set_visibility(4); + } + else{ + viewport_set_visibility(5); + } + + RCT2_GLOBAL(0x00F64F0D, uint8) |= (1 << 3); + break; + case 4: + // Banners + //6e2612 + cost = game_do_command( + map_tile.x, + parameter_1 | 0x69, + map_tile.y, + parameter_2, + GAME_COMMAND_PLACE_BANNER, + parameter_3, + 0); + + if (cost == MONEY32_UNDEFINED) + return cost; + + RCT2_GLOBAL(0x00F64EC4, sint16) = map_tile.x; + RCT2_GLOBAL(0x00F64EC6, sint16) = map_tile.y; + RCT2_GLOBAL(0x00F64F09, uint8) = (parameter_2 & 0xFF); + RCT2_GLOBAL(0x00F64EC0, uint8) = ((parameter_2 >> 8) & 0xFF); + RCT2_GLOBAL(0x00F64F0D, uint8) |= (1 << 4); + break; + } + + return cost; +} + +/** +* +* rct2: 0x006E287B +*/ +void top_toolbar_tool_update_scenery(sint16 x, sint16 y){ + map_invalidate_selection_rect(); + map_invalidate_map_selection_tiles(); + + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~((1 << 0) | (1 << 1)); + + if (window_scenery_is_repaint_scenery_tool_on) + return; + + sint16 selected_tab = window_scenery_selected_scenery_by_tab[window_scenery_active_tab_index]; + + if (selected_tab == -1){ + scenery_remove_ghost_tool_placement(); + return; + } + + uint8 scenery_type = (selected_tab & 0xFF00) >> 8; + uint8 selected_scenery = selected_tab & 0xFF; + rct_xy16 mapTile = { 0 }; + uint32 parameter1, parameter2, parameter3; + + sub_6E1F34(x, y, selected_tab, &mapTile.x, &mapTile.y, ¶meter1, ¶meter2, ¶meter3); + + if (mapTile.x == (sint16)0x8000){ + scenery_remove_ghost_tool_placement(); + return; + } + + rct_scenery_entry* scenery; + uint8 bl; + money32 cost; + + switch (scenery_type){ + case 0: + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 0); + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) = mapTile.x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) = mapTile.y; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) = mapTile.x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) = mapTile.y; + + scenery = g_smallSceneryEntries[selected_scenery]; + + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4; + if (!(scenery->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE)){ + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = ((parameter2 & 0xFF) ^ 2) + 6; + } + + map_invalidate_selection_rect(); + + // If no change in ghost placement + if ((RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 0)) && + mapTile.x == RCT2_GLOBAL(0x00F64EC4, sint16) && + mapTile.y == RCT2_GLOBAL(0x00F64EC6, sint16) && + (parameter2 & 0xFF) == RCT2_GLOBAL(0x00F64F0E, uint8)&& + RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16) == RCT2_GLOBAL(0x00F64F0A, sint16) && + RCT2_GLOBAL(0x00F64EDA, uint16) == selected_tab){ + return; + } + + scenery_remove_ghost_tool_placement(); + + RCT2_GLOBAL(0x00F64F0E, uint8) = (parameter2 & 0xFF); + RCT2_GLOBAL(0x00F64F0A, sint16) = RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16); + + bl = 1; + if (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16) != 0 && + RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_SHIFT_PRESSED, uint8) != 0){ + bl = 20; + } + + for (; bl != 0; bl--){ + cost = try_place_ghost_scenery( + mapTile, + parameter1, + parameter2, + parameter3, + selected_tab); + + if (cost != MONEY32_UNDEFINED) + break; + RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16) += 8; + } + + RCT2_GLOBAL(0x00F64EB4, money32) = cost; + break; + case 1: + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 0); + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) = mapTile.x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) = mapTile.y; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) = mapTile.x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) = mapTile.y; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4; + + map_invalidate_selection_rect(); + + // If no change in ghost placement + if ((RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 1)) && + mapTile.x == RCT2_GLOBAL(0x00F64EC4, sint16) && + mapTile.y == RCT2_GLOBAL(0x00F64EC6, sint16) && + (parameter2 & 0xFF) == RCT2_GLOBAL(0x00F64F09, uint8)){ + return; + } + + scenery_remove_ghost_tool_placement(); + + cost = try_place_ghost_scenery( + mapTile, + parameter1, + parameter2, + parameter3, + selected_tab); + + RCT2_GLOBAL(0x00F64EB4, money32) = cost; + break; + case 2: + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 0); + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) = mapTile.x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) = mapTile.y; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) = mapTile.x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) = mapTile.y; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 10 + parameter2 & 0xFF; + + map_invalidate_selection_rect(); + + // If no change in ghost placement + if ((RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 2)) && + mapTile.x == RCT2_GLOBAL(0x00F64EC4, sint16) && + mapTile.y == RCT2_GLOBAL(0x00F64EC6, sint16) && + (parameter2 & 0xFF) == RCT2_GLOBAL(0x00F64F11, uint8) && + RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16) == RCT2_GLOBAL(0x00F64F0A, sint16) + ){ + return; + } + + scenery_remove_ghost_tool_placement(); + + RCT2_GLOBAL(0x00F64F11, uint8) = (parameter2 & 0xFF); + RCT2_GLOBAL(0x00F64F0A, sint16) = RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16); + + bl = 1; + if (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16) != 0 && + RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_SHIFT_PRESSED, uint8) != 0){ + bl = 20; + } + + cost = 0; + for (; bl != 0; bl--){ + cost = try_place_ghost_scenery( + mapTile, + parameter1, + parameter2, + parameter3, + selected_tab); + + if (cost != MONEY32_UNDEFINED) + break; + RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16) += 8; + } + + RCT2_GLOBAL(0x00F64EB4, money32) = cost; + break; + case 3: + scenery = g_largeSceneryEntries[selected_scenery]; + rct_xy16* selectedTile = gMapSelectionTiles; + + for (rct_large_scenery_tile* tile = scenery->large_scenery.tiles; tile->x_offset != (sint16)0xFFFF; tile++){ + rct_xy16 tileLocation = { + .x = tile->x_offset, + .y = tile->y_offset + }; + + rotate_map_coordinates(&tileLocation.x, &tileLocation.y, (parameter1 >> 8) & 0xFF); + + tileLocation.x += mapTile.x; + tileLocation.y += mapTile.y; + + selectedTile->x = tileLocation.x; + selectedTile->y = tileLocation.y; + selectedTile++; + } + selectedTile->x = 0xFFFF; + + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 1); + map_invalidate_map_selection_tiles(); + + // If no change in ghost placement + if ((RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 3)) && + mapTile.x == RCT2_GLOBAL(0x00F64EC4, sint16) && + mapTile.y == RCT2_GLOBAL(0x00F64EC6, sint16) && + RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16) == RCT2_GLOBAL(0x00F64F0A, sint16) && + (parameter3 & 0xFFFF) == RCT2_GLOBAL(0x00F64EDA, uint16)){ + return; + } + + scenery_remove_ghost_tool_placement(); + + RCT2_GLOBAL(0x00F64EDA, uint16) = (parameter3 & 0xFFFF); + RCT2_GLOBAL(0x00F64F0A, sint16) = RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16); + + bl = 1; + if (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16) != 0 && + RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_SHIFT_PRESSED, uint8) != 0){ + bl = 20; + } + + cost = 0; + for (; bl != 0; bl--){ + cost = try_place_ghost_scenery( + mapTile, + parameter1, + parameter2, + parameter3, + selected_tab); + + if (cost != MONEY32_UNDEFINED) + break; + RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16) += 8; + } + + RCT2_GLOBAL(0x00F64EB4, money32) = cost; + break; + case 4: + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= (1 << 0); + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) = mapTile.x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) = mapTile.y; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) = mapTile.x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) = mapTile.y; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4; + + map_invalidate_selection_rect(); + + // If no change in ghost placement + if ((RCT2_GLOBAL(0x00F64F0D, uint8) & (1 << 4)) && + mapTile.x == RCT2_GLOBAL(0x00F64EC4, sint16) && + mapTile.y == RCT2_GLOBAL(0x00F64EC6, sint16) && + (parameter2 & 0xFF) == RCT2_GLOBAL(0x00F64F09, uint8) && + ((parameter2 >> 8) & 0xFF) == RCT2_GLOBAL(0x00F64EC0, uint8)){ + return; + } + + scenery_remove_ghost_tool_placement(); + + cost = try_place_ghost_scenery( + mapTile, + parameter1, + parameter2, + parameter3, + selected_tab); + + RCT2_GLOBAL(0x00F64EB4, money32) = cost; + break; + } +} + /** * * rct2: 0x0066CB25 @@ -1532,20 +2327,20 @@ static void window_top_toolbar_tool_update() switch (widgetIndex){ case WIDX_CLEAR_SCENERY: - RCT2_CALLPROC_X(0x0068E213, x, y, 0, widgetIndex, (int)w, 0, 0); + top_toolbar_tool_update_scenery_clear(x, y); break; case WIDX_LAND: if (LandPaintMode) - // Use the method that allows dragging the selection area + // Create a new version for this instance as scenery_clear is silly for this RCT2_CALLPROC_X(0x0068E213, x, y, 0, widgetIndex, (int)w, 0, 0); else - RCT2_CALLPROC_X(0x00664280, x, y, 0, widgetIndex, (int)w, 0, 0); + top_toolbar_tool_update_land(x, y); break; case WIDX_WATER: - RCT2_CALLPROC_X(0x006E6BDC, x, y, 0, widgetIndex, (int)w, 0, 0); + top_toolbar_tool_update_water(x, y); break; case WIDX_SCENERY: - RCT2_CALLPROC_X(0x006E287B, x, y, 0, widgetIndex, (int)w, 0, 0); + top_toolbar_tool_update_scenery(x, y); break; } } @@ -1608,7 +2403,7 @@ static void window_top_toolbar_tool_down(){ * * rct2: 0x006644DD */ -void selection_raise_land(uint8 flags){ +money32 selection_raise_land(uint8 flags){ int center_x = (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16) + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16) ) / 2; @@ -1629,12 +2424,12 @@ void selection_raise_land(uint8 flags){ if (RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) == 0) { int di = 1; - game_do_command(center_x, flags, center_y, dx, GAME_COMMAND_EDIT_LAND_SMOOTH, di, bp); + return game_do_command(center_x, flags, center_y, dx, GAME_COMMAND_EDIT_LAND_SMOOTH, di, bp); } else { int di = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16); - game_do_command(center_x, flags, center_y, dx, GAME_COMMAND_RAISE_LAND, di, bp); + return game_do_command(center_x, flags, center_y, dx, GAME_COMMAND_RAISE_LAND, di, bp); } } @@ -1642,7 +2437,7 @@ void selection_raise_land(uint8 flags){ * * rct2: 0x006645B3 */ -void selection_lower_land(uint8 flags){ +money32 selection_lower_land(uint8 flags){ int center_x = (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16) + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16) ) / 2; @@ -1663,11 +2458,11 @@ void selection_lower_land(uint8 flags){ if (RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) == 0) { int di = 0xFFFF; - game_do_command(center_x, flags, center_y, dx, GAME_COMMAND_EDIT_LAND_SMOOTH, di, bp); + return game_do_command(center_x, flags, center_y, dx, GAME_COMMAND_EDIT_LAND_SMOOTH, di, bp); } else { int di = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16); - game_do_command(center_x, flags, center_y, dx, GAME_COMMAND_LOWER_LAND, di, bp); + return game_do_command(center_x, flags, center_y, dx, GAME_COMMAND_LOWER_LAND, di, bp); } } diff --git a/src/windows/track_list.c b/src/windows/track_list.c index a44fc6b2dd..91019a49f9 100644 --- a/src/windows/track_list.c +++ b/src/windows/track_list.c @@ -392,7 +392,7 @@ static void window_track_list_paint() uint16 holes, speed, drops, dropHeight, inversions; fixed32_2dp rating; int trackIndex, x, y, colour, gForces, airTime; - rct_g1_element tmpElement, *subsituteElement, *g1Elements = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element); + rct_g1_element tmpElement, *subsituteElement; window_paint_get_registers(w, dpi); diff --git a/src/windows/track_place.c b/src/windows/track_place.c index 348e310fd7..4e0ebe457c 100644 --- a/src/windows/track_place.c +++ b/src/windows/track_place.c @@ -603,7 +603,7 @@ static void window_track_place_paint() { rct_window *w; rct_drawpixelinfo *dpi, *clippedDpi; - rct_g1_element tmpElement, *subsituteElement, *g1Elements = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element); + rct_g1_element tmpElement, *subsituteElement; window_paint_get_registers(w, dpi); diff --git a/src/windows/viewport.c b/src/windows/viewport.c index c476272bf0..2d3e98d96c 100644 --- a/src/windows/viewport.c +++ b/src/windows/viewport.c @@ -151,7 +151,7 @@ static void window_viewport_mouseup() { short widgetIndex; rct_window *w, *mainWindow; - int x, y; + sint16 x, y; window_widget_get_registers(w, widgetIndex); diff --git a/src/world/footpath.c b/src/world/footpath.c index 6c937d7d93..5cc366dc8b 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -493,9 +493,11 @@ void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, int z, interactionType; rct_map_element *myMapElement; rct_viewport *viewport; - get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_FOOTPATH, x, y, &interactionType, &myMapElement, &viewport); + rct_xy16 map_pos = { 0 }; + + get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_FOOTPATH, &map_pos.x, &map_pos.y, &interactionType, &myMapElement, &viewport); if (interactionType != VIEWPORT_INTERACTION_ITEM_FOOTPATH || !(viewport->flags & (VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_HIDE_VERTICAL))) { - get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN, x, y, &interactionType, &myMapElement, &viewport); + get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN, &map_pos.x, &map_pos.y, &interactionType, &myMapElement, &viewport); if (interactionType == VIEWPORT_INTERACTION_ITEM_NONE) { if (x != NULL) *x = 0x8000; return; @@ -512,16 +514,15 @@ void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, } RCT2_GLOBAL(0x00F1AD3C, uint16) = z; - RCT2_GLOBAL(0x00F1AD34, sint16) = *x; - RCT2_GLOBAL(0x00F1AD36, sint16) = *y; - RCT2_GLOBAL(0x00F1AD38, sint16) = *x + 31; - RCT2_GLOBAL(0x00F1AD3A, sint16) = *y + 31; + RCT2_GLOBAL(0x00F1AD34, sint16) = map_pos.x; + RCT2_GLOBAL(0x00F1AD36, sint16) = map_pos.y; + RCT2_GLOBAL(0x00F1AD38, sint16) = map_pos.x + 31; + RCT2_GLOBAL(0x00F1AD3A, sint16) = map_pos.y + 31; - *x += 16; - *y += 16; + map_pos.x += 16; + map_pos.y += 16; rct_xy16 start_vp_pos = screen_coord_to_viewport_coord(viewport, screenX, screenY); - rct_xy16 map_pos = { *x, *y }; for (int i = 0; i < 5; i++) { if (RCT2_GLOBAL(0x00F1AD3E, uint8) != 6) { @@ -573,7 +574,12 @@ void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, // First check if we point at an entrance or exit. In that case, we would want the path coming from the entrance/exit. int interactionType; rct_viewport *viewport; - get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_RIDE, x, y, &interactionType, mapElement, &viewport); + + rct_xy16 map_pos = { 0 }; + get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_RIDE, &map_pos.x, &map_pos.y, &interactionType, mapElement, &viewport); + *x = map_pos.x; + *y = map_pos.y; + if (interactionType == VIEWPORT_INTERACTION_ITEM_RIDE && viewport->flags & (VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_HIDE_VERTICAL) && map_element_get_type(*mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) { @@ -588,7 +594,9 @@ void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, } } - get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_RIDE & VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN, x, y, &interactionType, mapElement, &viewport); + get_map_coordinates_from_pos(screenX, screenY, VIEWPORT_INTERACTION_MASK_RIDE & VIEWPORT_INTERACTION_MASK_FOOTPATH & VIEWPORT_INTERACTION_MASK_TERRAIN, &map_pos.x, &map_pos.y, &interactionType, mapElement, &viewport); + *x = map_pos.x; + *y = map_pos.y; if (interactionType == VIEWPORT_INTERACTION_ITEM_RIDE && map_element_get_type(*mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) { int ebp = (*mapElement)->properties.entrance.type << 4; int bl = (*mapElement)->properties.entrance.index & 0xF; // Seems to be always 0? diff --git a/src/world/map.c b/src/world/map.c index 790e645a90..b9852b9eb1 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1560,68 +1560,59 @@ void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i *ebx = cost; } -/** - * - * rct2: 0x006E66A0 - */ -void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) -{ - int ax = (uint16)*eax; - int ay = (uint16)*ecx; - int bx = (uint16)*edi; - int by = (uint16)*ebp; - - int cost = 0; +money32 raise_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags){ + money32 cost = 0; uint8 max_height = 0xFF; - for(int yi = ay; yi <= by; yi += 32){ - for(int xi = ax; xi <= bx; xi += 32){ + for (int yi = y0; yi <= y1; yi += 32){ + for (int xi = x0; xi <= x1; xi += 32){ rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); uint8 height = map_element->base_height; - if(map_element->properties.surface.terrain & 0x1F){ + if (map_element->properties.surface.terrain & 0x1F){ height = (map_element->properties.surface.terrain & 0x1F) * 2; } - if(max_height > height){ + if (max_height > height){ max_height = height; } } } - for(int yi = ay; yi <= by; yi += 32){ - for(int xi = ax; xi <= bx; xi += 32){ + for (int yi = y0; yi <= y1; yi += 32){ + for (int xi = x0; xi <= x1; xi += 32){ rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); - - if(map_element->base_height <= max_height){ + + if (map_element->base_height <= max_height){ uint8 height = (map_element->properties.surface.terrain & 0x1F); - if(height){ + if (height){ height *= 2; - if(height > max_height){ + if (height > max_height){ continue; } height += 2; - }else{ + } + else{ height = map_element->base_height + 2; } - int eax2 = xi, ebx2 = *ebx, ecx2 = yi, edx2 = (max_height << 8) + height, esi2, edi2, ebp2; - ebx2 = game_do_command_p(GAME_COMMAND_16, &eax2, &ebx2, &ecx2, &edx2, &esi2, &edi2, &ebp2); - if(ebx2 == MONEY32_UNDEFINED){ - *ebx = MONEY32_UNDEFINED; - return; - }else{ - cost += ebx2; + + money32 cost2 = game_do_command(xi, flags, yi, (max_height << 8) + height, GAME_COMMAND_16, 0, 0); + if (cost2 == MONEY32_UNDEFINED){ + return MONEY32_UNDEFINED; + } + else{ + cost += cost2; } } } } - if(*ebx & GAME_COMMAND_FLAG_APPLY){ - int x = ((ax + bx) / 2) + 16; - int y = ((ay + by) / 2) + 16; + if (flags & GAME_COMMAND_FLAG_APPLY){ + int x = ((x0 + x1) / 2) + 16; + int y = ((y0 + y1) / 2) + 16; int z = map_element_height(x, y); sint16 water_height_z = z >> 16; sint16 base_height_z = z; z = water_height_z; - if(!z){ + if (!z){ z = base_height_z; } RCT2_GLOBAL(0x009DEA5E, uint32) = x; @@ -1629,7 +1620,79 @@ void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, RCT2_GLOBAL(0x009DEA62, uint32) = z; sound_play_panned(SOUND_LAYING_OUT_WATER, 0x8001, x, y, z); } - *ebx = cost; + return cost; +} + +/** + * + * rct2: 0x006E66A0 + */ +void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + *ebx = raise_water( + (sint16)*eax, + (sint16)*ecx, + (sint16)*edi, + (sint16)*ebp, + (uint8)*ebx); +} + +money32 lower_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags){ + money32 cost = 0; + + uint8 min_height = 0; + + for (int yi = y0; yi <= y1; yi += 32){ + for (int xi = x0; xi <= x1; xi += 32){ + rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); + + uint8 height = map_element->properties.surface.terrain & 0x1F; + if (height){ + height *= 2; + if (height > min_height){ + min_height = height; + } + } + } + } + + for (int yi = y0; yi <= y1; yi += 32){ + for (int xi = x0; xi <= x1; xi += 32){ + rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); + + uint8 height = (map_element->properties.surface.terrain & 0x1F); + if (height){ + height *= 2; + if (height < min_height){ + continue; + } + height -= 2; + int cost2 = game_do_command(xi, flags, yi, (min_height << 8) + height, GAME_COMMAND_16, 0, 0); + if (cost2 == MONEY32_UNDEFINED){ + return MONEY32_UNDEFINED; + } + else{ + cost += cost2; + } + } + } + } + if (flags & GAME_COMMAND_FLAG_APPLY){ + int x = ((x0 + x1) / 2) + 16; + int y = ((y0 + y1) / 2) + 16; + int z = map_element_height(x, y); + sint16 water_height_z = z >> 16; + sint16 base_height_z = z; + z = water_height_z; + if (!z){ + z = base_height_z; + } + RCT2_GLOBAL(0x009DEA5E, uint32) = x; + RCT2_GLOBAL(0x009DEA60, uint32) = y; + RCT2_GLOBAL(0x009DEA62, uint32) = z; + sound_play_panned(SOUND_LAYING_OUT_WATER, 0x8001, x, y, z); + } + return cost; } /** @@ -1638,66 +1701,12 @@ void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, */ void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { - int ax = (uint16)*eax; - int ay = (uint16)*ecx; - int bx = (uint16)*edi; - int by = (uint16)*ebp; - - int cost = 0; - - uint8 min_height = 0; - - for(int yi = ay; yi <= by; yi += 32){ - for(int xi = ax; xi <= bx; xi += 32){ - rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); - - uint8 height = map_element->properties.surface.terrain & 0x1F; - if(height){ - height *= 2; - if(height > min_height){ - min_height = height; - } - } - } - } - - for(int yi = ay; yi <= by; yi += 32){ - for(int xi = ax; xi <= bx; xi += 32){ - rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); - - uint8 height = (map_element->properties.surface.terrain & 0x1F); - if(height){ - height *= 2; - if(height < min_height){ - continue; - } - height -= 2; - int ebx2 = game_do_command(xi, *ebx, yi, (min_height << 8) + height, GAME_COMMAND_16, 0, 0); - if(ebx2 == MONEY32_UNDEFINED){ - *ebx = MONEY32_UNDEFINED; - return; - }else{ - cost += ebx2; - } - } - } - } - if(*ebx & GAME_COMMAND_FLAG_APPLY){ - int x = ((ax + bx) / 2) + 16; - int y = ((ay + by) / 2) + 16; - int z = map_element_height(x, y); - sint16 water_height_z = z >> 16; - sint16 base_height_z = z; - z = water_height_z; - if(!z){ - z = base_height_z; - } - RCT2_GLOBAL(0x009DEA5E, uint32) = x; - RCT2_GLOBAL(0x009DEA60, uint32) = y; - RCT2_GLOBAL(0x009DEA62, uint32) = z; - sound_play_panned(SOUND_LAYING_OUT_WATER, 0x8001, x, y, z); - } - *ebx = cost; + *ebx = lower_water( + (sint16)*eax, + (sint16)*ecx, + (sint16)*edi, + (sint16)*ebp, + (uint8)*ebx); } /** @@ -1732,6 +1741,12 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, return; } } + + if (!(*ebx & GAME_COMMAND_FLAG_APPLY)){ + *ebx = 0; + return; + } + rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.type]; if(scenery_entry->wall.var_0D != 0xFF){ rct_banner* banner = &gBanners[map_element->properties.fence.item[0]]; @@ -1865,7 +1880,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi if(RCT2_GLOBAL(0x009D8150, uint8) & 1 || (x <= RCT2_GLOBAL(0x01358836, uint16) && y <= RCT2_GLOBAL(0x01358836, uint16))){ rct_scenery_entry* scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].chunks[scenery_type]; if((scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE && scenery_entry->small_scenery.flags & (SMALL_SCENERY_FLAG9 | SMALL_SCENERY_FLAG24 | SMALL_SCENERY_FLAG25)) || scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG9){ - base_height = 0; + quadrant = 0; } int x2 = x; int y2 = y; @@ -1936,7 +1951,6 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi } if(!(scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG24)){ if(scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG9 && scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE){ - // this stuff that uses rol and ror are untested, couldnt find any scenery with these flags if(scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG25){ bp ^= 2; bp += rotation; @@ -1948,7 +1962,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi bp += rotation; bp &= 1; bl = 0xA; - bl = ror8(bl, bp); + bl >>= bp; } } }else{ diff --git a/src/world/map.h b/src/world/map.h index 6e3ba65b85..7d9337fa12 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -279,6 +279,10 @@ rct_map_element *map_element_insert(int x, int y, int z, int flags); int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *clearFunc, uint8 bl); int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); int sub_6BA278(int ebx); +void rotate_map_coordinates(sint16* x, sint16* y, uint8 rotation); +money32 map_clear_scenery(int x0, int y0, int x1, int y1, int flags); +money32 lower_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags); +money32 raise_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags); void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); diff --git a/src/world/park.c b/src/world/park.c index d487006ad6..2dcdcb164a 100644 --- a/src/world/park.c +++ b/src/world/park.c @@ -435,7 +435,7 @@ static int park_calculate_guest_generation_probability() // Reward or penalties for park awards for (i = 0; i < MAX_AWARDS; i++) { - rct_award *award = &RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award)[i]; + rct_award *award = &gCurrentAwards[i]; if (award->time == 0) continue;