@tmustier/pi-nes 0.2.12 → 0.2.14
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/extensions/nes/index.ts +11 -12
- package/extensions/nes/native/nes-core/index.node +0 -0
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/mapper.rs +2 -2
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/ppu.rs +7 -3
- package/extensions/nes/native/nes-core/vendor/nes_rust/src/rom.rs +9 -3
- package/extensions/nes/nes-component.ts +4 -0
- package/extensions/nes/renderer.ts +13 -6
- package/package.json +1 -1
package/extensions/nes/index.ts
CHANGED
|
@@ -289,18 +289,16 @@ async function attachSession(
|
|
|
289
289
|
): Promise<boolean> {
|
|
290
290
|
let shouldStop = false;
|
|
291
291
|
try {
|
|
292
|
-
const
|
|
293
|
-
const overlayOptions =
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
303
|
-
: undefined;
|
|
292
|
+
const isImageRenderer = config.renderer === "image";
|
|
293
|
+
const overlayOptions = {
|
|
294
|
+
overlay: true,
|
|
295
|
+
overlayOptions: {
|
|
296
|
+
width: isImageRenderer ? "90%" : "85%",
|
|
297
|
+
maxHeight: "90%",
|
|
298
|
+
anchor: "center",
|
|
299
|
+
margin: { top: 1 },
|
|
300
|
+
},
|
|
301
|
+
};
|
|
304
302
|
|
|
305
303
|
const renderIntervalMs = config.renderer === "image"
|
|
306
304
|
? config.imageQuality === "high"
|
|
@@ -323,6 +321,7 @@ async function attachSession(
|
|
|
323
321
|
config.keybindings,
|
|
324
322
|
config.renderer,
|
|
325
323
|
config.pixelScale,
|
|
324
|
+
isImageRenderer,
|
|
326
325
|
debug,
|
|
327
326
|
() => session.getStats(),
|
|
328
327
|
"native",
|
|
Binary file
|
|
@@ -118,14 +118,14 @@ impl Mapper for MMC1Mapper {
|
|
|
118
118
|
fn map(&self, address: u32) -> u32 {
|
|
119
119
|
let bank: u32;
|
|
120
120
|
let mut offset = address & 0x3FFF;
|
|
121
|
-
let bank_num = self.prg_bank_register.load() as u32 &
|
|
121
|
+
let bank_num = self.prg_bank_register.load() as u32 & 0x1F;
|
|
122
122
|
|
|
123
123
|
match self.control_register.load_bits(2, 2) {
|
|
124
124
|
0 | 1 => {
|
|
125
125
|
// switch 32KB at 0x8000, ignoring low bit of bank number
|
|
126
126
|
// TODO: Fix me
|
|
127
127
|
offset = offset | (address & 0x4000);
|
|
128
|
-
bank = bank_num &
|
|
128
|
+
bank = bank_num & 0x1E;
|
|
129
129
|
},
|
|
130
130
|
2 => {
|
|
131
131
|
// fix first bank at 0x8000 and switch 16KB bank at 0xC000
|
|
@@ -1365,14 +1365,18 @@ impl Sprite {
|
|
|
1365
1365
|
}
|
|
1366
1366
|
|
|
1367
1367
|
fn on(&self, y: u8, height: u8) -> bool {
|
|
1368
|
-
|
|
1368
|
+
let sprite_y = self.get_y() as u16 + 1;
|
|
1369
|
+
let y = y as u16;
|
|
1370
|
+
y >= sprite_y && y < sprite_y + height as u16
|
|
1369
1371
|
}
|
|
1370
1372
|
|
|
1371
1373
|
fn get_y_in_sprite(&self, y: u8, height: u8) -> u8 {
|
|
1372
1374
|
// Assumes self.on(y, height) is true
|
|
1375
|
+
let sprite_y = self.get_y() as u16 + 1;
|
|
1376
|
+
let delta = (y as u16 - sprite_y) as u8;
|
|
1373
1377
|
match self.vertical_flip() {
|
|
1374
|
-
true => height - 1 -
|
|
1375
|
-
false =>
|
|
1378
|
+
true => height - 1 - delta,
|
|
1379
|
+
false => delta
|
|
1376
1380
|
}
|
|
1377
1381
|
}
|
|
1378
1382
|
}
|
|
@@ -20,9 +20,15 @@ impl Rom {
|
|
|
20
20
|
pub fn new(data: Vec<u8>) -> Self {
|
|
21
21
|
let header = RomHeader::new(data[0..HEADER_SIZE].to_vec());
|
|
22
22
|
let mapper = MapperFactory::create(&header);
|
|
23
|
+
let data_start = HEADER_SIZE + if header.has_trainer() { 512 } else { 0 };
|
|
24
|
+
let rom_data = if data.len() > data_start {
|
|
25
|
+
data[data_start..].to_vec()
|
|
26
|
+
} else {
|
|
27
|
+
Vec::new()
|
|
28
|
+
};
|
|
23
29
|
Rom {
|
|
24
30
|
header: header,
|
|
25
|
-
memory: Memory::new(
|
|
31
|
+
memory: Memory::new(rom_data),
|
|
26
32
|
mapper: mapper
|
|
27
33
|
}
|
|
28
34
|
}
|
|
@@ -180,8 +186,8 @@ impl RomHeader {
|
|
|
180
186
|
self.extract_bits(self.control_byte1(), 1, 1) == 1
|
|
181
187
|
}
|
|
182
188
|
|
|
183
|
-
fn
|
|
184
|
-
self.extract_bits(self.control_byte1(), 2, 1)
|
|
189
|
+
pub fn has_trainer(&self) -> bool {
|
|
190
|
+
self.extract_bits(self.control_byte1(), 2, 1) == 1
|
|
185
191
|
}
|
|
186
192
|
|
|
187
193
|
fn four_screen_mirroring(&self) -> bool {
|
|
@@ -84,6 +84,7 @@ export class NesOverlayComponent implements Component {
|
|
|
84
84
|
private readonly imageRenderer = new NesImageRenderer();
|
|
85
85
|
private readonly rendererMode: RendererMode;
|
|
86
86
|
private readonly pixelScale: number;
|
|
87
|
+
private readonly windowed: boolean;
|
|
87
88
|
private readonly debug: boolean;
|
|
88
89
|
private readonly statsProvider?: () => NesSessionStats;
|
|
89
90
|
private readonly debugLabel?: string;
|
|
@@ -97,6 +98,7 @@ export class NesOverlayComponent implements Component {
|
|
|
97
98
|
inputMapping: InputMapping = DEFAULT_INPUT_MAPPING,
|
|
98
99
|
rendererMode: RendererMode = "image",
|
|
99
100
|
pixelScale = 1,
|
|
101
|
+
windowed = false,
|
|
100
102
|
debug = false,
|
|
101
103
|
statsProvider?: () => NesSessionStats,
|
|
102
104
|
debugLabel?: string,
|
|
@@ -104,6 +106,7 @@ export class NesOverlayComponent implements Component {
|
|
|
104
106
|
this.inputMapping = inputMapping;
|
|
105
107
|
this.rendererMode = rendererMode;
|
|
106
108
|
this.pixelScale = pixelScale;
|
|
109
|
+
this.windowed = windowed;
|
|
107
110
|
this.debug = debug;
|
|
108
111
|
this.statsProvider = statsProvider;
|
|
109
112
|
this.debugLabel = debugLabel;
|
|
@@ -154,6 +157,7 @@ export class NesOverlayComponent implements Component {
|
|
|
154
157
|
width,
|
|
155
158
|
footerRows,
|
|
156
159
|
this.pixelScale,
|
|
160
|
+
!this.windowed,
|
|
157
161
|
);
|
|
158
162
|
if (debugLine) {
|
|
159
163
|
lines.push(truncateToWidth(debugLine, width));
|
|
@@ -68,17 +68,18 @@ export class NesImageRenderer {
|
|
|
68
68
|
widthCells: number,
|
|
69
69
|
footerRows = 1,
|
|
70
70
|
pixelScale = 1,
|
|
71
|
+
padToHeight = true,
|
|
71
72
|
): string[] {
|
|
72
73
|
const caps = getCapabilities();
|
|
73
74
|
if (caps.images === "kitty") {
|
|
74
|
-
const shared = this.renderKittySharedMemory(frameBuffer, tui, widthCells, footerRows, pixelScale);
|
|
75
|
+
const shared = this.renderKittySharedMemory(frameBuffer, tui, widthCells, footerRows, pixelScale, padToHeight);
|
|
75
76
|
if (shared) {
|
|
76
77
|
return shared;
|
|
77
78
|
}
|
|
78
|
-
return this.renderKittyRaw(frameBuffer, tui, widthCells, footerRows, pixelScale);
|
|
79
|
+
return this.renderKittyRaw(frameBuffer, tui, widthCells, footerRows, pixelScale, padToHeight);
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
return this.renderPng(frameBuffer, tui, widthCells, footerRows, pixelScale);
|
|
82
|
+
return this.renderPng(frameBuffer, tui, widthCells, footerRows, pixelScale, padToHeight);
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
dispose(tui: TUI): void {
|
|
@@ -121,6 +122,7 @@ export class NesImageRenderer {
|
|
|
121
122
|
widthCells: number,
|
|
122
123
|
footerRows: number,
|
|
123
124
|
pixelScale: number,
|
|
125
|
+
padToHeight: boolean,
|
|
124
126
|
): string[] | null {
|
|
125
127
|
const module = this.getSharedMemoryModule();
|
|
126
128
|
if (!module) {
|
|
@@ -155,7 +157,8 @@ export class NesImageRenderer {
|
|
|
155
157
|
const marker = `\x1b_pi:nes:${this.rawVersion}\x07`;
|
|
156
158
|
lines.push(`${moveUp}${sequence}${marker}`);
|
|
157
159
|
|
|
158
|
-
|
|
160
|
+
const padded = applyHorizontalPadding(lines, padLeft);
|
|
161
|
+
return padToHeight ? centerLines(padded, availableRows) : padded;
|
|
159
162
|
}
|
|
160
163
|
|
|
161
164
|
private renderKittyRaw(
|
|
@@ -164,6 +167,7 @@ export class NesImageRenderer {
|
|
|
164
167
|
widthCells: number,
|
|
165
168
|
footerRows: number,
|
|
166
169
|
pixelScale: number,
|
|
170
|
+
padToHeight: boolean,
|
|
167
171
|
): string[] {
|
|
168
172
|
const layout = computeKittyLayout(tui, widthCells, footerRows, pixelScale);
|
|
169
173
|
const { availableRows, columns, rows, padLeft } = layout;
|
|
@@ -199,7 +203,8 @@ export class NesImageRenderer {
|
|
|
199
203
|
const marker = `\x1b_pi:nes:${this.rawVersion}\x07`;
|
|
200
204
|
lines.push(`${moveUp}${cached.sequence}${marker}`);
|
|
201
205
|
|
|
202
|
-
|
|
206
|
+
const padded = applyHorizontalPadding(lines, padLeft);
|
|
207
|
+
return padToHeight ? centerLines(padded, availableRows) : padded;
|
|
203
208
|
}
|
|
204
209
|
|
|
205
210
|
private renderPng(
|
|
@@ -208,6 +213,7 @@ export class NesImageRenderer {
|
|
|
208
213
|
widthCells: number,
|
|
209
214
|
footerRows: number,
|
|
210
215
|
pixelScale: number,
|
|
216
|
+
padToHeight: boolean,
|
|
211
217
|
): string[] {
|
|
212
218
|
const layout = computePngLayout(tui, widthCells, footerRows, pixelScale);
|
|
213
219
|
const { availableRows, maxWidthCells, padLeft, targetHeight, targetWidth } = layout;
|
|
@@ -244,7 +250,8 @@ export class NesImageRenderer {
|
|
|
244
250
|
{ widthPx: this.cachedImage.width, heightPx: this.cachedImage.height },
|
|
245
251
|
);
|
|
246
252
|
|
|
247
|
-
|
|
253
|
+
const padded = applyHorizontalPadding(image.render(widthCells), padLeft);
|
|
254
|
+
return padToHeight ? centerLines(padded, availableRows) : padded;
|
|
248
255
|
}
|
|
249
256
|
|
|
250
257
|
private fillRawBuffer(frameBuffer: FrameBuffer): void {
|