Compare commits

..

4 Commits

2 changed files with 35 additions and 41 deletions

View File

@ -37,19 +37,4 @@ pre {
color: #c0c0c0; color: #c0c0c0;
border: 1px solid rgba(255, 255, 255, 0.3); 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> </style>

View File

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