Compare commits

..

4 Commits

2 changed files with 35 additions and 41 deletions

View File

@ -37,19 +37,4 @@ pre {
color: #c0c0c0;
border: 1px solid rgba(255, 255, 255, 0.3);
}
:deep(ul) {
padding: 0;
}
:deep(ul ul) {
padding: 0 0 0 1.5em;
}
:deep(li) {
list-style: none;
line-height: 1.5rem;
margin: 0;
padding: 0;
}
</style>

View File

@ -41,25 +41,29 @@ export interface IAttributes {
export interface IStandardDirEntry {
type: 'standard-entry'
id: string
name: string
basename: string
extension: string
attributes: IAttributes
size: number
firstCluster: number
clusterChain: number[]
subDirEntries: TDirEntry[]
}
export interface ILongFileNameDirEntry {
type: 'long-filename-entry'
id: string
}
export interface IFinalDirEntry {
type: 'final-entry'
id: string
}
export interface IUnusedDirEntry {
type: 'unused-entry'
id: string
}
export type TDirEntry = IStandardDirEntry | ILongFileNameDirEntry | IFinalDirEntry | IUnusedDirEntry
@ -188,36 +192,35 @@ export class FloppyDisk {
return chain
}
addDirectory(listing: string, entries: TDirEntry[]) {
listing += '\n<ul>'
addDirectory(listing: string, path: string[], entries: TDirEntry[]) {
for (let i = 0; i < entries.length; i++) {
const entry = entries[i]
if (entry.type !== 'standard-entry') {
if (
entry.type !== 'standard-entry' ||
entry.attributes.volumeId ||
entry.name === '..' ||
entry.name === '.'
) {
continue
}
const fullName = `${entry.name}${entry.extension ? '.' + entry.extension : ''}`
listing += `${path.join('\\') + '\\'}${entry.name}`
if (entry.name === '.' || entry.name === '..' || entry.attributes.volumeId) {
// do nothing
} else if (entry.attributes.directory) {
listing += `\n<li>${fullName}\\`
listing = this.addDirectory(listing, entry.subDirEntries)
listing += '</li>\n'
if (entry.attributes.directory) {
listing += '\\<br/>'
listing = this.addDirectory(listing, [...path, entry.name], entry.subDirEntries)
} else {
listing += `\n<li>${fullName}</li>\n`
listing += '<br/>'
}
}
listing += '\n</ul>'
return listing
}
buildFileListing(): string {
let listing = '<ul>A:\\'
listing += this.addDirectory('', this.rootDirEntries ?? [])
listing += '</ul>'
let listing = '<p>\\<br/>'
listing += this.addDirectory('', [''], this.rootDirEntries ?? [])
listing += '</p>'
return listing
}
}
@ -305,20 +308,25 @@ function decodeDirectoryEntry(data: DataView, fd: FloppyDisk): TDirEntry | null
const firstByte = data.getUint8(0)
const attributeByte = data.getUint8(11)
const id = crypto.randomUUID()
if (firstByte === 0) {
return { type: 'final-entry' }
return { type: 'final-entry', id }
} else if (firstByte === 0xe5) {
return { type: 'unused-entry' }
return { type: 'unused-entry', id }
} else if (attributeByte === 0x0f) {
return { type: 'long-filename-entry' }
return { type: 'long-filename-entry', id }
} else {
const asciiDecoder = new TextDecoder('ascii')
const name = asciiDecoder.decode(data.buffer.slice(data.byteOffset, data.byteOffset + 8)).trim()
const basename = asciiDecoder
.decode(data.buffer.slice(data.byteOffset, data.byteOffset + 8))
.trim()
const extension = asciiDecoder
.decode(data.buffer.slice(data.byteOffset + 8, data.byteOffset + 11))
.trim()
const name = basename + (extension ? '.' + extension : '')
const attributeByte = data.getUint8(11)
const attributes: IAttributes = {
@ -335,24 +343,25 @@ function decodeDirectoryEntry(data: DataView, fd: FloppyDisk): TDirEntry | null
const entry: IStandardDirEntry = {
type: 'standard-entry',
id,
name,
basename,
extension,
attributes,
firstCluster,
clusterChain: [],
size,
subDirEntries: [],
}
if (entry.attributes.directory && entry.name !== '.' && entry.name !== '..') {
entry.clusterChain = fd.clusterChain(entry.firstCluster)
const clusterChain = fd.clusterChain(entry.firstCluster)
const dataSize = entry.clusterChain.length * fd.bytesPerCluster
const dataSize = clusterChain.length * fd.bytesPerCluster
if (dataSize !== 0) {
const entryData = new Uint8Array(dataSize)
for (let i = 0; i < entry.clusterChain.length; i++) {
const offset = (entry.clusterChain[i] - 2) * fd.bytesPerCluster
for (let i = 0; i < clusterChain.length; i++) {
const offset = (clusterChain[i] - 2) * fd.bytesPerCluster
const view = new Uint8Array(fd.buffer, fd.dataOffset + offset, fd.bytesPerCluster)
entryData.set(view, i * fd.bytesPerCluster)
}