diff --git a/contributors.md b/contributors.md
new file mode 100644
index 0000000000..067ff42af2
--- /dev/null
+++ b/contributors.md
@@ -0,0 +1,80 @@
+# Contributors to OpenRCT2
+Includes all git commit authors. Aliases are GitHub user names.
+
+## Project team
+* Ted John (IntelOrca) - Owner
+
+## Long term developers
+* Ted John (IntelOrca)
+* Duncan Frost (duncanspumpkin)
+
+## Implementation (RCT2)
+* Ted John (IntelOrca)
+* Duncan Frost (duncanspumpkin)
+* Peter Hill (ZedFree) - String handling, misc.
+* (qcz) - Scenery window, misc.
+* Matthias Lanzinger (lnz) - Climate, finance, scenario, ride reachability
+* (zsilencer) - Audio, misc.
+* Adrian Wielgosik (adrian17) - Misc.
+* (hexdec) - Misc.
+* Dennis Devriendt (ddevrien) - Misc.
+* Maciek Baron (MaciekBaron) - Misc.
+* (AngeloG) - Scrollbar input, misc.
+* (jcdavis) - Misc.
+* (marcotc) - Rain drawing, misc.
+* (vanderkleij) - Misc.
+* Ben Pye (benpye) - Misc.
+* (JeroenSack) - Misc.
+* (Vijfhoek) - Misc.
+* (wolfreak99) - Misc.
+* Inseok Lee (dlunch) - Original command line
+
+## Additional implementation (OpenRCT2)
+* (atmaxinger) - User configuration
+* (anyc) - Housecleaning, cross-platform fixes
+* Miso Zmiric (mzmiric5) - Misc.
+* (DutchRPW) - Housecleaning, initialisation
+* Jørn Lomax (jvlomax) - User configuration
+* (KingHual) - Housecleaning
+* Alexander Overvoorde (Overv) - Misc.
+* (eezstreet) - Misc.
+
+## Bug fixes
+* (halfbro)
+* (Myrtle)
+* (nean)
+
+## Toolchain
+* (Balletie) - OSX
+* Kevin Burke (kevinburke) - OSX, Unix
+* Miso Zmiric (mzmiric5) - OSX
+* (JarnoVgr) - Windows build server
+* Ted John (IntelOrca) - Windows
+
+## Documentation
+* (honzi)
+* Kevin Burke (kevinburke)
+* James Robertson (rd3k)
+* Max Boße (MakaHost)
+* (MaxBareiss)
+* Philip Plarkson (Philpax)
+* (RollingStar)
+
+## Translation
+* English (UK) - Ted John (IntelOrca), (Tinytimrob)
+* French - (fbourigault)
+* German - (atmaxinger), (Yepoleb)
+* Dutch - Michael Steenbeek (Gymnasiast), (hostbrute), (mrtnptrs), (xzbobzx)
+* Spanish - (mdtrooper)
+* Swedish - (Jinxit), (mharrys)
+
+## RollerCoaster Tycoon 2 credits
+Design and programming by Chris Sawyer
+Graphics by Simon Foster
+Sound and music by Allister Brimble
+Additional sounds recorded by David Ellis
+Representation by Jacqui Lyons at Mar jacq Ltd.
+
+Thanks to: Peter James Adcock, Joe Booth, and John Wardley
+
+Licensed to Infogrames Interactive Inc.
\ No newline at end of file
diff --git a/data/language/dutch.txt b/data/language/dutch.txt
index 78af2f4ec8..a58df3c813 100644
--- a/data/language/dutch.txt
+++ b/data/language/dutch.txt
@@ -561,13 +561,13 @@ STR_0559 :
STR_0560 :
STR_0561 :
STR_0562 :
-STR_0563 :Bezoekers zitten in comfortabele treinen met enkel een schootbeugel en gaan door soepel door grote afdalingen en kronkelende stukken baan, met veel 'airtime' in de heuvels
+STR_0563 :Bezoekers zitten in comfortabele treinen met enkel een schootbeugel en gaan soepel door grote afdalingen en kronkelende stukken baan, met veel 'airtime' in de heuvels
STR_0564 :Deze over een houten baan lopende achtbaan is snel, ruw, luidruchting en geeft het gevoel van controleverlies met veel 'airtime'
STR_0565 :Een simpele houten achtbaan die enkel in staat is rustige hellingen en bochten te bedwingen, de karretjes worden enkel op de baan gehouden door middel van zijfrictiewielen en zwaartekracht
STR_0566 :Losse karretjes rijden over een kronkelende baan scherpe bochten en korte felle afdalingen
STR_0567 :Bezoekers zitten in stoelen aan beide kanten van de baan, en draaien alle kanten op terwijl ze door de diepe afdalingen gaan en door diverse omkeringen.
STR_0568 :
-STR_0569 :Bezoekers zitten in een speciaal tuig onder de baan en krijgen zo de ervaring dat ze vliegen
+STR_0569 :Bezoekers zitten in een speciaal tuigje onder de baan en krijgen zo de ervaring dat ze vliegen
STR_0570 :
STR_0571 :
STR_0572 :
@@ -584,7 +584,7 @@ STR_0582 :
STR_0583 :
STR_0584 :
STR_0585 :
-STR_0586 :Bootvormige karretjes lopen over achtbaanrails waardoor ze hellende bochten en diepe afdalingen kunnen maken, waarna ze in bakken water neerplonzen en rustig een stukje kunnen varen
+STR_0586 :Bootvormige karretjes lopen over achtbaanrails, waardoor ze hellende bochten en diepe afdalingen kunnen maken, waarna ze in bakken water neerplonzen en rustig een stukje kunnen varen
STR_0587 :
STR_0588 :
STR_0589 :
@@ -879,7 +879,7 @@ STR_0877 :Te laag!
STR_0878 :Te hoog!
STR_0879 :Kan het land hier niet verlagen...
STR_0880 :Kan het land hier niet verhogen...
-STR_0881 :Object in de weg
+STR_0881 :Object staat in de weg
STR_0882 :Spel laden
STR_0883 :Spel opslaan
STR_0884 :Landschap laden
@@ -892,18 +892,18 @@ STR_0890 :SCR{COMMA16}.PNG
STR_0891 :Screenshot
STR_0892 :Screenshot opgeslagen als '{STRINGID}'
STR_0893 :Screenshot maken mislukt!
-STR_0894 :Landscape data area zit vol!
+STR_0894 :"Landscape data area" zit vol!
STR_0895 :Kan niet gedeeltelijk onder en boven de grond bouwen
STR_0896 :{POP16}{POP16}{STRINGID} Constructie
STR_0897 :Richting
STR_0898 :{SMALLFONT}{BLACK}Bocht naar links
STR_0899 :{SMALLFONT}{BLACK}Bocht naar rechts
-STR_0900 :{SMALLFONT}{BLACK}Bocht naar links (kleine radius)
-STR_0901 :{SMALLFONT}{BLACK}Bocht naar rechts (kleine radius)
-STR_0902 :{SMALLFONT}{BLACK}Bocht naar links (zeer kleine radius)
-STR_0903 :{SMALLFONT}{BLACK}Bocht naar rechts (zeer kleine radius)
-STR_0904 :{SMALLFONT}{BLACK}Bocht naar links (grote radius)
-STR_0905 :{SMALLFONT}{BLACK}Bocht naar rechts (grote radius)
+STR_0900 :{SMALLFONT}{BLACK}Bocht naar links (kleine straal)
+STR_0901 :{SMALLFONT}{BLACK}Bocht naar rechts (kleine straal)
+STR_0902 :{SMALLFONT}{BLACK}Bocht naar links (zeer kleine straal)
+STR_0903 :{SMALLFONT}{BLACK}Bocht naar rechts (zeer kleine straal)
+STR_0904 :{SMALLFONT}{BLACK}Bocht naar links (grote straal)
+STR_0905 :{SMALLFONT}{BLACK}Bocht naar rechts (straal)
STR_0906 :{SMALLFONT}{BLACK}Recht stuk
STR_0907 :Helling
STR_0908 :Roll/Banking
@@ -911,10 +911,10 @@ STR_0909 :Stoelrot.
STR_0910 :{SMALLFONT}{BLACK}Roll voor bocht naar links
STR_0911 :{SMALLFONT}{BLACK}Roll voor bocht naar rechts
STR_0912 :{SMALLFONT}{BLACK}Geen roll
-STR_0913 :{SMALLFONT}{BLACK}Ga naar vorig segment
-STR_0914 :{SMALLFONT}{BLACK}Ga naar volgend segment
-STR_0915 :{SMALLFONT}{BLACK}Bouw het geselecteerde segment
-STR_0916 :{SMALLFONT}{BLACK}Verwijder het gemarkeerde segment
+STR_0913 :{SMALLFONT}{BLACK}Ga naar vorig gedeelte
+STR_0914 :{SMALLFONT}{BLACK}Ga naar volgend gedeelte
+STR_0915 :{SMALLFONT}{BLACK}Bouw het geselecteerde gedeelte
+STR_0916 :{SMALLFONT}{BLACK}Verwijder het gemarkeerde gedeelte
STR_0917 :{SMALLFONT}{BLACK}Verticale val
STR_0918 :{SMALLFONT}{BLACK}Steile helling naar beneden
STR_0919 :{SMALLFONT}{BLACK}Helling naar beneden
@@ -932,9 +932,9 @@ STR_0930 :S-bocht (rechts)
STR_0931 :Verticale looping (links)
STR_0932 :Verticale looping (rechts)
STR_0933 :Verhoog of verlaag eerst het land
-STR_0934 :Attractieingang in de weg
-STR_0935 :Attractieuitgang in de weg
-STR_0936 :Parkingang in de weg
+STR_0934 :Attractieingang staat in de weg
+STR_0935 :Attractieuitgang staat in de weg
+STR_0936 :Parkingang staat in de weg
STR_0937 :{SMALLFONT}{BLACK}Beeldopties
STR_0938 :{SMALLFONT}{BLACK}Landhoogte en -helling aanpassen
STR_0939 :Zicht ondergronds/binnen
@@ -945,7 +945,7 @@ STR_0943 :Doorzichtig decor
STR_0944 :Opslaan
STR_0945 :Niet opslaan
STR_0946 :Annuleren
-STR_0947 :Dit spel opslaan voordat je een ander laadt?
+STR_0947 :Dit spel opslaan voordat je een ander spel laadt?
STR_0948 :Dit spel opslaan voordat je afsluit?
STR_0949 :Dit spel opslaan voordat je afsluit?
STR_0950 :Spel laden
@@ -953,7 +953,7 @@ STR_0951 :Spel afsluiten
STR_0952 :Spel afsluiten
STR_0953 :Landschap laden
STR_0954 :
-STR_0955 :{SMALLFONT}{BLACK}Selecteer de draaiing van de stoelen voor dit segment
+STR_0955 :{SMALLFONT}{BLACK}Selecteer de draaiing van de stoelen voor dit gedeelte
STR_0956 :-180{DEGREE}
STR_0957 :-135{DEGREE}
STR_0958 :-90{DEGREE}
@@ -1003,7 +1003,7 @@ STR_1001 :Baan is ongeschikt voor dit type trein
STR_1002 :Kan {POP16}{POP16}{POP16}{STRINGID} niet openen...
STR_1003 :Kan {POP16}{POP16}{POP16}{STRINGID} niet testen...
STR_1004 :Kan {POP16}{POP16}{POP16}{STRINGID} niet sluiten...
-STR_1005 :Kan verbouwing van {POP16}{POP16}{POP16}{STRINGID} niet beginnen...
+STR_1005 :Kan de verbouwing van {POP16}{POP16}{POP16}{STRINGID} niet starten...
STR_1006 :Moet eerst worden gesloten
STR_1007 :Kan niet voldoende voertuigen aanmaken
STR_1008 :{SMALLFONT}{BLACK}Attractie openen, sluiten of testen
@@ -1013,7 +1013,7 @@ STR_1011 :Alles sluiten
STR_1012 :Alles openen
STR_1013 :Park sluiten
STR_1014 :Park openen
-STR_1015 :Kan in deze modus niet met meer dan een station werken
+STR_1015 :Kan in deze modus niet met meer dan één station werken
STR_1016 :Kan in deze modus niet met minder dan twee stations werken
STR_1017 :Kan modus niet veranderen...
STR_1018 :Kan geen veranderingen aanbrengen...
@@ -1057,7 +1057,7 @@ STR_1055 :{SMALLFONT}{BLACK}Persoonsnaam
STR_1056 :{SMALLFONT}{BLACK}Werknemersnaam
STR_1057 :Attractienaam
STR_1058 :Voer een nieuwe naam in voor deze attractie:
-STR_1059 :Kan deze attractienaam geen andere naam geven...
+STR_1059 :Kan deze attractie geen andere naam geven...
STR_1060 :Ongeldige attractienaam
STR_1061 :Normale stand
STR_1062 :Voortdurend circuit
@@ -1068,8 +1068,8 @@ STR_1066 :Bootverhuurmodus
STR_1067 :Opwaartse lancering
STR_1068 :Draaiendeliftmodus
STR_1069 :Station-naar-station
-STR_1070 :Enkele rit per toegang
-STR_1071 :Onbeperkt aantal ritten per toegang
+STR_1070 :Enkele rit per entree
+STR_1071 :Onbeperkt aantal ritten per entree
STR_1072 :Doolhofstand
STR_1073 :Racestand
STR_1074 :Botsautomodus
@@ -1177,7 +1177,7 @@ STR_1175 :Kan dit niet op hellend voetpad neerzetten
STR_1176 :Kan hier geen voetpad neerzetten...
STR_1177 :Kan dit voetpad niet verwijderen...
STR_1178 :Landhelling is ongeschikt
-STR_1179 :Voetpad in de weg
+STR_1179 :Voetpad staat in de weg
STR_1180 :Dit kan niet onder water worden gebouwd!
STR_1181 :Voetpaden
STR_1182 :Type
@@ -1187,8 +1187,8 @@ STR_1185 :{SMALLFONT}{BLACK}Richting
STR_1186 :{SMALLFONT}{BLACK}Helling naar beneden
STR_1187 :{SMALLFONT}{BLACK}Vlak
STR_1188 :{SMALLFONT}{BLACK}Helling naar boven
-STR_1189 :{SMALLFONT}{BLACK}Bouw het geselecteerde segment
-STR_1190 :{SMALLFONT}{BLACK}Verwijder vorig segment
+STR_1189 :{SMALLFONT}{BLACK}Bouw het geselecteerde gedeelte
+STR_1190 :{SMALLFONT}{BLACK}Verwijder vorig gedeelte
STR_1191 :{BLACK}{STRINGID}
STR_1192 :{OUTLINE}{RED}{STRINGID}
STR_1193 :{WINDOW_COLOUR_2}{STRINGID}
@@ -1218,7 +1218,7 @@ STR_1216 :{SMALLFONT}{BLACK}Selecteer of een trein op hetzelfde moment moet v
STR_1217 :{COMMA16} seconden
STR_1218 :{BLACK}{SMALLUP}
STR_1219 :{BLACK}{SMALLDOWN}
-STR_1220 :Alleen uitgang
+STR_1220 :Alleen een uitgang
STR_1221 :Geen ingang
STR_1222 :Geen uitgang
STR_1223 :{SMALLFONT}{BLACK}Transportattracties
@@ -1383,7 +1383,7 @@ STR_1381 :Gedraaide liftheuvel (links)
STR_1382 :Gedraaide liftheuvel (rechts)
STR_1383 :Kwartlooping
STR_1384 :{YELLOW}{STRINGID}
-STR_1385 :{SMALLFONT}{BLACK}Andere baanconfiguraties
+STR_1385 :{SMALLFONT}{BLACK}Andere baanmogelijkheden
STR_1386 :Speciaal...
STR_1387 :Kan het landtype niet aanpassen...
STR_1388 :{OUTLINE}{GREEN}+ {CURRENCY}
@@ -1409,7 +1409,7 @@ STR_1407 :{WINDOW_COLOUR_2}Dit bouwen...
STR_1408 :{WINDOW_COLOUR_2}Kosten: {BLACK}{CURRENCY}
STR_1409 :Platform voor ingang/uitgang
STR_1410 :Verticale toren
-STR_1411 :{STRINGID} in de weg
+STR_1411 :{STRINGID} staat in de weg
STR_1412 :{15}Datalog is niet beschikbaar voor dit type attractie
STR_1413 :{15}Datalog zal beginnen wanneer de volgende {STRINGID} {STRINGID} verlaat
STR_1414 :{SMALLFONT}{BLACK}{DURATION}
@@ -1443,10 +1443,10 @@ STR_1441 :Veegt voetpad
STR_1442 :Leegt prullenbak
STR_1443 :Geeft planten water
STR_1444 :Kijkt naar {STRINGID}
-STR_1445 :Kijkt naar bouw van {STRINGID}
+STR_1445 :Kijkt naar de bouw van {STRINGID}
STR_1446 :Kijkt naar decor
STR_1447 :Verlaat het park
-STR_1448 :Kijkt naar bouw van nieuwe attractie
+STR_1448 :Kijkt naar de bouw van de nieuwe attractie
STR_1449 :{SPRITE} {STRINGID}{NEWLINE}({STRINGID})
STR_1450 :{INLINE_SPRITE}{09}{20}{00}{00}{SPRITE} {STRINGID}{NEWLINE}({STRINGID})
STR_1451 :{STRINGID}{NEWLINE}({STRINGID})
@@ -1502,7 +1502,7 @@ STR_1500 :{SMALLFONT}{OPENQUOTES}Ik heb honger{ENDQUOTES}
STR_1501 :{SMALLFONT}{OPENQUOTES}Ik heb dorst{ENDQUOTES}
STR_1502 :{SMALLFONT}{OPENQUOTES}Ik moet naar de WC{ENDQUOTES}
STR_1503 :{SMALLFONT}{OPENQUOTES}Ik kan {STRINGID} niet vinden{ENDQUOTES}
-STR_1504 :{SMALLFONT}{OPENQUOTES}Zoveel betalen ik niet voor het gebruik van {STRINGID}{ENDQUOTES}
+STR_1504 :{SMALLFONT}{OPENQUOTES}Zoveel betaal ik niet voor het gebruik van {STRINGID}{ENDQUOTES}
STR_1505 :{SMALLFONT}{OPENQUOTES}Ik ga niet in {STRINGID} als het regent{ENDQUOTES}
STR_1506 :{SMALLFONT}{OPENQUOTES}Het is hier een zwijnenstal{ENDQUOTES}
STR_1507 :{SMALLFONT}{OPENQUOTES}Ik kan de parkuitgang niet vinden{ENDQUOTES}
@@ -1515,14 +1515,14 @@ STR_1513 :{SMALLFONT}{OPENQUOTES}Er is hier erg veel vandalisme{ENDQUOTES}
STR_1514 :{SMALLFONT}{OPENQUOTES}Mooi decor!{ENDQUOTES}
STR_1515 :{SMALLFONT}{OPENQUOTES}Dit park is erg schoon en netjes{ENDQUOTES}
STR_1516 :{SMALLFONT}{OPENQUOTES}Die springende fonteinen zijn erg leuk{ENDQUOTES}
-STR_1517 :{SMALLFONT}{OPENQUOTES}Er speelt hier leuke muziek{ENDQUOTES}
+STR_1517 :{SMALLFONT}{OPENQUOTES}Er wordt hier leuke muziek gedraaid{ENDQUOTES}
STR_1518 :{SMALLFONT}{OPENQUOTES}Deze ballon van {STRINGID} is erg goedkoop{ENDQUOTES}
STR_1519 :{SMALLFONT}{OPENQUOTES}Deze knuffel van {STRINGID} is erg goedkoop{ENDQUOTES}
STR_1520 :{SMALLFONT}{OPENQUOTES}Deze plattegrond van {STRINGID} is erg goedkoop{ENDQUOTES}
STR_1521 :{SMALLFONT}{OPENQUOTES}Deze actiefoto van {STRINGID} is erg goedkoop{ENDQUOTES}
STR_1522 :{SMALLFONT}{OPENQUOTES}Deze paraplu van {STRINGID} is erg goedkoop{ENDQUOTES}
STR_1523 :{SMALLFONT}{OPENQUOTES}Deze frisdrank van {STRINGID} is erg goedkoop{ENDQUOTES}
-STR_1524 :{SMALLFONT}{OPENQUOTES}Deze hamburger {STRINGID} is erg goedkoop{ENDQUOTES}
+STR_1524 :{SMALLFONT}{OPENQUOTES}Deze hamburger van {STRINGID} is erg goedkoop{ENDQUOTES}
STR_1525 :{SMALLFONT}{OPENQUOTES}Deze frietjes van {STRINGID} zijn erg goedkoop{ENDQUOTES}
STR_1526 :{SMALLFONT}{OPENQUOTES}Dit ijsje van {STRINGID} is erg goedkoop{ENDQUOTES}
STR_1527 :{SMALLFONT}{OPENQUOTES}Deze suikerspin van {STRINGID} is erg goedkoop{ENDQUOTES}
@@ -1556,7 +1556,7 @@ STR_1554 :{SMALLFONT}{OPENQUOTES}Zoveel betaal ik niet voor een plattegrond v
STR_1555 :{SMALLFONT}{OPENQUOTES}Zoveel betaal ik niet voor een actiefoto van {STRINGID}{ENDQUOTES}
STR_1556 :{SMALLFONT}{OPENQUOTES}Zoveel betaal ik niet voor een paraplu van {STRINGID}{ENDQUOTES}
STR_1557 :{SMALLFONT}{OPENQUOTES}Zoveel betaal ik niet voor frisdrank van {STRINGID}{ENDQUOTES}
-STR_1558 :{SMALLFONT}{OPENQUOTES}Zoveel betaal ik niet voor een hamburger {STRINGID}{ENDQUOTES}
+STR_1558 :{SMALLFONT}{OPENQUOTES}Zoveel betaal ik niet voor een hamburger van {STRINGID}{ENDQUOTES}
STR_1559 :{SMALLFONT}{OPENQUOTES}Zoveel betaal ik niet voor frietjes van {STRINGID}{ENDQUOTES}
STR_1560 :{SMALLFONT}{OPENQUOTES}Zoveel betaal ik niet voor een ijsje van {STRINGID}{ENDQUOTES}
STR_1561 :{SMALLFONT}{OPENQUOTES}Zoveel betaal ik niet voor een suikerspin van {STRINGID}{ENDQUOTES}
@@ -1668,7 +1668,7 @@ STR_1666 :{WINDOW_COLOUR_2}Dorst:
STR_1667 :{WINDOW_COLOUR_2}WC-behoefte:
STR_1668 :{WINDOW_COLOUR_2}Voldoening: {BLACK}onbekend
STR_1669 :{WINDOW_COLOUR_2}Voldoening: {BLACK}{COMMA16}%
-STR_1670 :{WINDOW_COLOUR_2}Totale bezoekers: {BLACK}{COMMA32}
+STR_1670 :{WINDOW_COLOUR_2}Totaal aantal bezoekers: {BLACK}{COMMA32}
STR_1671 :{WINDOW_COLOUR_2}Totale winst: {BLACK}{CURRENCY2DP}
STR_1672 :Remmen
STR_1673 :Draaistop
@@ -1694,7 +1694,7 @@ STR_1692 :{WINDOW_COLOUR_2} Kosten: {BLACK}vanaf {CURRENCY}
STR_1693 :{SMALLFONT}{BLACK}Bezoekers
STR_1694 :{SMALLFONT}{BLACK}Werknemers
STR_1695 :{SMALLFONT}{BLACK}Inkomsten en kosten
-STR_1696 :{SMALLFONT}{BLACK}Klantinformatie
+STR_1696 :{SMALLFONT}{BLACK}Klanteninformatie
STR_1697 :Dit kan niet op wachtrijen worden geplaatst
STR_1698 :Dit kan alleen op wachtrijen worden geplaatst
STR_1699 :Teveel personen in het spel
@@ -1763,7 +1763,7 @@ STR_1761 :{SMALLFONT}{BLACK}Bouw doolhof in deze richting
STR_1762 :Watervallen
STR_1763 :Stroomversnelling
STR_1764 :Balkendrempels
-STR_1765 :Actiefoto-installatie
+STR_1765 :Actiefotogedeelte
STR_1766 :Draaischijf
STR_1767 :Draaiende tunnel
STR_1768 :Kan het aantal schommelingen niet aanpassen...
@@ -1771,7 +1771,7 @@ STR_1769 :{WINDOW_COLOUR_2}Aantal schommelingen:
STR_1770 :{SMALLFONT}{BLACK}Aantal complete schommelingen
STR_1771 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16}
STR_1772 :{COMMA16}
-STR_1773 :Een attractie mag maar één actiefoto-installatie hebben
+STR_1773 :Een attractie mag maar één actiefotogedeelte hebben
STR_1774 :Een attractie mag maar één kabellift hebben
STR_1775 :Uit
STR_1776 :Aan
@@ -1918,9 +1918,9 @@ STR_1916 :{WINDOW_COLOUR_2}Lening:
STR_1917 :{POP16}{POP16}{POP16}{CURRENCY}
STR_1918 :Kan niet meer geld lenen!
STR_1919 :Onvoldoende contant geld beschikbaar!
-STR_1920 :Kan geen lening terugbetalen!
+STR_1920 :Kan lening niet terugbetalen!
STR_1921 :{SMALLFONT}{BLACK}Een nieuw spel starten
-STR_1922 :{SMALLFONT}{BLACK}Verder gaan aan een opgeslagen spel
+STR_1922 :{SMALLFONT}{BLACK}Verder gaan met een opgeslagen spel
STR_1923 :{SMALLFONT}{BLACK}Tutorial tonen
STR_1924 :{SMALLFONT}{BLACK}Afsluiten
STR_1925 :Kan hier geen persoon plaatsen...
@@ -1945,10 +1945,10 @@ STR_1943 :{SMALLFONT}{BLACK}Recente gedachten van deze bezoeker tonen
STR_1944 :{SMALLFONT}{BLACK}Toon de dingen die de gast bij zich heeft
STR_1945 :{SMALLFONT}{BLACK}Orders en opties voor deze werknemer tonen
STR_1946 :{SMALLFONT}{BLACK}Kostuum van deze entertainer selecteren
-STR_1947 :{SMALLFONT}{BLACK}Werkgebieden van het geselecteerde type werknemer weergeven, en de dichtstbijzijnde werknemer localiseren
+STR_1947 :{SMALLFONT}{BLACK}Werkgebieden van het geselecteerde type werknemer weergeven en de dichtstbijzijnde werknemer localiseren
STR_1948 :{SMALLFONT}{BLACK}Nieuwe werknemer van het geselecteerde type aannemen
STR_1949 :Samenvatting financiën
-STR_1950 :Grafiek financiën
+STR_1950 :Grafiek van financiën
STR_1951 :Grafiek van parkwaardering
STR_1952 :Winstgrafiek
STR_1953 :Marketing
@@ -2226,7 +2226,7 @@ STR_2224 :{WINDOW_COLOUR_2}Contant: {BLACK}{CURRENCY2DP}
STR_2225 :{WINDOW_COLOUR_2}Contant: {RED}{CURRENCY2DP}
STR_2226 :{WINDOW_COLOUR_2}Parkwaarde: {BLACK}{CURRENCY}
STR_2227 :{WINDOW_COLOUR_2}Bedrijfswaarde: {BLACK}{CURRENCY}
-STR_2228 :{WINDOW_COLOUR_2}Inkomsten horeca en merchandise{NEWLINE}vorige maand: {BLACK}{CURRENCY}
+STR_2228 :{WINDOW_COLOUR_2}Inkomsten horeca en souvenirs{NEWLINE}vorige maand: {BLACK}{CURRENCY}
STR_2229 :Helling omhoog naar verticaal
STR_2230 :Verticale baan
STR_2231 :Vasthoudrem voor afdaling
@@ -2311,7 +2311,7 @@ STR_2309 :Nieuw baanontwerp installeren
STR_2310 :Eigen ontwerp bouwen
STR_2311 :{WINDOW_COLOUR_2}Spanningswaarde: {BLACK}{COMMA2DP32} (ongeveer)
STR_2312 :{WINDOW_COLOUR_2}Intensiteitswaarde: {BLACK}{COMMA2DP32} (ongeveer)
-STR_2313 :{WINDOW_COLOUR_2}Misselheidswaarde: {BLACK}{COMMA2DP32} (ongeveer)
+STR_2313 :{WINDOW_COLOUR_2}Missellijkheidswaarde: {BLACK}{COMMA2DP32} (ongeveer)
STR_2314 :{WINDOW_COLOUR_2}Lengte: {BLACK}{STRINGID}
STR_2315 :{WINDOW_COLOUR_2}Kosten: {BLACK}ongeveer {CURRENCY}
STR_2316 :{WINDOW_COLOUR_2}Vereiste ruimte: {BLACK}{COMMA16} x {COMMA16} blokken
@@ -2350,7 +2350,7 @@ STR_2348 :{SMALLFONT}{BLACK}Statistieken voor deze werknemer tonen
STR_2349 :{WINDOW_COLOUR_2}Loon: {BLACK}{CURRENCY} per month
STR_2350 :{WINDOW_COLOUR_2}In dienst genomen: {BLACK}{MONTHYEAR}
STR_2351 :{WINDOW_COLOUR_2}Velden gemaaid: {BLACK}{COMMA16}
-STR_2352 :{WINDOW_COLOUR_2}Bloembakken water gegeven: {BLACK}{COMMA16}
+STR_2352 :{WINDOW_COLOUR_2}Bloemen water gegeven: {BLACK}{COMMA16}
STR_2353 :{WINDOW_COLOUR_2}Afval opgeveegd: {BLACK}{COMMA16}
STR_2354 :{WINDOW_COLOUR_2}Prullenbakken geleegd: {BLACK}{COMMA16}
STR_2355 :{WINDOW_COLOUR_2}Reparaties: {BLACK}{COMMA16}
@@ -2391,22 +2391,22 @@ STR_2389 :{BLACK}Om de beste {STRINGID} te bouwen!
STR_2390 :{BLACK}Om 10 verschillende typen achtbanen in je park te hebben, elk met een spanningswaarde van minstens 6,00
STR_2391 :{BLACK}Om minstens {COMMA16} bezoekers in je park te hebben. Je parkwaardering mag geen moment onder de 700 komen!
STR_2392 :{BLACK}Om in één maand minstens {POP16}{POP16}{CURRENCY} aan attractiekaartjes te verdienen
-STR_2393 :{BLACK}Om 10 verschillende typen achtbanen in je park te hebben, elk met een lengte van minstens {LENGTH}, en een spanningswaarde van minstens 7,00
+STR_2393 :{BLACK}Om 10 verschillende typen achtbanen in je park te hebben, elk met een lengte van minstens {LENGTH} en een spanningswaarde van minstens 7,00
STR_2394 :{BLACK}Om alle 5 deels gebouwde achtbanen in je park af te maken, ek met een spanningswaarde van minstens {POP16}{POP16}{COMMA2DP32}
STR_2395 :{BLACK}Om je lening terug te betalen en een parkwaarde van minstens {POP16}{POP16}{CURRENCY} te bereiken
-STR_2396 :{BLACK}Om in één maand minstens {POP16}{POP16}{CURRENCY} aan de verkoop van eten, drinken en merchandise te verdienen
+STR_2396 :{BLACK}Om in één maand minstens {POP16}{POP16}{CURRENCY} aan de verkoop van eten, drinken en souvenirs te verdienen
STR_2397 :Geen
STR_2398 :Aantal bezoekers op een bepaalde datum
STR_2399 :Parkwaarde op een bepaalde datum
STR_2400 :Plezier hebben
STR_2401 :De beste attractie te bouwen
-STR_2402 :10 achtbanen bouwen
+STR_2402 :Tien achtbanen bouwen
STR_2403 :Aantal bezoekers in het park
STR_2404 :Maandelijks inkomen van attractiekaartjes
-STR_2405 :10 achtbanen van een bepaalde lengte bouwen
-STR_2406 :5 achtbanen afmaken
+STR_2405 :Tien achtbanen van een bepaalde lengte bouwen
+STR_2406 :Vijf achtbanen afmaken
STR_2407 :Lening terugbetalen en een bepaalde parkwaarde bereiken
-STR_2408 :Maandelijks inkomen van voedsel/merchandise
+STR_2408 :Maandelijks inkomen van voedsel/souvenirs
STR_2409 :{WINDOW_COLOUR_2}Lopende marketingcampagnes
STR_2410 :{BLACK}Geen
STR_2411 :{WINDOW_COLOUR_2}Beschikbare marketingcampagnes
@@ -2458,7 +2458,7 @@ STR_2456 :{SMALLFONT}{BLACK}{CURRENCY2DP} -
STR_2457 :{SMALLFONT}{BLACK}Laat financiële posten zien
STR_2458 :{SMALLFONT}{BLACK}Toon grafiek van saldoverloop (zonder lening)
STR_2459 :{SMALLFONT}{BLACK}Toon grafiek van parkwaardeverloop
-STR_2460 :{SMALLFONT}{BLACK}Toon grafiek van wekelijke winst
+STR_2460 :{SMALLFONT}{BLACK}Toon grafiek van wekelijkse winst
STR_2461 :{SMALLFONT}{BLACK}Toon marketingcampagnes
STR_2462 :{SMALLFONT}{BLACK}Toon beeld van de parkingang
STR_2463 :{SMALLFONT}{BLACK}Toon grafiek van parkwaarderingverloop
@@ -2718,30 +2718,30 @@ 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_2736 :???
-STR_2737 :???
-STR_2738 :???
-STR_2739 :???
-STR_2740 :???
-STR_2741 :???
-STR_2742 :???
-STR_2743 :???
+STR_2720 :{UINT16}s
+STR_2721 :{UINT16}s
+STR_2722 :{UINT16}m {UINT16}s
+STR_2723 :{UINT16}m {UINT16}s
+STR_2724 :{UINT16}m {UINT16}s
+STR_2725 :{UINT16}m {UINT16}s
+STR_2726 :{UINT16}m
+STR_2727 :{UINT16}m
+STR_2728 :{UINT16}h {UINT16}m
+STR_2729 :{UINT16}h {UINT16}m
+STR_2730 :{UINT16}h {UINT16}m
+STR_2731 :{UINT16}h {UINT16}m
+STR_2732 :{COMMA16} ft
+STR_2733 :{COMMA16} m
+STR_2734 :{COMMA16} mph
+STR_2735 :{COMMA16} km/h
+STR_2736 :{MONTH}, jaar {COMMA16}
+STR_2737 :{STRINGID} {MONTH}, jaar {COMMA16}
+STR_2738 :Titelschermmuziek
+STR_2739 :Geen
+STR_2740 :RollerCoaster Tycoon 1
+STR_2741 :RollerCoaster Tycoon 2
+STR_2742 :css50.dat niet gevonden
+STR_2743 :Kopieer data\css17.dat van je RCT1-installatie naar data\css50.dat in je RCT2-installatie.
STR_2744 :[
STR_2745 :\
STR_2746 :]
@@ -2784,7 +2784,7 @@ STR_2782 :SHIFT +
STR_2783 :CTRL +
STR_2784 :Sneltoets wijzigen
STR_2785 :{WINDOW_COLOUR_2}Voer een nieuwe sneltoets in voor:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES}
-STR_2786 :{SMALLFONT}{BLACK}Klik op de beschrijving op een nieuwe sneltoets in te stellen
+STR_2786 :{SMALLFONT}{BLACK}Klik op de beschrijving om een nieuwe sneltoets in te stellen
STR_2787 :{WINDOW_COLOUR_2}Parkwaarde: {BLACK}{CURRENCY}
STR_2788 :{WINDOW_COLOUR_2}Gefeliciteerd!{NEWLINE}{BLACK}Je hebt je doel bereikt met een bedrijfswaarde van {CURRENCY}!
STR_2789 :{WINDOW_COLOUR_2}Je hebt je doel niet bereikt!
@@ -2810,38 +2810,38 @@ STR_2808 :{RED}Bezoekers klagen over het vandalisme in je park{NEWLINE}Contro
STR_2809 :{RED}Bezoekers hebben honger en kunnen geen plek vinden om voedsel te kopen
STR_2810 :{RED}Bezoekers hebben dorst en kunnen geen plek vinden om drinken te kopen
STR_2811 :{RED}Bezoekers klagen omdat ze de toiletten in je park niet kunnen vinden
-STR_2812 :{RED}Bezoekers raken verdwaald of komen vast te zitten{NEWLINE}Controleer of de indeling van je voetpaden voor verbetering vatbaar is
+STR_2812 :{RED}Bezoekers raken verdwaald of komen vast te zitten{NEWLINE}Controleer of je de indeling van je voetpaden kunt verbeteren
STR_2813 :{RED}Je entreeprijs is te hoog!{NEWLINE}Verlaag de entreeprijs of verbeter het park om meer bezoekers te trekken
-STR_2814 :{WINDOW_COLOUR_2}Rommeligste park
-STR_2815 :{WINDOW_COLOUR_2}Netste park
-STR_2816 :{WINDOW_COLOUR_2}Beste achtbanen
-STR_2817 :{WINDOW_COLOUR_2}Beste park
-STR_2818 :{WINDOW_COLOUR_2}Mooiste park
-STR_2819 :{WINDOW_COLOUR_2}Slechtste park
-STR_2820 :{WINDOW_COLOUR_2}Veiligste park
-STR_2821 :{WINDOW_COLOUR_2}Beste personeel
-STR_2822 :{WINDOW_COLOUR_2}Beste eten
-STR_2823 :{WINDOW_COLOUR_2}Slechtste eten
-STR_2824 :{WINDOW_COLOUR_2}Beste toiletten
-STR_2825 :{WINDOW_COLOUR_2}Meest teleurstellende park
-STR_2826 :{WINDOW_COLOUR_2}Beste waterattracties
-STR_2827 :{WINDOW_COLOUR_2}Beste unieke attracties
-STR_2828 :{WINDOW_COLOUR_2}Meest duizelingwekkende kleurenschema
-STR_2829 :{WINDOW_COLOUR_2}Vreemdste indeling
-STR_2830 :{WINDOW_COLOUR_2}Beste rustige attracties
+STR_2814 :{WINDOW_COLOUR_2}Prijs voor het rommeligste park
+STR_2815 :{WINDOW_COLOUR_2}Prijs voor het netste park
+STR_2816 :{WINDOW_COLOUR_2}Prijs voor de beste achtbanen
+STR_2817 :{WINDOW_COLOUR_2}Prijs voor het park met de beste prijs/kwaliteitsverhouding
+STR_2818 :{WINDOW_COLOUR_2}Prijs voor het mooiste park
+STR_2819 :{WINDOW_COLOUR_2}Prijs voor het park met de slechtste prijs/kwaliteitsverhouding
+STR_2820 :{WINDOW_COLOUR_2}Prijs voor het veiligste park
+STR_2821 :{WINDOW_COLOUR_2}Prijs voor het beste personeel
+STR_2822 :{WINDOW_COLOUR_2}Prijs voor het beste eten
+STR_2823 :{WINDOW_COLOUR_2}Prijs voor het slechtste eten
+STR_2824 :{WINDOW_COLOUR_2}Prijs voor beste toiletten
+STR_2825 :{WINDOW_COLOUR_2}Prijs voor het meest teleurstellende park
+STR_2826 :{WINDOW_COLOUR_2}Prijs voor de beste waterattracties
+STR_2827 :{WINDOW_COLOUR_2}Prijs voor de beste unieke attracties
+STR_2828 :{WINDOW_COLOUR_2}Prijs voor het meest duizelingwekkende kleurenschema
+STR_2829 :{WINDOW_COLOUR_2}Prijs voor het park met de vreemdste indeling
+STR_2830 :{WINDOW_COLOUR_2}Prijs voor de beste rustige attracties
STR_2831 :{TOPAZ}Je park heeft een prijs gekregen: 'Rommeligste park van het land'!
STR_2832 :{TOPAZ}Je park heeft een prijs gekregen: 'Netste park van het land'!
STR_2833 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de beste achtbanen'!
-STR_2834 :{TOPAZ}Je park heeft een prijs gekregen: 'Beste park van het land'!
+STR_2834 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de beste prijs/kwaliteitsverhouding'!
STR_2835 :{TOPAZ}Je park heeft een prijs gekregen: 'Mooiste park van het land'!
-STR_2836 :{TOPAZ}Je park heeft een prijs gekregen: 'Slechtste park van het land'!
-STR_2837 :{TOPAZ}Je park heeft een prijs gekregen: 'Veiligste park'!
+STR_2836 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de slechtste prijs/kwaliteitsverhouding'!
+STR_2837 :{TOPAZ}Je park heeft een prijs gekregen: 'Veiligste park van het land'!
STR_2838 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de beste werknemers'!
STR_2839 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met het beste eten van het land'!
STR_2840 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met het slechtste eten van het land'!
STR_2841 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de beste toiletten van het land'!
-STR_2842 :{TOPAZ}Je park heeft een prijs gekregen: 'Meest teleurstellende park'!
-STR_2843 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de beste waterattracties'!
+STR_2842 :{TOPAZ}Je park heeft een prijs gekregen: 'Meest teleurstellende park van het land'!
+STR_2843 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de beste waterattracties van het land'!
STR_2844 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de beste unieke attracties'!
STR_2845 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met het meest duizelingwekkende kleurenschema'!
STR_2846 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de vreemdste indeling'!
@@ -2986,7 +2986,7 @@ STR_2984 :Kan de tekst op deze banier niet veranderen...
STR_2985 :Banier
STR_2986 :{SMALLFONT}{BLACK}Tekst op deze banier aanpassen
STR_2987 :{SMALLFONT}{BLACK}Deze banier gebruiken als bord voor 'geen toegang' voor de bezoekers
-STR_2988 :{SMALLFONT}{BLACK}Deze banier vernietigen
+STR_2988 :{SMALLFONT}{BLACK}Deze banier verwijderen
STR_2989 :{SMALLFONT}{BLACK}Hoofdkleur selecteren
STR_2990 :{SMALLFONT}{BLACK}Tekstkleur selecteren
STR_2991 :Bord
@@ -3043,7 +3043,7 @@ STR_3041 :Moderne stijl
STR_3042 :Piratenstijl
STR_3043 :Rockstijl 3
STR_3044 :Snoepstijl
-STR_3045 :{SMALLFONT}{BLACK}Selecteer welke muziekstijl er moet worden gespeeld
+STR_3045 :{SMALLFONT}{BLACK}Selecteer welke muziekstijl er moet worden gedraaid
STR_3046 :Deze attractie kan niet worden aangepast
STR_3047 :De gemeente staat de sloop van en wijzigingen aan deze attractie niet toe
STR_3048 :Marketingcampagnes worden niet toegestaan door de gemeente
@@ -3054,20 +3054,20 @@ STR_3052 :Golfhole D
STR_3053 :Golfhole E
STR_3054 :Laden...
STR_3055 :Wit
-STR_3056 :Doorzichting
+STR_3056 :Doorzichtig
STR_3057 :{WINDOW_COLOUR_2}Bouwmarkering:
STR_3058 :Stenen muren
STR_3059 :Heggen
STR_3060 :Blokken ijs
STR_3061 :Houten schuttingen
STR_3062 :{SMALLFONT}{BLACK}Standard achtbaanspoor
-STR_3063 :{SMALLFONT}{BLACK}Watersegment (spoor onder water)
+STR_3063 :{SMALLFONT}{BLACK}Watergedeelte (spoor onder water)
STR_3064 :Eenvoudige parken
STR_3065 :Uitdagende parken
STR_3066 :Moeilijke parken
STR_3067 :{OPENQUOTES}Echte{ENDQUOTES} parken
STR_3068 :Andere parken
-STR_3069 :Bovensegment
+STR_3069 :Bovengedeelte
STR_3070 :Van helling naar vlak
STR_3071 :{WINDOW_COLOUR_2}Dezelfde prijs in het hele park
STR_3072 :{SMALLFONT}{BLACK}Selecteer of deze prijs in het hele park moet worden gehanteerd
@@ -3089,7 +3089,7 @@ STR_3087 :Sneeuw/ijs-ingang
STR_3088 :Pagode-ingang
STR_3089 :Ruimte-ingang
STR_3090 :{SMALLFONT}{BLACK}Selecteer de stijl van de ingang, uitgang, en het station
-STR_3091 :Je mag dit segment niet verwijderen!
+STR_3091 :Je mag dit gedeelte niet verwijderen!
STR_3092 :Je mag het station van deze attractie niet verplaatsen of veranderen!
STR_3093 :{WINDOW_COLOUR_2}Favoriet: {BLACK}{STRINGID}
STR_3094 :n.v.t.
@@ -3118,8 +3118,8 @@ STR_3116 :{SMALLFONT}{BLACK}Baanontwerp opslaan (Niet mogelijk voordat de att
STR_3117 :{BLACK}Monteur wordt opgeroepen...
STR_3118 :{BLACK}{STRINGID} gaat naar deze attractie
STR_3119 :{BLACK}{STRINGID} is bezig deze attractie te repareren
-STR_3120 :{SMALLFONT}{BLACK}Vind de dichtstbijzijnde monteur, of de monteur die de attractie aan het repareren is
-STR_3121 :Kan geen monteur vinden, of alle monteurs in de buurt zijn bezig
+STR_3120 :{SMALLFONT}{BLACK}Vind de dichtstbijzijnde monteur of de monteur die de attractie aan het repareren is
+STR_3121 :Kan geen monteur vinden of alle monteurs in de buurt zijn bezig
STR_3122 :{WINDOW_COLOUR_2}Favoriet van: {BLACK}{COMMA16} bezoeker
STR_3123 :{WINDOW_COLOUR_2}Favoriet van: {BLACK}{COMMA16} bezoekers
STR_3124 :{STRINGID} defect
@@ -3211,10 +3211,10 @@ STR_3209 :Terug naar de vorige stap:
STR_3210 :Verder naar de volgende stap:
STR_3211 :{WINDOW_COLOUR_2}Kaartgrootte:
STR_3212 :{POP16}{COMMA16} x {PUSH16}{COMMA16}
-STR_3213 :Kan kaart niet verder verkleinen
-STR_3214 :Kan kaart niet verder vergroten
+STR_3213 :Kan de kaart niet verder verkleinen
+STR_3214 :Kan de kaart niet verder vergroten
STR_3215 :Te dicht bij de rand van de kaart
-STR_3216 :{SMALLFONT}{BLACK}Selecteer parkland, etc.
+STR_3216 :{SMALLFONT}{BLACK}Selecteer parkland etc.
STR_3217 :Eigendom van het park
STR_3218 :Bouwrechten voor het park
STR_3219 :Te koop
@@ -3310,11 +3310,11 @@ STR_3308 :{WINDOW_COLOUR_2}Spanningswaarde:
STR_3309 :{WINDOW_COLOUR_2}{COMMA16}
STR_3310 :{WINDOW_COLOUR_2}{LENGTH}
STR_3311 :{WINDOW_COLOUR_2}{COMMA2DP32}
-STR_3312 :{WINDOW_COLOUR_2}Attracties met monumentenstatus:
+STR_3312 :{WINDOW_COLOUR_2}Attracties met een monumentenstatus:
STR_3313 :Scenarionaam
STR_3314 :Voer een naam in voor het scenario:
STR_3315 :Details park/scenario
-STR_3316 :Geef een beschrijving voor dit scenario:
+STR_3316 :Geef een beschrijving van dit scenario:
STR_3317 :Nog geen details
STR_3318 :{SMALLFONT}{BLACK}Selecteer in welke groep dit scenario moet verschijnen
STR_3319 :{WINDOW_COLOUR_2}Scenariogroep:
@@ -3329,9 +3329,9 @@ STR_3327 :Startpositie voor bezoekers niet aangegeven
STR_3328 :Kan niet verder naar volgende stap...
STR_3329 :Parkingang nog niet gebouwd
STR_3330 :Park moet land bezitten
-STR_3331 :Pad van de parkingang naar de rand van de kaart is incompleet of te complex - het pad mag maar één blok breed zijn en moet zo min mogelijk kruisingen en bochten bevatten
+STR_3331 :Pad van de parkingang naar de rand van de kaart is incompleet of te complex; het pad mag maar één blok breed zijn en moet zo min mogelijk kruisingen en bochten bevatten
STR_3332 :Parkingang staan achterstevoren of heeft geen pad naar de rand van de kaart
-STR_3333 :Niet-standaard objecten meeleveren in opgeslagen spellen
+STR_3333 :Plug-inobjecten meeleveren in opgeslagen spellen
STR_3334 :{SMALLFONT}{BLACK}Selecteer of toegevoegde (niet-standaard) objecten in opgeslagen spellen en scenario's moeten worden meegeleverd, zodat ze geopend kunnen worden door iemand die deze objecten nog niet heeft
STR_3335 :Achtbaanontwerper - Attractietypes en -voertuigen selecteren
STR_3336 :Baanontwerpbeheer - Attractietype selecteren
@@ -3345,7 +3345,7 @@ STR_3343 :Opgeslagen spel omzetten naar scenario
STR_3344 :Achtbaanontwerper
STR_3345 :Baanontwerpbeheer
STR_3346 :Kan baanontwerp niet opslaan
-STR_3347 :Attractie is te groot, bevat teveel elementen, of het decor is te ver verspreid
+STR_3347 :Attractie is te groot, bevat teveel elementen of het decor is te ver verspreid
STR_3348 :Naam wijzigen
STR_3349 :Verwijderen
STR_3350 :Naam baanontwerp
@@ -3359,7 +3359,7 @@ STR_3357 :{WINDOW_COLOUR_2}Weet je zeker dat je {STRINGID} permanent wilt ver
STR_3358 :Kan het baanontwerp niet verwijderen...
STR_3359 :{BLACK}Geen baanontwerpen van dit type
STR_3360 :Waarschuwing!
-STR_3361 :Te veel baanontwerpen van dit type - sommige staan niet in de lijst
+STR_3361 :Te veel baanontwerpen van dit type; sommige staan niet in de lijst
STR_3362 :Mixing via softwarebuffer forceren
STR_3363 :{SMALLFONT}{BLACK}Selecteer deze optie om de prestaties te verbeteren als het spel vertraagt bij het afspelen van geluiden of als er ruis hoorbaar is
STR_3364 :Meer opties
@@ -3382,7 +3382,7 @@ STR_3380 :Kan dit baanontwerp niet installeren...
STR_3381 :Bestand is niet compatible of bevat ongeldige gegevens
STR_3382 :Kopiëren van bestand mislukt
STR_3383 :Selecteer nieuwe naam voor dit baanontwerp
-STR_3384 :Er bestaat al een baanontwerp met deze naam - verzin een andere naam voor dit ontwerp:
+STR_3384 :Er bestaat al een baanontwerp met deze naam; verzin een andere naam voor dit ontwerp:
STR_3385 :Tutorial voor beginners
STR_3386 :Toturial voor eigen ontwerpen
STR_3387 :Toturial voor achtbanen bouwen
@@ -3406,8 +3406,8 @@ STR_3404 :{SMALLFONT}{BLACK}Oh, juist - het park is nog gesloten! Laten we on
STR_3405 :{SMALLFONT}{BLACK}Terwijl we op onze eerste bezoekers wachten kunnen we wat decorstukken neerzetten...
STR_3406 :{SMALLFONT}{BLACK}Dit is ons lege park. We gaan een simpele zelfontworpen attractie bouwen...
STR_3407 :{SMALLFONT}{BLACK}Ten eerste hebben we een startpositie nodig...
-STR_3408 :{SMALLFONT}{BLACK}Het stuk baan dat we net gebouwd hebben is een 'station', en zorgt ervoor dat bezoekers in en uit kunnen stappen...
-STR_3409 :{SMALLFONT}{BLACK}We verlengen het perron een beetje door nog wat stationssegmenten aan te leggen...
+STR_3408 :{SMALLFONT}{BLACK}Het stuk baan dat we net gebouwd hebben is een 'station' en zorgt ervoor dat bezoekers in en uit kunnen stappen...
+STR_3409 :{SMALLFONT}{BLACK}We verlengen het perron een beetje door nog wat stationsgedeeltes aan te leggen...
STR_3410 :{SMALLFONT}{BLACK}De knopjes aan de bovenkant van het bouwvenster laten je tusen verschillende soorten baanstukjes kiezen...
STR_3411 :{SMALLFONT}{BLACK}We gaan een bocht naar links bouwen...
STR_3412 :{SMALLFONT}{BLACK}De bocht is nog niet gebouwd, maar het witte spookplaatje laat zien waar het gebouwd gaat worden. Als je op de grote knop klikt wordt het gebouwd...
@@ -3416,7 +3416,7 @@ STR_3414 :{SMALLFONT}{BLACK}De baan is af, we kunnen nu de ingang en uitgang
STR_3415 :{SMALLFONT}{BLACK}Laten we testen of onze attractie werkt...
STR_3416 :{SMALLFONT}{BLACK}Terwijl de attractie wordt getest kunnen we een wachtrij en uitgangspad bouwen...
STR_3417 :{SMALLFONT}{BLACK}Goed - laten we het park en onze attractie openen...
-STR_3418 :{SMALLFONT}{BLACK}Onze nieuwe attractie is niet heel erg spannend - misschien moeten we wat decor toevoegen?
+STR_3418 :{SMALLFONT}{BLACK}Onze nieuwe attractie is niet heel erg spannend; misschien moeten we wat decor toevoegen?
STR_3419 :{SMALLFONT}{BLACK}Om decor te bouwen boven ander decor (of midden in de lucht) hou je de SHIFT-toets ingedrukt en beweeg je de muis om de hoogte te bepalen...
STR_3420 :{SMALLFONT}{BLACK}Sommige types decor kunnen opnieuw geverfd worden nadat ze zijn gebouwd...
STR_3421 :{SMALLFONT}{BLACK}Laten we wat muziek draaien in onze attractie...
@@ -3425,15 +3425,15 @@ STR_3423 :{SMALLFONT}{BLACK}Er zijn veel kant-en-klare achtbanen, maar wij ga
STR_3424 :{SMALLFONT}{BLACK}Zo, het station is af. Nu hebben we een liftheuvel nodig...
STR_3425 :{SMALLFONT}{BLACK}Achtbaankarretjes zijn niet aangedreven, dus is een 'kettinglift' nodig om ze eerst een heuvel op te trekken...
STR_3426 :{SMALLFONT}{BLACK}Goed, de liftheuvel is klaar - nu de eerste afdaling...
-STR_3427 :{SMALLFONT}{BLACK}Die bochten zijn een slecht idee - de passagiers zullen naar de zijkanten gesmeten worden wanneer de trein er doorheen raast...
-STR_3428 :{SMALLFONT}{BLACK}De bochten een banking (schuinleggen) geven zal de rit prettiger maken - de passagiers zullen in hun stoelen geduwd worden in plaats van naar de zijkanten...
-STR_3429 :{SMALLFONT}{BLACK}Dit gaat niet werken! Kijk naar de hoogtemarkeringen - De tweede heuvel is hoger dan de liftheuvel...
+STR_3427 :{SMALLFONT}{BLACK}Die bochten zijn een slecht idee; de passagiers zullen naar de zijkanten geslingerd worden door de G-kracht wanneer de trein er doorheen raast...
+STR_3428 :{SMALLFONT}{BLACK}De bochten een banking geven (schuinleggen) zal de rit prettiger maken, aangezien de passagiers in hun stoelen geduwd zullen worden in plaats van naar de zijkanten...
+STR_3429 :{SMALLFONT}{BLACK}Dit gaat niet werken! Kijk naar de hoogtemarkeringen: de tweede heuvel is hoger dan de liftheuvel...
STR_3430 :{SMALLFONT}{BLACK}Om ervoor te zorgen dat de trein terug naar het station komt, moet elke heuvel iets lager zijn dan de heuvel daarvoor...
STR_3431 :{SMALLFONT}{BLACK}Dat ziet er beter uit! Onze trein zou het nu moeten halen! Laten we wat meer bochtige stukjes toevoegen...
STR_3432 :{SMALLFONT}{BLACK}We moeten de trein afremmen voordat we de laatste bocht en het station inkomen, dus laten we wat remmen toevoegen...
STR_3433 :{SMALLFONT}{BLACK}En tenslotte voegen we 'blokremmen' toe. Die zorgen ervoor dat twee treinen tegelijk (en veilig) op de baan kunnen zitten...
STR_3434 :{SMALLFONT}{BLACK}Laten we kijken of onze achtbaan werkt!
-STR_3435 :{SMALLFONT}{BLACK}Fantastisch - hij werkt! Laten we wat voetpaden aanleggen zodat bezoekers bij onze nieuwe achtbaan kunnen komen...
+STR_3435 :{SMALLFONT}{BLACK}Fantastisch, hij werkt! Laten we wat voetpaden aanleggen, zodat bezoekers bij onze nieuwe achtbaan kunnen komen...
STR_3436 :{SMALLFONT}{BLACK}Terwijl we wachten op onze eerste bezoekers, kunnen we onze achtbaan een beetje aanpassen...
STR_3437 :{SMALLFONT}{BLACK}Grote gebieden met decor van het landschap verwijderen
STR_3438 :Kan hier niet al het decor verwijderen...
diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt
index 1cfa8ed27c..ac2dad12af 100644
--- a/data/language/english_uk.txt
+++ b/data/language/english_uk.txt
@@ -2692,13 +2692,13 @@ STR_2686 :???
STR_2687 :???
STR_2688 :???
STR_2689 :???
-STR_2690 :???
-STR_2691 :???
-STR_2692 :???
-STR_2693 :???
-STR_2694 :???
-STR_2695 :???
-STR_2696 :???
+STR_2690 :Map Generation
+STR_2691 :{WINDOW_COLOUR_2}Base height:
+STR_2692 :{WINDOW_COLOUR_2}Water level:
+STR_2693 :{WINDOW_COLOUR_2}Terrain:
+STR_2694 :Generate
+STR_2695 :Random terrain
+STR_2696 :Place trees
STR_2697 :???
STR_2698 :???
STR_2699 :???
@@ -2722,30 +2722,30 @@ 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_2736 :???
-STR_2737 :???
-STR_2738 :???
-STR_2739 :???
-STR_2740 :???
-STR_2741 :???
-STR_2742 :???
-STR_2743 :???
+STR_2720 :{UINT16}sec
+STR_2721 :{UINT16}secs
+STR_2722 :{UINT16}min:{UINT16}sec
+STR_2723 :{UINT16}min:{UINT16}secs
+STR_2724 :{UINT16}mins:{UINT16}sec
+STR_2725 :{UINT16}mins:{UINT16}secs
+STR_2726 :{UINT16}min
+STR_2727 :{UINT16}mins
+STR_2728 :{UINT16}hour:{UINT16}min
+STR_2729 :{UINT16}hour:{UINT16}mins
+STR_2730 :{UINT16}hours:{UINT16}min
+STR_2731 :{UINT16}hours:{UINT16}mins
+STR_2732 :{COMMA16}ft
+STR_2733 :{COMMA16}m
+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_2739 :None
+STR_2740 :RollerCoaster Tycoon 1
+STR_2741 :RollerCoaster Tycoon 2
+STR_2742 :css50.dat not found
+STR_2743 :Copy data\css17.dat from your RCT1 installation to data\css50.dat in your RCT2 installation.
STR_2744 :[
STR_2745 :\
STR_2746 :]
diff --git a/data/language/english_us.txt b/data/language/english_us.txt
index b3e187b88b..8da74f757e 100644
--- a/data/language/english_us.txt
+++ b/data/language/english_us.txt
@@ -2526,6 +2526,7 @@ STR_2521 :Show staff list
STR_2522 :Show recent messages
STR_2523 :Show map
STR_2524 :Screenshot
+
STR_2525 :???
STR_2526 :???
STR_2527 :???
@@ -2691,13 +2692,13 @@ STR_2686 :???
STR_2687 :???
STR_2688 :???
STR_2689 :???
-STR_2690 :???
-STR_2691 :???
-STR_2692 :???
-STR_2693 :???
-STR_2694 :???
-STR_2695 :???
-STR_2696 :???
+STR_2690 :Map Generation
+STR_2691 :{WINDOW_COLOUR_2}Base height:
+STR_2692 :{WINDOW_COLOUR_2}Water level:
+STR_2693 :{WINDOW_COLOUR_2}Terrain:
+STR_2694 :Generate
+STR_2695 :Random terrain
+STR_2696 :Place trees
STR_2697 :???
STR_2698 :???
STR_2699 :???
@@ -2721,47 +2722,57 @@ 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_2736 :???
-STR_2737 :???
-STR_2738 :???
-STR_2739 :???
-STR_2740 :???
-STR_2741 :???
-STR_2742 :???
-STR_2743 :???
+STR_2720 :{UINT16}sec
+STR_2721 :{UINT16}secs
+STR_2722 :{UINT16}min:{UINT16}sec
+STR_2723 :{UINT16}min:{UINT16}secs
+STR_2724 :{UINT16}mins:{UINT16}sec
+STR_2725 :{UINT16}mins:{UINT16}secs
+STR_2726 :{UINT16}min
+STR_2727 :{UINT16}mins
+STR_2728 :{UINT16}hour:{UINT16}min
+STR_2729 :{UINT16}hour:{UINT16}mins
+STR_2730 :{UINT16}hours:{UINT16}min
+STR_2731 :{UINT16}hours:{UINT16}mins
+STR_2732 :{COMMA16}ft
+STR_2733 :{COMMA16}m
+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_2739 :None
+STR_2740 :RollerCoaster Tycoon 1
+STR_2741 :RollerCoaster Tycoon 2
+STR_2742 :css50.dat not found
+STR_2743 :Copy data\css17.dat from your RCT1 installation to data\css50.dat in your RCT2 installation.
STR_2744 :[
STR_2745 :\
STR_2746 :]
STR_2747 :{ENDQUOTES}
STR_2748 :Bar
STR_2749 :???
-STR_2750 :???
-STR_2751 :???
-STR_2752 :???
-STR_2753 :???
-STR_2754 :???
-STR_2755 :???
-STR_2756 :???
-STR_2757 :???
-STR_2758 :???
-STR_2759 :???
+
+
+
+
+
+
+
+
+
+
# New strings used in the cheats window previously these were ???
+STR_2750 :Move all items to top
+STR_2751 :Move all items to bottom
+STR_2752 :Clear grass
+STR_2753 :Mowed grass
+STR_2754 :Water plants
+STR_2755 :Fix vandalism
+STR_2756 :Remove litter
+STR_2757 :Force Sun
+STR_2758 :Force Thunder
+STR_2759 :Zero Clearance
STR_2760 :+5K Money
STR_2761 :Pay For Entrance
STR_2762 :Pay For Rides
@@ -2781,9 +2792,11 @@ STR_2775 :Fullscreen (desktop)
STR_2776 :Language
STR_2777 :{MOVE_X}{SMALLFONT}{STRING}
STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING}
+STR_2779 :Viewport #{COMMA16}
+STR_2780 :Extra viewport
# End of new strings
-STR_2779 :???
-STR_2780 :???
+
+
STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID}{STRINGID}
STR_2782 :SHIFT +
STR_2783 :CTRL +
diff --git a/data/language/polish.txt b/data/language/polish.txt
index 34260d3a26..f88b5e5dbb 100644
--- a/data/language/polish.txt
+++ b/data/language/polish.txt
@@ -983,28 +983,30 @@ STR_0973 :OK
STR_0974 :Atrakcje
STR_0975 :Sklepy
STR_0976 :Toalety i Punkty Informacyjne
-# ------------------------------------------ Polish end
-STR_0977 :New Transport Rides
-STR_0978 :New Gentle Rides
-STR_0979 :New Roller Coasters
-STR_0980 :New Thrill Rides
-STR_0981 :New Water Rides
-STR_0982 :New Shops & Stalls
-STR_0983 :Research & Development
+STR_0977 :Nowa atrakcja transportowa
+STR_0978 :Nowa łagodna atrakcja
+STR_0979 :Nowa kolejka górska
+STR_0980 :Nowa intensywna atrakcja
+STR_0981 :Nowa wodna atrakcja
+STR_0982 :Nowy sklep lub stoisko
+STR_0983 :Badania i rozwój
STR_0984 :{WINDOW_COLOUR_2}{UP}{BLACK} {CURRENCY2DP}
STR_0985 :{WINDOW_COLOUR_2}{DOWN}{BLACK} {CURRENCY2DP}
STR_0986 :{BLACK}{CURRENCY2DP}
+# ------------------------------------------ Polish end
STR_0987 :Too many rides/attractions
STR_0988 :Can't create new ride/attraction...
STR_0989 :{STRINGID}
STR_0990 :{SMALLFONT}{BLACK}Construction
STR_0991 :Station platform
-STR_0992 :{SMALLFONT}{BLACK}Demolish entire ride/attraction
-STR_0993 :Demolish ride/attraction
-STR_0994 :Demolish
-STR_0995 :{WINDOW_COLOUR_1}Are you sure you want to completely demolish {STRINGID}?
-STR_0996 :Overall view
-STR_0997 :{SMALLFONT}{BLACK}View selection
+# ------------------------------------------ Polish start
+STR_0992 :{SMALLFONT}{BLACK}Zniszcz całą atrakcję
+STR_0993 :Zniszcz atrakcję
+STR_0994 :Zniszcz
+STR_0995 :{WINDOW_COLOUR_1}Jesteś pewien, że chcesz zniszczyć {STRINGID}?
+STR_0996 :Widok ogólny
+STR_0997 :{SMALLFONT}{BLACK}Wybór widoku
+# ------------------------------------------ Polish end
STR_0998 :No more stations allowed on this ride
STR_0999 :Requires a station platform
STR_1000 :Track is not a complete circuit
@@ -1015,13 +1017,15 @@ STR_1004 :Can't close {POP16}{POP16}{POP16}{STRINGID}...
STR_1005 :Can't start construction on {POP16}{POP16}{POP16}{STRINGID}...
STR_1006 :Must be closed first
STR_1007 :Unable to create enough vehicles
-STR_1008 :{SMALLFONT}{BLACK}Open, close, or test ride/attraction
-STR_1009 :{SMALLFONT}{BLACK}Open or close all rides/attractions
-STR_1010 :{SMALLFONT}{BLACK}Open or close park
-STR_1011 :Close all
-STR_1012 :Open all
-STR_1013 :Close park
-STR_1014 :Open park
+# ------------------------------------------ Polish start
+STR_1008 :{SMALLFONT}{BLACK}Otwórz, zamknij lub testuj atrakcję
+STR_1009 :{SMALLFONT}{BLACK}Otwórz / zamknij wszystkie atrakcje
+STR_1010 :{SMALLFONT}{BLACK}Otwórz / zamknij park
+STR_1011 :Zamknij wszystkie
+STR_1012 :Otwórz wszystkie
+STR_1013 :Zamknij park
+STR_1014 :Otwórz park
+# ------------------------------------------ Polish end
STR_1015 :Unable to operate with more than one station platform in this mode
STR_1016 :Unable to operate with less than two stations in this mode
STR_1017 :Can't change operating mode...
@@ -1043,27 +1047,29 @@ STR_1032 :Can only build this on water!
STR_1033 :Can only build this above ground!
STR_1034 :Can only build this on land!
STR_1035 :Local authority won't allow construction above tree-height!
-STR_1036 :Load Game
-STR_1037 :Load Landscape
-STR_1038 :Convert saved game to scenario
-STR_1039 :Install new track design
-STR_1040 :Save Game
-STR_1041 :Save Scenario
-STR_1042 :Save Landscape
-STR_1043 :RollerCoaster Tycoon 2 Saved Game
-STR_1044 :RollerCoaster Tycoon 2 Scenario File
-STR_1045 :RollerCoaster Tycoon 2 Landscape File
-STR_1046 :RollerCoaster Tycoon 2 Track Design File
-STR_1047 :Game save failed!
-STR_1048 :Scenario save failed!
-STR_1049 :Landscape save failed!
-STR_1050 :Failed to load...{NEWLINE}File contains invalid data!
-STR_1051 :Invisible Supports
-STR_1052 :Invisible People
-STR_1053 :{SMALLFONT}{BLACK}Rides/attractions in park
-STR_1054 :{SMALLFONT}{BLACK}Name ride/attraction
-STR_1055 :{SMALLFONT}{BLACK}Name person
-STR_1056 :{SMALLFONT}{BLACK}Name staff member
+# ------------------------------------------ Polish start
+STR_1036 :Wczytaj grę
+STR_1037 :Wczytaj krajobraz
+STR_1038 :Przekonwertuj zapis gry do scenariusza
+STR_1039 :Dodaj nowy projekt trasy
+STR_1040 :Zapisz grę
+STR_1041 :Zapisz scenariusz
+STR_1042 :Zapisz krajobraz
+STR_1043 :Zapis gry RollerCoaster Tycoon 2
+STR_1044 :Scenariusz RollerCoaster Tycoon 2
+STR_1045 :Krajobrazu RollerCoaster Tycoon 2
+STR_1046 :Projekt trasy RollerCoaster Tycoon 2
+STR_1047 :Zapis gry nieudany!
+STR_1048 :Zapis scenariusza nieudany!
+STR_1049 :Zapis krajobrazu nieudany!
+STR_1050 :Nie udało się wczytać...{NEWLINE}Plik zawiera błędne dane!
+STR_1051 :Przezroczyste wsporniki
+STR_1052 :Przezroczyści ludzie
+STR_1053 :{SMALLFONT}{BLACK}Atrakcje w parku
+STR_1054 :{SMALLFONT}{BLACK}Nazwij atrakcję
+STR_1055 :{SMALLFONT}{BLACK}Nazwij osobę
+STR_1056 :{SMALLFONT}{BLACK}Nazwij pracownika
+# ------------------------------------------ Polish end
STR_1057 :Ride/attraction name
STR_1058 :Enter new name for this ride/attraction:
STR_1059 :Can't rename ride/attraction...
@@ -1155,25 +1161,25 @@ STR_1144 :Can't build/move entrance for this ride/attraction...
STR_1145 :Can't build/move exit for this ride/attraction...
STR_1146 :Entrance not yet built
STR_1147 :Exit not yet built
-STR_1148 :Quarter load
-STR_1149 :Half load
-STR_1150 :Three-quarter load
-STR_1151 :Full load
-STR_1152 :Any load
-STR_1153 :Height Marks on Ride Tracks
-STR_1154 :Height Marks on Land
-STR_1155 :Height Marks on Paths
+# ------------------------------------------ Polish start
+STR_1148 :25% zapełnienia
+STR_1149 :50% zapełnienia
+STR_1150 :70% zapełnienia
+STR_1151 :100% zapełnienia
+STR_1152 :dowolne zapełnienie
+STR_1153 :Znaczniki wysokości torów
+STR_1154 :Znaczniki wysokości terenu
+STR_1155 :Znaczniki wysokości chodników
STR_1156 :{MOVE_X}{SMALLFONT}{STRINGID}
STR_1157 :{TICK}{MOVE_X}{SMALLFONT}{STRINGID}
-STR_1158 :Can't remove this...
-STR_1159 :{SMALLFONT}{BLACK}Place scenery, gardens, and other accessories
-STR_1160 :{SMALLFONT}{BLACK}Create/adjust lakes & water
-STR_1161 :Can't position this here...
+STR_1158 :Nie można tego usunąć...
+STR_1159 :{SMALLFONT}{BLACK}Buduj scenerię, ogrody i inne akcesoria
+STR_1160 :{SMALLFONT}{BLACK}Twórz i zmieniaj obszary wodne
+STR_1161 :Nie można tego tu umieścić...
STR_1162 :{OUTLINE}{TOPAZ}{STRINGID}
-STR_1163 :{STRINGID}{NEWLINE}(Right-Click to Modify)
-STR_1164 :{STRINGID}{NEWLINE}(Right-Click to Remove)
+STR_1163 :{STRINGID}{NEWLINE}(Kliknij PPM by zmodyfikować)
+STR_1164 :{STRINGID}{NEWLINE}(Kliknij PPM by usunąć)
STR_1165 :{STRINGID} - {STRINGID} {COMMA16}
-# ------------------------------------------ Polish start
STR_1166 :Nie można tu obniżyć poziomu wody...
STR_1167 :Nie można tu podnieść poziomu wody...
STR_1168 :Opcje
@@ -1214,21 +1220,21 @@ STR_1202 :1 osoba w kolejce
STR_1203 :{COMMA16} osób w kolejce
STR_1204 :{COMMA16} minuta czekania
STR_1205 :{COMMA16} minut czekania
-# ------------------------------------------ Polish end
-STR_1206 :{WINDOW_COLOUR_2}Wait for:
-STR_1207 :{WINDOW_COLOUR_2}Leave if another train arrives at station
-STR_1208 :{WINDOW_COLOUR_2}Leave if another boat arrives at station
-STR_1209 :{SMALLFONT}{BLACK}Select whether should wait for passengers before departing
-STR_1210 :{SMALLFONT}{BLACK}Select whether should leave if another vehicle arrives at the same station
-STR_1211 :{WINDOW_COLOUR_2}Minimum waiting time:
-STR_1212 :{WINDOW_COLOUR_2}Maximum waiting time:
-STR_1213 :{SMALLFONT}{BLACK}Select minimum length of time to wait before departing
-STR_1214 :{SMALLFONT}{BLACK}Select maximum length of time to wait before departing
-STR_1215 :{WINDOW_COLOUR_2}Synchronize with adjacent stations
-STR_1216 :{SMALLFONT}{BLACK}Select whether to synchronize departure with all adjacent stations (for 'racing')
-STR_1217 :{COMMA16} seconds
+STR_1206 :{WINDOW_COLOUR_2}Czekaj na:
+STR_1207 :{WINDOW_COLOUR_2}Wyrusz, gdy inna kolejka trafi na tą samą stację
+STR_1208 :{WINDOW_COLOUR_2}Wyrusz, gdy inna łódka trafi na tą samą stację
+STR_1209 :{SMALLFONT}{BLACK}Ustal, czy pojazdy powinny czekać na pasażerów przed wyruszeniem ze stacji
+STR_1210 :{SMALLFONT}{BLACK}Ustal, czy pojazdy powinny wyruszać ze stacj gdy tylko inny pojazd dotrze do tej samej stacji
+STR_1211 :{WINDOW_COLOUR_2}Minimalny czas oczekiwania:
+STR_1212 :{WINDOW_COLOUR_2}Maksymalny czas oczekiwania:
+STR_1213 :{SMALLFONT}{BLACK}Wybierz minimalny czas oczekiwania na stacji przed wyruszeniem
+STR_1214 :{SMALLFONT}{BLACK}Wybierz maksymalny czas oczekiwania na stacji przed wyruszeniem
+STR_1215 :{WINDOW_COLOUR_2}Synchronizuj z sąsiadującymi stacjami
+STR_1216 :{SMALLFONT}{BLACK}Wybierz, czy kolejki mają synchronizować start z innymi stacjami (dla 'wyścigów')
+STR_1217 :{COMMA16} sekund
STR_1218 :{BLACK}{SMALLUP}
STR_1219 :{BLACK}{SMALLDOWN}
+# ------------------------------------------ Polish end
STR_1220 :Exit only
STR_1221 :No entrance
STR_1222 :No exit
@@ -1666,20 +1672,22 @@ STR_1650 :{SMALLFONT}{OPENQUOTES}Wow! A new ride being built!{ENDQUOTES}
STR_1651 :{SMALLFONT}{OPENQUOTES}Nice ride! But not as good as the Phoenix...{ENDQUOTES}
STR_1652 :{SMALLFONT}{OPENQUOTES}I'm so excited - It's an Intamin ride!{ENDQUOTES}
STR_1653 :{SMALLFONT}{OPENQUOTES}...and here we are on {STRINGID}!{ENDQUOTES}
-STR_1654 :{WINDOW_COLOUR_2}Recent thoughts:
-STR_1655 :{SMALLFONT}{BLACK}Construct footpath on land
-STR_1656 :{SMALLFONT}{BLACK}Construct bridge or tunnel footpath
-STR_1657 :{WINDOW_COLOUR_2}Preferred ride
-STR_1658 :{WINDOW_COLOUR_2}intensity: {BLACK}less than {COMMA16}
-STR_1659 :{WINDOW_COLOUR_2}intensity: {BLACK}between {COMMA16} and {COMMA16}
-STR_1660 :{WINDOW_COLOUR_2}intensity: {BLACK}more than {COMMA16}
-STR_1661 :{WINDOW_COLOUR_2}Nausea tolerance: {BLACK}{STRINGID}
-STR_1662 :{WINDOW_COLOUR_2}Happiness:
-STR_1663 :{WINDOW_COLOUR_2}Nausea:
-STR_1664 :{WINDOW_COLOUR_2}Energy:
-STR_1665 :{WINDOW_COLOUR_2}Hunger:
-STR_1666 :{WINDOW_COLOUR_2}Thirst:
-STR_1667 :{WINDOW_COLOUR_2}Bathroom:
+# ------------------------------------------ Polish start
+STR_1654 :{WINDOW_COLOUR_2}Ostatnie myśli:
+STR_1655 :{SMALLFONT}{BLACK}Buduj ścieżki na ziemi
+STR_1656 :{SMALLFONT}{BLACK}Buduj ścieżki w powietrzu lub pod ziemią
+STR_1657 :{WINDOW_COLOUR_2}Preferowana
+STR_1658 :{WINDOW_COLOUR_2}intensywność: {BLACK}poniżej {COMMA16}
+STR_1659 :{WINDOW_COLOUR_2}intensywność: {BLACK}między {COMMA16} a {COMMA16}
+STR_1660 :{WINDOW_COLOUR_2}intensywność: {BLACK}powyżej {COMMA16}
+STR_1661 :{WINDOW_COLOUR_2}Odporność na mdłości: {BLACK}{STRINGID}
+STR_1662 :{WINDOW_COLOUR_2}Szczęście:
+STR_1663 :{WINDOW_COLOUR_2}Mdłości:
+STR_1664 :{WINDOW_COLOUR_2}Energia:
+STR_1665 :{WINDOW_COLOUR_2}Głód:
+STR_1666 :{WINDOW_COLOUR_2}Pragnienie:
+STR_1667 :{WINDOW_COLOUR_2}Pęcherz:
+# ------------------------------------------ Polish end
STR_1668 :{WINDOW_COLOUR_2}Satisfaction: {BLACK}Unknown
STR_1669 :{WINDOW_COLOUR_2}Satisfaction: {BLACK}{COMMA16}%
STR_1670 :{WINDOW_COLOUR_2}Total customers: {BLACK}{COMMA32}
@@ -1840,48 +1848,51 @@ STR_1822 :{WINDOW_COLOUR_2}Guests thinking about {POP16}{STRINGID}
STR_1823 :{SMALLFONT}{BLACK}Show guests' thoughts about this ride/attraction
STR_1824 :{SMALLFONT}{BLACK}Show guests on this ride/attraction
STR_1825 :{SMALLFONT}{BLACK}Show guests queuing for this ride/attraction
-STR_1826 :Status
-STR_1827 :Popularity
-STR_1828 :Satisfaction
-STR_1829 :Profit
-STR_1830 :Queue length
-STR_1831 :Queue time
-STR_1832 :Reliability
-STR_1833 :Down-time
-STR_1834 :Guests favorite
-STR_1835 :Popularity: Unknown
-STR_1836 :Popularity: {COMMA16}%
-STR_1837 :Satisfaction: Unknown
-STR_1838 :Satisfaction: {COMMA16}%
-STR_1839 :Reliability: {COMMA16}%
-STR_1840 :Down-time: {COMMA16}%
-STR_1841 :Profit: {CURRENCY} per hour
-STR_1842 :Favorite of: {COMMA16} guest
-STR_1843 :Favorite of: {COMMA16} guests
-STR_1844 :{SMALLFONT}{BLACK}Select information type to show in ride/attraction list
+# ------------------------------------------ Polish start
+STR_1826 :Stan
+STR_1827 :Popularność
+STR_1828 :Satysfakcja
+STR_1829 :Zysk
+STR_1830 :Długość kolejki
+STR_1831 :Czas w kolejce
+STR_1832 :Niezawodność
+STR_1833 :Przestoje
+STR_1834 :Ulubieniec gości
+STR_1835 :Popularność: Nieznana
+STR_1836 :Popularność: {COMMA16}%
+STR_1837 :Satysfakcja: Nieznana
+STR_1838 :Satysfakcja: {COMMA16}%
+STR_1839 :Niezawodność: {COMMA16}%
+STR_1840 :Przestoje w pracy: {COMMA16}%
+STR_1841 :Zysk: {CURRENCY} per hour
+STR_1842 :Ulubiony dla: {COMMA16} gościa
+STR_1843 :Ulubiony dla: {COMMA16} gości
+STR_1844 :{SMALLFONT}{BLACK}Wybierz rodzaj informacji do pokazania
STR_1845 :{MONTHYEAR}
-STR_1846 :{COMMA16} guests
-STR_1847 :{INLINE_SPRITE}{11}{20}{00}{00}{COMMA16} guests
-STR_1848 :{INLINE_SPRITE}{10}{20}{00}{00}{COMMA16} guests
-STR_1849 :{WINDOW_COLOUR_2}Play music
-STR_1850 :{SMALLFONT}{BLACK}Select whether music should be played for this ride
-STR_1851 :{WINDOW_COLOUR_2}Running cost: {BLACK}{CURRENCY2DP} per hour
-STR_1852 :{WINDOW_COLOUR_2}Running cost: {BLACK}Unknown
-STR_1853 :{WINDOW_COLOUR_2}Built: {BLACK}This Year
-STR_1854 :{WINDOW_COLOUR_2}Built: {BLACK}Last Year
-STR_1855 :{WINDOW_COLOUR_2}Built: {BLACK}{COMMA16} Years Ago
-STR_1856 :{WINDOW_COLOUR_2}Profit per item sold: {BLACK}{CURRENCY2DP}
-STR_1857 :{WINDOW_COLOUR_2}Loss per item sold: {BLACK}{CURRENCY2DP}
-STR_1858 :{WINDOW_COLOUR_2}Cost: {BLACK}{CURRENCY} per month
-STR_1859 :Handymen
-STR_1860 :Mechanics
-STR_1861 :Security Guards
-STR_1862 :Entertainers
-STR_1863 :Handyman
-STR_1864 :Mechanic
-STR_1865 :Security Guard
-STR_1866 :Entertainer
+STR_1846 :{COMMA16} gości
+STR_1847 :{INLINE_SPRITE}{11}{20}{00}{00}{COMMA16} gości
+STR_1848 :{INLINE_SPRITE}{10}{20}{00}{00}{COMMA16} gości
+STR_1849 :{WINDOW_COLOUR_2}Graj muzykę
+STR_1850 :{SMALLFONT}{BLACK}Wybierz, czy w tej atrakcji może grać muzyka
+STR_1851 :{WINDOW_COLOUR_2}Koszty utrzymania: {BLACK}{CURRENCY2DP} na godzinę
+STR_1852 :{WINDOW_COLOUR_2}Koszty utrzymania: {BLACK}Nieznane
+STR_1853 :{WINDOW_COLOUR_2}Zbudowany: {BLACK}W tym roku
+STR_1854 :{WINDOW_COLOUR_2}Zbudowany: {BLACK}W zeszłym roku
+STR_1855 :{WINDOW_COLOUR_2}Zbudowany: {BLACK}{COMMA16} lat temu
+STR_1856 :{WINDOW_COLOUR_2}Zysk na sztuce: {BLACK}{CURRENCY2DP}
+STR_1857 :{WINDOW_COLOUR_2}Strata na sztuce: {BLACK}{CURRENCY2DP}
+# could be "pensja" but I'm not sure if it's used outside of staff window
+STR_1858 :{WINDOW_COLOUR_2}Koszt: {BLACK}{CURRENCY} miesięcznie
+STR_1859 :dozorcy
+STR_1860 :mechanicy
+STR_1861 :strażnicy
+STR_1862 :klauni
+STR_1863 :dozorca
+STR_1864 :mechanik
+STR_1865 :strażnik
+STR_1866 :klaun
STR_1867 :{BLACK}{COMMA16} {STRINGID}
+# ------------------------------------------ Polish end
STR_1868 :Can't change number of rotations...
STR_1869 :{WINDOW_COLOUR_2}Number of rotations:
STR_1870 :{SMALLFONT}{BLACK}Number of complete rotations
@@ -2273,7 +2284,7 @@ STR_2252 :Można budować tylko w poprzek chodników!
STR_2253 :Transport
STR_2254 :Łagodne atrakcje
STR_2255 :Kolejki górskie
-STR_2256 :Mocne atrakcje
+STR_2256 :Intensywne atrakcje
STR_2257 :Wodne atrakcje
STR_2258 :Sklepy i stoiska
STR_2259 :Scenerie i dekoracje
@@ -2298,7 +2309,7 @@ STR_2277 :Nieznany
STR_2278 :Transport
STR_2279 :Łagodne atrakcje
STR_2280 :Kolejki górskie
-STR_2281 :Mocne atrakcje
+STR_2281 :Intensywne atrakcje
STR_2282 :Wodne atrakcje
STR_2283 :Sklepy i stoiska
STR_2284 :Scenerie i dekoracje
@@ -2309,20 +2320,22 @@ STR_2288 :Nieznane
STR_2289 :{STRINGID} {STRINGID}
STR_2290 :{SMALLFONT}{BLACK}{STRINGID} {STRINGID}
STR_2291 :Wybierz scenariusz dla nowej gry
+STR_2292 :{WINDOW_COLOUR_2}Odwiedzone atrakcje:
+STR_2293 :{BLACK} Nic
# ------------------------------------------ Polish end
-STR_2292 :{WINDOW_COLOUR_2}Rides been on:
-STR_2293 :{BLACK} Nothing
STR_2294 :{SMALLFONT}{BLACK}Change base land style
STR_2295 :{SMALLFONT}{BLACK}Change vertical edges of land
-STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} paid to enter park
-STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} ride
-STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} rides
-STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} item of food
-STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} items of food
-STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} drink
-STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} drinks
-STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} souvenir
-STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} souvenirs
+# ------------------------------------------ Polish start
+STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na wejście do parku
+STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} atrakcji
+STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} atrakcjach
+STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} posiłku
+STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} posiłkach
+STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} napoju
+STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} napojach
+STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} pamiątce
+STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} pamiątkach
+# ------------------------------------------ Polish end
STR_2305 :Track design files
STR_2306 :Save track design
STR_2307 :Select {STRINGID} design
@@ -2367,18 +2380,16 @@ STR_2344 :Imperialne
STR_2345 :Metryczne
STR_2346 :Grafika
STR_2347 :{RED}{STRINGID} utonął!
-# ------------------------------------------ Polish end
-STR_2348 :{SMALLFONT}{BLACK}Show statistics for this staff member
-STR_2349 :{WINDOW_COLOUR_2}Wages: {BLACK}{CURRENCY} per month
-STR_2350 :{WINDOW_COLOUR_2}Employed: {BLACK}{MONTHYEAR}
-STR_2351 :{WINDOW_COLOUR_2}Lawns mown: {BLACK}{COMMA16}
-STR_2352 :{WINDOW_COLOUR_2}Gardens watered: {BLACK}{COMMA16}
-STR_2353 :{WINDOW_COLOUR_2}Litter swept: {BLACK}{COMMA16}
-STR_2354 :{WINDOW_COLOUR_2}Bins emptied: {BLACK}{COMMA16}
-STR_2355 :{WINDOW_COLOUR_2}Rides fixed: {BLACK}{COMMA16}
-STR_2356 :{WINDOW_COLOUR_2}Rides inspected: {BLACK}{COMMA16}
-STR_2357 :House
-# ------------------------------------------ Polish start
+STR_2348 :{SMALLFONT}{BLACK}Pokaż statystyki tego pracownika
+STR_2349 :{WINDOW_COLOUR_2}Pensja: {BLACK}{CURRENCY} miesięcznie
+STR_2350 :{WINDOW_COLOUR_2}Zatrudniony: {BLACK}{MONTHYEAR}
+STR_2351 :{WINDOW_COLOUR_2}Skoszone trawniki: {BLACK}{COMMA16}
+STR_2352 :{WINDOW_COLOUR_2}Podlane ogrody: {BLACK}{COMMA16}
+STR_2353 :{WINDOW_COLOUR_2}Sprzątnięte śmieci: {BLACK}{COMMA16}
+STR_2354 :{WINDOW_COLOUR_2}Opróżnione kosze: {BLACK}{COMMA16}
+STR_2355 :{WINDOW_COLOUR_2}Naprawione atrakcje: {BLACK}{COMMA16}
+STR_2356 :{WINDOW_COLOUR_2}Skontrolowane atrakcje: {BLACK}{COMMA16}
+STR_2357 :Dom
STR_2358 :Jednostki
STR_2359 :Prawdziwe wartości
STR_2360 :{WINDOW_COLOUR_2}Rozdzielczość:
@@ -2744,30 +2755,36 @@ 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_2736 :???
-STR_2737 :???
-STR_2738 :???
-STR_2739 :???
-STR_2740 :???
-STR_2741 :???
-STR_2742 :???
-STR_2743 :???
+# New strings (previously these were ???)
+# sec, secs
+STR_2720 :{UINT16}sek
+STR_2721 :{UINT16}sek
+# min+sec, min+secs, mins+sec, mins+secs
+STR_2722 :{UINT16}min:{UINT16}sek
+STR_2723 :{UINT16}min:{UINT16}sek
+STR_2724 :{UINT16}min:{UINT16}sek
+STR_2725 :{UINT16}min:{UINT16}sek
+# min, mins
+STR_2726 :{UINT16}min
+STR_2727 :{UINT16}min
+# hour+min, hour+mins, hours+min, hours+mins
+STR_2728 :{UINT16}godz:{UINT16}min
+STR_2729 :{UINT16}godz:{UINT16}min
+STR_2730 :{UINT16}godz:{UINT16}min
+STR_2731 :{UINT16}godz:{UINT16}min
+STR_2732 :{COMMA16}ft
+STR_2733 :{COMMA16}m
+STR_2734 :{COMMA16}mph
+STR_2735 :{COMMA16}km/h
+STR_2736 :{MONTH}, Rok {COMMA16}
+STR_2737 :{STRINGID} {MONTH}, Rok {COMMA16}
+STR_2738 :Muzyka tytułowa
+STR_2739 :Brak
+STR_2740 :RollerCoaster Tycoon 1
+STR_2741 :RollerCoaster Tycoon 2
+STR_2742 :Nie znaleziono css50.dat
+STR_2743 :Przekopiuj data\css17.dat z folderu RCT1 do data\css50.dat folderu instalacji RCT2.
+# End of new strings
STR_2744 :[
STR_2745 :\
STR_2746 :]
@@ -3137,9 +3154,11 @@ STR_3103 :Can't re-paint this...
STR_3104 :{SMALLFONT}{BLACK}List rides
STR_3105 :{SMALLFONT}{BLACK}List shops and stalls
STR_3106 :{SMALLFONT}{BLACK}List information kiosks and other guest facilities
-STR_3107 :Close
-STR_3108 :Test
-STR_3109 :Open
+# ------------------------------------------ Polish start
+STR_3107 :Zamknij
+STR_3108 :Testuj
+STR_3109 :Otwórz
+# ------------------------------------------ Polish end
STR_3110 :{WINDOW_COLOUR_2}Block Sections: {BLACK}{COMMA16}
STR_3111 :{SMALLFONT}{BLACK}Click on design to build it
STR_3112 :{SMALLFONT}{BLACK}Click on design to rename or delete it
diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj
index 9fc2710c45..5944dcba2e 100644
--- a/projects/openrct2.vcxproj
+++ b/projects/openrct2.vcxproj
@@ -22,6 +22,7 @@
+
@@ -59,7 +60,6 @@
-
@@ -68,11 +68,11 @@
+
-
@@ -88,16 +88,15 @@
-
-
+
@@ -125,6 +124,7 @@
+
@@ -135,6 +135,8 @@
+
+
@@ -174,19 +176,19 @@
-
+
+
-
@@ -198,6 +200,8 @@
+
+
diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters
index 0493ff0915..657a0d8858 100644
--- a/projects/openrct2.vcxproj.filters
+++ b/projects/openrct2.vcxproj.filters
@@ -120,9 +120,6 @@
Source\Windows
-
- Source\Windows
-
Source\Windows
@@ -204,9 +201,6 @@
Source\Localisation
-
- Source\Platform
-
Source\Ride
@@ -330,10 +324,6 @@
Source\Drawing
-
-
-
-
Source
@@ -341,29 +331,28 @@
Source
-
Source\World
-
+
Source\World
Source\Windows
-
+
Source\Windows
Source\Windows
-
+
Source\Windows
-
+
Source\Windows
@@ -394,9 +383,6 @@
Source
-
- Source
-
Source\Windows
@@ -406,9 +392,6 @@
Source\Windows
-
- Source\Windows
-
Source\Localisation
@@ -424,6 +407,24 @@
Source\Windows
+
+ Source\World
+
+
+ Source\World
+
+
+ Source\Windows
+
+
+ Source\Windows
+
+
+ Source\Ride
+
+
+ Source
+
@@ -495,9 +496,6 @@
Source\Localisation
-
- Source\Platform
-
Source\Ride
@@ -609,8 +607,17 @@
Source
-
+
Source
+
+ Source\World
+
+
+ Source\World
+
+
+ Source\Ride
+
\ No newline at end of file
diff --git a/projects/openrct2.vcxproj.user b/projects/openrct2.vcxproj.user
index d08f3ad23c..3ef1339416 100644
--- a/projects/openrct2.vcxproj.user
+++ b/projects/openrct2.vcxproj.user
@@ -1,18 +1,8 @@
-
- false
-
-
- $(TargetDir)\openrct2.exe
- WindowsLocalDebugger
- $(TargetDir)
-
- $(TargetDir)\openrct2.exe
$(TargetDir)
WindowsLocalDebugger
-
-
+ $(TargetDir)\openrct2.exe
\ No newline at end of file
diff --git a/src/addresses.h b/src/addresses.h
index 921c3d423f..60fab7f688 100644
--- a/src/addresses.h
+++ b/src/addresses.h
@@ -129,6 +129,7 @@
#define RCT2_ADDRESS_RIDE_ENTRIES 0x009ACFA4
#define RCT2_ADDRESS_INSTALLED_OBJECT_LIST 0x009ADAE8
+#define RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST 0x009ADAEC
#define RCT2_ADDRESS_CURRENT_SOUND_DEVICE 0x009AF280
@@ -169,6 +170,8 @@
#define RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER 0x009DE55E
#define RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX 0x009DE560
+#define RCT2_ADDRESS_PALETTE_EFFECT_FRAME_NO 0x009DE584
+
#define RCT2_ADDRESS_MAP_SELECTION_FLAGS 0x009DE58A
#define RCT2_ADDRESS_MAP_SELECTION_A_X 0x009DE58C
#define RCT2_ADDRESS_MAP_SELECTION_B_X 0x009DE58E
@@ -178,6 +181,11 @@
#define RCT2_ADDRESS_SCREEN_FLAGS 0x009DEA68
#define RCT2_ADDRESS_SCREENSHOT_COUNTDOWN 0x009DEA6D
+// Note: not only the zeroth bit can be set to control pause
+// When paused by saving track 2nd bit is set
+// When paused by save menu 1st bit is set
+// When paused by pause button 0th bit is set
+#define RCT2_ADDRESS_GAME_PAUSED 0x009DEA6E
#define RCT2_ADDRESS_PLACE_OBJECT_MODIFIER 0x009DEA70
#define RCT2_ADDRESS_ON_TUTORIAL 0x009DEA71
@@ -253,6 +261,24 @@
#define RCT2_ADDRESS_STAFF_HIGHLIGHTED_INDEX 0x00F43908
+#define RCT2_ADDRESS_TRACK_PREVIEW_ROTATION 0x00F440AE
+
+#define RCT2_ADDRESS_TRACK_PREVIEW_X_MIN 0x00F440F9
+#define RCT2_ADDRESS_TRACK_PREVIEW_X_MAX 0x00F440FB
+#define RCT2_ADDRESS_TRACK_PREVIEW_Y_MIN 0x00F440FD
+#define RCT2_ADDRESS_TRACK_PREVIEW_Y_MAX 0x00F440FF
+#define RCT2_ADDRESS_TRACK_PREVIEW_Z_MIN 0x00F44101
+#define RCT2_ADDRESS_TRACK_PREVIEW_Z_MAX 0x00F44103
+#define RCT2_ADDRESS_TRACK_DESIGN_CACHE 0x00F44105
+#define RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE 0x00F44109
+#define RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE 0x00F44119
+
+#define RCT2_ADDRESS_TRACK_DESIGN_COST 0x00F4411D
+
+#define RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE 0x00F44152
+
+#define RCT2_ADDRESS_TRACK_LIST 0x00F441EC
+
#define RCT2_ADDRESS_CURRENT_MONTH_YEAR 0x00F663A8
#define RCT2_ADDRESS_CURRENT_MONTH_TICKS 0x00F663AA
#define RCT2_ADDRESS_SCENARIO_TICKS 0x00F663AC
@@ -268,6 +294,8 @@
#define RCT2_ADDRESS_SPRITES_START_TEXTFX 0x013573C2
#define RCT2_ADDRESS_SPRITES_START_LITTER 0x013573C4
+#define RCT2_ADDRESS_PARK_NAME 0x013573D4
+#define RCT2_ADDRESS_PARK_NAME_ARGS 0x013573D8
#define RCT2_ADDRESS_INITIAL_CASH 0x013573DC
#define RCT2_ADDRESS_CURRENT_LOAN 0x013573E0
#define RCT2_ADDRESS_MAXIMUM_LOAN 0x013580F0
@@ -324,6 +352,7 @@
#define RCT2_ADDRESS_NEXT_RESEARCH_EXPECTED_DAY 0x013580E7
#define RCT2_ADDRESS_NEXT_RESEARCH_EXPECTED_MONTH 0x013580E8
+#define RCT2_ADDRESS_MAP_SIZE_UNITS 0x01358830
#define RCT2_ADDRESS_MAP_MAXIMUM_X_Y 0x01358832
#define RCT2_ADDRESS_MAP_SIZE 0x01358834
#define RCT2_ADDRESS_PARK_SIZE 0x013580EA
@@ -338,6 +367,7 @@
#define RCT2_ADDRESS_PARK_ENTRANCE_X 0x01359350
#define RCT2_ADDRESS_PARK_ENTRANCE_Y 0x01359358
#define RCT2_ADDRESS_PARK_ENTRANCE_Z 0x01359360
+#define RCT2_ADDRESS_PARK_ENTRANCE_DIRECTION 0x01359368
#define RCT2_ADDRESS_CURRENT_TICKS 0x013628F4
#define RCT2_ADDRESS_RIDE_LIST 0x013628F8
@@ -379,12 +409,10 @@
#define RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER 0x0141ED68
-#define RCT2_ADDRESS_AUDIO_INFO 0x01425B40
+#define RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE 0x0141F56C
-#define RCT2_ADDRESS_SOUND_CHANNEL_LIST 0x014262E0
-
-#define RCT2_ADDRESS_WATER_RAISE_COST 0x0141F738
-#define RCT2_ADDRESS_WATER_LOWER_COST 0x0141F73C
+#define RCT2_ADDRESS_WATER_RAISE_COST 0x0141F738
+#define RCT2_ADDRESS_WATER_LOWER_COST 0x0141F73C
#define RCT2_ADDRESS_CURRENT_WINDOW_COLOUR_1 0x0141F740
#define RCT2_ADDRESS_CURRENT_WINDOW_COLOUR_2 0x0141F741
@@ -475,6 +503,10 @@
#define RCT2_ADDRESS_INPUT_QUEUE 0x01424340
+#define RCT2_ADDRESS_AUDIO_INFO 0x01425B40
+
+#define RCT2_ADDRESS_SOUND_CHANNEL_LIST 0x014262E0
+
#define RCT2_ADDRESS_COMMON_FORMAT_ARGS 0x013CE952
#define RCT2_ADDRESS_STAFF_MODE_ARRAY 0x013CA672
@@ -494,24 +526,11 @@
#define RCT2_ADDRESS_X_END_POINT_GLOBAL 0x9ABDA8 //sint16
#define RCT2_ADDRESS_X_START_POINT_GLOBAL 0xEDF80C //sint16
#define RCT2_ADDRESS_DPI_LINE_LENGTH_GLOBAL 0x9ABDB0 //uint16 width+pitch
+#define RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_OBJECTS 0x009AA00D
+#define RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_CONFIG 0x009AB4C6
#pragma endregion
-static void RCT2_CALLPROC_EBPSAFE(int address)
-{
- #ifdef _MSC_VER
- __asm push ebp
- __asm call address
- __asm pop ebp
- #else
- __asm__ ( "\
- push ebp \n\
- call %[address] \n\
- pop ebp \n\
- " : [address] "+m" (address) );
- #endif
-}
-
/* Returns the flags register
*
*Flags register is as follows:
@@ -566,45 +585,9 @@ static int RCT2_CALLPROC_X(int address, int _eax, int _ebx, int _ecx, int _edx,
#endif
}
-static void RCT2_CALLPROC_X_EBPSAFE(int address, int _eax, int _ebx, int _ecx, int _edx, int _esi, int _edi, int _ebp)
+static int RCT2_CALLPROC_EBPSAFE(int address)
{
- #ifdef _MSC_VER
- __asm {
- push ebp
- push address
- mov eax, _eax
- mov ebx, _ebx
- mov ecx, _ecx
- mov edx, _edx
- mov esi, _esi
- mov edi, _edi
- mov ebp, _ebp
- call[esp]
- add esp, 4
- pop ebp
- }
- #else
- __asm__ ( "\
- \n\
- push ebx \n\
- push ebp \n\
- push %[address] \n\
- mov eax, %[_eax] \n\
- mov ebx, %[_ebx] \n\
- mov ecx, %[_ecx] \n\
- mov edx, %[_edx] \n\
- mov esi, %[_esi] \n\
- mov edi, %[_edi] \n\
- mov ebp, %[_ebp] \n\
- call [esp] \n\
- add esp, 4 \n\
- pop ebp \n\
- pop ebx \n\
- " : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp)
- :
- : "eax","ecx","edx","esi","edi"
- );
- #endif
+ return RCT2_CALLPROC_X(address, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB);
}
/* Returns the flags register
diff --git a/src/audio/audio.c b/src/audio/audio.c
index 42e436e3c4..227550767c 100644
--- a/src/audio/audio.c
+++ b/src/audio/audio.c
@@ -23,7 +23,7 @@
#include "../config.h"
#include "../interface/viewport.h"
#include "../interface/window.h"
-#include "../platform/osinterface.h"
+#include "../platform/platform.h"
#include "../world/map.h"
#include "../world/sprite.h"
#include "audio.h"
@@ -693,32 +693,32 @@ int sound_prepare(int sound_id, rct_sound *sound, int channels, int software)
rct_sound_effect* sound_effect = sound_get_effect(sound_id);
if (sound_effect) {
if (sound_effect_loadvars(sound_effect, &bufferdesc.lpwfxFormat, &buffer, &bufferdesc.dwBufferBytes)) {
- bufferdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STATIC;
- if (channels) {
- if (channels == 2) {
+ if (channels == 0){
+ bufferdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STATIC;
+ }
+ else if (channels == 2) {
bufferdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D | DSBCAPS_STATIC;
- } else {
+ } else {
bufferdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY | DSBCAPS_STATIC;
+ }
+ if (RCT2_GLOBAL(0x009E2B90, uint32)) {
+ bufferdesc.dwFlags |= DSBCAPS_CTRLPAN;
+ }
+ if (software) {
+ bufferdesc.dwFlags |= DSBCAPS_LOCSOFTWARE;
+ }
+ if (SUCCEEDED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->CreateSoundBuffer(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), &bufferdesc, &sound->dsbuffer, 0))) {
+ if (sound_fill_buffer(sound->dsbuffer, buffer, bufferdesc.dwBufferBytes)) {
+ sound->id = sound_id;
+ DSBCAPS caps;
+ caps.dwSize = sizeof(caps);
+ sound->dsbuffer->lpVtbl->GetCaps(sound->dsbuffer, &caps);
+ sound->has_caps = caps.dwFlags;
+ sound_add(sound);
+ return 1;
}
- if (RCT2_GLOBAL(0x009E2B90, uint32)) {
- bufferdesc.dwFlags |= DSBCAPS_CTRLPAN;
- }
- if (software) {
- bufferdesc.dwFlags |= DSBCAPS_LOCSOFTWARE;
- }
- if (SUCCEEDED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->CreateSoundBuffer(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), &bufferdesc, &sound->dsbuffer, 0))) {
- if (sound_fill_buffer(sound->dsbuffer, buffer, bufferdesc.dwBufferBytes)) {
- sound->id = sound_id;
- DSBCAPS caps;
- caps.dwSize = sizeof(caps);
- sound->dsbuffer->lpVtbl->GetCaps(sound->dsbuffer, &caps);
- sound->has_caps = caps.dwFlags;
- sound_add(sound);
- return 1;
- }
- sound->dsbuffer->lpVtbl->Release(sound->dsbuffer);
- sound->dsbuffer = 0;
- }
+ sound->dsbuffer->lpVtbl->Release(sound->dsbuffer);
+ sound->dsbuffer = 0;
}
sound->dsbuffer = 0;
}
@@ -1329,7 +1329,7 @@ int dsound_create_primary_buffer(int a, int device, int channels, int samples, i
if (FAILED(DirectSoundCreate(&dsdevice->guid, &RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), 0))) {
return 0;
}
- if (FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->SetCooperativeLevel(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), RCT2_GLOBAL(0x009E2D70, HWND), DSSCL_NORMAL)) ||
+ if (FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->SetCooperativeLevel(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), windows_get_window_handle(), DSSCL_NORMAL)) ||
FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->CreateSoundBuffer(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), &bufferdesc, &RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER), 0))) {
RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->Release(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND));
RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND) = 0;
@@ -1374,7 +1374,7 @@ int dsound_create_primary_buffer(int a, int device, int channels, int samples, i
if (FAILED(DirectSoundCreate(&dsdevice->guid, &RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), 0))) {
return 0;
}
- if (FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->SetCooperativeLevel(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), RCT2_GLOBAL(0x009E2D70, HWND), DSSCL_PRIORITY))) {
+ if (FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->SetCooperativeLevel(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), windows_get_window_handle(), DSSCL_PRIORITY))) {
RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->Release(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND));
RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND) = 0;
return 0;
@@ -1431,7 +1431,7 @@ int sound_play_panned(int sound_id, int ebx, sint16 x, sint16 y, sint16 z)
sint16 y2 = y & 0xFFE0;
if (x2 < 0x1FFF && y2 < 0x1FFF) {
rct_map_element* mapelement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[((y2 * 256 + x2) & 0xFFFF) / 8];
- while (mapelement->type & MAP_ELEMENT_TYPE_MASK) {
+ while (map_element_get_type(mapelement) != MAP_ELEMENT_TYPE_SURFACE) {
mapelement++;
}
if ((mapelement->base_height * 8) - 5 > z) {
@@ -1544,13 +1544,25 @@ void stop_completed_sounds()
*/
void start_title_music()
{
+ int musicPathId;
+ switch (gGeneral_config.title_music) {
+ default:
+ return;
+ case 1:
+ musicPathId = PATH_ID_CSS50;
+ break;
+ case 2:
+ musicPathId = PATH_ID_CSS17;
+ break;
+ }
+
if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)) && RCT2_GLOBAL(0x009AF59D, uint8) & 1 && RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1) {
if (!RCT2_GLOBAL(0x009AF600, uint8)) {
#ifdef USE_MIXER
- gTitleMusicChannel = Mixer_Play_Music(PATH_ID_CSS17);
+ gTitleMusicChannel = Mixer_Play_Music(musicPathId);
#else
RCT2_GLOBAL(0x014241BC, uint32) = 1;
- int result = sound_channel_load_file2(3, (char*)get_file_path(PATH_ID_CSS17), 0);
+ int result = sound_channel_load_file2(3, (char*)get_file_path(musicPathId), 0);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
if (result) {
RCT2_GLOBAL(0x014241BC, uint32) = 1;
@@ -1690,13 +1702,10 @@ void audio_init1()
do {
rct_ride_music_info* ride_music_info = &RCT2_GLOBAL(0x009AF1C8, rct_ride_music_info*)[m];
const char* path = get_file_path(ride_music_info->pathid);
- RCT2_GLOBAL(0x014241BC, uint32) = 3;
- HANDLE hfile = osinterface_file_open(path);
- RCT2_GLOBAL(0x014241BC, uint32) = 0;
- if (hfile != INVALID_HANDLE_VALUE) {
- RCT2_GLOBAL(0x014241BC, uint32) = 3;
- osinterface_file_read(hfile, &RCT2_GLOBAL(0x009AF47E, uint32), 4);
- osinterface_file_close(hfile);
+ FILE *file = fopen(path, "rb");
+ if (file != NULL) {
+ fread(&RCT2_GLOBAL(0x009AF47E, uint32), 4, 1, file);
+ fclose(file);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
if (RCT2_GLOBAL(0x009AF47E, uint32) == 0x78787878) {
ride_music_info->var_0 = 0;
diff --git a/src/audio/mixer.cpp b/src/audio/mixer.cpp
index 042f349a78..0888df65b4 100644
--- a/src/audio/mixer.cpp
+++ b/src/audio/mixer.cpp
@@ -25,6 +25,7 @@ extern "C" {
#include "../config.h"
#include "../platform/platform.h"
#include "audio.h"
+ #include "../localisation/localisation.h"
}
#include "mixer.h"
@@ -44,33 +45,50 @@ Sample::~Sample()
bool Sample::Load(const char* filename)
{
+ log_verbose("Sample::Load(%s)", filename);
+
+ utf8 utf8filename[512];
+ win1252_to_utf8(utf8filename, filename, sizeof(utf8filename));
+
Unload();
- SDL_RWops* rw = SDL_RWFromFile(filename, "rb");
- if (!rw) {
- SDL_RWclose(rw);
+ SDL_RWops* rw = SDL_RWFromFile(utf8filename, "rb");
+ if (rw == NULL) {
+ log_verbose("Error loading %s", filename);
return false;
}
+
SDL_AudioSpec audiospec;
memset(&audiospec, 0, sizeof(audiospec));
SDL_AudioSpec* spec = SDL_LoadWAV_RW(rw, false, &audiospec, &data, (Uint32*)&length);
+ SDL_RWclose(rw);
+
if (spec != NULL) {
format.freq = spec->freq;
format.format = spec->format;
format.channels = spec->channels;
issdlwav = true;
} else {
+ log_verbose("Error loading %s, unsupported WAV format", filename);
return false;
}
+
return true;
}
bool Sample::LoadCSS1(const char* filename, unsigned int offset)
{
+ log_verbose("Sample::LoadCSS1(%s, %d)", filename, offset);
+
+ utf8 utf8filename[512];
+ win1252_to_utf8(utf8filename, filename, sizeof(utf8filename));
+
Unload();
- SDL_RWops* rw = SDL_RWFromFile(filename, "rb");
- if (!rw) {
+ SDL_RWops* rw = SDL_RWFromFile(utf8filename, "rb");
+ if (rw == NULL) {
+ log_verbose("Unable to load %s", filename);
return false;
}
+
Uint32 numsounds;
SDL_RWread(rw, &numsounds, sizeof(numsounds), 1);
if (offset > numsounds) {
diff --git a/src/cmdline.c b/src/cmdline.c
index 3964c2f2be..d101e4ca25 100644
--- a/src/cmdline.c
+++ b/src/cmdline.c
@@ -50,10 +50,6 @@ static const char *const usage[] = {
*/
int cmdline_run(const char **argv, int argc)
{
- // For argparse's sake, add virtual first argument process path
- argc++;
- argv--;
-
//
int version = 0, verbose = 0, width = 0, height = 0;
diff --git a/src/config.c b/src/config.c
index 5dd2b18a75..f1e91ddf38 100644
--- a/src/config.c
+++ b/src/config.c
@@ -22,7 +22,6 @@
#include "addresses.h"
#include "config.h"
#include "localisation/localisation.h"
-#include "platform/osinterface.h"
#include "platform/platform.h"
// Current keyboard shortcuts
@@ -88,10 +87,13 @@ general_configuration_t gGeneral_config_default = {
0, // show_height_as_units
1, // save_plugin_data
0, // fullscreen mode (default: windowed)
+ -1, // fullscreen_width
+ -1, // fullscreen_height
-1, // window_width
-1, // window_height
LANGUAGE_ENGLISH_UK, // language
- 5 // window_snap_proximity
+ 5, // window_snap_proximity
+ 2 // title music
};
sound_configuration_t gSound_config;
@@ -252,6 +254,11 @@ void config_write_ini_general(FILE *fp)
else
fprintf(fp, "fullscreen_mode = borderless_fullscreen\n");
+ if (gGeneral_config.fullscreen_width != -1)
+ fprintf(fp, "fullscreen_width = %d\n", gGeneral_config.fullscreen_width);
+ if (gGeneral_config.fullscreen_height != -1)
+ fprintf(fp, "fullscreen_height = %d\n", gGeneral_config.fullscreen_height);
+
if (gGeneral_config.window_width != -1)
fprintf(fp, "window_width = %d\n", gGeneral_config.window_width);
if (gGeneral_config.window_height != -1)
@@ -260,6 +267,8 @@ void config_write_ini_general(FILE *fp)
fprintf(fp, "language = %d\n", gGeneral_config.language);
fprintf(fp, "window_snap_proximity = %d\n", gGeneral_config.window_snap_proximity);
+
+ fprintf(fp, "title_music = %d\n", gGeneral_config.title_music);
}
/**
@@ -275,6 +284,9 @@ void config_apply_to_old_addresses()
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_CONSTRUCTION_MARKER, uint8) = gGeneral_config.construction_marker_colour;
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_QUALITY, sint8) = gSound_config.sound_quality;
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, sint8) = gSound_config.forced_software_buffering;
+ RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, sint16) = (gGeneral_config.measurement_format + 1) * 256;
+ if (gGeneral_config.show_height_as_units)
+ RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, sint16) = 0;
int configFlags = 0;
if (gGeneral_config.always_show_gridlines)
@@ -296,7 +308,7 @@ void config_apply_to_old_addresses()
*/
void config_load()
{
- char *path = osinterface_get_orct2_homefolder();
+ char *path = platform_get_orct2_homefolder();
FILE* fp;
memcpy(&gGeneral_config, &gGeneral_config_default, sizeof(general_configuration_t));
@@ -307,7 +319,7 @@ void config_load()
return;
}
- sprintf(path, "%s%c%s", path, osinterface_get_path_separator(), "config.ini");
+ sprintf(path, "%s%c%s", path, platform_get_path_separator(), "config.ini");
fp = fopen(path, "r");
if (!fp) {
@@ -329,9 +341,9 @@ void config_load()
void config_save()
{
- char *configIniPath = osinterface_get_orct2_homefolder();;
+ char *configIniPath = platform_get_orct2_homefolder();;
- sprintf(configIniPath, "%s%c%s", configIniPath, osinterface_get_path_separator(), "config.ini");
+ sprintf(configIniPath, "%s%c%s", configIniPath, platform_get_path_separator(), "config.ini");
config_save_ini(configIniPath);
config_apply_to_old_addresses();
@@ -374,8 +386,8 @@ int config_find_or_browse_install_directory()
char *installPath;
if (!config_find_rct2_path(gGeneral_config.game_path)) {
- osinterface_show_messagebox("Unable to find RCT2 installation directory. Please select the directory where you installed RCT2!");
- installPath = osinterface_open_directory_browser("Please select your RCT2 directory");
+ platform_show_messagebox("Unable to find RCT2 installation directory. Please select the directory where you installed RCT2!");
+ installPath = platform_open_directory_browser("Please select your RCT2 directory");
if (installPath == NULL)
return 0;
@@ -554,6 +566,12 @@ static void config_general(char *setting, char *value){
else
gGeneral_config.fullscreen_mode = 2;
}
+ else if (strcmp(setting, "fullscreen_width") == 0) {
+ gGeneral_config.fullscreen_width = atoi(value);
+ }
+ else if (strcmp(setting, "fullscreen_height") == 0) {
+ gGeneral_config.fullscreen_height = atoi(value);
+ }
else if (strcmp(setting, "window_width") == 0) {
gGeneral_config.window_width = atoi(value);
}
@@ -566,6 +584,9 @@ static void config_general(char *setting, char *value){
else if (strcmp(setting, "window_snap_proximity") == 0) {
gGeneral_config.window_snap_proximity = clamp(0, atoi(value), 255);
}
+ else if (strcmp(setting, "title_music") == 0) {
+ gGeneral_config.title_music = atoi(value);
+ }
}
/**
@@ -757,7 +778,7 @@ static int config_parse_currency(char *currency)
*/
static void config_error(char *msg){
- osinterface_show_messagebox(msg);
+ platform_show_messagebox(msg);
//TODO:SHUT DOWN EVERYTHING!
}
@@ -835,28 +856,29 @@ void config_dat_load()
// return;
- RCT2_GLOBAL(0x009AB4C6, sint8) = 1; // no idea on what this does
+ RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_CONFIG, sint8) = 1; // Marks config as first time loaded
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, sint16) = (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) + 2) * 256;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS))
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, sint16) = (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) + 1) * 256;
- RCT2_GLOBAL(0x009AA00D, sint8) = 0;
+ // No longer used (controls first time object load)
+ //RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_OBJECTS, sint8) = 0;
}
}
/* TODO: CLEANUP
- if (RCT2_GLOBAL(0x009AB4C6, sint8) == 1)
+ if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_CONFIG, sint8) == 1)
return;
- RCT2_GLOBAL(0x009AB4C6, sint8) = 1;
+ RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_CONFIG, sint8) = 1;
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_TEMPERATURE, sint8) = 1;
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_CURRENCY, sint8) = 1;
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, sint16) = 0;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS))
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, sint16) = (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) + 1) * 256;
- RCT2_GLOBAL(0x009AA00D, sint8) = 1;
+ RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_OBJECTS, sint8) = 1;
}
}
@@ -875,7 +897,7 @@ void config_dat_load()
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, sint16) = 0;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS))
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, sint16) = (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) + 1) * 256;
- RCT2_GLOBAL(0x009AA00D, sint8) = 1;
+ RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_OBJECTS, sint8) = 1;
}
/**
diff --git a/src/config.h b/src/config.h
index 3098031780..6193381412 100644
--- a/src/config.h
+++ b/src/config.h
@@ -132,10 +132,13 @@ typedef struct general_configuration {
//new
uint8 fullscreen_mode;
+ sint16 fullscreen_width;
+ sint16 fullscreen_height;
sint16 window_width;
sint16 window_height;
uint16 language;
uint8 window_snap_proximity;
+ uint8 title_music;
} general_configuration_t;
static const struct { const char *key; int value; } _currencyLookupTable[] = {
diff --git a/src/cursors.c b/src/cursors.c
new file mode 100644
index 0000000000..720f40833a
--- /dev/null
+++ b/src/cursors.c
@@ -0,0 +1,533 @@
+/*****************************************************************************
+* Copyright (c) 2014 Ted John, Duncan Frost
+* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+*
+* This file is part of OpenRCT2.
+*
+* OpenRCT2 is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+*****************************************************************************/
+
+#include "cursors.h"
+
+unsigned char blank_cursor_data[32 * 4] = {
+ 0
+};
+unsigned char blank_cursor_mask[32 * 4] = {
+ 0
+};
+
+unsigned char up_arrow_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x04, 0x10, 0x00,
+ 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x02, 0x20, 0x00,
+ 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00,
+ 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+unsigned char up_arrow_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xF0, 0x00,
+ 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x03, 0xE0, 0x00,
+ 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00,
+ 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+unsigned char up_down_arrow_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0xA0, 0x00,
+ 0x00, 0x05, 0x50, 0x00, 0x00, 0x0A, 0x28, 0x00, 0x00, 0x17, 0x74, 0x00, 0x00, 0x21, 0x42, 0x00,
+ 0x00, 0x1D, 0xDC, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x20, 0x00,
+ 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0xE0, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0xD0, 0x00, 0x00, 0x1D, 0x5C, 0x00,
+ 0x00, 0x21, 0x42, 0x00, 0x00, 0x17, 0x74, 0x00, 0x00, 0x0A, 0x28, 0x00, 0x00, 0x05, 0x50, 0x00,
+ 0x00, 0x02, 0xA0, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+unsigned char up_down_arrow_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00,
+ 0x00, 0x07, 0x70, 0x00, 0x00, 0x0E, 0x38, 0x00, 0x00, 0x1F, 0x7C, 0x00, 0x00, 0x3F, 0x7E, 0x00,
+ 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00,
+ 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x1F, 0x7C, 0x00,
+ 0x00, 0x3F, 0x7E, 0x00, 0x00, 0x1F, 0x7C, 0x00, 0x00, 0x0E, 0x38, 0x00, 0x00, 0x07, 0x70, 0x00,
+ 0x00, 0x03, 0xE0, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+
+unsigned char zzz_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C,
+ 0x00, 0x00, 0x03, 0xE2, 0x00, 0x00, 0xFC, 0x34, 0x00, 0x01, 0x07, 0x62, 0x00, 0x3F, 0xEA, 0xDC,
+ 0x00, 0x40, 0xD4, 0x20, 0x00, 0x3D, 0xBB, 0xC0, 0x3F, 0xCB, 0x04, 0x00, 0x40, 0x34, 0xF8, 0x00,
+ 0x40, 0x2F, 0x00, 0x00, 0x3C, 0x40, 0x80, 0x00, 0x08, 0xBF, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x23, 0xC0, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+unsigned char zzz_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C,
+ 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x3F, 0xFB, 0xDC,
+ 0x00, 0x7F, 0xF7, 0xE0, 0x00, 0x3F, 0xFB, 0xC0, 0x3F, 0xCF, 0xFC, 0x00, 0x7F, 0xFC, 0xF8, 0x00,
+ 0x7F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x0F, 0xBF, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00,
+ 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+unsigned char diagonal_arrow_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00,
+ 0x00, 0x1C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+unsigned char diagonal_arrow_cursor_mask[32 * 4] = {
+ 0xFE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00,
+ 0xFC, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00,
+ 0x01, 0xC2, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00,
+ 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+unsigned char picker_cursor_data[32 * 4] = {
+ 0x00, 0x07, 0xC0, 0x00, 0x00, 0x08, 0x60, 0x00, 0x00, 0x13, 0x30, 0x00, 0x00, 0x17, 0xB0, 0x00,
+ 0x00, 0x17, 0xB0, 0x00, 0x00, 0x13, 0x30, 0x00, 0x00, 0x08, 0x60, 0x00, 0x00, 0x0F, 0xE0, 0x00,
+ 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x17, 0x30, 0x00, 0x00, 0x12, 0x30, 0x00, 0x00, 0x21, 0x18, 0x00,
+ 0x00, 0x23, 0x18, 0x00, 0x00, 0x44, 0x8C, 0x00, 0x00, 0x44, 0x8C, 0x00, 0x00, 0x88, 0x46, 0x00,
+ 0x00, 0x90, 0x26, 0x00, 0x01, 0x10, 0x23, 0x00, 0x01, 0x20, 0x13, 0x00, 0x02, 0x40, 0x09, 0x80,
+ 0x02, 0x40, 0x09, 0x80, 0x04, 0x80, 0x04, 0xC0, 0x04, 0x80, 0x04, 0xC0, 0x04, 0x80, 0x04, 0xC0,
+ 0x04, 0x80, 0x04, 0xC0, 0x04, 0x80, 0x04, 0xC0, 0x04, 0x40, 0x08, 0xC0, 0x02, 0x40, 0x09, 0x80,
+ 0x01, 0x20, 0x13, 0x00, 0x00, 0x90, 0x26, 0x00, 0x00, 0x68, 0x5C, 0x00, 0x00, 0x1C, 0xF0, 0x00,
+};
+unsigned char picker_cursor_mask[32 * 4] = {
+ 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00,
+ 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00,
+ 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00,
+ 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7C, 0xFC, 0x00, 0x00, 0x7C, 0xFC, 0x00, 0x00, 0xF8, 0x7E, 0x00,
+ 0x00, 0xF0, 0x3E, 0x00, 0x01, 0xF0, 0x3F, 0x00, 0x01, 0xE0, 0x1F, 0x00, 0x03, 0xC0, 0x0F, 0x80,
+ 0x03, 0xC0, 0x0F, 0x80, 0x07, 0x80, 0x07, 0xC0, 0x07, 0x80, 0x07, 0xC0, 0x07, 0x80, 0x07, 0xC0,
+ 0x07, 0x80, 0x07, 0xC0, 0x07, 0x80, 0x07, 0xC0, 0x07, 0xC0, 0x0F, 0xC0, 0x03, 0xC0, 0x0F, 0x80,
+ 0x01, 0xE0, 0x1F, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0x78, 0x7C, 0x00, 0x00, 0x1C, 0xF0, 0x00,
+};
+
+unsigned char tree_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x01, 0x89, 0xC0, 0x00, 0x02, 0x06, 0x20,
+ 0x00, 0x07, 0x00, 0x18, 0x00, 0x07, 0x40, 0x04, 0x00, 0x03, 0x80, 0x04, 0x00, 0x01, 0xC0, 0x02,
+ 0x00, 0x03, 0x82, 0x02, 0x00, 0x03, 0xD0, 0x04, 0x00, 0x07, 0xF9, 0x08, 0x00, 0x0F, 0x6E, 0x04,
+ 0x00, 0x0E, 0xB8, 0x82, 0x00, 0x0F, 0x44, 0x22, 0x00, 0x0F, 0xA8, 0x46, 0x00, 0x0F, 0xFC, 0x16,
+ 0x00, 0x07, 0xEE, 0x8C, 0x0F, 0x81, 0xFF, 0xD8, 0x08, 0x80, 0x7D, 0xF0, 0x08, 0x80, 0x3A, 0x00,
+ 0x08, 0x80, 0x1A, 0x00, 0x08, 0x80, 0x1A, 0x00, 0x08, 0x80, 0x12, 0x00, 0x08, 0x80, 0x12, 0x00,
+ 0x08, 0x80, 0x11, 0x00, 0xF8, 0xF8, 0x60, 0x80, 0x40, 0x11, 0x80, 0x60, 0x20, 0x22, 0x09, 0x90,
+ 0x10, 0x41, 0xD5, 0x60, 0x08, 0x80, 0x22, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char tree_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x01, 0xF9, 0xC0, 0x00, 0x03, 0xFF, 0xE0,
+ 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFE,
+ 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFC,
+ 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFE,
+ 0x00, 0x07, 0xFF, 0xFC, 0x0F, 0x81, 0xFF, 0xF8, 0x0F, 0x80, 0x7F, 0xF0, 0x0F, 0x80, 0x3E, 0x00,
+ 0x0F, 0x80, 0x1E, 0x00, 0x0F, 0x80, 0x1E, 0x00, 0x0F, 0x80, 0x1E, 0x00, 0x0F, 0x80, 0x1E, 0x00,
+ 0x0F, 0x80, 0x1F, 0x00, 0xFF, 0xF8, 0x7F, 0x80, 0x7F, 0xF1, 0xFF, 0xE0, 0x3F, 0xE3, 0xFF, 0xF0,
+ 0x1F, 0xC1, 0xF7, 0x60, 0x0F, 0x80, 0x22, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char fountain_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0E, 0x00,
+ 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x7B, 0xC0, 0x00, 0x01, 0x8B, 0x30, 0x00, 0x02, 0x17, 0xC8,
+ 0x00, 0x02, 0x0F, 0x88, 0x0F, 0x83, 0x80, 0x38, 0x08, 0x82, 0x7F, 0xD8, 0x08, 0x81, 0x01, 0xF0,
+ 0x08, 0x80, 0xE3, 0xE0, 0x08, 0x80, 0x3F, 0x80, 0x08, 0x80, 0x17, 0x00, 0x08, 0x80, 0x13, 0x00,
+ 0x08, 0x80, 0x13, 0x00, 0xF8, 0xF8, 0x27, 0x80, 0x40, 0x10, 0x4E, 0xC0, 0x20, 0x20, 0x80, 0xE0,
+ 0x10, 0x40, 0xC1, 0xA0, 0x08, 0x80, 0x7F, 0xC0, 0x05, 0x00, 0x1F, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char fountain_down_cursor_mask[32 * 4] = {
+ 0x00, 0x01, 0x04, 0x00, 0x00, 0x10, 0x10, 0x81, 0x00, 0x00, 0x41, 0x14, 0x00, 0x05, 0x08, 0x20,
+ 0x00, 0x00, 0x22, 0x81, 0x00, 0x00, 0x88, 0x10, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0E, 0x00,
+ 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x01, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF8,
+ 0x00, 0x03, 0xFF, 0xF8, 0x0F, 0x83, 0xFF, 0xF8, 0x0F, 0x83, 0xFF, 0xF8, 0x0F, 0x81, 0xFF, 0xF0,
+ 0x0F, 0x80, 0xFF, 0xE0, 0x0F, 0x80, 0x3F, 0x80, 0x0F, 0x80, 0x1F, 0x00, 0x0F, 0x80, 0x1F, 0x00,
+ 0x0F, 0x80, 0x1F, 0x00, 0xFF, 0xF8, 0x3F, 0x80, 0x7F, 0xF0, 0x7F, 0xC0, 0x3F, 0xE0, 0xFF, 0xE0,
+ 0x1F, 0xC0, 0xFF, 0xE0, 0x0F, 0x80, 0x7F, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char statue_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x07, 0x03, 0x30,
+ 0x00, 0x02, 0x84, 0x98, 0x00, 0x01, 0x44, 0x98, 0x00, 0x00, 0xB5, 0xA8, 0x00, 0x00, 0x4A, 0xD0,
+ 0x00, 0x00, 0x21, 0x20, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x10, 0x80,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00,
+ 0x00, 0x00, 0x05, 0x00, 0x0F, 0x80, 0x08, 0x80, 0x08, 0x80, 0x04, 0x80, 0x08, 0x80, 0x05, 0x00,
+ 0x08, 0x80, 0x0D, 0x00, 0x08, 0x80, 0x09, 0x00, 0x08, 0x80, 0x3F, 0x80, 0x08, 0x80, 0x20, 0x80,
+ 0x08, 0x80, 0x20, 0x80, 0xF8, 0xF8, 0x20, 0x80, 0x40, 0x10, 0x20, 0x80, 0x20, 0x20, 0x20, 0x80,
+ 0x10, 0x40, 0x7F, 0xC0, 0x08, 0x80, 0x80, 0x20, 0x05, 0x00, 0xFF, 0xE0, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char statue_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x07, 0x03, 0x30,
+ 0x00, 0x03, 0x87, 0x98, 0x00, 0x01, 0xC7, 0x98, 0x00, 0x00, 0xF7, 0xB8, 0x00, 0x00, 0x7E, 0xF0,
+ 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80,
+ 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x0F, 0x80, 0x0F, 0x80, 0x0F, 0x80, 0x07, 0x80, 0x0F, 0x80, 0x07, 0x00,
+ 0x0F, 0x80, 0x0F, 0x00, 0x0F, 0x80, 0x0F, 0x00, 0x0F, 0x80, 0x3F, 0x80, 0x0F, 0x80, 0x3F, 0x80,
+ 0x0F, 0x80, 0x3F, 0x80, 0xFF, 0xF8, 0x3F, 0x80, 0x7F, 0xF0, 0x3F, 0x80, 0x3F, 0xE0, 0x3F, 0x80,
+ 0x1F, 0xC0, 0x7F, 0xC0, 0x0F, 0x80, 0xFF, 0xE0, 0x07, 0x00, 0xFF, 0xE0, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char bench_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00,
+ 0x00, 0x04, 0x60, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x05, 0x81, 0x80,
+ 0x00, 0x05, 0x60, 0x60, 0x00, 0x0D, 0x18, 0x18, 0x00, 0x33, 0x06, 0x04, 0x00, 0xC0, 0xC1, 0x84,
+ 0x00, 0xF0, 0x30, 0x64, 0x00, 0xAC, 0x0C, 0x1C, 0x00, 0xA7, 0x03, 0x14, 0x00, 0x40, 0xC0, 0xD4,
+ 0x00, 0x00, 0xF0, 0x34, 0x0F, 0x80, 0xAC, 0x0C, 0x08, 0x80, 0xA3, 0x3C, 0x08, 0x80, 0x41, 0xD4,
+ 0x08, 0x80, 0x01, 0xD4, 0x08, 0x80, 0x01, 0x48, 0x08, 0x80, 0x01, 0x40, 0x08, 0x80, 0x00, 0x80,
+ 0x08, 0x80, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
+ 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char bench_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00,
+ 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x80,
+ 0x00, 0x07, 0x7F, 0xE0, 0x00, 0x0F, 0x1F, 0xF8, 0x00, 0x3F, 0x07, 0xFC, 0x00, 0xFF, 0xC1, 0xFC,
+ 0x00, 0xFF, 0xF0, 0x7C, 0x00, 0xEF, 0xFC, 0x1C, 0x00, 0xE7, 0xFF, 0x1C, 0x00, 0x40, 0xFF, 0xDC,
+ 0x00, 0x00, 0xFF, 0xFC, 0x0F, 0x80, 0xEF, 0xFC, 0x0F, 0x80, 0xE3, 0xFC, 0x0F, 0x80, 0x41, 0xDC,
+ 0x0F, 0x80, 0x01, 0xDC, 0x0F, 0x80, 0x01, 0xC8, 0x0F, 0x80, 0x01, 0xC0, 0x0F, 0x80, 0x00, 0x80,
+ 0x0F, 0x80, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
+ 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char cross_hair_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE2, 0x3F, 0x80,
+ 0x10, 0x15, 0x40, 0x40, 0x0F, 0xE2, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
+ 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+unsigned char cross_hair_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE2, 0x3F, 0x80,
+ 0x1F, 0xF7, 0x7F, 0xC0, 0x0F, 0xE2, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+unsigned char bin_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x22, 0x00,
+ 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0xC3, 0x80, 0x00, 0x01, 0x00, 0xC0, 0x00, 0x02, 0x57, 0xE0,
+ 0x00, 0x02, 0x00, 0x60, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x01, 0x01, 0xC0, 0x00, 0x01, 0x40, 0xC0,
+ 0x00, 0x01, 0x50, 0xC0, 0x0F, 0x81, 0x50, 0x40, 0x08, 0x81, 0x51, 0x40, 0x08, 0x81, 0x51, 0x40,
+ 0x08, 0x81, 0x55, 0x40, 0x08, 0x81, 0x55, 0x40, 0x08, 0x81, 0x55, 0x40, 0x08, 0x81, 0x55, 0x40,
+ 0x08, 0x81, 0x55, 0x40, 0xF8, 0xF9, 0x55, 0x40, 0x40, 0x11, 0x55, 0x40, 0x20, 0x21, 0xFF, 0xC0,
+ 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char bin_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x22, 0x00,
+ 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0xE0,
+ 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xC0,
+ 0x00, 0x01, 0xFF, 0xC0, 0x0F, 0x81, 0xFF, 0xC0, 0x0F, 0x81, 0xFF, 0xC0, 0x0F, 0x81, 0xFF, 0xC0,
+ 0x0F, 0x81, 0xFF, 0xC0, 0x0F, 0x81, 0xFF, 0xC0, 0x0F, 0x81, 0xFF, 0xC0, 0x0F, 0x81, 0xFF, 0xC0,
+ 0x0F, 0x81, 0xFF, 0xC0, 0xFF, 0xF9, 0xFF, 0xC0, 0x7F, 0xF1, 0xFF, 0xC0, 0x3F, 0xE1, 0xFF, 0xC0,
+ 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char lamppost_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0xFF, 0x80,
+ 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x32, 0x00,
+ 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x94, 0x80,
+ 0x00, 0x01, 0xF7, 0xC0, 0x00, 0x00, 0x94, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00,
+ 0x00, 0x00, 0x14, 0x00, 0x0F, 0x80, 0x14, 0x00, 0x08, 0x80, 0x14, 0x00, 0x08, 0x80, 0x14, 0x00,
+ 0x08, 0x80, 0x14, 0x00, 0x08, 0x80, 0x14, 0x00, 0x08, 0x80, 0x14, 0x00, 0x08, 0x80, 0x1C, 0x00,
+ 0x08, 0x80, 0x1C, 0x00, 0xF8, 0xF8, 0x32, 0x00, 0x40, 0x10, 0x61, 0x00, 0x20, 0x20, 0x61, 0x00,
+ 0x10, 0x40, 0x71, 0x00, 0x08, 0x80, 0x7D, 0x00, 0x05, 0x00, 0xFF, 0x80, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char lamppost_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0x80,
+ 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x3E, 0x00,
+ 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x9C, 0x80,
+ 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x9C, 0x80, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1C, 0x00,
+ 0x00, 0x00, 0x1C, 0x00, 0x0F, 0x80, 0x1C, 0x00, 0x0F, 0x80, 0x1C, 0x00, 0x0F, 0x80, 0x1C, 0x00,
+ 0x0F, 0x80, 0x1C, 0x00, 0x0F, 0x80, 0x1C, 0x00, 0x0F, 0x80, 0x1C, 0x00, 0x0F, 0x80, 0x1C, 0x00,
+ 0x0F, 0x80, 0x1C, 0x00, 0xFF, 0xF8, 0x3E, 0x00, 0x7F, 0xF0, 0x7F, 0x00, 0x3F, 0xE0, 0x7F, 0x00,
+ 0x1F, 0xC0, 0x7F, 0x00, 0x0F, 0x80, 0x7F, 0x00, 0x07, 0x00, 0xFF, 0x80, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char fence_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x4E, 0x60, 0x00, 0x00,
+ 0x43, 0xB0, 0x00, 0x00, 0x20, 0xB1, 0x80, 0x00, 0x2C, 0x3A, 0xC0, 0x00, 0x2F, 0x0E, 0xC6, 0x00,
+ 0x2C, 0x82, 0xCB, 0x00, 0x2C, 0xB0, 0x6B, 0x18, 0x6C, 0xBC, 0x1B, 0x2C, 0x7C, 0xB2, 0x83, 0x2C,
+ 0x1E, 0xB2, 0xE1, 0xAC, 0x07, 0xB2, 0xD8, 0x6C, 0x01, 0xF2, 0xCA, 0x0C, 0x00, 0x7A, 0xCB, 0x86,
+ 0x00, 0x1E, 0xCB, 0x66, 0x0F, 0x87, 0xCB, 0x2E, 0x08, 0x81, 0xEB, 0x2C, 0x08, 0x80, 0x7B, 0x2C,
+ 0x08, 0x80, 0x1F, 0x2C, 0x08, 0x80, 0x07, 0xAC, 0x08, 0x80, 0x01, 0xEC, 0x08, 0x80, 0x00, 0x78,
+ 0x08, 0x80, 0x00, 0x18, 0xF8, 0xF8, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
+ 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char fence_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x7E, 0x60, 0x00, 0x00,
+ 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xF1, 0x80, 0x00, 0x3F, 0xFB, 0xC0, 0x00, 0x3F, 0xFF, 0xC6, 0x00,
+ 0x3C, 0xFF, 0xCF, 0x00, 0x3C, 0xFF, 0xEF, 0x18, 0x7C, 0xFF, 0xFF, 0x3C, 0x7C, 0xF3, 0xFF, 0x3C,
+ 0x1E, 0xF3, 0xFF, 0xBC, 0x07, 0xF3, 0xDF, 0xFC, 0x01, 0xF3, 0xCF, 0xFC, 0x00, 0x7B, 0xCF, 0xFE,
+ 0x00, 0x1F, 0xCF, 0x7E, 0x0F, 0x87, 0xCF, 0x3E, 0x0F, 0x81, 0xEF, 0x3C, 0x0F, 0x80, 0x7F, 0x3C,
+ 0x0F, 0x80, 0x1F, 0x3C, 0x0F, 0x80, 0x07, 0xBC, 0x0F, 0x80, 0x01, 0xFC, 0x0F, 0x80, 0x00, 0x78,
+ 0x0F, 0x80, 0x00, 0x18, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
+ 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char flower_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x18, 0x44, 0x30,
+ 0x00, 0x24, 0x54, 0x48, 0x00, 0x22, 0x54, 0x88, 0x00, 0x11, 0x55, 0x10, 0x00, 0x0A, 0xBA, 0xA0,
+ 0x00, 0x05, 0xBB, 0x40, 0x00, 0x03, 0xC7, 0x80, 0x00, 0x7C, 0x92, 0x7C, 0x00, 0x83, 0x47, 0x82,
+ 0x01, 0x1D, 0x89, 0xF1, 0x00, 0x83, 0x23, 0x82, 0x00, 0x7C, 0x8A, 0x7C, 0x00, 0x03, 0xE7, 0x80,
+ 0x00, 0x05, 0xBB, 0x40, 0x0F, 0x8A, 0xBA, 0xA0, 0x08, 0x91, 0x55, 0x10, 0x08, 0x92, 0x54, 0x90,
+ 0x08, 0x8C, 0x44, 0x6C, 0x08, 0x98, 0x44, 0x32, 0x08, 0xA6, 0x44, 0x42, 0x08, 0xA1, 0x28, 0x82,
+ 0x08, 0xA0, 0xB9, 0x24, 0xF8, 0xFA, 0xBA, 0x44, 0x40, 0x11, 0x6A, 0x88, 0x20, 0x28, 0xED, 0x10,
+ 0x10, 0x46, 0x4A, 0x60, 0x08, 0x81, 0x81, 0x80, 0x05, 0x00, 0x7E, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char flower_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x18, 0x7C, 0x30,
+ 0x00, 0x3C, 0x7C, 0x78, 0x00, 0x3E, 0x7C, 0xF8, 0x00, 0x1F, 0x7D, 0xF0, 0x00, 0x0F, 0xBB, 0xE0,
+ 0x00, 0x07, 0xBB, 0xC0, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x7C, 0xFE, 0x7C, 0x00, 0xFF, 0xFF, 0xFE,
+ 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x7C, 0xFE, 0x7C, 0x00, 0x03, 0xFF, 0x80,
+ 0x00, 0x07, 0xBB, 0xC0, 0x0F, 0x8F, 0xBB, 0xE0, 0x0F, 0x9F, 0x7D, 0xF0, 0x0F, 0x9E, 0x7C, 0xF0,
+ 0x0F, 0x8C, 0x7C, 0x6C, 0x0F, 0x98, 0x7C, 0x3E, 0x0F, 0xBE, 0x7C, 0x7E, 0x0F, 0xBF, 0x38, 0xFE,
+ 0x0F, 0xBF, 0xB9, 0xFC, 0xFF, 0xFF, 0xBB, 0xFC, 0x7F, 0xFF, 0xFB, 0xF8, 0x3F, 0xEF, 0xFF, 0xF0,
+ 0x1F, 0xC7, 0xFF, 0xE0, 0x0F, 0x81, 0xFF, 0x80, 0x07, 0x00, 0x7E, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char path_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x01, 0x85, 0x80, 0x00,
+ 0x06, 0x48, 0x60, 0x00, 0x1A, 0x24, 0x58, 0x00, 0x62, 0x3A, 0x46, 0x00, 0x79, 0xC1, 0x45, 0x80,
+ 0x1E, 0x27, 0xFC, 0x60, 0x07, 0x98, 0x82, 0x58, 0x01, 0xE0, 0x82, 0x46, 0x00, 0x79, 0x45, 0x79,
+ 0x00, 0x1E, 0x28, 0x87, 0x0F, 0x87, 0x94, 0x9E, 0x08, 0x81, 0xE2, 0x78, 0x08, 0x80, 0x79, 0xE0,
+ 0x08, 0x80, 0x1F, 0x80, 0x08, 0x80, 0x06, 0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00,
+ 0x08, 0x80, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
+ 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char path_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x00,
+ 0x07, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xFF, 0x80,
+ 0x1F, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xFF,
+ 0x00, 0x1F, 0xFF, 0xFF, 0x0F, 0x87, 0xFF, 0xFE, 0x0F, 0x81, 0xFF, 0xF8, 0x0F, 0x80, 0x7F, 0xE0,
+ 0x0F, 0x80, 0x1F, 0x80, 0x0F, 0x80, 0x06, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00,
+ 0x0F, 0x80, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
+ 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char dig_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xA4,
+ 0x00, 0x00, 0x01, 0x52, 0x00, 0x00, 0x02, 0x8B, 0x00, 0x00, 0x02, 0x96, 0x00, 0x00, 0x02, 0x6C,
+ 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x08, 0xF0, 0x00, 0x00, 0x11, 0x80, 0x00, 0x03, 0x2A, 0x00,
+ 0x00, 0x04, 0xC6, 0x00, 0x00, 0x09, 0x8C, 0x00, 0x00, 0x15, 0x18, 0x00, 0x00, 0x22, 0x30, 0x00,
+ 0x00, 0x24, 0x78, 0x00, 0x0F, 0xC5, 0xE4, 0x00, 0x08, 0xC7, 0xC4, 0x00, 0x08, 0xC3, 0x28, 0x00,
+ 0x08, 0xA0, 0x10, 0x00, 0x08, 0x90, 0x20, 0x00, 0x08, 0x88, 0xC0, 0x00, 0x08, 0x87, 0x00, 0x00,
+ 0x08, 0x80, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
+ 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char dig_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xFC,
+ 0x00, 0x00, 0x01, 0xDE, 0x00, 0x00, 0x03, 0x8F, 0x00, 0x00, 0x03, 0x9E, 0x00, 0x00, 0x03, 0xFC,
+ 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x03, 0x3E, 0x00,
+ 0x00, 0x07, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x3F, 0xF0, 0x00,
+ 0x00, 0x3F, 0xF8, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xF8, 0x00,
+ 0x0F, 0xBF, 0xF0, 0x00, 0x0F, 0x9F, 0xE0, 0x00, 0x0F, 0x8F, 0xC0, 0x00, 0x0F, 0x87, 0x00, 0x00,
+ 0x0F, 0x80, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
+ 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char water_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x82, 0x00,
+ 0x08, 0x20, 0x82, 0x00, 0x14, 0x51, 0x45, 0x00, 0x63, 0x8E, 0x38, 0xC0, 0x88, 0x20, 0x82, 0x20,
+ 0x77, 0xDF, 0x7D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x82, 0x08, 0x00, 0x20, 0x82, 0x08,
+ 0x00, 0x51, 0x45, 0x14, 0x00, 0x8E, 0x38, 0xE2, 0x0F, 0xA0, 0x82, 0x09, 0x08, 0xDF, 0x7D, 0xF6,
+ 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x82, 0x00, 0x08, 0x80, 0x82, 0x00, 0x08, 0x81, 0x45, 0x00,
+ 0x08, 0x86, 0x38, 0xC0, 0xF8, 0xF8, 0x82, 0x20, 0x40, 0x17, 0x7D, 0xC0, 0x20, 0x20, 0x00, 0x00,
+ 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char water_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x82, 0x00,
+ 0x08, 0x20, 0x82, 0x00, 0x1C, 0x71, 0xC7, 0x00, 0x7F, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xE0,
+ 0x77, 0xDF, 0x7D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x82, 0x08, 0x00, 0x20, 0x82, 0x08,
+ 0x00, 0x71, 0xC7, 0x1C, 0x00, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0xDF, 0x7D, 0xF6,
+ 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x82, 0x00, 0x0F, 0x80, 0x82, 0x00, 0x0F, 0x81, 0xC7, 0x00,
+ 0x0F, 0x87, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xE0, 0x7F, 0xF7, 0x7D, 0xC0, 0x3F, 0xE0, 0x00, 0x00,
+ 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char house_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xF0, 0x00, 0x00, 0x2A, 0x10,
+ 0x00, 0x00, 0x45, 0xE0, 0x00, 0x00, 0x93, 0x20, 0x00, 0x01, 0x19, 0x20, 0x00, 0x02, 0x0C, 0x20,
+ 0x00, 0x04, 0x7E, 0x20, 0x00, 0x08, 0x03, 0x20, 0x00, 0x10, 0xFF, 0x90, 0x00, 0x20, 0x00, 0xC8,
+ 0x00, 0x47, 0xFF, 0xE4, 0x00, 0xF0, 0x00, 0x7E, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10,
+ 0x00, 0x11, 0xEF, 0xD0, 0x00, 0x11, 0x28, 0x50, 0x0F, 0x91, 0x28, 0x50, 0x08, 0x91, 0x28, 0x50,
+ 0x08, 0x91, 0x2F, 0xD0, 0x08, 0x91, 0x20, 0x10, 0x08, 0x91, 0x20, 0x10, 0x08, 0x9F, 0xFF, 0xF0,
+ 0x08, 0x80, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
+ 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char house_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xF0, 0x00, 0x00, 0x3B, 0xF0,
+ 0x00, 0x00, 0x7D, 0xE0, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xE0,
+ 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xF8,
+ 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xF0,
+ 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x1F, 0x38, 0x70, 0x0F, 0x9F, 0x38, 0x70, 0x0F, 0x9F, 0x38, 0x70,
+ 0x0F, 0x9F, 0x3F, 0xF0, 0x0F, 0x9F, 0x3F, 0xF0, 0x0F, 0x9F, 0x3F, 0xF0, 0x0F, 0x9F, 0xFF, 0xF0,
+ 0x0F, 0x80, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
+ 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char volcano_down_cursor_data[32 * 4] = {
+ 0x00, 0x08, 0xA0, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00,
+ 0x00, 0x07, 0xB0, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x17, 0x84, 0x00, 0x00, 0x30, 0x1E, 0x00,
+ 0x00, 0x76, 0x72, 0x00, 0x00, 0x5A, 0x89, 0x00, 0x00, 0x81, 0x1C, 0x80, 0x03, 0x08, 0x0A, 0x70,
+ 0x04, 0x18, 0x17, 0x88, 0x18, 0x30, 0x0A, 0xA6, 0x23, 0xC2, 0x07, 0x7F, 0x7C, 0x5F, 0x8F, 0xEC,
+ 0x40, 0xF0, 0xD8, 0xC0, 0x00, 0x40, 0x20, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00,
+ 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00,
+ 0x08, 0x80, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
+ 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char volcano_down_cursor_mask[32 * 4] = {
+ 0x00, 0x08, 0xA0, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00,
+ 0x00, 0x07, 0xB0, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x3F, 0xFE, 0x00,
+ 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0xF0,
+ 0x07, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x7C, 0x7F, 0xFF, 0xEC,
+ 0x40, 0xF0, 0xF8, 0xC0, 0x00, 0x40, 0x20, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00,
+ 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00,
+ 0x0F, 0x80, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
+ 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char walk_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00,
+ 0x02, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00,
+ 0x00, 0x12, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x1C, 0x00,
+ 0x02, 0x20, 0x22, 0x00, 0x02, 0x10, 0x21, 0x00, 0x01, 0x08, 0x10, 0x80, 0x00, 0x88, 0x08, 0x80,
+ 0x00, 0x72, 0x07, 0x20, 0x00, 0x0D, 0x00, 0xD0, 0x0F, 0x89, 0x00, 0x90, 0x08, 0x86, 0x00, 0x60,
+ 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x0E, 0x00, 0x08, 0x80, 0x11, 0x00, 0x08, 0x80, 0x10, 0x80,
+ 0x08, 0x80, 0x08, 0x40, 0xF8, 0xF8, 0x04, 0x40, 0x40, 0x10, 0x03, 0x90, 0x20, 0x20, 0x00, 0x68,
+ 0x10, 0x40, 0x00, 0x48, 0x08, 0x80, 0x00, 0x30, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char walk_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00,
+ 0x03, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00,
+ 0x00, 0x1E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x1C, 0x00,
+ 0x03, 0xE0, 0x3E, 0x00, 0x03, 0xF0, 0x3F, 0x00, 0x01, 0xF8, 0x1F, 0x80, 0x00, 0xF8, 0x0F, 0x80,
+ 0x00, 0x72, 0x07, 0x20, 0x00, 0x0F, 0x00, 0xF0, 0x0F, 0x8F, 0x00, 0xF0, 0x0F, 0x86, 0x00, 0x60,
+ 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x0E, 0x00, 0x0F, 0x80, 0x1F, 0x00, 0x0F, 0x80, 0x1F, 0x80,
+ 0x0F, 0x80, 0x0F, 0xC0, 0xFF, 0xF8, 0x07, 0xC0, 0x7F, 0xF0, 0x03, 0x90, 0x3F, 0xE0, 0x00, 0x78,
+ 0x1F, 0xC0, 0x00, 0x78, 0x0F, 0x80, 0x00, 0x30, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char paint_down_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xFA,
+ 0x00, 0x00, 0x01, 0xF6, 0x00, 0x00, 0x03, 0xE4, 0x00, 0x03, 0x07, 0xCC, 0x00, 0x07, 0x84, 0x98,
+ 0x00, 0x0F, 0xC8, 0x70, 0x00, 0x1B, 0xF8, 0x60, 0x00, 0x3D, 0xE0, 0xC0, 0x00, 0x7E, 0xE3, 0x00,
+ 0x00, 0xFF, 0x62, 0x00, 0x00, 0xDF, 0xBE, 0x00, 0x00, 0x7F, 0xDF, 0x00, 0x00, 0x37, 0xEF, 0x80,
+ 0x00, 0x1B, 0xF7, 0xC0, 0x07, 0xCF, 0xFB, 0xC0, 0x04, 0x46, 0x9D, 0xC0, 0x04, 0x43, 0x07, 0x80,
+ 0x04, 0x41, 0x83, 0x00, 0x04, 0x40, 0xC6, 0x00, 0x04, 0x40, 0x6C, 0x00, 0x04, 0x40, 0x28, 0x00,
+ 0x7C, 0x7C, 0x10, 0x00, 0x20, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00,
+ 0x04, 0x40, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+unsigned char paint_down_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xFE,
+ 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x03, 0x07, 0xFC, 0x00, 0x07, 0x87, 0xF8,
+ 0x00, 0x0F, 0xCF, 0xF0, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0x00,
+ 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x80,
+ 0x00, 0x1F, 0xFF, 0xC0, 0x07, 0xCF, 0xFF, 0xC0, 0x07, 0xC7, 0xFF, 0xC0, 0x07, 0xC3, 0xFF, 0x80,
+ 0x07, 0xC1, 0xFF, 0x00, 0x07, 0xC0, 0xFE, 0x00, 0x07, 0xC0, 0x7C, 0x00, 0x07, 0xC0, 0x38, 0x00,
+ 0x7F, 0xFC, 0x10, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00,
+ 0x07, 0xC0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+unsigned char entrance_down_cursor_data[32 * 4] = {
+ 0x20, 0x00, 0x00, 0x08, 0x50, 0x00, 0x00, 0x14, 0x88, 0x00, 0x00, 0x22, 0x50, 0x00, 0x00, 0x14,
+ 0x7F, 0xFF, 0xFF, 0xFC, 0x58, 0x00, 0x00, 0x34, 0x54, 0x00, 0x00, 0x54, 0x54, 0x00, 0x00, 0x54,
+ 0x54, 0x00, 0x00, 0x54, 0x5C, 0x00, 0x00, 0x34, 0x5F, 0xFF, 0xFF, 0xF4, 0x50, 0x00, 0x00, 0x14,
+ 0x50, 0x00, 0x00, 0x14, 0x50, 0x00, 0x00, 0x14, 0x50, 0x00, 0x00, 0x14, 0x50, 0x00, 0x00, 0x14,
+ 0x50, 0x00, 0x00, 0x14, 0x5F, 0x80, 0x00, 0x14, 0xD8, 0x80, 0x00, 0x14, 0x58, 0x80, 0x02, 0xB5,
+ 0x58, 0x80, 0x00, 0x14, 0xD8, 0x80, 0x00, 0x14, 0x58, 0x80, 0x05, 0x74, 0x08, 0x80, 0x00, 0x00,
+ 0x08, 0x80, 0x00, 0xD2, 0xF8, 0xF8, 0x0E, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
+ 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+unsigned char entrance_down_cursor_mask[32 * 4] = {
+ 0x20, 0x00, 0x00, 0x08, 0x70, 0x00, 0x00, 0x1C, 0xF8, 0x00, 0x00, 0x3E, 0x70, 0x00, 0x00, 0x1C,
+ 0x7F, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFC, 0x77, 0xFF, 0xFF, 0xDC, 0x77, 0xFF, 0xFF, 0xDC,
+ 0x77, 0xFF, 0xFF, 0xDC, 0x7F, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFC, 0x70, 0x00, 0x00, 0x1C,
+ 0x70, 0x00, 0x00, 0x1C, 0x70, 0x00, 0x00, 0x1C, 0x70, 0x00, 0x00, 0x1C, 0x70, 0x00, 0x00, 0x1C,
+ 0x70, 0x00, 0x00, 0x1C, 0x7F, 0x80, 0x00, 0x1C, 0xFF, 0x80, 0x00, 0x1C, 0x7F, 0x80, 0x02, 0xBD,
+ 0x7F, 0x80, 0x00, 0x1C, 0xFF, 0x80, 0x00, 0x1C, 0x7F, 0x80, 0x05, 0x7C, 0x0F, 0x80, 0x00, 0x00,
+ 0x0F, 0x80, 0x00, 0xD2, 0xFF, 0xF8, 0x0E, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
+ 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+};
+
+unsigned char hand_open_cursor_data[32 * 4] = {
+ 0x00, 0x06, 0x10, 0x00, 0x00, 0x09, 0x38, 0x00, 0x00, 0x09, 0x24, 0x00, 0x03, 0x08, 0xA4, 0x00,
+ 0x04, 0x88, 0xA4, 0xC0, 0x04, 0x48, 0x63, 0x20, 0x04, 0x24, 0x63, 0x10, 0x06, 0x24, 0x61, 0x90,
+ 0x02, 0x14, 0x21, 0x90, 0x03, 0x0C, 0x21, 0x10, 0x01, 0x04, 0x21, 0x10, 0x01, 0x86, 0x01, 0x10,
+ 0x00, 0x82, 0x00, 0x08, 0x00, 0xC0, 0x00, 0x08, 0x00, 0x60, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08,
+ 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x08, 0x00, 0x10, 0x00, 0x08, 0x00, 0x10, 0x00, 0x08,
+ 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10,
+ 0x0F, 0xC0, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x14, 0x00, 0x00, 0x08, 0x12, 0x00, 0x00, 0x08,
+ 0x0F, 0x0F, 0x00, 0x04, 0x01, 0xF9, 0x80, 0x04, 0x00, 0x00, 0xC0, 0x18, 0x00, 0x00, 0x7F, 0xE0,
+};
+unsigned char hand_open_cursor_mask[32 * 4] = {
+ 0x00, 0x06, 0x10, 0x00, 0x00, 0x0F, 0x38, 0x00, 0x00, 0x0F, 0x3C, 0x00, 0x03, 0x0F, 0xBC, 0x00,
+ 0x07, 0x8F, 0xBC, 0xC0, 0x07, 0xCF, 0xFF, 0xE0, 0x07, 0xE7, 0xFF, 0xF0, 0x07, 0xE7, 0xFF, 0xF0,
+ 0x03, 0xF7, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xF0,
+ 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF8,
+ 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xF8,
+ 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xF0,
+ 0x0F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xF8,
+ 0x0F, 0xFF, 0xFF, 0xFC, 0x01, 0xF9, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xE0,
+};
+
+unsigned char hand_closed_cursor_data[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0xE0, 0x00, 0x00, 0x43, 0x10, 0x00, 0x00, 0x41, 0x8C, 0x00,
+ 0x00, 0x20, 0x87, 0x00, 0x0E, 0x20, 0x42, 0x80, 0x11, 0x98, 0x62, 0x40, 0x10, 0x6C, 0x61, 0x20,
+ 0x18, 0x14, 0x21, 0x20, 0x0C, 0x0C, 0x21, 0x10, 0x06, 0x04, 0x21, 0x10, 0x03, 0x06, 0x01, 0x10,
+ 0x00, 0x82, 0x00, 0x08, 0x00, 0xC0, 0x00, 0x08, 0x00, 0x60, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08,
+ 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x08, 0x00, 0x10, 0x00, 0x08, 0x00, 0x10, 0x00, 0x08,
+ 0x07, 0x10, 0x00, 0x10, 0x08, 0x90, 0x00, 0x10, 0x08, 0x60, 0x00, 0x10, 0x0A, 0x00, 0x00, 0x10,
+ 0x0A, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x08, 0x03, 0x80, 0x00, 0x08,
+ 0x00, 0x7F, 0x00, 0x04, 0x00, 0x01, 0x80, 0x04, 0x00, 0x00, 0xC0, 0x18, 0x00, 0x00, 0x7F, 0xE0,
+};
+unsigned char hand_closed_cursor_mask[32 * 4] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0xE0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x7F, 0xFC, 0x00,
+ 0x00, 0x3F, 0xFF, 0x00, 0x0E, 0x3F, 0xFF, 0x80, 0x1F, 0x9F, 0xFF, 0xC0, 0x1F, 0xEF, 0xFF, 0xE0,
+ 0x1F, 0xF7, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xF0,
+ 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF8,
+ 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xF8,
+ 0x07, 0x1F, 0xFF, 0xF0, 0x0F, 0x9F, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0,
+ 0x0F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xF8,
+ 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xE0,
+};
\ No newline at end of file
diff --git a/src/cursors.h b/src/cursors.h
index 531abf7e62..19b19a2448 100644
--- a/src/cursors.h
+++ b/src/cursors.h
@@ -21,571 +21,164 @@
#ifndef _CURSORS_H_
#define _CURSORS_H_
-#define NO_CURSORS 27
+enum {
+ CURSOR_ARROW = 0,
+ CURSOR_BLANK = 1,
+ CURSOR_UP_ARROW = 2,
+ CURSOR_UP_DOWN_ARROW = 3,
+ CURSOR_HAND_POINT = 4,
+ CURSOR_ZZZ = 5,
+ CURSOR_DIAGONAL_ARROWS = 6,
+ CURSOR_PICKER = 7,
+ CURSOR_TREE_DOWN = 8,
+ CURSOR_FOUNTAIN_DOWN = 9,
+ CURSOR_STATUE_DOWN = 10,
+ CURSOR_BENCH_DOWN = 11,
+ CURSOR_CROSS_HAIR = 12,
+ CURSOR_BIN_DOWN = 13,
+ CURSOR_LAMPPOST_DOWN = 14,
+ CURSOR_FENCE_DOWN = 15,
+ CURSOR_FLOWER_DOWN = 16,
+ CURSOR_PATH_DOWN = 17,
+ CURSOR_DIG_DOWN = 18,
+ CURSOR_WATER_DOWN = 19,
+ CURSOR_HOUSE_DOWN = 20,
+ CURSOR_VOLCANO_DOWN = 21,
+ CURSOR_WALK_DOWN = 22,
+ CURSOR_PAINT_DOWN = 23,
+ CURSOR_ENTRANCE_DOWN = 24,
+ CURSOR_HAND_OPEN = 25,
+ CURSOR_HAND_CLOSED = 26,
+ CURSOR_COUNT
+};
-unsigned char blank_cursor_data[32 * 4] = {
- 0
-};
-unsigned char blank_cursor_mask[32 * 4] = {
- 0
-};
+extern unsigned char blank_cursor_data[32 * 4];
+extern unsigned char blank_cursor_mask[32 * 4];
#define BLANK_CURSOR_HOTX 0
#define BLANK_CURSOR_HOTY 0
-unsigned char up_arrow_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x04, 0x10, 0x00,
- 0x00, 0x08, 0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x02, 0x20, 0x00,
- 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00,
- 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-unsigned char up_arrow_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xF0, 0x00,
- 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x03, 0xE0, 0x00,
- 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00,
- 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
+extern unsigned char up_arrow_cursor_data[32 * 4];
+extern unsigned char up_arrow_cursor_mask[32 * 4];
#define UP_ARROW_CURSOR_HOTX 15
#define UP_ARROW_CURSOR_HOTY 0
-unsigned char up_down_arrow_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0xA0, 0x00,
- 0x00, 0x05, 0x50, 0x00, 0x00, 0x0A, 0x28, 0x00, 0x00, 0x17, 0x74, 0x00, 0x00, 0x21, 0x42, 0x00,
- 0x00, 0x1D, 0xDC, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x20, 0x00,
- 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0xE0, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x05, 0xD0, 0x00, 0x00, 0x1D, 0x5C, 0x00,
- 0x00, 0x21, 0x42, 0x00, 0x00, 0x17, 0x74, 0x00, 0x00, 0x0A, 0x28, 0x00, 0x00, 0x05, 0x50, 0x00,
- 0x00, 0x02, 0xA0, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-unsigned char up_down_arrow_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00,
- 0x00, 0x07, 0x70, 0x00, 0x00, 0x0E, 0x38, 0x00, 0x00, 0x1F, 0x7C, 0x00, 0x00, 0x3F, 0x7E, 0x00,
- 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x03, 0xE0, 0x00,
- 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0xE0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x1F, 0x7C, 0x00,
- 0x00, 0x3F, 0x7E, 0x00, 0x00, 0x1F, 0x7C, 0x00, 0x00, 0x0E, 0x38, 0x00, 0x00, 0x07, 0x70, 0x00,
- 0x00, 0x03, 0xE0, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
+extern unsigned char up_down_arrow_cursor_data[32 * 4];
+extern unsigned char up_down_arrow_cursor_mask[32 * 4];
#define UP_DOWN_ARROW_CURSOR_HOTX 7
#define UP_DOWN_ARROW_CURSOR_HOTY 31
-unsigned char zzz_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C,
- 0x00, 0x00, 0x03, 0xE2, 0x00, 0x00, 0xFC, 0x34, 0x00, 0x01, 0x07, 0x62, 0x00, 0x3F, 0xEA, 0xDC,
- 0x00, 0x40, 0xD4, 0x20, 0x00, 0x3D, 0xBB, 0xC0, 0x3F, 0xCB, 0x04, 0x00, 0x40, 0x34, 0xF8, 0x00,
- 0x40, 0x2F, 0x00, 0x00, 0x3C, 0x40, 0x80, 0x00, 0x08, 0xBF, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
- 0x23, 0xC0, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-unsigned char zzz_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C,
- 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x3F, 0xFB, 0xDC,
- 0x00, 0x7F, 0xF7, 0xE0, 0x00, 0x3F, 0xFB, 0xC0, 0x3F, 0xCF, 0xFC, 0x00, 0x7F, 0xFC, 0xF8, 0x00,
- 0x7F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x0F, 0xBF, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00,
- 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
+extern unsigned char zzz_cursor_data[32 * 4];
+extern unsigned char zzz_cursor_mask[32 * 4];
#define ZZZ_CURSOR_HOTX 0
#define ZZZ_CURSOR_HOTY 0
-unsigned char diagonal_arrow_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
- 0x48, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00,
- 0x00, 0x1C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-unsigned char diagonal_arrow_cursor_mask[32 * 4] = {
- 0xFE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00,
- 0xFC, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00,
- 0x01, 0xC2, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00,
- 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
+extern unsigned char diagonal_arrow_cursor_data[32 * 4];
+extern unsigned char diagonal_arrow_cursor_mask[32 * 4];
#define DIAGONAL_ARROW_CURSOR_HOTX 0
#define DIAGONAL_ARROW_CURSOR_HOTY 0
-unsigned char picker_cursor_data[32 * 4] = {
- 0x00, 0x07, 0xC0, 0x00, 0x00, 0x08, 0x60, 0x00, 0x00, 0x13, 0x30, 0x00, 0x00, 0x17, 0xB0, 0x00,
- 0x00, 0x17, 0xB0, 0x00, 0x00, 0x13, 0x30, 0x00, 0x00, 0x08, 0x60, 0x00, 0x00, 0x0F, 0xE0, 0x00,
- 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x17, 0x30, 0x00, 0x00, 0x12, 0x30, 0x00, 0x00, 0x21, 0x18, 0x00,
- 0x00, 0x23, 0x18, 0x00, 0x00, 0x44, 0x8C, 0x00, 0x00, 0x44, 0x8C, 0x00, 0x00, 0x88, 0x46, 0x00,
- 0x00, 0x90, 0x26, 0x00, 0x01, 0x10, 0x23, 0x00, 0x01, 0x20, 0x13, 0x00, 0x02, 0x40, 0x09, 0x80,
- 0x02, 0x40, 0x09, 0x80, 0x04, 0x80, 0x04, 0xC0, 0x04, 0x80, 0x04, 0xC0, 0x04, 0x80, 0x04, 0xC0,
- 0x04, 0x80, 0x04, 0xC0, 0x04, 0x80, 0x04, 0xC0, 0x04, 0x40, 0x08, 0xC0, 0x02, 0x40, 0x09, 0x80,
- 0x01, 0x20, 0x13, 0x00, 0x00, 0x90, 0x26, 0x00, 0x00, 0x68, 0x5C, 0x00, 0x00, 0x1C, 0xF0, 0x00,
-};
-unsigned char picker_cursor_mask[32 * 4] = {
- 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00,
- 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x00,
- 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xF8, 0x00,
- 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7C, 0xFC, 0x00, 0x00, 0x7C, 0xFC, 0x00, 0x00, 0xF8, 0x7E, 0x00,
- 0x00, 0xF0, 0x3E, 0x00, 0x01, 0xF0, 0x3F, 0x00, 0x01, 0xE0, 0x1F, 0x00, 0x03, 0xC0, 0x0F, 0x80,
- 0x03, 0xC0, 0x0F, 0x80, 0x07, 0x80, 0x07, 0xC0, 0x07, 0x80, 0x07, 0xC0, 0x07, 0x80, 0x07, 0xC0,
- 0x07, 0x80, 0x07, 0xC0, 0x07, 0x80, 0x07, 0xC0, 0x07, 0xC0, 0x0F, 0xC0, 0x03, 0xC0, 0x0F, 0x80,
- 0x01, 0xE0, 0x1F, 0x00, 0x00, 0xF0, 0x3E, 0x00, 0x00, 0x78, 0x7C, 0x00, 0x00, 0x1C, 0xF0, 0x00,
-};
+extern unsigned char picker_cursor_data[32 * 4];
+extern unsigned char picker_cursor_mask[32 * 4];
#define PICKER_CURSOR_HOTX 15
#define PICKER_CURSOR_HOTY 31
-unsigned char tree_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x01, 0x89, 0xC0, 0x00, 0x02, 0x06, 0x20,
- 0x00, 0x07, 0x00, 0x18, 0x00, 0x07, 0x40, 0x04, 0x00, 0x03, 0x80, 0x04, 0x00, 0x01, 0xC0, 0x02,
- 0x00, 0x03, 0x82, 0x02, 0x00, 0x03, 0xD0, 0x04, 0x00, 0x07, 0xF9, 0x08, 0x00, 0x0F, 0x6E, 0x04,
- 0x00, 0x0E, 0xB8, 0x82, 0x00, 0x0F, 0x44, 0x22, 0x00, 0x0F, 0xA8, 0x46, 0x00, 0x0F, 0xFC, 0x16,
- 0x00, 0x07, 0xEE, 0x8C, 0x0F, 0x81, 0xFF, 0xD8, 0x08, 0x80, 0x7D, 0xF0, 0x08, 0x80, 0x3A, 0x00,
- 0x08, 0x80, 0x1A, 0x00, 0x08, 0x80, 0x1A, 0x00, 0x08, 0x80, 0x12, 0x00, 0x08, 0x80, 0x12, 0x00,
- 0x08, 0x80, 0x11, 0x00, 0xF8, 0xF8, 0x60, 0x80, 0x40, 0x11, 0x80, 0x60, 0x20, 0x22, 0x09, 0x90,
- 0x10, 0x41, 0xD5, 0x60, 0x08, 0x80, 0x22, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char tree_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x01, 0xF9, 0xC0, 0x00, 0x03, 0xFF, 0xE0,
- 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFE,
- 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFC,
- 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFE,
- 0x00, 0x07, 0xFF, 0xFC, 0x0F, 0x81, 0xFF, 0xF8, 0x0F, 0x80, 0x7F, 0xF0, 0x0F, 0x80, 0x3E, 0x00,
- 0x0F, 0x80, 0x1E, 0x00, 0x0F, 0x80, 0x1E, 0x00, 0x0F, 0x80, 0x1E, 0x00, 0x0F, 0x80, 0x1E, 0x00,
- 0x0F, 0x80, 0x1F, 0x00, 0xFF, 0xF8, 0x7F, 0x80, 0x7F, 0xF1, 0xFF, 0xE0, 0x3F, 0xE3, 0xFF, 0xF0,
- 0x1F, 0xC1, 0xF7, 0x60, 0x0F, 0x80, 0x22, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char tree_down_cursor_data[32 * 4];
+extern unsigned char tree_down_cursor_mask[32 * 4];
#define TREE_DOWN_CURSOR_HOTX 7
#define TREE_DOWN_CURSOR_HOTY 31
-unsigned char fountain_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0E, 0x00,
- 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x7B, 0xC0, 0x00, 0x01, 0x8B, 0x30, 0x00, 0x02, 0x17, 0xC8,
- 0x00, 0x02, 0x0F, 0x88, 0x0F, 0x83, 0x80, 0x38, 0x08, 0x82, 0x7F, 0xD8, 0x08, 0x81, 0x01, 0xF0,
- 0x08, 0x80, 0xE3, 0xE0, 0x08, 0x80, 0x3F, 0x80, 0x08, 0x80, 0x17, 0x00, 0x08, 0x80, 0x13, 0x00,
- 0x08, 0x80, 0x13, 0x00, 0xF8, 0xF8, 0x27, 0x80, 0x40, 0x10, 0x4E, 0xC0, 0x20, 0x20, 0x80, 0xE0,
- 0x10, 0x40, 0xC1, 0xA0, 0x08, 0x80, 0x7F, 0xC0, 0x05, 0x00, 0x1F, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char fountain_down_cursor_mask[32 * 4] = {
- 0x00, 0x01, 0x04, 0x00, 0x00, 0x10, 0x10, 0x81, 0x00, 0x00, 0x41, 0x14, 0x00, 0x05, 0x08, 0x20,
- 0x00, 0x00, 0x22, 0x81, 0x00, 0x00, 0x88, 0x10, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x02, 0x00,
- 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0E, 0x00,
- 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x01, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xF8,
- 0x00, 0x03, 0xFF, 0xF8, 0x0F, 0x83, 0xFF, 0xF8, 0x0F, 0x83, 0xFF, 0xF8, 0x0F, 0x81, 0xFF, 0xF0,
- 0x0F, 0x80, 0xFF, 0xE0, 0x0F, 0x80, 0x3F, 0x80, 0x0F, 0x80, 0x1F, 0x00, 0x0F, 0x80, 0x1F, 0x00,
- 0x0F, 0x80, 0x1F, 0x00, 0xFF, 0xF8, 0x3F, 0x80, 0x7F, 0xF0, 0x7F, 0xC0, 0x3F, 0xE0, 0xFF, 0xE0,
- 0x1F, 0xC0, 0xFF, 0xE0, 0x0F, 0x80, 0x7F, 0xC0, 0x07, 0x00, 0x1F, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char fountain_down_cursor_data[32 * 4];
+extern unsigned char fountain_down_cursor_mask[32 * 4];
#define FOUNTAIN_DOWN_CURSOR_HOTX 7
#define FOUNTAIN_DOWN_CURSOR_HOTY 31
-unsigned char statue_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x07, 0x03, 0x30,
- 0x00, 0x02, 0x84, 0x98, 0x00, 0x01, 0x44, 0x98, 0x00, 0x00, 0xB5, 0xA8, 0x00, 0x00, 0x4A, 0xD0,
- 0x00, 0x00, 0x21, 0x20, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x10, 0x80,
- 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x0F, 0x80, 0x08, 0x80, 0x08, 0x80, 0x04, 0x80, 0x08, 0x80, 0x05, 0x00,
- 0x08, 0x80, 0x0D, 0x00, 0x08, 0x80, 0x09, 0x00, 0x08, 0x80, 0x3F, 0x80, 0x08, 0x80, 0x20, 0x80,
- 0x08, 0x80, 0x20, 0x80, 0xF8, 0xF8, 0x20, 0x80, 0x40, 0x10, 0x20, 0x80, 0x20, 0x20, 0x20, 0x80,
- 0x10, 0x40, 0x7F, 0xC0, 0x08, 0x80, 0x80, 0x20, 0x05, 0x00, 0xFF, 0xE0, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char statue_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x07, 0x03, 0x30,
- 0x00, 0x03, 0x87, 0x98, 0x00, 0x01, 0xC7, 0x98, 0x00, 0x00, 0xF7, 0xB8, 0x00, 0x00, 0x7E, 0xF0,
- 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x1F, 0x80,
- 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00,
- 0x00, 0x00, 0x07, 0x00, 0x0F, 0x80, 0x0F, 0x80, 0x0F, 0x80, 0x07, 0x80, 0x0F, 0x80, 0x07, 0x00,
- 0x0F, 0x80, 0x0F, 0x00, 0x0F, 0x80, 0x0F, 0x00, 0x0F, 0x80, 0x3F, 0x80, 0x0F, 0x80, 0x3F, 0x80,
- 0x0F, 0x80, 0x3F, 0x80, 0xFF, 0xF8, 0x3F, 0x80, 0x7F, 0xF0, 0x3F, 0x80, 0x3F, 0xE0, 0x3F, 0x80,
- 0x1F, 0xC0, 0x7F, 0xC0, 0x0F, 0x80, 0xFF, 0xE0, 0x07, 0x00, 0xFF, 0xE0, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char statue_down_cursor_data[32 * 4];
+extern unsigned char statue_down_cursor_mask[32 * 4];
#define STATUE_DOWN_CURSOR_HOTX 7
#define STATUE_DOWN_CURSOR_HOTY 31
-unsigned char bench_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00,
- 0x00, 0x04, 0x60, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x05, 0x81, 0x80,
- 0x00, 0x05, 0x60, 0x60, 0x00, 0x0D, 0x18, 0x18, 0x00, 0x33, 0x06, 0x04, 0x00, 0xC0, 0xC1, 0x84,
- 0x00, 0xF0, 0x30, 0x64, 0x00, 0xAC, 0x0C, 0x1C, 0x00, 0xA7, 0x03, 0x14, 0x00, 0x40, 0xC0, 0xD4,
- 0x00, 0x00, 0xF0, 0x34, 0x0F, 0x80, 0xAC, 0x0C, 0x08, 0x80, 0xA3, 0x3C, 0x08, 0x80, 0x41, 0xD4,
- 0x08, 0x80, 0x01, 0xD4, 0x08, 0x80, 0x01, 0x48, 0x08, 0x80, 0x01, 0x40, 0x08, 0x80, 0x00, 0x80,
- 0x08, 0x80, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
- 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char bench_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00,
- 0x00, 0x07, 0xE0, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x80,
- 0x00, 0x07, 0x7F, 0xE0, 0x00, 0x0F, 0x1F, 0xF8, 0x00, 0x3F, 0x07, 0xFC, 0x00, 0xFF, 0xC1, 0xFC,
- 0x00, 0xFF, 0xF0, 0x7C, 0x00, 0xEF, 0xFC, 0x1C, 0x00, 0xE7, 0xFF, 0x1C, 0x00, 0x40, 0xFF, 0xDC,
- 0x00, 0x00, 0xFF, 0xFC, 0x0F, 0x80, 0xEF, 0xFC, 0x0F, 0x80, 0xE3, 0xFC, 0x0F, 0x80, 0x41, 0xDC,
- 0x0F, 0x80, 0x01, 0xDC, 0x0F, 0x80, 0x01, 0xC8, 0x0F, 0x80, 0x01, 0xC0, 0x0F, 0x80, 0x00, 0x80,
- 0x0F, 0x80, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
- 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char bench_down_cursor_data[32 * 4];
+extern unsigned char bench_down_cursor_mask[32 * 4];
#define BENCH_DOWN_CURSOR_HOTX 7
#define BENCH_DOWN_CURSOR_HOTY 31
-unsigned char cross_hair_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
- 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
- 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE2, 0x3F, 0x80,
- 0x10, 0x15, 0x40, 0x40, 0x0F, 0xE2, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
- 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
- 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-unsigned char cross_hair_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
- 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
- 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE2, 0x3F, 0x80,
- 0x1F, 0xF7, 0x7F, 0xC0, 0x0F, 0xE2, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
- 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
- 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
+extern unsigned char cross_hair_cursor_data[32 * 4];
+extern unsigned char cross_hair_cursor_mask[32 * 4];
#define CROSS_HAIR_CURSOR_HOTX 15
#define CROSS_HAIR_CURSOR_HOTY 15
-unsigned char bin_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x22, 0x00,
- 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0xC3, 0x80, 0x00, 0x01, 0x00, 0xC0, 0x00, 0x02, 0x57, 0xE0,
- 0x00, 0x02, 0x00, 0x60, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x01, 0x01, 0xC0, 0x00, 0x01, 0x40, 0xC0,
- 0x00, 0x01, 0x50, 0xC0, 0x0F, 0x81, 0x50, 0x40, 0x08, 0x81, 0x51, 0x40, 0x08, 0x81, 0x51, 0x40,
- 0x08, 0x81, 0x55, 0x40, 0x08, 0x81, 0x55, 0x40, 0x08, 0x81, 0x55, 0x40, 0x08, 0x81, 0x55, 0x40,
- 0x08, 0x81, 0x55, 0x40, 0xF8, 0xF9, 0x55, 0x40, 0x40, 0x11, 0x55, 0x40, 0x20, 0x21, 0xFF, 0xC0,
- 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char bin_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x22, 0x00,
- 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0xE0,
- 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xC0,
- 0x00, 0x01, 0xFF, 0xC0, 0x0F, 0x81, 0xFF, 0xC0, 0x0F, 0x81, 0xFF, 0xC0, 0x0F, 0x81, 0xFF, 0xC0,
- 0x0F, 0x81, 0xFF, 0xC0, 0x0F, 0x81, 0xFF, 0xC0, 0x0F, 0x81, 0xFF, 0xC0, 0x0F, 0x81, 0xFF, 0xC0,
- 0x0F, 0x81, 0xFF, 0xC0, 0xFF, 0xF9, 0xFF, 0xC0, 0x7F, 0xF1, 0xFF, 0xC0, 0x3F, 0xE1, 0xFF, 0xC0,
- 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char bin_down_cursor_data[32 * 4];
+extern unsigned char bin_down_cursor_mask[32 * 4];
#define BIN_DOWN_CURSOR_HOTX 7
#define BIN_DOWN_CURSOR_HOTY 31
-unsigned char lamppost_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0xFF, 0x80,
- 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x32, 0x00,
- 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x94, 0x80,
- 0x00, 0x01, 0xF7, 0xC0, 0x00, 0x00, 0x94, 0x80, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00,
- 0x00, 0x00, 0x14, 0x00, 0x0F, 0x80, 0x14, 0x00, 0x08, 0x80, 0x14, 0x00, 0x08, 0x80, 0x14, 0x00,
- 0x08, 0x80, 0x14, 0x00, 0x08, 0x80, 0x14, 0x00, 0x08, 0x80, 0x14, 0x00, 0x08, 0x80, 0x1C, 0x00,
- 0x08, 0x80, 0x1C, 0x00, 0xF8, 0xF8, 0x32, 0x00, 0x40, 0x10, 0x61, 0x00, 0x20, 0x20, 0x61, 0x00,
- 0x10, 0x40, 0x71, 0x00, 0x08, 0x80, 0x7D, 0x00, 0x05, 0x00, 0xFF, 0x80, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char lamppost_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0x80,
- 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x3E, 0x00,
- 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x9C, 0x80,
- 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x9C, 0x80, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x1C, 0x00,
- 0x00, 0x00, 0x1C, 0x00, 0x0F, 0x80, 0x1C, 0x00, 0x0F, 0x80, 0x1C, 0x00, 0x0F, 0x80, 0x1C, 0x00,
- 0x0F, 0x80, 0x1C, 0x00, 0x0F, 0x80, 0x1C, 0x00, 0x0F, 0x80, 0x1C, 0x00, 0x0F, 0x80, 0x1C, 0x00,
- 0x0F, 0x80, 0x1C, 0x00, 0xFF, 0xF8, 0x3E, 0x00, 0x7F, 0xF0, 0x7F, 0x00, 0x3F, 0xE0, 0x7F, 0x00,
- 0x1F, 0xC0, 0x7F, 0x00, 0x0F, 0x80, 0x7F, 0x00, 0x07, 0x00, 0xFF, 0x80, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char lamppost_down_cursor_data[32 * 4];
+extern unsigned char lamppost_down_cursor_mask[32 * 4];
#define LAMPPOST_DOWN_CURSOR_HOTX 7
#define LAMPPOST_DOWN_CURSOR_HOTY 31
-unsigned char fence_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x4E, 0x60, 0x00, 0x00,
- 0x43, 0xB0, 0x00, 0x00, 0x20, 0xB1, 0x80, 0x00, 0x2C, 0x3A, 0xC0, 0x00, 0x2F, 0x0E, 0xC6, 0x00,
- 0x2C, 0x82, 0xCB, 0x00, 0x2C, 0xB0, 0x6B, 0x18, 0x6C, 0xBC, 0x1B, 0x2C, 0x7C, 0xB2, 0x83, 0x2C,
- 0x1E, 0xB2, 0xE1, 0xAC, 0x07, 0xB2, 0xD8, 0x6C, 0x01, 0xF2, 0xCA, 0x0C, 0x00, 0x7A, 0xCB, 0x86,
- 0x00, 0x1E, 0xCB, 0x66, 0x0F, 0x87, 0xCB, 0x2E, 0x08, 0x81, 0xEB, 0x2C, 0x08, 0x80, 0x7B, 0x2C,
- 0x08, 0x80, 0x1F, 0x2C, 0x08, 0x80, 0x07, 0xAC, 0x08, 0x80, 0x01, 0xEC, 0x08, 0x80, 0x00, 0x78,
- 0x08, 0x80, 0x00, 0x18, 0xF8, 0xF8, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
- 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char fence_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x7E, 0x60, 0x00, 0x00,
- 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xF1, 0x80, 0x00, 0x3F, 0xFB, 0xC0, 0x00, 0x3F, 0xFF, 0xC6, 0x00,
- 0x3C, 0xFF, 0xCF, 0x00, 0x3C, 0xFF, 0xEF, 0x18, 0x7C, 0xFF, 0xFF, 0x3C, 0x7C, 0xF3, 0xFF, 0x3C,
- 0x1E, 0xF3, 0xFF, 0xBC, 0x07, 0xF3, 0xDF, 0xFC, 0x01, 0xF3, 0xCF, 0xFC, 0x00, 0x7B, 0xCF, 0xFE,
- 0x00, 0x1F, 0xCF, 0x7E, 0x0F, 0x87, 0xCF, 0x3E, 0x0F, 0x81, 0xEF, 0x3C, 0x0F, 0x80, 0x7F, 0x3C,
- 0x0F, 0x80, 0x1F, 0x3C, 0x0F, 0x80, 0x07, 0xBC, 0x0F, 0x80, 0x01, 0xFC, 0x0F, 0x80, 0x00, 0x78,
- 0x0F, 0x80, 0x00, 0x18, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
- 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char fence_down_cursor_data[32 * 4];
+extern unsigned char fence_down_cursor_mask[32 * 4];
#define FENCE_DOWN_CURSOR_HOTX 7
#define FENCE_DOWN_CURSOR_HOTY 31
-unsigned char flower_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x18, 0x44, 0x30,
- 0x00, 0x24, 0x54, 0x48, 0x00, 0x22, 0x54, 0x88, 0x00, 0x11, 0x55, 0x10, 0x00, 0x0A, 0xBA, 0xA0,
- 0x00, 0x05, 0xBB, 0x40, 0x00, 0x03, 0xC7, 0x80, 0x00, 0x7C, 0x92, 0x7C, 0x00, 0x83, 0x47, 0x82,
- 0x01, 0x1D, 0x89, 0xF1, 0x00, 0x83, 0x23, 0x82, 0x00, 0x7C, 0x8A, 0x7C, 0x00, 0x03, 0xE7, 0x80,
- 0x00, 0x05, 0xBB, 0x40, 0x0F, 0x8A, 0xBA, 0xA0, 0x08, 0x91, 0x55, 0x10, 0x08, 0x92, 0x54, 0x90,
- 0x08, 0x8C, 0x44, 0x6C, 0x08, 0x98, 0x44, 0x32, 0x08, 0xA6, 0x44, 0x42, 0x08, 0xA1, 0x28, 0x82,
- 0x08, 0xA0, 0xB9, 0x24, 0xF8, 0xFA, 0xBA, 0x44, 0x40, 0x11, 0x6A, 0x88, 0x20, 0x28, 0xED, 0x10,
- 0x10, 0x46, 0x4A, 0x60, 0x08, 0x81, 0x81, 0x80, 0x05, 0x00, 0x7E, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char flower_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x18, 0x7C, 0x30,
- 0x00, 0x3C, 0x7C, 0x78, 0x00, 0x3E, 0x7C, 0xF8, 0x00, 0x1F, 0x7D, 0xF0, 0x00, 0x0F, 0xBB, 0xE0,
- 0x00, 0x07, 0xBB, 0xC0, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x7C, 0xFE, 0x7C, 0x00, 0xFF, 0xFF, 0xFE,
- 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x7C, 0xFE, 0x7C, 0x00, 0x03, 0xFF, 0x80,
- 0x00, 0x07, 0xBB, 0xC0, 0x0F, 0x8F, 0xBB, 0xE0, 0x0F, 0x9F, 0x7D, 0xF0, 0x0F, 0x9E, 0x7C, 0xF0,
- 0x0F, 0x8C, 0x7C, 0x6C, 0x0F, 0x98, 0x7C, 0x3E, 0x0F, 0xBE, 0x7C, 0x7E, 0x0F, 0xBF, 0x38, 0xFE,
- 0x0F, 0xBF, 0xB9, 0xFC, 0xFF, 0xFF, 0xBB, 0xFC, 0x7F, 0xFF, 0xFB, 0xF8, 0x3F, 0xEF, 0xFF, 0xF0,
- 0x1F, 0xC7, 0xFF, 0xE0, 0x0F, 0x81, 0xFF, 0x80, 0x07, 0x00, 0x7E, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char flower_down_cursor_data[32 * 4];
+extern unsigned char flower_down_cursor_mask[32 * 4];
#define FLOWER_DOWN_CURSOR_HOTX 7
#define FLOWER_DOWN_CURSOR_HOTY 31
-unsigned char path_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x01, 0x85, 0x80, 0x00,
- 0x06, 0x48, 0x60, 0x00, 0x1A, 0x24, 0x58, 0x00, 0x62, 0x3A, 0x46, 0x00, 0x79, 0xC1, 0x45, 0x80,
- 0x1E, 0x27, 0xFC, 0x60, 0x07, 0x98, 0x82, 0x58, 0x01, 0xE0, 0x82, 0x46, 0x00, 0x79, 0x45, 0x79,
- 0x00, 0x1E, 0x28, 0x87, 0x0F, 0x87, 0x94, 0x9E, 0x08, 0x81, 0xE2, 0x78, 0x08, 0x80, 0x79, 0xE0,
- 0x08, 0x80, 0x1F, 0x80, 0x08, 0x80, 0x06, 0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00,
- 0x08, 0x80, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
- 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char path_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x00,
- 0x07, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xFF, 0x80,
- 0x1F, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xFF,
- 0x00, 0x1F, 0xFF, 0xFF, 0x0F, 0x87, 0xFF, 0xFE, 0x0F, 0x81, 0xFF, 0xF8, 0x0F, 0x80, 0x7F, 0xE0,
- 0x0F, 0x80, 0x1F, 0x80, 0x0F, 0x80, 0x06, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00,
- 0x0F, 0x80, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
- 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char path_down_cursor_data[32 * 4];
+extern unsigned char path_down_cursor_mask[32 * 4];
#define PATH_DOWN_CURSOR_HOTX 7
#define PATH_DOWN_CURSOR_HOTY 31
-unsigned char dig_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xA4,
- 0x00, 0x00, 0x01, 0x52, 0x00, 0x00, 0x02, 0x8B, 0x00, 0x00, 0x02, 0x96, 0x00, 0x00, 0x02, 0x6C,
- 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x08, 0xF0, 0x00, 0x00, 0x11, 0x80, 0x00, 0x03, 0x2A, 0x00,
- 0x00, 0x04, 0xC6, 0x00, 0x00, 0x09, 0x8C, 0x00, 0x00, 0x15, 0x18, 0x00, 0x00, 0x22, 0x30, 0x00,
- 0x00, 0x24, 0x78, 0x00, 0x0F, 0xC5, 0xE4, 0x00, 0x08, 0xC7, 0xC4, 0x00, 0x08, 0xC3, 0x28, 0x00,
- 0x08, 0xA0, 0x10, 0x00, 0x08, 0x90, 0x20, 0x00, 0x08, 0x88, 0xC0, 0x00, 0x08, 0x87, 0x00, 0x00,
- 0x08, 0x80, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
- 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char dig_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xFC,
- 0x00, 0x00, 0x01, 0xDE, 0x00, 0x00, 0x03, 0x8F, 0x00, 0x00, 0x03, 0x9E, 0x00, 0x00, 0x03, 0xFC,
- 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x03, 0x3E, 0x00,
- 0x00, 0x07, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x3F, 0xF0, 0x00,
- 0x00, 0x3F, 0xF8, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xF8, 0x00,
- 0x0F, 0xBF, 0xF0, 0x00, 0x0F, 0x9F, 0xE0, 0x00, 0x0F, 0x8F, 0xC0, 0x00, 0x0F, 0x87, 0x00, 0x00,
- 0x0F, 0x80, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
- 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char dig_down_cursor_data[32 * 4];
+extern unsigned char dig_down_cursor_mask[32 * 4];
#define DIG_DOWN_CURSOR_HOTX 7
#define DIG_DOWN_CURSOR_HOTY 31
-unsigned char water_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x82, 0x00,
- 0x08, 0x20, 0x82, 0x00, 0x14, 0x51, 0x45, 0x00, 0x63, 0x8E, 0x38, 0xC0, 0x88, 0x20, 0x82, 0x20,
- 0x77, 0xDF, 0x7D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x82, 0x08, 0x00, 0x20, 0x82, 0x08,
- 0x00, 0x51, 0x45, 0x14, 0x00, 0x8E, 0x38, 0xE2, 0x0F, 0xA0, 0x82, 0x09, 0x08, 0xDF, 0x7D, 0xF6,
- 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x82, 0x00, 0x08, 0x80, 0x82, 0x00, 0x08, 0x81, 0x45, 0x00,
- 0x08, 0x86, 0x38, 0xC0, 0xF8, 0xF8, 0x82, 0x20, 0x40, 0x17, 0x7D, 0xC0, 0x20, 0x20, 0x00, 0x00,
- 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char water_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x82, 0x00,
- 0x08, 0x20, 0x82, 0x00, 0x1C, 0x71, 0xC7, 0x00, 0x7F, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xE0,
- 0x77, 0xDF, 0x7D, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x82, 0x08, 0x00, 0x20, 0x82, 0x08,
- 0x00, 0x71, 0xC7, 0x1C, 0x00, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0xDF, 0x7D, 0xF6,
- 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x82, 0x00, 0x0F, 0x80, 0x82, 0x00, 0x0F, 0x81, 0xC7, 0x00,
- 0x0F, 0x87, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xE0, 0x7F, 0xF7, 0x7D, 0xC0, 0x3F, 0xE0, 0x00, 0x00,
- 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char water_down_cursor_data[32 * 4];
+extern unsigned char water_down_cursor_mask[32 * 4];
#define WATER_DOWN_CURSOR_HOTX 7
#define WATER_DOWN_CURSOR_HOTY 31
-unsigned char house_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xF0, 0x00, 0x00, 0x2A, 0x10,
- 0x00, 0x00, 0x45, 0xE0, 0x00, 0x00, 0x93, 0x20, 0x00, 0x01, 0x19, 0x20, 0x00, 0x02, 0x0C, 0x20,
- 0x00, 0x04, 0x7E, 0x20, 0x00, 0x08, 0x03, 0x20, 0x00, 0x10, 0xFF, 0x90, 0x00, 0x20, 0x00, 0xC8,
- 0x00, 0x47, 0xFF, 0xE4, 0x00, 0xF0, 0x00, 0x7E, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10,
- 0x00, 0x11, 0xEF, 0xD0, 0x00, 0x11, 0x28, 0x50, 0x0F, 0x91, 0x28, 0x50, 0x08, 0x91, 0x28, 0x50,
- 0x08, 0x91, 0x2F, 0xD0, 0x08, 0x91, 0x20, 0x10, 0x08, 0x91, 0x20, 0x10, 0x08, 0x9F, 0xFF, 0xF0,
- 0x08, 0x80, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
- 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char house_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xF0, 0x00, 0x00, 0x3B, 0xF0,
- 0x00, 0x00, 0x7D, 0xE0, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xE0,
- 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xF8,
- 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xF0,
- 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x1F, 0x38, 0x70, 0x0F, 0x9F, 0x38, 0x70, 0x0F, 0x9F, 0x38, 0x70,
- 0x0F, 0x9F, 0x3F, 0xF0, 0x0F, 0x9F, 0x3F, 0xF0, 0x0F, 0x9F, 0x3F, 0xF0, 0x0F, 0x9F, 0xFF, 0xF0,
- 0x0F, 0x80, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
- 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char house_down_cursor_data[32 * 4];
+extern unsigned char house_down_cursor_mask[32 * 4];
#define HOUSE_DOWN_CURSOR_HOTX 7
#define HOUSE_DOWN_CURSOR_HOTY 31
-unsigned char volcano_down_cursor_data[32 * 4] = {
- 0x00, 0x08, 0xA0, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00,
- 0x00, 0x07, 0xB0, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x17, 0x84, 0x00, 0x00, 0x30, 0x1E, 0x00,
- 0x00, 0x76, 0x72, 0x00, 0x00, 0x5A, 0x89, 0x00, 0x00, 0x81, 0x1C, 0x80, 0x03, 0x08, 0x0A, 0x70,
- 0x04, 0x18, 0x17, 0x88, 0x18, 0x30, 0x0A, 0xA6, 0x23, 0xC2, 0x07, 0x7F, 0x7C, 0x5F, 0x8F, 0xEC,
- 0x40, 0xF0, 0xD8, 0xC0, 0x00, 0x40, 0x20, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00,
- 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00,
- 0x08, 0x80, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
- 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char volcano_down_cursor_mask[32 * 4] = {
- 0x00, 0x08, 0xA0, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00,
- 0x00, 0x07, 0xB0, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x3F, 0xFE, 0x00,
- 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0xF0,
- 0x07, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x7C, 0x7F, 0xFF, 0xEC,
- 0x40, 0xF0, 0xF8, 0xC0, 0x00, 0x40, 0x20, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00,
- 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00,
- 0x0F, 0x80, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
- 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char volcano_down_cursor_data[32 * 4];
+extern unsigned char volcano_down_cursor_mask[32 * 4];
#define VOLCANO_DOWN_CURSOR_HOTX 7
#define VOLCANO_DOWN_CURSOR_HOTY 31
-unsigned char walk_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00,
- 0x02, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00,
- 0x00, 0x12, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x1C, 0x00,
- 0x02, 0x20, 0x22, 0x00, 0x02, 0x10, 0x21, 0x00, 0x01, 0x08, 0x10, 0x80, 0x00, 0x88, 0x08, 0x80,
- 0x00, 0x72, 0x07, 0x20, 0x00, 0x0D, 0x00, 0xD0, 0x0F, 0x89, 0x00, 0x90, 0x08, 0x86, 0x00, 0x60,
- 0x08, 0x80, 0x00, 0x00, 0x08, 0x80, 0x0E, 0x00, 0x08, 0x80, 0x11, 0x00, 0x08, 0x80, 0x10, 0x80,
- 0x08, 0x80, 0x08, 0x40, 0xF8, 0xF8, 0x04, 0x40, 0x40, 0x10, 0x03, 0x90, 0x20, 0x20, 0x00, 0x68,
- 0x10, 0x40, 0x00, 0x48, 0x08, 0x80, 0x00, 0x30, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char walk_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00,
- 0x03, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00,
- 0x00, 0x1E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x1C, 0x00,
- 0x03, 0xE0, 0x3E, 0x00, 0x03, 0xF0, 0x3F, 0x00, 0x01, 0xF8, 0x1F, 0x80, 0x00, 0xF8, 0x0F, 0x80,
- 0x00, 0x72, 0x07, 0x20, 0x00, 0x0F, 0x00, 0xF0, 0x0F, 0x8F, 0x00, 0xF0, 0x0F, 0x86, 0x00, 0x60,
- 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, 0x0E, 0x00, 0x0F, 0x80, 0x1F, 0x00, 0x0F, 0x80, 0x1F, 0x80,
- 0x0F, 0x80, 0x0F, 0xC0, 0xFF, 0xF8, 0x07, 0xC0, 0x7F, 0xF0, 0x03, 0x90, 0x3F, 0xE0, 0x00, 0x78,
- 0x1F, 0xC0, 0x00, 0x78, 0x0F, 0x80, 0x00, 0x30, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char walk_down_cursor_data[32 * 4];
+extern unsigned char walk_down_cursor_mask[32 * 4];
#define WALK_DOWN_CURSOR_HOTX 7
#define WALK_DOWN_CURSOR_HOTY 31
-unsigned char paint_down_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xFA,
- 0x00, 0x00, 0x01, 0xF6, 0x00, 0x00, 0x03, 0xE4, 0x00, 0x03, 0x07, 0xCC, 0x00, 0x07, 0x84, 0x98,
- 0x00, 0x0F, 0xC8, 0x70, 0x00, 0x1B, 0xF8, 0x60, 0x00, 0x3D, 0xE0, 0xC0, 0x00, 0x7E, 0xE3, 0x00,
- 0x00, 0xFF, 0x62, 0x00, 0x00, 0xDF, 0xBE, 0x00, 0x00, 0x7F, 0xDF, 0x00, 0x00, 0x37, 0xEF, 0x80,
- 0x00, 0x1B, 0xF7, 0xC0, 0x07, 0xCF, 0xFB, 0xC0, 0x04, 0x46, 0x9D, 0xC0, 0x04, 0x43, 0x07, 0x80,
- 0x04, 0x41, 0x83, 0x00, 0x04, 0x40, 0xC6, 0x00, 0x04, 0x40, 0x6C, 0x00, 0x04, 0x40, 0x28, 0x00,
- 0x7C, 0x7C, 0x10, 0x00, 0x20, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00,
- 0x04, 0x40, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-unsigned char paint_down_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xFE,
- 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x03, 0x07, 0xFC, 0x00, 0x07, 0x87, 0xF8,
- 0x00, 0x0F, 0xCF, 0xF0, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0x00,
- 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x80,
- 0x00, 0x1F, 0xFF, 0xC0, 0x07, 0xCF, 0xFF, 0xC0, 0x07, 0xC7, 0xFF, 0xC0, 0x07, 0xC3, 0xFF, 0x80,
- 0x07, 0xC1, 0xFF, 0x00, 0x07, 0xC0, 0xFE, 0x00, 0x07, 0xC0, 0x7C, 0x00, 0x07, 0xC0, 0x38, 0x00,
- 0x7F, 0xFC, 0x10, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00,
- 0x07, 0xC0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
+extern unsigned char paint_down_cursor_data[32 * 4];
+extern unsigned char paint_down_cursor_mask[32 * 4];
#define PAINT_DOWN_CURSOR_HOTX 8
#define PAINT_DOWN_CURSOR_HOTY 30
-unsigned char entrance_down_cursor_data[32 * 4] = {
- 0x20, 0x00, 0x00, 0x08, 0x50, 0x00, 0x00, 0x14, 0x88, 0x00, 0x00, 0x22, 0x50, 0x00, 0x00, 0x14,
- 0x7F, 0xFF, 0xFF, 0xFC, 0x58, 0x00, 0x00, 0x34, 0x54, 0x00, 0x00, 0x54, 0x54, 0x00, 0x00, 0x54,
- 0x54, 0x00, 0x00, 0x54, 0x5C, 0x00, 0x00, 0x34, 0x5F, 0xFF, 0xFF, 0xF4, 0x50, 0x00, 0x00, 0x14,
- 0x50, 0x00, 0x00, 0x14, 0x50, 0x00, 0x00, 0x14, 0x50, 0x00, 0x00, 0x14, 0x50, 0x00, 0x00, 0x14,
- 0x50, 0x00, 0x00, 0x14, 0x5F, 0x80, 0x00, 0x14, 0xD8, 0x80, 0x00, 0x14, 0x58, 0x80, 0x02, 0xB5,
- 0x58, 0x80, 0x00, 0x14, 0xD8, 0x80, 0x00, 0x14, 0x58, 0x80, 0x05, 0x74, 0x08, 0x80, 0x00, 0x00,
- 0x08, 0x80, 0x00, 0xD2, 0xF8, 0xF8, 0x0E, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00,
- 0x10, 0x40, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
-unsigned char entrance_down_cursor_mask[32 * 4] = {
- 0x20, 0x00, 0x00, 0x08, 0x70, 0x00, 0x00, 0x1C, 0xF8, 0x00, 0x00, 0x3E, 0x70, 0x00, 0x00, 0x1C,
- 0x7F, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFC, 0x77, 0xFF, 0xFF, 0xDC, 0x77, 0xFF, 0xFF, 0xDC,
- 0x77, 0xFF, 0xFF, 0xDC, 0x7F, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFC, 0x70, 0x00, 0x00, 0x1C,
- 0x70, 0x00, 0x00, 0x1C, 0x70, 0x00, 0x00, 0x1C, 0x70, 0x00, 0x00, 0x1C, 0x70, 0x00, 0x00, 0x1C,
- 0x70, 0x00, 0x00, 0x1C, 0x7F, 0x80, 0x00, 0x1C, 0xFF, 0x80, 0x00, 0x1C, 0x7F, 0x80, 0x02, 0xBD,
- 0x7F, 0x80, 0x00, 0x1C, 0xFF, 0x80, 0x00, 0x1C, 0x7F, 0x80, 0x05, 0x7C, 0x0F, 0x80, 0x00, 0x00,
- 0x0F, 0x80, 0x00, 0xD2, 0xFF, 0xF8, 0x0E, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00,
- 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-};
+extern unsigned char entrance_down_cursor_data[32 * 4];
+extern unsigned char entrance_down_cursor_mask[32 * 4];
#define ENTRANCE_DOWN_CURSOR_HOTX 7
#define ENTRANCE_DOWN_CURSOR_HOTY 31
-unsigned char hand_open_cursor_data[32 * 4] = {
- 0x00, 0x06, 0x10, 0x00, 0x00, 0x09, 0x38, 0x00, 0x00, 0x09, 0x24, 0x00, 0x03, 0x08, 0xA4, 0x00,
- 0x04, 0x88, 0xA4, 0xC0, 0x04, 0x48, 0x63, 0x20, 0x04, 0x24, 0x63, 0x10, 0x06, 0x24, 0x61, 0x90,
- 0x02, 0x14, 0x21, 0x90, 0x03, 0x0C, 0x21, 0x10, 0x01, 0x04, 0x21, 0x10, 0x01, 0x86, 0x01, 0x10,
- 0x00, 0x82, 0x00, 0x08, 0x00, 0xC0, 0x00, 0x08, 0x00, 0x60, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08,
- 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x08, 0x00, 0x10, 0x00, 0x08, 0x00, 0x10, 0x00, 0x08,
- 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10,
- 0x0F, 0xC0, 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x14, 0x00, 0x00, 0x08, 0x12, 0x00, 0x00, 0x08,
- 0x0F, 0x0F, 0x00, 0x04, 0x01, 0xF9, 0x80, 0x04, 0x00, 0x00, 0xC0, 0x18, 0x00, 0x00, 0x7F, 0xE0,
-};
-unsigned char hand_open_cursor_mask[32 * 4] = {
- 0x00, 0x06, 0x10, 0x00, 0x00, 0x0F, 0x38, 0x00, 0x00, 0x0F, 0x3C, 0x00, 0x03, 0x0F, 0xBC, 0x00,
- 0x07, 0x8F, 0xBC, 0xC0, 0x07, 0xCF, 0xFF, 0xE0, 0x07, 0xE7, 0xFF, 0xF0, 0x07, 0xE7, 0xFF, 0xF0,
- 0x03, 0xF7, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xF0,
- 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF8,
- 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xF8,
- 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xF0,
- 0x0F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xF8,
- 0x0F, 0xFF, 0xFF, 0xFC, 0x01, 0xF9, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xE0,
-};
+extern unsigned char hand_open_cursor_data[32 * 4];
+extern unsigned char hand_open_cursor_mask[32 * 4];
#define HAND_OPEN_CURSOR_HOTX 0
#define HAND_OPEN_CURSOR_HOTY 0
-unsigned char hand_closed_cursor_data[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0xE0, 0x00, 0x00, 0x43, 0x10, 0x00, 0x00, 0x41, 0x8C, 0x00,
- 0x00, 0x20, 0x87, 0x00, 0x0E, 0x20, 0x42, 0x80, 0x11, 0x98, 0x62, 0x40, 0x10, 0x6C, 0x61, 0x20,
- 0x18, 0x14, 0x21, 0x20, 0x0C, 0x0C, 0x21, 0x10, 0x06, 0x04, 0x21, 0x10, 0x03, 0x06, 0x01, 0x10,
- 0x00, 0x82, 0x00, 0x08, 0x00, 0xC0, 0x00, 0x08, 0x00, 0x60, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08,
- 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x08, 0x00, 0x10, 0x00, 0x08, 0x00, 0x10, 0x00, 0x08,
- 0x07, 0x10, 0x00, 0x10, 0x08, 0x90, 0x00, 0x10, 0x08, 0x60, 0x00, 0x10, 0x0A, 0x00, 0x00, 0x10,
- 0x0A, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x08, 0x03, 0x80, 0x00, 0x08,
- 0x00, 0x7F, 0x00, 0x04, 0x00, 0x01, 0x80, 0x04, 0x00, 0x00, 0xC0, 0x18, 0x00, 0x00, 0x7F, 0xE0,
-};
-unsigned char hand_closed_cursor_mask[32 * 4] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0xE0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x7F, 0xFC, 0x00,
- 0x00, 0x3F, 0xFF, 0x00, 0x0E, 0x3F, 0xFF, 0x80, 0x1F, 0x9F, 0xFF, 0xC0, 0x1F, 0xEF, 0xFF, 0xE0,
- 0x1F, 0xF7, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xF0,
- 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF8,
- 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xF8,
- 0x07, 0x1F, 0xFF, 0xF0, 0x0F, 0x9F, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0,
- 0x0F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xF8,
- 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xE0,
-};
+extern unsigned char hand_closed_cursor_data[32 * 4];
+extern unsigned char hand_closed_cursor_mask[32 * 4];
#define HAND_CLOSED_CURSOR_HOTX 0
#define HAND_CLOSED_CURSOR_HOTY 0
diff --git a/src/drawing/drawing.c b/src/drawing/drawing.c
index 26a57dc3ec..99b9988fd4 100644
--- a/src/drawing/drawing.c
+++ b/src/drawing/drawing.c
@@ -22,7 +22,8 @@
#include "../common.h"
#include "../localisation/localisation.h"
#include "../interface/window.h"
-#include "../platform/osinterface.h"
+#include "../platform/platform.h"
+#include "../object.h"
#include "drawing.h"
// HACK These were originally passed back through registers
@@ -136,7 +137,7 @@ void gfx_transpose_palette(int pal, unsigned char product)
rct_g1_element g1 = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[pal];
int width = g1.width;
int x = g1.x_offset;
- uint8* dest_pointer = (uint8*)&(RCT2_ADDRESS(0x014124680,uint8)[x]);
+ uint8* dest_pointer = (uint8*)&(RCT2_ADDRESS(0x01424680, uint8)[x * 4]);
uint8* source_pointer = g1.offset;
for (; width > 0; width--) {
@@ -146,7 +147,33 @@ void gfx_transpose_palette(int pal, unsigned char product)
source_pointer += 3;
dest_pointer += 4;
}
- osinterface_update_palette((char*)0x01424680, 10, 236);//Odd would have expected dest_pointer
+ platform_update_palette((char*)0x01424680, 10, 236);
+}
+
+/* rct2: 0x006837E3 */
+void load_palette(){
+ uint8* water_chunk = object_entry_groups[OBJECT_TYPE_WATER].chunks[0];
+
+ uint32 palette = 0x5FC;
+
+ if (water_chunk != (uint8*)-1){
+ palette = *((uint32*)(water_chunk + 2));
+ }
+
+ rct_g1_element g1 = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[palette];
+ int width = g1.width;
+ int x = g1.x_offset;
+ uint8* dest_pointer = (uint8*)&(RCT2_ADDRESS(0x01424680, uint8)[x * 4]);
+ uint8* source_pointer = g1.offset;
+
+ for (; width > 0; width--) {
+ dest_pointer[0] = source_pointer[0];
+ dest_pointer[1] = source_pointer[1];
+ dest_pointer[2] = source_pointer[2];
+ source_pointer += 3;
+ dest_pointer += 4;
+ }
+ platform_update_palette((char*)0x01424680, 10, 236);
}
/**
diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h
index ab22bc8f7e..bd593ff621 100644
--- a/src/drawing/drawing.h
+++ b/src/drawing/drawing.h
@@ -75,6 +75,7 @@ void gfx_invalidate_screen();
// palette
void gfx_transpose_palette(int pal, unsigned char product);
+void load_palette();
// other
void gfx_draw_rain(int left, int top, int width, int height, sint32 x_start, sint32 y_start);
diff --git a/src/editor.c b/src/editor.c
index 0f0ef83a72..63b6ecf030 100644
--- a/src/editor.c
+++ b/src/editor.c
@@ -31,7 +31,8 @@
#include "management/news_item.h"
#include "object.h"
#include "peep/staff.h"
-#include "platform/osinterface.h"
+#include "platform/platform.h"
+#include "rct1.h"
#include "ride/ride.h"
#include "scenario.h"
#include "util/sawyercoding.h"
@@ -47,7 +48,7 @@ static int editor_load_landscape_from_sv4(const char *path);
static int editor_load_landscape_from_sc4(const char *path);
static int editor_read_sc4(char *src, int length);
static int editor_read_sv4(char *src, int length);
-static int editor_read_s4(char *src);
+static int editor_read_s4(rct1_s4 *data);
static int editor_read_s6(const char *path);
/**
@@ -61,7 +62,7 @@ void editor_load()
pause_sounds();
unpause_sounds();
object_unload_all();
- map_init();
+ map_init(150);
RCT2_CALLPROC_EBPSAFE(0x006B9CB0);
reset_park_entrances();
user_string_clear_all();
@@ -85,7 +86,7 @@ void editor_load()
mainWindow = window_get_main();
window_scroll_to_location(mainWindow, 2400, 2400, 112);
mainWindow->flags &= ~WF_SCROLLING_TO_LOCATION;
- RCT2_CALLPROC_EBPSAFE(0x006837E3);
+ load_palette();
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, sint16) = 0;
}
@@ -106,7 +107,7 @@ static int show_convert_saved_game_to_scenario_dialog(char *resultPath)
format_string(filterName, STR_RCT2_SAVED_GAME, NULL);
pause_sounds();
- result = osinterface_open_common_file_dialog(1, title, filename, "*.SV6", filterName);
+ result = platform_open_common_file_dialog(1, title, filename, "*.SV6", filterName);
unpause_sounds();
if (result)
@@ -155,7 +156,7 @@ void editor_convert_save_to_scenario()
format_string(s6Info->details, STR_NO_DETAILS_YET, NULL);
s6Info->name[0] = 0;
- }
+}
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_SCENARIO_EDITOR;
s6Info->var_000 = 4;
@@ -194,7 +195,7 @@ void editor_convert_save_to_scenario()
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
window_new_ride_init_vars();
RCT2_GLOBAL(0x009DEB7C, uint16) = 0;
- RCT2_CALLPROC_EBPSAFE(0x006837E3); // (palette related)
+ load_palette();
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, uint16) = 0;
}
@@ -208,7 +209,7 @@ void trackdesigner_load()
rct_window *mainWindow;
object_unload_all();
- map_init();
+ map_init(150);
set_all_land_owned();
RCT2_CALLPROC_EBPSAFE(0x006B9CB0);
reset_park_entrances();
@@ -231,7 +232,7 @@ void trackdesigner_load()
mainWindow = window_get_main();
window_scroll_to_location(mainWindow, 2400, 2400, 112);
mainWindow->flags &= ~WF_SCROLLING_TO_LOCATION;
- RCT2_CALLPROC_EBPSAFE(0x006837E3);
+ load_palette();
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, sint16) = 0;
}
@@ -245,7 +246,7 @@ void trackmanager_load()
rct_window *mainWindow;
object_unload_all();
- map_init();
+ map_init(150);
set_all_land_owned();
RCT2_CALLPROC_EBPSAFE(0x006B9CB0);
reset_park_entrances();
@@ -268,7 +269,7 @@ void trackmanager_load()
mainWindow = window_get_main();
window_scroll_to_location(mainWindow, 2400, 2400, 112);
mainWindow->flags &= ~WF_SCROLLING_TO_LOCATION;
- RCT2_CALLPROC_EBPSAFE(0x006837E3);
+ load_palette();
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, sint16) = 0;
}
@@ -299,12 +300,6 @@ void sub_6BD3A4() {
sub_6C0C3F();
}
-static void read(void *dst, void **src, int length)
-{
- memcpy(dst, *src, length);
- *((char**)src) += length;
-}
-
/**
*
* rct2: 0x006758C0
@@ -328,6 +323,254 @@ void editor_load_landscape(const char *path)
editor_read_s6(path);
}
+/**
+ *
+ * rct2: 0x00666DFD
+ */
+static void sub_666DFD()
+{
+ int x, y;
+ rct_map_element *mapElement;
+
+ x = RCT2_GLOBAL(0x013573EA, uint16);
+ y = RCT2_GLOBAL(0x013573EC, uint16);
+ if (x == 0x8000)
+ return;
+
+ x /= 32;
+ y /= 32;
+ mapElement = map_get_first_element_at(x, y);
+ do {
+ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) {
+ if (mapElement->properties.entrance.type == ENTRANCE_TYPE_PARK_ENTRANCE) {
+ mapElement->properties.entrance.path_type = 0;
+ break;
+ }
+ }
+ } while (!map_element_is_last_for_tile(mapElement++));
+}
+
+/**
+ *
+ * rct2: 0x0069F06A
+ */
+static void sub_69F06A()
+{
+ RCT2_CALLPROC_EBPSAFE(0x0069F06A); return;
+
+ // TODO, bug with the following code
+ RCT2_GLOBAL(0x013CE770, uint32) |= (1 << 0) | (1 << 1) | (1 << 14) | (1 << 2) | (1 << 3);
+ if (!(RCT2_GLOBAL(0x013CE770, uint32) & (1 << 4))) {
+ RCT2_GLOBAL(0x013CE770, uint32) |= (1 << 4);
+ RCT2_CALLPROC_EBPSAFE(0x006B9CB0);
+ }
+ if (!(RCT2_GLOBAL(0x013CE770, uint32) & (1 << 6))) {
+ RCT2_GLOBAL(0x013CE770, uint32) |= (1 << 6);
+ RCT2_CALLPROC_EBPSAFE(0x0069E891);
+ }
+ RCT2_GLOBAL(0x013CE770, uint32) |= (1 << 7);
+ if (!(RCT2_GLOBAL(0x013CE770, uint32) & (1 << 8))) {
+ RCT2_GLOBAL(0x013CE770, uint32) |= (1 << 8);
+ sub_666DFD();
+ }
+ if (!(RCT2_GLOBAL(0x013CE770, uint32) & (1 << 9))) {
+ RCT2_GLOBAL(0x013CE770, uint32) |= (1 << 9);
+ RCT2_CALLPROC_EBPSAFE(0x0069E89B);
+ }
+ if (!(RCT2_GLOBAL(0x013CE770, uint32) & (1 << 13))) {
+ RCT2_GLOBAL(0x013CE770, uint32) |= (1 << 13);
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) = 127 * 32;
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, uint16) = 4350;
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) = 128;
+ RCT2_GLOBAL(0x01358836, uint16) = 4095;
+ }
+ if (!(RCT2_GLOBAL(0x013CE770, uint32) & (1 << 15))) {
+ RCT2_GLOBAL(0x013CE770, uint32) |= (1 << 15);
+ RCT2_GLOBAL(0x01358838, uint32) = 0;
+ }
+ RCT2_GLOBAL(0x013CE770, uint32) |= (1 << 16) | (1 << 18) | (1 << 19);
+}
+
+/**
+ *
+ * rct2: 0x006A2B62
+ */
+static void sub_6A2B62()
+{
+ int i;
+ rct_sprite *sprite;
+ rct_ride *ride;
+ map_element_iterator it;
+
+ RCT2_CALLPROC_EBPSAFE(0x0069F007);
+
+ // Free sprite user strings
+ for (i = 0; i < MAX_SPRITES; i++) {
+ sprite = &g_sprite_list[i];
+ if (sprite->unknown.sprite_identifier != 255)
+ user_string_free(sprite->unknown.name_string_idx);
+ }
+
+ reset_sprite_list();
+
+ // Free ride user strings
+ FOR_ALL_RIDES(i, ride)
+ user_string_free(ride->name);
+
+ ride_init_all();
+ RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_HEADING_FOR_PARK, uint16) = 0;
+ RCT2_GLOBAL(0x01357BC8, uint16) = 0;
+ RCT2_GLOBAL(0x013573FE, uint8) = 0;
+ RCT2_CALLPROC_EBPSAFE(0x0069F44B);
+ sub_69F06A();
+ RCT2_CALLPROC_EBPSAFE(0x0069F143);
+ RCT2_CALLPROC_EBPSAFE(0x0069F2D0);
+ RCT2_CALLPROC_EBPSAFE(0x0069F3AB);
+
+ // Fix paths and remove all ride track / entrance / exit
+ map_element_iterator_begin(&it);
+ do {
+ switch (map_element_get_type(it.element)) {
+ case MAP_ELEMENT_TYPE_PATH:
+ if (it.element->type & 1) {
+ it.element->properties.path.type &= 0xF7;
+ it.element->properties.path.addition_status = 255;
+ }
+ break;
+
+ case MAP_ELEMENT_TYPE_TRACK:
+ RCT2_CALLPROC_EBPSAFE(0x006A7594);
+ sub_6A6AA7(it.x * 32, it.y * 32, it.element);
+ map_element_remove(it.element);
+ map_element_iterator_restart_for_tile(&it);
+ break;
+
+ case MAP_ELEMENT_TYPE_ENTRANCE:
+ if (it.element->properties.entrance.type != ENTRANCE_TYPE_PARK_ENTRANCE) {
+ RCT2_CALLPROC_EBPSAFE(0x006A7594);
+ sub_6A6AA7(it.x * 32, it.y * 32, it.element);
+ map_element_remove(it.element);
+ map_element_iterator_restart_for_tile(&it);
+ }
+ break;
+ }
+ } while (map_element_iterator_next(&it));
+
+ object_unload_all();
+
+ RCT2_CALLPROC_EBPSAFE(0x0069F53D);
+ RCT2_CALLPROC_EBPSAFE(0x006A9FC0);
+ RCT2_CALLPROC_EBPSAFE(0x006A2730);
+ RCT2_CALLPROC_EBPSAFE(0x006A2956);
+ RCT2_CALLPROC_EBPSAFE(0x006A29B9);
+ RCT2_CALLPROC_EBPSAFE(0x006A2A68);
+ RCT2_CALLPROC_EBPSAFE(0x0069F509);
+ RCT2_CALLPROC_EBPSAFE(0x00685675);
+ RCT2_CALLPROC_EBPSAFE(0x0068585B);
+
+ climate_reset(RCT2_GLOBAL(RCT2_ADDRESS_CLIMATE, uint8));
+ RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_SCENARIO_EDITOR;
+ viewport_init_all();
+ news_item_init_queue();
+ window_editor_main_open();
+
+ rct_s6_header *s6Header = (rct_s6_header*)0x009E34E4;
+ rct_s6_info *s6Info = (rct_s6_info*)0x0141F570;
+
+ s6Info->var_000 = 1;
+ s6Info->category = 4;
+ format_string(s6Info->details, STR_NO_DETAILS_YET, NULL);
+ s6Info->name[0] = 0;
+ if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint8) & PARK_FLAGS_NO_MONEY) {
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint8) |= PARK_FLAGS_NO_MONEY_SCENARIO;
+ } else {
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint8) &= PARK_FLAGS_NO_MONEY_SCENARIO;
+ }
+ if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) == MONEY_FREE) {
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint8) |= PARK_FLAGS_PARK_FREE_ENTRY;
+ } else {
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint8) &= ~PARK_FLAGS_PARK_FREE_ENTRY;
+ }
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint8) &= ~PARK_FLAGS_18;
+ RCT2_GLOBAL(RCT2_ADDRESS_GUEST_INITIAL_CASH, money16) = clamp(
+ MONEY(10,00),
+ RCT2_GLOBAL(RCT2_ADDRESS_GUEST_INITIAL_CASH, money16),
+ MONEY(100,00)
+ );
+ RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, money32) = min(
+ MONEY(10000,00),
+ RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, money32)
+ );
+ RCT2_CALLPROC_EBPSAFE(0x0069E89B);
+ RCT2_CALLPROC_EBPSAFE(0x0069E869);
+
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32) = clamp(
+ MONEY(0,00),
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32),
+ MONEY(5000000,00)
+ );
+
+ RCT2_GLOBAL(RCT2_ADDRESS_MAXIMUM_LOAN, money32) = clamp(
+ MONEY(0,00),
+ RCT2_GLOBAL(RCT2_ADDRESS_MAXIMUM_LOAN, money32),
+ MONEY(5000000,00)
+ );
+
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, uint8) = clamp(
+ 5,
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, uint8),
+ 80
+ );
+
+ if (
+ RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) == OBJECTIVE_NONE ||
+ RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) == OBJECTIVE_HAVE_FUN ||
+ RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) == OBJECTIVE_BUILD_THE_BEST
+ ) {
+ RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) = OBJECTIVE_GUESTS_BY;
+ RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_YEAR, uint8) = 4;
+ RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_NUM_GUESTS, uint16) = 1000;
+ }
+
+ RCT2_GLOBAL(0x01358774, uint16) = 0;
+
+ // Initialise main view
+ rct_window *w = window_get_main();
+ rct_viewport *viewport = w->viewport;
+
+ w->viewport_target_sprite = -1;
+ w->saved_view_x = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_X, sint16);
+ w->saved_view_y = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, sint16);
+
+ 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;
+
+ int cx = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION, sint16) - viewport->zoom;
+ if (cx != 0) {
+ if (cx >= 0) {
+ viewport->view_width <<= cx;
+ viewport->view_height <<= cx;
+ } else {
+ cx = -cx;
+ viewport->view_width >>= cx;
+ viewport->view_height >>= cx;
+ }
+ }
+ w->saved_view_x -= viewport->view_width >> 1;
+ w->saved_view_y -= viewport->view_height >> 1;
+
+ window_invalidate(w);
+ sub_69E9A7();
+ RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
+ window_new_ride_init_vars();
+ RCT2_GLOBAL(0x009DEB7C, uint16) = 0;
+ load_palette();
+ gfx_invalidate_screen();
+
+ RCT2_GLOBAL(0x009DEA66, uint16) = 0;
+}
+
/**
*
* rct2: 0x006A2B02
@@ -355,7 +598,7 @@ static int editor_load_landscape_from_sv4(const char *path)
editor_read_sv4(fpBuffer, fpLength);
free(fpBuffer);
- RCT2_CALLPROC_EBPSAFE(0x006A2B62);
+ sub_6A2B62();
return 1;
}
@@ -386,62 +629,71 @@ static int editor_load_landscape_from_sc4(const char *path)
editor_read_sc4(fpBuffer, fpLength);
free(fpBuffer);
- RCT2_CALLPROC_EBPSAFE(0x006A2B62);
+ sub_6A2B62();
return 1;
}
static int editor_read_sc4(char *src, int length)
{
int decodedLength;
- char *decodedBuffer;
+ rct1_s4 *data;
- decodedBuffer = malloc(2065676);
- decodedLength = sawyercoding_decode_sc4(src, decodedBuffer, length);
- if (decodedLength != 2065676) {
- free(decodedBuffer);
+ int fileType = sawyercoding_detect_file_type(src, length);
+
+ data = malloc(sizeof(rct1_s4));
+ decodedLength = (fileType & FILE_VERSION_MASK) == FILE_VERSION_RCT1 ?
+ sawyercoding_decode_sv4(src, (char*)data, length) :
+ sawyercoding_decode_sc4(src, (char*)data, length);
+ if (decodedLength != sizeof(rct1_s4)) {
+ free(data);
return 0;
}
- editor_read_s4(decodedBuffer);
- free(decodedBuffer);
+ editor_read_s4(data);
+ free(data);
return 1;
}
static int editor_read_sv4(char *src, int length)
{
int decodedLength;
- char *decodedBuffer;
+ rct1_s4 *data;
- decodedBuffer = malloc(2065676);
- decodedLength = sawyercoding_decode_sv4(src, decodedBuffer, length);
- if (decodedLength != 2065676) {
- free(decodedBuffer);
+ data = malloc(sizeof(rct1_s4));
+ decodedLength = sawyercoding_decode_sv4(src, (char*)data, length);
+ if (decodedLength != sizeof(rct1_s4)) {
+ free(data);
return 0;
}
- editor_read_s4(decodedBuffer);
- free(decodedBuffer);
+ editor_read_s4(data);
+ free(data);
return 1;
}
+static void read(void *dst, void *src, int length)
+{
+ memcpy(dst, src, length);
+}
+
/**
*
* rct2: 0x0069EEA0
*/
-static int editor_read_s4(char *src)
+static int editor_read_s4(rct1_s4 *src)
{
int i;
rct_banner *banner;
- read((void*)RCT2_ADDRESS_CURRENT_MONTH_YEAR, &src, 16);
- memset((void*)RCT2_ADDRESS_MAP_ELEMENTS, 0, 0x60000 * 4);
- read((void*)RCT2_ADDRESS_MAP_ELEMENTS, &src, 0x60000);
- read((void*)0x010E63B8, &src, 0x138804);
+ read((void*)RCT2_ADDRESS_CURRENT_MONTH_YEAR, &src->month, 16);
+ memset((void*)RCT2_ADDRESS_MAP_ELEMENTS, 0, 0x30000 * sizeof(rct_map_element));
+ read((void*)RCT2_ADDRESS_MAP_ELEMENTS, src->map_elements, sizeof(src->map_elements));
+ read((void*)0x010E63B8, &src->unk_counter, 4 + sizeof(src->sprites));
for (i = 0; i < MAX_BANNERS; i++)
gBanners[i].type = 255;
- read((void*)0x013573BC, &src, 12424);
+ read((void*)0x013573BC, &src->next_sprite_index, 12424);
for (i = 0; i < MAX_BANNERS; i++) {
banner = &gBanners[i];
@@ -449,10 +701,10 @@ static int editor_read_s4(char *src)
banner->string_idx = 778;
}
- read((void*)0x0135A8F4, &src, 0x2F51C);
+ read((void*)0x0135A8F4, &src->string_table, 0x2F51C);
memset((void*)0x013CA672, 0, 204);
- read((void*)0x0138B580, &src, 0x258F2);
- read((void*)0x013C6A72, &src, 0x3C00);
+ read((void*)0x0138B580, &src->animated_objects, 0x258F2);
+ read((void*)0x013C6A72, &src->patrol_areas, sizeof(src->patrol_areas));
char *esi = (char*)0x13C6A72;
char *edi = (char*)0x13B0E72;
@@ -477,9 +729,9 @@ static int editor_read_s4(char *src)
memset(edi, 0, 64); edi += 64;
} while (--edx);
- read((void*)0x013CA672, &src, 116);
- read((void*)0x013CA73A, &src, 4);
- read((void*)0x013CA73E, &src, 0x41EA);
+ read((void*)0x013CA672, &src->unk_1F42AA, 116);
+ read((void*)0x013CA73A, &src->unk_1F431E, 4);
+ read((void*)0x013CA73E, &src->unk_1F4322, 0x41EA);
return 1;
}
@@ -641,9 +893,9 @@ static int editor_read_s6(const char *path)
MONEY(5000000,00)
);
- RCT2_GLOBAL(0x013580F0, money32) = clamp(
+ RCT2_GLOBAL(RCT2_ADDRESS_MAXIMUM_LOAN, money32) = clamp(
MONEY(0,00),
- RCT2_GLOBAL(0x013580F0, money32),
+ RCT2_GLOBAL(RCT2_ADDRESS_MAXIMUM_LOAN, money32),
MONEY(5000000,00)
);
@@ -699,7 +951,7 @@ static int editor_read_s6(const char *path)
RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
window_new_ride_init_vars();
RCT2_GLOBAL(0x009DEB7C, uint16) = 0;
- RCT2_CALLPROC_EBPSAFE(0x006837E3); // (palette related)
+ load_palette();
gfx_invalidate_screen();
return 1;
diff --git a/src/game.c b/src/game.c
index 9befcfdf14..568d4b2a81 100644
--- a/src/game.c
+++ b/src/game.c
@@ -31,12 +31,13 @@
#include "interface/widget.h"
#include "interface/window.h"
#include "management/finance.h"
+#include "management/marketing.h"
#include "management/news_item.h"
#include "management/research.h"
#include "object.h"
#include "peep/peep.h"
#include "peep/staff.h"
-#include "platform/osinterface.h"
+#include "platform/platform.h"
#include "ride/ride.h"
#include "ride/ride_ratings.h"
#include "ride/vehicle.h"
@@ -70,7 +71,7 @@ void game_reduce_game_speed()
void game_create_windows()
{
window_main_open();
- window_game_top_toolbar_open();
+ window_top_toolbar_open();
window_game_bottom_toolbar_open();
RCT2_CALLPROC_EBPSAFE(0x0066B905);
}
@@ -96,7 +97,7 @@ void update_palette_effects()
RCT2_ADDRESS(0x01424680 + xoffset, uint8)[(i * 4) + 2] = -((0xFF - g1_element.offset[(i * 3) + 2]) / 2) - 1;
}
RCT2_GLOBAL(0x014241BC, uint32) = 2;
- osinterface_update_palette(RCT2_ADDRESS(0x01424680, uint8), 10, 236);
+ platform_update_palette(RCT2_ADDRESS(0x01424680, uint8), 10, 236);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint8)++;
} else {
@@ -125,7 +126,7 @@ void update_palette_effects()
q = 2;
}
}
- uint32 j = RCT2_GLOBAL(0x009DE584, uint32);
+ uint32 j = RCT2_GLOBAL(RCT2_ADDRESS_PALETTE_EFFECT_FRAME_NO, uint32);
j = (((uint16)((~j / 2) * 128) * 15) >> 16);
int p = 1533;
if (RCT2_GLOBAL(0x009ADAE0, int) != -1) {
@@ -164,7 +165,7 @@ void update_palette_effects()
vd += 4;
}
- j = ((uint16)(RCT2_GLOBAL(0x009DE584, uint32) * -960) * 3) >> 16;
+ 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];
vs = &g1_element.offset[j * 3];
@@ -182,11 +183,11 @@ void update_palette_effects()
}
RCT2_GLOBAL(0x014241BC, uint32) = 2;
- osinterface_update_palette(RCT2_ADDRESS(0x01424680, uint8), 230, 16);
+ platform_update_palette(RCT2_ADDRESS(0x01424680, uint8), 230, 16);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint8) == 2) {
RCT2_GLOBAL(0x014241BC, uint32) = 2;
- osinterface_update_palette(RCT2_ADDRESS(0x01424680, uint8), 10, 236);
+ platform_update_palette(RCT2_ADDRESS(0x01424680, uint8), 10, 236);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint8) = 0;
}
@@ -219,7 +220,7 @@ void game_update()
}
// Update the game one or more times
- if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0) {
+ if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0) {
for (i = 0; i < numUpdates; i++) {
game_logic_update();
start_title_music();
@@ -435,7 +436,7 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int *
//
if (!(flags & 0x20)) {
// Update money balance
- finance_payment(cost, RCT2_GLOBAL(0x0141F56C, uint8));
+ finance_payment(cost, RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) / 4);
if (RCT2_GLOBAL(0x0141F568, uint8) == RCT2_GLOBAL(0x013CA740, uint8)) {
// Create a +/- money text effect
if (cost != 0)
@@ -464,83 +465,40 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int *
*
* rct2: 0x00667C15
*/
-void game_pause_toggle()
+void game_pause_toggle(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
- char input_bl;
-
- #ifdef _MSC_VER
- __asm mov input_bl, bl
- #else
- __asm__ ( "mov %[input_bl], bl " : [input_bl] "+m" (input_bl) );
- #endif
-
-
- if (input_bl & 1) {
- RCT2_GLOBAL(0x009DEA6E, uint32) ^= 1;
+ if (*ebx & GAME_COMMAND_FLAG_APPLY) {
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint32) ^= 1;
window_invalidate_by_class(WC_TOP_TOOLBAR);
- if (RCT2_GLOBAL(0x009DEA6E, uint32) & 1)
+ if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint32) & 1)
pause_sounds();
else
unpause_sounds();
}
-
- #ifdef _MSC_VER
- __asm mov ebx, 0
- #else
- __asm__ ( "mov ebx, 0 " );
- #endif
-
+ *ebx = 0;
}
/**
*
* rct2: 0x0066DB5F
*/
-static void game_load_or_quit()
+static void game_load_or_quit(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
- char input_bl, input_dl;
- short input_di;
-
- #ifdef _MSC_VER
- __asm mov input_bl, bl
- #else
- __asm__ ( "mov %[input_bl], bl " : [input_bl] "+m" (input_bl) );
- #endif
-
- #ifdef _MSC_VER
- __asm mov input_dl, dl
- #else
- __asm__ ( "mov %[input_dl], dl " : [input_dl] "+m" (input_dl) );
- #endif
-
- #ifdef _MSC_VER
- __asm mov input_di, di
- #else
- __asm__ ( "mov %[input_di], di " : [input_di] "+m" (input_di) );
- #endif
-
- if (!(input_bl & 1))
- return; // 0;
-
- switch (input_dl) {
- case 0:
- RCT2_GLOBAL(RCT2_ADDRESS_SAVE_PROMPT_MODE, uint16) = input_di;
- window_save_prompt_open();
- break;
- case 1:
- window_close_by_class(WC_SAVE_PROMPT);
- break;
- default:
- game_load_or_quit_no_save_prompt();
- break;
+ if (*ebx & GAME_COMMAND_FLAG_APPLY) {
+ switch (*edx & 0xFF) {
+ case 0:
+ RCT2_GLOBAL(RCT2_ADDRESS_SAVE_PROMPT_MODE, uint16) = *edi & 0xFF;
+ window_save_prompt_open();
+ break;
+ case 1:
+ window_close_by_class(WC_SAVE_PROMPT);
+ break;
+ default:
+ game_load_or_quit_no_save_prompt();
+ break;
+ }
}
-
-#ifdef _MSC_VER
- __asm mov ebx, 0
-#else
- __asm__ ( "mov ebx, 0 " );
-#endif
-
+ *ebx = 0;
}
/**
@@ -554,7 +512,7 @@ static int open_landscape_file_dialog()
strcpy((char*)0x0141EF68, (char*)RCT2_ADDRESS_LANDSCAPES_PATH);
format_string((char*)0x0141EE68, STR_RCT2_LANDSCAPE_FILE, 0);
pause_sounds();
- result = osinterface_open_common_file_dialog(1, (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, (char*)0x0141EF68, "*.SV6;*.SV4;*.SC6", (char*)0x0141EE68);
+ result = platform_open_common_file_dialog(1, (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, (char*)0x0141EF68, "*.SV6;*.SV4;*.SC6", (char*)0x0141EE68);
unpause_sounds();
// window_proc
return result;
@@ -571,7 +529,7 @@ static int open_load_game_dialog()
strcpy((char*)0x0141EF68, (char*)RCT2_ADDRESS_SAVED_GAMES_PATH);
format_string((char*)0x0141EE68, STR_RCT2_SAVED_GAME, 0);
pause_sounds();
- result = osinterface_open_common_file_dialog(1, (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, (char*)0x0141EF68, "*.SV6", (char*)0x0141EE68);
+ result = platform_open_common_file_dialog(1, (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, (char*)0x0141EF68, "*.SV6", (char*)0x0141EE68);
unpause_sounds();
// window_proc
return result;
@@ -724,7 +682,7 @@ int game_load_save(const char *path)
if (RCT2_GLOBAL(0x0013587C4, uint32) == 0) // this check is not in scenario play
sub_69E869();
- RCT2_CALLPROC_EBPSAFE(0x006837E3); // (palette related)
+ load_palette();
gfx_invalidate_screen();
return 1;
}
@@ -790,7 +748,7 @@ static int show_save_game_dialog(char *resultPath)
format_string(filterName, STR_RCT2_SAVED_GAME, NULL);
pause_sounds();
- result = osinterface_open_common_file_dialog(0, title, filename, "*.SV6", filterName);
+ result = platform_open_common_file_dialog(0, title, filename, "*.SV6", filterName);
unpause_sounds();
if (result)
@@ -860,15 +818,15 @@ void game_load_or_quit_no_save_prompt()
static uint32 game_do_command_table[58] = {
0x006B2FC5,
0x0066397F,
- (uint32)game_pause_toggle,
+ 0,
0x006C511D,
0x006C5B69,
- (uint32)game_load_or_quit,
+ 0,
0x006B3F0F,
0x006B49D9,
0x006B4EA6,
0x006B52D4,
- 0x006B578B, // 10
+ 0, // 10
0x006B5559,
0x006660A8,
0x0066640B,
@@ -892,21 +850,21 @@ static uint32 game_do_command_table[58] = {
0x006C0B83,
0x006C0BB5,
0x00669C6D,
- 0x00669D4A,
+ 0,
0x006649BD,
0x006666E7,
- 0x00666A63,
+ 0,
0x006CD8CE,
- (uint32)game_command_set_park_entrance_fee,
- (uint32)game_command_update_staff_colour, // 40
+ 0,
+ 0, // 40
0x006E519A,
0x006E5597,
0x006B893C,
0x006B8E1B,
- 0x0069DFB3,
- 0x00684A7F,
+ 0,
+ 0,
0x006D13FE,
- 0x0069E73C,
+ 0,
0x006CDEE4,
0x006B9E6D, // 50
0x006BA058,
@@ -923,15 +881,15 @@ void game_command_emptysub(int* eax, int* ebx, int* ecx, int* edx, int* esi, int
static GAME_COMMAND_POINTER* new_game_command_table[58] = {
game_command_emptysub,
game_command_emptysub,
+ game_pause_toggle,
+ game_command_emptysub,
+ game_command_emptysub,
+ game_load_or_quit,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
- game_command_emptysub,
- game_command_emptysub,
- game_command_emptysub,
- game_command_emptysub,
- game_command_emptysub, // 10
+ game_command_set_ride_name, // 10
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
@@ -954,22 +912,22 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = {
game_command_emptysub, // 30
game_command_emptysub,
game_command_emptysub,
+ game_command_set_park_name,
+ game_command_set_park_open,
+ game_command_emptysub,
+ game_command_emptysub,
+ game_command_remove_park_entrance,
+ game_command_emptysub,
+ game_command_set_park_entrance_fee,
+ game_command_update_staff_colour, // 40
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
game_command_emptysub,
+ game_command_set_current_loan,
+ game_command_set_research_funding,
game_command_emptysub,
- game_command_emptysub,
- game_command_emptysub,
- game_command_emptysub, // 40
- game_command_emptysub,
- game_command_emptysub,
- game_command_emptysub,
- game_command_emptysub,
- game_command_emptysub,
- game_command_emptysub,
- game_command_emptysub,
- game_command_emptysub,
+ game_command_start_campaign,
game_command_emptysub,
game_command_emptysub, // 50
game_command_emptysub,
diff --git a/src/game.h b/src/game.h
index c5a1af6b20..d748ac417f 100644
--- a/src/game.h
+++ b/src/game.h
@@ -55,11 +55,11 @@ enum GAME_COMMAND {
GAME_COMMAND_SET_STAFF_PATROL, //30
GAME_COMMAND_FIRE_STAFF_MEMBER, // 31
GAME_COMMAND_SET_STAFF_ORDER, // 32
- GAME_COMMAND_33,
+ GAME_COMMAND_SET_PARK_NAME,
GAME_COMMAND_SET_PARK_OPEN, // 34
GAME_COMMAND_35,
- GAME_COMMAND_36,
- GAME_COMMAND_37,
+ GAME_COMMAND_PLACE_PARK_ENTRANCE,
+ GAME_COMMAND_REMOVE_PARK_ENTRANCE,
GAME_COMMAND_38,
GAME_COMMAND_SET_PARK_ENTRANCE_FEE, // 39
GAME_COMMAND_SET_STAFF_COLOUR, // 40
@@ -106,7 +106,7 @@ void game_reduce_game_speed();
void game_load_or_quit_no_save_prompt();
int game_load_save(const char *path);
-void game_pause_toggle();
+void game_pause_toggle(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
char save_game();
void rct2_exit();
diff --git a/src/input.c b/src/input.c
index 896ff4596a..e72a5fb393 100644
--- a/src/input.c
+++ b/src/input.c
@@ -22,6 +22,7 @@
#include "addresses.h"
#include "audio/audio.h"
#include "config.h"
+#include "cursors.h"
#include "game.h"
#include "input.h"
#include "interface/keyboard_shortcut.h"
@@ -29,7 +30,7 @@
#include "interface/widget.h"
#include "interface/window.h"
#include "localisation/localisation.h"
-#include "platform/osinterface.h"
+#include "platform/platform.h"
#include "ride/ride_data.h"
#include "scenario.h"
#include "tutorial.h"
@@ -97,7 +98,7 @@ void game_handle_input()
if (RCT2_GLOBAL(0x009DEA64, uint16) & 2) {
RCT2_GLOBAL(0x009DEA64, uint16) &= ~2;
game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 2, 0);
- }
+}
if (RCT2_GLOBAL(0x009ABDF2, uint8) != 0) {
for (w = g_window_list; w < RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); w++)
@@ -112,7 +113,7 @@ void game_handle_input()
break;
game_handle_input_mouse(x, y, state & 0xFF);
- }
+}
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5) {
game_handle_input_mouse(x, y, state);
@@ -123,8 +124,8 @@ void game_handle_input()
game_handle_input_mouse(x, y, state);
process_mouse_over(x, y);
process_mouse_tool(x, y);
- }
- }
+}
+}
for (w = g_window_list; w < RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); w++)
RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_08], 0, 0, 0, 0,(int) w, 0, 0);
@@ -133,7 +134,7 @@ void game_handle_input()
/**
*
* rct2: 0x006E83C7
- */
+*/
static void game_get_next_input(int *x, int *y, int *state)
{
rct_mouse_data* eax = get_mouse_input();
@@ -142,7 +143,7 @@ static void game_get_next_input(int *x, int *y, int *state)
*y = gCursorState.y;
*state = 0;
return;
- }
+}
*x = eax->x;
*y = eax->y;
@@ -172,7 +173,7 @@ static void game_get_next_input(int *x, int *y, int *state)
}
/**
- *
+ *
* rct2: 0x00407074
*/
static rct_mouse_data* get_mouse_input()
@@ -185,7 +186,7 @@ static rct_mouse_data* get_mouse_input()
RCT2_GLOBAL(RCT2_ADDRESS_MOUSE_READ_INDEX, uint32) = (read_index + 1) % 64;
return &mouse_buffer[read_index];
-}
+ }
/**
*
@@ -253,8 +254,8 @@ static void game_handle_input_mouse(int x, int y, int state)
input_viewport_drag_end();
if (RCT2_GLOBAL(0x009DE540, sint16) < 500) {
viewport_interaction_right_click(x, y);
- }
- }
+ }
+ }
break;
case INPUT_STATE_DROPDOWN_ACTIVE:
input_state_widget_pressed(x, y, state, widgetIndex, w, widget);
@@ -305,10 +306,10 @@ static void game_handle_input_mouse(int x, int y, int state)
else{
if ((RCT2_GLOBAL(0x9DE518, uint32) & (1 << 4)))
break;
-
+
viewport_interaction_left_click(x, y);
- }
- }
+ }
+ }
break;
case INPUT_STATE_SCROLL_LEFT:
if (state == 0)
@@ -326,14 +327,14 @@ static void game_handle_input_mouse(int x, int y, int state)
if (state == 0 || state == 2)
input_window_resize_continue(w, x, y);
- }
+ }
break;
case 9:
RCT2_CALLPROC_X(0x006E8ACB, x, y, state, widgetIndex, (int)w, (int)widget, 0);
break;
- }
+ }
}
-
+
#pragma region Window positioning / resizing
void input_window_position_begin(rct_window *w, int widgetIndex, int x, int y)
@@ -344,7 +345,7 @@ void input_window_position_begin(rct_window *w, int widgetIndex, int x, int y)
_dragWindowClass = w->classification;
_dragWindowNumber = w->number;
_dragWidgetIndex = widgetIndex;
-}
+ }
static void input_window_position_continue(rct_window *w, int wdx, int wdy, int x, int y)
{
@@ -352,7 +353,7 @@ static void input_window_position_continue(rct_window *w, int wdx, int wdy, int
snapProximity = w->flags & WF_NO_SNAPPING ? 0 : gGeneral_config.window_snap_proximity;
window_move_and_snap(w, x - wdx, y - wdy, snapProximity);
-}
+ }
static void input_window_position_end(rct_window *w, int x, int y)
{
@@ -362,7 +363,7 @@ static void input_window_position_end(rct_window *w, int x, int y)
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = _dragWindowNumber;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = _dragWidgetIndex;
RCT2_CALLPROC_X(w->event_handlers[WE_MOVED], 0, 0, x, y, (int)w, 0, 0);
-}
+ }
static void input_window_resize_begin(rct_window *w, int widgetIndex, int x, int y)
{
@@ -374,7 +375,7 @@ static void input_window_resize_begin(rct_window *w, int widgetIndex, int x, int
_dragWidgetIndex = widgetIndex;
_originalWindowWidth = w->width;
_originalWindowHeight = w->height;
-}
+ }
static void input_window_resize_continue(rct_window *w, int x, int y)
{
@@ -391,8 +392,8 @@ static void input_window_resize_continue(rct_window *w, int x, int y)
targetWidth - w->width,
targetHeight - w->height
);
- }
-}
+ }
+ }
static void input_window_resize_end()
{
@@ -535,77 +536,77 @@ static void input_scroll_continue(rct_window *w, int widgetIndex, int state, int
rct_widget *widget;
widget = &w->widgets[widgetIndex];
- if (widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint32)){
- invalidate_scroll();
- return;
- }
- if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8)){
- invalidate_scroll();
- return;
- }
- if (w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16)){
- invalidate_scroll();
- return;
- }
+ if (widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint32)){
+ invalidate_scroll();
+ return;
+ }
+ if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8)){
+ invalidate_scroll();
+ return;
+ }
+ if (w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16)){
+ invalidate_scroll();
+ return;
+ }
- if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_HSCROLLBAR_THUMB){
- int temp_x = x;
- x -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16);
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = temp_x;
- RCT2_CALLPROC_X(0x006E98F2, x, temp_x, state, w->number, (int)w, (int)widget, x);
- return;
- }
+ if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_HSCROLLBAR_THUMB){
+ int temp_x = x;
+ x -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16);
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = temp_x;
+ RCT2_CALLPROC_X(0x006E98F2, x, temp_x, state, w->number, (int)w, (int)widget, x);
+ return;
+ }
- if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_VSCROLLBAR_THUMB){
- int temp_y = y;
- y -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16);
- RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = temp_y;
- RCT2_CALLPROC_X(0x006E99A9, temp_y, y, state, w->number, (int)w, (int)widget, y);
- return;
- }
- int scroll_part, scroll_id;
- widget_scroll_get_part(w, widget, x, y, &x, &y, &scroll_part, &scroll_id);
+ if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_VSCROLLBAR_THUMB){
+ int temp_y = y;
+ y -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16);
+ RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = temp_y;
+ RCT2_CALLPROC_X(0x006E99A9, temp_y, y, state, w->number, (int)w, (int)widget, y);
+ return;
+ }
+ int scroll_part, scroll_id;
+ widget_scroll_get_part(w, widget, x, y, &x, &y, &scroll_part, &scroll_id);
- if (scroll_part != RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16)){
- invalidate_scroll();
- return;
- }
+ if (scroll_part != RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16)){
+ invalidate_scroll();
+ return;
+ }
- switch (scroll_part){
- case SCROLL_PART_VIEW:
- RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DRAG], w->number / 18, y, x, y, (int)w, (int)widget, (int)w->event_handlers);
- break;
- case SCROLL_PART_HSCROLLBAR_LEFT:
- RCT2_CALLPROC_X(0x006E9A60, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
- break;
- case SCROLL_PART_HSCROLLBAR_RIGHT:
- RCT2_CALLPROC_X(0x006E9ABF, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
- break;
- case SCROLL_PART_HSCROLLBAR_LEFT_TROUGH:
- case SCROLL_PART_HSCROLLBAR_RIGHT_TROUGH:
- return;
- break;
- case SCROLL_PART_HSCROLLBAR_THUMB:
- case SCROLL_PART_VSCROLLBAR_TOP:
- RCT2_CALLPROC_X(0x006E9C37, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
- break;
- case SCROLL_PART_VSCROLLBAR_BOTTOM:
- RCT2_CALLPROC_X(0x006E9C96, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
- break;
- case SCROLL_PART_VSCROLLBAR_TOP_TROUGH:
- case SCROLL_PART_VSCROLLBAR_BOTTOM_TROUGH:
- return;
- break;
- default:
- return;
- }
-}
+ switch (scroll_part){
+ case SCROLL_PART_VIEW:
+ RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_DRAG], w->number / 18, y, x, y, (int)w, (int)widget, (int)w->event_handlers);
+ break;
+ case SCROLL_PART_HSCROLLBAR_LEFT:
+ RCT2_CALLPROC_X(0x006E9A60, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
+ break;
+ case SCROLL_PART_HSCROLLBAR_RIGHT:
+ RCT2_CALLPROC_X(0x006E9ABF, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
+ break;
+ case SCROLL_PART_HSCROLLBAR_LEFT_TROUGH:
+ case SCROLL_PART_HSCROLLBAR_RIGHT_TROUGH:
+ return;
+ break;
+ case SCROLL_PART_HSCROLLBAR_THUMB:
+ case SCROLL_PART_VSCROLLBAR_TOP:
+ RCT2_CALLPROC_X(0x006E9C37, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
+ break;
+ case SCROLL_PART_VSCROLLBAR_BOTTOM:
+ RCT2_CALLPROC_X(0x006E9C96, x, y, scroll_part, w->number, (int)w, (int)widget, 0);
+ break;
+ case SCROLL_PART_VSCROLLBAR_TOP_TROUGH:
+ case SCROLL_PART_VSCROLLBAR_BOTTOM_TROUGH:
+ return;
+ break;
+ default:
+ return;
+ }
+ }
static void input_scroll_end()
{
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
invalidate_scroll();
-}
+ }
#pragma endregion
@@ -638,8 +639,8 @@ static void input_widget_over(int x, int y, rct_window *w, int widgetIndex)
else if (ecx == 0) {
RCT2_CALLPROC_X(w->event_handlers[WE_SCROLL_MOUSEOVER], edx, 0, eax, ebx, (int)w, 0, 0);
input_update_tooltip(w, widgetIndex, x, y);
- }
- } else {
+ }
+ } else {
input_update_tooltip(w, widgetIndex, x, y);
}
@@ -714,7 +715,7 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex)
if (w != NULL) {
windowClass = w->classification;
windowNumber = w->number;
- }
+}
window_close_by_class(WC_ERROR);
window_close_by_class(WC_TOOLTIP);
@@ -773,7 +774,7 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex)
widget_invalidate_by_number(windowClass, windowNumber, widgetIndex);
window_event_mouse_down_call(w, widgetIndex);
- }
+ }
break;
}
}
@@ -781,9 +782,9 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex)
#pragma endregion
/**
-*
+ *
* rct2: 0x006ED833
-*/
+ */
void process_mouse_over(int x, int y)
{
rct_window* window;
@@ -797,7 +798,7 @@ void process_mouse_over(int x, int y)
RCT2_GLOBAL(0x9A9808, sint16) = -1;
window = window_find_from_point(x, y);
- if (window != NULL) {
+ if (window != NULL) {
widgetId = window_find_widget_from_point(window, x, y);
RCT2_GLOBAL(0x1420046, sint16) = (widgetId & 0xFFFF);
if (widgetId != -1) {
@@ -807,9 +808,9 @@ void process_mouse_over(int x, int y)
if (viewport_interaction_left_over(x, y)) {
sub_6ED990(CURSOR_HAND_POINT);
return;
- }
- break;
- }
+ }
+ break;
+ }
cursorId = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8);
subWindow = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass),
@@ -818,8 +819,8 @@ void process_mouse_over(int x, int y)
ebp = (int)subWindow;
if (subWindow == NULL)
{
- break;
- }
+ break;
+ }
ebx = ebx & 0xFFFFFF00;
edi = cursorId;
esi = (int) subWindow;
@@ -829,28 +830,28 @@ void process_mouse_over(int x, int y)
{
sub_6ED990(cursorId);
return;
- }
- break;
+ }
+ break;
case WWT_FRAME:
case WWT_RESIZE:
if (!(window->flags & 0x100))
{
- break;
- }
+ break;
+ }
if (window->min_width == window->max_width && window->min_height == window->max_height)
{
- break;
- }
+ break;
+ }
if (x < window->x + window->width - 0x13)
{
- break;
- }
+ break;
+ }
if (y < window->y + window->height - 0x13)
{
- break;
- }
+ break;
+ }
cursorId = CURSOR_DIAGONAL_ARROWS;
- break;
+ break;
case WWT_SCROLL:
RCT2_GLOBAL(0x9DE558, uint16) = x;
RCT2_GLOBAL(0x9DE55A, uint16) = y;
@@ -860,8 +861,8 @@ void process_mouse_over(int x, int y)
if (output_scroll_area != SCROLL_PART_VIEW)
{
cursorId = CURSOR_ARROW;
- break;
- }
+ break;
+ }
//Fall through to default
default:
ecx = x;
@@ -874,17 +875,17 @@ void process_mouse_over(int x, int y)
RCT2_CALLFUNC_X(window->event_handlers[WE_CURSOR], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
if (ebx == 0xFFFFFFFF) {
cursorId = CURSOR_ARROW;
- break;
- }
- cursorId = ebx;
- break;
- }
+ break;
}
- }
+ cursorId = ebx;
+ break;
+ }
+ }
+ }
viewport_interaction_right_over(x, y);
sub_6ED990(cursorId);
-}
+ }
/**
*
@@ -904,16 +905,15 @@ void process_mouse_tool(int x, int y)
else
RCT2_CALLPROC_X(w->event_handlers[WE_TOOL_UPDATE], x, y, 0, RCT2_GLOBAL(0x9DE546, uint16), (int)w, 0, 0);
- }
-}
+ }
+ }
/**
*
* rct2: 0x006E8DA7
*/
-void input_state_widget_pressed( int x, int y, int state, int widgetIndex, rct_window* w, rct_widget* widget ){
- //RCT2_CALLPROC_X(0x006E8DA7, x, y, state, widgetIndex, (int)w, (int)widget, 0);
- //return;
+void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_window *w, rct_widget *widget)
+{
RCT2_GLOBAL(0x1420054, uint16) = x;
RCT2_GLOBAL(0x1420056, uint16) = y;
@@ -923,7 +923,7 @@ void input_state_widget_pressed( int x, int y, int state, int widgetIndex, rct_w
cursor_w_number = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber);
int cursor_widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint32);
- rct_window* cursor_w = window_find_by_number(cursor_w_class, cursor_w_number);
+ rct_window *cursor_w = window_find_by_number(cursor_w_class, cursor_w_number);
if (cursor_w == NULL) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0;
return;
@@ -932,31 +932,33 @@ void input_state_widget_pressed( int x, int y, int state, int widgetIndex, rct_w
switch (state){
case 0:
if (!w || cursor_w_class != w->classification || cursor_w_number != w->number || widgetIndex != cursor_widgetIndex)
- break;
+ break;
if (w->disabled_widgets & (1ULL << widgetIndex))
break;
- if (RCT2_GLOBAL(0x9DE528, uint16) != 0) RCT2_GLOBAL(0x9DE528, uint16)++;
+ if (RCT2_GLOBAL(0x009DE528, uint16) != 0)
+ RCT2_GLOBAL(0x009DE528, uint16)++;
- if (w->var_020 & (1ULL << widgetIndex) &&
- RCT2_GLOBAL(0x9DE528, uint16) >= 0x10 &&
- (!(RCT2_GLOBAL(0x9DE528, uint16) & 0x3))){
+ if (w->hold_down_widgets & (1ULL << widgetIndex) &&
+ RCT2_GLOBAL(0x009DE528, uint16) >= 16 &&
+ !(RCT2_GLOBAL(0x009DE528, uint16) & 3)
+ ) {
window_event_mouse_down_call(w, widgetIndex);
}
- if (RCT2_GLOBAL(0x9DE518, uint32) & 1) return;
+ if (RCT2_GLOBAL(0x009DE518, uint32) & 1) return;
- RCT2_GLOBAL(0x9DE518, uint32) |= 1;
+ RCT2_GLOBAL(0x009DE518, uint32) |= 1;
widget_invalidate_by_number(cursor_w_class, cursor_w_number, widgetIndex);
return;
case 3:
case 2:
- if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == 5){
+ if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == 5) {
if (w) {
int dropdown_index = 0;
- if (w->classification == WC_DROPDOWN){
+ if (w->classification == WC_DROPDOWN) {
dropdown_index = dropdown_index_from_point(x, y, w);
if (dropdown_index == -1)goto dropdown_cleanup;
@@ -965,8 +967,7 @@ void input_state_widget_pressed( int x, int y, int state, int widgetIndex, rct_w
// gDropdownItemsFormat[dropdown_index] will not work until all windows that use dropdown decompiled
if (RCT2_ADDRESS(0x9DEBA4, uint16)[dropdown_index] == 0)goto dropdown_cleanup;
- }
- else{
+ } else {
if (cursor_w_class != w->classification || cursor_w_number != w->number || widgetIndex != cursor_widgetIndex)
goto dropdown_cleanup;
dropdown_index = -1;
@@ -980,7 +981,7 @@ void input_state_widget_pressed( int x, int y, int state, int widgetIndex, rct_w
window_close_by_class(WC_DROPDOWN);
cursor_w = window_find_by_number(cursor_w_class, cursor_w_number);
- if (RCT2_GLOBAL(0x9DE518, uint32) & 1){
+ if (RCT2_GLOBAL(0x9DE518, uint32) & 1) {
RCT2_GLOBAL(0x9DE518, uint32) &= 0xFFFE;
widget_invalidate_by_number(cursor_w_class, cursor_w_number, cursor_widgetIndex);
}
@@ -1002,24 +1003,24 @@ void input_state_widget_pressed( int x, int y, int state, int widgetIndex, rct_w
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = cursor_widgetIndex;
if (!w)
- break;
+ break;
if (!widget)
- break;
+ break;
int mid_point_x = (widget->left + widget->right) / 2 + w->x;
sound_play_panned(5, mid_point_x, 0, 0, 0);
if (cursor_w_class != w->classification || cursor_w_number != w->number || widgetIndex != cursor_widgetIndex)
- break;
+ break;
if (w->disabled_widgets & (1ULL << widgetIndex))
- break;
+ break;
widget_invalidate_by_number(cursor_w_class, cursor_w_number, widgetIndex);
window_event_mouse_up_call(w, widgetIndex);
default:
return;
- }
+ }
RCT2_GLOBAL(0x9DE528, uint16) = 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) != 5){
@@ -1027,9 +1028,9 @@ void input_state_widget_pressed( int x, int y, int state, int widgetIndex, rct_w
if (RCT2_GLOBAL(0x9DE518, uint32) & 1){
RCT2_GLOBAL(0x9DE518, uint32) &= 0xFFFE;
widget_invalidate_by_number(cursor_w_class, cursor_w_number, cursor_widgetIndex);
- }
+ }
return;
- }
+ }
if (!w) return;
@@ -1067,7 +1068,7 @@ static void input_update_tooltip(rct_window *w, int widgetIndex, int x, int y)
window_tooltip_open(w, widgetIndex, x, y);
// RCT2_CALLPROC_X(0x006EA10D, x, y, 0, widgetIndex, w, widget, 0); // window_tooltip_open();
- }
+}
} else {
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) != w->classification ||
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) != w->number ||
@@ -1170,7 +1171,6 @@ void game_handle_keyboard_input()
keyboard_shortcut_handle(key);
}
}
-
}
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0)
@@ -1208,13 +1208,13 @@ void game_handle_keyboard_input()
* rct2: 0x00406CD2
*/
int get_next_key()
-{
+ {
int i;
for (i = 0; i < 221; i++) {
if (gKeysPressed[i]) {
gKeysPressed[i] = 0;
return i;
- }
+}
}
return 0;
@@ -1238,7 +1238,7 @@ void sub_6ED990(char cursor_id){
}
RCT2_GLOBAL(RCT2_ADDRESS_CURENT_CURSOR, uint8) = cursor_id;
RCT2_GLOBAL(0x14241BC, uint32) = 2;
- osinterface_set_cursor(cursor_id);
+ platform_set_cursor(cursor_id);
RCT2_GLOBAL(0x14241BC, uint32) = 0;
}
@@ -1367,4 +1367,4 @@ void game_handle_key_scroll()
mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_VIEWPORT_SCROLLING;
}
-}
\ No newline at end of file
+}
diff --git a/src/interface/screenshot.c b/src/interface/screenshot.c
index cef28b0290..b44a3cc0f9 100644
--- a/src/interface/screenshot.c
+++ b/src/interface/screenshot.c
@@ -25,7 +25,6 @@
#include "../drawing/drawing.h"
#include "../game.h"
#include "../localisation/localisation.h"
-#include "../platform/osinterface.h"
#include "../platform/platform.h"
#include "../windows/error.h"
#include "screenshot.h"
@@ -71,7 +70,7 @@ void screenshot_check()
static int screenshot_get_next_path(char *path, int format)
{
- char *screenshotPath = osinterface_get_orct2_homesubfolder("screenshot");
+ char *screenshotPath = platform_get_orct2_homesubfolder("screenshot");
if (!platform_ensure_directory_exists(screenshotPath)) {
free(screenshotPath);
@@ -84,7 +83,7 @@ static int screenshot_get_next_path(char *path, int format)
RCT2_GLOBAL(0x013CE952, uint16) = i;
// Glue together path and filename
- sprintf(path, "%s%cSCR%d%s", screenshotPath, osinterface_get_path_separator(), i, _screenshot_format_extension[format]);
+ sprintf(path, "%s%cSCR%d%s", screenshotPath, platform_get_path_separator(), i, _screenshot_format_extension[format]);
if (!platform_file_exists(path)) {
return i;
diff --git a/src/interface/viewport.c b/src/interface/viewport.c
index 039f314461..21ae7f1535 100644
--- a/src/interface/viewport.c
+++ b/src/interface/viewport.c
@@ -339,8 +339,11 @@ void sub_6E7DE1(sint16 x, sint16 y, rct_window* w, rct_viewport* viewport){
//return;
uint8 zoom = (1 << viewport->zoom);
- sint16 x_diff = (viewport->view_x - x) / zoom;
- sint16 y_diff = (viewport->view_y - y) / zoom;
+ // Note: do not do the subtraction and then divide!
+ // Note: Due to arithmatic shift != /zoom a shift will have to be used
+ // hopefully when 0x006E7FF3 is finished this can be converted to /zoom.
+ sint16 x_diff = (viewport->view_x >> viewport->zoom) - (x >> viewport->zoom);
+ sint16 y_diff = (viewport->view_y >> viewport->zoom) - (y >> viewport->zoom);
viewport->view_x = x;
viewport->view_y = y;
@@ -527,8 +530,6 @@ void viewport_update_position(rct_window *window)
//RCT2_CALLPROC_X(0x6E7DE1, x, y, 0, 0, (int)window, (int)viewport, 0);
}
-void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, int top, int right, int bottom);
-
/**
*
* rct2: 0x00685C02
diff --git a/src/interface/viewport.h b/src/interface/viewport.h
index 10dc86f7b5..27eae985d7 100644
--- a/src/interface/viewport.h
+++ b/src/interface/viewport.h
@@ -80,6 +80,7 @@ void viewport_create(rct_window *w, int x, int y, int width, int height, int zoo
void viewport_update_pointers();
void viewport_update_position(rct_window *window);
void viewport_render(rct_drawpixelinfo *dpi, rct_viewport *viewport, int left, int top, int right, int bottom);
+void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, int top, int right, int bottom);
void sub_689174(sint16* x, sint16* y, sint16 *z, uint8 curr_rotation);
diff --git a/src/interface/viewport_interaction.c b/src/interface/viewport_interaction.c
index ad3b10d566..8849a2fe02 100644
--- a/src/interface/viewport_interaction.c
+++ b/src/interface/viewport_interaction.c
@@ -81,8 +81,8 @@ int viewport_interaction_get_item_left(int x, int y, viewport_interaction_info *
ride_set_map_tooltip(mapElement);
break;
case VIEWPORT_INTERACTION_ITEM_PARK:
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = RCT2_GLOBAL(0x013573D4, uint16);
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint32) = RCT2_GLOBAL(0x013573D8, uint32);
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id);
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32);
break;
default:
info->type = VIEWPORT_INTERACTION_ITEM_NONE;
@@ -190,7 +190,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info
case VIEWPORT_INTERACTION_ITEM_RIDE:
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR)
return info->type = VIEWPORT_INTERACTION_ITEM_NONE;
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH)
+ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH)
return info->type = VIEWPORT_INTERACTION_ITEM_NONE;
ride = GET_RIDE(mapElement->properties.track.ride_index);
@@ -199,13 +199,13 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = 1163;
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE) {
+ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) {
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint16) =
mapElement->properties.track.type == ENTRANCE_TYPE_RIDE_ENTRANCE ? 1335 : 1337;
} else if (mapElement->properties.track.type == 1 || mapElement->properties.track.type == 2 || mapElement->properties.track.type == 3) {
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint16) = 1333;
} else {
- if (!map_is_location_owned(x, y, mapElement->base_height << 4))
+ if (!map_is_location_owned(info->x, info->y, mapElement->base_height << 4))
return info->type = VIEWPORT_INTERACTION_ITEM_NONE;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint16) = ride->name;
@@ -285,10 +285,10 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info
return info->type;
case VIEWPORT_INTERACTION_ITEM_PARK:
- if (!(RCT2_ADDRESS_SCREEN_FLAGS & SCREEN_FLAGS_SCENARIO_EDITOR))
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR))
break;
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_ENTRANCE)
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE)
break;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = 1164;
@@ -331,8 +331,8 @@ int viewport_interaction_right_click(int x, int y)
return 0;
case VIEWPORT_INTERACTION_ITEM_SPRITE:
- if (info.mapElement->type == 0)
- RCT2_CALLPROC_X(0x006B4857, info.x, 0, info.y, (int)info.sprite, 0, 0, 0);
+ if (info.sprite->unknown.sprite_identifier == SPRITE_IDENTIFIER_VEHICLE)
+ ride_construct(info.sprite->vehicle.ride);
break;
case VIEWPORT_INTERACTION_ITEM_RIDE:
ride_modify(info.mapElement, info.x, info.y);
@@ -397,13 +397,14 @@ static void viewport_interaction_remove_footpath(rct_map_element *mapElement, in
if (w != NULL)
sub_6A7831();
- mapElement2 = TILE_MAP_ELEMENT_POINTER((y / 32) * 256 + (x / 32));
+ mapElement2 = map_get_first_element_at(x / 32, y / 32);
do {
- if ((mapElement2->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH && mapElement2->base_height == z) {
+ if (map_element_get_type(mapElement2) == MAP_ELEMENT_TYPE_PATH && mapElement2->base_height == z) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_REMOVE_FOOTPATH_FROM_HERE;
footpath_remove(x, y, z, 1);
+ break;
}
- } while (!((mapElement2++)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
+ } while (!map_element_is_last_for_tile(mapElement2++));
}
/**
@@ -436,7 +437,19 @@ static void viewport_interaction_remove_footpath_item(rct_map_element *mapElemen
*/
static void viewport_interaction_remove_park_entrance(rct_map_element *mapElement, int x, int y)
{
- RCT2_CALLPROC_X(0x00666C0E, x, 0, y, (int)mapElement, 0, 0, 0);
+ int rotation = (mapElement->type + 1) & 3;
+ switch (mapElement->properties.entrance.index & 0x0F) {
+ case 1:
+ x += TileDirectionDelta[rotation].x;
+ y += TileDirectionDelta[rotation].y;
+ break;
+ case 2:
+ x -= TileDirectionDelta[rotation].x;
+ y -= TileDirectionDelta[rotation].y;
+ break;
+ }
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_REMOVE_THIS;
+ game_do_command(x, GAME_COMMAND_FLAG_APPLY, y, mapElement->base_height / 2, GAME_COMMAND_REMOVE_PARK_ENTRANCE, 0, 0);
}
/**
@@ -451,10 +464,10 @@ static void viewport_interaction_remove_park_wall(rct_map_element *mapElement, i
if (sceneryEntry->wall.var_0D != 0xFF){
window_sign_small_open(mapElement->properties.fence.item[0]);
} else {
- RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = 1158;
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = STR_CANT_REMOVE_THIS;
game_do_command(
x,
- 1,
+ GAME_COMMAND_FLAG_APPLY,
y,
(mapElement->type & 0x3) | (mapElement->base_height << 8),
GAME_COMMAND_REMOVE_FENCE,
diff --git a/src/interface/window.c b/src/interface/window.c
index 5a2218b827..69b9ca1b44 100644
--- a/src/interface/window.c
+++ b/src/interface/window.c
@@ -23,7 +23,7 @@
#include "../game.h"
#include "../drawing/drawing.h"
#include "../input.h"
-#include "../platform/osinterface.h"
+#include "../platform/platform.h"
#include "../world/map.h"
#include "../world/sprite.h"
#include "widget.h"
@@ -319,7 +319,7 @@ static void window_all_wheel_input()
w = window_find_from_point(gCursorState.x, gCursorState.y);
if (w != NULL) {
// Check if main window
- if (w->classification == WC_MAIN_WINDOW) {
+ if (w->classification == WC_MAIN_WINDOW || w->classification == WC_VIEWPORT) {
window_viewport_wheel_input(w, wheel);
return;
}
@@ -417,7 +417,7 @@ rct_window *window_create(int x, int y, int width, int height, uint32 *event_han
w->enabled_widgets = 0;
w->disabled_widgets = 0;
w->pressed_widgets = 0;
- w->var_020 = 0;
+ w->hold_down_widgets = 0;
w->viewport_focus_coordinates.var_480 = 0;
w->viewport_focus_coordinates.x = 0;
w->viewport_focus_coordinates.y = 0;
@@ -1007,7 +1007,7 @@ rct_window *window_get_main()
/**
* Based on
- * rct2: 0x696ee9 & 0x66842F
+ * rct2: 0x696ee9 & 0x66842F & 0x006AF3B3
*
*/
void window_scroll_to_viewport(rct_window *w)
@@ -1654,6 +1654,38 @@ void window_bubble_list_item(rct_window* w, int item_position){
w->list_item_positions[item_position + 1] = swap;
}
+/* rct2: 0x006ED710
+ * Called after a window resize to move windows if they
+ * are going to be out of sight.
+ */
+void window_relocate_windows(int width, int height){
+ int new_location = 8;
+ for (rct_window* w = g_window_list; w < RCT2_NEW_WINDOW; w++){
+
+ // Work out if the window requires moving
+ if (w->x + 10 < width){
+ if (w->flags&(WF_STICK_TO_BACK | WF_STICK_TO_FRONT)){
+ if (w->y -22 < height)continue;
+ }
+ if (w->y + 10 < height)continue;
+ }
+
+ // Calculate the new locations
+ int x = w->x;
+ int y = w->y;
+ w->x = new_location;
+ w->y = new_location + 28;
+
+ // Move the next new location so windows are not directly on top
+ new_location += 8;
+
+ // Adjust the viewport if required.
+ if (w->viewport){
+ w->viewport->x -= x - w->x;
+ w->viewport->y -= y - w->y;
+ }
+ }
+}
/**
* rct2: 0x0066B905
@@ -1808,7 +1840,7 @@ void sub_6EA73F()
{
rct_window *w;
- if (RCT2_GLOBAL(0x009DEA6E, uint8) != 0)
+ if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0)
RCT2_GLOBAL(0x01423604, uint32)++;
for (w = RCT2_LAST_WINDOW; w >= g_window_list; w--) {
diff --git a/src/interface/window.h b/src/interface/window.h
index df38f2047f..dacc55a0b4 100644
--- a/src/interface/window.h
+++ b/src/interface/window.h
@@ -190,7 +190,7 @@ typedef struct rct_window {
uint64 enabled_widgets; // 0x008
uint64 disabled_widgets; // 0x010
uint64 pressed_widgets; // 0x018
- uint64 var_020;
+ uint64 hold_down_widgets; // 0x020
rct_widget* widgets; // 0x028
sint16 x; // 0x02C
sint16 y; // 0x02E
@@ -223,7 +223,7 @@ typedef struct rct_window {
};
sint16 page; // 0x48A
sint16 var_48C;
- sint16 frame_no; // 0x48E updated every tic for motion in windows sprites
+ uint16 frame_no; // 0x48E updated every tic for motion in windows sprites
uint16 list_information_type; // 0x490 0 for none, Used as current position of marquee in window_peep
sint16 var_492;
uint32 var_494;
@@ -397,7 +397,8 @@ enum {
WC_CHEATS = 110,
WC_RESEARCH = 111,
WC_VIEWPORT = 112,
- WC_TEXTINPUT = 113
+ WC_TEXTINPUT = 113,
+ WC_MAPGEN = 114
} WINDOW_CLASS;
enum PROMPT_MODE {
@@ -481,9 +482,10 @@ void window_update_viewport_ride_music();
// Open window functions
void window_main_open();
+void window_relocate_windows(int width, int height);
void window_resize_gui(int width, int height);
void window_resize_gui_scenario_editor(int width, int height);
-void window_game_top_toolbar_open();
+void window_top_toolbar_open();
void window_game_bottom_toolbar_open();
void window_about_open();
void window_footpath_open();
@@ -535,9 +537,9 @@ void window_publisher_credits_open();
void window_track_manage_open();
void window_viewport_open();
void window_text_input_open(rct_window* call_w, int call_widget, rct_string_id title, rct_string_id description, rct_string_id existing_text, uint32 existing_args, int maxLength);
+rct_window *window_mapgen_open();
void window_editor_main_open();
-void window_editor_top_toolbar_open();
void window_editor_bottom_toolbar_open();
void window_editor_object_selection_open();
void window_editor_inventions_list_open();
diff --git a/src/intro.c b/src/intro.c
index 17f22c2ce0..e5d9e09bef 100644
--- a/src/intro.c
+++ b/src/intro.c
@@ -23,7 +23,7 @@
#include "drawing/drawing.h"
#include "intro.h"
#include "localisation/localisation.h"
-#include "platform/osinterface.h"
+#include "platform/platform.h"
#include "sprites.h"
static void screen_intro_process_mouse_input();
@@ -262,7 +262,7 @@ void intro_update()
(*part) = 0;
// Change palette
- RCT2_CALLPROC_EBPSAFE(0x006837E3);
+ load_palette();
RCT2_GLOBAL(0x009E2C78, sint32) = 0;
gfx_invalidate_screen();
diff --git a/src/localisation/localisation.c b/src/localisation/localisation.c
index d659e2ce0d..a0ae867d76 100644
--- a/src/localisation/localisation.c
+++ b/src/localisation/localisation.c
@@ -18,6 +18,7 @@
* along with this program. If not, see .
*****************************************************************************/
+#include
#include "../addresses.h"
#include "../config.h"
#include "../game.h"
@@ -342,6 +343,84 @@ void format_currency_2dp(char **dest, long long value)
}
}
+void format_date(char **dest, uint16 value)
+{
+ uint16 args[] = { date_get_month(value), date_get_year(value) + 1 };
+ uint16 *argsRef = args;
+ format_string_part(dest, 2736, (char**)&argsRef);
+ (*dest)--;
+}
+
+void format_length(char **dest, uint16 value)
+{
+ rct_string_id stringId = 2733;
+
+ if (gGeneral_config.measurement_format == MEASUREMENT_FORMAT_IMPERIAL) {
+ value = metres_to_feet(value);
+ stringId--;
+ }
+
+ uint16 *argRef = &value;
+ format_string_part(dest, stringId, (char**)&argRef);
+}
+
+void format_velocity(char **dest, uint16 value)
+{
+ rct_string_id stringId = 2734;
+
+ if (gGeneral_config.measurement_format == MEASUREMENT_FORMAT_METRIC) {
+ value = mph_to_kmph(value);
+ stringId++;
+ }
+
+ uint16 *argRef = &value;
+ format_string_part(dest, stringId, (char**)&argRef);
+}
+
+void format_duration(char **dest, uint16 value)
+{
+ uint16 minutes = value / 60;
+ uint16 seconds = value % 60;
+ uint16 args[] = { minutes, seconds };
+ uint16 *argsRef = &args[1];
+ rct_string_id stringId = 2720;
+
+ if (minutes > 0) {
+ stringId += 2;
+ if (minutes != 1)
+ stringId += 2;
+
+ argsRef--;
+ }
+
+ if (seconds != 1)
+ stringId++;
+
+ format_string_part(dest, stringId, (char**)&argsRef);
+}
+
+void format_realtime(char **dest, uint16 value)
+{
+ uint16 hours = value / 60;
+ uint16 minutes = value % 60;
+ uint16 args[] = { hours, minutes };
+ uint16 *argsRef = &args[1];
+ rct_string_id stringId = 2726;
+
+ if (hours > 0) {
+ stringId += 2;
+ if (hours != 1)
+ stringId += 2;
+
+ argsRef--;
+ }
+
+ if (minutes != 1)
+ stringId++;
+
+ format_string_part(dest, stringId, (char**)&argsRef);
+}
+
void format_string_code(unsigned char format_code, char **dest, char **args)
{
int value;
@@ -418,13 +497,7 @@ void format_string_code(unsigned char format_code, char **dest, char **args)
value = *((uint16*)*args);
*args += 2;
- uint16 dateArgs[] = { date_get_month(value), date_get_year(value) + 1 };
- uint16 *dateArgs2 = dateArgs;
- char formatString[] = "?, Year ?";
- formatString[0] = FORMAT_MONTH;
- formatString[8] = FORMAT_COMMA16;
- format_string_part_from_raw(dest, formatString, (char**)&dateArgs2);
- (*dest)--;
+ format_date(dest, value);
break;
case FORMAT_MONTH:
// Pop argument
@@ -439,15 +512,7 @@ void format_string_code(unsigned char format_code, char **dest, char **args)
value = *((sint16*)*args);
*args += 2;
- if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, uint8)) {
- format_comma_separated_integer(dest, mph_to_kmph(value));
- strcpy(*dest, "kmh");
- *dest += strlen(*dest);
- } else {
- format_comma_separated_integer(dest, value);
- strcpy(*dest, "mph");
- *dest += strlen(*dest);
- }
+ format_velocity(dest, value);
break;
case FORMAT_POP16:
*args += 2;
@@ -460,45 +525,21 @@ void format_string_code(unsigned char format_code, char **dest, char **args)
value = *((uint16*)*args);
*args += 2;
- if (value / 60 > 0) {
- format_integer(dest, value / 60);
- strcpy(*dest, value / 60 == 1 ? "min:" : "mins:");
- *dest += strlen(*dest);
- }
-
- format_integer(dest, value % 60);
- strcpy(*dest, value % 60 == 1 ? "sec" : "secs");
- *dest += strlen(*dest);
+ format_duration(dest, value);
break;
case FORMAT_REALTIME:
// Pop argument
value = *((uint16*)*args);
*args += 2;
- if (value / 60 > 0) {
- format_integer(dest, value / 60);
- strcpy(*dest, value / 60 == 1 ? "hour:" : "hours:");
- *dest += strlen(*dest);
- }
-
- format_integer(dest, value % 60);
- strcpy(*dest, value % 60 == 1 ? "min" : "mins");
- *dest += strlen(*dest);
+ format_realtime(dest, value);
break;
case FORMAT_LENGTH:
// Pop argument
value = *((sint16*)*args);
*args += 2;
- if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, uint8)) {
- format_comma_separated_integer(dest, value);
- strcpy(*dest, "m");
- *dest += strlen(*dest);
- } else {
- format_comma_separated_integer(dest, metres_to_feet(value));
- strcpy(*dest, "ft");
- *dest += strlen(*dest);
- }
+ format_length(dest, value);
break;
case FORMAT_SPRITE:
// Pop argument
@@ -700,4 +741,13 @@ int get_string_length(char* buffer)
}
}
return length;
+}
+
+int win1252_to_utf8(utf8string dst, const char *src, int maxBufferLength)
+{
+ utf16 intermediateBuffer[512];
+
+ // TODO this supports only a maximum of 512 characters
+ MultiByteToWideChar(CP_ACP, 0, src, -1, intermediateBuffer, 512);
+ return WideCharToMultiByte(CP_UTF8, 0, intermediateBuffer, -1, dst, maxBufferLength, NULL, NULL);
}
\ No newline at end of file
diff --git a/src/localisation/localisation.h b/src/localisation/localisation.h
index 97068d7eed..cdaa833954 100644
--- a/src/localisation/localisation.h
+++ b/src/localisation/localisation.h
@@ -32,8 +32,11 @@ void error_string_quit(int error, rct_string_id format);
int get_string_length(char* buffer);
void user_string_clear_all();
+rct_string_id user_string_allocate(int base, const char *text);
void user_string_free(rct_string_id id);
+int win1252_to_utf8(utf8string dst, const char *src, int maxBufferLength);
+
#define MAX_USER_STRINGS 1024
#define USER_STRING_MAX_LENGTH 32
diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h
index be11141345..1d6965f4cc 100644
--- a/src/localisation/string_ids.h
+++ b/src/localisation/string_ids.h
@@ -485,6 +485,7 @@ enum {
STR_YES = 1710,
STR_FIRE_STAFF_ID = 1711,
+ STR_INVALID_NAME_FOR_PARK = 1716,
STR_CANT_RENAME_PARK = 1717,
STR_PARK_NAME = 1718,
STR_ENTER_PARK_NAME = 1719,
@@ -822,6 +823,7 @@ enum {
STR_TILE_SMOOTHING_TIP = 2362,
STR_GRIDLINES = 2363,
STR_GRIDLINES_TIP = 2364,
+ STR_BANK_REFUSES_TO_INCREASE_LOAN = 2365,
STR_CELSIUS = 2366,
STR_FAHRENHEIT = 2367,
//STR_NONE = 2368,
@@ -1199,9 +1201,25 @@ enum {
STR_LIST = 3159,
+ STR_UNABLE_TO_SELECT_THIS_OBJECT = 3176,
+ STR_UNABLE_TO_DE_SELECT_THIS_OBJECT = 3177,
STR_AT_LEAST_ONE_PATH_OBJECT_MUST_BE_SELECTED = 3178,
STR_INVALID_SELECTION_OF_OBJECTS = 3180,
+ STR_OBJECT_SELECTION = 3181,
+ STR_PARK_ENTRANCE_TYPE_MUST_BE_SELECTED = 3182,
+ STR_WATER_TYPE_MUST_BE_SELECTED = 3183,
+ STR_OBJECT_SELECTION_RIDE_VEHICLES_ATTRACTIONS = 3184,
+ STR_OBJECT_SELECTION_SMALL_SCENERY = 3185,
+ STR_OBJECT_SELECTION_LARGE_SCENERY = 3186,
+ STR_OBJECT_SELECTION_WALLS_FENCES = 3187,
+ STR_OBJECT_SELECTION_PATH_SIGNS = 3188,
+ STR_OBJECT_SELECTION_FOOTPATHS = 3189,
+ STR_OBJECT_SELECTION_PATH_EXTRAS = 3190,
+ STR_OBJECT_SELECTION_SCENERY_GROUPS = 3191,
+ STR_OBJECT_SELECTION_PARK_ENTRANCE = 3192,
+ STR_OBJECT_SELECTION_WATER = 3193,
+ STR_OBJECT_SELECTION_SCENARIO_DESCRIPTION = 3194,
STR_INVENTION_LIST = 3195,
@@ -1296,6 +1314,8 @@ enum {
STR_PARK_ENTRANCE_WRONG_DIRECTION_OR_NO_PATH = 3332,
STR_SAVE_PLUGIN_DATA = 3333,
STR_SAVE_PLUGIN_DATA_TIP = 3334,
+ STR_ROLLER_COASTER_DESIGNER_SELECT_RIDE_TYPES_VEHICLES = 3335,
+ STR_TRACK_DESIGNS_MANAGER_SELECT_RIDE_TYPE = 3336,
STR_SIX_FLAGS_PARK = 3337,
STR_GAME_TOOLS = 3341,
@@ -1317,9 +1337,16 @@ enum {
STR_SOUND_FORCED_SOFTWARE_BUFFER_MIXING = 3362,
STR_SOUND_FORCED_SOFTWARE_BUFFER_MIXING_TIP = 3363,
+ STR_OBJECT_SELECTION_ADVANCED = 3364,
+ STR_OBJECT_SELECTION_ADVANCED_TIP = 3365,
STR_MAP_RIDE = 3366,
+ STR_WARNING_TOO_MANY_OBJECTS_SELECTED = 3374,
+ STR_NOT_ALL_OBJECTS_IN_THIS_SCENERY_GROUP_COULD_BE_SELECTED = 3375,
+ STR_INSTALL_NEW_TRACK_DESIGN = 3376,
+ STR_INSTALL_NEW_TRACK_DESIGN_TIP = 3377,
+
STR_TUTORIAL_BEGINNERS = 3385,
STR_TUTORIAL_CUSTOM_RIDES = 3386,
STR_TUTORIAL_ROLLER_COASTER = 3387,
diff --git a/src/localisation/user.c b/src/localisation/user.c
index a832775f15..54a856ef02 100644
--- a/src/localisation/user.c
+++ b/src/localisation/user.c
@@ -18,6 +18,7 @@
* along with this program. If not, see .
*****************************************************************************/
+#include "../addresses.h"
#include "localisation.h"
char *gUserStrings = (char*)0x0135A8F4;
@@ -31,6 +32,21 @@ void user_string_clear_all()
memset(gUserStrings, 0, MAX_USER_STRINGS * USER_STRING_MAX_LENGTH);
}
+/**
+ *
+ * rct2: 0x006C421D
+ */
+rct_string_id user_string_allocate(int base, const char *text)
+{
+ int eax, ebx, ecx, edx, esi, edi, ebp;
+
+ ecx = base;
+ edi = (int)text;
+ RCT2_CALLFUNC_X(0x006C421D, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+
+ return eax & 0xFFFF;
+}
+
/**
*
* rct2: 0x006C42AC
diff --git a/src/management/award.c b/src/management/award.c
index a30c45d054..5f50011ba2 100644
--- a/src/management/award.c
+++ b/src/management/award.c
@@ -412,13 +412,13 @@ static int award_is_deserved_most_disappointing(int awardType, int activeAwardTy
disappointingRides = 0;
FOR_ALL_RIDES(i, ride) {
- if (ride->excitement == 0xFFFF || ride->var_158 == 0xFF)
+ if (ride->excitement == 0xFFFF || ride->popularity == 0xFF)
continue;
countedRides++;
- // Satification maybe?
- if (ride->var_158 <= 6)
+ // Unpopular
+ if (ride->popularity <= 6)
disappointingRides++;
}
diff --git a/src/management/finance.c b/src/management/finance.c
index d8426ed1ef..81a382e152 100644
--- a/src/management/finance.c
+++ b/src/management/finance.c
@@ -19,7 +19,9 @@
*****************************************************************************/
#include "../addresses.h"
+#include "../game.h"
#include "../interface/window.h"
+#include "../localisation/localisation.h"
#include "../peep/peep.h"
#include "../ride/ride.h"
#include "../world/park.h"
@@ -42,6 +44,8 @@ const money32 research_cost_table[4] = {
MONEY(400,00) // Maximum funding
};
+int dword_988E60[] = { 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0 };
+
/**
* Pay an amount of money.
* rct2: 0x069C674
@@ -56,7 +60,7 @@ void finance_payment(money32 amount, rct_expenditure_type type)
//overflow check
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32) = ENCRYPT_MONEY(new_money);
RCT2_ADDRESS(RCT2_ADDRESS_EXPENDITURE_TABLE, money32)[type] -= amount;
- if (RCT2_ADDRESS(0x00988E60, uint32)[type] & 1)
+ if (dword_988E60[type] & 1)
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_EXPENDITURE, money32) -= amount; // Cumulative amount of money spent this day
@@ -131,7 +135,7 @@ void finance_pay_ride_upkeep()
if (upkeep != -1) {
ride->total_profit -= upkeep;
ride->var_14D |= 2;
- finance_payment(upkeep, RCT2_EXPENDITURE_TYPE_RIDE_UPKEEP);
+ finance_payment(upkeep, RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS);
}
}
}
@@ -239,7 +243,7 @@ void sub_69E869()
{
// This subroutine is loan related and is used for cheat detection
sint32 value = 0x70093A;
- value -= RCT2_GLOBAL(0x013573DC, money32); // Cheat detection
+ value -= RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, money32);
value = ror32(value, 5);
value -= RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32);
value = ror32(value, 7);
@@ -247,3 +251,50 @@ void sub_69E869()
value = ror32(value, 3);
RCT2_GLOBAL(0x013587C4, sint32) = value;
}
+
+void finance_set_loan(money32 loan)
+{
+ game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, loan, GAME_COMMAND_SET_CURRENT_LOAN, 0, 0);
+}
+
+/**
+ *
+ * rct2: 0x0069DFB3
+ */
+void game_command_set_current_loan(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp)
+{
+ money32 money, loanDifference, currentLoan;
+ money32 newLoan = *edx;
+
+ currentLoan = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32);
+ money = DECRYPT_MONEY(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, money32));
+ loanDifference = currentLoan - newLoan;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_INTEREST * 4;
+ if (newLoan > currentLoan) {
+ if (newLoan > RCT2_GLOBAL(RCT2_ADDRESS_MAXIMUM_LOAN, money32)) {
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_BANK_REFUSES_TO_INCREASE_LOAN;
+ *ebx = MONEY32_UNDEFINED;
+ return;
+ }
+ } else {
+ if (loanDifference > money) {
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_NOT_ENOUGH_CASH_AVAILABLE;
+ *ebx = MONEY32_UNDEFINED;
+ return;
+ }
+ }
+
+ if (*ebx & GAME_COMMAND_FLAG_APPLY) {
+ money -= loanDifference;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32) = newLoan;
+ RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, money32) = money;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, money32) = ENCRYPT_MONEY(money);
+ sub_69E869();
+
+ window_invalidate_by_class(WC_FINANCES);
+ RCT2_GLOBAL(0x009A9804, uint16) |= 1;
+ }
+
+ *ebx = 0;
+}
\ No newline at end of file
diff --git a/src/management/finance.h b/src/management/finance.h
index f87998ab15..ffd8da01d5 100644
--- a/src/management/finance.h
+++ b/src/management/finance.h
@@ -26,10 +26,20 @@
typedef int rct_expenditure_type;
enum {
- RCT2_EXPENDITURE_TYPE_RIDE_UPKEEP = 1,
- RCT_EXPENDITURE_TYPE_WAGES = 10,
- RCT_EXPENDITURE_TYPE_RESEARCH = 12,
- RCT_EXPENDITURE_TYPE_INTEREST = 13
+ RCT_EXPENDITURE_TYPE_RIDE_CONSRUCTION,
+ RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS,
+ RCT_EXPENDITURE_TYPE_LAND_PURCHASE,
+ RCT_EXPENDITURE_TYPE_LANDSCAPING,
+ RCT_EXPENDITURE_TYPE_PARK_ENTRANCE_TICKETS,
+ RCT_EXPENDITURE_TYPE_PARK_RIDE_TICKETS,
+ RCT_EXPENDITURE_TYPE_SHOP_SHOP_SALES,
+ RCT_EXPENDITURE_TYPE_SHOP_STOCK,
+ RCT_EXPENDITURE_TYPE_FOODDRINK_SALES,
+ RCT_EXPENDITURE_TYPE_FOODDRINK_STOCK,
+ RCT_EXPENDITURE_TYPE_WAGES,
+ RCT_EXPENDITURE_TYPE_MARKETING,
+ RCT_EXPENDITURE_TYPE_RESEARCH,
+ RCT_EXPENDITURE_TYPE_INTEREST
};
extern const money32 research_cost_table[4];
@@ -44,4 +54,7 @@ void finance_init();
void finance_update_daily_profit();
void sub_69E869();
+void finance_set_loan(money32 loan);
+void game_command_set_current_loan(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
+
#endif
\ No newline at end of file
diff --git a/src/management/marketing.c b/src/management/marketing.c
index c8e56269e0..dcf575e74b 100644
--- a/src/management/marketing.c
+++ b/src/management/marketing.c
@@ -19,8 +19,10 @@
*****************************************************************************/
#include "../addresses.h"
+#include "../game.h"
#include "../interface/window.h"
#include "../localisation/localisation.h"
+#include "../management/finance.h"
#include "../ride/ride.h"
#include "marketing.h"
#include "news_item.h"
@@ -36,6 +38,9 @@ const money16 AdvertisingCampaignPricePerWeek[] = {
const int advertisingCampaignGuestGenerationProbabilities[] = { 400, 300, 200, 200, 250, 200 };
+uint8 *gMarketingCampaignDaysLeft = RCT2_ADDRESS(0x01358102, uint8);
+uint8 *gMarketingCampaignRideIndex = RCT2_ADDRESS(0x01358116, uint8);
+
int marketing_get_campaign_guest_generation_probability(int campaign)
{
int probability = advertisingCampaignGuestGenerationProbabilities[campaign];
@@ -52,7 +57,7 @@ int marketing_get_campaign_guest_generation_probability(int campaign)
probability /= 8;
break;
case ADVERTISING_CAMPAIGN_RIDE_FREE:
- ride = &g_ride_list[RCT2_ADDRESS(0x01358116, uint8)[campaign]];
+ ride = &g_ride_list[gMarketingCampaignRideIndex[campaign]];
if (ride->price < 3)
probability /= 8;
break;
@@ -68,33 +73,32 @@ int marketing_get_campaign_guest_generation_probability(int campaign)
void marketing_update()
{
for (int campaign = 0; campaign < ADVERTISING_CAMPAIGN_COUNT; campaign++) {
- uint8 campaign_weeks_left = RCT2_ADDRESS(0x01358102, uint8)[campaign];
- if (campaign_weeks_left == 0)
+ int active = (gMarketingCampaignDaysLeft[campaign] & CAMPAIGN_ACTIVE_FLAG) != 0;
+ if (gMarketingCampaignDaysLeft[campaign] == 0)
continue;
window_invalidate_by_class(WC_FINANCES);
- // High bit marks the campaign as inactive, on first check the campaign is set actice
+ // High bit marks the campaign as inactive, on first check the campaign is set active
// this makes campaigns run a full x weeks even when started in the middle of a week
- RCT2_ADDRESS(0x01358102, uint8)[campaign] &= ~(1 << 7);
- if (campaign_weeks_left & (1 << 7))
+ gMarketingCampaignDaysLeft[campaign] &= ~CAMPAIGN_ACTIVE_FLAG;
+ if (active)
continue;
- RCT2_ADDRESS(0x01358102, uint8)[campaign]--;
- if (campaign_weeks_left - 1 != 0)
+ if (--gMarketingCampaignDaysLeft[campaign] != 0)
continue;
- int campaign_item = RCT2_ADDRESS(0x01358116, uint8)[campaign];
+ int campaignItem = gMarketingCampaignRideIndex[campaign];
// This sets the string parameters for the marketing types that have an argument.
if (campaign == ADVERTISING_CAMPAIGN_RIDE_FREE || campaign == ADVERTISING_CAMPAIGN_RIDE) {
- RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x01362942 + 304 * campaign_item, uint16);
- RCT2_GLOBAL(0x013CE954, uint32) = RCT2_GLOBAL(0x01362944 + 152 * campaign_item, uint32);
+ RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x01362942 + 304 * campaignItem, uint16);
+ RCT2_GLOBAL(0x013CE954, uint32) = RCT2_GLOBAL(0x01362944 + 152 * campaignItem, uint32);
} else if (campaign == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) {
- campaign_item += 2016;
- if (campaign_item >= 2048)
- campaign_item += 96;
- RCT2_GLOBAL(0x013CE952, uint16) = campaign_item;
+ campaignItem += 2016;
+ if (campaignItem >= 2048)
+ campaignItem += 96;
+ RCT2_GLOBAL(0x013CE952, uint16) = campaignItem;
}
news_item_add_to_queue(NEWS_ITEM_MONEY, STR_MARKETING_FINISHED_BASE + campaign, 0);
@@ -111,8 +115,8 @@ void marketing_set_guest_campaign(rct_peep *peep, int campaign)
case ADVERTISING_CAMPAIGN_RIDE_FREE:
peep->item_standard_flags |= PEEP_ITEM_VOUCHER;
peep->voucher_type = VOUCHER_TYPE_RIDE_FREE;
- peep->voucher_arguments = RCT2_ADDRESS(0x01358116, uint8)[campaign];
- peep->guest_heading_to_ride_id = RCT2_ADDRESS(0x01358116, uint8)[campaign];
+ peep->voucher_arguments = gMarketingCampaignRideIndex[campaign];
+ peep->guest_heading_to_ride_id = gMarketingCampaignRideIndex[campaign];
peep->var_C6 = 240;
break;
case ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE:
@@ -122,13 +126,46 @@ void marketing_set_guest_campaign(rct_peep *peep, int campaign)
case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE:
peep->item_standard_flags |= PEEP_ITEM_VOUCHER;
peep->voucher_type = VOUCHER_TYPE_FOOD_OR_DRINK_FREE;
- peep->voucher_arguments = RCT2_ADDRESS(0x01358116, uint8)[campaign];
+ peep->voucher_arguments = gMarketingCampaignRideIndex[campaign];
break;
case ADVERTISING_CAMPAIGN_PARK:
break;
case ADVERTISING_CAMPAIGN_RIDE:
- peep->guest_heading_to_ride_id = RCT2_ADDRESS(0x01358116, uint8)[campaign];
+ peep->guest_heading_to_ride_id = gMarketingCampaignRideIndex[campaign];
peep->var_C6 = 240;
break;
}
+}
+
+void marketing_start_campaign(int type, int rideOrItem, int numWeeks)
+{
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_START_MARKETING_CAMPAIGN;
+ game_do_command(0, (numWeeks << 8) | GAME_COMMAND_FLAG_APPLY, 0, (rideOrItem << 8) | type, GAME_COMMAND_START_MARKETING_CAMPAIGN, 0, 0);
+}
+
+/**
+ *
+ * rct2: 0x0069E73C
+ */
+void game_command_start_campaign(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp)
+{
+ int type = *edx & 0xFF;
+ int rideOrItem = (*edx >> 8) & 0xFF;
+ int numWeeks = (*ebx >> 8) & 0xFF;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_MARKETING * 4;
+ if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_FORBID_MARKETING_CAMPAIGN) {
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 3048;
+ *ebx = MONEY32_UNDEFINED;
+ return;
+ }
+
+ if (*ebx & GAME_COMMAND_FLAG_APPLY) {
+ gMarketingCampaignDaysLeft[type] = numWeeks | CAMPAIGN_ACTIVE_FLAG;
+ gMarketingCampaignRideIndex[type] = rideOrItem;
+
+ window_invalidate_by_class(WC_FINANCES);
+ }
+
+ *ebx = numWeeks * AdvertisingCampaignPricePerWeek[type];
}
\ No newline at end of file
diff --git a/src/management/marketing.h b/src/management/marketing.h
index 6435256cb4..33abb47560 100644
--- a/src/management/marketing.h
+++ b/src/management/marketing.h
@@ -41,10 +41,16 @@ enum{
VOUCHER_TYPE_FOOD_OR_DRINK_FREE,
};
+#define CAMPAIGN_ACTIVE_FLAG (1 << 7)
+
extern const money16 AdvertisingCampaignPricePerWeek[6];
+extern uint8 *gMarketingCampaignDaysLeft;
+extern uint8 *gMarketingCampaignRideIndex;
int marketing_get_campaign_guest_generation_probability(int campaign);
void marketing_update();
void marketing_set_guest_campaign(rct_peep *peep, int campaign);
+void marketing_start_campaign(int type, int rideOrItem, int numWeeks);
+void game_command_start_campaign(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
#endif
\ No newline at end of file
diff --git a/src/management/research.c b/src/management/research.c
index 4aac4d1b3e..94436bab4a 100644
--- a/src/management/research.c
+++ b/src/management/research.c
@@ -19,12 +19,14 @@
*****************************************************************************/
#include "../addresses.h"
+#include "../game.h"
#include "../interface/window.h"
#include "../localisation/date.h"
+#include "../management/finance.h"
+#include "../scenario.h"
#include "../world/scenery.h"
#include "news_item.h"
#include "research.h"
-#include "../scenario.h"
const int _researchRate[] = { 0, 160, 250, 400 };
@@ -262,7 +264,10 @@ void research_update()
}
}
-/* rct2: 0x684AC3*/
+/**
+ *
+ * rct2: 0x00684AC3
+ */
void sub_684AC3(){
rct_research_item* research = gResearchItems;
for (; research->entryIndex != -2; research++);
@@ -317,4 +322,39 @@ void sub_684AC3(){
RCT2_GLOBAL(RCT2_ADDRESS_LAST_RESEARCHED_ITEM_SUBJECT, sint32) = -1;
RCT2_GLOBAL(RCT2_ADDRESS_RESEARH_PROGRESS_STAGE, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_RESEARH_PROGRESS, uint16) = 0;
+}
+
+void research_set_funding(int amount)
+{
+ game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, amount, GAME_COMMAND_SET_RESEARCH_FUNDING, 0, 0);
+
+}
+
+void research_set_priority(int activeCategories)
+{
+ game_do_command(0, (1 << 8) | GAME_COMMAND_FLAG_APPLY, 0, activeCategories, GAME_COMMAND_SET_RESEARCH_FUNDING, 0, 0);
+}
+
+/**
+ *
+ * rct2: 0x00684A7F
+ */
+void game_command_set_research_funding(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp)
+{
+ int setPriorities = (*ebx & (1 << 8)) != 0;
+ int fundingAmount = *edx;
+ int activeCategories = *edx;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RESEARCH * 4;
+ if (*ebx & GAME_COMMAND_FLAG_APPLY) {
+ if (!setPriorities)
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RESEARCH_LEVEL, uint8) = fundingAmount;
+ else
+ RCT2_GLOBAL(RCT2_ADDRESS_ACTIVE_RESEARCH_TYPES, uint8) = activeCategories;
+
+ window_invalidate_by_class(WC_FINANCES);
+ window_invalidate_by_class(WC_RESEARCH);
+ }
+
+ *ebx = 0;
}
\ No newline at end of file
diff --git a/src/management/research.h b/src/management/research.h
index 0a07d36d1c..b62d84d4de 100644
--- a/src/management/research.h
+++ b/src/management/research.h
@@ -55,4 +55,8 @@ void research_update_uncompleted_types();
void research_update();
void sub_684AC3();
+void research_set_funding(int amount);
+void research_set_priority(int activeCategories);
+void game_command_set_research_funding(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
+
#endif
\ No newline at end of file
diff --git a/src/object.c b/src/object.c
index 03ce1d7d80..3637bda5ed 100644
--- a/src/object.c
+++ b/src/object.c
@@ -21,7 +21,6 @@
#include "addresses.h"
#include "localisation/localisation.h"
#include "object.h"
-#include "platform/osinterface.h"
#include "platform/platform.h"
#include "util/sawyercoding.h"
@@ -51,7 +50,7 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi
subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), (char*)installedObject + 16);
- // log_verbose("loading object, %s", path);
+ log_verbose("loading object, %s", path);
file = fopen(path, "rb");
if (file == NULL)
@@ -495,7 +494,7 @@ int object_get_scenario_text(rct_object_entry *entry)
void object_free_scenario_text()
{
if (RCT2_GLOBAL(0x009ADAF8, void*) != NULL) {
- free(RCT2_GLOBAL(0x009ADAF8, void*));
+ rct2_free(RCT2_GLOBAL(0x009ADAF8, void*));
RCT2_GLOBAL(0x009ADAF8, void*) = NULL;
}
}
@@ -534,4 +533,20 @@ rct_object_entry *object_get_next(rct_object_entry *entry)
pos += 4;
return (rct_object_entry*)pos;
+}
+
+char *object_get_name(rct_object_entry *entry)
+{
+ uint8 *pos = (uint8*)entry;
+
+ // Skip sizeof(rct_object_entry)
+ pos += 16;
+
+ // Skip filename
+ while (*pos++);
+
+ // Skip
+ pos += 4;
+
+ return pos;
}
\ No newline at end of file
diff --git a/src/object.h b/src/object.h
index 70be1a0f5a..dfe8e6fbc9 100644
--- a/src/object.h
+++ b/src/object.h
@@ -87,7 +87,11 @@ int object_calculate_checksum(const rct_object_entry *entry, const char *data, i
int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp);
rct_object_entry *object_get_next(rct_object_entry *entry);
int sub_6A9F42(FILE *file, rct_object_entry* entry);
+void sub_6A9FC0();
+int find_object_in_entry_group(rct_object_entry* entry, uint8* entry_type, uint8* entry_index);
rct_object_entry *object_list_find(rct_object_entry *entry);
+char *object_get_name(rct_object_entry *entry);
+
#endif
\ No newline at end of file
diff --git a/src/object_list.c b/src/object_list.c
index 09cb0bcf1f..abb7ef2278 100644
--- a/src/object_list.c
+++ b/src/object_list.c
@@ -22,7 +22,6 @@
#include "localisation/localisation.h"
#include "object.h"
#include "platform/platform.h"
-#include "platform/osinterface.h"
#include "ride/track.h"
#include "util/sawyercoding.h"
@@ -79,7 +78,7 @@ rct_object_entry_group object_entry_groups[] = {
(uint8**)(0x009ACFA4 + (699 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (699 * 20)), // scenery sets
(uint8**)(0x009ACFA4 + (718 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (718 * 20)), // park entrance
(uint8**)(0x009ACFA4 + (719 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (719 * 20)), // water
- (uint8**)(0x009ACFA4 + (720 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (720 * 20)) // scenario text
+ (uint8**)(0x009ACFA4 + (720 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (720 * 20)) // scenario text
};
static int object_list_cache_load(int totalFiles, uint64 totalFileSize, int fileDateModifiedChecksum);
@@ -90,11 +89,61 @@ static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* in
static void get_plugin_path(char *path)
{
- char *homePath = osinterface_get_orct2_homefolder();
- sprintf(path, "%s%c%s", homePath, osinterface_get_path_separator(), "plugin.dat");
+ char *homePath = platform_get_orct2_homefolder();
+ sprintf(path, "%s%c%s", homePath, platform_get_path_separator(), "plugin.dat");
free(homePath);
}
+static void object_list_sort()
+{
+ rct_object_entry **objectBuffer, *newBuffer, *entry, *destEntry, *lowestEntry;
+ int numObjects, i, j, bufferSize, entrySize, lowestIndex;
+ char *objectName, *lowestString;
+ uint8 *copied;
+
+ objectBuffer = &RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
+ numObjects = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, sint32);
+ copied = calloc(numObjects, sizeof(uint8));
+
+ // Get buffer size
+ entry = *objectBuffer;
+ for (i = 0; i < numObjects; i++)
+ entry = object_get_next(entry);
+ bufferSize = (int)entry - (int)*objectBuffer;
+
+ // Create new buffer
+ newBuffer = rct2_malloc(bufferSize);
+ destEntry = newBuffer;
+
+ // Copy over sorted objects
+ for (i = 0; i < numObjects; i++) {
+ // Find next lowest string
+ lowestString = NULL;
+ entry = *objectBuffer;
+ for (j = 0; j < numObjects; j++) {
+ if (!copied[j]) {
+ objectName = object_get_name(entry);
+ if (lowestString == NULL || strcmp(objectName, lowestString) < 0) {
+ lowestEntry = entry;
+ lowestString = objectName;
+ lowestIndex = j;
+ }
+ }
+ entry = object_get_next(entry);
+ }
+ entrySize = object_get_length(lowestEntry);
+ memcpy(destEntry, lowestEntry, entrySize);
+ destEntry = (rct_object_entry*)((int)destEntry + entrySize);
+ copied[lowestIndex] = 1;
+ }
+
+ // Replace old buffer
+ rct2_free(*objectBuffer);
+ *objectBuffer = newBuffer;
+
+ free(copied);
+}
+
/**
*
* rct2: 0x006A93CD
@@ -111,6 +160,7 @@ static void object_list_examine()
object = object_get_next(object);
}
+ object_list_sort();
// Create a search index
object_list_create_hash_table();
@@ -136,7 +186,7 @@ void sub_6A9FC0()
for (int j = 0; j < object_entry_group_counts[type]; j++){
uint8* chunk = object_entry_groups[type].chunks[j];
if (chunk != (uint8*)-1)
- object_paint(type, 0, 0, 0, 0, (int)chunk, 0, 0);
+ object_paint(type, 0, j, type, 0, (int)chunk, 0, 0);
}
}
}
@@ -194,8 +244,10 @@ void object_list_load()
// Reload object list
- if (RCT2_GLOBAL(0x9AA00D, uint8) != 0)
- RCT2_GLOBAL(0x9AA00D, uint8) = 0;
+ // RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_OBJECTS used to control if this was the first time loading objects
+ // and display the starting RCT2 for the first time message.
+ //if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_OBJECTS, uint8) != 0)
+ // RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_OBJECTS, uint8) = 0;
sub_6A9FC0();
@@ -390,6 +442,7 @@ int object_read_and_load_entries(FILE *file)
entries = malloc(OBJECT_ENTRY_COUNT * sizeof(rct_object_entry));
sawyercoding_read_chunk(file, (uint8*)entries);
+ uint8 load_fail = 0;
// Load each object
for (i = 0; i < OBJECT_ENTRY_COUNT; i++) {
if (!check_object_entry(&entries[i]))
@@ -407,14 +460,18 @@ int object_read_and_load_entries(FILE *file)
if (!object_load(entryGroupIndex, &entries[i], NULL)) {
log_error("failed to load entry: %.8s", entries[i].name);
memcpy((char*)0x13CE952, &entries[i], sizeof(rct_object_entry));
- free(entries);
- object_unload_all();
- RCT2_GLOBAL(0x14241BC, uint32) = 0;
- return 0;
+ load_fail = 1;
}
}
- free(entries);
+ free(entries);
+ if (load_fail){
+ object_unload_all();
+ RCT2_GLOBAL(0x14241BC, uint32) = 0;
+ return 0;
+ }
+
+ log_verbose("finished loading required objects");
return 1;
}
@@ -481,11 +538,35 @@ void object_list_create_hash_table()
// Set hash table slot
_installedObjectHashTable[index] = installedObject;
- // Next installde object
+ // Next installed object
installedObject = object_get_next(installedObject);
}
}
+/* 0x006A9DA2
+ * bl = entry_index
+ * ecx = entry_type
+ */
+int find_object_in_entry_group(rct_object_entry* entry, uint8* entry_type, uint8* entry_index){
+ *entry_type = entry->flags & 0xF;
+
+ rct_object_entry_group entry_group = object_entry_groups[*entry_type];
+ for (*entry_index = 0;
+ *entry_index < object_entry_group_counts[*entry_type];
+ ++(*entry_index),
+ entry_group.chunks++,
+ entry_group.entries++){
+
+ if (*entry_group.chunks == (uint8*)-1) continue;
+
+ if (object_entry_compare((rct_object_entry*)entry_group.entries, entry))break;
+ }
+
+ if (*entry_index == object_entry_group_counts[*entry_type])return 0;
+ return 1;
+}
+
+
rct_object_entry *object_list_find(rct_object_entry *entry)
{
uint32 hash = object_get_hash_code(entry);
diff --git a/src/openrct2.c b/src/openrct2.c
index 36dd388bdc..98d0c49375 100644
--- a/src/openrct2.c
+++ b/src/openrct2.c
@@ -27,8 +27,8 @@
#include "localisation/localisation.h"
#include "openrct2.h"
#include "platform/platform.h"
-#include "platform/osinterface.h"
#include "util/sawyercoding.h"
+#include "world/mapgen.h"
int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE;
char gOpenRCT2StartupActionPath[512] = { 0 };
@@ -77,15 +77,17 @@ void openrct2_launch()
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_PLAYING;
break;
case STARTUP_ACTION_EDIT:
- if (strlen(gOpenRCT2StartupActionPath) == 0)
+ if (strlen(gOpenRCT2StartupActionPath) == 0) {
editor_load();
- else
+ } else {
editor_load_landscape(gOpenRCT2StartupActionPath);
+ }
break;
}
+ log_verbose("begin openrct2 loop");
openrct2_loop();
- osinterface_free();
+ platform_free();
// HACK Some threads are still running which causes the game to not terminate. Investigation required!
exit(gExitCode);
@@ -110,9 +112,9 @@ static void openrct2_loop()
lastTick = currentTick;
- osinterface_process_messages();
+ platform_process_messages();
rct2_update();
- osinterface_draw();
+ platform_draw();
} while (!_finished);
}
diff --git a/src/peep/peep.c b/src/peep/peep.c
index f514a77537..cc614c4183 100644
--- a/src/peep/peep.c
+++ b/src/peep/peep.c
@@ -33,6 +33,13 @@
#include "staff.h"
static void peep_update(rct_peep *peep);
+static int peep_has_empty_container(rct_peep* peep);
+static int peep_has_food_standard_flag(rct_peep* peep);
+static int peep_has_food_extra_flag(rct_peep* peep);
+static int peep_empty_container_standard_flag(rct_peep* peep);
+static int peep_empty_container_extra_flag(rct_peep* peep);
+static int peep_should_find_bench(rct_peep* peep);
+static void peep_stop_purchase_thought(rct_peep* peep, uint8 ride_type);
const char *gPeepEasterEggNames[] = {
"MICHAEL SCHUMACHER",
@@ -111,22 +118,20 @@ int sub_68F3AE(rct_peep* peep){
peep->var_C4++;
if ((peep->var_C4 & 0xF) != (peep->sprite_index & 0xF))return 1;
- uint16 ebx = (peep->next_x | (peep->next_y << 8)) >> 5;
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(ebx);
+ rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32);
uint8 map_type = MAP_ELEMENT_TYPE_PATH;
- if ((peep->next_z >> 8) & ((1 << 4) | (1 << 3))){
+ if (peep->next_var_29 & ((1 << 4) | (1 << 3))){
map_type = MAP_ELEMENT_TYPE_SURFACE;
}
- int z = peep->next_z & 0xFF;
+ int z = peep->next_z;
- for (;; map_element++){
- if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == map_type){
+ do {
+ if (map_element_get_type(map_element) == map_type){
if (z == map_element->base_height)return 1;
}
- if (map_element->flags & MAP_ELEMENT_FLAG_LAST_TILE)break;
- }
+ } while (!map_element_is_last_for_tile(map_element++));
peep_decrement_num_riders(peep);
peep->state = PEEP_STATE_FALLING;
@@ -155,12 +160,86 @@ void sub_693B58(rct_peep* peep){
invalidate_sprite((rct_sprite*)peep);
}
+/* 0x00693BE5 */
+static void sub_693BE5(rct_peep* peep, uint8 al){
+ if (al == peep->var_6D)return;
+
+ peep->var_6D = al;
+
+ // If NONE_1 or NONE_2
+ if (peep->action >= PEEP_ACTION_NONE_1){
+ peep->action = PEEP_STATE_FALLING;
+ }
+ sub_693B58(peep);
+}
+
static void peep_state_reset(rct_peep* peep){
peep_decrement_num_riders(peep);
peep->state = PEEP_STATE_1;
peep_window_state_update(peep);
- RCT2_CALLPROC_X(0x00693BE5, 0, 0, 0, 0, (int)peep, 0, 0);
+ sub_693BE5(peep, 0);
+}
+
+/* rct2: 0x69C308
+ * Check if lost.
+ */
+void peep_check_if_lost(rct_peep* peep){
+ if (!(peep->flags & PEEP_FLAGS_LOST)){
+ if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_COUNT, uint16) < 2)return;
+ peep->flags ^= PEEP_FLAGS_21;
+
+ if (!(peep->flags & PEEP_FLAGS_21)) return;
+
+ peep->var_F4++;
+ if (peep->var_F4 != 254)return;
+ peep->var_F4 = 230;
+ }
+ peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_LOST, 0xFF);
+ if (peep->happiness_growth_rate < 30) peep->happiness_growth_rate = 0;
+ else peep->happiness_growth_rate -= 30;
+}
+
+/* rct2: 0x69C26B
+* Check if cant find ride.
+*/
+void peep_check_cant_find_ride(rct_peep* peep){
+ if (peep->guest_heading_to_ride_id == 0xFF) return;
+
+ if (peep->var_C6 == 30 || peep->var_C6 == 60){
+ peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_CANT_FIND, peep->guest_heading_to_ride_id);
+
+ if (peep->happiness_growth_rate < 30) peep->happiness_growth_rate = 0;
+ else peep->happiness_growth_rate -= 30;
+ }
+
+ peep->var_C6--;
+ if (peep->var_C6 != 0)return;
+
+ peep->guest_heading_to_ride_id = 0xFF;
+ rct_window* w = window_find_by_number(WC_PEEP, peep->sprite_index);
+
+ if (w){
+ window_event_invalidate_call(w);
+ }
+
+ widget_invalidate_by_number(WC_PEEP, peep->sprite_index, 12);
+}
+
+/* rct2: 0x69C2D0
+* Check if cant find exit.
+*/
+void peep_check_cant_find_exit(rct_peep* peep){
+ if (!(peep->flags & PEEP_FLAGS_LEAVING_PARK))return;
+
+ if (peep->var_C6 == 1){
+ peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_CANT_FIND_EXIT, 0xFF);
+
+ if (peep->happiness_growth_rate < 30) peep->happiness_growth_rate = 0;
+ else peep->happiness_growth_rate -= 30;
+ }
+
+ if (--peep->var_C6 == 0) peep->var_C6 = 90;
}
/* rct2: 0x6939EB
@@ -347,16 +426,13 @@ void peep_update_falling(rct_peep* peep){
}
// If not drowning then falling. Note: peeps 'fall' after leaving a ride/enter the park.
-
- rct_map_element *map_element = TILE_MAP_ELEMENT_POINTER((peep->y / 32) * 256 + (peep->x /32));
+ rct_map_element *map_element = map_get_first_element_at(peep->x / 32, peep->y / 32);
rct_map_element *saved_map = NULL;
int saved_height = 0;
- for (int final_element = 0; !final_element; map_element++){
- final_element = map_element->flags & MAP_ELEMENT_FLAG_LAST_TILE;
-
+ do {
// If a path check if we are on it
- if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH){
+ if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_PATH){
int height = map_height_from_slope(peep->x, peep->y, map_element->properties.surface.slope)
+ map_element->base_height * 8;
@@ -366,7 +442,7 @@ void peep_update_falling(rct_peep* peep){
saved_map = map_element;
break;
} // If a surface get the height and see if we are on it
- else if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SURFACE){
+ else if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SURFACE){
// If the surface is water check to see if we could be drowning
if (map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK){
int height = (map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK) * 16;
@@ -404,7 +480,7 @@ void peep_update_falling(rct_peep* peep){
saved_map = map_element;
} // If not a path or surface go see next element
else continue;
- }
+ } while (!map_element_is_last_for_tile(map_element++));
// This will be null if peep is falling
if (saved_map == NULL){
@@ -431,7 +507,7 @@ void peep_update_falling(rct_peep* peep){
if (saved_map->type != MAP_ELEMENT_TYPE_PATH){
edx = 8;
}
- peep->next_z += edx << 8;
+ peep->next_var_29 = edx;
peep_decrement_num_riders(peep);
peep->state = PEEP_STATE_1;
peep_window_state_update(peep);
@@ -462,7 +538,7 @@ void peep_try_get_up_from_sitting(rct_peep* peep){
* rct2: 0x0069152B
*/
void peep_update_sitting(rct_peep* peep){
- if (peep->var_2C == 0){
+ if (peep->sub_state == 0){
if (!sub_68F3AE(peep))return;
//691541
@@ -483,12 +559,12 @@ void peep_update_sitting(rct_peep* peep){
peep->var_6F = 7;
RCT2_CALLPROC_X(0x693BAB, 0, 0, 0, 0, (int)peep, 0, 0);
- peep->var_2C++;
+ peep->sub_state++;
// Sets time to sit on seat
peep->time_to_sitdown = (129 - peep->energy) * 16 + 50;
}
- else if (peep->var_2C == 1){
+ else if (peep->sub_state == 1){
if (peep->action < 0xFE){
sint16 x, y;
sub_6939EB(&x, &y, peep);
@@ -560,7 +636,7 @@ void peep_update_sitting(rct_peep* peep){
/* rct2: 0x691A30
* Also used by entering_ride and queueing_front */
static void peep_update_leaving_ride(rct_peep* peep){
- RCT2_CALLPROC_X(RCT2_ADDRESS(0x9820DC, int)[peep->var_2C], 0, 0, 0, 0, (int)peep, 0, 0);
+ RCT2_CALLPROC_X(RCT2_ADDRESS(0x9820DC, int)[peep->sub_state], 0, 0, 0, 0, (int)peep, 0, 0);
}
/**
@@ -580,14 +656,14 @@ static void peep_update_queuing(rct_peep* peep){
return;
}
- if (peep->var_2C != 0xA){
+ if (peep->sub_state != 0xA){
if (peep->var_74 == 0xFFFF){
//Happens every time peep goes onto ride.
peep->destination_tolerence = 0;
peep_decrement_num_riders(peep);
peep->state = PEEP_STATE_QUEUING_FRONT;
peep_window_state_update(peep);
- peep->var_2C = 0;
+ peep->sub_state = 0;
return;
}
//Give up queueing for the ride
@@ -597,6 +673,7 @@ static void peep_update_queuing(rct_peep* peep){
peep_decrement_num_riders(peep);
peep->state = PEEP_STATE_1;
peep_window_state_update(peep);
+ return;
}
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
@@ -686,7 +763,7 @@ static void peep_update_mowing(rct_peep* peep){
peep->var_37++;
if (peep->var_37 == 1){
- RCT2_CALLPROC_X(0x00693BE5, 2, 0, 0, 0, (int)peep, 0, 0);
+ sub_693BE5(peep, 2);
}
if (RCT2_ADDRESS(0x9929C8, uint16)[peep->var_37 * 2] == 0xFFFF){
@@ -699,9 +776,9 @@ static void peep_update_mowing(rct_peep* peep){
if (peep->var_37 != 7)continue;
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER((peep->next_x | (peep->next_y << 8)) >> 5);
+ rct_map_element *map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32);
- for (; ((map_element->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_SURFACE); map_element++);
+ for (; (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SURFACE); map_element++);
if ((map_element->properties.surface.terrain & MAP_ELEMENT_SURFACE_TERRAIN_MASK) == (TERRAIN_GRASS << 5)){
map_element->properties.surface.grass_length = 0;
@@ -715,7 +792,7 @@ static void peep_update_mowing(rct_peep* peep){
/* rct2: 0x006BF7E6 */
static void peep_update_watering(rct_peep* peep){
peep->var_E2 = 0;
- if (peep->var_2C == 0){
+ if (peep->sub_state == 0){
if (!sub_68F3AE(peep))return;
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
@@ -728,9 +805,9 @@ static void peep_update_watering(rct_peep* peep){
sub_693B58(peep);
invalidate_sprite((rct_sprite*)peep);
- peep->var_2C = 1;
+ peep->sub_state = 1;
}
- else if (peep->var_2C == 1){
+ else if (peep->sub_state == 1){
if (peep->action != PEEP_ACTION_NONE_2){
sint16 x, y;
sub_6939EB(&x, &y, peep);
@@ -740,11 +817,11 @@ static void peep_update_watering(rct_peep* peep){
int x = peep->next_x + RCT2_ADDRESS(0x993CCC, sint16)[peep->var_37 * 2];
int y = peep->next_y + RCT2_ADDRESS(0x993CCE, sint16)[peep->var_37 * 2];
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER((x | (y << 8)) >> 5);
+ rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32);
for (;; map_element++){
- if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SCENERY){
- if (abs((peep->next_z & 0xFF) - map_element->base_height) <= 4){
+ if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY){
+ if (abs(((int)peep->next_z) - map_element->base_height) <= 4){
rct_scenery_entry* scenery_entry = g_smallSceneryEntries[map_element->properties.scenery.type];
if (scenery_entry->small_scenery.flags& SMALL_SCENERY_FLAG6){
@@ -755,7 +832,7 @@ static void peep_update_watering(rct_peep* peep){
}
}
}
- if (map_element->flags&MAP_ELEMENT_FLAG_LAST_TILE){
+ if (map_element_is_last_for_tile(map_element)) {
peep_state_reset(peep);
return;
}
@@ -767,7 +844,7 @@ static void peep_update_watering(rct_peep* peep){
static void peep_update_emptying_bin(rct_peep* peep){
peep->var_E2 = 0;
- if (peep->var_2C == 0){
+ if (peep->sub_state == 0){
if (!sub_68F3AE(peep))return;
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
@@ -780,9 +857,9 @@ static void peep_update_emptying_bin(rct_peep* peep){
sub_693B58(peep);
invalidate_sprite((rct_sprite*)peep);
- peep->var_2C = 1;
+ peep->sub_state = 1;
}
- else if (peep->var_2C == 1){
+ else if (peep->sub_state == 1){
if (peep->action == PEEP_ACTION_NONE_2){
peep_state_reset(peep);
@@ -794,32 +871,35 @@ static void peep_update_emptying_bin(rct_peep* peep){
if (peep->action_frame != 11)return;
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER((peep->next_x | (peep->next_y << 8)) >> 5);
+ rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32);
- for (;; map_element++){
- if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH){
- if ((peep->next_z & 0xFF) == map_element->base_height)break;
+ for (;; map_element++) {
+ if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_PATH) {
+ if (peep->next_z == map_element->base_height)
+ break;
}
- if (map_element->flags&MAP_ELEMENT_FLAG_LAST_TILE){
+ if (map_element_is_last_for_tile(map_element)) {
peep_state_reset(peep);
return;
}
}
- if ((map_element->properties.path.additions & 0xF) == 0){
+ if ((map_element->properties.path.additions & 0x0F) == 0) {
peep_state_reset(peep);
return;
}
rct_scenery_entry* scenery_entry = g_pathBitSceneryEntries[(map_element->properties.path.additions & 0xF) - 1];
- if (!(scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG1)
- || map_element->flags&(1 << 5)
- || map_element->properties.path.additions & (1 << 7)){
+ if (
+ !(scenery_entry->path_bit.var_06 & 1)
+ || map_element->flags & (1 << 5)
+ || map_element->properties.path.additions & (1 << 7)
+ ) {
peep_state_reset(peep);
return;
}
- map_element->properties.path.addition_status = ((3 << peep->var_37) << peep->var_37);
+ map_element->properties.path.addition_status |= ((3 << peep->var_37) << peep->var_37);
gfx_invalidate_scrollingtext(peep->next_x, peep->next_y, map_element->base_height * 8, map_element->clearance_height * 8);
@@ -890,8 +970,8 @@ static void peep_update_1(rct_peep* peep){
*/
static void peep_update_picked(rct_peep* peep){
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x1F) return;
- peep->var_2C++;
- if (peep->var_2C == 13){
+ peep->sub_state++;
+ if (peep->sub_state == 13){
peep_insert_new_thought(peep, PEEP_THOUGHT_HELP, 0xFF);
}
}
@@ -928,7 +1008,7 @@ static void peep_update_leaving_park(rct_peep* peep){
/* rct2: 0x6916D6 */
static void peep_update_watching(rct_peep* peep){
- if (peep->var_2C == 0){
+ if (peep->sub_state == 0){
if (!sub_68F3AE(peep))return;
RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
@@ -945,12 +1025,12 @@ static void peep_update_watching(rct_peep* peep){
RCT2_CALLPROC_X(0x693BAB, 0, 0, 0, 0, (int)peep, 0, 0);
- peep->var_2C++;
+ peep->sub_state++;
peep->time_to_stand = clamp(0, ((129 - peep->energy) * 16 + 50) / 2, 255);
RCT2_CALLPROC_X(0x0069B8CC, 0, 0, 0, 0, (int)peep, 0, 0);
}
- else if (peep->var_2C == 1){
+ else if (peep->sub_state == 1){
if (peep->action < 0xFE){
//6917F6
sint16 x = 0, y = 0;
@@ -1041,6 +1121,675 @@ static void peep_update_entering_park(rct_peep* peep){
window_invalidate_by_class(WC_GUEST_LIST);
}
+/* rct2: 0x00690582*/
+static int peep_update_walking_find_bench(rct_peep* peep){
+ if (!peep_should_find_bench(peep))return 0;
+
+ rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32);
+
+ for (;; map_element++){
+ if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_PATH){
+ if (peep->next_z == map_element->base_height)break;
+ }
+ if (map_element_is_last_for_tile(map_element)){
+ return 0;
+ }
+ }
+
+ uint8 additions = map_element->properties.path.additions & 0xF;
+
+ if (!additions) return 0;
+ rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
+
+ if (!(sceneryEntry->path_bit.var_06 & 0x2))return 0;
+
+ if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)return 0;
+
+ if (map_element->properties.path.additions & 0x80)return 0;
+
+ int edges = (map_element->properties.path.edges & 0xF) ^ 0xF;
+ if (edges == 0) return 0;
+
+ uint8 chosen_edge = scenario_rand() & 0x3;
+
+ for (; !(edges & (1 << chosen_edge));)chosen_edge = (chosen_edge + 1) & 0x3;
+
+ uint16 sprite_id = RCT2_ADDRESS(0xF1EF60, uint16)[((peep->x & 0x1FE0) << 3) | (peep->y >> 5)];
+ uint8 free_edge = 3;
+
+ for (rct_sprite* sprite; sprite_id != SPRITE_INDEX_NULL; sprite_id = sprite->unknown.var_02){
+ sprite = &g_sprite_list[sprite_id];
+
+ if (sprite->unknown.linked_list_type_offset != SPRITE_LINKEDLIST_OFFSET_PEEP)continue;
+
+ if (sprite->peep.state != PEEP_STATE_SITTING)continue;
+
+ if (peep->z != sprite->peep.z)continue;
+
+ if ((sprite->peep.var_37 & 0x3) != chosen_edge)continue;
+
+ free_edge &= ~(1 << ((sprite->peep.var_37 & 0x4) >> 2));
+ }
+
+ if (!free_edge) return 0;
+
+ free_edge ^= 0x3;
+ if (!free_edge){
+ if (scenario_rand() & 0x8000000) free_edge = 1;
+ }
+
+ peep->var_37 = ((free_edge & 1) << 2) | chosen_edge;
+
+ peep_decrement_num_riders(peep);
+ peep->state = PEEP_STATE_SITTING;
+ peep_window_state_update(peep);
+
+ peep->sub_state = 0;
+
+ int ebx = peep->var_37 & 0x7;
+ int x = (peep->x & 0xFFE0) + RCT2_ADDRESS(0x981F2C, uint16)[ebx * 2];
+ int y = (peep->y & 0xFFE0) + RCT2_ADDRESS(0x981F2E, uint16)[ebx * 2];
+
+ peep->destination_x = x;
+ peep->destination_y = y;
+ peep->destination_tolerence = 3;
+
+ return 1;
+}
+
+static int peep_update_walking_find_bin(rct_peep* peep){
+ if (!peep_has_empty_container(peep)) return 0;
+
+ if (peep->next_var_29 & 0x18)return 0;
+
+ rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32);
+
+ for (;; map_element++){
+ if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_PATH){
+ if (peep->next_z == map_element->base_height)break;
+ }
+ if (map_element_is_last_for_tile(map_element)){
+ return 0;
+ }
+ }
+
+ uint8 additions = map_element->properties.path.additions & 0xF;
+
+ if (!additions) return 0;
+ rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
+
+ if (!(sceneryEntry->path_bit.var_06 & 0x1))return 0;
+
+ if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)return 0;
+
+ if (map_element->properties.path.additions & 0x80)return 0;
+
+ int edges = (map_element->properties.path.edges & 0xF) ^ 0xF;
+ if (edges == 0) return 0;
+
+ uint8 chosen_edge = scenario_rand() & 0x3;
+
+ // Note: Bin qunatity is inverted 0 = full, 3 = empty
+ uint8 bin_quantities = map_element->properties.path.addition_status;
+
+ // Rotate the bin to the correct edge. Makes it easier for next calc.
+ bin_quantities = ror8(ror8(bin_quantities, chosen_edge), chosen_edge);
+
+ for (uint8 free_edge = 4; free_edge != 0; free_edge--){
+ // If not full
+ if (bin_quantities & 0x3){
+ if (edges&(1 << chosen_edge))break;
+ }
+ chosen_edge = (chosen_edge + 1) & 0x3;
+ bin_quantities = ror8(bin_quantities, 2);
+ if ((free_edge - 1) == 0) return 0;
+ }
+
+ peep->var_37 = chosen_edge;
+
+ peep_decrement_num_riders(peep);
+ peep->state = PEEP_STATE_USING_BIN;
+ peep_window_state_update(peep);
+
+ peep->sub_state = 0;
+
+ int ebx = peep->var_37 & 0x3;
+ int x = (peep->x & 0xFFE0) + RCT2_ADDRESS(0x992A4C, uint16)[ebx * 2];
+ int y = (peep->y & 0xFFE0) + RCT2_ADDRESS(0x992A4E, uint16)[ebx * 2];
+
+ peep->destination_x = x;
+ peep->destination_y = y;
+ peep->destination_tolerence = 3;
+
+ return 1;
+}
+
+/* rct2: 0x00690848*/
+static void peep_update_walking_break_scenery(rct_peep* peep){
+ if (!(peep->flags & PEEP_FLAGS_ANGRY)){
+ if (peep->happiness >= 48) return;
+ if (peep->energy < 85) return;
+ if (peep->state != PEEP_STATE_WALKING) return;
+
+ if ((peep->var_E1 & 0xC0) != 0xC0 &&
+ (peep->var_E3 & 0xC0) != 0xC0) return;
+
+ if ((scenario_rand() & 0xFFFF) > 3276) return;
+ }
+
+ if (peep->next_var_29 & 0x18) return;
+
+ rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32);
+
+ for (;; map_element++){
+ if ( map_element_get_type(map_element) == MAP_ELEMENT_TYPE_PATH){
+ if (peep->next_z == map_element->base_height)break;
+ }
+ if (map_element_is_last_for_tile(map_element)){
+ return;
+ }
+ }
+
+ uint8 additions = map_element->properties.path.additions & 0xF;
+
+ if (!additions) return;
+ rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
+
+ if (!(sceneryEntry->path_bit.var_06 & 0x4))return;
+
+ if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)return;
+
+ if (map_element->properties.path.additions & 0x80)return;
+
+ int edges = map_element->properties.path.edges & 0xF;
+ if (edges == 0xF) return;
+
+ rct_peep* inner_peep;
+ uint16 sprite_index;
+
+ FOR_ALL_STAFF(sprite_index, inner_peep){
+ if (inner_peep->staff_type != STAFF_TYPE_SECURITY)continue;
+
+ if (inner_peep->x == (sint16)SPRITE_LOCATION_NULL)continue;
+
+ int x_diff = abs(inner_peep->x - peep->x);
+ int y_diff = abs(inner_peep->y - peep->y);
+
+ if (max(x_diff, y_diff) < 224)return;
+ }
+
+ map_element->flags |= MAP_ELEMENT_FLAG_BROKEN;
+
+ map_invalidate_tile(
+ peep->next_x,
+ peep->next_y,
+ (map_element->base_height << 3) + 32,
+ map_element->base_height << 3);
+
+ peep->var_F3 = 0x10;
+
+ return;
+}
+
+/* rct2: 0x006912A3 */
+static void peep_update_buying(rct_peep* peep)
+{
+ //RCT2_CALLPROC_X(0x006912A3, 0, 0, 0, 0, (int)peep, 0, 0);
+ //return;
+
+ if (!sub_68F3AE(peep))return;
+
+ rct_ride* ride = GET_RIDE(peep->current_ride);
+ if (ride->type == RIDE_TYPE_NULL || ride->status != RIDE_STATUS_OPEN){
+ peep_decrement_num_riders(peep);
+ peep->state = PEEP_STATE_FALLING;
+ peep_window_state_update(peep);
+ return;
+ }
+
+ if (peep->sub_state == 1){
+ if (peep->action != 0xFF){
+ sint16 x, y;
+ sub_6939EB(&x, &y, peep);
+ return;
+ }
+
+ if (ride->type == RIDE_TYPE_ATM){
+ if (peep->current_ride != peep->previous_ride){
+ peep->cash_in_pocket += MONEY(50,00);
+ }
+ window_invalidate_by_number(WC_PEEP, peep->sprite_index);
+ }
+ peep->sprite_direction ^= 0x10;
+ peep->destination_x = peep->next_x + 16;
+ peep->destination_y = peep->next_y + 16;
+ peep->var_78 ^= 2;
+
+ peep_decrement_num_riders(peep);
+ peep->state = PEEP_STATE_WALKING;
+ peep_window_state_update(peep);
+ return;
+ }
+
+ uint8 item_bought = 0;
+
+ if (peep->current_ride != peep->previous_ride){
+ if (ride->type == RIDE_TYPE_ATM){
+ item_bought = !(RCT2_CALLPROC_X(0x0069AEB7, peep->current_ride << 8, 0, 0, 0, (int)peep, 0, 0) & 0x100);
+
+ if (!item_bought){
+ peep->previous_ride = peep->current_ride;
+ peep->previous_ride_time_out = 0;
+ }
+ else{
+ peep->action = PEEP_ACTION_WITHDRAW_MONEY;
+ peep->action_frame = 0;
+ peep->var_70 = 0;
+
+ sub_693B58(peep);
+ invalidate_sprite((rct_sprite*)peep);
+
+ ride->no_primary_items_sold++;
+ }
+ }
+ else{
+ rct_ride_type* ride_type = gRideTypeList[ride->subtype];
+ if (ride_type->shop_item_secondary != 0xFF){
+ money16 price = ride->price_secondary;
+
+ item_bought = !(RCT2_CALLPROC_X(0x0069AF1E, ride_type->shop_item_secondary | (peep->current_ride << 8), 0, price, 0, (int)peep, 0, 0) & 0x100);
+
+ if (item_bought){
+ ride->no_secondary_items_sold++;
+ }
+ }
+
+ if (!item_bought && ride_type->shop_item != 0xFF){
+ money16 price = ride->price;
+
+ item_bought = !(RCT2_CALLPROC_X(0x0069AF1E, ride_type->shop_item | (peep->current_ride << 8), 0, price, 0, (int)peep, 0, 0) & 0x100);
+
+ if (item_bought){
+ ride->no_primary_items_sold++;
+ }
+ }
+ }
+ }
+
+ if (item_bought){
+ ride_update_popularity(ride, 1);
+
+ peep_stop_purchase_thought(peep, ride->type);
+ }
+ else{
+ ride_update_popularity(ride, 0);
+ }
+ peep->sub_state = 1;
+ return;
+}
+
+/* rct2: 0x00691089 */
+static void peep_update_using_bin(rct_peep* peep){
+ //RCT2_CALLPROC_X(0x0691089, 0, 0, 0, 0, peep, 0, 0);
+ //return;
+ if (peep->sub_state == 0){
+ if (!sub_68F3AE(peep))return;
+
+ RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
+ if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return;
+
+ peep->sub_state = 1;
+ }
+ else if (peep->sub_state == 1){
+
+ if (peep->action != PEEP_ACTION_NONE_2){
+ sint16 x, y;
+ sub_6939EB(&x, &y, peep);
+ return;
+ }
+
+ rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32);
+
+ for (;;map_element++){
+ if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_PATH){
+ continue;
+ }
+
+ if (map_element->base_height == peep->next_z)break;
+
+ if (map_element_is_last_for_tile(map_element)){
+ peep_state_reset(peep);
+ return;
+ }
+ }
+
+ uint8 additions = map_element->properties.path.additions & 0x0F;
+ if (!additions){
+ peep_state_reset(peep);
+ return;
+ }
+
+ rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
+ if (!(sceneryEntry->path_bit.var_06 & 1)){
+ peep_state_reset(peep);
+ return;
+ }
+
+ if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN){
+ peep_state_reset(peep);
+ return;
+ }
+
+ if (map_element->properties.path.additions & 0x80){
+ peep_state_reset(peep);
+ return;
+ }
+
+ // Bin selection is one of 4 corners
+ uint8 selected_bin = peep->var_37 * 2;
+
+ // This counts down 2 = No rubbish, 0 = full
+ uint8 rubbish_in_bin = 0x3 & (map_element->properties.path.addition_status >> selected_bin);
+ uint32 empty_containers = peep_empty_container_standard_flag(peep);
+
+ for (uint8 cur_container = 0; cur_container < 32; cur_container++){
+ if (!(empty_containers & (1 << cur_container))) continue;
+
+ if (rubbish_in_bin != 0){
+ // OpenRCT2 modification: This previously used
+ // the tick count as a simple random function
+ // switched to scenario_rand as it is more reliable
+ if (scenario_rand() & 7) rubbish_in_bin--;
+ peep->item_standard_flags &= ~(1 << cur_container);
+ peep->var_45 |= 8;
+ RCT2_CALLPROC_X(0x0069B8CC, 0, 0, 0, 0, (int)peep, 0, 0);
+ continue;
+ }
+ uint8 bp = RCT2_ADDRESS(0x97EFCC, uint8)[cur_container];
+
+ int x, y;
+ x = peep->x + scenario_rand() & 7 - 3;
+ y = peep->y + scenario_rand() & 7 - 3;
+
+ RCT2_CALLPROC_X(0x67375D, x, scenario_rand() & 3, y, peep->z, 0, 0, bp);
+ peep->item_standard_flags &= ~(1 << cur_container);
+ peep->var_45 |= 8;
+
+ RCT2_CALLPROC_X(0x0069B8CC, 0, 0, 0, 0, (int)peep, 0, 0);
+ }
+
+ // Original bug: This would clear any rubbish placed by the previous function
+ //rubbish_in_bin = 0x3 & (map_element->properties.path.addition_status >> selected_bin);
+ empty_containers = peep_empty_container_extra_flag(peep);
+
+ for (uint8 cur_container = 0; cur_container < 32; cur_container++){
+ if (!(empty_containers & (1 << cur_container))) continue;
+
+ if (rubbish_in_bin != 0){
+ // OpenRCT2 modification: This previously used
+ // the tick count as a simple random function
+ // switched to scenario_rand as it is more reliable
+ if (scenario_rand() & 7) rubbish_in_bin--;
+ peep->item_extra_flags &= ~(1 << cur_container);
+ peep->var_45 |= 8;
+
+ RCT2_CALLPROC_X(0x0069B8CC, 0, 0, 0, 0, (int)peep, 0, 0);
+ continue;
+ }
+ uint8 bp = RCT2_ADDRESS(0x97EFE8, uint8)[cur_container];
+
+ int x, y;
+ x = peep->x + scenario_rand() & 7 - 3;
+ y = peep->y + scenario_rand() & 7 - 3;
+
+ RCT2_CALLPROC_X(0x67375D, x, scenario_rand() & 3, y, peep->z, 0, 0, bp);
+ peep->item_extra_flags &= ~(1 << cur_container);
+ peep->var_45 |= 8;
+
+ RCT2_CALLPROC_X(0x0069B8CC, 0, 0, 0, 0, (int)peep, 0, 0);
+ }
+
+ // Place new amount in bin by first clearing the value
+ map_element->properties.path.addition_status &= ~(3 << selected_bin);
+ // Then placeing the new value.
+ map_element->properties.path.addition_status |= rubbish_in_bin << selected_bin;
+
+ gfx_invalidate_scrollingtext(peep->next_x, peep->next_y, map_element->base_height << 3, map_element->clearance_height << 3);
+ peep_state_reset(peep);
+ }
+}
+
+/* rct2: 0x0069030A */
+static void peep_update_walking(rct_peep* peep){
+ //RCT2_CALLPROC_X(0x0069030A, 0, 0, 0, 0, (int)peep, 0, 0);
+ //return;
+
+ if (!sub_68F3AE(peep))return;
+
+ if (peep->flags & PEEP_FLAGS_WAVING){
+ if (peep->action >= PEEP_ACTION_NONE_1){
+ if ((0xFFFF & scenario_rand()) < 936){
+ invalidate_sprite((rct_sprite*)peep);
+
+ peep->action = PEEP_ACTION_WAVE_2;
+ peep->action_frame = 0;
+ peep->var_70 = 0;
+
+ sub_693B58(peep);
+ invalidate_sprite((rct_sprite*)peep);
+ }
+ }
+ }
+
+ if (peep->flags & PEEP_FLAGS_PHOTO){
+ if (peep->action >= PEEP_ACTION_NONE_1){
+ if ((0xFFFF & scenario_rand()) < 936){
+ invalidate_sprite((rct_sprite*)peep);
+
+ peep->action = PEEP_ACTION_TAKE_PHOTO;
+ peep->action_frame = 0;
+ peep->var_70 = 0;
+
+ sub_693B58(peep);
+ invalidate_sprite((rct_sprite*)peep);
+ }
+ }
+ }
+
+ if (peep->flags & PEEP_FLAGS_PAINTING){
+ if (peep->action >= PEEP_ACTION_NONE_1){
+ if ((0xFFFF & scenario_rand()) < 936){
+ invalidate_sprite((rct_sprite*)peep);
+
+ peep->action = PEEP_ACTION_DRAW_PICTURE;
+ peep->action_frame = 0;
+ peep->var_70 = 0;
+
+ sub_693B58(peep);
+ invalidate_sprite((rct_sprite*)peep);
+ }
+ }
+ }
+
+ if (peep->flags & PEEP_FLAGS_LITTER){
+ if (!(peep->next_var_29 & 0x18)){
+ if ((0xFFFF & scenario_rand()) <= 4096){
+ int ebp = (scenario_rand() & 0x3) + 2;
+ int x = peep->x + (scenario_rand() & 0x7) - 3;
+ int y = peep->y + (scenario_rand() & 0x7) - 3;
+ int direction = (scenario_rand() & 0x3);
+
+ RCT2_CALLPROC_X(0x67375D, x, direction, y, peep->z, 0, 0, ebp);
+ }
+ }
+ }
+ else if (peep_has_empty_container(peep)){
+ if ((!(peep->next_var_29 & 0x18)) &&
+ ((peep->sprite_index & 0x1FF) == (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x1FF))&&
+ ((0xFFFF & scenario_rand()) <= 4096)){
+
+ uint8 pos_stnd = 0;
+ for (int container = peep_empty_container_standard_flag(peep); pos_stnd < 32; pos_stnd++)if (container&(1<item_standard_flags &= ~(1 << pos_stnd);
+ bp = RCT2_ADDRESS(0x97EFCC, uint8)[pos_stnd];
+ }
+ else{
+ uint8 pos_extr = 0;
+ for (int container = peep_empty_container_extra_flag(peep); pos_extr < 32; pos_extr++)if (container&(1 << pos_extr))break;
+ peep->item_extra_flags &= ~(1 << pos_extr);
+ bp = RCT2_ADDRESS(0x97EFE8, uint8)[pos_extr];
+ }
+
+ peep->var_45 |= 8;
+ RCT2_CALLPROC_X(0x0069B8CC, 0, 0, 0, 0, (int)peep, 0, 0);
+
+ int x = peep->x + (scenario_rand() & 0x7) - 3;
+ int y = peep->y + (scenario_rand() & 0x7) - 3;
+ int direction = (scenario_rand() & 0x3);
+
+ RCT2_CALLPROC_X(0x67375D, x, direction, y, peep->z, 0, 0, bp);
+ }
+ }
+
+ RCT2_CALLPROC_X(0x693C9E, 0, 0, 0, 0, (int)peep, 0, 0);
+ if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return;
+
+ if ((peep->next_var_29 & 0x18) == 8){
+ rct_map_element* map_element = map_get_surface_element_at(peep->next_x / 32, peep->next_y / 32);
+
+ int water_height = map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK;
+ if (water_height){
+ invalidate_sprite((rct_sprite*)peep);
+ water_height *= 16;
+ sprite_move(peep->x, peep->y, water_height, (rct_sprite*)peep);
+ invalidate_sprite((rct_sprite*)peep);
+
+ peep_decrement_num_riders(peep);
+ peep->state = PEEP_STATE_FALLING;
+ peep_window_state_update(peep);
+ return;
+ }
+ }
+
+ peep_check_if_lost(peep);
+ peep_check_cant_find_ride(peep);
+ peep_check_cant_find_exit(peep);
+
+ if (peep_update_walking_find_bench(peep))return;
+
+ if (peep_update_walking_find_bin(peep))return;
+
+ peep_update_walking_break_scenery(peep);
+
+ if (peep->state != PEEP_STATE_WALKING)return;
+
+ if (peep->flags & PEEP_FLAGS_LEAVING_PARK)return;
+
+ if (peep->nausea > 140)return;
+
+ if (peep->happiness < 120)return;
+
+ if (peep->bathroom > 140)return;
+
+ uint16 chance = 13107;
+ if (peep_has_food(peep))chance = 2849;
+
+ if ((scenario_rand() & 0xFFFF) > chance)return;
+
+ if (peep->next_var_29 & 0x1C)return;
+
+ rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32);
+
+ for (;; map_element++){
+ if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_PATH){
+ if (peep->next_z == map_element->base_height)break;
+ }
+ if (map_element_is_last_for_tile(map_element)){
+ return;
+ }
+ }
+
+ uint8 additions = map_element->properties.path.additions & 0xF;
+
+ int ebp = 15;
+
+ if (additions){
+ if (!(map_element->properties.path.additions & 0x80)){
+ rct_scenery_entry* sceneryEntry = RCT2_ADDRESS(0x9ADA50, rct_scenery_entry*)[additions];
+
+ if (!(sceneryEntry->path_bit.var_06 & 0x2)) ebp = 9;
+ }
+ }
+
+ int edges = (map_element->properties.path.edges & 0xF) ^ 0xF;
+ if (edges == 0) return;
+
+ uint8 chosen_edge = scenario_rand() & 0x3;
+
+ for (; !(edges & (1 << chosen_edge));)chosen_edge = (chosen_edge + 1) & 3;
+
+ uint8 ride_to_view;
+ uint8 ride_seat_to_view;
+ {
+ int eax = chosen_edge, _ebx = 0, ecx, edx = 0, esi = (int)peep, _ebp = 0, edi = 0;
+ // Work out what to look at
+ if (RCT2_CALLFUNC_X(0x00690B99, &eax, &_ebx, &ecx, &edx, &esi, &edi, &_ebp) & 0x100)return;
+
+ ride_to_view = ecx & 0xFF;
+ ride_seat_to_view = (ecx & 0xFF00) >> 8;
+ }
+
+ uint16 sprite_id = RCT2_ADDRESS(0xF1EF60, uint16)[((peep->x & 0x1FE0) << 3) | (peep->y >> 5)];
+ for (rct_sprite* sprite; sprite_id != SPRITE_INDEX_NULL; sprite_id = sprite->unknown.var_02){
+ sprite = &g_sprite_list[sprite_id];
+
+ if (sprite->unknown.linked_list_type_offset != SPRITE_LINKEDLIST_OFFSET_PEEP)continue;
+
+ if (sprite->peep.state != PEEP_STATE_WATCHING)continue;
+
+ if (peep->z != sprite->peep.z)continue;
+
+ if ((sprite->peep.var_37 & 0x3) != chosen_edge)continue;
+
+ ebp &= ~(1 << ((sprite->peep.var_37 & 0x1C) >> 2));
+ }
+
+ if (!ebp)return;
+
+ uint8 chosen_position = scenario_rand() & 0x3;
+
+ for (; !(ebp & (1 << chosen_position));)chosen_position = (chosen_position + 1) & 3;
+
+ peep->current_ride = ride_to_view;
+ peep->current_seat = ride_seat_to_view;
+ peep->var_37 = chosen_edge | (chosen_position << 2);
+
+ peep_decrement_num_riders(peep);
+ peep->state = PEEP_STATE_WATCHING;
+ peep_window_state_update(peep);
+
+ peep->sub_state = 0;
+
+ int ebx = peep->var_37 & 0x1F;
+ int x = (peep->x & 0xFFE0) + RCT2_ADDRESS(0x981F4C, uint16)[ebx * 2];
+ int y = (peep->y & 0xFFE0) + RCT2_ADDRESS(0x981F4E, uint16)[ebx * 2];
+
+ peep->destination_x = x;
+ peep->destination_y = y;
+ peep->destination_tolerence = 3;
+
+ if (peep->current_seat&1){
+ peep_insert_new_thought(peep, PEEP_THOUGHT_NEW_RIDE, 0xFF);
+ }
+ if (peep->current_ride == 0xFF){
+ peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_SCENERY, 0xFF);
+ }
+}
+
/* From peep_update */
static void peep_update_thoughts(rct_peep* peep){
// Thoughts must always have a gap of at least
@@ -1100,9 +1849,9 @@ static void peep_update(rct_peep *peep)
//return;
if (peep->type == PEEP_TYPE_GUEST) {
- if (peep->var_AD != 255)
- if (++peep->var_AE < 720)
- peep->var_AD = 255;
+ if (peep->previous_ride != 255)
+ if (++peep->previous_ride_time_out >= 720)
+ peep->previous_ride = 255;
peep_update_thoughts(peep);
}
@@ -1113,7 +1862,7 @@ static void peep_update(rct_peep *peep)
stepsToTake = 95;
if ((peep->flags & PEEP_FLAGS_SLOW_WALK) && peep->state != PEEP_STATE_QUEUING)
stepsToTake /= 2;
- if (peep->action == 255 && ((peep->next_z >> 8) & 4)) {
+ if (peep->action == 255 && (peep->next_var_29 & 4)) {
stepsToTake /= 2;
if (peep->state == PEEP_STATE_QUEUING)
stepsToTake += stepsToTake / 2;
@@ -1145,7 +1894,7 @@ static void peep_update(rct_peep *peep)
peep_update_leaving_ride(peep);
break;
case PEEP_STATE_WALKING:
- RCT2_CALLPROC_X(0x0069030A, 0, 0, 0, 0, (int)peep, 0, 0);
+ peep_update_walking(peep);
break;
case PEEP_STATE_QUEUING:
peep_update_queuing(peep);
@@ -1182,7 +1931,7 @@ static void peep_update(rct_peep *peep)
RCT2_CALLPROC_X(0x006C0E8B, 0, 0, 0, 0, (int)peep, 0, 0);
break;
case PEEP_STATE_BUYING:
- RCT2_CALLPROC_X(0x006912A3, 0, 0, 0, 0, (int)peep, 0, 0);
+ peep_update_buying(peep);
break;
case PEEP_STATE_WATCHING:
peep_update_watching(peep);
@@ -1190,8 +1939,8 @@ static void peep_update(rct_peep *peep)
case PEEP_STATE_EMPTYING_BIN:
peep_update_emptying_bin(peep);
break;
- case PEEP_STATE_20:
- RCT2_CALLPROC_X(0x00691089, 0, 0, 0, 0, (int)peep, 0, 0);
+ case PEEP_STATE_USING_BIN:
+ peep_update_using_bin(peep);
break;
case PEEP_STATE_WATERING:
peep_update_watering(peep);
@@ -1525,7 +2274,7 @@ void get_arguments_from_action(rct_peep* peep, uint32 *argument_1, uint32* argum
*argument_2 = ride.name_arguments;
break;
case PEEP_STATE_WALKING:
- case PEEP_STATE_20:
+ case PEEP_STATE_USING_BIN:
if (peep->guest_heading_to_ride_id != 0xFF){
ride = g_ride_list[peep->guest_heading_to_ride_id];
*argument_1 = STR_HEADING_FOR | (ride.name << 16);
@@ -1588,11 +2337,11 @@ void get_arguments_from_action(rct_peep* peep, uint32 *argument_1, uint32* argum
*argument_2 = 0;
break;
case PEEP_STATE_ANSWERING:
- if (peep->var_2C == 0){
+ if (peep->sub_state == 0){
*argument_1 = STR_WALKING;
*argument_2 = 0;
}
- else if (peep->var_2C == 1){
+ else if (peep->sub_state == 1){
*argument_1 = STR_ANSWERING_RADIO_CALL;
*argument_2 = 0;
}
@@ -1800,11 +2549,8 @@ int peep_is_mechanic(rct_peep *peep)
);
}
-/* To simplify check of 0x36BA3E0 and 0x11FF78
- * returns 0 on no food.
- */
-int peep_has_food(rct_peep* peep){
- return (peep->item_standard_flags &(
+static int peep_has_food_standard_flag(rct_peep* peep){
+ return peep->item_standard_flags &(
PEEP_ITEM_DRINK |
PEEP_ITEM_BURGER |
PEEP_ITEM_FRIES |
@@ -1818,8 +2564,11 @@ int peep_has_food(rct_peep* peep){
PEEP_ITEM_DONUT |
PEEP_ITEM_COFFEE |
PEEP_ITEM_CHICKEN |
- PEEP_ITEM_LEMONADE)) ||
- (peep->item_extra_flags &(
+ PEEP_ITEM_LEMONADE);
+}
+
+static int peep_has_food_extra_flag(rct_peep* peep){
+ return peep->item_extra_flags &(
PEEP_ITEM_PRETZEL |
PEEP_ITEM_CHOCOLATE |
PEEP_ITEM_ICED_TEA |
@@ -1834,7 +2583,61 @@ int peep_has_food(rct_peep* peep){
PEEP_ITEM_SUB_SANDWICH |
PEEP_ITEM_COOKIE |
PEEP_ITEM_ROAST_SAUSAGE
- ));
+ );
+}
+
+/* To simplify check of 0x36BA3E0 and 0x11FF78
+ * returns 0 on no food.
+ */
+int peep_has_food(rct_peep* peep){
+ return peep_has_food_standard_flag(peep) ||
+ peep_has_food_extra_flag(peep);
+}
+
+static int peep_empty_container_standard_flag(rct_peep* peep){
+ return peep->item_standard_flags &(
+ PEEP_ITEM_EMPTY_CAN |
+ PEEP_ITEM_EMPTY_BURGER_BOX |
+ PEEP_ITEM_EMPTY_CUP |
+ PEEP_ITEM_RUBBISH |
+ PEEP_ITEM_EMPTY_BOX |
+ PEEP_ITEM_EMPTY_BOTTLE
+ );
+}
+
+static int peep_empty_container_extra_flag(rct_peep* peep){
+ return peep->item_extra_flags &(
+ PEEP_ITEM_EMPTY_BOWL_RED |
+ PEEP_ITEM_EMPTY_DRINK_CARTON |
+ PEEP_ITEM_EMPTY_JUICE_CUP |
+ PEEP_ITEM_EMPTY_BOWL_BLUE
+ );
+}
+
+static int peep_has_empty_container(rct_peep* peep){
+ return peep_empty_container_standard_flag(peep) ||
+ peep_empty_container_extra_flag(peep);
+}
+
+/* Simplifies 0x690582. Returns 1 if should find bench*/
+static int peep_should_find_bench(rct_peep* peep){
+ if (!(peep->flags & PEEP_FLAGS_LEAVING_PARK)){
+ if (peep_has_food(peep)){
+ if (peep->hunger < 128 || peep->happiness < 128){
+ if (!(peep->next_var_29 & 0x1C)){
+ return 1;
+ }
+ }
+ }
+ if (peep->nausea <= 170 && peep->energy > 50){
+ return 0;
+ }
+
+ if (!(peep->next_var_29 & 0x1C)){
+ return 1;
+ }
+ }
+ return 0;
}
/**
@@ -1878,6 +2681,45 @@ void peep_insert_new_thought(rct_peep *peep, uint8 thought_type, uint8 thought_a
peep->var_45 |= (1 << 0);
}
+/* rct2: 0x00699FE3
+ * Stops peeps that are having thoughts
+ * such as "I'm hungry" after visiting a food shop.
+ * Works for Thirst/Hungry/Low Money/Bathroom
+ */
+static void peep_stop_purchase_thought(rct_peep* peep, uint8 ride_type){
+
+ uint8 thought_type = PEEP_THOUGHT_TYPE_HUNGRY;
+
+ if (!(RCT2_ADDRESS(0x97CF40, uint32)[ride_type * 2] & 0x800000)){
+ thought_type = PEEP_THOUGHT_TYPE_THIRSTY;
+ if (!(RCT2_ADDRESS(0x97CF40, uint32)[ride_type * 2] & 0x1000000)){
+ thought_type = PEEP_THOUGHT_RUNNING_OUT;
+ if (ride_type != RIDE_TYPE_ATM){
+ thought_type = PEEP_THOUGHT_TYPE_BATHROOM;
+ if (!(RCT2_ADDRESS(0x97CF40, uint32)[ride_type * 2] & 0x2000000)){
+ return;
+ }
+ }
+ }
+ }
+
+ //Remove the related thought
+ for (int i = 0; i < PEEP_MAX_THOUGHTS; ++i){
+ rct_peep_thought* thought = &peep->thoughts[i];
+
+ if (thought->type == PEEP_THOUGHT_TYPE_NONE) break;
+
+ if (thought->type != thought_type)continue;
+
+ memmove(thought, thought + 1, sizeof(rct_peep_thought)*(PEEP_MAX_THOUGHTS - i - 1));
+
+ peep->thoughts[PEEP_MAX_THOUGHTS - 1].type = PEEP_THOUGHT_TYPE_NONE;
+
+ peep->var_45 |= (1 << 0);
+ i--;
+ }
+}
+
void peep_set_map_tooltip(rct_peep *peep)
{
if (peep->type == PEEP_TYPE_GUEST) {
@@ -1900,4 +2742,4 @@ void peep_set_map_tooltip(rct_peep *peep)
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 8, uint32) = arg0;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 12, uint32) = arg1;
}
-}
\ No newline at end of file
+}
diff --git a/src/peep/peep.h b/src/peep/peep.h
index 2a93663327..9bdf564f5a 100644
--- a/src/peep/peep.h
+++ b/src/peep/peep.h
@@ -202,7 +202,7 @@ enum PEEP_STATE {
PEEP_STATE_BUYING = 17,
PEEP_STATE_WATCHING = 18,
PEEP_STATE_EMPTYING_BIN = 19,
- PEEP_STATE_20 = 20,
+ PEEP_STATE_USING_BIN = 20,
PEEP_STATE_WATERING = 21,
PEEP_STATE_HEADING_TO_INSPECTION = 22,
PEEP_STATE_INSPECTING = 23
@@ -230,9 +230,14 @@ enum PEEP_ACTION_EVENTS {
PEEP_ACTION_STAFF_WATERING = 19,
PEEP_ACTION_WAVE = 22,
PEEP_ACTION_STAFF_EMPTY_BIN = 23,
+ PEEP_ACTION_WAVE_2 = 24,
PEEP_ACTION_TAKE_PHOTO = 25,
PEEP_ACTION_CLAP = 26,
+ PEEP_ACTION_DRAW_PICTURE = 28,
+
+ PEEP_ACTION_WITHDRAW_MONEY = 30,
+
PEEP_ACTION_NONE_1 = 254,
PEEP_ACTION_NONE_2 = 255
};
@@ -258,6 +263,8 @@ enum PEEP_FLAGS {
PEEP_FLAGS_EATING = (1 << 17), // Reduces hunger
PEEP_FLAGS_EXPLODE = (1 << 18),
+ PEEP_FLAGS_21 = (1<<21),
+
PEEP_FLAGS_JOY = (1 << 23), // Makes the peep jump in joy
PEEP_FLAGS_ANGRY = (1 << 24),
PEEP_FLAGS_ICE_CREAM = (1 << 25) // Unconfirmed
@@ -357,10 +364,11 @@ typedef struct {
uint16 name_string_idx; // 0x22
uint16 next_x; // 0x24
uint16 next_y; // 0x26
- uint16 next_z; // 0x28 possibly split into two uint8s
+ uint8 next_z; // 0x28
+ uint8 next_var_29; // 0x29
uint8 var_2A;
uint8 state; // 0x2B
- uint8 var_2C;
+ uint8 sub_state; // 0x2C
uint8 sprite_type; // 0x2D
uint8 type; // 0x2E
union{
@@ -428,8 +436,8 @@ typedef struct {
money32 cash_spent; // 0xA4
sint32 time_in_park; // 0xA8
uint8 var_AC; // 0xAC
- uint8 var_AD; // creation/hire time?
- uint16 var_AE;
+ uint8 previous_ride; // 0xAD
+ uint16 previous_ride_time_out; // 0xAE
rct_peep_thought thoughts[PEEP_MAX_THOUGHTS]; // 0xB0
uint8 var_C4; // 0xC4
union // 0xC5
@@ -446,9 +454,9 @@ typedef struct {
uint32 var_CC;
uint8 pad_D0[0x10];
uint8 var_E0; // 0xE0
- uint8 pad_E1;
+ uint8 var_E1;
uint8 var_E2; // 0xE2
- uint8 pad_E3;
+ uint8 var_E3;
union{
money16 paid_to_enter; // 0xE4
uint16 staff_lawns_mown; // 0xE4
@@ -475,7 +483,8 @@ typedef struct {
uint8 voucher_arguments; // 0xF1 ride_id or string_offset_id
uint8 pad_F2;
uint8 var_F3;
- uint8 pad_F4[0x02];
+ uint8 var_F4;
+ uint8 pad_F5;
uint8 balloon_colour; // 0xF6
uint8 umbrella_colour; // 0xF7
uint8 hat_colour; // 0xF8
diff --git a/src/peep/staff.c b/src/peep/staff.c
index 6b56bebb9b..1321bf01ea 100644
--- a/src/peep/staff.c
+++ b/src/peep/staff.c
@@ -28,38 +28,23 @@
#include "staff.h"
/**
-*
-* rct2: 0x00669E55
-*/
-void game_command_update_staff_colour()
+ *
+ * rct2: 0x00669E55
+ */
+void game_command_update_staff_colour(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
{
- uint8 staff_type, colour, _bl;
+ uint8 staffType, colour;
int spriteIndex;
rct_peep *peep;
- #ifdef _MSC_VER
- __asm mov _bl, bl
- #else
- __asm__("mov %[_bl], bl " : [_bl] "+m" (_bl));
- #endif
+ staffType = (*ebx >> 8) & 0xFF;
+ colour = (*edx >> 8) & 0xFF;
- #ifdef _MSC_VER
- __asm mov staff_type, bh
- #else
- __asm__("mov %[staff_type], bh " : [staff_type] "+m" (staff_type));
- #endif
-
- #ifdef _MSC_VER
- __asm mov colour, dh
- #else
- __asm__("mov %[colour], bh " : [colour] "+m" (colour));
- #endif
-
- if (_bl & 1) {
- RCT2_ADDRESS(RCT2_ADDRESS_HANDYMAN_COLOUR, uint8)[staff_type] = colour;
+ if (*ebx & GAME_COMMAND_FLAG_APPLY) {
+ RCT2_ADDRESS(RCT2_ADDRESS_HANDYMAN_COLOUR, uint8)[staffType] = colour;
FOR_ALL_PEEPS(spriteIndex, peep) {
- if (peep->type == PEEP_TYPE_STAFF && peep->staff_type == staff_type) {
+ if (peep->type == PEEP_TYPE_STAFF && peep->staff_type == staffType) {
peep->tshirt_colour = colour;
peep->trousers_colour = colour;
}
@@ -67,25 +52,19 @@ void game_command_update_staff_colour()
}
gfx_invalidate_screen();
-
- #ifdef _MSC_VER
- __asm mov ebx, 0
- #else
- __asm__("mov ebx, 0 ");
- #endif
+ *ebx = 0;
}
/**
-*
-* rct2: 0x006BEFA1
-*/
-void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
- int* esi, int* edi, int* ebp)
+ *
+ * rct2: 0x006BEFA1
+ */
+void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp)
{
uint8 _bl = *ebx & 0xFF, staff_type = (*ebx & 0xFF00) >> 8;
uint16 _ax = *eax & 0xFFFF, _cx = *ecx & 0xFFFF, _dx = *edx & 0xFFFF;
- RCT2_GLOBAL(0x0141F56C, uint8) = 0x28;
+ RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_WAGES * 4;
RCT2_GLOBAL(0x009DEA5E, uint16) = _ax;
RCT2_GLOBAL(0x009DEA60, uint16) = _cx;
RCT2_GLOBAL(0x009DEA62, uint16) = _dx;
@@ -204,7 +183,7 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
sprite_move( newPeep->x, newPeep->y, newPeep->z, (rct_sprite*)newPeep);
invalidate_sprite((rct_sprite*)newPeep);
- newPeep->var_AD = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint8);
+ newPeep->time_in_park = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16);
newPeep->var_CC = 0xFFFFFFFF;
uint8 colour = RCT2_ADDRESS(RCT2_ADDRESS_HANDYMAN_COLOUR, uint8)[staff_type > 2 ? 2 : staff_type];
@@ -234,30 +213,23 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
/*
* Updates the colour of the given staff type.
-*/
-void update_staff_colour(uint8 staff_type, uint16 colour)
+ */
+void update_staff_colour(uint8 staffType, uint16 colour)
{
- game_do_command(
- 0,
- (staff_type << 8) + 1,
- 0,
- (colour << 8) + 4,
- GAME_COMMAND_SET_STAFF_COLOUR,
- 0,
- 0);
+ game_do_command(0, (staffType << 8) | GAME_COMMAND_FLAG_APPLY, 0, (colour << 8) | 4, GAME_COMMAND_SET_STAFF_COLOUR, 0, 0);
}
/*
* Hires a new staff member of the given type. If the hire cannot be completed (eg. the maximum
* number of staff is reached or there are too many people in the game) it returns 0xFFFF.
-*/
-uint16 hire_new_staff_member(uint8 staff_type)
+ */
+uint16 hire_new_staff_member(uint8 staffType)
{
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, uint16) = STR_CANT_HIRE_NEW_STAFF;
int eax, ebx, ecx, edx, esi, edi, ebp;
eax = 0x8000;
- ebx = staff_type << 8 | 1;
+ ebx = staffType << 8 | GAME_COMMAND_FLAG_APPLY;
int result = game_do_command_p(GAME_COMMAND_HIRE_NEW_STAFF_MEMBER, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
diff --git a/src/peep/staff.h b/src/peep/staff.h
index 758159489c..a036731abf 100644
--- a/src/peep/staff.h
+++ b/src/peep/staff.h
@@ -40,11 +40,11 @@ enum STAFF_TYPE {
STAFF_TYPE_ENTERTAINER
};
-void game_command_update_staff_colour();
-void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
+void game_command_update_staff_colour(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
+void game_command_hire_new_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
-void update_staff_colour(uint8 staff_type, uint16 color);
-uint16 hire_new_staff_member(uint8 staff_type);
+void update_staff_colour(uint8 staffType, uint16 color);
+uint16 hire_new_staff_member(uint8 staffType);
void sub_6C0C3F();
int mechanic_is_location_in_patrol(rct_peep *mechanic, int x, int y);
diff --git a/src/platform/osinterface.c b/src/platform/osinterface.c
deleted file mode 100644
index 6d36f67f90..0000000000
--- a/src/platform/osinterface.c
+++ /dev/null
@@ -1,929 +0,0 @@
-/*****************************************************************************
- * Copyright (c) 2014 Ted John, Alexander Overvoorde
- * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
- *
- * This file is part of OpenRCT2.
- *
- * OpenRCT2 is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-
-#include
-#include
-#include
-#include
-#include
-
-#include "../addresses.h"
-#include "../config.h"
-#include "../cursors.h"
-#include "../drawing/drawing.h"
-#include "../input.h"
-#include "../interface/keyboard_shortcut.h"
-#include "../interface/screenshot.h"
-#include "../interface/window.h"
-#include "osinterface.h"
-
-typedef void(*update_palette_func)(char*, int, int);
-
-openrct2_cursor gCursorState;
-const unsigned char *gKeysState;
-unsigned char *gKeysPressed;
-unsigned int gLastKeyPressed;
-char* gTextInput;
-int gTextInputLength;
-int gTextInputMaxLength;
-int gTextInputCursorPosition = 0;
-
-static void osinterface_create_window();
-static void osinterface_close_window();
-static void osinterface_resize(int width, int height);
-
-static SDL_Window *_window;
-static SDL_Surface *_surface;
-static SDL_Palette *_palette;
-
-static int _screenBufferSize;
-static void *_screenBuffer;
-
-static SDL_Cursor* _cursors[NO_CURSORS];
-
-static const int _fullscreen_modes[] = { 0, SDL_WINDOW_FULLSCREEN, SDL_WINDOW_FULLSCREEN_DESKTOP };
-
-static unsigned int _lastGestureTimestamp;
-static float _gestureRadius;
-
-void osinterface_init()
-{
- osinterface_create_window();
-
- gKeysPressed = malloc(sizeof(unsigned char) * 256);
- memset(gKeysPressed, 0, sizeof(unsigned char) * 256);
-
- // RCT2_CALLPROC(0x00404584); // dinput_init()
-}
-
-int osinterface_scancode_to_rct_keycode(int sdl_key){
- char keycode = (char)SDL_GetKeyFromScancode((SDL_Scancode)sdl_key);
-
- // Until we reshufle the text files to use the new positions
- // this will suffice to move the majority to the correct positions.
- // Note any special buttons PgUp PgDwn are mapped wrong.
- if (keycode >= 'a' && keycode <= 'z')keycode = toupper(keycode);
-
- return keycode;
-}
-
-void osinterface_start_text_input(char* buffer, int max_length){
- SDL_StartTextInput();
- gTextInputMaxLength = max_length - 1;
- gTextInput = buffer;
- gTextInputCursorPosition = strnlen(gTextInput, max_length);
- gTextInputLength = gTextInputCursorPosition;
-}
-
-void osinterface_stop_text_input(){
- SDL_StopTextInput();
- gTextInput = NULL;
-}
-
-/**
- * This is not quite the same as the below function as we don't want to
- * derfererence the cursor before the function.
- * rct2: 0x0407956
- */
-void osinterface_set_cursor(char cursor){
- //HCURSOR hCurs = RCT2_ADDRESS(RCT2_ADDRESS_HCURSOR_START, HCURSOR)[cursor];
- //SetCursor((HCURSOR)hCurs);
- SDL_SetCursor(_cursors[cursor]);
-}
-/**
- *rct2: 0x0068352C
- */
-static void osinterface_load_cursors(){
-
- RCT2_GLOBAL(0x14241BC, uint32) = 2;
- HINSTANCE hInst = RCT2_GLOBAL(RCT2_ADDRESS_HINSTANCE, HINSTANCE);
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_ARROW, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x74));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_BLANK, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0xA1));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_UP_ARROW, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x6D));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_UP_DOWN_ARROW, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x6E));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_HAND_POINT, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x70));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_ZZZ, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x78));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_DIAGONAL_ARROWS, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x77));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_PICKER, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x7C));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_TREE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x83));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_FOUNTAIN_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x7F));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_STATUE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x80));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_BENCH_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x81));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_CROSS_HAIR, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x82));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_BIN_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x84));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_LAMPPOST_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x85));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_FENCE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8A));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_FLOWER_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x89));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_PATH_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8B));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_DIG_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8D));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_WATER_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8E));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_HOUSE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8F));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_VOLCANO_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x90));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_WALK_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x91));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_PAINT_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x9E));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_ENTRANCE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x9F));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_HAND_OPEN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0xA6));
- RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_HAND_CLOSED, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0xA5));
-
- _cursors[0] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
- _cursors[1] = SDL_CreateCursor(blank_cursor_data, blank_cursor_mask, 32, 32, BLANK_CURSOR_HOTX, BLANK_CURSOR_HOTY);
- _cursors[2] = SDL_CreateCursor(up_arrow_cursor_data, up_arrow_cursor_mask, 32, 32, UP_ARROW_CURSOR_HOTX, UP_ARROW_CURSOR_HOTY);
- _cursors[3] = SDL_CreateCursor(up_down_arrow_cursor_data, up_down_arrow_cursor_mask, 32, 32, UP_DOWN_ARROW_CURSOR_HOTX, UP_DOWN_ARROW_CURSOR_HOTY);
- _cursors[4] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
- _cursors[5] = SDL_CreateCursor(zzz_cursor_data, zzz_cursor_mask, 32, 32, ZZZ_CURSOR_HOTX, ZZZ_CURSOR_HOTY);
- _cursors[6] = SDL_CreateCursor(diagonal_arrow_cursor_data, diagonal_arrow_cursor_mask, 32, 32, DIAGONAL_ARROW_CURSOR_HOTX, DIAGONAL_ARROW_CURSOR_HOTY);
- _cursors[7] = SDL_CreateCursor(picker_cursor_data, picker_cursor_mask, 32, 32, PICKER_CURSOR_HOTX, PICKER_CURSOR_HOTY);
- _cursors[8] = SDL_CreateCursor(tree_down_cursor_data, tree_down_cursor_mask, 32, 32, TREE_DOWN_CURSOR_HOTX, TREE_DOWN_CURSOR_HOTY);
- _cursors[9] = SDL_CreateCursor(fountain_down_cursor_data, fountain_down_cursor_mask, 32, 32, FOUNTAIN_DOWN_CURSOR_HOTX, FOUNTAIN_DOWN_CURSOR_HOTY);
- _cursors[10] = SDL_CreateCursor(statue_down_cursor_data, statue_down_cursor_mask, 32, 32, STATUE_DOWN_CURSOR_HOTX, STATUE_DOWN_CURSOR_HOTY);
- _cursors[11] = SDL_CreateCursor(bench_down_cursor_data, bench_down_cursor_mask, 32, 32, BENCH_DOWN_CURSOR_HOTX, BENCH_DOWN_CURSOR_HOTY);
- _cursors[12] = SDL_CreateCursor(cross_hair_cursor_data, cross_hair_cursor_mask, 32, 32, CROSS_HAIR_CURSOR_HOTX, CROSS_HAIR_CURSOR_HOTY);
- _cursors[13] = SDL_CreateCursor(bin_down_cursor_data, bin_down_cursor_mask, 32, 32, BIN_DOWN_CURSOR_HOTX, BIN_DOWN_CURSOR_HOTY);
- _cursors[14] = SDL_CreateCursor(lamppost_down_cursor_data, lamppost_down_cursor_mask, 32, 32, LAMPPOST_DOWN_CURSOR_HOTX, LAMPPOST_DOWN_CURSOR_HOTY);
- _cursors[15] = SDL_CreateCursor(fence_down_cursor_data, fence_down_cursor_mask, 32, 32, FENCE_DOWN_CURSOR_HOTX, FENCE_DOWN_CURSOR_HOTY);
- _cursors[16] = SDL_CreateCursor(flower_down_cursor_data, flower_down_cursor_mask, 32, 32, FLOWER_DOWN_CURSOR_HOTX, FLOWER_DOWN_CURSOR_HOTY);
- _cursors[17] = SDL_CreateCursor(path_down_cursor_data, path_down_cursor_mask, 32, 32, PATH_DOWN_CURSOR_HOTX, PATH_DOWN_CURSOR_HOTY);
- _cursors[18] = SDL_CreateCursor(dig_down_cursor_data, dig_down_cursor_mask, 32, 32, DIG_DOWN_CURSOR_HOTX, DIG_DOWN_CURSOR_HOTY);
- _cursors[19] = SDL_CreateCursor(water_down_cursor_data, water_down_cursor_mask, 32, 32, WATER_DOWN_CURSOR_HOTX, WATER_DOWN_CURSOR_HOTY);
- _cursors[20] = SDL_CreateCursor(house_down_cursor_data, house_down_cursor_mask, 32, 32, HOUSE_DOWN_CURSOR_HOTX, HOUSE_DOWN_CURSOR_HOTY);
- _cursors[21] = SDL_CreateCursor(volcano_down_cursor_data, volcano_down_cursor_mask, 32, 32, VOLCANO_DOWN_CURSOR_HOTX, VOLCANO_DOWN_CURSOR_HOTY);
- _cursors[22] = SDL_CreateCursor(walk_down_cursor_data, walk_down_cursor_mask, 32, 32, WALK_DOWN_CURSOR_HOTX, WALK_DOWN_CURSOR_HOTY);
- _cursors[23] = SDL_CreateCursor(paint_down_cursor_data, paint_down_cursor_mask, 32, 32, PAINT_DOWN_CURSOR_HOTX, PAINT_DOWN_CURSOR_HOTY);
- _cursors[24] = SDL_CreateCursor(entrance_down_cursor_data, entrance_down_cursor_mask, 32, 32, ENTRANCE_DOWN_CURSOR_HOTX, ENTRANCE_DOWN_CURSOR_HOTY);
- _cursors[25] = SDL_CreateCursor(hand_open_cursor_data, hand_open_cursor_mask, 32, 32, HAND_OPEN_CURSOR_HOTX, HAND_OPEN_CURSOR_HOTY);
- _cursors[26] = SDL_CreateCursor(hand_closed_cursor_data, hand_closed_cursor_mask, 32, 32, HAND_CLOSED_CURSOR_HOTX, HAND_CLOSED_CURSOR_HOTY);
- osinterface_set_cursor(CURSOR_ARROW);
- RCT2_GLOBAL(0x14241BC, uint32) = 0;
-}
-
-static void osinterface_unload_cursors(){
- for (int i = 0; i < NO_CURSORS; ++i){
- if (_cursors[i] != NULL)SDL_FreeCursor(_cursors[i]);
- }
-}
-
-static void osinterface_create_window()
-{
- SDL_SysWMinfo wmInfo;
- HWND hWnd;
- int width, height;
-
- if (SDL_Init(SDL_INIT_VIDEO) < 0) {
- RCT2_ERROR("SDL_Init %s", SDL_GetError());
- exit(-1);
- }
-
- // stuff
- {
- osinterface_load_cursors();
- RCT2_CALLPROC_EBPSAFE(0x0068371D);
-
- width = gGeneral_config.window_width;
- height = gGeneral_config.window_height;
-
- if (width == -1) width = 640;
- if (height == -1) height = 480;
- }
-
- RCT2_GLOBAL(0x009E2D8C, sint32) = 0;
-
- _window = SDL_CreateWindow("OpenRCT2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height,
- _fullscreen_modes[gGeneral_config.fullscreen_mode] | SDL_WINDOW_RESIZABLE);
- if (!_window) {
- RCT2_ERROR("SDL_CreateWindow failed %s", SDL_GetError());
- exit(-1);
- }
-
- SDL_VERSION(&wmInfo.version);
- // Get the HWND context
- if (SDL_GetWindowWMInfo(_window, &wmInfo) != SDL_TRUE) {
- RCT2_ERROR("SDL_GetWindowWMInfo failed %s", SDL_GetError());
- exit(-1);
- }
- hWnd = wmInfo.info.win.window;
- RCT2_GLOBAL(0x009E2D70, HWND) = hWnd;
-
- // Set the update palette function pointer
- RCT2_GLOBAL(0x009E2BE4, update_palette_func) = osinterface_update_palette;
-
- // Initialise the surface, palette and draw buffer
- osinterface_resize(width, height);
-}
-
-
-static void osinterface_resize(int width, int height)
-{
- rct_drawpixelinfo *screenDPI;
- int newScreenBufferSize;
- void *newScreenBuffer;
-
- if (_surface != NULL)
- SDL_FreeSurface(_surface);
- if (_palette != NULL)
- SDL_FreePalette(_palette);
-
- _surface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0);
- _palette = SDL_AllocPalette(256);
-
- if (!_surface || !_palette) {
- RCT2_ERROR("%p || %p == NULL %s", _surface, _palette, SDL_GetError());
- exit(-1);
- }
-
- if (SDL_SetSurfacePalette(_surface, _palette)) {
- RCT2_ERROR("SDL_SetSurfacePalette failed %s", SDL_GetError());
- exit(-1);
- }
-
- newScreenBufferSize = _surface->pitch * _surface->h;
- newScreenBuffer = malloc(newScreenBufferSize);
- if (_screenBuffer == NULL) {
- memset(newScreenBuffer, 0, newScreenBufferSize);
- } else {
- memcpy(newScreenBuffer, _screenBuffer, min(_screenBufferSize, newScreenBufferSize));
- if (newScreenBufferSize - _screenBufferSize > 0)
- memset((uint8*)newScreenBuffer + _screenBufferSize, 0, newScreenBufferSize - _screenBufferSize);
- free(_screenBuffer);
- }
-
- _screenBuffer = newScreenBuffer;
- _screenBufferSize = newScreenBufferSize;
-
- RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) = width;
- RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) = height;
-
- screenDPI = RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo);
- screenDPI->bits = _screenBuffer;
- screenDPI->x = 0;
- screenDPI->y = 0;
- screenDPI->width = width;
- screenDPI->height = height;
- screenDPI->pitch = _surface->pitch - _surface->w;
-
- RCT2_GLOBAL(0x009ABDF0, uint8) = 6;
- RCT2_GLOBAL(0x009ABDF1, uint8) = 3;
- RCT2_GLOBAL(0x009ABDF2, uint8) = 1;
- RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_WIDTH, sint16) = 64;
- RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_HEIGHT, sint16) = 8;
- RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, sint32) = (width >> 6) + 1;
- RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_ROWS, sint32) = (height >> 3) + 1;
-
- window_resize_gui(width, height);
- //RCT2_CALLPROC_EBPSAFE(0x0066B905); // resize_gui()
-
- gfx_invalidate_screen();
-}
-
-void osinterface_update_palette(char* colours, int start_index, int num_colours)
-{
- SDL_Color base[256];
- SDL_Surface *surface;
- int i;
-
- surface = SDL_GetWindowSurface(_window);
- if (!surface) {
- RCT2_ERROR("SDL_GetWindowSurface failed %s", SDL_GetError());
- exit(1);
- }
-
- for (i = 0; i < 256; i++) {
- base[i].r = colours[2];
- base[i].g = colours[1];
- base[i].b = colours[0];
- base[i].a = 0;
- colours += 4;
- }
-
- if (SDL_SetPaletteColors(_palette, base, 0, 256)) {
- RCT2_ERROR("SDL_SetPaletteColors failed %s", SDL_GetError());
- exit(1);
- }
-}
-
-void osinterface_draw()
-{
- // Lock the surface before setting its pixels
- if (SDL_MUSTLOCK(_surface))
- if (SDL_LockSurface(_surface) < 0) {
- RCT2_ERROR("locking failed %s", SDL_GetError());
- return;
- }
-
- // Copy pixels from the virtual screen buffer to the surface
- memcpy(_surface->pixels, _screenBuffer, _surface->pitch * _surface->h);
-
- // Unlock the surface
- if (SDL_MUSTLOCK(_surface))
- SDL_UnlockSurface(_surface);
-
- // Copy the surface to the window
- if (SDL_BlitSurface(_surface, NULL, SDL_GetWindowSurface(_window), NULL)) {
- RCT2_ERROR("SDL_BlitSurface %s", SDL_GetError());
- exit(1);
- }
- if (SDL_UpdateWindowSurface(_window)) {
- RCT2_ERROR("SDL_UpdateWindowSurface %s", SDL_GetError());
- exit(1);
- }
-}
-
-void osinterface_process_messages()
-{
- SDL_Event e;
-
- gLastKeyPressed = 0;
- // gCursorState.wheel = 0;
- gCursorState.left &= ~CURSOR_CHANGED;
- gCursorState.middle &= ~CURSOR_CHANGED;
- gCursorState.right &= ~CURSOR_CHANGED;
- gCursorState.old = 0;
-
- while (SDL_PollEvent(&e)) {
- switch (e.type) {
- case SDL_QUIT:
-// rct2_finish();
- rct2_quit();
- break;
- case SDL_WINDOWEVENT:
- if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
- osinterface_resize(e.window.data1, e.window.data2);
- break;
- case SDL_MOUSEMOTION:
- RCT2_GLOBAL(0x0142406C, int) = e.motion.x;
- RCT2_GLOBAL(0x01424070, int) = e.motion.y;
-
- gCursorState.x = e.motion.x;
- gCursorState.y = e.motion.y;
- break;
- case SDL_MOUSEWHEEL:
- gCursorState.wheel += e.wheel.y * 128;
- break;
- case SDL_MOUSEBUTTONDOWN:
- RCT2_GLOBAL(0x01424318, int) = e.button.x;
- RCT2_GLOBAL(0x0142431C, int) = e.button.y;
- switch (e.button.button) {
- case SDL_BUTTON_LEFT:
- store_mouse_input(1);
- gCursorState.left = CURSOR_PRESSED;
- gCursorState.old = 1;
- break;
- case SDL_BUTTON_MIDDLE:
- gCursorState.middle = CURSOR_PRESSED;
- break;
- case SDL_BUTTON_RIGHT:
- store_mouse_input(3);
- gCursorState.right = CURSOR_PRESSED;
- gCursorState.old = 2;
- break;
- }
- break;
- case SDL_MOUSEBUTTONUP:
- RCT2_GLOBAL(0x01424318, int) = e.button.x;
- RCT2_GLOBAL(0x0142431C, int) = e.button.y;
- switch (e.button.button) {
- case SDL_BUTTON_LEFT:
- store_mouse_input(2);
- gCursorState.left = CURSOR_RELEASED;
- gCursorState.old = 3;
- break;
- case SDL_BUTTON_MIDDLE:
- gCursorState.middle = CURSOR_RELEASED;
- break;
- case SDL_BUTTON_RIGHT:
- store_mouse_input(4);
- gCursorState.right = CURSOR_RELEASED;
- gCursorState.old = 4;
- break;
- }
- break;
- case SDL_KEYDOWN:
- if (e.key.keysym.sym == SDLK_KP_ENTER){
- // Map Keypad enter to regular enter.
- e.key.keysym.scancode = SDL_SCANCODE_RETURN;
- }
-
- gLastKeyPressed = e.key.keysym.sym;
- gKeysPressed[e.key.keysym.scancode] = 1;
- if (e.key.keysym.sym == SDLK_RETURN && e.key.keysym.mod & KMOD_ALT)
- osinterface_set_fullscreen_mode(!gGeneral_config.fullscreen_mode);
-
- // Text input
-
- // If backspace and we have input text with a cursor position none zero
- if (e.key.keysym.sym == SDLK_BACKSPACE && gTextInputLength > 0 && gTextInput && gTextInputCursorPosition){
- // When at max length don't shift the data left
- // as it would buffer overflow.
- if (gTextInputCursorPosition != gTextInputMaxLength)
- memmove(gTextInput + gTextInputCursorPosition - 1, gTextInput + gTextInputCursorPosition, gTextInputMaxLength - gTextInputCursorPosition - 1);
- gTextInput[gTextInputLength - 1] = '\0';
- gTextInputCursorPosition--;
- gTextInputLength--;
- }
- if (e.key.keysym.sym == SDLK_END){
- gTextInputCursorPosition = gTextInputLength;
- }
- if (e.key.keysym.sym == SDLK_HOME){
- gTextInputCursorPosition = 0;
- }
- if (e.key.keysym.sym == SDLK_DELETE && gTextInputLength > 0 && gTextInput && gTextInputCursorPosition != gTextInputLength){
- memmove(gTextInput + gTextInputCursorPosition, gTextInput + gTextInputCursorPosition + 1, gTextInputMaxLength - gTextInputCursorPosition - 1);
- gTextInput[gTextInputMaxLength - 1] = '\0';
- gTextInputLength--;
- }
- if (e.key.keysym.sym == SDLK_LEFT && gTextInput){
- if (gTextInputCursorPosition) gTextInputCursorPosition--;
- }
- else if (e.key.keysym.sym == SDLK_RIGHT && gTextInput){
- if (gTextInputCursorPosition < gTextInputLength) gTextInputCursorPosition++;
- }
- break;
- case SDL_MULTIGESTURE:
- if (e.mgesture.numFingers == 2) {
- if (e.mgesture.timestamp > _lastGestureTimestamp + 1000)
- _gestureRadius = 0;
- _lastGestureTimestamp = e.mgesture.timestamp;
- _gestureRadius += e.mgesture.dDist;
-
- // Zoom gesture
- const int tolerance = 128;
- int gesturePixels = (int)(_gestureRadius * RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16));
- if (gesturePixels > tolerance) {
- _gestureRadius = 0;
- keyboard_shortcut_handle_command(SHORTCUT_ZOOM_VIEW_IN);
- } else if (gesturePixels < -tolerance) {
- _gestureRadius = 0;
- keyboard_shortcut_handle_command(SHORTCUT_ZOOM_VIEW_OUT);
- }
- }
- break;
-
- case SDL_TEXTINPUT:
- if (gTextInputLength < gTextInputMaxLength && gTextInput){
- // Convert the utf-8 code into rct ascii
- char new_char;
- if (!(e.text.text[0] & 0x80))
- new_char = *e.text.text;
- else if (!(e.text.text[0] & 0x20))
- new_char = ((e.text.text[0] & 0x1F) << 6) | (e.text.text[1] & 0x3F);
-
- // If inserting in center of string make space for new letter
- if (gTextInputLength > gTextInputCursorPosition){
- memmove(gTextInput + gTextInputCursorPosition + 1, gTextInput + gTextInputCursorPosition, gTextInputMaxLength - gTextInputCursorPosition - 1);
- gTextInput[gTextInputCursorPosition] = new_char;
- gTextInputLength++;
- }
- else gTextInput[gTextInputLength++] = new_char;
-
- gTextInputCursorPosition++;
- }
- break;
- default:
- break;
- }
- }
-
- gCursorState.any = gCursorState.left | gCursorState.middle | gCursorState.right;
-
- // Updates the state of the keys
- int numKeys = 256;
- gKeysState = SDL_GetKeyboardState(&numKeys);
-}
-
-static void osinterface_close_window()
-{
- if (_window != NULL)
- SDL_DestroyWindow(_window);
- if (_surface != NULL)
- SDL_FreeSurface(_surface);
- if (_palette != NULL)
- SDL_FreePalette(_palette);
- osinterface_unload_cursors();
-}
-
-void osinterface_free()
-{
- free(gKeysPressed);
-
- osinterface_close_window();
- SDL_Quit();
-}
-
-void osinterface_set_fullscreen_mode(int mode){
- if (mode == gGeneral_config.fullscreen_mode)
- return;
-
- if (SDL_SetWindowFullscreen(_window, _fullscreen_modes[mode])){
- RCT2_ERROR("SDL_SetWindowFullscreen %s", SDL_GetError());
- exit(1);
- }
- //SDL automatically resizes the fullscreen window to the nearest allowed screen resolution
- //No need to call osinterface_resize() here, SDL_WINDOWEVENT_SIZE_CHANGED event will be triggered anyway
-
- gGeneral_config.fullscreen_mode = mode;
-
- config_save();
-}
-
-/**
- *
- * rct2: 0x00407978
- */
-int osinterface_407978(rct2_install_info* install_info, char* source, char* font, uint8 charset)
-{
- char subkey[MAX_PATH];
- char subkey2[MAX_PATH];
- strcpy(subkey, "Software\\Infogrames\\");
- strcat(subkey, source);
- strcpy(subkey2, "Software\\Fish Technology Group\\");
- strcat(subkey2, source);
- LOGFONTA lf;
- memset(&lf, 0, sizeof(lf));
- lf.lfCharSet = charset;
- lf.lfHeight = 12;
- lf.lfWeight = 400;
- strcpy(lf.lfFaceName, font);
- RCT2_GLOBAL(RCT2_ADDRESS_HFONT, HFONT) = CreateFontIndirectA(&lf);
- HKEY hkey;
- if (RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &hkey) != ERROR_SUCCESS && RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey2, &hkey) != ERROR_SUCCESS) {
- return 0;
- } else {
- DWORD type;
- DWORD size = 260;
- RegQueryValueExA(hkey, "Title", 0, &type, install_info->title, &size);
- size = 260;
- RegQueryValueExA(hkey, "Path", 0, &type, install_info->path, &size);
- install_info->var_20C = 235960;
- size = 4;
- RegQueryValueExA(hkey, "InstallLevel", 0, &type, (LPBYTE)&install_info->installlevel, &size);
- for (int i = 0; i <= 15; i++) {
- char name[100];
- sprintf(name, "AddonPack%d", i);
- size = sizeof(install_info->addon[i]);
- if (RegQueryValueExA(hkey, name, 0, &type, install_info->addon[i], &size) == ERROR_SUCCESS) {
- install_info->addons |= (1 << i);
- }
- }
- RegCloseKey(hkey);
- return 1;
- }
-}
-
-/**
- *
- * rct2: 0x00407D80
- */
-int osinterface_get_cursor_pos(int* x, int* y)
-{
- POINT point;
- GetCursorPos(&point);
- *x = point.x;
- *y = point.y;
-}
-
-/**
- *
- * rct2: 0x00407E15
- */
-int osinterface_print_window_message(UINT msg, WPARAM wparam, LPARAM lparam)
-{
- const char* msgname = "NULL";
- // get the string representation of the msg id, from 190 different values in 0x009A61D8 - 0x009A8873
- // not going to bother reading those since this function is going to be unused and taken out anyways
- char temp[1024];
- sprintf(temp, "Message id = %s (%i), wParam = 0x%x, lParam = 0x%x\n", msgname, msg, wparam, lparam);
- OutputDebugStringA(temp);
- return 1;
-}
-
-/**
- *
- * rct2: 0x00407E6E
- */
-int osinterface_progressbar_create(char* title, int a2)
-{
- DWORD style = WS_VISIBLE | WS_BORDER | WS_DLGFRAME;
- if (a2) {
- style = WS_VISIBLE | WS_BORDER | WS_DLGFRAME | PBS_SMOOTH;
- }
- int width = 340;
- int height = GetSystemMetrics(SM_CYCAPTION) + 24;
- HWND hwnd = CreateWindowExA(WS_EX_TOPMOST | WS_EX_DLGMODALFRAME, "msctls_progress32", title, style, (RCT2_GLOBAL(0x01423C08, sint32) - width) / 2, (RCT2_GLOBAL(0x01423C0C, sint32) - height) / 2, width, height, 0, 0, RCT2_GLOBAL(RCT2_ADDRESS_HINSTANCE, HINSTANCE), 0);
- RCT2_GLOBAL(RCT2_ADDRESS_PROGRESSBAR_HWND, HWND) = hwnd;
- if (hwnd) {
- RCT2_GLOBAL(0x009E2DFC, uint32) = 1;
- if (RCT2_GLOBAL(RCT2_ADDRESS_HFONT, HFONT)) {
- SendMessageA(hwnd, WM_SETFONT, (WPARAM)RCT2_GLOBAL(RCT2_ADDRESS_HFONT, HFONT), 1);
- }
- SetWindowTextA(hwnd, title);
- osinterface_progressbar_setmax(0xFF);
- osinterface_progressbar_setpos(0);
- return 1;
- } else {
- return 0;
- }
-}
-
-/**
- *
- * rct2: 0x00407F16
- */
-int osinterface_progressbar_destroy()
-{
- if (DestroyWindow(RCT2_GLOBAL(RCT2_ADDRESS_PROGRESSBAR_HWND, HWND))) {
- RCT2_GLOBAL(0x009E2DFC, uint32) = 0;
- return 1;
- } else {
- return 0;
- }
-}
-
-/**
- *
- * rct2: 0x00407F2E
- */
-void osinterface_progressbar_setmax(int max)
-{
- SendMessageA(RCT2_GLOBAL(RCT2_ADDRESS_PROGRESSBAR_HWND, HWND), PBM_SETRANGE, MAKEWPARAM(0, max), 0);
- SendMessageA(RCT2_GLOBAL(RCT2_ADDRESS_PROGRESSBAR_HWND, HWND), PBM_SETSTEP, 1, 0);
-}
-
-/**
- *
- * rct2: 0x00407F60
- */
-void osinterface_progressbar_setpos(int pos)
-{
- SendMessageA(RCT2_GLOBAL(RCT2_ADDRESS_PROGRESSBAR_HWND, HWND), PBM_SETPOS, MAKEWPARAM(pos, 0), 0);
-}
-
-/**
- *
- * rct2: 0x00407F78
- */
-int osinterface_file_seek_from_begin(HANDLE handle, int offset)
-{
- return SetFilePointer(handle, offset, 0, FILE_BEGIN);
-}
-
-/**
- *
- * rct2: 0x00407F8B
- */
-int osinterface_file_seek_from_current(HANDLE handle, int offset)
-{
- return SetFilePointer(handle, offset, 0, FILE_CURRENT);
-}
-
-/**
- *
- * rct2: 0x00407F9E
- */
-int osinterface_file_seek_from_end(HANDLE handle, int offset)
-{
- return SetFilePointer(handle, offset, 0, FILE_END);
-}
-
-/**
- *
- * rct2: 0x00407FB1
- */
-int osinterface_file_read(HANDLE handle, void* data, int size)
-{
- DWORD read;
- BOOL result;
- if (size == -1) {
- DWORD current = SetFilePointer(handle, 0, 0, FILE_CURRENT);
- DWORD remaining = SetFilePointer(handle, 0, 0, FILE_END) - current;
- result = ReadFile(handle, data, remaining, &read, 0);
- } else {
- result = ReadFile(handle, data, size, &read, 0);
- }
- if (result) {
- return read;
- } else {
- return -1;
- }
-}
-
-/**
- *
- * rct2: 0x00408024
- */
-int osinterface_file_write(HANDLE handle, const void* data, int size)
-{
- DWORD written;
- if (WriteFile(handle, data, size, &written, 0)) {
- return written;
- } else {
- return -1;
- }
-}
-
-/**
- *
- * rct2: 0x0040804A
- */
-int osinterface_file_close(HANDLE handle)
-{
- if (handle) {
- return CloseHandle(handle);
- } else {
- return 1;
- }
-}
-
-/**
- *
- * rct2: 0x00408060
- */
-HANDLE osinterface_file_open(const char* filename)
-{
- return CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_NORMAL, 0);
-}
-
-/**
- *
- * rct2: 0x0040807D
- */
-HANDLE osinterface_file_create(const char* filename)
-{
- return CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
-}
-
-/**
- *
- * rct2: 0x00408099
- */
-int osinterface_file_move(const char* srcfilename, const char* dstfilename)
-{
- return (MoveFileA(srcfilename, dstfilename) != 0) - 1;
-}
-
-/**
- *
- * rct2: 0x004080AF
- */
-int osinterface_file_delete(const char* filename)
-{
- return (DeleteFileA(filename) != 0) - 1;
-}
-
-/**
- *
- * rct2: 0x004080EA
- */
-int osinterface_open_common_file_dialog(int type, char *title, char *filename, char *filterPattern, char *filterName)
-{
- char initialDirectory[MAX_PATH], *dotAddress, *slashAddress;
- OPENFILENAME openFileName;
- BOOL result;
- int tmp;
- DWORD commonFlags;
-
- // Get directory path from given filename
- strcpy(initialDirectory, filename);
- dotAddress = strrchr(initialDirectory, '.');
- if (dotAddress != NULL) {
- slashAddress = strrchr(initialDirectory, '\\');
- if (slashAddress < dotAddress)
- *(slashAddress + 1) = 0;
- }
-
- // Clear filename
- if (type != 0)
- *filename = 0;
-
- // Set open file name options
- memset(&openFileName, 0, sizeof(OPENFILENAME));
- openFileName.lStructSize = sizeof(OPENFILENAME);
- openFileName.hwndOwner = RCT2_GLOBAL(0x009E2D70, HWND);
- openFileName.lpstrFile = filename;
- openFileName.nMaxFile = MAX_PATH;
- openFileName.lpstrInitialDir = initialDirectory;
- openFileName.lpstrTitle = title;
-
- // Copy filter name
- strcpy((char*)0x01423800, filterName);
-
- // Copy filter pattern
- strcpy((char*)0x01423800 + strlen(filterName) + 1, filterPattern);
- *((char*)(0x01423800 + strlen(filterName) + 1 + strlen(filterPattern) + 1)) = 0;
- openFileName.lpstrFilter = (char*)0x01423800;
-
- //
- tmp = RCT2_GLOBAL(0x009E2C74, uint32);
- if (RCT2_GLOBAL(0x009E2BB8, uint32) == 2 && RCT2_GLOBAL(0x009E1AF8, uint32) == 1)
- RCT2_GLOBAL(0x009E2C74, uint32) = 1;
-
- // Open dialog
- commonFlags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
- if (type == 0) {
- openFileName.Flags = commonFlags | OFN_CREATEPROMPT | OFN_OVERWRITEPROMPT;
- result = GetSaveFileName(&openFileName);
- } else if (type == 1) {
- openFileName.Flags = commonFlags | OFN_NONETWORKBUTTON | OFN_FILEMUSTEXIST;
- result = GetOpenFileName(&openFileName);
- }
-
- //
- RCT2_GLOBAL(0x009E2C74, uint32) = tmp;
-
- return result;
-}
-
-void osinterface_show_messagebox(char* message)
-{
- MessageBox(NULL, message, "OpenRCT2", MB_OK);
-}
-
-char* osinterface_open_directory_browser(char *title)
-{
- BROWSEINFO bi;
- char pszBuffer[MAX_PATH];
- LPITEMIDLIST pidl;
- LPMALLOC lpMalloc;
-
- // Initialize COM
- if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED))) {
- CoUninitialize();
-
- log_error("Error opening directory browse window");
- return 0;
- }
-
- // Get a pointer to the shell memory allocator
- if (FAILED(SHGetMalloc(&lpMalloc))) {
- CoUninitialize();
-
- log_error("Error opening directory browse window");
- return 0;
- }
-
- bi.hwndOwner = NULL;
- bi.pidlRoot = NULL;
- bi.pszDisplayName = pszBuffer;
- bi.lpszTitle = _T(title);
- bi.ulFlags = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS;
- bi.lpfn = NULL;
- bi.lParam = 0;
-
- char *outPath = NULL;
-
- if (pidl = SHBrowseForFolder(&bi)) {
- // Copy the path directory to the buffer
- if (SHGetPathFromIDList(pidl, pszBuffer)) {
- // Store pszBuffer (and the path) in the outPath
- outPath = (char*) malloc(strlen(pszBuffer)+1);
- strcpy(outPath, pszBuffer);
- }
- }
- CoUninitialize();
- return outPath;
-}
-
-char* osinterface_get_orct2_homefolder()
-{
- char *path=NULL;
- path = malloc(sizeof(char) * MAX_PATH);
- if (path == NULL){
- log_fatal("Error allocating memory!");
- exit(EXIT_FAILURE);
- }
-
- path[0] = '\0';
-
- if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, path)))
- strcat(path, "\\OpenRCT2");
-
- return path;
-}
-
-char *osinterface_get_orct2_homesubfolder(const char *subFolder)
-{
- char *path = osinterface_get_orct2_homefolder();
- strcat(path, "\\");
- strcat(path, subFolder);
- return path;
-}
-
-char osinterface_get_path_separator()
-{
- return '\\';
-}
diff --git a/src/platform/osinterface.h b/src/platform/osinterface.h
deleted file mode 100644
index 27561cd889..0000000000
--- a/src/platform/osinterface.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*****************************************************************************
- * Copyright (c) 2014 Ted John
- * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
- *
- * This file is part of OpenRCT2.
- *
- * OpenRCT2 is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-
-#ifndef _SDL_INTERFACE_H_
-#define _SDL_INTERFACE_H_
-
-#include
-#include "../common.h"
-
-enum {
- CURSOR_UP = 0,
- CURSOR_DOWN = 1,
- CURSOR_CHANGED = 2,
- CURSOR_RELEASED = CURSOR_UP | CURSOR_CHANGED,
- CURSOR_PRESSED = CURSOR_DOWN | CURSOR_CHANGED,
-};
-
-enum{
- CURSOR_ARROW = 0,
- CURSOR_BLANK = 1,
- CURSOR_UP_ARROW = 2,
- CURSOR_UP_DOWN_ARROW = 3,
- CURSOR_HAND_POINT = 4,
- CURSOR_ZZZ = 5,
- CURSOR_DIAGONAL_ARROWS = 6,
- CURSOR_PICKER = 7,
- CURSOR_TREE_DOWN = 8,
- CURSOR_FOUNTAIN_DOWN = 9,
- CURSOR_STATUE_DOWN = 10,
- CURSOR_BENCH_DOWN = 11,
- CURSOR_CROSS_HAIR = 12,
- CURSOR_BIN_DOWN = 13,
- CURSOR_LAMPPOST_DOWN = 14,
- CURSOR_FENCE_DOWN = 15,
- CURSOR_FLOWER_DOWN = 16,
- CURSOR_PATH_DOWN = 17,
- CURSOR_DIG_DOWN = 18,
- CURSOR_WATER_DOWN = 19,
- CURSOR_HOUSE_DOWN = 20,
- CURSOR_VOLCANO_DOWN = 21,
- CURSOR_WALK_DOWN = 22,
- CURSOR_PAINT_DOWN = 23,
- CURSOR_ENTRANCE_DOWN = 24,
- CURSOR_HAND_OPEN = 25,
- CURSOR_HAND_CLOSED = 26
-};
-
-typedef struct {
- int x, y;
- unsigned char left, middle, right, any;
- int wheel;
- int old;
-} openrct2_cursor;
-
-typedef struct {
- uint32 installlevel;
- char title[260];
- char path[260];
- uint32 var_20C;
- uint8 pad_210[0x100];
- char addon[16][0x80];
- uint32 addons; //0xB10
-} rct2_install_info;
-
-extern openrct2_cursor gCursorState;
-extern const unsigned char *gKeysState;
-extern unsigned char *gKeysPressed;
-extern unsigned int gLastKeyPressed;
-extern int gTextInputCursorPosition;
-
-void osinterface_start_text_input(char* buffer, int max_length);
-void osinterface_stop_text_input();
-void osinterface_init();
-void osinterface_process_messages();
-void osinterface_draw();
-void osinterface_free();
-void osinterface_update_palette(char* colours, int start_index, int num_colours);
-
-void osinterface_set_fullscreen_mode(int mode);
-
-void osinterface_progressbar_setmax(int max);
-void osinterface_progressbar_setpos(int pos);
-
-void osinterface_set_cursor(char cursor);
-
-HANDLE osinterface_file_open(const char* filename);
-int osinterface_file_read(HANDLE handle, void* data, int size);
-int osinterface_file_close(HANDLE handle);
-
-int osinterface_open_common_file_dialog(int type, char *title, char *filename, char *filterPattern, char *filterName);
-void osinterface_show_messagebox(char* message);
-char* osinterface_open_directory_browser(char *title);
-
-char* osinterface_get_orct2_homefolder();
-char *osinterface_get_orct2_homesubfolder(const char *subFolder);
-
-char osinterface_get_path_separator();
-int osinterface_scancode_to_rct_keycode(int sdl_key);
-
-#endif
diff --git a/src/platform/platform.h b/src/platform/platform.h
index 2b2e8db336..1ceead246a 100644
--- a/src/platform/platform.h
+++ b/src/platform/platform.h
@@ -21,6 +21,8 @@
#ifndef _PLATFORM_H_
#define _PLATFORM_H_
+#include
+
#include "../common.h"
#ifndef MAX_PATH
@@ -29,12 +31,57 @@
#define INVALID_HANDLE -1
+typedef struct {
+ int width, height;
+} resolution;
+
typedef struct {
const char *path;
uint64 size;
uint64 last_modified;
} file_info;
+typedef struct {
+ int x, y;
+ unsigned char left, middle, right, any;
+ int wheel;
+ int old;
+} openrct2_cursor;
+
+enum {
+ CURSOR_UP = 0,
+ CURSOR_DOWN = 1,
+ CURSOR_CHANGED = 2,
+ CURSOR_RELEASED = CURSOR_UP | CURSOR_CHANGED,
+ CURSOR_PRESSED = CURSOR_DOWN | CURSOR_CHANGED,
+};
+
+extern openrct2_cursor gCursorState;
+extern const unsigned char *gKeysState;
+extern unsigned char *gKeysPressed;
+extern unsigned int gLastKeyPressed;
+extern int gTextInputCursorPosition;
+
+extern int gResolutionsAllowAnyAspectRatio;
+extern int gNumResolutions;
+extern resolution *gResolutions;
+extern SDL_Window *gWindow;
+
+// Platform shared definitions
+void platform_update_fullscreen_resolutions();
+void platform_get_closest_resolution(int inWidth, int inHeight, int *outWidth, int *outHeight);
+void platform_init();
+void platform_draw();
+void platform_free();
+void platform_update_palette(char* colours, int start_index, int num_colours);
+void platform_set_fullscreen_mode(int mode);
+void platform_set_cursor(char cursor);
+void platform_process_messages();
+char *platform_get_orct2_homesubfolder();
+int platform_scancode_to_rct_keycode(int sdl_key);
+void platform_start_text_input(char* buffer, int max_length);
+void platform_stop_text_input();
+
// Platform specific definitions
char platform_get_path_separator();
int platform_file_exists(const char *path);
@@ -44,10 +91,28 @@ int platform_lock_single_instance();
int platform_enumerate_files_begin(const char *pattern);
int platform_enumerate_files_next(int handle, file_info *outFileInfo);
void platform_enumerate_files_end(int handle);
+int platform_file_move(const char *srcPath, const char *dstPath);
+int platform_file_delete(const char *path);
void platform_hide_cursor();
void platform_show_cursor();
void platform_get_cursor_position(int *x, int *y);
void platform_set_cursor_position(int x, int y);
unsigned int platform_get_ticks();
+char *platform_get_orct2_homefolder();
+void platform_show_messagebox(char *message);
+int platform_open_common_file_dialog(int type, char *title, char *filename, char *filterPattern, char *filterName);
+char *platform_open_directory_browser(char *title);
+
+// Windows specific definitions
+#ifdef _WIN32
+ // Defining WIN32_LEAN_AND_MEAN breaks dsound.h in audio.h (uncomment when dsound is finally removed)
+ // #ifndef WIN32_LEAN_AND_MEAN
+ // #define WIN32_LEAN_AND_MEAN
+ // #endif
+ #include
+
+ int windows_get_registry_install_info(rct2_install_info *installInfo, char *source, char *font, uint8 charset);
+ HWND windows_get_window_handle();
+#endif
#endif
\ No newline at end of file
diff --git a/src/platform/shared.c b/src/platform/shared.c
index 20a00a3bd2..01ca5114db 100644
--- a/src/platform/shared.c
+++ b/src/platform/shared.c
@@ -18,3 +18,651 @@
* along with this program. If not, see .
*****************************************************************************/
+#include
+#include
+#include "../addresses.h"
+#include "../config.h"
+#include "../cursors.h"
+#include "../drawing/drawing.h"
+#include "../interface/keyboard_shortcut.h"
+#include "../interface/window.h"
+#include "../input.h"
+#include "platform.h"
+
+typedef void(*update_palette_func)(char*, int, int);
+
+openrct2_cursor gCursorState;
+const unsigned char *gKeysState;
+unsigned char *gKeysPressed;
+unsigned int gLastKeyPressed;
+char* gTextInput;
+int gTextInputLength;
+int gTextInputMaxLength;
+int gTextInputCursorPosition = 0;
+
+int gNumResolutions = 0;
+resolution *gResolutions = NULL;
+int gResolutionsAllowAnyAspectRatio = 0;
+
+SDL_Window *gWindow;
+
+static SDL_Surface *_surface;
+static SDL_Palette *_palette;
+static int _screenBufferSize;
+static void *_screenBuffer;
+static SDL_Cursor* _cursors[CURSOR_COUNT];
+static const int _fullscreen_modes[] = { 0, SDL_WINDOW_FULLSCREEN, SDL_WINDOW_FULLSCREEN_DESKTOP };
+static unsigned int _lastGestureTimestamp;
+static float _gestureRadius;
+
+static void platform_create_window();
+static void platform_load_cursors();
+static void platform_unload_cursors();
+
+int resolution_sort_func(const void *pa, const void *pb)
+{
+ const resolution *a = (resolution*)pa;
+ const resolution *b = (resolution*)pb;
+
+ int areaA = a->width * a->height;
+ int areaB = b->width * b->height;
+
+ if (areaA == areaB) return 0;
+ if (areaA < areaB) return -1;
+ return 1;
+}
+
+void platform_update_fullscreen_resolutions()
+{
+ int i, displayIndex, numDisplayModes;
+ SDL_DisplayMode mode;
+ resolution *resLook, *resPlace;
+ float desktopAspectRatio, aspectRatio;
+
+ // Query number of display modes
+ displayIndex = SDL_GetWindowDisplayIndex(gWindow);
+ numDisplayModes = SDL_GetNumDisplayModes(displayIndex);
+
+ // Get desktop aspect ratio
+ SDL_GetDesktopDisplayMode(displayIndex, &mode);
+ desktopAspectRatio = (float)mode.w / mode.h;
+
+ if (gResolutions != NULL)
+ free(gResolutions);
+
+ // Get resolutions
+ gNumResolutions = numDisplayModes;
+ gResolutions = malloc(gNumResolutions * sizeof(resolution));
+
+ gNumResolutions = 0;
+ for (i = 0; i < numDisplayModes; i++) {
+ SDL_GetDisplayMode(displayIndex, i, &mode);
+
+ aspectRatio = (float)mode.w / mode.h;
+ if (gResolutionsAllowAnyAspectRatio || fabs(desktopAspectRatio - aspectRatio) < 0.0001f) {
+ gResolutions[gNumResolutions].width = mode.w;
+ gResolutions[gNumResolutions].height = mode.h;
+ gNumResolutions++;
+ }
+ }
+
+ // Sort by area
+ qsort(gResolutions, gNumResolutions, sizeof(resolution), resolution_sort_func);
+
+ // Remove duplicates
+ resPlace = &gResolutions[0];
+ for (int i = 1; i < gNumResolutions; i++) {
+ resLook = &gResolutions[i];
+ if (resLook->width != resPlace->width || resLook->height != resPlace->height)
+ *++resPlace = *resLook;
+ }
+
+ gNumResolutions = (int)(resPlace - &gResolutions[0]) + 1;
+
+ // Update config fullscreen resolution if not set
+ if (gGeneral_config.fullscreen_width == -1 || gGeneral_config.fullscreen_height == -1) {
+ gGeneral_config.fullscreen_width = gResolutions[gNumResolutions - 1].width;
+ gGeneral_config.fullscreen_height = gResolutions[gNumResolutions - 1].height;
+ }
+}
+
+void platform_get_closest_resolution(int inWidth, int inHeight, int *outWidth, int *outHeight)
+{
+ int i, destinationArea, areaDiff, closestAreaDiff, closestWidth, closestHeight;
+
+ closestAreaDiff = -1;
+ destinationArea = inWidth * inHeight;
+ for (i = 0; i < gNumResolutions; i++) {
+ // Check if exact match
+ if (gResolutions[i].width == inWidth && gResolutions[i].height == inHeight) {
+ closestWidth = gResolutions[i].width;
+ closestHeight = gResolutions[i].height;
+ break;
+ }
+
+ // Check if area is closer to best match
+ areaDiff = abs((gResolutions[i].width * gResolutions[i].height) - destinationArea);
+ if (closestAreaDiff == -1 || areaDiff < closestAreaDiff) {
+ closestAreaDiff = areaDiff;
+ closestWidth = gResolutions[i].width;
+ closestHeight = gResolutions[i].height;
+ }
+ }
+
+ if (closestAreaDiff != -1) {
+ *outWidth = closestWidth;
+ *outHeight = closestHeight;
+ } else {
+ *outWidth = 640;
+ *outHeight = 480;
+ }
+}
+
+void platform_draw()
+{
+ // Lock the surface before setting its pixels
+ if (SDL_MUSTLOCK(_surface))
+ if (SDL_LockSurface(_surface) < 0) {
+ RCT2_ERROR("locking failed %s", SDL_GetError());
+ return;
+ }
+
+ // Copy pixels from the virtual screen buffer to the surface
+ memcpy(_surface->pixels, _screenBuffer, _surface->pitch * _surface->h);
+
+ // Unlock the surface
+ if (SDL_MUSTLOCK(_surface))
+ SDL_UnlockSurface(_surface);
+
+ // Copy the surface to the window
+ if (SDL_BlitSurface(_surface, NULL, SDL_GetWindowSurface(gWindow), NULL)) {
+ RCT2_ERROR("SDL_BlitSurface %s", SDL_GetError());
+ exit(1);
+ }
+ if (SDL_UpdateWindowSurface(gWindow)) {
+ RCT2_ERROR("SDL_UpdateWindowSurface %s", SDL_GetError());
+ exit(1);
+ }
+}
+
+static void platform_resize(int width, int height)
+{
+ rct_drawpixelinfo *screenDPI;
+ int newScreenBufferSize;
+ void *newScreenBuffer;
+
+ if (_surface != NULL)
+ SDL_FreeSurface(_surface);
+ if (_palette != NULL)
+ SDL_FreePalette(_palette);
+
+ _surface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0);
+ _palette = SDL_AllocPalette(256);
+
+ if (!_surface || !_palette) {
+ RCT2_ERROR("%p || %p == NULL %s", _surface, _palette, SDL_GetError());
+ exit(-1);
+ }
+
+ if (SDL_SetSurfacePalette(_surface, _palette)) {
+ RCT2_ERROR("SDL_SetSurfacePalette failed %s", SDL_GetError());
+ exit(-1);
+ }
+
+ newScreenBufferSize = _surface->pitch * _surface->h;
+ newScreenBuffer = malloc(newScreenBufferSize);
+ if (_screenBuffer == NULL) {
+ memset(newScreenBuffer, 0, newScreenBufferSize);
+ } else {
+ memcpy(newScreenBuffer, _screenBuffer, min(_screenBufferSize, newScreenBufferSize));
+ if (newScreenBufferSize - _screenBufferSize > 0)
+ memset((uint8*)newScreenBuffer + _screenBufferSize, 0, newScreenBufferSize - _screenBufferSize);
+ free(_screenBuffer);
+ }
+
+ _screenBuffer = newScreenBuffer;
+ _screenBufferSize = newScreenBufferSize;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) = width;
+ RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) = height;
+
+ screenDPI = RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo);
+ screenDPI->bits = _screenBuffer;
+ screenDPI->x = 0;
+ screenDPI->y = 0;
+ screenDPI->width = width;
+ screenDPI->height = height;
+ screenDPI->pitch = _surface->pitch - _surface->w;
+
+ RCT2_GLOBAL(0x009ABDF0, uint8) = 6;
+ RCT2_GLOBAL(0x009ABDF1, uint8) = 3;
+ RCT2_GLOBAL(0x009ABDF2, uint8) = 1;
+ RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_WIDTH, sint16) = 64;
+ RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_HEIGHT, sint16) = 8;
+ RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, sint32) = (width >> 6) + 1;
+ RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_ROWS, sint32) = (height >> 3) + 1;
+
+ window_resize_gui(width, height);
+ window_relocate_windows(width, height);
+
+ gfx_invalidate_screen();
+}
+
+void platform_update_palette(char* colours, int start_index, int num_colours)
+{
+ SDL_Color base[256];
+ SDL_Surface *surface;
+ int i;
+
+ surface = SDL_GetWindowSurface(gWindow);
+ if (!surface) {
+ RCT2_ERROR("SDL_GetWindowSurface failed %s", SDL_GetError());
+ exit(1);
+ }
+
+ for (i = 0; i < 256; i++) {
+ base[i].r = colours[2];
+ base[i].g = colours[1];
+ base[i].b = colours[0];
+ base[i].a = 0;
+ colours += 4;
+ }
+
+ if (SDL_SetPaletteColors(_palette, base, 0, 256)) {
+ RCT2_ERROR("SDL_SetPaletteColors failed %s", SDL_GetError());
+ exit(1);
+ }
+}
+
+void platform_process_messages()
+{
+ SDL_Event e;
+
+ gLastKeyPressed = 0;
+ // gCursorState.wheel = 0;
+ gCursorState.left &= ~CURSOR_CHANGED;
+ gCursorState.middle &= ~CURSOR_CHANGED;
+ gCursorState.right &= ~CURSOR_CHANGED;
+ gCursorState.old = 0;
+
+ while (SDL_PollEvent(&e)) {
+ switch (e.type) {
+ case SDL_QUIT:
+// rct2_finish();
+ rct2_quit();
+ break;
+ case SDL_WINDOWEVENT:
+ if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
+ platform_resize(e.window.data1, e.window.data2);
+ break;
+ case SDL_MOUSEMOTION:
+ RCT2_GLOBAL(0x0142406C, int) = e.motion.x;
+ RCT2_GLOBAL(0x01424070, int) = e.motion.y;
+
+ gCursorState.x = e.motion.x;
+ gCursorState.y = e.motion.y;
+ break;
+ case SDL_MOUSEWHEEL:
+ gCursorState.wheel += e.wheel.y * 128;
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ RCT2_GLOBAL(0x01424318, int) = e.button.x;
+ RCT2_GLOBAL(0x0142431C, int) = e.button.y;
+ switch (e.button.button) {
+ case SDL_BUTTON_LEFT:
+ store_mouse_input(1);
+ gCursorState.left = CURSOR_PRESSED;
+ gCursorState.old = 1;
+ break;
+ case SDL_BUTTON_MIDDLE:
+ gCursorState.middle = CURSOR_PRESSED;
+ break;
+ case SDL_BUTTON_RIGHT:
+ store_mouse_input(3);
+ gCursorState.right = CURSOR_PRESSED;
+ gCursorState.old = 2;
+ break;
+ }
+ break;
+ case SDL_MOUSEBUTTONUP:
+ RCT2_GLOBAL(0x01424318, int) = e.button.x;
+ RCT2_GLOBAL(0x0142431C, int) = e.button.y;
+ switch (e.button.button) {
+ case SDL_BUTTON_LEFT:
+ store_mouse_input(2);
+ gCursorState.left = CURSOR_RELEASED;
+ gCursorState.old = 3;
+ break;
+ case SDL_BUTTON_MIDDLE:
+ gCursorState.middle = CURSOR_RELEASED;
+ break;
+ case SDL_BUTTON_RIGHT:
+ store_mouse_input(4);
+ gCursorState.right = CURSOR_RELEASED;
+ gCursorState.old = 4;
+ break;
+ }
+ break;
+ case SDL_KEYDOWN:
+ if (e.key.keysym.sym == SDLK_KP_ENTER){
+ // Map Keypad enter to regular enter.
+ e.key.keysym.scancode = SDL_SCANCODE_RETURN;
+ }
+
+ gLastKeyPressed = e.key.keysym.sym;
+ gKeysPressed[e.key.keysym.scancode] = 1;
+ if (e.key.keysym.sym == SDLK_RETURN && e.key.keysym.mod & KMOD_ALT) {
+ int targetMode = gGeneral_config.fullscreen_mode == 0 ? 2 : 0;
+ platform_set_fullscreen_mode(targetMode);
+ gGeneral_config.fullscreen_mode = targetMode;
+ config_save();
+ break;
+ }
+
+ // Text input
+
+ // If backspace and we have input text with a cursor position none zero
+ if (e.key.keysym.sym == SDLK_BACKSPACE && gTextInputLength > 0 && gTextInput && gTextInputCursorPosition){
+ // When at max length don't shift the data left
+ // as it would buffer overflow.
+ if (gTextInputCursorPosition != gTextInputMaxLength)
+ memmove(gTextInput + gTextInputCursorPosition - 1, gTextInput + gTextInputCursorPosition, gTextInputMaxLength - gTextInputCursorPosition - 1);
+ gTextInput[gTextInputLength - 1] = '\0';
+ gTextInputCursorPosition--;
+ gTextInputLength--;
+ }
+ if (e.key.keysym.sym == SDLK_END){
+ gTextInputCursorPosition = gTextInputLength;
+ }
+ if (e.key.keysym.sym == SDLK_HOME){
+ gTextInputCursorPosition = 0;
+ }
+ if (e.key.keysym.sym == SDLK_DELETE && gTextInputLength > 0 && gTextInput && gTextInputCursorPosition != gTextInputLength){
+ memmove(gTextInput + gTextInputCursorPosition, gTextInput + gTextInputCursorPosition + 1, gTextInputMaxLength - gTextInputCursorPosition - 1);
+ gTextInput[gTextInputMaxLength - 1] = '\0';
+ gTextInputLength--;
+ }
+ if (e.key.keysym.sym == SDLK_LEFT && gTextInput){
+ if (gTextInputCursorPosition) gTextInputCursorPosition--;
+ }
+ else if (e.key.keysym.sym == SDLK_RIGHT && gTextInput){
+ if (gTextInputCursorPosition < gTextInputLength) gTextInputCursorPosition++;
+ }
+ break;
+ case SDL_MULTIGESTURE:
+ if (e.mgesture.numFingers == 2) {
+ if (e.mgesture.timestamp > _lastGestureTimestamp + 1000)
+ _gestureRadius = 0;
+ _lastGestureTimestamp = e.mgesture.timestamp;
+ _gestureRadius += e.mgesture.dDist;
+
+ // Zoom gesture
+ const int tolerance = 128;
+ int gesturePixels = (int)(_gestureRadius * RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16));
+ if (gesturePixels > tolerance) {
+ _gestureRadius = 0;
+ keyboard_shortcut_handle_command(SHORTCUT_ZOOM_VIEW_IN);
+ } else if (gesturePixels < -tolerance) {
+ _gestureRadius = 0;
+ keyboard_shortcut_handle_command(SHORTCUT_ZOOM_VIEW_OUT);
+ }
+ }
+ break;
+
+ case SDL_TEXTINPUT:
+ if (gTextInputLength < gTextInputMaxLength && gTextInput){
+ // Convert the utf-8 code into rct ascii
+ char new_char;
+ if (!(e.text.text[0] & 0x80))
+ new_char = *e.text.text;
+ else if (!(e.text.text[0] & 0x20))
+ new_char = ((e.text.text[0] & 0x1F) << 6) | (e.text.text[1] & 0x3F);
+
+ // If inserting in center of string make space for new letter
+ if (gTextInputLength > gTextInputCursorPosition){
+ memmove(gTextInput + gTextInputCursorPosition + 1, gTextInput + gTextInputCursorPosition, gTextInputMaxLength - gTextInputCursorPosition - 1);
+ gTextInput[gTextInputCursorPosition] = new_char;
+ gTextInputLength++;
+ }
+ else gTextInput[gTextInputLength++] = new_char;
+
+ gTextInputCursorPosition++;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ gCursorState.any = gCursorState.left | gCursorState.middle | gCursorState.right;
+
+ // Updates the state of the keys
+ int numKeys = 256;
+ gKeysState = SDL_GetKeyboardState(&numKeys);
+}
+
+static void platform_close_window()
+{
+ if (gWindow != NULL)
+ SDL_DestroyWindow(gWindow);
+ if (_surface != NULL)
+ SDL_FreeSurface(_surface);
+ if (_palette != NULL)
+ SDL_FreePalette(_palette);
+ platform_unload_cursors();
+}
+
+void platform_init()
+{
+ platform_create_window();
+ gKeysPressed = malloc(sizeof(unsigned char) * 256);
+ memset(gKeysPressed, 0, sizeof(unsigned char) * 256);
+ // RCT2_CALLPROC(0x00404584); // dinput_init()
+}
+
+static void platform_create_window()
+{
+ int width, height;
+
+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ RCT2_ERROR("SDL_Init %s", SDL_GetError());
+ exit(-1);
+ }
+
+ platform_load_cursors();
+ RCT2_CALLPROC_EBPSAFE(0x0068371D);
+
+ // Get window size
+ width = gGeneral_config.window_width;
+ height = gGeneral_config.window_height;
+ if (width == -1) width = 640;
+ if (height == -1) height = 480;
+
+ RCT2_GLOBAL(0x009E2D8C, sint32) = 0;
+
+ // Create window in window first rather than fullscreen so we have the display the window is on first
+ gWindow = SDL_CreateWindow(
+ "OpenRCT2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_RESIZABLE
+ );
+ if (!gWindow) {
+ log_fatal("SDL_CreateWindow failed %s", SDL_GetError());
+ exit(-1);
+ }
+
+ // Set the update palette function pointer
+ RCT2_GLOBAL(0x009E2BE4, update_palette_func) = platform_update_palette;
+
+ // Initialise the surface, palette and draw buffer
+ platform_resize(width, height);
+
+ platform_update_fullscreen_resolutions();
+ platform_set_fullscreen_mode(gGeneral_config.fullscreen_mode);
+}
+
+int platform_scancode_to_rct_keycode(int sdl_key)
+{
+ char keycode = (char)SDL_GetKeyFromScancode((SDL_Scancode)sdl_key);
+
+ // Until we reshufle the text files to use the new positions
+ // this will suffice to move the majority to the correct positions.
+ // Note any special buttons PgUp PgDwn are mapped wrong.
+ if (keycode >= 'a' && keycode <= 'z')
+ keycode = toupper(keycode);
+
+ return keycode;
+}
+
+void platform_free()
+{
+ free(gKeysPressed);
+
+ platform_close_window();
+ SDL_Quit();
+}
+
+void platform_start_text_input(char* buffer, int max_length)
+{
+ SDL_StartTextInput();
+ gTextInputMaxLength = max_length - 1;
+ gTextInput = buffer;
+ gTextInputCursorPosition = strnlen(gTextInput, max_length);
+ gTextInputLength = gTextInputCursorPosition;
+}
+
+void platform_stop_text_input()
+{
+ SDL_StopTextInput();
+ gTextInput = NULL;
+}
+
+static void platform_unload_cursors()
+{
+ for (int i = 0; i < CURSOR_COUNT; i++)
+ if (_cursors[i] != NULL)
+ SDL_FreeCursor(_cursors[i]);
+}
+
+void platform_set_fullscreen_mode(int mode)
+{
+ int width, height;
+
+ mode = _fullscreen_modes[mode];
+
+ // HACK Changing window size when in fullscreen usually has no effect
+ if (mode == SDL_WINDOW_FULLSCREEN)
+ SDL_SetWindowFullscreen(gWindow, 0);
+
+ // Set window size
+ if (mode == SDL_WINDOW_FULLSCREEN) {
+ platform_update_fullscreen_resolutions();
+ platform_get_closest_resolution(gGeneral_config.fullscreen_width, gGeneral_config.fullscreen_height, &width, &height);
+ SDL_SetWindowSize(gWindow, width, height);
+ } else if (mode == 0) {
+ SDL_SetWindowSize(gWindow, gGeneral_config.window_width, gGeneral_config.window_height);
+ }
+
+ if (SDL_SetWindowFullscreen(gWindow, mode)) {
+ log_fatal("SDL_SetWindowFullscreen %s", SDL_GetError());
+ exit(1);
+
+ // TODO try another display mode rather than just exiting the game
+ }
+}
+
+char *platform_get_orct2_homesubfolder(const char *subFolder)
+{
+ char seperator = platform_get_path_separator();
+
+ char *path = platform_get_orct2_homefolder();
+ strcat(path, &seperator);
+ strcat(path, subFolder);
+ return path;
+}
+
+/**
+ * This is not quite the same as the below function as we don't want to
+ * derfererence the cursor before the function.
+ * rct2: 0x0407956
+ */
+void platform_set_cursor(char cursor)
+{
+ SDL_SetCursor(_cursors[cursor]);
+}
+/**
+ *
+ * rct2: 0x0068352C
+ */
+static void platform_load_cursors()
+{
+ RCT2_GLOBAL(0x14241BC, uint32) = 2;
+ HINSTANCE hInst = RCT2_GLOBAL(RCT2_ADDRESS_HINSTANCE, HINSTANCE);
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_ARROW, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x74));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_BLANK, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0xA1));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_UP_ARROW, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x6D));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_UP_DOWN_ARROW, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x6E));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_HAND_POINT, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x70));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_ZZZ, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x78));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_DIAGONAL_ARROWS, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x77));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_PICKER, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x7C));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_TREE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x83));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_FOUNTAIN_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x7F));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_STATUE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x80));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_BENCH_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x81));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_CROSS_HAIR, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x82));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_BIN_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x84));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_LAMPPOST_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x85));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_FENCE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8A));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_FLOWER_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x89));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_PATH_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8B));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_DIG_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8D));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_WATER_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8E));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_HOUSE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8F));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_VOLCANO_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x90));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_WALK_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x91));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_PAINT_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x9E));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_ENTRANCE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x9F));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_HAND_OPEN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0xA6));
+ RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_HAND_CLOSED, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0xA5));
+
+ _cursors[0] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
+ _cursors[1] = SDL_CreateCursor(blank_cursor_data, blank_cursor_mask, 32, 32, BLANK_CURSOR_HOTX, BLANK_CURSOR_HOTY);
+ _cursors[2] = SDL_CreateCursor(up_arrow_cursor_data, up_arrow_cursor_mask, 32, 32, UP_ARROW_CURSOR_HOTX, UP_ARROW_CURSOR_HOTY);
+ _cursors[3] = SDL_CreateCursor(up_down_arrow_cursor_data, up_down_arrow_cursor_mask, 32, 32, UP_DOWN_ARROW_CURSOR_HOTX, UP_DOWN_ARROW_CURSOR_HOTY);
+ _cursors[4] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
+ _cursors[5] = SDL_CreateCursor(zzz_cursor_data, zzz_cursor_mask, 32, 32, ZZZ_CURSOR_HOTX, ZZZ_CURSOR_HOTY);
+ _cursors[6] = SDL_CreateCursor(diagonal_arrow_cursor_data, diagonal_arrow_cursor_mask, 32, 32, DIAGONAL_ARROW_CURSOR_HOTX, DIAGONAL_ARROW_CURSOR_HOTY);
+ _cursors[7] = SDL_CreateCursor(picker_cursor_data, picker_cursor_mask, 32, 32, PICKER_CURSOR_HOTX, PICKER_CURSOR_HOTY);
+ _cursors[8] = SDL_CreateCursor(tree_down_cursor_data, tree_down_cursor_mask, 32, 32, TREE_DOWN_CURSOR_HOTX, TREE_DOWN_CURSOR_HOTY);
+ _cursors[9] = SDL_CreateCursor(fountain_down_cursor_data, fountain_down_cursor_mask, 32, 32, FOUNTAIN_DOWN_CURSOR_HOTX, FOUNTAIN_DOWN_CURSOR_HOTY);
+ _cursors[10] = SDL_CreateCursor(statue_down_cursor_data, statue_down_cursor_mask, 32, 32, STATUE_DOWN_CURSOR_HOTX, STATUE_DOWN_CURSOR_HOTY);
+ _cursors[11] = SDL_CreateCursor(bench_down_cursor_data, bench_down_cursor_mask, 32, 32, BENCH_DOWN_CURSOR_HOTX, BENCH_DOWN_CURSOR_HOTY);
+ _cursors[12] = SDL_CreateCursor(cross_hair_cursor_data, cross_hair_cursor_mask, 32, 32, CROSS_HAIR_CURSOR_HOTX, CROSS_HAIR_CURSOR_HOTY);
+ _cursors[13] = SDL_CreateCursor(bin_down_cursor_data, bin_down_cursor_mask, 32, 32, BIN_DOWN_CURSOR_HOTX, BIN_DOWN_CURSOR_HOTY);
+ _cursors[14] = SDL_CreateCursor(lamppost_down_cursor_data, lamppost_down_cursor_mask, 32, 32, LAMPPOST_DOWN_CURSOR_HOTX, LAMPPOST_DOWN_CURSOR_HOTY);
+ _cursors[15] = SDL_CreateCursor(fence_down_cursor_data, fence_down_cursor_mask, 32, 32, FENCE_DOWN_CURSOR_HOTX, FENCE_DOWN_CURSOR_HOTY);
+ _cursors[16] = SDL_CreateCursor(flower_down_cursor_data, flower_down_cursor_mask, 32, 32, FLOWER_DOWN_CURSOR_HOTX, FLOWER_DOWN_CURSOR_HOTY);
+ _cursors[17] = SDL_CreateCursor(path_down_cursor_data, path_down_cursor_mask, 32, 32, PATH_DOWN_CURSOR_HOTX, PATH_DOWN_CURSOR_HOTY);
+ _cursors[18] = SDL_CreateCursor(dig_down_cursor_data, dig_down_cursor_mask, 32, 32, DIG_DOWN_CURSOR_HOTX, DIG_DOWN_CURSOR_HOTY);
+ _cursors[19] = SDL_CreateCursor(water_down_cursor_data, water_down_cursor_mask, 32, 32, WATER_DOWN_CURSOR_HOTX, WATER_DOWN_CURSOR_HOTY);
+ _cursors[20] = SDL_CreateCursor(house_down_cursor_data, house_down_cursor_mask, 32, 32, HOUSE_DOWN_CURSOR_HOTX, HOUSE_DOWN_CURSOR_HOTY);
+ _cursors[21] = SDL_CreateCursor(volcano_down_cursor_data, volcano_down_cursor_mask, 32, 32, VOLCANO_DOWN_CURSOR_HOTX, VOLCANO_DOWN_CURSOR_HOTY);
+ _cursors[22] = SDL_CreateCursor(walk_down_cursor_data, walk_down_cursor_mask, 32, 32, WALK_DOWN_CURSOR_HOTX, WALK_DOWN_CURSOR_HOTY);
+ _cursors[23] = SDL_CreateCursor(paint_down_cursor_data, paint_down_cursor_mask, 32, 32, PAINT_DOWN_CURSOR_HOTX, PAINT_DOWN_CURSOR_HOTY);
+ _cursors[24] = SDL_CreateCursor(entrance_down_cursor_data, entrance_down_cursor_mask, 32, 32, ENTRANCE_DOWN_CURSOR_HOTX, ENTRANCE_DOWN_CURSOR_HOTY);
+ _cursors[25] = SDL_CreateCursor(hand_open_cursor_data, hand_open_cursor_mask, 32, 32, HAND_OPEN_CURSOR_HOTX, HAND_OPEN_CURSOR_HOTY);
+ _cursors[26] = SDL_CreateCursor(hand_closed_cursor_data, hand_closed_cursor_mask, 32, 32, HAND_CLOSED_CURSOR_HOTX, HAND_CLOSED_CURSOR_HOTY);
+ platform_set_cursor(CURSOR_ARROW);
+ RCT2_GLOBAL(0x14241BC, uint32) = 0;
+}
+
+/**
+ *
+ * rct2: 0x00407D80
+ */
+int platform_get_cursor_pos(int* x, int* y)
+{
+ POINT point;
+ GetCursorPos(&point);
+ *x = point.x;
+ *y = point.y;
+}
\ No newline at end of file
diff --git a/src/platform/windows.c b/src/platform/windows.c
index c258dbcc77..308b75e050 100644
--- a/src/platform/windows.c
+++ b/src/platform/windows.c
@@ -20,7 +20,9 @@
#ifdef _WIN32
+#include
#include
+#include
#include "../addresses.h"
#include "../cmdline.h"
#include "../openrct2.h"
@@ -70,7 +72,7 @@ __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInsta
// Get command line arguments in standard form
argv = CommandLineToArgvA(lpCmdLine, &argc);
runGame = cmdline_run(argv, argc);
- LocalFree(argv);
+ GlobalFree(argv);
if (runGame)
openrct2_launch();
@@ -190,6 +192,16 @@ void platform_enumerate_files_end(int handle)
enumFileInfo->active = 0;
}
+int platform_file_move(const char *srcPath, const char *dstPath)
+{
+ return MoveFileA(srcPath, dstPath);
+}
+
+int platform_file_delete(const char *path)
+{
+ return DeleteFileA(path);
+}
+
void platform_hide_cursor()
{
ShowCursor(FALSE);
@@ -223,6 +235,203 @@ unsigned int platform_get_ticks()
return GetTickCount();
}
+char* platform_get_orct2_homefolder()
+{
+ char *path = NULL;
+ path = malloc(sizeof(char) * MAX_PATH);
+ if (path == NULL){
+ log_fatal("Error allocating memory!");
+ exit(EXIT_FAILURE);
+ }
+
+ path[0] = '\0';
+
+ if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, path)))
+ strcat(path, "\\OpenRCT2");
+
+ return path;
+}
+
+void platform_show_messagebox(char *message)
+{
+ MessageBoxA(windows_get_window_handle(), message, "OpenRCT2", MB_OK);
+}
+
+/**
+ *
+ * rct2: 0x004080EA
+ */
+int platform_open_common_file_dialog(int type, char *title, char *filename, char *filterPattern, char *filterName)
+{
+ char initialDirectory[MAX_PATH], *dotAddress, *slashAddress;
+ OPENFILENAME openFileName;
+ BOOL result;
+ int tmp;
+ DWORD commonFlags;
+
+ // Get directory path from given filename
+ strcpy(initialDirectory, filename);
+ dotAddress = strrchr(initialDirectory, '.');
+ if (dotAddress != NULL) {
+ slashAddress = strrchr(initialDirectory, '\\');
+ if (slashAddress < dotAddress)
+ *(slashAddress + 1) = 0;
+ }
+
+ // Clear filename
+ if (type != 0)
+ *filename = 0;
+
+ // Set open file name options
+ memset(&openFileName, 0, sizeof(OPENFILENAME));
+ openFileName.lStructSize = sizeof(OPENFILENAME);
+ openFileName.hwndOwner = windows_get_window_handle();
+ openFileName.lpstrFile = filename;
+ openFileName.nMaxFile = MAX_PATH;
+ openFileName.lpstrInitialDir = initialDirectory;
+ openFileName.lpstrTitle = title;
+
+ // Copy filter name
+ strcpy((char*)0x01423800, filterName);
+
+ // Copy filter pattern
+ strcpy((char*)0x01423800 + strlen(filterName) + 1, filterPattern);
+ *((char*)(0x01423800 + strlen(filterName) + 1 + strlen(filterPattern) + 1)) = 0;
+ openFileName.lpstrFilter = (char*)0x01423800;
+
+ //
+ tmp = RCT2_GLOBAL(0x009E2C74, uint32);
+ if (RCT2_GLOBAL(0x009E2BB8, uint32) == 2 && RCT2_GLOBAL(0x009E1AF8, uint32) == 1)
+ RCT2_GLOBAL(0x009E2C74, uint32) = 1;
+
+ // Open dialog
+ commonFlags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
+ if (type == 0) {
+ openFileName.Flags = commonFlags | OFN_CREATEPROMPT | OFN_OVERWRITEPROMPT;
+ result = GetSaveFileName(&openFileName);
+ } else if (type == 1) {
+ openFileName.Flags = commonFlags | OFN_NONETWORKBUTTON | OFN_FILEMUSTEXIST;
+ result = GetOpenFileName(&openFileName);
+ }
+
+ //
+ RCT2_GLOBAL(0x009E2C74, uint32) = tmp;
+
+ return result;
+}
+
+char *platform_open_directory_browser(char *title)
+{
+ BROWSEINFO bi;
+ char pszBuffer[MAX_PATH];
+ LPITEMIDLIST pidl;
+ LPMALLOC lpMalloc;
+
+ // Initialize COM
+ if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED))) {
+ CoUninitialize();
+
+ log_error("Error opening directory browse window");
+ return 0;
+ }
+
+ // Get a pointer to the shell memory allocator
+ if (FAILED(SHGetMalloc(&lpMalloc))) {
+ CoUninitialize();
+
+ log_error("Error opening directory browse window");
+ return 0;
+ }
+
+ bi.hwndOwner = NULL;
+ bi.pidlRoot = NULL;
+ bi.pszDisplayName = pszBuffer;
+ bi.lpszTitle = title;
+ bi.ulFlags = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS;
+ bi.lpfn = NULL;
+ bi.lParam = 0;
+
+ char *outPath = NULL;
+
+ if (pidl = SHBrowseForFolder(&bi)) {
+ // Copy the path directory to the buffer
+ if (SHGetPathFromIDList(pidl, pszBuffer)) {
+ // Store pszBuffer (and the path) in the outPath
+ outPath = (char*) malloc(strlen(pszBuffer)+1);
+ strcpy(outPath, pszBuffer);
+ }
+ }
+ CoUninitialize();
+ return outPath;
+}
+
+/**
+ *
+ * rct2: 0x00407978
+ */
+int windows_get_registry_install_info(rct2_install_info *installInfo, char *source, char *font, uint8 charset)
+{
+ char subkeyInfogrames[MAX_PATH], subkeyFishTechGroup[MAX_PATH], keyName[100];
+ LOGFONTA lf;
+ HKEY hKey;
+ DWORD type, size;
+
+ strcpy(subkeyInfogrames, "Software\\Infogrames\\");
+ strcat(subkeyInfogrames, source);
+ strcpy(subkeyFishTechGroup, "Software\\Fish Technology Group\\");
+ strcat(subkeyFishTechGroup, source);
+
+ memset(&lf, 0, sizeof(lf));
+ lf.lfCharSet = charset;
+ lf.lfHeight = 12;
+ lf.lfWeight = 400;
+ strcpy(lf.lfFaceName, font);
+
+ RCT2_GLOBAL(RCT2_ADDRESS_HFONT, HFONT) = CreateFontIndirectA(&lf);
+
+ if (RegOpenKeyA(HKEY_LOCAL_MACHINE, subkeyInfogrames, &hKey) != ERROR_SUCCESS)
+ return 0;
+
+ if (RegOpenKeyA(HKEY_LOCAL_MACHINE, subkeyFishTechGroup, &hKey) != ERROR_SUCCESS)
+ return 0;
+
+
+ size = 260;
+ RegQueryValueExA(hKey, "Title", 0, &type, installInfo->title, &size);
+
+ size = 260;
+ RegQueryValueExA(hKey, "Path", 0, &type, installInfo->path, &size);
+
+ installInfo->var_20C = 235960;
+
+ size = 4;
+ RegQueryValueExA(hKey, "InstallLevel", 0, &type, (LPBYTE)&installInfo->installLevel, &size);
+ for (int i = 0; i <= 15; i++) {
+ sprintf(keyName, "AddonPack%d", i);
+ size = sizeof(installInfo->expansionPackNames[i]);
+ if (RegQueryValueExA(hKey, keyName, 0, &type, installInfo->expansionPackNames[i], &size) == ERROR_SUCCESS)
+ installInfo->activeExpansionPacks |= (1 << i);
+ }
+
+ RegCloseKey(hKey);
+ return 1;
+}
+
+HWND windows_get_window_handle()
+{
+ SDL_SysWMinfo wmInfo;
+
+ if (gWindow == NULL)
+ return NULL;
+
+ SDL_VERSION(&wmInfo.version);
+ if (SDL_GetWindowWMInfo(gWindow, &wmInfo) != SDL_TRUE) {
+ log_error("SDL_GetWindowWMInfo failed %s", SDL_GetError());
+ exit(-1);
+ }
+ return wmInfo.info.win.window;
+}
+
/**
* http://alter.org.ua/en/docs/win/args/
*/
@@ -243,11 +452,13 @@ PCHAR *CommandLineToArgvA(PCHAR CmdLine, int *_argc)
i = ((len + 2) / 2)*sizeof(PVOID) + sizeof(PVOID);
argv = (PCHAR*)GlobalAlloc(GMEM_FIXED,
- i + (len + 2)*sizeof(CHAR));
+ i + (len + 2)*sizeof(CHAR) + 1);
_argv = (PCHAR)(((PUCHAR)argv) + i);
- argc = 0;
+ // Add in virtual 1st command line argument, process path, for arg_parse's sake.
+ argv[0] = 0;
+ argc = 1;
argv[argc] = _argv;
in_QM = FALSE;
in_TEXT = FALSE;
diff --git a/src/rct1.h b/src/rct1.h
new file mode 100644
index 0000000000..466e5fc184
--- /dev/null
+++ b/src/rct1.h
@@ -0,0 +1,347 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#ifndef _RCT1_H_
+#define _RCT1_H_
+
+#include "management/award.h"
+#include "management/news_item.h"
+#include "management/research.h"
+#include "rct2.h"
+#include "ride/ride.h"
+#include "world/banner.h"
+#include "world/map.h"
+#include "world/sprite.h"
+
+typedef struct {
+ uint16 x;
+ uint16 y;
+ uint16 z;
+ uint8 direction;
+} rct1_entrance;
+
+/**
+ * RCT1,AA,LL scenario / saved game structure.
+ * size: 0x1F850C
+ */
+typedef struct {
+ uint16 month;
+ uint16 day;
+ uint32 ticks;
+ uint32 random_a;
+ uint32 random_b;
+ rct_map_element map_elements[0xC000];
+ uint32 unk_counter;
+ rct_sprite sprites[5000];
+ uint16 next_sprite_index;
+ uint16 first_vehicle_sprite_index;
+ uint16 first_peep_sprite_index;
+ uint16 first_duck_sprite_index;
+ uint16 first_litter_sprite_index;
+ uint16 first_oversized_ride_car_sprite_index;
+ uint16 sprites_available;
+ uint16 num_vehicle_sprites;
+ uint16 num_peep_sprites;
+ uint16 num_duck_sprites;
+ uint16 num_litter_sprites;
+ uint16 num_oversized_ride_car_sprites;
+ uint32 park_name_string_index;
+ uint32 unk_198830;
+ money32 cash;
+ money32 loan;
+ uint32 park_flags;
+ money16 park_entrance_fee;
+ rct1_entrance park_entrance;
+ uint8 unk_198849;
+ rct2_peep_spawn peep_spawn[2];
+ uint8 unk_198856;
+ uint8 research_level;
+ uint32 unk_198858;
+ uint8 available_rides[32];
+ uint8 available_vehicles[32];
+ uint32 ride_feature_1[128];
+ uint32 ride_feature_2[128];
+ uint16 guests_in_park;
+ uint16 unk_198C9E;
+ money32 expenditure[14 * 16];
+ uint32 guests_in_park_2;
+ uint8 unk_199024;
+ uint8 handman_colour;
+ uint8 mechanic_colour;
+ uint8 security_guard_colour;
+ uint8 available_scenery[128];
+ uint16 available_banners;
+ uint8 unk_1990AA[94];
+ uint16 park_rating;
+ uint8 park_rating_history[32];
+ uint8 guests_in_park_history[32];
+ uint8 research_priority;
+ uint8 research_progress;
+ uint8 last_research_item;
+ uint8 last_research_ride;
+ uint8 last_research_category;
+ uint8 last_research_flag;
+ rct_research_item research_items[200];
+ uint8 next_research_item;
+ uint8 next_research_ride;
+ uint8 next_research_category;
+ uint8 next_research_flag;
+ uint16 unk_19953C;
+ uint32 unk_19953E;
+ uint16 cheat_detection_land_owned;
+ uint16 unk_199544;
+ money16 median_recommended_park_entry_fee;
+ money32 max_loan;
+ money16 guest_initial_cash;
+ uint8 guest_initial_hunger;
+ uint8 guest_initial_thirst;
+ uint8 scenario_objective_type;
+ uint8 scenario_objective_years;
+ uint16 unk_199552;
+ money32 scenario_objective_currency;
+ uint16 scenario_objective_num_guests;
+ uint8 marketing_status[20];
+ uint8 marketing_assoc[20];
+ uint8 unk_199582[2];
+ money32 cash_history[128];
+ money32 total_expenditure;
+ money32 profit;
+ uint8 unk_199788[8];
+ money32 weekly_profit_history[128];
+ money32 park_value;
+ money32 park_value_history[128];
+ uint32 scenario_objective_score;
+ uint32 num_admissions;
+ money32 admission_total_income;
+ money32 company_value;
+ uint8 thought_timer[16];
+ rct_award awards[4];
+ money16 land_price;
+ money16 construction_rights_price;
+ uint16 unk_199BCC;
+ uint16 unk_199BCE;
+ uint32 unk_199BD0;
+ char username[64];
+ uint32 game_version;
+ money32 objective_completion_company_value;
+ uint32 finance_checksum;
+ uint16 num_rides;
+ uint16 cheat_detection_neg_num_rides;
+ uint16 cheat_detection_max_owned_tiles;
+ uint16 cheat_detection_neg_max_owned_tiles;
+ uint32 finance_checksum_3;
+ uint32 scenario_slot_index_checksum;
+ char scenario_winner[32];
+ uint32 finance_checksum_2;
+ char copyright_notice[40];
+ uint16 cheat_detection_sv6_sc4[4];
+ uint16 unk_199C84;
+ uint16 unk_199C86;
+ uint16 map_size_unk_a;
+ uint16 map_size_unk_b;
+ uint16 map_size;
+ uint16 map_size_unk_c;
+ uint32 same_price_flags;
+ uint16 unk_199C94;
+ uint8 unk_199C96[3];
+ uint8 water_colour;
+ uint16 unk_199C9A;
+ rct_research_item research_items_LL[180];
+ uint8 unk_19A020[5468];
+ rct_banner banners[100];
+ char string_table[32][1024];
+ uint32 game_time_counter;
+ rct_ride rides[255];
+ uint16 unk_game_time_counter;
+ uint16 view_x;
+ uint16 view_y;
+ uint8 view_zoom;
+ uint8 view_rotation;
+ uint8 animated_objects[6000];
+ uint32 num_animated_objects;
+ uint8 unk_1CADBC[12];
+ uint16 scrolling_text_step;
+ uint32 unk_1CADCA;
+ uint16 unk_1CADCE;
+ uint8 unk_1CADD0[116];
+ rct_ride_measurement ride_measurements[8];
+ uint32 next_guest_index;
+ uint16 game_counter_5;
+ uint8 patrol_areas[0x3C00];
+ uint8 unk_1F42AA[116];
+ uint8 unk_1F431E[4];
+ uint8 unk_1F4322[8];
+ uint8 climate;
+ uint8 unk_1F432B;
+ uint16 climate_timer;
+ uint8 weather;
+ uint8 target_weather;
+ uint8 temperature;
+ uint8 target_temperature;
+ uint8 thunder_frequency;
+ uint8 target_thunder_frequency;
+ uint8 weather_gloom;
+ uint8 target_weather_gloom;
+ uint8 rain;
+ uint8 target_rain;
+ rct_news_item messages[61];
+ char scenario_name[62];
+ uint16 scenario_slot_index;
+ uint32 scenario_flags;
+ uint8 unk_1F8358[432];
+ uint32 expansion_pack_checksum;
+} rct1_s4;
+
+enum {
+ RCT1_RIDE_TYPE_NULL = 255,
+ RCT1_RIDE_TYPE_WOODEN_ROLLER_COASTER = 0,
+ RCT1_RIDE_TYPE_STAND_UP_STEEL_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_SUSPENDED_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_INVERTED_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_STEEL_MINI_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_MINIATURE_RAILROAD,
+ RCT1_RIDE_TYPE_MONORAIL,
+ RCT1_RIDE_TYPE_SUSPENDED_SINGLE_RAIL_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_BOAT_HIRE,
+ RCT1_RIDE_TYPE_WOODEN_CRAZY_RODENT_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_SINGLE_RAIL_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_CAR_RIDE,
+ RCT1_RIDE_TYPE_WHOA_BELLY,
+ RCT1_RIDE_TYPE_BOBSLED_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_OBSERVATION_TOWER,
+ RCT1_RIDE_TYPE_STEEL_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_WATER_SLIDE,
+ RCT1_RIDE_TYPE_MINE_TRAIN_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_CHAIRLIFT,
+ RCT1_RIDE_TYPE_STEEL_CORKSCREW_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_HEDGE_MAZE,
+ RCT1_RIDE_TYPE_SPIRAL_SLIDE,
+ RCT1_RIDE_TYPE_GO_KARTS,
+ RCT1_RIDE_TYPE_LOG_FLUME,
+ RCT1_RIDE_TYPE_RIVER_RAPIDS,
+ RCT1_RIDE_TYPE_BUMPER_CARS,
+ RCT1_RIDE_TYPE_SWINGING_SHIP,
+ RCT1_RIDE_TYPE_SWINGING_INVERTER_SHIP,
+ RCT1_RIDE_TYPE_ICE_CREAM_STALL,
+ RCT1_RIDE_TYPE_FRIES_STALL,
+ RCT1_RIDE_TYPE_DRINK_STALL,
+ RCT1_RIDE_TYPE_COTTON_CANDY_STALL,
+ RCT1_RIDE_TYPE_BURGER_BAR,
+ RCT1_RIDE_TYPE_MERRY_GO_ROUND,
+ RCT1_RIDE_TYPE_BALLOON_STALL,
+ RCT1_RIDE_TYPE_INFORMATION_KIOSK,
+ RCT1_RIDE_TYPE_BATHROOM,
+ RCT1_RIDE_TYPE_FERRIS_WHEEL,
+ RCT1_RIDE_TYPE_MOTION_SIMULATOR,
+ RCT1_RIDE_TYPE_3D_CINEMA,
+ RCT1_RIDE_TYPE_GRAVITRON,
+ RCT1_RIDE_TYPE_SPACE_RINGS,
+ RCT1_RIDE_TYPE_REVERSE_WHOA_BELLY_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_SOUVENIR_STALL,
+ RCT1_RIDE_TYPE_VERTICAL_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_PIZZA_STALL,
+ RCT1_RIDE_TYPE_SCRAMBLED_EGGS,
+ RCT1_RIDE_TYPE_HAUNTED_HOUSE,
+ RCT1_RIDE_TYPE_POPCORN_STALL,
+ RCT1_RIDE_TYPE_CIRCUS_SHOW,
+ RCT1_RIDE_TYPE_GHOST_TRAIN,
+ RCT1_RIDE_TYPE_STEEL_TWISTER_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_WOODEN_TWISTER_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_WOODEN_SIDE_FRICTION_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_STEEL_WILD_MOUSE_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_HOT_DOG_STALL,
+ RCT1_RIDE_TYPE_EXOTIC_SEA_FOOD_STALL,
+ RCT1_RIDE_TYPE_HAT_STALL,
+ RCT1_RIDE_TYPE_CANDY_APPLE_STAND,
+ RCT1_RIDE_TYPE_VIRGINIA_REEL,
+ RCT1_RIDE_TYPE_RIVER_RIDE,
+ RCT1_RIDE_TYPE_CYCLE_MONORAIL,
+ RCT1_RIDE_TYPE_FLYING_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_SUSPENDED_MONORAIL,
+ RCT1_RIDE_TYPE_40,
+ RCT1_RIDE_TYPE_WOODEN_REVERSER_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_HEARTLINE_TWISTER_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_MINIATURE_GOLF,
+ RCT1_RIDE_TYPE_44,
+ RCT1_RIDE_TYPE_ROTO_DROP,
+ RCT1_RIDE_TYPE_FLYING_SAUCERS,
+ RCT1_RIDE_TYPE_CROOKED_HOUSE,
+ RCT1_RIDE_TYPE_CYCLE_RAILWAY,
+ RCT1_RIDE_TYPE_SUSPENDED_LOOPING_ROLLER_COASTER,
+ RCT1_RIDE_TYPE_WATER_COASTER,
+ RCT1_RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER,
+ RCT1_RIDE_TYPE_INVERTED_WILD_MOUSE_COASTER,
+ RCT1_RIDE_TYPE_JET_SKIS,
+ RCT1_RIDE_TYPE_T_SHIRT_STALL,
+ RCT1_RIDE_TYPE_RAFT_RIDE,
+ RCT1_RIDE_TYPE_DOUGHNUT_SHOP,
+ RCT1_RIDE_TYPE_ENTERPRISE,
+ RCT1_RIDE_TYPE_COFFEE_SHOP,
+ RCT1_RIDE_TYPE_FRIED_CHICKEN_STALL,
+ RCT1_RIDE_TYPE_LEMONADE_STALL
+};
+
+typedef struct{
+ uint8 type; // 0x00
+ uint8 vehicle_type; // 0x01
+ uint32 special_track_flags; // 0x02
+ uint8 operating_mode; // 0x06
+ uint8 vehicle_colour_version; // 0x07 Vehicle colour type in first two bits, Version in bits 3,4
+ uint8 body_trim_colour[24]; // 0x08
+ uint8 track_spine_colour_rct1; // 0x20
+ uint8 track_rail_colour_rct1; // 0x21
+ uint8 track_support_colour_rct1; // 0x22
+ uint8 departure_control_flags; // 0x23
+ uint8 number_of_trains; // 0x24
+ uint8 cars_per_train; // 0x25
+ uint8 min_wait_time; // 0x26
+ uint8 max_wait_time; // 0x27
+ uint8 speed; // 0x28
+ uint8 max_speed; // 0x29
+ uint8 average_speed; // 0x2A
+ uint16 ride_length; // 0x2B
+ uint8 max_positive_vertical_g; // 0x2D
+ uint8 max_negitive_vertical_g; // 0x2E
+ uint8 max_lateral_g; // 0x2F
+ union {
+ uint8 inversions; // 0x30
+ uint8 holes; // 0x30
+ };
+ uint8 drops; // 0x31
+ uint8 highest_drop_height; // 0x32
+ uint8 excitement; // 0x33
+ uint8 intensity; // 0x34
+ uint8 nausea; // 0x35
+ uint8 pad_36[2];
+ union{
+ uint16 start_track_data_original; // 0x38
+ uint8 track_spine_colour[4]; // 0x38
+ };
+ uint8 track_rail_colour[4]; // 0x3C
+ union{
+ uint8 track_support_colour[4]; // 0x40
+ uint8 wall_type[4]; // 0x40
+ };
+ uint8 pad_41[0x83];
+ uint16 start_track_data_AA_CF; // 0xC4
+}rct_track_td4; // Information based off RCTTechDepot
+
+#endif
+
\ No newline at end of file
diff --git a/src/rct2.c b/src/rct2.c
index 916bceb320..db2247fc84 100644
--- a/src/rct2.c
+++ b/src/rct2.c
@@ -35,7 +35,6 @@
#include "management/news_item.h"
#include "object.h"
#include "openrct2.h"
-#include "platform/osinterface.h"
#include "platform/platform.h"
#include "ride/ride.h"
#include "ride/track.h"
@@ -93,7 +92,7 @@ int rct2_init()
gfx_load_g1();
gfx_load_character_widths();
- osinterface_init();
+ platform_init();
audio_init1();//RCT2_CALLPROC_EBPSAFE(0x006BA8E0); // init_audio();
viewport_init_all();
news_item_init_queue();
@@ -104,7 +103,7 @@ int rct2_init()
ride_init_all();
window_guest_list_init_vars_a();
sub_6BD3A4();// RCT2_CALLPROC_EBPSAFE(0x006BD3A4); //Peep?
- map_init();
+ map_init(150);
park_init();
RCT2_CALLPROC_EBPSAFE(0x0066B5C0); // 0x0066B5C0 (part of 0x0066B3E8) screen_game_create_windows()
date_reset();
@@ -119,6 +118,7 @@ int rct2_init()
gfx_clear(RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo), 10);
RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) = gGeneral_config.play_intro ? 8 : 255;
+ log_verbose("initialising game finished");
return 1;
}
@@ -128,13 +128,15 @@ int rct2_init()
*/
int rct2_init_directories()
{
+ // windows_get_registry_install_info((rct2_install_info*)0x009AA10C, "RollerCoaster Tycoon 2 Setup", "MS Sans Serif", 0);
+
// check install directory
if (!platform_directory_exists(gGeneral_config.game_path)) {
log_verbose("install directory does not exist, %s", gGeneral_config.game_path);
if (!config_find_or_browse_install_directory()) {
log_fatal("Invalid RCT2 installation path. Please correct in config.ini.");
return 0;
- }
+ }
}
strcpy(RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH, char), gGeneral_config.game_path);
@@ -222,7 +224,10 @@ int rct2_open_file(const char *path)
strcpy(scenarioBasic.path, path);
scenario_load_and_play_from_path(scenarioBasic.path);
} else if (_stricmp(extension, "td6") == 0 || _stricmp(extension, "td4") == 0) {
+ return 1;
+ } else if (!_stricmp(extension, "td6") || !_stricmp(extension, "td4")) {
// TODO track design install
+ return 1;
}
return 0;
@@ -233,10 +238,10 @@ int rct2_open_file(const char *path)
* rct2: 0x00674C95
*/
int check_file_paths()
-{
+ {
for (int pathId = 0; pathId < PATH_ID_END; pathId++)
if (!check_file_path(pathId))
- return 0;
+ return 0;
return 1;
}
@@ -251,24 +256,7 @@ int check_file_path(int pathId)
HANDLE file = CreateFile(path, FILE_GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
switch (pathId) {
- case PATH_ID_GAMECFG:
- case PATH_ID_SCORES:
- case PATH_ID_TRACKSIDX:
- case PATH_ID_PLUGIN:
- // Do nothing; these will be created later if they do not exist yet
- break;
-
- case PATH_ID_CUSTOM1:
- if (file != INVALID_HANDLE_VALUE)
- RCT2_GLOBAL(0x009AF164, unsigned int) = SetFilePointer(file, 0, 0, FILE_END); // Store file size in music_custom1_size @ 0x009AF164
- break;
-
- case PATH_ID_CUSTOM2:
- if (file != INVALID_HANDLE_VALUE)
- RCT2_GLOBAL(0x009AF16E, unsigned int) = SetFilePointer(file, 0, 0, FILE_END); // Store file size in music_custom2_size @ 0x009AF16E
- break;
-
- default:
+ case PATH_ID_G1:
if (file == INVALID_HANDLE_VALUE) {
// A data file is missing from the installation directory. The original implementation
// asks for a CD-ROM path at this point and stores it in cdrom_path @ 0x9AA318.
@@ -281,6 +269,16 @@ int check_file_path(int pathId)
return 0;
}
break;
+
+ case PATH_ID_CUSTOM1:
+ if (file != INVALID_HANDLE_VALUE)
+ RCT2_GLOBAL(0x009AF164, unsigned int) = SetFilePointer(file, 0, 0, FILE_END); // Store file size in music_custom1_size @ 0x009AF164
+ break;
+
+ case PATH_ID_CUSTOM2:
+ if (file != INVALID_HANDLE_VALUE)
+ RCT2_GLOBAL(0x009AF16E, unsigned int) = SetFilePointer(file, 0, 0, FILE_END); // Store file size in music_custom2_size @ 0x009AF16E
+ break;
}
if (file != INVALID_HANDLE_VALUE)
@@ -294,11 +292,11 @@ int check_file_path(int pathId)
* rct2: 0x00674C0B
*/
int check_files_integrity()
-{
+ {
int i;
const char *path;
HANDLE file;
- WIN32_FIND_DATA find_data;
+ WIN32_FIND_DATA find_data;
for (i = 0; files_to_check[i].pathId != PATH_ID_END; i++) {
path = get_file_path(files_to_check[i].pathId);
@@ -324,16 +322,12 @@ void rct2_update_2()
tick = timeGetTime();
- RCT2_GLOBAL(0x009DE588, sint16) = tick2 = tick - RCT2_GLOBAL(0x009DE580, sint32);
- if (RCT2_GLOBAL(0x009DE588, sint16) > 500)
- RCT2_GLOBAL(0x009DE588, sint16) = 500;
+ tick2 = tick - RCT2_GLOBAL(0x009DE580, sint32);
+ RCT2_GLOBAL(0x009DE588, sint16) = tick2 = min(tick2, 500);
RCT2_GLOBAL(0x009DE580, sint32) = tick;
- if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0)
- RCT2_GLOBAL(0x009DE584, sint32) += tick2;
-
- if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0)
- RCT2_GLOBAL(0x009DE584, sint32) += tick2;
+ if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0)
+ RCT2_GLOBAL(RCT2_ADDRESS_PALETTE_EFFECT_FRAME_NO, sint32) += tick2;
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 0)
RCT2_GLOBAL(0x009DE588, sint16) = 31;
@@ -513,4 +507,4 @@ void *rct2_realloc(void *block, size_t numBytes)
void rct2_free(void *block)
{
RCT2_CALLPROC_1(0x004068DE, void*, block);
-}
\ No newline at end of file
+}
diff --git a/src/rct2.h b/src/rct2.h
index 85ff1868c2..0b035a6aea 100644
--- a/src/rct2.h
+++ b/src/rct2.h
@@ -43,6 +43,11 @@ typedef unsigned short uint16;
typedef unsigned long uint32;
typedef unsigned long long uint64;
+typedef char utf8;
+typedef wchar_t utf16;
+typedef utf8* utf8string;
+typedef utf16* utf16string;
+
#define rol8(x, shift) (((uint8)(x) << (shift)) | ((uint8)(x) >> (8 - (shift))))
#define ror8(x, shift) (((uint8)(x) >> (shift)) | ((uint8)(x) << (8 - (shift))))
#define rol16(x, shift) (((uint16)(x) << (shift)) | ((uint16)(x) >> (16 - (shift))))
@@ -98,11 +103,22 @@ typedef fixed32_1dp money32;
// Construct a money value in the format MONEY(10,70) to represent 10.70. Fractional part must be two digits.
#define MONEY(whole, fraction) ((whole) * 10 + ((fraction) / 10))
+#define MONEY_FREE MONEY(0,00)
#define MONEY32_UNDEFINED ((money32)0x80000000)
typedef void (EMPTY_ARGS_VOID_POINTER)();
typedef unsigned short rct_string_id;
+typedef struct {
+ uint32 installLevel;
+ char title[260];
+ char path[260];
+ uint32 var_20C;
+ uint8 pad_210[256];
+ char expansionPackNames[16][128];
+ uint32 activeExpansionPacks; //0xB10
+} rct2_install_info;
+
enum {
// Although this is labeled a flag it actually means when
// zero the screen is in playing mode.
@@ -178,6 +194,7 @@ enum {
PATH_ID_CSS44,
PATH_ID_CSS45,
PATH_ID_CSS46,
+ PATH_ID_CSS50,
PATH_ID_END
};
@@ -245,7 +262,8 @@ static const char * const file_paths[] =
"Data\\CSS43.DAT",
"Data\\CSS44.DAT",
"Data\\CSS45.DAT",
- "Data\\CSS46.DAT"
+ "Data\\CSS46.DAT",
+ "Data\\CSS50.DAT"
};
// Files to check (rct2 @ 0x0097FB5A)
diff --git a/src/ride/ride.c b/src/ride/ride.c
index 10ea7cb8b1..3c14be80e8 100644
--- a/src/ride/ride.c
+++ b/src/ride/ride.c
@@ -26,10 +26,10 @@
#include "../interface/window.h"
#include "../localisation/date.h"
#include "../localisation/localisation.h"
+#include "../management/finance.h"
#include "../management/news_item.h"
#include "../peep/peep.h"
#include "../peep/staff.h"
-#include "../platform/osinterface.h"
#include "../scenario.h"
#include "../util/util.h"
#include "../windows/error.h"
@@ -247,6 +247,7 @@ money32 ride_calculate_income_per_hour(rct_ride *ride)
shopItem = entry->shop_item_secondary;
if (shopItem != 255) {
+ priceMinusCost += ride->price_secondary;
priceMinusCost -= get_shop_item_cost(shopItem);
priceMinusCost /= 2;
}
@@ -266,47 +267,42 @@ money32 ride_calculate_income_per_hour(rct_ride *ride)
*/
rct_map_element *sub_6CAF80(int rideIndex, int *outX, int *outY)
{
- rct_map_element *resultMapElement, *mapElement;
+ map_element_iterator it;
+ rct_map_element *resultMapElement;
int foundSpecialTrackPiece;
resultMapElement = (rct_map_element*)-1;
foundSpecialTrackPiece = 0;
- uint16 x, y;
- for (x = 0; x < 256; x++) {
- for (y = 0; y < 256; y++) {
- // Iterate through map elements on tile
- int tileIndex = (y << 8) | x;
- mapElement = TILE_MAP_ELEMENT_POINTER(tileIndex);
- do {
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_TRACK)
- continue;
- if (rideIndex != mapElement->properties.track.ride_index)
- continue;
+ map_element_iterator_begin(&it);
+ do {
+ if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_TRACK)
+ continue;
+ if (rideIndex != it.element->properties.track.ride_index)
+ continue;
- // Found a track piece for target ride
+ // Found a track piece for target ride
- // Check if its a ???
- int specialTrackPiece = (
- (mapElement->properties.track.type != 2 && mapElement->properties.track.type != 3) &&
- (RCT2_ADDRESS(0x0099BA64, uint8)[mapElement->properties.track.type * 16] & 0x10)
- );
+ // Check if its a ???
+ int specialTrackPiece = (
+ (it.element->properties.track.type != 2 && it.element->properties.track.type != 3) &&
+ (RCT2_ADDRESS(0x0099BA64, uint8)[it.element->properties.track.type * 16] & 0x10)
+ );
- // Set result tile to this track piece if first found track or a ???
- if (resultMapElement == (rct_map_element*)-1 || specialTrackPiece) {
- resultMapElement = mapElement;
+ // Set result tile to this track piece if first found track or a ???
+ if (resultMapElement == (rct_map_element*)-1 || specialTrackPiece) {
+ resultMapElement = it.element;
- if (outX != NULL) *outX = x * 32;
- if (outY != NULL) *outY = y * 32;
- }
-
- if (specialTrackPiece) {
- foundSpecialTrackPiece = 1;
- return resultMapElement;
- }
- } while (!(mapElement->flags & MAP_ELEMENT_FLAG_LAST_TILE) && mapElement++);
+ if (outX != NULL) *outX = it.x * 32;
+ if (outY != NULL) *outY = it.y * 32;
}
- }
+
+ if (specialTrackPiece) {
+ foundSpecialTrackPiece = 1;
+ return resultMapElement;
+ }
+ } while (map_element_iterator_next(&it));
+
return resultMapElement;
}
@@ -511,12 +507,20 @@ int ride_create_ride(ride_list_item listItem)
*/
void ride_construct_new(ride_list_item listItem)
{
- rct_window *w;
int rideIndex;
rideIndex = ride_create_ride(listItem);
- if (rideIndex == -1)
- return;
+ if (rideIndex != -1)
+ ride_construct(rideIndex);
+}
+
+/**
+ *
+ * rct2: 0x006B4857
+ */
+void ride_construct(int rideIndex)
+{
+ rct_window *w;
// Open construction window
// HACK In the original game this created a mouse up event. This has been
@@ -669,7 +673,7 @@ static void ride_remove_peeps(int rideIndex)
continue;
peep_decrement_num_riders(peep);
- if (peep->state == PEEP_STATE_QUEUING_FRONT && peep->var_2C == 0)
+ if (peep->state == PEEP_STATE_QUEUING_FRONT && peep->sub_state == 0)
RCT2_CALLPROC_X(0x006966A9, 0, 0, 0, 0, (int)peep, 0, 0);
invalidate_sprite((rct_sprite*)peep);
@@ -677,11 +681,11 @@ static void ride_remove_peeps(int rideIndex)
if (exitDirection == 255) {
x = peep->next_x + 16;
y = peep->next_y + 16;
- z = (peep->next_z & 0xFF) * 8;
- if ((peep->next_z >> 8) & 4)
+ z = peep->next_z * 8;
+ if (peep->next_var_29 & 4)
z += 8;
z++;
- sprite_move(exitX, exitY, exitZ, (rct_sprite*)peep);
+ sprite_move(x, y, z, (rct_sprite*)peep);
} else {
sprite_move(exitX, exitY, exitZ, (rct_sprite*)peep);
peep->sprite_direction = exitDirection;
@@ -723,7 +727,7 @@ void sub_6C9627()
&x,
&y,
RCT2_GLOBAL(0x00F440AC, uint16),
- RCT2_GLOBAL(0x00F440AE, uint8) & 3,
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) & 3,
RCT2_GLOBAL(0x00F440AF, uint8),
0,
0,
@@ -881,7 +885,7 @@ int ride_modify(rct_map_element *mapElement, int x, int y)
ride_remove_peeps(rideIndex);
// Check if element is a station entrance or exit
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE)
+ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE)
return ride_modify_entrance_or_exit(mapElement, x, y);
constructionWindow = ride_create_or_find_construction_window(rideIndex);
@@ -905,7 +909,7 @@ int ride_modify(rct_map_element *mapElement, int x, int y)
RCT2_GLOBAL(0x00F440A8, uint16) = x;
RCT2_GLOBAL(0x00F440AA, uint16) = y;
RCT2_GLOBAL(0x00F440AC, uint16) = z;
- RCT2_GLOBAL(0x00F440AE, uint8) = direction;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = direction;
RCT2_GLOBAL(0x00F440AF, uint8) = type;
RCT2_GLOBAL(0x00F440B0, uint8) = 0;
RCT2_GLOBAL(0x00F440B1, uint8) = 0;
@@ -925,7 +929,7 @@ int ride_modify(rct_map_element *mapElement, int x, int y)
RCT2_GLOBAL(0x00F440A8, uint16) = x;
RCT2_GLOBAL(0x00F440AA, uint16) = y;
RCT2_GLOBAL(0x00F440AC, uint16) = z;
- RCT2_GLOBAL(0x00F440AE, uint8) = direction;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = direction;
RCT2_GLOBAL(0x00F440AF, uint8) = type;
RCT2_GLOBAL(0x00F440B0, uint8) = 0;
RCT2_GLOBAL(0x00F440B1, uint8) = 0;
@@ -937,7 +941,7 @@ int ride_modify(rct_map_element *mapElement, int x, int y)
RCT2_GLOBAL(0x00F440A8, uint16) = x;
RCT2_GLOBAL(0x00F440AA, uint16) = y;
RCT2_GLOBAL(0x00F440AC, uint16) = z;
- RCT2_GLOBAL(0x00F440AE, uint8) = direction;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = direction;
RCT2_GLOBAL(0x00F440AF, uint8) = type;
RCT2_GLOBAL(0x00F440B0, uint8) = 0;
RCT2_GLOBAL(0x00F440B1, uint8) = 0;
@@ -988,7 +992,7 @@ int sub_6CC3FB(int rideIndex)
RCT2_GLOBAL(0x00F440B6, uint8) = 0;
RCT2_GLOBAL(0x00F440B7, uint8) = 0;
- RCT2_GLOBAL(0x00F440AE, uint8) = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = 0;
RCT2_GLOBAL(0x00F440A6, uint8) = 4;
RCT2_GLOBAL(0x00F440B0, uint8) = 0;
RCT2_GLOBAL(0x00F440B1, uint8) = 0;
@@ -1072,7 +1076,7 @@ static void ride_update(int rideIndex)
ride->var_14D |= 2;
if (ride->upkeep_cost != (money16)0xFFFF)
- ride->profit = (money16)(ride->income_per_hour - ((money32)ride->upkeep_cost * 16));
+ ride->profit = (ride->income_per_hour - ((money32)ride->upkeep_cost * 16));
}
// Ride specific updates
@@ -1124,6 +1128,23 @@ static void ride_chairlift_update(rct_ride *ride)
map_invalidate_tile(x, y, z, z + (4 * 8));
}
+/* rct2: 0x0069A3D7
+ * Updates the ride popularity
+ * edi : ride
+ * bl : pop_amount
+ * pop_amount can be zero if peep visited but did not purchase.
+ */
+void ride_update_popularity(rct_ride* ride, uint8 pop_amount){
+ ride->popularity_next += pop_amount;
+ ride->popularity_time_out++;
+ if (ride->popularity_time_out < 25)return;
+
+ ride->popularity = ride->popularity_next;
+ ride->popularity_next = 0;
+ ride->popularity_time_out = 0;
+ ride->var_14D |= 1;
+}
+
/**
*
* rct2: 0x006AC545
@@ -1548,7 +1569,7 @@ static void ride_call_mechanic(int rideIndex, rct_peep *mechanic, int forInspect
peep_decrement_num_riders(mechanic);
mechanic->state = forInspection ? PEEP_STATE_HEADING_TO_INSPECTION : PEEP_STATE_ANSWERING;
peep_window_state_update(mechanic);
- mechanic->var_2C = 0;
+ mechanic->sub_state = 0;
ride->mechanic_status = RIDE_MECHANIC_STATUS_HEADING;
ride->var_14D |= 0x20;
ride->mechanic = mechanic->sprite_index;
@@ -1625,13 +1646,13 @@ rct_peep *find_closest_mechanic(int x, int y, int forInspection)
continue;
if (forInspection) {
- if ((peep->state != PEEP_STATE_HEADING_TO_INSPECTION || peep->var_2C >= 4) && peep->state != PEEP_STATE_PATROLLING)
+ if ((peep->state != PEEP_STATE_HEADING_TO_INSPECTION || peep->sub_state >= 4) && peep->state != PEEP_STATE_PATROLLING)
continue;
if (!(peep->staff_orders & 2))
continue;
} else {
- if (peep->state != PEEP_STATE_PATROLLING && !(peep->staff_orders & 1))
+ if (peep->state != PEEP_STATE_PATROLLING || !(peep->staff_orders & 1))
continue;
}
@@ -2031,29 +2052,35 @@ void ride_check_all_reachable()
* rct2: 0x006B7C59
* @return 1 if the coordinate is reachable or has no entrance, 0 otherwise
*/
-static int ride_entrance_exit_is_reachable(uint16 coordinate, rct_ride* ride, int index) {
- int x = ((coordinate >> 8) & 0xFF) << 5, // cx
- y = (coordinate & 0xFF) << 5; // ax
- uint8 station_height = ride->station_heights[index];
- int tile_idx = ((x << 8) | y) >> 5;
- rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx];
+static int ride_entrance_exit_is_reachable(uint16 coordinate, rct_ride* ride, int index)
+{
+ int x, y, z;
+ rct_map_element *mapElement;
- while(1) {
- uint8 element_type = tile->type & MAP_ELEMENT_TYPE_MASK;
- if (element_type == MAP_ELEMENT_TYPE_ENTRANCE && station_height == tile->base_height) {
- break;
- } else if (tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) {
- return 1;
- }
- tile++;
+ x = coordinate & 0xFF;
+ y = (coordinate >> 8) & 0xFF;
+ z = ride->station_heights[index];
+ mapElement = map_get_first_element_at(x, y);
+
+ for (;;) {
+ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE && z == mapElement->base_height) {
+ break;
+ } else if (map_element_is_last_for_tile(mapElement)) {
+ return 1;
+ }
+ mapElement++;
}
- uint8 face_direction = tile->type & 3;
- y -= RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2];
- x -= RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2];
- tile_idx = ((x << 8) | y) >> 5;
+ uint8 face_direction = mapElement->type & 3;
- return map_coord_is_connected(tile_idx, station_height, face_direction);
+ x *= 32;
+ y *= 32;
+ x -= RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2];
+ y -= RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2];
+ x /= 32;
+ y /= 32;
+
+ return map_coord_is_connected(x, y, z, face_direction);
}
static void ride_entrance_exit_connected(rct_ride* ride, int ride_idx)
@@ -2086,64 +2113,66 @@ static void ride_entrance_exit_connected(rct_ride* ride, int ride_idx)
static void ride_shop_connected(rct_ride* ride, int ride_idx)
{
- rct_ride* ride_back = ride;
+ int x, y, count;
+ rct_map_element *mapElement;
+
uint16 coordinate = ride->station_starts[0];
if (coordinate == 0xFFFF)
return;
- int x = ((coordinate >> 8) & 0xFF) << 5, // cx
- y = (coordinate & 0xFF) << 5; // ax
+ x = (coordinate & 0xFF);
+ y = (coordinate >> 8) & 0xFF;
- rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[coordinate];
-
- for (; ; tile++){
- uint8 element_type = tile->type & MAP_ELEMENT_TYPE_MASK;
- if(element_type == MAP_ELEMENT_TYPE_TRACK && tile->properties.track.ride_index == ride_idx)
- break;
- if(tile->flags & MAP_ELEMENT_FLAG_LAST_TILE)
- return;
- }
+ mapElement = map_get_first_element_at(x, y);
+ do {
+ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK && mapElement->properties.track.ride_index == ride_idx)
+ break;
+ } while (!map_element_is_last_for_tile(mapElement++));
uint16 entrance_directions = 0;
- uint8 track_type = tile->properties.track.type;
- ride = &g_ride_list[tile->properties.track.ride_index];
- if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x80000) {
+ uint8 track_type = mapElement->properties.track.type;
+ ride = &g_ride_list[mapElement->properties.track.ride_index];
+ if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x80000) {
entrance_directions = RCT2_ADDRESS(0x0099CA64, uint8)[track_type * 16];
- } else {
+ } else {
entrance_directions = RCT2_ADDRESS(0x0099BA64, uint8)[track_type * 16];
- }
+ }
-
- uint8 tile_direction = tile->type & MAP_ELEMENT_DIRECTION_MASK;
+ uint8 tile_direction = mapElement->type & MAP_ELEMENT_DIRECTION_MASK;
entrance_directions <<= tile_direction;
entrance_directions = ((entrance_directions >> 12) | entrance_directions) & 0xF;
- // now each bit in entrance_directions stands for an entrance direction to check
+ // Now each bit in entrance_directions stands for an entrance direction to check
if (entrance_directions == 0)
return;
- for (int count = 0; entrance_directions != 0; ++count) {
+ // Turn x, y from tiles into units
+ x *= 32;
+ y *= 32;
+
+ for (count = 0; entrance_directions != 0; count++) {
if (!(entrance_directions & 1)) {
entrance_directions >>= 1;
- continue;
- }
+ continue;
+ }
entrance_directions >>= 1;
- uint8 face_direction = count ^ 2; // flip direction north<->south, east<->west
- int y2 = y - RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2];
- int x2 = x - RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2];
- int tile_idx = ((x2 << 8) | y2) >> 5;
+ // Flip direction north<->south, east<->west
+ uint8 face_direction = count ^ 2;
- if (map_coord_is_connected(tile_idx, tile->base_height, face_direction))
- return;
- }
-
- // name of ride is parameter of the format string
- RCT2_GLOBAL(0x013CE952, uint16) = ride->name;
+ int y2 = y - RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2];
+ int x2 = x - RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2];
+
+ if (map_coord_is_connected(x2 / 32, y2 / 32, mapElement->base_height, face_direction))
+ return;
+ }
+
+ // Name of ride is parameter of the format string
+ RCT2_GLOBAL(0x013CE952, uint16) = ride->name;
RCT2_GLOBAL(0x013CE954, uint32) = ride->name_arguments;
news_item_add_to_queue(1, STR_ENTRANCE_NOT_CONNECTED, ride_idx);
- ride->connected_message_throttle = 3;
+ ride->connected_message_throttle = 3;
}
#pragma endregion
@@ -2242,7 +2271,7 @@ static void ride_entrance_set_map_tooltip(rct_map_element *mapElement)
void ride_set_map_tooltip(rct_map_element *mapElement)
{
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE) {
+ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) {
ride_entrance_set_map_tooltip(mapElement);
} else {
if (
@@ -2659,4 +2688,81 @@ void ride_music_update_final()
}
}
-#pragma endregion
\ No newline at end of file
+#pragma endregion
+
+void ride_set_name(int rideIndex, const char *name)
+{
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_RENAME_RIDE_ATTRACTION;
+ game_do_command(1, (rideIndex << 8) | 1, 0, *((int*)(name + 0)), GAME_COMMAND_SET_RIDE_NAME, *((int*)(name + 8)), *((int*)(name + 4)));
+ game_do_command(2, (rideIndex << 8) | 1, 0, *((int*)(name + 12)), GAME_COMMAND_SET_RIDE_NAME, *((int*)(name + 20)), *((int*)(name + 16)));
+ game_do_command(0, (rideIndex << 8) | 1, 0, *((int*)(name + 24)), GAME_COMMAND_SET_RIDE_NAME, *((int*)(name + 32)), *((int*)(name + 28)));
+}
+
+/**
+ *
+ * rct2: 0x006B578B
+ */
+void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
+{
+ rct_window *w;
+ rct_ride *ride;
+ rct_string_id newUserStringId;
+ char oldName[128];
+ static char newName[128];
+
+ int rideIndex = (*ebx >> 8) & 0xFF;
+ int nameChunkIndex = *eax & 0xFFFF;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4;
+ if (*ebx & GAME_COMMAND_FLAG_APPLY) {
+ int nameChunkOffset = nameChunkIndex - 1;
+ if (nameChunkOffset < 0)
+ nameChunkOffset = 2;
+ nameChunkOffset *= 12;
+ RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx;
+ RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp;
+ RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi;
+ }
+
+ if (nameChunkIndex != 0) {
+ *ebx = 0;
+ return;
+ }
+
+ ride = GET_RIDE(rideIndex);
+ format_string(oldName, ride->name, &ride->name_arguments);
+ if (strcmp(oldName, newName) == 0) {
+ *ebx = 0;
+ return;
+ }
+
+ if (newName[0] == 0) {
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_INVALID_RIDE_ATTRACTION_NAME;
+ *ebx = MONEY32_UNDEFINED;
+ return;
+ }
+
+ newUserStringId = user_string_allocate(4, newName);
+ if (newUserStringId == 0) {
+ *ebx = MONEY32_UNDEFINED;
+ return;
+ }
+
+ if (*ebx & GAME_COMMAND_FLAG_APPLY) {
+ // Free the old ride name
+ user_string_free(ride->name);
+
+ ride->name = newUserStringId;
+
+ gfx_invalidate_screen();
+
+ // Force ride list window refresh
+ w = window_find_by_class(WC_RIDE_LIST);
+ if (w != NULL)
+ w->no_list_items = 0;
+ } else {
+ user_string_free(newUserStringId);
+ }
+
+ *ebx = 0;
+}
\ No newline at end of file
diff --git a/src/ride/ride.h b/src/ride/ride.h
index 54cbc7b959..08daaf3599 100644
--- a/src/ride/ride.h
+++ b/src/ride/ride.h
@@ -173,14 +173,16 @@ typedef struct {
};
uint16 reliability; // 0x146
uint16 var_148;
- uint16 var_14A;
- uint8 pad_14C;
+ uint8 satisfaction; // 0x14A
+ uint8 satisfaction_time_out; // 0x14B
+ uint8 satisfaction_next; // 0x14C
uint8 var_14D;
uint8 pad_14E[0x02];
uint32 total_customers; // 0x150
money32 total_profit; // 0x154
- uint16 var_158;
- uint8 pad_15A;
+ uint8 popularity; // 0x158
+ uint8 popularity_time_out; // 0x159 Updated every purchase and ?possibly by time?
+ uint8 popularity_next; // 0x15A When timeout reached this will be the next popularity
uint8 num_riders; // 0x15B
uint8 music_tune_id; // 0x15C
uint8 var_15D;
@@ -218,8 +220,8 @@ typedef struct {
uint8 var_1A1;
uint8 var_1A2;
uint8 var_1A3;
- uint32 no_primary_items_sold;
- uint32 no_secondary_items_sold;
+ uint32 no_primary_items_sold; // 0x1A4
+ uint32 no_secondary_items_sold; // 0x1A8
uint8 var_1AC;
uint8 var_1AD;
uint8 var_1AE;
@@ -610,9 +612,11 @@ void reset_all_ride_build_dates();
void ride_update_favourited_stat();
void ride_update_all();
void ride_check_all_reachable();
+void ride_update_popularity(rct_ride* ride, uint8 pop_amount);
rct_map_element *sub_6CAF80(int rideIndex, int *outX, int *outY);
rct_map_element *ride_find_track_gap(rct_map_element *startTrackElement, int *outX, int *outY);
void ride_construct_new(ride_list_item listItem);
+void ride_construct(int rideIndex);
int ride_modify(rct_map_element *trackMapElement, int x, int y);
void ride_get_status(int rideIndex, int *formatSecondary, int *argument);
rct_peep *ride_get_assigned_mechanic(rct_ride *ride);
@@ -634,4 +638,7 @@ void ride_set_map_tooltip(rct_map_element *mapElement);
int ride_music_params_update(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint16 sampleRate, uint32 position, uint8 *tuneId);
void ride_music_update_final();
+void ride_set_name(int rideIndex, const char *name);
+void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
+
#endif
diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c
index 9a88f57509..570bfd1dad 100644
--- a/src/ride/ride_ratings.c
+++ b/src/ride/ride_ratings.c
@@ -236,11 +236,11 @@ static void ride_ratings_update_state_2()
y = RCT2_GLOBAL(0x0138B586, uint16) / 32;
z = RCT2_GLOBAL(0x0138B588, uint16) / 8;
- mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x);
+ mapElement = map_get_first_element_at(x, y);
trackType = RCT2_GLOBAL(0x0138B592, uint8);
do {
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_TRACK)
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK)
continue;
if (mapElement->base_height != z)
continue;
@@ -271,7 +271,7 @@ static void ride_ratings_update_state_2()
RCT2_GLOBAL(0x0138B588, uint16) = z;
RCT2_GLOBAL(0x0138B592, uint8) = mapElement->properties.track.type;
}
- } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
+ } while (!map_element_is_last_for_tile(mapElement++));
_rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE;
}
@@ -333,11 +333,11 @@ static void ride_ratings_update_state_5()
y = RCT2_GLOBAL(0x0138B586, uint16) / 32;
z = RCT2_GLOBAL(0x0138B588, uint16) / 8;
- mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x);
+ mapElement = map_get_first_element_at(x, y);
trackType = RCT2_GLOBAL(0x0138B592, uint8);
do {
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_TRACK)
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK)
continue;
if (mapElement->base_height != z)
continue;
@@ -363,7 +363,7 @@ static void ride_ratings_update_state_5()
RCT2_GLOBAL(0x0138B588, uint16) = z;
RCT2_GLOBAL(0x0138B592, uint8) = mapElement->properties.track.type;
}
- } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
+ } while (!map_element_is_last_for_tile(mapElement++));
_rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE;
}
@@ -733,18 +733,18 @@ static int ride_ratings_get_scenery_score(rct_ride *ride)
// Count surrounding scenery items
numSceneryItems = 0;
- for (yy = y - 5; yy <= y + 5; yy++) {
- for (xx = x - 5; xx <= x + 5; xx++) {
+ for (yy = max(y - 5, 0); yy <= y + 5; yy++) {
+ for (xx = max(x - 5, 0); xx <= x + 5; xx++) {
// Count scenery items on this tile
- mapElement = TILE_MAP_ELEMENT_POINTER(yy * 256 + xx);
+ mapElement = map_get_first_element_at(xx, yy);
do {
- if (mapElement->flags & 0x10)
+ if (mapElement->flags & (1 << 4))
continue;
- type = mapElement->type & MAP_ELEMENT_TYPE_MASK;
+ type = map_element_get_type(mapElement);
if (type == MAP_ELEMENT_TYPE_SCENERY || type == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE)
numSceneryItems++;
- } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
+ } while (!map_element_is_last_for_tile(mapElement++));
}
}
diff --git a/src/ride/station.c b/src/ride/station.c
index 398c98892e..d2eec14bdf 100644
--- a/src/ride/station.c
+++ b/src/ride/station.c
@@ -294,16 +294,13 @@ rct_map_element *ride_get_station_start_track_element(rct_ride *ride, int statio
y = ride->station_starts[stationIndex] >> 8;
z = ride->station_heights[stationIndex];
- // Get first element of the tile
- mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x);
-
// Find the station track element
+ mapElement = map_get_first_element_at(x, y);
do {
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_TRACK && z == mapElement->base_height)
+ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK && z == mapElement->base_height)
return mapElement;
- mapElement++;
- } while (!((mapElement - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
+ } while (!map_element_is_last_for_tile(mapElement++));
return NULL;
}
@@ -312,16 +309,12 @@ rct_map_element *ride_get_station_exit_element(rct_ride *ride, int x, int y, int
{
rct_map_element *mapElement;
- // Get first element of the tile
- mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x);
-
// Find the station track element
+ mapElement = map_get_first_element_at(x, y);
do {
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE && z == mapElement->base_height)
+ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE && z == mapElement->base_height)
return mapElement;
-
- mapElement++;
- } while (!((mapElement - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
+ } while (!map_element_is_last_for_tile(mapElement++));
return NULL;
}
\ No newline at end of file
diff --git a/src/ride/track.c b/src/ride/track.c
index 7124bb6f9a..0207b387b0 100644
--- a/src/ride/track.c
+++ b/src/ride/track.c
@@ -19,9 +19,14 @@
*****************************************************************************/
#include "../addresses.h"
-#include "../platform/osinterface.h"
+#include "../game.h"
+#include "../interface/viewport.h"
+#include "../localisation/localisation.h"
+#include "../platform/platform.h"
+#include "../rct1.h"
#include "../util/sawyercoding.h"
#include "../util/util.h"
+#include "../world/park.h"
#include "ride.h"
#include "track.h"
@@ -220,13 +225,223 @@ const rct_trackdefinition gTrackDefinitions[] = {
{ TRACK_HALF_LOOP_2, TRACK_DOWN_25, TRACK_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_HALF_LOOP_DOWN }, // ELEM_LEFT_LARGE_HALF_LOOP_DOWN
};
+uint32* sub_6AB49A(rct_object_entry* entry){
+ rct_object_entry* object_list_entry = object_list_find(entry);
+
+ if (object_list_entry == NULL) return NULL;
+
+ // Return the address of the last value of the list entry
+ return (((uint32*)object_get_next(object_list_entry)) - 1);
+}
+
+static void get_track_idx_path(char *path)
+{
+ char *homePath = platform_get_orct2_homefolder();
+ sprintf(path, "%s%c%s", homePath, platform_get_path_separator(), "tracks.idx");
+ free(homePath);
+}
+
+static void track_list_query_directory(int *outTotalFiles){
+ int enumFileHandle;
+ file_info enumFileInfo;
+
+ *outTotalFiles = 0;
+
+ // Enumerate through each track in the directory
+ enumFileHandle = platform_enumerate_files_begin(RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char));
+ if (enumFileHandle == INVALID_HANDLE)
+ return;
+
+ while (platform_enumerate_files_next(enumFileHandle, &enumFileInfo)) {
+ (*outTotalFiles)++;
+ }
+ platform_enumerate_files_end(enumFileHandle);
+}
+
+static int track_list_cache_save(int fileCount, uint8* track_list_cache, uint32 track_list_size){
+ char path[MAX_PATH];
+ FILE *file;
+
+ log_verbose("saving track list cache (tracks.idx)");
+ get_track_idx_path(path);
+ file = fopen(path, "wb");
+ if (file == NULL) {
+ log_error("Failed to save %s", path);
+ return 0;
+ }
+
+ fwrite(&fileCount, sizeof(int), 1, file);
+ fwrite(track_list_cache, track_list_size, 1, file);
+ uint8 last_entry = 0xFE;
+ fwrite(&last_entry, 1, 1, file);
+ fclose(file);
+ return 1;
+}
+
+static uint8* track_list_cache_load(int totalFiles){
+ char path[MAX_PATH];
+ FILE *file;
+
+ log_verbose("loading track list cache (tracks.idx)");
+ get_track_idx_path(path);
+ file = fopen(path, "rb");
+ if (file == NULL) {
+ log_error("Failed to load %s", path);
+ return 0;
+ }
+
+ uint8* track_list_cache;
+ uint32 fileCount;
+ // Remove 4 for the file count variable
+ long track_list_size = fsize(file) - 4;
+
+ if (track_list_size < 0) return 0;
+
+ fread(&fileCount, 4, 1, file);
+
+ if (fileCount != totalFiles){
+ log_verbose("Track file count is different.");
+ return 0;
+ }
+
+ track_list_cache = malloc(track_list_size);
+ fread(track_list_cache, track_list_size, 1, file);
+ return track_list_cache;
+}
+
+void track_list_populate(ride_list_item item, uint8* track_list_cache){
+ uint8* track_pointer = track_list_cache;
+
+ uint8 cur_track_entry_index = 0;
+ for (uint8 track_type = *track_pointer++; track_type != 0xFE;
+ track_pointer += strlen(track_pointer) + 1,
+ track_type = *track_pointer++){
+ rct_object_entry* track_object = (rct_object_entry*)track_pointer;
+ track_pointer += sizeof(rct_object_entry);
+
+ if (track_type != item.type){
+ continue;
+ }
+
+ uint8 entry_type, entry_index;
+ if (item.entry_index != 0xFF){
+
+ if (!find_object_in_entry_group(track_object, &entry_type, &entry_index))continue;
+
+ if (item.entry_index != entry_index)continue;
+ }
+ else{
+ if (find_object_in_entry_group(track_object, &entry_type, &entry_index)){
+ if (GET_RIDE_ENTRY(entry_index)->var_008 & 0x3000)continue;
+ }
+ else{
+ uint32* esi = sub_6AB49A(track_object);
+ if (esi == NULL) continue;
+ if (*esi & 0x1000000)continue;
+ }
+ }
+
+ // If cur_track_entry_index is greater than max number of tracks
+ if (cur_track_entry_index >= 1000){
+ RCT2_GLOBAL(0xF635ED, uint8) |= 1;
+ break;
+ }
+
+ uint8 track_entry_index = 0;
+ uint8 isBelow = 0;
+ for (; track_entry_index != cur_track_entry_index; track_entry_index++){
+ if (strcicmp(track_pointer, &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8)[track_entry_index * 128]) < 0){
+ isBelow = 1;
+ break;
+ }
+ }
+
+ if (isBelow == 1){
+ memmove(
+ &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8)[track_entry_index * 128 + 128],
+ &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8)[track_entry_index * 128],
+ (cur_track_entry_index - track_entry_index) * 128);
+ }
+
+ strcpy(&RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8)[track_entry_index * 128], track_pointer);
+ cur_track_entry_index++;
+ }
+
+ RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8)[cur_track_entry_index * 128] = '\0';
+ free(track_list_cache);
+}
+
/**
*
* rct2: 0x006CED50
*/
void track_load_list(ride_list_item item)
{
- RCT2_CALLPROC_X(0x006CED50, 0, 0, 0, *((uint16*)&item), 0, 0, 0);
+ RCT2_GLOBAL(0xF635ED, uint8) = 0;
+
+ if (item.type < 0x80){
+ rct_ride_type* ride_type = gRideTypeList[item.entry_index];
+ if (!(ride_type->var_008 & 0x2000)){
+ item.entry_index = 0xFF;
+ }
+ }
+
+ int totalFiles;
+
+ track_list_query_directory(&totalFiles);
+
+ uint8* track_list_cache;
+
+ if (item.type == 0xFC || !(track_list_cache = track_list_cache_load(totalFiles))){
+ uint8* new_track_file;
+
+ new_track_file = malloc(0x40000);
+
+ uint8* new_file_pointer = new_track_file;
+ file_info enumFileInfo;
+
+ int enumFileHandle = platform_enumerate_files_begin(RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char));
+ if (enumFileHandle == INVALID_HANDLE)
+ return;
+
+ while (platform_enumerate_files_next(enumFileHandle, &enumFileInfo)) {
+ if (new_file_pointer > new_track_file + 0x3FF00)break;
+
+ char path[MAX_PATH];
+ subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), enumFileInfo.path);
+
+ rct_track_td6* loaded_track = load_track_design(path);
+ if (loaded_track){
+ *new_file_pointer++ = loaded_track->type;
+ }
+ else{
+ *new_file_pointer++ = 0xFF;
+ }
+ memcpy(new_file_pointer, &loaded_track->vehicle_object, sizeof(rct_object_entry));
+ new_file_pointer += sizeof(rct_object_entry);
+
+ int file_name_length = strlen(enumFileInfo.path);
+ strcpy(new_file_pointer, enumFileInfo.path);
+ new_file_pointer += file_name_length + 1;
+ }
+ platform_enumerate_files_end(enumFileHandle);
+
+ if (!track_list_cache_save(totalFiles, new_track_file, new_file_pointer - new_track_file)){
+ log_error("Track list failed to save.");
+ return;
+ }
+ free(new_track_file);
+
+ track_list_cache = track_list_cache_load(totalFiles);
+ if (!track_list_cache){
+ log_error("Track list failed to load after new save");
+ return;
+ }
+ }
+
+ track_list_populate(item, track_list_cache);
+ free(track_list_cache);
+ //RCT2_CALLPROC_X(0x006CED50, 0, 0, 0, *((uint16*)&item), 0, 0, 0);
}
static void read(void *dst, void **src, int length)
@@ -240,30 +455,28 @@ static void read(void *dst, void **src, int length)
* rct2: 0x0067726A
* path: 0x0141EF68
*/
-int sub_67726A(const char *path)
+rct_track_td6* load_track_design(const char *path)
{
FILE *fp;
long fpLength;
- const char *ch;
- char trackFilename[MAX_PATH], *fpBuffer, *decoded, *src, *dst;
+ char *fpBuffer, *decoded, *src;
int i, decodedLength;
uint8* edi;
RCT2_GLOBAL(0x009AAC54, uint8) = 1;
- // Get filename
- ch = strrchr(path, '\\');
- ch = ch == NULL ? path : ch + 1;
- dst = trackFilename;
- while (*ch != 0 && *ch != '.') {
- *dst++ = *ch++;
- }
- *dst = 0;
-
fp = fopen(path, "rb");
if (fp == NULL)
return 0;
+ char* track_name_pointer = (char*)path;
+ while (*track_name_pointer++ != '\0');
+ while (*--track_name_pointer != '\\');
+ char* default_name = RCT2_ADDRESS(0x009E3504, char);
+ // Copy the track name for use as the default name of this ride
+ while (*++track_name_pointer != '.')*default_name++ = *track_name_pointer;
+ *default_name++ = '\0';
+
// Read whole file into a buffer
fpLength = fsize(fp);
fpBuffer = malloc(fpLength);
@@ -280,100 +493,500 @@ int sub_67726A(const char *path)
realloc(decoded, decodedLength);
free(fpBuffer);
+ rct_track_td6* track_design = RCT2_ADDRESS(0x009D8178, rct_track_td6);
// Read decoded data
src = decoded;
- memset((void*)0x009D81D8, 0, 67);
- read((void*)0x009D8178, &src, 32);
+ // Clear top of track_design as this is not loaded from the td4 files
+ memset(&track_design->track_spine_colour, 0, 67);
+ // Read start of track_design
+ read(track_design, &src, 32);
- uint8 al = RCT2_GLOBAL(0x009D817F, uint8) >> 2;
- if (al >= 2)
- read((void*)0x009D8198, &src, 40);
+ uint8 version = track_design->var_07 >> 2;
- read((void*)0x009D81C0, &src, 24);
- al = RCT2_GLOBAL(0x009D817F, uint8) >> 2;
- if (al != 0)
- read((void*)0x009D81D8, &src, al == 1 ? 140 : 67);
-
- read((void*)0x009D821B, &src, 24572);
- al = RCT2_GLOBAL(0x009D817F, uint8) >> 2;
- if (al < 2) {
- if (RCT2_GLOBAL(0x009D8178, uint8) == 20) {
- edi = (uint8*)0x009D821B;
- while (*edi != 0) {
- edi += 4;
- }
- edi += 4;
- memset(edi, 255, (uint8*)0x009DE217 - edi);
- } else {
- edi = (uint8*)0x009D821B;
- while (*edi != 255) {
- edi += 2;
- }
- edi++;
- memset(edi, 255, (uint8*)0x009DE217 - edi);
- }
+ if (version > 2){
+ free(decoded);
+ return NULL;
}
+
+ // In td6 there are 32 sets of two byte vehicle colour specifiers
+ // In td4 there are 12 sets so the remaining 20 need to be read.
+ if (version == 2)
+ read(&track_design->vehicle_colours[12], &src, 40);
+
+ read(&track_design->pad_48, &src, 24);
+
+ // In td4 (version AA/CF) and td6 both start actual track data at 0xA3
+ if (version > 0)
+ read(&track_design->track_spine_colour, &src, version == 1 ? 140 : 67);
+
+ uint8* track_elements = RCT2_ADDRESS(0x9D821B, uint8);
+ // Read the actual track data.
+ read(track_elements, &src, 24572);
+
+ uint8* final_track_element_location = track_elements + 24572;
free(decoded);
- //
- al = RCT2_GLOBAL(0x009D817F, uint8) >> 2;
- if (al > 2)
- return 0;
+ // td4 files require some work to be recognised as td6.
+ if (version < 2) {
- if (al <= 1) {
- edi = (uint8*)0x009D8180;
+ // Set any element passed the tracks to 0xFF
+ if (track_design->type == RIDE_TYPE_MAZE) {
+ uint32* maze_element = (uint32*)track_elements;
+ while (*maze_element != 0) {
+ maze_element++;
+ }
+ maze_element++;
+ memset(maze_element, 255, final_track_element_location - (uint8*)maze_element);
+ } else {
+ uint8* track_element = track_elements;
+ while (*track_element != 255) {
+ track_element += 2;
+ }
+ track_element++;
+ memset(track_element, 255, final_track_element_location - track_element);
+ }
+
+ // Edit the colours to use the new versions
+ // Unsure why it is 67
+ edi = (uint8*)&track_design->vehicle_colours;
for (i = 0; i < 67; i++)
*edi++ = RCT2_ADDRESS(0x0097F0BC, uint8)[*edi];
- edi = (uint8*)0x009D81D8;
+ // Edit the colours to use the new versions
+ edi = (uint8*)&track_design->track_spine_colour;
for (i = 0; i < 12; i++)
*edi++ = RCT2_ADDRESS(0x0097F0BC, uint8)[*edi];
- RCT2_GLOBAL(0x009D81D2, uint8) >>= 1;
- if (!RCT2_CALLPROC_X(0x00677530, 0, 0, 0, 0, 0, 0, 0))
- RCT2_GLOBAL(0x009D8178, uint8) = 255;
+ // Highest drop height is 1bit = 3/4 a meter in td6
+ // Highest drop height is 1bit = 1/3 a meter in td4
+ // Not sure if this is correct??
+ track_design->highest_drop_height >>= 1;
+ if (0x100 & RCT2_CALLPROC_X(0x00677530, 0, 0, 0, 0, 0, 0, 0))
+ track_design->type = RIDE_TYPE_NULL;
- if (RCT2_GLOBAL(0x009D8178, uint8) == 4)
- RCT2_GLOBAL(0x009D8178, uint8) = 255;
+ if (track_design->type == RCT1_RIDE_TYPE_STEEL_MINI_ROLLER_COASTER)
+ track_design->type = RIDE_TYPE_NULL;
- if (RCT2_GLOBAL(0x009D8178, uint8) == 0)
- RCT2_GLOBAL(0x009D8178, uint8) = 52;
+ if (track_design->type == RCT1_RIDE_TYPE_WOODEN_ROLLER_COASTER)
+ track_design->type = RIDE_TYPE_WOODEN_ROLLER_COASTER;
- if (RCT2_GLOBAL(0x009D8178, uint8) == 19) {
- if (RCT2_GLOBAL(0x009D817E, uint8) == 3)
- RCT2_GLOBAL(0x009D817E, uint8) = 35;
- if (RCT2_GLOBAL(0x009D8179, uint8) == 79) {
- if (RCT2_GLOBAL(0x009D817E, uint8) == 2)
- RCT2_GLOBAL(0x009D817E, uint8) = 1;
+ if (track_design->type == RIDE_TYPE_CORKSCREW_ROLLER_COASTER) {
+ if (track_design->var_06 == 3)
+ track_design->var_06 = 35;
+ if (track_design->vehicle_type == 79) {
+ if (track_design->var_06 == 2)
+ track_design->var_06 = 1;
}
}
- int unk1 = RCT2_GLOBAL(0x009D8179, uint8);
- if (RCT2_GLOBAL(0x009D8178, uint8) == 20) {
- unk1 = 0x0097F66C;
+ rct_object_entry* vehicle_object;
+ if (track_design->type == RIDE_TYPE_MAZE) {
+ vehicle_object = RCT2_ADDRESS(0x0097F66C, rct_object_entry);
} else {
- if (unk1 == 3 && RCT2_GLOBAL(0x009D8178, uint8) == 3)
- unk1 = 80;
- unk1 = 0x0097F0DC + (unk1 * 16);
+ int vehicle_type = track_design->vehicle_type;
+ if (vehicle_type == 3 && track_design->type == RIDE_TYPE_INVERTED_ROLLER_COASTER)
+ vehicle_type = 80;
+ vehicle_object = &RCT2_ADDRESS(0x0097F0DC, rct_object_entry)[vehicle_type];
}
- memcpy((void*)0x009D81E8, (void*)unk1, 16);
+ memcpy(&track_design->vehicle_object, vehicle_object, sizeof(rct_object_entry));
for (i = 0; i < 32; i++)
- RCT2_ADDRESS(0x009D81FA, uint8)[i] = RCT2_ADDRESS(0x009D8181, uint8)[i * 2];
+ track_design->vehicle_additional_colour[i] = track_design->vehicle_colours[i].trim_colour;
- RCT2_GLOBAL(0x009D81F8, uint8) = 255;
- RCT2_GLOBAL(0x009D81F9, uint8) = 255;
- RCT2_GLOBAL(0x009D821A, uint8) = 5;
+ track_design->space_required_x = 255;
+ track_design->space_required_y = 255;
+ track_design->var_A2 = 5;
}
- RCT2_GLOBAL(0x009D81C8, uint8) = min(
- RCT2_GLOBAL(0x009D81C8, uint8),
- RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + 5 + (RCT2_GLOBAL(0x009D8178, uint8) * 8), uint8)
+ track_design->var_50 = min(
+ track_design->var_50,
+ RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + 5 + (track_design->type * 8), uint8)
);
+ return track_design;
+}
+
+/* rct2: 0x006D1DCE*/
+void reset_track_list_cache(){
+ int* track_list_cache = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE, int);
+ for (int i = 0; i < 4; ++i){
+ track_list_cache[i] = -1;
+ }
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE, uint32) = 0;
+}
+
+/* rct2: 0x006D1C68 */
+int backup_map(){
+ RCT2_GLOBAL(0xF440ED, uint8*) = malloc(0xED600);
+ if (RCT2_GLOBAL(0xF440ED, uint32) == 0) return 0;
+
+ RCT2_GLOBAL(0xF440F1, uint8*) = malloc(0x40000);
+ if (RCT2_GLOBAL(0xF440F1, uint32) == 0){
+ free(RCT2_GLOBAL(0xF440ED, uint8*));
+ return 0;
+ }
+
+ RCT2_GLOBAL(0xF440F5, uint8*) = malloc(14);
+ if (RCT2_GLOBAL(0xF440F5, uint32) == 0){
+ free(RCT2_GLOBAL(0xF440ED, uint8*));
+ free(RCT2_GLOBAL(0xF440F1, uint8*));
+ return 0;
+ }
+
+ uint32* map_elements = RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, uint32);
+ memcpy(RCT2_GLOBAL(0xF440ED, uint32*), map_elements, 0xED600);
+
+ uint32* tile_map_pointers = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, uint32);
+ memcpy(RCT2_GLOBAL(0xF440F1, uint32*), tile_map_pointers, 0x40000);
+
+ uint8* backup_info = RCT2_GLOBAL(0xF440F5, uint8*);
+ *(uint32*)backup_info = RCT2_GLOBAL(0x0140E9A4, uint32);
+ *(uint16*)(backup_info + 4) = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16);
+ *(uint16*)(backup_info + 6) = RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, uint16);
+ *(uint16*)(backup_info + 8) = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16);
+ *(uint32*)(backup_info + 10) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32);
return 1;
}
+/* rct2: 0x006D2378 */
+void reload_map_backup(){
+ uint32* map_elements = RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, uint32);
+ memcpy(map_elements, RCT2_GLOBAL(0xF440ED, uint32*), 0xED600);
+
+ uint32* tile_map_pointers = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, uint32);
+ memcpy(tile_map_pointers, RCT2_GLOBAL(0xF440F1, uint32*), 0x40000);
+
+ uint8* backup_info = RCT2_GLOBAL(0xF440F5, uint8*);
+ RCT2_GLOBAL(0x0140E9A4, uint32) = *(uint32*)backup_info;
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) = *(uint16*)(backup_info + 4);
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, uint16) = *(uint16*)(backup_info + 6);
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16) = *(uint16*)(backup_info + 8);
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) = *(uint32*)(backup_info + 10);
+
+ free(RCT2_GLOBAL(0xF440ED, uint8*));
+ free(RCT2_GLOBAL(0xF440F1, uint8*));
+ free(RCT2_GLOBAL(0xF440F5, uint8*));
+}
+
+/* rct2: 0x006D1D9A */
+void blank_map(){
+
+ // These values were previously allocated in backup map but
+ // it seems more fitting to place in this function
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) = 0x1FE0;
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, uint16) = 0x20FE;
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16) = 0x100;
+
+ rct_map_element* map_element;
+ for (int i = 0; i < MAX_TILE_MAP_ELEMENT_POINTERS; i++) {
+ map_element = GET_MAP_ELEMENT(i);
+ map_element->type = MAP_ELEMENT_TYPE_SURFACE;
+ map_element->flags = MAP_ELEMENT_FLAG_LAST_TILE;
+ map_element->base_height = 2;
+ map_element->clearance_height = 0;
+ map_element->properties.surface.slope = 0;
+ map_element->properties.surface.terrain = 0;
+ map_element->properties.surface.grass_length = 1;
+ map_element->properties.surface.ownership = OWNERSHIP_OWNED;
+ }
+ map_update_tile_pointers();
+}
+
+/* rct2: 0x006ABDB0 */
+void load_track_scenery_objects(){
+ uint8 entry_index = RCT2_GLOBAL(0xF44157, uint8);
+ rct_object_entry_extended* object_entry = &object_entry_groups[0].entries[entry_index];
+
+ rct_object_entry* copied_entry = RCT2_ADDRESS(0xF43414, rct_object_entry);
+ memcpy(copied_entry, object_entry, sizeof(rct_object_entry));
+
+ object_unload_all();
+ object_load(-1, copied_entry, 0);
+ uint8 entry_type;
+ find_object_in_entry_group(copied_entry, &entry_type, &entry_index);
+ RCT2_GLOBAL(0xF44157, uint8) = entry_index;
+
+ rct_track_td6* track_design = RCT2_ADDRESS(0x009D8178, rct_track_td6);
+ uint8* track_elements = RCT2_ADDRESS(0x9D821B, uint8);
+
+ if (track_design->type == RIDE_TYPE_MAZE){
+ // Skip all of the maze track elements
+ while (*(uint32*)track_elements != 0)track_elements += 4;
+ track_elements += 4;
+ }
+ else{
+ // Skip track_elements
+ while (*track_elements != 255) track_elements += 2;
+ track_elements++;
+
+ // Skip entrance exit elements
+ while (*track_elements != 255) track_elements += 6;
+ track_elements++;
+ }
+
+ while (*track_elements != 255){
+ if (!find_object_in_entry_group((rct_object_entry*)track_elements, &entry_type, &entry_index)){
+ object_load(-1, (rct_object_entry*)track_elements, 0);
+ }
+ // Skip object and location/direction/colour
+ track_elements += sizeof(rct_object_entry) + 6;
+ }
+
+ sub_6A9FC0();
+}
+
+/**
+* Places a virtual track. This can involve highlighting the surface tiles and showing the track layout. It is also used by
+* the track preview window to place the whole track.
+* Depending on the value of bl it modifies the function.
+* bl == 0, Draw outlines on the ground
+* bl == 3, Returns the z value of a succesful placement
+* bl == 5, Returns cost to create the track. Places the track. (used by the preview)
+* bl == 6, Clear white outlined track.
+* rct2: 0x006D01B3
+*/
+int sub_6D01B3(int bl, int x, int y, int z)
+{
+ int eax, ebx, ecx, edx, esi, edi, ebp;
+ eax = x;
+ ebx = bl;
+ ecx = y;
+ edx = z;
+ esi = 0;
+ edi = 0;
+ ebp = 0;
+ RCT2_CALLFUNC_X(0x006D01B3, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ return *((short*)&ebx);
+}
+
+/* rct2: 0x006D2189
+ * ebx = ride_id
+ * cost = edi
+ */
+int sub_6D2189(int* cost, uint8* ride_id){
+ RCT2_GLOBAL(0xF44151, uint8) = 0;
+ rct_track_td6* track_design = RCT2_ADDRESS(0x009D8178, rct_track_td6);
+ uint8 entry_type, entry_index;
+
+ if (!find_object_in_entry_group(&track_design->vehicle_object, &entry_type, &entry_index))
+ entry_index = 0xFF;
+
+ int eax = 0, ebx, ecx = 0, edx, esi, edi = 0, ebp = 0;
+ ebx = 41;
+ edx = track_design->type | (entry_index << 8);
+ esi = GAME_COMMAND_6;
+
+ if (0x80000000 == game_do_command_p(GAME_COMMAND_6, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp)) return 1;
+
+ // bh
+ *ride_id = edi & 0xFF;
+
+ rct_ride* ride = GET_RIDE(*ride_id);
+
+ uint8* ride_name = RCT2_ADDRESS(0x9E3504, uint8);
+ rct_string_id new_ride_name = user_string_allocate(132, ride_name);
+
+ if (new_ride_name){
+ rct_string_id old_name = ride->name;
+ ride->name = new_ride_name;
+ user_string_free(old_name);
+ }
+
+ uint8 version = track_design->var_07 >> 2;
+
+ if (version == 2){
+ ride->entrance_style = track_design->entrance_style;
+ }
+
+ if (version != 0){
+ memcpy(&ride->track_colour_main, &track_design->track_spine_colour, 4);
+ memcpy(&ride->track_colour_additional, &track_design->track_rail_colour, 4);
+ memcpy(&ride->track_colour_supports, &track_design->track_support_colour, 4);
+ }
+ else{
+ memset(&ride->track_colour_main, track_design->track_spine_colour_rct1, 4);
+ memset(&ride->track_colour_additional, track_design->track_rail_colour_rct1, 4);
+ memset(&ride->track_colour_supports, track_design->track_support_colour_rct1, 4);
+ }
+
+ RCT2_GLOBAL(0x009D8150, uint8) |= 1;
+ uint8 backup_rotation = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8);
+ uint32 backup_park_flags = RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32);
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_FORBID_HIGH_CONSTRUCTION;
+ int map_size = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16) << 4;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = 0;
+ int z = sub_6D01B3(3, map_size, map_size, 16);
+
+ if (RCT2_GLOBAL(0xF4414E, uint8) & 4){
+ RCT2_GLOBAL(0xF44151, uint8) |= 2;
+ }
+ //dx
+ z += 16 - RCT2_GLOBAL(0xF44129, uint16);
+
+ int bl = 5;
+ if (RCT2_GLOBAL(0xF4414E, uint8) & 2){
+ bl |= 0x80;
+ RCT2_GLOBAL(0xF44151, uint8) |= 1;
+ }
+ edi = sub_6D01B3((*ride_id << 8) | bl, map_size, map_size, z);
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) = backup_park_flags;
+
+ if (edi != 0x80000000){
+
+ if (!find_object_in_entry_group(&track_design->vehicle_object, &entry_type, &entry_index)){
+ RCT2_GLOBAL(0xF44151, uint8) |= 4;
+ }
+
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = backup_rotation;
+ RCT2_GLOBAL(0x009D8150, uint8) &= ~1;
+ *cost = edi;
+ return 1;
+ }
+ else{
+
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = backup_rotation;
+ user_string_free(ride->name);
+ ride->type = RIDE_TYPE_NULL;
+ RCT2_GLOBAL(0x009D8150, uint8) &= ~1;
+ return 0;
+ }
+}
+
+/* rct2: 0x006D235B */
+void sub_6D235B(uint8 ride_id){
+ rct_ride* ride = GET_RIDE(ride_id);
+ user_string_free(ride->name);
+ ride->type = RIDE_TYPE_NULL;
+}
+
+/* rct2: 0x006D1EF0 */
+void draw_track_preview(uint8** preview){
+ // Make a copy of the map
+ if (!backup_map())return;
+
+ blank_map();
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER){
+ load_track_scenery_objects();
+ }
+
+ int cost;
+ uint8 ride_id;
+
+ if (!sub_6D2189(&cost, &ride_id)){
+ memset(preview, 0, TRACK_PREVIEW_IMAGE_SIZE * 4);
+ reload_map_backup();
+ return;
+ }
+
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_COST, money32) = cost;
+
+ rct_viewport* view = RCT2_ADDRESS(0x9D8161, rct_viewport);
+ rct_drawpixelinfo* dpi = RCT2_ADDRESS(0x9D8151, rct_drawpixelinfo);
+ int left, top, right, bottom;
+
+ int center_x = (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_X_MAX, sint16) + RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_X_MIN, sint16)) / 2 + 16;
+ int center_y = (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Y_MAX, sint16) + RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Y_MIN, sint16)) / 2 + 16;
+ int center_z = (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Z_MIN, sint16) + RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Z_MAX, sint16)) / 2;
+
+ int width = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_X_MAX, sint16) - RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_X_MIN, sint16);
+ int height = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Y_MAX, sint16) - RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_Y_MIN, sint16);
+
+ if (width < height)
+ width = height;
+
+ int zoom_level = 1;
+
+ if (width > 1120)
+ zoom_level = 2;
+
+ if (width > 2240)
+ zoom_level = 3;
+
+ width = 370 << zoom_level;
+ height = 217 << zoom_level;
+
+ int x = center_y - center_x - width / 2;
+ int y = (center_y + center_x) / 2 - center_z - height / 2;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) = 0;
+
+ view->width = 370;
+ view->height = 217;
+ view->view_width = width;
+ view->view_height = height;
+ view->x = 0;
+ view->y = 0;
+ view->view_x = x;
+ view->view_y = y;
+ view->zoom = zoom_level;
+ view->flags = VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_INVISIBLE_SPRITES;
+
+ dpi->zoom_level = zoom_level;
+ dpi->x = 0;
+ dpi->y = 0;
+ dpi->width = 370;
+ dpi->height = 217;
+ dpi->pitch = 0;
+ dpi->bits = (char*)preview;
+
+ top = y;
+ left = x;
+ bottom = y + height;
+ right = x + width;
+
+ viewport_paint(view, dpi, left, top, right, bottom);
+
+ dpi->bits += TRACK_PREVIEW_IMAGE_SIZE;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) = 1;
+ x = -center_y - center_x - width / 2;
+ y = (center_y - center_x) / 2 - center_z - height / 2;
+
+ view->view_x = x;
+ view->view_y = y;
+ top = y;
+ left = x;
+ bottom = y + height;
+ right = x + width;
+
+ viewport_paint(view, dpi, left, top, right, bottom);
+
+ dpi->bits += TRACK_PREVIEW_IMAGE_SIZE;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) = 2;
+ x = center_x - center_y - width / 2;
+ y = (-center_y - center_x) / 2 - center_z - height / 2;
+
+ view->view_x = x;
+ view->view_y = y;
+ top = y;
+ left = x;
+ bottom = y + height;
+ right = x + width;
+
+ viewport_paint(view, dpi, left, top, right, bottom);
+
+ dpi->bits += TRACK_PREVIEW_IMAGE_SIZE;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) = 3;
+ x = center_x + center_y - width / 2;
+ y = (center_x - center_y) / 2 - center_z - height / 2;
+
+ view->view_x = x;
+ view->view_y = y;
+ top = y;
+ left = x;
+ bottom = y + height;
+ right = x + width;
+
+ viewport_paint(view, dpi, left, top, right, bottom);
+
+ sub_6D235B(ride_id);
+ reload_map_backup();
+}
+
/**
*
* I don't think preview is a necessary output argument. It can be obtained easily using the track design structure.
@@ -382,45 +995,55 @@ int sub_67726A(const char *path)
rct_track_design *track_get_info(int index, uint8** preview)
{
rct_track_design *trackDesign;
- uint8 *trackDesignList = (uint8*)0x00F441EC;
+ uint8 *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8);
int i;
trackDesign = NULL;
// Check if track design has already been loaded
for (i = 0; i < 4; i++) {
- if (index == RCT2_ADDRESS(0x00F44109, uint32)[i]) {
- trackDesign = &RCT2_GLOBAL(0x00F44105, rct_track_design*)[i];
+ if (index == RCT2_ADDRESS(RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE, uint32)[i]) {
+ trackDesign = &RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_CACHE, rct_track_design*)[i];
break;
}
}
if (trackDesign == NULL) {
// Load track design
- i = RCT2_GLOBAL(0x00F44119, uint32);
- RCT2_GLOBAL(0x00F44119, uint32)++;
- if (RCT2_GLOBAL(0x00F44119, uint32) >= 4)
- RCT2_GLOBAL(0x00F44119, uint32) = 0;
+ i = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE, uint32)++;
+ if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE, uint32) >= 4)
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE, uint32) = 0;
- RCT2_ADDRESS(0x00F44109, uint32)[i] = index;
- subsitute_path((char*)0x0141EF68, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignList + (index * 128));
- if (!sub_67726A((char*)0x0141EF68)) {
+ RCT2_ADDRESS(RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE, uint32)[i] = index;
+
+ char track_path[MAX_PATH] = { 0 };
+ subsitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignList + (index * 128));
+
+ rct_track_td6* loaded_track = NULL;
+
+ log_verbose("Loading track: %s", trackDesignList + (index * 128));
+
+ if (!(loaded_track = load_track_design(track_path))) {
if (preview != NULL) *preview = NULL;
+ log_error("Failed to load track: %s", trackDesignList + (index * 128));
return NULL;
}
- trackDesign = &RCT2_GLOBAL(0x00F44105, rct_track_design*)[i];
+ trackDesign = &RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_CACHE, rct_track_design*)[i];
+
+ // Copy the track design apart from the preview image
+ memcpy(&trackDesign->track_td6, loaded_track, sizeof(rct_track_td6));
+ // Load in a new preview image, calculate cost variable, calculate var_06
+ draw_track_preview((uint8**)trackDesign->preview);
+ //RCT2_CALLPROC_X(0x006D1EF0, 0, 0, 0, 0, 0, (int)&trackDesign->preview, 0);
- memcpy(trackDesign, (void*)0x009D8178, 163);
- RCT2_CALLPROC_EBPSAFE(0x006D1EF0);
-
- trackDesign->cost = RCT2_GLOBAL(0x00F4411D, money32);
- trackDesign->var_06 = RCT2_GLOBAL(0x00F44151, uint8) & 7;
+ trackDesign->track_td6.cost = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_COST, money32);
+ trackDesign->track_td6.var_06 = RCT2_GLOBAL(0x00F44151, uint8) & 7;
}
// Set preview to correct preview image based on rotation
if (preview != NULL)
- *preview = trackDesign->preview[RCT2_GLOBAL(0x00F440AE, uint8)];
+ *preview = trackDesign->preview[RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8)];
return trackDesign;
}
@@ -431,7 +1054,47 @@ rct_track_design *track_get_info(int index, uint8** preview)
*/
int track_rename(const char *text)
{
- return (RCT2_CALLPROC_X(0x006D3664, 0, 0, 0, (int)text, 0, 0, 0) & 0x100) != 0;
+ const char* txt_chr = text;
+
+ while (*txt_chr != '\0'){
+ switch (*txt_chr){
+ case '.':
+ case '/':
+ case '\\':
+ case '*':
+ case '?':
+ // Invalid characters
+ RCT2_GLOBAL(0x141E9AC, uint16) = 3353;
+ return 0;
+ }
+ txt_chr++;
+ }
+
+ char new_path[MAX_PATH];
+ subsitute_path(new_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), text);
+ strcat(new_path, ".TD6");
+
+ rct_window* w = window_find_by_class(WC_TRACK_DESIGN_LIST);
+
+ char old_path[MAX_PATH];
+ subsitute_path(old_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char)[128 * w->track_list.var_482]);
+
+ if (!platform_file_move(old_path, new_path)) {
+ RCT2_GLOBAL(0x141E9AC, uint16) = 3354;
+ return 0;
+ }
+
+ ride_list_item item = { 0xFC, 0 };
+ track_load_list(item);
+
+ item.type = RCT2_GLOBAL(0xF44158, uint8);
+ item.entry_index = RCT2_GLOBAL(0xF44159, uint8);
+ track_load_list(item);
+
+ reset_track_list_cache();
+
+ window_invalidate(w);
+ return 1;
}
/**
@@ -440,5 +1103,25 @@ int track_rename(const char *text)
*/
int track_delete()
{
- return (RCT2_CALLPROC_X(0x006D3761, 0, 0, 0, 0, 0, 0, 0) & 0x100) != 0;
-}
\ No newline at end of file
+ rct_window* w = window_find_by_class(WC_TRACK_DESIGN_LIST);
+
+ char path[MAX_PATH];
+ subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char)[128 * w->track_list.var_482]);
+
+ if (!platform_file_delete(path)) {
+ RCT2_GLOBAL(0x141E9AC, uint16) = 3355;
+ return 0;
+ }
+
+ ride_list_item item = { 0xFC, 0 };
+ track_load_list(item);
+
+ item.type = RCT2_GLOBAL(0xF44158, uint8);
+ item.entry_index = RCT2_GLOBAL(0xF44159, uint8);
+ track_load_list(item);
+
+ reset_track_list_cache();
+
+ window_invalidate(w);
+ return 1;
+}
diff --git a/src/ride/track.h b/src/ride/track.h
index b4c89ef6e8..2ab8bc6a84 100644
--- a/src/ride/track.h
+++ b/src/ride/track.h
@@ -23,6 +23,7 @@
#include "../common.h"
#include "ride.h"
+#include "../object.h"
typedef struct {
uint8 type;
@@ -34,21 +35,85 @@ typedef struct {
uint8 pad[2];
} rct_trackdefinition;
+/**
+* Size: 0x0A
+*/
+typedef struct {
+ uint8 var_00;
+ sint16 x;
+ sint16 y;
+ uint8 pad_05[3];
+ uint8 var_08;
+ uint8 unk_09;
+} rct_preview_track;
+
+/**
+* Size: 0x04
+*/
+typedef struct {
+ union {
+ uint32 all;
+ struct {
+ sint8 x;
+ sint8 y;
+ uint8 unk_2;
+ uint8 type;
+ };
+ };
+} rct_maze_element;
+
+/* Size: 0x02 */
+typedef struct{
+ uint8 type;
+ uint8 flags;
+}rct_track_element;
+
+enum{
+ TRACK_ELEMENT_FLAG_CHAIN_LIFT = (1<<7),
+ TRACK_ELEMENT_FLAG_INVERTED = (1<<6),
+ TRACK_ELEMENT_FLAG_TERMINAL_STATION = (1<<3),
+};
+
+#define TRACK_ELEMENT_FLAG_MAGNITUDE_MASK 0x0F
+#define TRACK_ELEMENT_FLAG_COLOUR_MASK 0x30
+#define TRACK_ELEMENT_FLAG_STATION_NO_MASK 0x02
+
#define TRACK_PREVIEW_IMAGE_SIZE (370 * 217)
+/* size: 0x2 */
+typedef struct{
+ uint8 body_colour;
+ uint8 trim_colour;
+} rct_track_vehicle_colour;
+
/**
* Track design structure.
* size: 0x4E72B
*/
typedef struct {
uint8 type; // 0x00
- uint8 pad_01;
+ uint8 vehicle_type;
money32 cost; // 0x02
uint8 var_06;
uint8 var_07;
- uint8 pad_08[0x42];
- uint8 total_air_time; // 0x4A
- uint8 pad_4B[0x06];
+ rct_track_vehicle_colour vehicle_colours[32]; // 0x08
+ union{
+ uint8 pad_48;
+ uint8 track_spine_colour_rct1; // 0x48
+ };
+ union{
+ uint8 entrance_style; // 0x49
+ uint8 track_rail_colour_rct1; // 0x49
+ };
+ union{
+ uint8 total_air_time; // 0x4A
+ uint8 track_support_colour_rct1; // 0x4A
+ };
+ uint8 pad_4B;
+ uint8 number_of_trains; // 0x4C
+ uint8 number_of_cars_per_train; // 0x4D
+ uint8 pad_4E[2];
+ uint8 var_50;
uint8 max_speed; // 0x51
uint8 average_speed; // 0x52
uint16 ride_length; // 0x53
@@ -64,15 +129,24 @@ typedef struct {
uint8 excitement; // 0x5B
uint8 intensity; // 0x5C
uint8 nausea; // 0x5D
- uint8 pad_5E[0x0E];
+ uint8 pad_5E[2];
+ uint8 track_spine_colour[4]; // 0x60
+ uint8 track_rail_colour[4]; // 0x64
+ uint8 track_support_colour[4]; // 0x68
uint32 var_6C;
- uint8 pad_70[0x10];
+ rct_object_entry vehicle_object; // 0x70
uint8 space_required_x; // 0x80
uint8 space_required_y; // 0x81
- uint8 pad_82[0x21];
+ uint8 vehicle_additional_colour[32]; // 0x82
+ uint8 var_A2;
+} rct_track_td6;
+
+typedef struct{
+ rct_track_td6 track_td6;
uint8 preview[4][TRACK_PREVIEW_IMAGE_SIZE]; // 0xA3
} rct_track_design;
+
enum {
TRACK_NONE = 0,
@@ -133,7 +207,10 @@ enum {
void track_load_list(ride_list_item item);
int sub_67726A(const char *path);
rct_track_design *track_get_info(int index, uint8** preview);
+rct_track_td6* load_track_design(const char *path);
int track_rename(const char *text);
int track_delete();
+void reset_track_list_cache();
+int sub_6D01B3(int bl, int x, int y, int z);
-#endif
\ No newline at end of file
+#endif
diff --git a/src/ride/track_data.c b/src/ride/track_data.c
new file mode 100644
index 0000000000..636cb95522
--- /dev/null
+++ b/src/ride/track_data.c
@@ -0,0 +1,280 @@
+/*****************************************************************************
+* Copyright (c) 2014 Ted John
+* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+*
+* This file is part of OpenRCT2.
+*
+* OpenRCT2 is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+*****************************************************************************/
+
+#include "track_data.h"
+
+const rct_track_coordinates TrackCoordinates[256] = {
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 64, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 32, 0, 0 },
+ { 0, 0, 0, 32, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 64, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 32, 0, 0, 0 },
+ { 0, 0, 32, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 3, 0, 0, -64, -64 },
+ { 0, 1, 0, 0, -64, 64 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 3, 0, 0, -64, -64 },
+ { 0, 1, 0, 0, -64, 64 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 3, 0, 64, -64, -64 },
+ { 0, 1, 0, 64, -64, 64 },
+ { 0, 3, 64, 0, -64, -64 },
+ { 0, 1, 64, 0, -64, 64 },
+ { 0, 0, 0, 0, -64, -32 },
+ { 0, 0, 0, 0, -64, 32 },
+ { 0, 0, 0, 0, -32, -32 },
+ { 0, 0, 0, 0, -32, 32 },
+ { 0, 3, 0, 0, -32, -32 },
+ { 0, 1, 0, 0, -32, 32 },
+ { 0, 3, 0, 0, -32, -32 },
+ { 0, 1, 0, 0, -32, 32 },
+ { 0, 3, 0, 32, -32, -32 },
+ { 0, 1, 0, 32, -32, 32 },
+ { 0, 3, 32, 0, -32, -32 },
+ { 0, 1, 32, 0, -32, 32 },
+ { 0, 3, 0, 0, 0, 0 },
+ { 0, 1, 0, 0, 0, 0 },
+ { 0, 0, 0, 16, -64, 0 },
+ { 0, 0, 0, 16, -64, 0 },
+ { 0, 0, 0, -16, -64, 0 },
+ { 0, 0, 0, -16, -64, 0 },
+ { 0, 2, 0, 152, -32, 0 },
+ { 0, 2, 0, -152, 32, 0 },
+ { 0, 3, 0, 80, -32, -32 },
+ { 0, 1, 0, 80, -32, 32 },
+ { 0, 3, 0, -80, -32, -32 },
+ { 0, 1, 0, -80, -32, 32 },
+ { 0, 0, 0, 24, 0, 0 },
+ { 0, 0, 0, 24, 0, 0 },
+ { 0, 0, 24, 0, 0, 0 },
+ { 0, 0, 24, 0, 0, 0 },
+ { 0, 0, 0, 96, 32, 0 },
+ { 0, 0, 0, 32, 32, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 64, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 32, 0, 0 },
+ { 0, 0, 0, 32, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 64, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 32, 0, 0, 0 },
+ { 0, 0, 32, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 3, 0, 0, -64, -64 },
+ { 0, 1, 0, 0, -64, 64 },
+ { 0, 0, 0, 0, -64, -32 },
+ { 0, 0, 0, 0, -64, 32 },
+ { 0, 3, 0, 0, -32, -32 },
+ { 0, 1, 0, 0, -32, 32 },
+ { 0, 2, 0, 16, 0, -96 },
+ { 0, 2, 0, 16, 0, 96 },
+ { 0, 2, 16, 0, 0, -96 },
+ { 0, 2, 16, 0, 0, 96 },
+ { 0, 2, 0, 16, 0, -160 },
+ { 0, 2, 0, 16, 0, 160 },
+ { 0, 2, 16, 0, 0, -160 },
+ { 0, 2, 16, 0, 0, 160 },
+ { 0, 3, 0, 64, 0, 0 },
+ { 0, 1, 0, 64, 0, 0 },
+ { 0, 3, 64, 0, 0, 0 },
+ { 0, 1, 64, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 3, 0, 16, -64, -64 },
+ { 0, 1, 0, 16, -64, 64 },
+ { 0, 3, 16, 0, -64, -64 },
+ { 0, 1, 16, 0, -64, 64 },
+ { 0, 3, 0, 16, -64, -64 },
+ { 0, 1, 0, 16, -64, 64 },
+ { 0, 3, 16, 0, -64, -64 },
+ { 0, 1, 16, 0, -64, 64 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 16, 16, -128, 0 },
+ { 0, 0, 0, 88, -96, 0 },
+ { 0, 0, 0, 88, -96, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 88, 0, -96, 0 },
+ { 0, 0, 88, 0, -96, 0 },
+ { 0, 0, 0, -96, -96, 0 },
+ { 0, 0, 0, 240, -160, 0 },
+ { 0, 0, 0, 80, 32, 0 },
+ { 0, 0, 0, 32, 32, 0 },
+ { 0, 0, 32, 0, 32, 0 },
+ { 0, 0, 0, 56, 32, 0 },
+ { 0, 0, 56, 0, 0, 0 },
+ { 0, 0, 0, 56, 0, 0 },
+ { 0, 0, 56, 0, 32, 0 },
+ { 0, 0, 24, 0, 0, 0 },
+ { 0, 7, 0, 0, -64, -32 },
+ { 0, 4, 0, 0, -64, 32 },
+ { 4, 0, 0, 0, -64, 32 },
+ { 4, 1, 0, 0, -32, 64 },
+ { 0, 7, 0, 0, -64, -32 },
+ { 0, 4, 0, 0, -64, 32 },
+ { 4, 0, 0, 0, -64, 32 },
+ { 4, 1, 0, 0, -32, 64 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 4, 4, 0, 16, -32, 32 },
+ { 4, 4, 0, 64, -32, 32 },
+ { 4, 4, 0, 8, -32, 32 },
+ { 4, 4, 0, 32, -32, 32 },
+ { 4, 4, 0, 32, -32, 32 },
+ { 4, 4, 0, 8, -32, 32 },
+ { 4, 4, 16, 0, -32, 32 },
+ { 4, 4, 64, 0, -32, 32 },
+ { 4, 4, 8, 0, -32, 32 },
+ { 4, 4, 32, 0, -32, 32 },
+ { 4, 4, 32, 0, -32, 32 },
+ { 4, 4, 8, 0, -32, 32 },
+ { 4, 4, 0, 24, -32, 32 },
+ { 4, 4, 0, 24, -32, 32 },
+ { 4, 4, 24, 0, -32, 32 },
+ { 4, 4, 24, 0, -32, 32 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 4, 4, 0, 8, -32, 32 },
+ { 4, 4, 0, 8, -32, 32 },
+ { 4, 4, 0, 8, -32, 32 },
+ { 4, 4, 0, 8, -32, 32 },
+ { 4, 4, 8, 0, -32, 32 },
+ { 4, 4, 8, 0, -32, 32 },
+ { 4, 4, 8, 0, -32, 32 },
+ { 4, 4, 8, 0, -32, 32 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 4, 4, 0, 0, -32, 32 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 32, -64, 0 },
+ { 0, 0, 0, 32, -64, 0 },
+ { 0, 0, 0, -32, -64, 0 },
+ { 0, 0, 0, -32, -64, 0 },
+ { 0, 3, 0, 24, -32, -32 },
+ { 0, 1, 0, 24, -32, 32 },
+ { 0, 3, 24, 0, -32, -32 },
+ { 0, 1, 24, 0, -32, 32 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 2, 0, 280, -64, -32 },
+ { 0, 2, 0, 280, -64, 32 },
+ { 0, 2, 0, -280, 64, -32 },
+ { 0, 2, 0, -280, 64, 32 },
+ { 0, 0, 0, -16, -64, 0 },
+ { 0, 0, 0, -16, -64, 0 },
+ { 0, 0, 0, 16, -64, 0 },
+ { 0, 0, 0, 16, -64, 0 },
+ { 0, 2, 0, 120, -32, 0 },
+ { 0, 2, 0, -120, 32, 0 },
+ { 0, 3, 0, 48, -32, -32 },
+ { 0, 1, 0, 48, -32, 32 },
+ { 0, 3, 0, -48, -32, -32 },
+ { 0, 1, 0, -48, -32, 32 },
+ { 0, 2, 0, 32, 0, 0 },
+ { 0, 2, 0, -32, 0, 0 },
+ { 0, 0, 0, 0, -160, 0 },
+ { 0, 0, 0, 0, -160, 0 },
+ { 0, 0, 0, 0, -32, 0 },
+ { 0, 0, 0, 0, -32, 0 },
+ { 0, 0, 0, 0, -32, 0 },
+ { 0, 1, 0, 0, -32, 32 },
+ { 0, 3, 0, 0, -32, -32 },
+ { 0, 2, 0, -96, -96, 0 },
+ { 0, 2, 0, 128, 64, 0 },
+ { 0, 2, 0, -128, -96, 0 },
+ { 0, 3, 0, 16, -32, -32 },
+ { 0, 1, 0, 16, -32, 32 },
+ { 0, 0, 0, 0, -64, 0 },
+ { 0, 0, 0, 0, -64, 0 },
+ { 0, 0, 0, 0, -32, 0 },
+ { 0, 0, 80, 0, 32, 0 },
+ { 0, 0, 240, 0, -160, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ { 0, 3, 0, 32, -32, -32 },
+ { 0, 1, 0, 32, -32, 32 },
+ { 0, 3, 32, 0, -32, -32 },
+ { 0, 1, 32, 0, -32, 32 },
+ { 0, 3, 0, 64, -64, -64 },
+ { 0, 1, 0, 64, -64, 64 },
+ { 0, 3, 64, 0, -64, -64 },
+ { 0, 1, 64, 0, -64, 64 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 0, 16, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 16, 0, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 0, 8, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 0, 8, 0, 0, 0 },
+ { 0, 3, 0, 96, 0, 32 },
+ { 0, 1, 0, 96, 0, -32 },
+ { 0, 3, 96, 0, 0, 32 },
+ { 0, 1, 96, 0, 0, -32 },
+ { 0, 2, 0, 96, 64, 0 },
+ { 0, 2, 0, -128, -96, 0 },
+ { 0, 2, 0, 128, 64, 0 }
+};
\ No newline at end of file
diff --git a/src/toolbar.h b/src/ride/track_data.h
similarity index 53%
rename from src/toolbar.h
rename to src/ride/track_data.h
index 4c216c99a4..c10ad9bd3d 100644
--- a/src/toolbar.h
+++ b/src/ride/track_data.h
@@ -17,31 +17,17 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*****************************************************************************/
+#include "../common.h"
-#ifndef _TOOLBAR_H_
-#define _TOOLBAR_H_
+/* size 0x0A */
+typedef struct{
+ sint8 rotation_negative; // 0x00
+ sint8 rotation_positive; // 0x01
+ sint16 z_negative; // 0x02
+ sint16 z_positive; // 0x04
+ sint16 x; // 0x06
+ sint16 y; // 0x08
+}rct_track_coordinates;
-#include "interface/window.h"
-#include "interface/widget.h"
-
-typedef enum {
- DDIDX_UNDERGROUND_INSIDE = 0,
- DDIDX_HIDE_BASE = 1,
- DDIDX_HIDE_VERTICAL = 2,
- DDIDX_SEETHROUGH_RIDES = 4,
- DDIDX_SEETHROUGH_SCENARY = 5,
- DDIDX_INVISIBLE_SUPPORTS = 6,
- DDIDX_INVISIBLE_PEEPS = 7,
- DDIDX_LAND_HEIGHTS = 9,
- DDIDX_TRACK_HEIGHTS = 10,
- DDIDX_PATH_HEIGHTS = 11,
-} TOP_TOOLBAR_VIEW_MENU_DDIDX;
-
-void top_toolbar_init_view_menu(rct_window* window, rct_widget* widget);
-void top_toolbar_view_menu_dropdown(short dropdownIndex);
-
-void toggle_footpath_window();
-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);
-#endif
+// 0x009968BB, 0x009968BC, 0x009968BD, 0x009968BF, 0x009968C1, 0x009968C3
+extern const rct_track_coordinates TrackCoordinates[256];
\ No newline at end of file
diff --git a/src/scenario.c b/src/scenario.c
index 465957c071..3a077fe5fc 100644
--- a/src/scenario.c
+++ b/src/scenario.c
@@ -39,6 +39,8 @@
#include "world/park.h"
#include "world/sprite.h"
+static int scenario_create_ducks();
+
/**
* Loads only the basic information from a scenario.
* rct2: 0x006761D6
@@ -271,13 +273,13 @@ int scenario_load_and_play_from_path(const char *path)
// Set park name
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_RENAME_PARK;
- game_do_command(1, 1, 0, *((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 0)), GAME_COMMAND_33,
+ game_do_command(1, 1, 0, *((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 0)), GAME_COMMAND_SET_PARK_NAME,
*((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 8)),
*((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 4)));
- game_do_command(2, 1, 0, *((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 12)), GAME_COMMAND_33,
+ game_do_command(2, 1, 0, *((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 12)), GAME_COMMAND_SET_PARK_NAME,
*((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 20)),
*((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 16)));
- game_do_command(0, 1, 0, *((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 24)), GAME_COMMAND_33,
+ game_do_command(0, 1, 0, *((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 24)), GAME_COMMAND_SET_PARK_NAME,
*((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 32)),
*((int*)(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER + 28)));
@@ -327,12 +329,11 @@ int scenario_load_and_play_from_path(const char *path)
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) |= PARK_FLAGS_18;
- RCT2_CALLPROC_EBPSAFE(0x006837E3); // (palette related)
+ load_palette();
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, uint16) = 0;
RCT2_GLOBAL(0x009DEA5C, uint16) = 62000; // (doesn't appear to ever be read)
-
return 1;
}
@@ -596,21 +597,24 @@ void scenario_update()
if ((current_days_in_month * next_month_tick) >> 16 != (current_days_in_month * month_tick) >> 16) {
// daily checks
- finance_update_daily_profit(); // daily profit update
+ finance_update_daily_profit();
RCT2_CALLPROC_EBPSAFE(0x0069C35E); // some kind of peeps days_visited update loop
get_local_time();
- RCT2_CALLPROC_EBPSAFE(0x0066A13C); // objective 6 dragging
- if (objective_type == 10 || objective_type == 9 || objective_type == 8 ||
- objective_type == 6 || objective_type == 5) {
+ RCT2_CALLPROC_EBPSAFE(0x0066A13C); // objective 6 dragging
+ switch (objective_type) {
+ case OBJECTIVE_REPLAY_LOAN_AND_PARK_VALUE:
+ case OBJECTIVE_FINISH_5_ROLLERCOASTERS:
+ case OBJECTIVE_10_ROLLERCOASTERS_LENGTH:
+ case OBJECTIVE_GUESTS_AND_RATING:
+ case OBJECTIVE_10_ROLLERCOASTERS:
scenario_objectives_check();
+ break;
}
window_invalidate_by_class(WC_BOTTOM_TOOLBAR);
}
-
- //if ( (unsigned int)((4 * current_day) & 0xFFFF) >= 0xFFEFu) {
- if ( next_month_tick % 0x4000 == 0) {
+ if (next_month_tick % 0x4000 == 0) {
// weekly checks
finance_pay_wages();
finance_pay_research();
@@ -621,18 +625,9 @@ void scenario_update()
ride_update_favourited_stat();
if (month <= 1 && RCT2_GLOBAL(0x009ADAE0, sint32) != -1 && RCT2_GLOBAL(0x009ADAE0 + 14, uint16) & 1) {
- for (int i = 0; i < 100; ++i) {
- int carry;
- RCT2_CALLPROC_EBPSAFE(0x006744A9); // clears carry flag on failure -.-
- #ifdef _MSC_VER
- __asm mov carry, 0;
- __asm adc carry, 0;
- #else
- __asm__ ( "mov %[carry], 0; " : [carry] "+m" (carry) );
- __asm__ ( "adc %[carry], 0; " : [carry] "+m" (carry) );
- #endif
-
- if (!carry)
+ // 100 attempts at finding some water to create a few ducks at
+ for (int i = 0; i < 100; i++) {
+ if (scenario_create_ducks())
break;
}
}
@@ -640,7 +635,6 @@ void scenario_update()
park_calculate_size();
}
- //if ( (unsigned int)((2 * current_day) & 0xFFFF) >= 0xFFF8) {
if (next_month_tick % 0x8000 == 0) {
// fortnightly
finance_pay_ride_upkeep();
@@ -656,13 +650,67 @@ void scenario_update()
scenario_entrance_fee_too_high_check();
award_update_all();
}
-
}
/**
-*
-* rct2: 0x006E37D2
-*/
+ *
+ * rct2: 0x006744A9
+ */
+static int scenario_create_ducks()
+{
+ int i, j, r, c, x, y, waterZ, centreWaterZ, x2, y2;
+
+ r = scenario_rand();
+ x = ((r >> 16) & 0xFFFF) & 0x7F;
+ y = (r & 0xFFFF) & 0x7F;
+ x = (x + 64) * 32;
+ y = (y + 64) * 32;
+
+ if (!map_is_location_in_park(x, y))
+ return 0;
+
+ centreWaterZ = (map_element_height(x, y) >> 16) & 0xFFFF;
+ if (centreWaterZ == 0)
+ return 0;
+
+ // Check 7x7 area around centre tile
+ x2 = x - (32 * 3);
+ y2 = y - (32 * 3);
+ c = 0;
+ for (i = 0; i < 7; i++) {
+ for (j = 0; j < 7; j++) {
+ waterZ = (map_element_height(x2, y2) >> 16) & 0xFFFF;
+ if (waterZ == centreWaterZ)
+ c++;
+
+ x2 += 32;
+ }
+ x2 -= 224;
+ y2 += 32;
+ }
+
+ // Must be at least 25 water tiles of the same height in 7x7 area
+ if (c < 25)
+ return 0;
+
+ // Set x, y to the centre of the tile
+ x += 16;
+ y += 16;
+ c = (scenario_rand() & 3) + 2;
+ for (i = 0; i < c; i++) {
+ r = scenario_rand();
+ x2 = (r >> 16) & 0x7F;
+ y2 = (r & 0xFFFF) & 0x7F;
+ create_duck(x + x2 - 64, y + y2 - 64);
+ }
+
+ return 1;
+}
+
+/**
+ *
+ * rct2: 0x006E37D2
+ */
unsigned int scenario_rand()
{
int eax = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32);
@@ -676,26 +724,22 @@ unsigned int scenario_rand()
*/
void scenario_prepare_rides_for_save()
{
- int i, x, y;
- rct_map_element *mapElement;
+ int i;
rct_ride *ride;
+ map_element_iterator it;
int isFiveCoasterObjective = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) == OBJECTIVE_FINISH_5_ROLLERCOASTERS;
// Set all existing track to be indestructible
- for (y = 0; y < 256; y++) {
- for (x = 0; x < 256; x++) {
- mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x);
- do {
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_TRACK) {
- if (isFiveCoasterObjective)
- mapElement->flags |= 0x40;
- else
- mapElement->flags &= ~0x40;
- }
- } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
+ map_element_iterator_begin(&it);
+ do {
+ if (map_element_get_type(it.element) == MAP_ELEMENT_TYPE_TRACK) {
+ if (isFiveCoasterObjective)
+ it.element->flags |= 0x40;
+ else
+ it.element->flags &= ~0x40;
}
- }
+ } while (map_element_iterator_next(&it));
// Set all existing rides to have indestructible track
FOR_ALL_RIDES(i, ride) {
@@ -725,7 +769,7 @@ int scenario_prepare_for_save()
}
if (s6Info->name[0] == 0)
- format_string(s6Info->name, RCT2_GLOBAL(0x013573D4, rct_string_id), (void*)0x013573D8);
+ format_string(s6Info->name, RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id), (void*)RCT2_ADDRESS_PARK_NAME_ARGS);
s6Info->objective_type = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8);
s6Info->objective_arg_1 = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_YEAR, uint8);
diff --git a/src/scenario_list.c b/src/scenario_list.c
index 8b7a26cc5f..a05868efb9 100644
--- a/src/scenario_list.c
+++ b/src/scenario_list.c
@@ -143,14 +143,24 @@ static void scenario_list_sort()
}
/**
-* Basic scenario information compare function for sorting.
-* rct2: 0x00677C08
-*/
+ * Basic scenario information compare function for sorting.
+ * rct2: 0x00677C08
+ */
static int scenario_list_sort_compare(const void *a, const void *b)
{
return strcmp(((rct_scenario_basic*)a)->name, ((rct_scenario_basic*)b)->name);
}
+/**
+ * Gets the path for the scenario scores path.
+ */
+static void scenario_scores_get_path(char *outPath)
+{
+ char *homePath = platform_get_orct2_homefolder();
+ sprintf(outPath, "%s%c%s", homePath, platform_get_path_separator(), "scores.dat");
+ free(homePath);
+}
+
/**
*
* rct2: 0x006775A8
@@ -158,6 +168,9 @@ static int scenario_list_sort_compare(const void *a, const void *b)
static int scenario_scores_load()
{
FILE *file;
+ char scoresPath[MAX_PATH];
+
+ scenario_scores_get_path(scoresPath);
// Free scenario list if already allocated
if (gScenarioList != NULL) {
@@ -166,10 +179,15 @@ static int scenario_scores_load()
}
// Try and load the scores file
- file = fopen(get_file_path(PATH_ID_SCORES), "rb");
+
+ // First check user folder and then fallback to install directory
+ file = fopen(scoresPath, "rb");
if (file == NULL) {
- RCT2_ERROR("Unable to load scenario scores.");
- return 0;
+ file = fopen(get_file_path(PATH_ID_SCORES), "rb");
+ if (file == NULL) {
+ RCT2_ERROR("Unable to load scenario scores.");
+ return 0;
+ }
}
// Load header
@@ -206,8 +224,11 @@ static int scenario_scores_load()
int scenario_scores_save()
{
FILE *file;
-
- file = fopen(get_file_path(PATH_ID_SCORES), "wb");
+ char scoresPath[MAX_PATH];
+
+ scenario_scores_get_path(scoresPath);
+
+ file = fopen(scoresPath, "wb");
if (file == NULL) {
RCT2_ERROR("Unable to save scenario scores.");
return 0;
diff --git a/src/title.c b/src/title.c
index 422a7c2b24..87380c673b 100644
--- a/src/title.c
+++ b/src/title.c
@@ -90,7 +90,9 @@ static void title_create_windows();
*/
void title_load()
{
- if (RCT2_GLOBAL(0x009DEA6E, uint8) & 1)
+ log_verbose("loading title");
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) & 1)
RCT2_CALLPROC_X(0x00667C15, 0, 1, 0, 0, 0, 0, 0);//Game pause toggle
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_TITLE_DEMO;
@@ -101,7 +103,7 @@ void title_load()
ride_init_all();
window_guest_list_init_vars_a();
sub_6BD3A4(); // RCT2_CALLPROC_EBPSAFE(0x006BD3A4);
- map_init();
+ map_init(150);
park_init();
date_reset();
climate_reset(CLIMATE_COOL_AND_WET);
@@ -117,6 +119,8 @@ void title_load()
title_init_showcase();
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, uint16) = 0;
+
+ log_verbose("loading title finished");
}
/**
@@ -167,9 +171,11 @@ static void title_update_showcase()
_scriptWaitCounter = (*_currentScript++) * 32;
break;
case TITLE_SCRIPT_LOAD:
- if (!scenario_load(get_file_path(PATH_ID_SIXFLAGS_MAGICMOUNTAIN))) {
- log_fatal("OpenRCT2 can not currently cope when unable to load title screen scenario.");
- exit(-1);
+ if (scenario_load(get_file_path(PATH_ID_SIXFLAGS_MAGICMOUNTAIN))) {
+ log_verbose("loaded title scenario");
+ } else {
+ load_palette();
+ title_create_windows();
}
w = window_get_main();
@@ -264,7 +270,7 @@ void title_update()
screenshot_check();
title_handle_keyboard_input();
- if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0) {
+ if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0) {
title_update_showcase();
game_logic_update();
start_title_music();//title_play_music();
diff --git a/src/toolbar.c b/src/toolbar.c
deleted file mode 100644
index b04aea397d..0000000000
--- a/src/toolbar.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*****************************************************************************
-* Copyright (c) 2014 Ted John
-* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
-*
-* This file is part of OpenRCT2.
-*
-* OpenRCT2 is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see .
-*****************************************************************************/
-
-#include "rct2.h"
-#include "addresses.h"
-#include "input.h"
-#include "toolbar.h"
-#include "localisation/string_ids.h"
-#include "interface/viewport.h"
-#include "interface/window.h"
-#include "windows/dropdown.h"
-
-/**
-*
-* rct2: 0x0066CDE4
-*/
-void top_toolbar_init_view_menu(rct_window* w, rct_widget* widget) {
- gDropdownItemsFormat[0] = 1156;
- gDropdownItemsFormat[1] = 1156;
- gDropdownItemsFormat[2] = 1156;
- gDropdownItemsFormat[3] = 0;
- gDropdownItemsFormat[4] = 1156;
- gDropdownItemsFormat[5] = 1156;
- gDropdownItemsFormat[6] = 1156;
- gDropdownItemsFormat[7] = 1156;
- gDropdownItemsFormat[8] = 0;
- gDropdownItemsFormat[9] = 1156;
- gDropdownItemsFormat[10] = 1156;
- gDropdownItemsFormat[11] = 1156;
-
- gDropdownItemsArgs[0] = STR_UNDERGROUND_VIEW;
- gDropdownItemsArgs[1] = STR_REMOVE_BASE_LAND;
- gDropdownItemsArgs[2] = STR_REMOVE_VERTICAL_FACES;
- gDropdownItemsArgs[4] = STR_SEE_THROUGH_RIDES;
- gDropdownItemsArgs[5] = STR_SEE_THROUGH_SCENERY;
- gDropdownItemsArgs[6] = STR_INVISIBLE_SUPPORTS;
- gDropdownItemsArgs[7] = STR_INVISIBLE_PEOPLE;
- gDropdownItemsArgs[9] = STR_HEIGHT_MARKS_ON_LAND;
- gDropdownItemsArgs[10] = STR_HEIGHT_MARKS_ON_RIDE_TRACKS;
- gDropdownItemsArgs[11] = STR_HEIGHT_MARKS_ON_PATHS;
-
- window_dropdown_show_text(
- w->x + widget->left,
- w->y + widget->top,
- widget->bottom - widget->top + 1,
- w->colours[1] | 0x80,
- 0,
- 12
- );
-
- // Set checkmarks
- rct_viewport* mainViewport = window_get_main()->viewport;
- if (mainViewport->flags & VIEWPORT_FLAG_UNDERGROUND_INSIDE)
- gDropdownItemsChecked |= (1 << 0);
- if (mainViewport->flags & VIEWPORT_FLAG_HIDE_BASE)
- gDropdownItemsChecked |= (1 << 1);
- if (mainViewport->flags & VIEWPORT_FLAG_HIDE_VERTICAL)
- gDropdownItemsChecked |= (1 << 2);
- if (mainViewport->flags & VIEWPORT_FLAG_SEETHROUGH_RIDES)
- gDropdownItemsChecked |= (1 << 4);
- if (mainViewport->flags & VIEWPORT_FLAG_SEETHROUGH_SCENERY)
- gDropdownItemsChecked |= (1 << 5);
- if (mainViewport->flags & VIEWPORT_FLAG_INVISIBLE_SUPPORTS)
- gDropdownItemsChecked |= (1 << 6);
- if (mainViewport->flags & VIEWPORT_FLAG_INVISIBLE_PEEPS)
- gDropdownItemsChecked |= (1 << 7);
- if (mainViewport->flags & VIEWPORT_FLAG_LAND_HEIGHTS)
- gDropdownItemsChecked |= (1 << 9);
- if (mainViewport->flags & VIEWPORT_FLAG_TRACK_HEIGHTS)
- gDropdownItemsChecked |= (1 << 10);
- if (mainViewport->flags & VIEWPORT_FLAG_PATH_HEIGHTS)
- gDropdownItemsChecked |= (1 << 11);
-
- RCT2_GLOBAL(0x9DEBA2, uint16) = 0;
-}
-
-/**
-*
-* rct2: 0x0066CF8A
-*/
-void top_toolbar_view_menu_dropdown(short dropdownIndex) {
- if (dropdownIndex == -1) dropdownIndex = RCT2_GLOBAL(0x9DEBA2, uint16);
- rct_window* w = window_get_main();
- if (w) {
- switch (dropdownIndex) {
- case DDIDX_UNDERGROUND_INSIDE:
- w->viewport->flags ^= VIEWPORT_FLAG_UNDERGROUND_INSIDE;
- break;
- case DDIDX_HIDE_BASE:
- w->viewport->flags ^= VIEWPORT_FLAG_HIDE_BASE;
- break;
- case DDIDX_HIDE_VERTICAL:
- w->viewport->flags ^= VIEWPORT_FLAG_HIDE_VERTICAL;
- break;
- case DDIDX_SEETHROUGH_RIDES:
- w->viewport->flags ^= VIEWPORT_FLAG_SEETHROUGH_RIDES;
- break;
- case DDIDX_SEETHROUGH_SCENARY:
- w->viewport->flags ^= VIEWPORT_FLAG_SEETHROUGH_SCENERY;
- break;
- case DDIDX_INVISIBLE_SUPPORTS:
- w->viewport->flags ^= VIEWPORT_FLAG_INVISIBLE_SUPPORTS;
- break;
- case DDIDX_INVISIBLE_PEEPS:
- w->viewport->flags ^= VIEWPORT_FLAG_INVISIBLE_PEEPS;
- break;
- case DDIDX_LAND_HEIGHTS:
- w->viewport->flags ^= VIEWPORT_FLAG_LAND_HEIGHTS;
- break;
- case DDIDX_TRACK_HEIGHTS:
- w->viewport->flags ^= VIEWPORT_FLAG_TRACK_HEIGHTS;
- break;
- case DDIDX_PATH_HEIGHTS:
- w->viewport->flags ^= VIEWPORT_FLAG_PATH_HEIGHTS;
- break;
- default:
- return;
- }
- window_invalidate(w);
- }
-}
-
-
-/**
-*
-* rct2: 0x0066CCE7
-*/
-void toggle_footpath_window() {
- if (window_find_by_class(WC_FOOTPATH) == NULL) {
- window_footpath_open();
- } else {
- tool_cancel();
- window_close_by_class(WC_FOOTPATH);
- }
-}
-
-/*
-*
-* rct2: 0x0066CD54
-*/
-void toggle_land_window(rct_window* topToolbar, int widgetIndex) {
- if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 7) {
- tool_cancel();
- } else {
- show_gridlines();
- tool_set(topToolbar, widgetIndex, 18);
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
- RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1;
- window_land_open();
- }
-}
-
-/*
-*
-* rct2: 0x0066CD0C
-*/
-void toggle_clear_scenery_window(rct_window* topToolbar, int widgetIndex) {
- if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 16) {
- tool_cancel();
- } else {
- show_gridlines();
- tool_set(topToolbar, widgetIndex, 12);
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
- RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 2;
- window_clear_scenery_open();
- }
-}
-
-/*
-*
-* rct2: 0x0066CD9C
-*/
-void toggle_water_window(rct_window* topToolbar, int widgetIndex) {
- if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 8) {
- tool_cancel();
- } else {
- show_gridlines();
- tool_set(topToolbar, widgetIndex, 19);
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
- RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1;
- window_water_open();
- }
-}
\ No newline at end of file
diff --git a/src/util/sawyercoding.c b/src/util/sawyercoding.c
index 221d7761fa..3e669ae6d3 100644
--- a/src/util/sawyercoding.c
+++ b/src/util/sawyercoding.c
@@ -412,3 +412,28 @@ static void encode_chunk_rotate(char *buffer, int length)
}
#pragma endregion
+
+int sawyercoding_detect_file_type(char *src, int length)
+{
+ int i;
+
+ // Currently can't detect TD4, as the checksum is the same as SC4 (need alternative method)
+
+ uint32 checksum = *((uint32*)&src[length - 4]);
+ uint32 actualChecksum = 0;
+ for (i = 0; i < length - 4; i++) {
+ actualChecksum = (actualChecksum & 0xFFFFFF00) | (((actualChecksum & 0xFF) + (uint8)src[i]) & 0xFF);
+ actualChecksum = rol32(actualChecksum, 3);
+ }
+
+ switch (checksum - actualChecksum) {
+ case +108156: return FILE_VERSION_RCT1 | FILE_TYPE_SV4;
+ case -108156: return FILE_VERSION_RCT1 | FILE_TYPE_SC4;
+ case +110001: return FILE_VERSION_RCT1_AA | FILE_TYPE_SV4;
+ case -110001: return FILE_VERSION_RCT1_AA | FILE_TYPE_SC4;
+ case +120001: return FILE_VERSION_RCT1_LL | FILE_TYPE_SV4;
+ case -120001: return FILE_VERSION_RCT1_LL | FILE_TYPE_SC4;
+ }
+
+ return -1;
+}
\ No newline at end of file
diff --git a/src/util/sawyercoding.h b/src/util/sawyercoding.h
index d7993d391a..f05727180f 100644
--- a/src/util/sawyercoding.h
+++ b/src/util/sawyercoding.h
@@ -35,6 +35,18 @@ enum {
CHUNK_ENCODING_ROTATE
};
+enum {
+ FILE_VERSION_MASK = (3 << 0),
+ FILE_VERSION_RCT1 = (0 << 0),
+ FILE_VERSION_RCT1_AA = (1 << 0),
+ FILE_VERSION_RCT1_LL = (2 << 0),
+
+ FILE_TYPE_MASK = (3 << 2),
+ FILE_TYPE_TD4 = (0 << 2),
+ FILE_TYPE_SV4 = (1 << 2),
+ FILE_TYPE_SC4 = (2 << 2)
+};
+
int sawyercoding_validate_checksum(FILE *file);
uint32 sawyercoding_calculate_checksum(uint8* buffer, uint32 length);
int sawyercoding_read_chunk(FILE *file, uint8 *buffer);
@@ -44,4 +56,6 @@ int sawyercoding_decode_sc4(char *src, char *dst, int length);
int sawyercoding_encode_sv4(char *src, char *dst, int length);
int sawyercoding_decode_td6(char *src, char *dst, int length);
+int sawyercoding_detect_file_type(char *src, int length);
+
#endif
diff --git a/src/util/util.c b/src/util/util.c
index 8abdaca2ca..dffbb8a5ee 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -75,4 +75,14 @@ int bitscanforward(int source)
return i;
return -1;
+}
+
+/* case insensitve compare */
+int strcicmp(char const *a, char const *b)
+{
+ for (;; a++, b++) {
+ int d = tolower(*a) - tolower(*b);
+ if (d != 0 || !*a)
+ return d;
+ }
}
\ No newline at end of file
diff --git a/src/util/util.h b/src/util/util.h
index 82098918be..ac62a3ad79 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -31,5 +31,6 @@ void path_set_extension(char *path, const char *extension);
long fsize(FILE *fp);
int bitscanforward(int source);
+int strcicmp(char const *a, char const *b);
#endif
diff --git a/src/windows/banner.c b/src/windows/banner.c
index 71ed90e51e..8f0ac1605f 100644
--- a/src/windows/banner.c
+++ b/src/windows/banner.c
@@ -136,13 +136,15 @@ void window_banner_open(rct_windownumber number)
int view_x = gBanners[w->number].x << 5;
int view_y = gBanners[w->number].y << 5;
- int ebp = ((view_y << 8) | view_x) >> 5;
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(ebp);
-
- while(1){
- if (((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_BANNER) &&
- (map_element->properties.banner.index == w->number)) break;
+ rct_map_element* map_element = map_get_first_element_at(view_x / 32, view_y / 32);
+ while(1) {
+ if (
+ (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_BANNER) &&
+ (map_element->properties.banner.index == w->number)
+ ) {
+ break;
+ }
map_element++;
}
@@ -186,10 +188,10 @@ static void window_banner_mouseup()
int x = banner->x << 5;
int y = banner->y << 5;
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(((y << 8) | x) >> 5);
+ rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32);
while (1){
- if (((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_BANNER) &&
+ if ((map_element_get_type(map_element) == MAP_ELEMENT_TYPE_BANNER) &&
(map_element->properties.banner.index == w->number)) break;
map_element++;
}
@@ -285,17 +287,13 @@ static void window_banner_dropdown()
text_buffer[0] = banner->text_colour + FORMAT_COLOUR_CODE_START;
- int string_id = 0, ebx = 0, ecx = 128, edx = 0, ebp = 0, esi = 0;
- // Allocate text_buffer to a new string_id?
- RCT2_CALLFUNC_X(0x6C421D, &string_id, &ebx, &ecx, &edx, &esi, (int*)&text_buffer, &ebp);
-
- if (string_id){
+ rct_string_id stringId = user_string_allocate(128, text_buffer);
+ if (stringId != 0) {
rct_string_id prev_string_id = banner->string_idx;
- banner->string_idx = string_id;
+ banner->string_idx = stringId;
user_string_free(prev_string_id);
window_invalidate(w);
- }
- else{
+ } else {
window_error_open(2984, RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id));
}
break;
@@ -322,16 +320,13 @@ static void window_banner_textinput()
text_buffer[0] = banner->text_colour + FORMAT_COLOUR_CODE_START;
strncpy(text_buffer + 1, text, 32);
- int string_id = 0, ebx = 0, ecx = 128, edx = 0, ebp = 0, esi = 0;
- RCT2_CALLFUNC_X(0x6C421D, &string_id, &ebx, &ecx, &edx, &esi, (int*)&text_buffer, &ebp);
-
- if (string_id){
+ rct_string_id stringId = user_string_allocate(128, text_buffer);
+ if (stringId) {
rct_string_id prev_string_id = banner->string_idx;
- banner->string_idx = string_id;
+ banner->string_idx = stringId;
user_string_free(prev_string_id);
window_invalidate(w);
- }
- else{
+ } else {
window_error_open(2984, RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id));
}
}
diff --git a/src/windows/cheats.c b/src/windows/cheats.c
index f41e3682a5..361e042f9e 100644
--- a/src/windows/cheats.c
+++ b/src/windows/cheats.c
@@ -23,6 +23,7 @@
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../localisation/localisation.h"
+#include "../world/park.h"
#include "../peep/peep.h"
#include "../ride/ride.h"
#include "../scenario.h"
@@ -288,42 +289,32 @@ static void cheat_set_grass_length(int length)
static void cheat_water_plants()
{
- int x, y;
- rct_map_element *mapElement;
+ map_element_iterator it;
- for (y = 0; y < 256; y++) {
- for (x = 0; x < 256; x++) {
- mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x);
- do {
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SCENERY) {
- mapElement->properties.scenery.age = 0;
- }
- } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
+ map_element_iterator_begin(&it);
+ do {
+ if (map_element_get_type(it.element) == MAP_ELEMENT_TYPE_SCENERY) {
+ it.element->properties.scenery.age = 0;
}
- }
+ } while (map_element_iterator_next(&it));
gfx_invalidate_screen();
}
static void cheat_fix_vandalism()
{
- int x, y;
- rct_map_element *mapElement;
+ map_element_iterator it;
- for (y = 0; y < 256; y++) {
- for (x = 0; x < 256; x++) {
- mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x);
- do {
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_PATH)
- continue;
+ map_element_iterator_begin(&it);
+ do {
+ if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_PATH)
+ continue;
- if ((mapElement->properties.path.additions & 0x0F) == 0)
- continue;
+ if ((it.element->properties.path.additions & 0x0F) == 0)
+ continue;
- mapElement->flags &= ~MAP_ELEMENT_FLAG_BROKEN;
- } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
- }
- }
+ it.element->flags &= ~MAP_ELEMENT_FLAG_BROKEN;
+ } while (map_element_iterator_next(&it));
gfx_invalidate_screen();
}
@@ -488,8 +479,7 @@ static void window_cheats_misc_mouseup()
w->widgets[widgetIndex].image = w->widgets[widgetIndex].image == 2767 ? 2768 : 2767;
break;
case WIDX_OPEN_CLOSE_PARK:
- game_do_command(0, 1, 0, park_is_open() ? 0 : 0x101, GAME_COMMAND_SET_PARK_OPEN, 0, 0);
- window_invalidate_by_class(WC_PARK_INFORMATION);
+ park_set_open(park_is_open() ? 0 : 1);
break;
case WIDX_DECREASE_GAME_SPEED:
game_reduce_game_speed();
@@ -685,20 +675,15 @@ void window_cheats_misc_tool_down(){
// in the middle of a tile.
dest_x += 16;
dest_y += 16;
+
// Set the tile coordinate to top left of tile
- int tile_y = dest_y & 0xFFE0;
- int tile_x = dest_x & 0xFFE0;
+ int tile_x = (dest_x & 0xFFE0) >> 5;
+ int tile_y = (dest_y & 0xFFE0) >> 5;
- ebp = ((tile_y << 8) | tile_x) >> 5;
-
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(ebp);
-
- while (1){
- if ((map_element->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_SURFACE){
- map_element->clearance_height = 0;
+ rct_map_element *mapElement = map_get_first_element_at(tile_x, tile_y);
+ do {
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SURFACE) {
+ mapElement->clearance_height = 0;
}
- if (map_element->flags & MAP_ELEMENT_FLAG_LAST_TILE)
- break;
- map_element++;
- }
+ } while (!map_element_is_last_for_tile(mapElement++));
}
\ No newline at end of file
diff --git a/src/windows/dropdown.c b/src/windows/dropdown.c
index a4cf76fc46..2a02739add 100644
--- a/src/windows/dropdown.c
+++ b/src/windows/dropdown.c
@@ -150,6 +150,14 @@ void window_dropdown_show_text_custom_width(int x, int y, int extray, uint8 colo
// Set the widgets
gDropdownNumItems = num_items;
_dropdown_num_rows = num_items;
+
+ width = _dropdown_item_width * _dropdown_num_columns + 3;
+ int height = _dropdown_item_height * _dropdown_num_rows + 3;
+ if (x + width > RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16))
+ x = max(0, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) - width);
+ if (y + height > RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16))
+ y = max(0, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16) - height);
+
window_dropdown_widgets[WIDX_BACKGROUND].bottom = _dropdown_item_height * num_items + 3;
window_dropdown_widgets[WIDX_BACKGROUND].right = _dropdown_item_width + 3;
diff --git a/src/windows/editor_bottom_toolbar.c b/src/windows/editor_bottom_toolbar.c
index 71033da7db..934b6e0920 100644
--- a/src/windows/editor_bottom_toolbar.c
+++ b/src/windows/editor_bottom_toolbar.c
@@ -28,12 +28,12 @@
#include "../interface/viewport.h"
#include "../interface/widget.h"
#include "../interface/window.h"
-#include "../platform/osinterface.h"
+#include "../platform/platform.h"
#include "../title.h"
#include "../util/util.h"
#include "error.h"
-enum WINDOW_EDITOR_TOP_TOOLBAR_WIDGET_IDX {
+enum {
WIDX_PREVIOUS_IMAGE, // 1
WIDX_PREVIOUS_STEP_BUTTON, // 2
WIDX_NEXT_IMAGE, // 4
@@ -166,8 +166,8 @@ void window_editor_bottom_toolbar_jump_back_to_object_selection() {
*/
void window_editor_bottom_toolbar_jump_back_to_landscape_editor() {
window_close_all();
- RCT2_CALLPROC(0x006DFED0);
- RCT2_CALLPROC(0x006DFEE4);
+ RCT2_CALLPROC_EBPSAFE(0x006DFED0);
+ RCT2_CALLPROC_EBPSAFE(0x006DFEE4);
g_editor_step = EDITOR_STEP_LANDSCAPE_EDITOR;
window_map_open();
gfx_invalidate_screen();
@@ -274,7 +274,7 @@ static int show_save_scenario_dialog(char *resultPath)
format_string(filterName, STR_RCT2_SCENARIO_FILE, NULL);
pause_sounds();
- result = osinterface_open_common_file_dialog(0, title, filename, "*.SC6", filterName);
+ result = platform_open_common_file_dialog(0, title, filename, "*.SC6", filterName);
unpause_sounds();
if (result)
diff --git a/src/windows/editor_inventions_list.c b/src/windows/editor_inventions_list.c
index 0d94c6f080..fc2fd22967 100644
--- a/src/windows/editor_inventions_list.c
+++ b/src/windows/editor_inventions_list.c
@@ -19,13 +19,13 @@
*****************************************************************************/
#include "../addresses.h"
+#include "../cursors.h"
#include "../input.h"
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../localisation/localisation.h"
#include "../management/research.h"
#include "../object.h"
-#include "../platform/osinterface.h"
#include "../world/scenery.h"
#pragma region Widgets
diff --git a/src/windows/editor_main.c b/src/windows/editor_main.c
index d1231efaea..a9635b4e47 100644
--- a/src/windows/editor_main.c
+++ b/src/windows/editor_main.c
@@ -87,7 +87,7 @@ void window_editor_main_open()
RCT2_GLOBAL(0x009E32B3, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_TYPE, uint8) = 0;
- window_editor_top_toolbar_open();
+ window_top_toolbar_open();
window_editor_bottom_toolbar_open();
}
diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c
index b7f21646c2..df902e41ee 100644
--- a/src/windows/editor_object_selection.c
+++ b/src/windows/editor_object_selection.c
@@ -19,33 +19,75 @@
*****************************************************************************/
#include "../addresses.h"
+#include "../audio/audio.h"
#include "../game.h"
#include "../interface/widget.h"
#include "../interface/window.h"
+#include "../localisation/localisation.h"
#include "../object.h"
+#include "../ride/track.h"
+#include "error.h"
+
+enum {
+ WINDOW_OBJECT_SELECTION_PAGE_RIDE_VEHICLES_ATTRACTIONS,
+ WINDOW_OBJECT_SELECTION_PAGE_SMALL_SCENERY,
+ WINDOW_OBJECT_SELECTION_PAGE_LARGE_SCENERY,
+ WINDOW_OBJECT_SELECTION_PAGE_WALLS_FENCES,
+ WINDOW_OBJECT_SELECTION_PAGE_PATH_SIGNS,
+ WINDOW_OBJECT_SELECTION_PAGE_FOOTPATHS,
+ WINDOW_OBJECT_SELECTION_PAGE_PATH_EXTRAS,
+ WINDOW_OBJECT_SELECTION_PAGE_SCENERY_GROUPS,
+ WINDOW_OBJECT_SELECTION_PAGE_PARK_ENTRANCE,
+ WINDOW_OBJECT_SELECTION_PAGE_WATER,
+ WINDOW_OBJECT_SELECTION_PAGE_SCENARIO_DESCRIPTION,
+ WINDOW_OBJECT_SELECTION_PAGE_COUNT
+};
#pragma region Widgets
enum WINDOW_STAFF_LIST_WIDGET_IDX {
- WIDX_EDITOR_OBJECT_SELECTION_BACKGROUND, // 0, 1
- WIDX_EDITOR_OBJECT_SELECTION_TITLE, // 1, 2
- WIDX_EDITOR_OBJECT_SELECTION_CLOSE, // 2, 4
- WIDX_EDITOR_OBJECT_SELECTION_TAB_CONTENT_PANEL, // 3, 8
- WIDX_EDITOR_OBJECT_SELECTION_TAB_1, // 4, 10
- WIDX_EDITOR_OBJECT_SELECTION_TAB_2, // 5, 20
- WIDX_EDITOR_OBJECT_SELECTION_TAB_3, // 6, 40
- WIDX_EDITOR_OBJECT_SELECTION_TAB_4, // 7, 80
- WIDX_EDITOR_OBJECT_SELECTION_TAB_5, // 8, 100
- WIDX_EDITOR_OBJECT_SELECTION_TAB_6, // 9, 200
- WIDX_EDITOR_OBJECT_SELECTION_TAB_7, // 10, 400
- WIDX_EDITOR_OBJECT_SELECTION_TAB_8, // 11, 800
- WIDX_EDITOR_OBJECT_SELECTION_TAB_9, // 12, 1000
- WIDX_EDITOR_OBJECT_SELECTION_TAB_10, // 13, 2000
- WIDX_EDITOR_OBJECT_SELECTION_TAB_11, // 14, 4000
- WIDX_EDITOR_OBJECT_SELECTION_DROPDOWN1, // 15, 8000
- WIDX_EDITOR_OBJECT_SELECTION_LIST, // 16, 10000
- WIDX_EDITOR_OBJECT_SELECTION_FLATBTN, // 17, 20000
- WIDX_EDITOR_OBJECT_SELECTION_DROPDOWN2, // 18, 40000
+ WIDX_BACKGROUND, // 0, 1
+ WIDX_TITLE, // 1, 2
+ WIDX_CLOSE, // 2, 4
+ WIDX_TAB_CONTENT_PANEL, // 3, 8
+ WIDX_TAB_1, // 4, 10
+ WIDX_TAB_2, // 5, 20
+ WIDX_TAB_3, // 6, 40
+ WIDX_TAB_4, // 7, 80
+ WIDX_TAB_5, // 8, 100
+ WIDX_TAB_6, // 9, 200
+ WIDX_TAB_7, // 10, 400
+ WIDX_TAB_8, // 11, 800
+ WIDX_TAB_9, // 12, 1000
+ WIDX_TAB_10, // 13, 2000
+ WIDX_TAB_11, // 14, 4000
+ WIDX_DROPDOWN1, // 15, 8000
+ WIDX_LIST, // 16, 10000
+ WIDX_PREVIEW, // 17, 20000
+ WIDX_DROPDOWN2, // 18, 40000
+};
+
+static rct_widget window_editor_object_selection_widgets[] = {
+ { WWT_FRAME, 0, 0, 599, 0, 399, 0xFFFFFFFF, STR_NONE },
+ { WWT_CAPTION, 0, 1, 598, 1, 14, 3181, STR_WINDOW_TITLE_TIP },
+ { WWT_CLOSEBOX, 0, 587, 597, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
+ { WWT_RESIZE, 1, 0, 599, 43, 399, 0xFFFFFFFF, STR_NONE },
+ { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 1812 },
+ { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 1812 },
+ { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, 1812 },
+ { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, 1812 },
+ { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, 1812 },
+ { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, 1812 },
+ { WWT_TAB, 1, 189, 219, 17, 43, 0x2000144E, 1812 },
+ { WWT_TAB, 1, 220, 250, 17, 43, 0x2000144E, 1812 },
+ { WWT_TAB, 1, 251, 281, 17, 43, 0x2000144E, 1812 },
+ { WWT_TAB, 1, 282, 312, 17, 43, 0x2000144E, 1812 },
+ { WWT_TAB, 1, 313, 343, 17, 43, 0x2000144E, 1812 },
+ { WWT_DROPDOWN_BUTTON, 0, 470, 591, 23, 34, STR_OBJECT_SELECTION_ADVANCED, STR_OBJECT_SELECTION_ADVANCED_TIP },
+ { WWT_SCROLL, 1, 4, 291, 46, 386, 2, STR_NONE },
+ { WWT_FLATBTN, 1, 391, 504, 46, 159, 0xFFFFFFFF, STR_NONE },
+ { WWT_DROPDOWN_BUTTON, 0, 384, 595, 24, 35, STR_INSTALL_NEW_TRACK_DESIGN, STR_INSTALL_NEW_TRACK_DESIGN_TIP },
+ { WIDGETS_END }
};
#pragma endregion
@@ -54,10 +96,18 @@ enum WINDOW_STAFF_LIST_WIDGET_IDX {
static void window_editor_object_selection_emptysub() { }
+static void window_editor_object_selection_close();
static void window_editor_object_selection_mouseup();
+static void window_editor_object_selection_scrollgetsize();
+static void window_editor_object_selection_scroll_mousedown();
+static void window_editor_object_selection_scroll_mouseover();
+static void window_editor_object_selection_tooltip();
+static void window_editor_object_selection_invalidate();
+static void window_editor_object_selection_paint();
+static void window_editor_object_selection_scrollpaint();
static void* window_editor_object_selection_events[] = {
- (void*)0x006AB199,
+ window_editor_object_selection_close,
(void*)window_editor_object_selection_mouseup,
(void*)window_editor_object_selection_emptysub,
(void*)window_editor_object_selection_emptysub,
@@ -72,24 +122,71 @@ static void* window_editor_object_selection_events[] = {
(void*)window_editor_object_selection_emptysub,
(void*)window_editor_object_selection_emptysub,
(void*)window_editor_object_selection_emptysub,
- (void*)0x006AB031,
- (void*)0x006AB0B6,
+ (void*)window_editor_object_selection_scrollgetsize,
+ (void*)window_editor_object_selection_scroll_mousedown,
(void*)window_editor_object_selection_emptysub,
- (void*)0x006AB079,
+ (void*)window_editor_object_selection_scroll_mouseover,
(void*)window_editor_object_selection_emptysub,
(void*)window_editor_object_selection_emptysub,
(void*)window_editor_object_selection_emptysub,
- (void*)0x006AB058,
+ (void*)window_editor_object_selection_tooltip,
(void*)window_editor_object_selection_emptysub,
(void*)window_editor_object_selection_emptysub,
- (void*)0x006AA9FD,
- (void*)0x006AAB56,
- (void*)0x006AADA3
+ (void*)window_editor_object_selection_invalidate,
+ (void*)window_editor_object_selection_paint,
+ (void*)window_editor_object_selection_scrollpaint
};
#pragma endregion
static void window_editor_object_set_page(rct_window *w, int page);
+static void window_editor_object_selection_set_pressed_tab(rct_window *w);
+static void window_editor_object_selection_select_default_objects();
+static int window_editor_object_selection_select_object(int flags, rct_object_entry *entry);
+static int get_object_from_object_selection(uint8 object_type, int y, uint8 *object_selection_flags, rct_object_entry **installed_entry);
+static void window_editor_object_selection_manage_tracks();
+static void editor_load_selected_objects();
+
+static rct_object_entry DefaultSelectedObjects[] = {
+ // Objects that are always required
+ { 0x00000087, { "SCGTREES" }, 0 }, // Scenery: Trees
+ { 0x00000087, { "SCGSHRUB" }, 0 }, // Scenery: Shrubs and Ornaments
+ { 0x00000087, { "SCGGARDN" }, 0 }, // Scenery: Gardens
+ { 0x00000087, { "SCGFENCE" }, 0 }, // Scenery: Fences and Walls
+ { 0x00000087, { "SCGWALLS" }, 0 }, // Scenery: Walls and Roofs
+ { 0x00000087, { "SCGPATHX" }, 0 }, // Scenery: Signs and Items for Footpaths
+ { 0x00000085, { "TARMAC " }, 0 }, // Footpath: Tarmac
+
+ // An initial default selection
+ { 0x000080FF, { "TWIST1 " }, 0 }, // Ride: Twist
+ { 0x00008000, { "PTCT1 " }, 0 }, // Ride: Wooden Roller Coaster (Wooden Roller Coaster Trains)
+ { 0x00008000, { "ZLDB " }, 0 }, // Ride: Junior Roller Coaster (Ladybird Trains)
+ { 0x00008000, { "LFB1 " }, 0 }, // Ride: Log Flume
+ { 0x00008000, { "VCR " }, 0 }, // Ride: Vintage Cars
+ { 0x00008000, { "MGR1 " }, 0 }, // Ride: Merry-Go-Round
+ { 0x00008000, { "TLT1 " }, 0 }, // Ride: Restroom
+ { 0x00008000, { "ATM1 " }, 0 }, // Ride: Cash Machine
+ { 0x00008000, { "FAID1 " }, 0 }, // Ride: First Aid Room
+ { 0x00008000, { "INFOK " }, 0 }, // Ride: Information Kiosk
+ { 0x00008000, { "DRNKS " }, 0 }, // Ride: Drinks Stall
+ { 0x00008000, { "CNDYF " }, 0 }, // Ride: Cotten Candy Stall
+ { 0x00008000, { "BURGB " }, 0 }, // Ride: Burger Bar
+ { 0x00008000, { "BALLN " }, 0 }, // Ride: Balloon Stall
+ { 0x00008000, { "ARRT1 " }, 0 }, // Ride: Corkscrew Roller Coaster
+ { 0x00008000, { "RBOAT " }, 0 }, // Ride: Rowing Boats
+ { 0x00008800, { "PKENT1 " }, 0 }, // Park Entrace: Traditional Park Entrance
+ { 0x00008900, { "WTRCYAN " }, 0 }, // Water: Natural Water
+ { 0x00008500, { "TARMACB " }, 0 }, // Footpath: Brown Tarmac Footpath
+ { 0x00008500, { "PATHSPC " }, 0 }, // Footpath: Space Style Footpath
+ { 0x00008500, { "PATHDIR " }, 0 }, // Footpath: Dirt Footpath
+ { 0x00008500, { "PATHCRZ " }, 0 }, // Footpath: Crazy Paving Footpath
+ { 0x00008500, { "PATHASH " }, 0 }, // Footpath: Ash Footpath
+
+ // The following are for all random map generation features to work out the box
+ { 0x00000087, { "SCGJUNGL" }, 0 }, // Jungle Themeing
+ { 0x00000087, { "SCGSNOW " }, 0 }, // Snow and Ice Themeing
+ { 0x00000087, { "SCGWATER" }, 0 } // Water Feature Themeing
+};
/**
*
@@ -106,6 +203,10 @@ void window_editor_object_selection_open()
RCT2_CALLPROC_EBPSAFE(0x006AB211);
RCT2_CALLPROC_EBPSAFE(0x006AA770);
+ // Not really where its called, but easy way to change default objects for now
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR)
+ window_editor_object_selection_select_default_objects();
+
window = window_create(
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2 - 300,
max(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) / 2 - 200, 28),
@@ -115,14 +216,14 @@ void window_editor_object_selection_open()
WC_EDITOR_OBJECT_SELECTION,
WF_STICK_TO_FRONT
);
- window->widgets = (rct_widget*)0x009ADB00;
+ window->widgets = window_editor_object_selection_widgets;
window->enabled_widgets =
- (1 << WIDX_EDITOR_OBJECT_SELECTION_DROPDOWN1) |
- (1 << WIDX_EDITOR_OBJECT_SELECTION_DROPDOWN2) |
- (1 << WIDX_EDITOR_OBJECT_SELECTION_CLOSE);
+ (1 << WIDX_DROPDOWN1) |
+ (1 << WIDX_DROPDOWN2) |
+ (1 << WIDX_CLOSE);
- for (int i = WIDX_EDITOR_OBJECT_SELECTION_TAB_1; i <= WIDX_EDITOR_OBJECT_SELECTION_TAB_11; i++)
+ for (int i = WIDX_TAB_1; i <= WIDX_TAB_11; i++)
window->enabled_widgets |= (1LL << i);
window_init_scroll_widgets(window);
@@ -135,6 +236,35 @@ void window_editor_object_selection_open()
window->colours[2] = 1;
}
+/**
+ *
+ * rct2: 0x006AB199
+ */
+static void window_editor_object_selection_close()
+{
+ rct_window* w;
+ window_get_register(w);
+
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) &
+ (SCREEN_FLAGS_SCENARIO_EDITOR |
+ SCREEN_FLAGS_TRACK_DESIGNER |
+ SCREEN_FLAGS_TRACK_MANAGER))
+ )return;
+
+ RCT2_CALLPROC_EBPSAFE(0x6ABB66);
+ editor_load_selected_objects();
+ sub_6A9FC0();
+ object_free_scenario_text();
+ RCT2_CALLPROC_EBPSAFE(0x6AB316);
+ RCT2_CALLPROC_EBPSAFE(0x685675);
+ RCT2_CALLPROC_EBPSAFE(0x68585B);
+ window_new_ride_init_vars();
+}
+
+/**
+ *
+ * rct2: 0x006AAFAB
+ */
static void window_editor_object_selection_mouseup()
{
rct_window *w;
@@ -143,33 +273,33 @@ static void window_editor_object_selection_mouseup()
window_widget_get_registers(w, widgetIndex);
switch (widgetIndex) {
- case WIDX_EDITOR_OBJECT_SELECTION_CLOSE:
+ case WIDX_CLOSE:
game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 1, 0);
break;
- case WIDX_EDITOR_OBJECT_SELECTION_TAB_1:
- case WIDX_EDITOR_OBJECT_SELECTION_TAB_2:
- case WIDX_EDITOR_OBJECT_SELECTION_TAB_3:
- case WIDX_EDITOR_OBJECT_SELECTION_TAB_4:
- case WIDX_EDITOR_OBJECT_SELECTION_TAB_5:
- case WIDX_EDITOR_OBJECT_SELECTION_TAB_6:
- case WIDX_EDITOR_OBJECT_SELECTION_TAB_7:
- case WIDX_EDITOR_OBJECT_SELECTION_TAB_8:
- case WIDX_EDITOR_OBJECT_SELECTION_TAB_9:
- case WIDX_EDITOR_OBJECT_SELECTION_TAB_10:
- case WIDX_EDITOR_OBJECT_SELECTION_TAB_11:
- window_editor_object_set_page(w, widgetIndex - WIDX_EDITOR_OBJECT_SELECTION_TAB_1);
+ case WIDX_TAB_1:
+ case WIDX_TAB_2:
+ case WIDX_TAB_3:
+ case WIDX_TAB_4:
+ case WIDX_TAB_5:
+ case WIDX_TAB_6:
+ case WIDX_TAB_7:
+ case WIDX_TAB_8:
+ case WIDX_TAB_9:
+ case WIDX_TAB_10:
+ case WIDX_TAB_11:
+ window_editor_object_set_page(w, widgetIndex - WIDX_TAB_1);
break;
- case WIDX_EDITOR_OBJECT_SELECTION_DROPDOWN1:
+ case WIDX_DROPDOWN1:
w->list_information_type ^= 1;
window_invalidate(w);
break;
- case WIDX_EDITOR_OBJECT_SELECTION_DROPDOWN2:
+ case WIDX_DROPDOWN2:
if (w->selected_list_item != -1) {
w->selected_list_item = -1;
- RCT2_CALLPROC_EBPSAFE(0x006A982D); // object_free_scenario_text();
+ object_free_scenario_text();
}
window_invalidate(w);
@@ -183,6 +313,409 @@ static void window_editor_object_selection_mouseup()
}
}
+/**
+ *
+ * rct2: 0x006AB031
+ */
+static void window_editor_object_selection_scrollgetsize()
+{
+ rct_window *w;
+ short scrollIndex;
+ int numItems, width, height;
+
+ window_scroll_get_registers(w, scrollIndex);
+
+ numItems = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER) ?
+ RCT2_GLOBAL(0x00F43412, uint16) :
+ RCT2_ADDRESS(0x00F433E1, uint16)[w->selected_tab];
+
+ width = 0;
+ height = numItems * 12;
+ window_scrollsize_set_registers(width, height);
+}
+
+/**
+ *
+ * rct2: 0x006AB0B6
+ */
+static void window_editor_object_selection_scroll_mousedown()
+{
+ short x, y, scrollIndex;
+ rct_window *w;
+
+ window_scrollmouse_get_registers(w, scrollIndex, x, y);
+
+ uint8 object_selection_flags;
+ rct_object_entry* installed_entry;
+ int selected_object = get_object_from_object_selection((w->selected_tab & 0xFF), y, &object_selection_flags, &installed_entry);
+ if (selected_object == -1 || (object_selection_flags & 0x20))
+ return;
+
+ window_invalidate(w);
+
+ sound_play_panned(SOUND_CLICK_1, RCT2_GLOBAL(0x142406C,uint32), 0, 0, 0);
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
+ if (!window_editor_object_selection_select_object(1, installed_entry))
+ return;
+
+ window_close(w);
+
+ //This function calls window_track_list_open
+ window_editor_object_selection_manage_tracks();
+ return;
+ }
+
+ int ebx = 6;
+ // If already selected
+ if (!(object_selection_flags & 1))
+ ebx = 7;
+
+ RCT2_GLOBAL(0xF43411, uint8) = 0;
+ if (!window_editor_object_selection_select_object(ebx, installed_entry)) {
+ rct_string_id error_title = ebx & 1 ?
+ STR_UNABLE_TO_SELECT_THIS_OBJECT :
+ STR_UNABLE_TO_DE_SELECT_THIS_OBJECT;
+
+ window_error_open(error_title, RCT2_GLOBAL(0x141E9AC, uint16));
+ return;
+ }
+
+ if (!RCT2_GLOBAL(0xF43411, uint8) & 1)
+ return;
+
+ window_error_open(STR_WARNING_TOO_MANY_OBJECTS_SELECTED, STR_NOT_ALL_OBJECTS_IN_THIS_SCENERY_GROUP_COULD_BE_SELECTED);
+}
+
+/**
+ *
+ * rct2: 0x006AB079
+ */
+static void window_editor_object_selection_scroll_mouseover()
+{
+ rct_window *w;
+ rct_object_entry *installedEntry;
+ int selectedObject;
+ short x, y, scrollIndex;
+ uint8 objectSelectionFlags;
+
+ window_scrollmouse_get_registers(w, scrollIndex, x, y);
+
+ selectedObject = get_object_from_object_selection(
+ w->selected_tab & 0xFF, y, &objectSelectionFlags, &installedEntry
+ );
+ if (objectSelectionFlags & 0x20)
+ selectedObject = -1;
+
+ if (selectedObject == w->selected_list_item)
+ return;
+
+ w->selected_list_item = selectedObject;
+ w->var_494 = (uint32)installedEntry;
+ object_free_scenario_text();
+ if (selectedObject != -1)
+ object_get_scenario_text(installedEntry);
+
+ window_invalidate(w);
+}
+
+/**
+ *
+ * rct2: 0x006AB058
+ */
+static void window_editor_object_selection_tooltip()
+{
+ rct_window *w;
+ short widgetIndex;
+
+ window_scroll_get_registers(w, widgetIndex);
+
+ switch (widgetIndex) {
+ case WIDX_TAB_1:
+ case WIDX_TAB_2:
+ case WIDX_TAB_3:
+ case WIDX_TAB_4:
+ case WIDX_TAB_5:
+ case WIDX_TAB_6:
+ case WIDX_TAB_7:
+ case WIDX_TAB_8:
+ case WIDX_TAB_9:
+ case WIDX_TAB_10:
+ case WIDX_TAB_11:
+ RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_string_id) =
+ STR_OBJECT_SELECTION_RIDE_VEHICLES_ATTRACTIONS + (widgetIndex - WIDX_TAB_1);
+ break;
+ default:
+ RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_string_id) = STR_LIST;
+ break;
+ }
+}
+
+/**
+ *
+ * rct2: 0x006AA9FD
+ */
+static void window_editor_object_selection_invalidate()
+{
+ int i, x;
+ rct_window *w;
+ rct_widget *widget;
+
+ window_get_register(w);
+
+ // Set pressed widgets
+ w->pressed_widgets |= 1 << WIDX_PREVIEW;
+ window_editor_object_selection_set_pressed_tab(w);
+ if (w->list_information_type & 1)
+ w->pressed_widgets |= (1 << WIDX_DROPDOWN1);
+ else
+ w->pressed_widgets &= ~(1 << WIDX_DROPDOWN1);
+
+ // Set window title and buttons
+ RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_string_id) = STR_OBJECT_SELECTION_RIDE_VEHICLES_ATTRACTIONS + w->selected_tab;
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
+ w->widgets[WIDX_TITLE].image = STR_TRACK_DESIGNS_MANAGER_SELECT_RIDE_TYPE;
+ w->widgets[WIDX_CLOSE].type = WWT_EMPTY;
+ w->widgets[WIDX_DROPDOWN2].type = WWT_DROPDOWN_BUTTON;
+ } else if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) {
+ w->widgets[WIDX_TITLE].image = STR_ROLLER_COASTER_DESIGNER_SELECT_RIDE_TYPES_VEHICLES;
+ w->widgets[WIDX_CLOSE].type = WWT_CLOSEBOX;
+ w->widgets[WIDX_DROPDOWN2].type = WWT_EMPTY;
+ } else {
+ w->widgets[WIDX_TITLE].image = STR_OBJECT_SELECTION;
+ w->widgets[WIDX_CLOSE].type = WWT_CLOSEBOX;
+ w->widgets[WIDX_DROPDOWN2].type = WWT_EMPTY;
+ }
+
+ // Align tabs, hide advanced ones
+ x = 3;
+ for (i = 0; i < WINDOW_OBJECT_SELECTION_PAGE_COUNT; i++) {
+ widget = &w->widgets[WIDX_TAB_1 + i];
+
+ if (!(w->list_information_type & 1) && ((1 << i) & 0x5E)) {
+ widget->type = WWT_EMPTY;
+ } else {
+ widget->type = WWT_TAB;
+ widget->left = x;
+ widget->right = x + 30;
+ x += 31;
+ }
+ }
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_TRACK_MANAGER | SCREEN_FLAGS_TRACK_DESIGNER)) {
+ w->widgets[WIDX_DROPDOWN1].type = WWT_EMPTY;
+ for (i = 1; i < WINDOW_OBJECT_SELECTION_PAGE_COUNT; i++)
+ w->widgets[WIDX_TAB_1 + i].type = WWT_EMPTY;
+ x = 150;
+ } else {
+ w->widgets[WIDX_DROPDOWN1].type = WWT_DROPDOWN_BUTTON;
+ x = 300;
+ }
+
+ w->widgets[WIDX_LIST].right = 587 - x;
+ w->widgets[WIDX_PREVIEW].left = 537 - (x >> 1);
+ w->widgets[WIDX_PREVIEW].right = w->widgets[WIDX_PREVIEW].left + 113;
+}
+
+/**
+ *
+ * rct2: 0x006AAB56
+ */
+static void window_editor_object_selection_paint()
+{
+ int i, x, y, width, numSelected, totalSelectable, type;
+ rct_window *w;
+ rct_drawpixelinfo *dpi;
+ rct_widget *widget;
+ rct_object_entry *highlightedEntry;
+ rct_string_id stringId;
+ uint8 *text;
+ char *datName, *name, *stringBuffer;
+
+ window_paint_get_registers(w, dpi);
+
+ window_draw_widgets(w, dpi);
+
+ // Draw tabs
+ for (i = 0; i < WINDOW_OBJECT_SELECTION_PAGE_COUNT; i++) {
+ widget = &w->widgets[WIDX_TAB_1 + i];
+ if (widget->type == WWT_EMPTY)
+ continue;
+
+ x = w->x + widget->left;
+ y = w->y + widget->top;
+ gfx_draw_sprite(dpi, 5458 + i, x, y, 0);
+ }
+
+ // Preview background
+ widget = &w->widgets[WIDX_PREVIEW];
+ gfx_fill_rect(
+ dpi,
+ w->x + widget->left + 1,
+ w->y + widget->top + 1,
+ w->x + widget->right - 1,
+ w->y + widget->bottom - 1,
+ RCT2_ADDRESS(0x0141FC44, uint8)[w->colours[1] * 8]
+ );
+
+ // Draw number of selected items
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER)) {
+ x = w->x + 3;
+ y = w->y + w->height - 12;
+
+ numSelected = RCT2_ADDRESS(0x00F433F7, uint16)[w->selected_tab];
+ totalSelectable = object_entry_group_counts[w->selected_tab];
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER)
+ totalSelectable = 4;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = numSelected;
+ RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = totalSelectable;
+ gfx_draw_string_left(dpi, 3164, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y);
+ }
+
+ if (w->selected_list_item == -1 || RCT2_GLOBAL(0x009ADAF8, sint32) == -1)
+ return;
+
+ highlightedEntry = (rct_object_entry*)w->var_494;
+ type = highlightedEntry->flags & 0x0F;
+
+ // Draw preview
+ widget = &w->widgets[WIDX_PREVIEW];
+ x = w->x + (widget->left + widget->right) / 2 + 1;
+ y = w->y + (widget->top + widget->bottom) / 2 + 1;
+ object_paint(type, 3, type, x, y, 0, (int)dpi, RCT2_GLOBAL(0x009ADAF8, sint32));
+
+ // Draw name of object
+ x = w->x + (widget->left + widget->right) / 2 + 1;
+ y = w->y + widget->bottom + 3;
+ width = w->width - w->widgets[WIDX_LIST].right - 6;
+
+ // Skip object dat name
+ text = (char*)(highlightedEntry + 1);
+ datName = text;
+ do {
+ text++;
+ } while (*(text - 1) != 0);
+ text += 4;
+ name = text;
+
+ RCT2_GLOBAL(0x009BC677, uint8) = 14;
+
+ stringId = 3165;
+ stringBuffer = (char*)language_get_string(3165) + 1;
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER)) {
+ // Skip name
+ do {
+ text++;
+ } while (*(text - 1) != 0);
+ text += 4;
+ text += *text++ * 16;
+ text += *text++ * 16;
+
+ if (RCT2_GLOBAL(text, uint32) & 0x1000000) {
+ strcpy(stringBuffer, name);
+ } else {
+ int eax = *text;
+ if (*text == 0xFF) {
+ eax = *(text + 1);
+ if (*(text + 1) == 0xFF)
+ eax = *(text + 2);
+ }
+ format_string(stringBuffer, eax + 2, NULL);
+ }
+ } else {
+ strcpy(stringBuffer, name);
+ }
+ gfx_draw_string_centred_clipped(dpi, stringId, NULL, 0, x, y, width);
+
+ // Draw description of object
+ x = w->x + w->widgets[WIDX_LIST].right + 4;
+ y += 15;
+ object_paint(type, 259, type, x, y, (int)w, (int)dpi, RCT2_GLOBAL(0x009ADAF8, sint32));
+
+ // Draw object dat name
+ strcpy(stringBuffer, datName);
+ gfx_draw_string_right(dpi, stringId, NULL, 0, w->x + w->width - 5, w->y + w->height - 3 - 12);
+}
+
+/**
+ *
+ * rct2: 0x006AADA3
+ */
+static void window_editor_object_selection_scrollpaint()
+{
+ int x, y, i, colour, colour2, numObjects, type;
+ short scrollIndex;
+ rct_object_entry *entry;
+ rct_window *w;
+ rct_drawpixelinfo *dpi;
+ uint8 *itemFlags;
+
+ window_scrollpaint_get_registers(w, dpi, scrollIndex);
+
+ colour = RCT2_ADDRESS(0x0141FC48, uint8)[w->colours[1] * 8];
+ colour = (colour << 24) | (colour << 16) | (colour << 8) | colour;
+ gfx_clear(dpi, colour);
+
+ numObjects = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, sint32);
+ entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
+ itemFlags = RCT2_GLOBAL(0x009ADAEC, uint8*);
+ y = 0;
+ for (i = 0; i < numObjects; i++) {
+ type = entry->flags & 0x0F;
+ if (type == w->selected_tab && !(*itemFlags & 0x20)) {
+ if (y + 12 >= dpi->y && y <= dpi->y + dpi->height) {
+ // Draw checkbox
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) && !(*itemFlags & 0x20))
+ gfx_fill_rect_inset(dpi, 2, y, 11, y + 10, w->colours[1], 0xE0);
+
+ // Highlight background
+ colour = 142;
+ if (entry == (rct_object_entry*)w->var_494 && !(*itemFlags & 0x20)) {
+ gfx_fill_rect(dpi, 0, y, w->width, y + 11, 0x2000031);
+ colour = 14;
+ }
+
+ // Draw checkmark
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) && (*itemFlags & 1)) {
+ x = 2;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16) = colour == 14 ? -2 : -1;
+ colour2 = w->colours[1] & 0x7F;
+ if (*itemFlags & 0x1C)
+ colour2 |= 0x40;
+
+ gfx_draw_string(dpi, (char*)0x009DED72, colour2, x, y);
+ }
+
+ // Draw text
+ char *buffer = (char*)0x0141ED68;
+ *buffer = colour;
+ strcpy(buffer + 1, object_get_name(entry));
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
+ while (*buffer != 0 && *buffer != 9)
+ buffer++;
+
+ *buffer = 0;
+ }
+
+ if (*itemFlags & 0x20) {
+ colour = w->colours[1] & 0x7F;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16) = -1;
+ } else {
+ colour = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16) = 224;
+ }
+ x = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER ? 0 : 15;
+ gfx_draw_string(dpi, (char*)0x0141ED68, colour, x, y);
+ }
+ y += 12;
+ }
+
+ entry = object_get_next(entry);
+ itemFlags++;
+ }
+}
+
static void window_editor_object_set_page(rct_window *w, int page)
{
if (w->selected_tab == page)
@@ -192,6 +725,133 @@ static void window_editor_object_set_page(rct_window *w, int page)
w->selected_list_item = -1;
w->var_494 = 0xFFFFFFFF;
w->scrolls[0].v_top = 0;
- RCT2_CALLPROC_EBPSAFE(0x006A982D); // object_free_scenario_text();
+ object_free_scenario_text();
window_invalidate(w);
+}
+
+static void window_editor_object_selection_set_pressed_tab(rct_window *w)
+{
+ int i;
+ for (i = 0; i < WINDOW_OBJECT_SELECTION_PAGE_COUNT; i++)
+ w->pressed_widgets &= ~(1 << (WIDX_TAB_1 + i));
+ w->pressed_widgets |= 1LL << (WIDX_TAB_1 + w->selected_tab);
+}
+
+/**
+ *
+ * rct2: 0x006AA7E9
+ */
+static void window_editor_object_selection_select_default_objects()
+{
+ int i;
+
+ if (RCT2_GLOBAL(0x00F433F7, uint16) == 0)
+ return;
+
+ for (i = 0; i < countof(DefaultSelectedObjects); i++)
+ window_editor_object_selection_select_object(7, &DefaultSelectedObjects[i]);
+}
+
+/**
+ *
+ * rct2: 0x006AB54F
+ */
+static int window_editor_object_selection_select_object(int flags, rct_object_entry *entry)
+{
+ return (RCT2_CALLPROC_X(0x006AB54F, 0, flags, 0, 0, 0, 0, (int)entry) & 0x100) == 0;
+}
+
+/**
+ * Takes the y coordinate of the clicked on scroll list
+ * and converts this into an object selection.
+ * Returns the position in the list.
+ * Object_selection_flags, installed_entry also populated
+ *
+ * rct2: 0x006AA703
+ */
+static int get_object_from_object_selection(uint8 object_type, int y, uint8 *object_selection_flags, rct_object_entry **installed_entry)
+{
+ *installed_entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
+ uint8* selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*);
+ int object_count = 0;
+ for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){
+ if (((*installed_entry)->flags & 0xF) == object_type){
+ if (!(*selection_flags & 0x20)){
+ y -= 12;
+ *object_selection_flags = *selection_flags;
+ if (y < 0)return object_count;
+ object_count++;
+ }
+ }
+
+ *installed_entry = object_get_next(*installed_entry);
+ selection_flags++;
+ }
+ return -1;
+}
+
+/**
+ *
+ * rct2: 0x006D33E2
+ */
+static void window_editor_object_selection_manage_tracks()
+{
+ RCT2_GLOBAL(0x1357404, sint32) = -1;
+ RCT2_GLOBAL(0x1357408, sint32) = -1;
+ RCT2_GLOBAL(0x135740C, sint32) = -1;
+ RCT2_GLOBAL(0x1357410, sint32) = -1;
+
+ for (int i = 0; i < 128; ++i){
+ RCT2_ADDRESS(0x1357444, uint32)[i] = RCT2_ADDRESS(0x97C468, uint32)[i];
+ RCT2_ADDRESS(0x1357644, uint32)[i] = RCT2_ADDRESS(0x97C5D4, uint32)[i];
+ }
+
+ for (int i = 0; i < 8; ++i){
+ RCT2_ADDRESS(0x1357424, sint32)[i] = -1;
+ }
+
+ RCT2_GLOBAL(0x141F570, uint8) = 7;
+
+ int entry_index = 0;
+ for (; ((int)object_entry_groups[0].chunks[entry_index]) == -1; ++entry_index);
+
+ RCT2_GLOBAL(0xF44157, uint8) = entry_index;
+
+ rct_ride_type* ride_entry = GET_RIDE_ENTRY(entry_index);
+ uint8* ride_type_array = &ride_entry->var_00C;
+
+ int ride_type;
+ for (int i = 0; (ride_type = ride_type_array[i]) == 0xFF; i++);
+ RCT2_GLOBAL(0xF44158, uint8) = ride_type;
+
+ ride_list_item item = { ride_type, entry_index };
+ track_load_list(item);
+ window_track_list_open(item);
+}
+
+/**
+ *
+ * rct2: 0x006ABBBE
+ */
+static void editor_load_selected_objects()
+{
+ uint8 *selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*);
+ rct_object_entry *installed_entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) == 0)
+ return;
+
+ for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i != 0; i--, selection_flags++) {
+ if (*selection_flags & 1) {
+ uint8 entry_index, entry_type;
+ if (!find_object_in_entry_group(installed_entry, &entry_type, &entry_index)){
+ int chunk_size;
+ if (!object_load(-1, installed_entry, &chunk_size)) {
+ log_error("Failed to load entry %.8s", installed_entry->name);
+ }
+ }
+ }
+
+ installed_entry = object_get_next(installed_entry);
+ }
}
\ No newline at end of file
diff --git a/src/windows/editor_objective_options.c b/src/windows/editor_objective_options.c
index 7d3ae9863b..d417c30436 100644
--- a/src/windows/editor_objective_options.c
+++ b/src/windows/editor_objective_options.c
@@ -25,6 +25,7 @@
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../scenario.h"
+#include "../world/park.h"
#include "dropdown.h"
#include "error.h"
@@ -230,6 +231,15 @@ static uint64 window_editor_objective_options_page_enabled_widgets[] = {
(1 << WIDX_TAB_2)
};
+static uint64 window_editor_objective_options_page_hold_down_widgets[] = {
+ (1 << WIDX_OBJECTIVE_ARG_1_INCREASE) |
+ (1 << WIDX_OBJECTIVE_ARG_1_DECREASE) |
+ (1 << WIDX_OBJECTIVE_ARG_2_INCREASE) |
+ (1 << WIDX_OBJECTIVE_ARG_2_DECREASE),
+
+ 0
+};
+
#pragma endregion
/**
@@ -254,12 +264,12 @@ void window_editor_objective_options_open()
WF_10
);
w->widgets = window_editor_objective_options_main_widgets;
- w->enabled_widgets = window_editor_objective_options_page_enabled_widgets[0];
+ w->enabled_widgets = window_editor_objective_options_page_enabled_widgets[WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN];
w->pressed_widgets = 0;
- w->var_020 = 0x00003600;
+ w->hold_down_widgets = window_editor_objective_options_page_hold_down_widgets[WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN];
window_init_scroll_widgets(w);
w->var_4AE = 0;
- w->selected_tab = 0;
+ w->selected_tab = WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN;
w->no_list_items = 0;
w->selected_list_item = -1;
RCT2_CALLPROC_X(0x00672609, 0, 0, 0, 0, (int)w, 0, 0);
@@ -327,7 +337,7 @@ static void window_editor_objective_options_set_page(rct_window *w, int page)
w->no_list_items = 0;
w->selected_list_item = -1;
w->enabled_widgets = window_editor_objective_options_page_enabled_widgets[page];
- w->var_020 = page == WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN ? 0x3600 : 0;
+ w->hold_down_widgets = window_editor_objective_options_page_hold_down_widgets[page];
w->event_handlers = window_editor_objective_options_page_events[page];
w->widgets = window_editor_objective_options_widgets[page];
window_invalidate(w);
@@ -405,7 +415,7 @@ static void window_editor_objective_options_main_mouseup()
break;
case WIDX_PARK_NAME:
RCT2_GLOBAL(0x013CE962, uint32) = RCT2_GLOBAL(0x013573D8, uint32);
- window_text_input_open(w, WIDX_PARK_NAME, STR_PARK_NAME, STR_ENTER_PARK_NAME, RCT2_GLOBAL(0x013573D4, rct_string_id), 0, 32);
+ window_text_input_open(w, WIDX_PARK_NAME, STR_PARK_NAME, STR_ENTER_PARK_NAME, RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id), 0, 32);
break;
case WIDX_SCENARIO_NAME:
strcpy((char*)0x009BC677, s6Info->name);
@@ -799,13 +809,10 @@ static void window_editor_objective_options_main_textinput()
switch (widgetIndex) {
case WIDX_PARK_NAME:
- RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_RENAME_PARK;
- game_do_command(1, 1, 0, *((int*)(text + 0)), GAME_COMMAND_33, *((int*)(text + 8)), *((int*)(text + 4)));
- game_do_command(2, 1, 0, *((int*)(text + 12)), GAME_COMMAND_33, *((int*)(text + 20)), *((int*)(text + 16)));
- game_do_command(0, 1, 0, *((int*)(text + 24)), GAME_COMMAND_33, *((int*)(text + 32)), *((int*)(text + 28)));
+ park_set_name(text);
if (s6Info->name[0] == 0)
- format_string(s6Info->name, RCT2_GLOBAL(0x013573D4, uint16), (void*)0x013573D8);
+ format_string(s6Info->name, RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id), (void*)RCT2_ADDRESS_PARK_NAME_ARGS);
break;
case WIDX_SCENARIO_NAME:
strncpy(s6Info->name, text, 64);
@@ -1018,7 +1025,7 @@ static void window_editor_objective_options_main_paint()
if (stex != NULL) {
RCT2_GLOBAL(0x013CE952 + 0, uint16) = stex->park_name;
} else {
- RCT2_GLOBAL(0x013CE952 + 0, uint16) = RCT2_GLOBAL(0x013573D4, uint16);
+ RCT2_GLOBAL(0x013CE952 + 0, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id);
}
RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x0013573D8, uint32);
gfx_draw_string_left_clipped(dpi, 3298, (void*)0x013CE952, 0, x, y, width);
diff --git a/src/windows/editor_scenario_options.c b/src/windows/editor_scenario_options.c
index fecd939559..9ce4e60535 100644
--- a/src/windows/editor_scenario_options.c
+++ b/src/windows/editor_scenario_options.c
@@ -319,7 +319,7 @@ static uint64 window_editor_scenario_options_page_enabled_widgets[] = {
0x007F7B74
};
-static uint32 dword_9A9DE8[] = {
+static uint32 window_editor_scenario_options_page_hold_down_widgets[] = {
0x000DB600,
0x0006DB00,
0x00031B00
@@ -350,7 +350,7 @@ void window_editor_scenario_options_open()
);
w->widgets = window_editor_scenario_options_widgets[0];
w->enabled_widgets = window_editor_scenario_options_page_enabled_widgets[0];
- w->var_020 = dword_9A9DE8[0];
+ w->hold_down_widgets = window_editor_scenario_options_page_hold_down_widgets[0];
window_init_scroll_widgets(w);
w->var_4AE = 0;
w->page = 0;
@@ -422,7 +422,7 @@ static void window_editor_scenario_options_set_page(rct_window *w, int page)
w->frame_no = 0;
w->var_492 = 0;
w->enabled_widgets = window_editor_scenario_options_page_enabled_widgets[page];
- w->var_020 = dword_9A9DE8[page];
+ w->hold_down_widgets = window_editor_scenario_options_page_hold_down_widgets[page];
w->event_handlers = window_editor_scenario_options_page_events[page];
w->widgets = window_editor_scenario_options_widgets[page];
window_invalidate(w);
diff --git a/src/windows/editor_top_toolbar.c b/src/windows/editor_top_toolbar.c
deleted file mode 100644
index 936e532458..0000000000
--- a/src/windows/editor_top_toolbar.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/*****************************************************************************
-* Copyright (c) 2014 Dániel Tar, Ted John
-* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
-*
-* This file is part of OpenRCT2.
-*
-* OpenRCT2 is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see .
-*****************************************************************************/
-
-#include "../addresses.h"
-#include "../localisation/string_ids.h"
-#include "../sprites.h"
-#include "../game.h"
-#include "../editor.h"
-#include "../toolbar.h"
-#include "../interface/viewport.h"
-#include "../interface/widget.h"
-#include "../interface/window.h"
-#include "dropdown.h"
-
-enum WINDOW_EDITOR_TOP_TOOLBAR_WIDGET_IDX {
- WIDX_PAUSE, // 0, 1
- WIDX_FILE_MENU, // 1, 2
- WIDX_ZOOM_OUT, // 2, 4
- WIDX_ZOOM_IN, // 3, 8
- WIDX_ROTATE, // 4, 10
- WIDX_VIEW_MENU, // 5, 20
- WIDX_MAP, // 6, 40
- WIDX_LAND, // 7, 80
- WIDX_WATER, // 8, 100
- WIDX_SCENERY, // 9, 200
- WIDX_PATH, // 10, 400
- WIDX_CONSTRUCT_RIDE, // 11, 800
- WIDX_UNUSED1, // 12, 1000
- WIDX_UNUSED2, // 13, 2000
- WIDX_UNUSED3, // 14, 4000
- WIDX_UNUSED4, // 15, 8000
- WIDX_CLEAR_SCENERY, // 16, 10000
-};
-
-typedef enum {
- DDIDX_SE_LOAD_LANDSCAPE = 0,
- DDIDX_SE_SAVE_LANDSCAPE = 1,
- DDIDX_SE_ABOUT = 3,
- DDIDX_SE_OPTIONS = 4,
- DDIDX_SE_SCREENSHOT = 5,
- DDIDX_SE_QUIT_GAME = 7,
-} SCENARIO_EDITOR_FILE_MENU_DDIDX;
-
-typedef enum {
- DDIDX_TD_ABOUT = 0,
- DDIDX_TD_OPTIONS = 1,
- DDIDX_TD_SCREENSHOT = 2,
- DDIDX_TD_QUIT_GAME = 4,
-} TRACK_DESINGER_FILE_MENU_DDIDX;
-
-static rct_widget window_editor_top_toolbar_widgets[] = {
- { WWT_EMPTY, 0, 0, 0, 0, 0, 0xFFFFFFFF, 0xFFFF }, // 1 0x009A9844
- { WWT_TRNBTN, 0, 0, 29, 0, 27, 0x20000000 | SPR_TOOLBAR_FILE, STR_DISC_AND_GAME_OPTIONS_TIP }, // 2 0x009A9854
- { WWT_TRNBTN, 1, 40, 69, 0, 27, 0x20000000 | SPR_TOOLBAR_ZOOM_OUT, STR_ZOOM_OUT_TIP }, // 4 0x009A9864
- { WWT_TRNBTN, 1, 70, 99, 0, 27, 0x20000000 | SPR_TOOLBAR_ZOOM_IN, STR_ZOOM_IN_TIP }, // 8 0x009A9874
- { WWT_TRNBTN, 1, 100, 129, 0, 27, 0x20000000 | SPR_TOOLBAR_ROTATE, STR_ROTATE_TIP }, // 10 0x009A9884
- { WWT_TRNBTN, 1, 130, 159, 0, 27, 0x20000000 | SPR_TOOLBAR_VIEW, STR_VIEW_OPTIONS_TIP }, // 20 0x009A9894
- { WWT_TRNBTN, 1, 160, 189, 0, 27, 0x20000000 | SPR_TOOLBAR_MAP, STR_SHOW_MAP_TIP }, // 40 0x009A98A4
- { WWT_TRNBTN, 2, 267, 296, 0, 27, 0x20000000 | SPR_TOOLBAR_LAND, STR_ADJUST_LAND_TIP }, // 80 0x009A98B4
- { WWT_TRNBTN, 2, 297, 326, 0, 27, 0x20000000 | SPR_TOOLBAR_WATER, STR_ADJUST_WATER_TIP }, // 100 0x009A98C4
- { WWT_TRNBTN, 2, 327, 356, 0, 27, 0x20000000 | SPR_TOOLBAR_SCENERY, STR_PLACE_SCENERY_TIP }, // 200 0x009A98D4
- { WWT_TRNBTN, 2, 357, 386, 0, 27, 0x20000000 | SPR_TOOLBAR_FOOTPATH, STR_BUILD_FOOTPATH_TIP }, // 400 0x009A98E4
- { WWT_TRNBTN, 2, 387, 416, 0, 27, 0x20000000 | SPR_TOOLBAR_CONSTRUCT_RIDE, STR_BUILD_RIDE_TIP }, // 800 0x009A98F4
- { WWT_EMPTY, 0, 0, 0, 0, 0, 0xFFFFFFFF, 0xFFFF }, // 1000 0x009A9904
- { WWT_EMPTY, 0, 0, 0, 0, 0, 0xFFFFFFFF, 0xFFFF }, // 2000 0x009A9914
- { WWT_EMPTY, 0, 0, 0, 0, 0, 0xFFFFFFFF, 0xFFFF }, // 4000 0x009A9924
- { WWT_EMPTY, 0, 0, 0, 0, 0, 0xFFFFFFFF, 0xFFFF }, // 8000 0x009A9934
- { WWT_TRNBTN, 2, 560, 589, 0, 27, 0x20000000 | SPR_TOOLBAR_CLEAR_SCENERY, STR_CLEAR_SCENERY_TIP }, // 10000 0x009A9944
- { WIDGETS_END },
-};
-
-static void window_editor_top_toolbar_emptysub() { }
-
-static void window_editor_top_toolbar_mouseup();
-static void window_editor_top_toolbar_resize();
-static void window_editor_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
-static void window_editor_top_toolbar_dropdown();
-static void window_editor_top_toolbar_invalidate();
-static void window_editor_top_toolbar_paint();
-
-static void* window_editor_top_toolbar_events[] = {
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_mouseup, //(void*)0x0066f9d7, // mouseup
- window_editor_top_toolbar_resize, //(void*)0x0066fada, // resize
- window_editor_top_toolbar_mousedown, //(void*)0x0066fa57, // mousedown
- window_editor_top_toolbar_dropdown, //(void*)0x0066fa38, // dropdown
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- (void*)0x0066fb0e,
- (void*)0x0066fb5c,
- (void*)0x0066fb37,
- (void*)0x0066fc44,
- (void*)0x0066fa74,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_emptysub,
- window_editor_top_toolbar_invalidate, // (void*)0x0066f87d, // oninvalidate
- window_editor_top_toolbar_paint, //(void*)0x0066f9d1, // onpaint
- window_editor_top_toolbar_emptysub
-};
-
-/**
-* Creates the main editor top toolbar window.
-* rct2: 0x0066EFC8 (part of 0x0066EF38)
-*/
-void window_editor_top_toolbar_open()
-{
- rct_window* window;
-
- window = window_create(0, 0, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16), 28,
- (uint32*)window_editor_top_toolbar_events,
- WC_TOP_TOOLBAR, WF_STICK_TO_FRONT | WF_TRANSPARENT | WF_5);
- window->widgets = window_editor_top_toolbar_widgets;
-
- window->enabled_widgets |=
- (1 << WIDX_ZOOM_IN) |
- (1 << WIDX_ZOOM_OUT) |
- (1 << WIDX_ROTATE) |
- (1 << WIDX_FILE_MENU) |
- (1 << WIDX_LAND) |
- (1 << WIDX_VIEW_MENU) |
- (1 << WIDX_SCENERY) |
- (1 << WIDX_WATER) |
- (1 << WIDX_PATH) |
- (1 << WIDX_MAP) |
- (1 << WIDX_CONSTRUCT_RIDE) |
- (1 << WIDX_CLEAR_SCENERY);
-
- window_init_scroll_widgets(window);
- window->colours[0] = 7;
- window->colours[1] = 12;
- window->colours[2] = 24;
- window->colours[3] = 1;
-}
-
-/**
-*
-* rct2: 0x0066C957
-*/
-static void window_editor_top_toolbar_mouseup()
-{
- short widgetIndex;
- rct_window *w, *mainWindow;
-
- window_widget_get_registers(w, widgetIndex);
-
- switch (widgetIndex) {
- case WIDX_ZOOM_IN:
- if ((mainWindow = window_get_main()) != NULL)
- window_zoom_in(mainWindow);
- break;
- case WIDX_ZOOM_OUT:
- if ((mainWindow = window_get_main()) != NULL)
- window_zoom_out(mainWindow);
- break;
- case WIDX_ROTATE:
- if ((mainWindow = window_get_main()) != NULL)
- window_rotate_camera(mainWindow);
- break;
- case WIDX_SCENERY:
- if (!tool_set(w, WIDX_SCENERY, 0)) {
- RCT2_GLOBAL(0x009DE518, uint32) |= (1 << 6);
- window_scenery_open();
- }
- break;
- case WIDX_PATH:
- toggle_footpath_window();
- break;
- case WIDX_LAND:
- toggle_land_window(w, WIDX_LAND);
- break;
- case WIDX_CLEAR_SCENERY:
- toggle_clear_scenery_window(w, WIDX_CLEAR_SCENERY);
- break;
- case WIDX_WATER:
- toggle_water_window(w, WIDX_WATER);
- break;
- case WIDX_MAP:
- window_map_open();
- break;
- case WIDX_CONSTRUCT_RIDE:
- window_new_ride_open();
- break;
- }
-}
-
-/**
-*
-* rct2: 0x0066FADA
-*/
-static void window_editor_top_toolbar_resize() {
- rct_window *mainWindow = window_get_main();
- rct_window *w;
-
- window_get_register(w);
-
- int eax = 0;
-
- if ((w->disabled_widgets & 0xFF) == 0)
- eax |= (1 << 3);
-
- if ((w->disabled_widgets & 0xFF) == 3)
- eax |= (1 << 2);
-
- RCT2_CALLPROC_X(0x006ECE14, 0, 0, 0, 0, (int)w, 0, 0);
-}
-
-/**
-*
-* rct2: 0x0066FA57
-*/
-static void window_editor_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
-{
- if (widgetIndex == WIDX_FILE_MENU) {
- short dropdownItemCount = 8;
- gDropdownItemsFormat[0] = STR_LOAD_LANDSCAPE;
- gDropdownItemsFormat[1] = STR_SAVE_LANDSCAPE;
- gDropdownItemsFormat[2] = 0;
- gDropdownItemsFormat[3] = STR_ABOUT;
- gDropdownItemsFormat[4] = STR_OPTIONS;
- gDropdownItemsFormat[5] = STR_SCREENSHOT;
- gDropdownItemsFormat[6] = 0;
- gDropdownItemsFormat[7] = STR_QUIT_SCENARIO_EDITOR;
-
- if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER)) {
- dropdownItemCount = 5;
- gDropdownItemsFormat[0] = STR_ABOUT;
- gDropdownItemsFormat[1] = STR_OPTIONS;
- gDropdownItemsFormat[2] = STR_SCREENSHOT;
- gDropdownItemsFormat[3] = 0;
- gDropdownItemsFormat[4] = STR_QUIT_TRACK_DESIGNS_MANAGER;
-
- if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) {
- gDropdownItemsFormat[4] = STR_QUIT_ROLLERCOASTER_DESIGNER;
- }
- }
-
- window_dropdown_show_text(w->x + widget->left, w->y + widget->top,
- widget->bottom - widget->top + 1, w->colours[0] | 0x80, 0x80, dropdownItemCount);
- } else if (widgetIndex == WIDX_VIEW_MENU) {
- top_toolbar_init_view_menu(w, widget);
- }
-}
-
-/**
-*
-* rct2: 0x0066FA38
-*/
-void window_editor_top_toolbar_dropdown() {
- short widgetIndex, dropdownIndex;
- rct_window* w;
-
- window_dropdown_get_registers(w, widgetIndex, dropdownIndex);
-
- if (widgetIndex == WIDX_FILE_MENU) {
- if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER)) {
- if (dropdownIndex == DDIDX_TD_ABOUT) {
- window_about_open();
- } else if (dropdownIndex == DDIDX_TD_OPTIONS) {
- window_options_open();
- } else if (dropdownIndex == DDIDX_TD_SCREENSHOT) {
- RCT2_GLOBAL(RCT2_ADDRESS_SCREENSHOT_COUNTDOWN, sint8) = 10;
- } else if (dropdownIndex == DDIDX_TD_QUIT_GAME) {
- window_close_by_number(WC_MANAGE_TRACK_DESIGN, w->number);
- window_close_by_number(WC_TRACK_DELETE_PROMPT, w->number);
- game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 1, 0);
- }
- } else {
- if (dropdownIndex == DDIDX_SE_LOAD_LANDSCAPE) {
- game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 0, 0);
- } else if (dropdownIndex == DDIDX_SE_SAVE_LANDSCAPE) {
- RCT2_CALLPROC(0x0066FE2A);
- } else if (dropdownIndex == DDIDX_SE_ABOUT) {
- window_about_open();
- } else if (dropdownIndex == DDIDX_SE_OPTIONS) {
- window_options_open();
- } else if (dropdownIndex == DDIDX_SE_SCREENSHOT) {
- RCT2_GLOBAL(RCT2_ADDRESS_SCREENSHOT_COUNTDOWN, sint8) = 10;
- } else if (dropdownIndex == DDIDX_SE_QUIT_GAME) {
- window_close_by_number(WC_MANAGE_TRACK_DESIGN, w->number);
- window_close_by_number(WC_TRACK_DELETE_PROMPT, w->number);
- game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 1, 0);
- }
- }
- } else if (widgetIndex == WIDX_VIEW_MENU) {
- top_toolbar_view_menu_dropdown(dropdownIndex);
- }
-}
-
-/**
-*
-* rct2: 0x0066F87D
-*/
-void window_editor_top_toolbar_invalidate()
-{
- rct_window *w;
-
- window_get_register(w);
-
- sint16 screenWidth = max(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16), 640);
-
- window_editor_top_toolbar_widgets[WIDX_CONSTRUCT_RIDE].left = screenWidth - 30;
- window_editor_top_toolbar_widgets[WIDX_CONSTRUCT_RIDE].right =
- window_editor_top_toolbar_widgets[WIDX_CONSTRUCT_RIDE].left + 29;
-
- window_editor_top_toolbar_widgets[WIDX_PATH].left = screenWidth - 30;
- window_editor_top_toolbar_widgets[WIDX_PATH].right =
- window_editor_top_toolbar_widgets[WIDX_PATH].left + 29;
-
- window_editor_top_toolbar_widgets[WIDX_SCENERY].left =
- window_editor_top_toolbar_widgets[WIDX_PATH].left - 30;
- window_editor_top_toolbar_widgets[WIDX_SCENERY].right =
- window_editor_top_toolbar_widgets[WIDX_SCENERY].left + 29;
-
- window_editor_top_toolbar_widgets[WIDX_WATER].left =
- window_editor_top_toolbar_widgets[WIDX_SCENERY].left - 30;
- window_editor_top_toolbar_widgets[WIDX_WATER].right =
- window_editor_top_toolbar_widgets[WIDX_WATER].left + 29;
-
- window_editor_top_toolbar_widgets[WIDX_LAND].left =
- window_editor_top_toolbar_widgets[WIDX_WATER].left - 30;
- window_editor_top_toolbar_widgets[WIDX_LAND].right =
- window_editor_top_toolbar_widgets[WIDX_LAND].left + 29;
-
- window_editor_top_toolbar_widgets[WIDX_CLEAR_SCENERY].left =
- window_editor_top_toolbar_widgets[WIDX_LAND].left - 30;
- window_editor_top_toolbar_widgets[WIDX_CLEAR_SCENERY].right =
- window_editor_top_toolbar_widgets[WIDX_CLEAR_SCENERY].left + 29;
-
- window_editor_top_toolbar_widgets[WIDX_ZOOM_OUT].type = WWT_EMPTY;
- window_editor_top_toolbar_widgets[WIDX_ZOOM_IN].type = WWT_EMPTY;
- window_editor_top_toolbar_widgets[WIDX_ROTATE].type = WWT_EMPTY;
- window_editor_top_toolbar_widgets[WIDX_VIEW_MENU].type = WWT_EMPTY;
- window_editor_top_toolbar_widgets[WIDX_MAP].type = WWT_EMPTY;
- window_editor_top_toolbar_widgets[WIDX_CLEAR_SCENERY].type = WWT_EMPTY;
- window_editor_top_toolbar_widgets[WIDX_LAND].type = WWT_EMPTY;
- window_editor_top_toolbar_widgets[WIDX_WATER].type = WWT_EMPTY;
- window_editor_top_toolbar_widgets[WIDX_SCENERY].type = WWT_EMPTY;
- window_editor_top_toolbar_widgets[WIDX_PATH].type = WWT_EMPTY;
- window_editor_top_toolbar_widgets[WIDX_CONSTRUCT_RIDE].type = WWT_EMPTY;
-
-
- if (g_editor_step == EDITOR_STEP_LANDSCAPE_EDITOR) {
- window_editor_top_toolbar_widgets[WIDX_ZOOM_OUT].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_ZOOM_IN].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_ROTATE].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_VIEW_MENU].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_MAP].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_CLEAR_SCENERY].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_LAND].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_WATER].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_SCENERY].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_PATH].type = WWT_TRNBTN;
- } else if (g_editor_step == EDITOR_STEP_ROLLERCOASTER_DESIGNER) {
- window_editor_top_toolbar_widgets[WIDX_ZOOM_OUT].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_ZOOM_IN].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_ROTATE].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_VIEW_MENU].type = WWT_TRNBTN;
- window_editor_top_toolbar_widgets[WIDX_CONSTRUCT_RIDE].type = WWT_TRNBTN;
- }
-
- if (window_find_by_class(0x94) == NULL)
- w->pressed_widgets &= ~(1 << WIDX_PATH);
- else
- w->pressed_widgets |= (1 << WIDX_PATH);
-}
-
-/**
-*
-* rct2: 0x0066F9D1
-*/
-static void window_editor_top_toolbar_paint()
-{
- rct_window *w;
- rct_drawpixelinfo *dpi;
-
- window_paint_get_registers(w, dpi);
-
- window_draw_widgets(w, dpi);
-}
\ No newline at end of file
diff --git a/src/windows/finances.c b/src/windows/finances.c
index 58b7f0fa09..fc47d3aefa 100644
--- a/src/windows/finances.c
+++ b/src/windows/finances.c
@@ -508,6 +508,17 @@ static uint32 window_finances_page_enabled_widgets[] = {
(1 << WIDX_SCENERY_AND_THEMING)
};
+static uint32 window_finances_page_hold_down_widgets[] = {
+ (1 << WIDX_LOAN_INCREASE) |
+ (1 << WIDX_LOAN_DECREASE),
+
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
#pragma endregion
const int window_finances_tab_animation_loops[] = { 16, 32, 32, 32, 38, 16 };
@@ -527,28 +538,24 @@ void window_finances_open()
w = window_bring_to_front_by_class(WC_FINANCES);
if (w == NULL) {
w = window_create_auto_pos(530, 257, window_finances_page_events[0], WC_FINANCES, WF_10);
- w->widgets = window_finances_page_widgets[0];
- w->enabled_widgets = 0x1BF4;
w->number = 0;
- w->page = 0;
w->frame_no = 0;
- w->disabled_widgets = 0;
w->colours[0] = 1;
w->colours[1] = 19;
w->colours[2] = 19;
research_update_uncompleted_types();
}
- w->page = 0;
+ w->page = WINDOW_FINANCES_PAGE_SUMMARY;
window_invalidate(w);
w->width = 530;
w->height = 257;
window_invalidate(w);
- w->widgets = window_finances_page_widgets[0];
- w->enabled_widgets = window_finances_page_enabled_widgets[0];
- w->var_020 = RCT2_GLOBAL(0x00988E3C, uint32);
- w->event_handlers = window_finances_page_events[0];
+ w->widgets = window_finances_page_widgets[WINDOW_FINANCES_PAGE_SUMMARY];
+ w->enabled_widgets = window_finances_page_enabled_widgets[WINDOW_FINANCES_PAGE_SUMMARY];
+ w->hold_down_widgets = window_finances_page_hold_down_widgets[WINDOW_FINANCES_PAGE_SUMMARY];
+ w->event_handlers = window_finances_page_events[WINDOW_FINANCES_PAGE_SUMMARY];
w->pressed_widgets = 0;
w->disabled_widgets = 0;
window_init_scroll_widgets(w);
@@ -599,13 +606,13 @@ static void window_finances_summary_mousedown(int widgetIndex, rct_window*w, rct
case WIDX_LOAN_INCREASE:
newLoan = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32) + MONEY(1000, 00);
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_BORROW_ANY_MORE_MONEY;
- game_do_command(0, 1, 0, newLoan, GAME_COMMAND_SET_CURRENT_LOAN, 0, 0);
+ finance_set_loan(newLoan);
break;
case WIDX_LOAN_DECREASE:
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32) > 0) {
newLoan = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32) - MONEY(1000, 00);
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_PAY_BACK_LOAN;
- game_do_command(0, 1, 0, newLoan, GAME_COMMAND_SET_CURRENT_LOAN, 0, 0);
+ finance_set_loan(newLoan);
}
break;
}
@@ -1177,9 +1184,8 @@ static void window_finances_marketing_invalidate()
// Count number of active campaigns
int numActiveCampaigns = 0;
- uint8 *campaignDaysLeft = RCT2_ADDRESS(0x01358102, uint8);
for (i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++)
- if (campaignDaysLeft[i] != 0)
+ if (gMarketingCampaignDaysLeft[i] != 0)
numActiveCampaigns++;
int y = max(1, numActiveCampaigns) * 10 + 92;
@@ -1204,7 +1210,7 @@ static void window_finances_marketing_invalidate()
continue;
}
- if (campaignDaysLeft[i] != 0)
+ if (gMarketingCampaignDaysLeft[i] != 0)
continue;
campaginButton->type = WWT_DROPDOWN_BUTTON;
@@ -1235,27 +1241,24 @@ static void window_finances_marketing_paint()
y = w->y + 62;
int noCampaignsActive = 1;
- uint8 *campaignDaysLeft = RCT2_ADDRESS(0x01358102, uint8);
- uint8 *campaignRideIndex = RCT2_ADDRESS(0x01358116, uint8);
-
for (i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++) {
- if (campaignDaysLeft[i] == 0)
+ if (gMarketingCampaignDaysLeft[i] == 0)
continue;
noCampaignsActive = 0;
- RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x013573D4, uint16);
- RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x013573D8, uint32);
+ RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id);
+ RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32);
// Set special parameters
switch (i) {
case ADVERTISING_CAMPAIGN_RIDE_FREE:
case ADVERTISING_CAMPAIGN_RIDE:
- ride = GET_RIDE(campaignRideIndex[i]);
+ ride = GET_RIDE(gMarketingCampaignRideIndex[i]);
RCT2_GLOBAL(0x013CE952, uint16) = ride->name;
RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments;
break;
case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE:
- shopString = campaignRideIndex[i] + 2016; // STR_BALLOONS+
+ shopString = gMarketingCampaignRideIndex[i] + 2016; // STR_BALLOONS+
if (shopString >= 2048) // STR_AN_UMBRELLA
shopString += 96; // STR_ON_RIDE_PHOTOS+
RCT2_GLOBAL(0x013CE952, uint16) = shopString;
@@ -1266,7 +1269,7 @@ static void window_finances_marketing_paint()
gfx_draw_string_left_clipped(dpi, STR_VOUCHERS_FOR_FREE_ENTRY_TO + i, (void*)0x013CE952, 0, x + 4, y, 296);
// Duration
- weeksRemainingStringId = (STR_MARKETING_1_WEEK - 1) + (campaignDaysLeft[i] % 128);
+ weeksRemainingStringId = (STR_MARKETING_1_WEEK - 1) + (gMarketingCampaignDaysLeft[i] % 128);
gfx_draw_string_left(dpi, STR_MARKETING_WEEKS_REMAINING, &weeksRemainingStringId, 0, x + 304, y);
y += 10;
@@ -1294,7 +1297,7 @@ static void window_finances_marketing_paint()
continue;
}
- if (campaignDaysLeft[i] != 0)
+ if (gMarketingCampaignDaysLeft[i] != 0)
continue;
money32 pricePerWeek = AdvertisingCampaignPricePerWeek[i];
@@ -1344,7 +1347,7 @@ static void window_finances_research_mouseup()
case WIDX_SCENERY_AND_THEMING:
activeResearchTypes = RCT2_GLOBAL(RCT2_ADDRESS_ACTIVE_RESEARCH_TYPES, uint16);
activeResearchTypes ^= 1 << (widgetIndex - WIDX_TRANSPORT_RIDES);
- game_do_command(0, (1 << 8) | 1, 0, activeResearchTypes, GAME_COMMAND_SET_RESEARCH_FUNDING, 0, 0);
+ research_set_priority(activeResearchTypes);
break;
}
}
@@ -1396,7 +1399,7 @@ static void window_finances_research_dropdown()
if (widgetIndex != WIDX_RESEARCH_FUNDING_DROPDOWN_BUTTON || dropdownIndex == -1)
return;
- game_do_command(0, 1, 0, dropdownIndex, GAME_COMMAND_SET_RESEARCH_FUNDING, 0, 0);
+ research_set_funding(dropdownIndex);
}
/**
@@ -1493,7 +1496,7 @@ static void window_finances_set_page(rct_window *w, int page)
}
w->enabled_widgets = window_finances_page_enabled_widgets[page];
- w->var_020 = RCT2_ADDRESS(0x00988E3C, uint32)[page];
+ w->hold_down_widgets = window_finances_page_hold_down_widgets[page];
w->event_handlers = window_finances_page_events[page];
w->widgets = window_finances_page_widgets[page];
w->disabled_widgets = 0;
diff --git a/src/windows/footpath.c b/src/windows/footpath.c
index 6796dc2257..0b1c79328a 100644
--- a/src/windows/footpath.c
+++ b/src/windows/footpath.c
@@ -728,7 +728,7 @@ static void window_footpath_start_bridge_at_point(int screenX, int screenY)
if (x == 0x8000)
return;
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SURFACE) {
+ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SURFACE) {
// ?
uint8 dl = ((mapElement->properties.surface.slope & 0x0F) << direction) & 0xFF;
uint8 dh = dl;
@@ -739,7 +739,7 @@ static void window_footpath_start_bridge_at_point(int screenX, int screenY)
z += 2;
} else {
z = mapElement->base_height;
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH) {
+ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) {
if (mapElement->properties.path.type & 4) {
if (direction == (mapElement->properties.path.type & 3))
z += 2;
@@ -837,9 +837,9 @@ static rct_map_element *footpath_get_map_element_to_remove()
z = (RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Z, uint16) >> 3) & 0xFF;
zLow = z - 2;
- mapElement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[y * 256 + x];
+ mapElement = map_get_first_element_at(x, y);
do {
- if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_PATH) {
+ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) {
if (mapElement->base_height == z) {
if (mapElement->properties.path.type & 4)
if (((mapElement->properties.path.type & 3) ^ 2) != RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8))
@@ -854,7 +854,7 @@ static rct_map_element *footpath_get_map_element_to_remove()
return mapElement;
}
}
- } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
+ } while (!map_element_is_last_for_tile(mapElement++));
return NULL;
}
diff --git a/src/windows/game_bottom_toolbar.c b/src/windows/game_bottom_toolbar.c
index 37764ff1e1..0f40dec405 100644
--- a/src/windows/game_bottom_toolbar.c
+++ b/src/windows/game_bottom_toolbar.c
@@ -47,21 +47,26 @@ enum WINDOW_GAME_BOTTOM_TOOLBAR_WIDGET_IDX {
WIDX_DATE
};
+
+// Right panel needs to be a bit bigger than original so dates like "22nd September, Year 126" can fit.
+// Left panel size was also increased for symmetry.
+#define WIDTH_MOD 22
+
rct_widget window_game_bottom_toolbar_widgets[] = {
- { WWT_IMGBTN, 0, 0x0000, 0x0077, 0, 33, 0xFFFFFFFF, STR_NONE }, // Left outset panel
- { WWT_IMGBTN, 0, 0x0002, 0x0075, 2, 31, 0xFFFFFFFF, STR_NONE }, // Left inset panel
- { WWT_FLATBTN, 0, 0x0002, 0x0075, 1, 12, 0xFFFFFFFF, STR_PROFIT_PER_WEEK_AND_PARK_VALUE_TIP }, // Money window
- { WWT_FLATBTN, 0, 0x0002, 0x0075, 11, 22, 0xFFFFFFFF, STR_NONE }, // Guests window
- { WWT_FLATBTN, 0, 0x0002, 0x0075, 21, 31, 0xFFFFFFFF, STR_PARK_RATING_TIP }, // Park rating window
+ { WWT_IMGBTN, 0, 0x0000, 0x0077+WIDTH_MOD, 0, 33, 0xFFFFFFFF, STR_NONE }, // Left outset panel
+ { WWT_IMGBTN, 0, 0x0002, 0x0075+WIDTH_MOD, 2, 31, 0xFFFFFFFF, STR_NONE }, // Left inset panel
+ { WWT_FLATBTN, 0, 0x0002, 0x0075+WIDTH_MOD, 1, 12, 0xFFFFFFFF, STR_PROFIT_PER_WEEK_AND_PARK_VALUE_TIP }, // Money window
+ { WWT_FLATBTN, 0, 0x0002, 0x0075+WIDTH_MOD, 11, 22, 0xFFFFFFFF, STR_NONE }, // Guests window
+ { WWT_FLATBTN, 0, 0x0002, 0x0075+WIDTH_MOD, 21, 31, 0xFFFFFFFF, STR_PARK_RATING_TIP }, // Park rating window
- { WWT_IMGBTN, 2, 0x0078, 0x0207, 0, 33, 0xFFFFFFFF, STR_NONE }, // Middle outset panel
- { WWT_25, 2, 0x007A, 0x0205, 2, 31, 0xFFFFFFFF, STR_NONE }, // Middle inset panel
- { WWT_FLATBTN, 2, 0x007D, 0x0094, 5, 28, 0xFFFFFFFF, STR_SHOW_SUBJECT_TIP }, // Associated news item window
- { WWT_FLATBTN, 2, 0x01EB, 0x0202, 5, 28, SPR_LOCATE, STR_LOCATE_SUBJECT_TIP }, // Scroll to news item target
+ { WWT_IMGBTN, 2, 0x0078+WIDTH_MOD, 0x0207-WIDTH_MOD, 0, 33, 0xFFFFFFFF, STR_NONE }, // Middle outset panel
+ { WWT_25, 2, 0x007A+WIDTH_MOD, 0x0205-WIDTH_MOD, 2, 31, 0xFFFFFFFF, STR_NONE }, // Middle inset panel
+ { WWT_FLATBTN, 2, 0x007D+WIDTH_MOD, 0x0094+WIDTH_MOD, 5, 28, 0xFFFFFFFF, STR_SHOW_SUBJECT_TIP }, // Associated news item window
+ { WWT_FLATBTN, 2, 0x01EB-WIDTH_MOD, 0x0202-WIDTH_MOD, 5, 28, SPR_LOCATE, STR_LOCATE_SUBJECT_TIP }, // Scroll to news item target
- { WWT_IMGBTN, 0, 0x0208, 0x027F, 0, 33, 0xFFFFFFFF, STR_NONE }, // Right outset panel
- { WWT_IMGBTN, 0, 0x020A, 0x027D, 2, 31, 0xFFFFFFFF, STR_NONE }, // Right inset panel
- { WWT_FLATBTN, 0, 0x020A, 0x027D, 2, 13, 0xFFFFFFFF, 2290 }, // Date
+ { WWT_IMGBTN, 0, 0x0208-WIDTH_MOD, 0x027F, 0, 33, 0xFFFFFFFF, STR_NONE }, // Right outset panel
+ { WWT_IMGBTN, 0, 0x020A-WIDTH_MOD, 0x027D, 2, 31, 0xFFFFFFFF, STR_NONE }, // Right inset panel
+ { WWT_FLATBTN, 0, 0x020A-WIDTH_MOD, 0x027D, 2, 13, 0xFFFFFFFF, 2290 }, // Date
{ WIDGETS_END },
};
@@ -268,7 +273,7 @@ static void window_game_bottom_toolbar_invalidate()
window_game_bottom_toolbar_widgets[WIDX_RIGHT_OUTSET].right = x;
x -= 2;
window_game_bottom_toolbar_widgets[WIDX_RIGHT_INSET].right = x;
- x -= 115;
+ x -= (115 + WIDTH_MOD);
window_game_bottom_toolbar_widgets[WIDX_RIGHT_INSET].left = x;
x -= 2;
window_game_bottom_toolbar_widgets[WIDX_RIGHT_OUTSET].left = x;
@@ -441,16 +446,16 @@ static void window_game_bottom_toolbar_draw_park_rating(rct_drawpixelinfo *dpi,
{
short bar_width;
- bar_width = (factor * 90) / 256;
- gfx_fill_rect_inset(dpi, x, y + 1, x + 93, y + 9, w->colours[1], 48);
- if (!(colour & 0x80000000) || RCT2_GLOBAL(0x009DEA6E, uint8) != 0 || (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint8) & 8)) {
+ bar_width = (factor * (90 + WIDTH_MOD)) / 256;
+ gfx_fill_rect_inset(dpi, x, y + 1, x + (93 + WIDTH_MOD), y + 9, w->colours[1], 48);
+ if (!(colour & 0x80000000) || RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 || (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint8) & 8)) {
if (bar_width > 2)
gfx_fill_rect_inset(dpi, x + 2, y + 2, x + bar_width - 1, y + 8, colour & 0x7FFFFFFF, 0);
}
// Draw thumbs on the sides
gfx_draw_sprite(dpi, SPR_RATING_LOW, x - 14, y, 0);
- gfx_draw_sprite(dpi, SPR_RATING_HIGH, x + 92, y, 0);
+ gfx_draw_sprite(dpi, SPR_RATING_HIGH, x + (92 + WIDTH_MOD), y, 0);
}
static void window_game_bottom_toolbar_draw_right_panel(rct_drawpixelinfo *dpi, rct_window *w)
@@ -472,20 +477,16 @@ static void window_game_bottom_toolbar_draw_right_panel(rct_drawpixelinfo *dpi,
y = window_game_bottom_toolbar_widgets[WIDX_RIGHT_OUTSET].top + w->y + 2;
// Date
- char *freeStr = (char*)0x009BC677;
- freeStr[0] = FORMAT_STRINGID;
- freeStr[1] = ' ';
- freeStr[2] = FORMAT_MONTHYEAR;
- freeStr[3] = 0;
-
- int month = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, sint16) & 7;
+ int year = date_get_year(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, sint16)) + 1;
+ int month = date_get_month(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, sint16) & 7);
int day = ((RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_TICKS, uint16) * days_in_month[month]) >> 16) & 0xFF;
RCT2_GLOBAL(0x013CE952, short) = STR_DATE_DAY_1 + day;
- RCT2_GLOBAL(0x013CE954, short) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, sint16);
+ RCT2_GLOBAL(0x013CE954, short) = month;
+ RCT2_GLOBAL(0x013CE956, short) = year;
gfx_draw_string_centred(
dpi,
- 3165,
+ 2737,
x,
y,
(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) == 2 && RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, sint32) == WIDX_DATE ? 2 : w->colours[0] & 0x7F),
diff --git a/src/windows/game_top_toolbar.c b/src/windows/game_top_toolbar.c
deleted file mode 100644
index 16863fd0b3..0000000000
--- a/src/windows/game_top_toolbar.c
+++ /dev/null
@@ -1,719 +0,0 @@
-/*****************************************************************************
- * Copyright (c) 2014 Ted John
- * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
- *
- * This file is part of OpenRCT2.
- *
- * OpenRCT2 is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *****************************************************************************/
-
-#include "../addresses.h"
-#include "../game.h"
-#include "../input.h"
-#include "../sprites.h"
-#include "../toolbar.h"
-#include "../audio/audio.h"
-#include "../interface/widget.h"
-#include "../interface/window.h"
-#include "../interface/viewport.h"
-#include "../localisation/localisation.h"
-#include "dropdown.h"
-#include "scenery.h"
-
-enum {
- WIDX_PAUSE,
- WIDX_FILE_MENU,
- WIDX_ZOOM_OUT,
- WIDX_ZOOM_IN,
- WIDX_ROTATE,
- WIDX_VIEW_MENU,
- WIDX_MAP,
-
- WIDX_LAND,
- WIDX_WATER,
- WIDX_SCENERY,
- WIDX_PATH,
- WIDX_CONSTRUCT_RIDE,
- WIDX_RIDES,
- WIDX_PARK,
- WIDX_STAFF,
- WIDX_GUESTS,
- WIDX_CLEAR_SCENERY,
-
- //WIDX_FASTFORWARD,
- WIDX_FINANCES,
- WIDX_RESEARCH
-};
-
-typedef enum {
- DDIDX_LOAD_GAME = 0,
- DDIDX_SAVE_GAME = 1,
- DDIDX_ABOUT = 3,
- DDIDX_OPTIONS = 4,
- DDIDX_SCREENSHOT = 5,
- DDIDX_QUIT_GAME = 7,
-} FILE_MENU_DDIDX;
-
-static rct_widget window_game_top_toolbar_widgets[] = {
- { WWT_TRNBTN, 0, 0x0000, 0x001D, 0, 27, 0x20000000 | SPR_TOOLBAR_PAUSE, STR_PAUSE_GAME_TIP }, // Pause
- { WWT_TRNBTN, 0, 0x001E + 30, 0x003B + 30, 0, 27, 0x20000000 | SPR_TOOLBAR_FILE, STR_DISC_AND_GAME_OPTIONS_TIP }, // File menu
- { WWT_TRNBTN, 1, 0x0046 + 30, 0x0063 + 30, 0, 27, 0x20000000 | SPR_TOOLBAR_ZOOM_OUT, STR_ZOOM_OUT_TIP }, // Zoom out
- { WWT_TRNBTN, 1, 0x0064 + 30, 0x0081 + 30, 0, 27, 0x20000000 | SPR_TOOLBAR_ZOOM_IN, STR_ZOOM_IN_TIP }, // Zoom in
- { WWT_TRNBTN, 1, 0x0082 + 30, 0x009F + 30, 0, 27, 0x20000000 | SPR_TOOLBAR_ROTATE, STR_ROTATE_TIP }, // Rotate camera
- { WWT_TRNBTN, 1, 0x00A0 + 30, 0x00BD + 30, 0, 27, 0x20000000 | SPR_TOOLBAR_VIEW, STR_VIEW_OPTIONS_TIP }, // Transparancy menu
- { WWT_TRNBTN, 1, 0x00BE + 30, 0x00DB + 30, 0, 27, 0x20000000 | SPR_TOOLBAR_MAP, STR_SHOW_MAP_TIP }, // Map
-
- { WWT_TRNBTN, 2, 0x010B, 0x0128, 0, 27, 0x20000000 | SPR_TOOLBAR_LAND, STR_ADJUST_LAND_TIP }, // Land
- { WWT_TRNBTN, 2, 0x0129, 0x0146, 0, 27, 0x20000000 | SPR_TOOLBAR_WATER, STR_ADJUST_WATER_TIP }, // Water
- { WWT_TRNBTN, 2, 0x0147, 0x0164, 0, 27, 0x20000000 | SPR_TOOLBAR_SCENERY, STR_PLACE_SCENERY_TIP }, // Scenery
- { WWT_TRNBTN, 2, 0x0165, 0x0182, 0, 27, 0x20000000 | SPR_TOOLBAR_FOOTPATH, STR_BUILD_FOOTPATH_TIP }, // Path
- { WWT_TRNBTN, 2, 0x0183, 0x01A0, 0, 27, 0x20000000 | SPR_TOOLBAR_CONSTRUCT_RIDE, STR_BUILD_RIDE_TIP }, // Construct ride
- { WWT_TRNBTN, 3, 0x01EA, 0x0207, 0, 27, 0x20000000 | SPR_TOOLBAR_RIDES, STR_RIDES_IN_PARK_TIP }, // Rides
- { WWT_TRNBTN, 3, 0x0208, 0x0225, 0, 27, 0x20000000 | SPR_TOOLBAR_PARK, STR_PARK_INFORMATION_TIP }, // Park
- { WWT_TRNBTN, 3, 0x0226, 0x0243, 0, 27, 0x20000000 | 0x15F9, STR_STAFF_TIP }, // Staff
- { WWT_TRNBTN, 3, 0x0230, 0x024D, 0, 27, 0x20000000 | SPR_TOOLBAR_GUESTS, STR_GUESTS_TIP }, // Guests
- { WWT_TRNBTN, 2, 0x0230, 0x024D, 0, 27, 0x20000000 | SPR_TOOLBAR_CLEAR_SCENERY, STR_CLEAR_SCENERY_TIP }, // Clear scenery
-
- //{ WWT_TRNBTN, 0, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, STR_NONE }, // Fast forward
- { WWT_TRNBTN, 3, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, 3235 }, // Finances
- { WWT_TRNBTN, 3, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, 2275 }, // Research
- { WIDGETS_END },
-};
-
-static void window_game_top_toolbar_emptysub() { }
-static void window_game_top_toolbar_mouseup();
-static void window_game_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
-static void window_game_top_toolbar_dropdown();
-static void window_game_top_toolbar_tool_update();
-static void window_game_top_toolbar_tool_down();
-static void window_game_top_toolbar_tool_drag();
-static void window_game_top_toolbar_invalidate();
-static void window_game_top_toolbar_paint();
-
-static void* window_game_top_toolbar_events[] = {
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_mouseup,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_mousedown,
- window_game_top_toolbar_dropdown,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_tool_update,
- window_game_top_toolbar_tool_down,
- window_game_top_toolbar_tool_drag,
- (void*)0x0066CC5B,
- (void*)0x0066CA58,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_emptysub,
- window_game_top_toolbar_invalidate,
- window_game_top_toolbar_paint,
- window_game_top_toolbar_emptysub
-};
-
-/**
- * Creates the main game top toolbar window.
- * rct2: 0x0066B485 (part of 0x0066B3E8)
- */
-void window_game_top_toolbar_open()
-{
- rct_window* window;
-
- window = window_create(
- 0, 0,
- RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16), 28,
- (uint32*)window_game_top_toolbar_events,
- WC_TOP_TOOLBAR,
- WF_STICK_TO_FRONT | WF_TRANSPARENT | WF_5
- );
- window->widgets = window_game_top_toolbar_widgets;
-
- window->enabled_widgets |=
- (1 << WIDX_PAUSE) |
- (1 << WIDX_FILE_MENU) |
- (1 << WIDX_ZOOM_OUT) |
- (1 << WIDX_ZOOM_IN) |
- (1 << WIDX_ROTATE) |
- (1 << WIDX_VIEW_MENU) |
- (1 << WIDX_MAP) |
- (1 << WIDX_LAND) |
- (1 << WIDX_WATER) |
- (1 << WIDX_SCENERY) |
- (1 << WIDX_PATH) |
- (1 << WIDX_CONSTRUCT_RIDE) |
- (1 << WIDX_RIDES) |
- (1 << WIDX_PARK) |
- (1 << WIDX_STAFF) |
- (1 << WIDX_GUESTS) |
- (1 << WIDX_CLEAR_SCENERY) |
- //(1ULL << WIDX_FASTFORWARD) |
- (1ULL << WIDX_FINANCES) |
- (1ULL << WIDX_RESEARCH);
-
- window_init_scroll_widgets(window);
- window->colours[0] = 7;
- window->colours[1] = 12;
- window->colours[2] = 24;
- window->colours[3] = 1;
-}
-
-/**
- *
- * rct2: 0x0066C957
- */
-static void window_game_top_toolbar_mouseup()
-{
- short widgetIndex;
- rct_window *w, *mainWindow;
-
- window_widget_get_registers(w, widgetIndex);
-
- switch (widgetIndex) {
- case WIDX_PAUSE:
- game_do_command(0, 1, 0, 0, GAME_COMMAND_TOGGLE_PAUSE, 0, 0);
- break;
- // case WIDX_FASTFORWARD:
- // // This is an excellent place to add in debugging statements and
- // // print routines, that will be triggered when you press the
- // // button in the game. Use "git update-index --skip-worktree
- // // src/window_game_top_toolbar" to avoid committing these changes to
- // // version control.
- // window_cheats_open();
- // break;
-
- case WIDX_ZOOM_OUT:
- if ((mainWindow = window_get_main()) != NULL)
- window_zoom_out(mainWindow);
- break;
- case WIDX_ZOOM_IN:
- if ((mainWindow = window_get_main()) != NULL)
- window_zoom_in(mainWindow);
- break;
- case WIDX_ROTATE:
- if ((mainWindow = window_get_main()) != NULL)
- window_rotate_camera(mainWindow);
- break;
- case WIDX_CLEAR_SCENERY:
- toggle_clear_scenery_window(w, WIDX_CLEAR_SCENERY);
- break;
- case WIDX_LAND:
- toggle_land_window(w, WIDX_LAND);
- break;
- case WIDX_WATER:
- toggle_water_window(w, WIDX_WATER);
- break;
- case WIDX_SCENERY:
- if (!tool_set(w, WIDX_SCENERY, 0)) {
- RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
- window_scenery_open();
- }
- break;
- case WIDX_PATH:
- toggle_footpath_window();
- break;
- case WIDX_CONSTRUCT_RIDE:
- window_new_ride_open();
- break;
- case WIDX_RIDES:
- window_ride_list_open();
- break;
- case WIDX_PARK:
- window_park_entrance_open();
- break;
- case WIDX_STAFF:
- window_staff_list_open();
- break;
- case WIDX_GUESTS:
- window_guest_list_open();
- break;
- case WIDX_FINANCES:
- window_finances_open();
- break;
- case WIDX_RESEARCH:
- window_research_open();
- break;
- }
-}
-
-/**
- *
- * rct2: 0x0066CA3B
- */
-static void window_game_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
-{
- switch (widgetIndex) {
- case WIDX_FILE_MENU:
- gDropdownItemsFormat[0] = STR_LOAD_GAME;
- gDropdownItemsFormat[1] = STR_SAVE_GAME;
- gDropdownItemsFormat[2] = 0;
- gDropdownItemsFormat[3] = STR_ABOUT;
- gDropdownItemsFormat[4] = STR_OPTIONS;
- gDropdownItemsFormat[5] = STR_SCREENSHOT;
- gDropdownItemsFormat[6] = 0;
- gDropdownItemsFormat[7] = STR_QUIT_GAME;
- window_dropdown_show_text(
- w->x + widget->left,
- w->y + widget->top,
- widget->bottom - widget->top + 1,
- w->colours[0] | 0x80,
- 0x80,
- 8
- );
- break;
- case WIDX_VIEW_MENU:
- top_toolbar_init_view_menu(w, widget);
- break;
- case WIDX_MAP:
- gDropdownItemsFormat[0] = 2523;
- gDropdownItemsFormat[1] = 2780;
- window_dropdown_show_text(
- w->x + widget->left,
- w->y + widget->top,
- widget->bottom - widget->top + 1,
- w->colours[1] | 0x80,
- 0,
- 2
- );
- RCT2_GLOBAL(0x9DEBA2, uint16) = 0;
- break;
- }
-}
-
-/**
- *
- * rct2: 0x0066C9EA
- */
-static void window_game_top_toolbar_dropdown()
-{
- short widgetIndex, dropdownIndex;
- rct_window* w;
-
- window_dropdown_get_registers(w, widgetIndex, dropdownIndex);
-
- switch (widgetIndex) {
- case WIDX_FILE_MENU:
- switch (dropdownIndex) {
- case DDIDX_LOAD_GAME: // load game
- game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 0, 0);
- break;
- case DDIDX_SAVE_GAME: // save game
- tool_cancel();
- save_game();
- break;
- case DDIDX_ABOUT: // about
- window_about_open();
- break;
- case DDIDX_OPTIONS: // options
- window_options_open();
- break;
- case DDIDX_SCREENSHOT: // screenshot
- RCT2_GLOBAL(RCT2_ADDRESS_SCREENSHOT_COUNTDOWN, sint8) = 10;
- break;
- case DDIDX_QUIT_GAME: // quit game
- game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 1, 0);
- break;
- }
- break;
- case WIDX_VIEW_MENU:
- top_toolbar_view_menu_dropdown(dropdownIndex);
- break;
- case WIDX_MAP:
- if (dropdownIndex == -1)
- dropdownIndex = RCT2_GLOBAL(0x9DEBA2, uint16);
- switch (dropdownIndex) {
- case 0:
- window_map_open();
- break;
- case 1:
- window_viewport_open();
- break;
- }
- break;
- }
-}
-
-/**
- *
- * rct2: 0x0066C810
- */
-static void window_game_top_toolbar_invalidate()
-{
- int x;
- rct_window *w;
-
- window_get_register(w);
-
- // Anchor the right half of the buttons to the right
- x = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16);
- if (x < 640)
- x = 640;
- x--;
- window_game_top_toolbar_widgets[WIDX_GUESTS].right = x;
- x -= 29;
- window_game_top_toolbar_widgets[WIDX_GUESTS].left = x;
- x -= 1;
- window_game_top_toolbar_widgets[WIDX_STAFF].right = x;
- x -= 29;
- window_game_top_toolbar_widgets[WIDX_STAFF].left = x;
- x -= 1;
- window_game_top_toolbar_widgets[WIDX_PARK].right = x;
- x -= 29;
- window_game_top_toolbar_widgets[WIDX_PARK].left = x;
- x -= 1;
- window_game_top_toolbar_widgets[WIDX_RIDES].right = x;
- x -= 29;
- window_game_top_toolbar_widgets[WIDX_RIDES].left = x;
- x -= 1;
- window_game_top_toolbar_widgets[WIDX_RESEARCH].right = x;
- x -= 29;
- window_game_top_toolbar_widgets[WIDX_RESEARCH].left = x;
- x -= 1;
- window_game_top_toolbar_widgets[WIDX_FINANCES].right = x;
- x -= 29;
- window_game_top_toolbar_widgets[WIDX_FINANCES].left = x;
- x -= 11;
- window_game_top_toolbar_widgets[WIDX_CONSTRUCT_RIDE].right = x;
- x -= 29;
- window_game_top_toolbar_widgets[WIDX_CONSTRUCT_RIDE].left = x;
- x -= 1;
- window_game_top_toolbar_widgets[WIDX_PATH].right = x;
- x -= 29;
- window_game_top_toolbar_widgets[WIDX_PATH].left = x;
- x -= 1;
- window_game_top_toolbar_widgets[WIDX_SCENERY].right = x;
- x -= 29;
- window_game_top_toolbar_widgets[WIDX_SCENERY].left = x;
- x -= 1;
- window_game_top_toolbar_widgets[WIDX_WATER].right = x;
- x -= 29;
- window_game_top_toolbar_widgets[WIDX_WATER].left = x;
- x -= 1;
- window_game_top_toolbar_widgets[WIDX_LAND].right = x;
- x -= 29;
- window_game_top_toolbar_widgets[WIDX_LAND].left = x;
- x -= 1;
- window_game_top_toolbar_widgets[WIDX_CLEAR_SCENERY].right = x;
- x -= 29;
- window_game_top_toolbar_widgets[WIDX_CLEAR_SCENERY].left = x;
- x = 0;
- window_game_top_toolbar_widgets[WIDX_PAUSE].left = x;
- x += 29;
- window_game_top_toolbar_widgets[WIDX_PAUSE].right = x;
- // x += 1;
- // window_game_top_toolbar_widgets[WIDX_FASTFORWARD].left = x;
- // x += 29;
- // window_game_top_toolbar_widgets[WIDX_FASTFORWARD].right = x;
- x += 1;
- window_game_top_toolbar_widgets[WIDX_FILE_MENU].left = x;
- x += 29;
- window_game_top_toolbar_widgets[WIDX_FILE_MENU].right = x;
- x += 11;
- window_game_top_toolbar_widgets[WIDX_ZOOM_OUT].left = x;
- x += 29;
- window_game_top_toolbar_widgets[WIDX_ZOOM_OUT].right = x;
- x += 1;
- window_game_top_toolbar_widgets[WIDX_ZOOM_IN].left = x;
- x += 29;
- window_game_top_toolbar_widgets[WIDX_ZOOM_IN].right = x;
- x += 1;
- window_game_top_toolbar_widgets[WIDX_ROTATE].left = x;
- x += 29;
- window_game_top_toolbar_widgets[WIDX_ROTATE].right = x;
- x += 1;
- window_game_top_toolbar_widgets[WIDX_VIEW_MENU].left = x;
- x += 29;
- window_game_top_toolbar_widgets[WIDX_VIEW_MENU].right = x;
- x += 1;
- window_game_top_toolbar_widgets[WIDX_MAP].left = x;
- x += 29;
- window_game_top_toolbar_widgets[WIDX_MAP].right = x;
-
- // Footpath button pressed down
- if (window_find_by_class(WC_FOOTPATH) == NULL)
- w->pressed_widgets &= ~(1 << WIDX_PATH);
- else
- w->pressed_widgets |= (1 << WIDX_PATH);
-
- // Fast forward button pressed down
- // if (0)
- // w->pressed_widgets |= (1 << WIDX_FASTFORWARD);
- // else
- // w->pressed_widgets &= ~(1 << WIDX_FASTFORWARD);
-
- if (!(RCT2_GLOBAL(0x009DEA6E, uint32) & 1))
- w->pressed_widgets &= ~(1 << WIDX_PAUSE);
- else
- w->pressed_widgets |= (1 << WIDX_PAUSE);
-
- // Zoomed out/in disable. Not sure where this code is in the original.
- if (window_get_main()->viewport->zoom == 0){
- w->disabled_widgets |= (1 << WIDX_ZOOM_IN);
- }
- else if (window_get_main()->viewport->zoom == 3){
- w->disabled_widgets |= (1 << WIDX_ZOOM_OUT);
- }
- else
- {
- w->disabled_widgets &= ~((1 << WIDX_ZOOM_IN) | (1 << WIDX_ZOOM_OUT));
- }
-
- if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) {
- window_game_top_toolbar_widgets[WIDX_FINANCES].type = WWT_EMPTY;
- }
- else{
- window_game_top_toolbar_widgets[WIDX_FINANCES].type = WWT_TRNBTN;
- }
-}
-
-/**
- *
- * rct2: 0x0066C8EC
- */
-static void window_game_top_toolbar_paint()
-{
- int x, y, imgId;
- rct_window *w;
- rct_drawpixelinfo *dpi;
-
- window_paint_get_registers(w, dpi);
-
- window_draw_widgets(w, dpi);
-
- // Draw staff button image (setting masks to the staff colours)
- x = w->x + window_game_top_toolbar_widgets[WIDX_STAFF].left;
- y = w->y + window_game_top_toolbar_widgets[WIDX_STAFF].top;
- imgId = 5627;
- if (widget_is_pressed(w, WIDX_STAFF))
- imgId++;
- imgId |= (RCT2_GLOBAL(RCT2_ADDRESS_HANDYMAN_COLOUR, uint8) << 19) | 0xA0000000 | (RCT2_GLOBAL(RCT2_ADDRESS_MECHANIC_COLOUR, uint8) << 24);
- gfx_draw_sprite(dpi, imgId, x, y, 0);
-
- // Draw research button
- x = w->x + window_game_top_toolbar_widgets[WIDX_RESEARCH].left - 1;
- y = w->y + window_game_top_toolbar_widgets[WIDX_RESEARCH].top;
- imgId = SPR_TAB_FINANCES_RESEARCH_0;
- gfx_draw_sprite(dpi, imgId, x, y, 0);
-
- // Draw finances button
- if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)){
- x = w->x + window_game_top_toolbar_widgets[WIDX_FINANCES].left + 3;
- y = w->y + window_game_top_toolbar_widgets[WIDX_FINANCES].top + 1;
- imgId = SPR_FINANCE;
- gfx_draw_sprite(dpi, imgId, x, y, 0);
- }
-}
-
-/**
- * rct2: 0x6e2cc6
- */
-static void window_game_top_toolbar_scenery_tool_down(short x, short y, rct_window* w, short widgetIndex){
- RCT2_CALLPROC_EBPSAFE(0x006E2712);
- if (window_scenery_is_repaint_scenery_tool_on & 1){
- //6e3158
- RCT2_CALLPROC_X(0x6E2CC6, x, y, 0, widgetIndex, (int)w, 0, 0);
- }
-
- int selected_tab = window_scenery_selected_scenery_by_tab[window_scenery_active_tab_index];
- if (selected_tab == -1) return;
-
- sint16 grid_x, grid_y, grid_z;
- uint8 item_colour;
- uint8 model_type;
- int ebp = selected_tab;
-
- {
- int eax = x, ebx = y, ecx = 0, edx = 0, esi = 0, edi = 0;
- RCT2_CALLFUNC_X(0x6E1F34, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
- item_colour = edi;
- model_type = (ebx & 0xFF00) >> 8;
- grid_x = eax;
- grid_y = ecx;
- grid_z = edx;
- }
-
- if (grid_x == 0x8000)return;
-
- if (ebp >= 1024){
- RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = 1161;
-
- // The return value will be banner id but the input is colour
- int banner_id = item_colour;
-
- int ebx = (model_type << 8) | 1;
-
- {
- int esi = 0, eax = grid_x, ecx = grid_y, edx = grid_z;
- game_do_command_p(GAME_COMMAND_50, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp);
- }
-
- if (ebx == 0x80000000)return;
-
- sound_play_panned(SOUND_PLACE_ITEM, 0x8001, RCT2_GLOBAL(0x009DEA5E, uint16), RCT2_GLOBAL(0x009DEA60, uint16), RCT2_GLOBAL(0x009DEA62, uint16));
-
- window_banner_open(banner_id);
- }
- else if (ebp >= 768){
- //6e301c
- RCT2_CALLPROC_X(0x6E2CC6, x, y, 0, widgetIndex, (int)w, 0, 0);
- }
- else if (ebp >= 512){
- //6e2f2e
- RCT2_CALLPROC_X(0x6E2CC6, x, y, 0, widgetIndex, (int)w, 0, 0);
- }
- else if (ebp >= 256){
- //6e2eda
- RCT2_CALLPROC_X(0x6E2CC6, x, y, 0, widgetIndex, (int)w, 0, 0);
- }
- else{
- //6e2d2d
- RCT2_CALLPROC_X(0x6E2CC6, x, y, 0, widgetIndex, (int)w, 0, 0);
- }
-}
-
-/**
- *
- * rct2: 0x0066CB25
- */
-static void window_game_top_toolbar_tool_update()
-{
- short widgetIndex;
- rct_window *w;
- short x, y;
-
- window_tool_get_registers(w, widgetIndex, x, y);
-
- switch (widgetIndex){
- case WIDX_CLEAR_SCENERY:
- RCT2_CALLPROC_X(0x0068E213, x, y, 0, widgetIndex, (int)w, 0, 0);
- break;
- case WIDX_LAND:
- RCT2_CALLPROC_X(0x00664280, x, y, 0, widgetIndex, (int)w, 0, 0);
- break;
- case WIDX_WATER:
- RCT2_CALLPROC_X(0x006E6BDC, x, y, 0, widgetIndex, (int)w, 0, 0);
- break;
- case WIDX_SCENERY:
- RCT2_CALLPROC_X(0x006E287B, x, y, 0, widgetIndex, (int)w, 0, 0);
- break;
- }
-}
-
-/**
- * rct2: 0x0066CB73
- */
-static void window_game_top_toolbar_tool_down(){
- short widgetIndex;
- rct_window* w;
- short x, y;
-
- window_tool_get_registers(w, widgetIndex, x, y);
-
- switch (widgetIndex){
- case WIDX_CLEAR_SCENERY:
- if (!RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))
- break;
-
- RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = 3438;
-
- game_do_command(
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16),
- 1,
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16),
- 0,
- GAME_COMMAND_CLEAR_SCENERY,
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16),
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16)
- );
- RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = 12;
- break;
- case WIDX_LAND:
- if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16)&(1 << 0)){
- RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = 1387;
- game_do_command(
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16),
- 1,
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16),
- RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) | (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) << 8),
- GAME_COMMAND_CHANGE_SURFACE_STYLE,
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16),
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16)
- );
- RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = 3;
- }
- break;
- case WIDX_WATER:
- if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16)&(1 << 0)){
- RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = 3;
- }
- break;
- case WIDX_SCENERY:
- window_game_top_toolbar_scenery_tool_down(x, y, w, widgetIndex);
- break;
- }
-}
-
-/**
- *
- * rct2: 0x0066CB4E
- */
-static void window_game_top_toolbar_tool_drag()
-{
- short widgetIndex;
- rct_window *w;
- short x, y;
-
- window_tool_get_registers(w, widgetIndex, x, y);
-
- switch (widgetIndex){
- case WIDX_CLEAR_SCENERY:
- if (window_find_by_class(WC_ERROR) != NULL)
- break;
-
- if (!RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))
- break;
-
- RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = 3438;
-
- game_do_command(
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16),
- 1,
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16),
- 0,
- GAME_COMMAND_CLEAR_SCENERY,
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16),
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16)
- );
- RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = 12;
- break;
- case WIDX_LAND:
- RCT2_CALLPROC_X(0x00664454, x, y, 0, widgetIndex, (int)w, 0, 0);
- break;
- case WIDX_WATER:
- RCT2_CALLPROC_X(0x006E6D4B, x, y, 0, widgetIndex, (int)w, 0, 0);
- break;
- case WIDX_SCENERY:
- RCT2_CALLPROC_X(0x006E2CBC, x, y, 0, widgetIndex, (int)w, 0, 0);
- break;
- }
-}
\ No newline at end of file
diff --git a/src/windows/guest.c b/src/windows/guest.c
index 584f5e87b9..cd768e2770 100644
--- a/src/windows/guest.c
+++ b/src/windows/guest.c
@@ -516,7 +516,7 @@ void window_guest_open(rct_peep* peep){
window->widgets = window_guest_page_widgets[WINDOW_GUEST_OVERVIEW];
window->enabled_widgets = window_guest_page_enabled_widgets[WINDOW_GUEST_OVERVIEW];
- window->var_020 = RCT2_GLOBAL(0x981D54,uint32);
+ window->hold_down_widgets = 0;
window->event_handlers = window_guest_page_events[WINDOW_GUEST_OVERVIEW];
window->pressed_widgets = 0;
@@ -568,7 +568,7 @@ void window_guest_overview_resize(){
window_get_register(w);
window_guest_disable_widgets(w);
- RCT2_CALLPROC_EBPSAFE(w->event_handlers[WE_INVALIDATE]);
+ RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0);
widget_invalidate(w, WIDX_MARQUEE);
@@ -627,7 +627,7 @@ void window_guest_overview_mouse_up(){
sprite_move(0x8000, peep->y, peep->z, (rct_sprite*)peep);
peep_decrement_num_riders(peep);
peep->state = PEEP_STATE_PICKED;
- peep->var_2C = 0;
+ peep->sub_state = 0;
peep_window_state_update(peep);
break;
case WIDX_RENAME:
@@ -670,7 +670,7 @@ void window_guest_set_page(rct_window* w, int page){
}
w->enabled_widgets = window_guest_page_enabled_widgets[page];
- w->var_020 = RCT2_ADDRESS(0x981D54,uint32)[page];
+ w->hold_down_widgets = 0;
w->event_handlers = window_guest_page_events[page];
w->pressed_widgets = 0;
w->widgets = window_guest_page_widgets[page];
@@ -1376,7 +1376,7 @@ void window_guest_stats_bars_paint(int value, int x, int y, rct_window *w, rct_d
int blink_flag = colour & (1 << 0x1F); //0x80000000
colour &= ~(1 << 0x1F);
if (!blink_flag ||
- RCT2_GLOBAL(0x009DEA6E, uint8) != 0 ||
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 ||
(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 8) == 0)
{
if (value <= 2)
diff --git a/src/windows/map.c b/src/windows/map.c
index 47128823da..7adf1f8486 100644
--- a/src/windows/map.c
+++ b/src/windows/map.c
@@ -165,7 +165,9 @@ void window_map_open()
(1 << WIDX_BUILD_PARK_ENTRANCE) |
(1 << WIDX_ROTATE_90) |
(1 << WIDX_PEOPLE_STARTING_POSITION);
- w->var_020 |= 0x300;
+ w->hold_down_widgets =
+ (1 << WIDX_MAP_SIZE_SPINNER_UP) |
+ (1 << WIDX_MAP_SIZE_SPINNER_DOWN);
window_init_scroll_widgets(w);
window_map_set_bounds(w);
@@ -342,10 +344,10 @@ static void window_map_mousedown(int widgetIndex, rct_window*w, rct_widget* widg
// The normal map window doesn't have widget 8 or 9.
// I assume these widgets refer to the Scenario Editor's map window.
if (widgetIndex == 8) {
- RCT2_CALLPROC_EBPSAFE(0x0068D641);
+ RCT2_CALLPROC_X(0x0068D641, 0, 0, 0, widgetIndex, (int)w, 0, 0);
}
else if (widgetIndex == 9) {
- RCT2_CALLPROC_EBPSAFE(0x0068D6B4);
+ RCT2_CALLPROC_X(0x0068D6B4, 0, 0, 0, widgetIndex, (int)w, 0, 0);
}
}
@@ -355,7 +357,7 @@ static void window_map_mousedown(int widgetIndex, rct_window*w, rct_widget* widg
*/
static void window_map_update(rct_window *w)
{
- RCT2_CALLPROC_EBPSAFE(0x0068D7FB);
+ RCT2_CALLPROC_X(0x0068D7FB, 0, 0, 0, 0, (int)w, 0, 0);
}
/**
@@ -381,7 +383,11 @@ static void window_map_scrollgetsize()
*/
static void window_map_scrollmousedown()
{
- RCT2_CALLPROC_EBPSAFE(0x0068D726);
+ short x, y, scrollIndex;
+ rct_window *w;
+
+ window_scrollmouse_get_registers(w, scrollIndex, x, y);
+ RCT2_CALLPROC_X(0x0068D726, scrollIndex, 0, x, y, (int)w, 0, 0);
}
/**
@@ -626,11 +632,11 @@ static void window_map_scrollpaint()
*g1_element = pushed_g1_element;
if (w->selected_tab == 0)
- RCT2_CALLPROC_EBPSAFE(0x68DADA); //draws dots representing guests
+ RCT2_CALLPROC_X(0x68DADA, 0, 0, 0, 0, (int)w, (int)dpi, 0); //draws dots representing guests
else
- RCT2_CALLPROC_EBPSAFE(0x68DBC1); //draws dots representing trains
+ RCT2_CALLPROC_X(0x68DBC1, 0, 0, 0, 0, (int)w, (int)dpi, 0); //draws dots representing trains
- RCT2_CALLPROC_EBPSAFE(0x68D8CE); //draws the HUD rectangle on the map
+ RCT2_CALLPROC_X(0x68D8CE, 0, 0, 0, 0, (int)w, (int)dpi, 0); //draws the HUD rectangle on the map
}
/**
diff --git a/src/windows/mapgen.c b/src/windows/mapgen.c
new file mode 100644
index 0000000000..a704ba1eb4
--- /dev/null
+++ b/src/windows/mapgen.c
@@ -0,0 +1,646 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#include "../addresses.h"
+#include "../localisation/localisation.h"
+#include "../input.h"
+#include "../interface/widget.h"
+#include "../interface/viewport.h"
+#include "../interface/window.h"
+#include "../sprites.h"
+#include "../windows/scenery.h"
+#include "../world/mapgen.h"
+#include "dropdown.h"
+
+enum {
+ WINDOW_MAPGEN_PAGE_BASE,
+ WINDOW_MAPGEN_PAGE_RANDOM,
+ WINDOW_MAPGEN_PAGE_COUNT
+};
+
+enum {
+ WIDX_BACKGROUND,
+ WIDX_TITLE,
+ WIDX_CLOSE,
+ WIDX_PAGE_BACKGROUND,
+ WIDX_TAB_1,
+ WIDX_TAB_2,
+
+ WIDX_GENERATE,
+
+ WIDX_MAP_SIZE = 7,
+ WIDX_MAP_SIZE_UP,
+ WIDX_MAP_SIZE_DOWN,
+ WIDX_BASE_HEIGHT,
+ WIDX_BASE_HEIGHT_UP,
+ WIDX_BASE_HEIGHT_DOWN,
+ WIDX_WATER_LEVEL,
+ WIDX_WATER_LEVEL_UP,
+ WIDX_WATER_LEVEL_DOWN,
+ WIDX_FLOOR_TEXTURE,
+ WIDX_WALL_TEXTURE,
+
+ WIDX_RANDOM_TERRAIN = 7,
+ WIDX_PLACE_TREES,
+};
+
+#pragma region Widgets
+
+static rct_widget window_mapgen_base_widgets[] = {
+ { WWT_FRAME, 0, 0, 299, 0, 195, 0xFFFFFFFF, STR_NONE },
+ { WWT_CAPTION, 0, 1, 298, 1, 14, 2690, STR_WINDOW_TITLE_TIP },
+ { WWT_CLOSEBOX, 0, 287, 297, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
+ { WWT_RESIZE, 1, 0, 299, 43, 195, 0xFFFFFFFF, STR_NONE },
+ { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_NONE },
+ { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, STR_NONE },
+
+ { WWT_DROPDOWN_BUTTON, 1, 104, 198, 52, 63, 2694, STR_NONE },
+
+ { WWT_SPINNER, 1, 104, 198, 52, 63, STR_NONE, STR_NONE },
+ { WWT_DROPDOWN_BUTTON, 1, 187, 197, 53, 57, STR_NUMERIC_UP, STR_NONE },
+ { WWT_DROPDOWN_BUTTON, 1, 187, 197, 58, 62, STR_NUMERIC_DOWN, STR_NONE },
+ { WWT_SPINNER, 1, 104, 198, 70, 81, STR_NONE, STR_NONE },
+ { WWT_DROPDOWN_BUTTON, 1, 187, 197, 71, 75, STR_NUMERIC_UP, STR_NONE },
+ { WWT_DROPDOWN_BUTTON, 1, 187, 197, 76, 80, STR_NUMERIC_DOWN, STR_NONE },
+ { WWT_SPINNER, 1, 104, 198, 88, 99, STR_NONE, STR_NONE },
+ { WWT_DROPDOWN_BUTTON, 1, 187, 197, 89, 93, STR_NUMERIC_UP, STR_NONE },
+ { WWT_DROPDOWN_BUTTON, 1, 187, 197, 94, 98, STR_NUMERIC_DOWN, STR_NONE },
+ { WWT_FLATBTN, 1, 104, 150, 106, 141, 0xFFFFFFFF, STR_CHANGE_BASE_LAND_TIP },
+ { WWT_FLATBTN, 1, 151, 197, 106, 141, 0xFFFFFFFF, STR_CHANGE_VERTICAL_LAND_TIP },
+ { WIDGETS_END },
+};
+
+static rct_widget window_mapgen_random_widgets[] = {
+ { WWT_FRAME, 0, 0, 299, 0, 195, 0xFFFFFFFF, STR_NONE },
+ { WWT_CAPTION, 0, 1, 298, 1, 14, 2690, STR_WINDOW_TITLE_TIP },
+ { WWT_CLOSEBOX, 0, 287, 297, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
+ { WWT_RESIZE, 1, 0, 299, 43, 195, 0xFFFFFFFF, STR_NONE },
+ { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_NONE },
+ { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, STR_NONE },
+
+ { WWT_DROPDOWN_BUTTON, 1, 104, 198, 52, 63, 2694, STR_NONE },
+
+ { WWT_CHECKBOX, 1, 4, 198, 52, 63, 2695, STR_NONE },
+ { WWT_CHECKBOX, 1, 4, 198, 70, 81, 2696, STR_NONE },
+ { WIDGETS_END },
+};
+
+static rct_widget *window_mapgen_page_widgets[] = {
+ window_mapgen_base_widgets,
+ window_mapgen_random_widgets
+};
+
+#pragma endregion
+
+#pragma region Events
+
+static void window_mapgen_emptysub() { }
+
+static void window_mapgen_base_mouseup();
+static void window_mapgen_base_mousedown(int widgetIndex, rct_window *w, rct_widget* widget);
+static void window_mapgen_base_dropdown();
+static void window_mapgen_base_update(rct_window *w);
+static void window_mapgen_base_invalidate();
+static void window_mapgen_base_paint();
+static void window_mapgen_random_mouseup();
+static void window_mapgen_random_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
+static void window_mapgen_random_update(rct_window *w);
+static void window_mapgen_random_invalidate();
+static void window_mapgen_random_paint();
+
+static void* window_mapgen_base_events[] = {
+ window_mapgen_emptysub,
+ window_mapgen_base_mouseup,
+ window_mapgen_emptysub,
+ window_mapgen_base_mousedown,
+ window_mapgen_base_dropdown,
+ window_mapgen_emptysub,
+ window_mapgen_base_update,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_base_invalidate,
+ window_mapgen_base_paint,
+ window_mapgen_emptysub
+};
+
+static void* window_mapgen_random_events[] = {
+ window_mapgen_emptysub,
+ window_mapgen_random_mouseup,
+ window_mapgen_emptysub,
+ window_mapgen_random_mousedown,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_random_update,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_emptysub,
+ window_mapgen_random_invalidate,
+ window_mapgen_random_paint,
+ window_mapgen_emptysub
+};
+
+static void* window_mapgen_page_events[] = {
+ window_mapgen_base_events,
+ window_mapgen_random_events
+};
+
+#pragma endregion
+
+#pragma region Enabled widgets
+
+static uint32 window_mapgen_page_enabled_widgets[] = {
+ (1 << WIDX_CLOSE) |
+ (1 << WIDX_TAB_1) |
+ (1 << WIDX_TAB_2) |
+ (1 << WIDX_GENERATE) |
+ (1 << WIDX_MAP_SIZE_UP) |
+ (1 << WIDX_MAP_SIZE_DOWN) |
+ (1 << WIDX_BASE_HEIGHT_UP) |
+ (1 << WIDX_BASE_HEIGHT_DOWN) |
+ (1 << WIDX_WATER_LEVEL_UP) |
+ (1 << WIDX_WATER_LEVEL_DOWN) |
+ (1 << WIDX_FLOOR_TEXTURE) |
+ (1 << WIDX_WALL_TEXTURE),
+
+ (1 << WIDX_CLOSE) |
+ (1 << WIDX_TAB_1) |
+ (1 << WIDX_TAB_2) |
+ (1 << WIDX_GENERATE) |
+ (1 << WIDX_RANDOM_TERRAIN) |
+ (1 << WIDX_PLACE_TREES)
+};
+
+static uint32 window_mapgen_page_hold_down_widgets[] = {
+ (1 << WIDX_MAP_SIZE_UP) |
+ (1 << WIDX_MAP_SIZE_DOWN) |
+ (1 << WIDX_BASE_HEIGHT_UP) |
+ (1 << WIDX_BASE_HEIGHT_DOWN) |
+ (1 << WIDX_WATER_LEVEL_UP) |
+ (1 << WIDX_WATER_LEVEL_DOWN),
+
+ 0
+};
+
+#pragma endregion
+
+const int window_mapgen_tab_animation_loops[] = { 16, 16 };
+
+static void window_mapgen_set_page(rct_window *w, int page);
+static void window_mapgen_set_pressed_tab(rct_window *w);
+static void window_mapgen_anchor_border_widgets(rct_window *w);
+static void window_mapgen_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w);
+
+static char window_land_floor_texture_order[] = {
+ TERRAIN_SAND_DARK, TERRAIN_SAND_LIGHT, TERRAIN_DIRT, TERRAIN_GRASS_CLUMPS, TERRAIN_GRASS,
+ TERRAIN_ROCK, TERRAIN_SAND, TERRAIN_MARTIAN, TERRAIN_CHECKERBOARD, TERRAIN_ICE,
+ TERRAIN_GRID_RED, TERRAIN_GRID_YELLOW, TERRAIN_GRID_BLUE, TERRAIN_GRID_GREEN
+};
+
+static char window_land_wall_texture_order[] = {
+ TERRAIN_EDGE_ROCK, TERRAIN_EDGE_WOOD_RED,
+ TERRAIN_EDGE_WOOD_BLACK, TERRAIN_EDGE_ICE,
+ 0, 0
+};
+
+static int _mapSize = 150;
+static int _baseHeight = 12;
+static int _waterLevel = 6;
+static int _floorTexture = TERRAIN_GRASS;
+static int _wallTexture = TERRAIN_EDGE_ROCK;
+static int _randomTerrrain = 1;
+static int _placeTrees = 1;
+
+rct_window *window_mapgen_open()
+{
+ rct_window *w;
+
+ w = window_bring_to_front_by_class(WC_MAPGEN);
+ if (w == NULL) {
+ w = window_create(
+ (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 300) / 2,
+ (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 200) / 2,
+ 300,
+ 200,
+ window_mapgen_page_events[0],
+ WC_MAPGEN,
+ WF_10
+ );
+ w->number = 0;
+ w->frame_no = 0;
+ w->colours[0] = 12;
+ w->colours[1] = 24;
+ w->colours[2] = 24;
+ }
+
+ w->page = WINDOW_MAPGEN_PAGE_BASE;
+ window_invalidate(w);
+ w->widgets = window_mapgen_page_widgets[WINDOW_MAPGEN_PAGE_BASE];
+ w->enabled_widgets = window_mapgen_page_enabled_widgets[WINDOW_MAPGEN_PAGE_BASE];
+ w->hold_down_widgets = window_mapgen_page_hold_down_widgets[WINDOW_MAPGEN_PAGE_BASE];
+ w->event_handlers = window_mapgen_page_events[WINDOW_MAPGEN_PAGE_BASE];
+ w->pressed_widgets = 0;
+ w->disabled_widgets = 0;
+ window_init_scroll_widgets(w);
+
+ return w;
+}
+
+#pragma region Base page
+
+static void window_mapgen_base_mouseup()
+{
+ short widgetIndex;
+ rct_window *w;
+ mapgen_settings mapgenSettings;
+
+ window_widget_get_registers(w, widgetIndex);
+
+ switch (widgetIndex) {
+ case WIDX_CLOSE:
+ window_close(w);
+ break;
+ case WIDX_TAB_1:
+ case WIDX_TAB_2:
+ window_mapgen_set_page(w, widgetIndex - WIDX_TAB_1);
+ break;
+ case WIDX_GENERATE:
+ mapgenSettings.mapSize = _mapSize;
+ mapgenSettings.height = _baseHeight + 2;
+ mapgenSettings.waterLevel = _waterLevel + 2;
+ mapgenSettings.floor = _floorTexture;
+ mapgenSettings.wall = _wallTexture;
+
+ mapgen_generate_blank(&mapgenSettings);
+ gfx_invalidate_screen();
+ break;
+ }
+}
+
+static void window_mapgen_base_mousedown(int widgetIndex, rct_window *w, rct_widget* widget)
+{
+ int i;
+
+ switch (widgetIndex) {
+ case WIDX_MAP_SIZE_UP:
+ _mapSize = min(_mapSize + 1, 256);
+ window_invalidate(w);
+ break;
+ case WIDX_MAP_SIZE_DOWN:
+ _mapSize = max(_mapSize - 1, 16);
+ window_invalidate(w);
+ break;
+ case WIDX_BASE_HEIGHT_UP:
+ _baseHeight = min(_baseHeight + 2, 60);
+ window_invalidate(w);
+ break;
+ case WIDX_BASE_HEIGHT_DOWN:
+ _baseHeight = max(_baseHeight - 2, 0);
+ window_invalidate(w);
+ break;
+ case WIDX_WATER_LEVEL_UP:
+ _waterLevel = min(_waterLevel + 2, 54);
+ window_invalidate(w);
+ break;
+ case WIDX_WATER_LEVEL_DOWN:
+ _waterLevel = max(_waterLevel - 2, 0);
+ window_invalidate(w);
+ break;
+ case WIDX_FLOOR_TEXTURE:
+ for (i = 0; i < 14; i++) {
+ gDropdownItemsFormat[i] = -1;
+ gDropdownItemsArgs[i] = SPR_FLOOR_TEXTURE_GRASS + window_land_floor_texture_order[i];
+ if (window_land_floor_texture_order[i] == _floorTexture)
+ RCT2_GLOBAL(0x009DEBA2, sint16) = i;
+ }
+ window_dropdown_show_image(
+ w->x + widget->left, w->y + widget->top,
+ widget->bottom - widget->top,
+ w->colours[2],
+ 0,
+ 14,
+ 47, 36,
+ gAppropriateImageDropdownItemsPerRow[14]
+ );
+ break;
+ case WIDX_WALL_TEXTURE:
+ for (i = 0; i < 4; i++) {
+ gDropdownItemsFormat[i] = -1;
+ gDropdownItemsArgs[i] = SPR_WALL_TEXTURE_ROCK + window_land_wall_texture_order[i];
+ if (window_land_wall_texture_order[i] == _wallTexture)
+ RCT2_GLOBAL(0x009DEBA2, sint16) = i;
+ }
+ window_dropdown_show_image(
+ w->x + widget->left, w->y + widget->top,
+ widget->bottom - widget->top,
+ w->colours[2],
+ 0,
+ 4,
+ 47, 36,
+ gAppropriateImageDropdownItemsPerRow[4]
+ );
+ break;
+ }
+}
+
+static void window_mapgen_base_dropdown()
+{
+ int type;
+ short dropdownIndex, widgetIndex;
+ rct_window *w;
+
+ window_dropdown_get_registers(w, widgetIndex, dropdownIndex);
+
+ switch (widgetIndex) {
+ case WIDX_FLOOR_TEXTURE:
+ if (dropdownIndex == -1)
+ dropdownIndex = RCT2_GLOBAL(0x009DEBA2, sint16);
+
+ type = (dropdownIndex == -1) ?
+ _floorTexture :
+ *((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_FLOOR_TEXTURE_GRASS;
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) == type) {
+ RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) = 255;
+ } else {
+ RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) = type;
+ _floorTexture = type;
+ }
+ window_invalidate(w);
+ break;
+ case WIDX_WALL_TEXTURE:
+ if (dropdownIndex == -1)
+ dropdownIndex = RCT2_GLOBAL(0x009DEBA2, sint16);
+
+ type = (dropdownIndex == -1) ?
+ _wallTexture :
+ *((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_WALL_TEXTURE_ROCK;
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) == type) {
+ RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) = 255;
+ } else {
+ RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) = type;
+ _wallTexture = type;
+ }
+ window_invalidate(w);
+ break;
+ }
+}
+
+static void window_mapgen_base_update(rct_window *w)
+{
+ // Tab animation
+ if (++w->frame_no >= window_mapgen_tab_animation_loops[w->page])
+ w->frame_no = 0;
+ widget_invalidate(w, WIDX_TAB_1);
+}
+
+static void window_mapgen_base_invalidate()
+{
+ rct_window *w;
+
+ window_get_register(w);
+
+ if (w->widgets != window_mapgen_page_widgets[WINDOW_MAPGEN_PAGE_BASE]) {
+ w->widgets = window_mapgen_page_widgets[WINDOW_MAPGEN_PAGE_BASE];
+ window_init_scroll_widgets(w);
+ }
+
+ w->widgets[WIDX_FLOOR_TEXTURE].image = SPR_FLOOR_TEXTURE_GRASS + _floorTexture;
+ w->widgets[WIDX_WALL_TEXTURE].image = SPR_WALL_TEXTURE_ROCK + _wallTexture;
+
+ window_mapgen_set_pressed_tab(w);
+ window_mapgen_anchor_border_widgets(w);
+}
+
+static void window_mapgen_base_paint()
+{
+ uint16 arg;
+ rct_window *w;
+ rct_drawpixelinfo *dpi;
+
+ window_paint_get_registers(w, dpi);
+
+ window_draw_widgets(w, dpi);
+ window_mapgen_draw_tab_images(dpi, w);
+
+ gfx_draw_string_left(dpi, STR_MAP_SIZE, 0, 0, w->x + 4, w->y + w->widgets[WIDX_MAP_SIZE].top + 1);
+ gfx_draw_string_left(dpi, 2691, 0, 0, w->x + 4, w->y + w->widgets[WIDX_BASE_HEIGHT].top + 1);
+ gfx_draw_string_left(dpi, 2692, 0, 0, w->x + 4, w->y + w->widgets[WIDX_WATER_LEVEL].top + 1);
+ gfx_draw_string_left(dpi, 2693, 0, 0, w->x + 4, w->y + w->widgets[WIDX_FLOOR_TEXTURE].top + 1);
+
+ uint16 mapSizeArgs[2] = { _mapSize, _mapSize };
+ gfx_draw_string_left(dpi, 839, mapSizeArgs, w->colours[1], w->x + w->widgets[WIDX_MAP_SIZE].left + 1, w->y + w->widgets[WIDX_MAP_SIZE].top + 1);
+
+ arg = (_baseHeight - 12) / 2;
+ gfx_draw_string_left(dpi, 1737, &arg, w->colours[1], w->x + w->widgets[WIDX_BASE_HEIGHT].left + 1, w->y + w->widgets[WIDX_BASE_HEIGHT].top + 1);
+
+ arg = (_waterLevel - 12) / 2;
+ gfx_draw_string_left(dpi, 1737, &arg, w->colours[1], w->x + w->widgets[WIDX_WATER_LEVEL].left + 1, w->y + w->widgets[WIDX_WATER_LEVEL].top + 1);
+}
+
+#pragma endregion
+
+#pragma region Random page
+
+static void window_mapgen_random_mouseup()
+{
+ rct_window * w;
+ short widgetIndex;
+ mapgen_settings mapgenSettings;
+
+ window_widget_get_registers(w, widgetIndex);
+
+ switch (widgetIndex) {
+ case WIDX_CLOSE:
+ window_close(w);
+ break;
+ case WIDX_TAB_1:
+ case WIDX_TAB_2:
+ window_mapgen_set_page(w, widgetIndex - WIDX_TAB_1);
+ break;
+ case WIDX_GENERATE:
+ mapgenSettings.mapSize = _mapSize;
+ mapgenSettings.height = _baseHeight + 2;
+ mapgenSettings.waterLevel = _waterLevel + 2;
+ mapgenSettings.floor = _randomTerrrain ? -1 : _floorTexture;
+ mapgenSettings.wall = _randomTerrrain ? -1 : _wallTexture;
+ mapgenSettings.trees = _placeTrees;
+
+ mapgen_generate(&mapgenSettings);
+ gfx_invalidate_screen();
+ break;
+ case WIDX_RANDOM_TERRAIN:
+ _randomTerrrain ^= 1;
+ break;
+ case WIDX_PLACE_TREES:
+ _placeTrees ^= 1;
+ break;
+ }
+}
+
+static void window_mapgen_random_mousedown(int widgetIndex, rct_window *w, rct_widget* widget)
+{
+
+}
+
+static void window_mapgen_random_update(rct_window *w)
+{
+ // Tab animation
+ if (++w->frame_no >= window_mapgen_tab_animation_loops[w->page])
+ w->frame_no = 0;
+ widget_invalidate(w, WIDX_TAB_2);
+}
+
+static void window_mapgen_random_invalidate()
+{
+ rct_window *w;
+
+ window_get_register(w);
+
+ if (w->widgets != window_mapgen_page_widgets[WINDOW_MAPGEN_PAGE_RANDOM]) {
+ w->widgets = window_mapgen_page_widgets[WINDOW_MAPGEN_PAGE_RANDOM];
+ window_init_scroll_widgets(w);
+ }
+
+ w->pressed_widgets = 0;
+ if (_randomTerrrain)
+ w->pressed_widgets |= 1 << WIDX_RANDOM_TERRAIN;
+ if (_placeTrees)
+ w->pressed_widgets |= 1 << WIDX_PLACE_TREES;
+
+ window_mapgen_set_pressed_tab(w);
+ window_mapgen_anchor_border_widgets(w);
+}
+
+static void window_mapgen_random_paint()
+{
+ rct_window *w;
+ rct_drawpixelinfo *dpi;
+
+ window_paint_get_registers(w, dpi);
+
+ window_draw_widgets(w, dpi);
+ window_mapgen_draw_tab_images(dpi, w);
+}
+
+#pragma endregion
+
+#pragma region Common
+
+static void window_mapgen_set_page(rct_window *w, int page)
+{
+ w->page = page;
+ w->frame_no = 0;
+ if (w->viewport != NULL) {
+ w->viewport->width = 0;
+ w->viewport = NULL;
+ }
+
+ w->enabled_widgets = window_mapgen_page_enabled_widgets[page];
+ w->hold_down_widgets = window_mapgen_page_hold_down_widgets[page];
+ w->event_handlers = window_mapgen_page_events[page];
+ w->widgets = window_mapgen_page_widgets[page];
+ w->disabled_widgets = 0;
+ w->pressed_widgets = 0;
+
+ window_init_scroll_widgets(w);
+ window_invalidate(w);
+}
+
+static void window_mapgen_set_pressed_tab(rct_window *w)
+{
+ int i;
+ for (i = 0; i < WINDOW_MAPGEN_PAGE_COUNT; i++)
+ w->pressed_widgets &= ~(1 << (WIDX_TAB_1 + i));
+ w->pressed_widgets |= 1LL << (WIDX_TAB_1 + w->page);
+}
+
+static void window_mapgen_anchor_border_widgets(rct_window *w)
+{
+ int width = w->widgets[WIDX_GENERATE].right - w->widgets[WIDX_GENERATE].left;
+ int height = w->widgets[WIDX_GENERATE].bottom - w->widgets[WIDX_GENERATE].top;
+
+ w->widgets[WIDX_GENERATE].left = w->width - 3 - width;
+ w->widgets[WIDX_GENERATE].right = w->width - 3;
+ w->widgets[WIDX_GENERATE].bottom = w->height - 3;
+ w->widgets[WIDX_GENERATE].top = w->height - 3 - height;
+
+ w->widgets[WIDX_BACKGROUND].right = w->width - 1;
+ w->widgets[WIDX_BACKGROUND].bottom = w->height - 1;
+ w->widgets[WIDX_PAGE_BACKGROUND].right = w->width - 1;
+ w->widgets[WIDX_PAGE_BACKGROUND].bottom = w->height - 3 - height - 3;
+ w->widgets[WIDX_TITLE].right = w->width - 2;
+ w->widgets[WIDX_CLOSE].left = w->width - 13;
+ w->widgets[WIDX_CLOSE].right = w->width - 3;
+}
+
+static void window_mapgen_draw_tab_image(rct_drawpixelinfo *dpi, rct_window *w, int page, int spriteIndex)
+{
+ int widgetIndex = WIDX_TAB_1 + page;
+
+ if (!(w->disabled_widgets & (1LL << widgetIndex))) {
+ if (w->page == page) {
+ int frame = w->frame_no / 2;
+ if (page == WINDOW_MAPGEN_PAGE_BASE)
+ frame %= 8;
+ spriteIndex += frame;
+ }
+
+ gfx_draw_sprite(dpi, spriteIndex, w->x + w->widgets[widgetIndex].left, w->y + w->widgets[widgetIndex].top, 0);
+ }
+}
+
+static void window_mapgen_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w)
+{
+
+}
+
+#pragma endregion
\ No newline at end of file
diff --git a/src/windows/new_campaign.c b/src/windows/new_campaign.c
index b21dc913e7..c5e2ab2f56 100644
--- a/src/windows/new_campaign.c
+++ b/src/windows/new_campaign.c
@@ -152,7 +152,9 @@ void window_new_campaign_open(sint16 campaignType)
(1 << WIDX_WEEKS_INCREASE_BUTTON) |
(1 << WIDX_WEEKS_DECREASE_BUTTON) |
(1 << WIDX_START_BUTTON);
- w->var_020 = 0x300;
+ w->hold_down_widgets =
+ (1 << WIDX_WEEKS_INCREASE_BUTTON) |
+ (1 << WIDX_WEEKS_DECREASE_BUTTON);
window_init_scroll_widgets(w);
w->colours[0] = 19;
w->colours[1] = 19;
@@ -232,8 +234,7 @@ static void window_new_campaign_mouseup()
window_close(w);
break;
case WIDX_START_BUTTON:
- RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_START_MARKETING_CAMPAIGN;
- game_do_command(0, (w->campaign.no_weeks << 8) | 1, 0, (w->campaign.ride_id << 8) | w->campaign.campaign_type, GAME_COMMAND_START_MARKETING_CAMPAIGN, 0, 0);
+ marketing_start_campaign(w->campaign.campaign_type, w->campaign.ride_id, w->campaign.no_weeks);
window_close(w);
break;
}
diff --git a/src/windows/new_ride.c b/src/windows/new_ride.c
index e699f4e293..fead4b696a 100644
--- a/src/windows/new_ride.c
+++ b/src/windows/new_ride.c
@@ -658,7 +658,7 @@ static void window_new_ride_scrollmousedown()
window_scrollmouse_get_registers(w, scrollIndex, x, y);
- if (RCT2_GLOBAL(0x009DEA6E, uint8) != 0)
+ if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0)
return;
item = window_new_ride_scroll_get_ride_list_item_at(w, x, y);
diff --git a/src/windows/options.c b/src/windows/options.c
index 33a926693c..61527ed013 100644
--- a/src/windows/options.c
+++ b/src/windows/options.c
@@ -35,9 +35,10 @@
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../localisation/localisation.h"
+#include "../platform/platform.h"
#include "../sprites.h"
-#include "../platform/osinterface.h"
#include "dropdown.h"
+#include "error.h"
enum {
WINDOW_OPTIONS_PAGE_DISPLAY,
@@ -87,6 +88,8 @@ enum WINDOW_OPTIONS_WIDGET_IDX {
WIDX_SOUND_QUALITY_DROPDOWN,
WIDX_SOUND_SW_BUFFER_CHECKBOX,
WIDX_SOUND_PAUSED_CHECKBOX,
+ WIDX_TITLE_MUSIC,
+ WIDX_TITLE_MUSIC_DROPDOWN,
WIDX_SCREEN_EDGE_SCROLLING,
WIDX_HOTKEY_DROPDOWN,
@@ -96,7 +99,7 @@ enum WINDOW_OPTIONS_WIDGET_IDX {
};
#define WW 310
-#define WH 135
+#define WH 153
static rct_widget window_options_widgets[] = {
{ WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, STR_NONE, STR_NONE },
@@ -140,6 +143,8 @@ static rct_widget window_options_widgets[] = {
{ WWT_DROPDOWN_BUTTON, 0, 288, 298, 84, 93, 876, STR_NONE },
{ WWT_CHECKBOX, 0, 10, 299, 99, 110, STR_SOUND_FORCED_SOFTWARE_BUFFER_MIXING, STR_SOUND_FORCED_SOFTWARE_BUFFER_MIXING_TIP },
{ WWT_CHECKBOX, 0, 10, 229, 114, 125, STR_SOUND, STR_NONE }, // enable/disable sound
+ { WWT_DROPDOWN, 0, 155, 299, 130, 141, STR_NONE, STR_NONE }, // title music
+ { WWT_DROPDOWN_BUTTON, 0, 288, 298, 131, 140, 876, STR_NONE },
// Controls tab
{ WWT_CHECKBOX, 2, 10, 299, 53, 64, STR_SCREEN_EDGE_SCROLLING, STR_SCREEN_EDGE_SCROLLING_TIP },
@@ -228,6 +233,8 @@ void window_options_open()
(1ULL << WIDX_MUSIC_DROPDOWN) |
(1ULL << WIDX_SOUND_QUALITY) |
(1ULL << WIDX_SOUND_QUALITY_DROPDOWN) |
+ (1ULL << WIDX_TITLE_MUSIC) |
+ (1ULL << WIDX_TITLE_MUSIC_DROPDOWN) |
(1ULL << WIDX_LANGUAGE) |
(1ULL << WIDX_LANGUAGE_DROPDOWN) |
(1ULL << WIDX_CURRENCY) |
@@ -386,6 +393,18 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsChecked = 1 << gSound_config.sound_quality;
break;
+ case WIDX_TITLE_MUSIC_DROPDOWN:
+ num_items = 3;
+
+ for (i = 0; i < num_items; i++) {
+ gDropdownItemsFormat[i] = 1142;
+ gDropdownItemsArgs[i] = 2739 + i;
+ }
+
+ window_options_show_dropdown(w, widget, num_items);
+
+ gDropdownItemsChecked = 1 << gGeneral_config.title_music;
+ break;
case WIDX_CURRENCY_DROPDOWN:
num_items = 10;
@@ -409,7 +428,30 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsChecked = 1 << gGeneral_config.measurement_format;
break;
case WIDX_RESOLUTION_DROPDOWN:
- // RCT2_CALLPROC_EBPSAFE(0x006BB2AF);
+ {
+ platform_update_fullscreen_resolutions();
+
+ int selectedResolution = -1;
+ for (i = 0; i < gNumResolutions; i++) {
+ resolution *resolution = &gResolutions[i];
+
+ gDropdownItemsFormat[i] = 1142;
+
+ uint16 *args = (uint16*)&gDropdownItemsArgs[i];
+ args[0] = 839;
+ args[1] = resolution->width;
+ args[2] = resolution->height;
+
+ if (resolution->width == gGeneral_config.fullscreen_width && resolution->height == gGeneral_config.fullscreen_height)
+ selectedResolution = i;
+ }
+
+ window_options_show_dropdown(w, widget, gNumResolutions);
+
+ if (selectedResolution != -1 && selectedResolution < 32)
+ gDropdownItemsChecked = 1 << selectedResolution;
+ }
+
break;
case WIDX_FULLSCREEN_DROPDOWN:
gDropdownItemsFormat[0] = 1142;
@@ -516,6 +558,15 @@ static void window_options_dropdown()
config_save();
window_invalidate(w);
break;
+ case WIDX_TITLE_MUSIC_DROPDOWN:
+ if (dropdownIndex == 1 && !platform_file_exists(get_file_path(PATH_ID_CSS50))) {
+ window_error_open(2742, 2743);
+ } else {
+ gGeneral_config.title_music = (sint8)dropdownIndex;
+ config_save();
+ window_invalidate(w);
+ }
+ break;
case WIDX_CURRENCY_DROPDOWN:
gGeneral_config.currency_format = (sint8)dropdownIndex;
config_save();
@@ -527,13 +578,19 @@ static void window_options_dropdown()
window_options_update_height_markers();
break;
case WIDX_RESOLUTION_DROPDOWN:
- #ifdef _MSC_VER
- __asm movzx ax, dropdownIndex
- #else
- __asm__ ( "movzx ax, %[dropdownIndex] " : : [dropdownIndex] "g" ((char)dropdownIndex) );
- #endif
- // the switch replaces ax value
- RCT2_CALLPROC_EBPSAFE(0x006BB37D);
+ {
+ resolution *resolution = &gResolutions[dropdownIndex];
+ if (resolution->width != gGeneral_config.fullscreen_width || resolution->height != gGeneral_config.fullscreen_height) {
+ gGeneral_config.fullscreen_width = resolution->width;
+ gGeneral_config.fullscreen_height = resolution->height;
+
+ if (gGeneral_config.fullscreen_mode == SDL_WINDOW_FULLSCREEN)
+ platform_set_fullscreen_mode(SDL_WINDOW_FULLSCREEN);
+
+ config_save();
+ gfx_invalidate_screen();
+ }
+ }
break;
case WIDX_FULLSCREEN_DROPDOWN:
if (dropdownIndex != gGeneral_config.fullscreen_mode){
@@ -544,7 +601,10 @@ static void window_options_dropdown()
w->disabled_widgets &= ~(1 << WIDX_RESOLUTION_DROPDOWN);
w->disabled_widgets &= ~(1 << WIDX_RESOLUTION);
}
- osinterface_set_fullscreen_mode(dropdownIndex);
+ platform_set_fullscreen_mode(dropdownIndex);
+
+ gGeneral_config.fullscreen_mode = (uint8)dropdownIndex;
+ config_save();
}
break;
case WIDX_TEMPERATURE_DROPDOWN:
@@ -592,8 +652,8 @@ static void window_options_invalidate()
switch (w->page) {
case WINDOW_OPTIONS_PAGE_DISPLAY:
// resolution
- RCT2_GLOBAL(0x013CE952 + 16, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_RESOLUTION_WIDTH, uint16);
- RCT2_GLOBAL(0x013CE952 + 18, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_RESOLUTION_HEIGHT, uint16);
+ RCT2_GLOBAL(0x013CE952 + 16, uint16) = gGeneral_config.fullscreen_width;
+ RCT2_GLOBAL(0x013CE952 + 18, uint16) = gGeneral_config.fullscreen_height;
RCT2_GLOBAL(0x013CE952 + 12, uint16) = 2773 + gGeneral_config.fullscreen_mode;
// landscape tile smoothing checkbox
@@ -681,6 +741,8 @@ static void window_options_invalidate()
window_options_widgets[WIDX_SOUND_QUALITY_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
window_options_widgets[WIDX_SOUND_SW_BUFFER_CHECKBOX].type = WWT_CHECKBOX;
window_options_widgets[WIDX_SOUND_PAUSED_CHECKBOX].type = WWT_CHECKBOX;
+ window_options_widgets[WIDX_TITLE_MUSIC].type = WWT_DROPDOWN;
+ window_options_widgets[WIDX_TITLE_MUSIC_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
break;
case WINDOW_OPTIONS_PAGE_INPUT:
// screen edge scrolling checkbox
@@ -770,6 +832,15 @@ static void window_options_paint()
case WINDOW_OPTIONS_PAGE_AUDIO:
gfx_draw_string_left(dpi, STR_MUSIC, w, 0, w->x + 10, w->y + window_options_widgets[WIDX_MUSIC].top + 1);
gfx_draw_string_left(dpi, STR_SOUND_QUALITY, w, 0, w->x + 10, w->y + window_options_widgets[WIDX_SOUND_QUALITY].top + 1);
+ gfx_draw_string_left(dpi, 2738, w, 12, w->x + 10, w->y + window_options_widgets[WIDX_TITLE_MUSIC].top + 1);
+ gfx_draw_string_left(
+ dpi,
+ 2739 + gGeneral_config.title_music,
+ NULL,
+ 12,
+ w->x + window_options_widgets[WIDX_TITLE_MUSIC].left + 1,
+ w->y + window_options_widgets[WIDX_TITLE_MUSIC].top
+ );
break;
}
}
@@ -791,7 +862,7 @@ static void window_options_show_dropdown(rct_window *w, rct_widget *widget, int
static void window_options_update_height_markers()
{
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, uint16) = gGeneral_config.show_height_as_units ?
- 0 : (gGeneral_config.show_height_as_units + 1) * 256;
+ 0 : (gGeneral_config.measurement_format + 1) * 256;
config_save();
gfx_invalidate_screen();
}
diff --git a/src/windows/park.c b/src/windows/park.c
index 3b980c2d01..1bb0664ffc 100644
--- a/src/windows/park.c
+++ b/src/windows/park.c
@@ -572,6 +572,19 @@ static uint32 window_park_page_enabled_widgets[] = {
(1 << WIDX_TAB_7)
};
+static uint32 window_park_page_hold_down_widgets[] = {
+ 0,
+ 0,
+ 0,
+
+ (1 << WIDX_INCREASE_PRICE) |
+ (1 << WIDX_DECREASE_PRICE),
+
+ 0,
+ 0,
+ 0
+};
+
#pragma endregion
static void window_park_init_viewport(rct_window *w);
@@ -611,12 +624,18 @@ rct_window *window_park_open()
*
* rct2: 0x00667F8B
*/
-void window_park_set_disabled_tabs(rct_window *w)
+static void window_park_set_disabled_tabs(rct_window *w)
{
// Disable price tab if money is disabled
w->disabled_widgets = (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) ? (1 << WIDX_TAB_4) : 0;
}
+static void window_park_prepare_window_title_text()
+{
+ RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id);
+ RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32);
+}
+
#pragma region Entrance page
/**
@@ -694,7 +713,7 @@ static void window_park_entrance_mouseup()
break;
case WIDX_RENAME:
RCT2_GLOBAL(0x013CE962, uint32) = RCT2_GLOBAL(0x013573D8, uint32);
- window_text_input_open(w, WIDX_RENAME, STR_PARK_NAME, STR_ENTER_PARK_NAME, RCT2_GLOBAL(0x013573D4, rct_string_id), 0, 32);
+ window_text_input_open(w, WIDX_RENAME, STR_PARK_NAME, STR_ENTER_PARK_NAME, RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id), 0, 32);
break;
}
}
@@ -755,19 +774,17 @@ static void window_park_entrance_dropdown()
window_dropdown_get_registers(w, widgetIndex, dropdownIndex);
-
if (widgetIndex == WIDX_OPEN_OR_CLOSE) {
if (dropdownIndex == -1)
dropdownIndex = RCT2_GLOBAL(0x009DEBA2, sint16);
+
if (dropdownIndex != 0) {
- dropdownIndex &= 0x00FF;
- dropdownIndex |= 0x0100;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1724;
+ park_set_open(1);
} else {
- dropdownIndex &= 0x00FF;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1723;
+ park_set_open(0);
}
- game_do_command(0, 1, 0, dropdownIndex, GAME_COMMAND_SET_PARK_OPEN, 0, 0);
}
}
@@ -869,14 +886,8 @@ static void window_park_entrance_textinput()
window_textinput_get_registers(w, widgetIndex, result, text);
- if (widgetIndex == WIDX_RENAME) {
- if (result) {
- RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_RENAME_PARK;
- game_do_command(1, 1, 0, *((int*)(text + 0)), GAME_COMMAND_33, *((int*)(text + 8)), *((int*)(text + 4)));
- game_do_command(2, 1, 0, *((int*)(text + 12)), GAME_COMMAND_33, *((int*)(text + 20)), *((int*)(text + 16)));
- game_do_command(0, 1, 0, *((int*)(text + 24)), GAME_COMMAND_33, *((int*)(text + 32)), *((int*)(text + 28)));
- }
- }
+ if (widgetIndex == WIDX_RENAME && result)
+ park_set_name(text);
}
/**
@@ -896,8 +907,8 @@ static void window_park_entrance_invalidate()
window_park_set_pressed_tab(w);
// Set open / close park button state
- RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x013573D4, uint16);
- RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x013573D8, uint32);
+ RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id);
+ RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32);
window_park_entrance_widgets[WIDX_OPEN_OR_CLOSE].image = park_is_open() ? SPR_OPEN : SPR_CLOSED;
// Only allow closing of park for guest / rating objective
@@ -1070,7 +1081,7 @@ void window_park_rating_open()
window_invalidate(window);
window->widgets = window_park_rating_widgets;
window->enabled_widgets = window_park_page_enabled_widgets[WINDOW_PARK_PAGE_RATING];
- window->var_020 = 0;
+ window->hold_down_widgets = window_park_page_hold_down_widgets[WINDOW_PARK_PAGE_RATING];
window->event_handlers = (uint32*)window_park_rating_events;
window_init_scroll_widgets(window);
}
@@ -1133,9 +1144,7 @@ static void window_park_rating_invalidate()
}
window_park_set_pressed_tab(w);
-
- RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x013573D4, uint16);
- RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x013573D8, uint32);
+ window_park_prepare_window_title_text();
window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_7);
window_park_anchor_border_widgets(w);
@@ -1204,7 +1213,7 @@ void window_park_guests_open()
window_invalidate(window);
window->widgets = window_park_guests_widgets;
window->enabled_widgets = window_park_page_enabled_widgets[WINDOW_PARK_PAGE_GUESTS];
- window->var_020 = 0;
+ window->hold_down_widgets = window_park_page_hold_down_widgets[WINDOW_PARK_PAGE_GUESTS];
window->event_handlers = (uint32*)window_park_guests_events;
window_init_scroll_widgets(window);
}
@@ -1268,9 +1277,7 @@ static void window_park_guests_invalidate()
}
window_park_set_pressed_tab(w);
-
- RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x013573D4, uint16);
- RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x013573D8, uint32);
+ window_park_prepare_window_title_text();
window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_7);
window_park_anchor_border_widgets(w);
@@ -1367,12 +1374,12 @@ static void window_park_price_mousedown(int widgetIndex, rct_window*w, rct_widge
window_park_set_page(w, widgetIndex - WIDX_TAB_1);
break;
case WIDX_INCREASE_PRICE:
- newFee = min(1000, RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, uint16) + 10);
- game_do_command(0, 1, 0, 0, GAME_COMMAND_SET_PARK_ENTRANCE_FEE, newFee, 0);
+ newFee = min(MONEY(100,00), RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) + MONEY(1,00));
+ park_set_entrance_fee(newFee);
break;
case WIDX_DECREASE_PRICE:
- newFee = max(0, RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, uint16) - 10);
- game_do_command(0, 1, 0, 0, GAME_COMMAND_SET_PARK_ENTRANCE_FEE, newFee, 0);
+ newFee = max(MONEY(0,00), RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) - MONEY(1,00));
+ park_set_entrance_fee(newFee);
break;
}
}
@@ -1405,9 +1412,7 @@ static void window_park_price_invalidate()
}
window_park_set_pressed_tab(w);
-
- RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x013573D4, uint16);
- RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x013573D8, uint32);
+ window_park_prepare_window_title_text();
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_FREE_ENTRY) {
window_park_price_widgets[WIDX_PRICE].type = WWT_12;
@@ -1527,9 +1532,7 @@ static void window_park_stats_invalidate()
}
window_park_set_pressed_tab(w);
-
- RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x013573D4, uint16);
- RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x013573D8, uint32);
+ window_park_prepare_window_title_text();
window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_7);
window_park_anchor_border_widgets(w);
@@ -1610,7 +1613,7 @@ void window_park_objective_open()
window_invalidate(window);
window->widgets = window_park_objective_widgets;
window->enabled_widgets = window_park_page_enabled_widgets[WINDOW_PARK_PAGE_OBJECTIVE];
- window->var_020 = 0;
+ window->hold_down_widgets = window_park_page_hold_down_widgets[WINDOW_PARK_PAGE_OBJECTIVE];
window->event_handlers = (uint32*)window_park_objective_events;
window_init_scroll_widgets(window);
window->x = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) / 2 - 115;
@@ -1709,10 +1712,7 @@ static void window_park_objective_invalidate()
window_get_register(w);
window_park_set_pressed_tab(w);
-
- // Set window title arguments
- *((uint16*)0x013CE952) = RCT2_GLOBAL(0x013573D4, uint16);
- *((uint32*)0x013CE954) = RCT2_GLOBAL(0x013573D8, uint32);
+ window_park_prepare_window_title_text();
//
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_SCENARIO_COMPLETE_NAME_INPUT)
@@ -1800,7 +1800,7 @@ void window_park_awards_open()
window_invalidate(window);
window->widgets = window_park_awards_widgets;
window->enabled_widgets = window_park_page_enabled_widgets[WINDOW_PARK_PAGE_AWARDS];
- window->var_020 = 0;
+ window->hold_down_widgets = window_park_page_hold_down_widgets[WINDOW_PARK_PAGE_AWARDS];
window->event_handlers = (uint32*)window_park_awards_events;
window_init_scroll_widgets(window);
}
@@ -1863,9 +1863,7 @@ static void window_park_awards_invalidate()
}
window_park_set_pressed_tab(w);
-
- RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x013573D4, uint16);
- RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x013573D8, uint32);
+ window_park_prepare_window_title_text();
window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_7);
window_park_anchor_border_widgets(w);
@@ -1937,7 +1935,7 @@ static void window_park_set_page(rct_window *w, int page)
}
w->enabled_widgets = window_park_page_enabled_widgets[page];
- w->var_020 = RCT2_GLOBAL(0x0097BAE0 + (page * 4), uint32);
+ w->hold_down_widgets = window_park_page_hold_down_widgets[page];
w->event_handlers = window_park_page_events[page];
w->widgets = window_park_page_widgets[page];
window_park_set_disabled_tabs(w);
diff --git a/src/windows/research.c b/src/windows/research.c
index a06bc5a02c..9fc9f5c9da 100644
--- a/src/windows/research.c
+++ b/src/windows/research.c
@@ -249,7 +249,7 @@ void window_research_open()
w->widgets = window_research_page_widgets[0];
w->enabled_widgets = window_research_page_enabled_widgets[0];
- w->var_020 = RCT2_GLOBAL(0x00988E3C, uint32);
+ w->hold_down_widgets = 0;
w->event_handlers = window_research_page_events[0];
w->pressed_widgets = 0;
w->disabled_widgets = 0;
@@ -430,7 +430,7 @@ static void window_research_funding_mouseup()
case WIDX_SCENERY_AND_THEMING:
activeResearchTypes = RCT2_GLOBAL(RCT2_ADDRESS_ACTIVE_RESEARCH_TYPES, uint16);
activeResearchTypes ^= 1 << (widgetIndex - WIDX_TRANSPORT_RIDES);
- game_do_command(0, (1 << 8) | 1, 0, activeResearchTypes, GAME_COMMAND_SET_RESEARCH_FUNDING, 0, 0);
+ research_set_priority(activeResearchTypes);
break;
}
}
@@ -482,7 +482,7 @@ static void window_research_funding_dropdown()
if (widgetIndex != WIDX_RESEARCH_FUNDING_DROPDOWN_BUTTON || dropdownIndex == -1)
return;
- game_do_command(0, 1, 0, dropdownIndex, GAME_COMMAND_SET_RESEARCH_FUNDING, 0, 0);
+ research_set_funding(dropdownIndex);
window_invalidate(w);
}
@@ -591,7 +591,7 @@ static void window_research_set_page(rct_window *w, int page)
}
w->enabled_widgets = window_research_page_enabled_widgets[page];
- w->var_020 = RCT2_ADDRESS(0x00988E3C, uint32)[page];
+ w->hold_down_widgets = 0;
w->event_handlers = window_research_page_events[page];
w->widgets = window_research_page_widgets[page];
w->disabled_widgets = 0;
diff --git a/src/windows/ride.c b/src/windows/ride.c
index a25e1e1274..f9043aeae0 100644
--- a/src/windows/ride.c
+++ b/src/windows/ride.c
@@ -36,18 +36,18 @@
#define var_496(w) RCT2_GLOBAL((int)w + 0x496, uint16)
-enum WINDOW_PARK_PAGE {
- WINDOW_PARK_PAGE_MAIN,
- WINDOW_PARK_PAGE_VEHICLE,
- WINDOW_PARK_PAGE_OPERATING,
- WINDOW_PARK_PAGE_MAINTENANCE,
- WINDOW_PARK_PAGE_COLOUR,
- WINDOW_PARK_PAGE_MUSIC,
- WINDOW_PARK_PAGE_MEASUREMENTS,
- WINDOW_PARK_PAGE_GRAPHS,
- WINDOW_PARK_PAGE_INCOME,
- WINDOW_PARK_PAGE_CUSTOMER,
- WINDOW_PARK_PAGE_COUNT
+enum {
+ WINDOW_RIDE_PAGE_MAIN,
+ WINDOW_RIDE_PAGE_VEHICLE,
+ WINDOW_RIDE_PAGE_OPERATING,
+ WINDOW_RIDE_PAGE_MAINTENANCE,
+ WINDOW_RIDE_PAGE_COLOUR,
+ WINDOW_RIDE_PAGE_MUSIC,
+ WINDOW_RIDE_PAGE_MEASUREMENTS,
+ WINDOW_RIDE_PAGE_GRAPHS,
+ WINDOW_RIDE_PAGE_INCOME,
+ WINDOW_RIDE_PAGE_CUSTOMER,
+ WINDOW_RIDE_PAGE_COUNT
};
#pragma region Widgets
@@ -489,6 +489,19 @@ const uint64 window_ride_page_enabled_widgets[] = {
0x000000000001FFF4
};
+const uint64 window_ride_page_hold_down_widgets[] = {
+ 0x0000000000000000,
+ 0x0000000000000000,
+ 0x00000000330D8000,
+ 0x0000000000000000,
+ 0x0000000000000000,
+ 0x0000000000000000,
+ 0x0000000000000000,
+ 0x0000000000000000,
+ 0x0000000000630000,
+ 0x0000000000000000
+};
+
#pragma endregion
#pragma region Events
@@ -944,7 +957,7 @@ static void window_ride_draw_tab_image(rct_drawpixelinfo *dpi, rct_window *w, in
*/
static void window_ride_draw_tab_main(rct_drawpixelinfo *dpi, rct_window *w)
{
- int widgetIndex = WIDX_TAB_1 + WINDOW_PARK_PAGE_MAIN;
+ int widgetIndex = WIDX_TAB_1 + WINDOW_RIDE_PAGE_MAIN;
if (!(w->disabled_widgets & (1LL << widgetIndex))) {
int spriteIndex;
@@ -953,17 +966,17 @@ static void window_ride_draw_tab_main(rct_drawpixelinfo *dpi, rct_window *w)
switch (gRideClassifications[rideType]) {
case RIDE_CLASS_RIDE:
spriteIndex = 5442;
- if (w->page == WINDOW_PARK_PAGE_MAIN)
+ if (w->page == WINDOW_RIDE_PAGE_MAIN)
spriteIndex += (w->frame_no / 4) % 16;
break;
case RIDE_CLASS_SHOP_OR_STALL:
spriteIndex = 5351;
- if (w->page == WINDOW_PARK_PAGE_MAIN)
+ if (w->page == WINDOW_RIDE_PAGE_MAIN)
spriteIndex += (w->frame_no / 4) % 16;
break;
case RIDE_CLASS_KIOSK_OR_FACILITY:
spriteIndex = 5367;
- if (w->page == WINDOW_PARK_PAGE_MAIN)
+ if (w->page == WINDOW_RIDE_PAGE_MAIN)
spriteIndex += (w->frame_no / 4) % 8;
break;
}
@@ -985,7 +998,7 @@ static void window_ride_draw_tab_vehicle(rct_drawpixelinfo *dpi, rct_window *w)
rct_ride_type *rideEntry;
vehicle_colour vehicleColour;
- widgetIndex = WIDX_TAB_1 + WINDOW_PARK_PAGE_VEHICLE;
+ widgetIndex = WIDX_TAB_1 + WINDOW_RIDE_PAGE_VEHICLE;
widget = &w->widgets[widgetIndex];
if (!(w->disabled_widgets & (1LL << widgetIndex))) {
@@ -993,7 +1006,7 @@ static void window_ride_draw_tab_vehicle(rct_drawpixelinfo *dpi, rct_window *w)
y = widget->top + 1;
width = widget->right - x;
height = widget->bottom - 3 - y;
- if (w->page == WINDOW_PARK_PAGE_VEHICLE)
+ if (w->page == WINDOW_RIDE_PAGE_VEHICLE)
height += 4;
x += w->x;
@@ -1026,7 +1039,7 @@ static void window_ride_draw_tab_vehicle(rct_drawpixelinfo *dpi, rct_window *w)
vehicleColour = ride_get_vehicle_colour(ride, 0);
spriteIndex = 32;
- if (w->page == WINDOW_PARK_PAGE_VEHICLE)
+ if (w->page == WINDOW_RIDE_PAGE_VEHICLE)
spriteIndex += w->frame_no;
spriteIndex /= (RCT2_GLOBAL(ebp + 0x2C, uint16) & 0x800) ? 4 : 2;
spriteIndex &= RCT2_GLOBAL(ebp + 0x1A, uint16);
@@ -1047,12 +1060,12 @@ static void window_ride_draw_tab_vehicle(rct_drawpixelinfo *dpi, rct_window *w)
static void window_ride_draw_tab_customer(rct_drawpixelinfo *dpi, rct_window *w)
{
int spriteIndex;
- int widgetIndex = WIDX_TAB_1 + WINDOW_PARK_PAGE_CUSTOMER;
+ int widgetIndex = WIDX_TAB_1 + WINDOW_RIDE_PAGE_CUSTOMER;
rct_widget *widget = &w->widgets[widgetIndex];
if (!(w->disabled_widgets & (1LL << widgetIndex))) {
spriteIndex = 0;
- if (w->page == WINDOW_PARK_PAGE_CUSTOMER)
+ if (w->page == WINDOW_RIDE_PAGE_CUSTOMER)
spriteIndex = w->var_492 & ~3;
spriteIndex += RCT2_GLOBAL(RCT2_GLOBAL(0x00982708, uint32), uint32);
@@ -1070,15 +1083,15 @@ static void window_ride_draw_tab_customer(rct_drawpixelinfo *dpi, rct_window *w)
static void window_ride_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w)
{
window_ride_draw_tab_vehicle(dpi, w);
- window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_OPERATING, 5201);
- window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_MAINTENANCE, 5205);
- window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_INCOME, 5253);
+ window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_OPERATING, 5201);
+ window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_MAINTENANCE, 5205);
+ window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_INCOME, 5253);
window_ride_draw_tab_main(dpi, w);
- window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_MEASUREMENTS, 5229);
- window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_COLOUR, 5221);
- window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_GRAPHS, 5237);
+ window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_MEASUREMENTS, 5229);
+ window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_COLOUR, 5221);
+ window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_GRAPHS, 5237);
window_ride_draw_tab_customer(dpi, w);
- window_ride_draw_tab_image(dpi, w, WINDOW_PARK_PAGE_MUSIC, 5335);
+ window_ride_draw_tab_image(dpi, w, WINDOW_RIDE_PAGE_MUSIC, 5335);
}
/**
@@ -1150,14 +1163,14 @@ rct_window *window_ride_main_open(int rideIndex)
}
}
- w->page = 0;
+ w->page = WINDOW_RIDE_PAGE_MAIN;
w->width = 316;
w->height = 180;
window_invalidate(w);
- w->widgets = window_ride_page_widgets[0];
- w->enabled_widgets = 0x007DBFF4;
- w->var_020 = 0;
- w->event_handlers = window_ride_page_events[0];
+ w->widgets = window_ride_page_widgets[WINDOW_RIDE_PAGE_MAIN];
+ w->enabled_widgets = window_ride_page_enabled_widgets[WINDOW_RIDE_PAGE_MAIN];
+ w->hold_down_widgets = window_ride_page_hold_down_widgets[WINDOW_RIDE_PAGE_MAIN];
+ w->event_handlers = window_ride_page_events[WINDOW_RIDE_PAGE_MAIN];
w->pressed_widgets = 0;
RCT2_CALLPROC_X(0x006AEB9F, 0, 0, 0, 0, (int)w, 0, 0);
window_init_scroll_widgets(w);
@@ -1196,14 +1209,14 @@ rct_window *window_ride_open_station(int rideIndex, int stationIndex)
tool_cancel();
}
- w->page = WINDOW_PARK_PAGE_MAIN;
+ w->page = WINDOW_RIDE_PAGE_MAIN;
w->width = 316;
w->height = 180;
window_invalidate(w);
w->widgets = window_ride_page_widgets[w->page];
w->enabled_widgets = window_ride_page_enabled_widgets[w->page];
- w->var_020 = RCT2_ADDRESS(0x0098DD68, uint32)[w->page];
+ w->hold_down_widgets = window_ride_page_hold_down_widgets[w->page];
w->event_handlers = window_ride_page_events[w->page];
w->pressed_widgets = 0;
RCT2_CALLPROC_X(0x006AEB9F, 0, 0, 0, 0, (int)w, 0, 0);
@@ -1225,7 +1238,7 @@ rct_window *window_ride_open_track(rct_map_element *mapElement)
{
int rideIndex = mapElement->properties.track.ride_index;
if (
- ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_ENTRANCE) ||
+ (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) ||
(RCT2_ADDRESS(0x0099BA64, uint8)[mapElement->properties.track.type * 16] & 0x10)
) {
// Open ride window in station view
@@ -1305,14 +1318,14 @@ rct_window *window_ride_open_vehicle(rct_vehicle *vehicle)
w->ride.var_482 = -1;
}
- w->page = WINDOW_PARK_PAGE_MAIN;
+ w->page = WINDOW_RIDE_PAGE_MAIN;
w->width = 316;
w->height = 180;
window_invalidate(w);
w->widgets = window_ride_page_widgets[w->page];
w->enabled_widgets = window_ride_page_enabled_widgets[w->page];
- w->var_020 = RCT2_ADDRESS(0x0098DD68, uint32)[w->page];
+ w->hold_down_widgets = window_ride_page_hold_down_widgets[w->page];
w->event_handlers = window_ride_page_events[w->page];
w->pressed_widgets = 0;
RCT2_CALLPROC_X(0x006AEB9F, 0, 0, 0, 0, (int)w, 0, 0);
@@ -1339,7 +1352,7 @@ static void window_ride_set_page(rct_window *w, int page)
// Set listen only to viewport
listen = 0;
- if (page == WINDOW_PARK_PAGE_MAIN && w->page == WINDOW_PARK_PAGE_MAIN && w->viewport != NULL && !(w->viewport->flags & VIEWPORT_FLAG_SOUND_ON))
+ if (page == WINDOW_RIDE_PAGE_MAIN && w->page == WINDOW_RIDE_PAGE_MAIN && w->viewport != NULL && !(w->viewport->flags & VIEWPORT_FLAG_SOUND_ON))
listen++;
w->page = page;
@@ -1351,7 +1364,7 @@ static void window_ride_set_page(rct_window *w, int page)
}
w->enabled_widgets = window_ride_page_enabled_widgets[page];
- w->var_020 = RCT2_ADDRESS(0x0098DD68, uint32)[page];
+ w->hold_down_widgets = window_ride_page_hold_down_widgets[page];
w->event_handlers = window_ride_page_events[page];
w->pressed_widgets = 0;
w->widgets = window_ride_page_widgets[page];
@@ -1371,7 +1384,7 @@ static void window_ride_set_page(rct_window *w, int page)
static void window_ride_set_pressed_tab(rct_window *w)
{
int i;
- for (i = 0; i < WINDOW_PARK_PAGE_COUNT; i++)
+ for (i = 0; i < WINDOW_RIDE_PAGE_COUNT; i++)
w->pressed_widgets &= ~(1 << (WIDX_TAB_1 + i));
w->pressed_widgets |= 1LL << (WIDX_TAB_1 + w->page);
}
@@ -1395,7 +1408,7 @@ static void window_ride_anchor_border_widgets(rct_window *w)
*/
static void window_ride_init_viewport(rct_window *w)
{
- if (w->page != WINDOW_PARK_PAGE_MAIN) return;
+ if (w->page != WINDOW_RIDE_PAGE_MAIN) return;
rct_ride* ride = GET_RIDE(w->number);
int eax = w->viewport_focus_coordinates.var_480 - 1;
@@ -1552,39 +1565,6 @@ static void window_ride_rename(rct_window *w)
window_text_input_open(w, WIDX_RENAME, STR_RIDE_ATTRACTION_NAME, STR_ENTER_NEW_NAME_FOR_THIS_RIDE_ATTRACTION, ride->name, ride->name_arguments, 32);
}
-/**
- *
- * rct2: 0x006AF3B3
- */
-static void window_ride_locate(rct_window *w)
-{
- rct_window *mainWindow;
- int xy, x, y, z;
-
- if (w->viewport->width == 0)
- return;
-
- xy = w->ride.var_482;
- z = w->ride.var_486;
- if (xy == -1)
- return;
-
- if (xy & 0x80000000) {
- rct_sprite *sprite = &g_sprite_list[xy & 0xFFFF];
- x = sprite->unknown.x;
- y = sprite->unknown.y;
- z = sprite->unknown.z;
- } else {
- x = (xy & ~0xC0000000) & 0xFFFF;
- y = (xy & ~0xC0000000) >> 16;
- z = z >> 16;
- }
-
- mainWindow = window_get_main();
- if (mainWindow != NULL)
- window_scroll_to_location(mainWindow, x, y, z);
-}
-
/**
*
* rct2: 0x006AF17E
@@ -1619,7 +1599,7 @@ static void window_ride_main_mouseup()
window_ride_rename(w);
break;
case WIDX_LOCATE:
- window_ride_locate(w);
+ window_scroll_to_viewport(w);
break;
case WIDX_DEMOLISH:
window_ride_demolish_prompt_open(w->number);
@@ -1932,10 +1912,7 @@ static void window_ride_main_textinput()
if (widgetIndex != WIDX_RENAME || !result)
return;
- RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_RENAME_RIDE_ATTRACTION;
- game_do_command(1, (w->number << 8) | 1, 0, *((int*)(text + 0)), GAME_COMMAND_SET_RIDE_NAME, *((int*)(text + 8)), *((int*)(text + 4)));
- game_do_command(2, (w->number << 8) | 1, 0, *((int*)(text + 12)), GAME_COMMAND_SET_RIDE_NAME, *((int*)(text + 20)), *((int*)(text + 16)));
- game_do_command(0, (w->number << 8) | 1, 0, *((int*)(text + 24)), GAME_COMMAND_SET_RIDE_NAME, *((int*)(text + 32)), *((int*)(text + 28)));
+ ride_set_name(w->number, text);
}
/**
@@ -2431,7 +2408,7 @@ static void window_ride_vehicle_invalidate()
// Vehicle type
window_ride_vehicle_widgets[WIDX_VEHICLE_TYPE].image = rideEntry->name;
- if (var_496(w) <= 1 && (w->enabled_widgets & (1 << WIDX_TAB_10))) {
+ if (var_496(w) <= 1 || (rideEntry->var_008 & (1 << 13))) {
window_ride_vehicle_widgets[WIDX_VEHICLE_TYPE].type = WWT_14;
window_ride_vehicle_widgets[WIDX_VEHICLE_TYPE_DROPDOWN].type = WWT_EMPTY;
w->enabled_widgets &= ~(1 << WIDX_VEHICLE_TYPE);
@@ -2508,18 +2485,24 @@ static void window_ride_vehicle_paint()
if (!(rideEntry->var_008 & 0x2000) && var_496(w) > 1) {
// Excitement Factor
factor = rideEntry->excitement_multipler;
- gfx_draw_string_left(dpi, 3125, &factor, 0, x, y);
- y += 10;
+ if (factor > 0) {
+ gfx_draw_string_left(dpi, 3125, &factor, 0, x, y);
+ y += 10;
+ }
// Intensity Factor
factor = rideEntry->intensity_multipler;
- gfx_draw_string_left(dpi, 3126, &factor, 0, x, y);
- y += 10;
+ if (factor > 0) {
+ gfx_draw_string_left(dpi, 3126, &factor, 0, x, y);
+ y += 10;
+ }
// Nausea Factor
factor = rideEntry->nausea_multipler;
- gfx_draw_string_left(dpi, 3127, &factor, 0, x, y);
- y += 10;
+ if (factor > 0) {
+ gfx_draw_string_left(dpi, 3127, &factor, 0, x, y);
+ y += 10;
+ }
}
}
@@ -3090,6 +3073,7 @@ static void window_ride_operating_invalidate()
break;
case RIDE_MODE_STATION_TO_STATION:
RCT2_GLOBAL(0x013CE964, uint16) = (ride->var_0D0 * 9) / 4;
+ format = 1331;
caption = STR_SPEED;
tooltip = STR_SPEED_TIP;
break;
@@ -3221,7 +3205,7 @@ static void window_ride_maintenance_draw_bar(rct_window *w, rct_drawpixelinfo *d
gfx_fill_rect_inset(dpi, x, y, x + 149, y + 8, w->colours[1], 0x30);
if (unk & (1 << 31)) {
unk &= ~(1 << 31);
- if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0 && (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 8))
+ if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 && (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 8))
return;
}
@@ -5449,23 +5433,23 @@ static void window_ride_income_invalidate()
window_ride_income_widgets[WIDX_PRIMARY_PRICE].image = STR_FREE;
primaryItem = 31;
- if (ride->type != RIDE_TYPE_BATHROOM) {
- if ((primaryItem = (sint8)rideEntry->shop_item) != -1) {
- window_ride_income_widgets[WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK].type = WWT_CHECKBOX;
- if (primaryItem < 32) {
- if (RCT2_GLOBAL(0x01358838, uint32) & (1 << primaryItem))
- w->pressed_widgets |= (1 << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK);
+ if (ride->type == RIDE_TYPE_BATHROOM || ((primaryItem = (sint8)rideEntry->shop_item) != -1)) {
+ window_ride_income_widgets[WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK].type = WWT_CHECKBOX;
+ if (primaryItem < 32) {
+ if (RCT2_GLOBAL(0x01358838, uint32) & (1 << primaryItem))
+ w->pressed_widgets |= (1 << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK);
- if (primaryItem != 31)
- window_ride_income_widgets[WIDX_PRIMARY_PRICE_LABEL].image = 1960 + primaryItem;
- } else {
- primaryItem -= 32;
- if (RCT2_GLOBAL(0x0135934C, uint32) & (1 << primaryItem))
- w->pressed_widgets |= (1 << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK);
-
- window_ride_income_widgets[WIDX_PRIMARY_PRICE_LABEL].image = 2100 + primaryItem;
- }
+ if (primaryItem != 31)
+ window_ride_income_widgets[WIDX_PRIMARY_PRICE_LABEL].image = 1960 + primaryItem;
}
+ else {
+ primaryItem -= 32;
+ if (RCT2_GLOBAL(0x0135934C, uint32) & (1 << primaryItem))
+ w->pressed_widgets |= (1 << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK);
+
+ window_ride_income_widgets[WIDX_PRIMARY_PRICE_LABEL].image = 2100 + primaryItem;
+ }
+
}
// Get secondary item
@@ -5496,7 +5480,7 @@ static void window_ride_income_invalidate()
w->pressed_widgets |= (1 << WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK);
} else {
secondaryItem -= 32;
- if (RCT2_GLOBAL(0x0135884C, uint32) & (1 << secondaryItem))
+ if (RCT2_GLOBAL(0x0135934C, uint32) & (1 << secondaryItem))
w->pressed_widgets |= (1 << WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK);
}
@@ -5570,9 +5554,9 @@ static void window_ride_income_paint()
profit = ride->price_secondary;
stringId = STR_PROFIT_PER_ITEM_SOLD;
- profit -= primaryItem < 32 ?
- RCT2_GLOBAL(0x00982164 + (primaryItem * 8), uint16) :
- RCT2_GLOBAL(0x00982144 + (primaryItem * 8), uint16);
+ profit -= secondaryItem < 32 ?
+ RCT2_GLOBAL(0x00982164 + (secondaryItem * 8), uint16) :
+ RCT2_GLOBAL(0x00982144 + (secondaryItem * 8), uint16);
if (profit < 0) {
profit *= -1;
stringId = STR_LOSS_PER_ITEM_SOLD;
@@ -5752,7 +5736,7 @@ static void window_ride_customer_paint()
y += 10;
// Popularity
- popularity = ride->var_158 & 0xFF;
+ popularity = ride->popularity;
if (popularity == 255) {
stringId = STR_POPULARITY_UNKNOWN;
} else {
@@ -5763,7 +5747,7 @@ static void window_ride_customer_paint()
y += 10;
// Satisfaction
- satisfaction = ride->var_14A & 0xFF;
+ satisfaction = ride->satisfaction;
if (satisfaction == 255) {
stringId = STR_SATISFACTION_UNKNOWN;
} else {
diff --git a/src/windows/ride_construction.c b/src/windows/ride_construction.c
index 7863f81f81..aa8eb48f76 100644
--- a/src/windows/ride_construction.c
+++ b/src/windows/ride_construction.c
@@ -189,7 +189,7 @@ rct_window *window_construction_open()
RCT2_GLOBAL(0x00F440B6, uint8) = 0;
RCT2_GLOBAL(0x00F440B7, uint8) = 0;
- RCT2_GLOBAL(0x00F440AE, uint8) = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = 0;
RCT2_GLOBAL(0x00F440A6, uint8) = 4;
RCT2_GLOBAL(0x00F440B0, uint8) = 0;
RCT2_GLOBAL(0x00F440B1, uint8) = 0;
@@ -216,12 +216,12 @@ void window_construction_close(){
rct_map_element* map_element = sub_6CAF80(ride_id, &x, &y);
if ((int)map_element == -1){
- int eax = RCT2_GLOBAL(0x009DEA6E, uint8);
+ int eax = RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8);
- RCT2_GLOBAL(0x009DEA6E, uint8) = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) = 0;
game_do_command(0, 9, 0, ride_id, GAME_COMMAND_7, 0, 0);
- RCT2_GLOBAL(0x009DEA6E, uint8) = eax;
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) = eax;
return;
}
@@ -247,12 +247,12 @@ void window_construction_maze_close(){
rct_ride* ride = GET_RIDE(ride_id);
if (ride->overall_view == 0xFFFF){
- int eax = RCT2_GLOBAL(0x009DEA6E, uint8);
+ int eax = RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8);
- RCT2_GLOBAL(0x009DEA6E, uint8) = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) = 0;
game_do_command(0, 9, 0, ride_id, GAME_COMMAND_7, 0, 0);
- RCT2_GLOBAL(0x009DEA6E, uint8) = eax;
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) = eax;
return;
}
@@ -314,11 +314,11 @@ void window_construction_mouseup_demolish(rct_window* w){
if (RCT2_GLOBAL(0xF440A6, uint8) != 2){
//6c9cc4
int eax = RCT2_GLOBAL(0xF440A8, uint16),
- ebx = RCT2_GLOBAL(0xF440AF, uint8) || (RCT2_GLOBAL(0xF440AE, uint8) << 8),
+ ebx = RCT2_GLOBAL(0xF440AF, uint8) || (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) << 8),
ecx = RCT2_GLOBAL(0xF440AA, uint16),
edx = RCT2_GLOBAL(0xF440AC, uint16);
- sub_6C683D(&eax, &ecx, edx, RCT2_GLOBAL(0xF440AE, uint8), RCT2_GLOBAL(0xF440AF, uint8) & 0x3FF, 0, 0, 0);
+ sub_6C683D(&eax, &ecx, edx, RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8), RCT2_GLOBAL(0xF440AF, uint8) & 0x3FF, 0, 0, 0);
}
int ride_id = RCT2_GLOBAL(0xF440A7, uint8);
diff --git a/src/windows/ride_list.c b/src/windows/ride_list.c
index d989a5b0e6..41fd4aaaec 100644
--- a/src/windows/ride_list.c
+++ b/src/windows/ride_list.c
@@ -471,16 +471,16 @@ static void window_ride_list_scrollpaint()
break;
case INFORMATION_TYPE_POPULARITY:
formatSecondary = STR_POPULARITY_UNKNOWN_LABEL;
- if ((ride->var_158 & 0xFF) != 255) {
+ if (ride->popularity != 255) {
formatSecondary = STR_POPULARITY_LABEL;
- RCT2_GLOBAL(0x013CE952 + 2, uint16) = (ride->var_158 & 0xFF) * 4;
+ RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride->popularity * 4;
}
break;
case INFORMATION_TYPE_SATISFACTION:
formatSecondary = STR_SATISFACTION_UNKNOWN_LABEL;
- if ((ride->var_14A & 0xFF) != 255) {
+ if (ride->satisfaction != 255) {
formatSecondary = STR_SATISFACTION_LABEL;
- RCT2_GLOBAL(0x013CE952 + 2, uint16) = (ride->var_14A & 0xFF) * 5;
+ RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride->satisfaction * 5;
}
break;
case INFORMATION_TYPE_PROFIT:
@@ -616,7 +616,7 @@ static void window_ride_list_refresh_list(rct_window *w)
case INFORMATION_TYPE_POPULARITY:
while (--current_list_position >= 0) {
otherRide = &g_ride_list[w->list_item_positions[current_list_position]];
- if ((ride->var_158 & 0xFF) * 4 <= (otherRide->var_158 & 0xFF) * 4)
+ if (ride->popularity * 4 <= otherRide->popularity * 4)
break;
window_bubble_list_item(w, current_list_position);
@@ -625,7 +625,7 @@ static void window_ride_list_refresh_list(rct_window *w)
case INFORMATION_TYPE_SATISFACTION:
while (--current_list_position >= 0) {
otherRide = &g_ride_list[w->list_item_positions[current_list_position]];
- if ((ride->var_14A & 0xFF) * 5 <= (otherRide->var_14A & 0xFF) * 5)
+ if (ride->satisfaction * 5 <= otherRide->satisfaction * 5)
break;
window_bubble_list_item(w, current_list_position);
diff --git a/src/windows/save_prompt.c b/src/windows/save_prompt.c
index 2fb1a9cac1..5bbc3daca1 100644
--- a/src/windows/save_prompt.c
+++ b/src/windows/save_prompt.c
@@ -164,7 +164,7 @@ void window_save_prompt_open()
window->colours[0] = 154;
// Pause the game
- RCT2_GLOBAL(0x009DEA6E, uint8) |= 2;
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) |= 2;
pause_sounds();
window_invalidate_by_class(WC_TOP_TOOLBAR);
@@ -215,7 +215,7 @@ void window_save_prompt_open()
static void window_save_prompt_close()
{
// Unpause the game
- RCT2_GLOBAL(0x009DEA6E, uint8) &= ~2;
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) &= ~2;
unpause_sounds();
window_invalidate_by_class(WC_TOP_TOOLBAR);
}
diff --git a/src/windows/shortcut_keys.c b/src/windows/shortcut_keys.c
index 42b482d716..509dc02afa 100644
--- a/src/windows/shortcut_keys.c
+++ b/src/windows/shortcut_keys.c
@@ -23,7 +23,7 @@
#include "../interface/window.h"
#include "../interface/widget.h"
#include "../localisation/localisation.h"
-#include "../platform/osinterface.h"
+#include "../platform/platform.h"
#define WW 340
#define WH 240
@@ -257,7 +257,7 @@ static void window_shortcut_scrollpaint()
uint16 shortcut_entry = gShortcutKeys[i];
if (shortcut_entry != 0xFFFF){
- RCT2_GLOBAL(0x13CE958, uint16) = STR_INDIVIDUAL_KEYS_BASE + osinterface_scancode_to_rct_keycode(shortcut_entry & 0xFF);
+ RCT2_GLOBAL(0x13CE958, uint16) = STR_INDIVIDUAL_KEYS_BASE + platform_scancode_to_rct_keycode(shortcut_entry & 0xFF);
//Display the modifer
if (shortcut_entry & 0x100){
RCT2_GLOBAL(0x13CE956, uint16) = STR_SHIFT_PLUS;
diff --git a/src/windows/sign.c b/src/windows/sign.c
index 49c58b1f19..8bed79575f 100644
--- a/src/windows/sign.c
+++ b/src/windows/sign.c
@@ -169,12 +169,11 @@ void window_sign_open(rct_windownumber number)
int view_x = gBanners[w->number].x << 5;
int view_y = gBanners[w->number].y << 5;
- int ebp = ((view_y << 8) | view_x) >> 5;
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(ebp);
+ rct_map_element* map_element = map_get_first_element_at(view_x / 32, view_y / 32);
while (1){
- if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE){
+ if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) {
int ebx = map_element->properties.scenerymultiple.type;
ebx |= (map_element->properties.scenerymultiple.index & 0x3) << 8;
rct_scenery_entry* scenery_entry = g_largeSceneryEntries[ebx];
@@ -213,7 +212,7 @@ void window_sign_open(rct_windownumber number)
view_z,
0,
-1
- );
+ );
w->viewport->flags = (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES) ? VIEWPORT_FLAG_GRIDLINES : 0;
w->flags |= WF_2;
@@ -234,7 +233,7 @@ static void window_sign_mouseup()
rct_string_id string_id;
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(((y << 8) | x) >> 5);
+ rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32);
switch (widgetIndex) {
case WIDX_CLOSE:
@@ -242,7 +241,7 @@ static void window_sign_mouseup()
break;
case WIDX_SIGN_DEMOLISH:
while (1){
- if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE){
+ if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) {
int ebx = map_element->properties.scenerymultiple.type;
ebx |= (map_element->properties.scenerymultiple.index & 0x3) << 8;
rct_scenery_entry* scenery_entry = g_largeSceneryEntries[ebx];
@@ -320,10 +319,10 @@ static void window_sign_dropdown()
int x = banner->x << 5;
int y = banner->y << 5;
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(((y << 8) | x) >> 5);
+ rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32);
while (1){
- if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE){
+ if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) {
int ebx = map_element->properties.scenerymultiple.type;
ebx |= (map_element->properties.scenerymultiple.index & 0x3) << 8;
rct_scenery_entry* scenery_entry = g_largeSceneryEntries[ebx];
@@ -361,17 +360,15 @@ static void window_sign_textinput()
if (widgetIndex == WIDX_SIGN_TEXT && result) {
if (*text != 0){
- int string_id = 0, ebx = 0, ecx = 128, edx = 0, ebp = 0, esi = 0;
- RCT2_CALLFUNC_X(0x6C421D, &string_id, &ebx, &ecx, &edx, &esi, (int*)&text, &ebp);
- if (string_id){
+ rct_string_id string_id = user_string_allocate(128, text);
+ if (string_id != 0) {
rct_string_id prev_string_id = banner->string_idx;
banner->string_idx = string_id;
user_string_free(prev_string_id);
banner->flags &= ~(BANNER_FLAG_2);
gfx_invalidate_screen();
- }
- else{
+ } else {
window_error_open(2984, RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id));
}
}
@@ -499,12 +496,11 @@ void window_sign_small_open(rct_windownumber number){
int view_x = gBanners[w->number].x << 5;
int view_y = gBanners[w->number].y << 5;
- int ebp = ((view_y << 8) | view_x) >> 5;
-
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(ebp);
+
+ rct_map_element* map_element = map_get_first_element_at(view_x / 32, view_y / 32);
while (1){
- if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_FENCE){
+ if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_FENCE) {
rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.slope];
if (scenery_entry->wall.var_0D != 0xFF){
if (map_element->properties.fence.item[0] == w->number)
@@ -538,7 +534,7 @@ void window_sign_small_open(rct_windownumber number){
view_z,
0,
-1
- );
+ );
w->viewport->flags = (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES) ? VIEWPORT_FLAG_GRIDLINES : 0;
w->flags |= WF_2;
@@ -559,7 +555,7 @@ static void window_sign_small_mouseup()
rct_string_id string_id;
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(((y << 8) | x) >> 5);
+ rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32);
switch (widgetIndex) {
case WIDX_CLOSE:
@@ -567,7 +563,7 @@ static void window_sign_small_mouseup()
break;
case WIDX_SIGN_DEMOLISH:
while (1){
- if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_FENCE){
+ if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_FENCE) {
rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.slope];
if (scenery_entry->wall.var_0D != 0xFF){
if (map_element->properties.fence.item[0] == w->number)
@@ -626,10 +622,10 @@ static void window_sign_small_dropdown()
int x = banner->x << 5;
int y = banner->y << 5;
- rct_map_element* map_element = TILE_MAP_ELEMENT_POINTER(((y << 8) | x) >> 5);
+ rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32);
while (1){
- if ((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_FENCE){
+ if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_FENCE) {
rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.slope];
if (scenery_entry->wall.var_0D != 0xFF){
if (map_element->properties.fence.item[0] == w->number)
diff --git a/src/windows/staff.c b/src/windows/staff.c
index 0d3961f229..f33bf52524 100644
--- a/src/windows/staff.c
+++ b/src/windows/staff.c
@@ -326,7 +326,7 @@ void window_staff_open(rct_peep* peep)
w->widgets = window_staff_overview_widgets;
w->enabled_widgets = window_staff_page_enabled_widgets[0];
- w->var_020 = RCT2_GLOBAL(0x9929BC, uint32);
+ w->hold_down_widgets = 0;
w->event_handlers = window_staff_page_events[0];
w->pressed_widgets = 0;
window_staff_disable_widgets(w);
@@ -413,7 +413,7 @@ void window_staff_set_page(rct_window* w, int page)
}
w->enabled_widgets = window_staff_page_enabled_widgets[page];
- w->var_020 = RCT2_ADDRESS(0x9929BC, uint32)[page];
+ w->hold_down_widgets = 0;
w->event_handlers = window_staff_page_events[page];
w->pressed_widgets = 0;
w->widgets = window_staff_page_widgets[page];
diff --git a/src/windows/text_input.c b/src/windows/text_input.c
index c66ae6f5d8..ed0d953afa 100644
--- a/src/windows/text_input.c
+++ b/src/windows/text_input.c
@@ -27,7 +27,7 @@
#include "../addresses.h"
#include "../config.h"
-#include "../platform/osinterface.h"
+#include "../platform/platform.h"
#include "../interface/window.h"
#include "../interface/widget.h"
#include "../localisation/localisation.h"
@@ -136,7 +136,7 @@ void window_text_input_open(rct_window* call_w, int call_widget, rct_string_id t
height,
(uint32*)window_text_input_events,
WC_TEXTINPUT,
- 0
+ WF_STICK_TO_FRONT
);
w->widgets = window_text_input_widgets;
@@ -150,7 +150,7 @@ void window_text_input_open(rct_window* call_w, int call_widget, rct_string_id t
calling_number = call_w->number;
calling_widget = call_widget;
- osinterface_start_text_input(text_input, maxLength);
+ platform_start_text_input(text_input, maxLength);
window_init_scroll_widgets(w);
w->colours[0] = call_w->colours[0];
@@ -172,7 +172,7 @@ static void window_text_input_mouseup(){
switch (widgetIndex){
case WIDX_CANCEL:
case WIDX_CLOSE:
- osinterface_stop_text_input();
+ platform_stop_text_input();
// Pass back the text that has been entered.
// ecx when zero means text input failed
if (calling_w != NULL)
@@ -180,7 +180,7 @@ static void window_text_input_mouseup(){
window_close(w);
break;
case WIDX_OKAY:
- osinterface_stop_text_input();
+ platform_stop_text_input();
// Pass back the text that has been entered.
// ecx when none zero means text input success
if (calling_w != NULL)
@@ -265,11 +265,11 @@ static void window_text_input_paint(){
static void window_text_input_text(int key, rct_window* w){
int text = key;
- char new_char = osinterface_scancode_to_rct_keycode(0xFF&key);
+ char new_char = platform_scancode_to_rct_keycode(0xFF&key);
// If the return button is pressed stop text input
if (new_char == '\r'){
- osinterface_stop_text_input();
+ platform_stop_text_input();
window_close(w);
rct_window* calling_w = window_find_by_number(calling_class, calling_number);
// Pass back the text that has been entered.
@@ -300,10 +300,11 @@ void window_text_input_update7()
window_invalidate(w);
}
-static void window_text_input_close(){
+static void window_text_input_close()
+{
// Make sure that we take it out of the text input
// mode otherwise problems may occur.
- osinterface_stop_text_input();
+ platform_stop_text_input();
}
static void window_text_input_invalidate(){
diff --git a/src/windows/title_logo.c b/src/windows/title_logo.c
index 835ab23d67..b76ca5c05a 100644
--- a/src/windows/title_logo.c
+++ b/src/windows/title_logo.c
@@ -63,6 +63,8 @@ static void* window_title_logo_events[] = {
window_title_logo_emptysub
};
+static void window_title_logo_draw_expansion_packs(rct_drawpixelinfo *dpi);
+
/**
* Creates the window containing the logo and the expansion packs on the title screen.
* rct2: 0x0066B679 (part of 0x0066B3E8)
@@ -94,23 +96,26 @@ void window_title_logo_open()
*/
static void window_title_logo_paint()
{
- int packs, x, y, i;
- char *buffer, *names;
rct_window *w;
rct_drawpixelinfo *dpi;
window_paint_get_registers(w, dpi);
gfx_draw_sprite(dpi, SPR_MENU_LOGO, w->x, w->y, 0);
+ window_title_logo_draw_expansion_packs(dpi);
+}
+
+static void window_title_logo_draw_expansion_packs(rct_drawpixelinfo *dpi)
+{
+ int packs, x, y, i;
+ char *buffer, *names;
x = 0;
y = 105;
packs = RCT2_GLOBAL(RCT2_ADDRESS_EXPANSION_FLAGS, uint16);
names = RCT2_ADDRESS(RCT2_ADDRESS_EXPANSION_NAMES, char);
-
buffer = (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER;
-
while (packs != 0) {
if (packs & 1) {
// Prefix for expansion name
@@ -120,23 +125,19 @@ static void window_title_logo_paint()
buffer[3] = '+';
buffer[4] = ' ';
- i = 0;
-
// Copies the expansion name to the buffer, offset by 5
+ i = 0;
do {
buffer[5 + i] = names[i];
i++;
} while (names[i - 1] != 0);
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint32) = 0;
-
gfx_draw_string(dpi, buffer, 0, x, y);
-
y += 10;
}
packs = packs >> 1;
-
names += 128;
}
}
\ No newline at end of file
diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c
new file mode 100644
index 0000000000..6cb873b68b
--- /dev/null
+++ b/src/windows/top_toolbar.c
@@ -0,0 +1,992 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#include "../addresses.h"
+#include "../editor.h"
+#include "../game.h"
+#include "../input.h"
+#include "../sprites.h"
+#include "../audio/audio.h"
+#include "../interface/widget.h"
+#include "../interface/window.h"
+#include "../interface/viewport.h"
+#include "../localisation/localisation.h"
+#include "dropdown.h"
+#include "scenery.h"
+
+enum {
+ WIDX_PAUSE,
+ WIDX_FILE_MENU,
+ WIDX_ZOOM_OUT,
+ WIDX_ZOOM_IN,
+ WIDX_ROTATE,
+ WIDX_VIEW_MENU,
+ WIDX_MAP,
+
+ WIDX_LAND,
+ WIDX_WATER,
+ WIDX_SCENERY,
+ WIDX_PATH,
+ WIDX_CONSTRUCT_RIDE,
+ WIDX_RIDES,
+ WIDX_PARK,
+ WIDX_STAFF,
+ WIDX_GUESTS,
+ WIDX_CLEAR_SCENERY,
+
+ //WIDX_FASTFORWARD,
+ WIDX_FINANCES,
+ WIDX_RESEARCH,
+
+ WIDX_SEPARATOR,
+};
+
+typedef enum {
+ DDIDX_LOAD_GAME = 0,
+ DDIDX_SAVE_GAME = 1,
+ DDIDX_ABOUT = 3,
+ DDIDX_OPTIONS = 4,
+ DDIDX_SCREENSHOT = 5,
+ DDIDX_QUIT_GAME = 7,
+} FILE_MENU_DDIDX;
+
+typedef enum {
+ DDIDX_UNDERGROUND_INSIDE = 0,
+ DDIDX_HIDE_BASE = 1,
+ DDIDX_HIDE_VERTICAL = 2,
+ DDIDX_SEETHROUGH_RIDES = 4,
+ DDIDX_SEETHROUGH_SCENARY = 5,
+ DDIDX_INVISIBLE_SUPPORTS = 6,
+ DDIDX_INVISIBLE_PEEPS = 7,
+ DDIDX_LAND_HEIGHTS = 9,
+ DDIDX_TRACK_HEIGHTS = 10,
+ DDIDX_PATH_HEIGHTS = 11,
+} TOP_TOOLBAR_VIEW_MENU_DDIDX;
+
+#pragma region Toolbar_widget_ordering
+
+// from left to right
+static const int left_aligned_widgets_order[] = {
+ WIDX_PAUSE,
+ //WIDX_FASTFORWARD,
+ WIDX_FILE_MENU,
+
+ WIDX_SEPARATOR,
+
+ WIDX_ZOOM_OUT,
+ WIDX_ZOOM_IN,
+ WIDX_ROTATE,
+ WIDX_VIEW_MENU,
+ WIDX_MAP,
+};
+
+// from right to left
+static const int right_aligned_widgets_order[] = {
+ WIDX_GUESTS,
+ WIDX_STAFF,
+ WIDX_PARK,
+ WIDX_RIDES,
+ WIDX_RESEARCH,
+ WIDX_FINANCES,
+
+ WIDX_SEPARATOR,
+
+ WIDX_CONSTRUCT_RIDE,
+ WIDX_PATH,
+ WIDX_SCENERY,
+ WIDX_WATER,
+ WIDX_LAND,
+ WIDX_CLEAR_SCENERY,
+};
+
+#pragma endregion
+
+static rct_widget window_top_toolbar_widgets[] = {
+ { WWT_TRNBTN, 0, 0x0000, 0x001D, 0, 27, 0x20000000 | SPR_TOOLBAR_PAUSE, STR_PAUSE_GAME_TIP }, // Pause
+ { WWT_TRNBTN, 0, 0x001E + 30, 0x003B + 30, 0, 27, 0x20000000 | SPR_TOOLBAR_FILE, STR_DISC_AND_GAME_OPTIONS_TIP }, // File menu
+ { WWT_TRNBTN, 1, 0x0046 + 30, 0x0063 + 30, 0, 27, 0x20000000 | SPR_TOOLBAR_ZOOM_OUT, STR_ZOOM_OUT_TIP }, // Zoom out
+ { WWT_TRNBTN, 1, 0x0064 + 30, 0x0081 + 30, 0, 27, 0x20000000 | SPR_TOOLBAR_ZOOM_IN, STR_ZOOM_IN_TIP }, // Zoom in
+ { WWT_TRNBTN, 1, 0x0082 + 30, 0x009F + 30, 0, 27, 0x20000000 | SPR_TOOLBAR_ROTATE, STR_ROTATE_TIP }, // Rotate camera
+ { WWT_TRNBTN, 1, 0x00A0 + 30, 0x00BD + 30, 0, 27, 0x20000000 | SPR_TOOLBAR_VIEW, STR_VIEW_OPTIONS_TIP }, // Transparancy menu
+ { WWT_TRNBTN, 1, 0x00BE + 30, 0x00DB + 30, 0, 27, 0x20000000 | SPR_TOOLBAR_MAP, STR_SHOW_MAP_TIP }, // Map
+
+ { WWT_TRNBTN, 2, 0x010B, 0x0128, 0, 27, 0x20000000 | SPR_TOOLBAR_LAND, STR_ADJUST_LAND_TIP }, // Land
+ { WWT_TRNBTN, 2, 0x0129, 0x0146, 0, 27, 0x20000000 | SPR_TOOLBAR_WATER, STR_ADJUST_WATER_TIP }, // Water
+ { WWT_TRNBTN, 2, 0x0147, 0x0164, 0, 27, 0x20000000 | SPR_TOOLBAR_SCENERY, STR_PLACE_SCENERY_TIP }, // Scenery
+ { WWT_TRNBTN, 2, 0x0165, 0x0182, 0, 27, 0x20000000 | SPR_TOOLBAR_FOOTPATH, STR_BUILD_FOOTPATH_TIP }, // Path
+ { WWT_TRNBTN, 2, 0x0183, 0x01A0, 0, 27, 0x20000000 | SPR_TOOLBAR_CONSTRUCT_RIDE, STR_BUILD_RIDE_TIP }, // Construct ride
+ { WWT_TRNBTN, 3, 0x01EA, 0x0207, 0, 27, 0x20000000 | SPR_TOOLBAR_RIDES, STR_RIDES_IN_PARK_TIP }, // Rides
+ { WWT_TRNBTN, 3, 0x0208, 0x0225, 0, 27, 0x20000000 | SPR_TOOLBAR_PARK, STR_PARK_INFORMATION_TIP }, // Park
+ { WWT_TRNBTN, 3, 0x0226, 0x0243, 0, 27, 0x20000000 | 0x15F9, STR_STAFF_TIP }, // Staff
+ { WWT_TRNBTN, 3, 0x0230, 0x024D, 0, 27, 0x20000000 | SPR_TOOLBAR_GUESTS, STR_GUESTS_TIP }, // Guests
+ { WWT_TRNBTN, 2, 0x0230, 0x024D, 0, 27, 0x20000000 | SPR_TOOLBAR_CLEAR_SCENERY, STR_CLEAR_SCENERY_TIP }, // Clear scenery
+
+ //{ WWT_TRNBTN, 0, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, STR_NONE }, // Fast forward
+ { WWT_TRNBTN, 3, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, 3235 }, // Finances
+ { WWT_TRNBTN, 3, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, 2275 }, // Research
+
+ { WWT_EMPTY, 0, 0, 10-1, 0, 0, 0xFFFFFFFF, STR_NONE }, // Artificial widget separator
+ { WIDGETS_END },
+};
+
+static void window_top_toolbar_emptysub() { }
+static void window_top_toolbar_mouseup();
+static void window_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
+static void window_top_toolbar_dropdown();
+static void window_top_toolbar_tool_update();
+static void window_top_toolbar_tool_down();
+static void window_top_toolbar_tool_drag();
+static void window_top_toolbar_invalidate();
+static void window_top_toolbar_paint();
+
+static void* window_top_toolbar_events[] = {
+ window_top_toolbar_emptysub,
+ window_top_toolbar_mouseup,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_mousedown,
+ window_top_toolbar_dropdown,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub, // check if editor versions are significantly different...
+ window_top_toolbar_tool_update, // editor: 0x0066fB0E
+ window_top_toolbar_tool_down, // editor: 0x0066fB5C
+ window_top_toolbar_tool_drag, // editor: 0x0066fB37
+ (void*)0x0066CC5B, // editor: 0x0066fC44
+ (void*)0x0066CA58, // editor: 0x0066fA74
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_emptysub,
+ window_top_toolbar_invalidate,
+ window_top_toolbar_paint,
+ window_top_toolbar_emptysub
+};
+
+void top_toolbar_init_view_menu(rct_window *window, rct_widget *widget);
+void top_toolbar_view_menu_dropdown(short dropdownIndex);
+
+void toggle_footpath_window();
+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);
+
+/**
+ * Creates the main game top toolbar window.
+ * rct2: 0x0066B485 (part of 0x0066B3E8)
+ */
+void window_top_toolbar_open()
+{
+ rct_window* window;
+
+ window = window_create(
+ 0, 0,
+ RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16), 28,
+ (uint32*)window_top_toolbar_events,
+ WC_TOP_TOOLBAR,
+ WF_STICK_TO_FRONT | WF_TRANSPARENT | WF_5
+ );
+ window->widgets = window_top_toolbar_widgets;
+
+ window_init_scroll_widgets(window);
+ window->colours[0] = 7;
+ window->colours[1] = 12;
+ window->colours[2] = 24;
+ window->colours[3] = 1;
+}
+
+/**
+ *
+ * rct2: 0x0066C957
+ */
+static void window_top_toolbar_mouseup()
+{
+ short widgetIndex;
+ rct_window *w, *mainWindow;
+
+ window_widget_get_registers(w, widgetIndex);
+
+ switch (widgetIndex) {
+ case WIDX_PAUSE:
+ game_do_command(0, 1, 0, 0, GAME_COMMAND_TOGGLE_PAUSE, 0, 0);
+ break;
+ // case WIDX_FASTFORWARD:
+ // // This is an excellent place to add in debugging statements and
+ // // print routines, that will be triggered when you press the
+ // // button in the game. Use "git update-index --skip-worktree
+ // // src/window_top_toolbar" to avoid committing these changes to
+ // // version control.
+ // window_cheats_open();
+ // break;
+
+ case WIDX_ZOOM_OUT:
+ if ((mainWindow = window_get_main()) != NULL)
+ window_zoom_out(mainWindow);
+ break;
+ case WIDX_ZOOM_IN:
+ if ((mainWindow = window_get_main()) != NULL)
+ window_zoom_in(mainWindow);
+ break;
+ case WIDX_ROTATE:
+ if ((mainWindow = window_get_main()) != NULL)
+ window_rotate_camera(mainWindow);
+ break;
+ case WIDX_CLEAR_SCENERY:
+ toggle_clear_scenery_window(w, WIDX_CLEAR_SCENERY);
+ break;
+ case WIDX_LAND:
+ toggle_land_window(w, WIDX_LAND);
+ break;
+ case WIDX_WATER:
+ toggle_water_window(w, WIDX_WATER);
+ break;
+ case WIDX_SCENERY:
+ if (!tool_set(w, WIDX_SCENERY, 0)) {
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
+ window_scenery_open();
+ }
+ break;
+ case WIDX_PATH:
+ toggle_footpath_window();
+ break;
+ case WIDX_CONSTRUCT_RIDE:
+ window_new_ride_open();
+ break;
+ case WIDX_RIDES:
+ window_ride_list_open();
+ break;
+ case WIDX_PARK:
+ window_park_entrance_open();
+ break;
+ case WIDX_STAFF:
+ window_staff_list_open();
+ break;
+ case WIDX_GUESTS:
+ window_guest_list_open();
+ break;
+ case WIDX_FINANCES:
+ window_finances_open();
+ break;
+ case WIDX_RESEARCH:
+ window_research_open();
+ break;
+ }
+}
+
+/**
+ *
+ * rct2: 0x0066CA3B
+ */
+static void window_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
+{
+ int numItems;
+
+ switch (widgetIndex) {
+ case WIDX_FILE_MENU:
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER)) {
+ gDropdownItemsFormat[0] = STR_ABOUT;
+ gDropdownItemsFormat[1] = STR_OPTIONS;
+ gDropdownItemsFormat[2] = STR_SCREENSHOT;
+ gDropdownItemsFormat[3] = 0;
+ gDropdownItemsFormat[4] = STR_QUIT_TRACK_DESIGNS_MANAGER;
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER)
+ gDropdownItemsFormat[4] = STR_QUIT_ROLLERCOASTER_DESIGNER;
+
+ numItems = 5;
+ } else if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) {
+ gDropdownItemsFormat[0] = STR_LOAD_LANDSCAPE;
+ gDropdownItemsFormat[1] = STR_SAVE_LANDSCAPE;
+ gDropdownItemsFormat[2] = 0;
+ gDropdownItemsFormat[3] = STR_ABOUT;
+ gDropdownItemsFormat[4] = STR_OPTIONS;
+ gDropdownItemsFormat[5] = STR_SCREENSHOT;
+ gDropdownItemsFormat[6] = 0;
+ gDropdownItemsFormat[7] = STR_QUIT_SCENARIO_EDITOR;
+ numItems = 8;
+ } else {
+ gDropdownItemsFormat[0] = STR_LOAD_GAME;
+ gDropdownItemsFormat[1] = STR_SAVE_GAME;
+ gDropdownItemsFormat[2] = 0;
+ gDropdownItemsFormat[3] = STR_ABOUT;
+ gDropdownItemsFormat[4] = STR_OPTIONS;
+ gDropdownItemsFormat[5] = STR_SCREENSHOT;
+ gDropdownItemsFormat[6] = 0;
+ gDropdownItemsFormat[7] = STR_QUIT_GAME;
+ numItems = 8;
+ }
+ window_dropdown_show_text(
+ w->x + widget->left,
+ w->y + widget->top,
+ widget->bottom - widget->top + 1,
+ w->colours[0] | 0x80,
+ 0x80,
+ numItems
+ );
+ break;
+ case WIDX_VIEW_MENU:
+ top_toolbar_init_view_menu(w, widget);
+ break;
+ case WIDX_MAP:
+ gDropdownItemsFormat[0] = 2523;
+ gDropdownItemsFormat[1] = 2780;
+ numItems = 2;
+
+ if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && g_editor_step == EDITOR_STEP_LANDSCAPE_EDITOR) {
+ gDropdownItemsFormat[2] = 2690;
+ numItems++;
+ }
+
+ window_dropdown_show_text(
+ w->x + widget->left,
+ w->y + widget->top,
+ widget->bottom - widget->top + 1,
+ w->colours[1] | 0x80,
+ 0,
+ numItems
+ );
+ RCT2_GLOBAL(0x009DEBA2, uint16) = 0;
+ break;
+ }
+}
+
+/**
+ *
+ * rct2: 0x0066C9EA
+ */
+static void window_top_toolbar_dropdown()
+{
+ short widgetIndex, dropdownIndex;
+ rct_window* w;
+
+ window_dropdown_get_registers(w, widgetIndex, dropdownIndex);
+
+ switch (widgetIndex) {
+ case WIDX_FILE_MENU:
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER))
+ dropdownIndex += DDIDX_ABOUT;
+
+ switch (dropdownIndex) {
+ case DDIDX_LOAD_GAME:
+ game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 0, 0);
+ break;
+ case DDIDX_SAVE_GAME:
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) {
+ RCT2_CALLPROC_EBPSAFE(0x0066FE2A);
+ } else {
+ tool_cancel();
+ save_game();
+ }
+ break;
+ case DDIDX_ABOUT:
+ window_about_open();
+ break;
+ case DDIDX_OPTIONS:
+ window_options_open();
+ break;
+ case DDIDX_SCREENSHOT:
+ RCT2_GLOBAL(RCT2_ADDRESS_SCREENSHOT_COUNTDOWN, sint8) = 10;
+ break;
+ case DDIDX_QUIT_GAME:
+ window_close_by_class(WC_MANAGE_TRACK_DESIGN);
+ window_close_by_class(WC_TRACK_DELETE_PROMPT);
+ game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 1, 0);
+ break;
+ }
+ break;
+ case WIDX_VIEW_MENU:
+ top_toolbar_view_menu_dropdown(dropdownIndex);
+ break;
+ case WIDX_MAP:
+ if (dropdownIndex == -1)
+ dropdownIndex = RCT2_GLOBAL(0x009DEBA2, uint16);
+
+ switch (dropdownIndex) {
+ case 0:
+ window_map_open();
+ break;
+ case 1:
+ window_viewport_open();
+ break;
+ case 2:
+ window_mapgen_open();
+ break;
+ }
+ break;
+ }
+}
+
+/**
+ *
+ * rct2: 0x0066C810
+ */
+static void window_top_toolbar_invalidate()
+{
+ int i, x, enabledWidgets, widgetIndex, widgetWidth, firstAlignment;
+ rct_window *w;
+ rct_widget *widget;
+
+ window_get_register(w);
+
+ // Enable / disable buttons
+ window_top_toolbar_widgets[WIDX_PAUSE].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_FILE_MENU].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_ZOOM_OUT].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_ZOOM_IN].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_ROTATE].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_VIEW_MENU].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_MAP].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_LAND].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_WATER].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_SCENERY].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_PATH].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_CONSTRUCT_RIDE].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_RIDES].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_PARK].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_STAFF].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_GUESTS].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_CLEAR_SCENERY].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_FINANCES].type = WWT_TRNBTN;
+ window_top_toolbar_widgets[WIDX_RESEARCH].type = WWT_TRNBTN;
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_SCENARIO_EDITOR | SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER)) {
+ window_top_toolbar_widgets[WIDX_PAUSE].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_RIDES].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_PARK].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_STAFF].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_GUESTS].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_FINANCES].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_RESEARCH].type = WWT_EMPTY;
+
+ if (g_editor_step != EDITOR_STEP_LANDSCAPE_EDITOR) {
+ window_top_toolbar_widgets[WIDX_MAP].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_LAND].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_WATER].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_SCENERY].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_PATH].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_CLEAR_SCENERY].type = WWT_EMPTY;
+ }
+
+ if (g_editor_step != EDITOR_STEP_ROLLERCOASTER_DESIGNER) {
+ window_top_toolbar_widgets[WIDX_CONSTRUCT_RIDE].type = WWT_EMPTY;
+ }
+
+ if (g_editor_step != EDITOR_STEP_LANDSCAPE_EDITOR && g_editor_step != EDITOR_STEP_ROLLERCOASTER_DESIGNER) {
+ window_top_toolbar_widgets[WIDX_ZOOM_OUT].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_ZOOM_IN].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_ROTATE].type = WWT_EMPTY;
+ window_top_toolbar_widgets[WIDX_VIEW_MENU].type = WWT_EMPTY;
+ }
+ } else {
+ if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)
+ window_top_toolbar_widgets[WIDX_FINANCES].type = WWT_EMPTY;
+ }
+
+ enabledWidgets = 0;
+ for (i = WIDX_PAUSE; i <= WIDX_RESEARCH; i++)
+ if (window_top_toolbar_widgets[i].type != WWT_EMPTY)
+ enabledWidgets |= (1 << i);
+ w->enabled_widgets = enabledWidgets;
+
+ // Align left hand side toolbar buttons
+ firstAlignment = 1;
+ x = 0;
+ for (int i = 0; i < countof(left_aligned_widgets_order); ++i) {
+ widgetIndex = left_aligned_widgets_order[i];
+ widget = &window_top_toolbar_widgets[widgetIndex];
+ if (widget->type == WWT_EMPTY && widgetIndex != WIDX_SEPARATOR)
+ continue;
+
+ if (firstAlignment && widgetIndex == WIDX_SEPARATOR)
+ continue;
+
+ widgetWidth = widget->right - widget->left;
+ widget->left = x;
+ x += widgetWidth;
+ widget->right = x;
+ x += 1;
+ firstAlignment = 0;
+ }
+
+ // Align right hand side toolbar buttons
+ firstAlignment = 1;
+ x = max(640, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16));
+ for (int i = 0; i < countof(right_aligned_widgets_order); ++i) {
+ widgetIndex = right_aligned_widgets_order[i];
+ widget = &window_top_toolbar_widgets[widgetIndex];
+ if (widget->type == WWT_EMPTY && widgetIndex != WIDX_SEPARATOR)
+ continue;
+
+ if (firstAlignment && widgetIndex == WIDX_SEPARATOR)
+ continue;
+
+ widgetWidth = widget->right - widget->left;
+ x -= 1;
+ widget->right = x;
+ x -= widgetWidth;
+ widget->left = x;
+ firstAlignment = 0;
+ }
+
+ // Footpath button pressed down
+ if (window_find_by_class(WC_FOOTPATH) == NULL)
+ w->pressed_widgets &= ~(1 << WIDX_PATH);
+ else
+ w->pressed_widgets |= (1 << WIDX_PATH);
+
+ // Fast forward button pressed down
+ // if (0)
+ // w->pressed_widgets |= (1 << WIDX_FASTFORWARD);
+ // else
+ // w->pressed_widgets &= ~(1 << WIDX_FASTFORWARD);
+
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint32) & 1))
+ w->pressed_widgets &= ~(1 << WIDX_PAUSE);
+ else
+ w->pressed_widgets |= (1 << WIDX_PAUSE);
+
+ // Zoomed out/in disable. Not sure where this code is in the original.
+ if (window_get_main()->viewport->zoom == 0){
+ w->disabled_widgets |= (1 << WIDX_ZOOM_IN);
+ } else if (window_get_main()->viewport->zoom == 3){
+ w->disabled_widgets |= (1 << WIDX_ZOOM_OUT);
+ } else {
+ w->disabled_widgets &= ~((1 << WIDX_ZOOM_IN) | (1 << WIDX_ZOOM_OUT));
+ }
+}
+
+/**
+ *
+ * rct2: 0x0066C8EC
+ */
+static void window_top_toolbar_paint()
+{
+ int x, y, imgId;
+ rct_window *w;
+ rct_drawpixelinfo *dpi;
+
+ window_paint_get_registers(w, dpi);
+
+ window_draw_widgets(w, dpi);
+
+ // Draw staff button image (setting masks to the staff colours)
+ if (window_top_toolbar_widgets[WIDX_STAFF].type != WWT_EMPTY) {
+ x = w->x + window_top_toolbar_widgets[WIDX_STAFF].left;
+ y = w->y + window_top_toolbar_widgets[WIDX_STAFF].top;
+ imgId = 5627;
+ if (widget_is_pressed(w, WIDX_STAFF))
+ imgId++;
+ imgId |= (RCT2_GLOBAL(RCT2_ADDRESS_HANDYMAN_COLOUR, uint8) << 19) | 0xA0000000 | (RCT2_GLOBAL(RCT2_ADDRESS_MECHANIC_COLOUR, uint8) << 24);
+ gfx_draw_sprite(dpi, imgId, x, y, 0);
+ }
+
+ // Draw research button
+ if (window_top_toolbar_widgets[WIDX_RESEARCH].type != WWT_EMPTY) {
+ x = w->x + window_top_toolbar_widgets[WIDX_RESEARCH].left - 1;
+ y = w->y + window_top_toolbar_widgets[WIDX_RESEARCH].top;
+ imgId = SPR_TAB_FINANCES_RESEARCH_0;
+ gfx_draw_sprite(dpi, imgId, x, y, 0);
+ }
+
+ // Draw finances button
+ if (window_top_toolbar_widgets[WIDX_FINANCES].type != WWT_EMPTY) {
+ x = w->x + window_top_toolbar_widgets[WIDX_FINANCES].left + 3;
+ y = w->y + window_top_toolbar_widgets[WIDX_FINANCES].top + 1;
+ imgId = SPR_FINANCE;
+ gfx_draw_sprite(dpi, imgId, x, y, 0);
+ }
+}
+
+/**
+ * rct2: 0x6e2cc6
+ */
+static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window* w, short widgetIndex){
+ RCT2_CALLPROC_EBPSAFE(0x006E2712);
+ if (window_scenery_is_repaint_scenery_tool_on & 1){
+ //6e3158
+ RCT2_CALLPROC_X(0x6E2CC6, x, y, 0, widgetIndex, (int)w, 0, 0);
+ }
+
+ int selected_tab = window_scenery_selected_scenery_by_tab[window_scenery_active_tab_index];
+ if (selected_tab == -1) return;
+
+ sint16 grid_x, grid_y, grid_z;
+ uint8 item_colour;
+ uint8 model_type;
+ int ebp = selected_tab;
+
+ {
+ int eax = x, ebx = y, ecx = 0, edx = 0, esi = 0, edi = 0;
+ RCT2_CALLFUNC_X(0x6E1F34, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
+ item_colour = edi;
+ model_type = (ebx & 0xFF00) >> 8;
+ grid_x = eax;
+ grid_y = ecx;
+ grid_z = edx;
+ }
+
+ if (grid_x == 0x8000)return;
+
+ if (ebp >= 1024){
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = 1161;
+
+ // The return value will be banner id but the input is colour
+ int banner_id = item_colour;
+
+ int ebx = (model_type << 8) | 1;
+
+ {
+ int esi = 0, eax = grid_x, ecx = grid_y, edx = grid_z;
+ game_do_command_p(GAME_COMMAND_50, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp);
+ }
+
+ if (ebx == 0x80000000)return;
+
+ sound_play_panned(SOUND_PLACE_ITEM, 0x8001, RCT2_GLOBAL(0x009DEA5E, uint16), RCT2_GLOBAL(0x009DEA60, uint16), RCT2_GLOBAL(0x009DEA62, uint16));
+
+ window_banner_open(banner_id);
+ }
+ else if (ebp >= 768){
+ //6e301c
+ RCT2_CALLPROC_X(0x6E2CC6, x, y, 0, widgetIndex, (int)w, 0, 0);
+ }
+ else if (ebp >= 512){
+ //6e2f2e
+ RCT2_CALLPROC_X(0x6E2CC6, x, y, 0, widgetIndex, (int)w, 0, 0);
+ }
+ else if (ebp >= 256){
+ //6e2eda
+ RCT2_CALLPROC_X(0x6E2CC6, x, y, 0, widgetIndex, (int)w, 0, 0);
+ }
+ else{
+ //6e2d2d
+ RCT2_CALLPROC_X(0x6E2CC6, x, y, 0, widgetIndex, (int)w, 0, 0);
+ }
+}
+
+/**
+ *
+ * rct2: 0x0066CB25
+ */
+static void window_top_toolbar_tool_update()
+{
+ short widgetIndex;
+ rct_window *w;
+ short x, y;
+
+ window_tool_get_registers(w, widgetIndex, x, y);
+
+ switch (widgetIndex){
+ case WIDX_CLEAR_SCENERY:
+ RCT2_CALLPROC_X(0x0068E213, x, y, 0, widgetIndex, (int)w, 0, 0);
+ break;
+ case WIDX_LAND:
+ RCT2_CALLPROC_X(0x00664280, x, y, 0, widgetIndex, (int)w, 0, 0);
+ break;
+ case WIDX_WATER:
+ RCT2_CALLPROC_X(0x006E6BDC, x, y, 0, widgetIndex, (int)w, 0, 0);
+ break;
+ case WIDX_SCENERY:
+ RCT2_CALLPROC_X(0x006E287B, x, y, 0, widgetIndex, (int)w, 0, 0);
+ break;
+ }
+}
+
+/**
+ * rct2: 0x0066CB73
+ */
+static void window_top_toolbar_tool_down(){
+ short widgetIndex;
+ rct_window* w;
+ short x, y;
+
+ window_tool_get_registers(w, widgetIndex, x, y);
+
+ switch (widgetIndex){
+ case WIDX_CLEAR_SCENERY:
+ if (!RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))
+ break;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = 3438;
+
+ game_do_command(
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16),
+ 1,
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16),
+ 0,
+ GAME_COMMAND_CLEAR_SCENERY,
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16),
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16)
+ );
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = 12;
+ break;
+ case WIDX_LAND:
+ if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16)&(1 << 0)){
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = 1387;
+ game_do_command(
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16),
+ 1,
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16),
+ RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) | (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) << 8),
+ GAME_COMMAND_CHANGE_SURFACE_STYLE,
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16),
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16)
+ );
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = 3;
+ }
+ break;
+ case WIDX_WATER:
+ if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16)&(1 << 0)){
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = 3;
+ }
+ break;
+ case WIDX_SCENERY:
+ window_top_toolbar_scenery_tool_down(x, y, w, widgetIndex);
+ break;
+ }
+}
+
+/**
+ *
+ * rct2: 0x0066CB4E
+ */
+static void window_top_toolbar_tool_drag()
+{
+ short widgetIndex;
+ rct_window *w;
+ short x, y;
+
+ window_tool_get_registers(w, widgetIndex, x, y);
+
+ switch (widgetIndex){
+ case WIDX_CLEAR_SCENERY:
+ if (window_find_by_class(WC_ERROR) != NULL)
+ break;
+
+ if (!RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) & (1 << 0))
+ break;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID, rct_string_id) = 3438;
+
+ game_do_command(
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16),
+ 1,
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16),
+ 0,
+ GAME_COMMAND_CLEAR_SCENERY,
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16),
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16)
+ );
+ RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = 12;
+ break;
+ case WIDX_LAND:
+ RCT2_CALLPROC_X(0x00664454, x, y, 0, widgetIndex, (int)w, 0, 0);
+ break;
+ case WIDX_WATER:
+ RCT2_CALLPROC_X(0x006E6D4B, x, y, 0, widgetIndex, (int)w, 0, 0);
+ break;
+ case WIDX_SCENERY:
+ RCT2_CALLPROC_X(0x006E2CBC, x, y, 0, widgetIndex, (int)w, 0, 0);
+ break;
+ }
+}
+
+/**
+ *
+ * rct2: 0x0066CDE4
+ */
+void top_toolbar_init_view_menu(rct_window* w, rct_widget* widget) {
+ gDropdownItemsFormat[0] = 1156;
+ gDropdownItemsFormat[1] = 1156;
+ gDropdownItemsFormat[2] = 1156;
+ gDropdownItemsFormat[3] = 0;
+ gDropdownItemsFormat[4] = 1156;
+ gDropdownItemsFormat[5] = 1156;
+ gDropdownItemsFormat[6] = 1156;
+ gDropdownItemsFormat[7] = 1156;
+ gDropdownItemsFormat[8] = 0;
+ gDropdownItemsFormat[9] = 1156;
+ gDropdownItemsFormat[10] = 1156;
+ gDropdownItemsFormat[11] = 1156;
+
+ gDropdownItemsArgs[0] = STR_UNDERGROUND_VIEW;
+ gDropdownItemsArgs[1] = STR_REMOVE_BASE_LAND;
+ gDropdownItemsArgs[2] = STR_REMOVE_VERTICAL_FACES;
+ gDropdownItemsArgs[4] = STR_SEE_THROUGH_RIDES;
+ gDropdownItemsArgs[5] = STR_SEE_THROUGH_SCENERY;
+ gDropdownItemsArgs[6] = STR_INVISIBLE_SUPPORTS;
+ gDropdownItemsArgs[7] = STR_INVISIBLE_PEOPLE;
+ gDropdownItemsArgs[9] = STR_HEIGHT_MARKS_ON_LAND;
+ gDropdownItemsArgs[10] = STR_HEIGHT_MARKS_ON_RIDE_TRACKS;
+ gDropdownItemsArgs[11] = STR_HEIGHT_MARKS_ON_PATHS;
+
+ window_dropdown_show_text(
+ w->x + widget->left,
+ w->y + widget->top,
+ widget->bottom - widget->top + 1,
+ w->colours[1] | 0x80,
+ 0,
+ 12
+ );
+
+ // Set checkmarks
+ rct_viewport* mainViewport = window_get_main()->viewport;
+ if (mainViewport->flags & VIEWPORT_FLAG_UNDERGROUND_INSIDE)
+ gDropdownItemsChecked |= (1 << 0);
+ if (mainViewport->flags & VIEWPORT_FLAG_HIDE_BASE)
+ gDropdownItemsChecked |= (1 << 1);
+ if (mainViewport->flags & VIEWPORT_FLAG_HIDE_VERTICAL)
+ gDropdownItemsChecked |= (1 << 2);
+ if (mainViewport->flags & VIEWPORT_FLAG_SEETHROUGH_RIDES)
+ gDropdownItemsChecked |= (1 << 4);
+ if (mainViewport->flags & VIEWPORT_FLAG_SEETHROUGH_SCENERY)
+ gDropdownItemsChecked |= (1 << 5);
+ if (mainViewport->flags & VIEWPORT_FLAG_INVISIBLE_SUPPORTS)
+ gDropdownItemsChecked |= (1 << 6);
+ if (mainViewport->flags & VIEWPORT_FLAG_INVISIBLE_PEEPS)
+ gDropdownItemsChecked |= (1 << 7);
+ if (mainViewport->flags & VIEWPORT_FLAG_LAND_HEIGHTS)
+ gDropdownItemsChecked |= (1 << 9);
+ if (mainViewport->flags & VIEWPORT_FLAG_TRACK_HEIGHTS)
+ gDropdownItemsChecked |= (1 << 10);
+ if (mainViewport->flags & VIEWPORT_FLAG_PATH_HEIGHTS)
+ gDropdownItemsChecked |= (1 << 11);
+
+ RCT2_GLOBAL(0x9DEBA2, uint16) = 0;
+}
+
+/**
+ *
+ * rct2: 0x0066CF8A
+ */
+void top_toolbar_view_menu_dropdown(short dropdownIndex) {
+ if (dropdownIndex == -1) dropdownIndex = RCT2_GLOBAL(0x9DEBA2, uint16);
+ rct_window* w = window_get_main();
+ if (w) {
+ switch (dropdownIndex) {
+ case DDIDX_UNDERGROUND_INSIDE:
+ w->viewport->flags ^= VIEWPORT_FLAG_UNDERGROUND_INSIDE;
+ break;
+ case DDIDX_HIDE_BASE:
+ w->viewport->flags ^= VIEWPORT_FLAG_HIDE_BASE;
+ break;
+ case DDIDX_HIDE_VERTICAL:
+ w->viewport->flags ^= VIEWPORT_FLAG_HIDE_VERTICAL;
+ break;
+ case DDIDX_SEETHROUGH_RIDES:
+ w->viewport->flags ^= VIEWPORT_FLAG_SEETHROUGH_RIDES;
+ break;
+ case DDIDX_SEETHROUGH_SCENARY:
+ w->viewport->flags ^= VIEWPORT_FLAG_SEETHROUGH_SCENERY;
+ break;
+ case DDIDX_INVISIBLE_SUPPORTS:
+ w->viewport->flags ^= VIEWPORT_FLAG_INVISIBLE_SUPPORTS;
+ break;
+ case DDIDX_INVISIBLE_PEEPS:
+ w->viewport->flags ^= VIEWPORT_FLAG_INVISIBLE_PEEPS;
+ break;
+ case DDIDX_LAND_HEIGHTS:
+ w->viewport->flags ^= VIEWPORT_FLAG_LAND_HEIGHTS;
+ break;
+ case DDIDX_TRACK_HEIGHTS:
+ w->viewport->flags ^= VIEWPORT_FLAG_TRACK_HEIGHTS;
+ break;
+ case DDIDX_PATH_HEIGHTS:
+ w->viewport->flags ^= VIEWPORT_FLAG_PATH_HEIGHTS;
+ break;
+ default:
+ return;
+ }
+ window_invalidate(w);
+ }
+}
+
+
+/**
+ *
+ * rct2: 0x0066CCE7
+ */
+void toggle_footpath_window()
+{
+ if (window_find_by_class(WC_FOOTPATH) == NULL) {
+ window_footpath_open();
+ } else {
+ tool_cancel();
+ window_close_by_class(WC_FOOTPATH);
+ }
+}
+
+/**
+ *
+ * rct2: 0x0066CD54
+ */
+void toggle_land_window(rct_window *topToolbar, int widgetIndex)
+{
+ if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 7) {
+ tool_cancel();
+ } else {
+ show_gridlines();
+ tool_set(topToolbar, widgetIndex, 18);
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
+ RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1;
+ window_land_open();
+ }
+}
+
+/**
+ *
+ * rct2: 0x0066CD0C
+ */
+void toggle_clear_scenery_window(rct_window *topToolbar, int widgetIndex)
+{
+ if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 16) {
+ tool_cancel();
+ } else {
+ show_gridlines();
+ tool_set(topToolbar, widgetIndex, 12);
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
+ RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 2;
+ window_clear_scenery_open();
+ }
+}
+
+/**
+ *
+ * rct2: 0x0066CD9C
+ */
+void toggle_water_window(rct_window *topToolbar, int widgetIndex)
+{
+ if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 8) {
+ tool_cancel();
+ } else {
+ show_gridlines();
+ tool_set(topToolbar, widgetIndex, 19);
+ RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
+ RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1;
+ window_water_open();
+ }
+}
\ No newline at end of file
diff --git a/src/windows/track_list.c b/src/windows/track_list.c
index 555a263d3d..26f7ac428a 100644
--- a/src/windows/track_list.c
+++ b/src/windows/track_list.c
@@ -94,15 +94,21 @@ static void* window_track_list_events[] = {
ride_list_item _window_track_list_item;
-void window_track_list_format_name(char *dst, const char *src, char colour)
+void window_track_list_format_name(char *dst, const char *src, char colour, char quotes)
{
if (colour != 0)
*dst++ = colour;
- *dst++ = FORMAT_OPENQUOTES;
+
+ if (quotes != 0)
+ *dst++ = FORMAT_OPENQUOTES;
+
while (*src != '.' && *src != 0) {
*dst++ = *src++;
}
- *dst++ = FORMAT_ENDQUOTES;
+
+ if (quotes != 0)
+ *dst++ = FORMAT_ENDQUOTES;
+
*dst = 0;
}
@@ -126,8 +132,8 @@ void window_track_list_open(ride_list_item item)
if (mem == NULL)
return;
- RCT2_GLOBAL(0x00F44105, void*) = mem;
- RCT2_CALLPROC_EBPSAFE(0x006D1DCE);
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_CACHE, void*) = mem;
+ reset_track_list_cache();
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
x = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2 - 300;
@@ -136,7 +142,7 @@ void window_track_list_open(ride_list_item item)
x = 0;
y = 29;
}
- w = window_create(0, 29, 600, 400, (uint32*)window_track_list_events, WC_TRACK_DESIGN_LIST, 0);
+ w = window_create(x, y, 600, 400, (uint32*)window_track_list_events, WC_TRACK_DESIGN_LIST, 0);
w->widgets = window_track_list_widgets;
w->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_ROTATE) | (1 << WIDX_TOGGLE_SCENERY);
window_init_scroll_widgets(w);
@@ -144,11 +150,11 @@ void window_track_list_open(ride_list_item item)
w->colours[1] = 26;
w->colours[2] = 26;
w->track_list.var_480 = 0xFFFF;
- w->track_list.var_482 = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER ? 1 : 0;
+ w->track_list.var_482 = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER ? 0 : 1;
w->track_list.var_484 = 0;
- RCT2_GLOBAL(0x00F44152, uint8) = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) = 0;
window_push_others_right(w);
- RCT2_GLOBAL(0x00F440AE, uint8) = 2;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = 2;
}
/**
@@ -157,7 +163,7 @@ void window_track_list_open(ride_list_item item)
*/
static void window_track_list_select(rct_window *w, int index)
{
- uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC;
+ uint8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8);
rct_track_design *trackDesign;
w->track_list.var_480 = index;
@@ -170,37 +176,39 @@ static void window_track_list_select(rct_window *w, int index)
}
if (RCT2_GLOBAL(0x00F44153, uint8) != 0)
- RCT2_GLOBAL(0x00F44152, uint8) = 1;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) = 1;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER))
index--;
- trackDesignItem = trackDesignList + (index * 128);;
+ trackDesignItem = trackDesignList + (index * 128);
RCT2_GLOBAL(0x00F4403C, uint8*) = trackDesignItem;
window_track_list_format_name(
(char*)0x009BC313,
trackDesignItem,
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER ?
- 0 :
- FORMAT_WHITE
- );
+ 0 :
+ FORMAT_WHITE,
+ 1);
- subsitute_path((char*)0x0141EF68, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem);
+ char track_path[MAX_PATH] = { 0 };
+ subsitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem);
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) {
window_track_manage_open();
return;
}
- if (!RCT2_CALLPROC_X(0x0067726A, 0, 0, 0, 0, 0, 0, 0)) {
+ if (!load_track_design(track_path)) {
w->track_list.var_480 = 0xFFFF;
window_invalidate(w);
return;
}
trackDesign = track_get_info(index, NULL);
- if (trackDesign->var_06 & 4)
+ if (trackDesign == NULL) return;
+ if (trackDesign->track_td6.var_06 & 4)
window_error_open(STR_THIS_DESIGN_WILL_BE_BUILT_WITH_AN_ALTERNATIVE_VEHICLE_TYPE, -1);
window_close(w);
@@ -210,7 +218,7 @@ static void window_track_list_select(rct_window *w, int index)
static int window_track_list_get_list_item_index_from_position(int x, int y)
{
int index;
- uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC;
+ uint8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8);
index = 0;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER)) {
@@ -236,7 +244,7 @@ static int window_track_list_get_list_item_index_from_position(int x, int y)
*/
static void window_track_list_close()
{
- free(RCT2_GLOBAL(0x00F44105, void*));
+ free(RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_CACHE, void*));
}
/**
@@ -260,13 +268,13 @@ static void window_track_list_mouseup()
}
break;
case WIDX_ROTATE:
- RCT2_GLOBAL(0x00F440AE, uint8)++;
- RCT2_GLOBAL(0x00F440AE, uint8) %= 4;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8)++;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) %= 4;
window_invalidate(w);
break;
case WIDX_TOGGLE_SCENERY:
- RCT2_GLOBAL(0x00F44152, uint8) ^= 1;
- RCT2_CALLPROC_EBPSAFE(0x006D1DCE);
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) ^= 1;
+ reset_track_list_cache();
window_invalidate(w);
break;
}
@@ -280,7 +288,7 @@ static void window_track_list_scrollgetsize()
{
rct_window *w;
int width, height;
- uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC;
+ uint8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8);
window_get_register(w);
@@ -305,7 +313,7 @@ static void window_track_list_scrollmousedown()
if (w->track_list.var_484 & 1)
return;
- if (RCT2_GLOBAL(0x009DEA6E, uint8) != 0)
+ if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0)
return;
i = window_track_list_get_list_item_index_from_position(x, y);
@@ -326,7 +334,7 @@ static void window_track_list_scrollmouseover()
if (w->track_list.var_484 & 1)
return;
- if (RCT2_GLOBAL(0x009DEA6E, uint8) != 0)
+ if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0)
return;
i = window_track_list_get_list_item_index_from_position(x, y);
@@ -377,7 +385,7 @@ static void window_track_list_invalidate()
w->disabled_widgets &= ~(1 << WIDX_TRACK_PREVIEW);
window_track_list_widgets[WIDX_ROTATE].type = WWT_FLATBTN;
window_track_list_widgets[WIDX_TOGGLE_SCENERY].type = WWT_FLATBTN;
- if (RCT2_GLOBAL(0x00F44152, uint8) == 0)
+ if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) == 0)
w->pressed_widgets |= (1 << WIDX_TOGGLE_SCENERY);
else
w->pressed_widgets &= ~(1 << WIDX_TOGGLE_SCENERY);
@@ -398,8 +406,8 @@ static void window_track_list_paint()
rct_window *w;
rct_drawpixelinfo *dpi;
rct_widget *widget;
- rct_track_design *trackDesign;
- uint8 *image, *trackDesignList = (uint8*)0x00F441EC;
+ rct_track_design *trackDesign = NULL;
+ uint8 *image, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8);
uint16 holes, speed, drops, dropHeight, inversions;
fixed32_2dp rating;
int trackIndex, x, y, colour, gForces, airTime;
@@ -428,6 +436,8 @@ static void window_track_list_paint()
if (trackDesign == NULL)
return;
+ rct_track_td6* track_td6 = &trackDesign->track_td6;
+
subsituteElement = &g1Elements[0];
tmpElement = *subsituteElement;
subsituteElement->offset = image;
@@ -444,15 +454,15 @@ static void window_track_list_paint()
RCT2_GLOBAL(0x00F44153, uint8) = 0;
// Warnings
- if ((trackDesign->var_06 & 4) && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER)) {
+ if ((track_td6->var_06 & 4) && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER)) {
// Vehicle design not available
gfx_draw_string_centred_clipped(dpi, STR_VEHICLE_DESIGN_UNAVAILABLE, NULL, 0, x, y, 368);
y -= 10;
}
- if (trackDesign->var_06 & 1) {
+ if (track_td6->var_06 & 1) {
RCT2_GLOBAL(0x00F44153, uint8) = 1;
- if (RCT2_GLOBAL(0x00F44152, uint8) == 0) {
+ if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) == 0) {
// Scenery not available
gfx_draw_string_centred_clipped(dpi, STR_DESIGN_INCLUDES_SCENERY_WHICH_IS_UNAVAILABLE, NULL, 0, x, y, 368);
y -= 10;
@@ -460,96 +470,96 @@ static void window_track_list_paint()
}
// Track design name
- window_track_list_format_name((char*)0x009BC677, trackDesignList + (trackIndex * 128), FORMAT_WINDOW_COLOUR_1);
+ window_track_list_format_name((char*)0x009BC677, trackDesignList + (trackIndex * 128), FORMAT_WINDOW_COLOUR_1, 1);
gfx_draw_string_centred_clipped(dpi, 3165, NULL, 0, x, y, 368);
// Information
x = w->x + widget->left + 1;
y = w->y + widget->bottom + 2;
- if (trackDesign->var_6C & 0x80000000) {
+ if (track_td6->var_6C & 0x80000000) {
// Six flags logo
gfx_draw_sprite(dpi, SPR_SIX_FLAGS, w->x + widget->right - 50, y + 4, 0);
}
// Stats
- rating = trackDesign->excitement * 10;
+ rating = track_td6->excitement * 10;
gfx_draw_string_left(dpi, STR_TRACK_LIST_EXCITEMENT_RATING, &rating, 0, x, y);
y += 10;
- rating = trackDesign->intensity * 10;
+ rating = track_td6->intensity * 10;
gfx_draw_string_left(dpi, STR_TRACK_LIST_INTENSITY_RATING, &rating, 0, x, y);
y += 10;
- rating = trackDesign->nausea * 10;
+ rating = track_td6->nausea * 10;
gfx_draw_string_left(dpi, STR_TRACK_LIST_NAUSEA_RATING, &rating, 0, x, y);
y += 14;
- if (trackDesign->type != RIDE_TYPE_MAZE) {
- if (trackDesign->type == RIDE_TYPE_MINI_GOLF) {
+ if (track_td6->type != RIDE_TYPE_MAZE) {
+ if (track_td6->type == RIDE_TYPE_MINI_GOLF) {
// Holes
- holes = trackDesign->holes & 0x1F;
+ holes = track_td6->holes & 0x1F;
gfx_draw_string_left(dpi, STR_HOLES, &holes, 0, x, y);
y += 10;
} else {
// Maximum speed
- speed = ((trackDesign->max_speed << 16) * 9) >> 18;
+ speed = ((track_td6->max_speed << 16) * 9) >> 18;
gfx_draw_string_left(dpi, STR_MAX_SPEED, &speed, 0, x, y);
y += 10;
// Average speed
- speed = ((trackDesign->average_speed << 16) * 9) >> 18;
+ speed = ((track_td6->average_speed << 16) * 9) >> 18;
gfx_draw_string_left(dpi, STR_AVERAGE_SPEED, &speed, 0, x, y);
y += 10;
}
// Ride length
RCT2_GLOBAL(0x013CE952 + 0, uint16) = 1345;
- RCT2_GLOBAL(0x013CE952 + 2, uint16) = trackDesign->ride_length;
+ RCT2_GLOBAL(0x013CE952 + 2, uint16) = track_td6->ride_length;
gfx_draw_string_left_clipped(dpi, STR_TRACK_LIST_RIDE_LENGTH, (void*)0x013CE952, 0, x, y, 214);
y += 10;
}
- if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (trackDesign->type * 8), uint32) & 0x80) {
+ if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (track_td6->type * 8), uint32) & 0x80) {
// Maximum positive vertical Gs
- gForces = trackDesign->max_positive_vertical_g * 32;
+ gForces = track_td6->max_positive_vertical_g * 32;
gfx_draw_string_left(dpi, STR_MAX_POSITIVE_VERTICAL_G, &gForces, 0, x, y);
y += 10;
// Maximum negative verical Gs
- gForces = trackDesign->max_negitive_vertical_g * 32;
+ gForces = track_td6->max_negitive_vertical_g * 32;
gfx_draw_string_left(dpi, STR_MAX_NEGATIVE_VERTICAL_G, &gForces, 0, x, y);
y += 10;
// Maximum lateral Gs
- gForces = trackDesign->max_lateral_g * 32;
+ gForces = track_td6->max_lateral_g * 32;
gfx_draw_string_left(dpi, STR_MAX_LATERAL_G, &gForces, 0, x, y);
y += 10;
- if (trackDesign->var_07 / 4 >= 2) {
- if (trackDesign->total_air_time != 0) {
+ if (track_td6->var_07 / 4 >= 2) {
+ if (track_td6->total_air_time != 0) {
// Total air time
- airTime = trackDesign->total_air_time * 25;
+ airTime = track_td6->total_air_time * 25;
gfx_draw_string_left(dpi, STR_TOTAL_AIR_TIME, &airTime, 0, x, y);
y += 10;
}
}
}
- if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (trackDesign->type * 8), uint32) & 0x400) {
+ if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (track_td6->type * 8), uint32) & 0x400) {
// Drops
- drops = trackDesign->drops & 0x3F;
+ drops = track_td6->drops & 0x3F;
gfx_draw_string_left(dpi, STR_DROPS, &drops, 0, x, y);
y += 10;
// Drop height is multiplied by 0.75
- dropHeight = (trackDesign->highest_drop_height + (trackDesign->highest_drop_height / 2)) / 2;
+ dropHeight = (track_td6->highest_drop_height + (track_td6->highest_drop_height / 2)) / 2;
gfx_draw_string_left(dpi, STR_HIGHEST_DROP_HEIGHT, &drops, 0, x, y);
y += 10;
}
- if (trackDesign->type != RIDE_TYPE_MINI_GOLF) {
- inversions = trackDesign->inversions & 0x1F;
+ if (track_td6->type != RIDE_TYPE_MINI_GOLF) {
+ inversions = track_td6->inversions & 0x1F;
if (inversions != 0) {
// Inversions
gfx_draw_string_left(dpi, STR_INVERSIONS, &inversions, 0, x, y);
@@ -558,16 +568,16 @@ static void window_track_list_paint()
}
y += 4;
- if (trackDesign->space_required_x != 0xFF) {
+ if (track_td6->space_required_x != 0xFF) {
// Space required
- RCT2_GLOBAL(0x013CE952 + 0, uint16) = trackDesign->space_required_x;
- RCT2_GLOBAL(0x013CE952 + 2, uint16) = trackDesign->space_required_y;
+ RCT2_GLOBAL(0x013CE952 + 0, uint16) = track_td6->space_required_x;
+ RCT2_GLOBAL(0x013CE952 + 2, uint16) = track_td6->space_required_y;
gfx_draw_string_left(dpi, STR_TRACK_LIST_SPACE_REQUIRED, (void*)0x013CE952, 0, x, y);
y += 10;
}
- if (trackDesign->cost != 0) {
- gfx_draw_string_left(dpi, STR_TRACK_LIST_COST_AROUND, &trackDesign->cost, 0, x, y);
+ if (track_td6->cost != 0) {
+ gfx_draw_string_left(dpi, STR_TRACK_LIST_COST_AROUND, &track_td6->cost, 0, x, y);
y += 14;
}
}
@@ -582,7 +592,7 @@ static void window_track_list_scrollpaint()
rct_drawpixelinfo *dpi;
rct_string_id stringId, stringId2;
int i, x, y, colour;
- uint8 *trackDesignItem, *trackDesignList = (uint8*)0x00F441EC;
+ uint8 *trackDesignItem, *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, uint8);
window_paint_get_registers(w, dpi);
@@ -614,9 +624,9 @@ static void window_track_list_scrollpaint()
stringId2 = STR_BUILD_CUSTOM_DESIGN;
gfx_draw_string_left(dpi, stringId, &stringId2, 0, x, y - 1);
y += 10;
+ i++;
}
- i++;
while (*trackDesignItem != 0) {
if (y + 10 >= dpi->y && y < dpi->y + dpi->height) {
if (i == w->track_list.var_482) {
@@ -628,7 +638,7 @@ static void window_track_list_scrollpaint()
}
// Draw track name
- window_track_list_format_name((char *)language_get_string(3165), trackDesignItem, 0);
+ window_track_list_format_name((char *)language_get_string(3165), trackDesignItem, 0, 1);
stringId2 = 3165;
gfx_draw_string_left(dpi, stringId, &stringId2, 0, x, y - 1);
}
diff --git a/src/windows/track_manage.c b/src/windows/track_manage.c
index f636a57c42..17a60a0818 100644
--- a/src/windows/track_manage.c
+++ b/src/windows/track_manage.c
@@ -146,15 +146,13 @@ static void window_track_delete_prompt_open();
*/
void window_track_manage_open()
{
- // RCT2_CALLPROC_EBPSAFE(0x006D348F);
-
rct_window *w, *trackDesignListWindow;
window_close_by_class(WC_MANAGE_TRACK_DESIGN);
w = window_create(
max(28, (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 250) / 2),
- (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 44) / 2,
+ (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 44) / 2,
250,
44,
(uint32*)window_track_manage_events,
@@ -199,6 +197,7 @@ static void window_track_manage_mouseup()
uint8 *trackDesignList = (uint8*)0x00F441EC;
rct_window *w, *trackDesignListWindow;
short widgetIndex;
+ char *dst, *src;
window_widget_get_registers(w, widgetIndex);
@@ -209,8 +208,12 @@ static void window_track_manage_mouseup()
case WIDX_RENAME:
trackDesignListWindow = window_find_by_class(WC_TRACK_DESIGN_LIST);
if (trackDesignListWindow != NULL) {
- strcpy((char*)0x009BC677, (char*)trackDesignList[trackDesignListWindow->track_list.var_482 * 128]);
- window_show_textinput(w, widgetIndex, 3350, 3351, 3165);
+ src = &trackDesignList[trackDesignListWindow->track_list.var_482 * 128];
+ dst = (char*)0x009BC677;
+ while (*src != 0 && *src != '.')
+ *dst++ = *src++;
+ *dst = 0;
+ window_text_input_open(w, widgetIndex, 3350, 3351, 3165, 0, 127);
}
break;
case WIDX_DELETE:
diff --git a/src/windows/track_place.c b/src/windows/track_place.c
index 676f1a99a9..785cc66364 100644
--- a/src/windows/track_place.c
+++ b/src/windows/track_place.c
@@ -28,6 +28,7 @@
#include "../localisation/localisation.h"
#include "../sprites.h"
#include "../ride/track.h"
+#include "../ride/track_data.h"
#define TRACK_MINI_PREVIEW_WIDTH 168
#define TRACK_MINI_PREVIEW_HEIGHT 78
@@ -114,33 +115,6 @@ static void window_track_place_clear_mini_preview()
memset(_window_track_place_mini_preview, 220, TRACK_MINI_PREVIEW_SIZE);
}
-/**
- * Size: 0x0A
- */
-typedef struct {
- uint8 var_00;
- sint16 x;
- sint16 y;
- uint8 pad_05[3];
- uint8 var_08;
- uint8 unk_09;
-} rct_preview_track;
-
-/**
- * Size: 0x04
- */
-typedef struct {
- union {
- uint32 all;
- struct {
- sint8 x;
- sint8 y;
- uint8 unk_2;
- uint8 type;
- };
- };
-} rct_preview_maze;
-
#define swap(x, y) x = x ^ y; y = x ^ y; x = x ^ y;
/**
@@ -149,10 +123,11 @@ typedef struct {
*/
static void window_track_place_draw_mini_preview()
{
- rct_track_design *design = (rct_track_design*)0x009D8178;
- uint8 *pixel, colour, *trackPtr, bits;
+ rct_track_td6 *track = RCT2_ADDRESS(0x009D8178, rct_track_td6);
+ uint8 *pixel, colour, bits;
int i, rotation, pass, x, y, pixelX, pixelY, originX, originY, minX, minY, maxX, maxY;
- rct_preview_maze *mazeBlock;
+ rct_maze_element *mazeElement;
+ rct_track_element *trackElement;
rct_preview_track *trackBlock;
window_track_place_clear_mini_preview();
@@ -171,14 +146,14 @@ static void window_track_place_draw_mini_preview()
originY -= ((maxY + minY) >> 6) << 5;
}
- if (design->type != RIDE_TYPE_MAZE) {
+ if (track->type != RIDE_TYPE_MAZE) {
#pragma region Track
- rotation = RCT2_GLOBAL(0x00F440AE, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32);
- trackPtr = design->preview[0];
+ rotation = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32);
+ trackElement = RCT2_ADDRESS(0x009D821B, rct_track_element);
- while (*trackPtr != 255) {
- int trackType = *trackPtr;
+ while (trackElement->type != 255) {
+ int trackType = trackElement->type;
if (trackType == 101)
trackType = 255;
@@ -218,7 +193,7 @@ static void window_track_place_draw_mini_preview()
} else {
pixelX = 80 + ((y / 32) - (x / 32)) * 4;
pixelY = 38 + ((y / 32) + (x / 32)) * 2;
- if (pixelX <= 160 && pixelY <= 75) {
+ if (pixelX >= 0 && pixelY >= 0 && pixelX <= 160 && pixelY <= 75) {
pixel = &_window_track_place_mini_preview[pixelY * TRACK_MINI_PREVIEW_WIDTH + pixelX];
bits = trackBlock->var_08 << (rotation & 3);
@@ -237,45 +212,47 @@ static void window_track_place_draw_mini_preview()
// Change rotation and next position based on track curvature
rotation &= 3;
+ const rct_track_coordinates* track_coordinate = &TrackCoordinates[trackType];
+
trackType *= 10;
switch (rotation) {
case 0:
- originX += RCT2_GLOBAL(0x009968C1 + trackType, sint16);
- originY += RCT2_GLOBAL(0x009968C3 + trackType, sint16);
+ originX += track_coordinate->x;
+ originY += track_coordinate->y;
break;
case 1:
- originX += RCT2_GLOBAL(0x009968C3 + trackType, sint16);
- originY -= RCT2_GLOBAL(0x009968C1 + trackType, sint16);
+ originX += track_coordinate->y;
+ originY -= track_coordinate->x;
break;
case 2:
- originX -= RCT2_GLOBAL(0x009968C1 + trackType, sint16);
- originY -= RCT2_GLOBAL(0x009968C3 + trackType, sint16);
+ originX -= track_coordinate->x;
+ originY -= track_coordinate->y;
break;
case 3:
- originX -= RCT2_GLOBAL(0x009968C3 + trackType, sint16);
- originY += RCT2_GLOBAL(0x009968C1 + trackType, sint16);
+ originX -= track_coordinate->y;
+ originY += track_coordinate->x;
break;
}
- rotation += RCT2_ADDRESS(0x009968BC, uint8)[trackType] - RCT2_ADDRESS(0x009968BB, uint8)[trackType];
+ rotation += track_coordinate->rotation_positive - track_coordinate->rotation_negative;
rotation &= 3;
- if (RCT2_ADDRESS(0x009968BC, uint8)[trackType] & 4)
+ if (track_coordinate->rotation_positive & 4)
rotation |= 4;
if (!(rotation & 4)) {
originX += RCT2_GLOBAL(0x00993CCC + (rotation * 4), sint16);
originY += RCT2_GLOBAL(0x00993CCE + (rotation * 4), sint16);
}
- trackPtr += 2;
+ trackElement++;
}
#pragma endregion
} else {
#pragma region Maze
- rotation = (RCT2_GLOBAL(0x00F440AE, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) & 3;
- mazeBlock = (rct_preview_maze*)design->preview[0];
- while (mazeBlock->all != 0) {
- x = mazeBlock->x * 32;
- y = mazeBlock->y * 32;
+ rotation = (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) & 3;
+ mazeElement = RCT2_ADDRESS(0x009D821B, rct_maze_element);
+ while (mazeElement->all != 0) {
+ x = mazeElement->x * 32;
+ y = mazeElement->y * 32;
switch (rotation) {
case 1:
x = -x;
@@ -294,7 +271,7 @@ static void window_track_place_draw_mini_preview()
y += originY;
// Entrance or exit is a lighter colour
- colour = mazeBlock->type == 8 || mazeBlock->type == 128 ? 222 : 218;
+ colour = mazeElement->type == 8 || mazeElement->type == 128 ? 222 : 218;
if (pass == 0) {
minX = min(minX, x);
@@ -315,7 +292,7 @@ static void window_track_place_draw_mini_preview()
}
}
}
- mazeBlock++;
+ mazeElement++;
}
#pragma endregion
@@ -337,24 +314,6 @@ static void sub_68A15E(int x, int y, short *ax, short *bx)
*bx = *((short*)&ebx);
}
-/**
- * Seems to highlight the surface tiles to match the track layout at the given position but also returns some Z value.
- * rct2: 0x006D01B3
- */
-static int sub_6D01B3(int bl, int x, int y, int z)
-{
- int eax, ebx, ecx, edx, esi, edi, ebp;
- eax = x;
- ebx = bl;
- ecx = y;
- edx = z;
- esi = 0;
- edi = 0;
- ebp = 0;
- RCT2_CALLFUNC_X(0x006D01B3, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
- return *((short*)&ebx);
-}
-
/**
*
* rct2: 0x006D017F
@@ -441,7 +400,7 @@ void window_track_place_open()
show_gridlines();
_window_track_place_last_cost = MONEY32_UNDEFINED;
_window_track_place_last_x = 0xFFFF;
- RCT2_GLOBAL(0x00F440AE, uint8) = (-RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)) & 3;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = (-RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)) & 3;
window_track_place_draw_mini_preview();
}
@@ -476,14 +435,14 @@ static void window_track_place_mouseup()
break;
case WIDX_ROTATE:
window_track_place_clear_provisional();
- RCT2_GLOBAL(0x00F440AE, uint16) = (RCT2_GLOBAL(0x00F440AE, uint16) + 1) & 3;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint16) = (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint16) + 1) & 3;
window_invalidate(w);
_window_track_place_last_x = 0xFFFF;
window_track_place_draw_mini_preview();
break;
case WIDX_MIRROR:
RCT2_CALLPROC_EBPSAFE(0x006D2436);
- RCT2_GLOBAL(0x00F440AE, uint16) = (-RCT2_GLOBAL(0x00F440AE, uint16)) & 3;
+ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint16) = (-RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint16)) & 3;
window_invalidate(w);
_window_track_place_last_x = 0xFFFF;
window_track_place_draw_mini_preview();
@@ -540,7 +499,7 @@ static void window_track_place_toolupdate()
// Get base Z position
z = window_track_place_get_base_z(x, y);
- if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0) {
+ if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0) {
window_track_place_clear_provisional();
// Try increasing Z until a feasible placement is found
diff --git a/src/world/map.c b/src/world/map.c
index 508d980c92..8eb938467b 100644
--- a/src/world/map.c
+++ b/src/world/map.c
@@ -19,8 +19,10 @@
*****************************************************************************/
#include "../addresses.h"
+#include "../game.h"
#include "../localisation/date.h"
#include "../localisation/localisation.h"
+#include "../management/finance.h"
#include "climate.h"
#include "map.h"
#include "park.h"
@@ -45,6 +47,66 @@ int _sub_6A876D_save_y;
static void tiles_init();
static void sub_6A87BB(int x, int y);
+void map_element_iterator_begin(map_element_iterator *it)
+{
+ it->x = 0;
+ it->y = 0;
+ it->element = map_get_first_element_at(0, 0);
+}
+
+int map_element_iterator_next(map_element_iterator *it)
+{
+ if (it->element == NULL) {
+ it->element = map_get_first_element_at(it->x, it->y);
+ return 1;
+ }
+
+ if (!map_element_is_last_for_tile(it->element)) {
+ it->element++;
+ return 1;
+ }
+
+ if (it->x < 255) {
+ it->x++;
+ it->element = map_get_first_element_at(it->x, it->y);
+ return 1;
+ }
+
+ if (it->y < 255) {
+ it->x = 0;
+ it->y++;
+ it->element = map_get_first_element_at(it->x, it->y);
+ return 1;
+ }
+
+ return 0;
+}
+
+void map_element_iterator_restart_for_tile(map_element_iterator *it)
+{
+ it->element = NULL;
+}
+
+rct_map_element *map_get_first_element_at(int x, int y)
+{
+ if (x < 0 || y < 0 || x > 255 || y > 255)
+ {
+ log_error("Trying to access element outside of range");
+ return NULL;
+ }
+ return TILE_MAP_ELEMENT_POINTER(x + y * 256);
+}
+
+int map_element_is_last_for_tile(rct_map_element *element)
+{
+ return element->flags & MAP_ELEMENT_FLAG_LAST_TILE;
+}
+
+int map_element_get_type(rct_map_element *element)
+{
+ return element->type & MAP_ELEMENT_TYPE_MASK;
+}
+
int map_element_get_terrain(rct_map_element *element)
{
int terrain = (element->properties.surface.terrain >> 5) & 7;
@@ -71,7 +133,7 @@ void map_element_set_terrain(rct_map_element *element, int terrain)
// Bits 0, 1, 2 for terrain are stored in element.terrain bit 5, 6, 7
element->properties.surface.terrain &= ~0xE0;
- element->properties.surface.terrain = (terrain & 7) << 5;
+ element->properties.surface.terrain |= (terrain & 7) << 5;
}
void map_element_set_terrain_edge(rct_map_element *element, int terrain)
@@ -89,13 +151,11 @@ void map_element_set_terrain_edge(rct_map_element *element, int terrain)
rct_map_element *map_get_surface_element_at(int x, int y)
{
- // Get first element of the tile
- rct_map_element *mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x);
+ rct_map_element *mapElement = map_get_first_element_at(x, y);
// Find the first surface element
- while ((mapElement->type & MAP_ELEMENT_TYPE_MASK) != MAP_ELEMENT_TYPE_SURFACE) {
- // Check if last element on tile
- if (mapElement->flags & MAP_ELEMENT_FLAG_LAST_TILE)
+ while (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SURFACE) {
+ if (map_element_is_last_for_tile(mapElement))
return NULL;
mapElement++;
@@ -108,7 +168,7 @@ rct_map_element *map_get_surface_element_at(int x, int y)
*
* rct2: 0x0068AB4C
*/
-void map_init()
+void map_init(int size)
{
int i;
rct_map_element *map_element;
@@ -126,6 +186,7 @@ void map_init()
map_element->properties.surface.slope = 0;
map_element->properties.surface.grass_length = 1;
map_element->properties.surface.ownership = 0;
+ map_element->properties.surface.terrain = 0;
map_element_set_terrain(map_element, TERRAIN_GRASS);
map_element_set_terrain_edge(map_element, TERRAIN_EDGE_ROCK);
@@ -134,10 +195,10 @@ void map_init()
RCT2_GLOBAL(0x013B0E70, sint16) = 0;
_sub_6A876D_save_x = 0;
_sub_6A876D_save_y = 0;
- RCT2_GLOBAL(0x01358830, sint16) = 4768;
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16) = 5054;
- RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, sint16) = 150;
- RCT2_GLOBAL(0x01358836, sint16) = 4767;
+ RCT2_GLOBAL(0x01358830, sint16) = size * 32 - 32;
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16) = size * 32 - 2;
+ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, sint16) = size;
+ RCT2_GLOBAL(0x01358836, sint16) = size * 32 - 33;
RCT2_GLOBAL(0x01359208, sint16) = 7;
map_update_tile_pointers();
RCT2_CALLPROC_EBPSAFE(0x0068ADBC);
@@ -151,7 +212,7 @@ void map_init()
*/
void map_update_tile_pointers()
{
- int i, x, y, lastTile;
+ int i, x, y;
for (i = 0; i < MAX_TILE_MAP_ELEMENT_POINTERS; i++)
TILE_MAP_ELEMENT_POINTER(i) = TILE_UNDEFINED_MAP_ELEMENT;
@@ -161,10 +222,7 @@ void map_update_tile_pointers()
for (y = 0; y < 256; y++) {
for (x = 0; x < 256; x++) {
*tile++ = mapElement;
- do {
- lastTile = (mapElement->flags & MAP_ELEMENT_FLAG_LAST_TILE);
- mapElement++;
- } while (!lastTile);
+ do { } while (!map_element_is_last_for_tile(mapElement++));
}
}
@@ -354,7 +412,7 @@ void sub_68B089()
mapElement++;
mapElementFirst++;
- } while (!((mapElement - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
+ } while (!map_element_is_last_for_tile(mapElement - 1));
// Update next free element?
mapElement = RCT2_GLOBAL(0x0140E9A4, rct_map_element*);
@@ -370,34 +428,32 @@ void sub_68B089()
* Checks if the tile at coordinate at height counts as connected.
* @return 1 if connected, 0 otherwise
*/
-int map_coord_is_connected(uint16 tile_idx, uint8 height, uint8 face_direction)
+int map_coord_is_connected(int x, int y, int z, uint8 faceDirection)
{
- rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx];
+ rct_map_element *mapElement = map_get_first_element_at(x, y);
- do {
- rct_map_element_path_properties props = tile->properties.path;
- uint8 path_type = props.type >> 2, path_dir = props.type & 3;
- uint8 element_type = tile->type & MAP_ELEMENT_TYPE_MASK;
+ do {
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_PATH)
+ continue;
- if (element_type != PATH_ROAD)
- continue;
+ rct_map_element_path_properties props = mapElement->properties.path;
+ uint8 pathType = props.type >> 2;
+ uint8 pathDirection = props.type & 3;
- if (path_type & 1) {
- if (path_dir == face_direction) {
- if (height == tile->base_height + 2)
+ if (pathType & 1) {
+ if (pathDirection == faceDirection) {
+ if (z == mapElement->base_height + 2)
return 1;
- }
- else if ((path_dir ^ 2) == face_direction && height == tile->base_height) {
+ } else if ((pathDirection ^ 2) == faceDirection && z == mapElement->base_height) {
return 1;
}
- } else {
- if (height == tile->base_height)
+ } else {
+ if (z == mapElement->base_height)
return 1;
- }
-
- } while (!(tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) && tile++);
+ }
+ } while (!map_element_is_last_for_tile(mapElement++));
- return 0;
+ return 0;
}
/**
@@ -536,7 +592,7 @@ money32 map_try_clear_scenery(int x, int y, rct_map_element *mapElement, int fla
entry = g_smallSceneryEntries[mapElement->properties.scenery.type];
cost = entry->small_scenery.removal_price * 10;
- RCT2_GLOBAL(0x0141F56C, uint8) = 12;
+ RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4;
RCT2_GLOBAL(0x009DEA5E, uint32) = x * 32 + 16;
RCT2_GLOBAL(0x009DEA60, uint32) = y * 32 + 16;
RCT2_GLOBAL(0x009DEA62, uint32) = mapElement->base_height * 8;
@@ -544,7 +600,7 @@ money32 map_try_clear_scenery(int x, int y, rct_map_element *mapElement, int fla
x *= 32;
y *= 32;
- if (!(flags & 0x40) && RCT2_GLOBAL(0x009DEA6E, uint8) != 0) {
+ if (!(flags & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED;
return MONEY32_UNDEFINED;
}
@@ -618,9 +674,9 @@ money32 map_clear_scenery_from_tile(int x, int y, int flags)
totalCost = 0;
restart_from_beginning:
- mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x);
+ mapElement = map_get_first_element_at(x, y);
do {
- type = mapElement->type & MAP_ELEMENT_TYPE_MASK;
+ type = map_element_get_type(mapElement);
switch (type) {
case MAP_ELEMENT_TYPE_PATH:
#ifdef CLEAR_SCENERY_REMOVES_PATHS
@@ -654,7 +710,7 @@ restart_from_beginning:
break;
}
- } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
+ } while (!map_element_is_last_for_tile(mapElement++));
return totalCost;
}
@@ -664,7 +720,7 @@ money32 map_clear_scenery(int x0, int y0, int x1, int y1, int flags)
int x, y, z;
money32 totalCost, cost;
- RCT2_GLOBAL(0x0141F56C, uint8) = 12;
+ RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4;
x = (x0 + x1) / 2 + 16;
y = (y0 + y1) / 2 + 16;
@@ -726,7 +782,7 @@ money32 map_change_surface_style(int x0, int y0, int x1, int y1, uint8 surface_s
money32 cur_cost = 0;
- if (RCT2_GLOBAL(0x9DEA6E, uint8) != 0){
+ if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0){
cur_cost += RCT2_GLOBAL(0x9E32B4, uint32);
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){
@@ -878,36 +934,30 @@ void sub_6A6AA7(int x, int y, rct_map_element *mapElement)
*/
void map_remove_all_rides()
{
- int x, y;
- rct_map_element *mapElement;
+ map_element_iterator it;
- for (y = 0; y < 256; y++) {
- for (x = 0; x < 256; x++) {
- repeat_tile:
- mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x);
+ map_element_iterator_begin(&it);
+ do {
+ switch (map_element_get_type(it.element)) {
+ case MAP_ELEMENT_TYPE_PATH:
+ if (it.element->type & 1) {
+ it.element->properties.path.type &= ~8;
+ it.element->properties.path.addition_status = 255;
+ }
+ break;
+ case MAP_ELEMENT_TYPE_ENTRANCE:
+ if (it.element->properties.entrance.type == ENTRANCE_TYPE_PARK_ENTRANCE)
+ break;
- do {
- switch (mapElement->type & MAP_ELEMENT_TYPE_MASK) {
- case MAP_ELEMENT_TYPE_PATH:
- if (mapElement->type & 1) {
- mapElement->properties.path.type &= ~8;
- mapElement->properties.path.addition_status = 255;
- }
- break;
- case MAP_ELEMENT_TYPE_ENTRANCE:
- if (mapElement->properties.entrance.type == ENTRANCE_TYPE_PARK_ENTRANCE)
- break;
-
- // fall-through
- case MAP_ELEMENT_TYPE_TRACK:
- RCT2_CALLPROC_EBPSAFE(0x006A7594);
- sub_6A6AA7(x * 32, y * 32, mapElement);
- map_element_remove(mapElement);
- goto repeat_tile;
- }
- } while (!((mapElement++)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
+ // fall-through
+ case MAP_ELEMENT_TYPE_TRACK:
+ RCT2_CALLPROC_EBPSAFE(0x006A7594);
+ sub_6A6AA7(it.x * 32, it.y * 32, it.element);
+ map_element_remove(it.element);
+ map_element_iterator_restart_for_tile(&it);
+ break;
}
- }
+ } while (map_element_iterator_next(&it));
}
/**
diff --git a/src/world/map.h b/src/world/map.h
index d6bcab08de..eb83a32c6a 100644
--- a/src/world/map.h
+++ b/src/world/map.h
@@ -47,8 +47,8 @@ typedef struct {
typedef struct {
uint8 type; //4
uint8 age; //5
- uint8 colour; //6
- uint8 unused; //7
+ uint8 colour_1; //6
+ uint8 colour_2; //7
} rct_map_element_scenery_properties;
typedef struct {
@@ -193,6 +193,8 @@ enum {
#define MAP_ELEMENT_SLOPE_MASK 0x1F
#define MAP_ELEMENT_SLOPE_EDGE_STYLE_MASK 0xE0
+
+// Terrain
#define MAP_ELEMENT_WATER_HEIGHT_MASK 0x1F
#define MAP_ELEMENT_SURFACE_TERRAIN_MASK 0xE0
@@ -203,6 +205,13 @@ enum {
#define TILE_UNDEFINED_MAP_ELEMENT (rct_map_element*)-1
+typedef struct {
+ sint16 x, y;
+} rct_xy16;
+
+typedef struct {
+ sint16 x, y, z;
+} rct_xyz16;
typedef struct {
uint16 x;
@@ -211,16 +220,14 @@ typedef struct {
uint8 direction;
} rct2_peep_spawn;
-typedef struct {
- sint16 x;
- sint16 y;
-} rct_xy16;
-
extern const rct_xy16 TileDirectionDelta[];
extern rct_xy16 *gMapSelectionTiles;
-void map_init();
+void map_init(int size);
void map_update_tile_pointers();
+rct_map_element *map_get_first_element_at(int x, int y);
+int map_element_is_last_for_tile(rct_map_element *element);
+int map_element_get_type(rct_map_element *element);
int map_element_get_terrain(rct_map_element *element);
int map_element_get_terrain_edge(rct_map_element *element);
void map_element_set_terrain(rct_map_element *element, int terrain);
@@ -229,7 +236,7 @@ int map_height_from_slope(int x, int y, int slope);
rct_map_element *map_get_surface_element_at(int x, int y);
int map_element_height(int x, int y);
void sub_68B089();
-int map_coord_is_connected(uint16 coordinate, uint8 height, uint8 face_direction);
+int map_coord_is_connected(int x, int y, int z, uint8 faceDirection);
void map_invalidate_animations();
void sub_6A876D();
int map_is_location_owned(int x, int y, int z);
@@ -256,4 +263,14 @@ void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, i
#define GET_MAP_ELEMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, rct_map_element)[x]))
#define TILE_MAP_ELEMENT_POINTER(x) (RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[x])
+typedef struct {
+ int x;
+ int y;
+ rct_map_element *element;
+} map_element_iterator;
+
+void map_element_iterator_begin(map_element_iterator *it);
+int map_element_iterator_next(map_element_iterator *it);
+void map_element_iterator_restart_for_tile(map_element_iterator *it);
+
#endif
diff --git a/src/world/map_helpers.c b/src/world/map_helpers.c
new file mode 100644
index 0000000000..8e494a7b87
--- /dev/null
+++ b/src/world/map_helpers.c
@@ -0,0 +1,290 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#include "map.h"
+#include "map_helpers.h"
+
+/**
+ * Not perfect, this still leaves some particular tiles unsmoothed.
+ */
+int map_smooth(int l, int t, int r, int b)
+{
+ int i, x, y, highest, count, cornerHeights[4], doubleCorner, raisedLand = 0;
+ rct_map_element *mapElement, *mapElement2;
+ for (y = t; y < b; y++) {
+ for (x = l; x < r; x++) {
+ mapElement = map_get_surface_element_at(x, y);
+ mapElement->properties.surface.slope &= ~0x1F;
+
+ // Raise to edge height - 2
+ highest = mapElement->base_height;
+ highest = max(highest, map_get_surface_element_at(x - 1, y + 0)->base_height);
+ highest = max(highest, map_get_surface_element_at(x + 1, y + 0)->base_height);
+ highest = max(highest, map_get_surface_element_at(x + 0, y - 1)->base_height);
+ highest = max(highest, map_get_surface_element_at(x + 0, y + 1)->base_height);
+ if (mapElement->base_height < highest - 2) {
+ raisedLand = 1;
+ mapElement->base_height = mapElement->clearance_height = highest - 2;
+ }
+
+ // Check corners
+ doubleCorner = -1;
+ cornerHeights[0] = map_get_surface_element_at(x - 1, y - 1)->base_height;
+ cornerHeights[1] = map_get_surface_element_at(x + 1, y - 1)->base_height;
+ cornerHeights[2] = map_get_surface_element_at(x + 1, y + 1)->base_height;
+ cornerHeights[3] = map_get_surface_element_at(x - 1, y + 1)->base_height;
+ highest = mapElement->base_height;
+ for (i = 0; i < 4; i++)
+ highest = max(highest, cornerHeights[i]);
+
+ if (highest >= mapElement->base_height + 4) {
+ count = 0;
+ for (i = 0; i < 4; i++)
+ if (cornerHeights[i] == highest)
+ count++;
+
+ if (count == 1) {
+ if (mapElement->base_height < highest - 4) {
+ mapElement->base_height = mapElement->clearance_height = highest - 4;
+ raisedLand = 1;
+ }
+ if (cornerHeights[0] == highest && cornerHeights[2] <= cornerHeights[0] - 4)
+ doubleCorner = 0;
+ else if (cornerHeights[1] == highest && cornerHeights[3] <= cornerHeights[1] - 4)
+ doubleCorner = 1;
+ else if (cornerHeights[2] == highest && cornerHeights[0] <= cornerHeights[2] - 4)
+ doubleCorner = 2;
+ else if (cornerHeights[3] == highest && cornerHeights[1] <= cornerHeights[3] - 4)
+ doubleCorner = 3;
+ } else {
+ if (mapElement->base_height < highest - 2) {
+ mapElement->base_height = mapElement->clearance_height = highest - 2;
+ raisedLand = 1;
+ }
+ }
+ }
+
+ if (doubleCorner != -1) {
+ mapElement->properties.surface.slope |= 16;
+ switch (doubleCorner) {
+ case 0:
+ mapElement->properties.surface.slope |= 2 | 4 | 8;
+ break;
+ case 1:
+ mapElement->properties.surface.slope |= 1 | 2 | 4;
+ break;
+ case 2:
+ mapElement->properties.surface.slope |= 1 | 2 | 8;
+ break;
+ case 3:
+ mapElement->properties.surface.slope |= 1 | 4 | 8;
+ break;
+ }
+ } else {
+ // Corners
+ mapElement2 = map_get_surface_element_at(x + 1, y + 1);
+ if (mapElement2->base_height > mapElement->base_height)
+ mapElement->properties.surface.slope |= 1;
+
+ mapElement2 = map_get_surface_element_at(x - 1, y + 1);
+ if (mapElement2->base_height > mapElement->base_height)
+ mapElement->properties.surface.slope |= 8;
+
+ mapElement2 = map_get_surface_element_at(x + 1, y - 1);
+ if (mapElement2->base_height > mapElement->base_height)
+ mapElement->properties.surface.slope |= 2;
+
+ mapElement2 = map_get_surface_element_at(x - 1, y - 1);
+ if (mapElement2->base_height > mapElement->base_height)
+ mapElement->properties.surface.slope |= 4;
+
+ // Sides
+ mapElement2 = map_get_surface_element_at(x + 1, y + 0);
+ if (mapElement2->base_height > mapElement->base_height)
+ mapElement->properties.surface.slope |= 1 | 2;
+
+ mapElement2 = map_get_surface_element_at(x - 1, y + 0);
+ if (mapElement2->base_height > mapElement->base_height)
+ mapElement->properties.surface.slope |= 4 | 8;
+
+ mapElement2 = map_get_surface_element_at(x + 0, y - 1);
+ if (mapElement2->base_height > mapElement->base_height)
+ mapElement->properties.surface.slope |= 2 | 4;
+
+ mapElement2 = map_get_surface_element_at(x + 0, y + 1);
+ if (mapElement2->base_height > mapElement->base_height)
+ mapElement->properties.surface.slope |= 1 | 8;
+
+ // Raise
+ if (mapElement->properties.surface.slope == (1 | 2 | 4 | 8)) {
+ mapElement->properties.surface.slope &= ~0x1F;
+ mapElement->base_height = mapElement->clearance_height += 2;
+ }
+ }
+ }
+ }
+
+ return raisedLand;
+}
+
+int map_get_corner_height(int x, int y, int corner)
+{
+ rct_map_element *mapElement = map_get_surface_element_at(x, y);
+ int baseHeight = mapElement->base_height;
+ int slope = mapElement->properties.surface.slope;
+ int doubleCorner = slope & 16;
+ if (doubleCorner) {
+ if (!(slope & 1)) doubleCorner = 4;
+ else if (!(slope & 2)) doubleCorner = 8;
+ else if (!(slope & 4)) doubleCorner = 1;
+ else if (!(slope & 8)) doubleCorner = 2;
+ }
+
+ switch (corner) {
+ case 0:
+ return baseHeight + (slope & 1 ? (doubleCorner == 1 ? 4 : 2) : 0);
+ case 1:
+ return baseHeight + (slope & 8 ? (doubleCorner == 8 ? 4 : 2) : 0);
+ case 2:
+ return baseHeight + (slope & 2 ? (doubleCorner == 2 ? 4 : 2) : 0);
+ case 3:
+ return baseHeight + (slope & 4 ? (doubleCorner == 4 ? 4 : 2) : 0);
+ default:
+ return baseHeight;
+ }
+}
+
+/**
+ * There are non-smoothed tiles with this version, but diagonal land blocks end up being wavy.
+ */
+int map_smooth_wavy(int l, int t, int r, int b)
+{
+ int i, x, y, highest, count, cornerHeights[4], doubleCorner, raisedLand = 0;
+ rct_map_element *mapElement;
+ for (y = t; y < b; y++) {
+ for (x = l; x < r; x++) {
+ mapElement = map_get_surface_element_at(x, y);
+ mapElement->properties.surface.slope &= ~0x1F;
+
+ // Raise to edge height - 2
+ highest = mapElement->base_height;
+ highest = max(highest, map_get_surface_element_at(x - 1, y + 0)->base_height);
+ highest = max(highest, map_get_surface_element_at(x + 1, y + 0)->base_height);
+ highest = max(highest, map_get_surface_element_at(x + 0, y - 1)->base_height);
+ highest = max(highest, map_get_surface_element_at(x + 0, y + 1)->base_height);
+ if (mapElement->base_height < highest - 2) {
+ raisedLand = 1;
+ mapElement->base_height = mapElement->clearance_height = highest - 2;
+ }
+
+ // Check corners
+ doubleCorner = -1;
+ cornerHeights[0] = max(map_get_corner_height(x - 1, y - 1, 0), max(map_get_corner_height(x + 1, y + 0, 1), map_get_corner_height(x + 0, y + 1, 2)));
+ cornerHeights[1] = max(map_get_corner_height(x + 1, y - 1, 1), max(map_get_corner_height(x - 1, y + 0, 0), map_get_corner_height(x + 0, y + 1, 3)));
+ cornerHeights[2] = max(map_get_corner_height(x + 1, y + 1, 3), max(map_get_corner_height(x + 1, y + 0, 3), map_get_corner_height(x + 0, y - 1, 0)));
+ cornerHeights[3] = max(map_get_corner_height(x - 1, y + 1, 2), max(map_get_corner_height(x - 1, y + 0, 2), map_get_corner_height(x + 0, y - 1, 1)));
+ highest = mapElement->base_height;
+ for (i = 0; i < 4; i++)
+ highest = max(highest, cornerHeights[i]);
+
+ if (highest >= mapElement->base_height + 4) {
+ count = 0;
+ for (i = 0; i < 4; i++)
+ if (cornerHeights[i] == highest)
+ count++;
+
+ if (count == 1) {
+ if (mapElement->base_height < highest - 4) {
+ mapElement->base_height = mapElement->clearance_height = highest - 4;
+ raisedLand = 1;
+ }
+ if (cornerHeights[0] == highest && cornerHeights[2] <= cornerHeights[0] - 4)
+ doubleCorner = 0;
+ else if (cornerHeights[1] == highest && cornerHeights[3] <= cornerHeights[1] - 4)
+ doubleCorner = 1;
+ else if (cornerHeights[2] == highest && cornerHeights[0] <= cornerHeights[2] - 4)
+ doubleCorner = 2;
+ else if (cornerHeights[3] == highest && cornerHeights[1] <= cornerHeights[3] - 4)
+ doubleCorner = 3;
+ } else {
+ if (mapElement->base_height < highest - 2) {
+ mapElement->base_height = mapElement->clearance_height = highest - 2;
+ raisedLand = 1;
+ }
+ }
+ }
+
+ if (doubleCorner != -1) {
+ mapElement->properties.surface.slope |= 16;
+ switch (doubleCorner) {
+ case 0:
+ mapElement->properties.surface.slope |= 2 | 4 | 8;
+ break;
+ case 1:
+ mapElement->properties.surface.slope |= 1 | 2 | 4;
+ break;
+ case 2:
+ mapElement->properties.surface.slope |= 1 | 2 | 8;
+ break;
+ case 3:
+ mapElement->properties.surface.slope |= 1 | 4 | 8;
+ break;
+ }
+ } else {
+ // Corners
+ if (
+ map_get_corner_height(x + 1, y + 1, 3) > mapElement->base_height ||
+ map_get_corner_height(x + 1, y + 0, 1) > mapElement->base_height ||
+ map_get_corner_height(x + 0, y + 1, 2) > mapElement->base_height
+ )
+ mapElement->properties.surface.slope |= 1;
+
+ if (
+ map_get_corner_height(x - 1, y + 1, 2) > mapElement->base_height ||
+ map_get_corner_height(x - 1, y + 0, 0) > mapElement->base_height ||
+ map_get_corner_height(x + 0, y + 1, 3) > mapElement->base_height
+ )
+ mapElement->properties.surface.slope |= 8;
+
+ if (
+ map_get_corner_height(x + 1, y - 1, 1) > mapElement->base_height ||
+ map_get_corner_height(x + 1, y + 0, 3) > mapElement->base_height ||
+ map_get_corner_height(x + 0, y - 1, 0) > mapElement->base_height
+ )
+ mapElement->properties.surface.slope |= 2;
+
+ if (
+ map_get_corner_height(x - 1, y - 1, 0) > mapElement->base_height ||
+ map_get_corner_height(x - 1, y + 0, 2) > mapElement->base_height ||
+ map_get_corner_height(x + 0, y - 1, 1) > mapElement->base_height
+ )
+ mapElement->properties.surface.slope |= 4;
+
+ // Raise
+ if (mapElement->properties.surface.slope == (1 | 2 | 4 | 8)) {
+ mapElement->properties.surface.slope &= ~0x1F;
+ mapElement->base_height = mapElement->clearance_height += 2;
+ }
+ }
+ }
+ }
+
+ return raisedLand;
+}
\ No newline at end of file
diff --git a/src/world/map_helpers.h b/src/world/map_helpers.h
new file mode 100644
index 0000000000..423bb4c25e
--- /dev/null
+++ b/src/world/map_helpers.h
@@ -0,0 +1,26 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#ifndef _MAP_HELPERS_H_
+#define _MAP_HELPERS_H_
+
+int map_smooth(int l, int t, int r, int b);
+
+#endif
\ No newline at end of file
diff --git a/src/world/mapgen.c b/src/world/mapgen.c
new file mode 100644
index 0000000000..558cd0837c
--- /dev/null
+++ b/src/world/mapgen.c
@@ -0,0 +1,778 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#ifndef _USE_MATH_DEFINES
+ #define _USE_MATH_DEFINES
+#endif
+#include
+#include "../addresses.h"
+#include "../object.h"
+#include "map.h"
+#include "map_helpers.h"
+#include "mapgen.h"
+#include "scenery.h"
+
+#pragma region Random objects
+
+const char *GrassTrees[] = {
+ // Dark
+ "TCF ", // Caucasian Fir Tree
+ "TRF ", // Red Fir Tree
+ "TRF2 ", // Red Fir Tree
+ "TSP ", // Scots Pine Tree
+ "TMZP ", // Montezuma Pine Tree
+ "TAP ", // Aleppo Pine Tree
+ "TCRP ", // Corsican Pine Tree
+ "TBP ", // Black Poplar Tree
+
+ // Light
+ "TCL ", // Cedar of Lebanon Tree
+ "TEL ", // European Larch Tree
+};
+
+// Trees to be placed in proximity to water
+const char *GrassWaterTrees[] = {
+ "TWW " // Weeping Willow Tree
+};
+
+const char *DesertTrees[] = {
+ "TMP ", // Monkey-Puzzle Tree
+ "THL ", // Honey Locust Tree
+ "TH1 ", // Canary Palm Tree
+ "TH2 ", // Palm Tree
+ "TPM ", // Palm Tree
+ "TROPT1 ", // Tree
+ "TBC ", // Cactus
+ "TSC ", // Cactus
+};
+
+const char *SnowTrees[] = {
+ "TCFS ", // Snow-covered Caucasian Fir Tree
+ "TNSS ", // Snow-covered Norway Spruce Tree
+ "TRF3 ", // Snow-covered Red Fir Tree
+ "TRFS ", // Snow-covered Red Fir Tree
+};
+
+#pragma endregion
+
+// Randomly chosen base terrains. We rarely want a whole map made out of chequerboard or rock.
+const uint8 BaseTerrain[] = { TERRAIN_GRASS, TERRAIN_SAND, TERRAIN_SAND_LIGHT, TERRAIN_DIRT, TERRAIN_ICE };
+
+#define BLOB_HEIGHT 255
+
+static void mapgen_place_trees();
+static void mapgen_set_water_level(int height);
+static void mapgen_blobs(int count, int lowSize, int highSize, int lowHeight, int highHeight);
+static void mapgen_blob(int cx, int cy, int size, int height);
+static void mapgen_smooth_height(int iterations);
+static void mapgen_set_height();
+
+static void mapgen_simplex();
+
+static int _heightSize;
+static uint8 *_height;
+
+static int get_height(int x, int y)
+{
+ if (x >= 0 && y >= 0 && x < _heightSize && y < _heightSize)
+ return _height[x + y * _heightSize];
+ else
+ return 0;
+}
+
+static void set_height(int x, int y, int height)
+{
+ if (x >= 0 && y >= 0 && x < _heightSize && y < _heightSize)
+ _height[x + y * _heightSize] = height;
+}
+
+void mapgen_generate_blank(mapgen_settings *settings)
+{
+ int x, y;
+ rct_map_element *mapElement;
+
+ map_init(settings->mapSize);
+ for (y = 1; y < settings->mapSize - 1; y++) {
+ for (x = 1; x < settings->mapSize - 1; x++) {
+ mapElement = map_get_surface_element_at(x, y);
+ map_element_set_terrain(mapElement, settings->floor);
+ map_element_set_terrain_edge(mapElement, settings->wall);
+ mapElement->base_height = settings->height;
+ mapElement->clearance_height = settings->height;
+ }
+ }
+
+ mapgen_set_water_level(settings->waterLevel);
+}
+
+void mapgen_generate(mapgen_settings *settings)
+{
+ int x, y, mapSize, floorTexture, wallTexture;
+ rct_map_element *mapElement;
+
+ srand((unsigned int)time(NULL));
+
+ mapSize = settings->mapSize;
+ floorTexture = settings->floor;
+ wallTexture = settings->wall;
+
+ if (floorTexture == -1)
+ floorTexture = BaseTerrain[rand() % countof(BaseTerrain)];
+
+ if (wallTexture == -1) {
+ // Base edge type on surface type
+ switch (floorTexture) {
+ case TERRAIN_DIRT:
+ wallTexture = TERRAIN_EDGE_WOOD_RED;
+ break;
+ case TERRAIN_ICE:
+ wallTexture = TERRAIN_EDGE_ICE;
+ break;
+ default:
+ wallTexture = TERRAIN_EDGE_ROCK;
+ break;
+ }
+ }
+
+ // Initialise the base map
+ map_init(mapSize);
+ for (y = 1; y < mapSize - 1; y++) {
+ for (x = 1; x < mapSize - 1; x++) {
+ mapElement = map_get_surface_element_at(x, y);
+ map_element_set_terrain(mapElement, floorTexture);
+ map_element_set_terrain_edge(mapElement, wallTexture);
+ mapElement->base_height = settings->height;
+ mapElement->clearance_height = settings->height;
+ }
+ }
+
+ // Create the temporary height map and initialise
+ _heightSize = mapSize * 2;
+ _height = (uint8*)malloc(_heightSize * _heightSize * sizeof(uint8));
+ memset(_height, 0, _heightSize * _heightSize * sizeof(uint8));
+
+ if (1) {
+ mapgen_simplex();
+ mapgen_smooth_height(2 + (rand() % 6));
+ } else {
+ // Keep overwriting the map with rough cicular blobs of different sizes and heights.
+ // This procedural method can produce intersecting contour like land and lakes.
+ // Large blobs, general shape of map
+ mapgen_blobs(6, _heightSize / 2, _heightSize * 4, 4, 16);
+ // Medium blobs
+ mapgen_blobs(12, _heightSize / 16, _heightSize / 8, 4, 18);
+ // Small blobs, small hills and lakes
+ mapgen_blobs(32, _heightSize / 32, _heightSize / 16, 4, 18);
+
+ // Smooth the land so that their aren't cliffs round every blob.
+ mapgen_smooth_height(2);
+ }
+
+ // Set the game map to the height map
+ mapgen_set_height();
+ free(_height);
+
+ // Set the tile slopes so that their are no cliffs
+ while (map_smooth(1, 1, mapSize - 1, mapSize - 1)) { }
+
+ // Add the water
+ int waterLevel = 6 + (rand() % 8) * 2;
+ mapgen_set_water_level(waterLevel);
+
+ // Add sandy beaches
+ int beachTexture = floorTexture;
+ if (settings->floor == -1 && floorTexture == TERRAIN_GRASS) {
+ switch (rand() % 4) {
+ case 0:
+ beachTexture = TERRAIN_SAND;
+ break;
+ case 1:
+ beachTexture = TERRAIN_SAND_LIGHT;
+ break;
+ }
+ }
+ for (y = 1; y < mapSize - 1; y++) {
+ for (x = 1; x < mapSize - 1; x++) {
+ mapElement = map_get_surface_element_at(x, y);
+
+ if (mapElement->base_height < waterLevel + 6)
+ map_element_set_terrain(mapElement, beachTexture);
+ }
+ }
+
+ // Place the trees
+ if (settings->trees != 0)
+ mapgen_place_trees();
+
+ map_reorganise_elements();
+}
+
+static void mapgen_place_tree(int type, int x, int y)
+{
+ int surfaceZ;
+ rct_map_element *mapElement;
+ rct_scenery_entry *sceneryEntry = g_smallSceneryEntries[type];
+
+ surfaceZ = map_element_height(x * 32 + 16, y * 32 + 16) / 8;
+ mapElement = map_element_insert(x, y, surfaceZ, (1 | 2 | 4 | 8));
+ mapElement->clearance_height = surfaceZ + (sceneryEntry->small_scenery.height >> 3);
+
+ mapElement->type = MAP_ELEMENT_TYPE_SCENERY | (rand() % 3);
+ mapElement->properties.scenery.type = type;
+ mapElement->properties.scenery.age = 0;
+ mapElement->properties.scenery.colour_1 = 26;
+ mapElement->properties.scenery.colour_1 = 18;
+}
+
+/**
+ * Randomly places a selection of preset trees on the map. Picks the right tree for the terrain it is placing it on.
+ */
+static void mapgen_place_trees()
+{
+ int x, y, mapSize, i, j, rindex, type;
+ rct_map_element *mapElement;
+
+ int numGrassTreeIds = 0, numDesertTreeIds = 0, numSnowTreeIds = 0;
+ int *grassTreeIds = (int*)malloc(countof(GrassTrees) * sizeof(int));
+ int *desertTreeIds = (int*)malloc(countof(DesertTrees) * sizeof(int));
+ int *snowTreeIds = (int*)malloc(countof(SnowTrees) * sizeof(int));
+
+ for (i = 0; i < object_entry_group_counts[OBJECT_TYPE_SMALL_SCENERY]; i++) {
+ rct_scenery_entry *sceneryEntry = g_smallSceneryEntries[i];
+ rct_object_entry_extended *entry = &object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].entries[i];
+
+ if (sceneryEntry == (rct_scenery_entry*)0xFFFFFFFF || sceneryEntry == NULL)
+ continue;
+
+ for (j = 0; j < countof(GrassTrees); j++)
+ if (strncmp(GrassTrees[j], entry->name, 8) == 0)
+ break;
+ if (j != countof(GrassTrees)) {
+ grassTreeIds[numGrassTreeIds++] = i;
+ continue;
+ }
+
+ for (j = 0; j < countof(DesertTrees); j++)
+ if (strncmp(DesertTrees[j], entry->name, 8) == 0)
+ break;
+ if (j != countof(DesertTrees)) {
+ desertTreeIds[numDesertTreeIds++] = i;
+ continue;
+ }
+
+ for (j = 0; j < countof(SnowTrees); j++)
+ if (strncmp(SnowTrees[j], entry->name, 8) == 0)
+ break;
+ if (j != countof(SnowTrees)) {
+ snowTreeIds[numSnowTreeIds++] = i;
+ continue;
+ }
+ }
+
+ mapSize = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, sint16);
+
+ int availablePositionsCount = 0;
+ struct { int x; int y; } tmp, *pos, *availablePositions;
+ availablePositions = malloc(256 * 256 * sizeof(tmp));
+
+ // Create list of available tiles
+ for (y = 1; y < mapSize - 1; y++) {
+ for (x = 1; x < mapSize - 1; x++) {
+ mapElement = map_get_surface_element_at(x, y);
+
+ // Exclude water tiles
+ if ((mapElement->properties.surface.terrain & 0x1F) != 0)
+ continue;
+
+ pos = &availablePositions[availablePositionsCount++];
+ pos->x = x;
+ pos->y = y;
+ }
+ }
+
+ // Shuffle list
+ for (i = 0; i < availablePositionsCount; i++) {
+ rindex = rand() % availablePositionsCount;
+ if (rindex == i)
+ continue;
+
+ tmp = availablePositions[i];
+ availablePositions[i] = availablePositions[rindex];
+ availablePositions[rindex] = tmp;
+ }
+
+ // Place trees
+ float treeToLandRatio = (10 + (rand() % 30)) / 100.0f;
+ int numTrees = max(4, (int)(availablePositionsCount * treeToLandRatio));
+
+ mapSize = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, sint16);
+ for (i = 0; i < numTrees; i++) {
+ pos = &availablePositions[i];
+
+ type = -1;
+ mapElement = map_get_surface_element_at(pos->x, pos->y);
+ switch (map_element_get_terrain(mapElement)) {
+ case TERRAIN_GRASS:
+ case TERRAIN_DIRT:
+ case TERRAIN_GRASS_CLUMPS:
+ if (numGrassTreeIds == 0)
+ break;
+
+ type = grassTreeIds[rand() % numGrassTreeIds];
+ break;
+
+ case TERRAIN_SAND:
+ case TERRAIN_SAND_DARK:
+ case TERRAIN_SAND_LIGHT:
+ if (numDesertTreeIds == 0)
+ break;
+
+ if (rand() % 4 == 0)
+ type = desertTreeIds[rand() % numDesertTreeIds];
+ break;
+
+ case TERRAIN_ICE:
+ if (numSnowTreeIds == 0)
+ break;
+
+ type = snowTreeIds[rand() % numSnowTreeIds];
+ break;
+ }
+
+ if (type != -1)
+ mapgen_place_tree(type, pos->x, pos->y);
+ }
+
+ free(availablePositions);
+ free(grassTreeIds);
+ free(desertTreeIds);
+ free(snowTreeIds);
+}
+
+/**
+ * Sets each tile's water level to the specified water level if underneath that water level.
+ */
+static void mapgen_set_water_level(int waterLevel)
+{
+ int x, y, mapSize;
+ rct_map_element *mapElement;
+
+ mapSize = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, sint16);
+
+ for (y = 1; y < mapSize - 1; y++) {
+ for (x = 1; x < mapSize - 1; x++) {
+ mapElement = map_get_surface_element_at(x, y);
+ if (mapElement->base_height < waterLevel)
+ mapElement->properties.surface.terrain |= (waterLevel / 2);
+ }
+ }
+}
+
+static void mapgen_blobs(int count, int lowSize, int highSize, int lowHeight, int highHeight)
+{
+ int i;
+ int sizeRange = highSize - lowSize;
+ int heightRange = highHeight - lowHeight;
+
+ int border = 2 + (rand() % 24);
+ int borderRange = _heightSize - (border * 2);
+ for (i = 0; i < count; i++) {
+ int radius = lowSize + (rand() % sizeRange);
+ mapgen_blob(
+ border + (rand() % borderRange),
+ border + (rand() % borderRange),
+ (int)(M_PI * radius * radius),
+ lowHeight + (rand() % heightRange)
+ );
+ }
+}
+
+/**
+ * Sets any holes within a new created blob to the specified height.
+ */
+static void mapgen_blob_fill(int height)
+{
+ // For each square find out whether it is landlocked by BLOB_HEIGHT and then fill it if it is
+ int left = 0,
+ top = 0,
+ right = _heightSize - 1,
+ bottom = _heightSize - 1;
+
+ uint8 *landX = (uint8*)malloc(_heightSize * _heightSize * sizeof(uint8));
+ int firstLand, lastLand;
+
+ // Check each row and see if each tile is between first land x and last land x
+ for (int y = top; y <= bottom; y++) {
+ // Calculate first land
+ firstLand = -1;
+ for (int xx = left; xx <= right; xx++) {
+ if (get_height(xx, y) == BLOB_HEIGHT) {
+ firstLand = xx;
+ break;
+ }
+ }
+
+ lastLand = -1;
+ if (firstLand >= 0) {
+ // Calculate last land
+ for (int xx = right; xx >= left; xx--) {
+ if (get_height(xx, y) == BLOB_HEIGHT) {
+ lastLand = xx;
+ break;
+ }
+ }
+ } else {
+ // No land on this row
+ continue;
+ }
+
+ for (int x = left; x <= right; x++)
+ if (x >= firstLand && x <= lastLand)
+ landX[x, y] = 1;
+ }
+
+ // Do the same for Y
+ for (int x = left; x <= right; x++) {
+ // Calculate first land
+ firstLand = -1;
+ for (int yy = top; yy <= bottom; yy++) {
+ if (get_height(x, yy) == BLOB_HEIGHT) {
+ firstLand = yy;
+ break;
+ }
+ }
+
+ lastLand = -1;
+ if (firstLand >= 0) {
+ // Calculate last land
+ for (int yy = bottom; yy >= top; yy--) {
+ if (get_height(x, yy) == BLOB_HEIGHT) {
+ lastLand = yy;
+ break;
+ }
+ }
+ } else {
+ // No land on this row
+ continue;
+ }
+
+ for (int y = top; y <= bottom; y++) {
+ if (y >= firstLand && y <= lastLand && landX[x, y]) {
+ // Not only do we know its landlocked to both x and y
+ // we can change the land too
+ set_height(x, y, BLOB_HEIGHT);
+ }
+ }
+ }
+
+ // Replace all the BLOB_HEIGHT with the actual land height
+ for (int x = left; x <= right; x++)
+ for (int y = top; y <= bottom; y++)
+ if (get_height(x, y) == BLOB_HEIGHT)
+ set_height(x, y, height);
+
+ free(landX);
+}
+
+/**
+ * Sets a rough circular blob of tiles of the specified size to the specified height.
+ */
+static void mapgen_blob(int cx, int cy, int size, int height)
+{
+ int x, y, currentSize, direction;
+
+ x = cx;
+ y = cy;
+ currentSize = 1;
+ direction = 0;
+ set_height(x, y, BLOB_HEIGHT);
+
+ while (currentSize < size) {
+ if (rand() % 2 == 0) {
+ set_height(x, y, BLOB_HEIGHT);
+ currentSize++;
+ }
+
+ switch (direction) {
+ case 0:
+ if (y == 0) {
+ currentSize = size;
+ break;
+ }
+
+ y--;
+ if (get_height(x + 1, y) != BLOB_HEIGHT)
+ direction = 1;
+ else if (get_height(x, y - 1) != BLOB_HEIGHT)
+ direction = 0;
+ else if (get_height(x - 1, y) != BLOB_HEIGHT)
+ direction = 3;
+ break;
+ case 1:
+ if (x == _heightSize - 1) {
+ currentSize = size;
+ break;
+ }
+
+ x++;
+ if (get_height(x, y + 1) != BLOB_HEIGHT)
+ direction = 2;
+ else if (get_height(x + 1, y) != BLOB_HEIGHT)
+ direction = 1;
+ else if (get_height(x, y - 1) != BLOB_HEIGHT)
+ direction = 0;
+ break;
+ case 2:
+ if (y == _heightSize - 1) {
+ currentSize = size;
+ break;
+ }
+
+ y++;
+ if (get_height(x - 1, y) != BLOB_HEIGHT)
+ direction = 3;
+ else if (get_height(x, y + 1) != BLOB_HEIGHT)
+ direction = 2;
+ else if (get_height(x + 1, y) != BLOB_HEIGHT)
+ direction = 1;
+ break;
+ case 3:
+ if (x == 0) {
+ currentSize = size;
+ break;
+ }
+
+ x--;
+ if (get_height(x, y - 1) != BLOB_HEIGHT)
+ direction = 0;
+ else if (get_height(x - 1, y) != BLOB_HEIGHT)
+ direction = 3;
+ else if (get_height(x, y + 1) != BLOB_HEIGHT)
+ direction = 2;
+ break;
+ }
+ }
+
+ mapgen_blob_fill(height);
+}
+
+/**
+ * Smooths the height map.
+ */
+static void mapgen_smooth_height(int iterations)
+{
+ int i, x, y, xx, yy, avg;
+ int arraySize = _heightSize * _heightSize * sizeof(uint8);
+ uint8 *copyHeight = malloc(arraySize);
+
+ for (i = 0; i < iterations; i++) {
+ memcpy(copyHeight, _height, arraySize);
+ for (y = 1; y < _heightSize - 1; y++) {
+ for (x = 1; x < _heightSize - 1; x++) {
+ avg = 0;
+ for (yy = -1; yy <= 1; yy++)
+ for (xx = -1; xx <= 1; xx++)
+ avg += copyHeight[(y + yy) * _heightSize + (x + xx)];
+ avg /= 9;
+ set_height(x, y, avg);
+ }
+ }
+ }
+
+ free(copyHeight);
+}
+
+/**
+ * Sets the height of the actual game map tiles to the height map.
+ */
+static void mapgen_set_height()
+{
+ int x, y, heightX, heightY, mapSize;
+ rct_map_element *mapElement;
+
+ mapSize = _heightSize / 2;
+ for (y = 1; y < mapSize - 1; y++) {
+ for (x = 1; x < mapSize - 1; x++) {
+ heightX = x * 2;
+ heightY = y * 2;
+
+ uint8 q00 = get_height(heightX + 0, heightY + 0);
+ uint8 q01 = get_height(heightX + 0, heightY + 1);
+ uint8 q10 = get_height(heightX + 1, heightY + 0);
+ uint8 q11 = get_height(heightX + 1, heightY + 1);
+
+ uint8 baseHeight = (q00 + q01 + q10 + q11) / 4;
+
+ mapElement = map_get_surface_element_at(x, y);
+ mapElement->base_height = max(2, baseHeight * 2);
+ mapElement->clearance_height = mapElement->base_height;
+
+ if (q00 > baseHeight)
+ mapElement->properties.surface.slope |= 4;
+ if (q01 > baseHeight)
+ mapElement->properties.surface.slope |= 8;
+ if (q10 > baseHeight)
+ mapElement->properties.surface.slope |= 2;
+ if (q11 > baseHeight)
+ mapElement->properties.surface.slope |= 1;
+ }
+ }
+}
+
+#pragma region Noise
+
+/**
+ * Simplex Noise Algorithm with Fractional Brownian Motion
+ * Based on:
+ * - https://code.google.com/p/simplexnoise/
+ * - https://code.google.com/p/fractalterraingeneration/wiki/Fractional_Brownian_Motion
+ */
+
+static float generate(float x, float y);
+static int fast_floor(float x);
+static float grad(int hash, float x, float y);
+
+static uint8 perm[512];
+
+static void noise_rand()
+{
+ for (int i = 0; i < countof(perm); i++)
+ perm[i] = rand() & 0xFF;
+}
+
+static float fractal_noise(int x, int y, float frequency, int octaves, float lacunarity, float persistence)
+{
+ float total = 0.0f;
+ float amplitude = persistence;
+ for (int i = 0; i < octaves; i++) {
+ total += generate(x * frequency, y * frequency) * amplitude;
+ frequency *= lacunarity;
+ amplitude *= persistence;
+ }
+ return total;
+}
+
+static float generate(float x, float y)
+{
+ const float F2 = 0.366025403f; // F2 = 0.5*(sqrt(3.0)-1.0)
+ const float G2 = 0.211324865f; // G2 = (3.0-Math.sqrt(3.0))/6.0
+
+ float n0, n1, n2; // Noise contributions from the three corners
+
+ // Skew the input space to determine which simplex cell we're in
+ float s = (x + y) * F2; // Hairy factor for 2D
+ float xs = x + s;
+ float ys = y + s;
+ int i = fast_floor(xs);
+ int j = fast_floor(ys);
+
+ float t = (float)(i + j) * G2;
+ float X0 = i - t; // Unskew the cell origin back to (x,y) space
+ float Y0 = j - t;
+ float x0 = x - X0; // The x,y distances from the cell origin
+ float y0 = y - Y0;
+
+ // For the 2D case, the simplex shape is an equilateral triangle.
+ // Determine which simplex we are in.
+ int i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
+ if (x0 > y0) { i1 = 1; j1 = 0; } // lower triangle, XY order: (0,0)->(1,0)->(1,1)
+ else { i1 = 0; j1 = 1; } // upper triangle, YX order: (0,0)->(0,1)->(1,1)
+
+ // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
+ // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
+ // c = (3-sqrt(3))/6
+
+ float x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
+ float y1 = y0 - j1 + G2;
+ float x2 = x0 - 1.0f + 2.0f * G2; // Offsets for last corner in (x,y) unskewed coords
+ float y2 = y0 - 1.0f + 2.0f * G2;
+
+ // Wrap the integer indices at 256, to avoid indexing perm[] out of bounds
+ int ii = i % 256;
+ int jj = j % 256;
+
+ // Calculate the contribution from the three corners
+ float t0 = 0.5f - x0 * x0 - y0 * y0;
+ if (t0 < 0.0f) n0 = 0.0f;
+ else {
+ t0 *= t0;
+ n0 = t0 * t0 * grad(perm[ii + perm[jj]], x0, y0);
+ }
+
+ float t1 = 0.5f - x1 * x1 - y1 * y1;
+ if (t1 < 0.0f) n1 = 0.0f;
+ else {
+ t1 *= t1;
+ n1 = t1 * t1 * grad(perm[ii + i1 + perm[jj + j1]], x1, y1);
+ }
+
+ float t2 = 0.5f - x2 * x2 - y2 * y2;
+ if (t2 < 0.0f) n2 = 0.0f;
+ else {
+ t2 *= t2;
+ n2 = t2 * t2 * grad(perm[ii + 1 + perm[jj + 1]], x2, y2);
+ }
+
+ // Add contributions from each corner to get the final noise value.
+ // The result is scaled to return values in the interval [-1,1].
+ return 40.0f * (n0 + n1 + n2); // TODO: The scale factor is preliminary!
+}
+
+static int fast_floor(float x)
+{
+ return (x > 0) ? ((int)x) : (((int)x) - 1);
+}
+
+static int mod(int x, int m)
+{
+ int a = x % m;
+ return a < 0 ? a + m : a;
+}
+
+static float grad(int hash, float x, float y)
+{
+ int h = hash & 7; // Convert low 3 bits of hash code
+ float u = h < 4 ? x : y; // into 8 simple gradient directions,
+ float v = h < 4 ? y : x; // and compute the dot product with (x,y).
+ return ((h & 1) != 0 ? -u : u) + ((h & 2) != 0 ? -2.0f * v : 2.0f * v);
+}
+
+static void mapgen_simplex()
+{
+ int x, y;
+
+ float freq = 1.75f * (1.0f / _heightSize);
+ int octaves = 6;
+
+ int low = rand() % 4;
+ int high = 12 + (rand() % (32 - 12));
+
+ noise_rand();
+ for (y = 0; y < _heightSize; y++) {
+ for (x = 0; x < _heightSize; x++) {
+ float noiseValue = clamp(-1.0f, fractal_noise(x, y, freq, octaves, 2.0f, 0.65f), 1.0f);
+ float normalisedNoiseValue = (noiseValue + 1.0f) / 2.0f;
+
+ set_height(x, y, low + (int)(normalisedNoiseValue * high));
+ }
+ }
+}
+
+#pragma endregion
\ No newline at end of file
diff --git a/src/world/mapgen.h b/src/world/mapgen.h
new file mode 100644
index 0000000000..d6771a48cd
--- /dev/null
+++ b/src/world/mapgen.h
@@ -0,0 +1,39 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#ifndef _MAPGEN_H_
+#define _MAPGEN_H_
+
+typedef struct {
+ // Base
+ int mapSize;
+ int height;
+ int waterLevel;
+ int floor;
+ int wall;
+
+ // Features (e.g. tree, rivers, lakes etc.)
+ int trees;
+} mapgen_settings;
+
+void mapgen_generate_blank(mapgen_settings *settings);
+void mapgen_generate(mapgen_settings *settings);
+
+#endif
\ No newline at end of file
diff --git a/src/world/park.c b/src/world/park.c
index 4b1e8cde19..43d911d176 100644
--- a/src/world/park.c
+++ b/src/world/park.c
@@ -19,6 +19,7 @@
*****************************************************************************/
#include "../addresses.h"
+#include "../game.h"
#include "../interface/window.h"
#include "../localisation/localisation.h"
#include "../management/award.h"
@@ -60,7 +61,7 @@ void park_init()
int i;
RCT2_GLOBAL(0x013CA740, uint8) = 0;
- RCT2_GLOBAL(0x013573D4, uint16) = 777;
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, uint16) = 777;
RCT2_GLOBAL(RCT2_ADDRESS_HANDYMAN_COLOUR, uint8) = 28;
RCT2_GLOBAL(RCT2_ADDRESS_MECHANIC_COLOUR, uint8) = 28;
RCT2_GLOBAL(RCT2_ADDRESS_SECURITY_COLOUR, uint8) = 28;
@@ -74,7 +75,7 @@ void park_init()
RCT2_GLOBAL(RCT2_ADDRESS_LAST_RESEARCHED_ITEM_SUBJECT, sint32) = -1;
for (i = 0; i < 20; i++)
- RCT2_ADDRESS(0x01358102, uint8)[i] = 0;
+ gMarketingCampaignDaysLeft[i] = 0;
research_reset_items();
finance_init();
@@ -130,21 +131,18 @@ void park_reset_history()
*/
int park_calculate_size()
{
- int tiles, x, y;
- rct_map_element *mapElement;
+ int tiles;
+ map_element_iterator it;
tiles = 0;
- for (y = 0; y < 256; y++) {
- for (x = 0; x < 256; x++) {
- mapElement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[y * 256 + x];
- while (mapElement->type & MAP_ELEMENT_TYPE_MASK) {
- mapElement++;
- }
-
- if (mapElement->properties.surface.ownership & 0x30)
+ map_element_iterator_begin(&it);
+ do {
+ if (map_element_get_type(it.element) == MAP_ELEMENT_TYPE_SURFACE) {
+ if (it.element->properties.surface.ownership & (OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED | OWNERSHIP_OWNED)) {
tiles++;
+ }
}
- }
+ } while (map_element_iterator_next(&it));
if (tiles != RCT2_GLOBAL(RCT2_ADDRESS_PARK_SIZE, sint16)) {
RCT2_GLOBAL(RCT2_ADDRESS_PARK_SIZE, sint16) = tiles;
@@ -333,7 +331,7 @@ money32 calculate_company_value()
*/
void reset_park_entrances()
{
- RCT2_GLOBAL(0x013573D4, uint16) = 0;
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id) = 0;
for (short i = 0; i < 4; i++) {
RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i] = 0x8000;
@@ -516,7 +514,7 @@ static void park_generate_new_guests()
// Extra guests generated by advertising campaigns
int campaign;
for (campaign = 0; campaign < ADVERTISING_CAMPAIGN_COUNT; campaign++) {
- if (RCT2_ADDRESS(0x01358102, uint8)[campaign] != 0) {
+ if (gMarketingCampaignDaysLeft[campaign] != 0) {
// Random chance of guest generation
if ((int)(scenario_rand() & 0xFFFF) < marketing_get_campaign_guest_generation_probability(campaign))
park_generate_new_guest_due_to_campaign(campaign);
@@ -581,38 +579,227 @@ void park_update_histories()
RCT2_CALLPROC_EBPSAFE(0x0066A231);
}
-/**
-*
-* rct2: 0x00669E30
-*/
-void game_command_set_park_entrance_fee()
+void park_set_entrance_fee(money32 value)
{
- uint8 _bl;
- uint16 new_fee;
-
- #ifdef _MSC_VER
- __asm mov _bl, bl
- #else
- __asm__("mov %[_bl], bl " : [_bl] "+m" (_bl));
- #endif
-
- #ifdef _MSC_VER
- __asm mov new_fee, di
- #else
- __asm__("mov %[new_fee], di " : [new_fee] "+m" (new_fee));
- #endif
-
- RCT2_GLOBAL(0x0141F56C, uint8) = 0x10;
-
- if (_bl & 1){
- RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, uint16) = new_fee;
+ game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, 0, GAME_COMMAND_SET_PARK_ENTRANCE_FEE, value, 0);
+}
+/**
+ *
+ * rct2: 0x00669E30
+ */
+void game_command_set_park_entrance_fee(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
+{
+ RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_PARK_ENTRANCE_TICKETS * 4;
+ if (*ebx & GAME_COMMAND_FLAG_APPLY) {
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) = (*edi & 0xFFFF);
window_invalidate_by_class(WC_PARK_INFORMATION);
}
+ *ebx = 0;
+}
- #ifdef _MSC_VER
- __asm mov ebx, 0
- #else
- __asm__("mov ebx, 0 ");
- #endif
+void park_set_open(int open)
+{
+ game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, open << 8, GAME_COMMAND_SET_PARK_OPEN, 0, 0);
+}
+
+/**
+ *
+ * rct2: 0x00669D4A
+ */
+void game_command_set_park_open(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp)
+{
+ if (*ebx & GAME_COMMAND_FLAG_APPLY) {
+ *ebx = 0;
+ return;
+ }
+
+ int dh = (*edx >> 8) & 0xFF;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_PARK_ENTRANCE_TICKETS * 4;
+ switch (dh) {
+ case 0:
+ if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_OPEN) {
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_PARK_OPEN;
+ window_invalidate_by_class(WC_PARK_INFORMATION);
+ }
+ break;
+ case 1:
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_OPEN)) {
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) |= PARK_FLAGS_PARK_OPEN;
+ window_invalidate_by_class(WC_PARK_INFORMATION);
+ }
+ break;
+ case 2:
+ RCT2_GLOBAL(0x01358838, uint32) = *edi;
+ window_invalidate_by_class(WC_RIDE);
+ break;
+ case 3:
+ RCT2_GLOBAL(0x0135934C, uint32) = *edi;
+ window_invalidate_by_class(WC_RIDE);
+ break;
+ }
+
+ *ebx = 0;
+}
+
+int park_get_entrance_index(int x, int y, int z)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (
+ x == RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[i] &&
+ y == RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Y, uint16)[i] &&
+ z == RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Z, uint16)[i]
+ ) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+void sub_6EC847(int x, int y, int z0, int z1)
+{
+ RCT2_CALLPROC_X(0x006EC847, x, 0, y, 0, z1, z0, 0);
+}
+
+void sub_664D05(int x, int y)
+{
+ RCT2_CALLPROC_X(0x00664D05, x, 0, y, 0, 0, 0, 0);
+}
+
+void park_remove_entrance_segment(int x, int y, int z)
+{
+ rct_map_element *mapElement;
+
+ mapElement = map_get_first_element_at(x / 32, y / 32);
+ do {
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE)
+ continue;
+ if (mapElement->base_height != z)
+ continue;
+ if (mapElement->properties.entrance.type != ENTRANCE_TYPE_PARK_ENTRANCE)
+ continue;
+
+ sub_6EC847(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
+ map_element_remove(mapElement);
+ sub_664D05(x, y);
+ } while (!map_element_is_last_for_tile(mapElement++));
+}
+
+/**
+ *
+ * rct2: 0x00666A63
+ */
+void game_command_remove_park_entrance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
+{
+ int x, y, z, entranceIndex, direction;
+
+ x = *eax & 0xFFFF;
+ y = *ecx & 0xFFFF;
+ z = *edx * 16;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint32) = RCT_EXPENDITURE_TYPE_LAND_PURCHASE * 4;
+ RCT2_GLOBAL(0x009DEA5E, uint16) = x;
+ RCT2_GLOBAL(0x009DEA60, uint16) = y;
+ RCT2_GLOBAL(0x009DEA62, uint16) = z;
+
+ if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) {
+ *ebx = 0;
+ return;
+ }
+
+ entranceIndex = park_get_entrance_index(x, y, z);
+ RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, uint16)[entranceIndex] = 0x8000;
+ direction = (RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_DIRECTION, uint8)[entranceIndex] - 1) & 3;
+ z = (*edx & 0xFF) * 2;
+
+ // Centre (sign)
+ park_remove_entrance_segment(x, y, z);
+
+ // Left post
+ park_remove_entrance_segment(
+ x + TileDirectionDelta[direction].x,
+ y + TileDirectionDelta[direction].y,
+ z
+ );
+
+ // Right post
+ park_remove_entrance_segment(
+ x - TileDirectionDelta[direction].x,
+ y - TileDirectionDelta[direction].y,
+ z
+ );
+
+ *ebx = 0;
+}
+
+void park_set_name(const char *name)
+{
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_RENAME_PARK;
+ game_do_command(1, GAME_COMMAND_FLAG_APPLY, 0, *((int*)(name + 0)), GAME_COMMAND_SET_PARK_NAME, *((int*)(name + 8)), *((int*)(name + 4)));
+ game_do_command(2, GAME_COMMAND_FLAG_APPLY, 0, *((int*)(name + 12)), GAME_COMMAND_SET_PARK_NAME, *((int*)(name + 20)), *((int*)(name + 16)));
+ game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, *((int*)(name + 24)), GAME_COMMAND_SET_PARK_NAME, *((int*)(name + 32)), *((int*)(name + 28)));
+}
+
+/**
+ *
+ * rct2: 0x00669C6D
+ */
+void game_command_set_park_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp)
+{
+ rct_string_id newUserStringId;
+ char oldName[128];
+ static char newName[128];
+
+ int nameChunkIndex = *eax & 0xFFFF;
+
+ RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4;
+ if (*ebx & GAME_COMMAND_FLAG_APPLY) {
+ int nameChunkOffset = nameChunkIndex - 1;
+ if (nameChunkOffset < 0)
+ nameChunkOffset = 2;
+ nameChunkOffset *= 12;
+ RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx;
+ RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp;
+ RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi;
+ }
+
+ if (nameChunkIndex != 0) {
+ *ebx = 0;
+ return;
+ }
+
+ format_string(oldName, RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id), &RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32));
+ if (strcmp(oldName, newName) == 0) {
+ *ebx = 0;
+ return;
+ }
+
+ if (newName[0] == 0) {
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_INVALID_RIDE_ATTRACTION_NAME;
+ *ebx = MONEY32_UNDEFINED;
+ return;
+ }
+
+ newUserStringId = user_string_allocate(4, newName);
+ if (newUserStringId == 0) {
+ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_INVALID_NAME_FOR_PARK;
+ *ebx = MONEY32_UNDEFINED;
+ return;
+ }
+
+ if (*ebx & GAME_COMMAND_FLAG_APPLY) {
+ // Free the old ride name
+ user_string_free(RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id));
+ RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id) = newUserStringId;
+
+ gfx_invalidate_screen();
+ } else {
+ user_string_free(newUserStringId);
+ }
+
+ *ebx = 0;
}
\ No newline at end of file
diff --git a/src/world/park.h b/src/world/park.h
index 4033a4d37e..5098c17369 100644
--- a/src/world/park.h
+++ b/src/world/park.h
@@ -61,6 +61,13 @@ void park_update_histories();
uint8 calculate_guest_initial_happiness(uint8 percentage);
-void game_command_set_park_entrance_fee();
+void park_set_open(int open);
+void park_set_name(const char *name);
+void park_set_entrance_fee(money32 value);
+
+void game_command_set_park_entrance_fee(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
+void game_command_set_park_open(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
+void game_command_remove_park_entrance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
+void game_command_set_park_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
#endif
diff --git a/src/world/scenery.h b/src/world/scenery.h
index 744f414e8b..eedf45dfa4 100644
--- a/src/world/scenery.h
+++ b/src/world/scenery.h
@@ -88,7 +88,8 @@ typedef enum {
} WALL_SCENERY_FLAGS;
typedef struct {
- uint8 pad_02[3];
+ uint16 var_06;
+ uint8 pad_08;
uint8 tool_id; // 0x09
uint16 price; // 0x0A
uint8 scenery_tab_id; // 0x0C
diff --git a/src/world/sprite.c b/src/world/sprite.c
index ce952a6387..ac4b6a3a07 100644
--- a/src/world/sprite.c
+++ b/src/world/sprite.c
@@ -33,6 +33,15 @@ void create_balloon(int x, int y, int z, int colour)
RCT2_CALLPROC_X(0x006736C7, x, colour << 8, y, z, 0, 0, 0);
}
+/**
+ *
+ * rct2: 0x0067440F
+ */
+void create_duck(int targetX, int targetY)
+{
+ RCT2_CALLPROC_X(0x0067440F, targetX, 0, targetY, 0, 0, 0, 0);
+}
+
/* rct2: 0x006EC473 */
void invalidate_sprite(rct_sprite* sprite){
if (sprite->unknown.sprite_left == (sint16)0x8000) return;
diff --git a/src/world/sprite.h b/src/world/sprite.h
index 6cca19d844..a9d24991eb 100644
--- a/src/world/sprite.h
+++ b/src/world/sprite.h
@@ -97,6 +97,7 @@ typedef union {
extern rct_sprite* g_sprite_list;
void create_balloon(int x, int y, int z, int colour);
+void create_duck(int targetX, int targetY);
rct_sprite *create_sprite(uint8 bl);
void reset_sprite_list();
void reset_0x69EBE4();