Dringtendo64

Dringtendo is a simple games console based on a Harvard CPU architecture. The CPU has a similar instruction set to a Little Man Computer (LMC) which has been extended to support immediate, indirect and indexed addressing modes as well as direct.

There are 256 bytes of data memory, some of which are mapped to hardware devices such as 64 sprite tiles and 5 buttons.

It's designed for A Level Computer Science students who want to get past the limitations of LMC and explore different addressing modes, interrupts and an alternative to a Von Neumann CPU.

LMC Instruction Set

All Little Man Computer instructions should work on the Dringtendo:

InstructionExampleExplanation
ADD dataADD 1Add value at data memory address 1 to ACC
SUB dataSUB 2Subtract value at data memory address 2 from ACC
STA dataSTA 3Save ACC to data memory address 3
LDA dataLDA 4Load value at data memory address 4 into ACC
BRA instructionBRA 5Branch to instruction memory address 5 (always)
BRZ instructionBRZ 6Branch to instruction memory address 6 (if ACC is zero)
BRP instructionBRP 7Branch to instruction memory address 7 (if ACC is positive)
INPINPInput to ACC
OUTOUTOutput ACC value
HLTHLTStop program

Addressing modes

There four addressing modes supported:

Addressing modeExampleExplanation
ImmediateLDA #100Load 100 into ACC
DirectLDA @100Load value from data memory address 100 into ACC
IndirectLDA ~100Use address in data memory address 100 to load value into ACC
Indexed (immediate offset)LDA [100]Load value from data memory address IR+100 into ACC
Indexed (direct offset)LDA [Label]Load offset from labelled data memory location and set ACC to data value at IR+offset

Additional instructions

As well as the Little Man Computer instruction set, there are some additional instructions:

InstructionExampleExplanation
LDIR dataLDIR #69Load immediate value 69 into Index Register
LDISR instructionLDISR #0Set interrupt service routine address to 0 (disable interrupts)
LDISR instructionLDISR #40Set interrupt service routine address to 40 (interrupt calls instruction at address 40)
PUSHPUSHPush value in ACC on to the stack
POPPOPPop value from stack into ACC
CALL instructionCALL 23Push PC on to stack then set PC to instruction
RETRETReturn from sub routine (pop address from stack into PC)
RNDRND #5Place a random number between 0 and 5 (inclusive) into the accumulator register
The following mnemonics are not instructions as they relate to how data is stored in data memory:
MnemonicExampleExplanation
ORGORG 69Set the next data memory address to 69 (after all sprite and button memory locations)
DAT

DAT 3

DAT 2

Stores the literal value 3 at the next available data location (69) then the value 2 into location 70

Examples:

Save
// Display HELLO WORLD
ORG 25		// set next data memory address to 25
Letters: DAT 72	// ASCII 72 is 'H'
DAT 69
DAT 76
DAT 76
DAT 79
DAT 0
DAT 0
DAT 0
DAT 87
DAT 79
DAT 82
DAT 76
DAT 68
DAT 0
DAT 0
DAT 0
															
Save
// Caesar cipher (no wrapping around alphabet)
INP // input the caesar shift
STA Shift

CALL CaesarShift    // shift HELLO

LDA #33
STA StartPos
LDA #4
STA CharCount
CALL CaesarShift    // shift WORLD
HLT

CaesarShift: LDIR StartPos
LDA [CharCount]
ADD Shift
STA [CharCount]
LDA CharCount
SUB #1
STA CharCount
BRP CaesarShift
RET


ORG 69
Shift: DAT
CharCount: DAT 4
StartPos: DAT 25

ORG 25		// set next data memory address to 25
Hello: DAT 72	// ASCII 72 is 'H'
DAT 69
DAT 76
DAT 76
DAT 79
DAT 0
DAT 0
DAT 0
World: DAT 87
DAT 79
DAT 82
DAT 76
DAT 68
DAT 0
DAT 0
DAT 0
															
															
Save
// Fill screen with smiles
LDA #97 // Smiley face
STA BackgroundSprite
CALL FillScreen

LDA #98 // Sad face
STA BackgroundSprite
CALL FillScreen
HLT

FillScreen: LDA #63 // Copy BackgroundSprite into 0-63
STA i
ScreenLoop: LDA BackgroundSprite
STA ~i // indirect addressing (i stores an address)
LDA i
SUB #1 // decrease address
STA i
BRP ScreenLoop // repeat for each screen cell
RET

ORG 69 // set next memory address to 69 (after screen and buttons)
BackgroundSprite: DAT 5
i: DAT 63
															
Save
// Move a sprite around the screen using interrupts
LDISR Button // Set interrupt handler

CALL UpdateScreen	// Clear background and draw player
HLT

Button: LDA Up // Interrupt handler

BRZ NoBtnUp // Check if up button was pressed
LDA pos
SUB #8
STA pos
LDA #0
STA Up

NoBtnUp:LDA Down // Check if Down button was pressed
BRZ NoBtnDown
LDA pos
ADD #8
STA pos
LDA #0
STA Down

NoBtnDown: LDA Left // Check if Left button was pressed
BRZ NoBtnLeft
LDA pos
SUB #1
STA pos
LDA #0
STA Left

NoBtnLeft: LDA Right // Check if right button was pressed
BRZ NoBtnRight
LDA pos
ADD #1
STA pos
LDA #0
STA Right

NoBtnRight: CALL UpdateScreen // Update screen
RET

UpdateScreen: CALL ClearScreen // Display game
LDA player
STA ~pos
RET

ClearScreen: LDA #63 // Clear game background
STA i
ScreenLoop: LDA Background
STA ~i
LDA i
SUB #1
STA i
BRP ScreenLoop
RET

ORG 64 // Start putting labels at address 64 (mapped to up button)

Up:DAT // Buttons
Down:DAT
Left:DAT
Right:DAT

i: DAT              // Used for looping through each pixel
pos: DAT            // Player position 
background: DAT 50  // Background sprite
player: DAT 41      // Player sprite