Wiznet makers

Benjamin

Published February 02, 2026 ©

100 UCC

11 WCC

8 VAR

0 Contests

0 Followers

1 Following

Original Link

Microcraft: Running a Minecraft Server on 512 Bytes of RAM with W5500

A minimal Minecraft 1.12.2 server in C targeting MSP430G2553, using W5500 hardware TCP/IP to fit within 512 bytes of RAM.

COMPONENTS Hardware components

texasinstruments - MSP430 Microcontroller

x 1


WIZnet - W5500

x 1


PROJECT DESCRIPTION

A Minecraft Server That Shouldn't Exist

Microcraft is a deliberately absurd experiment: cramming a Minecraft server into a microcontroller with just 512 bytes of RAM. Created by Alfredo Savi, a computer engineering student at UTFPR in Brazil, the project implements a subset of the Minecraft Java Edition protocol (version 1.12.2, protocol 340) in pure C, targeting the MSP430G2553 — a 16-bit MCU that was, in the developer's own words:

"jogado no fundo da minha gaveta" (thrown in the back of my drawer)

The project isn't meant to be practical. It's a technical challenge that pushes the boundaries of what minimal hardware can do — and the W5500 is what makes it even remotely possible.

Why the W5500 Is Essential, Not Optional

The MSP430G2553 has no Ethernet peripheral and only 512 bytes of RAM. Implementing a software TCP/IP stack on this MCU is out of the question — a typical lwIP configuration alone would consume several kilobytes of RAM. This is where the W5500 becomes the critical enabler.

The W5500 offloads the entire TCP/IP stack to hardware: ARP, ICMP, IPv4, TCP, and UDP are all handled internally. The MCU only needs to interact with socket-level abstractions over SPI. This means the MSP430 can focus its scarce RAM entirely on Minecraft protocol logic — packet parsing, state management, and response construction.

The connection uses SPI (MOSI, MISO, SCK) with a dedicated chip select and GPIO-controlled reset. The README specifically warns about SPI signal integrity:

"foram observados erros de bytes na comunicação SPI causados por jumpers 'longos' e/ou de baixa qualidade."

This is a practical note for anyone attempting to reproduce the setup — short, quality jumper wires are essential for reliable communication at SPI speeds.

Minecraft Protocol Implementation: What Actually Works

The codebase implements a clean state machine that walks through the Minecraft protocol's connection phases. The client structure is minimal — just a socket descriptor and a state flag:

// pc/client.h
typedef struct {
    int socket;
    int state;
} Client;

Each incoming packet is dispatched based on the current state (STATE_HANDSHAKE, STATE_STATUS, STATE_LOGIN, STATE_PLAY). The core dispatch logic in pc/client.c:L80-L120 parses VarInt-encoded packet IDs and routes them accordingly.

Handshake phase (client.c:L85-L112): Parses the client's handshake packet to determine whether it's requesting server status (state 1) or login (state 2). The code manually walks through VarInt-encoded fields — protocol version, server address, port, and next state — with no external parsing library.

Status phase (status.c): Returns a hardcoded JSON response conforming to the Minecraft Server List Ping format:

// pc/status.c:L23-L29
const char *json =
    "{"
    "\"version\":{\"name\":\"1.12.2\",\"protocol\":340},"
    "\"players\":{\"max\":1,\"online\":0},"
    "\"description\":{\"text\":\"TODO: descricao do server AQUI!\"}"
    "}";

This makes the server appear in the Minecraft client's server list with version and MOTD info.

Login phase (login.c): Handles the LOGIN_START packet by extracting the player name, then sends a Login Success response with a zeroed UUID (offline mode, no Mojang authentication). After login succeeds, the state transitions to PLAY.

Play phase (play.c): Sends two packets — Join Game (packet ID 0x23) and Player Position And Look (packet ID 0x2F). The join game packet sets survival mode, overworld dimension, and a single max player. The position packet spawns the player at coordinates (0, 70, 0). These two packets are enough to get the Minecraft client past the login screen and into the terrain loading state.

Protocol Building Blocks: VarInt and Packet Framing

The Minecraft protocol uses VarInt encoding extensively — a variable-length integer format where each byte contributes 7 data bits and 1 continuation bit. The implementation in mc_packet.c provides both read and write functions:

// pc/mc_packet.c:L46-L58 — VarInt encoding
int mc_write_varint(unsigned char *buf, int value) {
    int pos = 0;
    do {
        unsigned char temp = value & 0x7F;
        value >>= 7;
        if (value) {
            temp |= 0x80;
        }
        buf[pos++] = temp;
    } while (value);
    return pos;
}

Every Minecraft packet is framed as [length (VarInt)] [packet_id (VarInt)] [payload]. The mc_read_packet function reads the length first, allocates memory, then reads the exact number of payload bytes — a straightforward approach that works on PC but will need significant rethinking for the 512-byte RAM MCU target.

System Architecture

 

Note: This diagram represents the target architecture. The current repository only contains the PC version, which uses POSIX sockets instead of the W5500.

What's Missing — And That's the Point

The project is refreshingly honest about its incompleteness. The README lists a TODO that includes KeepAlive, chunk sending, player movement, and chat — basically the entire gameplay layer. The current implementation gets a client to the terrain loading screen, but no further.

More critically for this UCC, the MCU-specific code (SPI driver, W5500 register access, MSP430 initialization) has not been pushed to the repository yet. The pc/ directory serves as a protocol validation environment. The pin mapping table in the README is marked <!-- TODO -->, and the "Useful Links" section is also incomplete.

This is a work-in-progress experiment, not a finished product. Its value lies in the approach: proving that Minecraft protocol logic can be distilled to a level where a 512-byte-RAM MCU can handle it, provided the networking layer is offloaded entirely to hardware — which is exactly what the W5500 provides.

FAQ

Q1: Can a Minecraft client actually connect to this server? Yes, but only partially. The server handles Handshake, Status (server list ping), Login, and initial Join Game. The client reaches the terrain loading screen but cannot proceed further because no chunk data is sent.

Q2: Why MSP430G2553 instead of ESP32 or STM32? The developer chose it specifically because it was the most constrained MCU available — an old LaunchPad gathering dust. The challenge of running a Minecraft server on 512 bytes of RAM is the entire point. A more capable MCU would defeat the purpose.

Q3: Why is the W5500 necessary for this project? The MSP430G2553 has no Ethernet hardware and only 512 bytes of RAM. A software TCP/IP stack (like lwIP) would consume far more RAM than the MCU has. The W5500 implements TCP/IP entirely in hardware, letting the MCU work at the socket level and reserve its RAM for protocol logic.

Q4: Where is the MCU code? Currently only the PC test version is in the repository. The MCU-specific code (SPI driver, W5500 interface, MSP430 startup) has not been pushed yet. The PC version validates protocol correctness before porting.

Q5: What Minecraft version does this target? Protocol version 340 (Minecraft Java Edition 1.12.2). This is a relatively older version with a simpler protocol compared to modern releases.

Q6: How does the server handle Minecraft's VarInt encoding with only 512B RAM? The VarInt implementation is stateless — it processes one byte at a time with no buffer allocation, using only a few local variables. This makes it well-suited for extreme memory constraints.

Q7: Could this be extended to actually serve terrain? In theory, a minimal flat-world chunk could be constructed with relatively few bytes. The bigger challenge is KeepAlive timing and handling multiple packet types in the PLAY state within the RAM budget.

Documents
Comments Write