apple2js/js/util.ts
Ian Flanigan c9b7987c4c
Fix 2mg header parsing and add tests (#127)
Before, the offset for `FLAGS` in `2mg.ts` was `0x0A`, which is
incorrect according to the spec at:

https://apple2.org.za/gswv/a2zine/Docs/DiskImage_2MG_Info.txt

Now, all of the fields in the 2mg header are described, including
their lengths and any constraints.  These constraints are enforced by
`read2MGHeader` and tested by new tests.
2022-06-06 18:10:06 -07:00

103 lines
2.6 KiB
TypeScript

import { byte, memory, word } from './types';
/*eslint no-console: 0*/
const hex_digits = '0123456789ABCDEF';
const bin_digits = '01';
/** Returns a random byte. */
export function garbage(): byte {
return (Math.random() * 0x100) & 0xff;
}
export const testables = {
garbage
};
/**
* Returns an array or Uint8Array of `size` bytes filled as if the computer
* was just powered on.
*/
export function allocMem(size: number) {
const result = new Uint8Array(size);
for (let idx = 0; idx < size; idx++) {
result[idx] = (idx & 0x02) ? 0x00 : 0xff;
}
// Borrowed from AppleWin (https://github.com/AppleWin/AppleWin)
for (let idx = 0; idx < size; idx += 0x200) {
result[idx + 0x28] = garbage();
result[idx + 0x29] = garbage();
result[idx + 0x68] = garbage();
result[idx + 0x69] = garbage();
}
return result;
}
/** Returns an array or Uint8Array of 256 * `pages` bytes. */
export function allocMemPages(pages: number): memory {
return allocMem(pages << 8);
}
/** Returns a new Uint8Array for the input array. */
export function bytify(ary: number[]): memory {
return new Uint8Array(ary);
}
/** Returns a new Uint8Array with the concatenated data from the inputs. */
export function concat(...arys: Array<byte[] | Uint8Array>) {
const result = new Uint8Array(arys.reduce((l, ary) => l + ary.length, 0));
let offset = 0;
for (let i = 0; i < arys.length; i++) {
result.set(arys[i], offset);
offset += arys[i].length;
}
return result;
}
/** Writes to the console. */
export function debug(...args: unknown[]): void {
console.log(...args);
}
/**
* Returns a string of hex digits (all caps).
* @param v the value to encode
* @param n the number of nibbles. If `n` is missing, it is guessed from the value
* of `v`. If `v` < 256, it is assumed to be 2 nibbles, otherwise 4.
*/
export function toHex(v: byte | word | number, n?: number) {
if (!n) {
n = v < 256 ? 2 : 4;
}
let result = '';
for (let idx = 0; idx < n; idx++) {
result = hex_digits[v & 0x0f] + result;
v >>= 4;
}
return result;
}
/**
* Returns a string of 8 binary digits.
* @param v the value to encode
*/
export function toBinary(v: byte) {
let result = '';
for (let idx = 0; idx < 8; idx++) {
result = bin_digits[v & 0x01] + result;
v >>= 1;
}
return result;
}
/** Packs a 32-bit integer into a string in little-endian order. */
export function numToString(num: number) {
let result = '';
for (let idx = 0; idx < 4; idx++) {
result += String.fromCharCode(num & 0xff);
num >>= 8;
}
return result;
}