Manic Minerin hakkerointia (osa 2)

Olemme aiemmin muokanneet C16 Manic Minerista version, jossa elämät eivät loppuneet koskaan. Lisäksi selvitimme mitä muistiosoitetta meidän täytyy ohjelman ajon aikana muokata, jotta voimme määritellä mistä huoneesta peli alkaa. Nyt kun C16 versio on jyrätty läpi, meidän on aika siirtää huomiomme Commodore 64 versioon.

Kokemus on osoittanut, että hyvät harjoittelumahdollisuudet ovat erittäin suuri etu. Aina ei nimittäin ole niin, että loppupään huoneet olisivat hirvittävän vaikeita, mutta koska suhteellisesti harvemmat pelit etenevät pitkälle, huoneita ei aina ole mahdollista harjoitella riittävästi. Yritetään siis tehdä sama temppu kuusnelosen versiolle kuin C16:stakin, eli etsitään miten saamme määrättyä siinäkin aloitushuoneen.

Aiempi C-ohjelmani oli yksinkertainen, mutta siltikin tarpeettoman monimutkainen enum määrittelyineen kaikkineen. Tässä versiossa asioita on yksinkertaistettu, sillä kaikenlainen turha infrastruktuurin rakentaminen ns. kertakäyttöohjelmissa on silkkaa ajanhaaskausta. En tiedä mikä päähäni aiemmin meni, mutta pelkistetympi C-ohjelmani on seuraavanlainen:

#include <stdio.h>
#include <stdlib.h>


#define MANIC_SIZE 27093
#define MANIC_FILE "manic_miner.prg"

#define LDA 0xa9	/* immediate */
#define LDX 0xa2	/* immediate */
#define LDY 0xa0	/* immediate */
#define STA 0x8d	/* absolute */
#define STX 0x8e	/* absolute */
#define STY 0x8c	/* absolute */


unsigned char buf[MANIC_SIZE];


int main(void)
{
	FILE *fp;
	FILE *mm;
	int n;
	int i;
	int total = 0;
	char namebuf[12];
	char reg_name;

	fp = fopen(MANIC_FILE, "r");

	if ((n = fread(buf, MANIC_SIZE, 1, fp)) != 1) {
		fprintf(stderr, "fread error\n");
		exit(EXIT_FAILURE);
	}

	fclose(fp);

	fp = fopen("info.txt", "w");

	for (i = 0; i < MANIC_SIZE - 5; i++) {
		reg_name = 0;
		if (buf[i] == LDA && buf[i+1] == 0x00 && buf[i+2] == STA)
			reg_name = 'A';
		else if (buf[i] == LDX && buf[i+1] == 0x00 && buf[i+2] == STX)
			reg_name = 'X';
		else if (buf[i] == LDY && buf[i+1] == 0x00 && buf[i+2] == STY)
			reg_name = 'Y';

		if (reg_name) {
			++total;	
			snprintf(namebuf, sizeof namebuf, "mm%d.prg", total);
			fprintf(fp, "%s offset=%d (%x) register %c set to zero followed by absolute store\n",
					namebuf, i, i, reg_name);

			buf[i+1] = 0x01;

			mm = fopen(namebuf, "w");
			if ((n = fwrite(buf, MANIC_SIZE, 1, mm)) != 1) {
				fprintf(stderr, "fwrite mm%d.prg error\n", total);
				exit(EXIT_FAILURE);
			}
			fclose(mm);
			buf[i+1] = 0x00;
		}
	}

	fclose(fp);
	return 0;
}

Huomaa, että tässä MANIC_SIZE on yli kaksi kertaa suurempi kuin Commodore 16:n versiossa. Noin suuri ohjelma ei mahtuisi lainkaan laajentamattoman C16:n RAM-muistiin, mutta kuusnelosen isompi muisti riittää hyvin. Isompi koko selittyy mm. sillä, että C64 versiossa on erillinen aloitusruutu, aloitusruudun aikana soi musiikki, pelin aikana soi musiikki, ja peli loppuu pieneen animaatioon. Lyhyesti sanottuna tässä versiossa on kaikenlaista mitä Sinclair ZX Spectrumin originaalissakin on. C16 versiohan ei sisältänyt mitään lisukkeita itse pelin ohella.

Ajoin C-ohjelmani ja tuloksena oli tällä kertaa 41 erilaista Manic Minerin versiota. Sitten vain kokeilemaan osuiko joku niistä oikeaan. Annoin Linuxissa bash-komentotulkille komennot:

mkdir not_working
for i in {1..41}; do x64 mm${i}.prg && mv mm${i}.prg not_working; done

Historia toistaa itseään: mm2.prg on haluamamme ohjelma, ja tällä kertaa lopputuloskin on täysin odotettu. Olemme muuttaneet nollan ykköseksi ja peli alkaa nyt kakkoshuoneesta eli THE COLD ROOM:ista. Jostain oudosta syystähän Commodore 16:sta mm2.prg alkoi kolmoshuoneesta vaikka tekemämme muutos oli täsmälleen samanlainen.

Sitten taas vilkaisu C-ohjelmani tuottamaan info.txt tiedostoon:

mm2.prg offset=7164 (1bfc) register A set to zero followed by absolute store

Selvä homma. A-rekisteriä on taas sorkittu. Loppukin vastasi hyvin pitkälti menetelmää, jota käytimme C16 versiossa, eli seuraavaksi etsimme oikeaa tavusekvenssiä VICE:n konekielimonitorilla. Jälleen kävi niin, että toinen osuma oli oikea. Nyt tiedämme, että seuraavilla komennoilla on mahdollista muokata Commodore 64 Manic Minerin aloitusruutu haluamakseen:

fill 4023,4023 1
exit

Saatat muistaa, että aiemmassa blogissani kauhistelin Commodore 64 Manic Minerin SOLAR POWER GENERATOR huoneessa ilmennyttä bugia. Miner Willyhän jäi siinä kävelemään ilman päälle. Silloin spekuloin olikohan bugi krakkeriryhmän vahingossa aiheuttama, sillä he olivat introssaan maininneet korjanneensa jonkin grafiikkabugin. Olisi täysin mahdollista, että hyvää tarkoittava "korjaus" olisikin samalla rikkonut jotain muuta, jota krakkerit eivät vain olleet tulleet ajatelleeksi.

Nimenomaan tuon epäilykseni takia en tänään käyttänyt aiemmin netistä löytämääni MANICMIN.T64 tiedostoa, vaan etsin PRG-tiedostomuodossa olevan Manic Minerin. Jos haluat kokeilla sitä esimerkiksi C64 emulaattorissa, voit imuroida tiedoston tästä linkistä.

Nyt kun aloitushuoneen valinta oli mahdollista, halusin heti alkuun testata ilmenisikö SOLAR POWER GENERATOR huoneen bugi myös tässä itse muokkaamassamme versiossa. Ilokseni totesin, että huone näyttäisi toimivan ihan normaalisti! Voimme siis olla tyytyväisiä siitä, että nyt meillä on ehjä C64 Manic Miner harjoittelua varten.

Jos kuitenkin halutaan saavuttaa vieläkin suurempi varmuus, niin meillä on vaihtoehtona TAP-tiedostomuodossa oleva Manic Miner. TAP on eräänlainen "tape image" eli tarkka kopio alkuperäisestä ohjelmanauhasta. Netissä on ohjelmia, joilla TAP-tiedostot voi soittaa modernien tietokoneiden äänikortin kautta ja nauhoittaa syntynyt ääni kasettinauhurilla perinteisille C-kaseteille. Kasetteja voi sitten käyttää oikean kasettiaseman ja Commodore 64:n kanssa.

Myös VICE-emulaattori osaa ladata TAP-imaget, ja kun se tekee sen, pelaaja pääsee lähes autenttiseen retrotunnelmaan. Lataus nimittäin jäljittelee oikeaa latausproseduuria kasetilta, ja sehän saattaa kestää todella kauan.

Jos haluat Commodore 64 Manic Miner TAP-tiedoston ZIP-pakattuna, se löytyy tästä linkistä. Kyseinen tiedosto on haettu sivustolta The ULTIMATE C64 Tape Page. Sieltä löytyy paljon muitakin pelejä TAP-muodossa. Huomaathan, että VICE osaa ladata ZIP-pakatut TAP-imaget ilman, että ZIP-pakettia tarvitsisi purkaa. Itse annoin Linuxissa vain komennon:

x64 ManicMiner.zip

ja aloin odotella. Ruudun välkkyminen latauksen aikana on Manic Minerin tapauksessa normaalia eikä siitä kannata huolestua. Manic Minerin lataus TAP-imagesta kestää noin 14 (kyllä, neljätoista!) minuuttia.

Olen itse sen verran pelokas, että aion varmuuden vuoksi käyttää TAP-imagea harjoituksissani. Silloin voin olla lähes 100% varma, että mikään osa ohjelmakoodista ei ole korruptoitunut. Hakkerit ovat nimittäin olleet sen verran viisaita, että he ovat dumpanneet TAP-imaget useammalta alkuperäiseltä nauhalta ja vertailleet eri dumppausten lopputuloksia keskenään. Jos tulokset ovat olleet yhteneviä, niin varmuus dumpin ehjyydestä kasvaa. Vastaavasti jos tulokset eivät täsmää, niin nauhoissa on luultavasti ollut vikaa tai kasettiaseman säädöt ovat olleet pielessä.

Kilpapelejä varten olen jo tonkinut kaapistani esille yhden Commodore 64 tietokoneen ja kasettiaseman. Harmikseni en kuitenkaan löytänyt Manic Minerin ihan ensimmäistä julkaisua C64:lle, vaan ainoastaan myöhemmän uudelleenjulkaisun. Tiedän omistavani originaalin, mutta en tiedä missä laatikossa se on. Alkuperäisen Manic Minerin kansitaide on paljon hienompi kuin uudelleenjulkaisun, mutta sama peli näissä rumemmissa kuorissakin silti on:

c64_manic_miner_rerelease

Aion aloittaa treenauksen melko kevyesti, sillä olen vielä rasittunut C16:n Manic Minerin pelaamisesta.