Non mi assumo nessuna responsabilita' per danneggiamenti, perdita di dati
o danni personali come risultato diretto o indiretto dell'uso delle
informazioni contenute in queste pagine.
Questo materiale e' fornito cosi' com'e'
senza nessuna garanzia
implicita o esplicita.
Completamente per caso mi sono imbattuto in questo gioco: e' stato amore a prima vista! Secondo me e' veramente un capolavoro di pixel art, inoltre si tratta di un puzzle e io amo i puzzle, specie di questo tipo: mi riporta indietro al millennio scorso. Da prima mi sono imbattuto nella versione per C64, malgrado questo ero gia' convinto che fosse un bellissimo gioco. Devo ammettere che il C64 ha sempre incarnto per me il male: io vengo dall'MSX, per cui il C64 ha sempre rappresentato la concorrenza, l'avversario. Malgrado questo il gioco mi aveva gia' talmente rapito che ero quasi tentato di scaricare un emulatore per C64. Poi ho trovato la versione per ZX spectrum, ed e' stata una folgorazione totale: per quanto anche lo ZX spectrum fosse uno dei concorrenti era comunque piu' vicino al mio mondo, come l'MSX monta uno Z80, inoltre il frame buffer video e' molto simile a quello dell'MSX; all'epoca molti giochi per ZX spectrum venivano portati su MSX, perche' il porting era piu' semplice che da altri sistemi. Quindi mi sono lanciato sullo ZX spectrum, questo e' il codice sorgente scaricabile da questo sito. Vediamo che cosa c'e' dentro. I file
Almeno per il momento mi dedichero' alla versione 48k, la versione
128k dello ZX spectrum mi e' sempre stata sulle palle, io ho
conosciuto il computer con i tasti di gomma e voglio rimanere
fedele a questo ricordo. -rwxr-xr-x 1 alex alex 272 13 dic 22:14 tiles2.bin -rwxr-xr-x 1 alex alex 272 13 dic 22:14 tiles3.bin -rwxr-xr-x 1 alex alex 272 13 dic 22:14 tilesBase.bin -rwxr-xr-x 1 alex alex 256 13 dic 22:14 tiles.bin Proviamo a guardarci dentro: $ hexdump -Cv tiles.bin 00000000 00 40 00 00 00 00 02 00 aa aa 82 82 82 82 aa aa |.@..............| 00000010 00 00 00 00 20 24 6c 6c 6c 6c 24 24 00 00 00 00 |.... $llll$$....| 00000020 00 40 70 70 40 70 70 00 00 02 0e 0e 02 0e 0e 00 |.@pp@pp.........| 00000030 00 00 00 18 18 18 00 00 00 3c 42 5a 5a 42 3c 00 |......... A prima vista potrebbe non dire molto, ma il nome e' quantomeno sospetto, decido quindi di stamparlo in un modo diverso. Visto che non sono molto abile con gli script, metto insieme un programmino che stampi i byte in modo diverso: voglio una stampa bit per bit del contenuto del file in linee ordinate di 8 bit per linea. Per farlo uso questo codice. $ printile < tiles.bin printile version 0.01, Copyright (C) 2021 Alessandro Accattini ................ ..##............ ................ ................ ................ ................ ............##.. ................ ##..##..##..##.. ##..##..##..##.. ##..........##.. ##..........##.. ##..........##.. ##..........##.. ##..##..##..##.. ##..##..##..##.. ................ ................ ................ ................ ....##.......... ....##....##.... ..####..####.... ..####..####.... ..####..####.... ..####..####.... ....##....##.... ....##....##.... ................ ................ ................ ................ ................ ..##............ ..######........ ..######........ ..##............ ..######........ ..######........ ................ ................ ............##.. ........######.. ........######.. ............##.. ........######.. ........######.. ................ ................ ................ ................ ......####...... ......####...... ......####...... ................ ................ ................ ....########.... ..##........##.. ..##..####..##.. ..##..####..##.. ..##........##.. ....########.... ................ ##..####..###### ##..........##.. ......##........ ................ ................ ................ ................ ................ ................ ................ ................ ................ ................ ......##........ ##..........##.. ##..####..###### ##..##..##..##.. ................ ......##........ ................ ..##..##..##..## ................ ............##.. ................ ..............## ............#### ..............## ................ ................ ..............## ..........##..## ................ ##.............. ####............ ##.............. ................ ................ ##.............. ##..##.......... ................ ################ ##............## ##............## ##............## ##............## ##............## ##............## ################ ................ ........##...... ......######.... ....##########.. ..############## ................ ......######.... ......######.... ................ ......######.... ......######.... ................ ..############## ....##########.. ......######.... ........##...... ..############## ......##..####.. ..##..########## ......##......## ..##....######## ####............ ####..########## ....######..#### ......####..#### ####..########## ####............ ..##....######## ......##......## ..##..########## ......##..####.. ..############## ..####.......... ..######......## ..........##..## ####....######## ####..##..##..## ..##..##..###### ####..##..##..## ####..########## ..........####.. ##......######.. ##..##.......... ########....#### ##..##..##..#### ######..##..##.. ##..##..##..#### ##########..#### ................ ..############.. ..##########.... ..########..##.. ................ ....########.... ....######...... ....####..##.... ................ ..######........ ########..###### ..######..###### ########..###### ..####....###### ####..##..####.. ..........##..## ####..########## ##....##......## ####..##..##..## ##....##......## ####..########## ##....##........ ####..##........ ##....##..###### ##########..#### ##......##....## ##..##..##..#### ##......##....## ##########..#### ........##....## ........##..#### ######..##....## ####..########## ##....##......## ####..##..##..## ##....##......## ####..########## ##....##........ ####..##..###### ##.............. ##########..#### ##......##....## ##..##..##..#### ##......##....## ##########..#### ........##....## ######..##..#### ..............## ##..##....##..## ##..########..## ####..##..###### ..##..##..####.. ..########...... ..##........##.. ......########## ............##.. ##..##....##..## ##..########..## ######..##..#### ..####..##..##.. ......########.. ..##........##.. ##########...... ..##............ ##############.. ##..######..##.. ##############.. ##############.. ##############.. ##..######..##.. ##############.. ##############.. ................ ########..###### ########..###### ########..###### ................ ##..############ ##..############ ................ ................ ########..###### ########..###### ########..###### ................ ##..############ ##..############ ##..############ ..##..########## ......##..####.. ..##..########## ......##......## ..##....######## ####............ ####..########## ##....####..#### Ammetto che verso la fine diventi un po' criptico, ma sicuramente all'inzio si riconoscono un sacco di tessere del gioco. Questa rapprentazione in ASCII art serve sicuramente a sollevare l'entusiamo della truppa, ma possiamo fare di meglio: perche' non convertire le tessere in vere tessere, possiamo ad esempio farne una serie di png. Scatta quindi la scrittura di un nuovo codice che, dato un file binario di questo tipo in ingresso, produca una serie di png in uscita. Questo il codice. $ bin2png -b tiles -8 < tiles.bin bin2png version 0.01, Copyright (C) 2021 Alessandro Accattini Creating: tiles_00.png... done Creating: tiles_01.png... done Creating: tiles_02.png... done Creating: tiles_03.png... done Creating: tiles_04.png... done Creating: tiles_05.png... done Creating: tiles_06.png... done Creating: tiles_07.png... done Creating: tiles_08.png... done Creating: tiles_09.png... done Creating: tiles_10.png... done Creating: tiles_11.png... done Creating: tiles_12.png... done Creating: tiles_13.png... done Creating: tiles_14.png... done Creating: tiles_15.png... done Creating: tiles_16.png... done Creating: tiles_17.png... done Creating: tiles_18.png... done Creating: tiles_19.png... done Creating: tiles_20.png... done Creating: tiles_21.png... done Creating: tiles_22.png... done Creating: tiles_23.png... done Creating: tiles_24.png... done Creating: tiles_25.png... done Creating: tiles_26.png... done Creating: tiles_27.png... done Creating: tiles_28.png... done Creating: tiles_29.png... done Creating: tiles_30.png... done Creating: tiles_31.png... done $ montage tiles_??.png -tile 4x -geometry +16+16 -background Black tiles_table.png Il risultato si puo' vedere qui sotto:
Ok, l'indagine promette bene! Ora sbirciamo nei livelli. Nella directory levels si trovano dei file bin da level01.bin fono a level25.bin, apparentemente manca il file level00.bin. Per il momento soprassediamo e sbirciamo dentro level01.bin. Se lo guardiamo con hexdump non e' entusiasmante, a meno di non usare un trucco: $ hexdump -v -e '"%06.6_ax " 12/1 "%02x " "\n"' level01.bin 000000 00 00 00 00 00 00 00 00 00 00 00 00 00000c 00 00 00 00 00 00 00 00 00 00 00 00 000018 00 00 00 00 00 00 00 00 00 00 00 00 000024 00 00 00 00 00 00 00 00 00 00 00 00 000030 00 00 00 00 00 00 00 00 00 00 00 00 00003c 00 00 00 00 00 00 00 00 00 00 00 00 000048 00 00 00 00 00 00 00 00 00 00 00 00 000054 00 00 00 00 00 00 00 00 00 00 00 00 000060 00 00 00 00 00 00 00 00 00 00 00 00 00006c 00 00 00 00 00 00 00 00 00 00 00 00 000078 00 00 00 00 00 00 00 00 00 00 00 00 000084 00 00 00 00 00 00 00 00 00 00 00 00 000090 00 00 00 00 00 00 00 00 00 00 00 00 00009c 00 00 00 00 00 00 00 00 00 00 00 00 0000a8 00 00 00 00 00 00 00 00 00 00 00 00 0000b4 00 00 00 00 00 00 00 00 00 00 00 00 0000c0 00 00 00 00 00 00 00 00 00 00 00 00 0000cc 00 00 00 00 00 00 00 00 00 00 00 00 0000d8 00 00 00 00 00 00 00 00 00 00 00 00 0000e4 00 00 00 00 00 00 00 00 00 00 00 00 0000f0 00 00 00 00 00 00 00 00 00 00 00 00 0000fc 00 00 00 00 00 00 00 00 00 00 00 00 000108 00 00 00 00 00 00 00 00 00 00 00 00 000114 00 00 00 00 00 00 00 00 00 00 00 00 000120 00 00 00 00 00 00 00 00 00 00 00 00 00012c 00 00 00 00 00 00 00 00 00 00 00 00 000138 00 00 00 00 00 00 00 00 00 00 00 00 000144 00 00 00 00 00 00 00 00 00 00 00 00 000150 00 00 00 00 00 00 00 00 00 00 00 00 00015c 00 00 00 00 00 00 00 00 00 00 00 00 000168 00 00 00 00 00 00 00 00 00 00 00 00 000174 00 00 00 00 00 00 00 00 00 00 00 00 000180 00 00 00 00 00 00 00 00 00 00 00 00 00018c 00 00 00 00 00 00 00 00 00 0a 0a 0a 000198 00 00 00 00 00 00 0a 0a 0a 0a 0a 0a 0001a4 00 00 00 00 00 00 0a 0a 0a 0a 0a 00 0001b0 00 00 00 00 00 00 00 00 00 00 00 00 0001bc 00 00 0a 0a 0a 00 00 00 00 00 00 00 0001c8 00 0a 0a 0a 0a 0a 00 00 00 00 00 00 0001d4 00 00 00 00 00 00 00 0a 0a 0a 00 00 0001e0 00 00 00 00 00 00 00 00 0a 0a 0a 00 0001ec 00 00 00 0a 0a 00 00 00 00 00 00 00 0001f8 00 0a 0a 0a 0a 0a 09 00 00 00 00 00 000204 00 00 00 00 09 1e 1e 0c 0a 0a 00 00 000210 09 09 09 00 1e 1e 1e 1e 00 09 09 09 00021c 1d 1d 1d 1d 1d 1d 1d 1d 1d 1d 1d 1d 000228 07 06 06 06 07 06 06 07 06 06 06 07 000234 00 00 00 20 00 00 00 00 00 00 00 00 000240 09 0a 0a 00 06 1e 1e 06 00 09 09 09 00024c 1d 1d 1d 1d 06 1e 1e 06 1d 1d 1d 1d 000258 07 06 06 06 07 1e 1e 07 06 06 06 07 000264 06 1d 1d 1d 1d 1e 1e 1d 1d 1d 1d 06 000270 07 06 06 06 07 1e 1e 07 06 06 06 07 00027c 1d 1d 1d 1d 06 1e 1e 06 1d 1d 1d 1d 000288 00 00 08 08 06 1d 1d 06 00 08 08 08 000294 0a 00 00 00 00 08 00 00 00 00 00 00 0002a0 00 00 00 00 0a 0a 0a 0a 00 00 00 00 0002ac 00 00 00 00 00 00 00 00 21 00 00 00 0002b8 0a 0a 0a 00 00 00 00 00 00 0a 0a 0b 0002c4 0a 0a 00 00 00 00 00 0a 0a 0a 0a 0a 0002d0 09 00 1f 00 00 09 09 00 00 0d 09 00 0002dc 1d 1d 1d 1d 1d 1d 1d 1d 1d 1d 1d 1d 0002e8 00 00 00 00 00 00 00 00 00 00 00 00 0002f4 00 0a 0a 0a 0a 0a 0a 00 00 00 00 00
All'inizio e' tutto pieno di zeri, apparentemente inutili, ma se
guardate bene nella parte finale si riconosce la forma del primo
livello.
Supponiamo per un momento che ciascun byte in questo file sia
l'indice della tessera da prelevare dall'elenco precedente. $ bin2png -b tiles -4 < tiles.bin $ montage tiles_??.png -tile x1 -geometry +0+0 tiles_line.png $ levelpng -t tiles_line.png -o level01.png < level01.bin Il risultato e' l'immagine qui sotto.
Al di la del colore questo e' il primo livello. Il codice
A questo punto dobbiamo veramente aprire il codice sorgente e
sbirciarci dentro, niente paura: e' codice Z80. currentLevel: db START_LEVEL levels: dw level00 dw level02,level01,level03,level04,level06 dw level08,level09,level07,level10,level05 dw level11,level24,level25,level22,level12 dw level15,level21,level14,level13,level23 dw level02 level00: incbin "levels\menu.bin.mlz" level01: incbin "levels\level01.bin.mlz" level02: incbin "levels\level02.bin.mlz" level03: incbin "levels\level03.bin.mlz" level04: incbin "levels\level04.bin.mlz" level05: incbin "levels\level05.bin.mlz" level06: incbin "levels\level06.bin.mlz" level07: incbin "levels\level07.bin.mlz" level08: incbin "levels\level08.bin.mlz" level09: incbin "levels\level09.bin.mlz" level10: incbin "levels\level10.bin.mlz" level11: incbin "levels\level11.bin.mlz" level12: incbin "levels\level12.bin.mlz" level13: incbin "levels\level13.bin.mlz" ;level14: incbin "levels\level14.bin.mlz" ;level15: incbin "levels\level15.bin.mlz" ;level21: incbin "levels\level21.bin.mlz" ;level22: incbin "levels\level22.bin.mlz" ;level23: incbin "levels\level23.bin.mlz" ;level24: incbin "levels\level24.bin.mlz" ;level25: incbin "levels\level25.bin.mlz" Per qualche strano motivo la variabile levels riporta i livelli in ordine irregolare, non so, potrebbe essere un trucco per rimescolare l'ordine dei livelli senza rinominare tutti i file. Il file che viene incluso estensione mlz, anche questo e' un mistero; di fatto megalz.exe trasforma i file bin in mlz, potrebbe essere la forma compressa del file binario, lo scopriremo (forse) osservando il codice. Confermato: i file mlz sono compressi (probabilmente RLE o qualcosa di simile) e devono essere scompattati da una apposita routine. Qui sotto il pezzo di codice che scompatta il livello richiesto. unpackLevel: ld a,(currentLevel) ;in A il livello attuale ld l,a : ld h,0 ;lo copia in HL add hl,hl;x2 ;lo moltiplica per 2 ld de,levels ;punta DE all'array di livelli add hl,de ;punta HL all'interno dell'array ld a,(hl) ;punta HL al livello compresso inc hl ld h,(hl) ld l,a ld de,level ;punta DE a level call DEC40 ;scompatta il livello ; questa routine deve essere chiamata con: ; HL punta al blocco compresso ; DE punta all'area in cui scompattare ;quindi il livello viene scompattato in level ret ;termina Il pezzo di codice qui sopra preleva l'indice del livello attivo dalla variabile currentLevel e lo scompatta all'interno di level. Qui sotto la routine originale che si occupa della scompattazione. ;Z80 depacker for megalz V4 packed files (C) fyrex^mhm ; DESCRIPTION: ; ; Depacker is fully relocatable, not self-modifying, ;it's length is 110 bytes starting from DEC40. ;Register usage: AF,AF',BC,DE,HL. Must be CALL'ed, return is done by RET. ;Provide extra stack location for store 2 bytes (1 word). Depacker does not ;disable or enable interrupts, as well as could be interrupted at any time ;(no f*cking wicked stack usage :). ; USAGE: ; ; - put depacker anywhere you want, ; - put starting address of packed block in HL, ; - put location where you want data to be depacked in DE, ; (much like LDIR command, but without BC) ; - make CALL to depacker (DEC40). ; - enjoy! ;) ; PRECAUTIONS: ; ; Be very careful if packed and depacked blocks coincide somewhere in memory. ;Here are some advices: ; ; 1. put packed block to the highest addresses possible. ; Best if last byte of packed block has address #FFFF. ; ; 2. Leave some gap between ends of packed and depacked block. ; For example, last byte of depacked block at #FF00, ; last byte of packed block at #FFFF. ; ; 3. Place nonpackable data to the end of block. ; ; 4. Always check whether depacking occurs OK and neither corrupts depacked data ; nor hangs computer. ; DEC40 LD A,#80 EX AF,AF' MSl LDI M0l LD BC,#2FF M1l EX AF,AF' M1Xl ADD A,A JR NZ,M2l LD A,(HL) INC HL RLA M2l RL C JR NC,M1Xl EX AF,AF' DJNZ X2l LD A,2 SRA C JR C,N1l INC A INC C JR Z,N2l LD BC,#33F JR M1l X2l DJNZ X3l SRL C JR C,MSl INC B JR M1l X6l ADD A,C N2l LD BC,#4FF JR M1l N1l INC C JR NZ,M4l EX AF,AF' INC B N5l RR C RET C RL B ADD A,A JR NZ,N6l LD A,(HL) INC HL RLA N6l JR NC,N5l EX AF,AF' ADD A,B LD B,6 JR M1l X3l DJNZ X4l LD A,1 JR M3l X4l DJNZ X5l INC C JR NZ,M4l LD BC,#51F JR M1l X5l DJNZ X6l LD B,C M4l LD C,(HL) INC HL M3l DEC B PUSH HL LD L,C LD H,B ADD HL,DE LD C,A LD B,0 LDIR POP HL JR M0l Di fatto level e' un array di 768 byte in cui poter fare un po' quello che si vuole. Alla riga successiva sembra ci sia una sorta di background compresso, ma a questo arriveremo forse piu' avanti. ;tiles level level: ;block 0,768;incbin "levels\map.bin" bgPacked: incbin "res\bg2.scr.mlz" La routine unpackLevel viene chiamata una sola volta all'interno di initLevel, vediamo se riesco a capire qualcosa di questo pezzo di codice: ;it's just an adresses in mc of every exit initExits: ld hl,exitsList ;punta HL ad exitsList ld (exitsPointer),hl ;salva il puntatore in exitsPointer ld de,exitsList+1 ;punta DE al byte successivo ld bc,8*4-1 ;in BC il numero di byte da azzerare: 8*4 ld (hl),0 ;azzera il primo byte ldir ;azzera tutti gli altri ret ;termina ;adds a hero to list initHeroes: ;reset heroes count xor a ;azzera heroesCount ld (heroesCount),a ;reset list of heroes ld hl,heroList ;punta HL a heroList ld (activeHero),hl ;salva il puntatore in activeHero ld (heroPointer),hl ;salva il puntatore in heroPointer ld de,heroList+1 ;punta DE al byte successivo ld bc,8*6-1 ;in BC il numero di byte da azzerare: 8*6 ld (hl),0 ;azzera il primo byte ldir ;azzera tutti gli altri ret ;termina initBullets: ld hl,bulletsList ;punta HL a bulletsList ld (bulletsPointer),hl ;salva il puntatore in bulletsPointer xor a ;azzera A ld hl,bulletsList ;idem come sopra !!??! ld de,bulletsList+1 ;punta DE al byte successivo ld bc,4*7-1 ;in BC il numero di byte da azzerare: 4*7 ld (hl),a ;azzera il primo byte ldir ;azzera tutti gli altri ret ;termina initCanons: ld hl,canonsList ;punta HL a canonList ld (canonsPointer),hl ;salva il puntatore in cannonsPointer ld hl,baseCanons ;punta HL a baseConons ld de,canonsList ;punta DE a canonsList ld bc,8*6 ;in BC il numero di byte da copiare ldir ;copia l'array baseConons in canonsList ret ;termina initEnemies: ld hl,enemiesList ;punta HL a enemiesList ld (enemiesPointer),hl ;salva il puntatore in enemiesPointer ld hl,baseEnemies ;punta HL a baseEnemies ld de,enemiesList ;punta DE a enemiesList ld bc,8*8 ;in BS in numero di byte da copiare ldir ;copia l'array baseEnemies in enemiesList ret ;termina initCoins: ld hl,coinsList ;punta HL a coinsList ld (coinsListPointer),hl;salva il puntatore in coinsListPointer xor a ;azzera A ld hl,coinsList ;idem come sopra!??!! ld de,coinsList+1 ;punta DE al byte successivo ld bc,32*4-1 ;in BC il numero di byte da azzerare: 32*4 ld (hl),a ;azzera il primo byte ldir ;azzera tutti gli altri ret ;termina initMC: ld hl,mcList ;punta HL a mcList ld de,mcList+1 ;punta DE al byte successivo ld bc,mc1Size*4-1 ;in BC il numero di byte da azzerare: mc1Size*4 ld (hl),0 ;azzera il primo byte ldir ;azzera tutti gli altri ld hl,mcList2 ;idem per l'array mcList2 ld de,mcList2+1 ld bc,mc2Size*4-1 ld (hl),0 ldir ret ;termina initLevel: ld hl,49152 ;in HL il valore magico c000h ld (pixelStart+1),hl ;lo salva in pixelStart+1 set 5,h ;in HL il valore magico e000h ld (mcStart+1),hl ;lo salva in mcStart+1 xor a ;azzera A ld (goldCount),a ;azzera goldCount call clearPixels call unpackLevel ;scompatta il livello attuale ; ld hl,level01 ; ld de,level ; ld bc,72*12 ; ldir call initExits ;init vari visti sopra call initHeroes call initCanons call initBullets call initEnemies call initCoins call initMC ;=====draw level ld de,0+0*256 ;d-y e-x ld hl,level ;punta HL al livello scompattato ld c,64 ;in C il numero di righe ld b,12 ;in B il numero di colonne ld e,0 ;azzera E 1: ld a,(hl) ;preleva un byte dalla level map push bc ;salva i registri sullo stack push hl push de cp CANON_LEFT ;se A=CANON_LEFT=25 call z,addCanon ;chiama addCannon cp CANON_RIGHT ;se A=CANON_RIGHT=24 call z,addCanon ;idem cp ENEMY_RIGHT ;se A=ENEMY_RIGHT=32 call z,addEnemy ;chiama addEnemy cp ENEMY_LEFT ;se A=ENEMY_LEFT=33 call z,addEnemy ;chiama addEnemy cp TILE_COIN ;se A=TILE_COIN=7 call z,addCoin ;chiama AddCoin cp TILE_EXIT ;se A=TILE_EXIT=13 call z,addExit ;chiama addExit cp TILE_GOLD ;se A=TILE_GOLD=6 call z,addGold ;chiama addGold cp HERO_START ;se A=HERO_START=31 call z,initHero ;chiama initHero cp HERO_LEFT ;se A=HERO_LEFT=20 call z,addHero ;chiama addHero cp HERO_RIGHT ;se A=HERO_RIGHT=21 call z,addHero ;idem cp HERO_UP ;se A=HERO_UP=19 call z,addHero ;idem cp HERO_DOWN ;se A=HERO_DOWN=18 call z,addHero ;idem call drawTile ;stampa la tessera indicizzata da A nella ;posizione indicata da DE (E=x, D=y) pop de ;recupera i registri pop hl pop bc inc hl ;incrementa HL (byte successivo) inc e ;incrementa E (E=x) djnz 1b ;decrementa B, se non zero salta ;B contiene il numero di colonne (12) inc d ;riga successiva (D=y, E=x) dec c ;scala il contatore delle righe jr nz,2b ;se non zero, salta ret ; termina La routine initLevel inizia inizializzando degli oscuri buffer: vengono inizializzati a zero tranne alcuni il cui contenuto viene copiato da una costante. Dopo di questo legge la mappa del livello e usa drawTile per piazzare una tessera in un rettangolo di 12 colonne e 64 righe. Man mano che procede in questo riempimento verifica il tipo di tessera che sta posizionando ed aggiorna gli array di cui sopra. Alla fine della routine il livello e' costruito: tutti i pixel sono stati disegnati e gli array sono stati riempiti di teste, pipistrelli, omini, oro, etc...
Quindi ora sappiamo tutto! Di fatto la routine drawTile scrive in un frame buffer virtuale, molto probabilmente la parte interessata (64 righe sono tropper per il video) saranno copiate in seguito sul vero video buffer. Girando per il codice ho risolto un altro mistero: le pietre blu di contorno alla torre: a poche righe da quello che sembra l'entry point del programma c'e' un riferimento a bgPacked, viene scompattato dalla routine DEC40 direttamente nel video buffer (una delle poche scritture dirette a video). page 0 org 24500 start: call 49152 ;kempsotn test call kempstonTest ld a,e ld (haveKempston),a;1 - if have it di ld sp,24499 xor a call swapPage ld hl,nullProc ld (topProc+1),hl ld (botomProc+1),hl di: ld hl,interruptNull : call IMON: ei call startGame ld hl,bgPacked ld de,16384 call DEC40 Piu' avanti si trova la dichiarazione di gbPacked: ;tiles level level: ;block 0,768;incbin "levels\map.bin" bgPacked: incbin "res\bg2.scr.mlz" Il file bg2.scr contiene uno screen, ovvero la copia del video buffer, completo di attributi. Questo viene compresso, incluso nel codice e scompattato direttamente a video. Ho ricostruito i passaggi creando una nuova utility: $ screenpng -o bg2.png < 48k/res/bg2.scr $ convert bg2.png -scale 200% bg2_big.png
Colmiamo un'altra curiosita': ricordate la prima directory che abbiamo spulciato, conteneva 4 diversi file di tessere. Che differenza ci sara' tra uno e l'altro? -rwxr-xr-x 1 alex alex 272 13 dic 22:14 tiles2.bin -rwxr-xr-x 1 alex alex 272 13 dic 22:14 tiles3.bin -rwxr-xr-x 1 alex alex 272 13 dic 22:14 tilesBase.bin -rwxr-xr-x 1 alex alex 256 13 dic 22:14 tiles.bin
|
Questo sito e' stato realizzato interamente con vim.
Grazie a tutta la comunita' open source, alla free software foundation
e chiunque scriva software libero.