;**************************************************************************** ;** ** ;** SmartFiler version 27D -- BOOT block ** ;** ** ;**************************************************************************** ;disassembly and comments (c) 2000 by Richard F. Drushel 5 August 2000 ;**************************************************************************** ; ; SmartFiler 27D boot block ; SFBOOT -> Source re-created by Z80DIS 2.2 ; Z80DIS was written by Kenneth Gielow ; Palo Alto, CA ; ;**************************************************************************** .Z80 ;**************************************************************************** ;VRAM immediates I.0000 EQU 0000H ; ----I I$017F EQU 017FH ; ----I I$0204 EQU 0204H ; ----I I$037F EQU 037FH ; ----I I$0400 EQU 0400H ; ----I I$3FFF EQU 3FFFH ; ----I ;other miscellany BLOCK_1_ADDR EQU 0000H BLOCK_2_ADDR EQU 8400H PROG_START EQU 0100H ZERO EQU 0000H TRADET$ EQU 5CH ;trademark symbol T TRADEM$ EQU 5DH ;trademark symbol M COPY$ EQU 5EH ;copyright symbol (C) REG$ EQU 5FH ;registered symbol (R) ;blocks to read BLOCK_1 EQU 0001H ;directory BLOCK_2 EQU 0002H ;file1 BLOCK_5 EQU 0005H ;file2 ;OS-7 equates PUTFRAME EQU 080BH ;internal OS-7 entry point, not jump table!!! LOAD_ASCII EQU 1F7FH FILL_VRAM EQU 1F82H MODE_1 EQU 1F85H WRITE_REGISTER EQU 1FD9H WRITE_VRAM EQU 1FDFH VDP_MODE_WORD EQU 73C3H ;EOS equates _RD_1_BLOCK EQU 0FC69H _START_RD_1_BLOCK EQU 0FCA2H ;**************************************************************************** ;** ** ;** code begins here ** ;** ** ;**************************************************************************** COLD_BOOT_ADDR EQU 0C800H ORG COLD_BOOT_ADDR COLD_BOOT: LD A,B ;get boot device number LD (BOOT_DEVICE),A ;save it LD SP,COLD_BOOT ;set up stack CALL C$C85C ;draw initial boot screen ; ;Load boot graphics code and data (LOGOS) ;This is *evil* because it doesn't use the directory! It assumes that ;the file occupies certain blocks. LD HL,BLOCK_2_ADDR ;load address for LOGOS LD DE,BLOCK_2 ;start block of LOGOS LD B,03H ;length of LOGOS CALL LOAD_BLOCKS ;load LOGOS ; ;Start to read first block of SmartFiler (SMART_FILER) ;This is so that the tape can be spinning while the graphics are being ;displayed. ;Again, it bypasses the directory and assumes that it starts at a certain ;block and has a certain length. LD A,(BOOT_DEVICE) ;drive to read LD HL,PROG_START ;load address for SMART_FILER LD DE,BLOCK_5 ;block loword LD BC,ZERO ;block hiword CALL _START_RD_1_BLOCK ;read it ; ;Show the boot graphics screen. CALL BLOCK_2_ADDR ;run LOGOS to load SmartFiler graphic ; ;Load the rest of SmartFiler, assuming a certain start block and length. LD HL,PROG_START ;load address for SMART_FILER LD DE,BLOCK_5 ;start block of SMART_FILER LD B,1EH ;length of SMART_FILER CALL LOAD_BLOCKS ;load SMART_FILER ; ;This reads the directory block. ;How nice that it assumes it is only one block long... ;Why does it do this? It will overwrite the first block of SMART_FILER! ;The answer is evil: a quirk of ADAMnet is that it takes *2* reads of ;a block device to actually cause the data to be transferred into Z80 RAM. ;The first call makes the device read the data, but it doesn't get into ;Z80 RAM until the second consecutive call. So, the *effect* of a single ;call to _START_READ_1_BLOCK for block 1 is to just rewind the tape (if ;you're booting from data pack)--a major time savings for later. The trap ;for emulators is that, if they don't correctly emulate the read-twice ;behavior, they will cause the program to crash. LD A,(BOOT_DEVICE) ;drive to read LD HL,BLOCK_1_ADDR ;load address LD DE,BLOCK_1 ;block loword LD BC,ZERO ;block hiword CALL _START_RD_1_BLOCK ;read it ;Clumsy write to VDP register 1. LD HL,(VDP_MODE_WORD) ;get current value PUSH HL ;save it; why? ;When we (below) call WRITE_REGISTER, ;VDP_MODE_WORD will get changed. But now ;we have a program sitting at the site of ;OS-7's VDP_MODE_WORD (73C3H), and this ;will scramble program code. So, save the ;RAM contents, call WRITE_REGISTER, then ;restore them. ;Note: the smarter thing to do might have ;been to call the EOS version of ;WRITE_REGISTER at 0FD1DH *after* ;restoring the 32K RAM/32K RAM memory ;map; the location the of EOS's ;VDP_MODE_WORD is at 0FD61H, which is in ;EOS global RAM and not a threat to user ;program RAM. LD C,00H LD B,01H ; 1 CALL WRITE_REGISTER ;write C to VDP register B (OS-7 version) ; POP HL LD (VDP_MODE_WORD),HL ;restore program RAM contents. ;Restore standard memory configuration. LD BC,I$017F OUT (C),B ;bank switch to 32K RAM/32K RAM ;Run SMART_FILER. LD A,(BOOT_DEVICE) ;get drive LD B,A ;into B JP PROG_START ;and begin SmartFiler ; ; ----------------- ; ; Subroutine __________________________ ; Inputs ________________________ ; Outputs ________________________ ; C$C85C: LD BC,I$037F OUT (C),B CALL C$C8ED ;bank switch to OS7-24 K RAM/32K RAM ; LD HL,I.0000 LD DE,I$3FFF XOR A CALL FILL_VRAM ;wipe VRAM ; CALL MODE_1 ; CALL LOAD_ASCII ; LD IX,I$C9F4 CALL C.C8B3 ; LD IX,I$C9DA CALL C.C8B3 ; LD HL,I$C900 LD DE,I$0204 CALL C$C8AB ; LD HL,BOOT_TEXT CALL C.C895 ; CALL C$C8F9 ; RET ; ; ----------------- ; ; Subroutine __________________________ ; Inputs ________________________ ; Outputs ________________________ ; C.C895: LD A,(HL) INC A RET Z ; LD D,(HL) INC HL LD E,(HL) INC HL LD C,(HL) INC HL PUSH HL LD B,00H ADD HL,BC EX (SP),HL LD B,01H ; 1 CALL PUTFRAME ;internal OS-7 ref!!! ; POP HL JR C.C895 ; ; ----------------- ; ; Subroutine __________________________ ; Inputs ________________________ ; Outputs ________________________ ; C$C8AB: LD B,(HL) INC HL LD C,(HL) INC HL CALL PUTFRAME ;internal OS-7 ref!!! ; RET ; ; ----------------- ; ; Subroutine __________________________ ; Inputs ________________________ ; Outputs ________________________ ; C.C8B3: LD H,(IX+1) LD L,(IX) LD D,(IX+3) LD E,(IX+2) LD B,(IX+5) LD C,(IX+4) PUSH BC PUSH HL PUSH DE INC C DEC C JR Z,J$C8D1 ; LD B,00H CALL WRITE_VRAM ; J$C8D1: POP DE POP HL POP BC INC B DEC B RET Z ; PUSH BC LD B,00H ADD HL,BC EX DE,HL ADD HL,BC EX DE,HL POP BC LD C,00H CALL WRITE_VRAM ; RET ; ; ----------------- ;Orphaned code? ?.C8E5: LD C,01H ; 1 LD B,07H ; 7 CALL WRITE_REGISTER ;write 01H to VDP register 7 ; RET ; ; ----------------- ; ; Subroutine __________________________ ; Inputs ________________________ ; Outputs ________________________ ; C$C8ED: LD A,(VDP_MODE_WORD+1) ;saved VDP register 1 value RES 5,A ;clear bit 5 J$C8F2: LD C,A ;into C so we can write it LD B,01H ; 1 CALL WRITE_REGISTER ;update VDP register 1 ; RET ; ; ----------------- ; ; Subroutine __________________________ ; Inputs ________________________ ; Outputs ________________________ ; C$C8F9: LD A,(VDP_MODE_WORD+1) ;saved VDP register 1 value SET 6,A ;set bit 6 JR J$C8F2 ;write it back ; ; ----------------- I$C900: DEFB 5,25 ;number of data units, length of each data unit ; DEFB 00H,61H,63H,63H,64H DEFB 00H,61H,63H,63H,63H DEFB 6EH,00H,61H,63H,63H DEFB 64H,00H,61H,63H,64H DEFB 00H,7AH,63H,7EH,7FH ; DEFB 00H,62H,60H,66H,65H DEFB 00H,62H,60H,6FH,70H DEFB 60H,00H,62H,60H,66H DEFB 65H,00H,62H,60H,65H DEFB 00H,6AH,60H,00H,00H ; DEFB 00H,69H,67H,68H,60H DEFB 7CH,00H,60H,71H,72H DEFB 60H,00H,69H,67H,68H DEFB 60H,7CH,00H,60H,60H DEFB 79H,60H,60H,00H,00H ; DEFB 00H,6AH,60H,60H,60H DEFB 65H,00H,60H,73H,74H DEFB 60H,00H,6AH,60H,60H DEFB 60H,65H,00H,60H,75H DEFB 60H,77H,60H,00H,00H ; DEFB 69H,60H,6BH,6CH,6DH DEFB 60H,7CH,60H,60H,60H DEFB 7DH,69H,60H,6BH,6CH DEFB 6DH,60H,7CH,60H,76H DEFB 60H,78H,60H,00H,00H BOOT_TEXT: ;row, column, length of string, string data DEFB 9,14,3,"THE" DEFB 10,10,13,"COLECOVISION",REG$ DEFB 11,5,22,"FAMILY COMPUTER SYSTEM" DEFB 13,12,8,"PRESENTS" DEFB 15,10,13,"SMART FILER",TRADET$,TRADEM$ DEFB 17,10,13,COPY$," 1984 COLECO" DEFB 0FFH ;end of data I$C9DA: DEFW I$C9E0 ;RAM source address DEFW 2000H ;VRAM destination address DEFW 20 ;count I$C9E0: DEFB 50H,50H,50H,50H DEFB 0F0H,0F0H,0F0H,0F0H DEFB 0F0H,0F0H,0F0H,0F0H DEFB 50H,50H,50H,50H DEFB 50H,50H,50H,50H I$C9F4: DEFW I$C9FA ;RAM source address DEFW 02E0H ;VRAM destination address DEFW 288 ;count I$C9FA: DEFB 0FAH,23H,22H,22H,00H,00H,00H,00H DEFB 20H,60H,0A0H,20H,00H,00H,00H,00H DEFB 7CH,82H,0BAH,0A2H,0BAH,82H,7CH,00H DEFB 3CH,42H,0B9H,0A5H,0B9H,0ADH,42H,3CH DEFB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH DEFB 00H,00H,00H,00H,0FH,0FH,1FH,1FH DEFB 3FH,3FH,7FH,7FH,01H,00H,00H,00H DEFB 00H,00H,00H,00H,0FFH,0FFH,0FFH,0FFH DEFB 00H,00H,00H,00H,0C0H,0C0H,0E0H,0E0H DEFB 0F0H,0F0H,0F8H,0F8H,0FCH,0FCH,0FEH,0FEH DEFB 0FFH,0FFH,0FFH,0FFH,0CFH,0CFH,87H,87H DEFB 0FFH,0FFH,0FFH,0FFH,0FEH,0FEH,0FCH,0FCH DEFB 87H,03H,03H,03H,01H,01H,00H,00H DEFB 00H,00H,01H,01H,03H,03H,07H,07H DEFB 0FH,0FH,1FH,1FH,3FH,3FH,7FH,7FH DEFB 0FFH,0FFH,0C0H,0C0H,80H,80H,00H,00H DEFB 0FFH,0FFH,00H,00H,00H,00H,00H,00H DEFB 0FFH,0FFH,03H,03H,01H,01H,00H,00H DEFB 00H,00H,00H,00H,0F0H,0FCH,0FEH,0FEH DEFB 0FFH,0FFH,0FFH,0FFH,0FFH,80H,80H,80H DEFB 0FFH,0FFH,0FFH,0FFH,0FFH,03H,01H,01H DEFB 80H,80H,80H,80H,80H,80H,80H,80H DEFB 01H,01H,01H,01H,01H,01H,01H,01H DEFB 80H,80H,80H,80H,80H,80H,80H,0FFH DEFB 01H,01H,01H,01H,01H,01H,03H,0FFH DEFB 7FH,7FH,3FH,3FH,1FH,1FH,0FH,0FH DEFB 07H,07H,03H,03H,01H,01H,00H,00H DEFB 0FEH,0FEH,0FCH,0FCH,0F8H,0F8H,0F0H,0F0H DEFB 0E0H,0E0H,0C0H,0C0H,80H,80H,00H,00H DEFB 00H,00H,81H,81H,0C3H,0C3H,0E7H,0E7H DEFB 00H,00H,00H,00H,03H,03H,07H,07H DEFB 0F3H,55H,51H,51H,00H,00H,00H,00H DEFB 00H,00H,80H,80H,0C0H,0C0H,0E0H,0E0H DEFB 0FFH,0FFH,0FFH,0FFH,0FEH,0FEH,0FCH,0F0H DEFB 0FAH,23H,22H,22H,00H,00H,00H,00H DEFB 20H,60H,0A0H,20H,00H,00H,00H,00H ; ----------------- ;Load a contiguous series of blocks. On entry, B=number of blocks, ;HL=load address, DE=loword of start block (hiword is forced to 0) and ;(BOOT_DEVICE)=device to load from. On exit, the blocks are loaded. ;Note 1: if there is an error, the routine hangs forever! There is ;no bailout to SmartWriter! ;Note 2: this code is short-sighted because it assumes that the hiword ;of the block is zero. This is bad for large hard drives. LOAD_BLOCKS: PUSH BC ;save block counter (in B) J.CB1B: LD A,(BOOT_DEVICE) ;get drive LD BC,ZERO ;force hiword of block to zero PUSH DE PUSH HL CALL _RD_1_BLOCK ;read it ; POP HL POP DE JR NC,J.CB1B ;not ready, retry ; CP 80H ;done, but was there an error? JR NZ,J.CB1B ;yes, so retry ; LD BC,I$0400 ;length of one block ADD HL,BC ;offset to next address INC DE ;point to next block POP BC ;restore block counter (in B) DJNZ LOAD_BLOCKS ;keep going until no more blocks ; RET ; ; ----------------- BOOT_DEVICE: DEFB 20H ;where we save our boot device # ; ----------------- ;seems to be unused DEFB " " DEFB "BY SIERRA ON-LINE " DEFB 3EH,41H,5DH,55H,59H,55H,41H,3EH DEFB "@ PROGRAMMED BY DON MCGLAUFLIN@@" DEFB "@ ",1DH,"1984 SIERRA ON-LINE, INC.@" DEFB "@ PLEASE WAIT WHILE LOADING GAME@@" DEFB 00H,0FFH,0FFH,0FFH,00H,00H,00H,00H DEFB 0FFH,0FFH,0FFH,0FFH,00H,00H,00H,00H DEFB 0FFH,0FFH,0FFH,0FFH,00H,00H,00H,00H DEFB 0FFH,0FFH,0FFH,0FFH,00H,00H,00H,00H DEFB 0FFH,0FFH,0FFH,0FFH,00H,00H,00H,00H ; ----------------- END