2021-03-13 21:18:32 +00:00
|
|
|
import RAM, { RAMState } from '../ram';
|
Fix issue #187 (and upgrade jest) (#188)
* Update jest to v29.5.0
This updates jest to the latest version (29.5.0) and fixes everything
that the upgrade breaks. One of the biggest differences is that the
mock types changed and I'm once again confused as to the "proper" way
to create mocks in jest. Whatever.
* Fix issue #187 were bank writing was not working correctly
Before, `mmu.ts` would deactivate writing to the language card if
`prewrite` was reset. However, it is totally possible to reset
`prewrite` and leave writing enabled, as shown my Sather in
_Understanding the Apple IIe_, table 5.5, p. 5-24. For example:
```assembly_x86
sta $c08a ; WRITE DISABLE; READ DISABLE
lda $c08b ; PRE-WRITE set
lda $c08b ; WRITE enabled
sta $c08a ; PRE-WRITE reset; WRITE still enabled!
lda $c08b ; PRE-WRITE set; WRITE still enabled!
```
would not work correctly because the last line would clear `_writebsr`
before setting `_prewrite`, which is incorrect.
Now, `_writebsr` is only set when `_prewrite` is set and thus only
cleared when `writeSwitch` is false. This matches Table 5.5.
* Fix pre-write for the language card
This is the same issue as the `MMU`, namely that `langcard.ts` would
deactivate writing to the language card if `prewrite` was reset.
However, it is totally possible to reset `prewrite` and leave writing
enabled, as shown my Sather in _Understanding the Apple II_, table
5.4, p. 5-30. See the previous commit for an example.
This change also adds a test for the `LanguageCard` class.
2023-07-08 18:18:38 +00:00
|
|
|
// import { debug } from '../util';
|
2021-03-13 21:18:32 +00:00
|
|
|
import { Card, Memory, byte, Restorable } from '../types';
|
|
|
|
|
|
|
|
export interface LanguageCardState {
|
|
|
|
bank1: RAMState;
|
|
|
|
bank2: RAMState;
|
|
|
|
ram: RAMState;
|
|
|
|
|
|
|
|
readbsr: boolean;
|
|
|
|
writebsr: boolean;
|
|
|
|
bsr2: boolean;
|
|
|
|
prewrite: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
export default class LanguageCard implements Card, Restorable<LanguageCardState> {
|
|
|
|
private bank1: RAM;
|
|
|
|
private bank2: RAM;
|
|
|
|
private ram: RAM;
|
|
|
|
|
2022-07-14 03:34:50 +00:00
|
|
|
private _readbsr = false;
|
|
|
|
private _writebsr = false;
|
|
|
|
private _bsr2 = false;
|
|
|
|
private _prewrite = false;
|
2021-03-13 21:18:32 +00:00
|
|
|
|
|
|
|
private read1: Memory;
|
|
|
|
private read2: Memory;
|
|
|
|
|
|
|
|
private write1: Memory;
|
|
|
|
private write2: Memory;
|
|
|
|
|
|
|
|
constructor(private rom: Memory) {
|
Fix issue #187 (and upgrade jest) (#188)
* Update jest to v29.5.0
This updates jest to the latest version (29.5.0) and fixes everything
that the upgrade breaks. One of the biggest differences is that the
mock types changed and I'm once again confused as to the "proper" way
to create mocks in jest. Whatever.
* Fix issue #187 were bank writing was not working correctly
Before, `mmu.ts` would deactivate writing to the language card if
`prewrite` was reset. However, it is totally possible to reset
`prewrite` and leave writing enabled, as shown my Sather in
_Understanding the Apple IIe_, table 5.5, p. 5-24. For example:
```assembly_x86
sta $c08a ; WRITE DISABLE; READ DISABLE
lda $c08b ; PRE-WRITE set
lda $c08b ; WRITE enabled
sta $c08a ; PRE-WRITE reset; WRITE still enabled!
lda $c08b ; PRE-WRITE set; WRITE still enabled!
```
would not work correctly because the last line would clear `_writebsr`
before setting `_prewrite`, which is incorrect.
Now, `_writebsr` is only set when `_prewrite` is set and thus only
cleared when `writeSwitch` is false. This matches Table 5.5.
* Fix pre-write for the language card
This is the same issue as the `MMU`, namely that `langcard.ts` would
deactivate writing to the language card if `prewrite` was reset.
However, it is totally possible to reset `prewrite` and leave writing
enabled, as shown my Sather in _Understanding the Apple II_, table
5.4, p. 5-30. See the previous commit for an example.
This change also adds a test for the `LanguageCard` class.
2023-07-08 18:18:38 +00:00
|
|
|
// debug('Language card');
|
2021-03-13 21:18:32 +00:00
|
|
|
|
|
|
|
this.bank1 = new RAM(0xd0, 0xdf);
|
|
|
|
this.bank2 = new RAM(0xd0, 0xdf);
|
|
|
|
this.ram = new RAM(0xe0, 0xff);
|
|
|
|
|
|
|
|
this.write1 = this.rom;
|
|
|
|
this.write2 = this.rom;
|
|
|
|
|
|
|
|
this.read1 = this.rom;
|
|
|
|
this.read2 = this.rom;
|
|
|
|
}
|
|
|
|
|
2022-05-18 02:08:28 +00:00
|
|
|
private debug(..._args: unknown[]) {
|
2021-03-13 21:22:45 +00:00
|
|
|
// debug.apply(null, args);
|
2021-03-13 21:18:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private updateBanks() {
|
2022-07-14 03:34:50 +00:00
|
|
|
if (this._readbsr) {
|
|
|
|
this.read1 = this._bsr2 ? this.bank2 : this.bank1;
|
2021-03-13 21:18:32 +00:00
|
|
|
this.read2 = this.ram;
|
|
|
|
} else {
|
|
|
|
this.read1 = this.rom;
|
|
|
|
this.read2 = this.rom;
|
|
|
|
}
|
|
|
|
|
2022-07-14 03:34:50 +00:00
|
|
|
if (this._writebsr) {
|
|
|
|
this.write1 = this._bsr2 ? this.bank2 : this.bank1;
|
2021-03-13 21:18:32 +00:00
|
|
|
this.write2 = this.ram;
|
|
|
|
} else {
|
|
|
|
this.write1 = this.rom;
|
|
|
|
this.write2 = this.rom;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bank 2
|
|
|
|
// READBSR2: 0x80
|
|
|
|
// WRITEBSR2: 0x81
|
|
|
|
// OFFBSR2: 0x82
|
|
|
|
// READWRBSR2: 0x83
|
|
|
|
|
|
|
|
// Bank 1
|
|
|
|
// READBSR1: 0x88
|
|
|
|
// WRITEBSR1: 0x89
|
|
|
|
// OFFBSR1: 0x8a
|
|
|
|
// READWRBSR1: 0x8b
|
|
|
|
|
|
|
|
private access(off: byte, val?: byte) {
|
|
|
|
const readMode = val === undefined;
|
|
|
|
const result = readMode ? 0 : undefined;
|
|
|
|
|
|
|
|
const writeSwitch = off & 0x01;
|
|
|
|
const offSwitch = off & 0x02;
|
|
|
|
const bank1Switch = off & 0x08;
|
|
|
|
|
|
|
|
let bankStr;
|
|
|
|
let rwStr;
|
|
|
|
|
Fix issue #187 (and upgrade jest) (#188)
* Update jest to v29.5.0
This updates jest to the latest version (29.5.0) and fixes everything
that the upgrade breaks. One of the biggest differences is that the
mock types changed and I'm once again confused as to the "proper" way
to create mocks in jest. Whatever.
* Fix issue #187 were bank writing was not working correctly
Before, `mmu.ts` would deactivate writing to the language card if
`prewrite` was reset. However, it is totally possible to reset
`prewrite` and leave writing enabled, as shown my Sather in
_Understanding the Apple IIe_, table 5.5, p. 5-24. For example:
```assembly_x86
sta $c08a ; WRITE DISABLE; READ DISABLE
lda $c08b ; PRE-WRITE set
lda $c08b ; WRITE enabled
sta $c08a ; PRE-WRITE reset; WRITE still enabled!
lda $c08b ; PRE-WRITE set; WRITE still enabled!
```
would not work correctly because the last line would clear `_writebsr`
before setting `_prewrite`, which is incorrect.
Now, `_writebsr` is only set when `_prewrite` is set and thus only
cleared when `writeSwitch` is false. This matches Table 5.5.
* Fix pre-write for the language card
This is the same issue as the `MMU`, namely that `langcard.ts` would
deactivate writing to the language card if `prewrite` was reset.
However, it is totally possible to reset `prewrite` and leave writing
enabled, as shown my Sather in _Understanding the Apple II_, table
5.4, p. 5-30. See the previous commit for an example.
This change also adds a test for the `LanguageCard` class.
2023-07-08 18:18:38 +00:00
|
|
|
if (writeSwitch) { // 0xC081, 0xC083
|
2021-03-13 21:18:32 +00:00
|
|
|
if (readMode) {
|
Fix issue #187 (and upgrade jest) (#188)
* Update jest to v29.5.0
This updates jest to the latest version (29.5.0) and fixes everything
that the upgrade breaks. One of the biggest differences is that the
mock types changed and I'm once again confused as to the "proper" way
to create mocks in jest. Whatever.
* Fix issue #187 were bank writing was not working correctly
Before, `mmu.ts` would deactivate writing to the language card if
`prewrite` was reset. However, it is totally possible to reset
`prewrite` and leave writing enabled, as shown my Sather in
_Understanding the Apple IIe_, table 5.5, p. 5-24. For example:
```assembly_x86
sta $c08a ; WRITE DISABLE; READ DISABLE
lda $c08b ; PRE-WRITE set
lda $c08b ; WRITE enabled
sta $c08a ; PRE-WRITE reset; WRITE still enabled!
lda $c08b ; PRE-WRITE set; WRITE still enabled!
```
would not work correctly because the last line would clear `_writebsr`
before setting `_prewrite`, which is incorrect.
Now, `_writebsr` is only set when `_prewrite` is set and thus only
cleared when `writeSwitch` is false. This matches Table 5.5.
* Fix pre-write for the language card
This is the same issue as the `MMU`, namely that `langcard.ts` would
deactivate writing to the language card if `prewrite` was reset.
However, it is totally possible to reset `prewrite` and leave writing
enabled, as shown my Sather in _Understanding the Apple II_, table
5.4, p. 5-30. See the previous commit for an example.
This change also adds a test for the `LanguageCard` class.
2023-07-08 18:18:38 +00:00
|
|
|
if (this._prewrite) {
|
|
|
|
this._writebsr = true;
|
|
|
|
}
|
2021-03-13 21:18:32 +00:00
|
|
|
}
|
2022-07-14 03:34:50 +00:00
|
|
|
this._prewrite = readMode;
|
2021-03-13 21:18:32 +00:00
|
|
|
|
|
|
|
if (offSwitch) { // $C083, $C08B
|
2022-07-14 03:34:50 +00:00
|
|
|
this._readbsr = true;
|
2021-03-13 21:18:32 +00:00
|
|
|
rwStr = 'Read/Write';
|
|
|
|
} else { // $C081, $C089
|
2022-07-14 03:34:50 +00:00
|
|
|
this._readbsr = false;
|
2021-03-13 21:18:32 +00:00
|
|
|
rwStr = 'Write';
|
|
|
|
}
|
|
|
|
} else { // $C080, $C082, $C088, $C08A
|
2022-07-14 03:34:50 +00:00
|
|
|
this._writebsr = false;
|
|
|
|
this._prewrite = false;
|
2021-03-13 21:18:32 +00:00
|
|
|
|
|
|
|
if (offSwitch) { // $C082, $C08A
|
2022-07-14 03:34:50 +00:00
|
|
|
this._readbsr = false;
|
2021-03-13 21:18:32 +00:00
|
|
|
rwStr = 'Off';
|
|
|
|
} else { // $C080, $C088
|
2022-07-14 03:34:50 +00:00
|
|
|
this._readbsr = true;
|
2021-03-13 21:18:32 +00:00
|
|
|
rwStr = 'Read';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bank1Switch) { // C08[8-C]
|
2022-07-14 03:34:50 +00:00
|
|
|
this._bsr2 = false;
|
2021-03-13 21:18:32 +00:00
|
|
|
bankStr = 'Bank 1';
|
|
|
|
} else { // C08[0-3]
|
2022-07-14 03:34:50 +00:00
|
|
|
this._bsr2 = true;
|
2021-03-13 21:18:32 +00:00
|
|
|
bankStr = 'Bank 2';
|
|
|
|
}
|
|
|
|
|
|
|
|
this.debug(bankStr, rwStr);
|
|
|
|
this.updateBanks();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
start() {
|
|
|
|
return 0xd0;
|
|
|
|
}
|
|
|
|
|
|
|
|
end() {
|
|
|
|
return 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
ioSwitch(off: byte, val?: byte) {
|
|
|
|
return this.access(off, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
read(page: byte, off: byte): byte {
|
|
|
|
let result: number = 0;
|
|
|
|
if (page < 0xe0) {
|
|
|
|
result = this.read1.read(page, off);
|
|
|
|
} else {
|
|
|
|
result = this.read2.read(page, off);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
write(page: byte, off: byte, val: byte) {
|
|
|
|
if (page < 0xe0) {
|
|
|
|
this.write1.write(page, off, val);
|
|
|
|
} else {
|
|
|
|
this.write2.write(page, off, val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-14 03:34:50 +00:00
|
|
|
public get bsr2() {
|
|
|
|
return this._bsr2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public get readbsr() {
|
|
|
|
return this._readbsr;
|
|
|
|
}
|
|
|
|
|
|
|
|
public get writebsr() {
|
|
|
|
return this._writebsr;
|
|
|
|
}
|
|
|
|
|
2021-03-13 21:18:32 +00:00
|
|
|
getState() {
|
|
|
|
return {
|
|
|
|
readbsr: this.readbsr,
|
|
|
|
writebsr: this.writebsr,
|
|
|
|
bsr2: this.bsr2,
|
2022-07-14 03:34:50 +00:00
|
|
|
prewrite: this._prewrite,
|
2021-03-13 21:18:32 +00:00
|
|
|
ram: this.ram.getState(),
|
|
|
|
bank1: this.bank1.getState(),
|
|
|
|
bank2: this.bank2.getState()
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
setState(state: LanguageCardState) {
|
2022-07-14 03:34:50 +00:00
|
|
|
this._readbsr = state.readbsr;
|
|
|
|
this._writebsr = state.writebsr;
|
|
|
|
this._bsr2 = state.bsr2;
|
|
|
|
this._prewrite = state.prewrite;
|
2021-03-13 21:18:32 +00:00
|
|
|
this.ram.setState(state.ram);
|
|
|
|
this.bank1.setState(state.bank1);
|
|
|
|
this.bank2.setState(state.bank2);
|
|
|
|
this.updateBanks();
|
|
|
|
}
|
|
|
|
}
|