Scene ASM Example

Displaying an Exported .scr File on Real Z80 Hardware
by Norbert of Norbsoft

The Scene Editor's Export SCR button saves your drawing as a 6912-byte .scr file — the standard ZX Spectrum screen format used by emulators and snapshot tools. The first 6144 bytes are the pixel bitmap (the display file) and the final 768 bytes are the attribute data (ink, paper, bright and flash for each 8x8 cell).

To show a .scr file on real (or emulated) hardware, you need to get those 6912 bytes into screen memory at $4000-$5AFF. This example shows the simplest way to do that with INCBIN.

This example is written for Pasmo with the --tapbas flag, producing a .tap file that auto-runs in an emulator such as Fuse with --auto-load — exactly the workflow described in the Z80 Assembly Introduction.

Scene: Loading an Exported .scr File

[Back to top]

Embedding the .scr File with INCBIN

INCBIN (supported by Pasmo, NASM, z80asm and most modern Z80 assemblers) pulls a binary file's raw bytes directly into the assembled output at the point it appears, with a label pointing at the start of those bytes:

screen_data:
        incbin  "myscreen.scr"   ; embeds all 6912 bytes

This is by far the simplest way to bundle exported scene data with your program — there's no parsing required, just a label marking where the bytes begin.

Copying to Screen Memory

The display file occupies $4000-$57FF (6144 bytes) and the attribute file immediately follows at $5800-$5AFF (768 bytes). Two ldir blocks copy the embedded data straight into place:

        ld      hl, screen_data
        ld      de, $4000       ; display file ($4000-$57FF)
        ld      bc, 6144
        ldir
        ld      hl, screen_data + 6144
        ld      de, $5800       ; attribute file ($5800-$5AFF)
        ld      bc, 768
        ldir

screen_data + 6144 skips past the pixel bitmap to the start of the attribute bytes within the embedded file — the same split the Scene Editor uses when it writes the .scr file. Once both ldirs complete, the screen updates immediately because we've written directly into the memory the ULA reads from to generate the display — no further drawing instructions are needed.

Source: scene_viewer.asm

Here is the complete viewer. It expects a file named myscreen.scr in the same folder — the name the Scene Editor's Export SCR dialog suggests by default, though you can rename it to anything as long as the incbin line below matches:

; scene_viewer.asm
;
; Loads a 6912-byte .scr file (exported by the ZX Spectrum Scene Editor)
; and copies it into screen memory ($4000-$5AFF), displaying it full-screen.
;
; Assemble:  pasmo --tapbas scene_viewer.asm scene_viewer.tap
; Run:       fuse --auto-load scene_viewer.tap

        org     $8000

start:
        ld      hl, screen_data
        ld      de, $4000       ; display file ($4000-$57FF)
        ld      bc, 6144
        ldir
        ld      hl, screen_data + 6144
        ld      de, $5800       ; attribute file ($5800-$5AFF)
        ld      bc, 768
        ldir

halt_loop:
        halt
        jr      halt_loop

screen_data:
        incbin  "myscreen.scr"

        end     start

Assembling and Running

To try this with your own scene: export it from the Scene Editor as myscreen.scr (or edit the incbin line to match whatever filename you chose), place it in the same folder as scene_viewer.asm, then assemble and run it as described in the Z80 Assembly Introduction:

pasmo --tapbas scene_viewer.asm scene_viewer.tap && fuse --tape scene_viewer.tap --auto-load

The --tapbas flag wraps the assembled machine code in a small BASIC loader so the resulting .tap auto-runs when loaded; --auto-load tells Fuse to insert and run the tape image immediately on startup. Your scene should appear full-screen as soon as the program runs.