ac6502 1.6.0 → 1.8.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/dist/components/IO/Attachments/KeyboardEncoderAttachment.d.ts +1 -0
- package/dist/components/IO/Attachments/KeyboardEncoderAttachment.js +18 -10
- package/dist/components/IO/Attachments/KeyboardEncoderAttachment.js.map +1 -1
- package/dist/components/IO/RTC.d.ts +2 -4
- package/dist/components/IO/RTC.js +34 -48
- package/dist/components/IO/RTC.js.map +1 -1
- package/dist/components/IO/Storage.js +5 -1
- package/dist/components/IO/Storage.js.map +1 -1
- package/dist/components/IO.d.ts +1 -1
- package/dist/components/Machine.js +16 -16
- package/dist/components/Machine.js.map +1 -1
- package/dist/index.js +28 -13
- package/dist/index.js.map +1 -1
- package/dist/tests/IO/RTC.test.js +5 -8
- package/dist/tests/IO/RTC.test.js.map +1 -1
- package/dist/tests/IO/Video.test.js +1 -1
- package/dist/tests/Machine.test.js +1 -1
- package/package.json +1 -1
- package/src/components/IO/Attachments/KeyboardEncoderAttachment.ts +19 -11
- package/src/components/IO/RTC.ts +37 -50
- package/src/components/IO/Storage.ts +4 -1
- package/src/components/IO.ts +1 -1
- package/src/components/Machine.ts +16 -16
- package/src/index.ts +30 -13
- package/src/tests/IO/RTC.test.ts +5 -9
- package/src/tests/IO/Video.test.ts +1 -1
- package/src/tests/Machine.test.ts +1 -1
package/src/index.ts
CHANGED
|
@@ -12,7 +12,7 @@ import sdl from '@kmamal/sdl'
|
|
|
12
12
|
import { readFile, writeFile } from 'fs/promises'
|
|
13
13
|
import { existsSync } from 'fs'
|
|
14
14
|
|
|
15
|
-
const VERSION = '1.
|
|
15
|
+
const VERSION = '1.8.0'
|
|
16
16
|
const WIDTH = 320
|
|
17
17
|
const HEIGHT = 240
|
|
18
18
|
|
|
@@ -47,6 +47,7 @@ interface EmulatorOptions {
|
|
|
47
47
|
port?: string
|
|
48
48
|
storage?: string
|
|
49
49
|
target?: string
|
|
50
|
+
encoder?: string
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
class Emulator {
|
|
@@ -72,6 +73,7 @@ class Emulator {
|
|
|
72
73
|
await this.loadBinaries()
|
|
73
74
|
this.configureFrequency()
|
|
74
75
|
this.configureScale()
|
|
76
|
+
this.configureEncoder()
|
|
75
77
|
await this.setupSerialPort()
|
|
76
78
|
this.setupAudio()
|
|
77
79
|
this.setupWindow()
|
|
@@ -116,12 +118,23 @@ class Emulator {
|
|
|
116
118
|
;(this.machine.io4 as Storage).loadData(new Uint8Array(storageData))
|
|
117
119
|
} else {
|
|
118
120
|
console.log(`Storage file not found: ${this.options.storage}`)
|
|
119
|
-
console.log('
|
|
120
|
-
|
|
121
|
+
console.log('Initializing new storage file...')
|
|
122
|
+
const emptyStorage = (this.machine.io4 as Storage).getData()
|
|
123
|
+
await writeFile(this.options.storage, emptyStorage)
|
|
124
|
+
console.log(`Storage file created: ${this.options.storage}`)
|
|
121
125
|
}
|
|
122
126
|
}
|
|
123
127
|
}
|
|
124
128
|
|
|
129
|
+
private configureEncoder(): void {
|
|
130
|
+
const enc = this.options.encoder ?? 'matrix'
|
|
131
|
+
const activePort = enc === 'ps2' ? 'A' : enc === 'matrix' ? 'B' : 'both'
|
|
132
|
+
if (this.machine.keyboardEncoderAttachment) {
|
|
133
|
+
this.machine.keyboardEncoderAttachment.activePort = activePort as 'A' | 'B' | 'both'
|
|
134
|
+
console.log(`Keyboard encoder: ${enc} (Port ${activePort})`)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
125
138
|
private configureFrequency(): void {
|
|
126
139
|
if (this.options.freq) {
|
|
127
140
|
const frequency = Number(this.options.freq)
|
|
@@ -537,6 +550,9 @@ class Emulator {
|
|
|
537
550
|
}
|
|
538
551
|
|
|
539
552
|
private shutdown(): void {
|
|
553
|
+
// Stop the machine loop to prevent further rendering after window close
|
|
554
|
+
this.machine.stop()
|
|
555
|
+
|
|
540
556
|
// Close all connected controllers
|
|
541
557
|
for (const [id, controller] of this.controllers.entries()) {
|
|
542
558
|
if (!controller.closed) {
|
|
@@ -598,17 +614,18 @@ program
|
|
|
598
614
|
.description('Emulator for the A.C. Wright 6502 project.')
|
|
599
615
|
.version(VERSION, '-v, --version', 'Output the current emulator version')
|
|
600
616
|
.helpOption('-h, --help', 'Output help / options')
|
|
601
|
-
.
|
|
602
|
-
.
|
|
603
|
-
.
|
|
604
|
-
.
|
|
605
|
-
.
|
|
606
|
-
.
|
|
607
|
-
.
|
|
608
|
-
.
|
|
609
|
-
.
|
|
610
|
-
.
|
|
617
|
+
.addOption(new Option('-a, --parity <parity>', 'Parity (odd | even | none)').default('none'))
|
|
618
|
+
.addOption(new Option('-b, --baudrate <baudrate>', 'Baud Rate').default('9600'))
|
|
619
|
+
.addOption(new Option('-c, --cart <path>', 'Path to 32K Cart binary file'))
|
|
620
|
+
.addOption(new Option('-d, --databits <databits>', 'Data Bits (5 | 6 | 7 | 8)').default('8'))
|
|
621
|
+
.addOption(new Option('-f, --freq <freq>', 'Set the clock frequency in Hz').default('1000000'))
|
|
622
|
+
.addOption(new Option('-p, --port <port>', 'Path to the serial port (e.g., /dev/ttyUSB0)'))
|
|
623
|
+
.addOption(new Option('-r, --rom <path>', 'Path to 32K ROM binary file'))
|
|
624
|
+
.addOption(new Option('-s, --scale <scale>', 'Set the emulator scale').default('2'))
|
|
625
|
+
.addOption(new Option('-S, --storage <path>', 'Path to storage data file for Compact Flash card persistence'))
|
|
626
|
+
.addOption(new Option('-t, --stopbits <stopbits>', 'Stop Bits (1 | 1.5 | 2)').default('1'))
|
|
611
627
|
.addOption(new Option('-T, --target <target>', 'System target').choices(['cob', 'vcs', 'kim', 'dev']).default('cob'))
|
|
628
|
+
.addOption(new Option('-e, --encoder <mode>', 'Keyboard encoder active port (ps2 = Port A / CA1, matrix = Port B / CB1)').choices(['ps2', 'matrix', 'both']).default('matrix'))
|
|
612
629
|
.addHelpText('beforeAll', figlet.textSync('6502 Emulator', { font: 'cricket' }) + '\n' + `Version: ${VERSION} | A.C. Wright Design\n`)
|
|
613
630
|
.parse(process.argv)
|
|
614
631
|
|
package/src/tests/IO/RTC.test.ts
CHANGED
|
@@ -2,11 +2,6 @@ import { RTC } from '../../components/IO/RTC'
|
|
|
2
2
|
|
|
3
3
|
const bcdToDecimal = (bcd: number): number => (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f)
|
|
4
4
|
|
|
5
|
-
const enableTransfers = (rtc: RTC): void => {
|
|
6
|
-
rtc.write(0x0f, 0x80)
|
|
7
|
-
rtc.tick(1)
|
|
8
|
-
}
|
|
9
|
-
|
|
10
5
|
const setTime = (rtc: RTC, values: {
|
|
11
6
|
seconds: number
|
|
12
7
|
minutes: number
|
|
@@ -17,15 +12,16 @@ const setTime = (rtc: RTC, values: {
|
|
|
17
12
|
year: number
|
|
18
13
|
century: number
|
|
19
14
|
}): void => {
|
|
20
|
-
|
|
15
|
+
rtc.write(0x0f, 0x80) // Set TE to inhibit transfers
|
|
21
16
|
rtc.write(0x00, values.seconds)
|
|
22
17
|
rtc.write(0x01, values.minutes)
|
|
23
18
|
rtc.write(0x02, values.hours)
|
|
24
19
|
rtc.write(0x03, values.dayOfWeek)
|
|
25
20
|
rtc.write(0x04, values.date)
|
|
26
|
-
rtc.write(0x05, values.month
|
|
21
|
+
rtc.write(0x05, values.month) // EOSC=0: oscillator enabled (DS1511Y default)
|
|
27
22
|
rtc.write(0x06, values.year)
|
|
28
23
|
rtc.write(0x07, values.century)
|
|
24
|
+
rtc.write(0x0f, 0x00) // Clear TE: falling edge commits user to internal
|
|
29
25
|
}
|
|
30
26
|
|
|
31
27
|
describe('RTC', () => {
|
|
@@ -64,7 +60,7 @@ describe('RTC', () => {
|
|
|
64
60
|
expect(bcdToDecimal(century)).toBeGreaterThanOrEqual(0)
|
|
65
61
|
expect(bcdToDecimal(century)).toBeLessThanOrEqual(39)
|
|
66
62
|
|
|
67
|
-
expect(month & 0x80).toBe(
|
|
63
|
+
expect(month & 0x80).toBe(0x00)
|
|
68
64
|
})
|
|
69
65
|
})
|
|
70
66
|
|
|
@@ -150,7 +146,7 @@ describe('RTC', () => {
|
|
|
150
146
|
century: 0x20
|
|
151
147
|
})
|
|
152
148
|
|
|
153
|
-
rtc.write(0x05,
|
|
149
|
+
rtc.write(0x05, 0x81) // EOSC=1: oscillator disabled
|
|
154
150
|
rtc.tick(1)
|
|
155
151
|
|
|
156
152
|
expect(rtc.read(0x00)).toBe(0x10)
|
|
@@ -78,7 +78,7 @@ const setupTextMode = (vdp: Video): void => {
|
|
|
78
78
|
* Must not overshoot into the next frame (scanline 0 of the next
|
|
79
79
|
* frame clears the status register during sprite processing).
|
|
80
80
|
*/
|
|
81
|
-
const renderOneFrame = (vdp: Video, frequency: number =
|
|
81
|
+
const renderOneFrame = (vdp: Video, frequency: number = 1000000): void => {
|
|
82
82
|
// At 2MHz: cyclesPerFrame ≈ 33333, each tick = 128 cycles → ~261 ticks/frame
|
|
83
83
|
const ticksPerFrame = Math.ceil((frequency / 60) / 128)
|
|
84
84
|
for (let i = 0; i < ticksPerFrame; i++) {
|
|
@@ -24,7 +24,7 @@ describe('Machine', () => {
|
|
|
24
24
|
|
|
25
25
|
test('Machine initializes with correct default properties', () => {
|
|
26
26
|
expect(machine.isRunning).toBe(false)
|
|
27
|
-
expect(machine.frequency).toBe(
|
|
27
|
+
expect(machine.frequency).toBe(1000000)
|
|
28
28
|
expect(machine.scale).toBe(2)
|
|
29
29
|
expect(machine.frames).toBe(0)
|
|
30
30
|
})
|