- Archive old documentation and test files to `docs/archive/` and `local_tests/`. - Remove various temporary and old files from the project root. - Add `nekocode-rust` analysis tool and its output files (`nekocode/`, `.nekocode_sessions/`, `analysis.json`). - Minor updates to `apps/chip8_nyash/chip8_emulator.nyash` and `local_tests` files. This commit cleans up the repository and sets the stage for further code modularization efforts, particularly in the `src/interpreter` and `src/parser` modules, based on recent analysis.
345 lines
10 KiB
Plaintext
345 lines
10 KiB
Plaintext
// 🎮 Chip-8 Emulator in Nyash - Phase 10.2
|
||
// Testing fini propagation and reference lifecycle
|
||
|
||
// Chip8CPU - Central processing unit with fini propagation
|
||
static box Chip8CPU {
|
||
init { memory, graphics, sound, program_counter, registers }
|
||
|
||
constructor() {
|
||
me.program_counter = 512 // 0x200 = 512 decimal - Standard Chip-8 start address
|
||
me.registers = new ArrayBox() // 16 general registers V0-VF
|
||
|
||
// Initialize 16 registers to 0
|
||
local i = 0
|
||
loop(i < 16) {
|
||
me.registers.push(0)
|
||
i = i + 1
|
||
}
|
||
|
||
print("🔧 CPU initialized with 16 registers")
|
||
}
|
||
|
||
// ⭐ Phase 10: fini propagation test
|
||
fini() {
|
||
print("🔄 CPU cleanup triggered - fini propagation starting")
|
||
|
||
// Clean up dependent components in order
|
||
if (me.memory != null) {
|
||
me.memory.cleanup()
|
||
print("📦 Memory cleanup completed")
|
||
}
|
||
|
||
if (me.graphics != null) {
|
||
me.graphics.cleanup()
|
||
print("🖼️ Graphics cleanup completed")
|
||
}
|
||
|
||
if (me.sound != null) {
|
||
me.sound.cleanup()
|
||
print("🔊 Sound cleanup completed")
|
||
}
|
||
|
||
print("✅ CPU fini propagation complete")
|
||
}
|
||
|
||
execute_cycle() {
|
||
// Simplified fetch-decode-execute cycle
|
||
local opcode = me.fetch_instruction()
|
||
me.decode_and_execute(opcode)
|
||
me.update_timers()
|
||
}
|
||
|
||
fetch_instruction() {
|
||
// Fetch 2-byte instruction from memory
|
||
local high_byte = me.memory.read_byte(me.program_counter)
|
||
local low_byte = me.memory.read_byte(me.program_counter + 1)
|
||
|
||
if (high_byte != null and low_byte != null) {
|
||
me.program_counter = me.program_counter + 2
|
||
return (high_byte * 256) + low_byte
|
||
} else {
|
||
return 0 // NOP if memory read failed
|
||
}
|
||
}
|
||
|
||
decode_and_execute(opcode) {
|
||
// Simplified instruction decoding
|
||
local first_nibble = opcode / 4096 // (opcode AND 0xF000) >> 12
|
||
|
||
if (first_nibble == 1) {
|
||
// 1NNN - Jump to address NNN
|
||
me.program_counter = opcode % 4096 // opcode AND 0x0FFF
|
||
print("🦘 Jump to address: " + me.program_counter)
|
||
} else if (first_nibble == 6) {
|
||
// 6XNN - Set register VX to NN
|
||
local reg = (opcode / 256) % 16 // (opcode AND 0x0F00) >> 8
|
||
local value = opcode % 256 // opcode AND 0x00FF
|
||
me.registers.set(reg, value)
|
||
print("📝 Set register V" + reg + " = " + value)
|
||
} else if (first_nibble == 7) {
|
||
// 7XNN - Add NN to register VX
|
||
local reg = (opcode / 256) % 16
|
||
local value = opcode % 256
|
||
local current = me.registers.get(reg)
|
||
me.registers.set(reg, current + value)
|
||
print("➕ Add " + value + " to register V" + reg)
|
||
} else {
|
||
print("❓ Unknown opcode: " + opcode)
|
||
}
|
||
}
|
||
|
||
update_timers() {
|
||
// Timer updates would go here
|
||
// For demo, just a placeholder
|
||
}
|
||
}
|
||
|
||
// Chip8Memory - Memory system with CPU reference
|
||
static box Chip8Memory {
|
||
init { ram, cpu_ref } // CPU reference is to prevent cycles
|
||
|
||
constructor(cpu_instance) {
|
||
me.ram = new ArrayBox()
|
||
|
||
// Initialize 4KB of RAM (4096 bytes)
|
||
local i = 0
|
||
loop(i < 4096) {
|
||
me.ram.push(0)
|
||
i = i + 1
|
||
}
|
||
|
||
// Create reference to CPU
|
||
me.cpu_ref = cpu_instance
|
||
|
||
print("💾 Memory initialized: 4KB RAM + CPU reference")
|
||
me.load_test_program()
|
||
}
|
||
|
||
// ⭐ Phase 10: reference life cycle test
|
||
read_byte(address) {
|
||
// Check if CPU is still alive before accessing memory
|
||
if (me.cpu_ref != null) {
|
||
if (address >= 0 and address < 4096) {
|
||
return me.ram.get(address)
|
||
} else {
|
||
print("⚠️ Memory access out of bounds: " + address)
|
||
return null
|
||
}
|
||
} else {
|
||
print("⚠️ CPU destroyed, memory access blocked")
|
||
return null
|
||
}
|
||
}
|
||
|
||
write_byte(address, value) {
|
||
if (me.cpu_ref != null) {
|
||
if (address >= 0 and address < 4096) {
|
||
me.ram.set(address, value)
|
||
return true
|
||
} else {
|
||
print("⚠️ Memory write out of bounds: " + address)
|
||
return false
|
||
}
|
||
} else {
|
||
print("⚠️ CPU destroyed, memory write blocked")
|
||
return false
|
||
}
|
||
}
|
||
|
||
load_test_program() {
|
||
// Load a simple test program starting at 0x200
|
||
local start_addr = 512 // 0x200
|
||
|
||
// Simple test program: Set V0 = 5, Add 3 to V0, Jump to start
|
||
me.ram.set(start_addr, 96) // 6005 - Set V0 = 5 (high byte: decimal 96)
|
||
me.ram.set(start_addr + 1, 5) // (low byte: decimal 5)
|
||
me.ram.set(start_addr + 2, 112) // 7003 - Add 3 to V0 (high byte: decimal 112)
|
||
me.ram.set(start_addr + 3, 3) // (low byte: decimal 3)
|
||
me.ram.set(start_addr + 4, 18) // 1200 - Jump to address 512 (high byte: decimal 18)
|
||
me.ram.set(start_addr + 5, 0) // (low byte: decimal 0)
|
||
|
||
print("🎮 Test program loaded: Set V0=5, Add 3, Loop")
|
||
}
|
||
|
||
cleanup() {
|
||
print("🧹 Memory cleanup: clearing RAM")
|
||
me.ram.clear()
|
||
}
|
||
}
|
||
|
||
// Chip8Graphics - Display system
|
||
static box Chip8Graphics {
|
||
init { screen, cpu_ref }
|
||
|
||
constructor(cpu_instance) {
|
||
me.screen = new ArrayBox()
|
||
|
||
// Initialize 64x32 pixel display (2048 pixels)
|
||
local i = 0
|
||
loop(i < 2048) {
|
||
me.screen.push(0) // 0 = black, 1 = white
|
||
i = i + 1
|
||
}
|
||
|
||
me.cpu_ref = cpu_instance
|
||
print("🖼️ Graphics initialized: 64x32 display + CPU reference")
|
||
}
|
||
|
||
draw_sprite(x, y, sprite_data) {
|
||
if (me.cpu_ref != null) {
|
||
print("🎨 Drawing sprite at (" + x + ", " + y + ")")
|
||
// Sprite drawing logic would go here
|
||
return true
|
||
} else {
|
||
print("⚠️ CPU destroyed, graphics operation blocked")
|
||
return false
|
||
}
|
||
}
|
||
|
||
clear_screen() {
|
||
if (me.cpu_ref != null) {
|
||
local i = 0
|
||
loop(i < 2048) {
|
||
me.screen.set(i, 0)
|
||
i = i + 1
|
||
}
|
||
print("🧹 Screen cleared")
|
||
return true
|
||
} else {
|
||
print("⚠️ CPU destroyed, screen clear blocked")
|
||
return false
|
||
}
|
||
}
|
||
|
||
cleanup() {
|
||
print("🧹 Graphics cleanup: clearing display")
|
||
me.screen.clear()
|
||
}
|
||
}
|
||
|
||
// Chip8Sound - Audio system
|
||
static box Chip8Sound {
|
||
init { beep_timer, cpu_ref }
|
||
|
||
constructor(cpu_instance) {
|
||
me.beep_timer = 0
|
||
me.cpu_ref = cpu_instance
|
||
print("🔊 Sound initialized with CPU reference")
|
||
}
|
||
|
||
play_beep() {
|
||
if (me.cpu_ref != null) {
|
||
print("🔔 BEEP! (Sound playing)")
|
||
me.beep_timer = 60 // 1 second at 60Hz
|
||
return true
|
||
} else {
|
||
print("⚠️ CPU destroyed, sound playback blocked")
|
||
return false
|
||
}
|
||
}
|
||
|
||
update() {
|
||
if (me.cpu_ref != null) {
|
||
if (me.beep_timer > 0) {
|
||
me.beep_timer = me.beep_timer - 1
|
||
if (me.beep_timer == 0) {
|
||
print("🔇 Sound finished")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
cleanup() {
|
||
print("🧹 Sound cleanup: stopping audio")
|
||
me.beep_timer = 0
|
||
}
|
||
}
|
||
|
||
// Main Chip-8 System
|
||
static box Chip8System {
|
||
init { cpu, memory, graphics, sound }
|
||
|
||
main() {
|
||
print("🎮 Starting Chip-8 Emulator - Phase 10.2")
|
||
print("Testing fini propagation and reference lifecycle")
|
||
|
||
// Create CPU first
|
||
me.cpu = new Chip8CPU()
|
||
me.cpu.constructor()
|
||
|
||
// Create subsystems with references to CPU
|
||
me.memory = new Chip8Memory()
|
||
me.memory.constructor(me.cpu)
|
||
|
||
me.graphics = new Chip8Graphics()
|
||
me.graphics.constructor(me.cpu)
|
||
|
||
me.sound = new Chip8Sound()
|
||
me.sound.constructor(me.cpu)
|
||
|
||
// Link components to CPU for fini propagation
|
||
me.cpu.memory = me.memory
|
||
me.cpu.graphics = me.graphics
|
||
me.cpu.sound = me.sound
|
||
|
||
print("🔗 All components linked with references")
|
||
|
||
// Run a few emulation cycles
|
||
me.run_emulation()
|
||
|
||
// Test fini propagation by destroying CPU
|
||
print("💥 Testing fini propagation - destroying CPU...")
|
||
me.cpu.fini()
|
||
me.cpu = null
|
||
|
||
// Test reference after CPU destruction
|
||
print("🧪 Testing references after CPU destruction...")
|
||
me.test_weak_references()
|
||
|
||
return "Chip-8 emulation and memory management test complete"
|
||
}
|
||
|
||
run_emulation() {
|
||
print("🚀 Starting emulation cycles...")
|
||
|
||
local cycles = 0
|
||
loop(cycles < 5) {
|
||
print("⚡ Cycle " + (cycles + 1))
|
||
me.cpu.execute_cycle()
|
||
me.sound.update()
|
||
cycles = cycles + 1
|
||
}
|
||
|
||
print("✅ Emulation cycles complete")
|
||
}
|
||
|
||
test_weak_references() {
|
||
print("Testing memory access after CPU destruction:")
|
||
local result = me.memory.read_byte(512)
|
||
print("Memory read result: " + result)
|
||
|
||
print("Testing graphics operation after CPU destruction:")
|
||
local gfx_result = me.graphics.clear_screen()
|
||
print("Graphics operation result: " + gfx_result)
|
||
|
||
print("Testing sound operation after CPU destruction:")
|
||
local sound_result = me.sound.play_beep()
|
||
print("Sound operation result: " + sound_result)
|
||
}
|
||
}
|
||
|
||
// Entry point
|
||
static box Main {
|
||
init { console }
|
||
|
||
main() {
|
||
me.console = new ConsoleBox()
|
||
me.console.log("🚀 Phase 10.2: Chip-8 Emulator Starting")
|
||
|
||
local chip8 = new Chip8System()
|
||
local result = chip8.main()
|
||
|
||
me.console.log("🏁 Result: " + result)
|
||
return "Phase 10.2 Complete"
|
||
}
|
||
} |