logo
Kurashizu Blogwhere ideas flow
  • Home
  • News
  • Blog
  • About
  • Home
  • News
  • Blog
  • About

© 2026 Kurashizu. All rights reserved.

Admin·New Post·Service Status
Powered by Cloudflare·01.11.26
← Back to news

10 REM"_(C2SLFF4

Original article
beej.us|121 points|32 comments|by ingve|Jul 22, 2026

10 REM"_(C2SLFF4

Beej's Bit Bucket ⚡ Tech and Programming Fun | 2026-07-21

Let's take a deep dive into the source code of The Wizard's Castle!

The line 10 REM _(C2SLFF4 serves as the opening statement of this 1980s microcomputer BASIC game, which was originally developed for the Exidy Sorcerer platform.

In this specific language, a REM statement is simply a remark—a comment ignored by the interpreter. For those unfamiliar with vintage coding styles, the 10 is the line number. This exact string appears in the original source as printed in the July 1980 edition of Recreational Computing.


📝 Technical Notes

  • Notation: I will be toggling between decimal (which BASIC uses) and hexadecimal (which programmers prefer).
  • Hex Format: I'll denote hex values using the 0x prefix, the h suffix, or by using characters A-F.
  • Acknowledgements: A huge shout-out to my fellow hackers, Josh and Chris, for their extensive research and emulator work.

🔍 The Suspicion

Consider this snippet of the source code (cleaned up for clarity):

10 REM _(C2SLFF4 40 POKE 260,218: POKE 261,1: T = USR(0): T = PEEK(-2049) 80 Q = RND(-(2*T+1))

In Sorcerer BASIC, the colon (:) acts as a command separator. The system utilized signed 16-bit integers, meaning the address -2049 is calculated as: Address=65536−2049=63487 (or 0xF7FF in hex)\text{Address} = 65536 - 2049 = 63487 \text{ (or } 0\text{xF7FF in hex)}Address=65536−2049=63487 (or 0xF7FF in hex)

The RND() function (the pseudo-random number generator, or PRNG) is seeded when passed a negative value. Because older PRNGs typically required odd numbers for seeding, the expression −(2T+1)-(2T + 1)−(2T+1) was used to guarantee an odd result. Since line 80 is the first time T is used after being set by PEEK(), it's highly probable these lines are all part of the PRNG seeding process.

Since Sorcerer BASIC lacked a RANDOMIZE command, developers had limited options for seeding:

  • Prompt the user for a manual seed.
  • Use a timing loop that ends when a key is pressed.
  • Extract a "random-ish" value from the system hardware or existing software.

The Crazy Theory: Could the REM statement actually contain machine code that just happens to look like ASCII text? It seems absurd that meaningful Z80 machine code could be formed from standard characters, but it was a hypothesis worth testing.


⚙️ The USR() Function

The USR() call triggers a machine code function, though the implementation varies by system. After digging through old technical manuals, we discovered the following:

  1. Address 259 contains a JP (unconditional jump) instruction.
  2. This jump points to a 16-bit absolute address stored in little-endian format.
  3. By using POKE on addresses 260 and 261, the programmer specifies the destination of that jump.

Looking at line 40: 40 POKE 260,218: POKE 261,1: T = USR(0): T = PEEK(-2049)

The destination address is calculated as: Address=(1×256)+218=474\text{Address} = (1 \times 256) + 218 = 474Address=(1×256)+218=474

When USR(0) is executed, the CPU jumps to the code at address 474. While the argument 0 is stored as a 4-byte float in RAM, and the return value is assigned to T, the return value is actually irrelevant because T is immediately overwritten by the PEEK command.


💾 BASIC RAM Layout

Exidy Sorcerer Image Credit: Marcin Wichary, CC BY 2.0

When a line of code is entered into Sorcerer BASIC, the interpreter tokenizes it. For example:

  • PRINT →\rightarrow→ 0x97
  • REM →\rightarrow→ 0xC3

These lines are stored in memory as a linked list starting at address 469. Each node follows this structure:

OffsetSizeDescription
02 BytesPointer to the next node
22 BytesLine number
4VariableTokenized code bytes
End1 ByteNull terminator (0x00)

The Revelation

Let's map the mystery line 10 REM _(C2SLFF4 to RAM:

The USR(0) function is literally executing the text of the comment as Z80 machine code!

The ASCII characters in _(C2SLFF4 translate to the following hex values: 5F 28 43 32 53 4C 46 46 34

Disassembling these bytes yields:

22 5F 28    LD (285Fh), HL  ; _ (
43          LD B, E         ; C
32 53 4C    LD (4C53h), A   ; 2 S L
46          LD B, (HL)      ; F
46          LD B, (HL)      ; F
34          INC (HL)        ; 4

This code is a masterpiece of logic. In reality, it makes no sense. The addresses are arbitrary, the B register is never used, the LD B is redundant, and there is no RET instruction to return control to BASIC. Running this in an emulator causes "weird things" like soft resets. We suspect this was a printing error in the magazine where the printer substituted glyphs for bytes it couldn't render.


📺 The PEEK(-2049)

Finally, let's look at the PEEK again: T = PEEK(-2049)

Address -2049 (0xF7FF) corresponds to the very last byte of the memory-mapped screen text—specifically, the character in the bottom-right corner of the display.

This value is then used to seed the PRNG: 80 Q = RND(-(2*T+1))

If the character were simply a space (ASCII 32), every game would start with the same seed, ruining the replayability of the random dungeon. Therefore, the USR() function must be doing more than just crashing; it likely writes a specific value to address 0xF7FF before the PEEK reads it. Since the screen is cleared shortly after, the player never notices the character appearing there.