zxuno-git/utils.asm

179 lines
5.2 KiB
NASM

SCANDBLCTRL_REG = #0B
ZXUNO_ADDR = #FC3B
ZXUNO_REG = #FD3B
setNoTurboMode:
push af
push bc
ld a, SCANDBLCTRL_REG
ld bc, ZXUNO_ADDR
out (c), a
ld bc, ZXUNO_REG
in a, (c)
and #3f
out (c), a
pop bc
pop af
ret
setTurbo4Mode:
push af
push bc
ld a, SCANDBLCTRL_REG
ld bc, ZXUNO_ADDR
out (c), a
ld bc, ZXUNO_REG
in a, (c)
and #3f
or #80
out (c), a
pop bc
pop af
ret
; HL - string
; Return: bc - len
getStringLength:
ld bc, 0
strLnLp
ld a, (hl)
and a
ret z
inc bc
inc hl
jr strLnLp
SkipWhitespace:
ld a, (hl)
cp ' '
ret nz
inc hl
jr SkipWhitespace
;;;;;;;;;;;;;;;;;;;;;;;;
; Binary to decimal stuff
; From https://www.msx.org/forum/development/msx-development/32-bit-long-ascii
; Combined routine for conversion of different sized binary numbers into
; directly printable ASCII(Z)-string
; Input value in registers, number size and -related to that- registers to fill
; is selected by calling the correct entry:
;
; entry inputregister(s) decimal value 0 to:
; B2D8 A 255 (3 digits)
; B2D16 HL 65535 5 "
; B2D24 E:HL 16777215 8 "
; B2D32 DE:HL 4294967295 10 "
; B2D48 BC:DE:HL 281474976710655 15 "
; B2D64 IX:BC:DE:HL 18446744073709551615 20 "
;
; The resulting string is placed into a small buffer attached to this routine,
; this buffer needs no initialization and can be modified as desired.
; The number is aligned to the right, and leading 0's are replaced with spaces.
; On exit HL points to the first digit, (B)C = number of decimals
; This way any re-alignment / postprocessing is made easy.
; Changes: AF,BC,DE,HL,IX
; P.S. some examples below
; by Alwin Henseler
B2D8: LD H,0
LD L,A
B2D16: LD E,0
B2D24: LD D,0
B2D32: LD BC,0
B2D48: LD IX,0 ; zero all non-used bits
B2D64: LD (B2DINV),HL
LD (B2DINV+2),DE
LD (B2DINV+4),BC
LD (B2DINV+6),IX ; place full 64-bit input value in buffer
LD HL,B2DBUF
LD DE,B2DBUF+1
LD (HL)," "
B2DFILC: EQU $-1 ; address of fill-character
LD BC,18
LDIR ; fill 1st 19 bytes of buffer with spaces
LD (B2DEND-1),BC ;set BCD value to "0" & place terminating 0
LD E,1 ; no. of bytes in BCD value
LD HL,B2DINV+8 ; (address MSB input)+1
LD BC,0x0909
XOR A
B2DSKP0: DEC B
JR Z,B2DSIZ ; all 0: continue with postprocessing
DEC HL
OR (HL) ; find first byte <>0
JR Z,B2DSKP0
B2DFND1: DEC C
RLA
JR NC,B2DFND1 ; determine no. of most significant 1-bit
RRA
LD D,A ; byte from binary input value
B2DLUS2: PUSH HL
PUSH BC
B2DLUS1: LD HL,B2DEND-1 ; address LSB of BCD value
LD B,E ; current length of BCD value in bytes
RL D ; highest bit from input value -> carry
B2DLUS0: LD A,(HL)
ADC A,A
DAA
LD (HL),A ; double 1 BCD byte from intermediate result
DEC HL
DJNZ B2DLUS0 ; and go on to double entire BCD value (+carry!)
JR NC,B2DNXT
INC E ; carry at MSB -> BCD value grew 1 byte larger
LD (HL),1 ; initialize new MSB of BCD value
B2DNXT: DEC C
JR NZ,B2DLUS1 ; repeat for remaining bits from 1 input byte
POP BC ; no. of remaining bytes in input value
LD C,8 ; reset bit-counter
POP HL ; pointer to byte from input value
DEC HL
LD D,(HL) ; get next group of 8 bits
DJNZ B2DLUS2 ; and repeat until last byte from input value
B2DSIZ: LD HL,B2DEND ; address of terminating 0
LD C,E ; size of BCD value in bytes
OR A
SBC HL,BC ; calculate address of MSB BCD
LD D,H
LD E,L
SBC HL,BC
EX DE,HL ; HL=address BCD value, DE=start of decimal value
LD B,C ; no. of bytes BCD
SLA C ; no. of bytes decimal (possibly 1 too high)
LD A,"0"
RLD ; shift bits 4-7 of (HL) into bit 0-3 of A
CP "0" ; (HL) was > 9h?
JR NZ,B2DEXPH ; if yes, start with recording high digit
DEC C ; correct number of decimals
INC DE ; correct start address
JR B2DEXPL ; continue with converting low digit
B2DEXP: RLD ; shift high digit (HL) into low digit of A
B2DEXPH: LD (DE),A ; record resulting ASCII-code
INC DE
B2DEXPL: RLD
LD (DE),A
INC DE
INC HL ; next BCD-byte
DJNZ B2DEXP ; and go on to convert each BCD-byte into 2 ASCII
SBC HL,BC ; return with HL pointing to 1st decimal
RET
AppendB2D:
; Append results of B2D to string at HL
ex de, hl ; Get destination into DE
ld hl, B2DBUF
call SkipWhitespace
ldir
ex de, hl ; Get destination into DE
ret
B2DINV: DS 8 ; space for 64-bit input value (LSB first)
B2DBUF: DS 20 ; space for 20 decimal digits
B2DEND: DB 0 ; space for terminating 0