From 4a9fcbc4af62c1c9f9c3c2b53cb696acada89fe1 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Wed, 30 Dec 2020 21:51:48 +0800 Subject: [PATCH 1/7] Support System Update process for systems with 39SF040 flash chips Generate an update file. Updated docs. md.asm minors Update compression application --- ReadMe.md | 28 +++++++++++++++++++++++-- Source/HBIOS/Build.ps1 | 17 +++++++++++++-- Source/HBIOS/md.asm | 46 ++++++++++++++++++++++++++--------------- Tools/lzsa/lzsa.exe | Bin 171008 -> 173056 bytes 4 files changed, 70 insertions(+), 21 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index 21ccd7d7..64d961a1 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -1038,7 +1038,7 @@ system, you can use the FLASH application to update your ROM. The following is a typical example of transferring ROM image using XModem and flashing the chip in-situ. - E>xm r rom.img + E>xm r rom.rom XMODEM v12.5 - 07/13/86 RBC, 28-Aug-2019 [WBW], ASCI @@ -1050,7 +1050,7 @@ and flashing the chip in-situ. Thanks for the upload - E>flash write rom.img + E>flash write rom.rom FLASH4 by Will Sowerbutts version 1.2.3 Using RomWBW (v2.6+) bank switching. @@ -1179,6 +1179,30 @@ images. - FAT.COM - TUNE.COM +# System Update + +If the system running ROMWBW utilizes the SST39SF040 Flash chip then it is possible to do a System Update in place of +a System Upgrade in some cases. + +A System Update would involve only updating the BIOS, ROM applications and CP/M system. + +A System Update may be more favorable than a System Upgrade in cases such as: + + - Overwriting of the ROM drive is not desired. + - Space is unavailable to hold a full ROMWBW ROM. + - To mimimize time taken to transfer and flash a full ROM. + - Configuration changes are only minor and do not impact disk applications. + +The ROMWBW build process generates a system upgrade file along with the normal ROM image and can be identified by the +extension ".upd". It will be 128Kb in size. In comparison the normal ROM image will have the extension ".rom" and be +512Kb or 1024Kb in size. + +Transferring and flashing the System Update is accomplished in the same manner as described above in *Upgrading* with +the required difference being that the flash application needs to be directed to complete a partial flash using the +/p command line switch. + +`E>flash write rom.upd /p` + # RomWBW Distribution All source code and distributions are maintained on GitHub. Code diff --git a/Source/HBIOS/Build.ps1 b/Source/HBIOS/Build.ps1 index bd74126c..764efbe1 100644 --- a/Source/HBIOS/Build.ps1 +++ b/Source/HBIOS/Build.ps1 @@ -92,10 +92,11 @@ $ErrorAction = 'Stop' # Directories of required build tools (TASM & cpmtools) $TasmPath = '..\..\tools\tasm32' $CpmToolsPath = '..\..\tools\cpmtools' +$LzaToolsPath = '..\..\tools\lzsa' # Add tool directories to PATH and setup TASM's TABS directory path $env:TASMTABS = $TasmPath -$env:PATH = $TasmPath + ';' + $CpmToolsPath + ';' + $env:PATH +$env:PATH = $TasmPath + ';' + $CpmToolsPath + ';' + $LzaToolsPath + ';' + $env:PATH # Initialize working variables $OutDir = "../../Binary" # Output directory for final image file @@ -105,6 +106,7 @@ $RomDiskFile = "RomDisk.tmp" # Temporary filename used to create ROM disk image $RomFile = "${OutDir}/${RomName}.rom" # Final name of ROM image $ComFile = "${OutDir}/${RomName}.com" # Final name of COM image (command line loadable HBIOS/CBIOS) $ImgFile = "${OutDir}/${RomName}.img" # Final name of IMG image (memory loadable HBIOS/CBIOS image) +$UpdFile = "${OutDir}/${RomName}.upd" # Final name of System ROM image # Select the proper CBIOS to include in the ROM. UNA is special. if ($Platform -eq "UNA") {$Bios = 'una'} else {$Bios = 'wbw'} @@ -233,19 +235,30 @@ cpmchattr -f $RomFmt $RomDiskFile r 0:*.* # Finally, the individual binary components are concatenated together to produce # the final images. # +$SystemFileList = "hbios_rom.bin", "osimg.bin", "osimg1.bin", "osimg.bin" if ($Platform -eq "UNA") { Copy-Item 'osimg.bin' ${OutDir}\UNA_WBW_SYS.bin Copy-Item $RomDiskFile ${OutDir}\UNA_WBW_ROM${ROMSize}.bin Concat '..\UBIOS\UNA-BIOS.BIN','osimg.bin','..\UBIOS\FSFAT.BIN',$RomDiskFile $RomFile + Remove-Item $RomDiskFile } else { Concat 'hbios_rom.bin','osimg.bin','osimg1.bin','osimg.bin',$RomDiskFile $RomFile Concat 'hbios_app.bin','osimg_small.bin' $ComFile # Concat 'hbios_img.bin','osimg_small.bin' $ImgFile + Remove-Item $RomDiskFile + Set-Content $UpdFile -Value $null + foreach ($InputFile in $SystemFileList) + { + Copy-Item $InputFile $RomDiskFile +# lzsa -f2 -r $InputFile $RomDiskFile + Add-Content $UpdFile -Value ([System.IO.File]::ReadAllBytes($RomDiskFile)) -Encoding byte + Remove-Item $RomDiskFile + } } # Remove the temporary working ROM disk file -Remove-Item $RomDiskFile +#Remove-Item $RomDiskFile diff --git a/Source/HBIOS/md.asm b/Source/HBIOS/md.asm index 47160004..c03ac7cb 100644 --- a/Source/HBIOS/md.asm +++ b/Source/HBIOS/md.asm @@ -472,6 +472,7 @@ MD_SECM1: ; DESIRED SECTOR IS IN BUFFER ; MD_LBA4K .DW $FFFF ; LBA OF CURRENT SECTOR MD_FBAS .DW $FFFF ; BANK AND SECTOR +;MD_FLOP .DW $FFFF ; ADDRESS OF LAST OPERATION CALLED #ENDIF ; ; READ RAM / ROM @@ -710,17 +711,18 @@ MD_PROBE: #ENDIF PUSH HL CALL MD_CALBAS ; SETUP BANK AND SECTOR - LD HL,MD_FIDENT_R ; PUT ROUTINE TO CALL + LD HL,MD_FIDEN_R ; PUT ROUTINE TO CALL CALL MD_FNCALL ; EXECUTE: IDENTIFY FLASH CHIP LD HL,MD_TGTDEV ; IF WE MATCH WITH XOR A ; A NON 39SF040 SBC HL,BC ; CHIP SET THE - LD A,(MD_FFSEN) ; R/W FLAG TO R/O - OR H - OR L ; A NON ZERO VALUE - LD (MD_FFSEN),A ; MEANS WE CAN'T - POP HL ; ENABLE FLASH WRITING + JR Z,MD_PR2 ; R/W FLAG TO R/O + LD HL,MD_FFSEN ; A NON ZERO VALUE + SET 0,(HL) ; MEANS WE CAN'T + ; ENABLE FLASH WRITING; +MD_PR2: + POP HL #IF (MD_FVBS==1) CALL MD_LAND ; LOOKUP AND DISPLAY #ENDIF @@ -798,32 +800,32 @@ FF_NXT2: ;====================================================================== ; COMMON FUNCTION CALL FOR: ; -; MD_FIDENT_R - IDENTIFY FLASH CHIP +; MD_FIDEN_R - IDENTIFY FLASH CHIP ; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED -; HL POINTS TO THE ROUTINE TO RELOCATED AND CALLED +; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED ; ON EXIT BC CONTAINS THE CHIP ID BYTES. ; A NO STATUS IS RETURNED ; ; MD_FERAS_R - ERASE FLASH SECTOR ; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED -; HL POINTS TO THE ROUTINE TO RELOCATED AND CALLED +; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED ; ON EXIT A RETURNS STATUS 0=SUCCESS NZ=FAIL ; ; MD_FREAD_R - READ FLASH SECTOR ; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED -; HL POINTS TO THE ROUTINE TO RELOCATED AND CALLED +; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED ; IX POINTS TO WHERE TO SAVE DATA ; ON EXIT A NO STATUS IS RETURNED ; -; MD_VERI_R - VERIFY FLASH SECTOR +; MD_FVERI_R - VERIFY FLASH SECTOR ; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED -; HL POINTS TO THE ROUTINE TO RELOCATED AND CALLED +; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED ; IX POINTS TO DATA TO COMPARE. ; ON EXIT A RETURNS STATUS 0=SUCCESS NZ=FAIL ; ; MD_FWRIT_R - WRITE FLASH SECTOR ; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED -; HL POINTS TO THE ROUTINE TO RELOCATED AND CALLED +; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED ; IX POINTS TO DATA TO BE WRITTEN ; ON EXIT A NO STATUS IS RETURNED ; @@ -835,12 +837,22 @@ FF_NXT2: ; MD_FNCALL: ; USING HBX_BUF FOR CODE AREA ; +; EX DE,HL ; IF WE ARE +; LD HL,(MD_FLOP) ; REPEATING THE +; XOR A ; SAME OPERATION +; SBC HL,DE ; AS PREVIOUS +; EX DE,HL ; DONT COPY +; JR Z,MD_FSAME ; IF THE SAME, DE=0 +; LD (MD_FLOP),HL ; SAVE CURRENT OPERATION FOR NEXT TIME + LD DE,HBX_BUF ; EXECUTE / START ADDRESS LD BC,MD_CSIZE ; CODE SIZE. MAXIMUM 64 BYTES LDIR ; COPY OUR RELOCATABLE CODE TO THE BUFFER ; LD D,B ; PRESET DE TO ZERO TO REDUCE LD E,B ; CODE SIZE IN RELOCATABLE CODE +; +;MD_FSAME: ; LD BC,(MD_FBAS) ; PUT BANK AND SECTOR DATA IN BC ; @@ -891,7 +903,7 @@ MD_SAVSTK .DW 0 ; NO STATUS IS RETURNED ;====================================================================== ; -MD_FIDENT_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY +MD_FIDEN_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY ; LD D,A ; SAVE CURRENT BANK ; @@ -914,7 +926,7 @@ MD_FIDENT_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY ; ; RET ; -MD_I_SZ .EQU $-MD_FIDENT_R ; SIZE OF RELOCATABLE CODE BUFFER REQUIRED +MD_I_SZ .EQU $-MD_FIDEN_R ; SIZE OF RELOCATABLE CODE BUFFER REQUIRED ; ;====================================================================== ; ERASE FLASH SECTOR. @@ -1189,7 +1201,7 @@ MD_FFSEN .DB 00h ; FLASH FILES SYSTEM ENABLE ;====================================================================== ; #IF (MD_FDBG==1) - .ECHO "MD_FIDENT_R " + .ECHO "MD_FIDEN_R " .ECHO MD_I_SZ .ECHO "\n" ; @@ -1197,7 +1209,7 @@ MD_FFSEN .DB 00h ; FLASH FILES SYSTEM ENABLE .ECHO MD_R_SZ .ECHO "\n" ; - .ECHO "MD_VERI_R " + .ECHO "MD_FVERI_R " .ECHO MD_V_SZ .ECHO "\n" ; diff --git a/Tools/lzsa/lzsa.exe b/Tools/lzsa/lzsa.exe index 1c1927d7afb208af9276f412ad5897501dc53e54..f7ad589569ab7bfde41d331184adc69e77291e7f 100644 GIT binary patch delta 29232 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 Date: Wed, 30 Dec 2020 21:59:10 +0800 Subject: [PATCH 2/7] Update md.asm Remove cache'ng of flash routine . didn't work hxb_buf must be getting trashed by other processes. --- Source/HBIOS/md.asm | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/Source/HBIOS/md.asm b/Source/HBIOS/md.asm index c03ac7cb..53363889 100644 --- a/Source/HBIOS/md.asm +++ b/Source/HBIOS/md.asm @@ -472,7 +472,6 @@ MD_SECM1: ; DESIRED SECTOR IS IN BUFFER ; MD_LBA4K .DW $FFFF ; LBA OF CURRENT SECTOR MD_FBAS .DW $FFFF ; BANK AND SECTOR -;MD_FLOP .DW $FFFF ; ADDRESS OF LAST OPERATION CALLED #ENDIF ; ; READ RAM / ROM @@ -837,22 +836,12 @@ FF_NXT2: ; MD_FNCALL: ; USING HBX_BUF FOR CODE AREA ; -; EX DE,HL ; IF WE ARE -; LD HL,(MD_FLOP) ; REPEATING THE -; XOR A ; SAME OPERATION -; SBC HL,DE ; AS PREVIOUS -; EX DE,HL ; DONT COPY -; JR Z,MD_FSAME ; IF THE SAME, DE=0 -; LD (MD_FLOP),HL ; SAVE CURRENT OPERATION FOR NEXT TIME - LD DE,HBX_BUF ; EXECUTE / START ADDRESS LD BC,MD_CSIZE ; CODE SIZE. MAXIMUM 64 BYTES LDIR ; COPY OUR RELOCATABLE CODE TO THE BUFFER ; LD D,B ; PRESET DE TO ZERO TO REDUCE LD E,B ; CODE SIZE IN RELOCATABLE CODE -; -;MD_FSAME: ; LD BC,(MD_FBAS) ; PUT BANK AND SECTOR DATA IN BC ; From e9947c0a6899c5b4649ec959df6fcea7c37ed039 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Fri, 1 Jan 2021 20:26:55 +0800 Subject: [PATCH 3/7] Create updater.asm Beta release for romwbw xmodem flash updater --- Source/HBIOS/updater.asm | 1013 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 1013 insertions(+) create mode 100644 Source/HBIOS/updater.asm diff --git a/Source/HBIOS/updater.asm b/Source/HBIOS/updater.asm new file mode 100644 index 00000000..6024a5f1 --- /dev/null +++ b/Source/HBIOS/updater.asm @@ -0,0 +1,1013 @@ +;***************************************************************************** +; ROMWBW XMODEM FLASH UPDATER +; +; PROVIDES THE CAPABILTY TO UPDATE ROMWBW FROM THE SBC BOOT LOADER USING +; AN XMODEM FILE TRANSFER. FOR SYSTEMS WITH AN SST39SF040 FLASH CHIP. +; +; TO INSTALL, SAVE THIS FILE AS USRROM.ASM IN \RomWBW\Source\HBIOS +; AND REBUILD AND INSTALL THE NEW ROM VERSION. +; +; THE UPDATER CAN THEN BE ACCESSED USING THE "U" OPTION IN THE SBC BOOT LOADER. +; +; OPTION (C) AND (S) - CONSOLE AND SERIAL DEVICE +; +; BY DEFAULT THE UPDATER IS SET TO USE THE FIRST ROMWBW CONSOLE DEVICE (0) FOR +; DISPLAY OUTPUT AND FILES TRANSFER. IF YOU USE A DIFFERENT SERIAL DEVICE FOR +; THE FILE TRANSFER, PROGRESS INFORMATION WILL BE DISPLAYED. +; +; OPTION (V) - WRITE VERIFY +; +; BY DEFAULT EACH FLASH SECTOR WILL BE VERIFIED AFTER BEING WRITTEN. SLIGHT +; PERFORMANCE IMPROVEMENTS CAN BE GAINED IF TURNED OFF AND COULD BE USED IF +; YOU ARE EXPERIENCING RELIABLE TRANSFERS AND FLASHING. +; +; OPTION (R) - REBOOT +; EXECUTE A COLD REBOOT. THIS SHOULD BE DONE AFTER A SUCCESSFUL UPDATE. IF +; YOU PERFORM A COLD REBOOT AFTER A FAILED UPDATE THEN IT IS LIKELY THAT +; YOUR SYSTEM WILL BE UNUSABLE AND REMOVING AND REPROGRAMMING THE FLASH +; WILL BE REQUIRED. +; +; OPTION (U) - BEGIN UPDATE +; WILL BEGIN THE UPDATE PROCESS. THE UPDATER WILL EXPECT TO START RECEIVING +; AN XMODEM FILE ON THE SERIAL DEVICE UNIT. +; +; XMODEM SENDS THE FILE IN PACKETS OF 128 BYTES. THE UPDATER WILL CACHE 32 +; PACKETS WHICH IS 1 FLASH SECTOR AND THEN WRITE THAT SECTOR TO THE +; FLASH DEVICE. +; +; IF USING SEPARATE CONSOLE, BANK AND SECTOR PROGESS INFORMATION WILL SHOWN +; +; BANK 00 S00 S01 S02 S03 S04 S05 S06 S06 S07 +; BANK 01 S00 S01 S02 S03 S04 S05 S06 S06 S07 +; BANK 02 S00 S01 S02 S03 S04 S05 S06 S06 S07 etc +; +; THE XMODEM FILE TRANSFER PROTOCOL DOES NOT PROVIDE ANY FILENAME OR SIZE +; INFORMATION FOR THE TRANSFER SO THE UPDATER DOES NOT PERFORM ANY CHECKS +; ON THE FILE SUITABILITY. +; +; THE UPDATER EXPECTS THE FILE SIZE TO BE A MULTIPLE OF 4 KILOBYTES AND +; WILL WRITE ALL DATA RECEIVED TO THE FLASH DEVICE. A SYSTEM UPDATE +; FILE (128KB .IMG) OR COMPLETE ROM CAN BE RECEIVED AND WRITTEN (512KB OR +; 1024KB .ROM) +; +; IF THE UPDATE FAILS IT IS RECOMMENDED THAT YOU RETRY BEFORE REBOOTING OR +; EXITING TO THE SBC BOOT LOADER AS YOUR MACHINE MAY NOT BE BOOTABLE. +; +; OPTION (X) - EXIT TO THE SBC BOOT LOADER. THE SBC IS RELOADED FROM ROM AND +; EXECUTED. AFTER A SUCCESSFUL UPDATE A REBOOT SHOULD BE PERFORMED. HOWEVER, +; IN THE CASE OF A FAILED UPDATE THIS OPTION COULD BE USED TO ATTEMPT TO +; LOAD CP/M AND PERFORM THE NORMAL XMODEM / FLASH PROCESS TO RECOVER. +; +; V.DEV 1/1/2021 PHIL SUMMERS, B1ACKMAI1ER @ RETROBREWCOMPUTERS.ORG +; +; +; NOTES: +; TESTED WITH TERATERM XMODEM. +; ONLY SST39F040 FLASH CHIP IS SUPPORTED DUE TO 4K SECTOR REQUIREMENT. +; SBC V2-005 MEGAFLASH REQUIRED FOR 1MB FLASH SUPPORT. +; FAILURE HANDLING HAS NOT BEEN TESTED. +; TIMING LOOPS ARE NOT CALIBRATED. DEVELOPED ON A 10MHZ Z80 +; +; ACKNOWLEDGEMENTS: +; +; XR - Xmodem Receive for Z80 CP/M 2.2 using CON: +; Copyright 2017 Mats Engstrom, SmallRoomLabs +; Licensed under the MIT license +; https://github.com/SmallRoomLabs/xmodem80/blob/master/XR.Z80 +; +; md.asm - ROMWBW memory disk driver +; https://github.com/wwarthen/RomWBW/blob/master/Source/HBIOS/md.asm +; +;***************************************************************************** +; +#INCLUDE "std.asm" +; +HBX_BNKSEL .EQU $FE2B +HBX_START .EQU $FE00 +; +#DEFINE HB_DI DI +#DEFINE HB_EI EI +; + .ORG USR_LOC +; +; ASCII codes +; +LF: .EQU 'J'-40h ; ^J LF +CR: .EQU 'M'-40h ; ^M CR/ENTER +SOH: .EQU 'A'-40h ; ^A CTRL-A +EOT: .EQU 'D'-40h ; ^D = End of Transmission +ACK: .EQU 'F'-40h ; ^F = Positive Acknowledgement +NAK: .EQU 'U'-40h ; ^U = Negative Acknowledgement +CAN: .EQU 'X'-40h ; ^X = Cancel +BSPC: .EQU 'H'-40h ; ^H = Backspace +; +; Start of code +; + ld (oldSP),SP ; SETUP STACK BELOW HBIOS + ld SP,HBX_START-MD_CSIZ ; ALLOW FOR RELOCATABLE CODE AREA + + ld HL,msgHeader ; PRINT + call PRTSTR0 ; GREETING + + LD HL,MD_FSTART ; COPY FLASH + LD DE,HBX_START-MD_CSIZ ; ROUTINES TO + LD BC,MD_CSIZ ; HIGH MEMORY + LDIR +RESTART: + LD DE,$0000 ; SET UP + LD HL,$0000 ; START + CALL MD_CALBAS ; BANK AND + LD HL,MD_FIDEN ; SECTOR + CALL MD_FNCALL + LD HL,$B7BF ; ABORT + XOR A ; IF FLASH + SBC HL,BC ; CHIP IS + JP NZ,BADCHIP ; NOT SUPPORTED +; +MENULP: + CALL MENU ; DISPLAY MENU + CALL GETINP ; GET SELECTION +; + CP 'U' ; BEGIN + JR Z,CLRSER ; TRANSFER +; + CP 'V' ; CHECK FOR + CALL Z,OPTIONV ; VERIFY TOGGLE +; + CP 'X' ; CHECK FOR + JP Z,ABORT ; USER EXIT + + CP 'R' ; CHECK FOR + JP Z,REBOOT ; COLD REBOOT REQUEST +; + CP 'C' ; CHECK FOR + CALL Z,OPTIONC ; CONSOLE CHANGE +; + CP 'S' ; CHECK FOR + CALL Z,OPTIONS ; SERIAL CHANGE +; + JR MENULP +; +CLRSER: CALL SERST ; EMPTY SERIAL BUFFER + OR A ; SO WE HAVE A CLEAN + JR Z,SERCLR ; START ON TRANSFER + CALL SERIN + JR CLRSER +; +SERCLR: LD HL,msgInstr ; PROVIDE + call PRTSTR0 ; INSTRUCTION +; + LD A,(SERDEV) ; IF CONSOLE AND SERIAL + LD HL,CONDEV ; DEVICE ARE THE SAME, + SUB (HL) ; BLOCK ALL TEXT + LD (BLKCOUT),A ; OUTPUT DURING TRANSFER +; + ld A,1 ; THE FIRST PACKET IS NUMBER 1 + ld (pktNo),A + ld A,255-1 ; ALSO STORE THE 1-COMPLEMENT OF IT + ld (pktNo1c),A +; + LD DE,sector4k ; POINT TO START OF SECTOR TO WRITE +; +GetNewPacket: + ld A,20 ; WE RETRY 20 TIMES BEFORE GIVING UP + ld (retrycnt),A +; +NPloop: ld A,5 ; 5 SECONDS OF TIMEOUT BEFORE EACH NEW BLOCK + call GetCharTmo + jp NC,NotPacketTimeout + + ld HL,retrycnt ; REACHED MAX NUMBER OF RETRIES? + dec (HL) + jp Z,Failure0 ; YES, PRINT MESSAGE AND EXIT + + ld C,NAK ; SEND A NAK TO THE UPLOADER + call SEROUT + jp NPloop + +NotPacketTimeout: + cp EOT ; DID UPLOADER SAY WE'RE FINISHED? + jp Z,Done ; YES, THEN WE'RE DONE + cp CAN ; UPLOADER WANTS TO ABORT TRANSFER? + jp Z,Cancelled ; YES, THEN WE'RE ALSO DONE + cp SOH ; DID WE GET A START-OF-NEW-PACKET? + jp NZ,NPloop ; NO, GO BACK AND TRY AGAIN + + ld HL,packet ; SAVE THE RECEIVED CHAR INTO THE... + ld (HL),A ; ...PACKET BUFFER AND... + inc HL ; ...POINT TO THE NEXT LOCATION + push HL + + ld B,131 ; GET 131 MORE CHARACTERS FOR A FULL PACKET +GetRestOfPacket: + push BC + ld A,1 + call GetCharTmo + pop BC + + LD C,A ; ONLY SAVE + LD A,B ; THE DATA BYTES IN THE 4K SECTOR + CP 130 ; BUFFER I.E. SKIP FIRST 3 + LD A,C + JP P,DONTSAV + LD (DE),A + INC DE +DONTSAV: + pop HL ; SAVE THE RECEIVED CHAR INTO THE... + ld (HL),A ; ...PACKET BUFFER AND... + inc HL ; ...POINT TO THE NEXT LOCATION + push HL + + djnz GetRestOfPacket + POP HL + + ld HL,packet+3 ; CALCULATE CHECKSUM FROM 128 BYTES OF DATA + ld B,128 + ld A,0 +csloop: add A,(HL) ; JUST ADD UP THE BYTES + inc HL + djnz csloop + + xor (HL) ; HL POINTS TO THE RECEIVED CHECKSUM SO + jp NZ,Failure1 ; BY XORING IT TO OUR SUM WE CHECK FOR EQUALITY + + ld A,(pktNo) ; CHECK IF AGREEMENT OF PACKET NUMBERS + ld C,A + ld A,(packet+1) + cp C + jp NZ,Failure2 + + ld A,(pktNo1c) ; CHECK IF AGREEMENT OF 1-COMPL PACKET NUMBERS + ld C,A + ld A,(packet+2) + cp C + jp NZ,Failure3 + + LD HL,pktNo ; HAVE WE RECEIVED + LD A,(HL) ; A BLOCK OF 32 + DEC A ; XMODEM PACKETS + AND %00011111 ; IF YES THEN WERE WE + CP %00011111 ; HAVE ENOUGH TO + CALL Z,WSEC ; WRITE A FLASH SECTOR + + LD A,(VERRES) ; EXIT IF WE GOT A + OR A ; WRITE VERIFICATION + JP NZ,FailWrite ; ERROR + + ld HL,pktNo ; UPDATE THE PACKET COUNTERS + inc (HL) + ld HL,pktNo1c + dec (HL) + + ld C,ACK ; TELL UPLOADER THAT WE'RE HAPPY WITH WITH + call SEROUT ; PACKET AND GO BACK AND FETCH SOME MORE + + jp GetNewPacket + +Done: + ld C,ACK ; TELL UPLOADER WE'RE DONE + call SEROUT + LD A,$FF ; TURN ON OUTPUT + LD (BLKCOUT),A + ld HL,msgSucces1 ; PRINT SUCCESS MESSAGE + call PRTSTR0 + JP RESTART + +FailWrite: + ld HL,msgFailWrt + jp Die + +Failure0: +; LD C,'0' +; CALL CONOUT + JR Failure +Failure1: +; LD C,'1' +; CALL CONOUT + JR Failure +Failure2: +; LD C,'2' +; CALL CONOUT + JR Failure +Failure3: +; LD C,'3' +; CALL CONOUT + JR Failure +Failure: + ld HL,msgFailure + JR Die +Cancelled: + ld HL,msgCancel + JR Die +ABORT: + ld HL,msgAbort + JR Die +BADCHIP: + LD HL,msgBadChip + JR Die +REBOOT: + LD HL,msgReboot ; REBOOT MESSAGE + CALL PRTSTR0 + LD C,BF_SYSRES_COLD ; COLD RESTART + JR Die1 +; +Die: LD A,$FF + LD (BLKCOUT),A ; TURN ON OUTPUT + call PRTSTR0 ; Prints message and exits from program + LD C,BF_SYSRES_WARM ; WARM START +Die1: LD B,BF_SYSRESET ; SYSTEM RESTART + ld SP,(oldSP) + CALL $FFF0 ; CALL HBIOS + ret + +WSEC: PUSH HL + PUSH BC + PUSH DE +; + LD HL,MD_SECT ; IF SECTOR IS 0 + LD A,(HL) ; THEN DISPLAY + OR A ; BANK # PREFIX + JR NZ,NXTS1 + LD HL,msgBank + CALL PRTSTR0 + LD HL,MD_BANK + LD A,(HL) + CALL PRTHEXB +; +NXTS1: LD C,' ' ; DISPLAY + CALL CONOUT ; CURRENT + LD C,'S' ; SECTOR + CALL CONOUT + LD HL,MD_SECT + LD A,(HL) + RRCA + RRCA + RRCA + RRCA + CALL PRTHEXB +; + LD HL,MD_FERAS ; ERASE + CALL MD_FNCALL ; AND WRITE + LD IX,sector4k ; THIS + LD HL,MD_FWRIT ; BANK / SECTOR + CALL MD_FNCALL +; + LD A,(WRTVER) ; VERIFY + OR A ; WRITE IF + JR Z,NOVER ; OPTION + LD IX,sector4k ; SELECTED + LD HL,MD_FVERI + CALL MD_FNCALL + LD (VERRES),A ; SAVE STATUS +; +NOVER: POP DE ; POINT BACK TO + LD DE,sector4k ; START OF 4K BUFFER + PUSH DE + + LD HL,MD_FBAS + LD A,(HL) ; DID WE JUST + SUB $70 ; DO LAST + JR NZ,NXTS2 ; SECTOR +; + LD (HL),A ; RESET SECTOR TO 0 + INC HL + INC (HL) ; NEXT BANK + JR NXTS3 +; +NXTS2: LD A,$10 ; NEXT SECTOR + ADD A,(HL) ; EACH SECTOR IS $1000 + LD (HL),A ; BUT WE JUST INCREASE HIGH BYTE +; +NXTS3: POP DE + POP BC + POP HL + RET +; +; WAITS FOR UP TO A SECONDS FOR A CHARACTER TO BECOME AVAILABLE AND +; RETURNS IT IN A WITHOUT ECHO AND CARRY CLEAR. IF TIMEOUT THEN CARRY +; IT SET. +; +GetCharTmo: + ld B,A +GCtmoa: push BC + ld B,40 +GCtmob: push BC + ld B,255 +GCtmoc: push BC + call SERST + OR A +; cp 00h ; A CHAR AVAILABLE? + jp NZ,GotChar ; YES, GET OUT OF LOOP + ld HL,(0) ; WASTE SOME CYCLES + ld HL,(0) ; ... + ld HL,(0) ; ... + ld HL,(0) ; ... + ld HL,(0) ; ... + ld HL,(0) ; ... + pop BC + djnz GCtmoc + pop BC + djnz GCtmob + pop BC + djnz GCtmoa + scf ; SET CARRY SIGNALS TIMEOUT + ret +; +GotChar:pop BC + pop BC + pop BC + call SERIN + or A ; CLEAR CARRY SIGNALS SUCCESS + ret +; +GETINP: CALL CONIN ; GET A CHARACTER + LD C,A ; RETURN SEQUENCE + CALL CONOUT ; COVERT TO UPPERCASE + LD C,BSPC ; RETURN CHARACTER IN A + CALL CONOUT + LD B,A + CP BSPC + JR Z,GETINP +GETINP2:CALL CONIN + CP BSPC + JR Z,GETINP + CP CR + JR NZ,GETINP2 + LD A,B + LD C,A + CALL CONOUT + CP 'a' ; BELOW 'A'? + JR C,GETINP3 ; IF SO, NOTHING TO DO + CP 'z'+1 ; ABOVE 'Z'? + JR NC,GETINP3 ; IF SO, NOTHING TO DO + AND ~$20 ; CONVERT CHARACTER TO LOWER +GETINP3:RET +; +PRTSTR0:ld A,(HL) ; PRINT MESSAGE POINTED TOP HL UNTIL 0 + or A ; CHECK IF GOT ZERO? + ret Z ; IF ZERO RETURN TO CALLER + ld C,A + call CONOUT ; ELSE PRINT THE CHARACTER + inc HL + jp PRTSTR0 +; +MENU: LD HL,msgConsole ; DISPLAY + CALL PRTSTR0 ; CONSOLE + LD A,(CONDEV) ; DEVICE + ADD A,'0' + LD C,A + CALL CONOUT +; + LD HL,msgIODevice ; DISPLAY + CALL PRTSTR0 ; SERIAL + LD A,(SERDEV) ; DEVICE + ADD A,'0' + LD C,A + CALL CONOUT +; + LD HL,msgWriteV ; DISPLAY + CALL PRTSTR0 ; VERIFY + LD A,(WRTVER) ; OPTION + OR A + LD HL,msgYES + JR NZ,MENU1 + LD HL,msgNO +MENU1: CALL PRTSTR0 +; + LD HL,msgBegin ; DISPLAY OTHER + CALL PRTSTR0 ; MENU OPTIONS + RET +; +OPTIONV:LD A,(WRTVER) ; TOGGLE + CPL ; VERIFY + LD (WRTVER),A ; FLAG + RET +; +OPTIONC:LD HL,msgEnterUnit ; GET + CALL PRTSTR0 ; CONSOLE + CALL GETINP ; UNIT + SUB '0' ; NUMBER + LD (CONDEV),A +CLRCON: CALL CONST ; EMPTY CONSOLE BUFFER + OR A ; SO WE DON'T HAVE ANY + JR Z,CONCLR ; FALSE ENTRIES + CALL CONIN + JR CLRCON +CONCLR: XOR A + RET +; +OPTIONS:LD HL,msgEnterUnit ; GET + CALL PRTSTR0 ; CONSOLE + CALL GETINP ; UNIT + SUB '0' ; NUMBER + LD (SERDEV),A + XOR A + RET +; +SEROUT: PUSH HL ; SERIAL OUTPUT CHARACTER IN C + PUSH DE + PUSH BC + LD E,C + LD B,$01 + LD HL,SERDEV + LD C,(HL) + RST 08 + POP BC + POP DE + POP HL + RET +; +SERST: PUSH HL ; SERIAL STATUS. RETURN CHARACTERS AVAILABLE IN A + PUSH DE + PUSH BC + LD B,$02 + LD HL,SERDEV + LD C,(HL) + RST 08 + POP BC + POP DE + POP HL + RET +; +SERIN: PUSH HL ; SERIAL INPUT. WAIT FOR A CHARACTER ADD RETURN IT IN A + PUSH DE + PUSH BC + LD B,$00 + LD HL,SERDEV + LD C,(HL) + RST 08 + LD A,E + POP BC + POP DE + POP HL + RET +; +CONOUT: PUSH HL ; CONSOLE OUTPUT CHARACTER IN C + PUSH DE ; OUTPUT IS BLOCKED DURING THE + PUSH BC ; FILE TRANSFER WHEN THE + PUSH AF + LD A,(BLKCOUT) ; CONSOLE AND SERIAL LINE + OR A ; ARE THE SAME + JR Z,CONOUT1 + LD E,C + LD B,$01 + LD HL,CONDEV + LD C,(HL) + RST 08 +CONOUT1:POP AF + POP BC + POP DE + POP HL + RET +; +CONST: PUSH HL ; CONSOLE STATUS. RETURN CHARACTERS AVAILABLE IN A + PUSH DE + PUSH BC + LD E,C + LD B,$02 + LD HL,CONDEV + LD C,(HL) + RST 08 + POP BC + POP DE + POP HL + RET +; +CONIN: PUSH HL ; CONSOLE INPUT. WAIT FOR A CHARACTER ADD RETURN IT IN A + PUSH DE + PUSH BC + LD E,C + LD B,$00 + LD HL,CONDEV + LD C,(HL) + RST 08 + LD A,E + POP BC + POP DE + POP HL + RET +; +PRTHEXB:PUSH AF ; PRINT HEX BYTE IN A TO CONSOLE + PUSH DE + CALL HEXASC + LD C,D + CALL CONOUT + LD C,E + CALL CONOUT + POP DE + POP AF + RET + +HEXASC: LD D,A + CALL HEXCONV + LD E,A + LD A,D + RLCA + RLCA + RLCA + RLCA + CALL HEXCONV + LD D,A + RET +; +HEXCONV:AND 0FH ; CONVERT LOW NIBBLE OF A TO ASCII HEX + ADD A,90H + DAA + ADC A,40H + DAA + RET +; +;====================================================================== +; CALCULATE BANK AND ADDRESS DATA FROM MEMORY ADDRESS +; +; ON ENTRY DE:HL CONTAINS 32 BIT MEMORY ADDRESS. +; ON EXIT B CONTAINS BANK SELECT BYTE +; C CONTAINS HIGH BYTE OF SECTOR ADDRESS +;====================================================================== +; +MD_CALBAS: +; + PUSH HL + LD A,E ; BOTTOM PORTION OF SECTOR + AND $0F ; ADDRESS THAT GETS WRITTEN + RLC H ; WITH ERASE COMMAND BYTE + RLA ; A15 GETS DROPPED OFF AND + LD B,A ; ADDED TO BANK SELECT +; + LD A,H ; TOP SECTION OF SECTOR + RRA ; ADDRESS THAT GETS WRITTEN + AND $70 ; TO BANK SELECT PORT + LD C,A + POP HL +; + LD (MD_FBAS),BC ; SAVE BANK AND SECTOR FOR USE IN FLASH ROUTINES + RET +; +MD_FSTART: .EQU $ ; FLASH ROUTINES WHICH GET RELOCATED TO HIGH MEMORY +; +;====================================================================== +; COMMON FUNCTION CALL FOR: +; +; MD_FIDEN_R - IDENTIFY FLASH CHIP +; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED +; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED +; ON EXIT BC CONTAINS THE CHIP ID BYTES. +; A NO STATUS IS RETURNED +; +; MD_FERAS_R - ERASE FLASH SECTOR +; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED +; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED +; ON EXIT A RETURNS STATUS 0=SUCCESS NZ=FAIL +; +; MD_FREAD_R - READ FLASH SECTOR +; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED +; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED +; IX POINTS TO WHERE TO SAVE DATA +; ON EXIT A NO STATUS IS RETURNED +; +; MD_VERI_R - VERIFY FLASH SECTOR +; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED +; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED +; IX POINTS TO DATA TO COMPARE. +; ON EXIT A RETURNS STATUS 0=SUCCESS NZ=FAIL +; +; MD_FWRIT_R - WRITE FLASH SECTOR +; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED +; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED +; IX POINTS TO DATA TO BE WRITTEN +; ON EXIT A NO STATUS IS RETURNED +; +; GENERAL OPERATION: +; COPY FLASH CODE TO UPPER MEMORY +; CALL RELOCATED FLASH CODE +; RETURN WITH ID CODE. +;====================================================================== +; +MD_FNCALL: + LD DE,$0000 + LD BC,(MD_FBAS) ; PUT BANK AND SECTOR DATA IN BC +; + EX AF,AF' + PUSH AF + LD A,(HB_CURBNK) ; WE ARE STARTING IN HB_CURBNK +; + HB_DI + CALL MD_FJPHL + HB_EI +; + POP AF + EX AF,AF' +; + LD A,C ; RETURN WITH STATUS IN A + RET ; RETURN TO MD_READF, MD_WRITEF +; +MD_FJPHL: + JP (HL) +; +;====================================================================== +; FLASH IDENTIFY +; SELECT THE APPROPRIATE BANK / ADDRESS +; ISSUE ID COMMAND +; READ IN ID WORD +; ISSUE ID EXIT COMMAND +; SELECT ORIGINAL BANK +; +; ON ENTRY BC CONTAINS BANK AND SECTOR DATA +; A CONTAINS CURRENT BANK +; ON EXIT BC CONTAINS ID WORD +; NO STATUS IS RETURNED +;====================================================================== +; +MD_FIDEN_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY +; + LD D,A ; SAVE CURRENT BANK +; + LD A,B ; SELECT BANK + CALL HBX_BNKSEL ; TO PROGRAM +; + LD HL,$5555 ; LD A,$AA ; COMMAND + LD (HL),$AA ; LD ($5555),A ; SETUP + LD A,H ; LD A,$55 + LD ($2AAA),A ; LD ($2AAA),A + LD (HL),$90 ; LD A,$90 +; ; LD ($5555),A + LD BC,($0000) ; READ ID +; + LD A,$F0 ; LD A,$F0 ; EXIT + LD (HL),A ; LD ($5555),A ; COMMAND +; + LD A,D ; RETURN TO ORIGINAL BANK + JP HBX_BNKSEL ; WHICH IS OUR RAM BIOS COPY +; +;====================================================================== +; ERASE FLASH SECTOR. +; +; SELECT THE APPROPRIATE BANK / ADDRESS +; ISSUE ERASE SECTOR COMMAND +; POLL TOGGLE BIT FOR COMPLETION STATUS. +; SELECT ORIGINAL BANK +; +; ON ENTRY BC CONTAINS BANK AND SECTOR DATA +; A CONTAINS CURRENT BANK +; ON EXIT C RETURNS STATUS 0=SUCCESS NZ=FAIL +;====================================================================== +; +MD_FERAS_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY +; + EX AF,AF' ; SAVE CURRENT BANK + LD A,B ; SELECT BANK + CALL HBX_BNKSEL ; TO PROGRAM +; + LD HL,$5555 ; LD ($5555),A + LD DE,$2AAA ; LD A,$55 + LD A,L ; LD ($2AAA),A + LD (HL),E ; LD A,$80 + LD (DE),A ; LD ($5555),A + LD (HL),$80 ; LD A,$AA + LD (HL),E ; LD ($5555),A + LD (DE),A ; LD A,$55 +; ; LD ($2AAA),A + LD H,C ; SECTOR + LD L,$00 ; ADDRESS +; + LD A,$30 ; SECTOR ERASE + LD (HL),A ; COMMAND +; +MD_WT4: LD A,(HL) ; DO TWO SUCCESSIVE READS + LD C,(HL) ; FROM THE SAME FLASH ADDRESS. + XOR C ; IF THE SAME ON BOTH READS + BIT 6,A ; THEN ERASE IS COMPLETE SO EXIT. +; + JR Z,MD_WT5 ; BIT 6 = 0 IF SAME ON SUCCESSIVE READS = COMPLETE + ; BIT 6 = 1 IF DIFF ON SUCCESSIVE READS = INCOMPLETE +; + LD A,C ; OPERATION IS NOT COMPLETE. CHECK TIMEOUT BIT (BIT 5). + BIT 5,C ; IF NO TIMEOUT YET THEN LOOP BACK AND KEEP CHECKING TOGGLE STATUS + JR Z,MD_WT4 ; IF BIT 5=0 THEN RETRY; NZ TRUE IF BIT 5=1 +; + LD A,(HL) ; WE GOT A TIMOUT. RECHECK TOGGLE BIT IN CASE WE DID COMPLETE + XOR (HL) ; THE OPERATION. DO TWO SUCCESSIVE READS. ARE THEY THE SAME? + BIT 6,A ; IF THEY ARE THEN OPERATION WAS COMPLETED + JR Z,MD_WT5 ; OTHERWISE ERASE OPERATION FAILED OR TIMED OUT. +; + LD C,$F0 ; COMMON FAIL STATUS / PREPARE DEVICE RESET CODE + LD (HL),C ; WRITE DEVICE RESET + JR MD_WT6 +MD_WT5: LD C,L ; SET SUCCESS STATUS +; +MD_WT6: EX AF,AF' ; RETURN TO ORIGINAL BANK + JP HBX_BNKSEL ; WHICH IS OUR RAM BIOS COPY +; +;====================================================================== +; FLASH READ SECTOR. +; +; SELECT THE APPROPRIATE BANK / ADDRESS +; READ SECTOR OF 4096 BYTES, BYTE AT A TIME +; SELECT SOURCE BANK, READ DATA, +; SELECT DESTINATION BANK, WRITE DATA +; DESTINATION BANK IS ALWAYS CURRENT BANK +; +; ON ENTRY BC CONTAINS BANK AND SECTOR DATA +; DE = 0000 BYTE COUNT +; IX POINTS TO DATA TO BE WRITTEN +; A CONTAINS CURRENT BANK +; ON EXIT NO STATUS RETURNED +; AF' TRASHED +;====================================================================== +; +MD_FREAD_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY +; + LD H,C ; SECTOR + LD L,D ; ADDRESS +; + EX AF,AF' ; PUT DESTINATION BANK IN AF' + LD A,B ; PUT SOURCE BANK IN AF +; +MD_FRD1: + CALL HBX_BNKSEL ; READ ; SWITCH TO SOURCE BANK + LD C,(HL) ; BYTE +; + EX AF,AF' ; SELECT BANK ; SWITCH DESTINATION BANK + CALL HBX_BNKSEL ; TO WRITE + LD (IX+0),C ; WRITE BYTE + EX AF,AF' ; ; PUT SOURCE BANK IN AF +; + INC HL ; NEXT SOURCE LOCATION + INC IX ; NEXT DESTINATION LOCATION +; + INC DE ; CONTINUE READING UNTIL + BIT 4,D ; WE HAVE DONE ONE SECTOR + JR Z,MD_FRD1 +; + RET +; +;====================================================================== +; FLASH VERIFY SECTOR. +; +; SELECT THE APPROPRIATE BANK / ADDRESS +; VERIFY SECTOR OF 4096 BYTES, BYTE AT A TIME +; SELECT SOURCE BANK, READ DATA, +; SELECT DESTINATION BANK, COMPARE DATA +; DESTINATION BANK IS ALWAYS CURRENT BANK +; +; ON ENTRY BC CONTAINS BANK AND SECTOR DATA +; DE = 0000 BYTE COUNT +; IX POINTS TO DATA TO BE VERIFIED +; A CONTAINS CURRENT BANK +; ON EXIT C RETURNS STATUS 0=SUCCESS NZ=FAIL +;====================================================================== +; +MD_FVERI_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY +; + LD H,C ; SECTOR + LD L,D ; ADDRESS +; + EX AF,AF' ; PUT SOURCE BANK IN AF' (RAM) +; +MD_FVE1: + LD A,B ; SELECT BANK + CALL HBX_BNKSEL ; TO READ ; SWITCH TO FLASH BANK + LD A,(HL) ; READ BYTE +; + EX AF,AF' ; SELECT BANK ; SWITCH TO RAM BANK + CALL HBX_BNKSEL ; TO VERIFY AGAINST + EX AF,AF' +; + SUB (IX+0) ; COMPARE BYTE + JR NZ,MD_FVE2 ; EXIT IF MISMATCH +; + INC HL ; NEXT SOURCE LOCATION + INC IX ; NEXT DESTINATION LOCATION +; + INC DE ; CONTINUE READING UNTIL + BIT 4,D ; WE HAVE DONE ONE SECTOR + JR Z,MD_FVE1 +; +MD_FVE2: + LD C,A ; SET STATUS + EX AF,AF' +; + RET +; +;====================================================================== +; FLASH WRITE SECTOR. +; +; SELECT THE APPROPRIATE BANK / ADDRESS +; WRITE 1 SECTOR OF 4096 BYTES, BYTE AT A TIME +; ISSUE WRITE BYTE COMMAND AND WRITE THE DATA BYTE +; POLL TOGGLE BIT FOR COMPLETION STATUS. +; SELECT ORIGINAL BANK +; +; ON ENTRY BC CONTAINS BANK AND SECTOR DATA +; IX POINTS TO DATA TO BE WRITTEN +; DE = 0000 BYTE COUNT +; A CONTAINS CURRENT BANK +; ON EXIT NO STATUS IS RETURNED +;====================================================================== +; +MD_FWRIT_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY +; + LD H,C ; SECTOR + LD L,D ; ADDRESS +; +MD_FWRI1: + CALL HBX_BNKSEL ; SELECT BANK TO READ + EX AF,AF' ; SAVE CURRENT BANK +; + LD C,(IX+0) ; READ IN BYTE +; + LD A,B ; SELECT BANK + CALL HBX_BNKSEL ; TO PROGRAM +; + LD A,$AA ; COMMAND + LD ($5555),A ; SETUP + LD A,$55 + LD ($2AAA),A +; + LD A,$A0 ; WRITE + LD ($5555),A ; COMMAND +; + LD (HL),C ; WRITE OUT BYTE +; +; ; DO TWO SUCCESSIVE READS +MD_FW7: LD A,(HL) ; FROM THE SAME FLASH ADDRESS. + LD C,(HL) ; IF TOGGLE BIT (BIT 6) + XOR C ; IS THE SAME ON BOTH READS + BIT 6,A ; THEN WRITE IS COMPLETE SO EXIT. + JR NZ,MD_FW7 ; Z TRUE IF BIT 6=0 I.E. "NO TOGGLE" WAS DETECTED. +; + INC HL ; NEXT DESTINATION LOCATION + INC IX ; NEXT SOURCE LOCATION +; + EX AF,AF' ; RESTORE CURRENT BANK +; + INC DE ; CONTINUE WRITING UNTIL + BIT 4,D ; WE HAVE DONE ONE SECTOR + JR Z,MD_FWRI1 +; + JP HBX_BNKSEL ; RETURN TO ORIGINAL BANK WHICH IS OUR RAM BIOS COPY +; +MD_FEND .EQU $ +MD_CSIZ .EQU MD_FEND-MD_FSTART ; HOW MUCH SPACE WE NEED FOR RELOCATABLE CODE +; +MD_FIDEN .EQU HBX_START-MD_CSIZ+MD_FIDEN_R-MD_FSTART ; CALL ADDRESS FOR IDENTIFY FLASH CHIP +MD_FERAS .EQU HBX_START-MD_CSIZ+MD_FERAS_R-MD_FSTART ; CALL ADDRESS FOR ERASE FLASH SECTOR +MD_FREAD .EQU HBX_START-MD_CSIZ+MD_FREAD_R-MD_FSTART ; CALL ADDRESS FOR READ FLASH SECTOR +MD_FVERI .EQU HBX_START-MD_CSIZ+MD_FVERI_R-MD_FSTART ; CALL ADDRESS FOR VERIFY FLASH SECTOR +MD_FWRIT .EQU HBX_START-MD_CSIZ+MD_FWRIT_R-MD_FSTART ; CALL ADDRESS FOR WRITE FLASH SECTOR +;MD_FERAC .EQU HBX_START-MD_CSIZ+MD_FERAC_R-MD_FSTART ; CALL ADDRESS FOR ERASE FLASH CHIP +; +; Message strings +; +msgHeader: .DB CR,LF,CR,LF,"ROMWBW XMODEM FLASH UPDATER",CR,LF,0 +msgInstr: .DB CR,LF,CR,LF,"START TRANSFER OF YOUR UPDATE IMAGE OR ROM",CR,LF,0 +msgAbort: .DB CR,LF,"UPDATER ABORTED BY USER",CR,LF,0 +msgBank: .DB CR,LF,"BANK ",0 +msgBadChip: .DB CR,LF,"FLASH CHIP NOT SUPPORTED",CR,LF,0 +msgReboot: .DB CR,LF,"REBOOTING ...",CR,LF,0 +msgFailWrt: .DB CR,LF,"FLASH WRITE FAILED",CR,LF,0 +msgFailure: .DB CR,LF,"TRANSMISSION FAILED",CR,LF,0 +msgCancel: .DB CR,LF,"TRANSMISSION CANCELLED",CR,LF,0 +msgConsole: .DB CR,LF,"(C) Set Console Device : ",0 +msgIODevice: .DB CR,LF,"(S) Set Serial Device : ",0 +msgWriteV: .DB CR,LF,"(V) Toggle Write Verify : ",0 +msgBegin: .DB CR,LF,"(R) Reboot" + .DB CR,LF,"(U) Begin Update" + .DB CR,LF,"(X) Exit to Rom Loader" + .DB CR,LF,CR,LF,"Select : ",0 +msgSucces1: .DB CR,LF,CR,LF,"UPDATE COMPLETED WITHOUT ERRORS ",CR,LF,0 +msgEnterUnit: .DB CR,LF,"ENTER UNIT NUMBER : ",0 +msgCRLF: .DB CR,LF,0 +msgYES: .DB "YES",0 +msgNO: .DB "NO",0 +; +; Variables +; +CONDEV: .DB $00 ; HBIOS CONSOLE DEVICE NUMBER +SERDEV: .DB $00 ; HBIOS SERIAL DEVICE NUMBER USED FOR XMODEM TRANSFER +WRTVER: .DB $FF ; WRITE VERIFY OPTION FLAG +VERRES: .DB $00 ; WRITE VERIFY RESULT +BLKCOUT: .DB $FF ; BLOCK TEXT OUTPUT DURING TRANSFER IF ZERO +oldSP: .DW 0 ; The orginal SP to be restored before exiting +retrycnt: .DB 0 ; Counter for retries before giving up +chksum: .DB 0 ; For calculating the checksum of the packet +pktNo: .DB 0 ; Current packet Number +pktNo1c: .DB 0 ; Current packet Number 1-complemented +MD_FBAS .DW $FFFF ; CURRENT BANK AND SECTOR +MD_SECT .EQU MD_FBAS ; BANK BYTE +MD_BANK .EQU MD_FBAS+1 ; SECTOR BYTE +; +packet: .DB 0 ; SOH + .DB 0 ; PacketN + .DB 0 ; -PacketNo, + .FILL 128,0 ; data*128, + .DB 0 ; chksum +; +sector4k: .EQU $ ; 32 PACKETS GET ACCUMULATED HERE BEFORE FLASHING +; +SLACK .EQU (USR_END - $) + .FILL SLACK,$FF + .ECHO "User ROM space remaining: " + .ECHO SLACK + .ECHO " bytes.\n" + .END From 9bd2dda749376ea2153b2583c9a87a8fe3488f97 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sun, 3 Jan 2021 20:25:15 +0800 Subject: [PATCH 4/7] Update updater.asm Documented serial limitations. Improved error handling and messages. Tried to optimize packet read loop Tried to optimize character read polling Added some debug options for testing --- Source/HBIOS/updater.asm | 528 ++++++++++++++++++++++----------------- 1 file changed, 300 insertions(+), 228 deletions(-) diff --git a/Source/HBIOS/updater.asm b/Source/HBIOS/updater.asm index 6024a5f1..f3c70c18 100644 --- a/Source/HBIOS/updater.asm +++ b/Source/HBIOS/updater.asm @@ -1,17 +1,17 @@ ;***************************************************************************** -; ROMWBW XMODEM FLASH UPDATER +; ROMWBW XMODEM FLASH UPDATER ; -; PROVIDES THE CAPABILTY TO UPDATE ROMWBW FROM THE SBC BOOT LOADER USING +; PROVIDES THE CAPABILTY TO UPDATE ROMWBW FROM THE SBC BOOT LOADER USING ; AN XMODEM FILE TRANSFER. FOR SYSTEMS WITH AN SST39SF040 FLASH CHIP. ; ; TO INSTALL, SAVE THIS FILE AS USRROM.ASM IN \RomWBW\Source\HBIOS ; AND REBUILD AND INSTALL THE NEW ROM VERSION. -; +; ; THE UPDATER CAN THEN BE ACCESSED USING THE "U" OPTION IN THE SBC BOOT LOADER. ; ; OPTION (C) AND (S) - CONSOLE AND SERIAL DEVICE ; -; BY DEFAULT THE UPDATER IS SET TO USE THE FIRST ROMWBW CONSOLE DEVICE (0) FOR +; BY DEFAULT THE UPDATER IS SET TO USE THE FIRST ROMWBW CONSOLE DEVICE (0) FOR ; DISPLAY OUTPUT AND FILES TRANSFER. IF YOU USE A DIFFERENT SERIAL DEVICE FOR ; THE FILE TRANSFER, PROGRESS INFORMATION WILL BE DISPLAYED. ; @@ -22,24 +22,24 @@ ; YOU ARE EXPERIENCING RELIABLE TRANSFERS AND FLASHING. ; ; OPTION (R) - REBOOT -; EXECUTE A COLD REBOOT. THIS SHOULD BE DONE AFTER A SUCCESSFUL UPDATE. IF +; EXECUTE A COLD REBOOT. THIS SHOULD BE DONE AFTER A SUCCESSFUL UPDATE. IF ; YOU PERFORM A COLD REBOOT AFTER A FAILED UPDATE THEN IT IS LIKELY THAT ; YOUR SYSTEM WILL BE UNUSABLE AND REMOVING AND REPROGRAMMING THE FLASH ; WILL BE REQUIRED. ; ; OPTION (U) - BEGIN UPDATE ; WILL BEGIN THE UPDATE PROCESS. THE UPDATER WILL EXPECT TO START RECEIVING -; AN XMODEM FILE ON THE SERIAL DEVICE UNIT. +; AN XMODEM FILE ON THE SERIAL DEVICE UNIT. ; ; XMODEM SENDS THE FILE IN PACKETS OF 128 BYTES. THE UPDATER WILL CACHE 32 -; PACKETS WHICH IS 1 FLASH SECTOR AND THEN WRITE THAT SECTOR TO THE +; PACKETS WHICH IS 1 FLASH SECTOR AND THEN WRITE THAT SECTOR TO THE ; FLASH DEVICE. ; ; IF USING SEPARATE CONSOLE, BANK AND SECTOR PROGESS INFORMATION WILL SHOWN ; ; BANK 00 S00 S01 S02 S03 S04 S05 S06 S06 S07 -; BANK 01 S00 S01 S02 S03 S04 S05 S06 S06 S07 -; BANK 02 S00 S01 S02 S03 S04 S05 S06 S06 S07 etc +; BANK 01 S00 S01 S02 S03 S04 S05 S06 S06 S07 +; BANK 02 S00 S01 S02 S03 S04 S05 S06 S06 S07 etc ; ; THE XMODEM FILE TRANSFER PROTOCOL DOES NOT PROVIDE ANY FILENAME OR SIZE ; INFORMATION FOR THE TRANSFER SO THE UPDATER DOES NOT PERFORM ANY CHECKS @@ -58,7 +58,12 @@ ; IN THE CASE OF A FAILED UPDATE THIS OPTION COULD BE USED TO ATTEMPT TO ; LOAD CP/M AND PERFORM THE NORMAL XMODEM / FLASH PROCESS TO RECOVER. ; -; V.DEV 1/1/2021 PHIL SUMMERS, B1ACKMAI1ER @ RETROBREWCOMPUTERS.ORG +; OPTION (H) - DEBUG OPTION - SWITCH ON CPU CLCOK DIVIDER ON SBC-V2-004+ +; OPTION (T) - DEBUG OPTION - TEST TIMER FOR 20 SECONDS. * = START AND FINISH +; +; +; V.DEV 3/1/2021 PHIL SUMMERS, DIFFICULTYLEVELHIGH@GMAIL.COM +; b1ackmai1er ON RETROBREWCOMPUTERS.ORG ; ; ; NOTES: @@ -66,7 +71,17 @@ ; ONLY SST39F040 FLASH CHIP IS SUPPORTED DUE TO 4K SECTOR REQUIREMENT. ; SBC V2-005 MEGAFLASH REQUIRED FOR 1MB FLASH SUPPORT. ; FAILURE HANDLING HAS NOT BEEN TESTED. -; TIMING LOOPS ARE NOT CALIBRATED. DEVELOPED ON A 10MHZ Z80 +; TIMING BROADLY CALIBRATED ON A Z80 SBC-V2 +; UNABIOS NOT SUPPORTED +; +; MAXIMUM SERIAL SPEED LIMITATIONS +; +; SBC-V2 UART NO FLOW CONTROL 2MHZ | 9600 +; SBC-V2 UART NO FLOW CONTROL 4MHZ | 19200 +; SBC-V2 UART NO FLOW CONTROL 5MHZ | 19200 +; SBC-V2 UART NO FLOW CONTROL 8MHZ | 38400 +; SBC-V2 UART NO FLOW CONTROL 10MHZ | 38400 +; SBC-V2 USB-FIFO 2MHZ+ | N/A ; ; ACKNOWLEDGEMENTS: ; @@ -87,6 +102,8 @@ HBX_START .EQU $FE00 ; #DEFINE HB_DI DI #DEFINE HB_EI EI +; +XFUDBG .EQU 0 ; .ORG USR_LOC ; @@ -107,7 +124,7 @@ BSPC: .EQU 'H'-40h ; ^H = Backspace ld SP,HBX_START-MD_CSIZ ; ALLOW FOR RELOCATABLE CODE AREA ld HL,msgHeader ; PRINT - call PRTSTR0 ; GREETING + CALL PRTSTR0 ; GREETING LD HL,MD_FSTART ; COPY FLASH LD DE,HBX_START-MD_CSIZ ; ROUTINES TO @@ -119,13 +136,19 @@ RESTART: CALL MD_CALBAS ; BANK AND LD HL,MD_FIDEN ; SECTOR CALL MD_FNCALL - LD HL,$B7BF ; ABORT + LD HL,$B7BF ; FAIL XOR A ; IF FLASH SBC HL,BC ; CHIP IS - JP NZ,BADCHIP ; NOT SUPPORTED -; -MENULP: - CALL MENU ; DISPLAY MENU + JP NZ,FAILBC ; NOT SUPPORTED + + LD BC,$F8F0 ; GET CPU SPEED + RST 08 ; AND MULTIPLY + LD A,L ; BY 4 + ADD A,A ; TO CREATE + ADD A,A ; TIMOUT DELAY + LD (TmoFct),A ; FACTOR +; +MENULP: CALL MENU ; DISPLAY MENU CALL GETINP ; GET SELECTION ; CP 'U' ; BEGIN @@ -135,7 +158,7 @@ MENULP: CALL Z,OPTIONV ; VERIFY TOGGLE ; CP 'X' ; CHECK FOR - JP Z,ABORT ; USER EXIT + JP Z,FAILUX ; USER EXIT CP 'R' ; CHECK FOR JP Z,REBOOT ; COLD REBOOT REQUEST @@ -145,6 +168,14 @@ MENULP: ; CP 'S' ; CHECK FOR CALL Z,OPTIONS ; SERIAL CHANGE +; +#IF (XFUDBG) + CP 'T' ; TEST TIMEOUT + CALL Z,OPTIONT ; LOOP +; + CP 'H' ; HALF + CALL Z,OPTIONH ; SPEED SWITCH +#ENDIF ; JR MENULP ; @@ -154,175 +185,183 @@ CLRSER: CALL SERST ; EMPTY SERIAL BUFFER CALL SERIN JR CLRSER ; -SERCLR: LD HL,msgInstr ; PROVIDE - call PRTSTR0 ; INSTRUCTION +SERCLR: XOR A ; CLEAR VERIFY + LD (VERRES),A ; FAILURE FLAG +; + LD HL,msgInstr ; PROVIDE + CALL PRTSTR0 ; INSTRUCTION ; LD A,(SERDEV) ; IF CONSOLE AND SERIAL LD HL,CONDEV ; DEVICE ARE THE SAME, - SUB (HL) ; BLOCK ALL TEXT + SUB (HL) ; BLOCK ALL TEXT LD (BLKCOUT),A ; OUTPUT DURING TRANSFER ; - ld A,1 ; THE FIRST PACKET IS NUMBER 1 - ld (pktNo),A - ld A,255-1 ; ALSO STORE THE 1-COMPLEMENT OF IT - ld (pktNo1c),A + LD A,1 ; THE FIRST PACKET IS NUMBER 1 + LD (pktNo),A + LD A,255-1 ; ALSO STORE THE 1-COMPLEMENT OF IT + LD (pktNo1c),A ; LD DE,sector4k ; POINT TO START OF SECTOR TO WRITE ; GetNewPacket: ld A,20 ; WE RETRY 20 TIMES BEFORE GIVING UP - ld (retrycnt),A + LD (retrycnt),A ; -NPloop: ld A,5 ; 5 SECONDS OF TIMEOUT BEFORE EACH NEW BLOCK - call GetCharTmo +NPloop: LD B,5 ; 5 SECONDS OF TIMEOUT BEFORE EACH NEW BLOCK + CALL GetCharTmo jp NC,NotPacketTimeout - +; ld HL,retrycnt ; REACHED MAX NUMBER OF RETRIES? dec (HL) - jp Z,Failure0 ; YES, PRINT MESSAGE AND EXIT - - ld C,NAK ; SEND A NAK TO THE UPLOADER - call SEROUT - jp NPloop - + jp Z,FAILRT ; YES, PRINT MESSAGE AND EXIT +; + LD C,NAK ; SEND A NAK TO THE UPLOADER + CALL SEROUT + JR NPloop +; NotPacketTimeout: cp EOT ; DID UPLOADER SAY WE'RE FINISHED? jp Z,Done ; YES, THEN WE'RE DONE - cp CAN ; UPLOADER WANTS TO ABORT TRANSFER? - jp Z,Cancelled ; YES, THEN WE'RE ALSO DONE + cp CAN ; UPLOADER WANTS TO FAIL TRANSFER? + jp Z,FAILCN ; YES, THEN WE'RE ALSO DONE cp SOH ; DID WE GET A START-OF-NEW-PACKET? - jp NZ,NPloop ; NO, GO BACK AND TRY AGAIN - + JR NZ,NPloop ; NO, GO BACK AND TRY AGAIN +; ld HL,packet ; SAVE THE RECEIVED CHAR INTO THE... ld (HL),A ; ...PACKET BUFFER AND... - inc HL ; ...POINT TO THE NEXT LOCATION - push HL - - ld B,131 ; GET 131 MORE CHARACTERS FOR A FULL PACKET + INC HL ; ...POINT TO THE NEXT LOCATION +; + LD B,1 ; GET CHARACTER + CALL GetCharTmo ; SHOULD BE PACKET NUMBER + ld (HL),A + INC HL + JP C,FAILTO +; + LD B,1 ; GET CHARACTER + CALL GetCharTmo ; SHOULD BE PACKET NUMBER + ld (HL),A ; COMPLEMENT + INC HL + JP C,FAILTO +; + LD B,128 ; GET 128 MORE CHARACTERS FOR A FULL PACKET GetRestOfPacket: - push BC - ld A,1 - call GetCharTmo + push BC ; GET CHARACTER + LD B,1 + CALL GetCharTmo pop BC - - LD C,A ; ONLY SAVE - LD A,B ; THE DATA BYTES IN THE 4K SECTOR - CP 130 ; BUFFER I.E. SKIP FIRST 3 - LD A,C - JP P,DONTSAV - LD (DE),A - INC DE -DONTSAV: - pop HL ; SAVE THE RECEIVED CHAR INTO THE... - ld (HL),A ; ...PACKET BUFFER AND... - inc HL ; ...POINT TO THE NEXT LOCATION - push HL - - djnz GetRestOfPacket - POP HL - + JP C,FAILTO +; + LD (HL),A + INC HL ; SAVE THE RECEIVED CHAR INTO THE... + LD (DE),A ; ...PACKET BUFFER AND... + INC DE ; ...POINT TO THE NEXT LOCATION +; + DJNZ GetRestOfPacket +; + LD B,1 ; GET CHARACTER + CALL GetCharTmo ; SHOULD BE CHECKSUM + LD (HL),A + JP C,FAILTO +; ld HL,packet+3 ; CALCULATE CHECKSUM FROM 128 BYTES OF DATA ld B,128 - ld A,0 + XOR A csloop: add A,(HL) ; JUST ADD UP THE BYTES inc HL - djnz csloop - - xor (HL) ; HL POINTS TO THE RECEIVED CHECKSUM SO - jp NZ,Failure1 ; BY XORING IT TO OUR SUM WE CHECK FOR EQUALITY - - ld A,(pktNo) ; CHECK IF AGREEMENT OF PACKET NUMBERS - ld C,A - ld A,(packet+1) - cp C - jp NZ,Failure2 - - ld A,(pktNo1c) ; CHECK IF AGREEMENT OF 1-COMPL PACKET NUMBERS - ld C,A - ld A,(packet+2) - cp C - jp NZ,Failure3 - + DJNZ csloop +; + XOR (HL) ; HL POINTS TO THE RECEIVED CHECKSUM SO + JP NZ,FAILCS ; BY XORING IT TO OUR SUM WE CHECK FOR EQUALITY +; + LD HL,(pktNo) ; CHECK + LD BC,(packet+1) ; AGREEMENT +; XOR A ; PACKET + SBC HL,BC ; NUMBERS + JP NZ,FAILPN +; LD HL,pktNo ; HAVE WE RECEIVED LD A,(HL) ; A BLOCK OF 32 DEC A ; XMODEM PACKETS AND %00011111 ; IF YES THEN WERE WE CP %00011111 ; HAVE ENOUGH TO - CALL Z,WSEC ; WRITE A FLASH SECTOR - - LD A,(VERRES) ; EXIT IF WE GOT A - OR A ; WRITE VERIFICATION - JP NZ,FailWrite ; ERROR + LD A,0 ; WRITE A FLASH SECTOR + CALL Z,WSEC ; ASSUME FLASH SUCCESSFUL +; + OR A ; EXIT IF WE GOT A + JP NZ,FAILWF ; WRITE VERIFICATION ERROR ld HL,pktNo ; UPDATE THE PACKET COUNTERS - inc (HL) - ld HL,pktNo1c + INC (HL) + INC HL dec (HL) - - ld C,ACK ; TELL UPLOADER THAT WE'RE HAPPY WITH WITH - call SEROUT ; PACKET AND GO BACK AND FETCH SOME MORE - - jp GetNewPacket - -Done: - ld C,ACK ; TELL UPLOADER WE'RE DONE - call SEROUT - LD A,$FF ; TURN ON OUTPUT - LD (BLKCOUT),A - ld HL,msgSucces1 ; PRINT SUCCESS MESSAGE - call PRTSTR0 +; + LD C,ACK ; TELL UPLOADER THAT WE'RE HAPPY WITH WITH + CALL SEROUT ; PACKET AND GO BACK AND FETCH SOME MORE +; + JP GetNewPacket +; +Done: LD C,ACK ; TELL UPLOADER + CALL SEROUT ; WE'RE DONE + LD HL,msgSucces1 ; BACK TO + JR MSGRS ; MENU +; +FAILTO: LD HL,msgTimout ; TIMOUT WAITING + JR ERRRX ; FOR CHARACTER +; +FAILWF: LD HL,msgFailWrt ; FLASH + JR MSGRS ; VERIFY FAIL +; +FAILRT: LD HL,msgRetry ; RETRY + JR ERRRX ; TIMEOUT FAIL +; +FAILCS: LD HL,msgChkSum ; CHECKSUM + JR ERRRX ; ERROR +; +FAILPN: LD HL,msgPacErr ; PACKET + JR ERRRX ; NUMBER ERROR +; +FAILCN: LD HL,msgCancel ; TRANSMISSION + JR ERRRX ; FAILCN +; +FAILUX: LD HL,msgUserEx ; USER + JR Die ; EXIT +; +FAILBC: LD HL,msgUnsupC ; UNSUPPORTED + JR Die ; FLASH CHIP +; +ERRRX: LD A,$FF + LD (BLKCOUT),A ; TURN ON OUTPUT + CALL PRTSTR0 ; DISPLAY TRANSMISSION + LD HL,msgFailure ; RECEIPT ERROR + CALL PRTSTR0 JP RESTART - -FailWrite: - ld HL,msgFailWrt - jp Die - -Failure0: -; LD C,'0' -; CALL CONOUT - JR Failure -Failure1: -; LD C,'1' -; CALL CONOUT - JR Failure -Failure2: -; LD C,'2' -; CALL CONOUT - JR Failure -Failure3: -; LD C,'3' -; CALL CONOUT - JR Failure -Failure: - ld HL,msgFailure - JR Die -Cancelled: - ld HL,msgCancel - JR Die -ABORT: - ld HL,msgAbort - JR Die -BADCHIP: - LD HL,msgBadChip - JR Die -REBOOT: - LD HL,msgReboot ; REBOOT MESSAGE +; +MSGRS: LD A,$FF + LD (BLKCOUT),A ; TURN ON OUTPUT + CALL PRTSTR0 ; DISPLAY TRANSMISSION + JP RESTART +; +REBOOT: LD HL,msgReboot ; REBOOT MESSAGE CALL PRTSTR0 LD C,BF_SYSRES_COLD ; COLD RESTART JR Die1 -; +; Die: LD A,$FF LD (BLKCOUT),A ; TURN ON OUTPUT - call PRTSTR0 ; Prints message and exits from program + CALL PRTSTR0 ; Prints message and exits from program LD C,BF_SYSRES_WARM ; WARM START Die1: LD B,BF_SYSRESET ; SYSTEM RESTART ld SP,(oldSP) CALL $FFF0 ; CALL HBIOS - ret + RET -WSEC: PUSH HL - PUSH BC - PUSH DE +WSEC: PUSH HL ; WRITE A + PUSH BC ; FLASH + PUSH DE ; SECTOR +; + LD A,(BLKCOUT) ; SKIP OUTPUT + OR A ; IF TRANSFERRING + JR Z,WSEC1 ; OVER CONSOLE ; LD HL,MD_SECT ; IF SECTOR IS 0 LD A,(HL) ; THEN DISPLAY @@ -332,7 +371,6 @@ WSEC: PUSH HL CALL PRTSTR0 LD HL,MD_BANK LD A,(HL) - CALL PRTHEXB ; NXTS1: LD C,' ' ; DISPLAY CALL CONOUT ; CURRENT @@ -346,24 +384,26 @@ NXTS1: LD C,' ' ; DISPLAY RRCA CALL PRTHEXB ; - LD HL,MD_FERAS ; ERASE +WSEC1: LD HL,MD_FERAS ; ERASE CALL MD_FNCALL ; AND WRITE LD IX,sector4k ; THIS LD HL,MD_FWRIT ; BANK / SECTOR - CALL MD_FNCALL + CALL MD_FNCALL ; - LD A,(WRTVER) ; VERIFY + LD A,(WRTVER) ; VERIFY OR A ; WRITE IF JR Z,NOVER ; OPTION - LD IX,sector4k ; SELECTED - LD HL,MD_FVERI +; + LD IX,sector4k ; VERIFY + LD HL,MD_FVERI ; WRITE CALL MD_FNCALL LD (VERRES),A ; SAVE STATUS + CALL PRTHEXB ; -NOVER: POP DE ; POINT BACK TO +NOVER: POP DE ; POINT BACK TO LD DE,sector4k ; START OF 4K BUFFER PUSH DE - +; LD HL,MD_FBAS LD A,(HL) ; DID WE JUST SUB $70 ; DO LAST @@ -378,7 +418,8 @@ NXTS2: LD A,$10 ; NEXT SECTOR ADD A,(HL) ; EACH SECTOR IS $1000 LD (HL),A ; BUT WE JUST INCREASE HIGH BYTE ; -NXTS3: POP DE +NXTS3: LD A,(VERRES) ; EXIT WITH STATUS + POP DE POP BC POP HL RET @@ -387,40 +428,39 @@ NXTS3: POP DE ; RETURNS IT IN A WITHOUT ECHO AND CARRY CLEAR. IF TIMEOUT THEN CARRY ; IT SET. ; +; 4MHZ 20 SECONDS B=16 +; 10MHZ 20 SECONDS B=39 +; GetCharTmo: - ld B,A -GCtmoa: push BC - ld B,40 -GCtmob: push BC - ld B,255 -GCtmoc: push BC - call SERST - OR A -; cp 00h ; A CHAR AVAILABLE? - jp NZ,GotChar ; YES, GET OUT OF LOOP - ld HL,(0) ; WASTE SOME CYCLES - ld HL,(0) ; ... - ld HL,(0) ; ... - ld HL,(0) ; ... - ld HL,(0) ; ... - ld HL,(0) ; ... - pop BC + CALL SERST ; IF THER IS A + OR A ; CHARACTER AVAILABLE + JR NZ,GotChrX ; EXIT NO OTHERWISE POLL + PUSH BC + ld BC,255 ; C=CONSTANT (255) FOR INNER TIMING LOOP +TmoFct: .EQU $-1 ; B=SPEED FACTOR WHICH GETS UPDATED AT START +GCtmob: PUSH BC + ld B,C +GCtmoc: PUSH BC + CALL SERST + OR A ; A CHAR AVAILABLE? + JR NZ,GotChar ; YES, GET OUT OF LOOP + POP BC djnz GCtmoc - pop BC + POP BC djnz GCtmob - pop BC - djnz GCtmoa + POP BC + djnz GetCharTmo scf ; SET CARRY SIGNALS TIMEOUT - ret + RET ; -GotChar:pop BC - pop BC - pop BC - call SERIN +GotChar:POP BC + POP BC + POP BC +GotChrX:CALL SERIN or A ; CLEAR CARRY SIGNALS SUCCESS - ret + RET ; -GETINP: CALL CONIN ; GET A CHARACTER +GETINP: CALL CONIN ; GET A CHARACTER LD C,A ; RETURN SEQUENCE CALL CONOUT ; COVERT TO UPPERCASE LD C,BSPC ; RETURN CHARACTER IN A @@ -441,13 +481,13 @@ GETINP2:CALL CONIN CP 'z'+1 ; ABOVE 'Z'? JR NC,GETINP3 ; IF SO, NOTHING TO DO AND ~$20 ; CONVERT CHARACTER TO LOWER -GETINP3:RET +GETINP3:RET ; PRTSTR0:ld A,(HL) ; PRINT MESSAGE POINTED TOP HL UNTIL 0 or A ; CHECK IF GOT ZERO? - ret Z ; IF ZERO RETURN TO CALLER - ld C,A - call CONOUT ; ELSE PRINT THE CHARACTER + RET Z ; IF ZERO RETURN TO CALLER + LD C,A + CALL CONOUT ; ELSE PRINT THE CHARACTER inc HL jp PRTSTR0 ; @@ -485,8 +525,12 @@ OPTIONV:LD A,(WRTVER) ; TOGGLE ; OPTIONC:LD HL,msgEnterUnit ; GET CALL PRTSTR0 ; CONSOLE - CALL GETINP ; UNIT - SUB '0' ; NUMBER + CALL GETINP ; UNIT NUMBER + CP '0' + JR C,CONCLR + CP '9' + 1 + JR NC,CONCLR + SUB '0' LD (CONDEV),A CLRCON: CALL CONST ; EMPTY CONSOLE BUFFER OR A ; SO WE DON'T HAVE ANY @@ -499,11 +543,31 @@ CONCLR: XOR A OPTIONS:LD HL,msgEnterUnit ; GET CALL PRTSTR0 ; CONSOLE CALL GETINP ; UNIT - SUB '0' ; NUMBER + CP '0' + JR C,CONCLR + CP '9' + 1 + JR NC,CONCLR + SUB '0' ; NUMBER LD (SERDEV),A XOR A RET ; +#IF (XFUDBG) +OPTIONT:LD C,'*' + CALL CONOUT + LD B,20 + CALL GetCharTmo + LD C,'*' + CALL CONOUT + RET +; +OPTIONH:LD A,8 ; TURN ON THE + OUT (RTCIO),A ; SBC-V2-004+ + LD HL,TmoFct ; CLOCK DIVIDER + SRL (HL) ; AND ADJUST + RET ; DELAY FACTOR (/2) +#ENDIF +; SEROUT: PUSH HL ; SERIAL OUTPUT CHARACTER IN C PUSH DE PUSH BC @@ -544,7 +608,7 @@ SERIN: PUSH HL ; SERIAL INPUT. WAIT FOR A CHARACTER ADD RETURN IT IN A ; CONOUT: PUSH HL ; CONSOLE OUTPUT CHARACTER IN C PUSH DE ; OUTPUT IS BLOCKED DURING THE - PUSH BC ; FILE TRANSFER WHEN THE + PUSH BC ; FILE TRANSFER WHEN THE PUSH AF LD A,(BLKCOUT) ; CONSOLE AND SERIAL LINE OR A ; ARE THE SAME @@ -648,18 +712,18 @@ MD_FSTART: .EQU $ ; FLASH ROUTINES WHICH GET RELOCATED TO HIGH MEMORY ;====================================================================== ; COMMON FUNCTION CALL FOR: ; -; MD_FIDEN_R - IDENTIFY FLASH CHIP +; MD_FIDEN_R - IDENTIFY FLASH CHIP ; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED ; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED ; ON EXIT BC CONTAINS THE CHIP ID BYTES. -; A NO STATUS IS RETURNED +; A NO STATUS IS RETURNED ; -; MD_FERAS_R - ERASE FLASH SECTOR +; MD_FERAS_R - ERASE FLASH SECTOR ; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED ; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED ; ON EXIT A RETURNS STATUS 0=SUCCESS NZ=FAIL ; -; MD_FREAD_R - READ FLASH SECTOR +; MD_FREAD_R - READ FLASH SECTOR ; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED ; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED ; IX POINTS TO WHERE TO SAVE DATA @@ -671,7 +735,7 @@ MD_FSTART: .EQU $ ; FLASH ROUTINES WHICH GET RELOCATED TO HIGH MEMORY ; IX POINTS TO DATA TO COMPARE. ; ON EXIT A RETURNS STATUS 0=SUCCESS NZ=FAIL ; -; MD_FWRIT_R - WRITE FLASH SECTOR +; MD_FWRIT_R - WRITE FLASH SECTOR ; ON ENTRY MD_FBAS HAS BEEN SET WITH BANK AND SECTOR BEING ACCESSED ; HL POINTS TO THE ROUTINE TO BE RELOCATED AND CALLED ; IX POINTS TO DATA TO BE WRITTEN @@ -699,7 +763,7 @@ MD_FNCALL: EX AF,AF' ; LD A,C ; RETURN WITH STATUS IN A - RET ; RETURN TO MD_READF, MD_WRITEF + RET ; MD_FJPHL: JP (HL) @@ -713,9 +777,9 @@ MD_FJPHL: ; SELECT ORIGINAL BANK ; ; ON ENTRY BC CONTAINS BANK AND SECTOR DATA -; A CONTAINS CURRENT BANK +; A CONTAINS CURRENT BANK ; ON EXIT BC CONTAINS ID WORD -; NO STATUS IS RETURNED +; NO STATUS IS RETURNED ;====================================================================== ; MD_FIDEN_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY @@ -733,14 +797,14 @@ MD_FIDEN_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY ; ; LD ($5555),A LD BC,($0000) ; READ ID ; - LD A,$F0 ; LD A,$F0 ; EXIT + LD A,$F0 ; LD A,$F0 ; EXIT LD (HL),A ; LD ($5555),A ; COMMAND ; LD A,D ; RETURN TO ORIGINAL BANK JP HBX_BNKSEL ; WHICH IS OUR RAM BIOS COPY ; ;====================================================================== -; ERASE FLASH SECTOR. +; ERASE FLASH SECTOR. ; ; SELECT THE APPROPRIATE BANK / ADDRESS ; ISSUE ERASE SECTOR COMMAND @@ -748,7 +812,7 @@ MD_FIDEN_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY ; SELECT ORIGINAL BANK ; ; ON ENTRY BC CONTAINS BANK AND SECTOR DATA -; A CONTAINS CURRENT BANK +; A CONTAINS CURRENT BANK ; ON EXIT C RETURNS STATUS 0=SUCCESS NZ=FAIL ;====================================================================== ; @@ -759,15 +823,15 @@ MD_FERAS_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY CALL HBX_BNKSEL ; TO PROGRAM ; LD HL,$5555 ; LD ($5555),A - LD DE,$2AAA ; LD A,$55 - LD A,L ; LD ($2AAA),A - LD (HL),E ; LD A,$80 - LD (DE),A ; LD ($5555),A - LD (HL),$80 ; LD A,$AA - LD (HL),E ; LD ($5555),A - LD (DE),A ; LD A,$55 -; ; LD ($2AAA),A - LD H,C ; SECTOR + LD DE,$2AAA ; LD A,$55 + LD A,L ; LD ($2AAA),A + LD (HL),E ; LD A,$80 + LD (DE),A ; LD ($5555),A + LD (HL),$80 ; LD A,$AA + LD (HL),E ; LD ($5555),A + LD (DE),A ; LD A,$55 +; ; LD ($2AAA),A + LD H,C ; SECTOR LD L,$00 ; ADDRESS ; LD A,$30 ; SECTOR ERASE @@ -785,9 +849,9 @@ MD_WT4: LD A,(HL) ; DO TWO SUCCESSIVE READS BIT 5,C ; IF NO TIMEOUT YET THEN LOOP BACK AND KEEP CHECKING TOGGLE STATUS JR Z,MD_WT4 ; IF BIT 5=0 THEN RETRY; NZ TRUE IF BIT 5=1 ; - LD A,(HL) ; WE GOT A TIMOUT. RECHECK TOGGLE BIT IN CASE WE DID COMPLETE + LD A,(HL) ; WE GOT A TIMOUT. RECHECK TOGGLE BIT IN CASE WE DID COMPLETE XOR (HL) ; THE OPERATION. DO TWO SUCCESSIVE READS. ARE THEY THE SAME? - BIT 6,A ; IF THEY ARE THEN OPERATION WAS COMPLETED + BIT 6,A ; IF THEY ARE THEN OPERATION WAS COMPLETED JR Z,MD_WT5 ; OTHERWISE ERASE OPERATION FAILED OR TIMED OUT. ; LD C,$F0 ; COMMON FAIL STATUS / PREPARE DEVICE RESET CODE @@ -799,7 +863,7 @@ MD_WT6: EX AF,AF' ; RETURN TO ORIGINAL BANK JP HBX_BNKSEL ; WHICH IS OUR RAM BIOS COPY ; ;====================================================================== -; FLASH READ SECTOR. +; FLASH READ SECTOR. ; ; SELECT THE APPROPRIATE BANK / ADDRESS ; READ SECTOR OF 4096 BYTES, BYTE AT A TIME @@ -810,7 +874,7 @@ MD_WT6: EX AF,AF' ; RETURN TO ORIGINAL BANK ; ON ENTRY BC CONTAINS BANK AND SECTOR DATA ; DE = 0000 BYTE COUNT ; IX POINTS TO DATA TO BE WRITTEN -; A CONTAINS CURRENT BANK +; A CONTAINS CURRENT BANK ; ON EXIT NO STATUS RETURNED ; AF' TRASHED ;====================================================================== @@ -823,10 +887,10 @@ MD_FREAD_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY EX AF,AF' ; PUT DESTINATION BANK IN AF' LD A,B ; PUT SOURCE BANK IN AF ; -MD_FRD1: +MD_FRD1: CALL HBX_BNKSEL ; READ ; SWITCH TO SOURCE BANK LD C,(HL) ; BYTE -; +; EX AF,AF' ; SELECT BANK ; SWITCH DESTINATION BANK CALL HBX_BNKSEL ; TO WRITE LD (IX+0),C ; WRITE BYTE @@ -839,10 +903,10 @@ MD_FRD1: BIT 4,D ; WE HAVE DONE ONE SECTOR JR Z,MD_FRD1 ; - RET + RET ; ;====================================================================== -; FLASH VERIFY SECTOR. +; FLASH VERIFY SECTOR. ; ; SELECT THE APPROPRIATE BANK / ADDRESS ; VERIFY SECTOR OF 4096 BYTES, BYTE AT A TIME @@ -853,7 +917,7 @@ MD_FRD1: ; ON ENTRY BC CONTAINS BANK AND SECTOR DATA ; DE = 0000 BYTE COUNT ; IX POINTS TO DATA TO BE VERIFIED -; A CONTAINS CURRENT BANK +; A CONTAINS CURRENT BANK ; ON EXIT C RETURNS STATUS 0=SUCCESS NZ=FAIL ;====================================================================== ; @@ -864,7 +928,7 @@ MD_FVERI_R: ; THIS CODE GETS RELOCATED TO HIGH MEMORY ; EX AF,AF' ; PUT SOURCE BANK IN AF' (RAM) ; -MD_FVE1: +MD_FVE1: LD A,B ; SELECT BANK CALL HBX_BNKSEL ; TO READ ; SWITCH TO FLASH BANK LD A,(HL) ; READ BYTE @@ -884,13 +948,13 @@ MD_FVE1: JR Z,MD_FVE1 ; MD_FVE2: - LD C,A ; SET STATUS + LD C,A ; SET STATUS EX AF,AF' ; - RET + RET ; ;====================================================================== -; FLASH WRITE SECTOR. +; FLASH WRITE SECTOR. ; ; SELECT THE APPROPRIATE BANK / ADDRESS ; WRITE 1 SECTOR OF 4096 BYTES, BYTE AT A TIME @@ -901,7 +965,7 @@ MD_FVE2: ; ON ENTRY BC CONTAINS BANK AND SECTOR DATA ; IX POINTS TO DATA TO BE WRITTEN ; DE = 0000 BYTE COUNT -; A CONTAINS CURRENT BANK +; A CONTAINS CURRENT BANK ; ON EXIT NO STATUS IS RETURNED ;====================================================================== ; @@ -929,12 +993,12 @@ MD_FWRI1: ; LD (HL),C ; WRITE OUT BYTE ; -; ; DO TWO SUCCESSIVE READS -MD_FW7: LD A,(HL) ; FROM THE SAME FLASH ADDRESS. - LD C,(HL) ; IF TOGGLE BIT (BIT 6) +; ; DO TWO SUCCESSIVE READS +MD_FW7: LD A,(HL) ; FROM THE SAME FLASH ADDRESS. + LD C,(HL) ; IF TOGGLE BIT (BIT 6) XOR C ; IS THE SAME ON BOTH READS BIT 6,A ; THEN WRITE IS COMPLETE SO EXIT. - JR NZ,MD_FW7 ; Z TRUE IF BIT 6=0 I.E. "NO TOGGLE" WAS DETECTED. + JR NZ,MD_FW7 ; Z TRUE IF BIT 6=0 I.E. "NO TOGGLE" WAS DETECTED. ; INC HL ; NEXT DESTINATION LOCATION INC IX ; NEXT SOURCE LOCATION @@ -961,25 +1025,33 @@ MD_FWRIT .EQU HBX_START-MD_CSIZ+MD_FWRIT_R-MD_FSTART ; CALL ADDRESS FOR WRITE F ; msgHeader: .DB CR,LF,CR,LF,"ROMWBW XMODEM FLASH UPDATER",CR,LF,0 msgInstr: .DB CR,LF,CR,LF,"START TRANSFER OF YOUR UPDATE IMAGE OR ROM",CR,LF,0 -msgAbort: .DB CR,LF,"UPDATER ABORTED BY USER",CR,LF,0 +msgUserEx: .DB CR,LF,"UPDATER EXITED BY USER",CR,LF,0 msgBank: .DB CR,LF,"BANK ",0 -msgBadChip: .DB CR,LF,"FLASH CHIP NOT SUPPORTED",CR,LF,0 +msgUnsupC: .DB CR,LF,"FLASH CHIP NOT SUPPORTED",CR,LF,0 msgReboot: .DB CR,LF,"REBOOTING ...",CR,LF,0 msgFailWrt: .DB CR,LF,"FLASH WRITE FAILED",CR,LF,0 msgFailure: .DB CR,LF,"TRANSMISSION FAILED",CR,LF,0 -msgCancel: .DB CR,LF,"TRANSMISSION CANCELLED",CR,LF,0 +msgCancel: .DB CR,LF,"TRANSMISSION FAILCN",CR,LF,0 msgConsole: .DB CR,LF,"(C) Set Console Device : ",0 msgIODevice: .DB CR,LF,"(S) Set Serial Device : ",0 msgWriteV: .DB CR,LF,"(V) Toggle Write Verify : ",0 msgBegin: .DB CR,LF,"(R) Reboot" .DB CR,LF,"(U) Begin Update" .DB CR,LF,"(X) Exit to Rom Loader" +#IF (XFUDBG) + .DB CR,LF,"(H) Select half speed" + .DB CR,LF,"(T) Test 20s timeout" +#ENDIF .DB CR,LF,CR,LF,"Select : ",0 msgSucces1: .DB CR,LF,CR,LF,"UPDATE COMPLETED WITHOUT ERRORS ",CR,LF,0 msgEnterUnit: .DB CR,LF,"ENTER UNIT NUMBER : ",0 msgCRLF: .DB CR,LF,0 msgYES: .DB "YES",0 msgNO: .DB "NO",0 +msgPacErr: .DB CR,LF,"PACKET COUNT MISMATCH ERROR",CR,LF,0 +msgChkSum .DB CR,LF,"CHECKSUM ERROR",CR,LF,0 +msgRetry .DB CR,LF,"ERROR, RETRY COUNT EXCEED",CR,LF,0 +msgTimout .DB CR,LF,"ERROR, RECEIVE TIMEOUT",CR,LF,0 ; ; Variables ; @@ -993,7 +1065,7 @@ retrycnt: .DB 0 ; Counter for retries before giving up chksum: .DB 0 ; For calculating the checksum of the packet pktNo: .DB 0 ; Current packet Number pktNo1c: .DB 0 ; Current packet Number 1-complemented -MD_FBAS .DW $FFFF ; CURRENT BANK AND SECTOR +MD_FBAS .DW $FFFF ; CURRENT BANK AND SECTOR MD_SECT .EQU MD_FBAS ; BANK BYTE MD_BANK .EQU MD_FBAS+1 ; SECTOR BYTE ; From 59de9a01a9ce78c3228be2039d627a6fd891e5a2 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sun, 3 Jan 2021 22:12:13 +0800 Subject: [PATCH 5/7] Update updater.asm Fixups and optimization --- Source/HBIOS/updater.asm | 77 ++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/Source/HBIOS/updater.asm b/Source/HBIOS/updater.asm index f3c70c18..6d19c394 100644 --- a/Source/HBIOS/updater.asm +++ b/Source/HBIOS/updater.asm @@ -120,10 +120,10 @@ BSPC: .EQU 'H'-40h ; ^H = Backspace ; ; Start of code ; - ld (oldSP),SP ; SETUP STACK BELOW HBIOS - ld SP,HBX_START-MD_CSIZ ; ALLOW FOR RELOCATABLE CODE AREA + LD (oldSP),SP ; SETUP STACK BELOW HBIOS + LD SP,HBX_START-MD_CSIZ ; ALLOW FOR RELOCATABLE CODE AREA - ld HL,msgHeader ; PRINT + LD HL,msgHeader ; PRINT CALL PRTSTR0 ; GREETING LD HL,MD_FSTART ; COPY FLASH @@ -185,10 +185,7 @@ CLRSER: CALL SERST ; EMPTY SERIAL BUFFER CALL SERIN JR CLRSER ; -SERCLR: XOR A ; CLEAR VERIFY - LD (VERRES),A ; FAILURE FLAG -; - LD HL,msgInstr ; PROVIDE +SERCLR: LD HL,msgInstr ; PROVIDE CALL PRTSTR0 ; INSTRUCTION ; LD A,(SERDEV) ; IF CONSOLE AND SERIAL @@ -204,14 +201,14 @@ SERCLR: XOR A ; CLEAR VERIFY LD DE,sector4k ; POINT TO START OF SECTOR TO WRITE ; GetNewPacket: - ld A,20 ; WE RETRY 20 TIMES BEFORE GIVING UP + LD A,20 ; WE RETRY 20 TIMES BEFORE GIVING UP LD (retrycnt),A ; NPloop: LD B,5 ; 5 SECONDS OF TIMEOUT BEFORE EACH NEW BLOCK CALL GetCharTmo jp NC,NotPacketTimeout ; - ld HL,retrycnt ; REACHED MAX NUMBER OF RETRIES? + LD HL,retrycnt ; REACHED MAX NUMBER OF RETRIES? dec (HL) jp Z,FAILRT ; YES, PRINT MESSAGE AND EXIT ; @@ -227,28 +224,23 @@ NotPacketTimeout: cp SOH ; DID WE GET A START-OF-NEW-PACKET? JR NZ,NPloop ; NO, GO BACK AND TRY AGAIN ; - ld HL,packet ; SAVE THE RECEIVED CHAR INTO THE... - ld (HL),A ; ...PACKET BUFFER AND... + LD HL,packet ; SAVE THE RECEIVED CHAR INTO THE... + LD (HL),A ; ...PACKET BUFFER AND... INC HL ; ...POINT TO THE NEXT LOCATION ; - LD B,1 ; GET CHARACTER - CALL GetCharTmo ; SHOULD BE PACKET NUMBER - ld (HL),A + CALL GetCharTmo1 ; GET CHARACTER + LD (HL),A ; SHOULD BE PACKET NUMBER INC HL JP C,FAILTO ; - LD B,1 ; GET CHARACTER - CALL GetCharTmo ; SHOULD BE PACKET NUMBER - ld (HL),A ; COMPLEMENT - INC HL + CALL GetCharTmo1 ; GET CHARACTER + LD (HL),A ; SHOULD BE PACKET NUMBER + INC HL ; COMPLEMENT JP C,FAILTO ; - LD B,128 ; GET 128 MORE CHARACTERS FOR A FULL PACKET + LD C,128 ; GET 128 MORE CHARACTERS FOR A FULL PACKET GetRestOfPacket: - push BC ; GET CHARACTER - LD B,1 - CALL GetCharTmo - pop BC + CALL GetCharTmo1 ; GET CHARACTER JP C,FAILTO ; LD (HL),A @@ -256,15 +248,15 @@ GetRestOfPacket: LD (DE),A ; ...PACKET BUFFER AND... INC DE ; ...POINT TO THE NEXT LOCATION ; - DJNZ GetRestOfPacket + DEC C + JR NZ,GetRestOfPacket ; - LD B,1 ; GET CHARACTER - CALL GetCharTmo ; SHOULD BE CHECKSUM - LD (HL),A + CALL GetCharTmo1 ; GET CHARACTER + LD (HL),A ; SHOULD BE CHECKSUM JP C,FAILTO ; - ld HL,packet+3 ; CALCULATE CHECKSUM FROM 128 BYTES OF DATA - ld B,128 + LD HL,packet+3 ; CALCULATE CHECKSUM FROM 128 BYTES OF DATA + LD B,128 XOR A csloop: add A,(HL) ; JUST ADD UP THE BYTES inc HL @@ -290,7 +282,7 @@ csloop: add A,(HL) ; JUST ADD UP THE BYTES OR A ; EXIT IF WE GOT A JP NZ,FAILWF ; WRITE VERIFICATION ERROR - ld HL,pktNo ; UPDATE THE PACKET COUNTERS + LD HL,pktNo ; UPDATE THE PACKET COUNTERS INC (HL) INC HL dec (HL) @@ -351,7 +343,7 @@ Die: LD A,$FF CALL PRTSTR0 ; Prints message and exits from program LD C,BF_SYSRES_WARM ; WARM START Die1: LD B,BF_SYSRESET ; SYSTEM RESTART - ld SP,(oldSP) + LD SP,(oldSP) CALL $FFF0 ; CALL HBIOS RET @@ -398,7 +390,6 @@ WSEC1: LD HL,MD_FERAS ; ERASE LD HL,MD_FVERI ; WRITE CALL MD_FNCALL LD (VERRES),A ; SAVE STATUS - CALL PRTHEXB ; NOVER: POP DE ; POINT BACK TO LD DE,sector4k ; START OF 4K BUFFER @@ -431,25 +422,27 @@ NXTS3: LD A,(VERRES) ; EXIT WITH STATUS ; 4MHZ 20 SECONDS B=16 ; 10MHZ 20 SECONDS B=39 ; +GetCharTmo1: + LD B,1 GetCharTmo: - CALL SERST ; IF THER IS A + CALL SERST ; IF THERE IS A OR A ; CHARACTER AVAILABLE - JR NZ,GotChrX ; EXIT NO OTHERWISE POLL + JR NZ,GotChrX ; EXIT NOW OTHERWISE POLL PUSH BC - ld BC,255 ; C=CONSTANT (255) FOR INNER TIMING LOOP + LD BC,255 ; C=CONSTANT (255) FOR INNER TIMING LOOP TmoFct: .EQU $-1 ; B=SPEED FACTOR WHICH GETS UPDATED AT START GCtmob: PUSH BC - ld B,C + LD B,C GCtmoc: PUSH BC CALL SERST OR A ; A CHAR AVAILABLE? JR NZ,GotChar ; YES, GET OUT OF LOOP POP BC - djnz GCtmoc + DJNZ GCtmoc POP BC - djnz GCtmob + DJNZ GCtmob POP BC - djnz GetCharTmo + DJNZ GetCharTmo scf ; SET CARRY SIGNALS TIMEOUT RET ; @@ -457,7 +450,7 @@ GotChar:POP BC POP BC POP BC GotChrX:CALL SERIN - or A ; CLEAR CARRY SIGNALS SUCCESS + OR A ; CLEAR CARRY SIGNALS SUCCESS RET ; GETINP: CALL CONIN ; GET A CHARACTER @@ -483,7 +476,7 @@ GETINP2:CALL CONIN AND ~$20 ; CONVERT CHARACTER TO LOWER GETINP3:RET ; -PRTSTR0:ld A,(HL) ; PRINT MESSAGE POINTED TOP HL UNTIL 0 +PRTSTR0:LD A,(HL) ; PRINT MESSAGE POINTED TOP HL UNTIL 0 or A ; CHECK IF GOT ZERO? RET Z ; IF ZERO RETURN TO CALLER LD C,A @@ -1031,7 +1024,7 @@ msgUnsupC: .DB CR,LF,"FLASH CHIP NOT SUPPORTED",CR,LF,0 msgReboot: .DB CR,LF,"REBOOTING ...",CR,LF,0 msgFailWrt: .DB CR,LF,"FLASH WRITE FAILED",CR,LF,0 msgFailure: .DB CR,LF,"TRANSMISSION FAILED",CR,LF,0 -msgCancel: .DB CR,LF,"TRANSMISSION FAILCN",CR,LF,0 +msgCancel: .DB CR,LF,"TRANSMISSION CANCELLED",CR,LF,0 msgConsole: .DB CR,LF,"(C) Set Console Device : ",0 msgIODevice: .DB CR,LF,"(S) Set Serial Device : ",0 msgWriteV: .DB CR,LF,"(V) Toggle Write Verify : ",0 From fca73867fad4aa370049a6aee8a96df665cf018b Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Mon, 4 Jan 2021 21:09:47 +0800 Subject: [PATCH 6/7] ReadMe.md Getting \Started.md Revert change to ReadMe and add document change to GettingStarted. Hope this is right :) --- ReadMe.md | 30 +++--------------------------- Source/Doc/GettingStarted.md | 28 ++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index 64d961a1..2c727def 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -707,7 +707,7 @@ most stable and you are less likely to encounter problems. ### Notes - You can change media, but it must be done while at the OS command - prompt and you **must** warm start CP/M by pressing ctrl-c. This is + prompt and you **must** warm start CP/M by pressing ctrl-c. This is a CP/M 2.2 constraint and is well documented in the DRI manuals. - The original versions of DDT, DDTZ, and ZSID used the RST 38 vector @@ -1038,7 +1038,7 @@ system, you can use the FLASH application to update your ROM. The following is a typical example of transferring ROM image using XModem and flashing the chip in-situ. - E>xm r rom.rom + E>xm r rom.img XMODEM v12.5 - 07/13/86 RBC, 28-Aug-2019 [WBW], ASCI @@ -1050,7 +1050,7 @@ and flashing the chip in-situ. Thanks for the upload - E>flash write rom.rom + E>flash write rom.img FLASH4 by Will Sowerbutts version 1.2.3 Using RomWBW (v2.6+) bank switching. @@ -1179,30 +1179,6 @@ images. - FAT.COM - TUNE.COM -# System Update - -If the system running ROMWBW utilizes the SST39SF040 Flash chip then it is possible to do a System Update in place of -a System Upgrade in some cases. - -A System Update would involve only updating the BIOS, ROM applications and CP/M system. - -A System Update may be more favorable than a System Upgrade in cases such as: - - - Overwriting of the ROM drive is not desired. - - Space is unavailable to hold a full ROMWBW ROM. - - To mimimize time taken to transfer and flash a full ROM. - - Configuration changes are only minor and do not impact disk applications. - -The ROMWBW build process generates a system upgrade file along with the normal ROM image and can be identified by the -extension ".upd". It will be 128Kb in size. In comparison the normal ROM image will have the extension ".rom" and be -512Kb or 1024Kb in size. - -Transferring and flashing the System Update is accomplished in the same manner as described above in *Upgrading* with -the required difference being that the flash application needs to be directed to complete a partial flash using the -/p command line switch. - -`E>flash write rom.upd /p` - # RomWBW Distribution All source code and distributions are maintained on GitHub. Code diff --git a/Source/Doc/GettingStarted.md b/Source/Doc/GettingStarted.md index 8a0b41f1..5d96b795 100644 --- a/Source/Doc/GettingStarted.md +++ b/Source/Doc/GettingStarted.md @@ -1090,7 +1090,7 @@ update your ROM. The following is a typical example of transferring ROM image using XModem and flashing the chip in-situ. ``` -E>xm r rom.img +E>xm r rom.rom XMODEM v12.5 - 07/13/86 RBC, 28-Aug-2019 [WBW], ASCI @@ -1102,7 +1102,7 @@ To cancel: Ctrl-X, pause, Ctrl-X Thanks for the upload -E>flash write rom.img +E>flash write rom.rom FLASH4 by Will Sowerbutts version 1.2.3 Using RomWBW (v2.6+) bank switching. @@ -1238,6 +1238,30 @@ images. * FAT.COM * TUNE.COM +# System Update + +If the system running ROMWBW utilizes the SST39SF040 Flash chip then it is possible to do a System Update in place of +a System Upgrade in some cases. + +A System Update would involve only updating the BIOS, ROM applications and CP/M system. + +A System Update may be more favorable than a System Upgrade in cases such as: + + - Overwriting of the ROM drive is not desired. + - Space is unavailable to hold a full ROMWBW ROM. + - To mimimize time taken to transfer and flash a full ROM. + - Configuration changes are only minor and do not impact disk applications. + +The ROMWBW build process generates a system upgrade file along with the normal ROM image and can be identified by the +extension ".upd". It will be 128Kb in size. In comparison the normal ROM image will have the extension ".rom" and be +512Kb or 1024Kb in size. + +Transferring and flashing the System Update is accomplished in the same manner as described above in *Upgrading* with +the required difference being that the flash application needs to be directed to complete a partial flash using the +/p command line switch. + +`E>flash write rom.upd /p` + # RomWBW Distribution All source code and distributions are maintained on GitHub. Code From 50d449e0e3791fdbb2c178ffe3b8d4ced861ce58 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Mon, 4 Jan 2021 21:14:21 +0800 Subject: [PATCH 7/7] Update Build.ps1 Remove compressed update image option. Project for another time maybe. --- Source/HBIOS/Build.ps1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Source/HBIOS/Build.ps1 b/Source/HBIOS/Build.ps1 index 764efbe1..2610b25e 100644 --- a/Source/HBIOS/Build.ps1 +++ b/Source/HBIOS/Build.ps1 @@ -92,11 +92,10 @@ $ErrorAction = 'Stop' # Directories of required build tools (TASM & cpmtools) $TasmPath = '..\..\tools\tasm32' $CpmToolsPath = '..\..\tools\cpmtools' -$LzaToolsPath = '..\..\tools\lzsa' # Add tool directories to PATH and setup TASM's TABS directory path $env:TASMTABS = $TasmPath -$env:PATH = $TasmPath + ';' + $CpmToolsPath + ';' + $LzaToolsPath + ';' + $env:PATH +$env:PATH = $TasmPath + ';' + $CpmToolsPath + ';' + $env:PATH # Initialize working variables $OutDir = "../../Binary" # Output directory for final image file @@ -254,7 +253,6 @@ else foreach ($InputFile in $SystemFileList) { Copy-Item $InputFile $RomDiskFile -# lzsa -f2 -r $InputFile $RomDiskFile Add-Content $UpdFile -Value ([System.IO.File]::ReadAllBytes($RomDiskFile)) -Encoding byte Remove-Item $RomDiskFile }