# 01: Hello world on the VDG text screen. # # Exercises: memory-mapped globals, fixed arrays, `for`/`in`, # integer literals, hex literals, the divergent main loop. # The CoCo 2 text screen: 32x16 cells, one byte per cell, at $0400. # `at` pins a global to an absolute address; the compiler allocates # nothing for it. This is a language feature, not a library, on this # target. var screen: [Uint8; 512] at 0x0400 const COLS: Uint16 = 32 fn put_char(row: Uint16, col: Uint16, ch: Uint8) { # The compiler can't prove `row * COLS + col < 512` here, so this # index gets a runtime bounds check. That's the escape hatch, not # the idiom -- see `main` for the checked-once-per-loop style. screen[row * COLS + col] = ch } fn main() { # VDG character codes, not ASCII. A real program would use a # conversion table; string literal semantics are an open question. let msg: [Uint8; 5] = [0x08, 0x05, 0x0C, 0x0C, 0x0F] # "HELLO" # `for x in array` iterates by value; the compiler proves bounds # once for the whole loop. No index, no check. var col: Uint16 = 0 for ch in msg { put_char(0, col, ch + 0x40) col = col + 1 } # `loop` is an infinite loop; it types as Never, so `main` is # allowed to not return. loop {} }