Etudes
Alone Coder
If a long operation is in progress and
there is nowhere to put an honest percentage meter (on─
for example, this would greatly slow down the work), then
you can write it like this:
ld a,r
add a,a
call showprogress
Now the percentage meter will be called in
128 times less often.
Used inZXRarand in graphic
editorScratch.
* * *
Reverse byte string (de=beginning,
bc=length):
ld h,b
ld l,c
add hl,de ;hl=end+1
srl b
rr c ;bc=wid/2
mirrorbytes0
dec hl
ld a,(de)
ldi
dec hl
ld (hl),a
jp pe,mirrorbytes0
* * *
Last time we didn't show how to prepare─
prepare for the cycle djnz:dec c:jr nz:
ld a,c
dec bc
inc b
ld c,b ;bc=1..256 => c=1,
;bc=257..512 => c=2...
ld b,a
* * *
In addition to the "Etudes" in #11 (there was
definition AY ) - determination of availability
TurboSound FM: it is important because the player
under TFM works with register hundred waiting─
tus, which is not on the regularAY.
Algorithm:
- turn on FM mode and reading mode
party.
- write the number from the setting to the 0th register─
bit 7.
- We are waiting a little.
- read the register, look at the 7th bit.
If it's a zero, then it'sTFM,and it's ready. A
if not (that isпрочиталось записанное
число или пустая шина), то это не TFM.
В Evo SDK это выглядит так:
LD BC,#FFFD
LD A,%11111000
OUT (C),A ;FM on,status rg read on
ld d,b
dec d
jr nz,$-1 ;pause
XOR A
OUT (C),A ;select rg 0
dec d
jr nz,$-1 ;pause
LD B,#BF
OUT (C),B ;write some data in rg 0
dec d
jr nz,$-1 ;pause
inc a ;a=1
LD B,#FF
INF ;read status (P=ready)
JP P,tfmpresent ;a=1
xor a ;TFM not presenttfmpresent
ld (TURBOFMON),a
NB: with the current implementation of whites in
ZX Evocannot work withTFMat frequency 14
MHz. It is necessary to temporarily enable 3.5 MHz at
working with ports TFM!Otherwise the sound will deteriorate.
This cannot be detected in the emulator!
* * *
Our regular readers remember the terms─
addition with a constant for a fixed
time:
;CY=flag
;a=initial value
jc $+4
jr $+4
add a, which is conditionally added
;a=result
:19 t
Let's supplement it with conditional addition from the register─
strom for a fixed time:;CY=flag
;a=initial value
;b=what to conditionally add
jr c,$+6
nop
jp $+5
ret nc
add a,b
;a=result
:21 t
Or like this:
;CY=flag
;c=initial value
;b=what to conditionally add
sbc a,a
and b
[add a,c] ;not necessary if initially 0
ld c,a
;a=result
:12(16) t
* * *
How to move to the next EGA column
screen on ATM-Turbo (if the screen is connected
at 4000, 8000):
lda,0x9f ;0xa0,if not used
;top 8 lines
cp h
ld bc,0x4000
adc hl,bc
jp pe,nextstq ;in half the cases
;8000->с000 (need 6000)
;or a000->e001 (need 4001)
inc a ;if we use the top 8 lines
xor h
ld h,a
nextstq
If the screen is connected at 8000, c000, then
the transition can be done like this:
bit 6,h
set 6,h
jr z,$+2+4+2+2+1
ld a,h
xor 0x60
ld h,a
and 0x20
jr nz,$+3
inc hl
In some cases it is more profitable for everyone 4
options for the location of the sprite in X sde─
barkсвою ветку запоминания адресов в
стек, например (в Супер Марио ):
macro COUNTSCRADDR
add a,(hl)
inc h
ld c,a
adc a,(hl)
sub c
ld l,c
endm
macro NEXTCOLUMNS0
ld h,a ;.00
push hl
set 6,h ;.10
push hl
xor 0x20
ld h,a ;.01
push hl
set 6,h ;.11
endm
macro NEXTCOLUMNS1
ld c,a
xor 0x40
ld h,a ;.10
push hl
xor 0x60
ld h,a ;.01
push hl
set 6,h ;.11
push hl
ld h,c ;.00
inc hl
endm
macro NEXTCOLUMNS2
ld h,a
set 5,h ;.01
push hl
set 6,h ;.11
push hl
ld h,a ;.00
inc hl
push hl
set 6,h ;.10
endm
macro NEXTCOLUMNS3
ld c,a
xor 0x60
ld h,a ;.11
push hl
ld h,c ;.00
inc hl
push hl
set 6,h ;.10
push hl
ld a,h ;не старое, т.к. был inc hl
xor 0x60
ld h,a ;.01
endm
prcharxy
;de=gfx
;la=yx
;CY=0
ld h,tytoscr/256
rra
jr c,prcharxy_nextcolumns13
rra
jr c,prcharxy_nextcolumns2
prcharxy_nextcolumns0
COUNTSCRADDR
NEXTCOLUMNS0
jp prcharxy_scrok
prcharxy_nextcolumns2
COUNTSCRADDR
NEXTCOLUMNS2
jp prcharxy_scrok
prcharxy_nextcolumns13
srl a
jr c,prcharxy_nextcolumns3
prcharxy_nextcolumns1
COUNTSCRADDR
NEXTCOLUMNS1
jp prcharxy_scrok
prcharxy_nextcolumns3
COUNTSCRADDR
NEXTCOLUMNS3
prcharxy_scrok
3 addresses are remembered, the fourth remains─
in registers. Sprite width in this game
is 8 pixels, but this is not a limitation
method, but a feature of the code of the game itself. B
Evo SDKeach layer of the screen is drawn
entirely, and 4 addresses are also remembered there.
In the flooded 3D engine underATM-Turbo 2is─
uses this code:
ld (hl),a ;0x0000
set 6,h
ld (hl),a ;0x4000
add hl,bc ;bc=0xe000
ld (hl),a ;0x2000
set 6,h
ld (hl),a ;0x6000
add hl,de ;de=0xa001
To save a register pair, you can
rewrite tosbc hl,bc ... add hl,bc: inc
hl or on res 6,h:set 5,h ... add hl,bc.
* * *
How to return errors from procedures to─
top? I usually go to the original by mistake
point of the program with stack recovery. But
let us want error handling with correct─
freeing up resources.
Let the error be returned as CY=1.
The simplest method in the iS-DOS style:
call proc1
ret c
call proc2
ret c
jp proc3
You can even return the error type
in some register through everything about─
procedures.
In many practical cases, everything is
held - just assign─
typeld rp,()andld (),rp,which are not
change flags. Therefore you can write like this:
call proc1
call nc,proc2
ret c
jp proc3
(Used in GIF converter by DIS/
XPJ .)
But here, if we want to return the error type─
ki, we'll have to ban the use of this
case in assignments.
* * *
How can you do the procedure for capturing re─
resource (for example, opening a file) that
will free it itself at the exit from the block:
openresource
;if success, autopush closeresource
;out: nz=error
...open resource (out: nz=error)...
ret nz ;error
ld hl,closeresource
ex (sp),hl
jp (hl)
closeresource
;out: nz=error
...close resource (out: nz=error)...
ret
Использование:
work_with_resource
;out: nz=error
call openresource1
ret nz ;error
call openresource2
ret nz ;error
...work with resources 1 and 2...
ret
Применяется в Nedovigator'е.
* * *
Опять-таки в дополнение к "Этюдам" в
#11 - ещё один способ вызова функции по
номеру (номеразаняты не подряд):
;a=команда
ld hl,tcmds ;адрес списка команд
ld bc,ncmds ;число команд в списке
cpir
jp nz,ошибка
add hl,bc
add hl,bc
add hl,bc
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
jp (hl)
Список команд:
tcmds
db 'a'
db 's'
db 'd'
...
db 'x'
ncmds=$-tcmds
;дальше в обратном порядке лежат адреса
;обработчиков:
dw PROC_x
...
dw PROC_d
dw PROC_s
dw PROC_a
Used inNedoOS - due to support
command numbers fromCP/MandMSX-DOS.The most
Frequent commands are at the beginning of the listCPIR.
When the command numbers are consecutive, CPIR already
not needed, just going through the table is enough.
It's much faster!
Here is an option from NEO SPECTRUMAN:
ld h,tab ;7
ld h,(hl) ;7
jp (hl) ;4
And here fromSuper MariounderNedoOS:
;ld l,a
or 0xc0 ;7
ld h,a ;4
jp (hl) ;4
Share your thoughts about the article