ac6502 1.10.0 → 1.12.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 -97
- package/dist/components/CPU.d.ts +4 -0
- package/dist/components/CPU.js +87 -30
- package/dist/components/CPU.js.map +1 -1
- package/dist/components/IO/ACIA.d.ts +13 -21
- package/dist/components/IO/ACIA.js +53 -151
- package/dist/components/IO/ACIA.js.map +1 -1
- package/dist/components/IO/Attachments/KeyboardEncoderAttachment.js +1 -1
- package/dist/components/IO/Attachments/KeyboardEncoderAttachment.js.map +1 -1
- package/dist/components/IO/Empty.d.ts +1 -3
- package/dist/components/IO/Empty.js +1 -5
- package/dist/components/IO/Empty.js.map +1 -1
- package/dist/components/IO/RAMBank.d.ts +3 -4
- package/dist/components/IO/RAMBank.js +4 -13
- package/dist/components/IO/RAMBank.js.map +1 -1
- package/dist/components/IO/RTC.d.ts +2 -3
- package/dist/components/IO/RTC.js +17 -7
- package/dist/components/IO/RTC.js.map +1 -1
- package/dist/components/IO/Sound.d.ts +1 -3
- package/dist/components/IO/Sound.js +13 -23
- package/dist/components/IO/Sound.js.map +1 -1
- package/dist/components/IO/Storage.d.ts +1 -3
- package/dist/components/IO/Storage.js +1 -3
- package/dist/components/IO/Storage.js.map +1 -1
- package/dist/components/IO/VIA.d.ts +1 -3
- package/dist/components/IO/VIA.js +6 -7
- package/dist/components/IO/VIA.js.map +1 -1
- package/dist/components/IO/Video.d.ts +1 -3
- package/dist/components/IO/Video.js +3 -5
- package/dist/components/IO/Video.js.map +1 -1
- package/dist/components/IO.d.ts +1 -3
- package/dist/components/Machine.d.ts +3 -9
- package/dist/components/Machine.js +72 -259
- package/dist/components/Machine.js.map +1 -1
- package/dist/index.js +14 -118
- package/dist/index.js.map +1 -1
- package/dist/lib.d.ts +0 -2
- package/dist/lib.js +1 -5
- package/dist/lib.js.map +1 -1
- package/dist/tests/IO/ACIA.test.js +57 -108
- package/dist/tests/IO/ACIA.test.js.map +1 -1
- package/dist/tests/IO/Attachments/KeyboardEncoderAttachment.test.js +5 -0
- package/dist/tests/IO/Attachments/KeyboardEncoderAttachment.test.js.map +1 -1
- package/dist/tests/IO/Empty.test.js +2 -14
- package/dist/tests/IO/Empty.test.js.map +1 -1
- package/dist/tests/IO/RAMBank.test.js +5 -12
- package/dist/tests/IO/RAMBank.test.js.map +1 -1
- package/dist/tests/IO/RTC.test.js +7 -16
- package/dist/tests/IO/RTC.test.js.map +1 -1
- package/dist/tests/IO/Sound.test.js +6 -8
- package/dist/tests/IO/Sound.test.js.map +1 -1
- package/dist/tests/IO/Storage.test.js +0 -6
- package/dist/tests/IO/Storage.test.js.map +1 -1
- package/dist/tests/IO/VIA.test.js +6 -10
- package/dist/tests/IO/VIA.test.js.map +1 -1
- package/dist/tests/IO/Video.test.js +7 -7
- package/dist/tests/IO/Video.test.js.map +1 -1
- package/dist/tests/Machine.test.js +1 -1
- package/dist/tests/Machine.test.js.map +1 -1
- package/package.json +1 -1
- package/src/components/CPU.ts +94 -31
- package/src/components/IO/ACIA.ts +57 -176
- package/src/components/IO/Attachments/KeyboardEncoderAttachment.ts +1 -1
- package/src/components/IO/Empty.ts +1 -4
- package/src/components/IO/RAMBank.ts +4 -15
- package/src/components/IO/RTC.ts +18 -7
- package/src/components/IO/Sound.ts +14 -27
- package/src/components/IO/Storage.ts +2 -5
- package/src/components/IO/VIA.ts +6 -8
- package/src/components/IO/Video.ts +5 -7
- package/src/components/IO.ts +1 -4
- package/src/components/Machine.ts +81 -300
- package/src/index.ts +12 -111
- package/src/lib.ts +0 -2
- package/src/tests/IO/ACIA.test.ts +60 -122
- package/src/tests/IO/Attachments/KeyboardEncoderAttachment.test.ts +6 -0
- package/src/tests/IO/Empty.test.ts +2 -17
- package/src/tests/IO/RAMBank.test.ts +5 -14
- package/src/tests/IO/RTC.test.ts +7 -20
- package/src/tests/IO/Sound.test.ts +6 -8
- package/src/tests/IO/Storage.test.ts +0 -7
- package/src/tests/IO/VIA.test.ts +6 -12
- package/src/tests/IO/Video.test.ts +7 -8
- package/src/tests/Machine.test.ts +1 -1
- package/src/components/IO/Attachments/KeypadAttachment.ts +0 -153
- package/src/components/IO/Attachments/LCDAttachment.ts +0 -791
- package/src/tests/IO/Attachments/KeypadAttachment.test.ts +0 -389
- package/src/tests/IO/Attachments/LCDAttachment.test.ts +0 -795
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ A comprehensive, cycle-accurate emulator for the [A.C. Wright 6502](https://gith
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
This emulator provides a complete software implementation of a 65C02-based computer system, designed to run the same code as the hardware implementation. It features full I/O peripheral support, including video, sound, serial communication, storage, and GPIO interfaces.
|
|
7
|
+
This emulator provides a complete software implementation of a 65C02-based computer system, designed to run the same code as the hardware implementation. It features full I/O peripheral support, including video, sound, serial communication, storage, and GPIO interfaces.
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
@@ -42,7 +42,6 @@ This emulator provides a complete software implementation of a 65C02-based compu
|
|
|
42
42
|
- **Input Devices**
|
|
43
43
|
- Keyboard support (matrix and encoder modes)
|
|
44
44
|
- Joystick/gamepad support with button mapping (dual controller support)
|
|
45
|
-
- Keypad support (KIM mode)
|
|
46
45
|
- SDL input handling
|
|
47
46
|
|
|
48
47
|
- **Development Features**
|
|
@@ -59,16 +58,11 @@ Get up and running in seconds:
|
|
|
59
58
|
# Install globally
|
|
60
59
|
npm install -g ac6502
|
|
61
60
|
|
|
62
|
-
# Run the emulator
|
|
61
|
+
# Run the emulator
|
|
63
62
|
ac6502
|
|
64
63
|
|
|
65
64
|
# Load a ROM
|
|
66
65
|
ac6502 --rom /path/to/rom.bin
|
|
67
|
-
|
|
68
|
-
# Run in different system configurations
|
|
69
|
-
ac6502 --target kim --rom /path/to/kim.bin
|
|
70
|
-
ac6502 --target dev --cart /path/to/program.bin
|
|
71
|
-
ac6502 --target vcs --cart /path/to/game.bin
|
|
72
66
|
```
|
|
73
67
|
|
|
74
68
|
## Installation
|
|
@@ -120,7 +114,6 @@ ac6502 [options]
|
|
|
120
114
|
- `-r, --rom <path>` - Load a system ROM file
|
|
121
115
|
- `-f, --freq <frequency>` - Set CPU frequency in Hz (default: 1000000)
|
|
122
116
|
- `-s, --scale <factor>` - Set display scale factor (default: 1)
|
|
123
|
-
- `-T, --target <target>` - System target: cob, vcs, kim, dev (default: cob)
|
|
124
117
|
- `-p, --port <device>` - Serial port device path
|
|
125
118
|
- `-b, --baudrate <rate>` - Serial baud rate (default: 9600)
|
|
126
119
|
- `-a, --parity <type>` - Serial parity: none, even, odd (default: none)
|
|
@@ -135,99 +128,29 @@ ac6502 [options]
|
|
|
135
128
|
Load a cartridge:
|
|
136
129
|
|
|
137
130
|
```bash
|
|
138
|
-
ac6502 --cart /path/to/
|
|
131
|
+
ac6502 --rom /path/to/rom.bin --cart /path/to/cart.bin
|
|
139
132
|
```
|
|
140
133
|
|
|
141
134
|
Connect to serial hardware:
|
|
142
135
|
|
|
143
136
|
```bash
|
|
144
|
-
ac6502 --port /dev/ttyUSB0 --baudrate 9600 --rom /path/to/
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
Run in KIM mode with LCD and keypad:
|
|
148
|
-
|
|
149
|
-
```bash
|
|
150
|
-
ac6502 --target kim --rom /path/to/kim.bin --scale 2
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
Run in development mode with terminal:
|
|
154
|
-
|
|
155
|
-
```bash
|
|
156
|
-
ac6502 --target dev --cart /path/to/program.bin
|
|
137
|
+
ac6502 --port /dev/ttyUSB0 --baudrate 9600 --rom /path/to/rom.bin
|
|
157
138
|
```
|
|
158
139
|
|
|
159
140
|
Set custom CPU frequency and storage:
|
|
160
141
|
|
|
161
142
|
```bash
|
|
162
|
-
ac6502 --freq 2000000 --storage ./disk.img --cart /path/to/
|
|
143
|
+
ac6502 --freq 2000000 --storage ./disk.img --rom /path/to/rom.bin --cart /path/to/cart.bin
|
|
163
144
|
```
|
|
164
145
|
|
|
165
146
|
## Architecture
|
|
166
147
|
|
|
167
|
-
### System
|
|
168
|
-
|
|
169
|
-
The emulator supports four different system configurations via the `--target` option:
|
|
170
|
-
|
|
171
|
-
#### COB (Complete On-Board) - Default
|
|
172
|
-
|
|
173
|
-
Full-featured system with all peripherals:
|
|
174
|
-
|
|
175
|
-
```
|
|
176
|
-
Machine (COB)
|
|
177
|
-
├── CPU (65C02)
|
|
178
|
-
├── RAM (System Memory)
|
|
179
|
-
├── ROM (System BIOS/Monitor)
|
|
180
|
-
├── Cart (Optional Cartridge)
|
|
181
|
-
└── I/O Cards (8 slots)
|
|
182
|
-
├── IO1: RAM Card (Expansion)
|
|
183
|
-
├── IO2: RAM Card (Expansion)
|
|
184
|
-
├── IO3: RTC Card (DS1511Y+ Real-Time Clock)
|
|
185
|
-
├── IO4: Storage Card (Compact Flash 8-bit IDE Mode)
|
|
186
|
-
├── IO5: Serial Card (6551 ACIA)
|
|
187
|
-
├── IO6: VIA Card (6522 GPIO)
|
|
188
|
-
├── IO7: Sound Card (6581 SID)
|
|
189
|
-
└── IO8: Video Card (TMS9918)
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
#### VCS (Video Computer System)
|
|
148
|
+
### System Configuration
|
|
193
149
|
|
|
194
|
-
|
|
150
|
+
The emulator implements a full-featured 65C02 system with all peripherals:
|
|
195
151
|
|
|
196
152
|
```
|
|
197
|
-
Machine
|
|
198
|
-
├── CPU (65C02)
|
|
199
|
-
├── RAM (System Memory)
|
|
200
|
-
├── ROM (System BIOS/Monitor)
|
|
201
|
-
├── Cart (Optional Cartridge)
|
|
202
|
-
└── I/O Cards (8 slots)
|
|
203
|
-
├── IO6: VIA Card (6522 GPIO)
|
|
204
|
-
├── IO7: Sound Card (6581 SID)
|
|
205
|
-
└── IO8: Video Card (TMS9918)
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
#### KIM (Keyboard Input Monitor)
|
|
209
|
-
|
|
210
|
-
Single-board computer with LCD and keypad:
|
|
211
|
-
|
|
212
|
-
```
|
|
213
|
-
Machine (KIM)
|
|
214
|
-
├── CPU (65C02)
|
|
215
|
-
├── RAM (System Memory)
|
|
216
|
-
├── ROM (System BIOS/Monitor)
|
|
217
|
-
├── Cart (Optional Cartridge)
|
|
218
|
-
└── I/O Cards (8 slots)
|
|
219
|
-
├── IO5: Serial Card (6551 ACIA)
|
|
220
|
-
└── IO8: VIA Card (6522 GPIO)
|
|
221
|
-
├── LCD Attachment (HD44780 16×2 character display)
|
|
222
|
-
└── Keypad Attachment (4×6 matrix keypad)
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
#### DEV (Development)
|
|
226
|
-
|
|
227
|
-
System for software development with terminal interface:
|
|
228
|
-
|
|
229
|
-
```
|
|
230
|
-
Machine (DEV)
|
|
153
|
+
Machine
|
|
231
154
|
├── CPU (65C02)
|
|
232
155
|
├── RAM (System Memory)
|
|
233
156
|
├── ROM (System BIOS/Monitor)
|
|
@@ -245,17 +168,12 @@ Machine (DEV)
|
|
|
245
168
|
|
|
246
169
|
### VIA (GPIO) Attachments
|
|
247
170
|
|
|
248
|
-
The VIA card supports multiple attachment types
|
|
171
|
+
The VIA card supports multiple attachment types:
|
|
249
172
|
|
|
250
|
-
#### Standard Attachments (COB/DEV/VCS)
|
|
251
173
|
- **Keyboard Matrix**: PS/2-style keyboard matrix scanning
|
|
252
174
|
- **Keyboard Encoder**: Parallel keyboard encoder
|
|
253
175
|
- **Joystick A/B**: Game controllers with 8 buttons and directional input
|
|
254
176
|
|
|
255
|
-
#### KIM Attachments
|
|
256
|
-
- **LCD Display**: HD44780-compatible 16×2 character LCD with 5×8 pixel characters
|
|
257
|
-
- **Keypad**: 4×6 matrix keypad with 24-key layout
|
|
258
|
-
|
|
259
177
|
### Memory Map
|
|
260
178
|
|
|
261
179
|
The system uses a standard 6502 memory layout with I/O cards mapped into the address space. Each I/O card occupies a dedicated region accessible via memory-mapped registers.
|
|
@@ -288,9 +206,7 @@ src/
|
|
|
288
206
|
│ ├── Attachment.ts
|
|
289
207
|
│ ├── JoystickAttachment.ts
|
|
290
208
|
│ ├── KeyboardEncoderAttachment.ts
|
|
291
|
-
│
|
|
292
|
-
│ ├── KeypadAttachment.ts
|
|
293
|
-
│ └── LCDAttachment.ts
|
|
209
|
+
│ └── KeyboardMatrixAttachment.ts
|
|
294
210
|
└── tests/ # Comprehensive test suite
|
|
295
211
|
```
|
|
296
212
|
|
|
@@ -337,11 +253,10 @@ The emulator targets 1 MHz operation by default (configurable) and attempts to m
|
|
|
337
253
|
|
|
338
254
|
## Supported Input Devices
|
|
339
255
|
|
|
340
|
-
- **Keyboard**: Full keyboard support via SDL
|
|
341
|
-
- **Game Controllers**: Dual controller support (Player A and Player B)
|
|
256
|
+
- **Keyboard**: Full keyboard support via SDL
|
|
257
|
+
- **Game Controllers**: Dual controller support (Player A and Player B)
|
|
342
258
|
- D-pad and analog stick support
|
|
343
259
|
- 8 buttons: Up, Down, Left, Right, A, B, Select, Start
|
|
344
|
-
- **Keypad**: 4×6 matrix keypad for KIM target (24 keys including arrows, numbers, and function keys)
|
|
345
260
|
|
|
346
261
|
## Credits
|
|
347
262
|
|
package/dist/components/CPU.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export declare class CPU {
|
|
|
20
20
|
private opcode;
|
|
21
21
|
cyclesRem: number;
|
|
22
22
|
cycles: number;
|
|
23
|
+
private irqLine;
|
|
23
24
|
a: number;
|
|
24
25
|
x: number;
|
|
25
26
|
y: number;
|
|
@@ -31,6 +32,8 @@ export declare class CPU {
|
|
|
31
32
|
constructor(read: (address: number) => number, write: (address: number, data: number) => void);
|
|
32
33
|
reset(): void;
|
|
33
34
|
irq(): void;
|
|
35
|
+
irqTrigger(): void;
|
|
36
|
+
irqClear(): void;
|
|
34
37
|
nmi(): void;
|
|
35
38
|
tick(): void;
|
|
36
39
|
step(): number;
|
|
@@ -62,6 +65,7 @@ export declare class CPU {
|
|
|
62
65
|
private BCS;
|
|
63
66
|
private BEQ;
|
|
64
67
|
private BIT;
|
|
68
|
+
private BIT_IMM;
|
|
65
69
|
private BMI;
|
|
66
70
|
private BNE;
|
|
67
71
|
private BPL;
|
package/dist/components/CPU.js
CHANGED
|
@@ -12,6 +12,7 @@ class CPU {
|
|
|
12
12
|
this.opcode = 0x00; // The instruction byte
|
|
13
13
|
this.cyclesRem = 0; // Counts how many cycles the current instruction has remaining
|
|
14
14
|
this.cycles = 0; // Counts the total number of cycles executed
|
|
15
|
+
this.irqLine = false;
|
|
15
16
|
this.a = 0x00;
|
|
16
17
|
this.x = 0x00;
|
|
17
18
|
this.y = 0x00;
|
|
@@ -159,7 +160,7 @@ class CPU {
|
|
|
159
160
|
{ name: 'STX', cycles: 3, opcode: this.STX.bind(this), addrMode: this.ZP0.bind(this) },
|
|
160
161
|
{ name: 'SMB0', cycles: 5, opcode: this.SMB0.bind(this), addrMode: this.ZP0.bind(this) },
|
|
161
162
|
{ name: 'DEY', cycles: 2, opcode: this.DEY.bind(this), addrMode: this.IMP.bind(this) },
|
|
162
|
-
{ name: 'BIT', cycles: 2, opcode: this.
|
|
163
|
+
{ name: 'BIT', cycles: 2, opcode: this.BIT_IMM.bind(this), addrMode: this.IMM.bind(this) },
|
|
163
164
|
{ name: 'TXA', cycles: 2, opcode: this.TXA.bind(this), addrMode: this.IMP.bind(this) },
|
|
164
165
|
{ name: '???', cycles: 2, opcode: this.XXX.bind(this), addrMode: this.IMP.bind(this) },
|
|
165
166
|
{ name: 'STY', cycles: 4, opcode: this.STY.bind(this), addrMode: this.ABS.bind(this) },
|
|
@@ -329,6 +330,12 @@ class CPU {
|
|
|
329
330
|
this.cycles += 7;
|
|
330
331
|
}
|
|
331
332
|
}
|
|
333
|
+
irqTrigger() {
|
|
334
|
+
this.irqLine = true;
|
|
335
|
+
}
|
|
336
|
+
irqClear() {
|
|
337
|
+
this.irqLine = false;
|
|
338
|
+
}
|
|
332
339
|
nmi() {
|
|
333
340
|
// Push the program counter onto the stack
|
|
334
341
|
this.write(0x0100 + this.sp, (this.pc >> 8) & 0x00FF);
|
|
@@ -364,6 +371,10 @@ class CPU {
|
|
|
364
371
|
// addrMode() and opcode() return 1 or 0 if additional clock cycles are required
|
|
365
372
|
this.cyclesRem += addCycleAddrMode & addCycleOpcode;
|
|
366
373
|
this.cycles += addCycleAddrMode & addCycleOpcode;
|
|
374
|
+
// Level-triggered IRQ: check after instruction decode
|
|
375
|
+
if (this.irqLine) {
|
|
376
|
+
this.irq();
|
|
377
|
+
}
|
|
367
378
|
}
|
|
368
379
|
this.cyclesRem--;
|
|
369
380
|
}
|
|
@@ -576,12 +587,31 @@ class CPU {
|
|
|
576
587
|
//
|
|
577
588
|
ADC() {
|
|
578
589
|
this.fetch();
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
590
|
+
if (this.getFlag(CPU.D)) {
|
|
591
|
+
// BCD decimal mode (65C02)
|
|
592
|
+
const c = this.getFlag(CPU.C);
|
|
593
|
+
const bin = this.a + this.fetched + c;
|
|
594
|
+
let lo = (this.a & 0x0F) + (this.fetched & 0x0F) + c;
|
|
595
|
+
if (lo > 0x09)
|
|
596
|
+
lo += 0x06;
|
|
597
|
+
let hi = (this.a >> 4) + (this.fetched >> 4) + (lo > 0x0F ? 1 : 0);
|
|
598
|
+
if (hi > 0x09)
|
|
599
|
+
hi += 0x06;
|
|
600
|
+
const result = (hi << 4) | (lo & 0x0F);
|
|
601
|
+
this.setFlag(CPU.Z, (bin & 0xFF) === 0);
|
|
602
|
+
this.setFlag(CPU.V, ((this.a ^ bin) & (this.fetched ^ bin) & 0x80) !== 0);
|
|
603
|
+
this.setFlag(CPU.N, (bin & 0x80) !== 0);
|
|
604
|
+
this.setFlag(CPU.C, hi > 0x0F);
|
|
605
|
+
this.a = result & 0xFF;
|
|
606
|
+
}
|
|
607
|
+
else {
|
|
608
|
+
this.temp = this.a + this.fetched + this.getFlag(CPU.C);
|
|
609
|
+
this.setFlag(CPU.C, (this.temp & 0xFF00) != 0);
|
|
610
|
+
this.setFlag(CPU.Z, (this.temp & 0x00FF) == 0);
|
|
611
|
+
this.setFlag(CPU.V, ((this.temp ^ this.a) & (this.temp ^ this.fetched) & 0x0080) != 0);
|
|
612
|
+
this.setFlag(CPU.N, (this.temp & 0x0080) != 0);
|
|
613
|
+
this.a = this.temp & 0x00FF;
|
|
614
|
+
}
|
|
585
615
|
return 1;
|
|
586
616
|
}
|
|
587
617
|
AND() {
|
|
@@ -608,10 +638,10 @@ class CPU {
|
|
|
608
638
|
}
|
|
609
639
|
BCC() {
|
|
610
640
|
if (this.getFlag(CPU.C) == 0) {
|
|
611
|
-
this.
|
|
641
|
+
this.cyclesRem++;
|
|
612
642
|
this.addrAbs = this.pc + this.addrRel;
|
|
613
643
|
if ((this.addrAbs & 0xFF00) != (this.pc & 0xFF00)) {
|
|
614
|
-
this.
|
|
644
|
+
this.cyclesRem++;
|
|
615
645
|
}
|
|
616
646
|
this.pc = this.addrAbs;
|
|
617
647
|
}
|
|
@@ -619,10 +649,10 @@ class CPU {
|
|
|
619
649
|
}
|
|
620
650
|
BCS() {
|
|
621
651
|
if (this.getFlag(CPU.C) == 1) {
|
|
622
|
-
this.
|
|
652
|
+
this.cyclesRem++;
|
|
623
653
|
this.addrAbs = this.pc + this.addrRel;
|
|
624
654
|
if ((this.addrAbs & 0xFF00) != (this.pc & 0xFF00)) {
|
|
625
|
-
this.
|
|
655
|
+
this.cyclesRem++;
|
|
626
656
|
}
|
|
627
657
|
this.pc = this.addrAbs;
|
|
628
658
|
}
|
|
@@ -630,10 +660,10 @@ class CPU {
|
|
|
630
660
|
}
|
|
631
661
|
BEQ() {
|
|
632
662
|
if (this.getFlag(CPU.Z) == 1) {
|
|
633
|
-
this.
|
|
663
|
+
this.cyclesRem++;
|
|
634
664
|
this.addrAbs = this.pc + this.addrRel;
|
|
635
665
|
if ((this.addrAbs & 0xFF00) != (this.pc & 0xFF00)) {
|
|
636
|
-
this.
|
|
666
|
+
this.cyclesRem++;
|
|
637
667
|
}
|
|
638
668
|
this.pc = this.addrAbs;
|
|
639
669
|
}
|
|
@@ -647,12 +677,19 @@ class CPU {
|
|
|
647
677
|
this.setFlag(CPU.V, (this.fetched & (1 << 6)) != 0);
|
|
648
678
|
return 0;
|
|
649
679
|
}
|
|
680
|
+
BIT_IMM() {
|
|
681
|
+
this.fetch();
|
|
682
|
+
this.temp = this.a & this.fetched;
|
|
683
|
+
this.setFlag(CPU.Z, (this.temp & 0x00FF) == 0x00);
|
|
684
|
+
// N and V are NOT modified for BIT immediate (65C02)
|
|
685
|
+
return 0;
|
|
686
|
+
}
|
|
650
687
|
BMI() {
|
|
651
688
|
if (this.getFlag(CPU.N) == 1) {
|
|
652
|
-
this.
|
|
689
|
+
this.cyclesRem++;
|
|
653
690
|
this.addrAbs = this.pc + this.addrRel;
|
|
654
691
|
if ((this.addrAbs & 0xFF00) != (this.pc & 0xFF00)) {
|
|
655
|
-
this.
|
|
692
|
+
this.cyclesRem++;
|
|
656
693
|
}
|
|
657
694
|
this.pc = this.addrAbs;
|
|
658
695
|
}
|
|
@@ -660,10 +697,10 @@ class CPU {
|
|
|
660
697
|
}
|
|
661
698
|
BNE() {
|
|
662
699
|
if (this.getFlag(CPU.Z) == 0) {
|
|
663
|
-
this.
|
|
700
|
+
this.cyclesRem++;
|
|
664
701
|
this.addrAbs = this.pc + this.addrRel;
|
|
665
702
|
if ((this.addrAbs & 0xFF00) != (this.pc & 0xFF00)) {
|
|
666
|
-
this.
|
|
703
|
+
this.cyclesRem++;
|
|
667
704
|
}
|
|
668
705
|
this.pc = this.addrAbs;
|
|
669
706
|
}
|
|
@@ -671,10 +708,10 @@ class CPU {
|
|
|
671
708
|
}
|
|
672
709
|
BPL() {
|
|
673
710
|
if (this.getFlag(CPU.N) == 0) {
|
|
674
|
-
this.
|
|
711
|
+
this.cyclesRem++;
|
|
675
712
|
this.addrAbs = this.pc + this.addrRel;
|
|
676
713
|
if ((this.addrAbs & 0xFF00) != (this.pc & 0xFF00)) {
|
|
677
|
-
this.
|
|
714
|
+
this.cyclesRem++;
|
|
678
715
|
}
|
|
679
716
|
this.pc = this.addrAbs;
|
|
680
717
|
}
|
|
@@ -696,10 +733,10 @@ class CPU {
|
|
|
696
733
|
}
|
|
697
734
|
BVC() {
|
|
698
735
|
if (this.getFlag(CPU.V) == 0) {
|
|
699
|
-
this.
|
|
736
|
+
this.cyclesRem++;
|
|
700
737
|
this.addrAbs = this.pc + this.addrRel;
|
|
701
738
|
if ((this.addrAbs & 0xFF00) != (this.pc & 0xFF00)) {
|
|
702
|
-
this.
|
|
739
|
+
this.cyclesRem++;
|
|
703
740
|
}
|
|
704
741
|
this.pc = this.addrAbs;
|
|
705
742
|
}
|
|
@@ -707,10 +744,10 @@ class CPU {
|
|
|
707
744
|
}
|
|
708
745
|
BVS() {
|
|
709
746
|
if (this.getFlag(CPU.V) == 1) {
|
|
710
|
-
this.
|
|
747
|
+
this.cyclesRem++;
|
|
711
748
|
this.addrAbs = this.pc + this.addrRel;
|
|
712
749
|
if ((this.addrAbs & 0xFF00) != (this.pc & 0xFF00)) {
|
|
713
|
-
this.
|
|
750
|
+
this.cyclesRem++;
|
|
714
751
|
}
|
|
715
752
|
this.pc = this.addrAbs;
|
|
716
753
|
}
|
|
@@ -959,13 +996,33 @@ class CPU {
|
|
|
959
996
|
}
|
|
960
997
|
SBC() {
|
|
961
998
|
this.fetch();
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
999
|
+
if (this.getFlag(CPU.D)) {
|
|
1000
|
+
// BCD decimal mode (65C02)
|
|
1001
|
+
const c = this.getFlag(CPU.C);
|
|
1002
|
+
const bin = this.a - this.fetched - (1 - c);
|
|
1003
|
+
let lo = (this.a & 0x0F) - (this.fetched & 0x0F) - (1 - c);
|
|
1004
|
+
if (lo < 0)
|
|
1005
|
+
lo = ((lo - 0x06) & 0x0F) | ((this.a & 0xF0) - (this.fetched & 0xF0) - 0x10);
|
|
1006
|
+
else
|
|
1007
|
+
lo = (lo & 0x0F) | ((this.a & 0xF0) - (this.fetched & 0xF0));
|
|
1008
|
+
if (lo < 0)
|
|
1009
|
+
lo -= 0x60;
|
|
1010
|
+
const result = lo & 0xFF;
|
|
1011
|
+
this.setFlag(CPU.Z, (bin & 0xFF) === 0);
|
|
1012
|
+
this.setFlag(CPU.V, ((this.a ^ bin) & (~this.fetched ^ bin) & 0x80) !== 0);
|
|
1013
|
+
this.setFlag(CPU.N, (bin & 0x80) !== 0);
|
|
1014
|
+
this.setFlag(CPU.C, (bin & 0xFFFF) < 0x100);
|
|
1015
|
+
this.a = result;
|
|
1016
|
+
}
|
|
1017
|
+
else {
|
|
1018
|
+
const value = this.fetched ^ 0x00FF;
|
|
1019
|
+
this.temp = this.a + value + this.getFlag(CPU.C);
|
|
1020
|
+
this.setFlag(CPU.C, (this.temp & 0xFF00) != 0);
|
|
1021
|
+
this.setFlag(CPU.Z, (this.temp & 0x00FF) == 0);
|
|
1022
|
+
this.setFlag(CPU.V, ((this.temp ^ this.a) & (this.temp ^ value) & 0x0080) != 0);
|
|
1023
|
+
this.setFlag(CPU.N, (this.temp & 0x0080) != 0);
|
|
1024
|
+
this.a = this.temp & 0x00FF;
|
|
1025
|
+
}
|
|
969
1026
|
return 1;
|
|
970
1027
|
}
|
|
971
1028
|
SEC() {
|