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();