Code - Etudes: Calling a function by number, Searching for text by number, Determining the presence of a music coprocessor, Installing a pixel on ATM Turbo 2, Libraries of procedures in ALASM, Short random number generator, Accelerating LD:PUSH.

Info Guide #11
Sketches
Alone Coder 

        1. Call a function by number

a)if the numbers are not consecutive:

;HL=function list 
   ;(number, address offset),
   ;0=end of the list, i.e. function 0 no
;C=function number 
#1624
 CALL #1bDC
 RET NC;function not found
LD D,0
 LD E,(HL);function address offset
 ADD HL,DE
 JP (HL)
 ...
#1bDB
INC HL
#1bDC
 LD A,(HL)
 AND A
 RET Z;end of list, function not found
CP C
INC HL
   JR NZ,#1бDB
   SCF
   RET

;пример списка функций: 
   DB 1
   DB 255&(func1-$)
   DB 10
   DB 255&(func10-$)
   DB 0;конец списка
;сами функции рядом: 
func1
   ...
   RET
func10
   ...
   RET

 б)если номера функций идут подряд (1,2,
...): 

;B=номер функции 
   DJNZ nofunc1
   
   RET
nofunc1
   DJNZ nofunc2
 
 RET
nofunc2
 ...
;for the last function the number is not checked 
;(maybe 0) 
 
 RET


             2. Search text
     (for example, messages) by number

a)option from ACEdit:

;HL=pointer to text list 
   ;(each text ends with 0) 
;D=text number (1..n) 
;returns HL = pointer to the desired text 
LD B,H;sufficiently large number
XOR A;end-of-text character
 DEC D
 RET Z
 CPIR; looking for the end of text character
         ;and put HL after it
JR $-4

 b)option in ROM 48 Basic
(only for ASCII, because the 7th bit is occupied by
end of text):

;DE=pointer to a list of texts 
   ;(each with bit 7 set
   ;in the last character)
;A=text number (0..n) 
;returns DE = pointer to the desired text 
#0C41
PUSH AF
 EX DE,HL
INC A
#0C44
 BIT 7,(HL)
INC HL
 JR Z,#0C44
DEC A
 JR NZ,#0C44
 EX DE,HL
 POP AF
 cp #20 ;this
 ret c ;for
ld a,(de);us
 sub #41 ;not important
 RET

;list exampletexts: 
#0095
 DB #BF ;any byte with
              ;7th bit (will be skipped)
 DB "RN","D"+#80
 DB "INKEY","$"+#80
 ...


          3. Availability determination
        music coprocessor

LD BC,#FFFD
 XOR A;A=0/2/4/7/11 (full 8-bit)
 OUT (C),A;avoid OUT (C),0
IN L,(C);oldRO
INC L
LD B,#BF
 OUT (C),L;newRO != oldRO
;read R0 and check if it has changed 
LD B,#FF;#fdfd not possible on ATM1
IN A,(C);R0
CP L;newRO
JR Z,AY_ON;R0 == newRO
AY_OFF
   Who can come up with a shorter idea without losing the joint─
Timiness?


           4. Pixel installation
      in 320x200 mode on ATM Turbo 2

   Since the X coordinate does not fit into
one byte, cut off the least significant bit into a section─
registered

;setpixel (EGA screen) 
;screen pages - in two memory windows 
;addr = tY(y) + tX(x) 
;l=x 
;e=y 
;lx=xlow mask 
;d='tY 
;h='tX 
LD A,(DE);(y*40)
ADD A,(HL);x div 4
LD C,A
INC D
INC H
 LD A,(DE);'(y*40)
ADC A,(HL);f(x mod 4)
LD B,A
 LD A,(BC)
 (X)OR LX;xlow mask
 LD (BC),A
 DEC D
INC H
;74(66) t-states 
(cf. 62(58) clock cycles on 6912, see ZX-Guide #1)
Таблицы подготавливаются так:

   LD HL,#4000;экран в #4000 и #c000
   LD BC,40
   LD E,B
mktyO
   LD D,'tY
   LD A,L
   LD (DE),A
   INC D
   LD A,H
   LD (DE),A
   ADD HL,BC
   INC E
   JNZ mktyO
mktxO
   LD D,'tX
   LD A,E
   RRA
   RRA
   AND #3F
   LD (DE),A
   INC D
   LD A,E
   RRCA
   AND #80
   BIT 2,E
   JZ $+4
   OR #20
   LD (DE),A;#00,#80,#20,#a0
   INC E
   JNZ mktxO

   В Nedodemo 2 использовался вариант это─
го метода приX=0..255:

;l=x 
;e=y 
;d='tY 
   LD H,'tX
   LD A,(DE);(y*40)
   ADD A,(HL);x div 4
    LD C,A
   INC D
   INC H
   LD A,(DE);'(y*40)
   ADC A,(HL);f(x mod 4)
          ;#00,#00,#80,#80,#20,#20,#a0,#a0
    LD B,A   INC H;'tXmask
   LD A,(BC)
  (X)OR (HL);xlow mask
   LD (BC),A
   DEC D
;80(76) t-states 

   В  генераторе таблиц надо добавить тре─
тийRRA, второй RRCA, заменить #3F  на #1F
и вставить передLD (DE),A:
   INC D
   LD A,E
   RRA
   SBC A,A
   XOR %01000111;left pixel
   AND C


      5. Библиотеки процедур в ALASM

   Если  надо сделать библиотеку процедур,
каждая  из  которых  будет компилироваться
только тогда,когда используется в програм─
ме, то можно пойти такими путями:

 а)создать макросы на каждую процедуру:

    INCLUDE "math",pgmath
...
MUL _MUL
DIV _DIV

math.h:
 MACRO _MUL
;multiplication procedure 
 RET
ENDM

 MACRO _DIV
;division procedure 
 RET
ENDM

 b)include the same module several times─
only once - one for each procedure. 
It's more memory efficient than macros 
(where the page may simply overflow 
macros), but speed is not guaranteed: 

    ...
MUL INCLUDE "math",pgmath
DIV INCLUDE "math",pgmath
 ...

math.H:
IFN ?mathtwice
const1=1
const2=2
   ...
   MACRO mathbla
   ...
   ENDM
mathtwice
   ENDIF

   IFO ?MUL;если метка определена
   IFN ?MULcompiled
;процедура умножения 
   RET
MULcompiled
   ENDIF
   ENDIF

   IFO ?DIV;если метка определена
   IFN ?DIVcompiled
;процедура деления 
   RET
DIVcompiled
   ENDIF
   ENDIF

 в)include all libraries in the con itself─
so that they themselves can check which 
which procedures are used and which are not: 
 
    ...
CALL MUL
 CALL DIV
 ...
 INCLUDE "math",pgmath

math.h:
IFN ?MUL;if the label was accessed
MUL
;multiplication procedure 
 RET
ENDIF

IFN ?DIV;if the label was accessed
DIV
;division procedure 
 RET
ENDIF


   6. Short random number generator
              (sent by Tiboh)

 EXX
INC HL
 RES 3,H
LD A,R
 XOR (HL)
 EXX


           7. Acceleration LD:PUSH

   The usual code for displaying typeLD DE:
PUSH DE does not fit well with delays in phi─
time machines (4 eight-cycle cycles).
   If there is a free registerBC, then
you can gain speed by rewriting it like this:

LD BC,nn
 LD DE,nn
PUSH BC
 PUSH DE

   This takes 7 eight-cycle cycles, then
there are 3.5 for eachPUSH.
Adding a registerHL is generally disadvantageous─
but (11 eight-cycle cycles for threePUSH),
but if you try to drive the groupPUSH into
border field, you can achieve something.

Share your thoughts about the article