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;