; (c) 1993-1996, 2006 Karel 'Clock' Kulhavy ; tune (c) 2006 Alan 'Factor6' Petrik ; ; This program 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 2 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, write to the Free Software ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA screensrc equ 29825 itemtextdest equ 22502 numberdest equ itemtextdest+16 nrooms equ 69 ; More don't fit when the intro starts at 59565 sctarget equ 20703 ; Where the scroll character is being printed needitems equ 0x0395 ; 397 total, 2 uncollectable, BCD format! roomdefs EQU 32768 startroom equ 0 ; 0-68 is valid org 27000 firstaddress ch1 defb 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x52, 0xf7 ; Joystick ch2 defb 0x3c, 0x3c, 0x7e, 0x2c, 0x7c, 0x3c, 0x98, 0x7c ; Head ch3 defb 0xff, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3d ; Table ch4 defb 0x3f, 0x77, 0x77, 0x77, 0x6d, 0xff, 0xc4, 0xc4 ; Body ch5 defb 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x52, 0xf7 ; Joystick moved tunestart ; main voice, second voice. The third used to be length but was removed as unnecessary ; to save space. defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x3d, 0x25 defb 0x41, 0x25 defb 0x44, 0x25 defb 0x3d, 0x25 defb 0x41, 0x25 defb 0x44, 0x25 defb 0x3d, 0x25 defb 0x41, 0x25 defb 0x44, 0x25 defb 0x3d, 0x25 defb 0x41, 0x25 defb 0x44, 0x25 defb 0x3d, 0x2a defb 0x42, 0x2a defb 0x46, 0x2a defb 0x3d, 0x2a defb 0x42, 0x2a defb 0x46, 0x2a defb 0x3c, 0x24 defb 0x43, 0x24 defb 0x46, 0x24 defb 0x3c, 0x2b defb 0x40, 0x2b defb 0x43, 0x2b defb 0x35, 0x29 defb 0x38, 0x29 defb 0x3c, 0x29 defb 0x38, 0x29 defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x48, 0x29 defb 0x48, 0x30 defb 0x43, 0x30 defb 0x46, 0x30 defb 0x3c, 0x30 defb 0x43, 0x30 defb 0x46, 0x30 defb 0x3c, 0x30 defb 0x43, 0x30 defb 0x46, 0x30 defb 0x3c, 0x30 defb 0x43, 0x30 defb 0x48, 0x30 defb 0x48, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x49, 0x31 defb 0x41, 0x31 defb 0x46, 0x31 defb 0x3d, 0x31 defb 0x41, 0x31 defb 0x46, 0x31 defb 0x48, 0x2e defb 0x41, 0x2e defb 0x44, 0x2e defb 0x3c, 0x2e defb 0x41, 0x2e defb 0x44, 0x2e defb 0x46, 0x2b defb 0x40, 0x2b defb 0x43, 0x2b defb 0x3a, 0x28 defb 0x40, 0x28 defb 0x43, 0x28 defb 0x35, 0x29 defb 0x38, 0x29 defb 0x3c, 0x29 defb 0x38, 0x29 defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x3c, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x41, 0x29 defb 0x44, 0x29 defb 0x48, 0x29 defb 0x48, 0x30 defb 0x43, 0x30 defb 0x46, 0x30 defb 0x3c, 0x30 defb 0x43, 0x30 defb 0x46, 0x30 defb 0x3c, 0x30 defb 0x43, 0x30 defb 0x46, 0x30 defb 0x3c, 0x30 defb 0x43, 0x30 defb 0x48, 0x30 defb 0x48, 0x31 defb 0x41, 0x31 defb 0x44, 0x31 defb 0x3c, 0x31 defb 0x41, 0x31 defb 0x44, 0x31 defb 0x49, 0x2e defb 0x41, 0x2e defb 0x46, 0x2e defb 0x3d, 0x2e defb 0x41, 0x2e defb 0x46, 0x2e defb 0x48, 0x30 defb 0x40, 0x30 defb 0x43, 0x30 defb 0x3c, 0x30 defb 0x40, 0x30 defb 0x43, 0x30 defb 0x46, 0x28 defb 0x40, 0x28 defb 0x43, 0x28 defb 0x3a, 0x28 defb 0x40, 0x28 defb 0x43, 0x28 ;------------------ defb 0x41, 0x29 defb 0x00, 0x35 defb 0x41, 0x24 defb 0x00, 0x30 defb 0x00, 0x29 defb 0x00, 0x35 defb 0x00, 0x24 defb 0x00, 0x30 defb 0x00, 0x29 defb 0x00, 0x35 defb 0x00, 0x24 defb 0x00, 0x30 defb 0x00, 0x29 defb 0x00, 0x35 defb 0x00, 0x24 defb 0x00, 0x30 ;------------------ defb 0x48, 0x29 defb 0x46, 0x35 defb 0x48, 0x24 defb 0x46, 0x30 defb 0x45, 0x29 defb 0x45, 0x35 defb 0x41, 0x24 defb 0x41, 0x30 defb 0x41, 0x29 defb 0x41, 0x35 defb 0x45, 0x24 defb 0x46, 0x30 defb 0x48, 0x29 defb 0x46, 0x35 defb 0x45, 0x24 defb 0x46, 0x30 defb 0x48, 0x2c defb 0x4a, 0x38 defb 0x48, 0x27 defb 0x4a, 0x33 defb 0x4b, 0x2c defb 0x4a, 0x38 defb 0x4b, 0x27 defb 0x4a, 0x33 defb 0x48, 0x2c defb 0x48, 0x38 defb 0x48, 0x27 defb 0x48, 0x33 defb 0x48, 0x2c defb 0x48, 0x38 defb 0x48, 0x27 defb 0x48, 0x33 defb 0x4d, 0x29 defb 0x4d, 0x35 defb 0x4d, 0x24 defb 0x4d, 0x30 defb 0x4c, 0x29 defb 0x4c, 0x35 defb 0x4a, 0x24 defb 0x4a, 0x30 defb 0x48, 0x29 defb 0x46, 0x35 defb 0x45, 0x24 defb 0x46, 0x30 defb 0x48, 0x29 defb 0x48, 0x35 defb 0x45, 0x24 defb 0x45, 0x30 defb 0x49, 0x2c defb 0x48, 0x38 defb 0x46, 0x27 defb 0x48, 0x33 defb 0x49, 0x2c defb 0x49, 0x38 defb 0x46, 0x27 defb 0x46, 0x33 defb 0x4d, 0x2c defb 0x4d, 0x38 defb 0x4d, 0x27 defb 0x4d, 0x33 defb 0x4d, 0x2c defb 0x4d, 0x38 defb 0x4d, 0x27 defb 0x4d, 0x33 defb 0x48, 0x29 defb 0x46, 0x35 defb 0x48, 0x24 defb 0x46, 0x30 defb 0x45, 0x29 defb 0x45, 0x35 defb 0x41, 0x24 defb 0x41, 0x30 defb 0x41, 0x29 defb 0x41, 0x35 defb 0x45, 0x24 defb 0x46, 0x30 defb 0x48, 0x29 defb 0x46, 0x35 defb 0x45, 0x24 defb 0x46, 0x30 defb 0x48, 0x2c defb 0x4a, 0x38 defb 0x48, 0x27 defb 0x4a, 0x33 defb 0x4b, 0x2c defb 0x4a, 0x38 defb 0x4b, 0x27 defb 0x4a, 0x33 defb 0x48, 0x2c defb 0x48, 0x38 defb 0x48, 0x27 defb 0x48, 0x33 defb 0x48, 0x2c defb 0x48, 0x38 defb 0x48, 0x27 defb 0x48, 0x33 defb 0x4d, 0x29 defb 0x4d, 0x35 defb 0x4d, 0x24 defb 0x4d, 0x30 defb 0x4c, 0x29 defb 0x4c, 0x35 defb 0x4a, 0x24 defb 0x4a, 0x30 defb 0x48, 0x29 defb 0x46, 0x35 defb 0x45, 0x24 defb 0x46, 0x30 defb 0x48, 0x29 defb 0x48, 0x35 defb 0x45, 0x24 defb 0x45, 0x30 defb 0x49, 0x2c defb 0x48, 0x38 defb 0x46, 0x27 defb 0x48, 0x33 defb 0x49, 0x2c defb 0x49, 0x38 defb 0x46, 0x27 defb 0x46, 0x33 defb 0x4d, 0x2c defb 0x4d, 0x38 defb 0x4d, 0x27 defb 0x4d, 0x33 defb 0x4d, 0x2c defb 0x4d, 0x38 defb 0x4d, 0x27 defb 0x4d, 0x33 defb 0x48, 0x29 defb 0x46, 0x35 defb 0x48, 0x24 defb 0x46, 0x30 defb 0x45, 0x29 defb 0x45, 0x35 defb 0x41, 0x24 defb 0x41, 0x30 defb 0x41, 0x29 defb 0x41, 0x35 defb 0x45, 0x24 defb 0x46, 0x30 defb 0x48, 0x29 defb 0x46, 0x35 defb 0x45, 0x24 defb 0x46, 0x30 defb 0x48, 0x2c defb 0x4a, 0x38 defb 0x48, 0x27 defb 0x4a, 0x33 defb 0x4b, 0x2c defb 0x4a, 0x38 defb 0x4b, 0x27 defb 0x4a, 0x33 defb 0x48, 0x2c defb 0x48, 0x38 defb 0x48, 0x27 defb 0x48, 0x33 defb 0x48, 0x2c defb 0x48, 0x38 defb 0x48, 0x27 defb 0x48, 0x33 defb 0x4d, 0x29 defb 0x4d, 0x35 defb 0x4d, 0x24 defb 0x4d, 0x30 defb 0x4c, 0x29 defb 0x4c, 0x35 defb 0x4a, 0x24 defb 0x4a, 0x30 defb 0x48, 0x29 defb 0x46, 0x35 defb 0x45, 0x24 defb 0x46, 0x30 defb 0x48, 0x29 defb 0x48, 0x35 defb 0x45, 0x24 defb 0x45, 0x30 defb 0x49, 0x2c defb 0x48, 0x38 defb 0x46, 0x27 defb 0x48, 0x33 defb 0x49, 0x2c defb 0x49, 0x38 defb 0x46, 0x27 defb 0x46, 0x33 defb 0x4d, 0x2c defb 0x4d, 0x38 defb 0x4d, 0x27 defb 0x4d, 0x33 defb 0x4d, 0x2c defb 0x4d, 0x38 defb 0x4d, 0x27 defb 0x4d, 0x33 defb 0x48, 0x29 defb 0x46, 0x35 defb 0x48, 0x24 defb 0x46, 0x30 defb 0x45, 0x29 defb 0x45, 0x35 defb 0x41, 0x24 defb 0x41, 0x30 defb 0x41, 0x29 defb 0x41, 0x35 defb 0x45, 0x24 defb 0x46, 0x30 defb 0x48, 0x29 defb 0x46, 0x35 defb 0x45, 0x24 defb 0x46, 0x30 defb 0x48, 0x2c defb 0x4a, 0x38 defb 0x48, 0x27 defb 0x4a, 0x33 defb 0x4b, 0x2c defb 0x4a, 0x38 defb 0x4b, 0x27 defb 0x4a, 0x33 defb 0x48, 0x2c defb 0x48, 0x38 defb 0x48, 0x27 defb 0x48, 0x33 defb 0x48, 0x2c defb 0x48, 0x38 defb 0x48, 0x27 defb 0x48, 0x33 defb 0x4d, 0x29 defb 0x4d, 0x35 defb 0x4d, 0x24 defb 0x4d, 0x30 defb 0x4c, 0x29 defb 0x4c, 0x35 defb 0x4a, 0x24 defb 0x4a, 0x30 defb 0x48, 0x29 defb 0x46, 0x35 defb 0x45, 0x24 defb 0x46, 0x30 defb 0x48, 0x29 defb 0x48, 0x35 defb 0x45, 0x24 defb 0x45, 0x30 defb 0x49, 0x2c defb 0x48, 0x38 defb 0x46, 0x27 defb 0x48, 0x33 defb 0x49, 0x2c defb 0x49, 0x38 defb 0x46, 0x27 defb 0x46, 0x33 defb 0x4d, 0x2c defb 0x4d, 0x38 defb 0x4d, 0x27 defb 0x4d, 0x33 defb 0x4d, 0x2c defb 0x4d, 0x38 defb 0x4d, 0x27 defb 0x4d, 0x33 ;------ DJ clock added defb 0x49, 0x2c defb 0x48, 0x38 defb 0x46, 0x27 defb 0x48, 0x33 defb 0x49, 0x2c defb 0x49, 0x38 defb 0x46, 0x27 defb 0x46, 0x33 defb 0x49, 0x2c defb 0x48, 0x38 defb 0x46, 0x27 defb 0x48, 0x33 defb 0x49, 0x2c defb 0x49, 0x38 defb 0x46, 0x27 defb 0x46, 0x33 defb 0x4d, 0x2c defb 0x4d, 0x38 defb 0x4d, 0x27 defb 0x4d, 0x33 defb 0x4d, 0x2c defb 0x4d, 0x38 defb 0x4d, 0x27 defb 0x4d, 0x33 defb 0x00, 0x2c defb 0x00, 0x38 defb 0x00, 0x27 defb 0x00, 0x33 defb 0x00, 0x2c defb 0x00, 0x38 defb 0x00, 0x27 defb 0x00, 0x33 defb 0x48, 0x29 defb 0x46, 0x35 defb 0x48, 0x24 defb 0x46, 0x30 defb 0x45, 0x29 defb 0x45, 0x35 defb 0x41, 0x24 defb 0x41, 0x30 defb 0x41, 0x29 defb 0x41, 0x35 defb 0x41, 0x24 defb 0x41, 0x30 defb 0x00, 0x29 defb 0x00, 0x35 defb 0x00, 0x24 defb 0x00, 0x30 defb 0x00, 0x29 defb 0x00, 0x35 defb 0x00, 0x24 defb 0x00, 0x30 defb 0x00, 0x29 defb 0x00, 0x35 defb 0x00, 0x24 defb 0x00, 0x30 defb 0x00, 0x29 defb 0x00, 0x35 defb 0x00, 0x24 defb 0x00, 0x30 tuneend tunelen equ tuneend-tunestart iter defb 1 ; Frame counter for the current tone addr defw tunestart ITEMTEXT DEFM "Items collected " FCIFS defm "0000" halftones ; 16 halftones ; Starts at C2 (0x24) ; C 261.6 Hz is 1097.2299264 ; halftone 1.05946309435929526455 defw 274, 291, 308, 326 defw 346, 366, 388, 411 defw 435, 461, 489, 518 defw 549, 581, 616, 652 defw 691, 732, 776, 822 defw 871, 923, 978,1036 defw 1097,1162,1232,1305 defw 1382,1465,1552,1644 defw 1742,1845,1955,2071 defw 2194,2325,2463,2610 defw 2765,2929 ;3103,3288 ;defw 3483,3691,3910,4143 ;defw 4389,4650,4926,5219 ; keyboard test routine kbt1: LD A,191 ; Enter halfrow IN A,(0xfe) AND 1 ; Lowest bit is the edge key RET NZ POP HL ; Destroy return address JP one ; 60430 pokedprint push hl ld hl,ch1 ld (poke3),hl pop hl call print push hl ld hl,syscharset ld (poke3),hl pop hl ret kbtest: LD A,191 IN A,(0xfe) ; Keyboard read AND 1 RET NZ POP HL ; Destroy return address intogame: CALL WODE OR A JP Z,one ; 60430 probably jump if not completed game gaming: LD DE,str1 LD HL, 20527 LD BC,2 ; Length, BC=2 CALL pokedprint ; PR-STRING, DE adress, BC length LD L,79 ; HL=20606 LD C,2 ; BC=2 CALL pokedprint ; Print position 1 of the gaming guy call tensyn LD L, 47 ; HL=20527 inc c ; BC=1 - length CALL pokedprint ; Print position 2 of the gaming guy CALL tensyn CALL kbt1 JR gaming hexdigit: and 15 cp 10 jr c,nohex add a,'A'-('9'+1) nohex: add a,48 ld (de),a inc de ret hextext: ; updates hex item count from HL. Destroys DE. ld de,FCIFS ld a,h rrca rrca rrca rrca call hexdigit ld a,h call hexdigit ld a,l rrca rrca rrca rrca call hexdigit ld a,l call hexdigit ret ; Called tensyn because used to wait 10x vsync ; But now it waits 12 so the guy wiggles the joystick in sync to ; the tune ;-) ; Clobbers B, sets it to 0 ; Preserves af,bc,de,ix,iy tensyn: LD B,12 push hl ld hl,(sctl2) push hl tensyn1 ld hl,0x1080 ld (sctl2),hl ld hl,(0) tensyn2: tensynp equ tensyn2-2 ld (freq2),hl ld hl,(tensynp) inc hl inc hl ld (tensynp),hl push bc push de call hextext call tune call prtfcifs ; print the hex items pop de pop bc DJNZ tensyn1 pop hl ld (sctl2),hl pop hl ret tookitem ld hl,(newxypos) call getsix ld a,(newxpos) and 7 jr z,U51 ld a,(six+1) cp 6 jr nz,U49 inc l jr KONECC U49 ld a,(six+3) cp 6 jr nz,U50 inc l inc h jr KONECC U50 ld a,(six+5) cp 6 jr nz,U51 inc l inc h inc h jr KONECC U51 ld a,(six) cp 6 jr z,KONECC ld a,(six+2) cp 6 jr nz,U52 inc h jr KONECC U52 ld a,(six+4) cp 6 ret nz inc h inc h KONECC push hl ld hl,(sctl2) push hl ld hl,0x1680 ; Yellow, full volume ld (sctl2),hl ld hl,800 ld de,(freq2) ld b,5 CYK10 ld (freq2), hl call tune add hl,hl djnz cyk10 pop hl ld (sctl2),hl ld (freq2),de pop hl push hl call ROOMADDR or a push af ld a,(hl) jr z,U46 rrca rrca rrca rrca U46 or 15 ld b,a pop af ld a,b jr z,U47 rrca rrca rrca rrca U47 ld (hl),a ; Erase the item (set the char in room to 0xf) pop bc ld h,b ld l,c call GRCHAR ld (bc),a push de push hl call unpaintwilly ; Now Willy is missing from the screen pop hl pop de ld b,8 CYK11 ld a,(de) ; 7 ld (hl),a ; 7 inc de ; 6 inc h ; 4 djnz CYK11 ; 13 call getbgfromscrn ; Get Background from the Screen ld bc,(newxypos) call opbs ld hl,itemsbcd ld a,(hl) add a,1 daa ld (hl),a inc hl ld a,(hl) adc a,0 daa ld (hl),a call PRTNR pop hl jp NZSB ; These 3 labels must be in sequence str1 defb 0,1 str2 defb 2,3 str3 defb 4 scrolltext defm " Press ENTER to start. " defm " Twibright Labs present Jet Set Willy X. " defm "Left: 9ol, joys. " defm "Right: 0pENTER, joys. JUMP: 6yh, joys. " defm "Sound control: jk " defm "You would like to play games on your ZX Spectrum, " defm "but your strict wife doesn't allow you to until you " defm "collect all items in the city she wants. " defm "ZX Spectrum forever! " defm "(c) 1993-1996, 2006 Karel 'Clock' Kulhavy, music by " defm "Alan 'Factor6' Petrik. " defm "This program is free software; you can redistribute " defm "it and/or modify it under the terms of the GNU General " defm "Public License as published by the Free Software Foundation; " defm "either version 2 of the License, or (at your option) any later " defm "version. " defm "Good luck! *****PRESS ENTER TO START*****" scrolltextend org firstaddress-2 ; Stack address in sna_header defw introstart ; Return address for the SNA snapshot ORG 59540 SYS ; System variable area currentroom equ sys+0 oldxpos equ sys+1 oldxypos equ sys+1 oldypos equ sys+2 newxpos equ sys+3 newxypos equ sys+3 newypos equ sys+4 jumppos equ sys+5 unk7 equ sys+7 enterpos equ sys+9 ; Where Willy entered the screen. unk11 equ sys+11 unk13 equ sys+13 croomaddr equ sys+16 ; Current room address itemsbcd equ sys+18 ; Packed BCD how many items collected. bgstorage equ sys+20 ; Storage for graphics background six equ sys+52 ; 0 1 ; 2 3 ; 4 5 jumptable EQU SYS+58 ; 52 jump position, 2 bytes each -> 104 bytes. 58+104=162 njumppos equ 52 willysprites EQU SYS+162 ; 2 directions, each direction 8 positions ; each position 16 pixels high and 16 pixels (2 bytes) wide ; 512 bytes total CHARSET EQU SYS+674 SYSCHARSET EQU 15360 ; The ZX Spectrum ROM charset ; 256 chars, 8 bytes each. Total 2048 bytes. ; The code starts here. ORG SYS+2722 introstart DI LD A,58 ; A table full of ff LD I,A IM 2 ; Vector table xor a out (254),a ; black border one: call decomp_scr LD hl,roomdefs ; Room file start addr. LD DE,32 ; Room name length? ADD HL,DE ; LD B,nrooms l15: PUSH BC ; LD BC,320 ; 320 bytes beginning 24632 are processed in place. z6: LD A,(HL) ; HL is 24632 AND 15 CP 15 JR NZ,a1 ; if lower 4 bits of (HL) are not all set, jr to a1 LD A,(HL) AND 240 OR 6 LD (HL),A ; Replace lower 4 bits of (HL) with 6 a1: LD A,(HL) AND 240 CP 240 JR NZ,z5 LD A,(HL) AND 15 OR 96 LD (HL),A z5: INC HL DEC BC LD A,B OR C JR NZ,z6 LD BC,68 ; The room has 388 bytes, we processed 320, 68 remain ADD HL,BC POP BC DJNZ l15 LD IX,scrolltext ; IX - address in text LD HL,scrolltextend-scrolltext ; Width of the scrolled text? roll4: PUSH HL PUSH IX POP DE PUSH DE ld hl,sctarget LD BC,1 ; Length 1 CALL PRINT LD DE,287 ; 256+31 LD A,8 ; 8 rotations until we print another char roll3: ld c,a ld a,191 in a,(0xfe) and 1 jr nz, noent ; ENTER was pressed pop hl ; Destroy saved registers pop hl jp intogame noent: ld a,c LD HL,sctarget ; Within screen bitmap LD C,8 ; 8 microlines EI HALT ; Wait for VSYNC roll2: LD B,31 ; Text width + 1 OR A ; Reset the carry? roll1: RL (HL) ; Left scroll 1 pixel DEC HL DJNZ roll1 ADD HL,DE DEC C ; Microlines JR NZ,roll2 DEC A JR NZ,roll3 POP IX POP HL INC IX DEC HL LD A,H OR L JR NZ,roll4 ; If HL is not zero, jump waitforstart: CALL kbtest ; 0xeca1 = 60577, 0x94 offset in this program JR waitforstart ; Decompresses the title screen into the videoram ; Clobbers AF, BC, DE, HL decomp_scr: ld bc,screensrc ld de,16384 ld hl,decomp1 decomp1: ld a,(bc) ;7 inc bc ;6 or a ;4 jr z,decomp_zero ;7 ld (de),a ;7 inc de ;6 jp (hl) ;4 decomp_zero: ld a,(bc) inc bc or a ret z ld l,b ld b,a xor a decomp_block: ld (de),a inc de djnz decomp_block ld b,l ld l,decomp1&255 jp (hl) ; One rooms takes 388 bytes: ; 32 bytes name ; 320 bytes data (32x20, 2 chars per byte) ; 4 bytes exits (in what sequence?) ; The code begins at 62522 (0xF43A) ; Refresh all items in all rooms from taken into untaken state untake_items_in_all_rooms LD HL,roomdefs+32 LD D,nrooms untake_items_in_one_room LD BC,320 ; Room data area length untake_items_in_all_rooms1 LD A,(HL) OR 240 INC A JR Z,untake_items_in_all_rooms_rfl LD A,(HL) untake_items_in_all_rooms_brfl OR 15 INC A JR Z,untake_items_in_all_rooms_rfh untake_items_in_all_rooms_brfh INC HL DEC BC LD A,B OR C JP NZ,untake_items_in_all_rooms1 LD BC,68 ; 388-320 ADD HL,BC DEC D JP NZ,untake_items_in_one_room RET untake_items_in_all_rooms_rfl LD A,(HL) AND 240 OR 6 LD (HL),A JP untake_items_in_all_rooms_brfl untake_items_in_all_rooms_rfh LD A,(HL) AND 15 OR 96 LD (HL),A JP untake_items_in_all_rooms_brfh ; Prints the conveyors and flashes the items on the screen. ; 32 records by 5 byte holding flashing items ; and rolling conveyors. ; 0 conveyor screen address L ; 1 conveyor screen address H ; 2 bit 7 - 1 item, 0 conveyor, then lower bits length of the ; conveyor. 0=empty record. ; 3 coveyor upper content / item phase in lower 4 bits the rest ; ignored. ; 4 conveyor lower content ; Conserves AF, BC, DE, HL, IX belts_items_list DEFS 160 ;160-byte space , 32 records by 5 bytes draw_belts_items PUSH AF PUSH BC PUSH DE PUSH HL PUSH IX LD B,32 LD IX,belts_items_list draw_belts_items0 PUSH BC PUSH IX CALL draw_belt_item POP IX LD BC,5 ADD IX,BC POP BC DJNZ draw_belts_items0 POP IX POP HL POP DE POP BC POP AF RET ; Prints the conveyors to the screen actually ; IX - input of a 5-byte record ; Clobbers IX draw_belt_item LD A,(IX+2) OR A RET Z ; Empty item - final terminator of the list BIT 7,A ; 8 JR NZ,draw_item ; 7 LD D,(IX+3) ; 19 LD E,(IX+4) ; 19 BIT 6,A ; 8 JR NZ,drawn_belt_is_left ; 7 drawn_belt_is_right RRC D ; 8 RLC E ; 8 JP drawn_belt_item0 ; 10 drawn_belt_is_left RLC D RRC E drawn_belt_item0 LD (IX+3),D ; 19 LD (IX+4),E ; 19 LD L,(IX+0) ; 19 LD H,(IX+1) ; 19 AND 0x3f ; 7 CP 33 ; 7 RET NC ; 5 OR A ; A is conveyor length RET Z LD B,A LD C,A LD A,H AND 0xf8 LD H,A CP 64 RET C CP 88 RET NC drawn_belt_item1 LD (HL),D ; 0th line of the conveyor INC L DJNZ drawn_belt_item1 ; B is the conveyor length. INC H INC H ; 2 pixels down LD B,C drawn_belt_item2 dec l ; Go backwards LD (HL),e ; 2nd line of the conveyor DJNZ drawn_belt_item2 RET ; jumped to only from draw_belt_item. draw_item LD HL,(croomaddr) LD DE,32 ADD HL,DE LD E,(IX+0) LD A,(IX+1) CP 88 ; high byte of start of attributes address RET C ; address boundary check CP 91 ; high byte of address right behind attribute file RET NC ; address boundary check AND 3 LD D,A SRL D RR E RLA ADD HL,DE AND 1 LD A,(HL) JR Z,draw_item_nrot RRCA RRCA RRCA RRCA draw_item_nrot AND 15 CP 6 ; is 6 an item? RET NZ ; Return if not an item? LD A,(IX+3) ; Item phase? INC A ; Increase item phase? LD (IX+3),A ; Write item phase back? AND 31 ; Item cycle 32 phases LD HL,itemcolours ; Item colour table ; Add A to HL ADD A,L LD L,A ADC A,H SUB L LD H,A LD A,(HL) ; Fetch item colour LD L,(IX+0) ; (IX+0) and (IX+1) hold the address of the item ; attribute we want to change LD H,(IX+1) XOR (HL) AND 7 ; Change only the ink XOR (HL) LD (HL),A ; Write attr back RET ; Item colour flash table itemcolours DEFB 0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7 DEFB 7,7,6,6,5,5,4,4,3,3,2,2,1,1,0,0 ; Clobbers seemingly everything. WODE CALL untake_items_in_all_rooms LD HL,22528 LD DE,22529 LD BC,767 EI HALT LD (HL),0 LDIR ; Set attributes to zero LD HL,16384 LD DE,16385 LD BC,6143 LD (HL),0 LDIR ; Clear the screen LD HL,22528 LD DE,22529 LD BC,767 EI HALT LD (HL),71 ; Bright white on black LDIR ; Set the whole screen bright white on black LD HL,itemtextdest ; Lowermost row, 6 chars from left LD BC,20 ; 20 chars wide, centered LD DE,ITEMTEXT ; Items collected: xxxx CALL PRINT ; WCM LD A,startroom ld (currentroom),a WSR ld hl,34940 ld (oldxypos),hl ld (newxypos),hl ld (enterpos),hl LD HL,0 ld (jumppos),hl ld (unk7),hl ld (unk11),hl ld (unk13),hl WAM ld hl,roomdefs+388*startroom ld (croomaddr),hl WPB LD HL,0 ld (itemsbcd),hl call prtnr call PRTSCRN JP VPADL CYK7 ld a,127 in a,(0xfe) and 1 jr nz,U60 ld a,254 in a,(0xfe) ; test break and 1 jr nz,U60 xor a ret U60 ld a,(currentroom) or a jr nz,U61 ld a,(oldxpos) WEXS cp 124 jr nz,U61 ld a,(oldypos) WEYS cp 136 jr nz,U61 ld hl,(itemsbcd) ; number of items collected? WEPB ld bc,needitems ; number of items to collect or a sbc hl,bc jr c,U61 ld a,1 ; All items collected ret U61 ;in a,(31) ;and 31 xor a ; Joystick disabled ld (SYS+15),a ld a,143 in a,(254) or 224 cpl ld hl,SYS+15 or (hl) ld (hl),a call MUZPAD ld a,(jumppos) or a jr nz,U2 ld hl,SYS+6 bit 0,(hl) jr z,U1 ld hl,newypos inc (hl) jr nz,XXA dec (hl) XXA jr U3 U1 ld a,36 ld hl,SYS+8 cp (hl) jp c,KILL xor a ld (hl),a call OVLADANI U2 call SKOK U3 call ZABILSE or a jr z,U7 jp KILL VPADL CALL draw_belts_items ; Redraws the conveyors and the flashing items EI halt ; Wait for vertical blank jr U11 U7 call ZED call NVDP U4 call edge or a jr nz,VPADL call tookitem U10 call unpaintwilly U11 call getbgfromscrn ; Get Background from the Screen. ld bc,(newxypos) call opbs NZSB ld hl,(newxypos) ld (oldxypos),hl call getsix LD A,(SYS+6) RES 5,A BIT 1,A JR Z,CFLZ SET 5,A CFLZ LD (SYS+6),A jp CYK7 ; Rolls the conveyors, flashes the items and plays the tune, waits for vsync, ; Then paints the willy on given xy position in BC in a weird manner: ; Where Willy is 1, bgstore background content will be drawn into screen ; Where Willy is 0, original screen content will be kept. ; Useld always with oldxypos in bc ; Input: c=X ; b=Y unpaintwilly ld bc,(oldxypos) ld a,c ; X position and 7 RRCA RRCA RRCA LD E,A ; Lowest 3 bits of position in highest 3 bits of E LD A,(SYS+6) AND 32 ADD A,255 SBC A,A AND 1 LD D,A call scaddr ; calculate screen address into HL from YX position in BC LD IX,willysprites ADD IX,DE ; IX address of the right Willy sprite LD DE,bgstorage CALL draw_belts_items ; this rolls the conveyors and flashes the items call tune ; Itself waits for an interrupt and then disables it back. ld b,16 ; b counter (16) ; ix Willy addr ; hl screen addr ; de background addr in bgstorage pwcyc ld a,(DE) ; Take the background from the bgstorage inc DE ; Move the background pointer xor (HL) ; XOR-AND-XOR with screen content and (IX+0) ; Where Willy is 1, bgstore background content will be drawn into screen ; Where Willy is 0, original screen content will be kept. INC IX xor (HL) ld (hl),a ; Put back to the screen inc hl ;Not supposed to roll over ld a,(DE) inc DE XOR (HL) and (IX+0) INC IX xor (HL) ld (hl),a dec hl inc h ld a,h and 0x07 call z,fixhl djnz pwcyc ; 16 times ret ; Get Background from Screen ; gets background 16x16 pixels aligned at vertical 8 pixels (whole bytes) ; puts it into bgstorage directly ; bc - input coords in pixels getbgfromscrn ld bc,(newxypos) ld de,bgstorage call scaddr ld bc,0x10ff ; b 16 cycles, C 255 because LDI decrements C, and 255 is max value. nn ; a counter (16) ; bc screen coords ; hl screen addr ; de background storage addr ldi ; decrements c! Must be guard value in C. ldi ; decrements c! Must be guard value in C. dec hl ; This cannot be dec l since it can overflow when ; the guy is at the right edge of the screen. dec hl inc h ld a,h and 0x07 call z,fixhl djnz nn ret ; Calculates willy sprite position from his new positions and facing direction ; Prints him into the screen on his new position by oring with the screen content ; Input: none opbs ld a,(newxpos) ; Willy's new XY positions in pixels and 7 ; Take the lowest 3 bits rrca rrca rrca ; Multiply by 32 ld e,a ld a,(SYS+6) and 2 ; Which way he is looking rrca ld d,a push bc ld bc,willysprites ex de,hl add hl,bc ex de,hl pop bc call scaddr ld b,16 ; 16 pixels height opbs1 ld a,(de) ; de = Willy sprint address inc de or (hl) ; hl = screen address ld (hl),a inc hl ; never crosses the boundary ;inc l ld a,(de) ; right, second byte inc de or (hl) ld (hl),a dec hl inc h ld a,h and 7 call z,fixhl djnz opbs1 ret ; input - hl after h was incremented to go 1 pixel lower ; and h&7 happened to be 0 ; output - hl - corrected hl so it really points 1 pixel lower how ; it was intended fixhl ld a,l add a,0x20 ld l,a ret c ; l overflowed, the original value of h is OK ld a,h sub 0x08 ld h,a ret ; Calculate screen address ; Input: bc ; Output: hl ; Clobbers: af scaddr ld a,b rrca rrca rrca ld l,a xor b and 248 xor b and 31 or 64 ld h,a ld a,l xor c and 7 xor c rrca rrca rrca ld l,a ret SCRADR DEFS 2 ATTADR DEFS 2 IRMADR DEFS 2 ; Prints a room. Layout - lines: ; 0-19: room ; 20 - empty ; 21 - room name ; 22 - empty ; 23: Items collected: xxxx PRTSCRN LD HL,16384 LD (SCRADR),HL LD H,22528/256 LD (ATTADR),HL LD HL,(croomaddr) LD DE,32 ADD HL,DE LD (IRMADR),HL LD BC,320 ; 32 chars wide, 20 high, 2 chars per byte PRTS1 LD HL,(IRMADR) LD A,(HL) CALL PRCHAR LD HL,(IRMADR) LD A,(HL) INC HL LD (IRMADR),HL RRCA RRCA RRCA RRCA CALL PRCHAR DEC BC LD A,B OR C JP NZ,PRTS1 LD HL,(croomaddr) LD DE,356 ADD HL,DE EX DE,HL LD HL,20640 ; Screen target address of the room name LD BC,32 CALL PRINT ; Print the room name LD HL,belts_items_list LD DE,belts_items_list+1 LD BC,159 LD (HL),0 LDIR LD IX,(croomaddr) LD A,(IX+13) AND 7 RLCA LD C,(IX+4) LD E,(IX+6) CALL PRP1 LD (BTSR),BC LD C,E CALL PRP1 LD (BTSL),BC LD BC,320 LD IX,belts_items_list-5 XOR A LD (ENTS),A INC A LD (STEP),A LD HL,(croomaddr) LD DE,32 ADD HL,DE LD DE,16384 PRTS2 LD A,(HL) CALL TZNAK CALL POSDE LD A,(HL) RRCA RRCA RRCA RRCA CALL TZNAK CALL POSDE INC HL DEC BC LD A,B OR C JR NZ,PRTS2 RET POSDE INC E RET NZ LD A,D ADD A,8 LD D,A RET ; Loads conveyor contents PRP1 LD B,0 SLA C RL B SLA C RL B SLA C RL B LD IX,CHARSET ADD IX,BC LD C,(IX+0) LD B,(IX+2) RET STEP DEFS 1 ENTS DEFS 1 TZNAK PUSH BC PUSH HL AND 15 LD B,A LD A,(ENTS) CP 32 JP NC,TZRET LD A,B CP 6 JP Z,TZITEM CP 2 JP Z,TZPRIG CP 3 JP NZ,JZNAK TZPLEF LD A,(STEP) RRCA JP C,PLSTP LD A,(IX+2) AND 192 CP 64 JP NZ,PLSTP LD A,(IX+0) AND 31 LD B,A LD A,(IX+2) AND 63 ADD A,B CP 32 JP NC,PLSTP INC (IX+2) JP TZRET PLSTP LD HL,(BTSL) LD (IX+7),65 JP CMSTP TZPRIG LD A,(STEP) RRCA JP C,PRSTP LD A,(IX+2) AND 192 JP NZ,PRSTP LD A,(IX+0) AND 31 LD B,A LD A,(IX+2) AND 63 ADD A,B CP 32 JP NC,PRSTP INC (IX+2) JP TZRET PRSTP LD (IX+7),1 LD HL,(BTSR) CMSTP LD BC,5 ADD IX,BC LD (IX+0),E LD (IX+1),D LD (IX+3),L LD (IX+4),H XOR A LD (STEP),A LD A,(ENTS) INC A LD (ENTS),A JP TZRET TZITEM LD BC,5 ADD IX,BC LD (IX+0),E LD A,D RRCA RRCA RRCA AND 3 OR 88 LD (IX+1),A LD (IX+2),128 ; Set bit 7 - means item. ld a,r LD (IX+3),A LD A,1 LD (STEP),A LD A,(ENTS) INC A LD (ENTS),A TZRET POP HL POP BC RET JZNAK LD A,1 LD (STEP),A JP TZRET ; Prints the lower 4 bits as a room character. PRCHAR AND 15 RLCA LD HL,(croomaddr) ADD A,L LD L,A ADC A,H SUB L LD H,A LD A,(HL) INC HL LD E,(HL) LD HL,(ATTADR) LD (HL),E INC HL LD (ATTADR),HL LD E,A LD D,0 SLA E RL D SLA E RL D SLA E RL D LD HL,CHARSET ADD HL,DE LD DE,(SCRADR) PUSH BC LD B,8 PRCH1 LD A,(HL) LD (DE),A INC HL INC D DJNZ PRCH1 POP BC LD HL,(SCRADR) INC L LD (SCRADR),HL RET NZ LD A,H ADD A,8 LD (SCRADR+1),A RET PRTNR LD DE,FCIFS LD HL,(itemsbcd) CALL ONEB LD H,L CALL ONEB prtfcifs ld hl,numberdest ld de,fcifs ld bc,4 call print ret ;ZNAKY ;MENI:DE,HL,A ONEB LD A,H RRCA RRCA RRCA RRCA CALL ASCII LD (DE),A INC DE LD A,H CALL ASCII LD (DE),A INC DE RET ASCII AND 15 ADD A,48 RET GRCHAR call GCHAR ex de,hl ld hl,(croomaddr) ld b,0 sla a ld c,a add hl,bc ld c,(hl) inc hl ld a,(hl) push af ld hl,CHARSET sla c rl b sla c rl b sla c rl b add hl,bc ex de,hl ld b,h ld c,l sla c sla c sla c sla b sla b sla b call scaddr call ATTRADDR pop af ret ; retval in a ; if l>31 or h>19, returns 0 ; Preserves bc, de, hl GCHAR ld a,31 cp l jr c,gchar1 ld a,19 cp h jr c,gchar1 push hl push de call ROOMADDR or a ld a,(hl) jr z,PR3 rrca rrca rrca rrca PR3 pop de pop hl and 15 ret gchar1: xor a ret ; Input: H - Y coord in chars (5 bits) ; L - X coord in chars (5 bits) ; Output - HL=32+croomaddr+16*y+(x>>1), ; where x and y are treated as signed. ; A - lowest bit of input x coord ; BC, DE is preserved ROOMADDR push bc ld c,h ; hl=((int)l)>>1 xor a sra l rla push af ; Save the lowest bit for return ld a,l add a,a sbc a,a ld h,a ; bc=((int)c)<<4 sla c sbc a,a ld b,a sla c rl b sla c rl b sla c rl b add hl,bc ; Add together ld bc,(croomaddr) add hl,bc ; Add the current room address ld bc,32 ; Skip the charset at the beginning ; OPTIM - replace with inc h, inc h at the beginning! add hl,bc pop af pop bc ret ATTRADDR ld a,h rrca rrca rrca and 3 or 88 ld b,a ld c,l ret ; Input H - y addr (pixels) of the Willy position ; Input L - x addr (pixels) of the Willy position ; The Willy is apparently allowed to stick couple of pixels off the screen boundary. ; Clobbers HL, IX, IY, AF getsix: push bc ld b,h ld c,l ; Convert pixels to chars srl h srl h srl h srl l srl l srl l ld a,b cp 223 jr c,XXB ; Willy sticks out from the top. ld h,255 XXB ld a,c cp 253 jr c,XXC ; Willy sticks out from the left. ld l,255 XXC: push hl ld b,l call ROOMADDR push hl pop ix ld iy,six ; In even case, the left column is loaded loaded without rotation, the right one with rotation ; In odd case, the left column is loaded with rotation, the right one without rotation from a higher address. ; Let's assume IX is source and IY destination. to make the rotations static in the code: ; In even case, the unrotated is loaded from IX, IX+16 and IX+32 and put into IY, IY+2 and IY+4. ; In odd case, the unrotated is loaded from 1+IX, 1+IX+16 and 1+IX+32 and put into 1+IY, 1+IY+2 and 1+IY+4. ; In even case, the rotated is loaded from IX, IX+16 and IX+32 and put into IY+1, IY+3, IY+5 ; In odd case, the rotated is loaded from IX, IX+16 and IX+32 and put into IY, IY+2 and IY+4 ; There will be a core code that will load unrotated from IX, IX+16 and IX+32 and put into IY, IY+2 and IY+4 ; and then load from IX, IX+16 and IX+32 and put into IY, IY+2 and IY+4. ld a,b and 1 jr z,getsix1 ; Even jumps */ inc ix inc iy getsix1: ; Get the unrotated column ld a,(IX+0) ld (IY+0),a ld a,(IX+16) ld (IY+2),a ld a,(IX+32) ld (IY+4),a jr z,getsix2 ; Even jumps dec ix dec iy jp getsix3 getsix2: inc iy getsix3: ; Get the rotated column ld a,(IX+0) rrca rrca rrca rrca ld (IY+0),a ld a,(IX+16) rrca rrca rrca rrca ld (IY+2),a ld a,(IX+32) rrca rrca rrca rrca ld (IY+4),a ; Fix the contents of six - take ; only lower 4 bits and apply an ; identity. ld b,6 ld hl,six getsix4: ld a,(hl) and 0xf cp 10 jr c, getsix5 cp 13 jr nc, getsix5 ; Apply the identity and 7 getsix5: ld (hl),a inc hl djnz getsix4 ; Here B will be 0. We use that now: ; If the right column pops out of the screen, ; zero it out pop hl ld a,l cp 31 jr c,getsix7 ; Now the x is popping out somewhere ; 31 (right pop) or 255 (left pop) here ld ix,six jp m,getsix6 ; 31 (right pop) here inc ix ; Clear the right column instead of the left one getsix6: ld (ix+0),b ld (ix+2),b ld (ix+4),b getsix7: ld a,h cp 18 jr c,getsix9 ; 18 (bottom pop) or 255 (top pop) here. ld ix,six jp m, getsix8 ; 18 (bottom pop) here ld (ix+4),b ld (ix+5),b jp getsix9 getsix8: ld (ix+0),b ld (ix+1),b getsix9: pop bc ret OVLADANI ld d,0 ld b,2 ld c,3 call PASNEKAM or a jr z,U40 inc d jr U40A U40 ld b,3 ld c,2 call PASNEKAM or a jr z,U40A dec d U40A ld hl,SYS+6 ld a,(SYS+15) ld e,a or 252 inc a ld a,e jr z,NAV2 bit 0,a jr z,NAV1 inc d set 1,(hl) NAV1 bit 1,a jr z,NAV2 dec d res 1,(hl) NAV2 ld a,d or a jr z,SNV2 jp m,SNV3 ld a,1 set 1,(hl) ld d,a ex af,af' call TESTR ex af,af' jr SNV2 SNV3 ld a,255 res 1,(hl) ld d,a ex af,af' call TESTL ex af,af' SNV2 ld hl,oldxypos add a,(hl) inc hl inc hl ld (hl),a ld a,e bit 4,a jr z,KONEC1 ld hl,jumppos inc (hl) ld a,d or a jr nz,SNV1 xor a ld (unk7),a jr KONEC1 SNV1 ld a,255 ld (unk7),a ld hl,SYS+6 jp m,SNV4 res 2,(hl) jr KONEC1 SNV4 set 2,(hl) KONEC1 ret SKOK ld a,(jumppos) ; Jump position or a jr z,KONEC2 cp njumppos+1 jr nz,U16 xor a ld (jumppos),a jr KONEC2 U16 ld c,a ld b,0 ld hl,jumptable sla c rl b add hl,bc dec hl dec hl ld a,(hl) ex de,hl ld hl,oldypos add a,(hl) ld (newypos),a ex de,hl inc hl ld de,SYS+6 ld a,(de) bit 2,a ld a,(hl) jr z,PR4 neg PR4 ld hl,unk7 and (hl) ld hl,oldxypos add a,(hl) ld (newxpos),a ld hl,jumppos inc (hl) KONEC2 ret edge ld c,0 push bc VYLZNOV ld de,(newxypos) ld a,e cp 249 jr c,U19 ld a,252 cp e jr c,U19 ld e,0 ld bc,355 jr U22 U19 ld a,e cp 253 jr c,U20 ld a,255 cp e jr c,U20 ld e,248 ld bc,354 jr U22 U20 ld a,d cp 145 jr c,U21 ld a,200 cp d jr c,U21 ld d,0 ld bc,353 jr U22 U21 ld a,d cp 201 jr c,KONEC3 ld a,255 cp d jr c,KONEC3 ld d,136 ld bc,352 jr U22 KONEC3 pop bc ld a,c ret U22 ld hl,(croomaddr) add hl,bc ld a,(hl) ld (currentroom),a ld (newxypos),de pop bc ld c,1 push bc ex de,hl ld (oldxypos),hl ld (enterpos),hl ld hl,(jumppos) ld (unk11),hl ld hl,(unk7) ld (unk13),hl ld a,(currentroom) ld l,0 ld h,a ld c,a ld b,0 sla c rl b sla c rl b add hl,bc ld b,a ld c,0 srl b rr c add hl,bc NAVES4 ld bc,roomdefs add hl,bc ld (croomaddr),hl call PRTSCRN jp VYLZNOV MUZPAD ld a,(oldxpos) ld d,a ld a,(oldypos) ld e,a and 7 jr nz,U24 ld a,d and 7 jr z,U23 ld a,(six+5) or a jr z,U23 cp 5 jr z,U23 cp 6 jr z,U23 cp 15 jr z,U23 cp 8 jr z,U23 jp KONEC5 U23 ld a,(six+4) or a jp z,KONEC4 cp 5 jp z,KONEC4 cp 6 jr z,KONEC4 cp 15 jr z,KONEC4 cp 7 jr nz,KONEC5 ld a,d and 7 jr nz,KONEC4 jr KONEC5 U24 ld a,d and 7 jr z,U26 ld a,(six+5) cp 8 jr nz,U25 ld a,d and 7 ld b,a ld a,e and 7 add a,b cp 8 jr nc,KONEC5 jr U26 U25 ld a,(six+5) cp 7 jr nz,U26 ld a,d and 7 ld b,a ld a,e and 7 cp b jr c,KONEC5 U26 ld a,(six+4) cp 8 jr nz,U27 ld a,d and 7 ld b,a ld a,e and 7 add a,b cp 9 jr c,KONEC5 jr KONEC4 U27 ld a,(six+4) cp 7 jr nz,KONEC4 ld a,d and 7 ld b,a ld a,e and 7 cp b jr nc,KONEC5 jr KONEC4 KONEC5 ld hl,SYS+6 res 0,(hl) ret KONEC4 ld hl,SYS+6 set 0,(hl) ret NVDP ld a,(newypos) ld b,a cp 223 ret nc ld a,(oldypos) cp b jr nc,KONEC6 ld hl,SYS+6 bit 0,(hl) jr nz,BLV ld hl,(oldxypos) ld (newxypos),hl xor a ld (jumppos),a KONEC6 ret BLV ld hl,SYS+8 inc (hl) jr nz,KONEC6 dec (hl) ret ZED ld hl,(newxypos) call getsix ld a,(newypos) and 7 jr nz,U30 ld a,(newxpos) and 7 jr z,U29 jr U31 U30 ld a,(newxpos) and 7 jr z,U28 ld a,(six+1) cp 4 jr z,U32 ld a,(six+3) cp 4 jr z,U32 ld a,(six+5) cp 4 jr z,U32 U28 ld a,(six+4) cp 4 jr z,U32 U29 ld a,(six+2) cp 4 jr z,U32 ld a,(six) cp 4 jr z,U32 ret U31 ld a,(six) cp 4 jr z,U32 ld a,(six+1) cp 4 jr z,U32 ld a,(six+2) cp 4 jr z,U32 ld a,(six+3) cp 4 jr z,U32 ret U32 ld a,(oldxpos) ld hl,newxypos cp (hl) jr z,U33 ld a,(oldypos) ld hl,newypos cp (hl) jr z,U33 jr U34 U33 ld a,(oldypos) ld hl,newypos cp (hl) ld hl,(oldxypos) ld (newxypos),hl jr z,U35 xor a ld (jumppos),a U35 ret U34 ld a,(oldxpos) ld (newxpos),a jp ZED TESTR ld a,(newxpos) and 7 ld b,a ld a,(newypos) and 7 add a,b and 7 jr nz,U37 ld a,(newxpos) and 7 jr nz,U36 ld a,(six+3) cp 8 jr nz,U37 ld hl,newypos dec (hl) ret U36 ld a,(six+5) cp 8 jr nz,U37 ld hl,newypos dec (hl) ret U37 ld a,(newxpos) and 7 ld b,a ld a,(newypos) and 7 cp b ret nz ld a,(six+4) cp 7 ret nz ld hl,newypos inc (hl) ld hl,SYS+6 set 0,(hl) ret TESTL ld a,(newxpos) and 7 ld b,a ld a,(newypos) and 7 cp b jr nz,U38 ld hl,(newxypos) srl h srl h srl h srl l srl l srl l inc h dec l ld a,(newxpos) and 7 ld a,(six+4) call z,GCHAR cp 7 jr nz,U38 ld hl,newypos dec (hl) ret U38 ld a,(newxpos) and 7 ld b,a ld a,(newypos) and 7 add a,b and 7 ret nz ld a,(newxpos) and 7 ld a,(six+5) jr nz,U39 ld a,(six+4) U39 cp 8 ret nz ld hl,newypos inc (hl) ld hl,SYS+6 set 0,(hl) ret PASNEKAM ld a,(oldypos) and 7 ld a,0 ret nz ld a,(oldxpos) and 7 jr z,U43 ld a,(six+5) cp b jr z,U41 ld a,(six+4) cp b jr z,U42 jr KONEC7 U41 ld a,(six+4) cp c jr z,KONEC7 jr KONEC8 U42 ld a,(six+5) cp c jr nz,KONEC8 jr KONEC7 U43 ld a,(six+4) cp b jr nz,KONEC7 jr KONEC8 KONEC7 xor a ret KONEC8 ld a,1 ret KILL ld hl,(sctl2) push hl ld hl,(freq2) push hl ld hl,0x1280 ; Red, full volume ld (sctl2),hl ld hl,9000 ld b,9 CYK8 ld (freq2),hl call tune push hl pop de srl d rr e srl d rr e or a sbc hl,de djnz cyk8 pop hl ld (freq2),hl pop hl ld (sctl2),hl ld hl,(enterpos) ld (oldxypos),hl ld (newxypos),hl ld hl,(unk11) ld (jumppos),hl ld hl,(unk13) ld (unk7),hl call PRTSCRN jp VPADL ZABILSE ld a,(oldxpos) and 7 jr z,U48 ld a,(six+5) cp 5 jr z,KONECA ld a,(six+3) cp 5 jr z,KONECA ld a,(six+1) cp 5 jr z,KONECA U48 ld a,(six+4) cp 5 jr z,KONECA ld a,(six+2) cp 5 jr z,KONECA ld a,(six) cp 5 jr z,KONECA KONEC9 xor a ret KONECA ld a,1 ret tuneprefill ; Puts 0x10fe into the bc ; If DE is 0, puts 0 into HL, otherwise 0x80 ; Clobbers a ld a,d or e cp 1 ; nonzero -> nc, zero -> c sbc a,a ; nonzero -> 0, zero -> 0xff ld h,a ld l,a ; For de=0 hl=0xffff, otherwise 0x0000 ret calcfreq ; de - where to store the freq ; a - semitone no ; clobbers a, de or a jr z,silence sub 0x24 add a,a add a,halftones&255 push hl ld l,a adc a,halftones>>8 sub l ld h,a ldi ldi pop hl inc bc inc bc ret silence ld (de),a inc de ld (de),a ret ; Doesn't clobber anything. No input. Plays until interrupt comes. tune push af xor a push bc push de push hl ld bc,0x1080 tunea volume1 equ tunea-2 sborder1 equ tunea-1 ld de,(freq1) call tuneprefill exx push bc ; We need to store all because we don't know in what ; phase the exx will be when the interrupt hits push de push hl ld bc,0x1080 tuneb sctl2 equ tuneb-2 ; Total sound control volume2 equ tuneb-2 sborder2 equ tuneb-1 ld de,(freq2) call tuneprefill ld a,0x18 ; JR opcode ld (intpoke),a ei ; Zilog says during the paper, ULA reads for 6T every 8T and when ; you hit this time, you wait until ULA stops reading. tune1: ; 112 cycles total = 31.25 kHz exactly and is not slowed down by the ULA ; because it synchronizes on a 2-tick usable window every 8 ticks. ; The line is 224 ticks (15.625kHz, 64us), which is 28*8. ; Volume ratio of the two voices is 1:1 ld a,h ; 4 cp c ; 4 sbc a,a ;4 and b ; 4 add hl,de ; 11 out (254),a ; 11 exx ; 4 nop ; 4 jp tune1 ; 10 longjump: ; Interrupt jumps out of the tune1 loop. pop hl ; Discard the return address ld a,201 ; RET ld (intpoke),a xor a out (254),a ld a,(iter) dec a ld (iter),a jr nz, noadvance ; Next tone ld bc,(addr) ld a,(bc) ; First voice ld de,freq1 call calcfreq inc bc ld a,(bc) ; Second voice ld de,freq2 call calcfreq inc bc ; ld a,(bc) ; Length ; inc bc ld a,12 ld (iter),a ld a,b cp tuneend>>8 jr c,notuneend jr nz, tunereload ld a,c cp tuneend&255 jr c,notuneend tunereload: ld bc,tunestart notuneend: ld (addr),bc noadvance: pop hl pop de pop bc exx ld a,191 in a,(0xfe) or 0xf3 inc a jr z,vol_inactive cp -7 sbc a,a ld b,0xff or 1 ; -1 or +1 ld hl,volume1 add a,(hl) ; Inc or dec cp b ; Underflow -> nc sbc a,b ; nc->inc, c-> nothing cp 0x81 ; overflow -> nc adc a,b ; nc->dec, c-> nothing ld (hl),a ld (volume2),a vol_inactive: pop hl pop de pop bc pop af ret ; Prints a string from the system charset ; BC length of string - when it doesn't run out of screen, will ; be 0 ; HL screen address - will be advanced ; DE string source - will be advanced ; Clobbers AF PRINT PRIN2 LD A,B OR C RET Z LD A,H AND 0x18 OR 0x40 LD H,A CP 88 RET NC PUSH HL ; HL is the screen address LD A,(DE) INC DE PUSH DE LD E,A ; Charnum LD D,0 SLA E ; Mul by 8 RL D SLA E RL D SLA E RL D EX DE,HL PUSH BC LD BC,SYSCHARSET poke3 equ pke1-2 pke1 ADD HL,BC EX DE,HL LD B,8 mline LD A,(DE) LD (HL),A INC H INC DE DJNZ mline POP BC POP DE POP HL DEC BC INC L JP PRIN2 org 65524 jp longjump ; 3 bytes ; 65527 here, we can still stuff 8 bytes of variables here ;-) BTSR DEFS 2 BTSL DEFS 2 freq1 defw 0 ; Main voice freq2 defw 0 ; Second voice ORG 65535 intpoke RET ; Interrupt ret. Will be overpoked by a jr to when playing ; the (de)tune. The byte at addr. 0 is 243 (DI) and that causes ; a relative jump to 65524.