@gba-kit/arm-emulator 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Bruno Macabeus
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # @gba-kit/arm-emulator
2
+
3
+ Pure ARM7TDMI CPU emulator supporting both Thumb (16-bit) and ARM (32-bit) instruction sets.
4
+
5
+ > Note: It doesn't include any GBA-specific logic. The CPU accepts a `MemoryBus` interface and an optional SWI handler callback, so it can be embedded in any ARM7TDMI-based system.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @gba-kit/arm-emulator
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ### ARM CPU
16
+
17
+ ```typescript
18
+ import { GbaMemory } from '@gba-kit/arm-emulator';
19
+ import { ArmCpu } from '@gba-kit/arm-emulator/arm-cpu';
20
+
21
+ const memory = new GbaMemory();
22
+ const cpu = new ArmCpu(memory, {
23
+ swiHandler: (cpu, swiNumber) => {
24
+ // Platform-specific SWI handling
25
+ },
26
+ });
27
+
28
+ cpu.registers[15] = 0x08000000; // set PC
29
+ cpu.step(); // execute one instruction
30
+ ```
31
+
32
+ ### Disassembly
33
+
34
+ ```typescript
35
+ import { disassembleArm, disassembleThumb } from '@gba-kit/arm-emulator/disassembler';
36
+
37
+ const mnemonic = disassembleThumb(0x4770, 0x08000000);
38
+ // "bx lr"
39
+ ```
40
+
41
+ ## Exports
42
+
43
+ ### Main entry (`@gba-kit/arm-emulator`)
44
+
45
+ | Export | Type | Description |
46
+ | --------------------------------- | ----- | ------------------------------- |
47
+ | `GbaMemory` | class | Memory bus with region dispatch |
48
+ | `PC`, `LR`, `SP`, `SENTINEL_ADDR` | const | Register index constants |
49
+
50
+ Types: `CpsrFlags`, `DebugAction`, `DebugHooks`, `ExecutionResult`, `ExternalCall`, `MemoryBus`, `MemoryWrite`, `CpuSnapshot`
51
+
52
+ ### Subpath exports
53
+
54
+ | Subpath | Description |
55
+ | ------------------------------------ | -------------------------------------------------------------------- |
56
+ | `@gba-kit/arm-emulator/arm-cpu` | `ArmCpu` class — full ARM7TDMI with mode switching, banked registers |
57
+ | `@gba-kit/arm-emulator/disassembler` | `disassembleArm()`, `disassembleThumb()` functions |
58
+ | `@gba-kit/arm-emulator/cpu-snapshot` | `CpuSnapshot` interface for serializable CPU state |
59
+
60
+ ## Testing
61
+
62
+ ```bash
63
+ pnpm test
64
+ ```
@@ -0,0 +1,141 @@
1
+ /**
2
+ * ARM7TDMI Full CPU Emulator
3
+ *
4
+ * Supports both ARM (32-bit) and Thumb (16-bit) instruction sets,
5
+ * CPU modes with banked registers, and HLE BIOS calls via SWI.
6
+ *
7
+ * This class is the full-featured CPU for the GBA emulator.
8
+ *
9
+ * References:
10
+ * - ARM7TDMI TRM (DDI0029G): https://ww1.microchip.com/downloads/en/DeviceDoc/DDI0029G_7TDMI_R3_trm.pdf
11
+ * - GBATEK: http://problemkaputt.de/gbatek.htm
12
+ */
13
+ import type { CpuSnapshot } from './cpu-snapshot.js';
14
+ import type { CpsrFlags, DebugHooks, ExecutionResult, MemoryBus } from './types.js';
15
+ /** CPU mode codes (bits 4-0 of CPSR) */
16
+ export declare const MODE_USR = 16;
17
+ export declare const MODE_FIQ = 17;
18
+ export declare const MODE_IRQ = 18;
19
+ export declare const MODE_SVC = 19;
20
+ export declare const MODE_ABT = 23;
21
+ export declare const MODE_UND = 27;
22
+ export declare const MODE_SYS = 31;
23
+ /**
24
+ * Callback for Software Interrupt (SWI) instructions.
25
+ * Platform-specific: on GBA, the SWI number selects a BIOS function.
26
+ * If not provided, SWI instructions are silently ignored.
27
+ */
28
+ export type SwiHandler = (cpu: ArmCpu, swiNumber: number) => void;
29
+ /**
30
+ * Full ARM7TDMI CPU supporting ARM and Thumb instruction sets,
31
+ * with CPU modes and banked registers.
32
+ */
33
+ export declare class ArmCpu {
34
+ #private;
35
+ /** General-purpose registers r0-r15 (current view, mode-dependent) */
36
+ readonly registers: Uint32Array<ArrayBuffer>;
37
+ /**
38
+ * Current Program Status Register (full 32-bit).
39
+ *
40
+ * Bit layout:
41
+ * - 31: N (Negative)
42
+ * - 30: Z (Zero)
43
+ * - 29: C (Carry)
44
+ * - 28: V (Overflow)
45
+ * - 7: I (IRQ disable)
46
+ * - 6: F (FIQ disable)
47
+ * - 5: T (Thumb state: 0=ARM, 1=Thumb)
48
+ * - 4-0: Mode (0x10=USR, 0x11=FIQ, 0x12=IRQ, 0x13=SVC, 0x17=ABT, 0x1B=UND, 0x1F=SYS)
49
+ */
50
+ cpsr: number;
51
+ /** Memory bus */
52
+ readonly memory: MemoryBus;
53
+ constructor(memory: MemoryBus, options?: {
54
+ hooks?: DebugHooks;
55
+ swiHandler?: SwiHandler;
56
+ });
57
+ /**
58
+ * Set the banked SP for a given mode without switching modes.
59
+ * Used to initialize stack pointers (e.g. GBA BIOS sets IRQ/SVC stacks).
60
+ */
61
+ setBankedSP(mode: number, value: number): void;
62
+ /** Get condition flags from CPSR as a CpsrFlags object */
63
+ get flags(): CpsrFlags;
64
+ /** Get Negative flag */
65
+ getN(): boolean;
66
+ /** Get Zero flag */
67
+ getZ(): boolean;
68
+ /** Get Carry flag */
69
+ getC(): boolean;
70
+ /** Get Overflow flag */
71
+ getV(): boolean;
72
+ /** Get Thumb state bit */
73
+ getT(): boolean;
74
+ /** Get current CPU mode */
75
+ getMode(): number;
76
+ /** Set Negative flag */
77
+ setN(val: boolean): void;
78
+ /** Set Zero flag */
79
+ setZ(val: boolean): void;
80
+ /** Set Carry flag */
81
+ setC(val: boolean): void;
82
+ /** Set Overflow flag */
83
+ setV(val: boolean): void;
84
+ /** Set Thumb state bit */
85
+ setT(val: boolean): void;
86
+ /** Set all four condition flags at once from an AluResult */
87
+ setFlags(n: boolean, z: boolean, c: boolean, v: boolean): void;
88
+ /** Set NZ flags from a result value, leave C and V unchanged */
89
+ setNZ(result: number): void;
90
+ /** Get the SPSR for the current mode. Returns 0 for USR/SYS (no SPSR). */
91
+ getSPSR(): number;
92
+ /** Set the SPSR for the current mode. No-op for USR/SYS. */
93
+ setSPSR(value: number): void;
94
+ /**
95
+ * Switch CPU mode. Saves banked registers from the old mode
96
+ * and restores them for the new mode.
97
+ */
98
+ switchMode(newMode: number): void;
99
+ /** Attach or detach debug hooks */
100
+ setDebugHooks(hooks: DebugHooks | undefined): void;
101
+ /** Register a stub for an external function call */
102
+ registerStub(symbolName: string): number;
103
+ /** Serialize to a plain snapshot. */
104
+ serialize(): CpuSnapshot;
105
+ /** Restore from a snapshot. */
106
+ deserialize(snap: CpuSnapshot): void;
107
+ /** Reset CPU state for a new execution */
108
+ resetState(): void;
109
+ /** Check if IRQs are disabled (CPSR I bit set) */
110
+ irqDisabled(): boolean;
111
+ /**
112
+ * Enter IRQ exception.
113
+ *
114
+ * Standard ARM7TDMI exception entry:
115
+ * 1. Save CPSR to SPSR_irq
116
+ * 2. Switch to IRQ mode
117
+ * 3. Set LR_irq to return address (next instruction + 4)
118
+ * 4. Set I bit (disable further IRQs)
119
+ * 5. Clear T bit (enter ARM state)
120
+ * 6. Set PC to IRQ vector (0x00000018)
121
+ *
122
+ * The BIOS stub at 0x18 (installed by Gba.#installBiosStub) handles:
123
+ * - Saving registers to IRQ stack
124
+ * - Calling the user's handler from [0x03007FFC]
125
+ * - Restoring registers and returning from IRQ
126
+ *
127
+ * The BIOS stub at 0x80 handles IE/IF acknowledgment and BIOS IF mirror
128
+ * update before calling the user handler.
129
+ */
130
+ enterIrq(): void;
131
+ /** Enter Undefined Instruction exception */
132
+ enterUnd(instrAddr: number): void;
133
+ /**
134
+ * Execute one instruction (ARM or Thumb based on T bit).
135
+ * Returns false if halted.
136
+ */
137
+ step(): boolean;
138
+ /** Run until halt or instruction limit */
139
+ run(maxInstructions: number): ExecutionResult;
140
+ }
141
+ //# sourceMappingURL=arm-cpu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arm-cpu.d.ts","sourceRoot":"","sources":["../src/arm-cpu.ts"],"names":[],"mappings":"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"}