; Rub-1K's Cube ; Rubik's cube for the unexpanded ZX81 ; Controls ; A-I : move disc forward ; Shift A-I : move disc backwards ; X-Y-Z : rotate cube forward ; Shift X-Y-Z : rotate cube backwards ; N : start with New cube ; R : Randomize cube ; 12 bytes free reused for keypresstable org #4009 ; in LOWRES more sysvar are used, but in this way the shortest code ; over sysvar to start machinecode. This saves 11 bytes of BASIC basic ld h,dfile/256 ; highbyte of dfile jr init1 db 236 ; BASIC over DFILE data rtab db 212,28 ; rotation table goes over sysvar db 126,143,0,18 eline dw last chadd dw last-1 db 0,0,0,0,0,0 ; x berg db 0 ; x mem db 0,0 ; x OVERWRITTEN ON LOAD init1 ld l, dfile mod 256 ; low byte of dfile jr init2 lastk db 255,255,255 margin db 55 nxtlin dw basic ; BASIC-line over sysvar db 0,0 flagx db 0 db 0,0,0 ; x db 0,0,0 ; x frames dw 65535 init2 jp init4 ; overwrite sysvar db 0,0 cdflag db 64 start ld hl,keytab ; first free part of space, not needed anymore ld c,6 ; 6 sides of a cube setcube ld b,9 ; 9 fields per side setside ld (hl),c ; write colour to field inc hl ; go to next field djnz setside ; do 1 side dec c ; do next side jr nz,setcube ; all colours in field set in 54 bytes of data disp ld de,disptab ; the locations to display ld sp,#4400 ; error key needs reset SP ld c,3 ; show 3 sides, side 1, 2 and 3 nside ld b,9 ; 9 fields per side nfield call field ; get current data, fieldvalue returned in A add a,28 ; numbers only on the cube for now, shortest code ex de,hl ld e,(hl) ; get position on screen ex de,hl ld h,t1/256 ; full screenaddress ld (hl),a ; write to screen inc de ; get next screenpointer djnz nfield ; do next field dec c jr nz,nside ; do next side w4up inc a ; test for key up status ld d,a ; key up is always zero nokey ld bc,(lastk) ; get last key pressed ld a,c ; preload for keytest jr nz,w4up ; wait for no key pressed inc a jr z,nokey ; test any key pressed sra b ; ROM has wrong order scf ; we need C set, read only unshifted table call #7c1 ; get unshifted key ld a,254 in a,(254) ; read shift rra ld a,(hl) ; get keycode inc d ; 1 move jr c,nosh ; no shift pressed ld d,3 ; -1 move nosh cp "X"-27 jr nc,shview ; shift cube view with X, Y or Z cp "N"-27 jp z,start ; restart with new cube cp "R"-27 call z,random ; randomize the cube call keya2i d1 jr disp ; show new situation ; d = nr moves shview ld hl,#4000-61*3 fstep inc hl inc hl inc hl dec a jr nz,fstep ; HL now correct step3 table ld e,3 ; set 3 disc to turn ndisc push de ; nr moves and remaining discs push hl ld a,(hl) ; get disc letter call keya2i ; move disc pop hl inc hl ; go to next disc pop de dec e ; test end all discs jr nz,ndisc ; cube rotated jr d1 ; back to display rsrf ld a,(hl) and 15 ld d,a ld a,(hl) rlca rlca rlca rlca and 15 ld b,a ret field push bc ; save fieldcoordinates ld hl,keytab-10 ; start of field ffield inc hl ; always 1 field further djnz ffield ld a,c ld c,9 ; BC now 9, side size fside add hl,bc ; always 1 side further dec a jr nz,fside ld a,(hl) ; get colour on this field pop bc ; retrieve fieldcoordinates ret ; this table will write a field on a side to the right position on the visible screen disptab db s9 mod 256, s8 mod 256, s7 mod 256 db s6 mod 256, s5 mod 256, s4 mod 256 db s3 mod 256, s2 mod 256, s1 mod 256 db f9 mod 256, f8 mod 256, f7 mod 256 db f6 mod 256, f5 mod 256, f4 mod 256 db f3 mod 256, f2 mod 256, f1 mod 256 db t9 mod 256, t8 mod 256, t7 mod 256 db t6 mod 256, t5 mod 256, t4 mod 256 db t3 mod 256, t2 mod 256, t1 mod 256 ; The screen space equ #4105+dfile-t1-$ ds space ; all t1..f9 must be on same highbyte, still codeable ; the display of 3 visible sides of the cube dfile db 118 db "R"+101,"U"+101,"B"+101,150,157,"K"+101,0,129,128,128,128,128,128,128,128,128,128,128,118 db 0,0,0,0,46,0,129,1 t1 db 0,129,1 t2 db 0,129,1 t3 db 0,129,7,128,118 db 0,0,0,0,0,129,128,128,128,128,128,128,128,128,128,128 s3 db 0,128,118 db 0,0,45,0,129,1 t4 db 0,129,1 t5 db 0,129,1 t6 db 0,129,7,128,135,128,118 db 0,0,0,129,128,128,128,128,128,128,128,128,128,128 s2 db 0,128,7,128,118 db 44,0,129,1 t7 db 0,129,1 t8 db 0,129,1 t9 db 0,129,7,128,135,128 s6 db 0,128,118 db 0,133,128,128,128,128,128,128,128,128,128,128 s1 db 0,128,7,128,135,128,118 db 0,133,7,3,132,7,3,132,7,3,132,128,135,128 s5 db 0,128,7,128,118 db 43,133,5 f1 db 0,133,5 f2 db 0,133,5 f3 db 0,133,128,7,128,135,128 s9 db 0,128,118 db 0,133,130,131,129,130,131,129,130,131,129,128 s4 db 0,128,7,128,135,128,118 db 0,133,7,3,132,7,3,132,7,3,132,128,135,128 s8 db 0,128,128,1,118 db 42,133,5 f4 db 0,133,5 f5 db 0,133,5 f6 db 0,133,128,7,128,135,128,1,118 db 0,133,130,131,129,130,131,129,130,131,129,128 s7 db 0,128,128,1,118 db 0,133,7,3,132,7,3,132,7,3,132,128,135,128,1,118 db 41,133,5 f7 db 0,133,5 f8 db 0,133,5 f9 db 0,133,128,128,1,118 db 0,133,130,131,129,130,131,129,130,131,129,128,1,118 db 0,2,3,3,3,3,3,3,3,3,3,1,118 db 0,0,0,40,0,0,39,0,0,38,118 db 118,118 db 118 db 118,118,118 random ld de,#110 ; do 16 random turns rdisc push de ld hl,(frames) seed ld bc,0 add hl,bc inc hl ld a,h and #1f ld h,a ld (seed+1),hl ld a,(hl) frnd sub 9 jr nc,frnd add a,9+"A"-27 call keya2i ; move disc pop de dec e ; test end all discs jr nz,rdisc ; cube rotated ret keya2i ld hl,#4000+10 ; valid keytable seek ld b,l dec l jp m,d1 ; end of table reached, invalid key cp (hl) jr nz,seek ; read until found or end reached ld a,d ; A holds nr of moves ld hl,movtab-21 ld de,21 ftab add hl,de djnz ftab ; HL now correct movetable shloop push af ; save counter push hl ; save tabel mside call rsrf ; read sides ld e,d ld c,b ; side in C and E inc hl mfield call rsrf ; fields in B and D push bc ; save FROM push de ; save TO push hl ; save table call field ; calculate FROM ld b,d ; get parameters for TO ld c,e ex de,hl ; save FROM fieldaddress call field ; calculate TO fieldaddress ld a,(de) ; get FROM ld (hl),a ; write TO pop hl ; retrieve table inc hl ; point to next field in table pop de ; get TO parameters pop bc ; get FROM parameters fcnt ld a,0 inc a ld (fcnt+1),a sub 3 ; do 3 fields per side jr nz,mfield ld (fcnt+1),a scnt ld a,0 inc a ld (scnt+1),a sub 5 ; do 5! sides (1 side is buffered) jr nz,mside ld (scnt+1),a ; rotate sides ld a,(hl) ; get rotationcode and 15 ; make it nr of rotations ld e,a ld a,(hl) ; get rotationcode rrca rrca rrca rrca and 15 ; make it the side to rotate ld c,a ; side to c step push de ld b,5 ; use midfield as buffer call field ld a,(hl) ; get field 5 push af ; save field ld d,h ; set midfield as previous ld e,l ld hl,rtab ; the fields to rotate dorot ld b,(hl) ; get next field push hl call field ; calculate address ld a,(hl) ; move to previous address ld (de),a ld d,h ; new address becomes previous ld e,l pop hl ; get rotatetable ld a,(hl) inc hl cp 5 jr nz,dorot ; test end reached pop af ; repair switch field ld (de),a pop de dec e ; 1 rotattion is 2 steps, -1 rotation is 6 steps, no rotation = 8 steps (full round) jp nz,step pop hl ; retrieve movetable pop af ; retrieve direction dec a ; -1 = +3 moves of disc jp nz,shloop ret ; fieldnumbering ; +---+ side numbers ; !123! 1 ; !456! 2345 ; !789! 6 side 7 has 3 fields as buffer ; +---+---+---+---+ ; !123!123!123!123! ; !456!456!456!456! ; !789!789!789!789! ; +---+---+---+---+ ; !123! ; !456! ; !789! ; +---+ ; show side 1,2 and 3 ; ft rotate side nr movtab db #27,#71,#82,#93, #52,#77,#88,#99, #45,#77,#88,#99, #34,#77,#88,#99, #73,#17,#28,#39, #66 ; D db #27,#41,#52,#63, #52,#44,#55,#66, #45,#44,#55,#66, #34,#44,#55,#66, #73,#14,#25,#36, #38 ; E db #27,#11,#22,#33, #52,#11,#22,#33, #45,#11,#22,#33, #34,#11,#22,#33, #73,#11,#22,#33, #12 ; F db #17,#31,#62,#93, #21,#33,#66,#99, #62,#33,#66,#99, #46,#73,#46,#19, #74,#17,#24,#31, #36 ; A db #17,#21,#52,#83, #21,#22,#55,#88, #62,#22,#55,#88, #46,#82,#55,#28, #74,#18,#25,#32, #38 ; B db #17,#11,#42,#73, #21,#11,#44,#77, #62,#11,#44,#77, #46,#91,#64,#37, #74,#19,#26,#33, #52 ; C db #17,#71,#82,#93, #51,#97,#68,#39, #65,#39,#26,#13, #36,#13,#42,#71, #73,#11,#24,#37, #26 ; G db #17,#41,#52,#63, #51,#84,#55,#26, #65,#68,#55,#42, #36,#26,#55,#84, #73,#12,#25,#38, #38 ; H db #17,#11,#22,#33, #51,#71,#42,#13, #65,#97,#84,#71, #36,#39,#68,#97, #73,#13,#26,#39, #42 ; I ; each table 21 bytes keytab db "D"-27,"E"-27,"F"-27,"A"-27,"B"-27,"C"-27,"G"-27,"H"-27,"I"-27,"X"-27,"Y"-27,"Z"-27 init4 ld (basic+3),hl ; repair lowres display ld hl,keytab ld de,#4000 ld bc,12 ldir ; set keytab over sysvar, saves 12 bytes ld hl,rottab ld e,rtab mod 256 ld c,9 ldir jp start ; start game, make screen over keytab rottab defb 1,2,3,6,9,8,7,4,5 ; move order of fields on rotated disc vars db 128 last equ $ end