All the Things - Nakazoto/Hellorld GitHub Wiki

Hellorld! on All the Things

One of the greatest things about "Hellorld!" is it's really friendly for being displayed on all sorts of interesting displays, even 7-segment LED displays. This page is dedicated to getting all sorts of wild things to show "Hellorld!" Entries are in alphabetical order.

Quick links:

CARDIAC ENIAC Fluke DMM Psion Organiser II LZ
TI-83 / TI-86 Tranz 330 Credit Card POS VMU (Dreamcast) VTech Genius Leader 4000

CARDIAC

CARDIAC is short for CARDboard Illustrative Aid to Computation. It was created by Bell Labs to teach how computers work to school children. I use it in my introductory Computer Science class at Drexel University. For the purposes of Hellorld, the CARDIAC doesn't have textual output, so I have had it output the ASCII codes in decimal form. My CARDIAC page will tell you more than you ever want to know about it.

The assembly language code for Hellorld on the CARDIAC is as follows:

10	130	loop	CLA	msg
11	320		TAC	done
12	530	doout	OUT	msg
13	110		CLA	loop
14	200		ADD	00
15	610		STO	loop
16	112		CLA	doout
17	200		ADD	00
18	612		STO	doout
19	810		JMP	loop
20	900	done	HRS	00

30	072	msg	DATA	72, 101, 108, 108, 111, 114, 108, 100, 33, -1
31	101
32	108
33	108
34	111
35	114
36	108
37	100
38	033
39	-001

Running the code on an online implementation of the CARDIAC results in:

The following is a bootable card deck that can be put into the simulator and run.

002
800
010
130
011
320
012
530
013
110
014
200
015
610
016
112
017
200
018
612
019
810
020
900
030
072
031
101
032
108
033
108
034
111
035
114
036
108
037
100
038
033
039
-001
810

ENIAC

When it comes to Turing-complete machines it's hard to beat the ENIAC for uniqueness. Not only was there only ever one built, but its method of program control was very different from almost everything else. As originally built and used, operation sequencing was determined through patch cable wiring, rather than numerical encoding of instructions. (Later, instruction decoding was implemented on the ENIAC, and that's how it was programmed for most of its life. But that's a story for another time.) This page is where I attempt to document some subset of my trip down the rabbit hole with the ENIAC.

The ENIAC's output mechanism was an off-the-shelf IBM card punch. It was used exclusively for numerical output. For that reason, we are implementing Hellorld in terms of the numerical encodings of the characters. Because EBCDIC evolved from punched card representations of alphanumeric material, it seems the most appropriate encoding to use here. However, it's quite anachronistic, as EBCDIC didn't come into use until about 10 years after the ENIAC was retired.

A view of the simulator after the completion of the Hellorld! run:

image

A straight-on view of Accumulators 15-18 and Function Tables 2 and 3 after the 'r' character has been read from the function table but before it has been punched:

image

The programming is shown here in a sort of ENIAC "assembly language" configuration for an ENIAC simulator. Lines beginning with 'p' describe patch cable pluggings, those with 's' specify switch settings, and those with '#' are comments.

#
# Usagi Electric's Hellorld challenge
#

# EBCDIC characters in decimal on the second function table
# Mark the end of the string with a negative value and use the
# sign to determine whether we're continuing or halting.
s f2.mpm1 T
s f2.RA0S P
s f2.RA0L3 2
s f2.RA0L2 0
s f2.RA0L1 0
s f2.RA1S P
s f2.RA1L3 1
s f2.RA1L2 3
s f2.RA1L1 3
s f2.RA2S P
s f2.RA2L3 1
s f2.RA2L2 4
s f2.RA2L1 7
s f2.RA3S P
s f2.RA3L3 1
s f2.RA3L2 4
s f2.RA3L1 7
s f2.RA4S P
s f2.RA4L3 1
s f2.RA4L2 5
s f2.RA4L1 0
s f2.RA5S P
s f2.RA5L3 1
s f2.RA5L2 5
s f2.RA5L1 3
s f2.RA6S P
s f2.RA6L3 1
s f2.RA6L2 4
s f2.RA6L1 7
s f2.RA7S P
s f2.RA7L3 1
s f2.RA7L2 3
s f2.RA7L1 2
s f2.RA8S P
s f2.RA8L3 0
s f2.RA8L2 9
s f2.RA8L1 0
s f2.RA9S M
s f2.RA9L3 0
s f2.RA9L2 0
s f2.RA9L1 1

# Printing lower half of Acc 18
s pr.12 P

# Use the initial pulse to start the ball rolling
p i.Io 1-1

# Set up the data trunks
p 1 f2.arg
p f2.A 1
p a17.A 1
p 1 a18.α
p a18.A 1

# Start a function table lookup
p 1-1 f2.1i
s f2.op1 A0
s f2.cl1 NC
s f2.rp1 1
p f2.NC 1-2

# Transmit the table argument from Acc 17
p 1-2 a17.5i
s a17.op5 A
s a17.cc5 0
s a17.rp5 1
p a17.5o 1-3

# Increment the table argument in parallel with lookup
p 1-3 a17.6i
s a17.op6 ε
s a17.cc6 C
s a17.rp6 1
p a17.6o 1-4

# Clear Acc 18 in parallel with increment and lookup
p 1-3 a18.1i
s a18.op1 0
s a18.cc1 C

# Delay to end of FT loolup
p 1-4 a17.7i
s a17.op7 0
s a17.cc7 0
s a17.rp7 1
p a17.7o 1-5

# Transfer FT output to Acc 18
p 1-5 a18.5i
s a18.op5 α
s a18.cc5 0
s a18.rp5 1
p a18.5o 1-6

# Transmit Acc 18 subtractively.  The adapter connects
# the sign to control line 1-7.  Because we're transmitting
# subtractively, there will be no pulses for a negative number
# and 9 pulses for a positive number.  The pulses are sent
# through a dummy program to synchronize them with the
# central programming pulse and its output triggers the
# printing.  Completion of the printing starts the whole cycle
# over again.
p 1-6 a18.6i
s a18.op6 S
s a18.cc6 0
s a18.rp6 1
p a18.S ad.dp.1.11
p ad.dp.1.11 1-7
p 1-7 i.Pi
p i.Po 1-1

Fluke Digital Multimeter

This is my kind of crazy! Getting Hellorld! running on bonkers things is 100% up my alley, but a digital multimeter is taking it to an extreme that makes me smile ear-to-ear. The Fluke 45 is based upon a HD6303Y CPU from Hitachi, has a 16 bit address bus and 8 bit data bus. Hiding out on that address/data bus is a 64kb not-reprogrammable ROM, so Pengi got to work making an adapter to stuff an 8kB AT28C64B EEPROM in place and get the multimeter to do some tricky things.

The whole process is outlined here on Pengi's github..

Code: The code is a couple hundred lines long, and available in its entirety here. Included below is a short excerpt.

...
disp_d:
                TSX
                LDAB    $02,X              ; All calls use the same top argument
                PSHB

                JSR     disp_clear_digit

                LDAA    #1
                PSHA
                JSR     disp_set_segment
                PULA

                LDAA    #2
                PSHA
                JSR     disp_set_segment
                PULA

                LDAA    #3
                PSHA
                JSR     disp_set_segment
                PULA

                LDAA    #4
                PSHA
                JSR     disp_set_segment
                PULA

                LDAA    #6
                PSHA
                JSR     disp_set_segment
                PULA

                PULB
                RTS
...

Psion Organiser II LZ

The Psion Organiser launched in 1984 and was marketed as a full-on pocket computer. The Oragniser 2 shown here was released in 1986 as the successor the Organiser 1. The 2 was rocking an 8-bit Hitachi 6301 family processor, 64kb of battery backed RAM, and datapak support for expansion. The keyboard was “much improved” over the 1 model, but, you know, that still looks daunting. Which is even more impressive that Staven managed to get it to Hellorld! The code is just a string of raw hexadecimal that I have absolutely zero clue what means, but Staven has a Github dedicated to the project with all sorts of wonderful information.

Click here for Staven’s Github on this project.

Code:

CE0000200A48454C4C4F524C44210086193F14A600084D27043F1020F63F4839

TI-83 Plus / TI-86

Oooh, I'm 100% on board for this one! The TI-83 is really a highly specialized Z80 computer, which means it can do computery things, like print "Hellorld!" Which is exactly what stamasd over on the Discord did. After ordering a cable and a bit of code tweaking, stamasd was able to upload the assembled code and execute it on the real deal hardware, proving that even calculators can "Hellorld!" in style! But, they didn't stop there, stamasd got on a roll and managed to get it working on a TI-86 as well, absolutely epic!

TI-83 Plus Code:

.NOLIST
#define bcall(xxxx) rst 28h \ .dw xxxx
_newline    .equ 452Eh
_PutS        .equ 450Ah
_ClrLCDFull    .equ 4540h
.LIST
    .org 9D93h
    .db $BB,$6D
    ld a,0
    bcall(_ClrLcdFull)
    ld hl,tx1
    bcall(_NewLine) 
    bcall(_PutS)
    ld hl,tx2
    bcall(_NewLine) 
    bcall(_PutS)
    bcall(_NewLine)
    ret
tx1:
    .db "Hellorld!",0
tx2:
    .db "Courtesy of Z80",0
.end
.end

TI-86 Code:

_asm_exec_ram    .equ 0D748h
_clrLCD        .equ 4A7Eh
_curRow        .equ 0C00Fh
_curCol        .equ 0C010h
_puts        .equ 4A37h
_getkey        .equ 55AAh

.org     _asm_exec_ram 
    call _clrLCD
    ld a,0
    ld (_curRow),a
    ld a,0
    ld (_curCol),a
    ld hl,hellorld
    call _puts
    call _getkey
    ret

hellorld: .db "Hellorld!",0

.end
.end

Tranz 330 Credit Card Machine

The Tranz 330 is a Zilog Z80 based credit card terminal that uses standard Z80 peripherals and is very hacker friendly. As of 2023 these are still plentiful and cheap on the used market. I absolutely love seeing things like this get hacked for hilarious purposes. The Z80 is a wonderful little processor, and it makes perfect sense to use it in something like a Point of Sale device. But, being Z80 makes it perfect for "Hellorld!", which Andrew did and I absolutely adore it!

In the code below, spaces and newlines were eliminated to make it as compact as possible for display here. The full code, with comments, as well as information on how to implement is available on Andrew's Github at this link.

Code:

; Barebones program to write to the Tranz 330 VFD
; 2023 by Andrew Litt
            .ORG $0000
PIO_A_DAT   .EQU $00
PIO_A_CON   .EQU $01
STACK       .EQU $9000      ; seems like a decent place...
RST:
    DI                      ;interrupts stay off
    LD      HL, STACK       ; set up stack though we don't use it
    LD      SP, HL
    LD      A, $CF          ; enter PIO_A bit mode (3)
    OUT     (PIO_A_CON), A  ; next byte must be I/O direction
    LD      A, $80          ; All outputs except bit 7
    OUT     (PIO_A_CON), A
    LD      A, $07          ; disable PIO interrupts
    OUT     (PIO_A_CON), A  ; next byte must be GPIO int mask
    LD      A, $FF          ; PIO int mask (redundant)
    OUT     (PIO_A_CON), A
    LD      A, $3F          ; initial GPIO port state
    OUT     (PIO_A_DAT), A
    LD      A, $2F          ; assert display reset
    OUT     (PIO_A_DAT), A
    LD      B, $30          ; display reset hold time
VFD_RST_WAIT:
    DJNZ    VFD_RST_WAIT
    LD      A, $3F          ; deassert reset
    OUT     (PIO_A_DAT), A
    LD      HL, PAYLOAD
STRING_SEND_LOOP:
    LD      A, (HL)         ; test if the current string char is zero
    OR      A
    JR      Z, INFINITY
    LD      C, A

    LD      B, $08          ; 8 bits to xfer, MSB first
BIT_SEND_LOOP:
    IN      A, (PIO_A_DAT)  ; get current port state
    AND     A, $9F          ; mask off the CLK and DAT bits
    RLC     C               ; rotate left w/ MSb into carry
    JR      NC, BIT_IS_ZERO ; if the MSb is zero, skip setting it
    OR      A, $20          ; MSb is one, set the DAT bit to match
BIT_IS_ZERO:
    OUT     (PIO_A_DAT), A  ; data setup with CLK low
    OR      A, $40          ; toggle CLK high
    OUT     (PIO_A_DAT), A
    AND     A, $BF          ; toggle CLK low
    OUT     (PIO_A_DAT), A
    DJNZ    BIT_SEND_LOOP   ; next bit

    INC     HL              ; next byte
    JP      STRING_SEND_LOOP
INFINITY:
    JP      INFINITY
PAYLOAD:
    .BYTE   $FF             ; display to max brightness
    .BYTE   $AF             ; cursor to beginning of line
    .BYTE "    HELLORLD    ",0

Visual Memory Unit (Dreamcast)

The SEGA Dreamcast was a pretty righteous little game console, I remember being beyond hyped about Phantasy Star Online on the Dreamcast, but one of the coolest things about the Dreamcast was the memory card. It plugged into the controller, but it was so, so much more than a memory card. It was a full-fledged handheld game console by itself! It had an 8-bit Sanyo LC8670 CPU, a monochrome LCD, multiplayer gaming capability, second functionality, a real-time clock, file manager, 100KB of flash memory, and sound capability. All that in a memory card, absolutely bonkers!

But, can it "Hellorld"? Not easily. Fortunately, user insize over on the Discord is on the case! A lot of this is over my head, so I'll paraphrase here:

"The VMU has got only a bitmap so I had to program my own font engine. It's monospace to keep things simple but it still ended up getting pretty big. The font is encoded as Shift-JIS because it's the same that the VMU and Dreamcast use internally, it's a mix of Japanese characters with normal English ones (ASCII). The program first initializes the register and clears the screen to all zeroes. Then it enters the main loop to execute the print characters function. 'Print characters' gets called, and it first clears out some RAM to use as a buffer, and then initializes a few temporary registers. Then begins the print loop. First it takes a character from the string you fed it, then checks its value to see if it matches these ranges: 0x20 trough 0x80 for English characters or 0xA0 trough 0xE0 Japanese characters. If either fail it "prints" a blank char (skips the process and goes to the next char). Then it checks if the print position is odd or even, and if it's odd it has to shift the character 4 pixels to the right because the screen is encoded with the good ol' horizontal bytes. It then masks the new character, stores it into the buffer and moves to the next character in the string. When the whole procedure is done it copies the buffer into the main screen RAM and stalls the CPU."

The font engine is available at this link.

Below is just an excerpt of the code, the full code can be found at this link.

...
;    /////////////////////////////////////////////////////////////
;   ///                      SUBROUTINES                      ///
;  /////////////////////////////////////////////////////////////	
PrintStringFlash:
	; r2 and XBNK = XRAM location (make sure even line)
	; temp1 = char count
	; temp2 = flash address low
	; temp3 = flash address high
	
	; initialize WRAM
	ld temp1
	clr1 PSW, 7
	rorc
	addc #0
	st 1
  call ClearCharCellsWRAM

	; render text
	ld temp1
	st 1
	mov #0, chptr
.StringLoop:
	ld temp2
	st TRL
	ld temp3
	st TRH
	ldf
  call DrawChar
	inc temp2
	ld temp2
  bnz .NoCarry
	inc temp3
.NoCarry:
  dbnz 1, .StringLoop

	; copy result
	ld temp1
	clr1 PSW, 7
	rorc
	addc #0
	st 1
  call PrintCharCells
  ret
...

VTech Genius Leader 4000 (aka. PreComputer)

The "Genius Leader" is a line of Z80 based learning computers, known in the US as "PreComputer". If an (E)EPROM contains the correct signature, the machine happily executes any Z80 code you throw at it. This "hellorld!" does not use firmware ROM syscalls to display the text, but instead communicates with the LCD controller directly. That's why the code must include the whole HD44780 initialization code.

For the sake of simplicity, the text is written to the middle of the screen, without taking care of the display segmentation. That's why the exclamation mark appears on a different line - it crosses the display RAM segment boundary...

GL4000_hellorld

Code:

This code should also work on the GL2000 series (2-line LCD) or even PreComputer 1000 (1-line LCD) if the LCD offset (LCD_SETDDRAMADDR) and autostart signature are altered accordingly.

; "Hellorld!" for VTech Genius Leader 4000 Quadro aka. PreComputer
org	08000h

; VTech cartridge header
	.db	#0x55
	.db	#0xaa
	
	; "Normal" signature (i.e. non-autostart program cartridge)
	;.db #0x47 ; "G"
	;.db #0x41 ; "A"
	
	; "Auto-start" signature for PreComputer1000
	;.db #0x33  ; 0x33 = autostart jump to 0x8010
	;.db #0x00  ; Dont care
	
	; "Auto-start" signature for GL2000/4000/6000
	.db	#0x59	; "Y"
	.db	#0x45	; "E"
	
	; End of cartridge header
	di	; Disable interrupts
	ld	sp, #0xdff0	; Load Stack Pointer near top of RAM
	jp main

; LCD support functions
lcd_delay:
	push hl
	ld hl,0010fh	; Delay length
loop_lcd_delay:
	dec l
	jr nz,loop_lcd_delay
	dec h
	jr nz,loop_lcd_delay
	pop hl
	ret
lcd_write_control:
	out (00ah),a	; Write to LCD control register/port
	call lcd_delay	; Delay long...
	call lcd_delay	; ...by delaying twice
	ret
lcd_write_data:
	out (00bh),a	; Write to LCD data register/port
	call lcd_delay	; Delay a bit
	ret
lcd_init:
	; Initialize the HD44780 LCD controller
	
	; Enter 8 bit mode by sending 0x38 four times
	ld a,038h	; 0x38 = Function set: 2 Line, 8-bit, 5x7 dots
	call lcd_write_control
	call lcd_write_control
	call lcd_write_control
	call lcd_write_control
	
	; Clear screen
	ld a,001h
	call lcd_write_control
	
	; Set cursor/insert mode
	ld a,00fh		; LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSORON | LCD_BLINKON
	call lcd_write_control
	ld a,006h		; LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT
	call lcd_write_control
	ret

; Main function
main:
	call lcd_init
	
	; Start output at a continuous part of VRAM around the center of the screen
	ld a,0c8h		; LCD_SETDDRAMADDR | 72
	call lcd_write_control
	
	; Start at beginning of string
	ld hl,str_hello
	
	; Print loop
loop_print:
	ld a,(hl)	; Load next char
	or a	; Check if it is zero
	jr z,loop_halt	; If it is: Jump to end of loop
	
	call lcd_write_data
	inc hl
	jr loop_print
	; End of print loop
loop_halt:
	jr loop_halt	; Loop forever

; Data
str_hello:
	.ascii "Hellorld!"
	.db 0x00	; Zero-termination

A SDCC based SDK for those machines is available on HotKey's Github.