-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathvite.config.js
More file actions
174 lines (149 loc) · 5.88 KB
/
Copy pathvite.config.js
File metadata and controls
174 lines (149 loc) · 5.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// vite.config.js — Miracle build configuration
import path from "path";
import { existsSync, mkdirSync, readdirSync, writeFileSync } from "fs";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const z80Dir = path.join(__dirname, "src/z80");
// ---------------------------------------------------------------------------
// Opcode generation config
//
// Each entry maps a transform marker key to [datFile, register] where
// register is 'ix', 'iy', or null (for non-DDFD opcode sets).
// ---------------------------------------------------------------------------
const OPCODE_CONFIGS = [
["opcodes_base.dat", "opcodes_base.dat", null],
["opcodes_ed.dat", "opcodes_ed.dat", null],
["opcodes_cb.dat", "opcodes_cb.dat", null],
["opcodes_ddfd.dat ix", "opcodes_ddfd.dat", "ix"],
["opcodes_ddfd.dat iy", "opcodes_ddfd.dat", "iy"],
["opcodes_ddfdcb.dat", "opcodes_ddfdcb.dat", null],
];
// Disassembler: maps marker key to dat filename.
const DIS_CONFIGS = [
["opcodes_base.dat", "opcodes_base.dat"],
["opcodes_cb.dat", "opcodes_cb.dat"],
["opcodes_ed.dat", "opcodes_ed.dat"],
["opcodes_ddfd.dat", "opcodes_ddfd.dat"],
["opcodes_ddfdcb.dat", "opcodes_ddfdcb.dat"],
];
// Files to watch in dev mode.
const Z80_WATCH = [
...OPCODE_CONFIGS.map(([, dat]) => path.join(z80Dir, dat)),
...DIS_CONFIGS.map(([, dat]) => path.join(z80Dir, dat)),
// Generator modules themselves are NOT listed — ESM cache means they
// can't be hot-reloaded without a full process restart.
].filter((v, i, a) => a.indexOf(v) === i); // deduplicate
// ---------------------------------------------------------------------------
// Lazy-load the generators (avoids import-time side effects)
// ---------------------------------------------------------------------------
let _generators = null;
async function getGenerators() {
if (!_generators) {
const [z80mod, dismod] = await Promise.all([
import("./src/z80/z80_generator.mjs"),
import("./src/z80/disass.mjs"),
]);
_generators = { z80gen: z80mod.generate, disgen: dismod.generate };
}
return _generators;
}
// ---------------------------------------------------------------------------
// Z80 code generation
// ---------------------------------------------------------------------------
// Generated snippets, keyed by marker text. Populated in buildStart,
// consumed by the transform hook.
const generatedSnippets = new Map(); // opcode snippets
const generatedDisSnippets = new Map(); // disassembler snippets
async function generateZ80() {
const { z80gen, disgen } = await getGenerators();
// Opcode snippets: z80gen now returns pure JS directly.
generatedSnippets.clear();
for (const [markerKey, dat, register] of OPCODE_CONFIGS) {
generatedSnippets.set(markerKey, z80gen(path.join(z80Dir, dat), register));
}
// Disassembler snippets: disgen returns pure JS switch cases.
generatedDisSnippets.clear();
for (const [markerKey, dat] of DIS_CONFIGS) {
generatedDisSnippets.set(markerKey, disgen(path.join(z80Dir, dat)));
}
}
function z80CodegenPlugin() {
const z80OpsId = path.join(__dirname, "src/z80/z80_ops.js");
const z80DisId = path.join(__dirname, "src/z80/z80_dis.js");
return {
name: "z80-codegen",
async buildStart() {
await generateZ80();
for (const f of Z80_WATCH) this.addWatchFile(f);
},
async handleHotUpdate({ file, server }) {
if (!Z80_WATCH.includes(file)) return;
await generateZ80();
// Invalidate both generated modules so Vite pushes HMR updates.
const mods = [z80OpsId, z80DisId]
.map((id) => server.moduleGraph.getModuleById(id))
.filter(Boolean);
for (const mod of mods) server.moduleGraph.invalidateModule(mod);
return mods.length > 0 ? mods : undefined;
},
transform(code, id) {
// Replace /* @z80-generate <key> */ markers in z80_ops.js.
if (id === z80OpsId && generatedSnippets.size > 0) {
let result = code;
for (const [markerKey, snippet] of generatedSnippets) {
const marker = `/* @z80-generate ${markerKey} */`;
if (result.includes(marker))
result = result.replaceAll(marker, snippet);
}
return result !== code ? { code: result, map: null } : null;
}
// Replace /* @z80-dis-generate <key> */ markers in z80_dis.js.
if (id === z80DisId && generatedDisSnippets.size > 0) {
let result = code;
for (const [markerKey, snippet] of generatedDisSnippets) {
const marker = `/* @z80-dis-generate ${markerKey} */`;
if (result.includes(marker))
result = result.replaceAll(marker, snippet);
}
return result !== code ? { code: result, map: null } : null;
}
return null;
},
};
}
// ---------------------------------------------------------------------------
// ROM list generation
// ---------------------------------------------------------------------------
function generateRoms() {
const romsDir = path.join(__dirname, "public/roms");
const roms = existsSync(romsDir)
? readdirSync(romsDir)
.filter((f) => !f.startsWith("."))
.sort()
: [];
const content =
`export const RomList = [\n` +
roms.map((r) => ` ${JSON.stringify(r)},\n`).join("") +
`];\n`;
writeFileSync(path.join(__dirname, "src/roms.js"), content);
}
function romsPlugin() {
const romsDir = path.join(__dirname, "public/roms");
return {
name: "roms-codegen",
buildStart() {
mkdirSync(romsDir, { recursive: true });
generateRoms();
this.addWatchFile(romsDir);
},
handleHotUpdate({ file }) {
if (file.startsWith(romsDir)) generateRoms();
},
};
}
// ---------------------------------------------------------------------------
// Vite config
// ---------------------------------------------------------------------------
export default {
plugins: [z80CodegenPlugin(), romsPlugin()],
};