Read file data of root directory entries

This commit is contained in:
Jordan Goulder 2025-01-16 15:07:43 -05:00
parent 442253b953
commit a6503ae65b

View File

@ -46,6 +46,8 @@ export interface IStandardDirEntry {
attributes: IAttributes attributes: IAttributes
size: number size: number
firstCluster: number firstCluster: number
clusterChain: number[]
data: ArrayBuffer
} }
export interface ILongFileNameDirEntry { export interface ILongFileNameDirEntry {
@ -84,7 +86,45 @@ export class FloppyDisk {
new DataView(this._buffer, this.rootDirOffset, this.rootDirSize), new DataView(this._buffer, this.rootDirOffset, this.rootDirSize),
) )
} }
if (this._rootDirEntries === null) {
return null
} }
for (const entry of this._rootDirEntries) {
if (entry.type === 'standard-entry' && (entry.size > 0 || entry.attributes.directory)) {
entry.clusterChain = this.clusterChain(entry.firstCluster)
const dataSize = entry.clusterChain.length * this.bytesPerCluster
if (dataSize === 0) {
continue
}
const data = new Uint8Array(dataSize)
for (let i = 0; i < entry.clusterChain.length; i++) {
const offset = (entry.clusterChain[i] - 2) * this.bytesPerCluster
const view = new Uint8Array(
this._buffer,
this.dataOffset + offset,
this.bytesPerCluster,
)
data.set(view, i * this.bytesPerCluster)
}
console.log(
entry.name.trim() + (entry.extension.trim() ? '.' + entry.extension.trim() : ''),
)
entry.data = data.slice(0, entry.size > 0 ? entry.size : data.byteLength)
if (
!entry.attributes.directory &&
(['BAT', 'TXT', 'BAS'].includes(entry.extension) || entry.name.trim() === 'LICENSE')
) {
const decoder = new TextDecoder()
console.log(decoder.decode(entry.data))
}
}
}
}
return this._rootDirEntries return this._rootDirEntries
} }
@ -116,6 +156,14 @@ export class FloppyDisk {
return this.bootSectorInfo?.biosParameterBlock?.bytesPerSector ?? 0 return this.bootSectorInfo?.biosParameterBlock?.bytesPerSector ?? 0
} }
get sectorsPerCluster() {
return this.bootSectorInfo?.biosParameterBlock?.sectorsPerCluster ?? 0
}
get bytesPerCluster() {
return this.bytesPerSector * this.sectorsPerCluster
}
get rootDirSectors() { get rootDirSectors() {
if (this.bytesPerSector === 0) { if (this.bytesPerSector === 0) {
return 0 return 0
@ -143,6 +191,34 @@ export class FloppyDisk {
get rootDirSize() { get rootDirSize() {
return this.rootDirSectors * this.bytesPerSector return this.rootDirSectors * this.bytesPerSector
} }
nextCluster(current: number): number {
const tableOffset = Math.floor(current + current / 2)
const tableSector = Math.floor(this.reservedSectorCount + tableOffset / this.bytesPerSector)
const entityOffset = tableOffset % this.bytesPerSector
const table = new DataView(
this._buffer,
tableSector * this.bytesPerSector,
2 * this.bytesPerSector,
)
const value = table.getUint16(entityOffset, true)
return current & 1 ? value >> 4 : value & 0x0fff
}
clusterChain(start: number): number[] {
const chain = [start]
let next = this.nextCluster(start)
while (next > 1 && next < 0xff7) {
chain.push(next)
next = this.nextCluster(next)
}
return chain
}
} }
function decodeBootSector(data: DataView): IBootSectorInfo | null { function decodeBootSector(data: DataView): IBootSectorInfo | null {
@ -262,6 +338,8 @@ function decodeDirectoryEntry(data: DataView): DirEntry | null {
extension, extension,
attributes, attributes,
firstCluster, firstCluster,
clusterChain: [],
data: new ArrayBuffer(0),
size, size,
} }
} }