IMD 1.17: 10/06/2011 9:13:31 48k cp/m ver 2.2 cbios rev e.31 #931 movcpm; abcd: dj2d/b @e000 dj2d/b as console, blank list ssdd  1><<2O!|2.}2"DM =*1!"DMͶ>OچO!"Æ ¹*1 !"DMͶ>O چ O!"Æ ¹*1!"DMͶ>OچO!"Æ ¹*1!"DMͶ>OچO!"Æ ¹*1 ͨ!w# ‘!"ͨ!"DM>O ڨ O!"è *1ͨ!w# ‘!"ͨ!"DM>OڨO!"è *$1!w# x>2F1-y2dc' O2d-c- f*3áÒE8×vðû*Ò:L!3w# CC*#~!wwwww>>26҃>2͝q>>26ͭ"’y/2/¡:/͡:G:O:/W:W:W:*DM>>y2! ! 7>`i"'2222!> }7ɯ7y?2yM?22ͭy2:>x V2H*>k~#~#~# ~#!|õ>kw#w#w# w#¢!!͇_:=2:=N>7::<'!:##wy2!}A:l>xWH:2$z7' !>2w,U!͇lJA:O! :G>x2> !" GÊy2!+| 0!N#^q#{~6#6B:w#w ~2#~> -22:O:/:O:=/wOj*+|c~ :w>7*))!w~҂~~z‡^#V:w6r{7~µ~ʺ~¿y/G!^#~##~w~22:2:!\X COPYRIGHT (C) 1979, DIGITAL RESEARCH _͌> ͒> Ò> Ò͘~#͌ì _2<ý2˽ýýý߽ý !Ķ2:2a{_:ķʖ:ķ>Ľ˽ʖ:=2–!B!6#5ڽʖ:Ľ!ͬ¾ʧݾÂݾ )!F#xʺ~0wëw!" !~6ͽ:ý(!#͘*~ ""͌#>?͌͘ݾ =_.:;<> Oo$>!Y2*O"ʉ@G:ʐ:wÖx2p0ʹ#*©6?ëw˜0ï#6 ¹.0#*ٿ6?ۿwȿ0߿#6 #6" #~?  xDIR ERA TYPESAVEREN USER"!yO#< Ty#O 321y_͸2y2ͽ:1͘оA͌>>͌9ؾо2^ :ķ¥.!_~#fow]­Îå!v"!çREAD ERRORçNO FILE^:ķ ! ~ 3#0 Wx x G ~ # 3x~#B!Y~ɯ2:ķ=!ľý:ķ=!ľ:ý^T!~  6?#ˆ:`O> K{͘оA͒>:͒͢>:͒͢xK > K > ͒x  ͢¾ØÆ^ BRͧ9!5‚#~Y‚#"T<ÆALL (Y/N)?^ Tнʧ͘!6!~ڇ ¯w4!Y~ʆ͌¾†t=ʆf ^ T ¯2o&)|+!ؾڽ<ͧվÆNO SPACE^ :Ty!B*O=?_s#"^sG!~Yøpsp2mÆÆf ͧÆFILE EXISTS _: É: :ķʉ=2)ͽÉ T!@нk!ؾ}|q=qf^!~2>`~2į2\!!B!~> >#0~O#Cx2͘վ1)ͽÂf zͧÆBAD LOADCOMf^: !Ķ Â$$$ SUB"řťūű"C{2!"E9"1Aȯ22!ty)K!G_^#V*Cǐ~уEќѥѫ ,&-AGMSț!!ô!ô!Bdos Err On : $Bad Sector$Select$File R/O$:BA2!~6 O͐  :ȷE B 2>: ȷb# : ȷy! 4 5~yy5 6yҐ^H@Oy H H: –ͬ  #H: ! Ⱦ Hù H H $O͐: 2 *CN# x: 2 p&x~+é7Ư2 H! >w_: ! Ⱦ5ͤNkͱ¦ͱxʊ#Nx: ȷ! Ȗ2 ͤ! 5™#wO~x½p Hy<< ӷʑ :!qMD#2E>! ^#V w#P:BO|^#V#"##"##"##"!O*!O*|!6ʝ6>ӯ*w#w*w#w'û*ӷ! J*""!N#F*^#V*~#foyx*{_zW+*yx#*DM*s#r*s#ryOxG*0MD!!N:ҷ EG>O: \ɷSɀ*C :ҷqn& ^#V>O^"*}:*)=":O:ҡo"*C *C!ͮ~2~2ͦ:Ҧ2ͮ:ɯO:ҁw:w |g}o*ү#  ):BO!yoxg*:BO}!N#F "*#*s#r^ ~!J! J*:҅o$*C~i6iw**{#zr+s{ozg**͕** ʾ,w͜͸Ͳ!!N#F$**O!~#:AȾ#~$=2Ek͌::/GyO>2!q*C"͡ʔ*JҔ^:Oyʃ?|x | s̖-|N-# S:2E!~Яw>T D^6k-äPYy 5*{zBK5ڋ>*Cw~#+w#w+ɯ2E22i^ *C :ҷ~w~͔͔# #  w ~>2!E5T*C!"C"C!w# F! w͌xʯ2͢*C ~<wʃG:Ҡ!Ҧʎì 4~ʶ¬:<ʶ$ʶïZͻɯx>2>2ͻ:!ҾZί2:Eȷẅ́͊Ͳ>2>2T*CGͻ:ẅ́n>2;O ^DM;}H>"*C :ҷ:ddslO s#r:Eȷ͊:==»y==»*Ww#*"͸*:G#š"͸:!Ҿw4!iw:Z!E~=26ɯ2*C!!~~#~O~G#n,-.‹! w! yG!x͢.:E<ʄ! q!pQ:E<. ʄ$.:E<ʄi6}2ExN! ~态O>G~G!~G} *C!r#r#r ^ͥ_y#x#{s+p+q-*C ͥ!!q#p#w*:BOYG}*MD "ã:!BȾw!>2*C~=2u:B2~2wE:A*Cȶw>"!""ү2B!"!rQQQâ~?ͦ~?rQ*"CQ-Q͜QüQrQ$Q*):B"*)*)Q;*"E:;:A2AQÓQÜQ*C}/_|/*ҤW}_*"}o|g":ҷʑ*C6:ҷʑw:2E**E}DQ>2à@LaÁvlÐÒÅÊibÌ× 56K CP/M Vers. 2.2, Cbios rev 3.1 For Thinker Toys Disk Jockey 2D Controller @ 0E000H. ~#O Ó1!!6͓ӯ22!͊>22!"!"22:O!>2G7:ӧ:1>>22ʳӯ2O3-0>2?!"^>r><<V *^"^2?O!"^DMr> u*y2`i"y2A~ n& ~ʥ/oy2={$>22 =' !Z_A7*#~o&~9O s#rA ~2n~2!:o&))))y ~#fo+F{׸y2>2:O=ʃշz<2!ʟ#ʐ :=o&)))))))!>5֯5>2>=>2>!2" :O3:اO :O0O>7>!7!w#7!R!o!:_~#fo!R!:V!:r!:|!ÄlցFy:=2>222@!>=@@ >>2      %&'()*+, -. /0  12!"34#$!"#$1234%&'(5678 )*+,9:;<  -./0 12345678 !"#$%&'(9:;<=>?@)*+,-./0?4 < 3@+ t4  h@x1@;W@|, lVޡ @$A ABOOT& ASM ABOOT& ASM= ASM COM@BIOS ASM`BOOT ASMCBIOS& ASM !CBIOS& ASM"#$%&'()CBIOS& ASM*+,-./01CBIOS& ASM23456789CBIOS& ASM:;<=>?@ACBIOS& ASMBCDEFGHICBIOS& ASMJKLMNOPQCBIOS& ASMRSTUVWXYCBIOS& ASMZ[\]^_`aCBIOS& ASM bcdefghiCBIOS& ASM jklmnopqCBIOS& ASM rstuvwxyCBIOS& ASM z{|}~CBIOS& ASM CBIOS& ASMGCBIOS ASMEDDT COM&FORMT# PRNDEBLOCK ASMPDISKDEF LIB1DUMP ASM!DUMP COMED COM4FORMT# ASMPFORMT# COM INSTALL COM:FORMT# HEXack 0, sector 5 and * * continues through to track 1 sector 3. Only the first * * 3/4 K bytes of track 1, sector 3 is loaded since CP/M * * requires that the warm boot loader load up to the start * * of (but not past) the Cbios jump table. * * * * * * 8 inch floppy disk boot loader for the * * Morrow Designs Disk Jockey DMA (DJDMA) * * * * The loading is identical to that of of the DJ2DB except * * that the loader itself is loaded at 80h and the 'order' * * column does not apply. The DJDMA is capable of loading a * * complete track at a time and thus it merely zaps the * * tracks in all at once. * * * * * * 5 1/4 inch floppy disk boot loader for the * * Morrow Designs Disk Jockey DMA (DJDMA) * * * * The cold boot loader (track 0, sector 0) is loaded into * * RAM at 80h. This loader will start loading from track 0, * * sector 1 and stops at track 1, sector 9. The load * * sequence is as follows: * * INSTALL DOC LOAD COMFORMT# PRNMAKEPRL COMMAC COM\MAKEPRL COM?MAKEPRL DOCMBASIC COMMBASIC COM>MOVCPM COMjNOTESHD DOCyPIP COM:PRL DOC REGEN ASM|REGEN COMSTAT COM)SUBMIT COM SYSGEN COM XSUB COM SYS COMjSYSGEN COM XSUB COMBOOT PRN%BOOT HEX***************************************************************** * * * Morrow Designs CP/M vers 2.2 Cold Boot Loader. * * Cbios revision E.2, 3/4/82. * * * * The following routines will boot CP/M from the * * Disk Jockey 2D Rev. B 8 inch disk controller (DJ2D/B), * * Disk Jockey DMA 8 + 5 1/4 inch controller (DJDMA), * * Hard Disk Controller revision 3 (HDC3), * * or the Hard Disk DMA (HDDMA) disk controllers. * * * * Provisions have been made for a Micronix boot loader. * * This loader always gets loaded to 0100h. * * * * 8 inch floppy disk boot loader for the * * Morrow Designs Disk Jockey 2D/B (DJ2DB) * * * * The 'order' column is the interleave sequence used by the * * loader during the load. * * * * track sector sysgen load order Name * * * * 0 1 900 ff00 0 Boot loader * * 0 2 980 Unused * * 0 3 a00 * * 0 4 a80 * * 0 5 b00 9100 1 CCP * * 0 6 b80 9180 12 *  * * track sector sysgen load order Name * * 0 0 900 80 0 Cold boot * * 0 1 b00 9500 1 CCP * * 0 2 d00 9700 2 * * 0 3 f00 9900 3 * * 0 4 1100 9b00 4 * * 0 5 1300 9d00 5 BDOS * * 0 6 1500 9f00 6 * * 0 7 1700 a100 7 * * 0 8 1900 a300 8 * * 0 9 1b00 a500 9 * * * * 1 0 1d00 a700 10 * * 1 1 1f00 a900 11 * * 1 2 2100 ab00 12 CBIOS * * 1 3 2300 ad00 13 * * 1 4 2500 af00 14 * * 1 5 2700 b100 15 * * 1 6 2900 b300 16 * * 1 7 2b00 b500 17 * * 1 8 2d00 b700 18 * * 1 9 2f00 b900 19 * * * * The warm boot starts from track 0 sector 1 and continues * * through to track 1 sector 1. * * * * * * Shugart SA4000 disk interface boot loader for the * * Morrow Designs Hard Disk Controller rev. 3 (HDC3) * * * * The cold boot loader (track 0, sector 1) is loaded into * * RAM in the very last part of the Cbios. This area is * * used for uninitialized tables and thus is a safe place *  * 0 7 c00 9200 2 * * 0 8 c80 9280 13 * * 0 9 d00 9300 3 * * 0 10 d80 9380 14 * * 0 11 e00 9400 4 * * 0 12 e80 9480 15 * * 0 13 f00 9500 5 * * 0 14 f80 9580 16 * * 0 15 1000 9600 6 * * 0 16 1080 9680 17 * * 0 17 1100 9700 7 * * 0 18 1180 9780 18 * * 0 19 1200 9800 8 * * 0 20 1280 9880 19 * * 0 21 1300 9900 9 BDOS * * 0 22 1380 9980 20 * * 0 23 1400 9a00 10 * * 0 24 1480 9a80 21 * * 0 25 1500 9b00 11 * * 0 26 1580 9b80 22 * * * * Track 1 is recorded in double density format. There are * * 1024 bytes per sector. * * * * 1 1 1600 9c00 4 * * 1 2 1a00 a000 1 * * 1 3 1e00 a400 5 CBIOS (@ a700h) * * 1 4 2200 a800 2 * * 1 5 2600 ac00 6 * * 1 6 2a00 b000 3 * * 1 7 2e00 b400 7 * * 1 8 3200 b800 Unused * * * * Three spare sectors (track 0, sectors 2 to 4) have been * * provided for a more advanced boot loader at a later date. * * * * The warm boot loader starts on tr* for the loader. This cold boot loader will start loading * * the CCP from track 0, sector 2 and will finish up with * * the last part of the Cbios on track 0, sector 20. * * * * track sector sysgen load order Name * * 0 1 900 fc00 1 Cold boot * * 0 2 b00 9500 2 CCP * * 0 3 d00 9700 3 * * 0 4 f00 9900 4 * * 0 5 1100 9b00 5 * * 0 6 1300 9d00 6 BDOS * * 0 7 1500 9f00 7 * * 0 8 1700 a100 8 * * 0 9 1900 a300 9 * * 0 10 1b00 a500 10 * * 0 11 1d00 a700 11 * * 0 12 1f00 a900 12 * * 0 13 2100 ab00 13 CBIOS * * 0 14 2300 ad00 14 * * 0 15 2500 af00 15 * * 0 16 2700 b100 16 * * 0 17 2900 b300 17 * * 0 18 2b00 b500 18 * * 0 19 2d00 b700 19 * * 0 20 2f00 b900 20 * * 0 21 3100 Unused * * * * The warm boot load sequence starts at track 0, sector 2 * * and goes straight through to sector 12. There is still * * plenty of room left in this loader for more advanced * * things like sector interleaving although thie * * (lot?) of code shuffeling or in the creation of a Cbios * * that simply will not fit on a small disk drive. * * * * sysgen 48k 56k 60k 62k 64k * * image CP/M CP/M CP/M CP/M CP/M * * * * 900 ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ Loader * * b00 9500 b500 c500 cd00 d500 CCP * * 1300 9d00 bd00 cd00 d500 dd00 BDOS * * 2100 ab00 cb00 db00 e300 ed00 Cbios * * 3100 bb00 db00 eb00 f300 fb00 Tables * * 35ff bfff dfff efff f7ff ffff The End * * * * ~~~~ 8d00 ad00 bd00 c500 cd00 DDT * * * ***************************************************************** micron equ 0 ;Set to 1 for Micronix boot loader if micron eq 0 msize equ 48 ;Memory size of target CP/M biosln equ 10h ;BIOS length codlen equ 11h ;Code length ccpln equ 800h bdosln equ 0e00h size equ (msize*1024) ccp equ size-(biosln*100h+ccpln+bdosln) bdos equ ccp+ccpln bios equ ccp+ccpln+bdosln cboot equ bios ;Cold boot address for CP/M loaddr equ ccp ;Load address for floppy else n null equ 0fch ;Null command idbuff equ 0 ;Initialize data command isbuff equ 8 ;Initialize header command rsect equ 1 ;Read sector command wsect equ 5 ;Write sector command endif ***************************************************************** * * * The following equates are for the Hard Disk DMA. * * * ***************************************************************** if maxmw ne 0 cyl equ 153 ;Specifications for a Seagate Technology 506 heads equ 4 ;Number of heads per cylinder spt equ 9 ;Sectors per track precomp equ 64 ;Cylinder to start write precomensation lowcurr equ 128 ;Cylinder to start low current stepdly equ 30 ;Step delay (0-12.7 milliseconds) headdly equ 20 ;Settle delay (0-255 milliseconds) sectsiz equ 7 ;Sector size code (must be 3 for this Cbios) ; 0 = 128 byte sectors ; 1 = 256 byte sectors ; 3 = 512 byte sectors ; 7 = 1024 byte sectors (default for CP/M) ; f = 2048 byte sectors ;Define controller coms is hardly * * necessary on a hard disk. * * * * * * Shugart SA1000 disk interface boot loader for the * * Morrow Designs Hard Disk DMA controller (HDDMA) * * * * track sector sysgen load order Name * * 0 1 900 100 0 Cold boot + CCP * * 0 2 d00 9300 1 * * 0 3 1100 9700 2 * * 0 4 1500 9b00 3 Bdos (@ 9d00) * * 0 5 1900 9f00 4 * * 0 6 1d00 a300 5 * * 0 7 2100 a700 6 Cbios * * 0 8 2500 ab00 7 * * 0 9 2900 af00 8 * * * * 1 10 2d00 b300 9 * * * * Since 1k byte sectors were implemented on this disk; * * track 0, sector 1 contains both the cold boot loader and * * part of the CCP. The cold boot loader relocates this * * peice of the CCP to it proper resting place as part of * * the boot process. * * * ***************************************************************** ***************************************************************** * * * The following table gives a general idea as;Micronix boot loader cboot equ 0100h ;Cold boot address for the loader loaddr equ 0100h ;If the load address is moved forward from ;0100 then the starting extended address for ;the djdma boot loader should be adjusted. endif retries equ 10 ;Maximum # of disk retries ***************************************************************** * * * Only one of the following equates should be set. The * * others sould be 0. These equates define the boot loader * * that is to be used. * * * ****************************************************************** maxhd equ 0 ;Set to boot an HDC3 controller maxmw equ 0 ;Set to boot a HDDMA controller maxfd equ 1 ;Set to boot a DJ2D/B controller maxdm equ 0 ;Set to boot a DJDMA controller with 8 inch maxmf equ 0 ;Set to boot a DJDMA controller with 5 1/4 inch ***************************************************************** * * * The following equates are for the Hard Disk Controller 3. * * mands dmaread equ 0 ;Read sector dmawrit equ 1 ;Write sector dmarhed equ 2 ;Find a sector dmawhed equ 3 ;Write headers (format a track) dmalcon equ 4 ;Load disk parameters dmassta equ 5 ;Sense disk drive status dmanoop equ 6 ;Null controller operation reset equ 54h ;Reset controller attn equ 55h ;Send a controller attention chan equ 50h ;Default channel address stepout equ 10h ;Step direction out stepin equ 0 ;Step direction in band1 equ 40h ;No precomp, high current band2 equ 0c0h ;Precomp, high current band3 equ 80h ;precomp, low current track0 equ 1 ;Track zero status wfault equ 2 ;Write fault from drive dready equ 4 ;Drive ready endif ***************************************************************** * * * The following equates are for the Disk Jockey 2D/B. * * * ***************************************************************** if maxfd ne 0 origin equ 0f800h ;Orgin of DJ 2D Mod B PROM djram equ origin+400h ;Disk Jockey 2D Mod B r to where the * * various parts of of the operating system are in memory. * * * * The only changes to the map that I see in the future is * * the increasing the space for the uninitialized tables * * following the Cbios. The amount of code and table space * * that can actually be loaded from the disk is fixed by the * * amount of space available on the system tracks. * * * * Our most restrictive (smallest) drive is the 5 1/4 inch * * 'minnie floppy'. This drive has 20 512 byte sectors for * * a total of 10k bytes on the system tracks. The 8 inch * * floppy disk drive is also very close to being filled up. * * * * Since 512 bytes are reserved for the cold boot loader we * * have a total of 9.5k bytes for the operating system. Out * * of this 5.5k bytes are used by the (CCP + BDOS) leaving * * us with a total of 4k bytes of loaded code and data space * * to play with. Right now we are using all of this space * * so any major additions will have to result in a littl * ***************************************************************** if maxhd ne 0 hdorg equ 50h ;Hard Disk Controller hdstat equ hdorg ;Hard Disk Status hdcntl equ hdorg ;Hard Disk Control hddata equ hdorg+3 ;Hard Disk Data hdfunc equ hdorg+2 ;Hard Disk Function hdcmnd equ hdorg+1 ;Hard Disk Command hdreslt equ hdorg+1 ;Hard Disk Result retry equ 2 ;Retry bit of result tkz equ 1 ;Track zero bit of status opdone equ 2 ;Operaction done bit of status complt equ 4 ;Complete bit of status tmout equ 8 ;Time out bit of status wfault equ 10h ;Write fault bit of status drvrdy equ 20h ;Drive ready bit of status indx equ 40h ;Index bit of status pstep equ 4 ;Step bit of function nstep equ 0fbh ;Step bit mask of function hdrlen equ 4 ;Sector header length secln equ 512 ;Sector data length wenabl equ 0fh ;Write enable wreset equ 0bh ;Write reset of function scenbl equ 5 ;Controller control dskclk equ 7 ;Disk clock for control mdir equ 0f7h ;Direction mask for functiooutines tkzero equ origin+9h ;Track 0 seek trkset equ origin+0ch ;Set track setsec equ origin+0fH ;Set sector setdma equ origin+12h ;Set DMA address dread equ origin+15h ;Read sector dmast equ origin+24h ;Get DMA address status equ origin+27h ;Disk status dskerr equ origin+2ah ;Flash error light setden equ origin+2dh ;Set density endif ***************************************************************** * * * The following equates are for the Disk Jockey DMA if wanted. * * * ***************************************************************** if (maxdm ne 0) or (maxmf ne 0) djkick equ 0efh ;Kick port for DJDMA controller channl equ 50h if maxdm ne 0 ;8 inch boot loader trkoff equ 22*128 ;Number of bytes loaded from track 0 else ;5 1/4 inch boot loader trkoff equ 9*512 ;Number of bytes loaded from track 0 endif setdma equ 23h ;Set DMA address djhalt equ 25h ;Halt controller djbran equ 26h ;Branch controller command redtrk equ 29h ;Read track command . * * * ***************************************************************** if maxhd ne 0 ;Low level HDC3 drivers crdhd lxi b,retries*100h+1 ;Maximum # of attempts crhd push b ;Save error count call hdread ;Attempt the read pop b ;Restore the error count rnc ;Return if no error dcr b ;Update error count jnz crhd ;Try again if not too many errors jmp $ ;Dynamic error halt hdread call hdprep ;Prepare the sector header image rc ;Error exit mvi a,rsect ;Read sector command out hdcmnd call process ;Process the read rc ;Error exit xra a ;Pointer to data buffer out hdcmnd mvi b,secln/4 ;Number of bytes to read lhld cdmahd ;Get destination of data in hddata ;Two dummy data bytes in hddata rtloop in hddata ;Move four bytes mov m,a ;Byte one inx h in hddata ;Byte two mov m,a inx h in hddata ;Byte three mov m,a inx h in hddata ;Byte four mov m,a inx h dcr b ;Update byte count jnz rtloop ret process in hdstat ;Waitue ;Do load constants jc error ;Controller not present mvi a,dmassta ;Sense status command sta dmaop rdychek call hdissue ani dready ;Check for drive ready jnz rdychek ;Loop if not ready lxi h,0ffffh shld dmastep ;Do recalibrate call hdissue lxi h,0 shld dmastep ;Clear step counter shld dmarg0 ;Clear cylinder # shld dmarg3 ;Clear sector # + read disk command ret hdissue lxi h,dmastat ;Status byte mvi m,0 out attn ;Start controller lxi d,0 ;Time out counter mov b,e ;Controller busy status hdiloop mov a,m ;Get status ora a ;Set up CPU flags rm ;Return no error (carry reset) stc rnz ;Return error status xthl ;Waste some time xthl xthl xthl dcx d ;Bump timeout counter mov a,d ora e jnz hdiloop ;Loop if still busy stc ;Set error flag ret hdsec db 0 ;Currently selected sector dmachan equ $ ;Command channel area dmasel0 db 10h ;Drive select (step out, drive 0) dmastep dw 0 ;Relative step counter dmasel1 db 0 ;Head endif ***************************************************************** * * * Define the origin address for the various boot loaders. * * * ***************************************************************** if maxhd ne 0 ;HDC3 boot equ bios+(biosln*100h)-512 ;Very last part of CP/M system endif if maxmw ne 0 ;HDDMA boot equ 100h endif if maxfd ne 0 ;DJ2D/B boot equ djram+300h ;Upper 3/4 of on board floppy RAM endif if (maxdm ne 0) or (maxmf ne 0) ;DJDMA boot equ 80h endif offset equ 900h-boot ;DDT offset org boot ***************************************************************** * * * Cold Boot loader for a hard disk. * * * ***************************************************************** if (maxhd ne 0) or (maxmw ne 0) lxi sp,cstkhd ;Set up stack at end of this sector if maxhd ne 0 lxi b,19*100h+2 ;B = sector count, C = sector # call clodhd jmp cboot ;Go to CP/M else lxi h,boot+200h ;Copy part of CCP up  for command to finish mov b,a ani opdone jz process mvi a,dskclk ;Turn on Disk Clock out hdcntl in hdstat ani tmout ;Timed out ? stc rnz in hdreslt ani retry ;Any retries ? stc rnz xra a ;No error exit ret hdprep in hdstat ;Is Drive ready ? ani drvrdy stc rnz mvi a,isbuff ;Initialize pointer to header buffer out hdcmnd mvi a,null out hdfunc ;Select drive A xra a out hddata ;Form head byte out hddata ;Form track byte mvi a,0 ;Form sector byte hdsec equ $-1 out hddata mvi a,80h ;Form Key out hddata mvi a,dskclk ;Turn on Disk clock out hdcntl mvi a,wenabl ;Write enable on out hdcntl ret org boot+200h-2 ;Last word on sector is load address cstkhd equ $ dw boot endif if maxmw ne 0 ;Low level HDDMA routines crdhd call hdsetup ;Set up parameters lxi b,retries*100h+1 ;Maximum # of attempts crhd push b ;Save error count call hdissue ;Attempt the read pop b ;Restore the error count rnc ;Return if no error  select dmadma dw 0 ;DMA address db 0 ;Extended address dmarg0 db 0 ;First argument dmarg1 db stepdly ;Second argument (stepping time) dmarg2 db headdly ;Third argument (Settle time) dmarg3 db sectsiz ;Fourth argument (Sector size) dmaop db dmalcon ;Operation code dmastat db 0 ;Controller status byte dmalnk dw dmachan ;Link address to next command channel db 0 ;extended address org boot+200h cstkhd equ $ ;Stack area at end of sector endif endif ***************************************************************** * * * Cold boot loader for the Disk Jockey 2D Revision B controller * * * ***************************************************************** if maxfd ne 0 t0boot mvi a,5-2 ;First sector - 2 newsec equ $-1 inr a ;Update sector # inr a cpi 27 ;Size of track in sectors + 1 trksiz equ $-1 jc nowrap ;Skip if not at end of track jnz t1boot ;Done with this track exit equ $-2 sui 27-6 ;Back up to sector 6 backup equ $-1 lxi h,loaddlxi d,loaddr lxi b,200h movlop: mov a,m ;Get a byte stax d ;Save it inx h ;Bump pointers inx d dcx b ;Bump counter mov a,b ;Test for end ora c jnz movlop lxi b,10*100h+2 ;B = sector count, C = sector # call clodhd jmp cboot ;Go to CP/M endif clodhd push b ;Save sector and count mov a,c ;Load sector sta hdsec lxi h,loaddr-200h ;Get DMA address (self modifying) cdmahd equ $-2 ;Storage for previous DMA address if maxhd ne 0 lxi d,200h ;Offset to new DMA address else lxi d,400h endif dad d ;Add in offset, HL = new DMA address shld cdmahd ;Save new DMA address call crdhd ;Attempt a read pop b ;Recover sector number and count ; B = count, C = number dcr b ;Update sector count rz ;All done ? inr c ;Bump sector number jmp clodhd ;Continue reading ***************************************************************** * * * crdhd does the actual read from the controller, the DMA * * address and sector # have already been set updcr b ;Update error count jnz crhd ;Try again if not too many errors error jmp $ ;Dynamic error halt hdsetup shld dmadma ;Set up DMA address call hdreset ;Reset controller lda hdsec ;Set logical sector number dcr a ;Range is actaully 0-16 call divspt ;Figure out head number -> (c) adi spt ;Make real sector number sta dmarg3 mov a,c sta dmarg2 ;Save head number cma ;Negative logic for the controller ani 7 ;3 bits of head select rlc ;Shove over to bits 2 - 4 rlc sta dmasel1 ;Save in command channel head select ret divspt mvi c,0 ;Clear head counter divsptx sui spt ;Subtract a tracks worth of sectors rc ;Return if all done inr c ;Bump to next head jmp divsptx hdreset mvi a,(ret) ;One time code sta hdreset out reset ;Send reset pulse to controller lxi h,dmachan ;Address of command channel shld chan ;Default channel address xra a sta chan+2 ;Clear extended address byte xthl ;Wait for reset (around 10 uSEC's) xthl call hdissr-80h ;Memory address of sector - 100h nxtdma equ $-2 shld newdma nowrap sta newsec ;Save the updated sector # mov c,a call setsec ;Set up the sector lxi h,loaddr-100h ;Memory address of sector - 100h newdma equ $-2 lxi d,100h ;Update DMA address secsiz equ $-2 dad d nowrp shld newdma ;Save the updated DMA address mov b,h mov c,l call setdma ;Set up the new DMA address lxi b,retries*100h+0;Maximum # of errors, track # nxtrty equ $-2 fread push b call trkset ;Set up the proper track call dread ;Read the sector pop b jnc t0boot ;Continue if no error dcr b jnz fread ;Keep trying if error jmp dskerr ;Too many errors, flash the light t1boot lxi h,cboot ;We jump to cboot next time shld exit mvi c,1 ;Select double density call setden xra a ;First sector - 2 sta newsec mvi a,8 ;Size of (logical) track + 1 sta trksiz dcr a ;Number of sectors to back up sta backup lxi h,loaddr+0700h ;DMA start address for first revolution - 2048 shld newdmjhalt ;Halt controller djdone: db 0 ;Returned status org boot+5dh ;Boot + 5ch contains 'configuration byte' if maxdm ne 0 ;Booting from 8 inch drives sectb0: dw 0ffffh, 0ffffh ;Do not load boot loader dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;22 sectors to be loaded sectb1: dw 0, 0, 0, 0ff00h ;First seven sectors db retries ;Retry counter else ;Booting from 5 1/5 inch drives sectb0: dw 0ffh, 0, 0, 0, 0;Do not load boot loader sectb1: dw 0, 0, 0, 0, 0 ;Load ten sectors db retries ;Retry counter endif endtbl equ $-1 ;end of table marker endif end !4w_#~ ʸ A:4~~# ¼ > \ ?ʻ w# !ͼ ? !ͼ a lxi h,loaddr+0300h ;DMA start address for second revolution - 2048 shld nxtdma lxi h,2048 ;Difference between DMA addresses shld secsiz lxi h,retries*100h+1;Maximum # of errors, track # shld nxtrty jmp t0boot ;Go load in track 1 endif ***************************************************************** * * * Cold boot loader for the Disk Jockey DMA controller * * * ***************************************************************** if (maxdm ne 0) or (maxmf ne 0) ;Set up DJDMA loader mvi a,djbran ;Load branch channel command sta channl lxi h,commnd ;Load new command channel address shld channl+1 xra a sta channl+3 djstrt: out djkick ;Start controller djwait: lda djdone ;Get final status ora a ;0 = still busy jz djwait ;Loop if busy lxi h,sectb0 ;Check for bad load lxi b,40ffh ;b = ok, c = loaded lxi d,endtbl-sectb0 ;Error count + # of sectors djloop: mov a,m ;Load sector code cmp c ;Check for 0ffh (already loaded) jz djcont ;Ski1*" COPYRIGHT(C) 1978, DIGITAL RESEARCH á 4êü /L9ASMPRNHEX!)ͼ !ͼ :5͡ :6:6͡ :7͡ :\ ʻ 24!dͮ 25ͮ 27ͮ 26!8 ( ʃ !Y 1  :7ʞ !z 8  !"2D2X2#! 8 !ͼ z{* ! !"!8 w#  +6# *#"~!ͼ G:6QxJQS*!w#"! 1 !"!Y~~# …¡z!ͼ wʹ* ! w#" ! 8 !" ! zz_O4:  :6y:! G~#x=2> > ! >x6 #='G! ~ p( O*}O>4?:7w:#ĸ*"!͸* }w>ͪg( ʆ1 Y :7ʗ8 z !<ͼ CP/M ASSEMBLER - VER 2.0 NO SOURCE FILE PRESENT NO DIRECTORY SPACE SOURCE FILE NAME ERROR SOURCE FILE READ ERROR OUTPUT FILE WRITE ERROR CANNOT CLOSE FILES END OF ASSEMBLY G:7xʘ!#~ʄl͸Ä**!O {zʊ͸*"!!#^4!$wͯͯWƐ'@'ê>:ͪ!#^Ww*!{͚|͚}͚͚{!$~#͚͚> ͪ> ͪp if load was 'ok' mov m,c ;Load 'loaded' flag cmp b ;Check for 'ok' status jz djcont ;Skip if load ok inr m ;Make flag = 0 inr d ;Bump error counter djcont: dcr e ;Bump sector count inx h ;Bump table pointer jnz djloop mov a,d ;Check out error counter ora a jz cboot ;Start CP/M if no errors dcr m ;Drop retry counter jnz djstrt ;Retry load operation jmp $ ;Dynamic error halt commnd: db setdma ;Set DMA address dw loaddr-512 ;Start at CCP if micron eq 0 db 0 ;Extended address for CP/M else db 0ffh ;Wrap around from ffff00 to 000100 endif db redtrk ;Read track db 0 ;Track 0 db 0 ;Side 0 db 0 ;Drive 0 dw sectb0 ;Sector table 0 db 0 ;Extended address db 0 ;Returned status db setdma ;Set DMA address dw loaddr+trkoff ;Load address for track 1 db 0 ;Extended address db redtrk ;Read track db 1 ;Track 1 db 0 ;Side 0 db 0 ;Drive 0 dw sectb1 ;Sector table 1 db 0 ;Extended address db 0 ;Returned status db d@2 0 0:x0_<2! wI2 2> 2 >2ɯ22 !~@_6^4#: w~$w: 0 q: A: A͋q: a{_2  2 - !ɯ2I:  ;*:  ͭͷ ͭ͋>9q>9: '!2 >9 7:! 6 >2>2: 2 Qͭ:Ğ! :lj<͖<j<|<: OʊQ>ÖH >2 2 û: B­>ôD> ¸!52 !"!N#~#A07O! ~*!) " :  '<ͭ'<>V$>O$:Ğà\ÞØ`rÍÖ![w#w#b!"!F#v2[G*##~w*##~<*}q!~ڬ6![^![^#fk"͎͘!G#*####*^#Vû!^*"*:|: |Ë  |*" ͩ !6="1 :  1}1:n:>BʋSSͦSSxS 1:  1"" ͦ 1 |R >O U!" 1 1!|_!^#fk $8AP`ixH ñññ81Ľ y0îH ñGîG  ñH ñ(Ľ yîH ñîîĽ y0îîH ñG 1: :,; c*| } 8OĽ y0G G t :):,.>C :|: Jü;r :R: ʼʋ!ʼR!ʼʋ>SR{ozg!~4ʧͦ !6 ! **̈́**̈́\iͩ !w#H USE FACTOR !* "z{*"* "I !" :1 R O*UR X* G:xl :  *̩ : l x͖ *#"EH DH 0:~ ! ^4! w͆ Æ *! 6z͖ {͖ 4>R>V>D >P >L >Nhome jmp seldsk jmp settrk jmp setsec jmp setdma jmp read jmp write jmp listst ;list status jmp sectran ; maclib diskdef ;load the disk definition library disks 4 ;four disks diskdef 0,1,26,6,1024,243,64,64,offset diskdef 1,0 diskdef 2,0 diskdef 3,0 ; endef occurs at end of assembly ; ; end of controller - independent code, the remaining subroutines ; are tailored to the particular operating environment, and must ; be altered for any system which differs from the intel mds. ; ; the following code assumes the mds monitor exists at 0f800h ; and uses the i/o subroutines within the monitor ; ; we also assume the mds system has four disk drives revrt equ 0fdh ;interrupt revert port intc equ 0fch ;interrupt mask port icon equ 0f3h ;interrupt control port inte equ 0111$1110b ;enable rst 0(warm boot), rst 7 (monitor) ; ; mds monitor equates mon80 equ 0f800h ;mds monitor rmon80 equ 0ff0fh ;restart mon80 (boot error) ci equ 0f803h ;console character to reg-a ri equ 0f806{zA"*![N![ N#Fr+sq#p/>G=#w#w3#w#w!JSYMBOL TABLE OVERFLOW G*##~w*##~͎*_###s#r^#V`à 4 Wm ()*+,-/ABCDEHLMDBDIDSDWEIIFINORSPACIADCADDADIANAANDANICMACMCCMPCPIDAADADDCRDCXENDEQUHLTINRINXJMPLDALXIMODMOVMVINOPNOTORAORGORIOUTPOPPSWRALRARRETRLCRRCRSTSBBSBISETSHLSHRSTASTCSUBSUIXORXRAXRICALLENDMLDAXLHLDPCHLPUSHSHLDSPHLSTAXXCHGXTHLENDIFMACROTITLE  PF FP! ( 2/?'  v:P@< !  PP27 ( *"  NZZ NCC POPEP M x_BH!œ#¶ ¦{KÈCÈ<:JCR:  !6 s!#  ɯ<:O=_Z!F!V#fjQ̓E!^#Vo&)~#FxGyѯ<àn8!~ڢͅ6~44O! s#r!~ ڿ6ͅ^4!mw!wp!~ͅ!55N! N#fio&)^#fk; MDS-800 I/O Drivers for CP/M 2.2 ; (four drive single density version) ; ; Version 2.2 February, 1980 ; vers equ 22 ;version 2.2 ; ; Copyright (c) 1980 ; Digital Research ; Box 579, Pacific Grove ; California, 93950 ; ; true equ 0ffffh ;value of "true" false equ not true ;"false" test equ false ;true if test bios ; if test bias equ 03400h ;base of CCP in test system endif if not test bias equ 0000h ;generate relocatable cp/m system endif ; patch equ 1600h ; org patch cpmb equ $-patch ;base of cpm console processor bdos equ 806h+cpmb ;basic dos (resident portion) cpml equ $-cpmb ;length (in bytes) of cpm system nsects equ cpml/128 ;number of sectors to load offset equ 2 ;number of disk tracks used by cp/m cdisk equ 0004h ;address of last logged disk on warm start buff equ 0080h ;default buffer address retry equ 10 ;max retries on disk i/o before error ; ; perform following functions ; boot cold start ; wboot warm start (save i/o byte) ; (boot and wboot are the sameh ;reader in to reg-a co equ 0f809h ;console char from c to console out po equ 0f80ch ;punch char from c to punch device lo equ 0f80fh ;list from c to list device csts equ 0f812h ;console status 00/ff to register a ; ; disk ports and commands base equ 78h ;base of disk command io ports dstat equ base ;disk status (input) rtype equ base+1 ;result type (input) rbyte equ base+3 ;result byte (input) ; ilow equ base+1 ;iopb low address (output) ihigh equ base+2 ;iopb high address (output) ; readf equ 4h ;read function writf equ 6h ;write function recal equ 3h ;recalibrate drive iordy equ 4h ;i/o finished mask cr equ 0dh ;carriage return lf equ 0ah ;line feed ; signon: ;signon message: xxk cp/m vers y.y db cr,lf,lf if test db '32' ;32k example bios endif if not test db '00' ;memory size filled by relocator endif db 'k CP/M vers ' db vers/10+'0','.',vers mod 10+'0' db cr,lf,0 ; boot: ;print signon message and go to ccp ; (note: mds boot initialized iobyte at 0003h) lxi z'{ͅ>ɯo>g"k!m6ů{_zW5>)D*kOxGd !m?FDM!xGyOڂÃ)sn55)=â|g}o=î--#zg{ozg{ozg{oÓ:: ;,!ɯ22=2l!"]!~H5_!m~0:ą:  *":  :‰:̅ԅ!^#=ʅVq”*qͦ1& O:lµ̅>2ly:_!w~!s!m~ùy !~=w_!m~ ͅͰ>2lyPLnR>UX:l̅2l͓*>E2C!" """ :ʼ:*1 |R|ͦ0FIL: R  R* } *" :¿::¿üX!C^#fk[@ :Œ:=ʌG!ʆF#H vÛc*| EH ͺ,^1 ͦ *""1 EH DH ͺ,1 ͦ :  1:  " > 2  for mds) ; const console status ; reg-a = 00 if no character ready ; reg-a = ff if character ready ; conin console character in (result in reg-a) ; conout console character out (char in reg-c) ; list list out (char in reg-c) ; punch punch out (char in reg-c) ; reader paper tape reader in (result to reg-a) ; home move to track 00 ; ; (the following calls set-up the io parameter block for the ; mds, which is used to perform subsequent reads and writes) ; seldsk select disk given by reg-c (0,1,2...) ; settrk set track address (0,...76) for subsequent read/write ; setsec set sector address (1,...,26) for subsequent read/write ; setdma set subsequent dma address (initially 80h) ; ; (read and write assume previous calls to set up the io parameters) ; read read track/sector to preset dma address ; write write track/sector from preset dma address ; ; jump vector for indiviual routines jmp boot wboote: jmp wboot jmp const jmp conin jmp conout jmp list jmp punch jmp reader jmp sp,buff+80h lxi h,signon call prmsg ;print message xra a ;clear accumulator sta cdisk ;set initially to disk a jmp gocpm ;go to cp/m ; ; wboot:; loader on track 0, sector 1, which will be skipped for warm ; read cp/m from disk - assuming there is a 128 byte cold start ; start. ; lxi sp,buff ;using dma - thus 80 thru ff available for stack ; mvi c,retry ;max retries push b wboot0: ;enter here on error retries lxi b,cpmb ;set dma address to start of disk system call setdma mvi c,0 ;boot from drive 0 call seldsk mvi c,0 call settrk ;start with track 0 mvi c,2 ;start reading sector 2 call setsec ; ; read sectors, count nsects to zero pop b ;10-error count mvi b,nsects rdsec: ;read next sector push b ;save sector count call read jnz booterr ;retry if errors occur lhld iod ;increment dma address lxi d,128 ;sector size dad d ;incremented dma address in hl mov b,h mov c,l ;ready for call to set dma call setdma lda ios ;sector number just read cpi 20 if error mov a,c cpi ndisks ;too large? rnc ;leave HL = 0000 ; ani 10b ;00 00 for drive 0,1 and 10 10 for drive 2,3 sta dbank ;to select drive bank mov a,c ;00, 01, 10, 11 ani 1b ;mds has 0,1 at 78, 2,3 at 88 ora a ;result 00? jz setdrive mvi a,00110000b ;selects drive 1 in bank setdrive: mov b,a ;save the function lxi h,iof ;io function mov a,m ani 11001111b ;mask out disk number ora b ;mask in new disk number mov m,a ;save it in iopb mov l,c mvi h,0 ;HL=disk number dad h ;*2 dad h ;*4 dad h ;*8 dad h ;*16 lxi d,dpbase dad d ;HL=disk header table address ret ; ; settrk: ;set track address given by c lxi h,iot mov m,c ret ; setsec: ;set sector number given by c lxi h,ios mov m,c ret sectran: ;translate sector bc using table at de mvi b,0 ;double precision sector number in BC xchg ;translate table address to HL dad b ;translate(sector) address mov a,m ;translated sector number to A sta ios mov l,a ;return sector number in  retry ; ; check i/o error bits call inbyte ral jc wready ;unit not ready rar ani 11111110b ;any other errors? (deleted data ok) jnz werror ; ; read or write is ok, accumulator contains zero ret ; wready: ;not ready, treat as error for now call inbyte ;clear result byte jmp trycount ; werror: ;return hardware malfunction (crc, track, seek, etc.) ; the mds controller has returned a bit in each position ; of the accumulator, corresponding to the conditions: ; 0 - deleted data (accepted as ok above) ; 1 - crc error ; 2 - seek error ; 3 - address error (hardware malfunction) ; 4 - data over/under flow (hardware malfunction) ; 5 - write protect (treated as not ready) ; 6 - write error (hardware malfunction) ; 7 - not ready ; (accumulator bits are numbered 7 6 5 4 3 2 1 0) ; ; it may be useful to filter out the various conditions, ; but we will get a permanent error message if it is not ; recoverable. in any case, the not ready condition is ; treated as a separate condi6 ;read last sector? jc rd1 ; must be sector 26, zero and go to next track lda iot ;get track to register a inr a mov c,a ;ready for call call settrk xra a ;clear sector number rd1: inr a ;to next sector mov c,a ;ready for call call setsec pop b ;recall sector count dcr b ;done? jnz rdsec ; ; done with the load, reset default buffer address gocpm: ;(enter here from cold start boot) ; enable rst0 and rst7 di mvi a,12h ;initialize command out revrt xra a out intc ;cleared mvi a,inte ;rst0 and rst7 bits on out intc xra a out icon ;interrupt control ; ; set default buffer address to 80h lxi b,buff call setdma ; ; reset monitor entry points mvi a,jmp sta 0 lxi h,wboote shld 1 ;jmp wboot at location 00 sta 5 lxi h,bdos shld 6 ;jmp bdos at location 5 if not test sta 7*8 ;jmp to mon80 (may have been changed by ddt) lxi h,mon80 shld 7*8+1 endif ; leave iobyte set ; previously selected disk was b, send parameter to cpm lda cdisk ;last logL ret ; setdma: ;set dma address given by regs b,c mov l,c mov h,b shld iod ret ; read: ;read next disk record (assuming disk/trk/sec/dma set) mvi c,readf ;set to read function call setfunc call waitio ;perform read function ret ;may have error set in reg-a ; ; write: ;disk write function mvi c,writf call setfunc ;set to write function call waitio ret ;may have error set ; ; ; utility subroutines prmsg: ;print message at h,l to 0 mov a,m ora a ;zero? rz ; more to print push h mov c,a call conout pop h inx h jmp prmsg ; setfunc: ; set function for next i/o (command in reg-c) lxi h,iof ;io function address mov a,m ;get it to accumulator for masking ani 11111000b ;remove previous command ora c ;set to new command mov m,a ;replaced in iopb ; the mds-800 controller requires disk bank bit in sector byte ; mask the bit from the current i/o function ani 00100000b ;mask the disk select bit lxi h,ios ;address the sector select byte ora m ;tion for later improvement trycount: ; register c contains retry count, decrement 'til zero dcr c jnz rewait ;for another try ; ; cannot recover from error mvi a,1 ;error code ret ; ; intype, inbyte, instat read drive bank 00 or 10 intype: lda dbank ora a jnz intyp1 ;skip to bank 10 in rtype ret intyp1: in rtype+10h ;78 for 0,1 88 for 2,3 ret ; inbyte: lda dbank ora a jnz inbyt1 in rbyte ret inbyt1: in rbyte+10h ret ; instat: lda dbank ora a jnz insta1 in dstat ret insta1: in dstat+10h ret ; ; ; ; data areas (must be in ram) dbank: db 0 ;disk bank 00 if drive 0,1 ; 10 if drive 2,3 iopb: ;io parameter block db 80h ;normal i/o operation iof: db readf ;io function, initial read ion: db 1 ;number of sectors to read iot: db offset ;track number ios: db 1 ;sector number iod: dw buff ;io address ; ; ; define ram areas for bdos operation endef end ged disk number mov c,a ;send to ccp to log it in ei jmp cpmb ; ; error condition occurred, print message and retry booterr: pop b ;recall counts dcr c jz booter0 ; try again push b jmp wboot0 ; booter0: ; otherwise too many retries lxi h,bootmsg call prmsg jmp rmon80 ;mds hardware monitor ; bootmsg: db '?boot',0 ; ; const: ;console status to reg-a ; (exactly the same as mds call) jmp csts ; conin: ;console character to reg-a call ci ani 7fh ;remove parity bit ret ; conout: ;console character from c to console out jmp co ; list: ;list device out ; (exactly the same as mds call) jmp lo ; listst: ;return list status xra a ret ;always not ready ; punch: ;punch device out ; (exactly the same as mds call) jmp po ; reader: ;reader character in to reg-a ; (exactly the same as mds call) jmp ri ; home: ;move to home position ; treat as track 00 seek mvi c,0 jmp settrk ; seldsk: ;select disk given by register c lxi h,0000h ;return 000select proper disk bank mov m,a ;set disk select bit on/off ret ; waitio: mvi c,retry ;max retries before perm error rewait: ; start the i/o function and wait for completion call intype ;in rtype call inbyte ;clears the controller ; lda dbank ;set bank flags ora a ;zero if drive 0,1 and nz if 2,3 mvi a,iopb and 0ffh ;low address for iopb mvi b,iopb shr 8 ;high address for iopb jnz iodr1 ;drive bank 1? out ilow ;low address to controller mov a,b out ihigh ;high address jmp wait0 ;to wait for complete ; iodr1: ;drive bank 1 out ilow+10h ;88 for drive bank 10 mov a,b out ihigh+10h ; wait0: call instat ;wait for completion ani iordy ;ready? jz wait0 ; ; check io completion ok call intype ;must be io complete (00) unlinked ; 00 unlinked i/o complete, 01 linked i/o complete (not used) ; 10 disk status changed 11 (not used) cpi 10b ;ready status change? jz wready ; ; must be 00 in the accumulator ora a jnz werror ;some other condition, title 'mds cold start loader at 3000h' ; ; MDS-800 Cold Start Loader for CP/M 2.0 ; ; Version 2.0 August, 1979 ; false equ 0 true equ not false testing equ false ;if true, then go to mon80 on errors ; if testing bias equ 03400h endif if not testing bias equ 0000h endif cpmb equ bias ;base of dos load bdos equ 806h+bias ;entry to dos for calls bdose equ 1880h+bias ;end of dos load boot equ 1600h+bias ;cold start entry point rboot equ boot+3 ;warm start entry point ; org 03000h ;loaded down from hardware boot at 3000h ; bdosl equ bdose-cpmb ntrks equ 2 ;number of tracks to read bdoss equ bdosl/128 ;number of sectors in dos bdos0 equ 25 ;number of bdos sectors on track 0 bdos1 equ bdoss-bdos0 ;number of sectors on track 1 ; mon80 equ 0f800h ;intel monitor base rmon80 equ 0ff0fh ;restart location for mon80 base equ 078h ;'base' used by controller rtype equ base+1 ;result type rbyte equ base+3 ;result byte reset equ base+7 ;reset controller ; dstat equ base ;disk statusrs. The system diskette can be either * * single or double sided. The sector size on normal (non * * A: drive) diskettes is not restricted. Thus if you have * * a diskette with software that is supposed to run on the * * A: drive then you should mount the diskette in the B: * * drive and then PIP it over to a 1024 byte sector * * system diskette. * * * * Written by Les Kent and Marc Kupper 3/4/82 * * * * Date Programmer Description * * * **11 20 82 Marc Public release of revision E.31 * * 11 19 82 Marc Changed HDC3 equate to HDCA  port ilow equ base+1 ;low iopb address ihigh equ base+2 ;high iopb address bsw equ 0ffh ;boot switch recal equ 3h ;recalibrate selected drive readf equ 4h ;disk read function stack equ 100h ;use end of boot for stack ; rstart: lxi sp,stack;in case of call to mon80 ; clear disk status in rtype in rbyte ; check if boot switch is off coldstart: in bsw ani 02h ;switch on? jnz coldstart ; clear the controller out reset ;logic cleared ; ; mvi b,ntrks ;number of tracks to read lxi h,iopb0 ; start: ; ; read first/next track into cpmb mov a,l out ilow mov a,h out ihigh wait0: in dstat ani 4 jz wait0 ; ; check disk status in rtype ani 11b cpi 2 ; if testing cnc rmon80 ;go to monitor if 11 or 10 endif if not testing jnc rstart ;retry the load endif ; in rbyte ;i/o complete, check status ; if not ready, then go to mon80 ral cc rmon80 ;not ready bit set rar ;restore ani 11110b ;overrun/addr err/seek/crc/xxxx ; if testing cnz rmon80 ;g************************************************************************* * * * Morrow Designs CBIOS for CP/M Version 2.2. * * * * This CBIOS can be configured to run with the following devices. * * The disks may be configured to run with any or all of the disk * * systems. The logical order of the disks can be set to any order. * * * * Disk systems: * * HDCA 10, 20 and 26 megabyte hard disks. * * HDDMA 5, 10, 16, megabyte hard disk systems. * * DJDMA floppy disk controller with 8 and 5 1/4 inch disks. * * DJ 2D/B floppy disk controller with 8 inch disks. * * * * 11 19 82 Marc Changed blank IO routines from RET to JMP $ * * 11 19 82 Marc Converted BIOSLN to a byte value * * 11 9 82 Marc Reduced bad map size to 1 for non MW systems * * 11 8 82 Marc Deleted baud rate test from Multio drivers * * 11 4 82 Marc Added initial IOBYTE to IOCONF * * 11 3 82 Marc Added the North Star character I/O system * * 11 2 82 Marc Added character redirection code for the IOBYTE * * 11 1 82 Marc Changed serial i/o entry names to IOBYTE names * * 10 18 82 Marc Fixed SETHIGH for 2 sided DJDMA 8 inch disks * * 10 18 82 Marc Deleted the HyType drivers * **10 1 82 Marc Public release of revision E.3 * * 9 29 82 Marc 40H now points to the HDDMA command channel * * 9 28 82 Marc MW's now have 1024 directory entries * * 9 28 82 Marc Deleted the Centronicso to monitor endif if not testing jnz rstart ;retry the load endif ; ; lxi d,iopbl ;length of iopb dad d ;addressing next iopb dcr b ;count down tracks jnz start ; ; ; jmp to boot to print initial message, and set up jmps jmp boot ; ; parameter blocks iopb0: db 80h ;iocw, no update db readf ;read function db bdos0 ;# sectors to read on track 0 db 0 ;track 0 db 2 ;start with sector 2 on track 0 dw cpmb ;start at base of bdos iopbl equ $-iopb0 ; iopb1: db 80h db readf db bdos1 ;sectors to read on track 1 db 1 ;track 1 db 1 ;sector 1 dw cpmb+bdos0*128 ;base of second read ; end  * * Console I/O: * * Disk Jockey 2D/B serial. * * Disk Jockey DMA serial. * * Multi I/O serial. * * Decision I serial. * * * * Printer I/O: * * Multi I/O serial with handshaking. * * Multi I/O Diablo 1620 simulator for the Hytype II. * * * * Note: Floppy systems diskette (drive A:) has to have 1024 byte * * sectors in order for the cold and warm boot loaders to * * work. Be sure to format all new system diskettes with * * 1024 byte secto  drivers * * 9 27 82 Marc Changed login message to look like a label * * 9 27 82 Marc Changed the login messages to say M5, M10, ... * * 9 27 82 Marc Redefined the dparam table structure * * 9 22 82 Marc Added a serial console for the Switchboard * * 9 22 82 Marc Added initialization code for serial group 2 * * 9 22 82 Marc Added sector size byte to the HDCA DPB's * * 9 22 82 Marc Added sector size parameter to DPBGEN * * 9 9 82 Marc Fixed system length checks for 64K systems * * 9 9 82 Marc SETHIGH was botching 2 sided DPB pointers * * 8 31 82 Marc Changed TRACKS in HD driver to HDTRAK * * 8 27 82 Marc Added code/system length checker * * 8 27 82 Marc mwreset save/restores the track number * * 8 26 82 Marc mwreset now sets *step and *dir for CMI * * 8 20 82 Marc r flag * * 6 17 82 Marc Added save/restore of 50-52 to MW driver * * 6 17 82 Marc Fixed Centronics drivers * * 6 7 82 Marc Fixed allocation map sizes * * 6 7 82 Marc Fixed MW partitioning * * 6 7 82 Marc Fixed HD partitioning (again) * * 5 13 82 Marc Fixed illegal MAC labels * * 5 11 82 Marc Fixed North Star drive configurations * * 4 30 82 Marc Fixed Quantum Q2040 tracks to 512 * * 4 29 82 Marc Fixed ST412 step constant to 0 * * 4 26 82 Marc Added unallocated writing * * 4 22 82 Marc Fixed HD partition overlap * * 4 20 82 Marc Started testing and debugging of E.3 * * 4 19 82 Marc Added 1 sector to HD warm boot loader * * 4 19 82 Marc  * * will allow the CBIOS to use various data areas found inside of * * the CP/M 2.2 BDOS. If the CBIOS is used with a different * * operating system then NOSTAND should be set to 0. * * * * The DEBUG flag merely causes various internal values and * * addresses to be printed during the assembly process. This * * printing is forced via assembly errors and thus should not * * affect the resulting code in any way. * * * ************************************************************************* nostand equ 1 ;Set to 1 for non-standard mode debug equ 0 ;Set to 1 for debugging mode ************************************************************************* *  Added 'equ'ed handshaking to the serial LST: * * 8 19 82 Marc Removed clock switching code from HDCA driver * * 8 18 82 Marc Added handshake configuration code * * 8 18 82 Marc Added handshake configuration bytes * * 8 18 82 Marc Removed 'equ'ed handshaking from LST: * * 8 12 82 Marc Added configuration entries for a0 & d0 * * 8 11 82 Marc Added the autostart command structure * * 8 11 82 Marc Redefined the configuration table * * 8 11 82 Marc Added DJDMA drive parameter table * * 8 9 82 Marc Added clock switching to HDCA code * * 8 9 82 Marc Added seek complete clearing in HDCA * * 8 6 82 Marc Added buffer disable on home * * 8 6 82 Marc Fixed 8250 UART initialization sequence * * 8 6 82 Marc Strip parity on conout to clear up glitches  Added mod. number to CBIOS rev. number * * 4 19 82 Marc Clean up login message 'if's * * 4 15 82 Marc Fixed MCR Initialization for LST: * * 4 15 82 Marc Added Seagate ST412 drive * * 4 6 82 Marc Moved serial LST: device to port 2 * * 4 1 82 Marc Added common group select routines * * 4 1 82 Marc Fixed Diablo HyType II initialization * * 4 1 82 Marc Fixed LISTST for PROM driver * * 3 16 82 Marc Added Tandon TM602 and TM603 drives * * 3 16 82 Marc Use 'part number' equates for MW drives * * 3 15 82 Marc Dropped hdrev and mwrev equates * * 3 15 82 Marc Seagate ST506 head settle is 0 ms. * * 3 15 82 Marc Added MiniScribe 1006 and 1012 drives * * *3 1 82 Marc Public release of revision E.2  * * The following is set to the memory size of the CP/M the CBIOS is * * being created for. * * * ************************************************************************* msize equ 48 ;Memory size of target CP/M biosln equ 10h ;BIOS length. Also in ABOOT&.ASM ************************************************************************* * * * The following equates set up the disk systems to be included * * along with the types of drives and the logical order of the * * drives. * * * ************************************************************************* maxhd equ 0 ;Set to numb * * 8 6 82 Marc Fixed the 8 inch dpb256ss DPB's EXM * * 8 6 82 Marc Increased the HD capacities slightly * * 8 6 82 Marc Deleted all non-supported MW drives * * 8 6 82 Marc Deleted call to flush in conout * * 8 6 82 Marc Moved printer back to port 3 * * 7 28 82 Marc Moved conin flush call to conout * * 7 27 82 Marc Fixed double sided head settle time * * 7 14 82 Marc Optimized MWissue * * 7 14 82 Marc Clean up login message for HD a bit * * 6 30 82 Marc Fixed MF multi density problems * * 6 29 82 Marc Added Olivetti HD561/1 HD561/2 drives * * 6 28 82 Marc Added a MW error reporter * * 6 18 82 Marc Added nonstandard system mode flag * * 6 17 82 Marc Added a buffer erro * * 2 -- 82 Marc Pre-release testing and debugging * * 2 1 82 Les + Marc Initial coding of revision E * * * ************************************************************************* title 'CBIOS Revision E for CP/M Version 2.2 - March 4, 1982' revnum equ 53 ;CBIOS revision number 5.x = E cpmrev equ 22 ;CP/M revision number 2.2 ************************************************************************* * * * The following flags set a 'non-standard' system mode and an * * assembly time debugger. * * * * If this CBIOS is used with the CP/M 2.2 system that is shipped on * * a Morrow Designs diskette then NOSTAND can be set to 1. This er of HDCA hard disk drives maxmw equ 0 ;Set to number of HDDMA hard disks maxfd equ 4 ;Set to number of 2D/B floppies maxdm equ 0 ;Set to number of DJ DMA floppies 8 inch maxmf equ 0 ;Set to number of DJ DMA floppies 5 1/4 inch hdorder equ 0 ;Set the order of logical drives ELSE 0 if mworder equ 0 ; not included. fdorder equ 1 dmorder equ 0 mforder equ 0 ;HDCA controller disk drives. Set only one m10f equ 0 ;Fujitsu M2301B m20 equ 0 ;Fujitsu M2302B m26 equ 0 ;Shugart SA4000 m10m equ 0 ;Memorex ;HDDMA controller disk drives. Set only one mwquiet equ 0 ;Set for no names printed on login st506 equ 0 ;Seagate ST-506 st412 equ 0 ;Seagate ST-412 cm5619 equ qu 0 ;Set to number of non standard partitions ************************************************************************* * * * The following equates define the console and printer environments. * * * ************************************************************************* ************************************************************************* * * * Define the console driver to be used. * * * * CONTYP is: 0 Nothing, used for patching to PROM's. * * 1 Provide for 128 bytes of patch space. * * 2 Multi I/O or Decision I driver. * * 3 2D/B driver.  * ************************************************************************* lsttyp equ 1 lbaud equ 0 ************************************************************************* * * * The next equate determines if you have a Multi I/O Rev 3 or a * * Decision I mother board for parallel i/o. If are not using * * either of these boards then you need not worry about this equate. * * If you are using a Multi I/O rev. other than 3.x or 4.x then you * * should set MULTR3 to 0. * * * ************************************************************************* multr3 equ 0 ;0 = Decision, 1 = Multi I/O rev. 3 or 4 congrp equ 1 ;Cosole port (1 = p1, 2 = p2, 3 = p3) lstgrp equ 3 ;Printer 0 ;CMI CM-5619 wmdrive equ 0 ;Device to warm boot from. This is the ; CP/M logical drive number. if maxmw ne 0 ;Only HDDMA drives use the bad map badsiz equ 32 ;Number of badmap entries else badsiz equ 1 ;Leave one entry as filler endif ************************************************************************* * * * Since most hard disk drives hold more than 8 megabytes we * * partition the drive. We partition our drives using two different * * formulas. * * * * One is the so called 'standard partitioning' where we try to * * create as many 8 megabyte partitions as possible plus a small * * partition to take up the slack on t * * 4 DJDMA serial port * * 5 Switchboard serial port * * 6 North Star motherboard (2 serial + 1 parallel) * * * * Set CBAUD to the divisor latch value for the console. For an * * explanation of the values look at the DEFCON table. * * * ************************************************************************* contyp equ 3 cbaud equ 0 ************************************************************************* * * * Define the printer driver to be used. * * * * LSTTYP is: 0 Nothing, used for patching to PROM's.port (1 = p1, 2 = p2, 3 = p3) ************************************************************************* * * * The following equates are internal to the CBIOS. * * * ************************************************************************* m10 equ m10f or m10m if hdpart ne 0 ;Use non standard partitions hdlog equ hdpart else hdlog equ m10*2+m20*3+m26*3 ;Logical disks per drive for HDCA endif if mwpart ne 0 ;Use non standard partitions mwlog equ mwpart else mwlog set st506+st412*2++cm5619*2 ;Logical disks per drive for HDDMA endif hdca equ m26 or m20 or m10 ;HDCA controller fujitsu equ m20 or m10f hdspt equ 32*m26+21*m20+21*m10 ;Sectors per track hdma set he end of the drive. * * * * Another way the drives are partitioned is the so called 'even * * partition' formula. This means that the drive is split into * * equale sized partitions with the only restriction being that no * * partition be over 8 megabytes in length. * * * * All hard disk drives shipped from Morrow Designs are partitioned * * using the standard partition formula. If the user wishes to * * implement even partitioning then he/she must set HDPART or MWPART * * to the number of partitions desired. * * * ************************************************************************* hdpart equ 0 ;Set to number of non standard partitions mwpart e * * 1 Provide for 128 bytes of patch space. * * 2 Multio serial, no protocol. * * 3 Multio serial, Clear To Send protocol. * * 4 Multio serial, Data Set Ready protocol. * * 5 Multio serial, Xon/Xoff protocol. * * * * Note: The Decision board is functionally identical to the Multi * * I/O board for serial printer I/O. Selections 2 to 5 will * * work on the Wunderbuss i/o board. To use drivers 6 or 7 * * the MULTR3 equate will have to be set. * * * * Set pbaud to the divisor latch value for the printer. For an * * explanation of the values see the deflst table. * *   st506 or st412 or cm5619 ;HD DMA controller mwspt equ 9 ;Sectors per track maxlog equ (maxhd*hdlog)+(maxmw*mwlog)+maxfd+maxdm+maxmf ************************************************************************* * * * CP/M system equates. * * * ************************************************************************* ccpln equ 800h bdosln equ 0e00h size equ (msize*1024) ccp equ size-(biosln*100h+ccpln+bdosln) bdos equ ccp+ccpln bios equ ccp+ccpln+bdosln offsetc equ 2100h-bios ;Offset for sysgen if debug dbgtmp set offsetc ;DDT offset ! dbgtmp set ccp ;CCP address ! dbgtmp set bdos ;BDOS address ! dbgtmp set  generating the DPH, DPB and * * allocation tables. * * * ************************************************************************* dpbgen macro nam,log,dspt,dbsh,dblm,dexm,ddsm,ddrm,dal0,dal1,dcks,doff,ssiz dpb&nam&log equ $ dw dspt db dbsh db dblm db dexm dw ddsm dw ddrm db dal0 db dal1 dw dcks dw doff db ssiz endm dphgen macro nam,log,dpb1,dpb2 dph&nam&log equ $ dw 0 dw 0,0,0 dw dirbuf dw &dpb1&dpb2 dw csv&nam&log dw alv&nam&log endm alloc macro nam,log,al,cs csv&nam&log: ds cs alv&nam&log: ds al endm ************************************************************************************************************ org bios ;Cbios starting address jmp cboot ;Cold boot entry point wboote: jmp wboot ;Warm boot entry point if contyp ne 0 const: jmp conist ;Console status routine cin: jmp conin ;Console input cout: jmp costrp ;Console output else const: jmp $ ;Console status routine PROM pointer cin: jmp $ ;Console input PROM pointer cout: jmp $ ;Console output PROM pointer endif if (lsttyp ne 0) or (contyp eq 6) pout: jmp lstout ;List device output else pout: jmp cout ;List device output endif if contyp eq 6 ;North Star drivers have punch entry points jmp punout ;Punch device output else jmp cout ;Use console I/O endif bios ;CBIOS address ! endif cdisk equ 4 ;Address of last logged disk buff equ 80h ;Default buffer address tpa equ 100h ;Transient memory iobyte equ 3 ;IOBYTE location wbot equ 0 ;Warm boot jump address entry equ 5 ;BDOS entry jump address if nostand ne 0 cblock equ bios-19h ;Current actual block# * blkmsk ;Used for unallocated writting endif ************************************************************************* * * * The following are internal Cbios equates. Most are misc. constants. * * * ************************************************************************* retries equ 10 ;Max retries on disk i/o before error cle*********** * * * The following marco is used in generating the logical order of the * * CP/M drives. * * * ************************************************************************* order macro num if num eq hdorder dw hddst endif if num eq mworder dw mwdst endif if num eq fdorder dw fddst endif if num eq dmorder dw dmdst endif if num eq mforder dw mfdst endif endm ************************************************************************* * * * The folloing are offset numbers of Device Specification Tables. * *  if contyp eq 6 ;North Star drivers have reader entry points jmp rdrin ;Reader device input else jmp cin ;Use console I/O endif jmp home ;Home drive jmp setdrv ;Select disk jmp settrk ;Set track jmp setsec ;Set sector jmp setdma ;Set DMA address jmp read ;Read the disk jmp write ;Write the disk if lsttyp ne 0 jmp lstost ;List device status else jmp donop ;List device status endif jmp sectran ;Sector translation ; ; The following jumps are extended BIOS calls defined by Morrow Designs ; if maxfd ne 0 jmp fdsel ;Hookup for SINGLE.COM program else jmp donop endif jmp 0 ar equ 'Z'-64 ;Clear screen on an ADM 3 anul equ 0 ;Null aetx equ 'C'-64 ;ETX character aack equ 'F'-64 ;ACK character abel equ 'G'-64 ;Bell abs equ 'H'-64 ;Back Space aht equ 'I'-64 ;Horizontal tab alf equ 'J'-64 ;Line feed avt equ 'K'-64 ;Vertical tab aff equ 'L'-64 ;Form Feed acr equ 'M'-64 ;Carriage return xon equ 'Q'-64 ;Xon character xoff equ 'S'-64 ;Xoff character aesc equ 1bh ;Escape character ars equ 1eh ;RS character aus equ 1fh ;US character asp equ ' ' ;Space adel equ 7fh ;Delete ************************************************************************* * * * The following are the macros used in * ************************************************************************* d$wboot equ 0 ;Warm boot d$stran equ 1 ;Sector translation d$sel1 equ 2 ;Drive select, Return DPH d$sel2 equ 3 ;Drive select d$home equ 4 ;Home drive d$strk equ 5 ;Set track d$ssec equ 6 ;Set sector d$sdma equ 7 ;Set DMA address d$read equ 8 ;Read a physical sector d$write equ 9 ;Write a physical sector d$bad equ 10 ;Return pointer to bad sector info ************************************************************************* * * * The jump table below must remain in the same order, the routines * * may be changed, but the function executed must be the same. * * * ***************************  ;End of the jump table ************************************************************************* * * * Drive configuration table. * * * ************************************************************************* drconf: db 0 ;Revision 0 structure db 32 ;32 bytes long now ************************************************************************* * * * The following is the table of pointers to the Device * * Specification Tables. The order of this table defines the * * logical order of the CP/M drives. * * * ******************************************************* * * * * ;Select console group * * lda group ;Get group byte * * ori congrp ;Select the console port * * out grpsel ;Select the group * * * * ;Modify a bit in the group byte * * lda group ;Get group byte * * ori bank ;Set the bank bit * * sta group ;Save new group setting * * ori group2 ;Select second serial port * * out grpsel ;Select the desired group * * * * Note 8250's MODEM Status Register to strip * * out the desired handshake lines. Next the result of the ANDing * * is XORed with the second of the two bytes. This XORing allows * * the handshake lines to be inverted. Common byte values are * * shown below. * * * * cts equ 10h ;Clear To Send status mask * * * * db cts ;Morrow Designs 'Clear To Send' * * db 0 * * * * db cts ;Inverted Clear To Send * * db cts * * * * ****************** dsttab: equ $ dn set 1 rept 16 order %dn dn set dn+1 endm ************************************************************************* * * * I/O configuration table. * * * * At this CBIOS revision 11 bytes are defined for this table. * * Several extensive changes are planned for the table. Future * * revision of the IOCONF table will have independant entries for * * three serial ports and will be used by several character drivers. * * Also the IOBYTE will be implemented for all the character * * drivers. I might even write an external program to edit this * * table. * * : You should not set the group bits themselves in the * * group byte. * * * * * * The following two words define the default baud rates for the * * console and the list devices. These words are provided so that * * the user can easily modify them and that they will also be used * * in the future by Morrow Designs software. * * * * The following is a list of possible baud rates and the decimal * * value needed for the defcon or deflst words. * * * * Baud rate defcon/deflst Baud rate defcon/deflst * * 50 2304 2000 58  db 0 ;No handshaking * * db 0ffh * * * * * * The last byte in the revision one structure is the last character * * that was recieved from the printer. This byte is used to * * implement Xon/Xoff software handshaking. This handshaking * * protocol should not bother printers that have not implemented * * Xon/Xoff protocol so this driver is enabled all the time. * * * ************************************************************************* ioconf: db 2 ;Revision 2 structure db 11 ;11 bytes long now db contyp ;Console device driver number db lsttyp  * * The first two bytes show the I/O configuration that the CBIOS was * * assembled with. These bytes are used by external software to * * determine the configuration options that are available. * * * * The next byte is the initial IOBYTE value. This value is written * * to location 3 on cold boots. See the CP/M 2 alternation guide * * for a description of the IOBYTE. * * * * The next byte is to make sure that the group select byte on the * * Mult I/O or Decsion I stays consistant throughout the Cbios. * * Only the group bits themselves (bits 0 and 1) should be changed * * as you output to the group port. If you modify one of the other * * bits (such as driver-enable) then you should modify the same bit * * in this byte. For example:  * * 75 1536 2400 48 * * 110 1047 3600 32 * * 134.5 857 4800 24 * * 150 768 7200 16 * * 300 384 9600 12 * * 600 192 19200 6 * * 1200 96 38400 3 * * 1800 64 56000 2 * * * * * * The next two bytes are ued to configure the hardware handshaking * * protocall used by the serial list drivers with the Multio or * * Wunderbuss I/O boards. The first of these two bytes is a mask. * * This mask is ANDed with the  ;List device drive number iobyt equ $ ;The initial IOBYTE is kept here db 00$00$00$00b ;All devices go to CON: group: db 0 ;Group byte defcon: dw cbaud ;Console baud rate divisor value deflst: dw lbaud ;Printer baud rate divisor value if (lsttyp ne 3) and (lsttyp ne 4) ;Xon/Xoff protocol lstand: db 0 ;Serial list handshake mask lstxor: db 0ffh ;Serial list inversion flag endif if lsttyp eq 3 ;Clear To Send protocol lstand: db cts ;Serial list handshake mask lstxor: db 0 ;Serial list inversion flag endif if lsttyp eq 4 ;Data Set Ready protocol lstand: db dsr ;Serial list handshake mask lstxor: db 0 ;Serial list inversion flag endif lastch: db xon ;Last character recieved from the printer ************ * * * * rfu The next two words are reserved for future use. * * They must be zero. * * * * settle This word is similar to the previously defined * * step word. This specifies the head settle timing * * after the heads have been stepped. Example, * * Shugart's SA 850 head settle time is 15 * * milliseconds. The settle constant would be 15 * * * 34.1 or 512. * * * * An assembler macro (dconf) has been provided to assist in * * generating the dparam table. This macros parameters are the * * number ms settle * * * ************************************************************************* dconf 77, 8, 8 ;Drive 0 dconf 77, 8, 8 ;Drive 1 dconf 77, 8, 8 ;Drive 2 dconf 77, 8, 8 ;Drive 3 ************************************************************************* * * * Define 5 1/4 inch drive parameters * * Use Tandon parameters: 40 tracks, 5 ms step, 15 ms settle * * * ************************************************************************* dconf 40, 5, 15 ;Drive 0 dconf 40, 5, 15 ;Drive 1 dconf 40, 5, 15 ;Drive 2 dconf 40, 5, 15 ;************************************************************* * * * The following table are drive parameters for drives connected to * * the DJDMA floppy disk controller. There is one entry for each of * * the the eight drive that the controller can address. The first * * four entries are for the 8 inch drives and the last four are for * * the 5 1/4 inch drives. Users with fast stepping 8 inch drives * * (SA850/1) or slow 5 1/4 inch drives (SA400) should adjust this * * table for optimal device performace. * * * * Each table entry contains four fixed length fields. The fields * * are defined as follows: * * * * tracks This byte contains the number of tracks on thof tracks, the step rate in milliseconds, and the head * * settle time in milliseconds. For example: * * * * ;Shugart SA 850 * * dconf 77, 3, 15 ;77 tracks, 3 ms step, 15 ms settle * * * * ;Shugart SA 400 * * dconf 35, 40, 10 ;35 tracks, 40 ms step, 10 ms settle * * * * Note: Caution should be used when defining the drive parameters. * * Incorrect definations may damage the floppy disk drive. Morrow * * Designs takes no responsibility for damage that occures through * * the misuse of this macro. * * Drive 3 endif ************************************************************************* * * * Console driver routines. * * * * Routine used depends on the value of CONTYP. Possible CONTYP * * values are listed as follows: * * * * CONTYP is: 0 Nothing, used for patching to PROM's * * 1 Provide for 128 bytes of patch space * * 2 Multi I/O or Decision I driver * * 3 2D/B driver * * 4 DJDMA serial port * * 5 Switchboard serial port * * 6 e * * drive. Most 8 inch drives have 77 tracks and * * most 5 1/4 inch drives have 35 or 40 tracks. * * * * config This a a flag byte that indicates as to whether * * or not this drive has been configured. Set to * * 0 to force reconfiguration. * * * * step This word contains the stepping rate constant. * * The DJDMA's delay routines tick 34.1 times per * * millisecond. Thus the step constant would be the * * drive manufactors recomended stepping delay times * * 34.1. Example. Shugart SA 850's step at 3 * * milliseond intervals. The step constant would be * * 3 * 43.1 or 102.  * ************************************************************************* if (maxdm ne 0) or (maxmf ne 0) ;DJDMA present? dconf macro tracks, step, settle db tracks ;Number of tracks db 0 ;Reset the calibrated flag dw step*341/10 ;Step time dw 0 ;Reserved for future use, must be zero dw 0 ;Reserved for future use, must be zero dw settle*341/10 ;Head settle time endm dmarap: db 0, 10*8 ;Revision 0, length 80 bytes dparam: equ $ ;Drive parameter table ************************************************************************* * * * Define 8 inch drive parameters * * Use SA800 parameters: 77 tracks, 8 ms step, 8  North Star motherboard (2 serial + 1 parallel) * * * ************************************************************************* ************************************************************************* * * * This routine is an experiment to reduce missed and garbled * * characters on console output. * * * ************************************************************************* if contyp ne 0 costrp: mov a,c ;Strip parity on conout ani 7fh mov c,a jmp conout endif ***************************************************************** * * * The folowing equates will define the Decision I mother h ;Paper out cover equ 04h ;Cover open pfrdy equ 08h ;Paper feed ready crrdy equ 10h ;Carriage ready pwrdy equ 20h ;Print wheel ready check equ 40h ;Printer check (error) ready equ 80h ;Printer ready ; Define daisy 0 status input bits for Diablo HyType II driver crstrd equ 1020h ;Carriage ready pfstrd equ 810h ;Paper feed ready pwstrd equ 2040h ;Print wheel ready ; Define daisy 0 output bits d9 equ 01h ;Data bit 9 d10 equ 02h ;Data bit 10 d11 equ 04h ;Data bit 11 d12 equ 08h ;Data bit 12 pfstb equ 10h ;Paper feed strobe crstb equ 20h ;Carriage strobe pwstb equ 40h ;Print wheel strobe rest equ 80h ;Printer restore (Ribbon lift on Multi I/O) ; Define clock select b The standard divisor * * table is given below. * * * * Sense switch: 123 (0 = off, 1 = on) * * 000 = 110 * * 001 = 300 * * 010 = 1200 * * 011 = 2400 * * 100 = 4800 * * 101 = 9600 * * 110 = 19200 * * defcon = 9600 * * * * Note: If you are using a Multio then the switches will not be * * available * * board I/O or the Multi I/O environments if needed. * * * ***************************************************************** multio equ (contyp eq 2) or (lsttyp ge 2) ;Multi I/O board used? if multio ;Define Multi I/O environment mbase equ 48h ;Base address of Multi I/O or Decision I grpsel equ mbase+7 ;Group select port dll equ mbase ;Divisor (lsb) dlm equ mbase+1 ;Divisor (msb) ier equ mbase+1 ;Interupt enable register clk equ mbase+2 ;WB14 printer select port lcr equ mbase+3 ;Line control register mcr equ mbase+4 lsr equ mbase+5 ;Line status register msr equ mbase+6 rbr equ mbase ;Read data buffer thr equ mbase ;Tranmitter data buffer dlab equ 80h ;Divisor latch access bit thre its rlift equ 40h ;Ribbon lift pselect equ 80h ;Select (Not used by Diablo) ; Define Modem Control Register bits dtrenb equ 1 ;DTR enable rtsenb equ 2 ;RTS enable ; Define group select bits s0 equ 01h ;Group number (0-3) s1 equ 02h smask equ 03h bank equ 04h enint equ 08h restor equ 10h ;Printer restore on Multi I/O denable equ 20h ;Driver enable on Multi I/O ; Define special constants for the HyTyp II driver cperi equ 10 ;Default to 10 characters per inch lperi equ 6 ;Default lines per inch hinc equ 120 ;Horizontal increments per inch vinc equ 48 ;Vertical increments per inch numtabs equ 160 ;Number of horizontal tabs maxchrs equ 1024 ;Maximum number of printer characters to queue maxrgt equ 1584 ;Ma so the baud rate will be taken from DEFCON. * * * ************************************************************************* ************************************************************************* * * * Due to its length, the TTYSET routine driver is below the CBOOT * * CBOOT routine. * * * ************************************************************************* ***************************************************************** * * * Read a character from the serial port. * * * ***************************************************************** conin: call selcon equ 20h ;Status line THRE bit cts equ 10h ;Clear to send dsr equ 20h ;Data set ready dr equ 1 ;Line status DR bit wls0 equ 1 ;Word length select bit 0 wls1 equ 2 ;Word length select bit 1 for 8 bit word stb equ 4 ;Stop bit count - 2 stop bits ; Define multi I/O ports addresses for group zero gzero equ 0 daisy0 equ mbase ;Daisy input ports daisy1 equ mbase+1 sensesw equ mbase+1 ;Sense switches if multr3 eq 0 ;Daisy output ports are different daisi0 equ mbase ; for Decision I and Multi I/O. daisi1 equ mbase+1 ;These two are the Decision I ports else daisi0 equ mbase+1 ; and these are the Multi I/O's. daisi1 equ mbase endif ; Define daisy 0 status input bits ribbon equ 01h ;End of ribbon paper equ 02ximum carriage position dfrmln equ 110 ;Forms length times 10 autolf equ 0 ;Default to noIAuto line feed endif ***************************************************************** * * * CONTYP: 2 Multi I/O or Decision I console driver * * * ***************************************************************** if contyp eq 2 ************************************************************************* * * * This driver on cold boot will inspect bits 1-3 of the sense * * switches. If the value found is in the range 0-6 then the * * console baud rate will be taken from the rate table. Otherwise * * the baud rate will be set from the DEFCON word which is found * * just below the regular Cbios jump table.  ;Select console conin1: in lsr ;Read status register ani dr ;Wait till character ready jz conin1 in rbr ;Read character ani 7fh ;Strip parity ret ***************************************************************** * * * Output a character to serial port. * * * ***************************************************************** conout: call selcon ;Select console conout1:in lsr ;Read status ani thre ;Wait till transmitter buffer empty jz conout1 mov a,c ;Character is in (c) out thr ;Output to transmitter buffer ret ***************************************************************** *  ;For masking out parity ana m ret conist: lda serin+1 ;Pick up serial input status ora a rz ;If zero then no character ready mvi a,0ffh ;Set character ready ret endif ************************************************************************* * * * CONTYP: 5 Switchboard as serial console * * * ************************************************************************* if contyp eq 5 swbase equ 0 ;Base of the SWITCHBOARD conist: in swbase+2 ;Get the first ports status ani 4 ;Mask the data ready bits rz ;Return console not ready mvi a,0ffh ttyset: ret n cold boots only. * * 2 = give the command on warm boots only. * * 3 = give the command on warm and cold boots. * * * ***************************************************************** autost: db 0 ;Revision 0 structure db 100h - (low $) ;The rest of the page is used for this stuff autoflg:db 0 ;Auto command feature enable flag coldmes:dw coldcm ;Pointer to the cold start command warmes: dw warmcm ;Pointer to the warm start command ***************************************************************** * * * If there is a command inserted here, it will be passed to the * * CCP if the auto feature is enabled. For Example: * * * * coldcm: db colden * * Return serial port status. Returns zero if character is not * * ready to be read. Else returns 255 if ready. * * * ***************************************************************** conist: call selcon ;Select console in lsr ;Read status register ani dr rz ;No charactter ready mvi a,0ffh ;Character ready ret endif ;Multi I/O or Decision I ***************************************************************** * * * CONTYP: 3 2DB console driver * * * ***************************************************************** if contyp eq 3 conout: jmp fdcout ;Co ;NULL terminal initialization conin: in swbase+2 ;Get switchboard status ani 4 ;Test for data ready jz conin in swbase ;Get a character ani 7fh ;Strip off parity ret conout: in swbase+2 ;Check status ani 8 ;Wait till output buffer empty jz conout mov a,c ;Write a character out swbase ret endif ************************************************************************* * * * Multio/Wunderbuss group select routines * * * ************************************************************************* if (contyp eq 2) or (lsttyp ge 2) d-coldcm * * db 'MBASIC MYPROG' * * coldend equ $ * * * * will execute Microsoft BASIC, and MBASIC will execute the * * "MYPROG" BASIC program. Note: The command line must be in * * upper case for most commands. * * * ***************************************************************** coldcm: db coldend-coldcm ;Length of cold boot command db '' ;Cold boot command goes here coldend equ $ warmcm: db warmend-warmcm ;Length of warm boot command db '' ;Warm boot command goes here warmend equ $ ************************************************************************* * nsole output conin: jmp fdcin ;Console input conist: call fdtstat ;Console status mvi a,0ffh rz inr a ret endif ;2DB ***************************************************************** * * * CONTYP: 4 DJDMA console driver * * * ***************************************************************** if contyp eq 4 conout: lxi h,dmchan mvi m,serout ;Command for serial output inx h mov m,c jmp docmd conin: lxi h,serin+1 ;Serial input status xra a ci2: cmp m ;Wait till 40h deposited at 3fH jz ci2 mov m,a ;Clear status dcx h ;Point to input data mvi a,7fh  ;Need group select routines? selg0: lda group ;Select group zero out grpsel ret selcon: lda group ;Select console group ori congrp out grpsel ret selrdr: lda group ;Select reader/punch group ori 5-lstgrp ;Use 'other' serial port out grpsel ret sellst: lda group ;Select printer group ori lstgrp out grpsel ret endif ***************************************************************** * * * The following byte determines if an initial command is to be * * given to CP/M on warm or cold boots. The value of the byte is * * used to give the command to CP/M: * * * * 0 = never give command. * * 1 = give command o * * At the first page boundry following the CBIOS we have a series of * * pointers that point to various internal tables. At the start of * * each of these tables we have a revision byte and a length byte. * * The revision byte is the current revision number for that * * particular structure and the length byte is the length of that * * structure. This length does not include the revision byte nor * * the length byte itself. * * * * Revision Description * * E.0 1 and 2 defined * * E.3 This table is moved to a page boundry * * E.3 0, 3 and 4 defined * * * * The pointers defe configuration table pointer dw ioconf ;I/O configuration table pointer if (maxdm ne 0) or (maxmf ne 0) ;DJDMA present? dw dmarap ;Drive parameter table pointer else dw 0 endif dw autost ;Auto command structure pointer dw 0 ;End of table marker ************************************************************************* * * * The following code performs the mapping of logical to physical * * serial I/O devices. The physical entry points are CONIN, CONOUT, * * CONIST, RDRIN, PUNOUT, LSTOUT, and LSTOST. These entry points * * are mapped via the Intel standard I/O byte (IOBYTE) at location 3 * * in the base page to the low level device drivers. * * * * Note: A naming convention ints needed for * * each device handler. * * * * device setup input output input output * * name status status * * * * CON: CONIN CONOUT CONIST * * RDR: RDRIN RDRIST * * PUN: PUNOUT * * LST: LSTOUT LSTOST * * * * TTY: TTYSET TTYIN TTYOUT TTYIST TTYOST * * CRT: CRTSET CRTIN CRTOUT CRTIST CRTOST * * UC1: UC1SET UC1IN UC1OUT UC1IST * * ined so far are as follows: * * * * 0) High byte is the page number of the CBIOS. Low byte is * * the CBIOS revision number. Used to determine pointer * * structure. * * * * 1) This points to the drive configuration table. * * * * 2) This points to the I/O configuration bytes for the serial * * drivers. Eg, the console, printer, reader, and punch * * devices. * * * * 3) This points to the drive parameter table for DJDMA floppy * * disk drives. If no DJDMA is present then this pointer is has been chosen to reduce label * * colisions. The first three characters of a name indicate the * * device drivers name, the following three characters indicated the * * function performed by that particular device routine. The device * * names are defined and described in the "An Introduction to CP/M * * Features and Facilities" manual in the section on the STAT * * command and in the "CP/M Interface Guide" in the IOBYTE section. * * The device function postfixes are as follows. * * * * devSET Initial device setup and initialzation * * devIN Read one character from the device * * devOUT Write one character to the device * * devIST Return the device character input ready status * * devOST Return the device character output ready status * *  * * PTR: PTRSET PTRIN PTRIST * * UR1: UR1SET UR1IN UR1IST * * UR2: UR2SET UR2IN UR2IST * * * * PTP: PTPSET PTPOUT * * UP1: UP1SET UP1OUT * * UP2: UP2SET UP2OUT * * * * LPT: LPTSET LPTOUT LPTOST * * UL1: UL1SET UL1OUT UL1OST * * * * The CONIN, CONOUT, CONIST, RDRIN, RDRIST, PUNOUT, LSTOUT, and * * LSTOST routines are the logical device driver entry points *  * * null (0). * * * * 4) This points to the autostart command structures. Used to * * automatically invoke a command on cold or warm boot * * * * 5) This will be a null (0) pointer. It marks the end of the * * table. * * * ************************************************************************* if $ gt bios+256 ;Test for code overlap 'Fatal error, pointer table placement.' else ds bios+256-$ ;Start at a page boundry endif db high ($-1) ;CBIOS page number db revnum ;Cbios revision number dw drconf ;Driv * * The setup routine initializes the device and returns. The input * * routine returns one character in the A register (parity reset). * * The output routine write one character from the C register. The * * input status routine returns in the A register a 0 if the device * * does not have a character ready for input for 0ffh if a character * * is ready for input. The output status routine returns in the A * * register a 0 if the device is not ready accept a character and a * * 0ffh if the device is ready. The input and output routines * * should wait untill the device is ready for the desired operation * * before the doing the operation and returning. * * * * Not all of these functions need to be implemented for all the * * devices. The following is a table of the entry po* provided by this device mapper. The other entry names must be * * provided by the physical device drivers. * * * ************************************************************************* if contyp eq 6 ;I/O byte implemented for North Star ; drivers. Other drivers to follow conin: mvi e,1 ;Console input call redir ; IOBYTE: 76543210 dw ttyin ;CON: = TTY: xxxxxx00 dw crtin ;CON: = CRT: xxxxxx01 dw rdrin ;CON: = BAT: xxxxxx10 dw uc1in ;CON: = UC1: xxxxxx11 conout: mvi e,1 ;Console output call redir ; IOBYTE: 76543210 dw ttyout ;CON: = TTY:out ;LST: = LPT: 10xxxxxx dw ul1out ;LST: = UL1: 11xxxxxx lstost: mvi e,3 ;List output status call redir ; IOBYTE: 76543210 dw ttyost ;LST: = TTY: 00xxxxxx dw crtost ;LST: = CRT: 01xxxxxx dw lptost ;LST: = LPT: 10xxxxxx dw ul1ost ;LST: = UL1: 11xxxxxx redir: lda iobyte ;Get the INTEL standard iobyte redir0: rlc ;Shift the next field in dcr e ;Bump the shift count jnz redir0 redir1: ani 110b ;Mask the redirection field mov e,a ;Make the word table offset mvi d,0 pop h ;Get the table base dad d ;Offset into our table lements the North Star console I/O system. * * This system is for users who purchase a Morrow Designs disk * * system to replace their North Star disk system. The Mapping of * * the logical to physical entry points is performed as follows: * * * * Device name Left Right Parallel * * serial serial port * * * * Console CON: = TTY: CRT: UC1: * * Reader RDR: = TTY: PTR: UR1: * * Punch PUN: = TTY: PTP: UP1: * * List LST: = TTY: CRT: UL1: * * * * For example, to use a printer connected to the right serial port, * xxxxxx00 dw crtout ;CON: = CRT: xxxxxx01 dw lstout ;CON: = BAT: xxxxxx10 dw uc1out ;CON: = UC1: xxxxxx11 conist: mvi e,1 ;Console input status call redir ; IOBYTE: 76543210 dw ttyist ;CON: = TTY: xxxxxx00 dw crtist ;CON: = CRT: xxxxxx01 dw rdrist ;CON: = BAT: xxxxxx10 dw uc1ist ;CON: = UC1: xxxxxx11 rdrin: mvi e,7 ;Reader input call redir ; IOBYTE: 76543210 dw ttyin ;RDR: = TTY: xxxx00xx dw ptrin ;RDR: = PTR: xxxx01xx dw ur1in ;RDR: = UR1: xxxx10xx dw ur2in ;RDR: = UR2: xxxx11xx rdrist: mvi e,7  mov a,m ;Load the low level i/o routine pointer inx h mov h,m mov l,a pchl ;Execute the low level i/o driver endif ;IOBYTE redirector ************************************************************************* * * * CONTYP: 1 Blank space for console driver * * * * The driver entries CONOUT, CONIN, CONIST are defined in the CP/M * * alternation guide. Eg. Input parameters are in register C and * * results are returned in register A. The TTYSET routine is used * * for initialization code. It should execute a RET when complete. * * * * The TTYSET routine could be placed just below the CBOOT routine. * * use the CP/M command: * * * * STAT LST:=CRT: * * * * Likewise, the CP/M command "STAT LST:=UL1:" is used if you have a * * printer connected to the parallel port. * * * ************************************************************************* if contyp eq 6 ;Use North Star I/O? nsldat equ 2 ;Left serial port data port nslsta equ 3 ;Left serial port status port nsrdat equ 4 ;Right serial port data port nsrsta equ 5 ;Right serial port status port nsstbe equ 1 ;Transmitter buffer empty stat ;Reader input status call redir ; IOBYTE: 76543210 dw ttyist ;RDR: = TTY: xxxx00xx dw ptrist ;RDR: = PTR: xxxx01xx dw ur1ist ;RDR: = UR1: xxxx10xx dw ur2ist ;RDR: = UR2: xxxx11xx punout: mvi e,5 ;Punch output call redir ; IOBYTE: 76543210 dw ttyout ;PUN: = TTY: xx00xxxx dw ptpout ;PUN: = PTP: xx01xxxx dw up1out ;PUN: = UP1: xx10xxxx dw up2out ;PUN: = UP2: xx11xxxx lstout: mvi e,3 ;List output call redir ; IOBYTE: 76543210 dw ttyout ;LST: = TTY: 00xxxxxx dw crtout ;LST: = CRT: 01xxxxxx dw lpt * This space (below CBOOT) is recyled for use as a disk buffer * * after CBOOT is done. * * * ************************************************************************* if contyp eq 1 ;User defined IO area ttyset equ $ ;Console initialization conout equ $ ;Console output conin equ $ ;Console input conist equ $ ;Console input status jmp $ ds 125 endif ;User IO ************************************************************************* * * * CONYTP: 6 North Star * * * * The following code impus bit nssrbr equ 2 ;Reciever buffer ready status bit ;See the 8251 data sheets for more ; configuration information. nslin1 equ 0ceh ;Left serial port initialization # 1 nsrin1 equ 0ceh ;Right serial port initialization # 1 ;76543210 Bit definations ;11001110 Default configuration ;xxxxxx00 Synchronous mode ;xxxxxx01 1X clock rate ;xxxxxx10 16X clock rate ;xxxxxx11 64X clock rate ;xxxx00xx 5 bit characters ;xxxx01xx 6 bit characters ;xxxx10xx 7 bit characters l port routines. Use TTY: device. * * * ************************************************************************* ttyin: ;Read a character in nslsta ani nssrbr jz ttyin ;Wait till a character is ready in nsldat ;Get the character ani 7fh ;Strip parity ret ttyout: ;Write a character in nslsta ani nsstbe jz ttyout ;Wait till the buffer is empty mov a,c ;Write the character out nsldat ret ttyist: ;Return input buffer status in nslsta ani nssrbr rz ;Return not ready mvi a,0ffh ret :, * * and UL1: devices. * * * ************************************************************************* uc1in: ;Read a character ur1in: ur2in: in nspsta ani nsprbr jz uc1in ;Wait till a character is ready in nspdat ;Get the character push psw mvi a,30h ;Reset the parallel input flag out nspsta pop psw ani 7fh ;Strip parity ret uc1out: ;Write a character up1out: up2out: lptout: ul1out: in nspsta ani nsptbe jz uc1out ;Wait till the buffer is empty mvi a,20h ;Reset the parallel output flag out nspsta m ;xxxx11xx 8 bit characters ;xxx0xxxx Parity disbable ;xxx1xxxx Parity enable ;xx0xxxxx Odd parity generation/check ;xx1xxxxx Even parity generation/check ;00xxxxxx Invalid ;01xxxxxx 1 stop bit ;10xxxxxx 1.5 stop bits ;11xxxxxx 2 stop bits nslin2 equ 37h ;Left serial port initialization # 2 nsrin2 equ 37h ;Right serial port initialization # 2 ;76543210 Bit definations ;00110111 Default configuration ;xxxxxxx1 Enable transmitter ;xxxxxx1x Assert DTR*  ;There is a character ready ttyost: ;Return output buffer status in nslsta ani nsstbe rz ;Return not ready mvi a,0ffh ret ;Return ready ************************************************************************* * * * Right serial port routines. Use CRT:, PTR:, and PTP: devices. * * * ************************************************************************* crtin: ;Read a character ptrin: in nsrsta ani nssrbr jz crtin ;Wait till a character is ready in nsrdat ;Get the character ani 7fh ;Strip parity ret crtout: ov a,c ;Write the character, strobe bit 7 nspout: ori 80h out nspdat ani 7fh out nspdat ori 80H out nspdat ret uc1ist: ;Return input buffer status ur1ist: ur2ist: in nspsta ani nsprbr rz ;Return not ready mvi a,0ffh ret ;Return ready lptost: ;Return output buffer status ul1ost: in nspsta ani nsptbe rz ;Return not ready mvi a,0ffh ret ;Return ready endif ;North Star I/O configuration ************************************************************************* * * * LST: device driver routines.  ;xxxxx1xx Enable reciever ;xxxx1xxx Send break character, TxD low ;xxx1xxxx Reset PE, OE, FE error flags ;xx1xxxxx Assert RTS* ;x1xxxxxx Internal reset ;1xxxxxxx Enter hunt mode (for sync) nspdat equ 0 ;Parallel data port nspsta equ 6 ;Parallel status port nsprbr equ 1 ;Reciever buffer ready status bit nsptbe equ 2 ;Transmitter buffer empty status bit nsram equ 0c0h ;North Star memory parity port, ; set to 0 for no North Star RAM ************************************************************************* * * * Left seria ;Write a character ptpout: in nsrsta ani nsstbe jz crtout ;Wait till the buffer is empty mov a,c ;Write the character out nsrdat ret crtist: ;Return input buffer status ptrist: in nsrsta ani nssrbr rz ;Return not ready mvi a,0ffh ret ;There is a character ready crtost: ;Return output buffer status in nsrsta ani nsstbe rz ;Return not ready mvi a,0ffh ret ;Return ready ************************************************************************* * * * Parallel port routines. Use UC1:, UR1:, UR2:, UP1:, UP2:, LPT * * * * Routine used depends on the value of lsttyp. Possible LSTTYP * * values are listed as follows: * * * * LSTTYP is: 0 Nothing, used for patching to PROM's * * 1 Provide for 128 bytes of patch space * * 2 Multio serial, no protocol * * 3 Multio serial, Clear To Send protocol * * 4 Multio serial, Data Set Ready protocol * * 5 Multio serial, Xon/Xoff protocol * * * ************************************************************************* ************************************************************************* *  ;Return busy if buffer is not empty lhld lstand ;Fetch handshake mask bits in msr ;Get MODEM Status Register ana l ;Strip out hand-shake lines xra h ;Invert status rz ;Return busy if printer is busy lda lastch ;Get last character recieved from the printer mov b,a in lsr ;Check for a character from the printer ani dr jz xskip ;Skip if no character present in rbr ;Get the character ani 7fh ;Strip parity sta lastch ;Save last character recieved mov b,a xskip: mov a,b sui xoff ;Check for Xoff char (control S) jnz xsdone ;Printer ready ret ;Printer not ready (return zero) xsdone: mvi a,0ffh ;Printer rbot: rar lda cdisk ;Jump to CP/M with currently selected disk in C mov c,a jc ccp ;Enter CP/M, send message jmp ccp+3 ;Enter CP/M, no message cwflg: db 0 ;Cold/warm boot flag ***************************************************************** * * * WBOOT loads in all of CP/M except the CBIOS, then initializes * * system parameters as in cold boot. See the Cold Boot Loader * * listing for exactly what happens during warm and cold boots. * * * ***************************************************************** wboot: lxi sp,tpa ;Set up stack pointer mvi a,1 sta cwflg ;Set cold/warm boot flag mvi h,wmdrive ;Move drive to warm boot off of into (h) mvi l,d$wboot ;Peform warm boot operati * * lsttyp: 1 Blank space for printer driver * * * * The driver entries LSTOUT and LSTOST are defined in the CP/M * * alternation guide. Eg. Input parameters are in register C and * * results are returned in register A. The LSTSET routine is used * * for initialization code. It should execute a RET when complete. * * * * The LSTSET routine could be placed just below the CBOOT routine. * * This space (below CBOOT) is recyled for use as a disk buffer * * after CBOOT is done. * * * ************************************************************************* if lsttyp eq 1 lstset equ $ eady for data ret endif ;Multi I/O serial driver ***************************************************************** * * * Gocpm is the entry point from cold boots, and warm boots. It * * initializes some of the locations in page 0, and sets up the * * initial DMA address (80h). * * * ***************************************************************** gocpm: lxi h,buff ;Set up initial DMA address call setdma mvi a,(jmp) ;Initialize jump to warm boot sta wbot sta entry ;Initialize jump to BDOS lxi h,wboote ;Set up low memory entry to CBIOS warm boot shld wbot+1 lxi h,bdos+6 ;Set up low memory entry to BDOS shld entry+1 xra a ;A <- 0 on call jumper jnc gocpm ;No error hlt ;Halt computer db 0 jmp wboot ;In case user restarts the computer ***************************************************************** * * * Setsec just saves the desired sector to seek to until an * * actual read or write is attempted. * * * ***************************************************************** setsec: mov h,b ;Enter with sector number in (bc) mov l,c shld cpmsec donop: ret ***************************************************************** * * * Setdma saves the DMA address for the data transfer. * * * ************ ;Printer initialization lstout equ $ ;Printer output lstost equ $ ;Printer output status ret ds 127 endif ;User IO ***************************************************************** * * * lsttyp: 2, 3, 4, or 5 Serial printer, multi protocol * * * ***************************************************************** if (lsttyp ge 2) and (lsttyp le 5) lstout: call lstost ;Check printer status ora a jz lstout ;Loop if not ready mov a,c ;Print the character out thr ret lstost: call sellst ;Printer status routine in lsr ;Check if transmitter buffer empty ani thre rz  sta bufsec ;Set buffer to unknown state sta bufwrtn ;Set buffer not dirty flag sta error ;Clear buffer error flag lda cwflg ;Get cold/warm boot flag ora a lxi h,coldmes ;Pointer to initial cold command jz cldcmnd lxi h,warmes ;Pointer to initial warm command cldcmnd:mov e,m ;Do one level of indirection inx h mov d,m ldax d ;Get command length inr a ;Bump length to include length byte itself lxi h,ccp+7 ;Command buffer (includes length byte) mov c,a ;Set up for block move mvi b,0 call movbyt ;Move command to internal CCP buffer lda cwflg ;Figure out whether or not to send message ora a lda autoflg jz cldbot rar cld***************************************************** setdma: mov h,b ;Enter with DMA address in (bc) mov l,c shld cpmdma ;CP/M dma address ret ***************************************************************** * * * Home is translated into a seek to track zero. * * * ***************************************************************** home: lda bufwrtn ;Test buffer dirty flag ora a jnz dohome ;Skip buffer disable if buffer dirty xra a ;Invalidate buffer on home call sta bufsec dohome: lxi b,0 ;Track to seek to ***************************************************************** * * * Settrk saves the track # to seek to. Nothing is done a h,c ;Move logical drive into (h) mvi l,d$sel1 call jumper ;Call low level drive select mov a,h ;Check if the low level drive select returned ora l ; zero to indicate an error jz zret ;Yes, an error so report to CP/M push h ;Save DPH address call gdph ;Get entry if DPH save table pop d ;DPH -> (de) mov m,e ;Put address of DPH in table inx h mov m,d inx h mov m,c ;Put sector size in table inx h mov a,m ;Check if bad map has ever been read for this ora a ; drive cz getbad ;Never been read so read in bad map xchg ;DPH -> (hl) setd0: mov a,c ;Move sector size code into (a) sta se * ***************************************************************** dphtab: rept maxlog*4 db 0 endm ***************************************************************** * * * Getbad - Check if a device has a bad map. If the device has * * a bad sector map then append bad entries to end of badmap * * table. * * * ***************************************************************** getbad: mvi m,1 ;Set drive initilized push b push d lda cpmdrv ;Pick up current drive mov h,a ;Call drive routine to return a pointer to mvi l,d$bad ;the track and sector of the bad map call jumper mov a,h ;If routine returns 0t this * * point, everything is deffered until a read or write. * * * ***************************************************************** settrk: mov h,b ;Enter with track number in (bc) mov l,c shld cpmtrk ret ***************************************************************** * * * Sectran translates a logical sector number into a physical * * sector number. * * * ***************************************************************** sectran:lda cpmdrv ;Get the Drive Number mov h,a ;Drive in (h) mvi l,d$stran jmp jumper ;See device level sector translation routines ***************************************************************** * csiz ;Save sector size xra a setd1: dcr c ;Create number of (128 bytes/physical sector)-1 jz setd2 rlc ori 1 jmp setd1 setd2: sta secpsec ;Save for deblocking lda cpmdrv ;Save current drive as old drive sta lastdrv ; in case of select errors ret setd3: push d ;Save DPH address mov h,c ;Drive in (h) mvi l,d$sel2 ;Select drive call jumper call gdph ;Quick select pop d mov e,m ;DPH -> (de) inx h mov d,m inx h mov c,m ;Sector size -> (c) xchg ;DPH -> (hl) jmp setd0 gdph: lda cpmdrv ;Return pointer to DPH save area rlc ;Each entry is 4 bytes long rlc mov  then the device has ora l ; no bad sector map jz badret mov e,m ;Pick up track number of bad sector map -> (de) inx h mov d,m inx h xchg shld cpmtrk xchg mov a,m ;Pick up sector number of of bad sector map inx h mov h,m mov l,a shld truesec call fill ;Read in bad sector map into the buffer rc lhld badptr ;Pick up bad map pointer lxi d,buffer ;Start at beginning of buffer badl: ldax d ;Pick up an entry from the buffer ora a jz bade ;All done mov a,m ;Pick up entry from bad map table inr a jz overflo ;Bad map overflow lda cpmdrv ;Put drive in table mov m,a inx h  * * Setdrv selects the next drive to be used in read/write * * operations. If the drive has never been selected it calls * * a low level drive select routine that should perform some * * sort of check if the device is working. If not working then * * it should report an error. If the logical drive has been * * selected before then setdrv just returns the DPH without * * checking the drive. * * * ***************************************************************** setdrv: mov a,c ;Save the logical drive number sta cpmdrv cpi maxlog ;Check for a valid drive number jnc zret ;Illegal drive mov a,e ;Check if bit 0 of (e) = 1 ani 1 jnz setd3 ;Drive has allready been accessed mov  e,a mvi d,0 lxi h,dphtab ;DPH save area table dad d ;Add offset ret ;(hl) = DPH save area for current drive zret: lxi h,0 ;Seldrv error exit lda lastdrv ;Get last selected drive mov c,a lda cdisk ;Pick up user/drive ani 0f0h ;Save user number ora c ;Put together with old drive sta cdisk ret ***************************************************************** * * * DPH save area. Each entry is 4 bytes long: * * 0 - LSB of DPH address * * 1 - MSB of DPH address * * 2 - Sector size code (1 = 128, 2 = 256, 3 = 512... * * 3 - Bad map has been initilized (0 = Uninitilized) * *  lxi b,8 call movbyt ;Move the rest of information into the table jmp badl bade: shld badptr ;Restore new bad map pointer badret: pop d pop b ret overflo:lxi h,omes call message jmp badret omes: db 0dh, 0ah, 'BAD MAP OVERFLOW!', 0dh, 0ah, 0 nobad: lxi h,0 ;Used by device drives to indicate no bad ret ; sector map badptr: dw badmap ;Pointer to next available bad map entry ***************************************************************** * * * Write routine moves data from memory into the buffer. If the * * desired CP/M sector is not contained in the disk buffer, the * * buffer is first flushed to the disk if it has ever been * * written into, then a read is performed into the buffer to get * * the desired sector. Once the correct sector is  ;The 0 is modified to contain the log2 secsiz equ $-1 ; of the physical sector size/128 ; on the currently selected disk lhld cpmsec ;Get the desired CP/M sector # mov a,h ani 80h ;Save only the side bit mov c,a ;Remember the side mov a,h ani 7fh ;Forget the side bit mov h,a dcx h ;Temporary adjustment divloop:dcr b ;Update repeat count jz divdone ora a mov a,h rar mov h,a mov a,l rar ;Divide the CP/M sector # by the size ; of the physical sectors mov l,a jmp divloop ; divdone:inx h mov a,h ora c ;Restore the side bit mov h,a shl buffer dad h dad h dad h dad h dad h dad h lxi d,buffer ;Beginning address of buffer dad d ;Form beginning address of sectgr to transfer xchg ;DE = address in buffer lxi h,0 ;Get DMA address, the 0 is modified t/ ; contain the DMA address cpmdma equ $-2 mvi a,0 ;The zero gets modified to contain ; a zero if a read, or a 1 if write rdwr equ $-1 ana a ;Test which kind of operation jnz into ;Transfer data into the buffer outof: call mov128 lda error ;Get the buffer error flag ret into: xchg ; call mov128 ;Move the data, HL = destination ; DE = source in memory, the * * buffer written indicator is set, so the buffer will be * * flushed, then the data is transferred into the buffer. * * * ***************************************************************** write: mov a,c ;Save write command type sta writtyp mvi a,1 ;Set write command jmp rwent ***************************************************************** * * * Read routine to buffer data from the disk. If the sector * * requested from CP/M is in the buffer, then the data is simply * * transferred from the buffer to the desired dma address. If * * the buffer does not contain the desired sector, the buffer is * * flushed to the disk if it has ever been written into, then * * filled with the sector from the disk that contains the * * desired CP/M sector. d truesec ;Save the physical sector number lxi h,cpmdrv ;Pointer to desired drive,track, and sector lxi d,bufdrv ;Pointer to buffer drive,track, and sector mvi b,6 ;Count loop dtslop: dcr b ;Test if done with compare jz move ;Yes, match. Go move the data ldax d ;Get a byte to compare cmp m ;Test for match inx h ;Bump pointers to next data item inx d jz dtslop ;Match, continue testing ***************************************************************** * * * Drive, track, and sector don't match, flush the buffer if * * necessary and then refill. * * * *************************************************************** mvi a,1 sta bufwrtn ;Set buffer written into flag mvi a,0 ;Check for directory write writtyp equ $-1 dcr a ;Test for a directory write mvi a,0 rnz ;No error exit ***************************************************************** * * * Flush writes the contents of the buffer out to the disk if * * it has ever been written into. * * * ***************************************************************** flush: mvi a,0 ;The 0 is modified to reflect if ; the buffer has been written into bufwrtn equ $-1 ora a ;Test if written into rz ;Not written, all done mvi a,d$write sta rwop+1  * * * ***************************************************************** read: xra a ;Set the command type to read if nostand ne 0 sta unaloc ;Clear unallocated write flag endif rwent: sta rdwr ;Save command type ***************************************************************** * * * Redwrt calculates the physical sector on the disk that * * contains the desired CP/M sector, then checks if it is the * * sector currently in the buffer. If no match is made, the * * buffer is flushed if necessary and the correct sector read * * from the disk. * * * ***************************************************************** redwrt: mvi b,0 ** call fill ;Fill the buffer with correct physical sector rc ;No good, return with error indication ***************************************************************** * * * Move has been modified to cause either a transfer into or out * * the buffer. * * * ***************************************************************** move: lda cpmsec ;Get the CP/M sector to transfer dcr a ;Adjust to proper sector in buffer ani 0 ;Strip off high ordered bits secpsec equ $-1 ;The 0 is modified to represent the # of ; CP/M sectors per physical sectors mov l,a ;Put into HL mvi h,0 dad h ;Form offset into call prep ;Do the physical write sta error ;Set up the error flag ret ***************************************************************** * * * Prep prepares to read/write the disk. Retries are attempted. * * Upon entry, H&L must contain the read or write operation * * address. * * * ***************************************************************** prep: call alt ;Check for alternate sectors di ;Reset interrupts xra a ;Reset buffer written flag sta bufwrtn mvi b,retries ;Maximum number of retries to attempt retrylp:push b ;Save the retry count mvi l,d$sel2 ;Select drive call jumpbuf lhld alttrk  a jz fread ;Skip write type check if reading lda writtyp ;0 = alloc, 1 = dir, 2 = unalloc if nostand ne 0 ;Do non standard (but quick and dirty) check ora a jnz fnaloc ;Skip if not an allocated write lda unaloc ;Check unallocated write in progress flag ora a jz fwritin ;We are doing an allocated write lhld cblock ;Get current block address xchg lhld oblock ; and old block address mov a,d ;Compare old versus new cmp h jnz awritin ;Different, clear unallocated writting mode mov a,e cmp l jnz awritin lxi h,cpmdrv ;Test for different drive lda unadrv cmp m jnz awritin ;Drive is different, clear unallocated mode ret d mov l,a inx d ldax d mov h,a ;Get a DST pointer in (hl) inx d mov a,c ;Logical in (a) sub m ;Subtract from first entry in DST jnc jumpl ;Keep scanning table till correct driver found inx h ;Bump (hl) to point to start of dispatch table pop d ;Real (hl) -> (de) mov a,e ;Move offset number into (a) rlc ;Each entry is 2 bytes mov e,a ;Make an offset mvi d,0 dad d ;(hl) = **Routine mov a,m ;Pick up address of handler for selected inx h ; function mov h,m mov l,a ;(hl) = *routine mov a,c ;Logical in (a) pop b ;Restore saved registers pop d  ;Track number -> (hl) mov a,h ;Test for track zero ora l push h ;Save track number mvi l,d$home cz jumpbuf pop b ;Restore track # mvi l,d$strk call jumpbuf lhld altsec ;Sector -> (hl) mov b,h mov c,l mvi l,d$ssec call jumpbuf lxi b,buffer ;Set the DMA address mvi l,d$sdma call jumpbuf rwop: mvi l,0 ;Get operation address call jumpbuf pop b ;Restore the retry counter mvi a,0 ;No error exit status rnc ;Return no error dcr b ;Update the retry counter stc ;Assume retry count expired mvi a,0ffh ;Error return rz ;Return s ;Unallocated write, do nothing... fnaloc: dcr a jz awritin ;Do a directory write ;We are now doing an unallocated write lhld cblock ;Save current block number shld oblock lda cpmdrv ;Save drive that this block belongs to sta unadrv mvi a,1 ;Set unallocated write flag sta unaloc ret ; and we do nothing about the write awritin:xra a ;Clear unallocated writting mode sta unaloc else ;Do standard unallocated test sui 2 ;Test for an unallocated write rz endif fwritin:lda secsiz ;Check for 128 byte sectors dcr a rz ;No deblocking needed fread: mvi a,d$read sta rwop+1 call prep ;Read the physical sector the pchl ***************************************************************** * * * Check for alternate sectors in bad sector table. If an * * alternate sector is found replace alttrk and altsec with * * new sector number else pass along unaltered. * * * ***************************************************************** alt: lxi h,badmap ;Address of bad map -> (hl) lda bufdrv ;Pick up drive number currently working on mov c,a ;Move drive into (c) for speed in search all: xchg lhld badptr ;Get bad map pointer xchg ; -> (de) mov a,d ;Check if at end of bad map table cmp h jnz alt2 ;Still more mov a,e cmp l jnz alt2 ;Still moread news mov a,b cpi retries/2 jnz retrylp ;Try again push b ;Save retry count mvi l,d$home ;Home drive after (retries/2) errors call jumpbuf pop b jmp retrylp ;Try again ***************************************************************** * * * Fill fills the buffer with a new sector from the disk. * * * ***************************************************************** fill: call flush ;Flush buffer first rc ;Check for error lxi d,cpmdrv ;Update the drive, track, and sector lxi h,bufdrv lxi b,5 ;Number of bytes to move call movbyt ;Copy the data lda rdwr ;Test read write flag ora  buffer sta error ;Set the error status ret ***************************************************************** * * * Jumpbuf, jumper are used to dispatch to a low level device * * subroutine. Jumper is called with the drive in (h) and the * * routine number (see description above) in (l). It passes * * along the (bc) and (de) registers unaltered. Jumpbuf is * * a call to jumper with the drive number from bufdrv. * * * ***************************************************************** jumpbuf:lda bufdrv ;Dispatch with bufdrv for drive mov h,a jumper: push d push b push h mov a,h ;Logical drive into (a) lxi d,dsttab ;Drive specification pointer table jumpl: mov c,a ;Save logical in (c) ldax  lhld buftrk ;No alternate sector so use selected sector shld alttrk lhld bufsec shld altsec ret alt2: push h ;Save current bad map entry address mov a,c ;Move drive into (a) cmp m ;Check if drive in table matches jnz altmis ;Does not match skip this entry inx h ;Point to LSB of alternate track lda buftrk ;Pick up LSB of buffer track cmp m jnz altmis inx h ;Point to MSB alternate track lda buftrk+1 ;Pick up MSB of buffer track cmp m jnz altmis inx h ;Point to LSB of alternate sector lda bufsec ;Pick up LSB of buffer sector cmp m jnz altmis inx h ;Point to MSB of alternate sector lda bufsec+1  * * * ***************************************************************** retdph mov l,a ;Move logical drive into (l) mvi h,0 dad h ;Multiply by 16 (size of DPH) dad h dad h dad h dad d ;(hl) = pointer to DPH ret ***************************************************************** * * * Utility routine to output the message pointed at by (hl) * * terminated with a null. * * * ***************************************************************** message:mov a,m ;Get a character of the message inx h ;Bump text pointer ora a ;Test for end rz  equ 0 ;Initialize data buffer pointer rsect equ 1 ;Read sector wsect equ 5 ;Write sector isbuff equ 8 ;Initialize header buffer pointer ; Function port (52) pstep equ 04h ;Step bit nstep equ 0ffh-pstep ;Step bit mask null equ 0fch ;Null command ; Misc constants hdrlen equ 4 ;Sector header length seclen equ 512 ;Sector data length ***************************************************************** * * * Device Specification Table for HDCA controller driver * * * ***************************************************************** hddst: db maxhd*hdlog ;Number of logical drives dw hdwar ;Pick up MSB of buffer sector cmp m jnz altmis ;Found an alternate sector inx h ;Point to real info on the alternate sector lxi d,alttrk xchg ;MOVLOP (de) = source, (hl) = dest push b lxi b,4 call movbyt ;Move alternate sector info in correct place pop b pop h ret altmis: pop h ;Current alternate did not match lxi d,9 ;Bump pointer by the length of an entry dad d jmp all ;Loop for more ***************************************************************** * * * Mover moves 128 bytes of data. Source pointer in DE, Dest * * pointer in HL. * * * ********************** ;Return if done push h ;Save pointer to text mov c,a ;Output character in C call cout ;Output the character pop h ;Restore the pointer jmp message ;Continue until null reached ***************************************************************** * * * The following code is for the Diskus Hard disk * * * ***************************************************************** if hdca ne 0 ;Want HDC3 or 4 controller included ? hdorg equ 50h ;Hard Disk Controller origin hdstat equ hdorg ;Disk Status hdcntl equ hdorg ;Disk Control hdreslt equ hdorg+1 ;Disk Results hdcmnd equ hdorg+1 ;Disk Commands hdskomm ;Warm boot dw hdtran ;Sector translation dw hdldrv ;First time select dw hddrv ;General select dw hdhome ;Home current selected drive dw hdseek ;Seek to selected track dw hdsec ;Select sector dw hddma ;Set DMA address dw hdread ;Read a sector dw hdwrite ;Write a sector dw nobad ;No bad sector map hdwarm: call divlog ;Get physical drive number in (c) xra a lxi h,ccp-200h ;Initial DMA address push h sta head ;Select head zero inr a ; 1 -> (a) push psw ;Save first sector - 1 call hdd2 ;******************************************* mov128: lxi b,128 ;Length of transfer movbyt: xra a ;Check if host processor is a Z80 adi 3 jpo z80mov ;Yes, Its a Z80 so use block move m8080: ldax d ;Get a byte of source mov m,a ;Move it inx d ;Bump pointers inx h dcx b ;Update counter mov a,b ;Test for end ora c jnz m8080 ret z80mov: xchg ;Source in (hl), Destination in (de) dw 0b0edh ;ldir xchg ret ***************************************************************** * * * Return DPH pointer. Enter with (de) with DPH base address * * and (a) with logical drive number. Returns with DPH address * * in (hl). p equ hdorg+2 ;Seek complete clear port (on HDC4) hdfunc equ hdorg+2 ;Function port hddata equ hdorg+3 ;Data port ; Status port (50) tkzero equ 01h ;Track zero opdone equ 02h ;Operation done complt equ 04h ;Seek complete tmout equ 08h ;Time out wfault equ 10h ;Write fault drvrdy equ 20h ;Drive ready index equ 40h ;Delta index ; Control port (50) hdfren equ 01h ;Enable external drivers hdrun equ 02h ;Enable controllers state machine hdclok equ 04h ;Clock source control bit, high = disk hdwprt equ 08h ;Write protect a drive ; Result port (51) retry equ 02h ;Retry flag ; Command port (51) idbuffSelect drive mvi c,0 call hdhome ;Home the drive hdwrld: pop psw ;Restore sector pop h ;Restore DMA address inr a sta hdsect cpi 13 ;Past BDOS ? rz ;Yes, all done inr h ;Update DMA address inr h shld hdadd push h push psw hdwrrd: lxi b,retries*100h+0 ;Retry counter hdwr: push b ;Save the retry count call hdread ;Read the sector pop b jnc hdwrld ;Test for error dcr b ;Update the error count jnz hdwr ;Keep trying if not too many errors stc ;Error flag ret hdtran: mov h,b ;Sector transl mov a,l rar mov e,a dad d endif shld settle ;Save the count for timeout delay endif call hdhome hdl2: lda hdcur ;Load logical drive lxi d,dphhd0 ;Start of hard disk DPH's mvi c,3 ;Hard disk sector size equals 512 bytes jmp retdph dcrc: dcr c ;Conditional decrement C routine ret divlog: mvi c,0 divlx: sui hdlog rc inr c jmp divlx hddrv: sta hdcur call divlog ;Get the physical drive # hdd2: mov a,c sta hddisk ;Select the drive ori null out hdfunc mvi a,hdfren+hdrun+hdclok+hdwprt ;Write protect out hdcntl ret hdhome: call hdptr ;Get track pointer mvi ete to finish ani complt jz wsdone in hdskomp ;Clear sdone bit on an HDCA4 ret if m26 hdsec: mvi a,01fh ;For compatibility with Cbios revs. ; 2.3 and 2.4 ana c ;Mask in sector number (0-31) cz getspt ;Translate sector 0 to sector 32 sta hdsect ;Save translated sector number (1-32) mvi a,0e0h ;Get the head number ana c rlc rlc rlc sta head ;Save the head number getspt: mvi a,hdspt ret else hdsec: mov a,c call divspt adi hdspt ana a cz getspt sta hdsect mov a,c sta head getspt: mvi a,hdspt dcr c ret divspt: mvi c,0 dation is handled via mov l,c ; physical sector header skewwing inx h ret hdldrv: sta hdcur ;Save logical disk call divlog ;Divide by logical disks per drive mov a,c sta hddisk ;Save new physical drive call hdptr ;Get track pointers mov a,m ;Get current track inr a ;Check if -1 jnz hdl2 ;Nope, allready accessed ori null ;Select drive out hdfunc mvi a,hdfren+hdclok ;Enable drivers out hdcntl mvi c,239 ;Wait 2 minutes for disk ready lxi h,0 hdtdel: dcx h mov a,h ora l cz dcrc jz zret ;Drive not ready error in hdstat  m,0 ;Set track to zero in hdstat ;Test status ani tkzero ;At track zero ? rz ;Yes if not fujitsu hdstepo:in hdstat ;Test status ani tkzero ;At track zero ? jz hddelay mvi a,1 stc call accok ;Take one step out jmp hdstepo else xra a jmp accok endif if not fujitsu hddelay:lhld settle ;Get hddelay deloop: dcx h ;Wait 20ms mov a,h ora l inx h dcx h jnz deloop ret endif hdseek: call hdptr ;Get pointer to current track mov e,m ;Get current track mov m,c ;Update the trackivsx: sui hdspt rc inr c jmp divsx endif hdread: call hdprep rc xra a out hdcmnd cma out hddata out hddata mvi a,rsect ;Read sector command out hdcmnd call process rc xra a out hdcmnd mvi b,seclen/4 lhld hdadd in hddata in hddata rtloop: in hddata ;Move four bytes mov m,a inx h in hddata mov m,a inx h in hddata mov m,a inx h in hddata mov m,a inx h dcr b jnz rtloop ret hdwrite:call hdprep ;Prepare header rc xra a out hdcmnd lhld hdadd mvi b,seclen/4 wtloop: mov  ;Test if ready yet ani drvrdy jnz hdtdel if not fujitsu lxi h,0 ;Time one revolution of the drive mvi c,index in hdstat ana c mov b,a ;Save current index level in B hdinxd1:in hdstat ana c cmp b ;Loop untill index level changes jz hdinxd1 hdindx2:inx h in hdstat ;Start counting untill index returns to ana c ; previous state cmp b jnz hdindx2 if m10 ;Memorex M10's have 40 ms head settle dad h ;HL*2 endif if m26 ;Shugart M26's have 30 ms head settle xra a ;HL/2 + HL (same as HL*1.5) mov a,h rar mov d,a  mov a,e ;Need to seek at all ? sub c rz cmc ;Get carry into direction jc hdtrk2 cma inr a if fujitsu hdtrk2: jmp accok else hdtrk2: call accok jmp hddelay endif accok: mov b,a ;Prep for build call build sloop: ani nstep ;Get step pulse low out hdfunc ;Output low step line ori pstep ;Set step line high out hdfunc ;Output high step line dcr b ;Update repeat count jnz sloop ;Keep going the required # of tracks jmp wsdone hddma: mov h,b ;Save the DMA address mov l,c shld hdadd ret wsdone: in hdstat ;Wait for seek compl a,m ;Move 4 bytes out hddata inx h mov a,m out hddata inx h mov a,m out hddata inx h mov a,m out hddata inx h dcr b jnz wtloop mvi a,wsect ;Issue write sector command out hdcmnd call process rc mvi a,wfault ana b stc rz xra a ret process:in hdstat ;Wait for command to finish mov b,a ani opdone jz process mvi a,hdfren+hdrun+hdclok ;Write protect out hdcntl in hdstat ani tmout ;Timed out ? stc rnz in hdreslt ani retry ;Any retries ? stc rnz xra a ret hdprep:  * * The following equates relate the Morrow Designs 2D/B * * controller. If the controller is non standard (0F800H) * * only the FDORIG equate need be changed. * * * ***************************************************************** if maxfd ne 0 ;Include Discus 2D ? fdorig equ 0e000h ;Origin of Disk Jockey PROM fdboot equ fdorig+00h ;Disk Jockey 2D initialization fdcin equ fdorig+03h ;Disk Jockey 2D character input routine fdcout equ fdorig+06h ;Disk Jockey 2D character output routine fdhome equ fdorig+09h ;Disk Jockey 2D track zero seek fdseek equ fdorig+0ch ;Disk Jockey 2D track seek routine fdsec equ fdorig+0fh ;Disk Jockey 2D set sector routine fddma equ fdorig+12h ;Disk Jockey 2D set DMA address fdread equ fdorig+15h ;Disk Jockey 2D read ro ;Select drive A mvi c,0 ;Select side 0 call fdside wrmfail:call fdhome ;Track 0, single density jc wrmfail ;Loop if error ;The next block of code re-initializes ; the warm boot loader for track 0 mvi a,5-2 ;Initialize the sector to read - 2 sta newsec lxi h,ccp-100h ;First revolution DMA - 100h shld newdma ;Load all of track 0 t0boot: mvi a,5-2 ;First sector - 2 newsec equ $-1 inr a ;Update sector # inr a cpi 27 ;Size of track in sectors + 1 jc nowrap ;Skip if not at end of track jnz t1boot ;Done with this track sui 27-6 ;Back up to sector 6 lxi h,ccp-80h ;Memory address of sector - 100h in hdstat ani drvrdy stc rnz mvi a,isbuff ;Initialize pointer out hdcmnd call build ori 0ch out hdfunc lda head out hddata ;Form head byte call hdptr ;Get pointer to current drives track mov a,m ;Form track byte out hddata ana a mvi b,80h jz zkey mvi b,0 zkey: lda hdsect ;Form sector byte out hddata mov a,b out hddata mvi a,hdfren+hdrun+hdclok ;Write protect out hdcntl mvi a,hdfren+hdrun+hdclok+hdwprt ;Write protect out hdcntl xra a ret hdptr: lhld hddisk ;Get a pointer to the current drives mvi h,0 ; track position xchg utine fdwrite equ fdorig+18h ;Disk Jockey 2D write routine fdsel equ fdorig+1bh ;Disk Jockey 2D select drive routine fdtstat equ fdorig+21h ;Disk Jockey 2D terminal status routine fdstat equ fdorig+27h ;Disk Jockey 2D status routine fderr equ fdorig+2ah ;Disk Jockey 2D error, flash led fdden equ fdorig+2dh ;Disk Jockey 2D set density routine fdside equ fdorig+30h ;Disk Jockey 2D set side routine fdram equ fdorig+400h ;Disk Jockey 2D RAM address dblsid equ 20h ;Side bit from controller io equ fdorig+3f8h ;Start of I/O registers dreg equ io+1 cmdreg equ io+4 clrcmd equ 0d0h ***************************************************************** * * * Device Specification Table for the Disk Jockey 2D/B * * * ********************************* shld newdma nowrap: sta newsec ;Save the updated sector # mov c,a call fdsec ;Set up the sector lxi h,ccp-100h ;Memory address of sector - 100h newdma equ $-2 lxi d,100h ;Update DMA address dad d nowrp: shld newdma ;Save the updated DMA address mov b,h mov c,l call fddma ;Set up the new DMA address lxi b,retries*100h+0;Maximum # of errors, track # wrmfred:push b call fdseek ;Set up the proper track call fdread ;Read the sector pop b jnc t0boot ;Continue if no error dcr b jnz wrmfred ;Keep trying if error jmp fderr ;Too many errors, flash the light ;Load track 1, sector 1, sector 3 (partial), sector 2 (1024 byte sectors) t1boot: mvi c,1 ;Track 1 call fdsee lxi h,hdtrak dad d ret build: lda head ;Build a controller command byte ral ral ral ral lxi h,hddisk ora m xri 0f0h ret hdcur: db 0 ;Current logical disk hdadd: dw 0 ;DMA address hddisk: db 0 ;Current physical disk number head: db 0 ;Current physical head number hdsect: db 0 ;Current physical sector number hdtrak: db 0ffh ;Track pointer for each drive db 0ffh ;All drive default to an uncalibrated db 0ffh ; state (ff) db 0ffh settle: dw 0 ;Time delay constant for head settle endif ***************************************************************** * ******************************** fddst: db maxfd ;Number of logical drives dw fdwarm ;Warm boot dw fdtran ;Sector translation dw fdldrv ;Select drive 1 dw fdsel2 ;Select drive 2 dw fdlhome ;Home drive dw fdseek ;Seek to specified track dw fdssec ;Set sector dw fddma ;Set DMA address dw fdread ;Read a sector dw fdwrite ;Write a sector dw nobad ;No bad sector map ***************************************************************** * * * Floppy disk warm boot loader * * * ***************************************************************** fdwarm: mov c,a call fdsel k lxi b,ccp+0b00h ;Address for sector 1 lxi d,10*100h+1 ;Retry count + sector 1 call wrmread lxi b,ccp+0f00h ;Address for sector 2 lxi d,10*100h+3 ;Retry count + sector 3 call wrmread lxi b,0300h ;Size of partial sector lxi d,ccp+1300h ;Address for sector 3 lxi h,ccp+0f00h ;Address of sector 3 wrmcpy: mov a,m ;Get a byte and stax d ; save it inx d ;Bump pointers inx h dcx b ;Bump counter mov a,b ;Check if done ora c jnz wrmcpy ; if not, loop lxi b,ccp+0f00h ;Address for sector 2 lxi d,10*100h+2 ;Retry count + sector 2 call wrmread xra a ;Clear error indicator ret wrmread:push d call fddma call sideone mvi a,80h ;Side two bit ora h ; and sector mov h,a ret fdldrv: sta fdlog ;Save logical drive mov c,a ;Save drive # mvi a,0 ;Have the floppies been accessed yet ? flopflg equ $-1 ana a jnz flopok mvi b,17 ;Floppies havn't been accessed lxi h,fdboot ;Check if 2D controller is installed mvi a,(jmp) clopp: cmp m ;Must have 17 jumps jnz zret inx h inx h inx h dcr b jnz clopp lxi d,fdinit ;Initialization sequence lxi h,fdorig+7e2h ;Load address lxi b,30 ;Byte count call movbyt ;Load controller RAM mvi a,0ffh ;Start 1791 sta dreg mvi a,clrcm dad b ;(hl) is now a DPB pointer xchg ;Put proper DPB address in DPH.DPB mov m,e inx h mov m,d lxi h,15 ;Offset to DPB.SIZ dad d mov c,m ;Fetch sector size code fdget: lda fdlog ;Return proper DPH lxi d,dphfd0 jmp retdph fdsel2: sta fdlog mov c,a jmp fdsel fdlhome:mvi c,0 ;Select side 0 call fdside jmp fdhome ;Do actual home fdssec: push b ;Save sector number mov a,b ;Check side select bit rlc ;Move high bit to bit zero ani 1 mov c,a call fdside ;Call select side 0 = side A, 1 = Side B pop b jmp fdsec fdgsid: lxi h,fdlsid ;Side flag table lda fdlog ;Driv ;Set DMA address pop b call fdsec ;Set sector wrmfrd: push b ;Save error count call fdread ;Read a sector jc wrmerr ;Do retry stuff on error call fdstat ;Sector size must be 1024 bytes ani 0ch ;Mask length bits sui 0ch ;Carry (error) will be set if < 0c0h wrmerr: pop b ;Fetch retry count rnc ;Return if no error dcr b ;Bump error count jnz wrmfrd jmp fderr ;Error, flash the light fdtran: inx b push d ;Save table address push b ;Save sector # call fdget ;Get DPH for current drive lxi d,10 ;Load DPH pointer dad d mov a,m inx h mov h,m mov l,a mov ad ;1791 reset sta cmdreg mvi a,1 ;Set 2D initialized flag sta flopflg flopok: call flush ;Flush buffer since we are using it lda fdlog ;Select new drive mov c,a call fdsel call fdlhome ;Recalibrate the drive lxi h,1 ;Select sector 1 of track 2 shld truesec inx h shld cpmtrk xra a ;Make sure we are doing a read sta rdwr call fill ;Fill in buffer with sector jc zret ;Test for error return call fdstat ;Get status on current drive sta fdldst ;Save drive status ani 0ch ;Mask in sector size bits push psw ;Used to select a DPB rar lxi h,xlts ;Table of XLT addresses mov e,a mvi d,0 e number push d mov e,a ;Make offset mvi d,0 dad d ;Offset to proper entry pop d mov a,m ;Set up flags ora a ret fdinit: dw 0 ;Initialization bytes loaded onto 2D/B dw 1800h ;Head loaded timeout dw 0 ;DMA address db 0 ;Double sided flag db 0 ;Read header flag db 07eh ;Drive select constant db 0 ;Drive number db 8 ;Current disk db 0 ;Head loaded flag db 9 ;Drive 0 parameters db 0ffh ;Drive 0 track address db 9 ;Drive 1 parameters db 0ffh ;Drive 1 track address db 9 ;Drive 2 parameters db 0ffh ,m ;Get # of CP/M sectors/track ora a ;Clear carry rar ;Divide by two sub c ;Subtract sector number push psw ;Save adjusted sector jm sidetwo sidea: pop psw ;Discard adjusted sector pop b ;Restore sector requested pop d ;Restore address of xlt table sideone:xchg ;hl <- &(translation table) dad b ;bc = offset into table mov l,m ;hl <- physical sector mvi h,0 ret sidetwo:call fdgsid ;Check out number of sides jz sidea ;Single sided pop psw ;Retrieve adjusted sector pop b cma ;Make sector request positive inr a mov c,a ;Make new sector the requested sector pop d  dad d push h ;Save pointer to proper XLT call fdget ;Get pointer to proper DPH pop d lxi b,2 ;Copy XLT pointer into DPH call movbyt lxi d,8 ;Offset to DPB pointer in DPH dad d ;HL <- &DPH.DPB push h call fdgsid ;Get pointer to side flag table entry lda fdldst ;Get drive status ani dblsid ;Check double sided bit mov m,a ;Save sides flag lxi d,dpb128s ;Base for single sided DPB's jz sideok lxi d,dpb128d ;Base of double sided DPB's sideok: xchg pop d ;(HL) -> DPB base, (DE) -> &DPH.DPB pop psw ;Offset to correct DPB ral ral ;Make 0, 10, 20, 30 mov c,a mvi b,0 ;Make offset  ;Drive 2 track address db 9 ;Drive 3 parameters db 0ffh ;Drive 3 track address db 9 ;Current parameters db 0 ;Side desired db 1 ;Sector desired db 0 ;Track desired db 0 ;Header image, track db 0 ;Sector db 0 ;Side db 0 ;Sector dw 0 ;CRC fdlog: db 0 fdldst: db 0 ;Floppy drive status byte fdlsid: rept maxfd db 0ffh ;Double sided flag 0 = single, 1 = double endm endif if (maxfd ne 0) or (maxdm ne 0) ***************************************************************** * * * Xlts is a table of address that point to each of the xlt * * tables fo 49,50,51,52,53,54,55,56 db 9,10,11,12,13,14,15,16 db 33,34,35,36,37,38,39,40 db 57,58,59,60,61,62,63,64 db 17,18,19,20,21,22,23,24 db 41,42,43,44,45,46,47,48 ***************************************************************** * * * Each of the following tables describes a diskette with the * * specified characteristics. * * * ***************************************************************** ***************************************************************** * * * The following DPB defines a diskette for 128 byte sectors, * * single density, and single sided. * * * ************************************************* dw 32 ;CKS dw 2 ;OFF db 3 ;512 byte sectors ***************************************************************** * * * The following DPB defines a diskette as 1024 byte sectors, * * double density, and single sided. * * * ***************************************************************** dp1024s:dw 64 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 0 ;EXM dw 299 ;DSM dw 127 ;DRM db 0c0h ;AL0 db 0 ;AL1 dw 32 ;CKS dw 2 ;OFF db 4 ;1024 byte sectors ***********************************************r each sector size. * * * ***************************************************************** xlts: dw xlt128 ;Xlt for 128 byte sectors dw xlt256 ;Xlt for 256 byte sectors dw xlt512 ;Xlt for 512 byte sectors dw xlt124 ;Xlt for 1024 byte sectors ***************************************************************** * * * Xlt tables (sector skew tables) for CP/M 2.0. These tables * * define the sector translation that occurs when mapping CP/M * * sectors to physical sectors on the disk. There is one skew * * table for each of the possible sector sizes. Currently the * * tables are located on track 0 sectors 6 and 8. They are * * loaded into memory in the Cbios ram by the cold boot routine. * * **************** dpb128s:dw 26 ;CP/M sectors/track db 3 ;BSH db 7 ;BLM db 0 ;EXM dw 242 ;DSM dw 63 ;DRM db 0c0h ;AL0 db 0 ;AL1 dw 16 ;CKS dw 2 ;OFF db 1 ;128 byte sectors ***************************************************************** * * * The following DPB defines a diskette for 256 byte sectors, * * double density, and single sided. * * * ***************************************************************** dpb256s:dw 52 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 1 ****************** * * * The following DPB defines a diskette for 128 byte sectors, * * single density, and double sided. * * * ***************************************************************** dpb128d:dw 52 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 1 ;EXM dw 242 ;DSM dw 127 ;DRM db 0c0h ;AL0 db 0 ;AL1 dw 32 ;CKS dw 2 ;OFF db 1 ;128 byte sectors ***************************************************************** * * * The following DPB defines a diskette as 256 byte sectors, * * double density,  * ***************************************************************** xlt128: db 0 db 1,7,13,19,25 db 5,11,17,23 db 3,9,15,21 db 2,8,14,20,26 db 6,12,18,24 db 4,10,16,22 xlt256: db 0 db 1,2,19,20,37,38 db 3,4,21,22,39,40 db 5,6,23,24,41,42 db 7,8,25,26,43,44 db 9,10,27,28,45,46 db 11,12,29,30,47,48 db 13,14,31,32,49,50 db 15,16,33,34,51,52 db 17,18,35,36 xlt512: db 0 db 1,2,3,4,17,18,19,20 db 33,34,35,36,49,50,51,52 db 5,6,7,8,21,22,23,24 db 37,38,39,40,53,54,55,56 db 9,10,11,12,25,26,27,28 db 41,42,43,44,57,58,59,60 db 13,14,15,16,29,30,31,32 db 45,46,47,48 xlt124: db 0 db 1,2,3,4,5,6,7,8 db 25,26,27,28,29,30,31,32 db  ;EXM dw 242 ;DSM dw 127 ;DRM db 0c0h ;AL0 db 0 ;AL1 dw 32 ;CKS dw 2 ;OFF db 2 ;256 byte sectors ***************************************************************** * * * The following DPB defines a diskette as 512 byte sectors, * * double density, and single sided. * * * ***************************************************************** dpb512s:dw 60 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 0 ;EXM dw 280 ;DSM dw 127 ;DRM db 0c0h ;AL0 db 0 ;AL1 and double sided. * * * ***************************************************************** dpb256d:dw 104 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 0 ;EXM dw 486 ;DSM dw 255 ;DRM db 0f0h ;AL0 db 0 ;AL1 dw 64 ;CKS dw 2 ;OFF db 2 ;256 byte sectors ***************************************************************** * * * The following DPB defines a diskette as 512 byte sectors, * * double density, and double sided. * * * ********************************************************ve status dmsdma equ 23h ;Set DMA address intrqc equ 24h ;Set Interrupt request dmhaltc equ 25h ;Halt command bracha equ 26h ;Channel branch setcha equ 27h ;Set channel address setcrc equ 28h ;Set CRC retry count rdtrck equ 29h ;Read track command wrtrck equ 2ah ;Write track command serout equ 2bh ;Serial ouput through bit banger serial port senabl equ 2ch ;Enable serial input trksiz equ 2dh ;Set number of tracks setlog equ 2eh ;Set logical drives readm equ 0a0h ;Read from controller memory writem equ 0a1h ;Write to controller memory dmfstp equ 3*341/10 ;Fast stepping rate constant is 3 ms * 34.1 dmfset equ 15*341/10 ;Fast settling rate constant is 15 ms * 34.1 n$dubl equ 80h ;Double density n$2side equ 40h  ccp-512 ;First track DMA address - boot loader db 0 db rdtrck ;Read track command db 0 ;Track 0 db 0 ;Side 0 db 0 ;Drive 0 dw dmwsec ;Sector load/status map db 0 dmwst: db 0 ;Track read status db dmsdma dw ccp+dmtrck ;DMA address for track 1 db 0 db rdtrck db 1 ;Track 1 db 0 ;Side 0 db 0 ;Drive 0 dw dmwsec+26 ;Map is loaded right after track 0 status map db 0 db 0 ;Track read status db dmsdma dw buffer ;Sector 3 gets loaded in system buffer db 0 db rdsect db 1 ;Track 1 db 3 ;Side 0, sector 3 db********* dpb512d:dw 120 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 0 ;EXM dw 561 ;DSM dw 255 ;DRM db 0f0h ;AL0 db 0 ;AL1 dw 64 ;CKS dw 2 ;OFF db 3 ;512 byte sectors ***************************************************************** * * * The following DPB defines a diskette as 1024 byte sectors, * * double density, and double sided. * * * ***************************************************************** dp1024d:dw 128 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 0  ;2 sided drive serin equ 03eh ;Address of serial input data, (status - 1) ***************************************************************** * * * Device Specification Table for the Disk Jockey DMA floppy * * * ***************************************************************** if maxdm ne 0 dmdst: db maxdm ;Number of logical drives dw dmwarm ;Warm boot dw dmtran ;Sector translation dw dmldrv ;Select drive 1 dw dmselr ;Select drive 2 dw dmhome ;Home drive dw dmseek ;Seek to specified track dw dmssec ;Set sector dw dmdma ;Set DMA address dw dmread ;Read a sector dw dmwrite ;Write a sector  0 ;Drive 0 dmwend: db 0 ;Read status dw 0 ;Room for the halt dmwsec: dw 0ffffh, 0ffffh ;Do not load boot loader dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;22 sectors to be loaded dw 0, 0ffffh, 0ffffh, 0ffffh ;First 2 sectors on track 2 dmselr: sta dmlog mvi b,0 ;8 inch logical drives start at zero jmp dmsel2 dmtran: inx b push d ;Save table address push b ;Save sector # call dmget lxi d,10 dad d mov a,m inx h mov h,m mov l,a mov a,m ;Get # of CP/M sectors/track ora a ;Clear cary rar ;Divide by two sub c push psw ;Save adjusted sector jm dmside2 dmsidea:pop psw  ;EXM dw 599 ;DSM dw 255 ;DRM db 0f0h ;AL0 db 0 ;AL1 dw 64 ;CKS dw 2 ;OFF db 4 ;1024 byte sectors endif ***************************************************************** * * * The following equates relate the Morrow Designs DJDMA * * controller. * * * ***************************************************************** if (maxdm ne 0) or (maxmf ne 0) dmchan equ 50h ;Default channel address dmkick equ 0efh ;Kick I/O port address rdsect equ 20h ;Read sector command wrsect equ 21h ;Write a sector command gstat equ 22h ;Get dri dw nobad ;No bad sector map dmtrck equ 22*128 ;Amount of code on track 0 dmwarm: call dmselr ;Select drive 0 lxi h,dmchan ;Set up branch mvi m,bracha inx h mvi m,(low dmwchn) ;Low address byte inx h mvi m,(high dmwchn) ;High address byte inx h mvi m,0 dmwbad: lxi h,dmwend-1 ;Pointer to end of command structure call docmd ;Read in tracks lda dmwst ;Get track read status ani 40h jz dmwbad ;Loop on 'terrible' errors like no disk lxi b,300h ;3/4 K bytes of sector 3 needs to be moved lxi d,buffer ;Sector 3 is in our buffer lxi h,ccp+1300h ; and this is where we want it to go... call movbyt xra a ret dmwchn: db dmsdma ;Set track 0 DMA address dw  ;Discard adjusted sector pop b ;Restore sector requested pop d ;Restor address of xlt table dmside1:xchg ;hl <- &(translation table) dad b ;bc = offset into table mov l,m ;hl <- physical sector mvi h,0 ret dmside2:call dmstat ani 20h jz dmsidea pop psw ;Retrieve adjusted sector pop b cma ;Make sector request positive inr a mov c,a ;Make new sector the requested sector pop d call dmside1 mvi a,80h ;Side two bit ora h ; and sector mov h,a ret dmldrv: sta dmlog call dminit ;Test for a drive jc zret lxi h,1 ;Select sector 1 of track 2 shld truesec  parameter table entry mov d,h mov e,l dad h dad h dad d lxi d,dparam+1 ;Parameter table address dad d ;Skip the track size byte mvi m,0 ;Force reparamitization of this drive inx h ;Offset to the Stepping rate constant mvi m,(low dmfstp) ;Fast stepping rate constant inx h mvi m,(high dmfstp) lxi d,5 ;Skip over the reserved fields dad d mvi m,(low dmfset) ;Fast settling rate constant inx h mvi m,(high dmfset) call dmparm ;Set drive parameters for the SA850 ret endif ***************************************************************** * * * Drive specification table for b 0 db rdtrck db 1 ;Track 1 db 0 ;Side 0 db 0 ;Drive 0 dw mfwsec+10 ;Map is loaded right after track 0 status map db 0 mfwend: db 0 ;Track read status dw 0 ;Room for the halt mfwsec: dw 0ffh, 0, 0, 0, 0 ;Do not load boot loader dw 0, 0ffffh, 0ffffh, 0ffffh, 0ffffh ;first two sectors loaded mfssec: dcr c ;Minnie floppy sectors start at zero lda dblflg ;Get double sided flags ora a jz dmssec ;Nope, single sided mvi b,80h ;Set high bit for double sided select jmp dmssec dblflg: db 0 mfseek: xra a ;Clear double sided select sta dblflg lda mfpcon ani n$2side jz dmseek ;Only single sided mov  inx h shld cpmtrk xra a ;Make sure we are doing a read sta rdwr call fill ;Flush buffer and refill jc zret ;Test for error return call dmstat ;Get status on current drive ani 0ch ;Mask in sector size bits push psw ;Used to select a DPB rar lxi h,xlts ;Table of XLT addresses mov e,a mvi d,0 dad d push h ;Save pointer to proper XLT call dmget pop d lxi b,2 ;Number of bytes to move call movbyt ;Move the address of XLT lxi d,8 ;Offset to DPB pointer dad d ;HL <- &DPH.DPB push h call dmstat ani 20h ;Check double sided bit lxi d,dpb128s ;Base for singlDJDMA 5 1/4 inch drives * * * ***************************************************************** if maxmf ne 0 mfdst: db maxmf ;Number of logical drives dw mfwarm ;Warm boot dw mftran ;Sector translation dw mfldrv ;Select drive 1 dw mfsel2 ;Select drive 2 dw dmhome ;Home drive dw mfseek ;Seek to specified track dw mfssec ;Set sector dw dmdma ;Set DMA address dw dmread ;Read a sector dw dmwrite ;Write a sector dw nobad ;No bad sector map mftrck equ 9*512 ;Amount of code on track 0 mfwarm: call mfsel2 ;Select drive 0 lxi h,dmchan ;Set up branch mvi m,bracha inx h mvi m, a,c ;Move selected track in (a) sbi 35 ;Subtract by track by number of tracks jc dmseek ;Less than track 35 mov d,a ;Save adjusted track number mvi a,34 sub d ;Adjust to count tracks back out mov c,a ;Resave new track number mvi a,0ffh ;Set double sided flag sta dblflg jmp dmseek mfsel2: sta mflog mov c,a ;Get proper physical configuration byte mvi b,0 lxi h,mfscon dad b mov a,m sta mfpcon mov a,c ;Shhh, pretend that nothing happened mvi b,4 ;5 1/4 inch drives start at drive 4 jmp dmsel2 mftran: lda mfpcon ani n$dubl lxi h,mfxltd ;Point to double sided sector translation table jnz mftdubl e sided DPB's jz dmsok call sethigh ;Set controller to know about fast steping lxi d,dpb128d ;Base of double sided DPB's dmsok: xchg ;HL <- DBP base, DE <- &DPH.DPB pop d ;Restore DE (pointer into DPH) pop psw ;Offset to correct DPB ral ral mov c,a mvi b,0 dad b xchg ;Put DPB address in DPH mov m,e inx h mov m,d lxi h,15 dad d mov c,m dmget: lda dmlog lxi d,dphdm0 jmp retdph ; ; The current drive is double sided. Thus is it safe to set the ; stepping rate to 3 ms with 15 ms settling. ; sethigh:lhld dmlog ;Get the current drive number mvi h,0 ;Drive number is a byte dad h ;Ten bytes per(low mfwchn) ;Low address byte inx h mvi m,(high mfwchn) ;High address byte inx h mvi m,0 mfwfal: lxi h,mfwend-1 ;Pointer to end of command structure call docmd ;Read in tracks lda mfwst ;Check out drive status ani 40h ;Test for ok jz mfwfal ;Failed, loop xra a ;Return no error ret mfwchn: db dmsdma ;Set track 0 DMA address dw ccp-512 ;First track DMA address - boot loader db 0 db rdtrck ;Read track command db 0 ;Track 0 db 0 ;Side 0 db 0 ;Drive 0 dw mfwsec ;Sector load/status map db 0 mfwst db 0 ;Track read status db dmsdma dw ccp+mftrck ;DMA address for track 1 d ;Single density sector translation lxi h,mfxlts mftdubl:dad b ;Add offset sector number to table mov l,m ;Pick up sector number from table mvi h,0 ;MSB of sector number equal 0 ret mfldrv: sta mflog call dminit ;Test for a controller jc zret lda mflog ;Get proper physical configuration byte mov c,a mvi b,0 lxi h,mfscon dad b mvi a,n$dubl mov m,a sta mfpcon lxi h,1 ;Select sector 1 of track 0 shld truesec dcx h shld cpmtrk xra a ;Make sure we are doing a read sta rdwr call fill ;Flush buffer and refill jc zret ;Test for error return lda buffer+5ch ;Get diskette configuration byte pushd call mfgdph push h call dmstat ;Get status pop h ani 80h ;Check density bit mvi c,3 ;512 byte sectors rnz mvi c,2 ;256 byte sectors ret mfgdph lda mflog lxi d,dphmf0 jmp retdph mfpcon: db 0 ;Physical configuration byte mflog: db 0 mfscon: db 0, 0, 0, 0 ;Saved physical configuration bytes mfs: db 10h ;North Star CP/M 1.4 db 0 ;Single density, 35 tracks, single sided dw dpbmf0 ;1K groups db 90h ;North Star CP/M 1.4 db n$dubl ;Double density, 35 tracks, single sided dw dpbmf1 ;1K groups db 0b0h ;North Star CP/M 2.x db n$dubl ;Double density, 35 tracks, single sided dw dpbmf2  rlc ani 1 mov c,a call dmside pop b jmp dmsec dmdma lxi h,dmchan ;Default channel address mvi m,dmsdma ;Set DMA address inx h mov m,c ;Low byte first inx h mov m,b ;High byte next docmd xra a inx h mov m,a docmd2 inx h mvi m,dmhaltc inx h mov m,a out dmkick tests ora m jz tests ret dminit: lxi h,dmchan ;See if controller will halt mvi m,dmhaltc inx h mvi m,0 out dmkick ;Start controller lxi d,0 ;Set up timeout counter dminwt mov a,m ora a jnz dmiok ;Controller has responded dcx d ;Bump timeout counter mov a,d ora e  psw ;Save configuration byte lxi h,1 shld cpmtrk ;Load track 1 sector 1 call fill ;This is to fix bug with DJDMA firmware on jc zret ; returning single density status on track 0 pop psw ora a jnz mfl9 ;Non zero mvi a,90h ;Double density default configuration call dmstat ;If zero then determine sector size ani 80h ;Check density bit jnz mfl9 ;Its double density mvi a,10h ;Single density default configuration byte mfl9: mov c,a ;Move configuration byte into (c) lxi h,mfs ;Address of configuration table -> (hl) mfl2: mov a,m ;Get an entry ora a ;Check for end of the table jz zret ;Yes, select error cmp c ;Ch ;2K groups db 0f0h ;North Star CP/M 2.x db n$dubl+n$2side ;Double density, 35 tracks, double sided dw dpbmf3 ;2K groups db 0e5h ;North Star CP/M 1.4 db n$dubl ;Double density, 35 tracks, single sided dw dpbmf1 ;1K groups db 0a0h ;North Star CP/M 2.x (fake 40 track) db n$dubl ;Double density, 35 tracks, single sided dw dpbmf2 ;2K groups db 0d0h ;North Star CP/M 2.x (fake 40 track) db n$dubl+n$2side ;Double density, 35 tracks, double sided dw dpbmf3 ;2K groups db 0 ;End of configuration table mfxltd db 1, 2, 3, 4 db 21,22,23,24 db 5, 6, 7, 8 db 25,26,27,28 db 9,10,11,12 db 29,30,31,32 db 13,14,15,16 db jnz dminwt stc ;Set error flag ret dmiok push h ;Set drive parameters call dmparm pop h dcx h ;Back to start of command mvi m,setcrc ;Set CRC error retry count to one inx h mvi m,1 xra a jmp docmd2 ;Do command ; ; Set floppy drive parameters ; ; This routine reads the dparam table and if the a drive has not ; previously been calibrated then that drives track count, ; stepping rate, and head settling time are loaded. ; dmparm: mvi a,8 ;Eight drives lxi d,1340h ;Start with drive 0's table lxi h,dparam+1 ;Drive parameter table dmstr0: push psw ;Save the drive count mov a,m ;Load flags ora a ;Does the drive neck if entry matches selected drive jz mfl3 inx h ;Skip onfiguration byte inx h ;Skip drive type inx h ;Skip DPB address inx h jmp mfl2 mfl3: inx h mov a,m ;Pick up drive type sta mfpcon mov e,a push h lda mflog ;Get proper physical configuration byte mov c,a mvi b,0 lxi h,mfscon dad b mov m,e pop h inx h mov a,m inx h mov h,m mov l,a ;DPB address -> (hl) push h ;Save DPB address call mfgdph ;Get DPH lxi d,10 ;Offset to DPB address in DPH dad d pop d mov m,e ;Store DPB address in DPH inx h mov m, 33,34,35,36 db 17,18,19,20 db 37,38,39,40 mfxlts db 1, 2 db 3, 4 db 5, 6 db 7, 8 db 9,10 db 11,12 db 13,14 db 15,16 db 17,18 db 19,20 endif ***************************************************************** * * * Common routines for the DJDMA with 8 and 5 1/4 inch drives * * * ***************************************************************** dmsel2: mov c,a ;Move drive into (c) lxi h,dmchan mvi m,setlog ;Set logical drives inx h mov m,b ;Drive in (b) push b call docmd pop b jmp dmsel dmssec: push b ;Save sector number mov a,b eed to be calibrated? jnz dmstr1 ;No, do not fiddle around push h ;Save the parameter table pointer push d ;Save the controllers table pointer dcr m ;Set to calibrated mode (0ffh) dcx h ;Back up to the track size byte shld dmntrk ;Set the number of tracks pointer inx h inx h shld dmspar ;Set the stepping constants pointer xchg ;Set the local parameter table pointer shld dmloc0 inx h ;Offset to the stepping parameters inx h inx h inx h shld dmloc1 lxi h,dmwcon ;Write the drive constants out lxi d,17 ;Halt status offset call dmdoit pop d  ;Skip over returned status inx h inx h call docmd ;Issue command lda llss ;Get side bit of last operation ani 80h rrc ;Move to bit 7 mov c,a lxi h,dmchan+1 ;Point to drive mov a,m ;Load drive ora c ani 4 ;Mask upper drive select bit for 5 1/4 rlc rlc ;Move to bit 4 ora m ;Put together with lower drive bits ora c mov c,a inx h mvi a,10h ;Double density bit ana m rlc ;20h rlc ;40h rlc ;80h for density bit ora c mov c,a inx h mvi a,3 ;Sector length mask ana m ;And in rlc  db 0 ;Status ; ; Driver variables ; lltrk db 0 llss db 1 lldrv db 0 dmlog db 0 endif ***************************************************************** * * * The follwing equates are for the HDDMA hard disk controller * * * ***************************************************************** if maxmw ne 0 ;HDDMA controller present ? if st506 ;Specifications for a Seagate Technology 506 cyl equ 153 ;Number of cylinders heads equ 4 ;Number of heads per cylinder precomp equ 64 ;Cylinder to start write precomensation lowcurr equ 128 ;Cylinder to start low current stepdly equ 30 ;Step delay (0-12.7 milliseconds) steprcl equ 30 ;Recalibrate  ;Retrieve the table pointers pop h dmstr1: lxi b,10 ;Bump parameter table pointer dad b xchg lxi b,16 ;Bump controller tables pointer dad b xchg pop psw ;Retrieve drive count dcr a ;Bump count jnz dmstr0 ;Set up next drive ret dmhome xra a mov c,a ;Put a zero into (c) for track zero dmseek mov a,c ;Enter with track in (c) sta lltrk ;Save for use later ret dmsec lda llss ;Load sector ani 80h ;Save side select bit stores ora c sta llss ret dmside: mov a,c ;Move side bit into (a) ani 1 rrc ;Move around to bit 7 mov c,a ;Resave in (c)  ;Move to bits 2 & 3 rlc ora c mov c,a inx h mvi a,4 ;Mask for double sided bit ana m rlc ;8 rlc ;10 rlc ;20 ora c ret dmwrite mvi a,wrsect db 01 ;Ugh... dmread mvi a,rdsect lxi h,dmchan lxi d,lltrk-1 mvi b,4 cload mov m,a inx h inx d ldax d dcr b jnz cload dcx h call docmd lda dmchan+4 cpi 80h cmc ret ; ; Execute a DJDMA command, no command status is returned ; ; Entry: ; DE = offset to the halt status ; HL = pointer to the start of the command ; ; Returns: ; nothing ; dmdoit: mvi a,bracha ;Branch channel commanstep delay headdly equ 0 ;Settle delay (0-25.5 milliseconds) endif if st412 ;Specifications for a Seagate ST412 cyl equ 306 heads equ 4 precomp equ 128 lowcurr equ 128 stepdly equ 0 steprcl equ 30 headdly equ 0 endif if cm5619 ;Specifications for an CMI 5619 cyl equ 306 heads equ 6 precomp equ 128 lowcurr equ 128 stepdly equ 2 steprcl equ 30 headdly equ 0 endif sectsiz equ 7 ;Sector size code (must be 7 for this Cbios) ; 0 = 128 byte sectors ; 1 = 256 byte sectors ; 3 = 512 byte sectors ; 7 = 1024 byte sectors (default) ; f = 2048 byte sectors ;Define controller commands dmaread equ 0 ;Read sect lda llss ani 7fh ;Mask out old side select bit jmp stores dmsel: mov a,c ;Move drive into (a) sta lldrv dmden: ret ;Double density only ; ; Return status in the (a) register in the form: ; ; 7 6 5 5 3 2 1 0 ; ^ ^ ^ ^ ^ ^ ^ ^ ; Density --------------+ | | | | | | | ; Side select -------------+ | | | | | | ; Double sided ---------------+ | | | | | ; 5 1/4 -------------------------+ | | | | ; Sector size MSB ------------------+ | | | ; Sector size LSB ---------------------+ | | ; Drive select MSB -----------------------+ | ; Drive select LSB --------------------------+ ; dmstat lxi h,dmchan mvi m,gstat ;Set up read status inx h lda lldrv ;Get last selected drive mov m,a ;Store drive in command inx h d sta dmchan shld dmchan+1 ;Load command vector xra a ;Clear extended address sta dmchan+3 dad d ;Offset to the halt status mov m,a ;Clear the halt status indicator out dmkick ;Start the controller dmwait: ora m ;Wait for the operation complete status jz dmwait ret dmwcon: db writem ;Write track size dmntrk: dw 0 ;Number of tracks + desync db 0 ;X-address dw 2 ;Two bytes dmloc0: dw 0 ;Local controller address db writem ;Write stepping rate data dmspar: dw 0 ;Pointer to the stepping parameters db 0 dw 8 dmloc1: dw 0 db dmhaltc ;Controller halt or dmawrit equ 1 ;Write sector dmarhed equ 2 ;Find a sector dmawhed equ 3 ;Write headers (format a track) dmalcon equ 4 ;Load disk parameters dmassta equ 5 ;Sense disk drive status dmanoop equ 6 ;Null controller operation reset equ 54h ;Reset controller attn equ 55h ;Send a controller attention chan equ 50h ;Default channel address stepout equ 10h ;Step direction out stepin equ 0 ;Step direction in band1 equ 40h ;No precomp, high current band2 equ 0c0h ;Precomp, high current band3 equ 80h ;precomp, low current track0 equ 1 ;Track zero status wflt equ 2 ;Write fault from drive dready equ 4 ;Drive ready sekcmp equ 8 ;Seek complete ******************************** lxi d,buffer+200h lxi h,ccp lxi b,200h ;Move 200h bytes call movbyt lxi h,ccp-200h ;Initial DMA address push h xra a push a ;Save first sector -1 mwwlod pop psw ;Restore sector pop h ;Restore DMA address inr a sta mwsectr cpi 6 ;Past BDOS ? rz ;Yes, all done inr h ;Update DMA address by 1024 bytes inr h inr h inr h shld dmadma push h push psw call mwwread ;Read in a sector jnc mwwlod ret ;Return with error mwwread mvi c,retries ;Retry counter mwwerr push b ;Save the retry count call mwread ;Read the sector pop b rnc  ;Back to fast stepping mode mwbad: lxi h,mwbtab ;Return pointer to bad sector location ret mwbtab: dw 0 ;Track 0 dw 19 ;Head 2, sector 0 = (2 * SPT + 0) + 1 mwseek call mwptr ;Get track pointer mov e,m ;Get old track number inx h mov d,m dcx h mov m,c ;Store new track number inx h mov m,b mov l,c ;Build cylinder word mov h,b shld dmarg0 ;Set command channel cylinder number mov a,d inr a lxi h,0ffffh jnz mwskip0 mvi c,stepout jmp mwskip mwskip0:mov h,b ;(hl) = new track, (de) = old track mov l,c call mwhlmde mvi c,stepout mov a,h ani 80h ;Check hit bit for negitive direction ********************************* * * * Drive Specification Table for the HD DMA hard disk controller * * * ***************************************************************** mwdst: db maxmw*mwlog ;Number of logical drives dw mwwarm ;Warm boot dw mwtran ;Sector translation dw mwldrv ;Select logical drive 1 (First time select) dw mwdrv ;Select logical drive 2 (General select) dw mwhome ;Home current selected drive dw mwseek ;Seek to selected track dw mwsec ;Select sector dw mwdma ;Set DMA address dw mwread ;Read a sector dw mwwrite ;Write a sector if heads > 2 ;Test if drive is big enough for a bad spot map dw m dcr c ;Update the error count jnz mwwerr ;Keep trying if not too many errors stc ;Set error flag ret mwldrv sta mwcurl ;Save current logical drive call mwreset ;Reset controller card jc zret ;Controller failure lda mwcurl call mwdrv ;Select drive jc zret ;Select error call mwstat ;Get drive status ani dready ;Check if drive ready jnz zret call mwhome ;Home drive lxi d,dphmw0 ;Start of hard disk DPH's lda mwcurl mov l,a mvi h,0 dad h dad h dad h dad h dad d ;(hl) = pointer to DPH mvi c,4 ;Return sector size of 1024 ret mwdrv sta mwcurl call  jnz mwsout ;Step in mvi c,0 jmp mwskip mwsout: call mwneghl mwskip: shld dmastep lda mwdrive ora c sta dmasel0 mvi a,dmanoop ;No-operation command for the channel call mwprep ;Step to proper track lxi h,0 ;Clear step counter shld dmastep ret mwdma mov h,b ;Set DMA address mov l,c shld dmadma ret mwsec mov a,c ;Load sector number dcr a ;Range is actaully 0-16 call mwdspt ;Figure out head number -> (c) adi mwspt ;Make sector number sta mwsectr mov a,c sta mwhead ;Save head number ret mwdspt mvi c,0 ;Clear head counter mwdsptx sui mwspt ;Subtract a tracks worth of sectors rc wbad ;Return bad sector map info else dw nobad endif ***************************************************************** * * * The following are the lowest level drivers for the Morrow * * Designs Hard Disk DMA controller. * * * ***************************************************************** mwwarm xra a call mwdrv ;Select drive A call mwhome ;Home and reset the drive lxi b,0 ;Make sure we are on track 0 call mwseek xra a sta mwhead ;Select head zero sta mwsectr ;Select sector 1 lxi h,buffer ;Load sector 1 into buffer shld dmadma call mwwread ;Read CCP into buffer rc ;Return if error  mwdlog mov a,c sta mwdrive ;Save new selected drive mwsel mvi a,dmanoop jmp mwprep ;Execute disk command mwdlog: mvi c,0 mwllx: sui mwlog rc inr c jmp mwllx mwstat mvi a,dmassta ;Sense status operation code jmp mwprep ;Execute disk command mwhome call mwreset ;Reset controller, do a load constants lxi h,dmarg1 ;Load arguments mvi m,steprcl ;Load step delay (slow rate) inx h mvi m,headdly ;Head settle delay call mwissue ;Do load constants again call mwptr ;Get pointer to current cylinder number mvi m,0ffh ;Fake at cylinder 65535 for max head travel inx h mvi m,0ffh lxi b,0 ;Seek to cylinder 0 call mwseek ;Recal slowly jmp mwreset ! ;Return if all done inr c ;Bump to next head jmp mwdsptx mwreset lhld chan ;Save the command channel for a while shld tempb lda chan+2 sta tempb+2 out reset ;Send reset pulse to controller lxi h,dmachan ;Address of command channel shld chan ;Default channel address xra a sta chan+2 ;Clear extended address byte shld 40h ;Set up a pointer to the command channel sta 42h lhld dmarg0 ;Save the track number push h lxi h,dmasel1 ;Load arguments lda mwdrive ;Get the currently selected drive ori 03ch ;Raise *step and *dir mov m,a ;Save in drive select register lxi d,5 ;Offset to dmarg1 dad d mvi m,stepdly ;Li h,dmachan mvi c,16 ;16 bytes of status mwerr: push b push h mov a,m call hexout ;Print a byte of the status line call spout pop h pop b inx h ;Bump command channel pointer dcr c jnz mwerr mvi c,0ah ;Terminate with a CRLF call pout mvi c,0dh call pout pop psw ;Restore error status ret dspout: call spout ;Print two spaces spout: mvi c,' ' ;Print a space jmp pout hexout: push psw ;Poor persons number printer rrc rrc rrc rrc call nibout pop psw nibout: ani 0fh adi '0' cpi '9'+1 jc nibok adi 27h nibok: mov c,a jmp pout mwdoit equ $ else  0 ;Relative step counter dmasel1 db 0 ;Head select dmadma dw 0 ;DMA address db 0 ;Extended address dmarg0 db 0 ;First argument dmarg1 db 0 ;Second argument dmarg2 db 0 ;Third argument dmarg3 db 0 ;Fourth argument dmaop db 0 ;Operation code dmastat db 0 ;Controller status byte dmalnk dw dmachan ;Link address to next command channel db 0 ;extended address endif ***************************************************************** * * * Cbios ram locations that don't need initialization. * * * ***************************************************************** if nostand ne 0 ;Unallocated writting vaoad step delay inx h mvi m,headdly ;Head settle delay inx h mvi m,sectsiz ;Sector size code inx h mvi m,dmalcon ;Load constants command call mwissue ;Do load constants pop h ;Restore the track number shld dmarg0 push psw ;Save status lhld tempb ;Restore memory used for the channel pointer shld chan lda tempb+2 sta chan+2 pop psw ret mwread mvi a,dmaread ;Load disk read command jmp mwprep mwwrite mvi a,dmawrit ;Load disk write command mwprep: sta dmaop ;Save command channel op code mvi c,band1 lhld dmarg0 lxi d,precomp call mwhlcde jc mwpreps mvi c,band2 lxi d,lowcurr call mwhlcde jc  mwissue equ $ ;Do a disk command, handle timeouts + errors endif lxi h,dmastat ;Clear status byte mvi m,0 out attn ;Start the controller lxi d,0 ;Time out counter (65536 retries) mwiloop mov a,m ;Get status ora a ;Set up CPU flags rm ;Return no error (carry reset) stc rnz ;Return error status xthl ;Waste some time xthl xthl xthl dcx d ;Bump timeout counter mov a,d ora e jnz mwiloop ;Loop if still busy stc ;Set error flag ret mwptr lda mwdrive ;Get currently select drives track address rlc mov e,a mvi d,0 lxi h,mwtab dad d ;Offset inriables unaloc: db 0 ;Unallocated write in progress flag oblock: dw 0 ;Last unallocated block number written unadrv: db 0 ;Drive that the block belongs to endif cpmsec: dw 0 ;CP/M sector # cpmdrv: db 0 ;CP/M drive # cpmtrk: dw 0 ;CP/M track # truesec:dw 0 ;Physical sector that contains CP/M sector error: db 0 ;Buffer's error status flag bufdrv: db 0 ;Drive that buffer belongs to buftrk: dw 0 ;Track that buffer belongs to bufsec: dw 0 ;Sector that buffer belongs to alttrk: dw 0 ;Alternate track altsec: dw 0 ;Alterante sector lastdrv:db 0 ;Last selected drive ***************************************************************** * * * DPB and DPH area.  mwpreps mvi c,band3 ;cylinder > low_current mwpreps lda mwhead ;Load head address sta dmarg2 cma ;Negative logic for the controller ani 7 ;3 bits of head select rlc ;Shove over to bits 2 - 4 rlc ora c ;Add on low current and precomp bits mov c,a lda mwdrive ;Load drive address ora c ;Slap in drive bits sta dmasel1 ;Save in command channel head select lda mwsectr ;Load sector address sta dmarg3 if 0 ;Set to 1 for MW error reporter mwissue call mwdoit ;Do desired operation rnc ;Do nothing if no error push psw ;Save error info call hexout ;Print status call dspout ; and a space lxto track table ret mwtran: mov h,b mov l,c inx h ret mwneghl:mov a,h cma mov h,a mov a,l cma mov l,a inx h ret mwhlmde:xchg call mwneghl xchg dad d ret mwhlcde:mov a,h cmp d rnz mov a,l cmp e ret mwtab equ $ ;Collection of track addresses rept maxmw db 0ffh ;Initialize to (way out on the end of the disk) db 0ffh endm db 0ffh mwcurl db 0 ;Current logical drive mwdrive db 0ffh ;Currently selected drive mwhead db 0 ;Currently selected head mwsectr db 0 ;Currently selected sector dmachan equ $ ;Command channel area dmasel0 db 0 ;Drive select dmastep dw " * * * ***************************************************************** if maxhd ne 0 dphdsk set 0 ;Generate DPH's for the HDCA hard disks rept maxhd ldsk set 0 rept hdlog dphgen hd,%dphdsk,dpbhd,%ldsk ldsk set ldsk+1 dphdsk set dphdsk+1 endm endm if hdpart ne 0 ;Use non-standard partitioning ***************************************************************** * * * hdsectp is the number of 128 byte sectors per cylinder. * * * * hdtrks is the total number of data cylinders. Eg. it is * * the number of cyliders on the drive minus the number of * * cylinders that are used for the system. If the number of * * 'system tracks' is no db 3 ;SECSIZ dpbhd2 dw 1024 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 2047 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 127 ;OFF db 3 ;SECSIZ endif if m10 ne 0 dpbhd0 dw 336 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 1269 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 1 ;OFF db 3 ;SECSIZ dpbhd1 dw 336 ;CP/M sectors/track d 3 dpbgen mf, 3, 40, 4, 15, 1, 0a9h, 63, 80h, 0, 16, 2, 3 dn set 0 rept maxmf dphgen mf,%dn,dpbmf,%dn dn set dn+1 endm endif if maxfd ne 0 dn set 0 rept maxfd dphgen fd,%dn,0,0 dn set dn+1 endm endif if maxdm ne 0 dn set 0 rept maxdm dphgen dm,%dn,0,0 dn set dn+1 endm endif if maxmw ne 0 ***************************************************************** * * * mwsectp is the number of 128 byte sectors per cylinder. * * mwsectp = 72 * heads * * * * mwtrks is the total number of data cylinders. * * mwtrks = tracks - 1 * * t one then the initial value of * * 'off' should be adjusted accordingly. * * * * hdtrks = tracks - 1 * * * ***************************************************************** if m10 ne 0 hdsectp equ 336 ;Sectors per track hdtrks equ 243 ;Total data tracks endif if m20 ne 0 hdsectp equ 672 hdtrks equ 243 endif if m26 ne 0 hdsectp equ 1024 hdtrks equ 201 endif ldsk set 0 ;Use non-standard partitioning tracks set hdtrks/hdlog ;Number of tracks per partition dsm set hdsectp/8*tracks/4-1 ;Number of groups per partition off set 1 rept hdlog dpbgen hd,%ldsk,%hdsecb 5 ;BSH db 31 ;BLM db 1 ;EXM dw 1280 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 122 ;OFF db 3 ;SECSIZ endif if m20 ne 0 dpbhd0 dw 672 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 2036 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 1 ;OFF db 3 ;SECSIZ dpbhd1 dw 672 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM  * ***************************************************************** if st506 ne 0 mwsecpt equ 288 ;Sectors per track mwtrks equ 152 ;Total data tracks endif if st412 ne 0 mwsecpt set 288 mwtrks set 305 endif if cm5619 ne 0 mwsecpt set 432 mwtrks set 305 endif dphdsk set 0 ;Generate DPH's for the HDDMA hard disks rept maxmw ldsk set 0 rept mwlog dphgen mw,%dphdsk,dpbmw,%ldsk dphdsk set dphdsk+1 ldsk set ldsk+1 endm endm if mwpart ne 0 ;Generate DPB's for a HDDMA hard disk ldsk set 0 ;Use non-standard partitioning tracks set mwtrks/mwlog ;Number of tracks per partition dsm set mwsectp/8*tracks/4-1 ;Number of groups per partition offtp,5,31,1,%dsm,511,0ffh,0ffh,0,%off,3 off set off+tracks ldsk set ldsk+1 endm else ;Else use standard DPB's if m26 ne 0 dpbhd0 dw 1024 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 2015 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 1 ;OFF db 3 ;SECSIZ dpbhd1 dw 1024 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 2015 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 64 ;OFF dw 2036 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 98 ;OFF db 3 ;SECSIZ dpbhd2 dw 672 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 1028 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 195 ;OFF db 3 ;SECSIZ endif endif endif ;End of HD DPH's and DPB's if maxmf ne 0 dpbgen mf, 0, 20, 3, 7, 0, 04fh, 63, 0c0h, 0, 16, 3, 2 dpbgen mf, 1, 40, 3, 7, 0, 0a4h, 63, 0c0h, 0, 16, 2, 3 dpbgen mf, 2, 40, 4, 15, 1, 051h, 63, 80h, 0, 16, 2,# set 1 rept mwlog dpbgen mw,%ldsk,%mwsecpt,5,31,1,%dsm,1023,0ffh,0ffh,0,%off,4 off set off+tracks ldsk set ldsk+1 endm else ;Use standard partitioning off set 1 ;Initial system track offset trkoff set 8192/(mwsecpt/8)+1 ;The number of tracks in a partition blocks set mwsecpt/8*mwtrks ;The number of blocks on the drive psize set trkoff*(mwsecpt/8) ;The number of blocks in a partition ldsk set 0 rept blocks/8192 ;Generate some 8 megabyte DPB's dpbgen mw,%ldsk,%mwsecpt,5,31,1,2047,1023,0ffh,0ffh,0,%off,4 off set off+trkoff blocks set blocks-psize ldsk set ldsk+1 endm blocks set blocks/4 if blocks gt 256 ;If there is any stuff left, then use it blocks set blocks-1 dpbgen mw,%ldsk,%mwsecpt,5,31,1,%blocks,1023,0ffh,0ffh,0,%off,4 endif endi db 'Memorex' else db 'Fujitsu' endif db ' M10' endif if m20 ne 0 db 'Fujitsu M20' endif if m26 ne 0 db 'Shugart M26' endif endif if dn eq mworder ;Generate the HDDMA's message msbump maxmw*mwlog db 'HDDMA' if mwquiet eq 0 db ' ' if maxmw gt 1 db '(', maxmw+'0', ')' endif if st506 ne 0 db 'M5' endif if st412 ne 0 db 'M10' endif if cm5619 ne 0 db 'M16' endif endif endif if dn eq fdorder ;Generate the 2D/B message msbump maxfd db 'DJ2D/B @' prhex fdorig/100h prhex fdorig endif if dn eq dmorder ;Generate the DJDMA 8 message  h mov d,m inx h mov a,d ;Test for the end of the table ora e jz cboot2 push h ;Save the table pointer lxi h,cboot1 ;Return address push h xchg pchl ;'CALL' a device setup routine cboot1: pop h ;Restore the table pointer jmp cboot0 devset: dw ttyset, crtset, uc1set ;Device setup routine pointers dw ptrset, ur1set, ur2set dw ptpset, up1set, up2set dw lptset, ul1set, 0 cboot2 equ $ endif lxi h,prompt ;Prep for sending signon message call message ;Send the prompt jmp gocpm ***************************************************************** * * * Console and list device inf endif buffer equ $ ***************************************************************** * * * Signon message output during cold boot. * * * ***************************************************************** prompt: db 80h, clear ;Clean buffer and screen db acr, alf, alf db 'Morrow Designs ' db '0'+msize/10 ;CP/M memory size db '0'+(msize mod 10) db 'K CP/M ' ;CP/M version number db cpmrev/10+'0' db '.' db (cpmrev mod 10)+'0' db ' ' db (revnum/10)+'A'-1 db (revnum mod 10)+'0' db acr, alf ; ; Print a message like: ; ; AB: DJDMA 8", CD: DJDMA 5 1/4", E: HDDMA M5 ; msdrv set 0 ;Start with msbump maxdm db 'DJDMA 8"' endif if dn eq mforder ;Generate the DJDMA 5 1/4 message msbump maxmf db 'DJDMA 5 1/4"' endif dn set dn+1 endm db acr,alf db 0 ;End of message ***************************************************************** * * * Cboot is the cold boot loader. All of CP/M has been loaded in * * when control is passed here. * * * ***************************************************************** cboot: lxi sp,tpa ;Set up stack xra a ;Clear cold boot flag sta cwflg sta group ;Clear group select byte sta cpmdrv ;Select disk A: sta itialization routines follow. * * * ***************************************************************** if contyp eq 2 ;Multi I/O, Decision I ***************************************************************** * * * Terminal initilization routine. This routine reads the sense * * switch on the WB-14 and sets the speed accordingly. * * * ***************************************************************** ttyset: call selg0 ;Select group 0 in sensesw ;Get sense switch (ff on a Multio) push psw call selcon ;Select console pop psw push psw call tini0 ;Initialize the console pop psw push psw call sel drive A: msbump macro ndrives ;Print a drive name if dn gt 1 db ', ' endif rept ndrives db msdrv+'A' msdrv set msdrv+1 endm db ': ' endm prhex macro digit ;Write a byte in hex prnib digit/10h prnib digit endm prnib macro digit ;Write a digit in hex temp set digit and 0fh if temp < 10 db temp + '0' else db temp - 10 + 'A' endif endm dn set 1 ;Generate the drive messages rept 16 ;Run off at least 16 drives if dn eq hdorder ;Generate the HDCA's message msbump maxhd*hdlog db 'HDCA ' if maxhd gt 1 db '(', maxhd+'0', ')' endif if m10 ne 0 if m10m ne 0 cdisk lxi h,bios+3 ;Patch cold boot to warm code shld bios+1 lda iobyt ;Initialize the IOBYTE sta iobyte lxi d,badmap ;Clear out bad map stax d lxi h,badmap+1 lxi b,9*badsiz ;32 map entries call movbyt mvi m,0ffh ;End marker if contyp ne 6 ;Non IOBYTE inits if contyp ne 0 ;Do not call TTYSET for PROM's call ttyset ;Initialize the terminal endif if lsttyp ne 0 ;Do not call LSTSET for PROM's call lstset ;Initialize the list device endif else ;Do IOBYTE inits lxi h,devset ;Device setup routine pointer table cboot0: mov e,m ;Load a routine address inx $rdr ;Select the reader/punch pop psw call tini0 ;Initialize the reader/punch ret tini0: ani 0e0h ;Mask in upper three bits rlc ;Move into lower 3 bits rlc rlc cpi 7 ;check for sense = 7 (Default setting) jz dfbaud ;Use default baud rate lxi h,btab ;Pointer to baud rate table add a ;Table of words so double mov e,a ;Make a 16 bit number into (de) mvi d,0 dad d ;Get a pointer into baud rate table mov e,m ;Get lower byte of word inx h ;Bump to high byte of word mov d,m ;Get upper byte. (de) now has divisor jmp setit ;Set bau h,dmchan lxi b,10 ;Command length call movbyt dcx h xra a ;Clear serial input status sta serin+1 jmp docmd2 ;Do stuff and return dmaci: db writem ;Zot monitor disable flag dw ttyset ;Any non-zero byte will do db 0 dw 1 ;One byte dw 13f5h ;Magical place in monitor db senabl ;Enable serial input db 1 endif ************************************************************************* * * * Initialize the North Star Mother board, left serial port, right * * serial port, and North Star RAM parity. * * * *********p h ;Set carry if pointer is <= our page+1 jc nset0 ;Reset the next pages parity mov a,m ;Test for a PROM or no memory mov b,a ;Save the original byte cma ;See if this location will change mov m,a cmp m ;Test for a change mov m,b ;Restore the original value jz nset0 ;Value complemented, must be RAM ora a ;Test for no memory present jz nset1 ;Skip to the next page if no memory lxi d,700h ;Skip 2K bytes of 'PROM' dad d jnc nset1 ;Do a page check if no overflow nset2: mvi a,41h ;Re-enable parity on the memory boards out nsram endif crtset: d rate dfbaud: lhld defcon ;Use default baud rate xchg setit: mvi a,dlab+wls1+wls0+stb ;Enable divisor access latch out lcr ;Set the baud rate in (de) mov a,d out dlm ;Set upper divisor mov a,e out dll ;Set lower divisor mvi a,wls1+wls0+stb ;Clear Divisor latch out lcr xra a out ier ;Set no interrupts out lsr ;Clear status mvi a,dtrenb+rtsenb ;Enable DTR and RTS outputs to terminal out mcr in msr ;Clear MODEM Status Register in lsr ;Clear Line Status Register in rbr ;Clear reciever buffers in rbr ret btab: dw 1047 ;110 Baud 000 dw **************************************************************** if contyp eq 6 ;North Star drivers ttyset: ;Set up the parallel port + motherboard xra a ;Initialize mother board out 6 out 6 out 6 out 6 mvi a,30h ;Reset the parallel port input flag out nspsta mvi a,60h ;Set the parallel port output flag out nspsta mvi a,acr ;Force a CR out the parallel port call nspout ;Initialize the left serial port mvi a,nslin1 ;See the equates for bit definations out nslsta mvi a,nslin2 out nslsta xra a ;Clear the input/output buffers out nsldat in nsldat in nsl ;Null routines ptrset: ptpset: uc1set: ur1set: ur2set: up1set: up2set: lptset: ul1set: ret endif ;North Star drivers if (lsttyp ge 2) and (lsttyp le 5) ;Serial Multi I/O list drivers lstset: call sellst ;Select printer group mvi a,dlab ;Access divisor latch out lcr lhld deflst ;Get LST: baud rate divisor mov a,h out dlm ;Set upper baud rate mov a,l out dll mvi a,stb+wls0+wls1 ;2 stop bits + 8 bit word out lcr mvi a,dtrenb+rtsenb ;DTR + RTS enabled out mcr in rbr ;Clear input buffer xra a out ier ;No interrupts ret endif db 0,0ffh,0 codelen equ ($-bios) ;Lengt 384 ;300 001 dw 96 ;1200 010 dw 48 ;2400 011 dw 24 ;4800 100 dw 12 ;9600 101 dw 6 ;19200 110 ;DEFCON 111 endif ;Multi I/O, Decision I if contyp eq 3 ;2D/B console initialization ttyset: call fdtstat ;Clean input buffer rnz ;All empty call fdcin jmp ttyset endif ;2D/B console if contyp eq 4 ttyset: call dminit ;See if controller present rc ;No controller, return lxi d,dmaci ;Console initialization sequence lxi dat ;Initialize the right serial port mvi a,nsrin1 ;See the equates for bit definations out nsrsta mvi a,nsrin2 out nsrsta xra a ;Clear the input/output buffers out nsrdat in nsrdat in nsrdat if nsram ne 0 ;Reset parity on North Star RAMs mvi a,40h ;Disable parity logic out nsram lxi h,0 ;Starting address nset0: mov a,m ;Get a byte mov m,a ;Rewrite, set proper parity inr l ;Bump the address pointer jnz nset0 nset1: inr h ;Skip to the next memory page jz nset2 ;Skip if all done mvi a,(high $) + 1 ;Is the pointer above us? cm%h of Cbios code if codelen gt 1000h ;Test for SYSGEN problems 'FATAL ERROR, system is too big for SYSGEN rev. 4.X' dbgtmp set codelen ;Cbios code length ! endif if debug dbgtmp set codelen ;Cbios code length ! endif ds 512-($-buffer) ;Buffer for 512 byte sectors if (maxfd ne 0) or (maxdm ne 0) or (maxmw ne 0) ds 512 ;Additional space for 1k sector devices endif ***************************************************************** * * * Each bad map entry consists of 9 bytes: * * Logical drive number (1 byte) * * Track number of bad sector (2 bytes) * * Sector number of bad sector (2 bytes) * * Track number of alternate sector (2 bytes)  if maxdm ne 0 dn set 0 rept maxdm alloc dm,%dn,75,64 dn set dn+1 endm endif if maxmf ne 0 dn set 0 rept maxmf alloc mf,%dn,22,16 dn set dn+1 endm endif if maxmw ne 0 if mwpart ne 0 ;Use non-standard partitioning tracks set mwtrks/mwlog ;Number of tracks per partition dsm set mwsectp/8*tracks/4-1 ;Number of groups per partition alv set (dsm/8)+1 dn set 0 rept maxmw*mwlog ;Generate CKS and ALV tables alloc mw,%dn,%alv,0 dn set dn+1 endm else ;Use standard partitioning dn set 0 trkoff set 8192/(mwsecpt/8)+1 psize set trkoff*(mwsecpt/8) rept maxmw blocks set mwsecpt/8*mwtrks rept blocks/8192 ;Generate some 8 megaby; Skeletal CBIOS for first level of CP/M 2.0 alteration ; msize equ 20 ;cp/m version memory size in kilobytes ; ; "bias" is address offset from 3400H for memory systems ; than 16K (referred to as "b" throughout the text). ; bias equ (msize-20)*1024 ccp equ 3400H+bias ;base of ccp bdos equ ccp+806h ;base of bdos bios equ ccp+1600h ;base of bios cdisk equ 0004H ;current disk number 0=A,...,15=P iobyte equ 0003h ;intel i/o byte ; org bios ;origin of this program nsects equ ($-ccp)/128 ;warm start sector count ; ; jump vector for individual subroutines jmp boot ;cold start wboote: jmp wboot ;warm start jmp const ;console status jmp conin ;console character in jmp conout ;console character out jmp list ;list character out jmp punch ;punch character out jmp reader ;reader character out jmp home ;move head to home position jmp seldsk ;select disk jmp settrk ;set track number jmp setsec ;set sector number jmp setdma ;set dma address jmp read ;read disk jmp  * * Sector number of alternate sector (2 bytes) * * * ***************************************************************** badmap: ds badsiz*9+1 ;32 entries + end marker dirbuf: ds 128 ;Directory buffer tempb: ds 16 ;A little temporary buffer ***************************************************************** * * * Allocation and checked directory table area * * * ***************************************************************** if maxhd ne 0 if hdpart ne 0 ;Use non-standard partitioning tracks set hdtrks/hdlog ;Number of tracks per partition dsm set hdsectp/8*tracks/4-1 ;Number of groups per partition alv set (dsm/8)te ALV's alloc mw,%dn,256,0 blocks set blocks-psize dn set dn+1 endm blocks set blocks/4 if blocks gt 256 ;Use the remainder blocks set blocks-1 alv set (blocks/8)+1 alloc mw,%dn,%alv,0 dn set dn+1 endif endm endif endif bioslen equ (high ($-bios))+1 ;BIOS length in pages if bioslen gt biosln ;Test for overflow 'FATAL ERROR, system overflow. BIOSLN must be at least' dbgtmp set bioslen ;BIOSLN! endif if debug dbgtmp set biosln ;Current BIOSLN! if biosln gt bioslen dbgtmp set bioslen ;Optimal BIOSLN! endif endif end write ;write disk jmp listst ;return list status jmp sectran ;sector translate ; ; fixed data tables for four-drive standard ; IBM-compatible 8" disks ; disk parameter header for disk 00 dpbase: dw trans,0000H dw 0000H,0000H dw dirbf,dpblk dw chk00,all00 ; disk parameter header for disk 01 dw trans,0000H dw 0000H,0000H dw dirbf,dpblk dw chk01,all01 ; disk parameter header for disk 02 dw trans,0000H dw 0000H,0000H dw dirbf,dpblk dw chk02,all02 ; disk parameter header for disk 03 dw trans,0000H dw 0000H,0000H dw dirbf,dpblk dw chk03,all03 ; ; sector translate vector trans: db 1,7,13,19 ;sectors 1,2,3,4 db 25,5,11,17 ;sectors 5,6,7,8 db 23,3,9,15 ;sectors 9,10,11,12 db 21,2,8,14 ;sectors 13,14,15,16 db 20,26,6,12 ;sectors 17,18,19,20 db 18,24,4,10 ;sectors 21,22,23,24 db 16,22 ;sectors 25,26 ; dpblk: ;disk parameter block, common to all disks dw 26 ;sectors per track db 3 ;block shift factor db 7 ;block mask db 0 ;null mask dw 242 ;dis+1 dn set 0 rept maxhd*hdlog ;Generate CKS and ALV tables alloc hd,%dn,%alv,0 dn set dn+1 endm else ;Standard partitioning dn set 0 rept maxhd if m26 ne 0 alloc hd,%dn,252,0 dn set dn+1 alloc hd,%dn,252,0 dn set dn+1 alloc hd,%dn,256,0 dn set dn+1 endif if m10 ne 0 alloc hd,%dn,159,0 dn set dn+1 alloc hd,%dn,161,0 dn set dn+1 endif if m20 ne 0 alloc hd,%dn,255,0 dn set dn+1 alloc hd,%dn,255,0 dn set dn+1 alloc hd,%dn,129,0 dn set dn+1 endif endm endif endif if maxfd ne 0 dn set 0 rept maxfd alloc fd,%dn,75,64 dn set dn+1 endm endif &k size-1 dw 63 ;directory max db 192 ;alloc 0 db 0 ;alloc 1 dw 16 ;check size dw 2 ;track offset ; ; end of fixed tables ; ; individual subroutines to perform each function boot: ;simplest case is to just perform parameter initialization xra a ;zero in the accum sta iobyte ;clear the iobyte sta cdisk ;select disk zero jmp gocpm ;initialize and go to cp/m ; wboot: ;simplest case is to read the disk until all sectors loaded lxi sp,80h ;use space below buffer for stack mvi c,0 ;select disk 0 call seldsk call home ;go to track 00 ; mvi b,nsects ;b counts # of sectors to load mvi c,0 ;c has the current track number mvi d,2 ;d has the next sector to read ; note that we begin by reading track 0, sector 2 since sector 1 ; contains the cold start loader, which is skipped in a warm start lxi h,ccp ;base of cp/m (initial load point) load1: ;load one more sector push b ;save sector count, current track push d ;save next sector to read push h ;save dma addrcter output from register c mov a,c ;get to accumulator ds 10h ;space for output routine ret ; list: ;list character from register c mov a,c ;character to register a ret ;null subroutine ; listst: ;return list status (0 if not ready, 1 if ready) xra a ;0 is always ok to return ret ; punch: ;punch character from register c mov a,c ;character to register a ret ;null subroutine ; ; reader: ;read character into register a from reader device mvi a,1ah ;enter end of file for now (replace later) ani 7fh ;remember to strip parity bit ret ; ; ; i/o drivers for the disk follow ; for now, we will simply store the parameters away for use ; in the read and write subroutines ; home: ;move to the track 00 position of current drive ; translate this call into a settrk call with parameter 00 mvi c,0 ;select track 0 call settrk ret ;we will move to 00 on first read/write ; seldsk: ;select disk given by register C lxi h,0000h ;error return code mov a,c sta diskno cpi 4 bytes for expansion dmaad: ds 2 ;direct memory address diskno: ds 1 ;disk number 0-15 ; ; scratch ram area for BDOS use begdat equ $ ;beginning of data area dirbf: ds 128 ;scratch directory area all00: ds 31 ;allocation vector 0 all01: ds 31 ;allocation vector 1 all02: ds 31 ;allocation vector 2 all03: ds 31 ;allocation vector 3 chk00: ds 16 ;check vector 0 chk01: ds 16 ;check vector 1 chk02: ds 16 ;check vector 2 chk03: ds 16 ;check vector 3 ; enddat equ $ ;end of data area datsiz equ $-begdat;size of data area end ess mov c,d ;get sector address to register c call setsec ;set sector address from register c pop b ;recall dma address to b,c push b ;replace on stack for later recall call setdma ;set dma address from b,c ; ; drive set to 0, track set, sector set, dma address set call read cpi 00h ;any errors? jnz wboot ;retry the entire boot if an error occurs ; ; no error, move to next sector pop h ;recall dma address lxi d,128 ;dma=dma+128 dad d ;new dma address is in h,l pop d ;recall sector address pop b ;recall number of sectors remaining, and current trk dcr b ;sectors=sectors-1 jz gocpm ;transfer to cp/m if all have been loaded ; ; more sectors remain to load, check for track change inr d mov a,d ;sector=27?, if so, change tracks cpi 27 jc load1 ;carry generated if sector<27 ; ; end of current track, go to next track mvi d,1 ;begin with first sector of next track inr c ;track=track+1 ; ; save register state, and change tracks push b push d push h call settr;must be between 0 and 3 rnc ;no carry if 4,5,... ; disk number is in the proper range ds 10 ;space for disk select ; compute proper disk parameter header address lda diskno mov l,a ;L=disk number 0,1,2,3 mvi h,0 ;high order zero dad h ;*2 dad h ;*4 dad h ;*8 dad h ;*16 (size of each header) lxi d,dpbase dad d ;HL=.dpbase(diskno*16) ret ; settrk: ;set track given by register c mov a,c sta track ds 10h ;space for track select ret ; setsec: ;set sector given by register c mov a,c sta sector ds 10h ;space for sector select ret ; sectran: ;translate the sector given by BC using the ;translate table given by DE xchg ;HL=.trans dad b ;HL=.trans(sector) mov l,m ;L = trans(sector) mvi h,0 ;HL= trans(sector) ret ;with value in HL ; setdma: ;set dma address given by registers b and c mov l,c ;low order address mov h,b ;high order address shld dmaad ;save the address ds 10h ;space for setting the dma address ret ; read: ;perform read operatiok ;track address set from register c pop h pop d pop b jmp load1 ;for another sector ; ; end of load operation, set parameters and go to cp/m gocpm: mvi a,0c3h ;c3 is a jmp instruction sta 0 ;for jmp to wboot lxi h,wboote ;wboot entry point shld 1 ;set address field for jmp at 0 ; sta 5 ;for jmp to bdos lxi h,bdos ;bdos entry point shld 6 ;address field of jump at 5 to bdos ; lxi b,80h ;default dma address is 80h call setdma ; ei ;enable the interrupt system lda cdisk ;get current disk number mov c,a ;send to the ccp jmp ccp ;go to cp/m for further processing ; ; ; simple i/o handlers (must be filled in by user) ; in each case, the entry point is provided, with space reserved ; to insert your own code ; const: ;console status, return 0ffh if character ready, 00h if not ds 10h ;space for status subroutine mvi a,00h ret ; conin: ;console character into register a ds 10h ;space for input routine ani 7fh ;strip parity bit ret ; conout: ;console charan (usually this is similar to write ; so we will allow space to set up read command, then use ; common code in write) ds 10h ;set up read command jmp waitio ;to perform the actual i/o ; write: ;perform a write operation ds 10h ;set up write command ; waitio: ;enter here from read and write to perform the actual i/o ; operation. return a 00h in register a if the operation completes ; properly, and 01h if an error occurs during the read or write ; ; in this case, we have saved the disk number in 'diskno' (0,1) ; the track number in 'track' (0-76) ; the sector number in 'sector' (1-26) ; the dma address in 'dmaad' (0-65535) ds 256 ;space reserved for I/O drivers mvi a,1 ;error condition ret ;replaced when filled-in ; ; the remainder of the CBIOS is reserved uninitialized ; data area, and does not need to be a part of the ; system memory image (the space must be available, ; however, between "begdat" and "enddat"). ; track: ds 2 ;two bytes for expansion sector: ds 2 ;two '=COPYRIGHT (C) 1980, DIGITAL RESEARCH DDT VERS 2.2$10 !~=W!xe ~#Xbxʇ {z~#o}o҃i.2_!fp+q*e2_2_!hp+q*g!jp+q*i!lp+q*k!np+q*m2_!pp+q*oÃO$*sy͏ , $  ͌ 9!z6 # L!zw͌j# X:z 0 ͘=N#Fy}80*z{¯#z+++ ¥ z#½# · 9!`͠ y9!rͷ y=!z{w# % w!P͠ y͓}*w#"͌ @.@<!Eͷ~P !ͷ’P͌Q!ͷªP}QxQ!ͷ͓G@Q! ͷ y͓Gþ!ͷ ͓Q!ͷ͓Q͌Q!.ͷ6y#G͙Qà!2ͷQ͓͌Q!>ͷq eg͙Q:zJEËC–EQyQxQRQ** {zҷ*~#" <AOGƐ'@'OxƐ'@'ON#  ë «   Ͷ ͐ =« f xY |« }ҫ gA>S Ag}S S i |« }!w s#r:[ʔ _!~ʦ ![4ç \͢¦ 2[ 7 >?  e͢!g"c> _͢a_!f~> 5*c~#"c 0 7   > >  ͢| } @ >. *_}o| , 0 ë ^#V#!Y ))))o P q s#r#!V4 !V6# ,® >2Vñ m ͅ m ͅ m ͅ « Vʫ ! XN!~  ! _^! ^#V~ x+ >= = !~  . !   #x f L L ͓ͅ ҆ *" !6ï +"_*~ #E گ ʫ ^#V. ï ~ CZMEIABDHSP!"M"+"!91*~!O~6=G#^#V#~x (#"!N#FW( *J>7Å*M|N+"M N:LHͅÅD Å >* *͓ b" . *"] !/~##ʁtZ*F#n!Is!^#V&&##&))::^#V#*^#V>+)x-8_;***************************************************** ;* * ;* Sector Deblocking Algorithms for CP/M 2.0 * ;* * ;***************************************************** ; ; utility macro to compute sector mask smask macro hblk ;; compute log2(hblk), return @x as result ;; (2 ** @x = hblk on return) @y set hblk @x set 0 ;; count right shifts of @y until = 1 rept 8 if @y = 1 exitm endif ;; @y is not 1, shift right one position @y set @y shr 1 @x set @x + 1 endm endm ; ;***************************************************** ;* * ;* CP/M to host disk constants * ;* * ;***************************************************** blksiz equ 2048 ;CP/M allocation size hstsiz equ 512 ;host disk sector size hstspt equ 20 ;host disk sectors/trk hstblk equ hstsiz/1z8O!B N#N ¾SP.* |} !9":q!"28!"9:] !í 1)*)þ))>+><7"9.Yͯ * M^2U :2:2ͳ:_³ͯ !6! @!!BH @@ABH B! "BHI$$BI$BI $ HI D$HD$$ H B!$D$"$B$DA!ABI$H B$I $HI$H$! $I $I$$A !A@$I$"!$H$I$I "! $A$  HHAA"I @BB $A"$$$I$$H!!! BH" !I B  $$!BD! $!BI D@"!$I$$H"!I$I$I$UUU$$A$ 28 ;CP/M sects/host buff cpmspt equ hstblk * hstspt ;CP/M sectors/track secmsk equ hstblk-1 ;sector mask smask hstblk ;compute sector mask secshf equ @x ;log2(hstblk) ; ;***************************************************** ;* * ;* BDOS constants on entry to write * ;* * ;***************************************************** wrall equ 0 ;write to allocated wrdir equ 1 ;write to directory wrual equ 2 ;write to unallocated ; ;***************************************************** ;* * ;* The BDOS entry points given below show the * ;* code which is relevant to deblocking only. * ;* * ;***************************************************** ; ; DISKDEF macro, or hand coded tables go here dpbase equ $ ;disk param block base ; boot: wboot: ;enter here on system͓ !" >- Ͷ Aګ ҫ _!7^#V~  \p Z z ů2[\͓͢ ҫ ͐ =« f " ͓ ҫ ͐ ʻf " =ʻf "=« ý> 2͐ f "]=f =« *]}o"_  *]"a. ~ #E }"]*a 6 *]}#|#*]E ͐ « f f f {zA|« W}d ͐ f f f DMʡڏ"=ʡͲ=ʡYPͲ1**!O~4#~#F#x~#s#r#w>͐ « f f  . ᯕo>g. 2|2\  !]w# ʫ .&  0 6 #& .K !e K w# ʫ : U 6 #K 6AW w#] !e~H#~E#~X*}|́ "!́ ͐ !ʬ =« f kʫ j \͢F w# ͋ t ʫ : W& _& & O { `i"F & & w# & ͋ « t Y t Y GтWx ͢!o ~Z #N  *. *.  NEXT PC͐ =« f  . ~ Ͷ ʻ .͓ =« f |« }w#Ä >2L͐ ! =« f }ʫ +"MD Å D  !  #( boot to initialize xra a ;0 to accumulator sta hstact ;host buffer inactive sta unacnt ;clear unalloc count ret ; home: ;home the selected disk home: lda hstwrt ;check for pending write ora a jnz homed sta hstact ;clear host active flag homed: ret ; seldsk: ;select disk mov a,c ;selected disk number sta sekdsk ;seek disk number mov l,a ;disk number to HL mvi h,0 rept 4 ;multiply by 16 dad h endm lxi d,dpbase ;base of parm block dad d ;hl=.dpb(curdsk) ret ; settrk: ;set track given by registers BC mov h,b mov l,c shld sektrk ;track to seek ret ; setsec: ;set sector given by register c mov a,c sta seksec ;sector to seek ret ; setdma: ;set dma address given by BC mov h,b mov l,c shld dmaadr ret ; sectran: ;translate sector number BC mov h,b mov l,c ret ; ;***************************************************** ;* * ;* The READ entry point takes the place of ag ;rsflag = 0 jmp rwoper ;to perform the write ; alloc: ;not an unallocated record, requires pre-read xra a ;0 to accum sta unacnt ;unacnt = 0 inr a ;1 to accum sta rsflag ;rsflag = 1 ; ;***************************************************** ;* * ;* Common code for READ and WRITE follows * ;* * ;***************************************************** rwoper: ;enter here to perform the read/write xra a ;zero to accum sta erflag ;no errors (yet) lda seksec ;compute host sector rept secshf ora a ;carry = 0 rar ;shift right endm sta sekhst ;host sector to seek ; ; active host sector? lxi h,hstact ;host active flag mov a,m mvi m,1 ;always becomes 1 ora a ;was it already? jz filhst ;fill host if not ; ; host buffer active, same as seek buffer? lda sekdsk lxi h,hstdsk ;same disk? cmp m ;sekdsk = hstdsk? jnz nomatch ; ; same disk, same  inx d inx h ldax d cmp m ;sets flags ret ; ;***************************************************** ;* * ;* WRITEHST performs the physical write to * ;* the host disk, READHST reads the physical * ;* disk. * ;* * ;***************************************************** writehst: ;hstdsk = host disk #, hsttrk = host track #, ;hstsec = host sect #. write "hstsiz" bytes ;from hstbuf and return error flag in erflag. ;return erflag non-zero if error ret ; readhst: ;hstdsk = host disk #, hsttrk = host track #, ;hstsec = host sect #. read "hstsiz" bytes ;into hstbuf and return error flag in erflag. ret ; ;***************************************************** ;* * ;* Unitialized RAM data areas * ;* * ;***************************************************** ; * ;* the previous BIOS defintion for READ. * ;* * ;***************************************************** read: ;read the selected CP/M sector xra a sta unacnt mvi a,1 sta readop ;read operation sta rsflag ;must read data mvi a,wrual sta wrtype ;treat as unalloc jmp rwoper ;to perform the read ; ;***************************************************** ;* * ;* The WRITE entry point takes the place of * ;* the previous BIOS defintion for WRITE. * ;* * ;***************************************************** write: ;write the selected CP/M sector xra a ;0 to accumulator sta readop ;not a read operation mov a,c ;write type in c sta wrtype cpi wrual ;write unallocated? jnz chkuna ;check for unalloc ; ; write to unallocated, set parameters mvi a,blksiz/128 ;next unalloc recs sta unacnt lda setrack? lxi h,hsttrk call sektrkcmp ;sektrk = hsttrk? jnz nomatch ; ; same disk, same track, same buffer? lda sekhst lxi h,hstsec ;sekhst = hstsec? cmp m jz match ;skip if match ; nomatch: ;proper disk, but not correct sector lda hstwrt ;host written? ora a cnz writehst ;clear host buff ; filhst: ;may have to fill the host buffer lda sekdsk sta hstdsk lhld sektrk shld hsttrk lda sekhst sta hstsec lda rsflag ;need to read? ora a cnz readhst ;yes, if 1 xra a ;0 to accum sta hstwrt ;no pending write ; match: ;copy data to or from buffer lda seksec ;mask buffer number ani secmsk ;least signif bits mov l,a ;ready to shift mvi h,0 ;double count rept 7 ;shift left 7 dad h endm ; hl has relative host buffer address lxi d,hstbuf dad d ;hl = host address xchg ;now in DE lhld dmaadr ;get/put CP/M data mvi c,128 ;length of move lda readop ;which way? ora a jnz rwmove ;skip if read ; ; write operation, mark and switch sekdsk: ds 1 ;seek disk number sektrk: ds 2 ;seek track number seksec: ds 1 ;seek sector number ; hstdsk: ds 1 ;host disk number hsttrk: ds 2 ;host track number hstsec: ds 1 ;host sector number ; sekhst: ds 1 ;seek shr secshf hstact: ds 1 ;host active flag hstwrt: ds 1 ;host written flag ; unacnt: ds 1 ;unalloc rec cnt unadsk: ds 1 ;last unalloc disk unatrk: ds 2 ;last unalloc track unasec: ds 1 ;last unalloc sector ; erflag: ds 1 ;error reporting rsflag: ds 1 ;read sector flag readop: ds 1 ;1 if read operation wrtype: ds 1 ;write operation type dmaadr: ds 2 ;last dma address hstbuf: ds hstsiz ;host buffer ; ;***************************************************** ;* * ;* The ENDEF macro invocation goes here * ;* * ;***************************************************** end kdsk ;disk to seek sta unadsk ;unadsk = sekdsk lhld sektrk shld unatrk ;unatrk = sectrk lda seksec sta unasec ;unasec = seksec ; chkuna: ;check for write to unallocated sector lda unacnt ;any unalloc remain? ora a jz alloc ;skip if not ; ; more unallocated records remain dcr a ;unacnt = unacnt-1 sta unacnt lda sekdsk ;same disk? lxi h,unadsk cmp m ;sekdsk = unadsk? jnz alloc ;skip if not ; ; disks are the same lxi h,unatrk call sektrkcmp ;sektrk = unatrk? jnz alloc ;skip if not ; ; tracks are the same lda seksec ;same sector? lxi h,unasec cmp m ;seksec = unasec? jnz alloc ;skip if not ; ; match, move to next sector for future ref inr m ;unasec = unasec+1 mov a,m ;end of track? cpi cpmspt ;count CP/M sectors jc noovf ;skip if no overflow ; ; overflow to next track mvi m,0 ;unasec = 0 lhld unatrk inx h shld unatrk ;unatrk = unatrk+1 ; noovf: ;match found, mark as unnecessary read xra a ;0 to accumulator sta rsfl direction mvi a,1 sta hstwrt ;hstwrt = 1 xchg ;source/dest swap ; rwmove: ;C initially 128, DE is source, HL is dest ldax d ;source character inx d mov m,a ;to dest inx h dcr c ;loop 128 times jnz rwmove ; ; data has been moved to/from host buffer lda wrtype ;write type cpi wrdir ;to directory? lda erflag ;in case of errors rnz ;no further processing ; ; clear host buffer for directory write ora a ;errors? rnz ;skip if so xra a ;0 to accum sta hstwrt ;buffer written call writehst lda erflag ret ; ;***************************************************** ;* * ;* Utility subroutine for 16-bit compare * ;* * ;***************************************************** sektrkcmp: ;HL = .unatrk or .hsttrk, compare with sektrk xchg lxi h,sektrk ldax d ;low byte compare cmp m ;same? rnz ;return if not ; low bytes equal, test high 1s); CP/M 2.0 disk re-definition library ; ; Copyright (c) 1979 ; Digital Research ; Box 579 ; Pacific Grove, CA ; 93950 ; ; CP/M logical disk drives are defined using the ; macros given below, where the sequence of calls ; is: ; ; disks n ; diskdef parameter-list-0 ; diskdef parameter-list-1 ; ... ; diskdef parameter-list-n ; endef ; ; where n is the number of logical disk drives attached ; to the CP/M system, and parameter-list-i defines the ; characteristics of the ith drive (i=0,1,...,n-1) ; ; each parameter-list-i takes the form ; dn,fsc,lsc,[skf],bls,dks,dir,cks,ofs,[0] ; where ; dn is the disk number 0,1,...,n-1 ; fsc is the first sector number (usually 0 or 1) ; lsc is the last sector number on a track ; skf is optional "skew factor" for sector translate ; bls is the data block size (1024,2048,...,16384) ; dks is the disk size in bls increments (word) ; dir is the number of directory elements (word) ; cks is the number of dir elements to checksum ; ofs is the number of u als&fsc ;same allocation vector size css&dn equ css&fsc ;same checksum vector size xlt&dn equ xlt&fsc ;same translate table else secmax set lsc-(fsc) ;;sectors 0...secmax sectors set secmax+1;;number of sectors als&dn set (dks)/8 ;;size of allocation vector if ((dks) mod 8) ne 0 als&dn set als&dn+1 endif css&dn set (cks)/4 ;;number of checksum elements ;; generate the block shift value blkval set bls/128 ;;number of sectors/block blkshf set 0 ;;counts right 0's in blkval blkmsk set 0 ;;fills with 1's from right rept 16 ;;once for each bit position if blkval=1 exitm endif ;; otherwise, high order 1 not found yet blkshf set blkshf+1 blkmsk set (blkmsk shl 1) or 1 blkval set blkval/2 endm ;; generate the extent mask byte blkval set bls/1024 ;;number of kilobytes/block extmsk set 0 ;;fill from right with 1's rept 16 if blkval=1 exitm endif ;; otherwise more to shift extmsk set (extmsk shl 1) or 1 blkval set blkval/2 endm ;; may be double byte allocation if (dks)nddat equ $ datsiz equ $-begdat ;; db 0 at this point forces hex record endm ; tracks to skip (word) ; [0] is an optional 0 which forces 16K/directory entry ; ; for convenience, the form ; dn,dm ; defines disk dn as having the same characteristics as ; a previously defined disk dm. ; ; a standard four drive CP/M system is defined by ; disks 4 ; diskdef 0,1,26,6,1024,243,64,64,2 ; dsk set 0 ; rept 3 ; dsk set dsk+1 ; diskdef %dsk,0 ; endm ; endef ; ; the value of "begdat" at the end of assembly defines the ; beginning of the uninitialize ram area above the bios, ; while the value of "enddat" defines the next location ; following the end of the data area. the size of this ; area is given by the value of "datsiz" at the end of the ; assembly. note that the allocation vector will be quite ; large if a large disk size is defined with a small block ; size. ; dskhdr macro dn ;; define a single disk header list dpe&dn: dw xlt&dn,0000h ;translate table dw 0000h,0000h ;scratch area dw dirbuf,dpb&dn ;dir buff,parm block dw csv&dn,alv&dn ;check, alloc vec > 256 extmsk set (extmsk shr 1) endif ;; may be optional [0] in last position if not nul k16 extmsk set k16 endif ;; now generate directory reservation bit vector dirrem set dir ;;# remaining to process dirbks set bls/32 ;;number of entries per block dirblk set 0 ;;fill with 1's on each loop rept 16 if dirrem=0 exitm endif ;; not complete, iterate once again ;; shift right and add 1 high order bit dirblk set (dirblk shr 1) or 8000h if dirrem > dirbks dirrem set dirrem-dirbks else dirrem set 0 endif endm dpbhdr dn ;;generate equ $ ddw %sectors,<;sec per track> ddb %blkshf,<;block shift> ddb %blkmsk,<;block mask> ddb %extmsk,<;extnt mask> ddw %(dks)-1,<;disk size-1> ddw %(dir)-1,<;directory max> ddb %dirblk shr 8,<;alloc0> ddb %dirblk and 0ffh,<;alloc1> ddw %(cks)/4,<;check size> ddw %ofs,<;offset> ;; generate the translate table, if requested if nul skf xlt&dn equ 0 ;no xlate table else if skf = 0 xlt&dn equ 0 ;no xlate table else ;; generators endm ; disks macro nd ;; define nd disks ndisks set nd ;;for later reference dpbase equ $ ;base of disk parameter blocks ;; generate the nd elements dsknxt set 0 rept nd dskhdr %dsknxt dsknxt set dsknxt+1 endm endm ; dpbhdr macro dn dpb&dn equ $ ;disk parm block endm ; ddb macro data,comment ;; define a db statement db data comment endm ; ddw macro data,comment ;; define a dw statement dw data comment endm ; gcd macro m,n ;; greatest common divisor of m,n ;; produces value gcdn as result ;; (used in sector translate table generation) gcdm set m ;;variable for m gcdn set n ;;variable for n gcdr set 0 ;;variable for r rept 65535 gcdx set gcdm/gcdn gcdr set gcdm - gcdx*gcdn if gcdr = 0 exitm endif gcdm set gcdn gcdn set gcdr endm endm ; diskdef macro dn,fsc,lsc,skf,bls,dks,dir,cks,ofs,k16 ;; generate the set statements for later tables if nul lsc ;; current disk dn same as previous fsc dpb&dn equ dpb&fsc ;equivalent parameters als&dn eqte the translate table nxtsec set 0 ;;next sector to fill nxtbas set 0 ;;moves by one on overflow gcd %sectors,skf ;; gcdn = gcd(sectors,skew) neltst set sectors/gcdn ;; neltst is number of elements to generate ;; before we overlap previous elements nelts set neltst ;;counter xlt&dn equ $ ;translate table rept sectors ;;once for each sector if sectors < 256 ddb %nxtsec+(fsc) else ddw %nxtsec+(fsc) endif nxtsec set nxtsec+(skf) if nxtsec >= sectors nxtsec set nxtsec-sectors endif nelts set nelts-1 if nelts = 0 nxtbas set nxtbas+1 nxtsec set nxtbas nelts set neltst endif endm endif ;;end of nul fac test endif ;;end of nul bls test endm ; defds macro lab,space lab: ds space endm ; lds macro lb,dn,val defds lb&dn,%val&dn endm ; endef macro ;; generate the necessary ram data areas begdat equ $ dirbuf: ds 128 ;directory access buffer dsknxt set 0 rept ndisks ;;once for each disk lds alv,%dsknxt,als lds csv,%dsknxt,css dsknxt set dsknxt+1 endm e*; FILE DUMP PROGRAM, READS AN INPUT FILE AND PRINTS IN HEX ; ; COPYRIGHT (C) 1975, 1976, 1977, 1978 ; DIGITAL RESEARCH ; BOX 579, PACIFIC GROVE ; CALIFORNIA, 93950 ; ORG 100H BDOS EQU 0005H ;DOS ENTRY POINT CONS EQU 1 ;READ CONSOLE TYPEF EQU 2 ;TYPE FUNCTION PRINTF EQU 9 ;BUFFER PRINT ENTRY BRKF EQU 11 ;BREAK KEY FUNCTION (TRUE IF CHAR READY) OPENF EQU 15 ;FILE OPEN READF EQU 20 ;READ FUNCTION ; FCB EQU 5CH ;FILE CONTROL BLOCK ADDRESS BUFF EQU 80H ;INPUT DISK BUFFER ADDRESS ; ; NON GRAPHIC CHARACTERS CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED ; ; FILE CONTROL BLOCK DEFINITIONS FCBDN EQU FCB+0 ;DISK NAME FCBFN EQU FCB+1 ;FILE NAME FCBFT EQU FCB+9 ;DISK FILE TYPE (3 CHARACTERS) FCBRL EQU FCB+12 ;FILE'S CURRENT REEL NUMBER FCBRC EQU FCB+15 ;FILE'S RECORD COUNT (0 TO 128) FCBCR EQU FCB+32 ;CURRENT (NEXT) RECORD NUMBER (0 TO 127) FCBLN EQU FCB+33 ;FCB LENGTH ; ; SET UP STACK LXI H,0 DAD SP ; ENTRY STACK POINTER IN HL FROM THE CCP SHLD OLDSP ; SET SP TO LOCAL STACK AR ; READ ANOTHER BUFFER ; ; CALL DISKR ORA A ;ZERO VALUE IF READ OK JZ G0 ;FOR ANOTHER BYTE ; END OF DATA, RETURN WITH CARRY SET FOR EOF STC RET ; G0: ;READ THE BYTE AT BUFF+REG A MOV E,A ;LS BYTE OF BUFFER INDEX MVI D,0 ;DOUBLE PRECISION INDEX TO DE INR A ;INDEX=INDEX+1 STA IBP ;BACK TO MEMORY ; POINTER IS INCREMENTED ; SAVE THE CURRENT FILE ADDRESS LXI H,BUFF DAD D ; ABSOLUTE CHARACTER ADDRESS IS IN HL MOV A,M ; BYTE IS IN THE ACCUMULATOR ORA A ;RESET CARRY BIT RET ; SETUP: ;SET UP FILE ; OPEN THE FILE FOR INPUT XRA A ;ZERO TO ACCUM STA FCBCR ;CLEAR CURRENT RECORD ; LXI D,FCB MVI C,OPENF CALL BDOS ; 255 IN ACCUM IF OPEN ERROR RET ; DISKR: ;READ DISK FILE RECORD PUSH H! PUSH D! PUSH B LXI D,FCB MVI C,READF CALL BDOS POP B! POP D! POP H RET ; ; FIXED MESSAGE AREA SIGNON: DB 'FILE DUMP VERSION 1.4$' OPNMSG: DB CR,LF,'NO INPUT FILE PRESENT ON DISK$' ; VARIABLE AREA IBP: DS 2 ;INPUT BUFFER POINTER OLDSP: DS 2 ;ENTRY SP VALUE FROM CCP ;!9"1W͜Q>2!͢QG}DrYQ|͏}͏#> ex͏#r* _> e> e ҉0Ë7e}} :³ʳ7_<2!~ɯ2|\\FILE DUMP VERSION 1.4$ NO INPUT FILE PRESENT ON DISK$!Y , <    *$A!6 # T!w $r# *`: 0 *A*! ~ ʰxkb))))_y‘BK{ͅ*!66!"80*{#z+++ #EA (RESTORED AT FINIS) LXI SP,STKTOP ; READ AND PRINT SUCCESSIVE BUFFERS CALL SETUP ;SET UP INPUT FILE CPI 255 ;255 IF FILE NOT PRESENT JNZ OPENOK ;SKIP IF OPEN IS OK ; ; FILE NOT THERE, GIVE ERROR MESSAGE AND RETURN LXI D,OPNMSG CALL ERR JMP FINIS ;TO RETURN ; OPENOK: ;OPEN OPERATION OK, SET BUFFER INDEX TO END MVI A,80H STA IBP ;SET BUFFER POINTER TO 80H ; HL CONTAINS NEXT ADDRESS TO PRINT LXI H,0 ;START WITH 0000 ; GLOOP: PUSH H ;SAVE LINE POSITION CALL GNB POP H ;RECALL LINE POSITION JC FINIS ;CARRY SET BY GNB IF END FILE MOV B,A ; PRINT HEX VALUES ; CHECK FOR LINE FOLD MOV A,L ANI 0FH ;CHECK LOW 4 BITS JNZ NONUM ; PRINT LINE NUMBER CALL CRLF ; ; CHECK FOR BREAK KEY CALL BREAK ; ACCUM LSB = 1 IF CHARACTER READY RRC ;INTO CARRY JC FINIS ;DON'T PRINT ANY MORE ; MOV A,H CALL PHEX MOV A,L CALL PHEX NONUM: INX H ;TO NEXT LINE NUMBER MVI A,' ' CALL PCHAR MOV A,B CALL PHEX JMP GLOOP ; FINIS: ; END OF DUMP, RETURN TO CCP ; (NOTE  ; STACK AREA DS 64 ;RESERVE 32 LEVEL STACK STKTOP: ; END THAT A JMP TO 0000H REBOOTS) CALL CRLF LHLD OLDSP SPHL ; STACK POINTER CONTAINS CCP'S STACK LOCATION RET ;TO THE CCP ; ; ; SUBROUTINES ; BREAK: ;CHECK BREAK KEY (ACTUALLY ANY KEY WILL DO) PUSH H! PUSH D! PUSH B; ENVIRONMENT SAVED MVI C,BRKF CALL BDOS POP B! POP D! POP H; ENVIRONMENT RESTORED RET ; PCHAR: ;PRINT A CHARACTER PUSH H! PUSH D! PUSH B; SAVED MVI C,TYPEF MOV E,A CALL BDOS POP B! POP D! POP H; RESTORED RET ; CRLF: MVI A,CR CALL PCHAR MVI A,LF CALL PCHAR RET ; ; PNIB: ;PRINT NIBBLE IN REG A ANI 0FH ;LOW 4 BITS CPI 10 JNC P10 ; LESS THAN OR EQUAL TO 9 ADI '0' JMP PRN ; ; GREATER OR EQUAL TO 10 P10: ADI 'A' - 10 PRN: CALL PCHAR RET ; PHEX: ;PRINT HEX CHAR IN REG A PUSH PSW RRC RRC RRC RRC CALL PNIB ;PRINT NIBBLE POP PSW CALL PNIB RET ; ERR: ;PRINT ERROR MESSAGE ; D,E ADDRESSES MESSAGE ENDING WITH "$" MVI C,PRINTF ;PRINT BUFFER FUNCTION CALL BDOS RET ; ; GNB: ;GET NEXT BYTE LDA IBP CPI 80H JNZ G0 + COPYRIGHT (C) 1979, DIGITAL RESEARCH DISK OR DIRECTORY FULL$FILE EXISTS, ERASE IT$NEW FILE$** FILE IS READ/ONLY **$"SYSTEM" FILE NOT ACCESSIBLE$BAK$$$BAK$$$-(Y/N)?$NO MEMORY$BREAK "$" AT $1mM"m +!8s~1m!f6 *M  *!M 1m! 6!6! 6: 2Ebͽ!e:d\::eH2 H҆ͽ:e2!:d2e:!2dû :!I¬!: :H2 ҮX:h2iҐ:!ʍ:!:!H:!H,!"! 6#~ F)ͷX:! X):i!h)9 e:!:h2jO>F L>!":i!jHҼ*"+M ~ ʼͲ!f6!h6!"! 6F!f6:h2k!iҠ:i2k:j2h:k!hҶ9 æ:h2j!!6:j2he:! >"Ͳ*"M ~2!O :! *+":7 e !p+q*DM  =? ) !p+q.*DMF -L *9"`!"b!h6!j6!|6.!=\ -x !e:dʥ *eM \R :xʥ @ *dM \, :x \͕ :x - V :e _ :f w : =e !e:d*eM =e : =e =͕ !]6:x>- !"!76!6!6!66*dM  *dM !6:8!*`*;DM \u 2xʻ>!xҨ- *`*;6:82*`"`:<2w!"`9`h*`*;~2*`#"`:*eM !b+!s{!f!6:!b*b*^DM =ͅ N- *b"b:<2)f!"b!q9bڀ*b*^:w*b#"b!q:6ڶZͅ ʱ- !66*6& :w:6<26!J6*b}:J<2Jm=? :x- : ;*dM .=\ -=ͨ ;: *eM =ͨ .M= -C!q:Y*M !q:a/>z!/H!q*MaҎ:_:!q:ҥ*My:!p+q!'"!6>**ͪ{2**ͪ"*! ͪ":!!*FM8 *FM   Oy2F :FY5>>:!02HO> /!";u*)))*) *H& "PҘ! 6+s#ré! 6"DM!>))덑o|g =±^#V) ^#V|g}o _{ozgi`N#Fogo&og_{_z#W H = LIBX$$$$$$$LIB!!6e*!M͛ /$^L:!@OL:! 2͑e:b:! L:h<2hb:! b:hO>!hw:! pX:! …!!6  LÊ!!6ûô:!ʛ͑:! ҩ OҸû:!R†!6G>!!!6 :2.t -? >!!6!6s, !6:xB!6OU2!SB!G6:҃!6:G҃*G& ~2!:G<2G_ Qқ=e  b:!-®! 6:!#¿͇;J:!:!!6Lv:!:Jv: *#"͎! 6:!B)! >w!"&*o"(R :!C:eR :!DKeX :!K\ͷX :!Lj^ :!Pš͎҇! 6F×͢җ:Ç :!T¨F :!U¾: 2 :!V͎"$DMͩ/ *oDMͩ : 2 :! (::H%^bF : ͎H :!Ay! 6*""&*o"(R͎an͢na! 6R :!F”͢ґ Ä :!J $:2$͢ :=2:<2!*& ~2!ü*""I*M*o/!:"6:0O  ú!p+q:/(*DMͩ:  : I N* *DM:aO>!Һ x!: ڦ> ʡ* +" >¡! 6: <2 =O! N͒:  O͒: ! 6:h!o$O* ͸ ! 6 !h6!: 2 3* & 6 : <2 =O! N͒*dM  :sGsu n>!6:<2=O! N͒!">!"͎/Ҵ*+">>!": *#"*""*!".+",*$"**o".!",!36:3{.*22*,**"0M ~ H3*0"**+"*+">23:2/k!36,*+s#rx:3x*0"*: “**"&*"+"(á*$#"&**#"(*"#""*$#"$*"+""*$+"$*#"!4qM*"*$: *(y"$DM}|C#~ *#"*&DMyxC 1*+":4?w+"$""ͷR: —*$"("҈!"&Ô""&*""&$mڸ*o"(**$"($"O26͛*"M :6w͢:6 "&! 6R*I""ë :!M:H| ! 6>F ͛e: <2 O! Hqy d F : 2! 6*#s#r :!N ͢ *o/ Ҧ Ͷn! 6!"&R! 6o$ Î Ç :!S0 $͢- :2"+s#r!:* *& ~2!:<2 :!W> v :!X³ Z͎\ Ee ð :7/҃ E!76e ͕ :xƒ - ͷ*&"K(Kڰ *KM N͔*K"KҌ :!Z ͎  ͢ : :!  'v!gq:f *g&!lq:l $ !h4:l 1 !h6*lM :hB     !h55!mq:m :hO>H2ny} !m6 !o6:n!oښ *mM !o4‚ !pq:p ڪ >:p :p H:p H!qq*qM͛  ^W :q@2q*qMW   !sp+q*r !up+q *tDM !wp+q*v !zp+q*y2x!|p+q*{2x!~p+q*}2x!p+q*!p+q*!p+q*!p+q*2x!p+q*!6   >>! q* &!p+q*!7q:*7M͒:7o$+͛ͪ*$M ~28Om:8 I͇͢u$oqo͛rP! 6!"&*$"(R͎ҔM͢ҡÔ($ҵ! 6R͇vͶ2!*!Mm$"*"M :!w͢:! e2!:! : /HH/Q:! @!!6 R!!6 :!KR$*& :!w:<2dn!:s+q*$";!>6:>/;oH*;#"(";:92=*=& *(M !::=2>/H:=<2=*(#"(æÀ:>*(+"(R:>!6$:2*o/*!My:<2=O!s Hq**DMͷ! 6: e!"*""?k*&"?*?+M ~2A :hHҏ *&"?(?:A ½8*#" ҽ*?M ~2AO *?"?ҕ!"*"*"^: 2B! 6F:B2 o(>&H6͛9!C6>!Ca R>:C<2C?! 6!"͇͢Ґq"ڊ͛Íq!!6 !!6 !6*!Ma2D*!M͒2!:D/!+w!6e2!͢!Eq!E:!:H:H!Fq,***************************************************************** * * * Disk format program for Disk Jockey 2D controller. * * 11/16/79 * * * ***************************************************************** title '*** Format Program for CP/M Ver. 2.0 ***' org 100h revnum equ 52 ;Revision # times 10 bdos equ 5 ;CP/M entry point wboot equ 0 origin equ 0F800H DISKIO EQU ORIGIN+3f8h DATREG EQU DISKIO+7 DRVSEL EQU DISKIO+1 CSTALL EQU DISKIO+3 CMDREG EQU DISKIO+4 DSIDE EQU 10Q UNLOADB EQU 17Q WTCMD EQU 364Q SICMD EQU 131Q IMMIRQ EQU 320Q UNLOADA EQU 30Q RESTOR EQU 11Q INDEX EQU 20Q TRKZRO EQU 4 intrqa equ 1 intrqb equ 4 lhsdenb equ 90dh lhddenb equ 80ch lhsdena equ 111h lhddena equ 10h acr equ 0dh alf equ 0ah START lxi sp,stack LHLD ORIGIN+7 ;adjust INX H ; the MOV A,M ; calling LXI H,STDVSL+1 ; routines LXI D,4 ; for MOV M,A ; different XRI 3 ; versions DAD D ; of the MOV M,A ; disk DAD D ; jockey a newsize add a jz findix mov l,a mvi h,0 DAD D MOV C,M INX H MOV B,M LXI H,SLIST CALL OVLAY LXI B,DDLIST LXI H,DLIST CALL OVLAY call model lxi b,lhddena jz loadd lxi b,lhddenb loadd mov a,b call stbits mov a,c call stbits FINDIX CALL INDEXP MVI H,1 TKSTEP mvi a,'*' call pchar LXI D,CMDREG MVI A,SICMD STAX D WSICMS LDAX D RAR JNC WSICMS WSICMD LDAX D RAR JC WSICMD CALL TRACK MOV H,D INR H MVI A,77 CMP H JNZ TKSTEP call unload lxi d,fmessg call pbuff call rbuff cpi 'F' jz crok jmp wboot SENDMP PUSH h ;save second half CALL pbuff ;send first half LDA LETTER ;print the CALL pchar ; letter POP d ;send the second pbuff mvi c,9 jmp bdos rbuff lxi d,inbufx mvi c,10 call bdos lda inbufx+1 ana a mvi a,acr rz lda inbuf cpi 'a' rc cpi 'z'+1 rnc sui 40q ret pchar push h push b push d push psw mov e,a mvi c,2 call bdos pop psw pop d pop b pop h ret inbufx  and data mark WTL9 MVI M,0FBH ;data mark LXI B,0e540H ;data & count OVLS2 EQU $-2 WTL10 MOV M,B ;write first DCR C ; quarter of JNZ WTL10 ; sector data MVI C,40H ;count OVLS3 EQU $-1 WTL11 MOV M,B ;write second DCR C ; quarter of JNZ WTL11 ; sector data MVI C,40H ;count OVLS4 EQU $-1 WTL12 MOV M,B ;write third DCR C ; quarter of JNZ WTL12 ; sector data MVI C,40H ;count OVLS5 EQU $-1 WTL13 MOV M,B ;write fourth DCR C ; quarter of JNZ WTL13 ; sector data MVI M,0F7H ;crc data bytes MVI A,27 ;last sector + 1 OVLS6 EQU $-1 LXI B,4E36H ;count & data OVLS7 EQU $-2 WTL14 MOV M,B ;data DCR C ; postamble JNZ WTL14 ; field CMP E ;last sector test JNZ SLOOP WTL15 MOV M,B ;fill data DCR C ; to index hole JNZ WTL15 WTL16 MOV M,B ;fill data DCR C ; to index hole JNZ WTL16 WTL17 MOV M,B ;fill data DCR C ; to index hole JNZ WTL17 RET OVLAY MOV A,M ;length of list PUSH H ;save list ptr LXI H,WTRACK ;overlay area XTHL ; recoMOV M,A ; controller LXI d,SMESSG ;print the CALL pbuff ; sign on message CROK LXI d,DMESSG ;echo the CR and CALL pbuff ; print drive select CALL rbuff ;wait for response CPI 'N' ; new parameter JZ CROK ; request STA LETTER ;save for exit SUI 'A' ;test for good JP NOTLOW ; drive select INPUTB LXI d,BMESSG ;print the bad CALL pbuff ; input message JMP CROK ; and wait for input NOTLOW CPI 4 ;test for drive JP INPUTB ; select too large STA DRVNO ;save drive no. fmtsiz lxi d,denmsg ;Select the sector size call pbuff call rbuff cpi 'N' jz CROK sui '1' ;Strip off ASCII bias jp sizchk sizerr lxi d,bmessg call pbuff jmp fmtsiz sizchk cpi 4 jnc sizerr sta newsize SENDI LXI d,IMESSG ;send out the LXI h,JMESSG ; diskette insert CALL SENDMP ; message GETIN2 CALL rbuff ;wait for response CPI 'N' ;test for new JZ CROK ; parameter request PROCED lxi d,acralf call pbuff LDA DRVNO ;get the drive no MOdb 10,0 inbuf db 0,0,0,0,0,0,0,0,0,0 STDVSL STA DISKIO+1 RET STBITS STA DISKIO+2 RET GTSTAT LDA DISKIO+2 RET model lda diskio-4 cpi (ret) ret unload call model mvi a,unloada jz stbits mvi a,unloadb jmp stbits gtindx call model mvi b,0 rz mvi b,index ret INDEXP call gtindx windxh call gtstat ANI INDEX xra b JZ windxh windxl call gtstat ani index xra b jnz windxl ret indxw call gtindx jmp windxl TABLE DW L128 DW L256 DW L512 DW L1024 TRACK lda select call stdvsl XRA A STA SIDENO CALL WTRACK call gtstat ANI DSIDE RNZ INR A STA SIDENO LDA SELECT ANI 357Q call stdvsl WIL call indxw XCHG WTRACK LXI D,DATREG ;1791 data reg MVI L,1 ;initialize sector reg LXI B,4e50H ;data & count OVLD1 EQU $-2 MVI A,WTCMD ;issue a write STA CMDREG ; track command XCHG ;adjust the registers WTL1 MOV M,B ;index mark DCR C ; preamble JNZ WTL1 ; field LXI B,0CH ;data & count OVLD2 EQU $-2 WTL2 MOV M,B ver pointer MVI D,0 OVLAY1 INX H ;increment pointer MOV E,M ;get offset XTHL ;exchange pointers DAD D ;add the offset PUSH PSW ;save length count LDAX B ;get replacement data MOV M,A ;do the replacement INX B ;next replacement data POP PSW ;recover length count DCR A ;decrement XTHL ;exchange pointers JNZ OVLAY1 POP H ;adjust stack RET * The lists below represents the distances * between successive locations of the WTRACK * routine that are to be overlaid in order * that the same routine will serve to format * different sized and density diskette * sector formats DLIST DB 18 ;length of list DB OVLD1-WTRACK DB 1 DB OVLD2-OVLD1-1 DB OVLD3-OVLD2 DB 1 DB 1 DB OVLD4-OVLD3-2 DB 1 DB OVLD5-OVLD4-1 DB OVLD6-OVLD5 DB 1 DB 1 DB OVLD7-OVLD6-2 DB 1 DB OVLD8-OVLD7-1 DB OVLD9-OVLD8 DB 1 DB 1 SLIST DB 9 ;list length DB OVLS1-WTRACK DB OVLS2-OVLS1 DB 1 DB OVLS3-OVLS2-1 DB OVLS4-OVLS3 DB OVLS5-OVLS4 DB OVLS6-OVLS5 DB OVLS7-OVLS6 V C,A MVI A,177Q ;drive select bits QLOOP RLC ;rotate select bits DCR C ; to proper drive JP QLOOP ; position ani 3fh STA SELECT ;save for TRACK routine call stdvsl call model lxi b,lhsdena jz prep lxi b,lhsdenb prep mov a,b call stbits mov a,c call stbits lxi h,cmdreg mvi m,immirq mvi a,40h wirqd dcr a jnz wirqd mov a,m rar jc notrdy ral ral jc notrdy lxi d,wmessg ral jc notrdyx LXI D,0 call gtindx IXLOOP call gtstat ani index xra b JNZ dorest DCX D MOV A,D ORA E JNZ IXLOOP NOTRDY LXI d,RMESSG ;not ready message notrdyx xchg LXI d,AMESSG ;drive message CALL SENDMP ;send error message call unload JMP SENDI ;back for more input dorest MVI M,RESTOR wrstrs mov a,m rar jnc wrstrs wrstrd MOV A,M rar jc wrstrd MOV A,M ANI TRKZRO JZ NOTRDY LXI B,SDLIST LXI H,DLIST CALL OVLAY LXI B,L128 LXI H,SLIST CALL OVLAY mvi a,'*' call pchar CALL INDEXP MVI H,0 CALL TRACK LXI D,TABLE ld;index mark DCR C ; zero leader JNZ WTL2 ; field OVLD3 MVI M,0F6H ;special double MVI M,0F6H ; density clock MVI M,0F6H ; and data mark WTL3 MVI M,0FCH ;index mark LXI B,4E32H ;data & count OVLD4 EQU $-2 WTL4 MOV M,B ;sector mark DCR C ; preamble JNZ WTL4 ; field SLOOP LXI B,0CH ;data & count OVLD5 EQU $-2 WTL5 MOV M,B ;sector mark DCR C ; zero leader JNZ WTL5 ; field OVLD6 MVI M,0F5H ;special double MVI M,0F5H ; density clock MVI M,0F5H ; and data mark WTL6 MVI M,0FEH ;sector mark MOV M,D ;track number MVI M,0 ;side number SIDENO EQU $-1 MOV M,E ;sector number MVI M,1 ;sector length OVLS1 EQU $-1 MVI M,0F7H ;crc data bytes INR E ;increment sector LXI B,4E16H ;data & count OVLD7 EQU $-2 WTL7 MOV M,B ;sector mark DCR C ; postamble JNZ WTL7 ; field LXI B,0CH ;data & count OVLD8 EQU $-2 WTL8 MOV M,B ;data mark DCR C ; zero leader JNZ WTL8 ; field OVLD9 MVI M,0F5H ;special double MVI M,0F5H ; density clock MVI M,0F5H ;- DB 1 * Overlay data for single density * formatted diskettes SDLIST DW 0FF28H DB 6 JMP WTL3 DW 0FF1AH DB 6 JMP WTL6 DW 0FF0BH DB 6 JMP WTL9 * Overlay data for double density * formatted diskettes DDLIST DW 4E50H DB 0CH MVI M,0F6H DB 36H DW 4E32H DB 0CH MVI M,0F5H DB 36H DW 4E16H DB 0CH MVI M,0F5H DB 36H * Overlay data for single density * 26 sectors/track 128 byte sectors L128 DB 0 DW 0e520H DB 20H DB 20H DB 20H DB 27 DW 0FF1BH * Overlay data for double density * 26 sectors/track 256 byte sectors L256 DB 1 DW 0e540H DB 40H DB 40H DB 40H DB 27 DW 4E36H * Overlay data for double density * 15 sectors/track 512 byte sectors L512 DB 2 DW 0e580H DB 80H DB 80H DB 80H DB 16 DW 4E6AH * Overlay data for double density * 8 sectors/track 1024 byte sectors L1024 DB 3 DW 0e500H DB 0 DB 0 DB 0 DB 9 DW 4E74H AMESSG db acr,alf db 'Drive $' RMESSG db ' Is Not Ready.$' WMESSG db ' Is Write Prpe "^C" to return to CP/M, "N" to restart.$ Insert a Write Enabled Diskette in Drive $ Close the Drive Door and then Press RETURN: $ Function Complete. Type RETURN to return to CP/M, or F to Format another: $ Select a sector size: 1) 128 Byte Single density. 2) 256 Byte Double density. 3) 512 Byte Double Density. 4) 1024 Byte Double Density. Sector Size: $ $#fo !~#fo !~#fo##yx#B !N#F!<! <͢!>w#w!!~#fo!~#fo   !~#fo##~#fo!~#fo !~#fo}o|g}!~#fo##~#fo!~#fo ~OGyOxG!~#fo}o|gy xf !~#fo##~#fo!~#fo !<! <͢f !N#F!~#fo##N#F!~#foN#Fͬ!yD x#v !N#F!;<! <͢v !~w#~wM !>w#w!!  # !!~#fo!yOx#G>>  !N#F!yOx#Gywx#w!!N#F!}|!~#fo}o|g} !~w#~w !~#fo##~#fo!~#fo !~#fo }o|g} !~#fo##~#fo!~#fo !~#fo  }o|gMD!N#F!!~#foN#Fͬ!yª x# !N#F!;<! <͢!!N#F!~#fo##~#fo!~#fo !~#fo##N#FA !~w#~wÁ !~#fo##~#fo!~#fo !~#fo MD!9!!N#F!}!~#ʻ !>w>#w!~#ʾ !~#ʾ ! ~#fo~OG!yOx#Gy !~#fo!  ! ~w#~wa !#~~w+~w!~w#~w!~w#~wv !9otected.$' BMESSG db acr,alf db 'Improper Response.$' DMESSG db acr,alf db 'Select Drive (A,B,C,or D): $' SMESSG db 'Disk Jockey 2D Disk Format program' db ' Revision ' db '0'+revnum/10,'.','0'+(revnum mod 10) db acr,alf db 'Type "^C" to return to CP/M, "N" to restart.$' IMESSG db acr,alf db 'Insert a Write Enabled Diskette in Drive $' JMESSG db acr,alf db 'Close the Drive Door and then Press RETURN: $' FMESSG db acr,alf db 'Function Complete.' db acr,alf db 'Type RETURN to return to CP/M, or F to Format another: $' denmsg db acr,alf db 'Select a sector size:' db acr,alf db ' 1) 128 Byte Single density.' db acr,alf db ' 2) 256 Byte Double density.' db acr,alf db ' 3) 512 Byte Double Density.' db acr,alf db ' 4) 1024 Byte Double Density.' db acr,alf db 'Sector Size: $' acralf db acr,alf,'$' letter db 0 drvno db 0 select db 0 newsize db 0 ds 50 stack equ $ end * â Memory may be corrupted. Error reading %s. Next Load address: %h. Invalid CBIOS format in %s. Invalid load address %s. Can not open %s. Odd number of arguments. Usage: install [-string] file1.prl address1 [ file2.prl address2 ...] Install Revision %i.%i !9!>w#w!>w#w* ! * ! !<!~#fo##~#fo~-!~#fo##~w#~w!>w>#w!~#fo##~#fo~!!N#F!~w#~w!~#fo##N#F!~#fo##~w#~w~!~#fo6á>2!~#~>!<͢>!~w#~w!~w#~w!~#fo}o|g}^!<͢! ywx#w!>w#w!!  #!~#fo!!!~#fo)!~#fo N#Fzywx#w+#~Z!~#fo)!~#fo N#F!<͢Z!ywx#w!>w#w!!  #!~#fo)!~#fo N#F!N#FH!~w#~w!~w#~w!~#fo##!~#fo)##!~#fo N#Fpywx#w+~#!~#fo##!~#fo~#fo  !~#fo##~#fo}o|g}!~#fo)##!~#fo N#F!<͢!~w#!>w>#w!!}|!~w#~wͩ!N#F!~w#~w6!!N#F!~w#~w~OGyOxGywx#w!># !>#J!~#fo~ J!~w#~w!~w#~w~ !!}|!~w#~w!!~#fo#}|!!  #!!~#fo~!~#fo!~#fo~!~#fo!~!~w#~w!~w#~w !>#!~#fo~ ʦͩ!~#fo!~#fo~!~w#~w!~w#~w!~w#~wJͩ!N#F!~w#~w6q !!~#~!!}|!~w#~w!>w#w!!  #V!~#fo~™ͩͩ!~#fo!~#fo#}|!~w#~w!~w#~wÙͩͩ!~#fo!~#fo#}|!~w#~w!N#F!N#F1!~w#~w;!9!!~#~!N#F!} ~ !!N#F!| }|!!~#fo$ ~#~!>#v!~#›!~#fo& !~!N#F!~y!~#fo!yOx#G!~#fo$ !~#~!~#foMD!!  #!N#F!N#F!~#fo& !!yOx#G ͤ!!  #!>w#1*#~!www͎͎͓N2A:͎12͎͓N1^͎BU2+!W͓̓N͎:O> ?2ʜ xy!6>@=«~zvm̓f6 ~~~!!I!>*ͮ& :Jo&N#F!5!B xy&>*ͮ>YZ_b$>MO͎͓F͎:ͮ  :> :a{ _ 22::>>IR[d:28<2:F>22.PN>2^NNxp _ p g66662Np w p 6666r6s66Np ˜ p  6666@p °@p ·@p ¾@p 6>6Np |p p p ~!8#^ w=   Y (&rÊ ëPNNN 662N 66N 66 @@@@6N倀jN tN Drive $ Is Not Ready.$ Is Write Protected.$ Improper Response.$ Select Drive (A,B,C,or D): $Disk Jockey 2D Disk Format program Revision 5.1 Ty~w!~w#~wu!!~#fo##N#F! Hywx#w!:w:#w!*3  Ҟ!~#fo~OGyOxGyvx !~#fo##N#F!h<! <͢ !:w:#w!!~#fo~#fo }|!*3  !N#F!N#F1!~w#~w!~w#~w!~w#~wC!N#F!O<!9!!~#fo~!~#fo!~#fo~!~#fo!~!>w#w!~#fo~!~#fo~0!~#fo>9!!~#fo~OG!~#fo))))  }|!~#foMD!~#fo~A!~#fo>Z!~#fo~OG! MD#!~#fo~OGyax!~#fo~A^!~#fo>Z^!~#fo~OG! MDk!~#fo~OG>f>!!~#fo~A!~#fo>Z!~#fo~OG! MDø!~#fo~OG!~#fo))))  }|!~w#~wÂCan not write in location %h. Insufficient memory to read %s. Invalid PRL file format in %s. !9!!!~#foN#Fͬytxʓ!N#F!;<! <͢!~OGyOxGy­x!N#F!'<! <͢!!~#~!!~#~!~#fo##~#fo!~.w!>w>#wÛ!N#F!N#F!~#fo& !!yOx#G ͤ!!  #!!  #!>w#w!9!>w#w!|ywx#w!~#~!~#fo#~ !~#fo~ !~w#~wö!~w#~w!~Ʀw#~wÙ!~#fo~ !~#fo#~:y!~#fo!~#fo~aT!~#fo>zT!~#fo~OG! MDa!~#fo~OG! }!~w#~wÃ!~#fo6!!~#~!!~#fo#}|!!~#fo  !~#fo~ʫ!~#fo~.!~w#~w!!~#fo  ҧ!N#F!~w#~w6 !~#fo !~#fo 6~!~#fo! !~#fo" !~#fo# 6~ w!~#fo$ >w#w!N#F!~y—x/!~#fo#6 !N#F!~w#~w6 ç!N#F!~w#~w!~#fo~a!~#fo>z!~#fo~OG! MD!~#fo~OGyw!~w#~wç!~#foMD!9!!}|!!N#F!~w#~w~ ʖ!~%ʙ!~OG!~S!!N#F!~w#~w~ OG!ï!~#fo#~!-!~!~#fo!~#fo~#fo>o>g}| usOh)odi the top of CP/M. If you only have 48K of memory in .pa your system, you will first have to move your CP/M downward to make room. At this writing, the 14 inch hard disk drivers required approximately 3.5K bytes, (see FILES below), so you should construct a 44K CP/M, and type INSTALL -C M26.prl B000 (B000 is 44K in hex.) If you don't know how to move your CP/M downward, see your system manual. The required program is usually called "MOVCPM". To install the Disk Jockey as drives L and M in a 44K CP/M (with at least 48K of memory), type INSTALL dj.prl B000 djram.prl E400 Here, "dj.prl" contains the Disk Jockey 2D drivers, B000 is the top of the 44K CP/M (the drivers require 3.25K), "djram.prl" is updated controller firmware to be loaded into the controller RAM, and E400 is the address of the controller RAM. (If you have a non-standard controller, use the control- ler addr! !N#F!~w#~wN#FSS!!N#F!~w#~wN#FS!!N#F!~w#~wN#FS!N#F!~w#~wN#FͯS!~OG!~S!~#fo~!~#fo~ ! !~!N#F!~w#~w~OG!~ò!!  #B!N#F!N#F!N#F!!N#F!N#F}|  ډ!~#foA  !~ß!~#fo0 !~*#~##~#®~®+++~#fo!9N#F#^#V!xxGyO)MD!9q#po!9~o3||g}o'/<3)"MD!9q#poG! 9~#fo!9~o/< !9~o3|g}oa'!9N#F#q#p!9N#F#^#V"""O>/G!9N#F#^#V#~#foͻz w#û!9TT|xTDxTDLL|7xLTD(D|/g}/o#x/Gy/Ox/Gy/O>=))k# w#`` NAME INSTALL - integrate new device drivers into CP/M, Revision 1.3. SYNOPSIS INSTALL - string newbios address [ prlfile2 address2 ... ] DESCRIPTION INSTALL integrates new device drivers into an existing CP/M 2.x system. "Newbios" is a skeletal CP/M BIOS module in .PRL format (see the PRL.DOC file) containing the new drivers. INSTALL first loads "newbios" at the given address (usually the top of CP/M), then patches it into the existing BIOS by exchanging the addresses of the 17 jump vectors that begin each BIOS. If additional .PRL files are given, they are loaded at the requested addresses with no patching. Finally, INSTALL prints (top of newbios) + (newbios buffer size, if any) + 1 as the "new load address". Additional drivers can now be installed at this address. The flagged argument (-string) is copied to 80H and left there for examination by the newess +400 hex.) To install both the 14 inch hard disk and the Disk Jockey drives, you could first install one, then the other on top of it (at the printed "new load address"). This would require 6.75K of memory above CP/M. As a better alternative, there is a combined driver package that requires only 5K of memory. To use it, configure a 43K CP/M (assuming 48K of memory, or use available memory minus 5K), and type INSTALL M26+dj.prl AC00 djram.prl E400 BUGS Addresses must be specified in 4-digit hex (with no leading 0 and no trailing H). INSTALL should also accept octal and X- notation. When the Disk Jockey drivers are first accessed, they locate the controller by searching memory for a certain pattern in the controller ROM. The search is done carefully, but never- theless, might clobber someone's memory-mapped I/O.  ly installed "Newbios", or a NULL if no flagged argument is present. The BIOS modules provided here use this as an initial drive specification, i.e., -c specifies that the newly installed BIOS should respond to drives C. The CP/M system must be standard: its BIOS must begin with the jump table as defined in the "CP/M 2.0 Alteration Guide", and it must store the address of this table at location 1 in memory. A "skeletal" BIOS module begins with the same jump table, but may leave some of the required functions unimplemented. The corresponding jump vectors are left as jump-to-selfs. EXAMPLES To install the 14 inch hard disk (M26) as drives C, D, and E in a 48K CP/M (assuming that you have memory above 48K), execute INSTALL -C M26.prl C000 Here, M26.prl is the "skeletal BIOS" (provided with INSTALL) containing the 14 inch hard disk drivers, and C000 (hex for 48K) is/@ COPYRIGHT (C) 1978, DIGITAL RESEARCH ERROR: $, LOAD ADDRESS $DISK READ$INVERTED LOAD ADDRESS$DISK WRITE$LOAD ADDRESS $ERROR ADDRESS $BYTES READ:$INVALID HEX DIGIT$CHECK SUM ERROR $FIRST ADDRESS $LAST ADDRESS $BYTES READ $RECORDS WRITTEN $HEXCANNOT OPEN SOURCE$COMNO MORE DIRECTORY SPACE$CANNOT CLOSE FILE$*!9"!e !" !" \!""͊: ƒde"\\\͊: ²d\͝: )d;! q* &f  ! q> ! : A O: 0O! q: O: O! p+q* |O* }O! p+q*  f! p+q* DMB! p+q)R* DMB1B* DM+;! p+q* i2 ! p+q* i2 ! p+q* i2 i2 !" p+q*! f!$ p+q*# i!& p+q*% i!( p+q*' i2 !* p+q*) f!/ s+p+q+p+q:/ =2/ X*+ *- w*+ #"+ *- #"- 1* #" ͖r*   ~!" ! ͸×* " x20 º*   DM":0 Ad*   6!" Ç!" : !"6 "8 ": }2< !"4 "= !  Ä!~w#~w\!D!!"N#FD !4!! N#FD !>w#w!~#~ !!~#fo 6!~w#~wP!!!N#FzEy x«!; !!!!"N#F]yx!T!!! N#F]yx!4!; ! ~w#~w!~w#~w!#X##N#F+++N#F!N#Fr! N#F!!N#F!N#F!N#F!N#Fͣ! 9!"N#F=! N#F=!N#F=!$!]!~#fo!yOx#G!>!!FnV!!  #!; !~#fo!yOx#Gyx(!p; !>w#w!!  #!!~#fo!~#fo }o|g}|!>w>#w!N#F!~w#~wᗕ>!!~#fo||g}o}|x!!~#fo!~#fo !8Q}|!~#fo)!T ~#fo!~#fo)! yOx#Gyx3!!~#fo ! V!!~#fo !~#fo}/o|/g ! !  #y! !~#~!!~#fo!~#fo  !!~#fo!~#fo }|!X##N#F+++N#F!N#F!~#fo)! N#F!~#fo!~#fo !:0!4 :0& : 0::0!xI !4̨ e ::̮>͞ } !~5:Į ͵ !4̨!~5 G!~Ҩ4_!p!~ʮ5^!~> >2\0:0N *K0"+"X0:0 >''!:0N : 0,N :0 >  > !0N#~' ) > ''*K0"V0:\0x ʹ:\0" m }*K0"+"X0''*K0"V0>"4ͬ:2T/:[0 “ 2/-*M0"$/*X0!{#zڿ ~+"X0*M0+"M0wß #"K0*M0".:\0 N]T s#r+*V0*{_zW".:\02.R     % *I0:/ ͪ% ͬ:O0ĭ%  :.ʢ :0¢ *K0+"X0!2<20*#"" : 00Ĩ!??" 09"K0+"X0$< :0¢ : 0,? ʹ  *} :]0 :O0 :0 ͤ%:e0ĭ%:0 : 0  ͬͧ%vʹ   ͺ :0: 0 !;* _!5 ^#fkS \ h n 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 16Y: !2 6=21 á:1 : r+s#r==_HL"4 " >6 ͪS* "6 =23 :1 =21 v=O* #" Y8  ͝҉* +"8 .!2 ʞR̀* "4 4 = ͝* #" çR*6 DM+R*8 DM+R*: DM+R*< M!? q=  ͝Kd*= ! ͸p!@ 6>!@ X*= }O!< *@ & w*= #"= !@ 4)!< 4\mad* }O!< :? wlR*4 DM+{R* DM+R 4 ͝*4 }¿= 4 ͝< N*4 #"4  å;*4 DM+: Y2A 0O> :A 0:A AO>&R̀:A A H.2B !2 w:B !D s+q*C &͍:D _og_{ozg^#V) _{ozgi`N#Fogo&og_{_z#W( COPYRIGHT (C) 1977 DIGITAL RESEARCH 112O02Z0̀%!"K2.>2.*M0"$/̓%!"":g0i!"P0"R0"2:0v: 0$  :[0-ʬ+ʬ* :[0!_0M!f0P p  !   :O0Ĝ!":O0*V0}|<r ͪ*|Ĵ:O0_͑H *V0"Ù*V0"E V» ͪ»**»"Ù*K0"X0!0NA#~' ~p"K0*K0N"X0!0q#*w œ:0!x ͜ *V0*R0:_0̍"V02*M0r; !:r :0F: 0e%;m ">2:0b: 020 W,F:0b: 0e,ʹ:re*X0#![0~ʇww2/ͬ:2T/-"."$/2/>2.v:.ʸ!/6+͕%>20:.ʮ:.0209$<!5*}Ģ*V0":0y: 0:yv! X! ^#fkX _~ 0^ Z   2 5 8  :0‰:0=ʉG! 0ʃF#2sÖ*I0| E2V ,[ ͊m *R0"R0"P0 m E2D2V ,ʾ ͊:/ m :/ "> 2/:Į 'd ! ^#V#*0}o|g*  ":D x=D y0P 2!0^4! 0q :0Ė: 0,; Ė*I0m |}$† ͌oy Ԍ͋ 8O͖ Ăy01y 1m X:0 : 0, >C͘%:0 : 0 v;:0 : 0 v-!v !v-ʹ {ozg:.7ͮ2Z0!O0~4l!"*|>"V0*""J͊!/6 !/͒%:^0ʏ>2.͡%ͱ*K0*T0&*M0*T0&\ ͍!/w#õH USE FACTOR !/͒%*"P0Þ%z{*P0"R0*"V0 !":O0Ģ*R0̜*R0ĜG:O0xě%:/ *R0̍:xz*P0#"P0E2D20:b!^4!/wjj*R0!6zz{z4A_A?ɯ2.2*T0"V0!.8w# *V0*K0{zҤ*b0+"X0 =$**X0#Þ!.*V0".#"X0$:d0<:0<! 0~?<#ʐ: 0͡!.".^#V"V0}{##~2.*.^#V#"."V0*V0}d##~<2.G*V0##"X0:.> u!.~w>w> u:.*0F!9N#F#^#V#~#fo"Xkb"Xi`"XOGposLoad size is %h hex bytes longOutput file is %p Addresses don't matchSizes don't matchUnexpected last line in %pCan't make room for headerCan't create '%p'prlhx1hx1hx0Bad option -%acprlMAKEPRL Version %i.%i gV!9!>w#w!>w#w!>w#w! >w#w!>w#w!>w#w!>w#w!~w#~w!~w#~w!N#F!N#F!!~#±@ !~#fo~#fo~-!!~#fo~#~!~w#~w+~#fo~OG!2[U!~#~ʽ!~#~ʽ@ ý!!!!~w#~w+~#foN#F(!~w#~w!~w#~w!~w#~wñ!!$!~w#~w+~#foN#F !>w#wF!~#fo~OG!; F!!!D!~#foN#F !~#~!!!4!~#foN#F 3!!!4!~#fo##N#F !~A#~ʄ!!~#fo~#fo~!~#fo~!~#fo~.!~#fo6\!"!Dywx#w! !4ywx#w!!!!$$ywx#w+~#~!$!; !!$!~#foN#F:0 : 0 -Ͳ !/6+:.;?*$/*."$/?"$/:.l*.^#V{r+s5*.^#V ʓ:. r+s!06#wÚ> 209!e/~6![0~6".~,#!0w9 9*.~6 *: 0,Ĵ2f/*.s#r2[02e/*.#"X0$<5ͬ*$/"M00:T/2:/2[0 v>20*.".2[0v*R0m "R0͍"R0!/w >=G*R0*I0"R0"R0 m :/ }>͞ ¥͢ :O0*V0*ʿ͜">2:O0:0:O0!!4:0: 0,>"4:O0: 2\0:0=: 0 F!Fʹ%*X0"`0>2Z0*X0":0k: 0T!T:\0¦:O0¦:0=ʦ ʦ*"X0 !':[0'Tx»!Z04TT!Z05T:\0!":]0!**V0":O0*X0~ Ĵ*X06 '>#G*I0!" :0 :Z0 !0N*K0:O0Ÿ"b0+"X0yʛ 'É' Ͳ >ͮ 222:0: 0 !ͮ-:00P'!5^!/~ !~620͕%2.|z}z> u!.~w:.W=*u!.4C*V0^#V"V0ý!.5¯:20͕%!^4!/w>R͘%>V͘%>Dý>Pý>Lý>Oý>Bý>Sý>N͘%*6".~ 6"U4-!2~B6~44O!! s#r!1~ _6^4! w!p!2~~!55N!! N#fiooo&)^#fk9BIO[ov ͌z{>ɯo>g͌"!6ů{_zW5>)D*OxG !?DM!xGyO23)#͌)=R|g}o=^͌͌roz{͉͌͌}|͉͌Þ͌Þ͌ë͉͌!!o#Ã͌zg{o͌zg{o͌zg{oolo&3:0: 0 ;!,ɯ2122=2 !"I0&q!1~\5_! ~͔D:2:/ *!"I0:/ :0:0! 0^#=ʙV¨*0!҂ :0:0& !!>O: > =;>?>P?<=?>>=<<i;m=>c==>o>v<=<;8?N!Nw#w#W!"V0!.w#w#l2N!.~4^!.~w!.ͼ!.ͼ!.ͼ!/~w!$/ͼ!D/~w!T/~wN#Fp+q!.~^!.!. !. !. !/!$/ !D/!T/5~wN#Fq#p>BØ%!0" * F#%2NG*V0##~w*V0##~<͉:.t!.N!. yq~t +aG=#w#wY*M0!0n& {ozg"V0!K0{#z"M0b*M0!0N#yʢ ~Õb!."O1:N *M0!$/{#z"V0$ _!.*V0~#~1 ~#"M0û1 !͒%Þ%SYMBOL TABLE OVERFLOW G*V0##~w*V0##~=*V0_###1 s#r1 ^#V1 ##"X0P wP ~O!0~z 6~=ͼ !0N#~ͼ „ Ͳ O2Ny2f0!"&:O0*!"%2%2%2%Z&%u'!-x&z{:]0ʢ)*%F)w)!"%r&\‰)*%#"%+~):.2]0ʢ)r&\!~-N'*%F))Z&!"%*%B&%)¼))*)6# )G&*%*%#"%~!<-x&G:%7*$*x*7*x2*Ϳ'5*9**&*&w#"&!F)`&!"&*&%~ʅ*B&Œ*`*G&`*!S-x&ö,͟**>&*@&w#">&!F)l&!">&*@&&`*_!%~ *2%*b0}!,~ +*#+> *>#**> **b0~>+*#2+> *> *> *}2%!%*O*:/ :O0:%y*:%!O0•+:e0!]0+~,:/ ,!/~ +:f0,:/++:_0,+:/#,:/ ,:_0=+!/~ +!0s!%~!%*4:0!/,G~Y+#x=+> Y+> Y+20!/>x6 #=,G!/~ pͳ'*&}?,>*/,`&%͈':^0*+,!&6S#6Y#6M#w!&w:%2%!"&ͳ'*2%`&%͛'͠'+,:%ʶ,:%.*P0"%.*>&}ʶ,>͕*æ,:%,l&&͈'!-x&CP/M MACRO ASSEM 2.0 NO SOURCE FILE PRESENT N2 yU`:10_!~0!1s! ~͔ yU!1~N=w_! ~QZP>2 ypP͘% >U̘%>: 2 3>E͘%óf:.O*.~H:.=!4>͕%0:/#". ͆%2G:0xa{_ ʇ ʇ:0x҇_<20!/w:e/S:e/9ɯ2f/2d/2e/:0:e/ !2f/g/~#»S͉!f/~4!g/_:e/w2e/ɯ<*V0"36*"V0ɯ2!4!f/6".!f/~55!d/^4!g/~f:.:e/JGwf^l͗^{:e/&{!f/4#ww&ʞGʱ2e/xf͗ :e/&ʕ:0  ý͗&{&{ý͗  !e/~&>62/-!.6*M0"$/B".2f/*"V0͗ 2f/2e/2[020> 2͕%>20ɯ202!0~@$6^4#:[0w~$w:[00 6:[0A:[0?e@eAɷP6 o2[0:Z0ʦ:\0 :O0¦:[0':[0 !20:[0 R;/>20:Z0?:\0:O0?́;B*`0*X0++{z~ &À# $b${$*!:!X!!M"p"""""4#\#j# ()*+,-/ABCDEHLMDBDIDSDWEIEQGEGTIFINLELTNEORSPACIADCADDADIANAANDANICMACMCCMPCPIDAADADDCRDCXENDEQUHLTINRINXIRPJMPLDALOWLXIMODMOVMVINOPNOTNULORAORGORIOUTPOPPSWRALRARRETRLCRRCRSTSBBSBISETSHLSHRSTASTCSUBSUIXORXRAXRIASEGCALLCSEGDSEGELSEENDMHIGHIRPCLDAXLHLDNAMEPAGEPCHLPUSHREPTSHLDSPHLSTAXXCHGXTHLENDIFEXITMEXTRNLOCALMACROSTKLNTITLEINPAGEMACLIBPUBLIC7 PF FPA A A* A A A(#&&#&2#/?&#' '( v'( %:P!@"<& #*)&# PP%27&#(&#  $ %*%"$  NZZ NCC POPEP M x#_BH!™# 0#³# £#{ڽ#KÅ#CÅ#<: 0 JCR:0 $# $! 06 p#! 0$# # ɯ<:0O=_^$!"F!!V#fjQ̀#G$2!!!^#Vo&)O~#F##xGyѯ:͕*!%^Ww*%{-|-}--{?.!%~#-6.-> ͕*> ͕*͞*> ͞*ws++!+"X0:Z02Z0́ͪ'2Z0X:[0*K: ḰͪX? X́ö20Pg>ã6r>ã:[0'ƒ2[0>ã ¡:.ʔ>+2/͕%!/6 >20>20:[02́:0:Z0: 0=!EQ<!LT:[0=!LE>!GT:[0=!GE2[0" 0!04>20![0:0/ʦg¦´/ʦA¦:[0O<QA>HHR>22[0m:B_>fD> j!052!"0!0N#~#A҄0Æ7O!~*0!ʩң)Ú "0 x:[0 '¦́'æ:[0 :[0,;%:[0 !:[0; ,202́/>20:[02́:0G:0::0l:[0'́:[0' 20/:[0'|>20^—́:[0  <¨!~4 >¼!~5 : >20>V>O>I>B͘%!QéÉ $ ? H Y ` e Ò ü ò ~ÏGÇåûfD?<==:e>?; ><>; ;<=R>>>F>;>G==<==>=s;=P=*>=$?P:-?]>*<<==<;=>>y> ;:0000000000000000000@@@@@@@@@@@@@@@@AA AAQQQ"Q'Q,Q1Q6a *\ ?=)$=)w#Ž&!\60 ڱ&>GO#w ³&>O # &6 &6L#6I#6B#w2|r&\u'>2]0!"%![0~2%wG&!,x&>82%2%!"b0*"M0!1"%"&"@&#"K0"T0' _#~6' D':%A6'>:6'D'>.6'D'>-6'x&!,N'!k-x&!,N':% '> ':%'_!% '6 4ɯ2%2]02e02d02g02%:\ =)!%w#w#w#w#w#w#>2^02_0:m$(!~#$,(~(# 3(%Aʩ(Pʩ(Sʩ(Hʩ(Lʩ(*t(+t(-¶(^0~Sʣ(Mʣ(e0Lʣ(d0Qʣ(g0Rʣ(%1¶(x#3(~AҶ(#3(#6 !)-x&!x&!%͉&!%͉&ͳ'(`&͛'͠':%)!&͉&l&͛'1 9!~w#~w3gV!~#fo~ʃ !~#fo~. ! ~@ #~ !~#fo~ !N#F!~w#~w!N#F!~w#~w~C !N#F!~w#~w6.!~#fo~, !N#F!~w#~w!N#F!~w#~w~Û !N#F!~w#~w!N#F!~w#~w~ !~#fo6! ~& #~ʃ nV!~#fo6nVgV!!N#F!~w#~w!N#F80yʎ !~#fo ~ ” !~#fo 6nVnV!~#fo ~ < !~w#~w< Error: gV! ! N#F!N#F!N#F!N#F!!FnVUsage: makeprl [-s hex-no] [-o output] hex-file1 [hex-file2]gV! !!FnVgV!~#fo~:y nV!~#fo ~0 !~#fo ~0ʣ nV!!N#F!!~#fo#(y x nV!!N#F!!~#fo###(y x nV!>w#w!!~#fo  #~ !!~#fo)! ~#fo !!~#fo) !~#fo (yu xʣ nV!~#fo#~0³ !~#fo##~0³ nV!~w#~w nVCan't rewind '%p'file '%p' not at correct start addressUnexpected lasnV! >w#w+~#1!!/X!N#FzEnV!!/X!N#F80nVCan't write out memoryFlush can't seekgV!9!*/\!͖Qx2P`2Q`x2S`y2R`!P`!Q~#~#~#~*\#"\!!##N#F+++N#F!N#F̈́)x!a; *\}o|g!/X!N#FzEyx"!J; nVO!~#fo"d`!~#fo"``!~#fo"b`!>w#w!:d`w:e`#w!>w#w!``>#ґ*d`> *d`~!``>#*d`~-n!>w#w*d`#"d`:``2``:a`2a`:``2``:a`2a`*d`#"d`s! ~#~‘:``:a`ڑ*d`~0‘*d` ~A;*d` >Z;*d` ~OG! MDG*d` ~OGyxPx‘*d`##"d`:``2``:a`2a`Ñ*d`~+*d`#"d`:``2``:a`2a`!``>#*d`~0C*d`>9C!*d`~OG! }|X*b`!~#!N#F>O>G!N#Fywx#w!``>#*d`~A%*d`>Z%*d`~OG! MD-*d`~OGyl6x*d`#"d`*d`~a*d`>zÝ!!N#F! N#F͖Q!~#fo }|:``2``:a`2a`*d`#"d`Ñ*d`~A*d`>Z!*d`~A*d`>Z*d`~OG! MD*d`~OG! }|!!   #X*! ~#fo }|U!!}|!*``! ~#fo##N#F+++N#F!ͮ*ywx#w! ! ~#fo####}|U!!}|!>w#w! ! ~#fo####}|U*b`~d#"!!}|!!>>#!!!N#F!! ~#fo >+F+N=!!>$!9ywx#w! ! ~#fo }|U*b`~cG"*b`~sG"*b`~iG"!~ʉ"!~a¤"!! N#F! ~w#~w}|*b`~c"!>w#wq#!:b`w:c`#w!>w#wU!! N#F! ~w#~w~#~*b`~c@#!``>#@#!~w#~w@#!!~#fo~#~!!N#F!8Q}!!~!!}|!>w#wq#!!}|!*``!N#F!3ywx#w*b`~cU*b`~sU*b`~iU:b`2b`:c`2c`U!>##!N#F!N#F!N#F!~#fomV!~#"!!  #"!!!N#F!~#fomV!~w#~w#gV!N#F!!N#F͛9nVO!9!~#fo"d`!!F`;K$!!P`~#~s$!P`NO*d`*d`#"d`6-!!~#fo!~#fo }|!>>#$!>w#w!!~#fo#! >+F+N=$!94! 9ywxt line in hex file '%p'File '%p' not in hex formatCan't read '%p'gV!9!!N#F9 yg x{ !N#F!4 ; !!!!!^ ywx#w+~¬ #~ !N#F! ; !~ #~ !N#F! ; !!  # !N#F! ; !!'X##N#F+++N#F!N#F̈́)xB!N#F! ; nVBad line in hex filegV!9!!N#F9 y€x‰nV!! N#F!N#F!N#F!^ ywx#w+~#~!H; !~#~nVnVCan't open '%p'gV!!!!N#F͐ywx#w+~.#~E!N#F!; nV!~#foMDnVCan't write out bitmapSeek error in wrheadCan't write headerCan't rewind filegV!9!>w#w!~#~!!~#fo 6!~w#~wö!!}|!N#F!~w#~w6!N#F!~w#~w!~#fo!yOx#GyOxGyw!N#F!~w#~w!~#fo!yOx#G!8Q}o|g}!N#F!~w#~w6!N#F!~w#~w! ~#fo}o|g}!N#F!~w#~w! N#F!8Q}o|g}!!d`!yOx#GP can't write can't read O!9!t!}|!"``!*``*``#"``~!>#!>#*``> ,*``~,!>w#w!v/ywx#w!"b`!t:b`:c`#*b`~<!=!!*b` ͐y~!!!*b` !#!! 9!F~!>#CÔ!~w#~w*``#"``r!>#*``> *``~!tN#F!t~w#~w*``~A*``>Z*``~OG! MDä*``~OGyw!~w#~w*``#"``C!tN#F!t~w#~w6e!v!N#FP*b`#"b`ò*b`~>V!=!!*b` $y(x~!!*b` !!! 9!F~!N#F!~w#~w)!v :b`w:c`#w*b`~*b`#"b`~gV!N#F!~#ʫî!N#F͛9nVgV!N#F!\c,nVgV!!N#F!\!#.nVO!"d`*d`~#8*d`N#FL)*d`N#F!N#FzE*d`##"d`PO!~#fo"d`!~#fo"``!~#fo"b`*d`~nq*d`~N¢*d`#"d`*``*b`N#F*b`~w#~w~#fo}|*d`MDP*``>w#w*d`~0*d`>9*``*d`~OG*``~#foMD)) )  }|*d`#"d`ìO!9!~#fo"d#w!!N#F!~#fo#!<~w#~w>2``2a`!:``:a`#%!:``:a`#҈%*d`*d`#"d`!*`` ~*``#"``!~w#~w6%!>#&*d`*d`#"d`6.>2b`2c`!:b`:c`#E&*``*b` !yx#E&*d`*d`#"d`!*`` ~*``#"``*b`#"b`í%*d`*d`#"d`6e!#~m&*d`*d`#"d`6-!!~#fo>o>g}|{&!:b`:c`#&*d`*d`#"d`60*b`#"b`E&*d`*d`#"d`6+*d`*d`#"d`!N#F! QP0 }*d`*d`#"d`!N#F! ͘P0 }*d`!yOx#GPO!9!~#fo"d`!~#fo"b`!!F`;K8'*b`*b`#"b`6-!!P`~#~$'!P`NO!"``!!! >+F+N=R'*``94! 9ywx#w!!~#fo*d` }|!>>#'!>w#w!!N#F!!<~w#~w!!  #(!~#fo!yOx#G*`` "``!!~#~!>#;(*b`*b`#"b`60!d`>#(*b`*b`#"b`6.×(!>#(*b`*b`#"b`*``!yOxGyxҁ(*``*``#"``~OGÄ(0yw!~w#~w;(!#~(!d`>#(*b`*b`#"b`60!~w#~w:d`2d`:e`2e`×(!d`>#9)*b`*b`#"b`*``!yO~#fo!yOx#G! ||} !!+X##N#F+++N#F!N#F̈́)xT!; !!!N#FzEytx!~; !!##N#F+++N#F!N#F̈́)x!i; !N#F! N#F!N#FzEyx!R; nVCan't read in seg %iCan't write out seg %igV!9!\~#_!>w#w!~#~!/X!~#fo 6!~w#~w0!!~#fo}o|g!QP}|!!~#fo}o|g}|!!/\ ° #=*/\! ##N#F+++N#F!N#FZyxr*/\!; r!>w#w!~ր#~0!~#fo)1\ >w#w!~w#~w>2\2\_!/X!~#fo !~!:\:\#!!~#fo"\!!~#fo)1\ ~#!N#F! ##N#F+++N#F!N#F'y¶x!N#F!; !~#fo"/\*/\)1\ >w#w=!>w#w!~#~!/X!~#fo 6!~w#~wnVgV!!##N#F+++N#F! N#F!N#F͍! 9nVgV!!##N#F+++N#F! N#F!N#F͍! 9nVgV!9!!N#F!͖Qx2P`2Q`x2S`y2R`!P`!Q~#~#~#~!!##N#F+++N#F!N#F̈́)x`*d`"b`*b`~/*b`~%/*b`#"b`*b` "d`!b`:d`:e`#h*b`!d`yOx#G*d`!N#F!~#fomV*b`*b`#"b`~|P!>w#w!6 *b`~-½!>w#w!*b`#"b`*b`~*b`#"b`*b`~+!*b`#"b`*b`~*b`#"b`! !*b`;i`"b`!>w#w*b`~.)! !*b` ;i`"b`*b`~aM*b`~hM*b`~oM*b`~ux!*b`*b`#"b`~!~h>2``2a`õ!6a!~o˜>2``2a`õ!~u¯> 2``2a`õ!"``*b`~x!>w#wU*b`~b¡!! N#F! ~w#~w~#~!! N#F! ~w#~w~#fo}|!~#U!!!  #H!N#FO!N#Fywx#w!~#ʟ#!!  ##!!!N#F!~#fomV!~w#~w_*b`~p# !! ~#fo~#~!! N#F! ~w#~wN#FL)ywx#w!~#U!!!  # !N#F !N#Fywx#wU*b`~l› !~a!!! ~#fo~#~#~#~!>w#w!~w#~w+#~n!!!~#fo !##~!!$T] *b`~f¢!!!}|!!N#F!!yOx#G! ~#fo >+F+N= !&!9ywx#w! 2xGyx )*``*``#"``~OG#)0yw:d`2d`:e`2e`(*b`!yOx#GPO!~#fo"d`*d`"``*``~r)*``#"```)*``!d`yOx#GPO!N#FʹFi`"b`!b`~#ʮ)*b` ~)P*b` ~#fo"``! ~#)*``$ !~#~#~#~á*! ~)#~**``$ !Qá*>2d`2e`!*d`*b`fJxT*!*`` ~*d`}ƀo|g"d`**``$ *d`!~#fo MDx2P`2Q`x2S`y2R`!P`!S!Q~#~#~#~!~#foMDPO!~#fo"d`*d`"``!#~+! >#+!!P`~#~#~#~!P`͕T~#~#~#~*``*``#"``6-! ~#4+! > w#wY+! #~Y+! ! ~#fo>o>g}|!! #~~+~ !#~+!!R+! N#F!P`~#~#~#~!P`!ͨS##N#F+++N#F*``ͮ**`` "``*``!P`~#~#~#~!P`!S>02Z`2[`2Y`2X`!X`Q##~*``>9',*``~'w*``!d`yOx#GPwrite error write error bad putc call O!~#fo"d`!~#fo"``!d`~#Ÿ,!!T,!zE!F:a`,*d` ~#~,*d` N#F*d` ~w#~w*d` :``wg-*d` >#-*``MDP*d` Q "``6>2b`2c`!:b`:c`#6!~#6!!P`~#~H5!P`!`ͦMO!!ͭO!!P`~#~5!P`!X`!N#F UNO*d`*d`#"d`!~#fo0 }*b`#"b`5!!`;K!6!!P`~#~5!P`!`@LO*``#"``5:b`2b`:c`2c`à4!P`~#~/6!P`!`ͦM!`;K5*N` "b`!b`>#5!*b`)))` P`~#~|6!P`!ͦMO!`;K6!!O!*b` Q:``2``:a`2a`:b`2b`:c`2c`W6!:b`:c`#7*d`*d`#"d`60*b`#"b`6*``MDPPONMLKJIHGFEDCBACONRDRPUNLSTO>2d`2e`!"_:d`:e`#k7*d`=*d`#"d`J7:^OG! *^MDPO!~#fo"d`!^ywx#w!~#fo~#7*d`"b`!~#fo~#fo"``*b`*`` 7*``~7*b`#"b`*``#"``7P!~w#~wß7*b`*`` 7!~#fo##~OGPO!~#fo"d`!~#fo"``>2b`2c`*``~.ʮ8*``~ʮ8:b`:c`8*b`*b`#"b`*d` *``~a8*``>z8*``~OG! MDá8*``~OGyw*``#"``@8:b`:c`8*b`*b`#"b`*d` 6 î8*``~.8*``#"``8*``~8P>2b`25Cywx#w+~#$A:_2_:_2_@!~#OA!!:d`w:e`#w+N#F5Cywx#w!~#_AP!~#fo!~#fo }|!_~#ŽA!~#fo"_!~#fo!~#fo :_:_A!~#fo!~#fo "_!!~#fo##A@bad free call O!~#fo "d`!~#>B!_:d`:e`#$B!_:d`:e`#KB!!A!zE!F!~#foMDP!_~#kB*d` >w#w*d`"_>B!_:d`:e`#қB*d` :_w:_#w*d`"_*d`?>B*_"``*`` ~#fo"b`!b`~#B!d`:b`:c`#B*b`"``áB!b`~# C*d` :b`w:c`#w*`` :d`w:e`#w*d`?*``?>B*d` >w#w*`` :d`w:e`#w*``?>BgV!:_w:_#w*_!~#fo "_!:_:_xC!f`:_:_҉C!~#fo"_nV!~#foMDnVDD^DDO!~#fo"d`!~#fo"b`!>#D! yOxGyD! yCxD!FD*b`!yOx#GP*d` ~1D*d` ~OG!C[U*d` ~#fo"``!*d`VGyUDx¾DP*b`~OG! !~w#~w*b`#"b`ÿC*b`~OG! pD*b`~OG! pD!~#foMDP!>#?E*``! ~?E*``" N#F*``" ~w#~w*b`*b`#"b` N#F*d` *d`N#FzE*d` y.-x#N-! !G,!zE!Fg-*d` >w#w*d` :``w:`` t-:a`‹-*d` ~ˆ-#~,*``MDP*d` N#F*d` *d`N#FzE*d` y-x#-! !:,!zE!FP*d` >w#w*``MDPwrite error write error bad putl call O!~#fo"d`!~#fo"``!d`~#c.!!.!zE!FP!~#fo"b`!b`>#/!*d` *d` ~#fo }|!b`>#/*d` ~#~/!N#F!~w#~w*``*``#"``~:b`2b`:c`2c`*d` ~w#~wÛ.*d` ~/#~/*d` ~#/*d` ~#fo*d` ~ /*d` N#F*d` *d`N#FzE*d` yo/x#/! !-!zE!F/!b`>#n.!*d` *d`N#FzEy½/x/! !.!zE!Fn.*d` >w#wn.!~#foMDP*d` >w#w/10122+222 223O!N#FʹFi`"b`!b`~#[0P*b` ~#fo"d`!~#fo"``!>#0*b` ~0*b` ~OG! 0[U*``!yOx#GP!*b`VG!0[U!d`~#0P*d`! ~P1*d`* 6}*d`* ! ! !c`*``~g9:b`:c`g9*b`*b`#"b`*d` *``~aR9*``>zR9*``~OG! MDZ9*``~OGyw*``#"``9:b`:c`9*b`*b`#"b`*d` 6 g9*``~OGPO!9!~#fo"d`:^9!! y2^!>w#w!!"_  #9!~#fo))_ ~:!!"_  #:P!~w#~w9!!~#fo))_ }|!~#fo6!!~#X:!~#fo~w!~#fo##>w#w!:d`w:e`#w>2``2a`*d`~::*d`~::``:a`;*``*``#"``! *d`~a:*d`>z:*d`~OG! MD:*d`~OGyw;!*`` 6*d`~:;!~#fo"d`!~#fo#:^wT;*d`#"d`À:!~#fo#!̈́7yw~M;!N#F=P*d`#"d`!~#fo#~;!~#fo#~OGyy;x;!~Š;#~;!!͑?i`"b`!~#fo##:b`w:c`#w!*b`|K*b`( >w>#w!~#fo#~;!~#foMDP!~#foMDP*d`*b`8y2P`2Q`>2S`>2R`!P`Q!~w#~w*``! 5þD*d`~OGyOxGymE*``! ~mE*``" ~#fo6*d`~wÿC O!N#FʹFi`"b`!b`~#EP*b`~OGyOxGyE!N#F!N#F*b`ͦCP!~#fo"d`!>#F*d`"``!>#-F*d`~ -F*d`#"d`!~w#~wE*d`!yOx#GP*d`!``yOx#G*``*b`ͦC*d`!``yOx#G}cF|lFP!>#E!!wE*b`ͦCy”FxʝFP*d`#"d`!~w#~wEO!~#fo"d`:e`F!"_:d`:e`#F*d`))_ ~FP*d`))_ MDPgV!_~#%G!.G:_G:_%G*_mVi`"_F* _mV%GO*_"d`!~#fo"_*d`MDP8I2IIIO!~#fo"d`*d` ~#fo"``!*``$ P`~#~#~#~!P`!$T##~#~*``$ ##N#Fi`}o|g"b`*``! !!b`yOx#Gyw*``" *``* *b` }|!~#H!*``( H #HP!*d`RIxPH!N#F!N#F*d`fJxVHP*`` ~OG*`` ~OGyOxG}|HÈHi`"b`!*``( £H #®H*b`MDP*``( !~#~!b`~#H!*``* |KP*d` ~OG! *``* ! *d`! *d`+ ~OGyw*d`" *d`, }|*d`" ~#fo*d`+ ~OG 6 *``*d`" N#F*d`" ~w#~w~*d`! 5*b`~OGyOxGy1*``#"``!~w#~wt0*``!! yw{1P*``~ t0*``~t0*``~ʟ0*``~ 1*``!yOx#GP*``#"``!~w#~wt0P*``!yOx#GP!>#t0*d`! ~t0*``*d`" ~#fo~*b`~OGyOxGy¾2*``#"``!~w#~w*d`! 5*d`" ~w#~w*d`$ >2P`2Q`>2S`>2R`!P`Q+2*``~OG!$0[U*``!yOx#GP222*b` ~OGy2x3!F*``#"``!~w#~w2O!~#fo"d`*d`"b`!#~s3!>#s3!!~#fo>o>g}|*b`*b`#"b`6-!~#fo}o|g"``!~#ž3!> w#w3!#~3!!~#fo>o>g}|!:``:a`#3!N#F*``!N#FP*b`3*b` "b`*b`*``!N#FP0 }*b`>9&4*b`~'w*b`!d`yOx#GPO!9!~#fo"d`>2``2a`!#~4!!P`~#~s4!P`NO!!`;K5*N` "b`!b`>#5!*b`)))` ;K6!!P`~#~4!P`*b`)))` @LO*``!*b`~#fo"d`!#~=!!  #=*d`!~#fo ~5=!~#fo "``:a`=*d`*`` ~9=*d`*`` 60:``2``:a`2a`J=P:a`=*d`61!~#fo"``!``>#=*d`*`` 60:``2``:a`2a`Ý=*d`*`` 4Æ=PO!N#FʹFi`"d`!d`~#=P*d` ~#ʌ>*d`~OGyOxGyŒ>!*d`RI*d`~OGy OxGyj>*d` ~#fo ~w*d` N#F! *d` !*d` N#FAywx#w*d`6!~#foMDPO!~#fo"d`!~#fo"``*d`*`` "b`*b`*d`~#fo!``yOx#Gywx#w*b` *d` ~#~*d`*`` }|*b`MDPO!~#fo"d`*d` ~#fo"``*d`*d`~#fo ####!``yK?x#{?*d`*``~#fo####  *d` *`` ~#~Pout of heap space O!N#F!N#F?i`"d`!d`~#ʿ?*d`MDP!!~?!zE!FPO!~#fo"d`:d`:e`?@*d`MDi`#}o|g##"d`!_"``*``~#fo"b`!b`~#k@*b`~#fo####!d`yx#ڍ@*b`!d`  #Қ@*``*b` ~#~ñ@:_x@:_@:_2_:_2_@*b` "``@*``*d`*b`͞>ywx#w*b` !~#~*b` MDP!>w#w!d`:_:_#$A!!:_w:_#w+N#F3 *``! i`"b`!! *b`MD!JG[UP!*``* |KPPO!~#fo"d`*d` ~#fo"``*d`~OGyOxGyʮI!*``( N#F*d`fJy¥IxIP!~#`J*d`~OGyOxGy`J*d` ~OG! *``! *d`~w`J*d` ~OG! *``* ! *``! i`"b`!! !b`~#OJP*d`~w*d`~wîIPO!~#fo"d`*d` ~#fo"b`!N#F!8Q"``*b` ~OG:``¬J:a`J*d`~OGy OxGy[K*d` ~OG! *d`~OGyOxGyK*b`! xKP*d`~w*b` :``w*b`! xTK!~#TK*b`! xTK*d`~wP*d`~ w*b` !~#fo}o|g}PO!~#fo"d`!~#fo"``:``2``:a`2a`:a`K*d`6*d`#"d`ÕKP! 9~#foN#FxKO>G!9~#fo^#VzK_>WxƀGzƀWyoxL L>5L>5L! 9N#F!9~#fo# ##:L +:L LчWLL!9!9!6!N#F!]WyŠL! N#F > àM!~L!>#w›L!4!q#p! N#F L!4 !]WyʠMy!Ox#Gyƀ+wx#w !#w L!69!TWͶTq#px#w#wTͶTq#p#w#wTͶT w #w #w #wTͶT w #w #w #wT~#gU#~#foy#{Ux#|U+++~#fo##[U!9!9!N#F!]WyaV!q#p! N#F!]WyU!N#FKV!yOx#GUyV+~w#~w!UO>G! ~#+~wU Vw yVU!MD!  #w)V!N#F!rV!MD ! ~#fo+ #wXVW!9!9N#F! ~Vi`+ >#w‹VæV+¦VšV[W! ~V# +~w³V!9~w#~wæV! ~Vi`+ #~wV!9~w#~wV Wi`7#~wVæV!9~"Wi`+#wW[W5Wi`>#w+W>w! !9z~w+~ w++~ wOW!!9N#F!9^#V! #~#~ yW! ~#~WҚW+©W WW>w+~w}Wi`>#w¼WJ!9N#F###q#p+++q!9N#F#q#pcopyright (c) 1979 by Whitesmiths, Ltd. NAME MAKEPRL - make a .PRL file from absolute hex files SYNOPSIS MAKEPRL [-s hex number] [-o output file] hex1 hex2 DESCRIPTION MAKEPRL is used to create .PRL files suitable for loading by the INSTALL program (see INSTALL.DOC). The for mat for .PRL files can be found in PRL.DOC. The -s option is used for entering the reserved buffer space. (The reserved buffer space is entered as a 16-bit number in addresses 4 and 5 of the header, see PRL.DOC). The -o option is the output file specifier. If no output file is specified, the name from hex1 is taken with .PRL type extension added. If the output file does not have a type extension the default .PRL is added. The next two arguments must be specified. The first argument is the hex file input with an origin at 0. The second is the second hex file input with an origin at 100#~w M!MD! +&MMGM!MD!  #8M!4! +~w NM!5L!N#F!rV!~ʈM!~#ʈM~w! N#F !#~—MW!9!9! N#F!6 Mƀ4 !]WyN!q#p!N#F!]Wy N! N#F &%NN!~O#~Gyր+wx#w! #w )N>8!w! ~#+~w ?N!~hN!MD!  #^N!#~w oN!56N!N#F!rV!~ʨN!~#ʨN~w! N#F !#~·NW!9~#fo~#N~ƀw!9!9!N#F ! #wN!~ƀw! N#F!̀UW!9N#F!9~#fo~#~4OWMD!9!9!N#F!]WyʨOy֨OxGO!~#+~w|OyrOèOyʨO!#~w›O ÎO! @ON#F!~#~W@ON#F!~+~ +~+~ W@OMDóO!9*d`*b`*``i`!"``"b`"d`!9~w#~w#~w#~w+MD!9 _ #P{ !94P! 9~iP+w>#w! 9N#Fx}PO>GPҍPO>G! 9q#pW! 9~P+w>#w! 9N#FxPO>GPPO>G! 9q#pW! 9N#FP! 9q#pW! 9 hex. If the hex files do not have a type extension, '.hx0' and '.hx1' are added respectively. EXAMPLES To create a .PRL file of the hard disk I/O drivers, begin with the assembly language source. Assemble it at ori gin 0 and rename the hex output (with a .'hx0' extension.) Then assemble it again with an origin of 100 hex. (Con sult your assembler manual on how to do this. With some as semblers, you must re-edit the source file and change the 'org' statement). After you have assembled the source with an origin of 100 hex, rename it with a '.hx1' extension. Now you are ready to use the MAKEPRL program. This is an example of a typical way to do the procedure described above. The example assumes that the source is configured correctly. mac hd+dj ren hd+dj.hx0=hd+dj.hex mac hd+dj $+r ren hd+dj.hxN#FP! 9q#pW!9~$Q/#>+++>#~#~#~ #~{S>#># >#͹R!9MD!9~#foR! 9MD!9~#foR2R!9N#F!9SR͹R!9MD!9~#foR! 9MD!9~#foR2R!9N#F!9SR͹R! 9MD!9~#fo#R!9MD!9~#fo#R2R!9N#Fkb9SR͹RíS!9~S/<4TWO!9~#fo##~w#~w+++~w#~w TW!9~4T/#w>+++w>#wMD!9!9!N#F!>w#w#w##w#w!!rV! N#F !#~975717-7+7)7'7%7#7!77777 7 7 7 7 7 7f`.G $_ @ BCG@M [u+p41=hd+dj.hex makeprl -o hd+dj.prl hd+dj.hx0 hd+dj.hx1 In the MAKEPRL line it is not required that you specify the output or add type extensions because the program uses defaults. The MAKEPRL line could be written: makeprl hd+dj hd+dj This form does the same as the first but is quicker to type. The specification for the -s option must be a four digit hex number. FILES MAKEPRL.COM MAKEPRL program MAKEPRL.DOC This document. makeprl.doc 3/17/81 ldk ion callOverflowOut of memoryUndefined line numberSubscript out of rangeDuplicate DefinitionDivision by zeroIllegal directType mismatchOut of string spaceString too longString formula too complexCan't continueUndefined user functionNo RESUMERESUME without errorUnprintable errorMissing operandLine buffer overflow??FOR Without NEXT??WHILE without WENDWEND without WHILEFIELD overflowInternal errorBad file numberFile not foundBad file modeFile already open?Disk I/O errorFile already exists??Disk fullInput past endBad record numberBad file name?Direct statement in fileToo many filespP8`@` :Y! d! ~Y#=%iʎ%à&O[H> K> Yi>: y +=2i ZY#ZEo:ҋ0o.o%~ Ҡ ʠ ʠ> :i <ʩ=m+~ ʬ ʬ ʬ#>d2 ͋9C" :g ͬ! (" !9T  +V+^##* C" B* *Cd Nz)~S ͒(q)ʹ(QZ~>r)ʹ(E(OdG+ $* "* 3àE3\B" !9" ~: #~#ʅ #^#V": >[@1>]@ցLO! N#F#~: ҆ ځ#:l `#2l f>R~#"j &o"n >2m !~##"j +fC͎*j <2m n G("j ! 0?<=:l ҫ ګ*n ¨###^#V,:m 2g *n " *p " !n (E AOGEAGx3Ø(:l  *j #*C > 2 ,$`i P "  "!>:yHG+ȸ#", in Ok Break!9~#b  T N#F#`izv C T  *|<ʗ :  D=96543>7@?2C: * "   *" 2 2 |< "  * <֌W-͋9C" :g G:g x=ͬ:g  H * #^#V*Cs* C{! C{>HͣFH(µC(zʢPY" : {:_ u ~GC+K x),  <2~(z˜<* * "~ #####u   =>C,* =( |" 2 " â ~,dC+͆(~ʕ *n €€l>2á Q+!B>ee,%;d)1F6 * 4TF* ::G<:?=:G<:e ?=!B&Gá(* TF~\:I:G<:\V:G:e \!B\/V tz|TF›:::o<ʛ& ,C)+(* TF~:::e /<!B{= @è2go"C#ʧQHLo͋9;*0KDF>-?Redo from start #~ "4N: !!#G* Q!a ;#YHL">2>2 F~,2 ÓC;&G: ʫ>?@> @0KDů2 6,+>2 ͉:~+[(# "4([])Ì]z))DEc9@gQC}DE CsD +"]D  $ |D}DDD<|""XL{LL{PtM=$$YXTZZSR\SZeXY{TzTSYHIyII|(*g(678&+7y8919JHFIHH"+IFFz)) *m*zQ}QQU@VXVaQdQgQ;LM$Xq"9BLdhiUTϫNBTSLOSONԚLEAҒINSNDBV+V,V-O HRAL̶OMMOθHAIιELETŪATI͆EFSTҭEFINԮEFSNǯEFDB̰EƘLSŢNāRASŦDIԧRROҨRRX O/QO҂IELILERIOTωO TωOSUEEXNPUԅƋNSTNNMNKEYILPRINԞLISԟPOEԈINűOASEISԓO O0EEFTO1ERGOKI2KS3KD4IDEXԃUL̖AMEהOPEοUԝΕCTPTIOκRINԑUOKřOEEETURΎEAćUΊESTORŌE͏ESUMũSEIGHTNENUͬESEANDOMIZŻTOАWAХAVPCTEGQI TRTRINGPACEYSTEͽHEROΣROFƤABA SINSAARPTIDTȡAIԗHILŴENĵRITŷO۾yy||PF<2(z{ *z);*)&,,d-D.s)%%'i')1+%+Q+3)NEXT without FORSyntax errorRETURN without GOSUBOut of DATAIllegal functC{K2* " * |< " " * |! 4 4 5wY2B!{DP 2R U >(_#U * ~?o !P #GC!BʻY|<1>DA2MSB!E :* > @(K 2 Ç 2 *  C " :b ʢ >(Kڢ <=ʢ (ͬ~ ̾(" ҊSe]" ;5$ܢ"ʇ: \*v " * ͶB" t##s#r## w# y}ͯ!6"*" 7C*"* "â *bk~####~ ҷ ڷù#s#rïC *DM~#+##~#foC`i~#fo??2i 2h ;#~=!@}O|G!""y O:h ~ʂ#Y:aJg>2h 2i U%~|*O~#Ym?>HjZEڗ;;>ʸ;>HOZ#þGO TOUBZ!AO ^#V#ZOd#<y(!!!Z.!>dG>Y2i Y%=+ZOiMk֢ύ>2i W„Y>5W>Y{~.ʧ:"0":i ~O.O>Y(ͬ}Y|Y%~.ͬ:g * |>}e. 5, ~,B>2 d: =Bd̨H+~,ʿ+N6,E* 2 QC,͋9~,c: 2 TF—Qd¢WG"ʌ: Wʉ:,+FO: y!...+ʽ,G+M: C#~# #^#V" cCC(+B͓2 " * ~" ڎ_4:g {[H !xVzʬQںzʺ! :g  N#F#N#F! N#F#N#FKG* W " Ð)͙(6Çz)uÇxdd!BdX* \FÇy2h :g g+Wx(zOxdz o! N#F* *(" " ͩ( *!:h og~#fox(2g 6" ;)!A͙(*ʹ(" " i*͙(*g' .EJ ]<=ʓ<"FO&i:* ,C(#r PQ͉:C)|)IoBI'UTC)}* k(͋9" d(~a{_&([OʭH¬#~[Eҗ:0ÞG7))))o~ +8  )))0O í)#~ց(7>OyC,;*%#~#Y #^#V" y~.%$$$$$%** "͋9+%c%C,+8%": 2 2 ! 6ͷ(È%ͷ(t(x: ʩ(Ң%/<͙(ͩ((gb&|! %B&#ʈ0.͉&#&G~_#~W#~ON&hcGy&JTeox%2 |&y%O&)zWyO%x\E#&! w%%x! 5&F#~怩Oé( 4Ç0~_#~W#~O! ~/woG}_}W}Oq&CZQd& oz…&y-O{&Ë&-yOzW{_xGÅ&$cCu͍M r5E(&1r'ʹ(>2 ͙(!&ͧ7͙(ͩ(!&ͧ7i'͙(T(È%E(.(y2<'"7'PX!%!%'! ~#Y'Wy='O|g}oxGQ'x Gz/'CZQO͙(!-ͦ(E(ʐ0.(4g04g0+~2'+~2'+~2'AOW_2'}o|gxG>?ұ'2'7y<=':'x'> $&{_zWyO)xG:'2'y”'! 5”'%>.! N#G.x'(}! Gx&(ƀwW'(w+E(/%g0ʹ(xڀ0G͈%! 4À0: : /<! Op#6%͆(d+ ! ~w͆(og)d E(* ||O(* * ͷ(" `i" ! ^#V#N#F# (:g Gw#(! ~7w?##wy7O! ((! ( d !@ #G"G)Ͳ1F1Ͳ1416+͆(F16-k(#60: W:g 22һ1ͺ5! F : _ 1x*1{1Aqʟ1Eʟ1Dʟ101,1.¢1+60{ʫ1+6${+p2 ! 6 ͙(* * 2 f2E~2:101 #~1>DG1" `i" #~+N2-%20OxGN2#~ 2`xEC2y 1>2 S2|1;21" `i" ͩ(#W\4: 2Ë22ҏ2460̾("5+~0ʞ2.ľ(2d>"w#6+26-/</ 2:#p#w#6! #zQ334z4ͺ5{(=4b13p#6! #: ~ 3* 3+3-+$0I3#I3++w?3 3I36%3m36C){3)1+6%)d3E(\43_x44"5452_y/3/3{_x34434y5O4GO"53* =4P2*ѯ3E(7\4y/OzWO/4)4/<2  N#fi-++<(aZz)}/o|/g" :g q7xz)z ,{ʨ+F•{o|P {o|<«{o|2¸{/o|/}//o|//}o|g,::e 2 ͋9:g " " ͬB!9(:g * ~)C,* C,Á2N 2g !9(!9.,:g G:N Od}!P O:* * C)>" : OBO/2 OÐ9~ #~#`J x 2b b + C,u W : u 2_H 2u 2_H 2H /<z)zu 2 2 C,u Y +{>2e]!"N#F#xʇ TFQBN#F#Cچ " 1~ > @ !b !BÑ ~ͥB# b 2 e] #~  xE(!N(E(y! y )#x+y+z+{z|O(@)}P(! ( E(!N(E(O! y#)+f)I)N(d* )(! 6(&,)Ü)y%: 2 : B*: ½)))|/g}/o)! : )B*" >2g )aj)d* ʹ(6*x(! F#&* 6*|UY(d *!" " >>)d GOW_ʹ((gf*>b&|5&N&z< dE(*t(̀*k(dҦ* )! ~: ~B*6{y%! ~*O+~+¶*!*) *yʹ((+6+q*: O! >%-,2 Ñ,! ~5#*!x"+>);)+ ;=+|G+y4+|Gz)*͙(,N0|)+DM!>)ډ+)q+ ډ+=c+|+x+ʚ+*͙(*'x)*t(| ++DM!>+ +7>{_zW}o|g=+w+|G+|)Ooyg)* +|6*Y(ͨ+g{o)+! ~w! ~G+N (R,/<#Fwx+ B,F+N9(! G>w2 ! %-x,: 2 ,,4ʈ0Q-,>,! -G: º,! Vwz# Ÿ,x’,%! Y-,x,! w%: ,! ~++w! 4#,4ʈ0+60 ! ->!  6.#605#H56." #H 6,#dq5(! 6(&,*6> 5/>,K5>,p#=B5! ͦ(~5y%>B*ͩ(_6?5ʹ(/{_#zW#yO++Ғ5B&#ͩ(p#ڄ5>5e6>5N#F#* /}o|g5" p#=55w1_cƤ~@zZrN vH Tʚ;@B''d G" կʎ6))))Ÿ6y=ʟ6ʫ60:ڨ6 ʸ6ʊ6È6!t(͙(! 6ͦ(6)!r%>2 E(x+76ʗ0%yʹ(7: 77͍*)|" " ܻ6t(ͽ&'8;': `7hr7͙(͍*Ɓc7ͅ%!{7ͧ7J'͙(: o7%~0é(|Yt&wz^Pc|u~r1͙(+ʹ('͙(~#ͦ(='ͷ(͈%ð7RO!&ͦ(76*E(!H8>8!i8ͦ(!H8Ȇw#O ͷ(':G8<2G8!i8O |%ʹ({YOO6+F6!F84~֫58w %!i8(w+w+w85Jʙ9v" GSљ e͘w>ROhFhiuh!8|%: w: 82 t("~'͙(͍*ͅ%)8͈%͈%E(t(͈%t(: 82 !9͘7: 2 "~! _!A!_.!!!/!: -!<-!> >2 { =! ! <~J!#~#X! k*l!~#>l!+!:G@ #T]~u!#y!~v!ʏ!y_¢!: >2 ÷![®!2 !: >2 !> XG{!~#_XG!!2 E0:?+͎ " o6 r6*n )1:l O " H*">&{:m ;"!;"#~ ̾(~#m":m A" ^".h"Dh"EA"A"{v"*j 5$Ҕ"T]C!E #G!* C¦"`i" "\]~"\]C,u "z)d: E()È% PX/#,#BK/#C,/#C,( z`iC[# !C^#Vzn#~#+K#͑#^#Vzʌ##s#r u# 2 *+#~##^#Vʚ#O: y$#¦#¦#3z##£#3 > %$B!$#G11+ã#Undefined line #3###N#F>!#*j +p+q+w: Ò#CBCACSCE: * * C ~0  2 <2 ~̓$#y$\Aʔ$z)ð$!$#G KD#~.~•$z)"j87Random number seed (-32768 to 32767)$*" +%%$ 2 -# -~/w! Oyw#-q<-NsY+1-'- W~w+F-?-! C-~w# [-E(: %'͝.qʙ-G,Q-x ‚-y-Ñ,! --Ñ-L} : A--! (d-: -2 !t(. ! (.&, ! (>.".&,! 3.=-..! 5%! >5=.>! N#F#=(.>! p+q+=9.: ʔ0: %'44ʈ0͝.!7 qA>,?t.>,: <=,! [-!0 Y-xb.! 5b.%y2 +6 ~q+¨.(+~ڈ0w&,4È0%3*j%>2 `h)~&i-.+.+/.ʆ/e /E5/l#/L#/q#/Q4/:g N/>N/~%ʓ/#ʤ/!ʥ/dN/De/ͮ/2S0e/_{_//i/k(d!W')d e/ܮ/.!W'!z)e/ͮ/e/) *d.(.=d^'- ̓$> ̓$!  101(d0! 1(* |* "1C6Ie&X4#]I͙(8͙(ͩ(y8g'E(6t(: N9QYi'!%!X9͘7!8 J;xn{/|t1}=Z}~L~l+C,}92f NE G2#~.9ʵ9:ү90ҵ9E9G#~:90Ҽ9EҼ9.ʼ9x' 2~&9 :%$!#y_! V+z2g : =ʒ;):~(;3;2 : 2 }:*  " c:o[::g [::&* C;^#~#¸;:g ¸;~;#^^#V#˜;:f DMW']< #:¹;#ʾ;+͸<þ;:g w#_ʖ*x " >2g ( C"x ~ #FͨH͹( @ +B-G* * /O #CZG" # >G*v " !* !z *x CxGH!L " * " * * CʹG~###͚<²GH_ÕG* ^#Vz* G" ##^#V#" ÕG* C7H~###͚>>ͬ͹F* (H>>>ͥH<2g #~#fo(d ,»QZûQ Q͋9;*W_Wڬ Q¾Q"QG{,xQPXW1R!b Oz"yR QR RO{,yĊRW1R R{ +R,> +R+R1R1R͊RWQ"hV* *CMS~#hVSV:SS=S~,~#u SůSѯ*Qʦ   ! ~#fo" !"o]| G~,r CACS͋9;*O*o] "o]* Cڸ q#s#r9T7͋9;*ͥHF~O#^#VT*CT* CTY* * CUy!@1> @!b  ~#=GA"=[0A= A=_zW"=! =L=ʺ>O>>ʨ=1g= !>=#ʻ=>>= >>(9>ʵ=6>>@!B<~ͥB#¨=!>7A_>~=ͥB܁>=#~== !B<~>\ͥB~>ͥB́>=>\@~A +> +>+> +>>@ >wͥB# >6Hͨ=Aq>s> >s> ʑ>ʑ> ʑ> >>_‘>>_ʙ>ͥB+>> ~7W'#~+w#Ã>yڡ>>@>> o&DM#͹BwͥB#Þ>x+>ͥB>x+~ͥB> !Bz\@@_W@W~#!ʎ@#ʡ?&ʉ@g@+>H?+~#.?_}@\&???$ʚ?*??x#ڒ?~$> ž?#W?~#.?#ʡ?,?z@Wá?~#>.??# ?~##??T]^###xG#z+@x@~-@@>Wr@Cxz*1#G+7N@2 ;K@, ~#_~#foxE?m@@@?!BͫH@~#@_@Ò@>@r@;** AxxOI&G* 5@G> 5@@@z>+@TFfV:\A@:@27A C(u C,C)d$Ix 'IH0Ix > {͹FGH* w#?IHIO>~XIxIx C,;*C,* C)ͥHW'ͫHG=O>x~#F#fh GN#^#VUJ LJ#7Jѯx<#4JIJC(͋9;*#^#V* CڍJ*CҍJͣF(C,u ~JͥHG!W'y~?@> @(KͿAzK68Kp22 ͿAoK!B!=:>\2UK'K@+iK~@K+@K@!B!b 2OAK:ʐK>\@2yKCD7 ;L K ´K(KKCD(KK0K@> @>bKK>#iKK6!B!b K KxL*|>L!b ("_yq#@ K2e > @ͿA,L KzK: Bw!a >2 ;2 " $L33oL " ** áL LL" *" ##^#V#~#fo"͆(ʵLA3à* "à!9~#L L~#foC L >2 ͋9dU>  U!Ux͹FFTC$C(u ~,KU*Qʠ "QC)}͹FʅU͙BlUA~Uw# ^UF* DWڬ qU6Qʦ ʠ !' ~U U#~¸U`i}WÙU>O #~(PY!' ůwͱW:!͞Zʻ =ʝ =UѯÚ <ʻ !% ^#Vr+s9Q6V PY,V!#V`i>yV!' ~UͱW)9V6Qʦ !&QV! ~+n6Qʦ ! ~*~Ee\DM'~U4N#V pʝVzw w+s#r#6#6DM:V!" s#r#6 W! {zVWw<W<ʻ !! {w:W}W!! ~!) ;WU;W~#>W*~ʖ\( ~hW+~#5O ~+~tWzWJW7>*T]% N#F+q#p###6 ’WͱW: ͞Z>ªW>w+w!(HW7?*' 6#67ͥH~ʲ #^#fk_XN#~:X++@bXy@bXbX #RX~.0X>X7X#X2 z bXbX> >X7X> WX7Xò W<ʣ ! w#…XCACSW:!<¾ ͥH~ʠ #N#F OXIXR  C,#u C,{ʦ _A> @:A 3A6A:<:-A!MA6A<2Oɯ2:> 7A> 7A2:XG{A:e ʍA=2e >îA A> @:e €A ڮA:G:e ʥA!BʮA<2e OTFAWMS: 0P:A!7C!E #G:AD/2AD:e !B6!a > @> @TF3B:?B2ɯ2e :=@FBAA2CDD͙BƒBʌBAͷF_H!D " >2g :2@ > @+B> BC~ +üB*v  >ƕo>gB9*++"  BgGBB* C:G!^#V#C T*}D2 2 2 w#w#" *+" : XC2 2 ! 6#QC7!i8(!F8w#w#w2 og" " *v : ƒC" C* " " : T*++" ##!z "x r%DAgo" 2 "N " " 2 * |}~C##~:  *C(`i+" < D T" !z "x !*}<-D" * " 2DAB!J b Æ >OD22>^@@@!B* | * "u <2>2 ͋9! (* dC,͋9Gd * CD( (>2 ͋9D2 `i D * CD `i" ~,D(""  B!9 +" _MC(͋9s#r#~,=M #MC)" >!=_M=_M=_M!9DM!jM* * * à2 2 ~‡M2 #+͔R!" +NC,,ʸM"" +NC,MCACLCLNOC, 2 5$`i" NT]" CNO**+#~#N#^#V"N:N2 ͉:ʢNxG͒;>2 hN~(nNþN~(͉:zNxGN::g W):zBK!N N 2 ~(nN ͖N+"N(NC)"NC,BN"* * C#ON##~w#͚< NO* " N* C Oy_xW `i" * CNO##~w#͚2 : mS:2ùR2 2 * DM* " * #* " CNP `i" * *+zʠ `ià Q+PdP)1F* #^#V ªPr+s+5&G+P;ʿPC,+>,@ÇP>"@&G>"@íP*|Q~Q\}o|gQ> @+|79Q¯ WzZ" 1Y{1Y!~ 1Y6B#6A#6Sz"# w# >YwwͱWoY<ʻ ÅY<…Y£ cY!%w#w#w#w~ʨYCzW* ) p# ®YC T T _W<Yʣ Z!6# ͖ZW2 !͒Z!͒Zʣ O!  ~#@ygZ~ dZ>.@ QZ:e W:ڀZ> @@!BAZ~*6?# –ZO!!4¶Z#4¶Z#4y"Zʻ ><+Z* C! s#r#wZ2u]*Q  ! ^#V~,+ zʵ +s#r! w#w! ~#fo!CT[Ò[BK>!)g[)#h[))v[ u[#=][}_}la)ҍ[#x"o]! "q]!) "s]!}o|gCڼ[bk:u]\C[ \DM*s]*q]X\"q]PY\*o]#"o]}o|g|Ÿ[ \DM*q]*s]X\"q]PY[2*o]! ~#foCs#rG\:T\!T\!& äV~# xY\DM\ʓ\͹\! w!( V6 ʎ\zwø \ʓ\͹\! ~!ô\! ^#V! s#rDMͱ\ͫ\C" ͒#\>;S"]C ** C!X9}o|g(ÆNO SPACE^ :Ty!B*O=?_s#"^sG!~Ypsp2mÆÆf ͧÆFILE EXISTS _: É: :ʉ=2)ͽÉ T!@k!}|q=qf^!~2>`~22\!!B!~> >#0~O#Cx2͘1)ͽÂf zͧÆBAD LOADCOMf^: ! Â$$$ SUB""C {2!"E 9" 1A 22!ty)K!G_^#V*C   ~E , &-AGMS  !!ô!ô!Bdos Err On : $Bad Sector$Select$File R/O$ :B A2 ! ~6  O͐  : E  B 2 >: b # : y! 4 5~yy 5 6y Ґ ^H @Oy H  H : – ͬ   #H : !  H ù  H  H $O͐ : 2 *C N# !9}o|g ] \ \ ** C!9}o|g!X9}o|g S] )] )]*|<:  C*+6* ~šRÇ !?`2 "!"6:͗C2e " * ^#V"zB"UB"##^#V"A##^#V"A##^#V"=A 2!]!!"" !"22d 2 2 2!"!" !z "x ! "L *"v >2!^" :^^<2^!~" ^F#~+w##D^+6" !^/x^+6"" #/x^i^^6ZS^Mʐ^F C:dʯ^z{2ô^"v +^C/}^C:d" ô^+*v +"v +:!]"2<s#r# *  DM=^#"" {ozgB|g}o_|0_!{ozgB"v "" " *B}o|g++!_#G1!_#G!#G" !B! v] Owned by Microsoft Bytes freeBASIC-80 Rev. 5.21 [CP/M Version] Copyright 1977-1981 (C) by Microsoft Created: 28-Jul-81 ><<?!"2O!"DM -*!" -2>2=2 !"!"!"! "+>2sT!"P2RͯH>2ͯ‘!"ͯ!"""!6UC~7zº7\XSUBMIT INITHR COPYRIGHT (C) 1979, DIGITAL RESEARCH _͌> ͒> Ò> Ò͘~#͌ì _2<2 !2:2a{_:ʖ:>Ľʖ:=2–!B!6#5ʖ:Ľ!ͬʧ )!F#xʺ~0wëw!" !~6ͽ:ý(!  x : 2 p & x ~+é 7 2 H ! >w _ : ! 5ͤ N k ͱ ¦ ͱ xʊ #N x : ! 2 ͤ ! 5™ #wO ~x½  p H    y< < ʑ  : !qMD # 2E > ! ^#V w#P :B O|^#V#"##"##"##"!O *!O *|!6ʝ 6>*w#w*w#w'û *! J * ""!N#F*^#V*~#foyx *{_zW+ * yx # *DM*s#r*s#ryOxG*0MD!!N: E G>O: \ S *C  :q n& ^#V> O^ "*}:*)= ":O:o"*C  *C !ͮ ~2~2ͦ :2ͮ : O:w:w |g}o *# ) :B O! yoxg*:B O }!N#F "*#*s#r^  ~!J  ! J *:o$*C ~i 6i w**{#z r+s{ozg**͕ **  , w͜ ͸ Ͳ ! !N#F$**O !~#:G|g"! *xB {5~#o}o>$*½# K:m ! ~‹#c* DM! xʋ w#zÈL!Uͦ*)"[660#60 4~:ڬ+4#60ì!"ÈxG *w# x*  Invalid memory size$ Synchronization error$ Constructing 00K CP/M 2.2$ Ready for "sysgen" or "save 00 cpm00.com" $#͘*~ ""͌#>?͌͘ =_.:;<> Oo$>!Y2*O"ʉ@G:ʐ:wÖx2p0ʹ#*©6?ëw˜0ï#6 ¹.0#*6?w0#6 #6" #~?  xDIR ERA TYPESAVEREN USER"!yO#< Ty#O 321y_͸2y2ͽ:˜1͘A͌>>͌92^ :¥.!_~#fow]!v"!çREAD ERRORçNO FILE^: ! ~ 3#0 Wx x   G ~ # 3x~#B!Y~ɯ2:=!ý:=!:ý^T!~  6?#ˆ:`O> K{͘A͒>:͒͢>:͒͢xK > K > ͒x  ͢ØÆ^ BRͧ9!5‚#~Y‚#"T<ÆALL (Y/N)?^ Tʧ͘!6!~ڇ w4!Y~ʆ͌†t=ʆf ^ T 2o&)|+!<ͧ8"**#"͕  : 2 Þ y<_WyOxOxG* ~V5dw^  :ʈNÎ N#Fyʝ*}|\#u* #DM*6# x±**s#r͡ *6#6  ^ >:A #~$=2E k͌ : :/GyO>2!q*C " ͡  ʔ*J Ҕ^ :Oyʃ?|x | s-|N-# S:2E !~Яw > T   D ^ 6k -äPYy 5*{zBK5ڋ>*C w~#+w#w+ɯ2E 22 i  ^ *C :~w~͔͔# #  w ~>2!E 5T *C !"C  "C !w# F! w͌ x 2͢ *C  ~<wʃG:!ʎì 4~ʶ ¬:<ʶ$ ʶïZͻ   x >2>2ͻ :!Z2:E w ̈́ ͊ Ͳ  > UNLOADA EQU 30Q 0009 = RESTOR EQU 11Q 0010 = INDEX EQU 20Q 0004 = TRKZRO EQU 4 0001 = intrqa equ 1 0004 = intrqb equ 4 090D = lhsdenb equ 90dh 080C = lhddenb equ 80ch 0111 = lhsdena equ 111h 0010 = lhddena equ 10h 000D = acr equ 0dh 000A = alf equ 0ah 0100 319E06 START lxi sp,stack 0103 2A07F8 LHLD ORIGIN+7 ;adjust 0106 23 INX H ; the 0107 7E MOV A,M ; calling 0108 21CA02 LXI H,STDVSL+1 ; routines 010B 110400 LXI D,4 ; for 010E 77 MOV M,A ; different 010F EE03 XRI 3 ; versions 0111 19 DAD D ; of the 0112 77 MOV M,A ; disk 0113 19 DAD D ; jockey 0114 77 MOV M,A ; controller 0115 11AE04 LXI d,SMESSG ;print the 0118 CD8E02 CALL pbuff ; sign on message 011B 119004 CROK LXI d,DMESSG ;echo the CR and 011E CD8E02 CALL pbuff ; prbits 01A0 79 mov a,c 01A1 CDCD02 call stbits 01A4 21FCFB lxi h,cmdreg 01A7 36D0 mvi m,immirq 01A9 3E40 mvi a,40h 01AB 3D wirqd dcr a 01AC C2AB01 jnz wirqd 01AF 7E mov a,m 01B0 1F rar 01B1 DAD501 jc notrdy 01B4 17 ral 01B5 17 ral 01B6 DAD501 jc notrdy 01B9 116604 lxi d,wmessg 01BC 17 ral 01BD DAD801 jc notrdyx 01C0 110000 LXI D,0 01C3 CDE802 call gtindx 01C6 CDD102 IXLOOP call gtstat 01C9 E610 ani index 01CB A8 xra b 01CC C2E501 JNZ dorest 01CF 1B DCX D 01D0 7A MOV A,D 01D1 B3 ORA E 01D2 C2C601 JNZ IXLOOP 01D5 115704 NOTRDY LXI d,RMESSG ;not ready message 01D8 EB notrdyx xchg 01D9 114E04 LXI d,AMESSG ;drive message 01DC CD8302 CALL SENDMP ;send error message 01DF CDDB02 call unload 01E2 C36601 JMP SENDI ;back for more input 01E5 3609 dorest MVI M2>2T *C G ͻ : w ̈́ n> 2;O ^ DM;}H> "*C  ::dd slO s#r:E ͊ :==»y==»*Ww# *" ͸ *:G#š" ͸ :!w4!i w: Z!E ~=26 2*C !!~~#~O~G#n,-.‹! w! yG!x͢.:E <ʄ! q!pQ:E <. ʄ$.:E <ʄ i 6}2E x N! ~态O>G~G!~G} *C !r#r#r ^ ͥ_y#x#{s+p+q-*C  ͥ!!q#p#w*:B O Y G }*MD "ã:!B w!>2*C ~=2u:B 2~2wE:A *C w>" !""2B !" !r QQQâ~?ͦ ~?r Q *"C Q- Q͜QüQr Q$Q*):B  " *)*)Q;*"E :;:A  2A QÓQÜQ*C }/_|/*W}_*"}o|g":ʑ*C 6:ʑw:2E* *E }DQ>2int drive select 0121 CD9302 CALL rbuff ;wait for response 0124 FE4E CPI 'N' ; new parameter 0126 CA1B01 JZ CROK ; request 0129 326806 STA LETTER ;save for exit 012C D641 SUI 'A' ;test for good 012E F23A01 JP NOTLOW ; drive select 0131 117B04 INPUTB LXI d,BMESSG ;print the bad 0134 CD8E02 CALL pbuff ; input message 0137 C31B01 JMP CROK ; and wait for input 013A FE04 NOTLOW CPI 4 ;test for drive 013C F23101 JP INPUTB ; select too large 013F 326906 STA DRVNO ;save drive no. 0142 11B505 fmtsiz lxi d,denmsg ;Select the sector size 0145 CD8E02 call pbuff 0148 CD9302 call rbuff 014B FE4E cpi 'N' 014D CA1B01 jz CROK 0150 D631 sui '1' ;Strip off ASCII bias 0152 F25E01 jp sizchk 0155 117B04 sizerr lxi d,bmessg 0158 CD8E02 call pbuff 015B C34201 jmp fmtsiz 015E FE04 sizchk cpi 4 0160 D25501 jnc,RESTOR 01E7 7E wrstrs mov a,m 01E8 1F rar 01E9 D2E701 jnc wrstrs 01EC 7E wrstrd MOV A,M 01ED 1F rar 01EE DAEC01 jc wrstrd 01F1 7E MOV A,M 01F2 E604 ANI TRKZRO 01F4 CAD501 JZ NOTRDY 01F7 010604 LXI B,SDLIST 01FA 21E903 LXI H,DLIST 01FD CDD103 CALL OVLAY 0200 012A04 LXI B,L128 0203 21FC03 LXI H,SLIST 0206 CDD103 CALL OVLAY 0209 3E2A mvi a,'*' 020B CDAE02 call pchar 020E CDF102 CALL INDEXP 0211 2600 MVI H,0 0213 CD1503 CALL TRACK 0216 110D03 LXI D,TABLE 0219 3A6B06 lda newsize 021C 87 add a 021D CA4A02 jz findix 0220 6F mov l,a 0221 2600 mvi h,0 0223 19 DAD D 0224 4E MOV C,M 0225 23 INX H 0226 46 MOV B,M 0227 21FC03 LXI H,SLIST 022A CDD103 CALL OVLAY 022D 011804 LXI B,DDLIST 0230 21E903 LXI H,DLIST 0233 CDD103 CALL OVLAY 0236 CDD502  ***************************************************************** * * * Disk format program for Disk Jockey 2D controller. * * 11/16/79 * * * ***************************************************************** N title '*** Format Program for CP/M Ver. 2.0 ***' 0100 org 100h 0034 = revnum equ 52 ;Revision # times 10 0005 = bdos equ 5 ;CP/M entry point 0000 = wboot equ 0 F800 = origin equ 0F800H FBF8 = DISKIO EQU ORIGIN+3f8h FBFF = DATREG EQU DISKIO+7 FBF9 = DRVSEL EQU DISKIO+1 FBFB = CSTALL EQU DISKIO+3 FBFC = CMDREG EQU DISKIO+4 0008 = DSIDE EQU 10Q 000F = UNLOADB EQU 17Q 00F4 = WTCMD EQU 364Q 0059 = SICMD EQU 131Q 00D0 = IMMIRQ EQU 320Q 0018 =  sizerr 0163 326B06 sta newsize 0166 110C05 SENDI LXI d,IMESSG ;send out the 0169 213805 LXI h,JMESSG ; diskette insert 016C CD8302 CALL SENDMP ; message 016F CD9302 GETIN2 CALL rbuff ;wait for response 0172 FE4E CPI 'N' ;test for new 0174 CA1B01 JZ CROK ; parameter request 0177 116506 PROCED lxi d,acralf 017A CD8E02 call pbuff 017D 3A6906 LDA DRVNO ;get the drive no 0180 4F MOV C,A 0181 3E7F MVI A,177Q ;drive select bits 0183 07 QLOOP RLC ;rotate select bits 0184 0D DCR C ; to proper drive 0185 F28301 JP QLOOP ; position 0188 E63F ani 3fh 018A 326A06 STA SELECT ;save for TRACK routine 018D CDC902 call stdvsl 0190 CDD502 call model 0193 011101 lxi b,lhsdena 0196 CA9C01 jz prep 0199 010D09 lxi b,lhsdenb 019C 78 prep mov a,b 019D CDCD02 call st9:10010000319E062A07F8237E21CA0211040077EEE9 :10011000031977197711AE04CD8E02119004CD8E9C :1001200002CD9302FE4ECA1B01326806D641F23A56 :1001300001117B04CD8E02C31B01FE04F23101329A :10014000690611B505CD8E02CD9302FE4ECA1B0184 :10015000D631F25E01117B04CD8E02C34201FE0452 :10016000D25501326B06110C05213805CD8302CD25 :100170009302FE4ECA1B01116506CD8E023A690636 :100180004F3E7F070DF28301E63F326A06CDC9027A :10019000CDD502011101CA9C01010D0978CDCD0216 :1001A00079CDCD0221FCFB36D03E403DC2AB017E75 :1001B0001FDAD5011717DAD50111660417DAD8014D :1001C000110000CDE802CDD102E610A8C2E5011B66 :1001D0007AB3C2C601115704EB114E04CD8302CD90 :1001E000DB02C3660136097E1FD2E7017E1FDAEC0F :1001F000017EE604CAD50101060421E903CDD1033D :10020000012A0421FC03CDD1033E2ACDAE02CDF15B :10021000022600CD1503110D033A6B0687CA4A0268 :100220006F2600194E234621FC03CDD1030118048B :1002300021E903CDD103CDD502011000CA4202014C :100240000C0878CDCD0279CDCD02CDF10226013E4C :100250002ACDAE0211FCFB3E59121A1FD25A021AC5 :100260001FDA5F02CD150362243E4DBCC~#foy!0":O*z,{,*"*"ya#:a#:a#:a#:a#l }w# xro&))))~#O Ë\5< DO0 ڸ>2!"><<!"2O!"DM *   = =!~# x( =S' E*, ~#fo~{ n&Qr/g2~O>!>þ### `!l>2>2>2:~O<!"#"2v'2 !_,lQ: wZO s#r!N:~Â2~O0 xO0!:~_~~      %&'()*+, -. /0  12!"34#$!"#$1234%&'(5678 )*+,9:;<  -./0 12345678 !"#$%&'(9:;<=>?@)*+,-./0?4 < @+ 4 h@x1@W@:"" #@A$@B B HH II$@DI ABI$"$H$H@$$I! H*  $H@@A I $D!!$I"BI"I"@$BIIH$$$$BBI$@BI!"$$A DI$@ A$@$$@H! "!$$" @B$!!!DH$$"H @@BHH  !$$A"D@ "A" "BHA " !$ D B I $ !$$ H@BD D$ HI DIA!$$$ $" "$D ! $"  $AB " BDD $$D!"DI$!$BH!"IB I$"D HD" " $"! @H !BI " I  $I$I$DI$ !I$@"$"$! $I$I @@ I"H$H@D H H@@H ! I HB !D BD $BI DDDDD@*$HI H @@@@$  $@IPE24F02CDA2 :10027000DB02116705CD8E02CD9302FE46CA1B013B :10028000C30000E5CD8E023A6806CDAE02D10E095C :10029000C3050011BD020E0ACD05003ABE02A73EFD :1002A0000DC83ABF02FE61D8FE7BD0D620C9E5C595 :1002B000D5F55F0E02CD0500F1D1C1E1C90A0000FC :1002C00000000000000000000032F9FBC932FAFB18 :1002D000C93AFAFBC93AF4FBFEC9C9CDD5023E18AA :1002E000CACD023E0FC3CD02CDD5020600C806100E :1002F000C9CDE802CDD102E610A8CAF402CDD102E0 :10030000E610A8C2FD02C9CDE802C3FD022A0433EB :10031000043C0445043A6A06CDC902AF327503CDE8 :100320003803CDD102E608C03C3275033A6A06E6CE :10033000EFCDC902CD0703EB11FFFB2E0101504E9B :100340003EF432FCFBEB700DC24603010C00700D55 :10035000C24E0336F636F636F636FC01324E700DD6 :10036000C25E03010C00700DC2660336F536F53629 :10037000F536FE72360073360136F71C01164E70E4 :100380000DC27F03010C00700DC2870336F536F5F0 :1003900036F536FB0140E5700DC297030E40700D37 :1003A000C29E030E40700DC2A5030E40700DC2AC7C :1003B0000336F73E1B01364E700DC2B803BBC26355 :1003C00003700DC2C103700DC2C603700DC2CB0312 :1003D000C97EE5213803E3:"U##:"# $:"k$$ Morrow Designs 48K CP/M 2.2 E3 ABCD: DJ2D/B @E000 12a2B22!":A20"!1" l6͡!0͋ !áEEE !$ _͕yO! 3 $% ,% !+ ͤO͉͒y !W {A !\ ͤ: ͒H)(IX+(IY+yO 3zʉ W! W3\,% ! 3! ͤAF,AF'! z> zjbWTJ   ÅâÓyà×~Ù   `yOQ!><fg59=_!>22!"!"222:a!b=!d^#V2a&. vb`i"`i":2`i":g.y2{a.|s#r#q#~(y2 2:2a.^#V#N:_!!:O:26:g. |o^#V#"~#fo"v*0l~ä22*|O|g+|g}oõ#|g"!#v:=o&)))))))0!>i:i>2>=>>> 2Y%2 2 .*|..*DM.0..>7>x/./!l::·:**z{!:=*":2>2ɯ2:=>2Y%2:g|;Oogy#{_: Notes on CP/M Ver. 2.2 with Cbios rev.E.3. There are several features of Morrow Designs version of CP/M Version 2.2, Cbios revision E.3 with which users accustomed to single density CP/M on 8 inch drives may not be familiar. In addition, some explanation is required for certain utility com mands provided by Morrow Designs. These special features and utilities are discussed below. CBIOS The CBIOS supplied with CP/M Version 2.2 has some unique features which allow users to easily use floppy diskettes of different densities and/or sector sizes. The CBIOS will read and write diskettes formatted in IBM 3740 single density format and IBM system 34 double density format. This compatibility with IBM diskettes is only in the formatting information, not in the file structure. This means that the Disk Jockey 2D/B or Disk Jockey DMA can read IBM diskettes, but special software is needed to read IBM files. No change is necS and BOOT for the hard disk version, not for the floppy version. Assigning Density Users familiar with the Lifeboat/Morrow Designs 2D CP/M Ver. 1.4, who are accustomed to using the DENSITY.COM program, will appreciate the ability of the current programs to automatically determine diskette density. There is no need to inform CP/M Version 2.2 ahead of time of the density of a diskette. Just insert the diskette, the rest is taken care of. Care must be taken, however, when removing or replacing a diskette which has already been accessed by CP/M. A disk reset operation should be done either by performing a warm boot, or by making a BDOS call to reset the disk system (see the CP/M interface guide). As these new features have been added, the size of the Cbios has grown to the point where the version for the double density controller can no longer fit on the first two tracks if formatted in single density. This means that you can oand ABOOT&.ASM files. Many parameters of the Cbios can be modified by changing the value of certain key variables which are used during the assembly. For example, the label MSIZE is used to adjust the memory size of the reconfigured CP/M. The following list of equates were pulled out of the Cbios to give you an idea of the options available in the CBIOS&.ASM file. Refer to the CBIOS&.ASM file if you want to see a full explanation for some of these equates. List of Equates - CBIOS&.ASM maxhd equ 0 ;Set to number of HDCA3 hard disk drives maxmw equ 1 ;Set to number of HDDMA hard disks maxfd equ 0 ;Set to number of 2D/B floppies maxdm equ 2 ;Set to number of DJ DMA floppies 8" maxmf equ 2 ;Set to number of DJ DMA floppies 5 1/4" hdorder equ 0 ;Set the order of logical drives ELSE 0 mworder equ 1 ; if not included fdorder equ 0 dmorder equ 2 mforder equ 3 ;HDC3 controller disk drives. Set only 1 M26 equ 0 ;Shugart SAessary within the CBIOS to allow users to read and/or write any of the IBM standard sector sizes. The CBIOS also supports single and double-sided drives. Users with double-sided drives must use double-sided diskettes in order to take advantage of the built-in double-sided features. If single-sided diskettes are used in a double-sided drive, the single-sided parameters of the CBIOS will take precedence. Likewise, if a double-sided diskette is inserted and the system is warm-booted then the double-sided features will be switched on. Eg. 3 ms. seeks and extended storage. The CBIOS requires approximately 5K of memory. The source for the CBIOS is in the file CBIOS&.ASM, and the source for the COLD boot loaders is in the file ABOOT&.ASM. The two files, BIOS.COM and CBIOS.COM, are examples of disk and terminal I/O routines supplied by Digital Research. MOVCPM The MOVCPM.COM feature of CP/M can be used to directly relocate the "cold bnly boot up with a diskette that has been formatted with 1024 byte double density sectors. Formatting a Diskette - FORMT# The command file FORMT#.COM will format, or initialize, a floppy diskette in any IBM standard format for users with a Disk Jockey 2D/B floppy disk controller. Typing A>FORMT#[RET] executes a program that inquires the sector size - 128, 256, 512, or 1024 bytes - to be formatted, and the drive - A, B, C, or D - where the initialization will take place. The drive specified reflects the floppy drives only, nothing else. Formatting drive A formats the first floppy connected to the Disk Jockey 2D. Formatting a diskette will automatically write sector headers for the selected sector size. Again note that if your floppies have been added to your system via the INSTALL program, or if they are drives C:, D: or above, then the CP/M drive numbers have nothing to do with FORMT# and tha4000 M20 equ 0 ;Fujitsu M2302B M10F equ 0 ;Fujitsu M2301B M10M equ 0 ;Memorex ;HDDMA controller disk drives. Set only 1 cm5619 equ 0 ;CMI CM-5619 st412 equ 1 ;Seagate ST-412 st506 equ 0 ;Seagate ST-506 Make a copy of the .ASM files, then edit the CBIOS&.ASM file for your desired system configuration. This involves changing the numbers following the equ portion of the file to reflect the number of drives, their order within the system, the drive type, etc. Use the following as a guideline for assembling the files: A>MAC CBIOS&[RET] A>MAC ABOOT&[RET] Once the CBIOS&.ASM and ABOOT&.ASM files have been edited and re- assembled, the following procedure may be used to incorporate the new drivers into CP/M: Enter A>TYPE ABOOT&.PRN[RET] watch for the label "OFFSET" in the listing, and record its value. Enter A>TYPE CBIOS&.PRN[RET] watch for the label "OFFSETC" in the listing, and record its value. If the oot" loader, the CBIOS and CP/M. If modifications are done to any of the above, the MOVCPM.COM program will relocate all but the modified portions correctly. Follow the procedures on the next page if any of the above sections are modified. If a relocated CP/M program is created using the command: A>movcpm xx (where xx is the system size or * for auto-sizing) the relocated CP/M will begin executing. However, the relocated CP/M is highly unstable. In particular, if a warm boot occurs, the system may not re-boot properly. This is not a bug in the MOVCPM.COM program, but rather a function of the original and relocated CP/M's. It is recommended that the following procedure be used instead ([RET] means press the RETURN key): A>movcpm xx *[RET] A>sysgen[RET] cold boot the system. This will insure that the newly relocated CP/M is stable. For users with the hard disk systems, the MOVCPM.COM program relocates the CBIOt drive A will always be the first floppy disk drive. Formatting a Diskette - FORMATDJ The command file FORMATDJ.COM formats and initializes both 5 1/4 and 8 inch diskettes for the DJDMA floppy disk controller. This program is menu-driven and is therefore self explanatory. Simply enter A>FORMATDJ[RET] and follow the instructions. Formatting the Hard Disk - FORMATHD and FORMATMW If it is desired to format the hard disk, the program FORMATHD.COM (8 and 14 inch hard disks) or FORMATMW.COM (5 1/4 inch hard disks) should be used. CAUTION! Use caution with the hard disk format programs: They erase the data on the hard disk and it can not be recovered. If you have to format the disk, think about what is on the hard disk before proceeding. Reconfiguring a System To reconfigure the CP/M system for your particular hardware, you need the MAC assembler (not included with system software) to assemble the CBIOS&.ASM ;BIOSLN equate was modified, then we must modify the MOVCPM.COM program to create a CP/M system that matches the new Cbios's length. The following procedure will perform this modification. Enter A>DDT MOVCPM.COM[RET] -S103[RET] Location 103 contains the BIOSLN value for the MOVCPM program. Enter 0103 15 xx[RET] 0104 43 .[RET] where xx is the first two digits of BIOSLN and press RETURN. For instance, for a BIOSLN of 1800, type in 18[RET]. then enter -G0[RET] to exit DDT. Next enter A>SAVE 53 MOVCPM.COM[RET] to save the reconfigured MOVCPM program, and A>MOVCPM xx *[RET] where xx is the MSIZE value that you assembled the CBIOS&.ASM file with, then A>SAVE 48 CPMxx.COM[RET] with xx as above. Again enter DDT, this time with the new CP/M system file: A>DDT CPMxx.COM[REser to place an "A" or "B" diskette into Drive A. In other words, SINGLE turns Drive A into a logical dual drive system. The user, however, must keep track of which diskette has been designated the "A" diskette and which the "B" diskette. As an example, to copy a file from drive B to drive A, give the command: A>SINGLE S[RET] to begin operation in single mode (the "S" argument is for Start). The program will respond that SINGLE has been installed, and return to CP/M. Any operation that involves changing drives will now result in a prompt to place the "A" or "B" diskette into Drive A. In our example, the "B" diskette would be the one with the file which we wish to copy onto the system diskette. One could now type: A>PIP A:DEST.FILE=B:SOURCE.FILE[V] [RET] Depending upon the length of the file to be transferred, a fair number of requests to place the "A" or "B" diskette into Drive A will ap out the formatting, re- formats the track and then re-writes the data. This process is repeated until the whole diskette has been regenerated. The original diskette is both the source and destination diskette, and must therefore be write enabled. The final result should be a single density diskette that is readable both on the machine that originally produced it as well as on the Disk Jockey 2D/B controller. Simply typing REGEN will invoke this program. It has enough prompts to explain its use. BOOTHD The program BOOTHD.COM contains a boot strap loader for the HDCA hard disk controller. BOOTHD.COM could be programmed into a PROM so that you could boot directly onto the hard disks without having to bother with the floppies. BOOTMW The program BOOTMW.COM contains a boot strap loader for the HDC/DMA hard disk controller. The Morrow Designs MPZ80 CPU card has both BOOTHD and BOOTMW encoded in its PROM. Refer to theT] The value of xx is as above. Enter -HEX[RET] then -R(value of OFFSETC)[RET] Use the OFFSETC value obtained from the second step in this procedure. Be sure to omit the parenthesis. Continue by entering -IBIOS&.HEX[RET] then -R(value of OFFSET)[RET] with the OFFSET value obtained from the first step in this procedure. Finally, enter -^C (control C) to return to CP/M from DDT. Now enter A>SAVE 48 CPMxx.COM[RET] with xx as above, and then A>SYSGEN[RET] SYSGEN returns Morrow Designs SYSGEN version 4.1 Source drive name (or if in memory) Answer by pressing the RETURN key. (At this point the source for the new system is in RAM memory, not on the disk where you want it). The return: Destination drive name (or to warm boot) Enterpear until the copy is completed. An entire system disk could also be backed up this way. First one would format the destination disk. Next, the command: A>PIP A:=B:*.*[RET] would begin the copy. This process will take many many swaps but will do the job. The number of diskette swaps depends on the amount of memory which PIP has to use, and on the amount of data to be transferred. In general, any CP/M command which can be used in regular mode can be used while in single mode. There are two exceptions, however. The FORMT#.COM program, because it makes direct calls to Disk Jockey 2D/B firmware, will not function properly in single mode, and MOVCPM.COM because of memory relocation problems. To exit single mode, type: A>SINGLE E[RET] This will return the user to the standard CP/M system (The "E" argument is for End). Typing SINGLE E when not in single mode will report an error and return  MPZ80 manual for the proper switch settings.  the destination drive - A through P. Be careful about which drives (hard disk or floppy) are drives A, B, etc, as this step destroys the original CP/M on the destination drive. To complete this process, press the RETURN key twice: Destination on (drive):, type to warm boot) Function complete Destination drive name (or to warm boot) Reset the system and do a "cold boot." The system header displays your new system size now. SINGLE COMMAND The program SINGLE.COM is of interest mainly to those users who have only a single drive system and a DJ 2D/B controller. Its purpose is to allow these users to copy CP/M files between diskettes. Users with dual drive systems can perform such copies faster and more conveniently simply by using PIP. SINGLE operates by intercepting CP/M calls to disk drive select routines. Rather than selecting a NEW drive, SINGLE prompts the uwithout any change being made, as will typing SINGLE S if already in single mode. REGEN The REGEN.COM command regenerates CP/M single density diskettes which have been formatted in such a way that it is incompatible with the normal operation of the 1791 controller chip (IMSAI diskettes in particular have this problem). This program will be of interest to those users with the Morrow Designs Disk Jockey 2D/B Controller only. It is not intended for use with the Disk Jockey DMA controller. The REGEN program is designed to be used with diskettes which have been formatted incorrectly - not with diskettes that have been partially destroyed. An example of a diskette that could be used with the REGEN program is one that the Disk Jockey 1D board can read, but the Disk Jockey 2D/B cannot (the DJ1D does not utilize the 1791 controller chip). Essentially, the REGEN program reads a complete track of data and format information into memory, filters<(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE) COPYRIGHT (C) 1979, DIGITAL RESEARCH, PIP VERS 1.8$$$ SUB =.:,<> _[]INPIRDPTRUR1UR2RDROUTLPTUL1PRNLSTPTPUP1UP2PUNTTYCRTUC1CONNULEOFDISK READ ERROR$DISK WRITE ERROR$VERIFY ERROR$NOT A CHARACTER SINK$READER STOPPING $NOT A CHARACTER SOURCE$ABORTED$BAD PARAMETER$INVALID USER NUMBER$RECORD TOO LONG$INVALID DIGIT$END OF FILE, CTL-Z?$CHECKSUM ERROR$CORRECT ERROR, TYPE RETURN OR CTL-Z$INVALID FORMAT$HEX$$$$NO DIRECTORY SPACE$NO FILE$COM$START NOT FOUND$QUIT NOT FOUND$CANNOT CLOSE DESTINATION FILE$DESTINATION IS R/O, DELETE (Y/N)?$**NOT DELETED**$$$$$$$NOT FOUND$COPYING -$REQUIRES CP/M 2.0 OR NEWER FOR OPERATION.$UNRECOGNIZED DESTINATION$CANNOT WRITE$INVALID PIP FORMAT$CANNOT READ$INVALID SEPARATOR$1 :2L> ̈́M9  :2!q: " *M n :c4 *M n :2!c:Q !c:2: !:cw>!n !5 Y : { !6!q:!lwҙ  â :0O !q:O| :O| !6:]2l:o'2o:n'2n:m'2m*mMͣ *nMͣ *oMͣ :]:   *}2D" * * *&"!q:UY: Y:ҩ: ʩ:_2ʘ:€!6<:<2!ژ!6 >!]Ҥ; !6:Q::H: !6*M : !6!q:a/>z!/H:_2:!q:A/>Z!/H8: 2::=O>m:W!Q} Hmd>9>!6:2*M!E ^#V͎ڗO **~2*#"m2m͖ 2m!6m!6m!6 m2mͯ m!62m!62m!62m!62m'2:2:TҒ:2!6*ME:2::Ҳ:<22ý: 2:} >ͯ :i:2:d*M:[ 2*">!b!ͯ >!`0ͯ !q:E:24J!46*}a!44EJ *KM^'́:‚ͯ !36'n::0:f9OY#9.3'ͳ.:020' 'ͳ'7 6'!j>A+!s!"@͓1!"<**"͓n "Dn"":!Q2҂:X!Wғä:ڤ*MEÓ:ұ@@:O2Mc;!6#6>!)*&P ~"::H:H:H:H"!6!4:_jYO jM*"S*" 3@bl*M1͓!""7 *M^͆ \͔!":͎H*#"ͧÝ/ :>͛9ͯ .*#":_!' !'6!36' :1/!aE*#">z?C9IͲÁ.!6> !ڇ*&' ~2 ʀ: y.*M!4Q>!қ:=2á:2:Ҭ\>!ҿ:=2K:2K!:!:K\: \!p+q͈*221@:2!o6+6+6!6#6!6#6:G*o .!N6:^*M^!K6!6!6+6' :$::=2K  :ʤ\:ҷ\x'Ͳ:!\͢  :͈'! Ͳ:$: $͈Ͳ!N6' :!Cwͯ !6:^͢c!6{:/>!/H{ͯ :<2Š ::=HҮͯ !6:Ҿ:2 !6::/H͈;!6:> !/>HHͯ :^!w:<2:0}:@E}:!S!W6: z!]6:cm!c6:_z!_6l ::,: HHҰͯ : 2ó:E:1:2v!q!*8!*6: >ͦ>ͦ!q:_  !p+q.*   !q*&!p+q*2!p+q*2!p+q*22!p+q*!p+q*!p+q*!p+q*2!p+q**M:>!(:=2%> >>!F!5+N! ~2!4<2T>>!b}*bMͭz:b2!b6:<2é>!`ҥ*`MͭҞ!`6!6> :é:(!q:!wO! ~2*& :w>!:!4!6>:N<2N!> *N& N2 !p+q!6!6+6 !6: S: M!6g8:N2M*M8p!6!6!6>!ڕ*&P 6!4z!6!6#6#6!6*M8:ھ:*͇g2ê::¿::,͡A<2O>*M8):[ͱ!N5!6ñ:5!6#6>!ڰ!6:<2O>/:!O!T *M͡H~K:¡!6[–ͱ!N5:2:2!4=:[¼ͱ4:!6:.2O8: :* ͇g:[ ͱ!N5!6:%:<2*6 * 6å!q!6> !d*&I :]>!4A>:<2O* :w:?†!6!q!6?!:ҠgÐ!q*&*~!6:22: :]Hں:A2O>: 2ͯ DM!  ::=H-\:N2O_og_{ozg^#V))) _{ozg^#V) d^#V|g}o n_{ozgO{ozgi`N#Fogo&og H ©=¨!p+q* !q*& *M *M !p+q*!!p+q*"!p+q*$!6  !kp+q*j> >ڪ Þ !qp+q/ *pDM9: :M2r:N!r !:r *r& N!r4 !6:͔: :ͳ.!ws+p+q+p+q:w=2wN *s*u w*s#"s*u#"u' !"*M^7 !x6:!xھ **DM͆ 2yʭ :yʗ ͯ *"*6:2x÷ *"!x4d !"/ !j}=2| !"*KM^'_ !z6:|!z1 * "}*}DM͆ ' ͯ *"!z4 :e !"͆ !z6:|!z '? 2*H#"H!{6:{ր!Ң *{& :{4 2!{4m *":ڹ ͯ !z4I '2!"!q: !4>!S :S! :2*M! ^#V͎ * :w*#" = = = = = ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  ÷:S:QHI:N<22: H@"2Í202O> c!6Í202O> ڍ*&O*& !sc*&P :w:·>!ұͯ :22:_!6=!6>'!E!4!p+q*0 !r+s+p+q*~$7*>*>H&>*#"*#"> 2:R͎:!6!6=2:ʙ!6:“H9Ž>!6-e!6ͻ2=2ʺ-é:>>"ͻ2:!!5ͻ2ͬ!\-:>>!p+q:,!6*DM9:<!6:z 2W!6D*&L :w:<2Ov*:>=20O> ڒ:0:AO>Ҥ::A }}Hͬ!wͻO`idͻV[2O>2:!X!6:!:=O!L NE!4 E E:/.*&L 6$L9k9.Xͯ *KM^020 :020:121'ͳ':²ͯ !G6!"!"7 *M^n/ :a/:H!6:ͯ !&6=NAME prl -- "page reelocatable" format DESCRIPTION Prl ("page relocatable") is a file format for relocatable object code defined in the Mpm users manual. It begins with a 256 byte header: header[0] Octal 375. Not documented by Mpm. header[1 to 2] Program size (low byte first). header[3] Not documented by Mpm. header[4 to 5] Size of any required buffer space (low byte first). header[6 to 255] Currently unused, reserved by Mpm. Next comes "program-size" bytes of binary object code assembled at address 0. Finally comes a "bit map", one bit for each byte of code, beginning with the most significant bit of the map's first byte. A 1 bit indicates that the corresponding byte of code should be relocated by adding to it the most significant byte of the load address. The usual way to make a prl file is to assemble the source code twice, once at 0 and once at 100 hex. Then build the map by comparin;CP/M Tpa begin lxi sp,stack ;Stack pointer lxi d,prompt ;Sign-on call pbuff ;To console lhld origin+7 ;Adjust the calling routines for different inx h ; revisions of the Disk Jockey mov a,m lxi h,stdvsl+1 lxi d,4 mov m,a xri 3 dad d mov m,a dad d mov m,a start lxi d,srcmsg ;Prompt the user to select drive call readdrv ;Get a drive designator sta sdisk ;Save source disk lxi d,dstmsg ;Prompt the user to select drive call readdrv ;Get drive designator sta ddisk ;Save destination disk mount lxi d,mntmsg ;Prompt the user to call prbuff ;Read console jnz start ;Ignore anything else regena lxi d,acralf call pbuff xra a ;Select source call select ;Select the drive lxi h,cmdreg mvi m,immirq ;Immediate interupt request mvi a,40h ;Simple delay wirqda dcr a jnz wirqda mov a,m ;Check ready rar jc notrdy ral ral jc notrdy lxi d,0 call gtindx ;Get polarity of index pulse call gtstat ;Test for double sided ani dside jnz ixloi h,sectb ;Initialize sector data pointer table shld secix ; to first sector lxi h,tkbuf ;Initial Track buffer pointer mvi a,1 ;Initial sector number (1) sta secno ;Save sector number sloop lxi b,0feh ;Give up after 256 bytes call searc ;Search for Sector Address mark lxi d,4 ;Field byte count call setcrc ;Evaluate CRC status inx h ;Offset to track number jnz sloop ;Error - Continue Sector mark search lda tkno ;Get current track cmp m ;Compare with memory image jnz terr ;Illegal track number inx h ;Next byte must be 0 mov a,m ;Is it a zero ? ora a jnz terr ;No - jump inx h ;Sector number lda secno ;Get current sector number cmp m ;Correct sector ? jnz terr ;No - jump inx h ;Next byte mov a,m ; must also be ora a ; a zero jnz terr ;Not a zero - jump inx h ;Skip CRC word inx h sc1 lxi b,0fbh ;Search pattern and retry call searc ;Search for mark lxi d,128 ;Sector length (including Data Mark) call setcrc ;Get the CRC status inx h ;Offset pointer to g the bytes one-for-one, setting the corresponding bit to the difference. If two bytes differ by more than 1, then some non-relocatable construct has been used. BUGS The load address must be on a page boundry (multiple of 256). prl.doc 8/5/80 gf pa dblside lxi d,sglside ;No double sided diskettes jmp notrdyx ixlopa call gtstat ;Wait for index pulses ani index xra b jnz restora dcx d mov a,d ora a jnz ixlopa notrdy lxi d,rmessg ;Not ready message notrdyx xchg lxi d,amessg push h call pbuff ;Print drive message lda cdisk ana a lda sdisk jz notdrv lda ddisk notdrv adi 'A' ;And drive letter mov e,a mvi c,2 call bdos pop d call pbuff call unload ;Unload the heads jmp mount restora call restore regenb mvi a,1 ;Select destination call select ;Select the drive lxi h,cmdreg mvi m,immirq ;Immediate interupt request mvi a,40h ;Simple delay wirqdb dcr a jnz wirqdb mov a,m ;Check ready rar jc notrdy ral ral jc notrdy lxi d,wmessg ral jc notrdyx lxi d,0 call gtindx ;Get polarity of index pulse call gtstat ani dside ;Test for double sided diskette jz dblside ixlopb call gtstat ;Wait for index pulses ani index xra b jnz regen dcx d mov a,d ora a data jnz sc1 ;Error - continue search push d ;Save pointer to last CRC byte xchg ;Flip Data address into D,E lhld secix ;Get sector pointer index mov m,e ;Store the inx h ; new sector mov m,d ; data address inx h ;Point to next address storage shld secix ;Save sector index pop d ;Restore pointer to last CRC byte inx d ;Bump to next raw data byte lxi h,secno ;Point to the sector number inr m ; and bump to next sector mov a,m ;Get this number xchg ;Flip data pointer back to HL cpi 27 ;More sectors to go ? jc sloop ;Yes - jump lhld secix ;Get sector data address index dcx h ;To last high order mov d,m dcx h ;Low order mov e,m ;Load the start address lxi h,130 ;Sector length + CRC word dad d ;Compute last address used lxi d,-nbuf ;Negative of last track buffer address dad d ;Is sector data address out of bounds ? jc terr ;Yes - jump mvi a,1 call select ;Select destination drive mvi a,10 ;Reset some counters sta trcnt ;Reset track read error counte* * REGEN.ASM vers 1.1 september 30, 1980 * * By Bryan G. Moore * Design Technology * 4888-H Ronson Court * San Diego, CA 92111 * * Modified for all revision Disk Jockey 2D'S by Bobby Dale Gifford * 9/30/80 * * The program is used to correct the format on Single Density * IBM 3740 compatible diskettes. Attempts to use other diskettes * will probably result in an error message. * * vernum equ 11 ;Version number * 10 origin equ 0F800H bdos equ 5 ;CP/M entry point wboot equ 0 ;Warm boot diskio equ origin+3f8h datreg equ diskio+7 drvsel equ diskio+1 cstall equ diskio+3 cmdreg equ diskio+4 secreg equ diskio+6 trkreg equ diskio+5 sbegin equ origin+3deh ramins equ origin+7e2h dside equ 10Q unloadb equ 17Q sicmd equ 131Q immirq equ 320Q unloada equ 30Q restor equ 11Q rtcmd equ 0e4h wsec equ 0a0h rsec equ 80h index equ 20Q trkzro equ 4 intrqa equ 1 intrqb equ 4 lhsdenb equ 90dh lhddenb equ 80ch lhsdena equ 111h lhddena equ 10h acr equ 0dh alf equ 0ah org 100h jnz ixlopb jmp notrdy restore lxi h,cmdreg mvi m,restor ;Home to track 0 command wrstrs mov a,m rar ;Wait for busy jnc wrstrs wrstrd mov a,m rar ;Wait for not busy jc wrstrd mov a,m ani trkzro jz notrdy ret regen call restore xra a ;Initialize track number sta tkno ;Start with track 0 mvi a,10 ;Reset read retry sta trcnt ; counter to 10 dloop xra a call select call wnbusy ;Wait until not busy lxi d,datreg ;Pointer acts as Data Register lxi h,tkbuf ;Track buffer mvi c,24 ;C is page count mvi a,rtcmd ;Setup controller sta cmdreg datin ldax d ;Load a data byte mov m,a ;Store in memory inr l ;Bump pointer / counter jnz datin ;Get next byte inr h ;Bump high order dcr c ;Hit page count jnz datin ;Loop til track read in * * Scan track for Sector Address Mark (FE Hex) * Since this value is not always read properly using the Read * Track command, this search assumes the high four bits of the * Sector Address Mark are ones. * lx>r sta rwcnt ;Reset the Re-Write counter rewrt lxi h,sectb ;Point to Sector Data address table shld secix ;Initialize index value mvi a,1 ;Initialize sector number sta secno twloop call wnbusy ;Wait for Controller Ready lda secno ;Fetch sector number sta secreg ;Send to controller lhld secix ;Get sector address index mov e,m ;Load the next dma address inx h mov d,m ;High order inx h shld secix ;Save for next loop lxi h,datreg;Controller data register mvi a,wsec ;Write Sector command sta cmdreg ;Start controller mvi c,128 ;Bytes in a sector wloop ldax d ;Get source byte from memory mov m,a ;Write the data to the controller inx d ;Next data byte dcr c ;Hit data byte count jnz wloop ;Loop until data written lxi h,secno ;Point to the sector number inr m ;Increment to next mov a,m ;Load the value cpi 27 ;More sectors to write ? jc twloop ;Yes - jump * * Read the track back. Ignore the data, but verify the CRC * status from the Disk Jockey 1791. * call wnbusace units digit mov a,l ;Get the tens digit cpi '0' ;Is it an ASCII 0 ? jnz per2 ;No - use it mvi l,' ' ;Else make it a space per2 shld tdsply ;Save track number display lxi d,retmsg ;Prompt to press return jmp done ;Treat as if done * * Track read error - decrement counter and try again * terr lxi h,trcnt ;Point to the track read counter dcr m ;Have we tried too many times ? jnz dloop ;No - try again lxi d,tmessg ;Track read message jmp perr ;Continue error routine * * Wait until drive not busy * wnbusy lda cmdreg ;Wait for controller to accomplish ani 1 jnz wnbusy ;Loop until it does ret ;Return when Ready * * Wait for index hole to go by * windex call gtindx windxh call gtstat ani index xra b jz windxh windxl call gtstat ani index xra b jnz windxl ret * * Search up to (B) bytes at HL for pattern represented * by (C). Assumes upper 4 bits are 1s. Exit to TERR if * byte not found. * searc mov a,m ;Load a byte ori 0f0h ;Turn on call model 0239 011000 lxi b,lhddena 023C CA4202 jz loadd 023F 010C08 lxi b,lhddenb 0242 78 loadd mov a,b 0243 CDCD02 call stbits 0246 79 mov a,c 0247 CDCD02 call stbits 024A CDF102 FINDIX CALL INDEXP 024D 2601 MVI H,1 024F 3E2A TKSTEP mvi a,'*' 0251 CDAE02 call pchar 0254 11FCFB LXI D,CMDREG 0257 3E59 MVI A,SICMD 0259 12 STAX D 025A 1A WSICMS LDAX D 025B 1F RAR 025C D25A02 JNC WSICMS 025F 1A WSICMD LDAX D 0260 1F RAR 0261 DA5F02 JC WSICMD 0264 CD1503 CALL TRACK 0267 62 MOV H,D 0268 24 INR H 0269 3E4D MVI A,77 026B BC CMP H 026C C24F02 JNZ TKSTEP 026F CDDB02 call unload 0272 116705 lxi d,fmessg 0275 CD8E02 call pbuff 0278 CD9302 call rbuff 027B FE46 cpi 'F' 027D CA1B01 jz crok 0280 C30000 jmp wboot 0283 E5 SENDMP PUSH h ;save second half 02y ;Wait until not busy call windex ;Wait for index hole lxi h,datreg ;Data register pointer mvi a,1 ;Initialize the rtl1 sta secreg ; sector number mvi c,128 ;Bytes in a sector mvi a,rsec ;Read Sector command sta cmdreg ;Start controller rtloop mov a,m ;Read a byte dcr c ;Done this sector ? jnz rtloop ;No - Loop until sector is read call wnbusy ;Wait until not busy lda cmdreg ;Load controller status ani 9ch ;Extract Not Ready, Not Found, ; CRC Error, Lost Data jnz rwerr ;Go re-write if error lda secreg ;Load sector register inr a ;Next sector cpi 27 ;More sectors to do ? jc rtl1 ;Yes - Loop lxi h,tkno ;Point to Track number inr m ;Bump it mov a,m ;Get next track number cpi 77 ;Is re-formatting complete ? jc tkstep ;No - do next track call unload finish lxi d,fmessg ;Send completion done call prbuff ; message to console cpi 'R' ;More Re-formatting ? jz start ;Yes - jump exit xra a call selda call restore call unload  upper nibble mov m,a ;Save in memory cmp c ;Match ? rz ;Yes - Return inx h ;Bump data pointer dcr b ;Hit byte search count jnz searc ;Loop til search complete pop psw ;Clear stack jmp terr ;Go to error routine * * Checksum checker * Adapted from the Disk Jockey I Shugart Firmware * Performs the Cyclic Redundancy Check (CRC) * The polynomial is G(X) = X^16 + X^12 + X^5 + 1. * * Entry SETCRC - Pointer to data block in HL, * Field length (in bytes) - 1 in D,E * Verify checksum at end of block * Return with Z set if match * setcrc push h ;Save start address pointer xchg ;Flip start addr to DE dad d ;HL points to last byte xchg ;Swap back again crech lxi b,-1 ;Initial value per formula crechx push d ;Save terminating pointer mov a,m xra c mov d,a rrc rrc rrc rrc ani 0fh xra d mov e,a rrc rrc rrc mov d,a ani 1fh xra b mov c,a mov a,d ani 0e0h xra e mov b,a ;Update high order CRC word mov a,d rrc ani 0f0h xra c mov c,a ;S84 CD8E02 CALL pbuff ;send first half 0287 3A6806 LDA LETTER ;print the 028A CDAE02 CALL pchar ; letter 028D D1 POP d ;send the second 028E 0E09 pbuff mvi c,9 0290 C30500 jmp bdos 0293 11BD02 rbuff lxi d,inbufx 0296 0E0A mvi c,10 0298 CD0500 call bdos 029B 3ABE02 lda inbufx+1 029E A7 ana a 029F 3E0D mvi a,acr 02A1 C8 rz 02A2 3ABF02 lda inbuf 02A5 FE61 cpi 'a' 02A7 D8 rc 02A8 FE7B cpi 'z'+1 02AA D0 rnc 02AB D620 sui 40q 02AD C9 ret 02AE E5 pchar push h 02AF C5 push b 02B0 D5 push d 02B1 F5 push psw 02B2 5F mov e,a 02B3 0E02 mvi c,2 02B5 CD0500 call bdos 02B8 F1 pop psw 02B9 D1 pop d 02BA C1 pop b 02BB E1 pop h 02BC C9 ret 02BD 0A00 inbufx db 10,0 02BF 0000000000inb jmp wboot ;Ignore anything else * * Step to next track * tkstep lda sdisk mov b,a lda ddisk cmp b jz samedrv mvi a,'*' call pchar call takstep lda trkreg dcr a sta trkreg samedrv xra a call select call takstep jmp dloop takstep lxi d,cmdreg mvi a,sicmd stax d wsicms ldax d rar jnc wsicms wsicmd ldax d rar jc wsicmd ret * * Re-write error, track did not verify * Bump counter, then flag permanent error * rwerr lxi h,rwcnt ;Point to Track Verify Retry counter dcr m ;Decrement it jnz rewrt ;Go re-write if not expired lxi d,vmsg ;Permanent verify error * * Permanent error common routine * No error codes determined yet * Unload head, then abort * perr call pbuff ;Print the error message call unload lda trkreg ;Get current track number mvi l,'0'-1 ;L is one less than 0 per1 inr l ;Bump digit value sui 10 ;Hit tens digit count jnc per1 ;Loop til C = ASCII tens digit adi '0'+10 ;Restore + ASCII bias for units mov h,a ;Plave low order CRC word inx h ;Bump pointer to next data byte pop d ;Restore terminating pointer mov a,d ;Get high order cmp h ;Test for done CRECH jc crec1 ;Done - Test CRC and set flags jnz crechx ;Continue - next data byte mov a,e ;Get low order and cmp l ; test terminating pointer jnc crechx ;Loop if more bytes to scan crec1 xchg ;Swap CRC word pointer to D,E pop h ;Restore data start address pointer ldax d ;Test low order cmp c ;Clear Z flag if no match inx d ;Next byte rnz ;Done if error ldax d ;High order cmp b ;Set flags and ret ;Return * * Select selects the disk specified by drive A and * loads the head * select mov b,a ;Save in B lda cdisk ;Get currently selected disk cmp b jz loadhd mov a,b ;Recover request sta cdisk ;Update selected drive ana a lda sdisk ;Assume source lxi d,mntsrc ;Mount source message jz sselec ;Source select ? lda ddisk ;Not source, destination lxi d,mntdst ;Mount destination message s?uf db 0,0,0,0,0,0,0,0,0,0 02C9 32F9FB STDVSL STA DISKIO+1 02CC C9 RET 02CD 32FAFB STBITS STA DISKIO+2 02D0 C9 RET 02D1 3AFAFB GTSTAT LDA DISKIO+2 02D4 C9 RET 02D5 3AF4FB model lda diskio-4 02D8 FEC9 cpi (ret) 02DA C9 ret 02DB CDD502 unload call model 02DE 3E18 mvi a,unloada 02E0 CACD02 jz stbits 02E3 3E0F mvi a,unloadb 02E5 C3CD02 jmp stbits 02E8 CDD502 gtindx call model 02EB 0600 mvi b,0 02ED C8 rz 02EE 0610 mvi b,index 02F0 C9 ret 02F1 CDE802 INDEXP call gtindx 02F4 CDD102 windxh call gtstat 02F7 E610 ANI INDEX 02F9 A8 xra b 02FA CAF402 JZ windxh 02FD CDD102 windxl call gtstat 0300 E610 ani index 0302 A8 xra b 0303 C2FD02 jnz windxl 0306 C9 ret 0307 CDE802 indxw call  readdrv ;Invalid input ret * * Pbuff is the CP/M print buffer function * pbuff mvi c,9 jmp bdos pchar push h push b push d push psw mov e,a mvi c,2 call bdos pop psw pop d pop b pop h ret * * Rbuff is the CP/M read buffer function * prbuff call pbuff rbuff lxi d,inbuff mvi c,10 call bdos lda inbuff+1 ana a rz lda inbuff+2 cpi 'a' rc cpi 'z'+1 rnc sui ' ' ret inbuff db 10,10 ds 10 conin mvi c,1 call bdos ani 7fh cpi 3 jz finish ret stdvsl sta diskio+1 ret stbits sta diskio+2 ret gtstat lda diskio+2 ret unload call model mvi a,unloada jz stbits mvi a,unloadb jmp stbits * * Messages and data * prompt db acr,alf db 'Format correction program, VERS ' DB (VERNUM/10)+'0','.',(VERNUM MOD 10)+'0' DB acr,alf,'by Design Technology, San Diego, CA$' srcmsg db acr,alf db 'Select source drive A,B,C, or D (RETURN to exit): $' dstmsg db acr,alf db 'Select destination drive A,B,C or D (RETURN to exi1H͌*#~!www9v2nv2͌͠!6>@=G~xxgi^{¢ziFU͌::ʐ:A_͌->!6>@=±~xx1{gczx!6 ~~~x2> 2ͧ! >2w,$ !"! >2#5:š#~š#:š#~š###b*s#r#"!4~5*+V+^!ښ>> 22!">2ͧ:2*^#V#"!>2w !4~ڵͧͰ!>2>2~ ͧ:k:<!4~M6͠RF:G:P>*͑Z:=2Z>Y`e!5ªy͌:./, Ҁ:g}0‘. "G-!!5u:§gʳ¼~w#Ú~W_WOzGzO#z {G:Sx2:t/::G:̌O> I?p_ xyp:͌ͣ)Avv _͌ ::a{ ¼~22:p>> Format correctiogtindx 030A C3FD02 jmp windxl 030D 2A04 TABLE DW L128 030F 3304 DW L256 0311 3C04 DW L512 0313 4504 DW L1024 0315 3A6A06 TRACK lda select 0318 CDC902 call stdvsl 031B AF XRA A 031C 327503 STA SIDENO 031F CD3803 CALL WTRACK 0322 CDD102 call gtstat 0325 E608 ANI DSIDE 0327 C0 RNZ 0328 3C INR A 0329 327503 STA SIDENO 032C 3A6A06 LDA SELECT 032F E6EF ANI 357Q 0331 CDC902 call stdvsl WIL 0334 CD0703 call indxw 0337 EB XCHG 0338 11FFFB WTRACK LXI D,DATREG ;1791 data reg 033B 2E01 MVI L,1 ;initialize sector reg 033D 01504E LXI B,4e50H ;data & count 033E = OVLD1 EQU $-2 0340 3EF4 MVI A,WTCMD ;issue a write 0342 32FCFB STA CMDREG ; track command 0345 EB XCHG ;adjust the registers 0346 70 WTL1 MOV M,B ;index mark 0347 0D DCR C ; pt): $' mntmsg db acr,alf db 'Press RETURN to correct the format' db acr,alf,'on the above specified diskette: $' fmessg db acr,alf db 'Function Complete' db acr,alf db 'Type R to reformat another, RETURN to exit: $' wmessg db ' is Write Protected.$' rmessg db ' is Not Ready.$' amessg db acr,alf db 'Drive $' sglside db ' is not single sided.$' mntsrc db acr,alf db 'Insert source diskette, then press RETURN: $' mntdst db acr,alf db 'Insert destination diskette, then press RETURN: $' tmessg db acr,alf db 'Track read error' db acr,alf db 'Invalid CRC, Illegal Density, or' db acr,alf db 'Illegal track or sector sequence.$' retmsg db acr,alf db 'Error occured on Track: ' tdsply db ' .' db acr,alf db 'Type R to reformat another, RETURN to exit: $' vmsg db acr,alf db 'Diskette will not accept re-formatting.' db acr,alf db 'Permanent Verification Error and' db acr,alf db 'probable physical damage.$' acralf db acr,alf,'$' * * Data spacen program, VERS 1.1 by Design Technology, San Diego, CA$ Select source drive A,B,C, or D (RETURN to exit): $ Select destination drive A,B,C or D (RETURN to exit): $ Press RETURN to correct the format on the above specified diskette: $ Function Complete Type R to reformat another, RETURN to exit: $ is Write Protected.$ is Not Ready.$ Drive $ is not single sided.$ Insert source diskette, then press RETURN: $ Insert destination diskette, then press RETURN: $ Track read error Invalid CRC, Illegal Density, or Illegal track or sector sequence.$ Error occured on Track: . Type R to reformat another, RETURN to exit: $ Diskette will not accept re-formatting. Permanent Verification Error and probable physical damage.$ $selec push psw ;Save drive to select lda sdisk ;Get source drive mov b,a ;Save in B lda ddisk ;Get destination drive cmp b ;Same ? push psw cz unload pop psw push psw cz pbuff pop psw cz conin ;Print string, and read console pop psw ;Recover drive to select selda mov c,a mvi a,7fh ;Drive select bits qloop rlc ;Rotate select bits dcr c ; to proper drive position jp qloop ani 3fh call stdvsl loadhd call model lxi b,lhsdena jz selprep lxi b,lhsdenb selprep mov a,b call stbits mov a,c jmp stbits * * Get index level * gtindx call model mvi b,0 rz mvi b,index ret * * Get disk Jockey 2D model * model lda diskio-4 cpi (ret) ret * * Prompt the console for a drive, then read and verify the drive * selected * readdrv push d ;Save prompt call pbuff ;Send the prompt call rbuff ;Read the console character pop d ;Recover prompt jz exit sui 'A' ;Subtract ASCII bias jc readdrv ;Invalid input cpi 4 ;Upper limit jp * sdisk db 0ffh ddisk db 0ffh cdisk db 0ffh trcnt DS 1 ;Track read retry counter rwcnt DS 1 ;Re-write counter tkno DS 1 ;Track number secno DS 1 ;Sector number secix DS 2 ;Sector data pointer table pointer sectb ds 2*26 ;Space for sector address table ds 40 stack equ $ org (($+255)shr 8)shl 8 ;Must start on page tkbuf ds 1800H ;Lots of space for track buffer nbuf equ $-1 ;Last byte in track buffer storage area end @3 Copyright (c) 1979, Digital Research????????????CON:RDR:PUN:LST:DEV:VAL:USR:DSK:TTY:CRT:BAT:UC1:TTY:PTR:UR1:UR2:TTY:PTP:UP1:UP2:TTY:CRT:LPT:UL1:R/OR/WSYSDIRR/O R/W SYS DIR ** Aborted **Active User :Active Files: Drive Characteristics65536: 128 Byte Record CapacityKilobyte Drive Capacity32 Byte Directory EntriesChecked Directory EntriesRecords/ ExtentRecords/ BlockSectors/ TrackReserved Tracks is Temp R/O Disk: d:=R/OSet Indicator: d:filename.typ $R/O $R/W $SYS $DIRDisk Status : DSK: d:DSK:User Status : USR:Iobyte Assign: =Bad DelimiterInvalid AssignmentBad Delimiter: Bytes Remaining On R/, Space: Invalid File Indicator** Too Many Files **File Not Found Size Recs Bytes Ext Acc65536 set to R/O Invalid Disk AssignmentWrong CP/M Version (Requires 2.0)!9"2!T OË!]6:\:] Hr3 Ë:\ʀË͇ /ҋͺ *2!"q*"&L ͐ ͐ ͐!$p+q*#~*#N͐*##"#÷!&p+q͠*%DMͱ O O!(q*(& ON DISKSOURCE FILE INCOMPLETE4iW@|?yye RETURN to return to CP/M, or F to Format another: $ Select a sector size: 1) 128 Byte Single density. 2) 256 Byte Double density. 3) 512 Byte Double Density. 4) 1024 Byte Double Density. Sector Size: $ $B=DB * KN{\X COPYRIGHT (C) 1979, DIGITAL RESEARCH _͌> ͒> Ò> Ò͘~#͌ì _2<Ý2ͤ˝ÝÝÝͤߝͤÝ !虜2:2a{_:ʖ:路>Ľ˝ʖ:=2̤–!B!6#5ڝʖ:路Ľ!ͬžʧݞÂݞ )!F#xʺ~0wëw!" !~6ͽ:ý(!Ϡ#͘*~ ""͌#>?͌͘ݞ =_.:;<> Oo$>!ͤY2*O"ʉ@G:ʐ:wÖx2p0ʹ#*©6?ëw˜0ï#6 ¹.0#*ٟ6?۟wȟ0ߟ#6 #6" #~?  xDIR ERA TYPESAVEREN USER"!yΤO#< Ty#O 321y_͸2y2ͽ:˜1͘ОA͌>>͌9؞О2^ :¥.!_~#fow]!v"!ߠçREAD ERRORçNO FILE^:L!*p+q*)O2'!,p+q*+O2'O2'O!.p+q*-LRRLR\LR" O!/q*/& L!1p+q*0#L~*##N!ͽ͞"T!Vq*VMͳ!Xp+q!W* >Wr#MͲ!_p+q!`6>!`6*`&*^*`&Y />!`4 >*]& ~ O!]49!a6:a*]& ~2bO>z*bM >!b/~,H~:H~*H~.H~>H~<H~=H*]& 6!]4T!]4!cq*a&Y :cw!a4!gr+s+p+q!h6>fr*d*f!is*d́"dPY! "f>!h#~Haͫo!h6:i0O͐!mr+s+p+q*lTZs#r*lڶ*l+s#r*jN#F+q#pÌ!nq!"o"q}2uo&"s* s:n*sDM2u:uqos*s"s*o͊O !v6>!vQ*v&w 6`i+46)A*:'ʓ:'O!) ~2vʍ:vO!w 6,]!v6>!v*v&w ~һ*vM !v4˜8AO͐:͐ͱ*##N!ͽ"* N#F*͠"1><<2O!|2.}2"DM =*1!"DMͶ>OچO!"Æ ¹*1 !"DMͶ>O چ O!"Æ ¹*1!"DMͶ>OچO!"Æ ¹*1!"DMͶ>OچO!"Æ ¹*1 ͨ!w# ‘!"ͨ!"DM>O ڨ O!"è *1ͨ!w# ‘!"ͨ!"DM>OڨO!"è *$1!w# x>2F1-y2dc' O2d-c- f* !Τ ~ 3#0 Wx x G ~ # 3x~#B!Y~ɯ2ͤ:=!菉ý:=!菉:ý^T!Τ~  6?#ˆ:`O> K{̡͘ОA͒>:͒ԡ͢>:͒͢xK > K > ͒x  ١͢١žØÆ^ BRͧ9!5‚#~Y‚#"Tͤ<ÆALL (Y/N)?^ TНʧ͘!6!~ڇ w4!Y~ʆ͌ž†t=ʆ٠f ^ Tͤ 2o&)|+!؞ͤԢͤڝ<ͧ՞ÆNO SPACE^ :Ty!ͤݤB*O=?_s#"^sG!~Ypsp2ͤmͤÆÆf ͧÆFILE EXISTS _:Τ É:Τ ģ:ʉ=2)ͽÉ֤ T!@Нk!؞ͤ}|q=qf^!~2ͤ>`~2ݤ2\!ͤ!B!~> >#0~O#Cx2͘՞1)ͽÂf zͧÆBAD LOADCOMf^:Τ ! Â$$$ SUBCOPYRIGHT (C) 1978, DIGITAL RESEARCH 4  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN~# zo&)))))))a{__> ͜> Ü͢~͜#ñ*'x: O!$'*{#z+| ^#V"'0P0K>N2)>2(9x)x\>2))x9ͽ! "$>2!!!4:(N>2":)!"4!"^!*FNy̓*$DM2&:& !ͱ͎ ͢{<2&:#{ê!"$>42))ͽg1i!ͱ:] T\<!ͬ2|\K ! DM\š3! ͬ!͎ͬ ʚAoTA26A2 ͢!,ͱ͎ ͢2#!ͱ!J͎ͬ AڵÚA2A2 !w͎ͬ ͢!#6!ͱÚ2 ͢!ìSYSGEN VER 2.2SOURCE DRIVE NAME (OR RETURN TO SKIP)SOURCE ON A, THEN TYPE RETURNDESTINATION DRIVE NAME (OR RETURN TO REBOOT)DESTINATION ON , THEN TYPE RETURNPERMANENT ERROR, TYPE RETURN TO IGNOREFUNCTION COMPLETEINVALID DRIVE NAME (USE A - P)NO SOURCE FILE3áÒE8×vðû*Ò:L!3w# CC*#~!wwwww>>26҃>2͝q>>26ͭ"’y/2/¡:/͡:G:O:/W:W:W:*DM>>y2! ! 7>`i"'2222!> }7ɯ7y?2yM?22ͭy2:>x V2H*>k~#~#~# ~#!|õ>kw#w#w# w#¢!!͇_:=2:=N>7::<'!:##wy2!}A:l>xWH:2$z7' !>2w,U!͇lJA:O! :G>x2> !" GÊy2!+| 0!N#^q#{~6#6B:w#w ~2#~> -22:O:/:O:=/wOj*+|c~ :w>7*))!w~҂~~z‡^#V:w6r{7~µ~ʺ~¿y/G!^#~##~w~22:2:!A""C{2ֲ!"E9"1A22޲!ty)K!G_^#V*CȧΧԧ~Eȱױ ,&-AGMS!ʥ!եô!ô!ܥBdos Err On : $Bad Sector$Select$File R/O$ɦ:BA2ƥӦӦ!~6 O͐  :E B 2>: b# : y! 4 5~yy5 6yҐ^H@Oy H H: –ͬ  #Hɦ: !  Hù H H $O͐Ӧ: 2 *CN# x: 2 p&x~+é7ɦ2 H! >w_: ! 5ͤNkͱ¦ͱxʊ#Nx: ! 2 ͤ! 5™#wO~x½p Hy<< ʑ :!qMDӦ#2E>! ^#V w#P:BO|^#V#"##"##"##"в!O*!O*Ʋ|!ݲ6ʝ6>*w#w*w#w'û*! J*""!N#F*^#V*~#foyx*{_zW+*s+p+q-*C ͥ!!q#p#w*:BOYG}*MD "ã:ֲ!Bw!>2޲*C~=2ֲu:B2߲~2wE:A*Cw>"!""2B!"ڪ!rQQQâ~?±ͦ~?rQ*ٲ"CQ-Q͜QüQrQ$Q*):B"ڪ*)*)Q;*"E:ֲ;:A2AQÓQÜQҰ*C}/_|/*W}_*"}o|g":޲ʑ*C6:ಷʑw:߲2ֲE**E}DQ>2ղà@LaÁvlÐƴÒÅÊibÌ× 48K CP/M Vers. 2.2, Cbios rev 3.1 For Thinker Toys Disk Jockey 2D Controller @ 0F800H. ~#O Ó1!!6͓22!͊>22!"!"22յ:O!>2G7::1>>22ʳ2O3-0>2?!"^>r><<V *^"^2?O!"^DMr> u*y2`i"y2A~ n& ~ʥ/oy2={$>22 =' !Z_A7yx#*βDM*s#r*s#ryOxG*в0MD!!òN:㲷 EG>O: \S*C :ݲqn& ^#V>O^"*}:ò*)=":IJO:㲡o"*C *C!ͮ~2~2ͦ:Ų2ͮ:ղީO:㲁w:w |g}o*# ):BO!yoxg*:BO}!N#F "*Ȳ#*s#r^ ~!J! J*:鲅o$*C~i6iw**{#zr+s{ozg**̲͕** Ī,w͜͸ڪͲ!!N#F$**O!~#ҫ:A#~$=2Ek͌ҫ:Բ:Ų/GyO>2Բ!زq*C"ٲ͡ʔ*ٲJҔ^:زOyʃ?|x | s-|N-# S:2E!Բ~Яw>T D^6kƪ-äPYyѬ 5*Ʋ{zBK52:O=ʃz<2!ʟ#ʐ :=o&)))))))!>µ55>2յ>=>2̵>!2յ" :O3:O :O0O>7>Ե!7!۵w#7!R!¶oԵ!:_~#foԵ!R!:V!:r!:|!ʶÄlҶҶҶҶݶҶҶҶFҶyҶ:=2>22Ҷ2@!>=@@ >>2      %&'()*+, -. /0  12!"34#$!"#$1234%&'(5678 )*+,9:;<  -./0 12345678 !"#$%&'(9:;<=>?@)*+,-./0?4 < 3@+ t4  h@x1@;W@|, lV *C ^OèƪT *C~wD -'  -@ͦ~^*C Ox! N!Fwyxʋ>ڋ>*Cw~#+w#w+ɯ2E22i^ *C :ݲ~ۭw~͔͔# # ͭ w ~>2Ҳ!E5T*C!"C"C!w# F! w͌x2Ҳ͢*C ~<wʃG:Ų!Ҳʎì 4~ʶ¬:Ӳ<ʶ$ʶïZͻx>2ղ>2Ӳͻ:!ᲾZ2:Eẅ́͊ѨͲҩ>2ղ>2ӲT*CGͻ:ẅ́n>2ײ;O ^DM;}H>"*C :ݲ:ײddslO s#r:E͊:ղ==»y==»*Ww#*"Ѩ͸*:IJG#š"ڪѨ͸:!Ჾүw4!iw:ղҩZ!E~=26ҩ2ղ*C!!~~#~O~G#n,-.‹! w! yG!x͢.:E<ʄ! q!pQ:E<. ʄ$.:E<ʄi6}2ExN! ~态O>G~G!~G} *C!r#r#r ^ͥ_y#x#{ @$A $@B B HH II$@DI ABI$"$H$H@$$I! H*  $H@@A I $D!!$I"BI"I"@$BIIH$$$$BBI$@BI!"$$A DI$@ A$@$$@H! "!$$" @B$!!!DH$$"H @@BHH  !$$A"D@ "A" "BHA " !$ D B I $ !$$ H@BD D$ HI DIA!$$$ $" "B>!H% - *DM ͱͷDM  ͱ* N#F 9ͱ * ^#V))DM Tͱ* ~ *} *M!+s#r#4 !s+p+q!6!66:!ڄ !6!6>!r *&**&Y i !6!4+4A :} :!4- >!699 2¨ :!4: :2!6+6>! :O!9 DMi ͱ:!O!Y DMi :2:2͠!4 F :® )!6>!ګ ͠:O!9 DMi 8ͱ!6> !ڤ Å :2k ä  ͐:!O!Y DMi w !4C F :¿ >F : F :=229:Y= ;>9*&Y DM =2 I>!6:=28 :2:2 :!!29:Y T >:Y,e \>Ì !p+q*~:ʉ *N͐*#"o :͐!p+q!'"!6> **{2*́"PY! ">!+~H !6:0O͐à k͐ 0399 C29703 JNZ WTL10 ; sector data 039C 0E40 MVI C,40H ;count 039D = OVLS3 EQU $-1 039E 70 WTL11 MOV M,B ;write second 039F 0D DCR C ; quarter of 03A0 C29E03 JNZ WTL11 ; sector data 03A3 0E40 MVI C,40H ;count 03A4 = OVLS4 EQU $-1 03A5 70 WTL12 MOV M,B ;write third 03A6 0D DCR C ; quarter of 03A7 C2A503 JNZ WTL12 ; sector data 03AA 0E40 MVI C,40H ;count 03AB = OVLS5 EQU $-1 03AC 70 WTL13 MOV M,B ;write fourth 03AD 0D DCR C ; quarter of 03AE C2AC03 JNZ WTL13 ; sector data 03B1 36F7 MVI M,0F7H ;crc data bytes 03B3 3E1B MVI A,27 ;last sector + 1 03B4 = OVLS6 EQU $-1 03B5 01364E LXI B,4E36H ;count & data 03B6 = OVLS7 EQU $-2 03B8 70 WTL14 MOV M,B ;data 03B9 0D DCR C ; postamble 03BA C2B803 JNZ WTL14 ; field 03BD BB CMP E ;last sector test 03BE C26303 JNZ SLOOP 03C1 70 WTL1͠Q" 8AO͐jͱͷDM͏ m  Z"l"!6>ʥ *}҆ *M ͱ*}x O͐} W͐ͱ !+s#r!+s#r#4D ͠:\ʹ :\=Oͳͩ !6!)6l :) :)=2) :] & !"}2\!h6?!j6?\:'C:'ƀo&")!)6!"):)/)HҘ]!)6> !)ڎ*)&*)*)&*) y!)6 Ä:) 2):)<2)M*)#")/:)ҩ*)+")`*")#"]!*)!/H!")!"]*)) *)s#r!)6> !).*)&*)*)&*) w:)<2)*)) >w#6*)) w#6*)!) w#6*)%) w#6*)) N#F*)) q#p*)%) *) ~e *) * ~o&͞ *)%) q#p!)6* >!)6!)6>!)=:)!)w=*)&*)~2):)*)& *):)2):):*)!) *)) s, >X\:)“>!d!")>!)d!")!")*++!)a*)) ^#V")]*)")*)) ^#V")]!)6> !)T*)&*)~2)*)&*)~2)O;*)) ^#V"reamble 0348 C24603 JNZ WTL1 ; field 034B 010C00 LXI B,0CH ;data & count 034C = OVLD2 EQU $-2 034E 70 WTL2 MOV M,B ;index mark 034F 0D DCR C ; zero leader 0350 C24E03 JNZ WTL2 ; field 0353 36F6 OVLD3 MVI M,0F6H ;special double 0355 36F6 MVI M,0F6H ; density clock 0357 36F6 MVI M,0F6H ; and data mark 0359 36FC WTL3 MVI M,0FCH ;index mark 035B 01324E LXI B,4E32H ;data & count 035C = OVLD4 EQU $-2 035E 70 WTL4 MOV M,B ;sector mark 035F 0D DCR C ; preamble 0360 C25E03 JNZ WTL4 ; field 0363 010C00 SLOOP LXI B,0CH ;data & count 0364 = OVLD5 EQU $-2 0366 70 WTL5 MOV M,B ;sector mark 0367 0D DCR C ; zero leader 0368 C26603 JNZ WTL5 ; field 036B 36F5 OVLD6 MVI M,0F5H ;special double 036D 36F5 MVI M,0F5H ; density clock 036F 36F5 MVI M,0F5H ; and data mark 0371 36FE WTL6 MVI M,0FEH ;sector mark 0373 72 5 MOV M,B ;fill data 03C2 0D DCR C ; to index hole 03C3 C2C103 JNZ WTL15 03C6 70 WTL16 MOV M,B ;fill data 03C7 0D DCR C ; to index hole 03C8 C2C603 JNZ WTL16 03CB 70 WTL17 MOV M,B ;fill data 03CC 0D DCR C ; to index hole 03CD C2CB03 JNZ WTL17 03D0 C9 RET 03D1 7E OVLAY MOV A,M ;length of list 03D2 E5 PUSH H ;save list ptr 03D3 213803 LXI H,WTRACK ;overlay area 03D6 E3 XTHL ; recover pointer 03D7 1600 MVI D,0 03D9 23 OVLAY1 INX H ;increment pointer 03DA 5E MOV E,M ;get offset 03DB E3 XTHL ;exchange pointers 03DC 19 DAD D ;add the offset 03DD F5 PUSH PSW ;save length count 03DE 0A LDAX B ;get replacement data 03DF 77 MOV M,A ;do the replacement 03E0 03 INX B ;next replacement data 03E1 F1 POP PSW ;recover length count 03E2 3D DCR A ;decrement 03E3 E3 XTHL ;exchan)*)) *)) N#Fq#p*)) *)s#r*)#")!)6 J:)!)J!)6 :)<2)*)")҈q:tw͠ͱ!"))ҍ*)) ^#V")]͠.*)DM\ -°!\6:\ͣ:ͱ*}DM'ͫ*)%) N#F'ͫ*)!) N#F'k͐ͫ*)) N#FͫR͐/͐ *) ~IO͐NW͐ͫ8AO͐:͐ *) ~2)t(͐:)҃)͐*)#")Ã& \!"))\Ұ*)")]͠*)M! ^#V *) >*) w *) >*) w *) >*) w *) >*) w.*)DM\ -+!\6uͱ:)O! DMͱ*)#")Ù*))))))"):m w>.Yn -:YS:Z Hҧ!6> 2)½>!)6> !)*)&*)>2) :) .͐*)M͐:)<2)99:Y=/9&ͩ c,Hͩ 9 EHͺ i`N#Fog_og_ogDM!>))덑o|gҘ =†DM!>))ҭ =¥~ ³^#V) ½^#V|g}o _{ozgi`N#Fogo&og_{_z#WMOV M,D ;track number 0374 3600 MVI M,0 ;side number 0375 = SIDENO EQU $-1 0376 73 MOV M,E ;sector number 0377 3601 MVI M,1 ;sector length 0378 = OVLS1 EQU $-1 0379 36F7 MVI M,0F7H ;crc data bytes 037B 1C INR E ;increment sector 037C 01164E LXI B,4E16H ;data & count 037D = OVLD7 EQU $-2 037F 70 WTL7 MOV M,B ;sector mark 0380 0D DCR C ; postamble 0381 C27F03 JNZ WTL7 ; field 0384 010C00 LXI B,0CH ;data & count 0385 = OVLD8 EQU $-2 0387 70 WTL8 MOV M,B ;data mark 0388 0D DCR C ; zero leader 0389 C28703 JNZ WTL8 ; field 038C 36F5 OVLD9 MVI M,0F5H ;special double 038E 36F5 MVI M,0F5H ; density clock 0390 36F5 MVI M,0F5H ; and data mark 0392 36FB WTL9 MVI M,0FBH ;data mark 0394 0140E5 LXI B,0e540H ;data & count 0395 = OVLS2 EQU $-2 0397 70 WTL10 MOV M,B ;write first 0398 0D DCR C ; quarter of Cge pointers 03E4 C2D903 JNZ OVLAY1 03E7 E1 POP H ;adjust stack 03E8 C9 RET * The lists below represents the distances * between successive locations of the WTRACK * routine that are to be overlaid in order * that the same routine will serve to format * different sized and density diskette * sector formats 03E9 12 DLIST DB 18 ;length of list 03EA 06 DB OVLD1-WTRACK 03EB 01 DB 1 03EC 0D DB OVLD2-OVLD1-1 03ED 07 DB OVLD3-OVLD2 03EE 01 DB 1 03EF 01 DB 1 03F0 07 DB OVLD4-OVLD3-2 03F1 01 DB 1 03F2 07 DB OVLD5-OVLD4-1 03F3 07 DB OVLD6-OVLD5 03F4 01 DB 1 03F5 01 DB 1 03F6 10 DB OVLD7-OVLD6-2 03F7 01 DB 1 03F8 07 DB OVLD8-OVLD7-1 03F9 07 DB OVLD9-OVLD8 03FA 01 DB 1 03FB 01 H 0441 80 DB 80H 0442 10 DB 16 0443 6A4E DW 4E6AH * Overlay data for double density * 8 sectors/track 1024 byte sectors 0445 03 L1024 DB 3 0446 00E5 DW 0e500H 0448 00 DB 0 0449 00 DB 0 044A 00 DB 0 044B 09 DB 9 044C 744E DW 4E74H 044E 0D0A AMESSG db acr,alf 0450 4472697665 db 'Drive $' 0457 204973204ERMESSG db ' Is Not Ready.$' 0466 2049732057WMESSG db ' Is Write Protected.$' 047B 0D0A BMESSG db acr,alf 047D 496D70726F db 'Improper Response.$' 0490 0D0A DMESSG db acr,alf 0492 53656C6563 db 'Select Drive (A,B,C,or D): $' 04AE 4469736B20SMESSG db 'Disk Jockey 2D Disk Format program' 04D0 2052657669 db ' Revision ' 04DA 352E32 db '0'+revnum/10,'.','0'+(revnum mod 10) 04DD 0D0A db acr,alf 04DF 5479706520 db 'Type "^C" to return to CP/M, "N" to restart.$' 050C 0D0A IMESSG db acr,alf 050E 496E736572 db 'Insert a Write Enabled Diskette in Drive $' 0538 0D0A JMESSG db acr,alf 053A 436C6F7365 db 'Close the Drive Door and then Press RETURN: $' 0567 0D0A FMESSG db acr,alf 0569 46756E6374 db 'Function Complete.' 057B 0D0A db acr,alf 057D 5479706520 db 'Type RETURN to return to CP/M, or F to Format another: $' 05B5 0D0A denmsg db acr,alf 05B7 53656C6563 db 'Select a sector size:' 05CC 0D0A db acr,alf 05CE 2020202020 db ' 1) 128 Byte Single density.' 05EE 0D0A db acr,alf 05F0 2020202020 db ' 2) 256 Byte Double density.' 0610 0D0A db acr,alf 0612 2020202020 db ' 3) 512 Byte Double Density.' 0632 0D0A db acr,alf 0634 2020202020 db ' 4) 1024 Byte Double Density.' 0655 0D0A db acr,alf 0657 536563746F db 'Sector Size: $' 0665 0D0A24 DB 1 03FC 09 SLIST DB 9 ;list length 03FD 40 DB OVLS1-WTRACK 03FE 1D DB OVLS2-OVLS1 03FF 01 DB 1 0400 07 DB OVLS3-OVLS2-1 0401 07 DB OVLS4-OVLS3 0402 07 DB OVLS5-OVLS4 0403 09 DB OVLS6-OVLS5 0404 02 DB OVLS7-OVLS6 0405 01 DB 1 * Overlay data for single density * formatted diskettes 0406 28FF SDLIST DW 0FF28H 0408 06 DB 6 0409 C35903 JMP WTL3 040C 1AFF DW 0FF1AH 040E 06 DB 6 040F C37103 JMP WTL6 0412 0BFF DW 0FF0BH 0414 06 DB 6 0415 C39203 JMP WTL9 * Overlay data for double density * formatted diskettes 0418 504E DDLIST DW 4E50H 041A 0C DB 0CH 041B 36F6 MVI M,0F6H 041D 36 DB 36H 041E 324E DW 4E32H 0420 0C DB 0CH 0421 36F5 MVI 1600235EE319F50A77A9 :1003E00003F13DE3C2D903E1C91206010D07010182 :1003F00007010707010110010707010109401D015D :1004000007070709020128FF06C359031AFF06C39D :1004100071030BFF06C39203504E0C36F636324E74 :100420000C36F536164E0C36F5360020E520202029 :100430001B1BFF0140E54040401B364E0280E5801B :100440008080106A4E0300E500000009744E0D0A1A :1004500044726976652024204973204E6F742052BF :10046000656164792E242049732057726974652070 :1004700050726F7465637465642E240D0A496D7043 :10048000726F70657220526573706F6E73652E2483 :100490000D0A53656C656374204472697665202883 :1004A000412C422C432C6F722044293A2024446969 :1004B000736B204A6F636B65792032442044697303 :1004C0006B20466F726D61742070726F6772616D20 :1004D000205265766973696F6E20352E320D0A548D :1004E00079706520225E432220746F2072657475D6 :1004F000726E20746F2043502F4D2C20224E2220EC :10050000746F20726573746172742E240D0A496EC3 :1005100073657274206120577269746520456E613D :10052000626C6564204469736B6574746520696EE0 :1005300020447269766520240D0A436C6F73652030 :10054000746 acralf db acr,alf,'$' 0668 00 letter db 0 0669 00 drvno db 0 066A 00 select db 0 066B 00 newsize db 0 066C ds 50 069E = stack equ $ 069E end M,0F5H 0423 36 DB 36H 0424 164E DW 4E16H 0426 0C DB 0CH 0427 36F5 MVI M,0F5H 0429 36 DB 36H * Overlay data for single density * 26 sectors/track 128 byte sectors 042A 00 L128 DB 0 042B 20E5 DW 0e520H 042D 20 DB 20H 042E 20 DB 20H 042F 20 DB 20H 0430 1B DB 27 0431 1BFF DW 0FF1BH * Overlay data for double density * 26 sectors/track 256 byte sectors 0433 01 L256 DB 1 0434 40E5 DW 0e540H 0436 40 DB 40H 0437 40 DB 40H 0438 40 DB 40H 0439 1B DB 27 043A 364E DW 4E36H * Overlay data for double density * 15 sectors/track 512 byte sectors 043C 02 L512 DB 2 043D 80E5 DW 0e580H 043F 80 DB 80H 0440 80 DB 8086520447269766520446F6F7220611B :100550006E64207468656E20507265737320524516 :100560005455524E3A20240D0A46756E6374696FD5 :100570006E20436F6D706C6574652E0D0A54797032 :10058000652052455455524E20746F207265747523 :10059000726E20746F2043502F4D2C206F722046B6 :1005A00020746F20466F726D617420616E6F746885 :1005B00065723A20240D0A53656C656374206120CE :1005C000736563746F722073697A653A0D0A20202F :1005D000202020312920313238204279746520537F :1005E000696E676C652064656E736974792E0D0A97 :1005F000202020202032292032353620427974658F :1006000020446F75626C652064656E736974792E21 :100610000D0A202020202033292035313220427934 :10062000746520446F75626C652044656E736974EF :10063000792E0D0A20202020203429203130323418 :10064000204279746520446F75626C652044656E44 :10065000736974792E0D0A536563746F7220536940 :0C0660007A653A20240D0A2400000000F6 :0000000000 D copyright(c) 1977, digital research $Error On Line $SUBNo 'SUB' File Present$Disk Write Error$Command Buffer Overflow$Command Too Long$Parameter Error$Invalid Control Character$Directory Full$Cannot Close, Read/Only?$!9"!͇͊!p+q* ͊!p+q*͍2!p+q*͍2!p+q*͊!p+q*͍!p+q*͍!p+q*͍2!s+p+q+p+q:=2ʦ** w*#"*#"!p+q(+*DM*p*& 6:ep\:=ͧ!t6>!t%\= >!t6:t<2t=O! ~2u b:<2O>9b!60+~9b!60+4:uat:u_2u:uMʉSͧ!v6!"v!|6:|Ҁ!x6 2}:} Hk:} h:}$6 2}$*}M3:}02}O> ͧ3!z6ͭ:}"!}5́ͭ́3*yM"h:}^a a2}O>Vͧ^:}>*z& ~ !z4í!{q*v#"v͙dͧ*vv :{w:x<2xO>}|ͧreturnPermanent error, Type return to ignoreFunction completeInvalid drive (Use A through P)No such fileSource file incompleteCan not generate systems on 5 1/4 diskettes that are formatted in single density.o warm boot)Destination on 6, then type returnPermanent error, Type return to ignoreFunction completeInvalid drive (Use A through PNo such fileSourc?-!6]:ͧz2~e:~2O! 6*~& 6$>!~_z*~& w!~5Bx:yͧ*v+"vv ~_{ozg001 $$$$ SUBW Extended Submit Vers 2.0Xsub Already Present$Requires CP/M Version 2.0 or later$:y*###ƒ# yk   җ 4!~=ŐW!xʵ ~#èbx {~#o}où.xsubb!np+q*m2_!pp+q*o ]xsub*"-!/"*"+!""1 M*!"́!"* (xsub active)$|*y ʥ*"*7***x*́͋<͛ :%*=26͋!7^#6 #6 #6$ 8*7~O #w# !6:6=2% ͋*-"*$$$ SUBq:(=2(N *$*& w*$#"$*&#"&' !"N*M^7 !)6:!)ھ *N*DM͆ 2*ʭ :*ʗ ͯ *N"P*6:2)÷ *N"N!) $@BA$! A "!$""CCOPYRIGHT (C) 1978, DIGITAL RESEARCH   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOP~# |o&)))))))a{__> ͞> Þͤ~͞#ó*`z:O!$'*!ͳ6|3 ^#V"`#2_+?~(?>2_>(2)>2(w ~#f>P2)>2(rzbzw>2)bzrͿ:_ʝ::2\ ! ">2!4:(BN>2:)!4!^!*FNyͅ*DM:ʼ!ͳ͐ͤ ʼ!6"@!":_?!">62)!:(=?bͿè1!Iͳ:] ʡ\