The Mystery of the Wizard's Castle REM Statement

The Mystery of the Wizard's Castle REM Statement

The Mystery of the REM Statement

Exidy Sorcerer용으로 제작된 1980년 마이크로컴퓨터 게임 The Wizard's Castle의 소스 코드 첫 줄에는 10 REM"_(C2SLFF4라는 문구가 나타납니다. 이것은 오타나 쓰레기 데이터처럼 보이지만, 실제로는 게임의 의사 난수 생성기(PRNG) 시딩을 위한 RANDOMIZE 함수를 시뮬레이션하기 위해 BASIC 주석으로 위장된 Z80 머신 코드 루틴입니다.

How the Machine Code was Hidden

Exidy Sorcerer에서 BASIC 인터프리터는 명령어를 토큰화하여 주소 469부터 시작하는 RAM의 연결 리스트로 저장합니다. 프로그램 노드의 구조에는 다음 포인터, 라인 번호, 토큰화된 명령어 및 라인 텍스트가 포함됩니다.

프로그램의 첫 번째 라인의 경우:

  • 주소 469-470: Next pointer
  • 주소 471-472: 라인 번호 (10)
  • 주소 473: REM 토큰 (0xC3)
  • 주소 474: REM 텍스트의 시작

주소 260과 261에서 POKE 명령어를 통해 지정된 머신 코드 주소로 점프하는 USR() 함수를 사용하여, 게임은 REM 문구의 텍스트를 실제 Z80 명령어로 실행합니다. 구체적으로 POKE 260,218: POKE 261,1 코드는 USR() 함수가 REM 텍스트가 시작되는 정확한 위치인 주소 474로 점프하도록 지시합니다.

Dissecting the Z80 Routine

REM 텍스트를 ASCII로 역어셈블하려는 초기 시도는 실패했습니다. 원본 잡지 목록의 문자들이 ASCII로 인코딩되어 있지 않았기 때문입니다. 테이프 이미지에서 실제 바이트를 분석했을 때, 루틴은 다음과 같이 밝혀졌습니다:

LD A,R       ; R 레지스터를 누산기로 복사
JR Z,-4      ; 결과가 0이면 이전 명령어로 점프
LD (F7FF),A  ; 누산기를 F7FFh 주소로 복사
RET          ; BASIC으로 복귀

The PRNG Seeding Process

  1. Entropy Source: 루틴은 명령어 인출 중에 빈번하게 증가하는 R 레지스터를 읽어, 사용자가 게임을 시작하는 정확한 시점에 따라 준무작위 값을 제공합니다.
  2. Zero-Check: 부적절한 PRNG 시딩을 피하기 위해 값이 0이 아닌지 확인합니다.
  3. Memory Mapping: 값은 주소 0xF7FF에 저장되며, 이는 메모리 맵 화면 텍스트의 오른쪽 하단 문자 위치에 해당합니다.
  4. BASIC Retrieval: 그 후 BASIC 코드는 T = PEEK(-2049)(여기서 -2049는 0xF7FF)를 사용하여 이 값을 읽고, Q = RND(-(2*T+1))를 사용하여 RND() 함수를 시딩합니다.

R 레지스터는 하위 7비트만 증가시키기 때문에, 이 기술로 인해 게임에서 생성 가능한 던전의 수는 127개로 제한되었습니다.

The "Typing-In" Paradox

1980년대에 프로그래머들은 잡지에서 코드를 직접 타이핑했습니다. 하지만 The Wizard's CastleREM 문구는 문자 그대로 ASCII 문자로 타이핑되었다면 작동할 수 없었을 것입니다. 원본 사용자들이 이를 구현한 방식에 대해 두 가지 가능한 설명이 있습니다:

  1. Direct POKING: 작성자가 자리 표시용 REM을 타이핑한 다음, POKE 명령어를 사용하여 비-ASCII 바이트를 메모리에 수동으로 삽입했을 수 있습니다.
  2. Special Key Combinations: 연구에 따르면 Exidy Sorcerer에는 사용자가 0x80에서 0xFF 사이의 토큰과 값을 입력할 수 있는 Graphic+Shift 키 조합이 있었으며, 이는 목록에 보이는 글자들과 매핑됩니다.

Technical Insights from the Community

이 기술에 대한 분석은 고정된 RAM 위치와 멀티프로세싱의 부재로 인해 BASIC과 머신 코드를 매끄럽게 혼합할 수 있었던 초기 홈 컴퓨터의 결정론적 특성을 강조합니다.

"대부분의 타이핑 방식 하이브리드 BASIC-머신 언어 프로그램은 opcodes가 포함된 수많은 DATA 문과 이를 READ하여 POKE하는 루프를 가지고 있었을 것입니다... Commodore 64 BASIC의 LOAD"WHATEVER",8 명령은 검증 없이 BASIC 텍스트 영역에 모든 크기의 파일을 로드할 수 있었습니다." — @RiverCrochet

유사한 기술이 Sinclair ZX81과 같은 다른 플랫폼에서도 사용되었습니다. 해당 플랫폼에서는 전용 메모리 블록이나 DATA 문이 없는 경우 REM 문이나 기타 무시되는 라인을 사용하여 머신 코드를 저장했습니다.

Sources