Compare commits
No commits in common. "b3c3ce482163ccb57c03d547c9492bca1cca2a8d" and "f49754928ea5b334e494c8121eb4382818449040" have entirely different histories.
b3c3ce4821
...
f49754928e
@ -37,4 +37,19 @@ 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>
|
||||
|
||||
@ -41,29 +41,25 @@ 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
|
||||
@ -192,35 +188,36 @@ export class FloppyDisk {
|
||||
return chain
|
||||
}
|
||||
|
||||
addDirectory(listing: string, path: string[], entries: TDirEntry[]) {
|
||||
addDirectory(listing: string, entries: TDirEntry[]) {
|
||||
listing += '\n<ul>'
|
||||
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
const entry = entries[i]
|
||||
if (
|
||||
entry.type !== 'standard-entry' ||
|
||||
entry.attributes.volumeId ||
|
||||
entry.name === '..' ||
|
||||
entry.name === '.'
|
||||
) {
|
||||
if (entry.type !== 'standard-entry') {
|
||||
continue
|
||||
}
|
||||
|
||||
listing += `${path.join('\\') + '\\'}${entry.name}`
|
||||
const fullName = `${entry.name}${entry.extension ? '.' + entry.extension : ''}`
|
||||
|
||||
if (entry.attributes.directory) {
|
||||
listing += '\\<br/>'
|
||||
listing = this.addDirectory(listing, [...path, entry.name], entry.subDirEntries)
|
||||
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'
|
||||
} else {
|
||||
listing += '<br/>'
|
||||
listing += `\n<li>${fullName}</li>\n`
|
||||
}
|
||||
}
|
||||
|
||||
listing += '\n</ul>'
|
||||
return listing
|
||||
}
|
||||
|
||||
buildFileListing(): string {
|
||||
let listing = '<p>\\<br/>'
|
||||
listing += this.addDirectory('', [''], this.rootDirEntries ?? [])
|
||||
listing += '</p>'
|
||||
let listing = '<ul>A:\\'
|
||||
listing += this.addDirectory('', this.rootDirEntries ?? [])
|
||||
listing += '</ul>'
|
||||
return listing
|
||||
}
|
||||
}
|
||||
@ -308,25 +305,20 @@ 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', id }
|
||||
return { type: 'final-entry' }
|
||||
} else if (firstByte === 0xe5) {
|
||||
return { type: 'unused-entry', id }
|
||||
return { type: 'unused-entry' }
|
||||
} else if (attributeByte === 0x0f) {
|
||||
return { type: 'long-filename-entry', id }
|
||||
return { type: 'long-filename-entry' }
|
||||
} else {
|
||||
const asciiDecoder = new TextDecoder('ascii')
|
||||
const basename = asciiDecoder
|
||||
.decode(data.buffer.slice(data.byteOffset, data.byteOffset + 8))
|
||||
.trim()
|
||||
const name = 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 = {
|
||||
@ -343,25 +335,24 @@ 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 !== '..') {
|
||||
const clusterChain = fd.clusterChain(entry.firstCluster)
|
||||
entry.clusterChain = fd.clusterChain(entry.firstCluster)
|
||||
|
||||
const dataSize = clusterChain.length * fd.bytesPerCluster
|
||||
const dataSize = entry.clusterChain.length * fd.bytesPerCluster
|
||||
|
||||
if (dataSize !== 0) {
|
||||
const entryData = new Uint8Array(dataSize)
|
||||
for (let i = 0; i < clusterChain.length; i++) {
|
||||
const offset = (clusterChain[i] - 2) * fd.bytesPerCluster
|
||||
for (let i = 0; i < entry.clusterChain.length; i++) {
|
||||
const offset = (entry.clusterChain[i] - 2) * fd.bytesPerCluster
|
||||
const view = new Uint8Array(fd.buffer, fd.dataOffset + offset, fd.bytesPerCluster)
|
||||
entryData.set(view, i * fd.bytesPerCluster)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user