zxuno-git/software/ugophy/utils.asm

238 lines
6.6 KiB
NASM

; SPDX-FileCopyrightText: Copyright (C) 2019 Alexander Sharikhin
;
; SPDX-License-Identifier: GPL-3.0-or-later
SCANDBLCTRL_REG = #0B
ZXUNO_ADDR = #FC3B
ZXUNO_REG = #FD3B
; This routine checks availability of extended(128K) memory.
; Output:
; Flag: Z - High memory available
checkHighMem:
xor a : call changeBank: ld hl, #c000 : xor a :ld (hl), a ; Let's write in zero page zero value
inc a : call changeBank : ld a, 13 : ld (hl), a ; In other page - any other value. Let's write luck 13
xor a : call changeBank : ld a, (hl) : and a ; When we back to zero page - still there zero?!
ret
; A - memory bank
changeBank:
ld bc, #7ffd : or #18 : out (c), a
ret
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 ; And #3F - keep scandoubler settings
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
; Pushes to UART zero-terminated string
; HL - string poiner
uartWriteStringZ:
ld a, (hl) : and a : ret z
push hl : call uartWriteByte : pop hl
inc hl
jp uartWriteStringZ
; Print zero-terminated string
; HL - string pointer
putStringZ:
printZ64:
ld a,(hl) : and a : ret z
push hl : call putC : pop hl
inc hl
jr printZ64
printT64:
ld b, 63
ptlp:
ld a, 0 : or b : ret z
ld a, (hl)
and a : ret z
cp 09 : ret z
push bc
push hl : call putC : pop hl
inc hl : pop bc : dec b
jr ptlp
printL64:
ld a, (hl)
and a : ret z
cp #0A : ret z
cp #0D : ret z
push hl : call putC : pop hl
inc hl
jr printL64
; 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
findEnd:
ld a,(hl)
and a : ret z
inc hl
jr findEnd
;;;;;;;;;;;;;;;;;;;;;;;;
; 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