mirror of https://github.com/wwarthen/RomWBW.git
committed by
GitHub
8 changed files with 681 additions and 17 deletions
@ -1,5 +1,5 @@ |
|||||
OBJECTS = |
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 |
DEST = ../../../Binary/Apps/Test |
||||
TOOLS =../../../Tools |
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