Skip to content

SobshDev/RobotFactory

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RobotFactory

An assembler for Corewar — compiles .s warrior source files into .cor bytecode ready to run inside the Corewar virtual machine.


Corewar context

Corewar is a programming game in which small programs called warriors fight for control of a shared memory arena. Each warrior is written in a Redcode-like assembly language (.s source files), compiled to a compact binary format (.cor), and loaded into the VM. Warriors execute concurrently, one instruction per cycle; the last warrior to stay alive wins. This assembler (asm) is the tool that translates warrior source code into the bytecode the VM can execute.


What this binary does

./asm warrior.s   →   ./warrior.cor

asm reads a single .s source file, validates every directive, instruction, and label reference, then writes a .cor binary in the current directory.

Exit codes: 0 on success, 84 on any error (missing file, invalid extension, bad syntax, duplicate declarations, unresolved labels, …).


Build

make        # produces ./asm
make clean  # removes object files
make fclean # removes objects and the binary
make re     # full rebuild

Requires a C compiler (cc) and standard POSIX headers. No external dependencies.


Usage

./asm <source.s>
./asm -h        # print usage help
./asm --help

The output file is always placed in the current directory, named after the input file with the .s extension replaced by .cor.

Example

./asm Tester/champions/abel.s
# produces ./abel.cor

Source file format

A .s warrior file has two mandatory sections: a header block with .name and .comment directives, followed by an instruction block.

    .name    "Abel"           # warrior name  (≤ 128 bytes)
    .comment "L'amer noir."   # description   (≤ 2048 bytes)

    sti  r1, %:hi, %1   # store r1 at address (hi + 1), indirect-indexed

hi: live %234           # declare process alive with player id 234
    ld   %0, r3         # load literal 0 into r3
    zjmp %:hi           # jump back to label 'hi' if carry flag is zero

(Source: Tester/champions/abel.s)

Syntax rules

Element Syntax Example
Register r1r16 r1, r16
Direct (literal) %<value> %42, %-1
Indirect (memory offset) bare integer 100
Label reference (direct) %:<label> %:hi
Label definition <name>: hi:
Comment # to end of line # comment

Instruction set

The 16 supported opcodes, in opcode order:

Mnemonic Args Opcode Description
live dir 0x01 Declare process alive
ld dir|ind, reg 0x02 Load value into register
st reg, ind|reg 0x03 Store register to memory
add reg, reg, reg 0x04 Add two registers
sub reg, reg, reg 0x05 Subtract two registers
and any, any, reg 0x06 Bitwise AND
or any, any, reg 0x07 Bitwise OR
xor any, any, reg 0x08 Bitwise XOR
zjmp dir 0x09 Jump if carry is zero
ldi any, dir|reg, reg 0x0a Load indirect-indexed
sti reg, any, dir|reg 0x0b Store indirect-indexed
fork dir 0x0c Fork process
lld dir|ind, reg 0x0d Long load (no IDX_MOD)
lldi any, dir|reg, reg 0x0e Long load indirect-indexed
lfork dir 0x0f Long fork
aff reg 0x10 Print register value as ASCII

Output binary format (.cor)

All multi-byte integers are big-endian.

Offset Size (bytes) Field
0 4 Magic number (0x00ea83f3)
4 128 Program name (null-padded)
132 4 Padding (zeros)
136 4 Program size in bytes (code section only)
140 2048 Comment string (null-padded)
2188 4 Padding (zeros)
2192 Encoded instructions (code section)

Each instruction encodes as: [opcode 1B] [coding byte 1B*] [params…]

*The coding byte is omitted for single-parameter instructions (except aff). Each 2-bit field in the coding byte encodes the parameter type: 01 = register, 02 = direct, 03 = indirect.


Project layout

RobotFactory/
├── include/
│   ├── asm.h               # main assembler struct (asm_t)
│   ├── op.h                # header_t, op_t, constants (COREWAR_EXEC_MAGIC, …)
│   ├── instructions.h      # instruction_t, param_t, label_t, parse functions
│   ├── fill.h              # fill_data / fill_header / fill_instructions
│   ├── write.h             # write_output / write_header / write_data
│   ├── error_handling.h    # error codes enum, print_error, handle_errors
│   ├── linked_lists.h      # generic singly-linked list
│   ├── header.h            # parse_name, parse_comment
│   └── lib.h               # custom string/IO helpers (no libc dependency)
├── src/
│   ├── main.c
│   ├── cleanup.c
│   ├── asm/
│   │   ├── error_handling/ # handle_errors, print_error, print_help
│   │   └── fill_data/
│   │       ├── fill_data.c
│   │       ├── header/     # parse_name, parse_comment, fill_header
│   │       └── instructions/ # parse_line, parse_instructions,
│   │                          # parse_labels, parse_parameters, op_utils
│   ├── write/
│   │   ├── write_output.c
│   │   ├── write_header.c
│   │   ├── write_data.c
│   │   └── write_program_size.c
│   └── lib/
│       ├── general/        # my_atoi, my_str*, skip_spaces, …
│       └── linked_lists/   # create/push/append/delete/find node, lltoa
└── Tester/
    ├── champions/          # .s warrior sources used as test fixtures
    ├── reference/          # pre-built reference asm binary (not redistributed)
    ├── my/                 # copy of your asm binary placed here by test.sh
    ├── tester.sh           # per-champion diff test runner
    └── segfaulter.sh       # crash/edge-case stress script

Testing

The test suite compiles each .s file in Tester/champions/ with both a reference assembler and your build, then diffs the resulting .cor binaries byte-for-byte.

Prerequisites: place the Epitech reference asm binary in Tester/reference/.

# From the repo root:
bash test.sh

test.sh runs make, copies ./asm to Tester/my/, then runs Tester/tester.sh. Exit code 0 means all champions compiled identically to the reference; 1 means at least one diff was found (hexdump comparison printed to stdout).

To run the tester directly after a manual build:

cp asm Tester/my/
cd Tester && bash tester.sh

Error handling

The assembler prints coloured diagnostics with file name and line number context, then exits 84. Detected conditions include: missing/duplicate .name or .comment, invalid file extension, unknown instruction, wrong parameter count, invalid parameter type, invalid register number (r0 or r17+), unresolved label, and name/comment strings that exceed their maximum lengths.


Author

@SobshDev

Origin

Developed as part of the Epitech CPE curriculum — B-CPE-200, 1st year, S2 (2025). The project subject (PDF) is not redistributed here per Epitech policy.

About

Robot factory simulation in C.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors