|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 19712 (0x4d00) Types: TextFile Names: »XAMN.BAS«
└─⟦f77262dd7⟧ Bits:30002865 SWEEP version 4.1 for JET80 └─ ⟦this⟧ »XAMN.BAS«
$lines REM XAMN Disk track and sector editor. REM No warranty is made, expressed, or implied. var hl,de,bc,a_psw ; cpu registers dph ; location of disk parameter header block_size ; cp/m logical block size max_tracks ; number of tracks/disk seldsk ; bios select disk settrk ; bios set track routine setsec ; bios set sector routine setdma ; bios set dma address b_read ; bios read sector b_write ; bios write sector sectran ; bios sector skew disk_number ; disk number to examine = integer var crt ; logical device list ; logical device CR ; ASCII CR BS ; ASCII BS ascii_mask ; ASCII mask bit_0_mask ; mask used to look at bit 0 true, false ; true/false logical flags = integer var menu_selection ; prompt return = char var r1, r2, r3, r4 ; Real number for computations = real based spt ; sectors/track dsm ; max data block number drm ; number of dir blocks off ; number of reserved tracks wboot ; entry to bios dpb ; location of disk parameter block skew_table ; location of bios skew table (used by sectran) alv ; pointer to allocation table = integer based bsh ; block shift factor blm ; block mask exm ; extent mask alloc_byte ; used in searching allocation table = byte crt = 0 rem S-BASIC device # for con: list = 1 rem S-BASIC device # for lst: CR = 0DH BS = 8 ascii_mask = 007FH bit_0_mask = 1 true = -1 false = not true base wboot at 1 rem location of bios wboot entry seldsk = wboot + 0018H rem set up bios entry address settrk = wboot + 001BH setsec = wboot + 001EH setdma = wboot + 0021H b_read = wboot + 0024H b_write= wboot + 0027H sectran= wboot + 002DH rem dma buffer for read/write sector operations dim byte sector(128) var loc_sector = integer location array loc_sector = sector dim base char file_chars(11) fcb_name(11) byte_dm(15) dim base integer word_dm(7) based bios_return = byte rem high order byte of a_psw only location var hl = a_psw base bios_return at hl+1 0seldsk input "Disk number (0,1,...,15) ";disk_number bc = disk_number call ( seldsk, dph, de, bc, a_psw ) if dph=0 then 0seldsk base skew_table at dph base dpb at dph+10 base alv at dph+14 bc = loc_sector+1 call ( setdma, hl, de, bc, a_psw ) base spt at dpb base bsh at dpb+2 base blm at dpb+3 base exm at dpb+4 base dsm at dpb+5 base drm at dpb+7 base off at dpb+13 block_size = 1024*(2^(bsh-3)) r1 = ((dsm+1)*(block_size/128))/spt max_tracks = r1 + off function physical_sec ( sectr = integer ) = integer if skew_table=0 then sectr=sectr-1 end = sectr function skew ( sectr = integer ) = integer if skew_table<>0 then begin bc = sectr - 1 de = skew_table call (sectran, hl, de, bc, a_psw) end else hl = sectr - 1 end = hl procedure get_sector( track, sec = integer ) var x = integer for x=1 to 128 sectorÆxÅ = 0 next x bc = track call ( settrk, hl, de, bc, a_psw ) bc = sec call ( setsec, hl, de, bc, a_psw ) call ( b_read, hl, de, bc, a_psw ) sectorÆ0Å = bios_return end of get_sector procedure put_sector( track, sec = integer ) bc = track call ( settrk, hl, de, bc, a_psw ) bc = sec call ( setsec, hl, de, bc, a_psw ) call ( b_write, hl, de, bc, a_psw ) sectorÆ0Å = bios_return end of put_sector function ascii_character ( x = integer ) = char x = x and ascii_mask if x<32 then x = 46 end = x procedure display_sector ( device = integer ) var x, j = integer for x=1 to 128 step 16 print hex$(x-1);" "; for j=0 to 15 if j=8 then print ' '; print #device; right$(hex$(sectorÆx+jÅ),2);' '; next hex byte for j=0 to 15 if j=8 then print ' '; print #device; ascii_character(sectorÆx+jÅ); next ascii byte print #device next line of sector display end of display sector 0menu print print print "Drive number ...............";disk_number, "Current disk ";'A'+disk_number;':' print "Sectors/track ..............";spt, 'Æ'; hex$(spt) ;'Å' print "Tracks/Disk ................";max_tracks, 'Æ'; hex$(max_tracks) ;'Å',Ø "XAMN Disk editor" print "Number of reserved tracks ..";off, 'Æ'; hex$(off) ;'Å',Ø "Version 1.1" print "# of logical blocks ........";dsm+1, 'Æ'; hex$(dsm+1) ;'Å' print "# of directory entries .....";drm+1, 'Æ'; hex$(drm) ;'Å' print "Block size .................";block_size, 'Æ'; hex$(block_size) ;'Å' print "128 byte sectors/block .....";block_size/128, 'Æ'; hex$(block_size/128) ;'Å' print "Disk size in K .............";(dsm+1)*(2^(bsh-3)), 'Æ'; hex$( (dsm+1)*(2^(bsh-3)) ) ;'Å' text 0,% Help Examin a sector (physical)......... 1 A Examin a sector (logical skew)..... 2 B Move Sectors ...................... 3 C Produce a map of a file ........... 4 D Produce a map of disk ............. 5 E Find bad sectors .................. 6 F Compute Block from Trk & Sec ...... 7 G Compute Trk & Sec from Block ...... 8 H Select disk ....................... 9 I % input2 "Please enter selection ==>"; menu_selection var track, sectr =integer var letter = char function group ( trk, sec = integer ) = integer var sectrs, grp = real sectrs = ((trk-off)*spt)+sec-1 grp = sectrs/(block_size/128) end = grp procedure trk_sec ( grp = integer ) = integer var sectrs, sec, trk = real sectrs = grp*(block_size/128) trk = sectrs/spt track = trk + off sec = sectrs-((track-off)*spt) sectr = sec + 1 end procedure bump ( amount = integer ) sectr = sectr + amount if sectr>spt then begin track = track +1 if track>=max_tracks then track=max_tracks-1 sectr = 1 end if sectr<1 then begin track = track -1 if track<0 then track=0 sectr = spt end end of bump procedure dump_physical ( device = integer ) get_sector track, physical_sec(sectr) print #device; "Track=";track; " Physical sector=";sectr, Ø " Logical sector=";skew(sectr); if sectorÆ0Å=1 then print #device; " æBADå" else print #device display_sector device print end of dump_physical procedure dump_logical ( device = integer ) get_sector track, skew(sectr) print #device; "Track=";track; " Logical sector=";sectr, Ø " Physical sector=";skew(sectr); if sectorÆ0Å=1 then print #device; " æBADå" else print #device display_sector device print end of dump_logical function hex_byte ( c = char ) = char c = c-'0' if c>9 then c=c-7 end = c procedure modify ( t, s = integer ) var c=char var x=integer repeat begin x=1 repeat begin print hex$(x-1) ;' '; right$(hex$(sectorÆxÅ),2) ;' ';Ø ascii_character(sectorÆxÅ);' '; input3 c if c<>'.' and c<>CR and c<>BS then begin sectorÆxÅ=hex_byte(c) input3 c if c<>'.' and c<>CR and c<>BS then sectorÆxÅ=(sectorÆxÅ*16)+hex_byte(c) end if c='.' then x=128 if c=BS then begin x = x-2 if x<0 then x=0 end if c=CR and x=128 then x=127 print x=x+1 end until x>128 print print t,s display_sector crt repeat begin print input "(W)rite to disk, (C)hange more bytes, (A)bort ";c if c='W' then begin print "Writing sector to disk..." put_sector t, s if sectorÆ0Å=1 then begin input2 "Write fault. <ret> to continue";c print display_sector crt c=' ' end else c='A' end of write end until c='A' or c='C' end until c='A' end of procedure modify $page case menu_selection of '1': begin input "Track, sectr"; track, sectr print dump_physical crt repeat begin input "(F)oward, (B)ackward, (R)ange, (C)hange, (E)xit ";letter case letter of 'F': begin bump 1 dump_physical crt end 'B': begin bump -1 dump_physical crt end 'R': begin var s, c, device =integer input "Number of sectors to display";c device = crt for s=1 to c dump_physical device bump 1 next Sector end of 'R' 'C': modify track, physical_sec(sectr) end of case end until letter='E' end of option #1 '2': begin input "Track, sectr"; track, sectr print dump_logical crt repeat begin input "(F)oward, (B)ackward, (R)ange, (C)hange, (E)xit ";letter case letter of 'F': begin bump 1 dump_logical crt end 'B': begin bump -1 dump_logical crt end 'R': begin var s, c, device =integer input "Number of sectors to display";c device = crt for s=1 to c dump_logical device bump 1 next Sector end of 'R' 'C': modify track, skew(sectr) end of case end until letter='E' end of option #2 '3': begin var t = char repeat begin t = ' ' while t<>'L' and t<>'P' and t<>'E' do input "Move (L)logical sectors, (P)hysical sectors, (E)xit ";t if t<>'E' then begin var ok = char var trk1, trk2, sec1, sec2, cnt, x = integer ok = ' ' while ok<>'Y' and ok<>'A' do begin input "Source Track, Sector ";trk1, sec1 input "Dest. Track, Sector ";trk2, sec2 input "Number of sectors to move";cnt print print "Source Track, Sector = ";trk1, sec1 print "Dest. Track, Sector = ";trk2, sec2 print "Number of sectors to move ";cnt print input "Is the above correct (Y/N/(A)bort) ";ok end if ok<>'A' then begin for x=1 to cnt print "Reading track";trk1;" Sector";sec1; if t='L' then print " Physical #";skew(sec1); if t='P' then get_sector trk1, physical_sec(sec1) else get_sector trk1, skew(sec1) if sectorÆ0Å<>0 then print " Fault" else print print "Writing track";trk2;" Sector";sec2; if t='L' then print " Physical #";skew(sec2); if t='P' then put_sector trk2, physical_sec(sec2) else put_sector trk2, skew(sec2) if sectorÆ0Å<>0 then print " Fault" else print track = trk1 sectr = sec1 bump 1 trk1 = track sec1 = sectr track = trk2 sectr = sec2 bump 1 trk2 = track sec2 = sectr next sector end end end until t='E' end of option #3 '4': begin var count ; number of sectors to search = integer var file_name ; file name to search for = string:12 location var count=file_name locate file_chars at count track = off rem starting track sectr = 1 rem starting sector input "File name (<Ret> only to skip) ";file_name if len(file_name)>0 then begin function match = integer var result, x = integer result = true if fcb_nameÆ0Å=0E5H then result=false else for x=1 to 11 if file_charsÆxÅ<>(fcb_nameÆxÅ) and file_charsÆxÅ<>'?' Ø then result = false next x end = result procedure dump_fcb( device = integer ) var x = integer print #device; "Track";track; " Sector";sectr; ' '; for x=1 to 11 print #device; fcb_nameÆxÅ; next x print #device; ' '; if dsm>255 then for x=0 to 7 print #device; hex$(word_dmÆxÅ); ' '; next x else for x=0 to 15 print #device; right$( hex$(byte_dmÆxÅ),2 ); ' '; next x print #device end file_name = fcb$( file_name ) print "Search for file:";file_name for count = 1 to (drm+1)/4 get_sector track, skew(sectr) print "Searching Track:";track; " Sector:";skew(sectr);" ";chr(0DH); locate fcb_name at loc_sector+1 locate byte_dm at loc_sector+17 locate word_dm at loc_sector+17 if match then dump_fcb crt locate fcb_name at loc_sector+33 locate byte_dm at loc_sector+49 locate word_dm at loc_sector+49 if match then dump_fcb crt locate fcb_name at loc_sector+65 locate byte_dm at loc_sector+81 locate word_dm at loc_sector+81 if match then dump_fcb crt locate fcb_name at loc_sector+97 locate byte_dm at loc_sector+113 locate word_dm at loc_sector+113 if match then dump_fcb crt bump 1 next directory sector var x=char print input2 "Press <Ret> to continue";x end end of option #4 '5': begin function bin( x = integer ) = string var bits = string:8 var y = integer bits = "" for y=1 to 8 if x and bit_0_mask then bits="1"+bits else bits="0"+bits x=x/2 next y end = bits bc = 14 de = disk_number call(5,hl,de,bc,a_psw) rem bdos seldsk function var x, y = integer print for x = 0 to (dsm/8) step 8 print hex$(x*8);": "; for y = 0 to 7 if x+y<=(dsm/8) then begin base alloc_byte at alv+x+y print bin(alloc_byte);' '; end next y print next x print "Last block is";dsm+1,'Æ';hex$(dsm+1);'Å' input2 "Press return to cont.";x end of option #5 '6': begin var x = real var t1, t2 = integer input "Starting track, last track ";t1,t2 track = t1 sectr = 1 for x = 1 to (t2-t1+1)*spt print "Track:";track; " Sector:";sectr; " "; get_sector track, physical_sec(sectr) if sectorÆ0Å<>0 then print "æBADå" else print chr(0DH); bump 1 next x print input2 "Read complete, press <Ret> to cont.";x end of option #6 '7': begin input "Track, Sector ";track,sectr print "Group #";group(track,sectr), hex$(group(track,sectr)) input "Press <Ret> to cont. ";track end of #7 '8': begin var x = integer input "Group number";x trk_sec x print "Track:";track,"Sector:";sectr input "Press <Ret> to cont.";x end of #8 end of function number menu selection if menu_selection = '9' then 0seldsk case menu_selection of 'A': begin text 0,% To examine a physical sector use this command. Sectors are numbered from 1 to the end of the track. Tracks are numbered from 0 to the end of the disk. The physical sector number displayed is the sector number from 1 to end of track, the logical sector number is the number your BIOS uses to access this physical sector. When you type this command you will be asked for the track and sector you wish to examine. After you respond the sector will be displayed. You will then be asked if you want to move forward or backward from your current position on the disk. You may, at this time, specify a range of sectors to be displayed from the current position on the disk. You may also edit the sector making changes to it in an buffer internal to XAMN. And last but not least you can exit to the main menu. Each option is selected by one key press. The letters are F, B, R, C, and E. When changing a sector the sector address in hex will be displayed along with the hex contents of the byte and the ASCII character it represents (Period if none). To enter a new value type it in, to move forward push return, backward push back space, and to exit push period. Upon exit you may re-edit, write the sector to the disk, or abort leaving the sector on the disk un-changed. % input2 "Press <Ret> to cont.";track end of 'A' 'B': begin text 0,% Use this command to examine and edit logical sectors. Logical sectors are the sectors that the BDOS refers to, the physical sector number may be different. It is the physical sectors that the BIOS access. For more info see 'A' above. % input2 "Press <Ret> to cont.";track end of 'B' 'C': begin text 0,% This command is used to move sectors around on the disk. It can be used to move physical sectors or logical sectors around. The main purpose for moving sectors around is to allow re-formatting of a track on the disk. First, move the data on the track you wish to re-format to an unused area of the disk. This area can be found by generating a map of the disk using another of XAMN's commands (Map disk, see also help 'E'). Second, exit XAMN and using your system format utility format ONLY the track with the bad sector. Re-enter XAMN. Third, move the data back onto the track. This command will start by asking you if this is a physical move or a logical move (use logical if you want to move CP/M groups around). You can exit at this point. Next, you will be asked for the starting track and sector number, the destination track and sector and the number of sectors to move. BEFORE each sector is read or written you will be told of it, if an error occurs you can see where it happens. AFTER the operation the program will move on to the next sector if all is well or print "Fault" to show a read or write error. % input2 "Press <Ret> to cont.";track end of 'C' 'D': begin text 0,% This command generates a map of a file showing all the CP/M groups assigned to that file. It also reports on the directory sectors that contain that file's FCB. As each directory sector is searched a report of that operation is made sector by sector. % input2 "Press <Ret> to cont.";track end of 'D' 'E': begin text 0,% This command generated a disk map showing allocated groups. A 0 is an empty group, un-used by any file. A 1 is a group in use by a file. WARNING: this command makes a BDOS disk select call. At the end of the map a few groups that do not exist may be displayed as empty. This is because the disk map is made up of bytes where each bit in the byte is a group, the last byte in the map may not be fully used up. At the end of the map the last group number is given, use this number. This command can be used to find unused disk space. % input2 "Press <Ret> to cont.";track end of 'E' 'F': begin text 0,% This command is used to find a bad sector. It will ask for a starting track and an ending track. As it reads each track and sector it will report its progress. Any bad sectors will be reported. % input2 "Press <Ret> to cont.";track end of 'F' 'G': begin text 0,% Use this command to compute a group number from the LOGICAL track and sector. Remember that logical groups start in the directory, NOT in the reserved, or 'OFF' tracks. % input2 "Press <Ret> to cont.";track end of 'G' 'H': begin text 0,% Use this command to compute the track and LOGICAL sector number for a given group. % input2 "Press <Ret> to cont.";track end of 'H' 'I': begin text 0,% Use this command to select another disk. XAMN commands are in reference to the current disk number (see the display above the menu). % input2 "Press <Ret> to cont.";track end of 'I' end of help case statement if menu_selection=03H then stop goto 0menu «eof»