Claude Code Plugins

Community-maintained marketplace

Feedback

Guide for cross-compiling complex C programs (like DOOM) for embedded MIPS environments with custom VM runtimes. This skill applies when building software that targets MIPS architecture with limited stdlib support, custom syscall interfaces, or JavaScript-based VM execution environments. Use when cross-compiling games, applications, or any C code for constrained MIPS targets.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name make-doom-for-mips
description Guide for cross-compiling complex C programs (like DOOM) for embedded MIPS environments with custom VM runtimes. This skill applies when building software that targets MIPS architecture with limited stdlib support, custom syscall interfaces, or JavaScript-based VM execution environments. Use when cross-compiling games, applications, or any C code for constrained MIPS targets.

Cross-Compiling C Programs for MIPS VM Environments

Overview

This skill provides guidance for cross-compiling complex C programs to run on MIPS-based virtual machines with custom runtime environments. The primary challenge involves creating freestanding executables that work without standard system libraries, implementing custom syscall interfaces, and ensuring the compiled binary actually produces expected output in the target VM.

Critical Success Criteria

Before declaring any task complete, verify the actual acceptance criteria are met:

  1. Identify what output the VM expects (e.g., frame files, console output, specific exit codes)
  2. Run the compiled binary in the VM and confirm expected artifacts are created
  3. Never accept "the program runs some instructions" as success - verify end-to-end functionality

Approach

Phase 1: Environment Analysis

Before writing any code, thoroughly analyze the target environment:

  1. Read the VM implementation completely - Understand:

    • Available syscalls and their exact signatures
    • File system abstractions and path handling
    • Memory layout expectations
    • How the VM handles program termination
    • Any special requirements for input/output
  2. Analyze the source program's dependencies:

    • List all required standard library functions
    • Identify file I/O patterns (WAD files, config files, output files)
    • Understand the main loop structure and when output occurs
    • Map out initialization sequence and failure points
  3. Document the interface contract:

    • What syscall numbers map to what operations
    • Expected calling conventions
    • Return value semantics and error handling

Phase 2: Systematic Stdlib Implementation

Create custom standard library implementations methodically:

  1. Audit all required functions upfront - Do not add functions one-by-one as errors appear. Instead:

    • Grep for all function calls in the source
    • Create a complete list before starting implementation
    • Group by category: string ops, memory ops, I/O, math
  2. Implement complete functionality for critical functions:

    • printf, sprintf, snprintf - Implement actual formatting, not stubs returning 0
    • sscanf - Implement actual parsing if the program uses it
    • File operations - Ensure paths resolve correctly in the VM
  3. Create comprehensive stub headers - For each system header:

    • Define only what the program actually uses
    • Avoid pulling in real system headers that conflict

Phase 3: Cross-Compilation Setup

Configure the toolchain correctly:

  1. Compiler flags:

    • Use -ffreestanding to avoid system library assumptions
    • Use -nostdlib to prevent linking against host libraries
    • Use -msoft-float if the VM lacks FPU support
    • Address ABI warnings (hard-float vs soft-float) - these cause runtime failures
  2. Linker configuration:

    • Provide appropriate linker script if needed
    • Ensure entry point is correctly specified
    • Verify symbol resolution for all custom implementations

Phase 4: Iterative Testing with Verification

Test against actual success criteria at each step:

  1. After first successful compilation:

    • Run in VM immediately
    • Check if expected output files are created
    • If program terminates early, investigate why
  2. When program terminates unexpectedly:

    • Examine the termination address
    • Add debug output at key checkpoints
    • Verify resource loading (WAD files, data files)
    • Check if required command-line arguments are provided
  3. Trace program flow:

    • Understand when the expected output should be generated
    • If output depends on game loop iterations, verify the loop runs
    • Check tick counters or frame counters if output is periodic

Verification Strategies

Pre-Completion Checklist

Before declaring the task complete:

  • VM implementation has been read and understood
  • All syscalls used by custom stdlib match VM's implementation
  • Critical functions (printf, file I/O) have working implementations, not stubs
  • Resource files (WAD, data) are accessible via VM's file system
  • Program runs to the point where expected output should be generated
  • Expected output files actually exist after VM execution
  • Program executes a reasonable number of instructions (not early termination)

Debugging Early Termination

When a program terminates prematurely:

  1. Check the program counter at termination - what function/code is at that address?
  2. Add print statements at initialization milestones
  3. Verify file open operations succeed (check return values)
  4. Ensure required arguments are passed to main()
  5. Check if errno or error handlers are being triggered

Validating Output Generation

For frame-based output (like DOOM):

  1. Understand when frames are written (e.g., every N ticks)
  2. Verify the game loop executes enough iterations
  3. Check file write syscalls are being called
  4. Confirm output path is writable in VM environment

Common Pitfalls

Stub Functions That Break Programs

Problem: Implementing printf/sprintf as stubs returning 0 breaks programs that depend on formatted output for initialization or configuration parsing.

Solution: Implement actual formatting logic or at minimum ensure the output buffer receives expected content.

Ignoring Linker Warnings

Problem: ABI mismatch warnings (hard-float vs soft-float) are dismissed but cause runtime failures when floating-point operations execute.

Solution: Ensure consistent floating-point ABI across all compiled objects and the VM's expectations.

Premature Success Declaration

Problem: Seeing "program executed N instructions" and concluding success without verifying actual output.

Solution: Always verify the specific acceptance criteria (file creation, correct output content) before marking complete.

Missing Resource Files

Problem: DOOM and similar programs require data files (WAD) that must be accessible via the VM's file system abstraction.

Solution: Verify the binary can locate and open required resources. Check if paths need adjustment for VM environment.

Incomplete Dependency Analysis

Problem: Adding functions one-by-one as compilation errors appear leads to incomplete implementations and missed dependencies.

Solution: Systematically audit all function calls in the source code before starting implementation.

Decision Framework

When to Add Debug Output

Add debug output when:

  • Program terminates after fewer instructions than expected
  • Expected output files are not created
  • Unsure if initialization completes successfully

When to Re-examine VM Implementation

Re-read the VM code when:

  • Syscalls return unexpected values
  • File operations fail silently
  • Program behavior differs from expectations

When to Implement vs Stub a Function

Implement fully when:

  • Function output is used by the program (printf formatting, string operations)
  • Function affects control flow (file open success/failure)
  • Function result is checked by caller

Stub with caution when:

  • Function is called but result is ignored
  • Function is for features not needed in VM context
  • Must document why stub is safe