Skip to content

Commit d30485a

Browse files
committed
feat: various fixes
1 parent 011acc0 commit d30485a

File tree

7 files changed

+187
-40
lines changed

7 files changed

+187
-40
lines changed

godot-6502/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,11 @@ impl Emulator6502 {
327327
self.frequency = frequency
328328
}
329329

330+
#[func]
331+
pub fn get_frequency(&self) -> i32 {
332+
self.frequency
333+
}
334+
330335
#[func]
331336
pub fn get_line_number(&self, pc: u16) -> i32 {
332337
let line = self.cpu().get_line_number(pc);

godot/scenes/Main.tscn

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,16 @@ zoom_sensitivity = 1.0
7979
max_zoom = 100.0
8080

8181
[node name="Planet" parent="." instance=ExtResource("4_hrnxs")]
82-
transform = Transform3D(-0.84147, 0, 0.540303, 0, 1, 0, -0.540303, 0, -0.84147, 0, 0, 0)
82+
transform = Transform3D(-0.986832, 0, 0.16175, 0, 1, 0, -0.16175, 0, -0.986832, 0, 0, 0)
8383
physics_material_override = SubResource("PhysicsMaterial_q8u5g")
84-
constant_angular_velocity = Vector3(0, 0.005, 0)
85-
regenerate_in_editor = null
84+
regenerate_in_editor = false
8685
radius = 5000.0
8786
micro_octaves = 4
8887
micro_lacunarity = 10.0
8988
micro_gain = 3.0
9089
micro_strength = 0.05
9190
flatten_deadband = 0.2
9291
range_anisotropy = 0.3
93-
ice_cap_latitude_start = 0.95
94-
ice_cap_latitude_full = 0.96
95-
ice_cap_height_bias = 0.35
9692
smooth_lambda = 0.0
9793
gravitational_pull = 5e+07
9894
atmosphere_height_scale = 1.0

godot/scenes/Planet/Planet.gd

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,12 @@ func _build_planet_triangles(segs: int, uvs: Array[Vector2]) -> void:
313313
# Create and apply lunar material
314314
var material = create_planet_material()
315315

316-
mesh_instance.mesh = mesh
317-
mesh_instance.material_override = material
316+
# Ensure mesh_instance is valid before assigning
317+
if mesh_instance != null:
318+
mesh_instance.mesh = mesh
319+
mesh_instance.material_override = material
320+
else:
321+
push_error("mesh_instance is null in _build_planet_triangles")
318322

319323
func _add_triangle(i0: int, i1: int, i2: int, uvs: Array[Vector2]) -> void:
320324
# Add triangle with reduced function calls
@@ -557,18 +561,19 @@ func _physics_process(delta: float) -> void:
557561
_update_atmosphere_params()
558562

559563
# Apply gravitational pull only to bodies that aren't too far
560-
for body in get_tree().get_nodes_in_group("affected_by_gravity"):
561-
if body is RigidBody3D:
562-
if not is_instance_valid(body) or body.freeze:
563-
continue
564-
565-
var direction = global_position - body.global_position
566-
var distance = direction.length()
564+
if get_tree() != null:
565+
for body in get_tree().get_nodes_in_group("affected_by_gravity"):
566+
if body is RigidBody3D:
567+
if not is_instance_valid(body) or body.freeze:
568+
continue
569+
570+
var direction = global_position - body.global_position
571+
var distance = direction.length()
572+
573+
var force_magnitude = (gravitational_pull * body.mass) / (distance * distance)
574+
var force = direction.normalized() * force_magnitude
567575

568-
var force_magnitude = (gravitational_pull * body.mass) / (distance * distance)
569-
var force = direction.normalized() * force_magnitude
570-
571-
body.apply_central_force(force)
576+
body.apply_central_force(force)
572577

573578
# Update local scatter near camera
574579
if enable_scatter:
@@ -611,15 +616,16 @@ func _get_directional_light() -> DirectionalLight3D:
611616
if l is DirectionalLight3D:
612617
return l
613618
# Fallback: search the tree (first one)
614-
for node in get_tree().get_nodes_in_group(""):
615-
# no dedicated group; skip
616-
pass
617-
# Broad fallback: scan root children
618-
var root = get_tree().current_scene
619-
if root:
620-
for c in root.get_children():
621-
if c is DirectionalLight3D:
622-
return c
619+
if get_tree() != null:
620+
for node in get_tree().get_nodes_in_group(""):
621+
# no dedicated group; skip
622+
pass
623+
# Broad fallback: scan root children
624+
var root = get_tree().current_scene
625+
if root:
626+
for c in root.get_children():
627+
if c is DirectionalLight3D:
628+
return c
623629
return null
624630

625631
func _update_atmosphere_params() -> void:
@@ -642,10 +648,12 @@ func _update_atmosphere_params() -> void:
642648
var sun_dir_obj: Vector3 = (global_transform.basis.inverse() * sun_dir_world).normalized()
643649
atmosphere_material.set_shader_parameter("sun_dir_object", sun_dir_obj)
644650
# Camera position in planet object space
645-
var _cam := get_viewport().get_camera_3d()
646-
if _cam:
647-
var cam_obj: Vector3 = to_local(_cam.global_transform.origin)
648-
atmosphere_material.set_shader_parameter("camera_pos_object", cam_obj)
651+
var viewport = get_viewport()
652+
if viewport != null:
653+
var _cam := viewport.get_camera_3d()
654+
if _cam:
655+
var cam_obj: Vector3 = to_local(_cam.global_transform.origin)
656+
atmosphere_material.set_shader_parameter("camera_pos_object", cam_obj)
649657

650658
func _update_surface_atmo_params() -> void:
651659
var smat := mesh_instance.material_override as ShaderMaterial

godot/scenes/main.gd

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,39 @@ func _ready() -> void:
3333
ships = get_tree().get_nodes_in_group("ships")
3434
# If no ships exist, spawn one
3535
if ships.is_empty():
36-
spawn_ship()
36+
spawn_ship("
37+
THRUSTER_1 = $020C
38+
FIRE_UP = 8
39+
FIRE_DOWN = 4
40+
41+
.org $0600
42+
43+
main_loop:
44+
LDA #FIRE_UP
45+
STA THRUSTER_1
46+
JSR delay
47+
48+
LDA #0
49+
STA THRUSTER_1
50+
JSR delay
51+
52+
LDA #FIRE_DOWN
53+
STA THRUSTER_1
54+
JSR delay
55+
56+
LDA #0
57+
STA THRUSTER_1
58+
JSR delay
59+
60+
JMP main_loop
61+
62+
delay:
63+
LDX #5
64+
inner_loop:
65+
NOP
66+
DEX
67+
BNE inner_loop
68+
RTS")
3769

3870
WebHelper.expose_all(self)
3971

@@ -157,10 +189,23 @@ func js_step():
157189
return true
158190

159191
func js_getState():
192+
if active_ship == null:
193+
print("js_getState: active_ship is null")
194+
return null
195+
if active_ship.computer == null:
196+
print("js_getState: active_ship.computer is null")
197+
return null
198+
if active_ship.computer.emulator == null:
199+
print("js_getState: active_ship.computer.emulator is null")
200+
return null
201+
202+
var frequency = active_ship.computer.emulator.get_frequency()
203+
print("js_getState: frequency = ", frequency)
204+
160205
return {
161206
"code": active_ship.computer.program,
162207
"isPaused": active_ship.computer.pause,
163-
"frequency": active_ship.computer.emulator.frequency,
208+
"frequency": frequency,
164209
"shipIdx": ship_idx
165210
} as Dictionary
166211

web/src/lib/components/Asm6502Editor.svelte

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
2727
let editorContainer: HTMLDivElement;
2828
let view: EditorView | null = null;
29+
let isDirty = $state(false);
30+
let originalCode = $state('');
2931
3032
// 6502 opcodes and directives
3133
const OPCODES = [
@@ -357,6 +359,16 @@
357359
try {
358360
const helper = (window as any).WebHelper;
359361
if (!helper || !view) return;
362+
363+
// Don't highlight execution line if editor is dirty
364+
if (isDirty) {
365+
if (lastExecLine !== null) {
366+
lastExecLine = null;
367+
view.dispatch({ effects: setExecLineEffect.of(null) });
368+
}
369+
return;
370+
}
371+
360372
const line: number | null | undefined = await helper.getLineNumber();
361373
if (line !== lastExecLine && view) {
362374
lastExecLine = line ?? null;
@@ -395,6 +407,8 @@
395407
if (newValue !== value) {
396408
value = newValue;
397409
}
410+
// Update dirty state
411+
isDirty = newValue !== originalCode;
398412
}
399413
})
400414
];
@@ -416,6 +430,8 @@
416430
417431
onMount(() => {
418432
view = createEditor();
433+
originalCode = value;
434+
isDirty = false;
419435
420436
function updateLoop() {
421437
pollExecLine();
@@ -443,6 +459,9 @@
443459
insert: value
444460
}
445461
});
462+
// Update original code and reset dirty state when value changes externally
463+
originalCode = value;
464+
isDirty = false;
446465
} catch (error) {
447466
console.error('Failed to update editor value:', error);
448467
}

web/src/lib/components/FrequencySlider.svelte

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
import { onMount } from 'svelte';
33
import { appState } from '$lib/AppState.svelte';
44
5-
// Props
6-
let { initialFrequency = 10 }: { initialFrequency?: number } = $props();
5+
// No props needed - frequency comes from AppState
76
87
// Slider state for UI (derived from AppState frequency)
98
let sliderValue = $state(0);
@@ -92,17 +91,18 @@
9291
}
9392
}
9493
95-
// Initialize slider position based on initial frequency or AppState
94+
// Initialize slider position based on AppState frequency
9695
onMount(() => {
97-
if (appState.frequency !== initialFrequency) {
98-
appState.setFrequency(initialFrequency);
99-
}
96+
console.log('FrequencySlider onMount, appState.frequency:', appState.frequency);
10097
sliderValue = freqToSlider(appState.frequency);
98+
console.log('Set sliderValue to:', sliderValue);
10199
});
102100
103101
$effect(() => {
104102
// Keep slider position in sync with AppState frequency changes
103+
console.log('FrequencySlider effect, appState.frequency changed to:', appState.frequency);
105104
sliderValue = freqToSlider(appState.frequency);
105+
console.log('Updated sliderValue to:', sliderValue);
106106
});
107107
</script>
108108

web/src/routes/+page.svelte

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,83 @@
2323
} catch {}
2424
});
2525
26+
// Handle ship switching
27+
async function handleNextShip() {
28+
try {
29+
await WebHelper.nextShip();
30+
await updateFromGameState();
31+
} catch (error) {
32+
console.error('Failed to switch to next ship:', error);
33+
}
34+
}
35+
36+
async function handlePreviousShip() {
37+
try {
38+
await WebHelper.previousShip();
39+
await updateFromGameState();
40+
} catch (error) {
41+
console.error('Failed to switch to previous ship:', error);
42+
}
43+
}
44+
2645
// Handle engine ready callback
2746
function handleEngineReady(engineInstance: any) {
2847
engine = engineInstance;
48+
// Update app state with current ship's code when engine is ready
49+
// Add a delay and retry mechanism to ensure ships are spawned
50+
retryUpdateFromGameState();
51+
}
52+
53+
// Retry getting game state until ship is ready
54+
async function retryUpdateFromGameState(attempts = 0) {
55+
const maxAttempts = 20; // Max 2 seconds (20 * 100ms)
56+
57+
try {
58+
const state = await WebHelper.getState();
59+
if (state != null) {
60+
// Ship is ready, update state
61+
console.log('Game state ready:', state);
62+
appState.code = state.code || '';
63+
appState.isPaused = state.isPaused || false;
64+
appState.frequency = state.frequency || 10;
65+
appState.shipIdx = state.shipIdx || 0;
66+
console.log('Updated appState frequency to:', appState.frequency);
67+
return;
68+
}
69+
} catch (error) {
70+
console.warn('Attempt', attempts + 1, 'failed:', error);
71+
}
72+
73+
// If state is null and we haven't reached max attempts, retry
74+
if (attempts < maxAttempts) {
75+
setTimeout(() => {
76+
retryUpdateFromGameState(attempts + 1);
77+
}, 100);
78+
} else {
79+
console.warn('Failed to get game state after', maxAttempts, 'attempts');
80+
}
81+
}
82+
83+
// Update app state from game state
84+
async function updateFromGameState() {
85+
if (!engine) return;
86+
try {
87+
const state = await WebHelper.getState();
88+
console.log('Game state:', state); // Debug log
89+
90+
if (state == null) {
91+
console.warn('Game state is null, ship not ready yet');
92+
return;
93+
}
94+
95+
appState.code = state.code || '';
96+
appState.isPaused = state.isPaused || false;
97+
appState.frequency = state.frequency || 10; // Default to 10 if null
98+
appState.shipIdx = state.shipIdx || 0;
99+
console.log('Updated appState frequency to:', appState.frequency); // Debug log
100+
} catch (error) {
101+
console.warn('Failed to update from game state:', error);
102+
}
29103
}
30104
31105
async function handleRespawnShip() {

0 commit comments

Comments
 (0)