apple2js/js/formats/prodos/utils.ts

121 lines
3.2 KiB
TypeScript

import { STORAGE_TYPES } from './constants';
import { Directory } from './directory';
import type { byte, word } from 'js/types';
import { ProDOSVolume } from '.';
import { FileEntry } from './file_entry';
export function uint32ToDate(val: word) {
// yyyyyyy m|mmmm ddddd|000hhhhh|00mmmmmm
if (val) {
const yearMonthDay = val & 0xffff;
const hourMinute = val >> 16;
const year = yearMonthDay >> 9;
const month = (yearMonthDay & 0x01e0) >> 5;
const day = yearMonthDay & 0x001f;
const hour = hourMinute >> 8;
const min = hourMinute & 0xff;
return new Date(
year < 70 ? 2000 + year : 1900 + year,
month - 1,
day,
hour,
min
);
}
return new Date(0);
}
export function dateToUint32(date: Date) {
// yyyyyyy m|mmmm ddddd|000hhhhh|00mmmmmm
let val = 0;
if (date) {
const year = date.getFullYear() - 1900;
const month = date.getMonth() + 1;
const day = date.getDate();
const hour = date.getHours();
const min = date.getMinutes();
const yearMonthDay = (year << 9) | (month << 5) | day;
const hourMinute = (hour << 8) | min;
val = (hourMinute << 16) | yearMonthDay;
}
return val;
}
export function readFileName(
block: DataView,
offset: word,
nameLength: byte,
caseBits: word
) {
let name = '';
if (!(caseBits & 0x8000)) {
caseBits = 0;
}
// File is deleted, brute force old name
if (nameLength === 0) {
nameLength = 15;
}
for (let idx = 0; idx < nameLength; idx++) {
caseBits <<= 1;
const char = String.fromCharCode(block.getUint8(offset + idx) & 0x7f);
name += caseBits & 0x8000 ? char.toLowerCase() : char;
}
return name;
}
export function writeFileName(block: DataView, offset: word, name: string) {
let caseBits = 0;
for (let idx = 0; idx < name.length; idx++) {
caseBits <<= 1;
let charCode = name.charCodeAt(idx);
if (charCode > 0x60 && charCode < 0x7b) {
caseBits |= 0x1;
charCode -= 0x20;
}
block.setUint8(offset + idx, charCode);
}
return caseBits;
}
export function dumpDirectory(
volume: ProDOSVolume,
dirEntry: FileEntry,
depth: string
) {
const dir = new Directory(volume, dirEntry);
let str = '';
for (let idx = 0; idx < dir.entries.length; idx++) {
const fileEntry = dir.entries[idx];
if (fileEntry.storageType !== STORAGE_TYPES.DELETED) {
str += depth + fileEntry.name + '\n';
if (fileEntry.storageType === STORAGE_TYPES.DIRECTORY) {
str += dumpDirectory(volume, fileEntry, depth + ' ');
}
}
}
return str;
}
export function dump(volume: ProDOSVolume) {
const vdh = volume.vdh();
let str = vdh.name;
for (let idx = 0; idx < vdh.entries.length; idx++) {
const fileEntry = vdh.entries[idx];
str += fileEntry.name + '\n';
if (fileEntry.storageType === STORAGE_TYPES.DIRECTORY) {
str += dumpDirectory(volume, fileEntry, ' ');
}
}
return str;
}