TCH (statz) | #1, Főfasz (10443) |
5665 | #564c | ^ | Idézet | Thu, 03 Nov 2022 15:11:15 +01 |
188.143.*.* | *.pool.digikabel.hu |
Ha a Circus Charlie első pályáján visszafelé ugrasz át a tüzes cserepek felett az oroszlánnal, akkor időnként feldob egy 5000 pontot érő aranyat. (Videó itt.) Namármost, erre a mindenféle netes okosságok azt írják, hogy
(Az első ugyan elsősorban az arcade verzióval foglalkozik, de az eltéréseket (pl. kimaradt pálya) leírják és itt nem írták, hogy a NES-re ez nem vonatkozna.) Namármost, ezekből egy szó nem igaz. Én rájöttem, hogy mikor dob fel aranyat, ha visszaugrasz az oroszlánnal, bár derült égből módon. Próbálgattam, hogy mikor dob fel aranyat, hogy ha karikán ugrok át a cserép felett, ha pénzes karikán ugrok át a cserép felett, ha kétszer ugrok át karikán a cserép felett és az a vicc, hogy az utóbbival kb. sikerült reprodukálni, de valamiért nem volt 100%-os, nem mindig sikerült. Viszont a próbálkozás közben lejárt az idő. Úgyhogy úgy döntöttem, hogy megcsítelem az időt, hogy legyen időm próbálkozni. Az időt a játék a $340-$343 tartományban tárolja little endian módon, meglepő módon úgy, hogy egy digit egy byte 0-tól 9-ig; tehát nem BCD, nem bináris, hanem szó szerint oda van írva az idő, úgy, ahogy látod, csak fordított sorrendben (little endian, mint mondtam). Namármost, a játék a negyedik számjegyet (egyesek, $340) egyáltalán nem használja (dísznek van ott...meg ballasztnak), a harmadik számjegy (tízesek, $341) dekrementálódik talán 200ms-onként és úgy csökken az idő. Mivel ezt elkapni nehéz lett volna, így a második számjegyet (százasok, $342) próbáltam elkapni, azt néztem, hogy hol változott 9-ről 6-ra. Ez sikerült is, ez volt a $342-es cím. Találomra beírtam rá 7-et, majd elkezdtem kísérletezni, hogy vajon, hogy tárolja a dolgot és beírogattam 7-et a következő, meg az előző címre is, így meg is lett a tárolás. Az idő be lett lőve 7777-re, én meg elkezdtem ismét tesztelni a cserepeket. És itt szoptam le magam, mert FOLYTON érmét dobott, bármit csináltam. Ekkor jöttem rá, hogy az érme feldobása nem véletlenszerű, ahogy a StrategyWiki írja és nem is a karikáktól függ, ahogy a GameSpot állítja, hanem az időtől. És elkezdtem lekapcsolgatni a felülírásokat és az első kísérletek azt hozták, hogy a százas helyiértéket ($342) nézi. Ha ott 7 van, érmét dob. Viszont belefutottam abba, hogy az első számjegyre (ezresek, $343) 1-et írtam és amikor egyszer lekapcsoltam a felülírást és legördült nullára, többé nem működött ez a hetes trükk. Végigpróbálgattam szisztematikusan, hogy mi történik, ha melyik helyiértéken mi van és a következőre jöttem rá, hogy a hátsó két számjegy nem fontos, az ezreseken ($343) viszont páratlan számnak kell lennie. És mellette a százasokon ($342) 7-esnek. Akkor dobja fel az érmét, ha a cserép felett tolatva ugratok az oroszlánnal. Tehát cheat nélkül akkor fog megtörténni, ha az idő állása az 1700-1790-es, vagy a 3700-3790-es tartományokba esik, lévén az utolsó számjegyet nem használja a játék és mindig 5000-ről indulunk, tehát cheat nélkül más nem fordulhat elő, de egyébként ugyanúgy működik az 57XX, 77XX és 97XX tartományokban is (sőt, beírhatsz ennél többet is, csak akkor hülye karakterek fognak megjelenni). Azaz C-ben leírva: drop_coin = ((*((char *)0x343) & 1) != 0) && (*((char *)0x342) == 7);Én kívánok elnézést. Update: Ha olyan karika van a képernyőn, amin pénzeszsák lóg, akkor nem dobja fel az aranyat, hiába passzol az idő. Update #2: Rájöttem, hogy nem csak a páratlan ezres + 700 a nyerő kombó, de a páros ezres + 300 is. Tehát a valid "aranytartományok": 03XX, 17XX, 23XX, 37XX, 43XX. (Meg persze tovább is, csak az már cheat-only.) Azaz a fenti C képlet így módosul: drop_coin = (((*((char *)0x343) & 1) != 0) && (*((char *)0x342) == 7)) || (((*((char *)0x343) & 1) == 0) && (*((char *)0x342) == 3));Update #3: Vagy nagyon trükkösen, de három művelettel kevesebből felírva: drop_coin = ((*((char *)0x342) & 251) == 3) && ((((*((char *)0x342) >> 2) ^ *((char *)0x343)) & 1) == 0);Update #4: Ez utóbbit leprogramoztam 6502-ben, mer' miér' ne... drop_coin: lda $0342 and #$fb cmp #$03 beq drop_coin_1 rts drop_coin_1: lda $0342 lsr a lsr a eor $0343 and #$01 rtsA snippet a Z flag-ben adja vissza, hogy kell-e érmét dobni, azaz a visszatérés után beq-val lehet lecsekkolni. Gondolkodtam rajta, hogy a második lda $0342 parancsot inkább kiváltom egy tax-txa, vagy tay-tya kombóval, de elvetettem, mert ha register-trash módon közelítem meg, akkor sebességben ugyanott vagyunk (2+2 vs. 4 ciklus), méretben egyetlen byte-ot nyertünk, viszont cserébe eltrasheltünk egy indexregisztert; ha meg register-preserve módon, akkor meg már lassabb és nagyobb is lesz a kód. Update 2023.07.31.: Beposztoltam a nesdev-re. |