diff --git a/inspector.html b/inspector.html index e2b25ee..9050849 100644 --- a/inspector.html +++ b/inspector.html @@ -5,13 +5,14 @@ var gFile, gData, - gCAT_TRK_SEC, + gCatalog, gCAT_TRK, gCAT_SEC, gContext, - MAX_SIZE = 143360; + gFont; -const +const + MAX_DISK_SIZE = 143360, FILE_TYPE_TEXT = 0x00, FILE_TYPE_INTEGER = 0x01, FILE_TYPE_APPLESOFT = 0x02, @@ -20,7 +21,7 @@ const FILE_TYPE_RELOC = 0x10, FILE_TYPE_C = 0x20, FILE_TYPE_D = 0x40, - FILE_TYPES = [ 'T', 'I', 'A', 'B', 'S', 'R', 'C', 'D' ]; + FILE_TYPES = [ 'T', 'I', 'A', 'B', 'S', 'R', 'C', 'D' ]; console.log( "Loading..." ); @@ -44,20 +45,27 @@ console.log( "Loading..." ); function makeFileType( fileType ) { var type = 0, raw = fileType; - + while (raw > 0) { type++; raw >>= 1; } - + return FILE_TYPES[ type ]; } + function parseInt16( low, high ) + { + var n = makeUnsigned( low ) + n += makeUnsigned( high ) * 256; + return n; + } + function parseName( catalogEntry ) { var name = '', c, MAX_FILENAME = 30; - + for( var i = 0; i < MAX_FILENAME; i++ ) { // 0x00: FTOC Track @@ -72,18 +80,17 @@ console.log( "Loading..." ); return name; } - function parseInt16( low, high ) - { - var n = makeUnsigned( low ) - n += makeUnsigned( high ) * 256; - return n; - } +// --- Disk Utility --- function readTrackSectorBytes( track, sector, offset, length ) { + if (offset === undefined) offset = 0; // read entir sector + if (length === undefined) length = 256; // if not specified + if (track > 34) alert( "Track > 34" ); if (sector > 16) alert( "Sector > 16" ); if (offset >256) alert( "Offset > 256" ); + if (length > MAX_DISK_SIZE) alert( "Size > " + MAX_DISK_SIZE ); if( gData ) { @@ -95,9 +102,52 @@ console.log( "Loading..." ); return null; } +// --- DOS3.3 Meta Utility --- + + // @return array of blocks + function readFTOC( track, sector ) + { + var ftoc = [], + next_trk = track, + next_sec = sector, + i, trk, sec, raw, block; + + do + { + raw = readTrackSectorBytes( next_trk, next_sec, 0x00, 0x100 ); + next_trk = raw[ 0x01 ]; // next FTOC track + next_sec = raw[ 0x02 ]; // next FTOC sector + + for( i = 0x0C; i < 0x100; i += 2 ) + { + trk = raw[ i+0 ]; + sec = raw[ i+1 ]; + + if( !trk ) + break; + + block = trk*16 + sec; + ftoc.push( block ); + } + } while (next_trk > 0); + + return ftoc; + } + + function readVTOC() + { + var VTOC_TRK = 0x11, + vTOC_SEC = 0x00, + TRK_SEC; + + TRK_SEC = readTrackSectorBytes( VTOC_TRK, vTOC_SEC, 1, 2 ); + gCAT_TRK = TRK_SEC[0]; // $11 + gCAT_SEC = TRK_SEC[1]; // $0C + } + function readCatalogEntry( i ) { - var MAX_ENTRY_LENGTH = 0x23, + var MAX_ENTRY_LENGTH = 0x23, MAX_ENTRIES_PER_SECTOR = 7; // Catalog $11,C .. $11,1 @@ -119,24 +169,126 @@ console.log( "Loading..." ); // 0x03: Filename // 0x21: Length Low // 0x22: Length Hi - var raw = gCAT_TRK_SEC = readTrackSectorBytes( gCAT_TRK, sector, offset, 35 ), + var raw = readTrackSectorBytes( gCAT_TRK, sector, offset, 35 ), entry = {}, type = makeUnsigned( raw[0x02] ); - - entry.track = parseInt ( raw[0x00] ); - entry.sector = parseInt ( raw[0x01] ); - entry.locked = (type >= 128)|0; - entry.type = makeFileType( type & 0x7F ); - entry.name = parseName ( raw ); - entry.length = parseInt16 ( raw[0x21], raw[0x22] ); + + entry.track = parseInt ( raw[0x00] ); + entry.sector = parseInt ( raw[0x01] ); + entry.locked = (type >= 128)|0; + entry.file_type = type & 0x7f; + entry.type = makeFileType( type & 0x7F ); + entry.name = parseName ( raw ); + entry.length = parseInt16 ( raw[0x21], raw[0x22] ); return entry; } +// --- DOS 3.3 File Utility --- + + function readBinaryAddressLength( track, sector ) + { + var ftoc = readFTOC( track, sector ); + var data = readBlock( ftoc[0] ); + var address = parseInt16( data[0], data[1] ); + var size = parseInt16( data[2], data[3] ); + + return { address: address, size: size }; + } + + function readBlock( block ) + { + var trk = (block / 16)|0, + sec = (block % 16)|0; + return readTrackSectorBytes( trk, sec ); + } + + function readCatalog() + { + var entry, i = 0, LOCKED = [ ' ', '*' ], entries = [], text = (new Array( 40 ).join('-')) + '\n', totalSize = 0, start, length; + + do + { + entry = readCatalogEntry( i++ ); + if( entry && entry.track ) + { + text += LOCKED[ entry.locked ] + entry.type + ' ' + padLeft( entry.length, 5, '0' ) + ' ' + padLeft( entry.name, 30 ); + + var temp; + switch( entry.file_type ) + { + case FILE_TYPE_APPLESOFT: start = 0x0801; length = 0; break; + case FILE_TYPE_BINARY : temp = readBinaryAddressLength( entry.track, entry.sector ); start = temp.address; length = temp.size; break; + default: break; + } + + text += '\n'; + totalSize += entry.length; + entries.push( entry ); + } + } while (entry !== null) + + text += (new Array( 40 ).join('-')) + '\n'; + text += 'Total Files: ' + entries.length + ', Sectors Used: ' + totalSize; +console.log( text ); + + gCatalog = entries; + return entries; + } + + function readFile( name ) + { + var i, file, result = {}, data = null, ftoc; + + if( !gCatalog ) + return null; + + for( i = 0; i < gCatalog.length; i++ ) + { + file = gCatalog[i]; + if (name === file.name) + break; + else + file = null; + } + + if( file ) + { + ftoc = readFTOC( file.track, file.sector ); + data = readFileData( ftoc, file ); + } + + return data; + } + + // isBinary if 4 byte prefix should be stripped + function readFileData( ftoc, file ) + { + var iBlock, sector, nBlocks = ftoc.length, data = new Array( nBlocks * 256 ), offset, temp; + + for( iBlock = 0; iBlock < nBlocks; iBlock++ ) + { + sector = readBlock( ftoc[ iBlock ] ); + offset = iBlock*256; + for( var b = 0; b < 256; b++ ) + data[ offset + b ] = sector[ b ]; + } + + var address = 0, length = data.length; + + if (file.file_type === FILE_TYPE_BINARY) + { + address = parseInt16( data[0], data[1] ); + length = parseInt16( data[2], data[3] ); + data = data.slice( 4, 4 + length ); + } + + return { data: data, address: address, length: length }; + } + // --- Implementation --- /* Version 1 - --------------------------------------- *A 00006 ^HELLO *I 00002 APPLESOFT @@ -153,33 +305,36 @@ console.log( "Loading..." ); *B 00024 ^THINGS --------------------------------------- Total Files: 13, Sectors Used: 397 + + Version 1 + ^HELLO , A$0801, L44 (L$002C) + APPLESOFT, A$0801, L39 (L$0027) + PIX , A$2000, L$2000 + PICEX , A$2000, L$2000 + SEKTOR , A$4004, L$3FF0 + ^VOCAB , A$17DA, L$2D63 + ^CHARSET , A$4400, L$0400 + CASTLE , A$4004, L$3DFC + BACKUP , A$4004, L$3DFC + ^TEXT , A$0000, L$???? + @INIT , A$0880, L$12BE + @WOLF , A$0810, L$16EB + ^THINGS , A$4800, L$1638 + + Version 2: + ^TEXT , A$0000, L$???? <-- (shorter: 5 sectors vs 7 sectors) + PICEX , A$2000, L$2000 + PIX , A$2000, L$2000 + SEKTOR , A$4004, L$3FF0 + ^VOCAB , A$17DA, L$2D63 + ^CHARSET , A$4400, L$0400 + CASTLE , A$4004, L$3DFC + BACKUP , A$4004, L$3DFC + @INIT , A$0880, L$1432 <-- LONGER : $1432 vs $12BE + @WOLF , A$0810, L$161C <-- SHORTER: $161C vs $16EB + ^THINGS , A$4800, L$1638 <-- SHORTER: $1638 vs $16EB + ^RAM , A$0810, L$0167 <-- NEW */ - -function catalog() -{ - var entry, i = 0, LOCKED = [ ' ', '*' ], entries = [], text = (new Array( 40 ).join('-')) + '\n', totalSize = 0; - - do - { - entry = readCatalogEntry( i++ ); - if( entry && entry.track ) - { - text += LOCKED[ entry.locked ] + entry.type + ' ' + padLeft( entry.length, 5, '0' ) + ' ' + entry.name + '\n'; - totalSize += entry.length; - entries.push( entry ); - } - } while( entry !== null ) - - text += (new Array( 40 ).join('-')) + '\n'; - text += 'Total Files: ' + entries.length + ', Sectors Used: ' + totalSize; -console.log( text ); - return entries; -} - -function readFile( name ) -{ -} - function main() { console.log( " Done" ); @@ -189,8 +344,8 @@ function main() document.getElementById('id_select_dsk').addEventListener('change', onSelectFile, false); } - var canvas = document.getElementById( "canvas" ); - gContext = canvas.getContext( "2d" ); + var canvas = document.getElementById( "canvas" ); + gContext = canvas.getContext( "2d" ); // gContext.drawImage( image, x, y ); } @@ -200,18 +355,15 @@ function main() // .target.result; function onLoadFile( e ) { - if (e.loaded == MAX_SIZE) // .dsk is < 144K + if (e.loaded == MAX_DISK_SIZE) // .dsk is < 144K { gFile = e.target; gData = e.target.result; // Read VTOC to find CATALOG - gCAT_TRK_SEC = readTrackSectorBytes( 0x11, 0x00, 1, 2 ); - - gCAT_TRK = gCAT_TRK_SEC[0]; // $11 - gCAT_SEC = gCAT_TRK_SEC[1]; // $0C - - catalog(); + readVTOC(); + readCatalog(); + gFont = readFile( '^CHARSET' ); } } @@ -225,10 +377,10 @@ function onSelectFile( e ) for( iFile = 0; iFile < nFile; iFile++ ) { tFile = aFile[ iFile ]; - - if( tFile.size > MAX_SIZE ) + + if( tFile.size > MAX_DISK_SIZE ) { - alert( ".dsk images must be <= " + MAX_SIZE ); + alert( ".dsk images must be <= " + MAX_DISK_SIZE ); break; } reader = new FileReader();