Screen modes working

This commit is contained in:
Iván Izaguirre
2026-02-08 18:45:15 +01:00
parent 635cce512d
commit f14b2c4b34
6 changed files with 42 additions and 28 deletions
+3 -3
View File
@@ -16,7 +16,7 @@ A modern React + TypeScript frontend for the izapple2 Apple II emulator, compile
- Pause/Resume
- Reset
- Speed toggle
- Screen mode selection (NTSC, Plain, Green, Amber)
- Screen mode selection (NTSC, Plain, Green)
- Screenshot download
- ✅ Real-time status display (CPU frequency, disk status)
- ✅ Responsive design
@@ -113,7 +113,7 @@ The production files will be in `dist/`.
- **Reset**: Reboot the Apple II
- **Toggle Speed**: Switch between normal and fast speed
- **Screenshot**: Download current screen as PNG
- **Screen Mode**: Select display mode (NTSC, Plain, Green, Amber)
- **Screen Mode**: Select display mode (NTSC, Plain, Green)
**Status Bar** (bottom):
- Shows CPU frequency in MHz
@@ -298,7 +298,7 @@ interface EmulatorAPI {
// Configuration
toggleSpeed(): void;
setScreenMode(mode: 'ntsc' | 'plain' | 'green' | 'amber'): void;
setScreenMode(mode: 'ntsc' | 'plain' | 'green'): void;
// Screenshot
screenshot(): void;
-8
View File
@@ -77,11 +77,6 @@ func setupAPI(a *izapple2.Apple2, game *Game) {
})
// Configuration
api["toggleSpeed"] = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
a.SendCommand(izapple2.CommandToggleSpeed)
return nil
})
api["setScreenMode"] = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
if len(args) < 1 {
return nil
@@ -94,9 +89,6 @@ func setupAPI(a *izapple2.Apple2, game *Game) {
game.screenMode = screen.ScreenModePlain
case "green":
game.screenMode = screen.ScreenModeGreen
case "amber":
// Amber not available, use green as fallback
game.screenMode = screen.ScreenModeGreen
}
return nil
})
+12
View File
@@ -105,8 +105,15 @@ func (g *Game) putKey(key ebiten.Key) {
}
var globalGame *Game
var initialized bool
func main() {
if initialized {
fmt.Println("main() called again - ignoring to prevent duplicate Game instances")
return
}
initialized = true
a, err := izapple2.CreateConfiguredApple()
if err != nil {
fmt.Printf("Error: %v\n", err)
@@ -118,6 +125,11 @@ func main() {
}
func ebitenRun(a *izapple2.Apple2) {
if globalGame != nil {
fmt.Println("ebitenRun() called again - ignoring to prevent duplicate Game instances")
return
}
game := &Game{
a: a,
speaker: newWasmSpeaker(),
+1 -1
View File
@@ -32,7 +32,7 @@ export interface DiskInfo {
loaded: boolean;
}
export type ScreenMode = 'ntsc' | 'plain' | 'green' | 'amber';
export type ScreenMode = 'ntsc' | 'plain' | 'green';
// Extend Window interface for WASM API
declare global {
+25 -1
View File
@@ -1,7 +1,25 @@
// WASM loader - initializes the Go WebAssembly module
let wasmLoading = false;
let wasmLoaded = false;
let loadPromise: Promise<void> | null = null;
export async function loadWASM(): Promise<void> {
return new Promise((resolve, reject) => {
// If already loaded, return immediately
if (wasmLoaded) {
console.log('WASM already loaded, skipping');
return Promise.resolve();
}
// If currently loading, return the existing promise
if (wasmLoading && loadPromise) {
console.log('WASM loading in progress, waiting...');
return loadPromise;
}
// Start loading
wasmLoading = true;
loadPromise = new Promise((resolve, reject) => {
// Load wasm_exec.js if not already loaded
if (!window.Go) {
const script = document.createElement('script');
@@ -13,6 +31,8 @@ export async function loadWASM(): Promise<void> {
initWASM(resolve, reject);
}
});
return loadPromise;
}
async function initWASM(
@@ -33,13 +53,17 @@ async function initWASM(
// Wait a bit for the emulator to initialize and export functions
setTimeout(() => {
if (window.wasmAPI) {
wasmLoaded = true;
wasmLoading = false;
resolve();
} else {
wasmLoading = false;
console.error('WASM API not found on window object');
reject(new Error('WASM API not initialized'));
}
}, 1000);
} catch (error) {
wasmLoading = false;
console.error('Failed to initialize WASM:', error);
reject(error as Error);
}
@@ -12,7 +12,6 @@ import {
PlayArrow,
Pause,
Refresh,
Speed,
CameraAlt,
} from '@mui/icons-material';
import { emulator } from '../api/emulator';
@@ -32,9 +31,7 @@ export function ControlPanel({ paused }: ControlPanelProps) {
};
const handleReset = () => {
if (window.confirm('Reset the emulator? This will clear memory.')) {
emulator.reset();
}
emulator.reset();
};
const handleScreenModeChange = (event: SelectChangeEvent) => {
@@ -45,10 +42,6 @@ export function ControlPanel({ paused }: ControlPanelProps) {
emulator.screenshot();
};
const handleSpeedToggle = () => {
emulator.toggleSpeed();
};
return (
<Box
sx={{
@@ -73,12 +66,6 @@ export function ControlPanel({ paused }: ControlPanelProps) {
</IconButton>
</Tooltip>
<Tooltip title="Toggle Speed (Full/NTSC)">
<IconButton onClick={handleSpeedToggle}>
<Speed />
</IconButton>
</Tooltip>
<Tooltip title="Screenshot">
<IconButton onClick={handleScreenshot}>
<CameraAlt />
@@ -95,7 +82,6 @@ export function ControlPanel({ paused }: ControlPanelProps) {
<MenuItem value="ntsc">NTSC</MenuItem>
<MenuItem value="plain">Plain</MenuItem>
<MenuItem value="green">Green</MenuItem>
<MenuItem value="amber">Amber</MenuItem>
</Select>
</FormControl>
</Box>