* Add `spawn` as a way of calling promise-returning blocks
This change adds `spawn` which takes a no-argument, promise-returning
function, calls it, and returns `void`. This makes it easy to call
async blocks from `useEffect` and other places that don't take async
functions, but also makes such calls explicit.
* Adds interruptability to `spawn`
Now, the task function passed to `spawn` can take an `Interrupted`
argument, which is merely a method that returns `true` if the task
should stop doing work. Likewise, `spawn` returns an `Interrupt`
function that causes the `Interrupted` function to return `true`.
* Change to using `AbortController` and `AbortSignal`
Before, `spawn` used functions to interrupt and determine interruption
state. Now, based on feedback from @whscullin, it uses
`AbortController` and `AbortSignal`.
Tests now show how the controller can be used to abort long-running
tasks and API calls in the `spawn`. The also show how signals can be
chained using `addEventListener`.
* Fix `Apple2.tsx`
Forgot to change it to use `AbortController` and `AbortSignal`.
Co-authored-by: Will Scullin <scullin@scullin.com>
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.
This removes the `FileSystemFileHandleLike` interface in preference to
just implementing the correct interface. The advantage of the
`FileSystemFileHandle` interface is that it can be passed to the
worker directly to load the file.
This adds both the recommended TypeScript checks, plus the recommended
TypeScript checks that require type checking. This latter addition
means that eslint essentially has to compile all of the TypeScript in
the project, causing it to be slower. This isn't much of a problem in
VS Code because there's a lot of caching being done, but it's clearly
slower when run on the commandline.
All of the errors are either fixed or suppressed. Some errors are
suppressed because fixing them would be too laborious for the little
value gained.
The eslint config is also slightly refactored to separate the strictly
TypeScript checks from the JavaScript checks.
* Create a FileChooser component using showOpenFilePicker
Before, `FileModal` always used a file input control for selecting
local files. This allowed the emulator to read from the file, but
precluded writing back to the file.
With this change, the `FileModal` delegates to the new `FileChooser`
component. The `FileChooser` will use `showOpenFilePicker` if it is
available and a regular file input if it's not.
Using `showOpenFilePicker` has the advantage of allowing the emulator
to write back to the file (if the user grants permission). While the
emulator does not yet take advantage of this write capability, that
will come.
* Addressed comments
* useState() instead of direct DOM manipulation
* backed out eslint changes in favor of suppressing the warning
A test data set was published at https://github.com/TomHarte/ProcessorTests which contain cycle traces of instructions for various versions of the 6502.
This adds a test harness that reads those data files, and adjusts the CPU6502 behavior to match the behavior of the vanilla and WDC 65C02 test data.
Also converts the existing CPU tests to Typescript, and fixes any inconsistencies that came up from the new behaviors.
Disk side information was being dropped and thus not displayable in the UI. This plumbs the value through various formats and adds some light testing.
Also fixes an issue where URL encoded hashes were not properly interpreted.
* Refactor disk handling to allow disk processing to happen in a worker
* Type cleanup
* Convert format handlers to TypeScript
* Convert CFFA to TypeScript
* Switch modules to `esnext` to allow `webpack` to see import statements
* Pass rom names into Apple2 class
* Move ROMs into `system` and `character` directories to allow webpack bundle appropriate ROMs.
* Wait for ROMs to load before completing initialization.
Stop stringifying opcodes during runtime and only do so upon inspection. Moves all the debugging logic to a common place to allow building an interface.
Like the DOS 3.3 and ProDOS sector order issues, this change fixes the
physical order of the sectors on 13-sector disks when nibblized.
This change also adds tests for the 13-sector format to verify the
sector order.
One of the crazy things is that _Beneath Apple DOS_ failed me in this
instance because it doesn't discuss what happens to the last byte in
"5 and 3" encoding anywhere (AFAICT). I went back to the DOS 3.1
source released by the Computer History Museum here:
https://computerhistory.org/blog/apple-ii-dos-source-code/
The code is in `appdos31.lst` in the `POSTNIB` routine on line 4777.
Like the DOS 3.3 sector order issues in #49, this change fixes the
order of the physical sectors on the ProDOS disk when nibblized.
This change also adds tests similar to the DOS 3.3 tests to verify the
sector order.
Because the DOS 3.3 and ProDOS tests are so similar, the utility
methods have been refactored into their own file.
* Adds an initial test for DOS format (.do) files
* Fix physical sector order when nibblizing DOS 3.3 ordered images
Before, when `.dsk` or `.do` images were nibblized, the resulting
track had the sectors in the wrong physical layout.
Now the nibblized track has the correct physical layout (all sectors
in order) which results in the correct DOS 3.3 layout as well.
There is also a test that verifies the order.
* Add another test for a non-zero sector
The new test checks that the values in physical sector 1 are those for
DOS sector 7.
* Add test for all physical sectors on all tracks
This change also removes a few stray console.log calls in the test.
* Convert js/ram to a class
* Convert js/mmu to Typescript
* Convert js/apple2io to Typescript
* Convert js/canvas to Typescript
* Use new types in js/mmu
* Rename js/symbols.js to js/symbols.ts
* Remove the difference between readPages and writePages
As @whscullin said in PR #38, there's no need to have both readable
and writable pages since all implementations are currently both. This
change combines them into `Page`. Likewise, `PageHandler` now extends
`Page`.
`Apple2IO` now implements `PageHandler`. This caught a bug where `end`
had been renamed `endend` by mistake.
There are a few other formatting changes as well.
* Convert js/apple2 to Typescript
* Convert js/prefs to Typescript
* Convert all of the ROMs in js/roms to Typescript
Now all of the ROMs are classes that extend the ROM class. There is
some rudamentary checking to make sure that the length of the ROM
matches the declared start and end pages. (This caught what looks to
be an error in roms/apple2e, but it's hard for me to tell.)
The typing also caught an error where the character ROM was being
used for the main ROM for the apple2j version.
* Convert js/roms/cards/* to Typescript
* Convert js/formats/format_utils to Typescript
This change also seems to fix a bug with `.po` image files that
weren't being read correctly.
* Convert `js/util.js` to Typescript and add tests
Besides converting `js/util.js` to Typescript, this change also adds
`js/types.ts` that defines common types used in apple2js. Some of
these types, like `byte` and `word` are for information only.
* Convert `js/base64.js` to Typescript
This also adds a new type, `memory`, that is either an array of
numbers, or a Uint8Array.
* Convert `js/ram.js` to Typescript
This change does not convert `RAM` to a class; it just introduces types.
* Basic typing of cpu6502
This is a really rough first pass. There are some problems that can't
be fixed until this is turned into a real class, but at least all of
the function arguments are now typed. This caught a few cases where
extra arguments were being passed in.
* Convert `js/cpu6502` to a class
In theory, idiomatic classes should be better than the previous
closure-based classes. However, this conversion shows that the
instruction table does not fit well with idiomatic classes as method
referenced in the table need to be called with the correct `this`
everywhere.
This should, at best, be considered a first attempt.