Einstein 256 Primer cover: Graphics 7's 256 colours on the Einstein 256's screen
← Back to Modules
module
12

More Pixels, More Colours

Introduction

Graphics 4 gave every dot its own colour. The 256 has three more bitmap modes, each trading something for something else: more dots across, more colours, or more lines. All of them cost video memory, and some of them cost it twice over. This section shows you each one and what it costs, so you can choose.

Four Bitmap Modes

All four are set by register 0 and laid out the same way: line after line, from the start of the page.

ModeR#0Dots acrossColoursDots a byteBytes a line
Graphics 406h25616, from the palette2128
Graphics 508h5124, palette entries 0-34128
Graphics 60Ah51216, from the palette2256
Graphics 70Eh256256, fixed1256

The 512-dot modes fit twice as many dots into the same width of screen. Each dot is half as wide: fine detail, small text, thin lines.

Graphics 5: 512 Dots, Four Colours

Each byte holds four dots, the leftmost in bits 7-6, then 5-4, 3-2 and 1-0. Each pair is a colour number 0 to 3, and those are palette entries 0 to 3. The dot at (x, y) is in byte

y*128 + x/4

Bytes a line and bytes a screen are the same as Graphics 4: you trade colours for dots. Four colours from 512 is enough for a sharp, hi-res playfield in a chosen scheme, and S6's palette chooses them. Plotting a dot is S11's read-modify-write with a 2-bit mask: AND out the dot's two bits, OR in the colour shifted to them.

Its pages are 32K, as Graphics 4's are: R#2 = 3Fh shows the page at 08000h, and 5Fh the one at 10000h.

Graphics 6: 512 Dots, Sixteen Colours

Graphics 6 is Graphics 4 with twice the dots. Two dots a byte, the left dot in the high nibble, but 256 bytes a line:

y*256 + x/2

S11's plot works with one change: the address. y is the whole high byte and x/2 the low byte, which is even simpler.

A Graphics 6 screen is twice the size of a Graphics 4 one, so its pages are 64K: R#2 = 1Fh shows 00000h and 3Fh shows 10000h. There are two of them in the 128K. The page at 00000h covers MOS's screen, so a Graphics 6 game of your own uses the page at 10000h.

Graphics 7: 256 Colours

In Graphics 7 each byte is one dot, and the byte is the colour. There is no palette:

bit:   7  6  5   4  3  2   1  0
       G  G  G   R  R  R   B  B

Green and red have three bits each, levels 0 to 7, shown as 0, 36, 73, 109, 146, 182, 219 and 255. Blue has two bits, shown as levels 0, 2, 4 and 7: 0, 73, 146 and 255. So E0h is full green, 1Ch full red, 03h full blue, FFh white and 92h a mid grey (146, 146, 146). Writing the palette port changes nothing on a Graphics 7 screen.

The border follows suit: in Graphics 7, register 7 is read as a colour byte too, and so is every dot of colour 00h, which shows the border instead of black. Write 00h to register 7 and both are black.

Plotting is a plain write: one dot is one byte, so there is nothing to read first. The address is y*256 + x. The pages are 64K, as in Graphics 6: 1Fh and 3Fh show 00000h and 10000h.

Graphics 7 is for pictures: title screens, shaded backgrounds, a sky shaded from one colour to another without touching the palette. The price is a screen twice the size of Graphics 4's for the same 256 dots across.

212 Lines in Every Mode

Register 9's LN bit (bit 7, S11) works in all four modes. With it, each shows 212 lines, the extra 20 being lines 192 to 211 of the page.

424 Lines: Interlace

The 256 can weave two pages into one picture of twice the height. In one field it shows the even page, in the next field the odd page, each line of one falling between two lines of the other. In Graphics 6 that is 512 x 424.

Three settings do it:

  • R#2 on the odd page: 3Fh in Graphics 6, the page at 10000h. The even page is the one at 00000h.
  • R#9 bits 3 (IL) and 2 (EO) set.
  • R#9 bit 7 (LN) set as well, for 212 lines from each page. Without it you get 2 x 192 = 384.
        LD A, 3Fh
        LD B, 2
        CALL setreg     ; R#2: the odd page, 10000h
        LD A, 8Eh       ; LN + IL + EO + 50 Hz
        LD B, 9
        CALL setreg

Each line of the picture comes from the two pages in turn. The cost is both 64K pages: all 128K of the main video memory. MOS's screen in the even page goes with it, so a program using interlace leaves MOS to rebuild its screen with BE.

What Each Costs

192 lines212 linesPage sizePages in 128KPlotting a dot
Graphics II (TC-01)12,288--1 (16K)read-modify-write a bit
Graphics 424,57627,13632K4read-modify-write a nibble
Graphics 524,57627,13632K4read-modify-write 2 bits
Graphics 649,15254,27264K2read-modify-write a nibble
Graphics 749,15254,27264K2one write
Graphics 6 interlaced98,304108,544both1read-modify-write a nibble

Bytes are also time. Every full redraw sends all of a screen's bytes through port 8, so a Graphics 6 or 7 screen takes twice as long to clear or redraw as a Graphics 4 one. The pages matter too: S13 flips between two pages to hide drawing, and S17 keeps graphics in spare pages. Graphics 4 and 5 leave room for both; Graphics 6 and 7 have exactly two pages and nothing spare.

MOS's Own Graphics 6

MOS can set up Graphics 6 for you, and go on printing on it. SETMOD, MCAL 92h, takes a number in HL and sets the screen:

HLScreen
0Graphics II, 32 columns
1Graphics II, 40 columns (MOS's usual screen)
2Text 2, 80 columns (S18)
3, 4, 5, 6Graphics 6, 32, 40, 64 or 80 columns

It clears the screen. A number above 6 returns with carry set and changes nothing. At the > prompt the command S0 to S6 does the same.

In Graphics 6, MOS lays out the 64K page at 00000h like this:

AddressWhat MOS keeps there
0000h-BFFFhthe bitmap: 192 lines of 256 bytes. MOS draws its text here
E800ha copy of the screen's text, as characters
F000hthe font, which is also the sprite patterns
F800hthe sprite colour table
FA00hthe sprite attribute table
FA80hthe function-key table

The bitmap is an ordinary Graphics 6 bitmap. You can draw in it with the formula above and MOS will print over your drawing, so a program can mix MOS's text with lines, bars and charts. Keep to 0000h-BFFFh, and leave everything from E800h up to MOS.

One trap. After setting Graphics 6, MOS leaves register 15 at 2, so a read of port 9 returns status register 2, not 0. The frame interrupt handler in frame.asm reads port 9 to clear the frame flag. With R#15 at 2 it reads the wrong register and the interrupt is never cleared. Set R#15 to 0 before you turn the interrupt on.

The Code: 256 Colours

The first program shows every Graphics 7 colour at once, as a 16 x 16 grid, on the page at 10000h.

; S12: all 256 colours of Graphics 7 at once.
;
; Graphics 7: one byte a dot, 256 bytes a line. The byte IS the colour,
; GGGRRRBB, and the palette plays no part. Pages are 64K: R#2 = 3Fh shows
; the one at 10000h, above MOS's screen.
;
; A 16 x 16 grid of blocks, 16 dots by 12 lines each, 192 lines in all.
; Block (column c, row r) is colour r*16 + c: across a row the low four
; bits change (blue, and red's two low bits), down the grid the high four
; (red's top bit, and green). Shown for 250 frames, then back to MOS.
; MOS's BE puts R#7 back.

        ORG 256

        DI
        LD A, 0Eh
        LD B, 0
        CALL setreg     ; R#0 = 0Eh: Graphics 7 - before writing the page
        LD A, 3Fh
        LD B, 2
        CALL setreg     ; R#2 = 3Fh: show the 64K page at 10000h
        XOR A
        LD B, 7
        CALL setreg     ; R#7 = 00h: in G7 the border is a colour byte too,
                        ; and dots of colour 00h show it

        ; --- the sprites' own attribute table at 1FA00h (line 250 of
        ;     the page, below the picture): only Y = 216
        LD A, 7
        LD B, 14
        CALL setreg
        XOR A
        OUT (9), A
        LD A, 3Ah + 40h
        OUT (9), A
        LD A, 216
        OUT (8), A
        LD A, 0F7h
        LD B, 5
        CALL setreg
        LD A, 03h
        LD B, 11
        CALL setreg

        ; --- the grid, written as one run from 10000h: 192 lines
        LD A, 4
        LD B, 14
        CALL setreg     ; R#14 = 4: 10000h
        XOR A
        OUT (9), A
        LD A, 40h
        OUT (9), A      ; address 0000h, for writing
        LD D, 0         ; D = the colour at the start of this row of blocks
grow:   LD E, 12        ; 12 lines a block
gline:  LD C, D         ; this line starts at colour D
        LD H, 16        ; 16 blocks across
gblock: LD B, 16        ; 16 dots a block, a byte each
        LD A, C
gdot:   OUT (8), A
        DJNZ gdot
        INC C           ; next colour along
        DEC H
        JR NZ, gblock
        DEC E
        JR NZ, gline
        LD A, D
        ADD A, 16       ; next row of blocks: 16 colours on
        LD D, A
        JR NZ, grow     ; 256 colours = 16 rows, then D wraps to 0

        ; --- show it for 250 frames, then MOS's screen back
        CALL irqon
        LD A, 0E0h
        LD B, 1
        CALL setreg     ; display on, frame interrupt on
        EI
        LD B, 250
hold:   PUSH BC
        CALL waitf
        POP BC
        DJNZ hold
        LD A, 0C0h
        CALL irqoff
        CALL tomos
        RET

onframe: RET

        INCLUDE "frame.asm"

Build and run

Save it as s12-256-colours.asm next to frame.asm. Build and run it as in S2.

What you should see

A black border round a grid of 256 coloured blocks, 16 across and 16 down, filling the 192-line picture. The top-left block is black. Along each row the colour steps through four blues, then repeats with a touch more red, four times over. Down the grid, more red and then more green come in, so the bottom-right block is white. No two blocks are the same colour.

All 256 Graphics 7 colours in a 16 by 16 grid

After five seconds, MOS's screen comes back.

The Code: Drawing on MOS's Graphics 6

The second program asks MOS for its Graphics 6 screen, prints on it, draws on it, prints again, and puts MOS's usual screen back.

; S12: MOS's own Graphics 6 screen - 512 dots across, and MOS still prints.
;
; SETMOD (MCAL 92h) with HL = 4 sets Graphics 6 with 40 columns of text
; and clears it. MOS keeps its bitmap at 0000h-BFFFh: 256 bytes a line,
; two dots a byte, left dot in the high nibble. The program prints, draws
; in the same bitmap, prints again, holds the picture for 250 frames and
; puts MOS's usual screen back with SETMOD HL = 1.

        ORG 256

        LD HL, 4
        RST 8
        DEFB 92h        ; SETMOD: Graphics 6, 40 columns, cleared

        LD HL, title
        CALL print

        DI
        ; --- a white line across all 512 dots, on line 20
        LD D, 20
        LD E, 0FFh      ; colour 15 in both nibbles
        CALL gline

        ; --- 16 bars, one per colour, 32 dots (16 bytes) wide, lines 40-79
        LD D, 40
bars:   CALL gaddr      ; the start of line D
        LD C, 0         ; colour 0 ...
bar1:   LD A, C
        RLCA
        RLCA
        RLCA
        RLCA
        OR C            ; ... in both nibbles
        LD B, 16
bar2:   OUT (8), A
        DJNZ bar2
        INC C
        BIT 4, C
        JR Z, bar1      ; colours 0-15
        INC D
        LD A, D
        CP 80
        JR NZ, bars

        ; --- a band of single dots: white, black, white, black ...
        LD D, 90
fine:   LD E, 0F1h      ; one white dot, one black dot
        CALL gline
        INC D
        LD A, D
        CP 100
        JR NZ, fine

        XOR A
        LD B, 14
        CALL setreg     ; R#14 back to 0
        EI
        LD HL, more
        CALL print      ; MOS prints on, over our dots

        ; --- SETMOD left R#15 = 2. Set it to 0 BEFORE the frame interrupt:
        ;     the handler reads port 9, and must read S#0 to clear the flag.
        DI
        XOR A
        LD B, 15
        CALL setreg
        CALL irqon
        LD A, 0E0h
        LD B, 1
        CALL setreg     ; display on, frame interrupt on
        EI
        LD B, 250
hold:   PUSH BC
        CALL waitf
        POP BC
        DJNZ hold
        LD A, 40h
        CALL irqoff     ; frame interrupt off, MOS's table back

        LD HL, 1
        RST 8
        DEFB 92h        ; SETMOD: MOS's usual Graphics II, 40 columns
        RET

onframe: RET

; --- gaddr: write address of the start of line D (0-191) of MOS's
;     Graphics 6 bitmap: D*256 = R#14 (D/64), then (D mod 64)*256
gaddr:  LD A, D
        RLCA
        RLCA
        AND 3           ; D / 64
        LD B, 14
        CALL setreg     ; R#14
        XOR A
        OUT (9), A      ; low byte 0
        LD A, D
        AND 3Fh
        OR 40h
        OUT (9), A      ; high six bits, for writing
        RET

; --- gline: fill line D with byte E (256 bytes = 512 dots)
gline:  CALL gaddr
        LD B, 0         ; 256 times
gl1:    LD A, E
        OUT (8), A
        DJNZ gl1
        RET

; --- print: the text at HL, up to a 0, through MOS
print:  LD A, (HL)
        OR A
        RET Z
        RST 8
        DEFB 158
        INC HL
        JR print

title:  DEFB "MOS'S OWN GRAPHICS 6: 512 DOTS ACROSS", 13, 10, 0
more:   DEFB "AND MOS STILL PRINTS", 0

        INCLUDE "frame.asm"

Build and run

Save it as s12-mos-graphics-6.asm next to frame.asm. Build and run it as in S2.

What you should see

On MOS's blue, two lines of MOS's text at the top:

MOS'S OWN GRAPHICS 6: 512 DOTS ACROSS
AND MOS STILL PRINTS

Under them, a thin white line right across the picture. Below that, sixteen bars in the sixteen colours, from colour 0 on the left (the same blue as the border) to white on the right. Below the bars, a band ten lines deep that looks grey: up close it is white and black dots, alternating every single dot, 512 of them across the line.

MOS's Graphics 6 screen with text, a white line, sixteen colour bars and a band of single-dot stripes

After five seconds the usual 40-column screen comes back, cleared, with the register display and the prompt.

Change One Thing

  • In s12-256-colours.asm, change R#0 from 0Eh to 0Ah. The bytes are the same. What does each block look like now, and why is the picture twice as wide in dots?
  • Then change R#0 to 08h instead. The screen changes completely, and not just in its colours. Which page is it showing now?
  • In s12-mos-graphics-6.asm, change SETMOD's HL from 4 to 6. What happens to the text, and to your drawing?
  • Take out the three lines that set R#15 to 0. What does the program do now?

When It Goes Wrong

SymptomCause
In Graphics 7 the dots you meant to be black come out the border's colourColour 00h shows register 7. Set R#7 to 00h for a black border and black dots

Summary

You know the four bitmap modes and what each trades: Graphics 5 and 6 for 512 dots across, Graphics 7 for 256 fixed colours, interlace for 424 lines. You know what each screen costs in bytes and in pages, and you can draw on MOS's own Graphics 6 screen while MOS prints on it.

Next

S13, Flicker-Free: two pages, one shown while the other is drawn.

Get the Newsletter

New guides, disk images and community finds, roughly once a quarter. No spam, we promise, this isn't Tatung's marketing department.
Your subscription could not be saved. Please try again.
Your subscription has been successful.

Newsletter

Subscribe to our newsletter and stay updated.