ac6502 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -12
- package/dist/components/CPU.d.ts +162 -0
- package/dist/components/Cart.d.ts +9 -0
- package/dist/components/IO/ACIA.d.ts +76 -0
- package/dist/components/IO/ACIA.js +282 -0
- package/dist/components/IO/ACIA.js.map +1 -0
- package/dist/components/IO/Attachments/Attachment.d.ts +112 -0
- package/dist/components/IO/Attachments/Attachment.js +71 -0
- package/dist/components/IO/Attachments/Attachment.js.map +1 -0
- package/dist/components/IO/Attachments/JoystickAttachment.d.ts +53 -0
- package/dist/components/IO/Attachments/JoystickAttachment.js +90 -0
- package/dist/components/IO/Attachments/JoystickAttachment.js.map +1 -0
- package/dist/components/IO/Attachments/KeyboardEncoderAttachment.d.ts +63 -0
- package/dist/components/IO/Attachments/KeyboardEncoderAttachment.js +489 -0
- package/dist/components/IO/Attachments/KeyboardEncoderAttachment.js.map +1 -0
- package/dist/components/IO/Attachments/KeyboardMatrixAttachment.d.ts +44 -0
- package/dist/components/IO/Attachments/KeyboardMatrixAttachment.js +274 -0
- package/dist/components/IO/Attachments/KeyboardMatrixAttachment.js.map +1 -0
- package/dist/components/IO/Attachments/KeypadAttachment.d.ts +47 -0
- package/dist/components/IO/Attachments/KeypadAttachment.js +141 -0
- package/dist/components/IO/Attachments/KeypadAttachment.js.map +1 -0
- package/dist/components/IO/Attachments/LCDAttachment.d.ts +110 -0
- package/dist/components/IO/Attachments/LCDAttachment.js +716 -0
- package/dist/components/IO/Attachments/LCDAttachment.js.map +1 -0
- package/dist/components/IO/Attachments/SNESAttachment.d.ts +85 -0
- package/dist/components/IO/Attachments/SNESAttachment.js +184 -0
- package/dist/components/IO/Attachments/SNESAttachment.js.map +1 -0
- package/dist/components/IO/DevOutputBoard.d.ts +19 -0
- package/dist/components/IO/DevOutputBoard.js +33 -0
- package/dist/components/IO/DevOutputBoard.js.map +1 -0
- package/dist/components/IO/Empty.d.ts +9 -0
- package/dist/components/IO/Empty.js +5 -7
- package/dist/components/IO/Empty.js.map +1 -1
- package/dist/components/IO/EmptyCard.d.ts +9 -0
- package/dist/components/IO/GPIOAttachments/GPIOAttachment.d.ts +112 -0
- package/dist/components/IO/GPIOAttachments/GPIOJoystickAttachment.d.ts +53 -0
- package/dist/components/IO/GPIOAttachments/GPIOKeyboardEncoderAttachment.d.ts +63 -0
- package/dist/components/IO/GPIOAttachments/GPIOKeyboardMatrixAttachment.d.ts +44 -0
- package/dist/components/IO/GPIOAttachments/GPIOKeypadAttachment.d.ts +47 -0
- package/dist/components/IO/GPIOAttachments/GPIOLCDAttachment.d.ts +110 -0
- package/dist/components/IO/GPIOCard.d.ts +105 -0
- package/dist/components/IO/GPIOCard.js.map +1 -1
- package/dist/components/IO/RAMBank.d.ts +37 -0
- package/dist/components/IO/RAMBank.js +63 -0
- package/dist/components/IO/RAMBank.js.map +1 -0
- package/dist/components/IO/RAMCard.d.ts +37 -0
- package/dist/components/IO/RTC.d.ts +107 -0
- package/dist/components/IO/RTC.js +483 -0
- package/dist/components/IO/RTC.js.map +1 -0
- package/dist/components/IO/RTCCard.d.ts +107 -0
- package/dist/components/IO/SerialCard.d.ts +76 -0
- package/dist/components/IO/Sound.d.ts +120 -0
- package/dist/components/IO/Sound.js +622 -0
- package/dist/components/IO/Sound.js.map +1 -0
- package/dist/components/IO/SoundCard.d.ts +120 -0
- package/dist/components/IO/Storage.d.ts +74 -0
- package/dist/components/IO/Storage.js +409 -0
- package/dist/components/IO/Storage.js.map +1 -0
- package/dist/components/IO/StorageCard.d.ts +74 -0
- package/dist/components/IO/Terminal.d.ts +19 -0
- package/dist/components/IO/Terminal.js +33 -0
- package/dist/components/IO/Terminal.js.map +1 -0
- package/dist/components/IO/VIA.d.ts +105 -0
- package/dist/components/IO/VIA.js +597 -0
- package/dist/components/IO/VIA.js.map +1 -0
- package/dist/components/IO/Video.d.ts +141 -0
- package/dist/components/IO/Video.js +630 -0
- package/dist/components/IO/Video.js.map +1 -0
- package/dist/components/IO/VideoCard.d.ts +141 -0
- package/dist/components/IO.d.ts +8 -0
- package/dist/components/Machine.d.ts +62 -0
- package/dist/components/Machine.js +260 -153
- package/dist/components/Machine.js.map +1 -1
- package/dist/components/RAM.d.ts +9 -0
- package/dist/components/ROM.d.ts +9 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +61 -28
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +22 -0
- package/dist/lib.js +47 -0
- package/dist/lib.js.map +1 -0
- package/dist/tests/CPU.test.d.ts +1 -0
- package/dist/tests/Cart.test.d.ts +1 -0
- package/dist/tests/IO/ACIA.test.d.ts +1 -0
- package/dist/tests/IO/ACIA.test.js +423 -0
- package/dist/tests/IO/ACIA.test.js.map +1 -0
- package/dist/tests/IO/Attachments/Attachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/Attachment.test.js +339 -0
- package/dist/tests/IO/Attachments/Attachment.test.js.map +1 -0
- package/dist/tests/IO/Attachments/JoystickAttachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/JoystickAttachment.test.js +126 -0
- package/dist/tests/IO/Attachments/JoystickAttachment.test.js.map +1 -0
- package/dist/tests/IO/Attachments/KeyboardEncoderAttachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/KeyboardEncoderAttachment.test.js +779 -0
- package/dist/tests/IO/Attachments/KeyboardEncoderAttachment.test.js.map +1 -0
- package/dist/tests/IO/Attachments/KeyboardMatrixAttachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/KeyboardMatrixAttachment.test.js +355 -0
- package/dist/tests/IO/Attachments/KeyboardMatrixAttachment.test.js.map +1 -0
- package/dist/tests/IO/Attachments/KeypadAttachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/KeypadAttachment.test.js +323 -0
- package/dist/tests/IO/Attachments/KeypadAttachment.test.js.map +1 -0
- package/dist/tests/IO/Attachments/LCDAttachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/LCDAttachment.test.js +627 -0
- package/dist/tests/IO/Attachments/LCDAttachment.test.js.map +1 -0
- package/dist/tests/IO/Attachments/SNESAttachment.test.d.ts +1 -0
- package/dist/tests/IO/Attachments/SNESAttachment.test.js +331 -0
- package/dist/tests/IO/Attachments/SNESAttachment.test.js.map +1 -0
- package/dist/tests/IO/Empty.test.d.ts +1 -0
- package/dist/tests/IO/Empty.test.js +121 -0
- package/dist/tests/IO/Empty.test.js.map +1 -0
- package/dist/tests/IO/GPIOAttachments/GPIOAttachment.test.d.ts +1 -0
- package/dist/tests/IO/GPIOAttachments/GPIOJoystickAttachment.test.d.ts +1 -0
- package/dist/tests/IO/GPIOAttachments/GPIOKeyboardEncoderAttachment.test.d.ts +1 -0
- package/dist/tests/IO/GPIOAttachments/GPIOKeyboardMatrixAttachment.test.d.ts +1 -0
- package/dist/tests/IO/GPIOAttachments/GPIOKeypadAttachment.test.d.ts +1 -0
- package/dist/tests/IO/GPIOAttachments/GPIOLCDAttachment.test.d.ts +1 -0
- package/dist/tests/IO/GPIOCard.test.d.ts +1 -0
- package/dist/tests/IO/GPIOCard.test.js.map +1 -1
- package/dist/tests/IO/RAMBank.test.d.ts +1 -0
- package/dist/tests/IO/RAMBank.test.js +229 -0
- package/dist/tests/IO/RAMBank.test.js.map +1 -0
- package/dist/tests/IO/RAMCard.test.d.ts +1 -0
- package/dist/tests/IO/RTC.test.d.ts +1 -0
- package/dist/tests/IO/RTC.test.js +177 -0
- package/dist/tests/IO/RTC.test.js.map +1 -0
- package/dist/tests/IO/RTCCard.test.d.ts +1 -0
- package/dist/tests/IO/SerialCard.test.d.ts +1 -0
- package/dist/tests/IO/Sound.test.d.ts +1 -0
- package/dist/tests/IO/Sound.test.js +528 -0
- package/dist/tests/IO/Sound.test.js.map +1 -0
- package/dist/tests/IO/SoundCard.test.d.ts +1 -0
- package/dist/tests/IO/Storage.test.d.ts +1 -0
- package/dist/tests/IO/Storage.test.js +656 -0
- package/dist/tests/IO/Storage.test.js.map +1 -0
- package/dist/tests/IO/StorageCard.test.d.ts +1 -0
- package/dist/tests/IO/VIA.test.d.ts +1 -0
- package/dist/tests/IO/VIA.test.js +503 -0
- package/dist/tests/IO/VIA.test.js.map +1 -0
- package/dist/tests/IO/Video.test.d.ts +1 -0
- package/dist/tests/IO/Video.test.js +549 -0
- package/dist/tests/IO/Video.test.js.map +1 -0
- package/dist/tests/IO/VideoCard.test.d.ts +1 -0
- package/dist/tests/Machine.test.d.ts +1 -0
- package/dist/tests/Machine.test.js +27 -42
- package/dist/tests/Machine.test.js.map +1 -1
- package/dist/tests/RAM.test.d.ts +1 -0
- package/dist/tests/ROM.test.d.ts +1 -0
- package/package.json +5 -3
- package/src/components/IO/{SerialCard.ts → ACIA.ts} +2 -2
- package/src/components/IO/{GPIOAttachments/GPIOAttachment.ts → Attachments/Attachment.ts} +2 -2
- package/src/components/IO/{GPIOAttachments/GPIOJoystickAttachment.ts → Attachments/JoystickAttachment.ts} +3 -3
- package/src/components/IO/{GPIOAttachments/GPIOKeyboardEncoderAttachment.ts → Attachments/KeyboardEncoderAttachment.ts} +3 -3
- package/src/components/IO/{GPIOAttachments/GPIOKeyboardMatrixAttachment.ts → Attachments/KeyboardMatrixAttachment.ts} +5 -5
- package/src/components/IO/{GPIOAttachments/GPIOKeypadAttachment.ts → Attachments/KeypadAttachment.ts} +3 -3
- package/src/components/IO/{GPIOAttachments/GPIOLCDAttachment.ts → Attachments/LCDAttachment.ts} +7 -7
- package/src/components/IO/{EmptyCard.ts → Empty.ts} +1 -1
- package/src/components/IO/{RAMCard.ts → RAMBank.ts} +8 -8
- package/src/components/IO/{RTCCard.ts → RTC.ts} +1 -1
- package/src/components/IO/{SoundCard.ts → Sound.ts} +2 -2
- package/src/components/IO/{StorageCard.ts → Storage.ts} +70 -73
- package/src/components/IO/Terminal.ts +34 -0
- package/src/components/IO/{GPIOCard.ts → VIA.ts} +64 -64
- package/src/components/IO/{VideoCard.ts → Video.ts} +1 -1
- package/src/components/Machine.ts +286 -160
- package/src/index.ts +65 -35
- package/src/lib.ts +27 -0
- package/src/tests/IO/{SerialCard.test.ts → ACIA.test.ts} +5 -5
- package/src/tests/IO/{GPIOAttachments/GPIOAttachment.test.ts → Attachments/Attachment.test.ts} +12 -12
- package/src/tests/IO/{GPIOAttachments/GPIOJoystickAttachment.test.ts → Attachments/JoystickAttachment.test.ts} +23 -23
- package/src/tests/IO/{GPIOAttachments/GPIOKeyboardEncoderAttachment.test.ts → Attachments/KeyboardEncoderAttachment.test.ts} +4 -4
- package/src/tests/IO/{GPIOAttachments/GPIOKeyboardMatrixAttachment.test.ts → Attachments/KeyboardMatrixAttachment.test.ts} +5 -5
- package/src/tests/IO/{GPIOAttachments/GPIOKeypadAttachment.test.ts → Attachments/KeypadAttachment.test.ts} +38 -38
- package/src/tests/IO/{GPIOAttachments/GPIOLCDAttachment.test.ts → Attachments/LCDAttachment.test.ts} +12 -12
- package/src/tests/IO/Empty.test.ts +143 -0
- package/src/tests/IO/{RAMCard.test.ts → RAMBank.test.ts} +33 -33
- package/src/tests/IO/{RTCCard.test.ts → RTC.test.ts} +6 -6
- package/src/tests/IO/{SoundCard.test.ts → Sound.test.ts} +6 -6
- package/src/tests/IO/{StorageCard.test.ts → Storage.test.ts} +34 -25
- package/src/tests/IO/{GPIOCard.test.ts → VIA.test.ts} +7 -7
- package/src/tests/IO/{VideoCard.test.ts → Video.test.ts} +13 -13
- package/src/tests/Machine.test.ts +31 -38
- package/tsconfig.json +1 -0
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { IO } from '../IO'
|
|
2
|
-
import { readFile, writeFile } from 'fs/promises'
|
|
3
|
-
import { existsSync } from 'fs'
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
|
-
*
|
|
4
|
+
* Storage - Emulates a Compact Flash card in 8-bit IDE mode
|
|
7
5
|
*
|
|
8
6
|
* Emulates a 128MB CF card with ATA-style register interface.
|
|
9
7
|
* Uses LBA (Logical Block Addressing) for sector access.
|
|
@@ -25,12 +23,12 @@ import { existsSync } from 'fs'
|
|
|
25
23
|
* 0xEC: Identify Drive
|
|
26
24
|
* 0xEF: Set Features (accepted but not implemented)
|
|
27
25
|
*/
|
|
28
|
-
export class
|
|
26
|
+
export class Storage implements IO {
|
|
29
27
|
|
|
30
28
|
// Constants
|
|
31
29
|
private static readonly STORAGE_SIZE = 128 * 1024 * 1024 // 128MB
|
|
32
30
|
private static readonly SECTOR_SIZE = 512
|
|
33
|
-
private static readonly SECTOR_COUNT =
|
|
31
|
+
private static readonly SECTOR_COUNT = Storage.STORAGE_SIZE / Storage.SECTOR_SIZE // 262144 sectors
|
|
34
32
|
|
|
35
33
|
// Status Register Flags
|
|
36
34
|
private static readonly STATUS_ERR = 0x01 // Error
|
|
@@ -43,13 +41,13 @@ export class StorageCard implements IO {
|
|
|
43
41
|
private static readonly ERR_IDNF = 0x10 // ID Not Found
|
|
44
42
|
|
|
45
43
|
// Storage and Identity data (in-memory simulation)
|
|
46
|
-
private storage:
|
|
47
|
-
private identity:
|
|
44
|
+
private storage: Uint8Array
|
|
45
|
+
private identity: Uint8Array
|
|
48
46
|
|
|
49
47
|
// Data buffer (512 bytes)
|
|
50
|
-
private buffer:
|
|
48
|
+
private buffer: Uint8Array = new Uint8Array(Storage.SECTOR_SIZE)
|
|
51
49
|
private bufferIndex: number = 0
|
|
52
|
-
private commandDataSize: number =
|
|
50
|
+
private commandDataSize: number = Storage.SECTOR_SIZE
|
|
53
51
|
private sectorOffset: number = 0
|
|
54
52
|
|
|
55
53
|
// Registers
|
|
@@ -72,8 +70,8 @@ export class StorageCard implements IO {
|
|
|
72
70
|
|
|
73
71
|
constructor() {
|
|
74
72
|
// Initialize storage and identity buffers
|
|
75
|
-
this.storage =
|
|
76
|
-
this.identity =
|
|
73
|
+
this.storage = new Uint8Array(Storage.STORAGE_SIZE)
|
|
74
|
+
this.identity = new Uint8Array(Storage.SECTOR_SIZE)
|
|
77
75
|
this.generateIdentity()
|
|
78
76
|
this.reset(true)
|
|
79
77
|
}
|
|
@@ -137,7 +135,7 @@ export class StorageCard implements IO {
|
|
|
137
135
|
|
|
138
136
|
reset(coldStart: boolean): void {
|
|
139
137
|
this.bufferIndex = 0x0000
|
|
140
|
-
this.commandDataSize =
|
|
138
|
+
this.commandDataSize = Storage.SECTOR_SIZE
|
|
141
139
|
this.sectorOffset = 0
|
|
142
140
|
|
|
143
141
|
this.error = 0x00
|
|
@@ -147,7 +145,7 @@ export class StorageCard implements IO {
|
|
|
147
145
|
this.lba1 = 0x00
|
|
148
146
|
this.lba2 = 0x00
|
|
149
147
|
this.lba3 = 0xE0
|
|
150
|
-
this.status = 0x00 |
|
|
148
|
+
this.status = 0x00 | Storage.STATUS_RDY
|
|
151
149
|
this.command = 0x00
|
|
152
150
|
|
|
153
151
|
this.isIdentifying = false
|
|
@@ -162,36 +160,36 @@ export class StorageCard implements IO {
|
|
|
162
160
|
|
|
163
161
|
private executeCommand(): void {
|
|
164
162
|
// New command so clear errors and flags
|
|
165
|
-
this.status &= ~
|
|
166
|
-
this.status &= ~
|
|
163
|
+
this.status &= ~Storage.STATUS_ERR
|
|
164
|
+
this.status &= ~Storage.STATUS_DRQ
|
|
167
165
|
this.error = 0x00
|
|
168
|
-
this.commandDataSize =
|
|
166
|
+
this.commandDataSize = Storage.SECTOR_SIZE * this.sectorCount
|
|
169
167
|
this.bufferIndex = 0
|
|
170
168
|
this.sectorOffset = 0
|
|
171
169
|
|
|
172
170
|
// Check if already executing a command
|
|
173
171
|
if (this.isTransferring || this.isIdentifying) {
|
|
174
|
-
this.status |=
|
|
175
|
-
this.error |=
|
|
172
|
+
this.status |= Storage.STATUS_ERR
|
|
173
|
+
this.error |= Storage.ERR_ABRT
|
|
176
174
|
return
|
|
177
175
|
}
|
|
178
176
|
|
|
179
177
|
switch (this.command) {
|
|
180
178
|
case 0xC0: { // Erase sector
|
|
181
179
|
if (!this.sectorValid()) {
|
|
182
|
-
this.status |=
|
|
183
|
-
this.error |=
|
|
180
|
+
this.status |= Storage.STATUS_ERR
|
|
181
|
+
this.error |= Storage.ERR_ABRT | Storage.ERR_IDNF
|
|
184
182
|
} else {
|
|
185
|
-
const offset = this.sectorIndex() *
|
|
186
|
-
this.storage.fill(0x00, offset, offset +
|
|
183
|
+
const offset = this.sectorIndex() * Storage.SECTOR_SIZE
|
|
184
|
+
this.storage.fill(0x00, offset, offset + Storage.SECTOR_SIZE)
|
|
187
185
|
}
|
|
188
186
|
break
|
|
189
187
|
}
|
|
190
188
|
|
|
191
189
|
case 0xEC: { // Identify drive
|
|
192
|
-
this.
|
|
193
|
-
this.commandDataSize =
|
|
194
|
-
this.status |=
|
|
190
|
+
this.buffer.set(this.identity.subarray(0, Storage.SECTOR_SIZE))
|
|
191
|
+
this.commandDataSize = Storage.SECTOR_SIZE
|
|
192
|
+
this.status |= Storage.STATUS_DRQ
|
|
195
193
|
this.isIdentifying = true
|
|
196
194
|
break
|
|
197
195
|
}
|
|
@@ -199,13 +197,13 @@ export class StorageCard implements IO {
|
|
|
199
197
|
case 0x20: // Read sector
|
|
200
198
|
case 0x21:
|
|
201
199
|
if (!this.sectorValid()) {
|
|
202
|
-
this.status |=
|
|
203
|
-
this.error |=
|
|
200
|
+
this.status |= Storage.STATUS_ERR
|
|
201
|
+
this.error |= Storage.ERR_ABRT | Storage.ERR_IDNF
|
|
204
202
|
} else {
|
|
205
203
|
// Load first sector into buffer
|
|
206
|
-
const offset = this.sectorIndex() *
|
|
207
|
-
this.
|
|
208
|
-
this.status |=
|
|
204
|
+
const offset = this.sectorIndex() * Storage.SECTOR_SIZE
|
|
205
|
+
this.buffer.set(this.storage.subarray(offset, offset + Storage.SECTOR_SIZE))
|
|
206
|
+
this.status |= Storage.STATUS_DRQ
|
|
209
207
|
this.isTransferring = true
|
|
210
208
|
}
|
|
211
209
|
break
|
|
@@ -217,18 +215,18 @@ export class StorageCard implements IO {
|
|
|
217
215
|
case 0x30: // Write sector
|
|
218
216
|
case 0x31:
|
|
219
217
|
if (!this.sectorValid()) {
|
|
220
|
-
this.status |=
|
|
221
|
-
this.error |=
|
|
218
|
+
this.status |= Storage.STATUS_ERR
|
|
219
|
+
this.error |= Storage.ERR_ABRT | Storage.ERR_IDNF
|
|
222
220
|
} else {
|
|
223
|
-
this.status |=
|
|
221
|
+
this.status |= Storage.STATUS_DRQ
|
|
224
222
|
this.isTransferring = true
|
|
225
223
|
}
|
|
226
224
|
break
|
|
227
225
|
|
|
228
226
|
default:
|
|
229
227
|
// Unsupported command
|
|
230
|
-
this.status |=
|
|
231
|
-
this.error |=
|
|
228
|
+
this.status |= Storage.STATUS_ERR
|
|
229
|
+
this.error |= Storage.ERR_ABRT
|
|
232
230
|
break
|
|
233
231
|
}
|
|
234
232
|
}
|
|
@@ -242,14 +240,14 @@ export class StorageCard implements IO {
|
|
|
242
240
|
} else {
|
|
243
241
|
this.bufferIndex = 0
|
|
244
242
|
this.isIdentifying = false
|
|
245
|
-
this.status &= ~
|
|
243
|
+
this.status &= ~Storage.STATUS_DRQ
|
|
246
244
|
}
|
|
247
245
|
|
|
248
246
|
return data
|
|
249
247
|
} else if (this.isTransferring) {
|
|
250
248
|
const data = this.buffer[this.bufferIndex]
|
|
251
249
|
|
|
252
|
-
if (this.bufferIndex <
|
|
250
|
+
if (this.bufferIndex < Storage.SECTOR_SIZE - 1) {
|
|
253
251
|
this.bufferIndex++
|
|
254
252
|
} else {
|
|
255
253
|
this.bufferIndex = 0
|
|
@@ -257,11 +255,11 @@ export class StorageCard implements IO {
|
|
|
257
255
|
|
|
258
256
|
if (this.sectorOffset < this.sectorCount) {
|
|
259
257
|
// Load the next sector
|
|
260
|
-
const offset = (this.sectorIndex() + this.sectorOffset) *
|
|
261
|
-
this.
|
|
258
|
+
const offset = (this.sectorIndex() + this.sectorOffset) * Storage.SECTOR_SIZE
|
|
259
|
+
this.buffer.set(this.storage.subarray(offset, offset + Storage.SECTOR_SIZE))
|
|
262
260
|
} else {
|
|
263
261
|
this.isTransferring = false
|
|
264
|
-
this.status &= ~
|
|
262
|
+
this.status &= ~Storage.STATUS_DRQ
|
|
265
263
|
}
|
|
266
264
|
}
|
|
267
265
|
|
|
@@ -274,21 +272,21 @@ export class StorageCard implements IO {
|
|
|
274
272
|
private writeBuffer(value: number): void {
|
|
275
273
|
this.buffer[this.bufferIndex] = value
|
|
276
274
|
|
|
277
|
-
if (this.bufferIndex <
|
|
275
|
+
if (this.bufferIndex < Storage.SECTOR_SIZE - 1) {
|
|
278
276
|
this.bufferIndex++
|
|
279
277
|
} else {
|
|
280
278
|
this.bufferIndex = 0
|
|
281
279
|
|
|
282
280
|
// Write the current sector to storage
|
|
283
|
-
const offset = (this.sectorIndex() + this.sectorOffset) *
|
|
284
|
-
this.
|
|
281
|
+
const offset = (this.sectorIndex() + this.sectorOffset) * Storage.SECTOR_SIZE
|
|
282
|
+
this.storage.set(this.buffer.subarray(0, Storage.SECTOR_SIZE), offset)
|
|
285
283
|
|
|
286
284
|
this.sectorOffset++
|
|
287
285
|
|
|
288
286
|
// Check if all sectors have been written
|
|
289
287
|
if (this.sectorOffset >= this.sectorCount) {
|
|
290
288
|
this.isTransferring = false
|
|
291
|
-
this.status &= ~
|
|
289
|
+
this.status &= ~Storage.STATUS_DRQ
|
|
292
290
|
}
|
|
293
291
|
}
|
|
294
292
|
}
|
|
@@ -298,7 +296,7 @@ export class StorageCard implements IO {
|
|
|
298
296
|
}
|
|
299
297
|
|
|
300
298
|
private sectorValid(): boolean {
|
|
301
|
-
return this.sectorIndex() <
|
|
299
|
+
return this.sectorIndex() < Storage.SECTOR_COUNT
|
|
302
300
|
}
|
|
303
301
|
|
|
304
302
|
private generateIdentity(): void {
|
|
@@ -434,40 +432,39 @@ export class StorageCard implements IO {
|
|
|
434
432
|
}
|
|
435
433
|
|
|
436
434
|
/**
|
|
437
|
-
* Load storage data from a
|
|
438
|
-
* If
|
|
435
|
+
* Load storage data from a Uint8Array, ArrayBuffer, or number array
|
|
436
|
+
* If data is not provided or wrong size, storage remains empty
|
|
439
437
|
*/
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
438
|
+
loadData(data: Uint8Array | ArrayBuffer | number[] | null): void {
|
|
439
|
+
if (!data) {
|
|
440
|
+
console.log('No storage data provided. Storage will remain empty.')
|
|
441
|
+
return
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
let uint8Data: Uint8Array
|
|
445
|
+
if (data instanceof ArrayBuffer) {
|
|
446
|
+
uint8Data = new Uint8Array(data)
|
|
447
|
+
} else if (data instanceof Uint8Array) {
|
|
448
|
+
uint8Data = data
|
|
449
|
+
} else {
|
|
450
|
+
uint8Data = new Uint8Array(data)
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Ensure the data is exactly the expected size
|
|
454
|
+
if (uint8Data.length === Storage.STORAGE_SIZE) {
|
|
455
|
+
this.storage.set(uint8Data)
|
|
456
|
+
console.log(`Storage loaded (${Storage.STORAGE_SIZE} bytes)`)
|
|
457
|
+
} else {
|
|
458
|
+
console.warn(`Warning: Storage data size mismatch. Expected ${Storage.STORAGE_SIZE} bytes, got ${uint8Data.length} bytes.`)
|
|
459
|
+
console.warn('Storage will remain empty.')
|
|
458
460
|
}
|
|
459
461
|
}
|
|
460
462
|
|
|
461
463
|
/**
|
|
462
|
-
*
|
|
464
|
+
* Get storage data as Uint8Array for saving
|
|
463
465
|
*/
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
await writeFile(filePath, this.storage)
|
|
467
|
-
console.log(`Storage saved to: ${filePath}`)
|
|
468
|
-
} catch (error) {
|
|
469
|
-
console.error('Error saving storage file:', error)
|
|
470
|
-
}
|
|
466
|
+
getData(): Uint8Array {
|
|
467
|
+
return new Uint8Array(this.storage)
|
|
471
468
|
}
|
|
472
469
|
|
|
473
470
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { IO } from '../IO'
|
|
2
|
+
import { VTAC } from 'vtac-terminal'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Terminal - Emulates the VTAC fantasy terminal
|
|
6
|
+
*
|
|
7
|
+
* Register Map:
|
|
8
|
+
* $00: Data / Status Register
|
|
9
|
+
* Write: sends byte to VTAC for processing
|
|
10
|
+
* Read: always returns 0 (bit 7 is a busy flag on the real device; busy is never set here)
|
|
11
|
+
*/
|
|
12
|
+
export class Terminal implements IO {
|
|
13
|
+
|
|
14
|
+
raiseIRQ = () => {}
|
|
15
|
+
raiseNMI = () => {}
|
|
16
|
+
|
|
17
|
+
readonly vtac: VTAC = new VTAC()
|
|
18
|
+
|
|
19
|
+
read(address: number): number {
|
|
20
|
+
// Status register: bit 7 is busy flag on real device, never busy in emulation
|
|
21
|
+
return 0
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
write(address: number, data: number): void {
|
|
25
|
+
const register = address & 0x00
|
|
26
|
+
if (register === 0x00) {
|
|
27
|
+
this.vtac.parse(data)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
tick(frequency: number): void {}
|
|
32
|
+
reset(coldStart: boolean): void {}
|
|
33
|
+
|
|
34
|
+
}
|