The Project Story

A personal project of mine. I have always been fascinated by retro-computing and low-level hardware architecture, especially the Intel MCS-4 system. However, modern emulators often rely on high-level abstractions that hide the actual constraints of the era.

Quadium 4004 Workbench is a Windows desktop laboratory designed to learn and experiment with a complete, hardware-faithful system. It is centered on the Intel 4004 CPU but models everything: ROM, RAM, shift registers, inter-chip bus, and peripherals.

Core Features & Architecture

From High-Level to 4-Bit Reality: Code Transpilation to understand how the QuadBasic transpiler bridges the gap between readable code and raw Intel 4004 constraints, here is a practical compilation example. When you write a single string statement to target the display, the workbench generates the historical MCS-4 assembly architecture, populates the variable maps, maps the CPU registers, and setups the page-F runtime stubs dynamically. 

 The Source Input

10 PRINT @SCREEN, "Hi hackaday.io"
20 END

The Transpiled Intel 4004 Assembly (Raw Output)

; ===== Basic4 mini-BASIC => 4004 ASM =====
; R0..R9   : user NIBBLE variables (see Variable Map).
; R10 (T0) : expression temp, logic operand A, JMS results.
; R11 (T1) : expression temp, logic operand B, print char HI.
; R12 (ADR): FIM/SRC address (4*chip+reg); decimal quotient.
; R13 (DIG): FIM digit; print-started flag; PRINTDEC scratch.
; R14 (WLO): wide scalar low nibble (BYTE).
; R15 (WHI): wide scalar high nibble (BYTE).
; BYTE lives in RAM; R14/R15 are a per-statement window.
; System RAM: RAM[3,3,2,*] and RAM[3,3,3,*] (compiler/runtime scratch). Carry @ [3,3,3,0].

; =====================================================================
; BASIC4 VARIABLE MAP
; =====================================================================
; #   Name       Type          Storage
; --- ---------- ------------- ------------------------------------------
; --- ---------- ------------- ------------------------------------------
; Registers used: none of R0..R9            (10 free)
; RAM used:       0 nibbles
; =====================================================================

        ORG 0000H
; --- INIT OUTPUT DEVICE @SCREEN ---
        LDM 0                   ; 0=SCREEN
        JMS B4_SETDEV

L10:
; --- SELECT OUTPUT DEVICE (RAM[3,3,3,13]) ---
        LDM 0
        JMS B4_SETDEV

; 10 PRINT @SCREEN, "Hi hackaday.io"
;   char 'H' = 72 (0x48)
        LDM 8
        XCH R10
        LDM 4
        XCH R11
        JMS B4_PRINTCHAR
;   char 'i' = 105 (0x69)
        LDM 9
        XCH R10
        LDM 6
        XCH R11
        JMS B4_PRINTCHAR
;   char ' ' = 32 (0x20)
        LDM 0
        XCH R10
        LDM 2
        XCH R11
        JMS B4_PRINTCHAR
;   char 'h' = 104 (0x68)
        LDM 8
        XCH R10
        LDM 6
        XCH R11
        JMS B4_PRINTCHAR
;   char 'a' = 97 (0x61)
        LDM 1
        XCH R10
        LDM 6
        XCH R11
        JMS B4_PRINTCHAR
;   char 'c' = 99 (0x63)
        LDM 3
        XCH R10
        LDM 6
        XCH R11
        JMS B4_PRINTCHAR
;   char 'k' = 107 (0x6B)
        LDM 11
        XCH R10
        LDM 6
        XCH R11
        JMS B4_PRINTCHAR
;   char 'a' = 97 (0x61)
        LDM 1
        XCH R10
        LDM 6
        XCH R11
        JMS B4_PRINTCHAR
;   char 'd' = 100 (0x64)
        LDM 4
        XCH R10
        LDM 6
        XCH R11
        JMS B4_PRINTCHAR
;   char 'a' = 97 (0x61)
        LDM 1
        XCH R10
        LDM 6
        XCH R11
        JMS B4_PRINTCHAR
;   char 'y' = 121 (0x79)
        LDM 9
        XCH R10
        LDM 7
        XCH R11
        JMS B4_PRINTCHAR
;   char '.' = 46 (0x2E)
        LDM 14
        XCH R10
        LDM 2
        XCH R11
        JMS B4_PRINTCHAR
;   char 'i' = 105 (0x69)
        LDM 9
        XCH R10
        LDM 6
        XCH R11
        JMS B4_PRINTCHAR
;   char 'o' = 111 (0x6F)
        LDM 15
        XCH R10
        LDM 6
        XCH R11
        JMS B4_PRINTCHAR
        JMS B4_PRINTLF

L20:
; 20 END
        JUN QB4_END             ; END

QB4_END:
        JUN QB4_END             ; END of BASIC4 program (halt loop)


; ===== BASIC4 RUNTIME STUBS (page 0) =====
B4_PRINTLF:
        JUN B4_PRINTLF_F        ; jump to PRINTLF runtime in page F
B4_PRINTCHAR:
        JUN B4_PRINTCHAR_F      ; jump to PRINT CHAR runtime in page F
B4_SETDEV:
        JUN B4_SETDEV_F         ; jump to SETDEV runtime in page F


; ===== BASIC4 RUNTIME (page F @ 0F00H) =====
        ORG 0F00H
B4_PRINTCHAR_F:
; Entrada: R11 = HI nibble, R10 = LO nibble
        FIM 6P,020H             ; R12=2 (chip 2), R13=0 (port)
        SRC 6P                  ; select ROM2.PORT
        LD R10                  ; ACC = LO nibble
        WRR                     ; write LO to ROM2.PORT
        FIM 6P,010H             ; R12=1 (chip 1), R13=0 (port)
        SRC 6P                  ; select ROM1.PORT
        LD R11                  ; ACC = HI nibble
        WRR                     ; write HI to ROM1.PORT
        FIM 6P,000H             ; STROBE inline: R12=0 (ROM chip 0), R13=0 (port)
        SRC 6P                  ; select ROM0.PORT
        LDM 0                   ; strobe low
        WRR
        LDM 1                   ; strobe high (0->1 rising edge)
        WRR
        BBL 0                   ; return

B4_PRINTLF_F:
        FIM 6P,010H             ; ROM1 para HI de LF
        SRC 6P
        LDM 0
        WRR                     ; HI = 0
        FIM 6P,020H             ; ROM2 para LO de LF
        SRC 6P
        LDM 10                  ; LO = 0x0A (10 decimal)
        WRR
        FIM 6P,000H             ; STROBE inline: R12=0 (ROM chip 0), R13=0 (port)
        SRC 6P                  ; select ROM0.PORT
        LDM 0                   ; strobe low
        WRR
        LDM 1                   ; strobe high (0->1 rising edge)
        WRR
        BBL 0                   ; return, ACC=0

B4_SETDEV_F:
        XCH R10                 ; R10 = device id nibble
        LDM 3
        DCL                     ; bank 3
        FIM 6P,0FDH             ; R12=0x0F (4*3+3), R13=0x0D (digit 13)
        SRC 6P
        RDM                     ; ACC = current_id
        XCH R11                 ; R11 = current_id
        LD R10
        CLC
        SUB R11                 ; ACC = new_id - current_id
        JCN 4,B4_SETDEV_RET     ; if zero -> no change
        LD R10
        WRM                     ; write new id
B4_SETDEV_RET:
        BBL 0


Project Documentation & Manuals

Hardware manual (PDF)

QuadBasic reference manual (PDF)

VDP user guide (PDF)

Build Logs & Progress Updates

Update 01.06.2026
The Content Milestone: I have completed around 70 distinct educational lessons for the workbench. They are completely separate from the core user guides and the sandbox playground, covering everything from absolute low-level basics to advanced hardware architecture concepts.

Current Focus: Right now, I am heavily focused on developing the 8-bit Basic layer and refining the virtual Video Display Processor (VDP) to add more visual flavor to the simulation.

Project Roadmap & Support

This workbench is being developed as a standalone title targeted for a release in November 2026. 

If you are fascinated by the architecture of the 1971 hardware, want to test your own 4-bit logic loops, or just want to support an independent developer building hardware-faithful tools, please consider adding the project to your Steam Wishlist. Every bit of support helps keep the development going!

Wishlist Quadium 4004 Workbench on Steam