Skip to content

Instantly share code, notes, and snippets.

@svofski
Last active December 22, 2025 07:58
Show Gist options
  • Select an option

  • Save svofski/2181ff132772d60bcb464c0bbeab7b5b to your computer and use it in GitHub Desktop.

Select an option

Save svofski/2181ff132772d60bcb464c0bbeab7b5b to your computer and use it in GitHub Desktop.
тетрец
; Тетрис 512 байт для Вектора-06ц с кассетной загрузкой.
;
;
; Загружается начиная с адреса $db00, прямо в экранное ОЗУ
; стандартного загрузчика и перехватывает управление на себя.
;
; Особые зоны: DBA8..DBB2 - столбик (см. Around1)
; DCA8..DCB2 - столбик (см. Around2)
; DCEC.. - важно для 512-байт загрузчика
; DCEE.. - перехват адреса возврата
;
; save autotetrec.bin
; bin2wav.js -s 0xdb00 -m v06c-rom -c 6 autotetrec.bin autotetrec.wav
;
;
; - svofski 2025
;
.project autotetrec
.tape v06c-rom
.org 0db00h
hook
CTAKAH_WIDTH .equ 10
CTAKAH_BOTTOM .equ 32
CTAKAH_TOP .equ $f0
SPEED .equ 15
SCRBASE .equ $c0
DELAYTIME .equ $def6 ; 512-b delay var
tetris_start:
lxi h, SCRBASE << 8
sphl
clrscr:
mvi m, 0
inx h
mvi a, SCRBASE+16
cmp h
jnz clrscr
call shuffle
;----
ct_p1 .equ $+1
mvi h, SCRBASE
lxi b, ((CTAKAH_BOTTOM - 16) << 8) | (SCRBASE + 2 + CTAKAH_WIDTH)
ct0:
mvi l, CTAKAH_TOP
ct1:
stc
call xor_box
mov a, b
cmp l
jnz ct1
inr h
mov a, c
cmp h
jnz ct0
mvi a, CTAKAH_BOTTOM - 8
cmp b
jz ctakah_done
mov b, a ; = CTAKAH_BOTTOM - 8
mvi h, SCRBASE + 1
dcr c
jmp ct0
ctakah_done:
xra a ; don't touch dots anymore
sta xorbox_dot
nextfigure:
lda bagidx
push psw
inr a
cpi 7
cz shuffle
sta bagidx
pop psw
mvi h, bag >> 8 ; bag is always in the same 256-byte column
adi bag & 255
mov l, a
mov e, m
mvi d, figS >> 8
xchg
shld fig_first
xchg
lxi h, ((SCRBASE<<8) + (5 << 8)) + CTAKAH_TOP
;ret
call draw_fig
jnz burial ; game ovah
new_step:
mvi b, SPEED
lopup:
call delay
; test if it's time for gravity
dcr b
jz will_move
; test if input available
in 1
ani $e0
cmp c
mov c, a
jz lopup
xri 7 << 5
jnz will_move
jmp lopup
; definitely trying to move
will_move:
call draw_fig ; erase figure in the old position
; save position and rotation
push h
push d
; gravity has priority over keys
xra a
ora b
jnz keyboard_input ; b != 0 -> keyboard
gravity:
mvi a, -8 \ add l \ mov l, a ; one cell down
jmp try_new_place
keyboard_input:
call tuktuk
mov a, c
ral
cnc rotate
ral
jc $+4
inr h ; move right
ral
jc $+4
dcr h ; move left
try_new_place:
call draw_fig ; draw in new place
jnz move_fail
move_success:
pop psw ; discard saved position and rotation
pop psw
xra a
ora b
jz new_step
jmp lopup
.org $dba8
db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x81,0x81
Around1:
move_fail:
call draw_fig ; erase in new place
pop d
pop h ; restore previous placement
call draw_fig ; draw figure
; was a gravity move?
xra a
cmp b
jz kollaps ; gravity: fix, collapse and get new figure
jnz lopup ; no, normal move
kollaps:
mvi l, CTAKAH_BOTTOM
kolup:
kolup_same:
; l = line to check for completeness
; return z: line has holes
check_line:
mvi h, SCRBASE + 1
mvi c, CTAKAH_WIDTH
mvi a, $fe
chln_loop:
ana m
inr h
dcr c
jnz chln_loop
ora a
;---
jz kolup_next
; L = top of the full line (x8/x0)
push h
mvi a, -7 ; set dst pointer to the bottom of the current row
add l
mov l, a
; move everything above L one line down
move_down:
mov e, l
mvi a, 8
add l
mov l, a
mdl0:
call tuktuk
mvi h, SCRBASE + 1
mov d, h
mdl1:
mov a, m \ inr h \ stax d \ inr d
mvi a, SCRBASE + 1 + CTAKAH_WIDTH
cmp h
jnz mdl1
inr e
inr l
mvi a, CTAKAH_TOP - 8
cmp e
jnz mdl0
;ret
pop h
jmp kolup_same
kolup_next:
mvi a, 8
add l
mov l, a
cpi CTAKAH_TOP
jnz kolup
;ret
jmp nextfigure
; shuffle, return a = 0
shuffle:
mvi c, 6
shufflelup:
push b
shuffle1:
call rndptr ; hl = some item
xchg
call rndptr ; hl = some item (could be the same item but meh)
ldax d \ mov b, a\ mov a, m\ stax d\ mov m, b
pop b
dcr c
jnz shufflelup
xra a
ret
rndptr:
; Псевдослучайное 8-битное число с периодом 256 по отношению: X[1] = X[0] * 5 + 7
; I: -
; O: A=RND
; M: HL, AF
rnd8:
lxi h, rnd8val
mov a,m
add a
add a
add m
adi 7
mov m,a
; limit to 0..6
ani $7
cpi 7
jnc rnd8
; add offset rel to bag
lxi h, bag
add l
mov l, a
ret
rnd8val db 1
bag: .db figS & 255, figZ & 255, figL & 255, figJ & 255, figI & 255, figB & 255, figT & 255
rotate:
inx d \ inx d
ldax d
inr a
rnz
fig_first .equ $+1
lxi d, 0
ret
xor_box:
push psw
push b
lxi b, $fe07
jc $+5
mvi b, 0
drxl1:
mov a, b
ora a
jz xb_nocollision ; also no change
; != 0, therefore a == $fe
xra m
mov m, a
; if z, there was a collision
jnz xb_nocollision
push h
lxi h, collision_flag
inr m
pop h
xb_nocollision:
dcr l
dcr c
jnz drxl1
xorbox_dot:
inr m ; dot, patch to 00 after drawing the ctakah
dcr l
pop b
pop psw
ret
; hl = x,y
; de = fig (4 bytes)
; return a = collision flag, flag nz = collision
draw_fig:
push b
push h
push d
xra a \ sta collision_flag
lxi b, $406
dfig_l1:
ldax d
inx d
dcr c ; 6->5, 3->2
dfig_l1x:
push h
push b
dfig_l2:
rar
call xor_box
dcr b
jnz dfig_l2
pop b
pop h ; restore coord
inr h ; next col
dcr c ; 5->4, po 4->3, pe 2->1, po
jz dfig_vse
jpo dfig_l1x
jmp dfig_l1
dfig_vse:
pop d
pop h
pop b
lda collision_flag
ora a
ret
db 0 ; RESERVE
db 0 ; RESERVE
db 0 ; RESERVE
.org $dc97
figS: ; dc97
db 0b01100000
db 0b00001100
db 0b11001000
db 0b00000100
db 255
figZ:
db 0b11000000
db 0b00000110
db 0b11000100
db 0b00001000
db 255
figI:
db 0b01000100
db 0b01000100
db 0b11110000
db 0b00000000
db 255
figB:
db 0b01100000
db 0b00000110
; db 255 -- THIS BYTE IS THE FIRST 0xFF IN THE FILLER BELOW
.org $dca8
db 0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x81,0x81
Around2:
figL:
db 0b01000100
db 0b00000110
db 0b11100010
db 0b00000000
db 0b01001100
db 0b00000100
db 0b11100000
db 0b00001000
db 255
figJ:
db 0b01000110
db 0b00000100
db 0b11100000
db 0b00000010
db 0b01000100
db 0b00001100
db 0b11101000
db 0b00000000
db 255
figT:
db 0b01100100
db 0b00000100
db 0b11100000
db 0b00000100
db 0b11000100
db 0b00000100
db 0b11100100
db 0b00000000
db 255
; BSS -- we don't really need them to be here, could be equ-ed elsewhere
collision_flag .equ $8001
bagidx .equ $8000
burial:
; draw theh dots again when repainting the bucket
call draw_fig
mvi e, 100
death_delay:
call delay
dcr e
jnz death_delay
mvi a, $34 ; = inr m
sta xorbox_dot
jmp tetris_start
; dce2 is the last safe address!
db 0 ; RESERVE
db 0 ; RESERVE
.org $dcea
dw hook
dw $0101 ; 512-byte loader compat
dw hook
delay:
push d
ei \ hlt
pop d
ret
nop
tuktuk: ; dcf6
mvi a, 0b00000001
out 0
xri 1
sta tuktuk+1
ret
.end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment