Ymir Dungeon Designer is a level editor for Dungeon of Ymir, allowing users to design, review, save, and export custom maze sets. The program stores up to nine dungeon levels in a three-dimensional string array M$(9,20,30), with each cell holding either a space or CHR$(128) (the inverse space block graphic used as a wall tile). Cursor movement in the editor follows an 8-direction numpad-style scheme, with row and column wrapping handled explicitly. The export process is notably complex: it uses RAND USR calls at addresses 8200 and 837 to invoke machine code routines that transfer the designed mazes into the original game’s data via SRAM, requiring the user to load Part 2 of the Dungeon of Ymir tape in a specific sequence. Variables such as WL, FRAME, PRINT, CLEAR2, CLEAR1, and KEY store line numbers used as GOSUB targets, a common technique to make subroutine dispatch more readable.
Program Analysis
Program Structure
The program is organized into clearly separated functional sections, with a main menu dispatching to numbered modules via GOTO 1000*VAL Z$. An introductory splash screen runs first at line 9000, then falls through to initialization at line 100.
| Line Range | Function |
|---|---|
| 100–230 | Initialization: array, subroutine address variables, mode flags |
| 500–550 | Main menu display and dispatch |
| 1000–1090 | Option 1: View a maze level |
| 2000–2320 | Option 2: Edit a maze level |
| 3000–3080 | Option 3: Save dungeon to tape |
| 4000–4190 | Option 4: Export/install dungeon into game |
| 8000–8030 | Subroutine: level selector |
| 8100–8170 | Subroutine: draw border frame |
| 8200–8240 | Subroutine: print maze contents to screen |
| 8300–8340 | Subroutine: clear status lines 22–23 |
| 8400–8450 | Subroutine: “press any key” wait |
| 9000–9090 | Introduction/splash screen |
Data Storage
All nine dungeon levels are held in a single three-dimensional string array declared at line 100: DIM M$(9,20,30). Each element is a one-character string; walls are stored as CHR$(128) (the inverse-space block graphic) and empty cells as the default space. This maps neatly to a 20-row by 30-column playfield bordered by the frame subroutine.
Subroutine Address Variables
Lines 110–160 assign BASIC line numbers to named variables (WL, FRAME, PRINT, CLEAR2, CLEAR1, KEY), which are then used as GOSUB targets throughout the program. This is a deliberate idiom that improves readability and makes renumbering easier, at the cost of shadowing the BASIC keyword PRINT with a numeric variable of the same name — a legal but unusual choice that could surprise a reader.
Menu Dispatch
The menu at line 500 accepts a single keypress and dispatches with GOTO 1000*VAL Z$, routing to lines 1000, 2000, 3000, or 4000 for options 1–4, and to line 0 (non-existent) for option 0 — which causes a BASIC error and effectively performs a NEW-like reset since option 0 is described as “START ANEW (CLEARS DUNGEON).” This is a well-known technique for clearing program state without a dedicated handler.
Editor Mechanics
The maze editor at line 2000 uses an 8-direction movement scheme mapped to the keys 1–8. Row and column deltas are computed simultaneously using Boolean arithmetic in lines 2250–2260:
- Keys
6,1,3move south (row+1); keys7,2,4move north (row−1) - Keys
8,3,4move east (col+1); keys5,1,2move west (col−1)
Wrapping is handled explicitly at lines 2270–2300, with the boundary check IF NOT R serving as a test for zero (since NOT 0 is true in BASIC). The cursor is shown by printing an inverse asterisk [*] then immediately reprinting the cell’s actual content at the same position, exploiting the print position to restore the display.
The fill/erase toggle uses M as a Boolean (0 or 1). Pressing CHR$(118) (the ENTER/newline character as detected via INKEY$) toggles the mode. Wall data is written as CHR$(128*M) — either CHR$(128) for fill or CHR$(0) (space) for erase.
Machine Code Integration and Export Process
Option 4 provides a multi-step export procedure to patch the maze data into the original “Dungeon of Ymir” game. Two RAND USR calls are central to this process:
RAND USR 837: loads Part 2 of the game tape into memory (the maze data segment)RAND USR 8200: installs the new maze data from the designer into the game’s memory area
Line 4180 calls RAND USR 16514 to trigger a system-level routine, followed by NEW at line 4190 to reset BASIC. The SRAM (8K static RAM expansion) is required as temporary storage during the transfer. The process also involves re-saving the patched Part 2 back to tape, as described in the step-by-step on-screen instructions.
System Variable Manipulation
POKE 16418 appears repeatedly throughout the program. Address 16418 is the system variable FLAGS; poking it to 0 clears the print-suppression flag, ensuring output goes to the screen rather than the printer, while poking it to 2 at line 3010 redirects output. This is used carefully around SAVE to control what the system variable state is during tape operations.
Level Display
The print subroutine at line 8200 uses PRINT AT N,1;M$(L,N) to output each row of the current level’s maze slice as a string, exploiting the fact that slicing a 2D sub-array of a 3D string array returns a string of the full row width. Line 8230 displays the level number using CHR$(L+156), which maps levels 1–9 to characters 157–165 — the UDG character range, though here it relies on the game’s own character definitions being present.
Notable Anomalies
- Line 2030 lists “4: NORTH-WEST” twice (for both keys 2 and 4), though the movement code at line 2260 makes key 4 move northeast (east + north). This is a display bug in the help text.
- The introductory sequence calls
CLEARat line 9080 before jumping to line 100 whereDIM M$(9,20,30)is declared — this intentionally wipes any previous array contents, fulfilling the “CLEAR” semantics without losing the program itself. - The “press any key” subroutine at lines 8420–8430 first waits for all keys to be released, then waits for a keypress — a standard debounce pattern to avoid immediately consuming a prior keypress.
Content
Image Gallery
Source Code
1 REM E(RND)~~ ;)=4▘/+#[B]C▝Y▛>7<"#[L]4 PAUSE 5[F]RND)▒4▘£ GOSUB [K]TAN ▘/+5=4) # GOSUB [K]TAN
10 GOTO 9000
100 DIM M$(9,20,30)
110 LET WL=8000
120 LET FRAME=8100
130 LET PRINT=8200
140 LET CLEAR2=8300
150 LET CLEAR1=8320
160 LET KEY=8400
200 LET MENU=500
210 LET M=0
220 LET R=NOT M
230 LET C=NOT M
500 CLS
510 PRINT "[M][E][N][U][:]",,"0: START ANEW (CLEARS DUNGEON)","1: VIEW A MAZE",,"2: EDIT A MAZE",,"3: SAVE DUNGEON TO TAPE","4: INSTALL DUNGEON"
520 LET Z$=INKEY$
530 IF Z$="" THEN GOTO 520
540 IF Z$<"0" OR Z$>"4" THEN GOTO MENU
550 GOTO 1000*VAL Z$
1000 CLS
1010 GOSUB WL
1020 GOSUB FRAME
1030 GOSUB CLEAR2
1035 GOSUB PRINT
1040 PRINT AT 23,5;"PRINT NEXT LEVEL? Y/N"
1050 IF INKEY$ ="N" THEN GOTO MENU
1060 IF INKEY$ <>"Y" THEN GOTO 1050
1070 LET L=L+1
1080 IF L=10 THEN LET L=1
1090 GOTO 1030
2000 CLS
2010 GOSUB FRAME
2020 PRINT AT 3,8;"[C][U][R][S][O][R]█[C][O][N][T][R][O][L][S][:]"
2030 PRINT AT 5,3;"1: SOUTH-WEST 5: WEST";AT 6,3;"2: NORTH-WEST 6: SOUTH";AT 7,3;"3: SOUTH-EAST 7: NORTH";AT 8,3;"4: NORTH-WEST 8: EAST"
2040 PRINT AT 10,2;"ENTER: CHANGE FILL/ERASE MODE";AT 12,3;"Q: RETURN TO MENU";AT 16,3;
2050 GOSUB WL
2060 GOSUB PRINT
2100 LET M=NOT M
2105 GOSUB CLEAR1
2110 PRINT AT 23,0;"MODE: ";("FILL" AND M);("ERASE" AND NOT M)
2200 PRINT AT R,C;"[*]";AT R,C;M$(L,R,C)
2210 LET Z$=INKEY$
2220 IF Z$="Q" THEN GOTO MENU
2230 IF Z$=CHR$ 118 THEN GOTO 2100
2250 LET R=R+(Z$="6" OR Z$="1" OR Z$="3")-(Z$="7" OR Z$="2" OR Z$="4")
2260 LET C=C+(Z$="8" OR Z$="3" OR Z$="4")-(Z$="5" OR Z$="1" OR Z$="2")
2270 IF R>20 THEN LET R=1
2280 IF NOT R THEN LET R=20
2290 IF C>30 THEN LET C=1
2300 IF NOT C THEN LET C=30
2310 LET M$(L,R,C)=CHR$ (128*M)
2320 GOTO 2200
3000 CLS
3010 POKE 16418,2
3020 PRINT "SAVE TO TAPE: INPUT SAVE NAME.",,,,,"START TAPE BEFORE PRESSING ENTER"
3030 INPUT S$
3040 CLS
3050 PRINT "DUNGEON OF YMIR ALTERNATE MAZE: ",,"NAME: ";S$
3060 SAVE S$
3070 GOSUB KEY
3080 GOTO MENU
4000 CLS
4010 PRINT "ARE YOU SURE THAT THE DUNGEON ISAS YOU WANT IT?"
4020 PAUSE 4E4
4030 IF INKEY$ <>"Y" THEN GOTO MENU
4040 CLS
4050 PRINT "TO EXPORT YOUR NEW MAZE SET TO DUNGEON OF YMIR, PROCEED THUSLY:"
4060 PRINT ,,"1: BE SURE THAT YOUR 8K SRAM IS [E][N][A][B][L][E][D]. MAZES WILL BE TEMPO- RARILY STORED THERE."
4070 PRINT ,,"2: THIS PROGRAM WILL NEW ITSELF. WHEN THE CURSOR RE-APPEARS, ENTER [F][A][S][T] MODE."
4080 PRINT ,,"3: POSITION YOUR ORIGINAL D OF Y TAPE TO THE START OF PART 2."
4090 PRINT ,,"4: ENTER [R][A][N][D]█[U][S][R]█[8][3][7] AND START THE TAPE IN PLAY MODE."
4100 PRINT ,,"5: WHEN LOADED WITH ERROR C/0, ENTER [R][A][N][D]█[U][S][R]█[8][2][0][0]. THIS IN- STALLS THE NEW MAZE."
4110 GOSUB KEY
4120 PRINT "6: PUT YOUR NEW TAPE INTO YOUR RECORDER, AND POSITION TO JUST AFTER THEN END OF PART 1."
4130 PRINT ,,"7: SAVE THE MODIFIED PART TO YOUR TAPE BY ENTERING [G][O][T][O]█[2]."
4140 PRINT ,,"8: AFTER SAVING, THE PROGRAM WILL RUN, BUT THE COVER SCREEN WILL BE MESSED UP. THE PROPER SCREEN WILL BE DISPLAYED ON RE-LOADING LATER."
4150 PRINT ,,,,"[R][E][A][D]█[I][N][S][T][R][U][C][T][I][O][N][S]█[A][G][A][I][N][?]█[Y][/][N]"
4160 IF INKEY$ ="Y" THEN GOTO 4000
4170 IF INKEY$ <>"N" THEN GOTO 4160
4180 RAND USR 16514
4190 NEW
8000 PRINT "WHICH LEVEL? 1-9"
8010 LET L=CODE INKEY$ -28
8020 IF L<1 OR L>9 THEN GOTO 8010
8030 RETURN
8100 CLS
8110 POKE 16418,0
8120 PRINT "[▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒]";
8130 FOR N=0 TO 19
8140 PRINT "[▒]";TAB 31;"[▒]";
8150 NEXT N
8160 PRINT "[▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒][▒]";
8170 RETURN
8200 FOR N=1 TO 20
8210 PRINT AT N,1;M$(L,N)
8220 NEXT N
8230 PRINT AT 22,4;"[T][H][I][S]█[I][S]█[D][U][N][G][E][O][N]█[L][E][V][E][L]█";CHR$ (L+156)
8240 RETURN
8300 POKE 16418,0
8310 PRINT AT 22,0;" "
8320 POKE 16418,0
8330 PRINT AT 23,0;" "
8340 RETURN
8400 POKE 16418,0
8410 PRINT AT 23,0;"[P][R][E][S][S]█[A][N][Y]█[K][E][Y]█[T][O]█[C][O][N][T][I][N][U][E][.][.][.][.][.][.][.]"
8420 IF INKEY$ <>"" THEN GOTO 8420
8430 IF INKEY$ ="" THEN GOTO 8430
8440 CLS
8450 RETURN
9000 CLS
9010 PRINT "[C][U][S][T][O][M]█[M][A][Z][E][S]█[F][O][R]█[D][U][N][G][E][O][N]█[O][F]█[Y][M][I][R]",,"THIS PROGRAM LETS YOU DESIGN ANDINSTALL YOUR OWN MAZES FOR VERSN3 OF ""DUNGEON OF YMIR"""
9020 PRINT ,,"START BY LOADING ""YMIR"" (PART","1), AND BREAK WHEN LOADED. SAVE TO A NEW BLANK TAPE WITH GOTO 2."
9030 PRINT ,,"THEN LOAD THIS PROGRAM TO DESIGNYOUR NEW MAZES. FROM THE MENU, YOU MAY EDIT, SAVE, REVIEW, OR ""EXPORT"" (INSTALL) NEW ""DUNGEON"""
9040 PRINT ,,"[R][U][N] OR [C][L][E][A][R] ZAPS YOUR WORK. TO RE-START AFTER BREAK, ENTER [G][O][T][O]█[M][E][N][U]."
9050 PRINT ,,"YOU MAY MAKE YOUR MAZE LEVELS ASSIMPLE OR AS COMPLEX AS YOU LIKE"
9060 SLOW
9070 GOSUB 8400
9080 CLEAR
9090 GOTO 100
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.