forked from MirrorRepos/RomWBW
committed by
GitHub
8 changed files with 681 additions and 17 deletions
@ -1,5 +1,5 @@ |
|||
OBJECTS = |
|||
SUBDIRS = DMAmon I2C inttest ppidetst ramtest tstdskng rzsz vdctest kbdtest ps2info 2piotst piomon banktest |
|||
SUBDIRS = DMAmon I2C inttest ppidetst ramtest tstdskng rzsz vdctest kbdtest ps2info 2piotst piomon banktest portswp |
|||
DEST = ../../../Binary/Apps/Test |
|||
TOOLS =../../../Tools |
|||
|
|||
|
|||
@ -0,0 +1,11 @@ |
|||
@echo off |
|||
setlocal |
|||
|
|||
set TOOLS=../../../../Tools |
|||
set PATH=%TOOLS%\tasm32;%PATH% |
|||
set TASMTABS=%TOOLS%\tasm32 |
|||
|
|||
tasm -t180 -g3 -fFF portswp.asm portswp.com portswp.lst || exit /b |
|||
|
|||
copy /Y portswp.com ..\..\..\..\Binary\Apps\Test\ || exit /b |
|||
|
|||
@ -0,0 +1,6 @@ |
|||
@echo off |
|||
setlocal |
|||
|
|||
if exist *.com del *.com |
|||
if exist *.lst del *.lst |
|||
if exist *.bin del *.bin |
|||
@ -0,0 +1,9 @@ |
|||
OBJECTS = portswp.com |
|||
DEST = ../../../../Binary/Apps/Test |
|||
TOOLS =../../../../Tools |
|||
|
|||
USETASM=1 |
|||
|
|||
include $(TOOLS)/Makefile.inc |
|||
|
|||
TASM=$(BINDIR)/uz80as -t hd64180 |
|||
@ -0,0 +1,595 @@ |
|||
;=============================================================================== |
|||
; PORTSWP - Sweep Ports |
|||
; |
|||
;=============================================================================== |
|||
; |
|||
; Author: Wayne Warthen (wwarthen@gmail.com) |
|||
;_______________________________________________________________________________ |
|||
; |
|||
; Usage: |
|||
; PORTSWP |
|||
; |
|||
; Operation: |
|||
; Reads all ports (multiple ways) and displays values read |
|||
;_______________________________________________________________________________ |
|||
; |
|||
; Change Log: |
|||
; 2023-02-14 [WBW] Initial release |
|||
;_______________________________________________________________________________ |
|||
; |
|||
; ToDo: |
|||
;_______________________________________________________________________________ |
|||
; |
|||
;=============================================================================== |
|||
; Definitions |
|||
;=============================================================================== |
|||
; |
|||
runloc .equ $C000 ; Running location (upper memory required) |
|||
stksiz .equ $40 ; Working stack size |
|||
; |
|||
rmj .equ 3 ; intended HBIOS version - major |
|||
rmn .equ 1 ; intended HBIOS version - minor |
|||
; |
|||
restart .equ $0000 ; CP/M restart vector |
|||
; |
|||
#include "../../../HBIOS/hbios.inc" |
|||
; |
|||
;=============================================================================== |
|||
; Code Section |
|||
;=============================================================================== |
|||
; |
|||
.org $100 |
|||
; |
|||
; relocate worker code to upper memory |
|||
ld hl,begin ; start of working code image |
|||
ld de,runloc ; running location |
|||
ld bc,size ; size of working code image |
|||
ldir ; copy to upper RAM |
|||
jp runloc ; and go |
|||
; |
|||
; Start of working code |
|||
; |
|||
begin .equ $ ; image loaded here |
|||
; |
|||
.org runloc ; now generate running location adresses |
|||
; |
|||
; setup stack (save old value) |
|||
ld (stksav),sp ; save stack |
|||
ld sp,stack ; set new stack |
|||
; |
|||
; initialization |
|||
call init ; initialize |
|||
jr nz,exit ; abort if init fails |
|||
; |
|||
; process |
|||
call process ; do main processing |
|||
jr nz,exit ; abort on error |
|||
; |
|||
exit: ; clean up and return to command processor |
|||
call crlf ; formatting |
|||
ld sp,(stksav) ; restore stack |
|||
;jp restart ; return to CP/M via restart |
|||
ret ; return to CP/M w/o restart |
|||
; |
|||
; Initialization |
|||
; |
|||
init: |
|||
call crlf2 ; formatting |
|||
ld de,msgban ; point to version message part 1 |
|||
call prtstr ; print it |
|||
; |
|||
call idbio ; identify active BIOS |
|||
cp 1 ; check for HBIOS |
|||
jp nz,errbio ; handle BIOS error |
|||
; |
|||
ld a,rmj << 4 | rmn ; expected HBIOS ver |
|||
cp d ; compare with result above |
|||
jp nz,errbio ; handle BIOS error |
|||
; |
|||
initx |
|||
; initialization complete |
|||
xor a ; signal success |
|||
ret ; return |
|||
; |
|||
; Process |
|||
; |
|||
process: |
|||
call crlf |
|||
ld a,($FFE0) ; get current hbios bank id |
|||
ld (orgbnk),a ; and save it |
|||
ld a,0 ; start with port 0 |
|||
ld (curport),a ; save it for use below |
|||
; Test for z180 using mlt |
|||
ld de,$0506 ; 5 x 6 |
|||
mlt de ; de = 30 if z180 |
|||
ld a,e ; result to A |
|||
cp 30 ; check if multiply happened |
|||
jr nz,loop ; if invalid, then Z80 |
|||
or $FF ; flag value for Z180 |
|||
ld (is180),a ; save it |
|||
; |
|||
loop: |
|||
call crlf |
|||
ld a,(curport) |
|||
call prthex |
|||
ld a,':' |
|||
call prtchr |
|||
; |
|||
di ; interrupts off |
|||
; |
|||
ld hl,vallist ; init value list pointer |
|||
call portread ; read the port |
|||
call portread ; do it again |
|||
; |
|||
; restore possibly corrupted bank registers |
|||
ld a,(orgbnk) ; get proper bank id |
|||
call $FFF3 ; restore it |
|||
; |
|||
ei ; interrupts safe now |
|||
; |
|||
ld hl,vallist ; re-init value list pointer |
|||
ld b,4 ; print 4 values |
|||
prtloop: |
|||
ld a,' ' |
|||
call prtchr |
|||
ld a,(hl) |
|||
call prthex |
|||
inc hl |
|||
djnz prtloop |
|||
; |
|||
; update port and loop as needed |
|||
ld a,(curport) ; get current port |
|||
inc a ; move to next |
|||
ld (curport),a ; save it |
|||
jr z,done ; done on wraparound |
|||
jr loop ; loop until done |
|||
; |
|||
done: |
|||
; |
|||
call crlf2 |
|||
ld de,msgdone ; message to print |
|||
call prtstr ; do it |
|||
; |
|||
ret ; all done |
|||
; |
|||
; |
|||
; |
|||
portread: |
|||
ld a,(is180) |
|||
or a |
|||
jr nz,portread_z180 |
|||
; |
|||
portread_z80: ; user traditional "IN" |
|||
; read port using IN <portnum> |
|||
ld a,(curport) ; get current port |
|||
ld (port),a ; modify IN instruction |
|||
in a,($FF) ; read the port |
|||
port .equ $-1 |
|||
ld (hl),a ; save it |
|||
inc hl ; bump value list pointer |
|||
; |
|||
; read port using IN (C) |
|||
ld a,(curport) ; get current port |
|||
ld b,0 ; in case 16 bits decoded |
|||
ld c,a ; move to reg C |
|||
in a,(c) ; read the port |
|||
ld (hl),a ; save it |
|||
inc hl ; bump value list pointer |
|||
ret |
|||
; |
|||
portread_z180: ; use "IN0" |
|||
; read port using IN <portnum> |
|||
ld a,(curport) ; get current port |
|||
ld (port1),a ; modify IN instruction |
|||
in0 a,($FF) ; read the port |
|||
port1 .equ $-1 |
|||
ld (hl),a ; save it |
|||
inc hl ; bump value list pointer |
|||
; |
|||
; read port using IN (C) |
|||
ld a,(curport) ; get current port |
|||
ld b,0 ; in case 16 bits decoded |
|||
ld c,a ; move to reg C |
|||
in a,(c) ; read the port |
|||
ld (hl),a ; save it |
|||
inc hl ; bump value list pointer |
|||
ret |
|||
; |
|||
; Identify active BIOS. RomWBW HBIOS=1, UNA UBIOS=2, else 0 |
|||
; |
|||
idbio: |
|||
; |
|||
; Check for UNA (UBIOS) |
|||
ld a,($FFFD) ; fixed location of UNA API vector |
|||
cp $C3 ; jp instruction? |
|||
jr nz,idbio1 ; if not, not UNA |
|||
ld hl,($FFFE) ; get jp address |
|||
ld a,(hl) ; get byte at target address |
|||
cp $FD ; first byte of UNA push ix instruction |
|||
jr nz,idbio1 ; if not, not UNA |
|||
inc hl ; point to next byte |
|||
ld a,(hl) ; get next byte |
|||
cp $E5 ; second byte of UNA push ix instruction |
|||
jr nz,idbio1 ; if not, not UNA, check others |
|||
; |
|||
ld bc,$04FA ; UNA: get BIOS date and version |
|||
rst 08 ; DE := ver, HL := date |
|||
; |
|||
ld a,2 ; UNA BIOS id = 2 |
|||
ret ; and done |
|||
; |
|||
idbio1: |
|||
; Check for RomWBW (HBIOS) |
|||
ld hl,(HB_IDENT) ; HL := HBIOS ident location |
|||
ld a,'W' ; First byte of ident |
|||
cp (hl) ; Compare |
|||
jr nz,idbio2 ; Not HBIOS |
|||
inc hl ; Next byte of ident |
|||
ld a,~'W' ; Second byte of ident |
|||
cp (hl) ; Compare |
|||
jr nz,idbio2 ; Not HBIOS |
|||
; |
|||
ld b,BF_SYSVER ; HBIOS: VER function |
|||
ld c,0 ; required reserved value |
|||
rst 08 ; DE := version, L := platform id |
|||
; |
|||
ld a,1 ; HBIOS BIOS id = 1 |
|||
ret ; and done |
|||
; |
|||
idbio2: |
|||
; No idea what this is |
|||
xor a ; Setup return value of 0 |
|||
ret ; and done |
|||
; |
|||
; Print character in A without destroying any registers |
|||
; |
|||
prtchr: |
|||
push bc ; save registers |
|||
push de |
|||
push hl |
|||
ld e,a ; character to print in E |
|||
ld b,BF_CIOOUT ; HBIOS function to output a character |
|||
ld c,CIO_CONSOLE ; write to current console unit |
|||
call HB_INVOKE ; invoke HBIOS via call |
|||
pop hl ; restore registers |
|||
pop de |
|||
pop bc |
|||
ret |
|||
; |
|||
prtdot: |
|||
; |
|||
; shortcut to print a dot preserving all regs |
|||
push af ; save af |
|||
ld a,'.' ; load dot char |
|||
call prtchr ; print it |
|||
pop af ; restore af |
|||
ret ; done |
|||
; |
|||
prtspace: |
|||
; |
|||
; shortcut to print a space preserving all regs |
|||
push af ; save af |
|||
ld a,' ' ; load dot char |
|||
call prtchr ; print it |
|||
pop af ; restore af |
|||
ret ; done |
|||
; |
|||
prtcr: |
|||
; |
|||
; shortcut to print a dot preserving all regs |
|||
push af ; save af |
|||
ld a,13 ; load CR value |
|||
call prtchr ; print it |
|||
pop af ; restore af |
|||
ret ; done |
|||
; |
|||
; Print a zero terminated string at (DE) without destroying any registers |
|||
; |
|||
prtstr: |
|||
push de |
|||
; |
|||
prtstr1: |
|||
ld a,(de) ; get next char |
|||
or a |
|||
jr z,prtstr2 |
|||
call prtchr |
|||
inc de |
|||
jr prtstr1 |
|||
; |
|||
prtstr2: |
|||
pop de ; restore registers |
|||
ret |
|||
; |
|||
; Print a block of memory nicely formatted |
|||
; de=buffer address |
|||
; |
|||
dump_buffer: |
|||
call crlf |
|||
|
|||
push de |
|||
pop hl |
|||
inc d |
|||
inc d |
|||
|
|||
db_blkrd: |
|||
push bc |
|||
push hl |
|||
pop bc |
|||
call prthexword ; print start location |
|||
pop bc |
|||
call prtspace ; |
|||
ld c,16 ; set for 16 locs |
|||
push hl ; save starting hl |
|||
db_nxtone: |
|||
ld a,(hl) ; get byte |
|||
call prthex ; print it |
|||
call prtspace ; |
|||
db_updh: |
|||
inc hl ; point next |
|||
dec c ; dec. loc count |
|||
jr nz,db_nxtone ; if line not done |
|||
; now print 'decoded' data to right of dump |
|||
db_pcrlf: |
|||
call prtspace ; space it |
|||
ld c,16 ; set for 16 chars |
|||
pop hl ; get back start |
|||
db_pcrlf0: |
|||
ld a,(hl) ; get byte |
|||
and 060h ; see if a 'dot' |
|||
ld a,(hl) ; o.k. to get |
|||
jr nz,db_pdot ; |
|||
db_dot: |
|||
ld a,2eh ; load a dot |
|||
db_pdot: |
|||
call prtchr ; print it |
|||
inc hl ; |
|||
ld a,d ; |
|||
cp h ; |
|||
jr nz,db_updh1 ; |
|||
ld a,e ; |
|||
cp l ; |
|||
jp z,db_end ; |
|||
db_updh1: |
|||
; if block not dumped, do next character or line |
|||
dec c ; dec. char count |
|||
jr nz,db_pcrlf0 ; do next |
|||
db_contd: |
|||
call crlf ; |
|||
jp db_blkrd ; |
|||
|
|||
db_end: |
|||
ret |
|||
; |
|||
; Print the value in A in hex without destroying any registers |
|||
; |
|||
prthex: |
|||
push af ; save AF |
|||
push de ; save DE |
|||
call hexascii ; convert value in A to hex chars in DE |
|||
ld a,d ; get the high order hex char |
|||
call prtchr ; print it |
|||
ld a,e ; get the low order hex char |
|||
call prtchr ; print it |
|||
pop de ; restore DE |
|||
pop af ; restore AF |
|||
ret ; done |
|||
; |
|||
; print the hex word value in bc |
|||
; |
|||
prthexword: |
|||
push af |
|||
ld a,b |
|||
call prthex |
|||
ld a,c |
|||
call prthex |
|||
pop af |
|||
ret |
|||
; |
|||
; print the hex dword value in de:hl |
|||
; |
|||
prthex32: |
|||
push bc |
|||
push de |
|||
pop bc |
|||
call prthexword |
|||
push hl |
|||
pop bc |
|||
call prthexword |
|||
pop bc |
|||
ret |
|||
; |
|||
; Convert binary value in A to ascii hex characters in DE |
|||
; |
|||
hexascii: |
|||
ld d,a ; save A in D |
|||
call hexconv ; convert low nibble of A to hex |
|||
ld e,a ; save it in E |
|||
ld a,d ; get original value back |
|||
rlca ; rotate high order nibble to low bits |
|||
rlca |
|||
rlca |
|||
rlca |
|||
call hexconv ; convert nibble |
|||
ld d,a ; save it in D |
|||
ret ; done |
|||
; |
|||
; Convert low nibble of A to ascii hex |
|||
; |
|||
hexconv: |
|||
and $0F ; low nibble only |
|||
add a,$90 |
|||
daa |
|||
adc a,$40 |
|||
daa |
|||
ret |
|||
; |
|||
; Print value of A or HL in decimal with leading zero suppression |
|||
; Use prtdecb for A or prtdecw for HL |
|||
; |
|||
prtdecb: |
|||
push hl |
|||
ld h,0 |
|||
ld l,a |
|||
call prtdecw ; print it |
|||
pop hl |
|||
ret |
|||
; |
|||
prtdecw: |
|||
push af |
|||
push bc |
|||
push de |
|||
push hl |
|||
call prtdec0 |
|||
pop hl |
|||
pop de |
|||
pop bc |
|||
pop af |
|||
ret |
|||
; |
|||
prtdec0: |
|||
ld e,'0' |
|||
ld bc,-10000 |
|||
call prtdec1 |
|||
ld bc,-1000 |
|||
call prtdec1 |
|||
ld bc,-100 |
|||
call prtdec1 |
|||
ld c,-10 |
|||
call prtdec1 |
|||
ld e,0 |
|||
ld c,-1 |
|||
prtdec1: |
|||
ld a,'0' - 1 |
|||
prtdec2: |
|||
inc a |
|||
add hl,bc |
|||
jr c,prtdec2 |
|||
sbc hl,bc |
|||
cp e |
|||
ret z |
|||
ld e,0 |
|||
call prtchr |
|||
ret |
|||
; |
|||
; Start a new line |
|||
; |
|||
crlf2: |
|||
call crlf ; two of them |
|||
crlf: |
|||
push af ; preserve AF |
|||
ld a,13 ; <CR> |
|||
call prtchr ; print it |
|||
ld a,10 ; <LF> |
|||
call prtchr ; print it |
|||
pop af ; restore AF |
|||
ret |
|||
; |
|||
; Get the next non-blank character from (HL). |
|||
; |
|||
nonblank: |
|||
ld a,(hl) ; load next character |
|||
or a ; string ends with a null |
|||
ret z ; if null, return pointing to null |
|||
cp ' ' ; check for blank |
|||
ret nz ; return if not blank |
|||
inc hl ; if blank, increment character pointer |
|||
jr nonblank ; and loop |
|||
; |
|||
; Convert character in A to uppercase |
|||
; |
|||
ucase: |
|||
cp 'a' ; if below 'a' |
|||
ret c ; ... do nothing and return |
|||
cp 'z' + 1 ; if above 'z' |
|||
ret nc ; ... do nothing and return |
|||
res 5,a ; clear bit 5 to make lower case -> upper case |
|||
ret ; and return |
|||
; |
|||
; Add the value in A to HL (HL := HL + A) |
|||
; |
|||
addhl: |
|||
add a,l ; A := A + L |
|||
ld l,a ; Put result back in L |
|||
ret nc ; if no carry, we are done |
|||
inc h ; if carry, increment H |
|||
ret ; and return |
|||
; |
|||
; Jump indirect to address in HL |
|||
; |
|||
jphl: |
|||
jp (hl) |
|||
; |
|||
; Short delay functions. No clock speed compensation, so they |
|||
; will run longer on slower systems. The number indicates the |
|||
; number of call/ret invocations. a single call/ret is |
|||
; 27 t-states on a z80, 25 t-states on a z180 |
|||
; |
|||
; ; Z80 Z180 |
|||
; ; ---- ---- |
|||
dly64: call dly32 ; 1728 1600 |
|||
dly32: call dly16 ; 864 800 |
|||
dly16: call dly8 ; 432 400 |
|||
dly8: call dly4 ; 216 200 |
|||
dly4: call dly2 ; 108 100 |
|||
dly2: call dly1 ; 54 50 |
|||
dly1: ret ; 27 25 |
|||
|
|||
; |
|||
; Errors |
|||
; |
|||
erruse: ; command usage error (syntax) |
|||
ld de,msguse |
|||
jr err |
|||
; |
|||
errprm: ; command parameter error (syntax) |
|||
ld de,msgprm |
|||
jr err |
|||
; |
|||
errbio: ; invalid BIOS or version |
|||
ld de,msgbio |
|||
jr err |
|||
; |
|||
err: ; print error string and return error signal |
|||
call crlf2 ; print newline |
|||
; |
|||
err1: ; without the leading crlf |
|||
call prtstr ; print error string |
|||
; |
|||
err2: ; without the string |
|||
; call crlf ; print newline |
|||
or $FF ; signal error |
|||
ret ; done |
|||
; |
|||
;=============================================================================== |
|||
; Storage Section |
|||
;=============================================================================== |
|||
; |
|||
is180 .db 0 ; non-zero for z180 |
|||
orgbnk .db 0 ; original bank id |
|||
curport .db 0 ; current port being processed |
|||
vallist .fill 8,0 ; port values read |
|||
; |
|||
stksav .dw 0 ; stack pointer saved at start |
|||
.fill stksiz,0 ; stack |
|||
stack .equ $ ; stack top |
|||
; |
|||
; Messages |
|||
; |
|||
msgban .db "PORTSWP v1.0, 14-Feb-2023",13,10 |
|||
.db "Copyright (C) 2023, Wayne Warthen, GNU GPL v3",0 |
|||
msguse .db "Usage: PORTSWP",13,10 |
|||
msgprm .db "Parameter error (PORTSWP /? for usage)",0 |
|||
msgbio .db "Incompatible BIOS or version, " |
|||
.db "HBIOS v", '0' + rmj, ".", '0' + rmn, " required",0 |
|||
str_sep .db ": ",0 |
|||
; |
|||
;msgcur .db "Initial Bank ID = 0x",0 |
|||
;msg80 .db "Hello from bank 0x80!",0 |
|||
;msgxcal .db "Inter-bank procedure call test...",0 |
|||
msgdone .db "End of Port Sweep",0 |
|||
; |
|||
; |
|||
; |
|||
size .equ $ - runloc |
|||
; |
|||
.end |
|||
Loading…
Reference in new issue