Compare commits

..

No commits in common. "e6bdde292d9d5e90fe34b3b00aea83b47e2f14a5" and "85e07598d40c35aa056df72e793355bbf0f39cbf" have entirely different histories.

3 changed files with 54 additions and 130 deletions

View File

@ -1,18 +1,20 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed } from 'vue' import { computed } from 'vue'
import { FloppyDisk } from '@/floppy/disk.ts' import { getBiosParameterBlock } from '@/floppy/disk.ts'
import PropertyList from '@/components/PropertyList.vue'
const { data = new ArrayBuffer(0) } = defineProps<{ data: ArrayBuffer }>() const { data = new ArrayBuffer(0) } = defineProps<{ data: ArrayBuffer }>()
const floppyDisk = computed(() => { const biosParameterBlock = computed(() => {
return new FloppyDisk(data) return getBiosParameterBlock(data)
}) })
</script> </script>
<template> <template>
<section v-if="floppyDisk.bootSectorInfo"> <section v-if="biosParameterBlock">
<h3>Boot Sector</h3> <h3>BIOS Parameter Block (BPB)</h3>
<pre>{{ floppyDisk.bootSectorInfo }}</pre> <PropertyList :obj="biosParameterBlock" />
<pre>{{ biosParameterBlock }}</pre>
</section> </section>
</template> </template>

View File

@ -14,12 +14,8 @@ const hexDump = computed(() => {
return ''.padEnd(80, ' ') return ''.padEnd(80, ' ')
} }
let lastLine = ''
let repeat = false
while (offset < total) { while (offset < total) {
const offsetStr = offset.toString(16).padStart(8, '0') const values = [offset.toString(16).padStart(8, '0')]
const values = []
const asciiValues: string[] = [] const asciiValues: string[] = []
let cnt = 0 let cnt = 0
while (offset < total && cnt < 16) { while (offset < total && cnt < 16) {
@ -35,7 +31,7 @@ const hexDump = computed(() => {
values.push(byte.toString(16).padStart(2, '0')) values.push(byte.toString(16).padStart(2, '0'))
const char = String.fromCharCode(byte) const char = String.fromCharCode(byte)
if (char >= ' ' && char <= '~') { if (char > ' ' && char <= 'a') {
asciiValues.push(char) asciiValues.push(char)
} else { } else {
asciiValues.push('.') asciiValues.push('.')
@ -64,21 +60,7 @@ const hexDump = computed(() => {
asciiValues.push('|') asciiValues.push('|')
} }
const line = values.join(' ') lines.push(values.join(' ') + asciiValues.join(''))
if (line !== lastLine) {
if (repeat) {
lines.push('*'.padEnd(80, ' '))
}
repeat = false
lines.push([offsetStr, line].join(' ') + asciiValues.join(''))
lastLine = line
} else {
repeat = true
}
}
if (repeat) {
lines.push('*'.padEnd(80, ' '))
} }
lines.push(offset.toString(16).padStart(8, '0').padEnd(80, ' ')) lines.push(offset.toString(16).padStart(8, '0').padEnd(80, ' '))
return lines.join('\n') return lines.join('\n')
@ -94,7 +76,7 @@ pre {
width: fit-content; width: fit-content;
padding: 0.5em 1em 10em; padding: 0.5em 1em 10em;
box-sizing: border-box; box-sizing: border-box;
overflow-y: scroll; overflow: scroll;
min-height: 10rem; min-height: 10rem;
height: 20rem; height: 20rem;
max-height: 20rem; max-height: 20rem;

View File

@ -1,121 +1,61 @@
export interface IBootSectorInfo { export interface BiosParameterBlock {
jumpInstruction: [number, number, number] oemId: string
oemName: string
biosParameterBlock: IBiosParameterBlock
extendedBootSector: IExtendedBootSectorSmall
bootPartitionSignature: number
}
export interface IExtendedBootSectorSmall {
driveNumber: number
reserved: number
bootSignature: number
volumeId?: number
volumeLabel?: string
fileSystemType?: string
}
export interface IBiosParameterBlock {
bytesPerSector: number bytesPerSector: number
sectorsPerCluster: number sectorsPerCluster: number
reservedSectorCount: number numReservedSectors: number
tableCount: number numFATs: number
rootEntryCount: number numRootDirEntries: number
totalSectorsSmall: number totalSectors: number
mediaDescriptorType: number mediaTypeDescriptor: number
sectorsPerTableSmall: number sectorsPerFAT: number
sectorsPerTrack: number sectorsPerTrack: number
headCount: number numHeads: number
hiddenSectorCount: number bootSignature: number
totalSectorsLarge: number volumeId: number
volumeLabel: string
fileSystemId: string
} }
export class FloppyDisk { export function getBiosParameterBlock(buffer: ArrayBuffer): BiosParameterBlock | null {
private readonly _buffer = new ArrayBuffer(0) if (buffer.byteLength < 64) {
private _bootSector: IBootSectorInfo | null = null
constructor(buffer: ArrayBuffer) {
this._buffer = buffer
}
get bootSectorInfo() {
return (this._bootSector = this._bootSector ?? decodeBootSector(this._buffer))
}
}
function decodeBootSector(buffer: ArrayBuffer): IBootSectorInfo | null {
if (buffer.byteLength < 512) {
return null return null
} }
const asciiDecoder = new TextDecoder('ascii')
const data = new DataView(buffer) const data = new DataView(buffer)
const jumpInstruction: [number, number, number] = [ const asciiDecoder = new TextDecoder('ascii')
data.getUint8(0),
data.getUint8(1),
data.getUint8(2),
]
const oemName = asciiDecoder.decode(buffer.slice(3, 11)) const oemId = asciiDecoder.decode(buffer.slice(3, 11))
const bytesPerSector = data.getUint16(11, true) const bytesPerSector = data.getUint16(11, true)
const sectorsPerCluster = data.getUint8(13) const sectorsPerCluster = data.getUint8(13)
const reservedSectorCount = data.getUint16(14, true) const numReservedSectors = data.getUint16(14, true)
const tableCount = data.getUint8(16) const numFATs = data.getUint8(16)
const rootEntryCount = data.getUint16(17, true) const numRootDirEntries = data.getUint16(17, true)
const totalSectorsSmall = data.getUint16(19, true) const totalSectors = data.getUint16(19, true)
const mediaDescriptorType = data.getUint8(21) const mediaTypeDescriptor = data.getUint8(21)
const sectorsPerTableSmall = data.getUint16(22, true) const sectorsPerFAT = data.getUint16(22, true)
const sectorsPerTrack = data.getUint16(24, true) const sectorsPerTrack = data.getUint16(24, true)
const headCount = data.getUint16(26, true) const numHeads = data.getUint16(26, true)
const hiddenSectorCount = data.getUint32(28, true)
const totalSectorsLarge = data.getUint32(32, true)
const driveNumber = data.getUint8(36)
const reserved = data.getUint8(37)
const bootSignature = data.getUint8(38) const bootSignature = data.getUint8(38)
const volumeId = data.getUint32(39, true)
let volumeId const volumeLabel = asciiDecoder.decode(buffer.slice(43, 54))
if (bootSignature === 0x28 || bootSignature === 0x29) { const fileSystemId = asciiDecoder.decode(buffer.slice(54, 62))
volumeId = data.getUint32(39, true)
}
let volumeLabel
if (bootSignature === 0x29) {
volumeLabel = asciiDecoder.decode(buffer.slice(43, 54))
}
let fileSystemType
if (bootSignature === 0x29) {
fileSystemType = asciiDecoder.decode(buffer.slice(54, 62))
}
const bootPartitionSignature = data.getUint16(510, true)
return { return {
jumpInstruction, oemId,
oemName,
bootPartitionSignature,
biosParameterBlock: {
bytesPerSector, bytesPerSector,
sectorsPerCluster, sectorsPerCluster,
reservedSectorCount, numReservedSectors,
tableCount, numFATs,
rootEntryCount, numRootDirEntries,
totalSectorsSmall, totalSectors,
mediaDescriptorType, mediaTypeDescriptor,
sectorsPerTableSmall, sectorsPerFAT,
sectorsPerTrack, sectorsPerTrack,
headCount, numHeads,
hiddenSectorCount,
totalSectorsLarge,
},
extendedBootSector: {
driveNumber,
reserved,
bootSignature, bootSignature,
volumeId, volumeId,
volumeLabel, volumeLabel,
fileSystemType, fileSystemId,
},
} }
} }