You won't be able to write a very useful program for the computer in Ranger Citadel until you understand how it's... um... "built".
When you write programs for the 6502 processor, you write them based on the hardware specs and absolute memory locations of how that device was designed and constructed. That's a bit different than modern computers with programming languages that allow you to decouple yourself from the hardware, but deep down, they too need to be compiled to the specific instruction set of the processor. Computers back in the 80's were far simpler machines without operating systems or disk drives. A program was loaded directly into addressable memory and executed. That addressable memory also contained the ROM itself as well as direct mapping of the address space for the monitor and graphics output. To display things onscreen, you'd write values directly to memory locations that represented the monitor's memory for pixels. To make things easier, soft switches were also added. These were memory locations that is accessed by a peek or poke (reading or writing) would trigger some action, like playing a sound or switching graphics modes from hi-res to low-res, etc.
Writing a program for a computer based on a 6502 processor means you are writing a program directly for that hardware. 6502 programs aren't universal. Although the NES, Commodore 64 and Apple ][ were all based on the 6502 processor, they each had very different hardware specs and memory allocations.
The Wasteland 2 computer, which I lovingly call the Agave ][, was designed with it's own unique structure. It is very simple, but should offer enterprising programmers a playground to create some really wonderful programs/games.
Let's get going!
--- The Agave ][ Computer Hardware ---
The 6502 computers of Wasteland use the amazingly robust 650WL2 64k processor. (See what I did there ) Hardware memory mapping is as follows:
0x0000 - 0x00FF : Zero page storage.
0x0100 - 0x01FF : Stack location (do not use)
0x0200 - 0x03FF : Monitor memory text buffer page 0
0x0400 - 0x35FF : Monitor memory graphics page 0
0x3600 - 0x37FF : Monitor memory text buffer page 1
0x3800 - 0x69FF : Monitor memory graphics page 1
0x7000 - 0xEFFF : User program space (32k)
0xF000 - 0xF7FF : ASCII Font definitions (8 bytes per character = 8 bits per row, 8 rows)
0xF800 - 0xFEFF : ROM Reserved Space for future use
0xFF00 - 0xFFFF : Soft switches, input and other variables
The following memory locations offer special abilities:
0xFF00 - Read/Write to switch to Low-Res graphics mode (default), clears screen
0xFF01 - Read/Write to switch to High-Res graphics mode, clears screen
0xFF02 - Read/Write to switch to Text mode, clears screen
0xFF03 - Read/Write to switch to TextOR mode (text layered on high-res), clears screen
0xFF04 - Read/Write to switch to Low-Res graphics mode, does not clear screen
0xFF05 - Read/Write to switch to High-Res graphics mode, does not clear screen
0xFF06 - Read/Write to switch to Text mode, does not clear screen
0xFF07 - Read/Write to switch to TextOR mode (text layered on high-res), does not clear screen
0xFF08 - Clears low/high-res graphics memory page 0
0xFF09 - Fills low/high-res graphics memory page 0 with value
0xFF0A - Clears low/high-res graphics memory page 1
0xFF0B - Fills low/high-res graphics memory page 1 with value
0xFF0C - Clears text buffer memory page 0
0xFF0D - Fills text buffer memory page 0 with value
0xFF0E - Clears text buffer memory page 1
0xFF0F - Fills text buffer memory page 1 with value
0xFF10 - Set active graphics page to 0
0xFF11 - Set active graphics page to 1
0xFF12 - Set active text page to 0
0xFF13 - Set active text page to 1
0x0000 - Although you can set the program counter to any address, setting it to $0000 will pause execution until the next Unity update call. You can leverage this to create a delay by setting $00 to 0xEA (NOP) and $01 to 0x60 (RTS), then calling JSR $0000 within your loop.
0xFFFF - BRK or errors jump here then program counter sits here and does nothing. This is different than the standard 6502 BRK instruction. Note, there are no hardware interrupts.
0xFFF0 - Last key pressed (0-255 ASCII value)
0xFFFA - A random number (0-255) updated after every operation
--- Graphics ---
16 colors (4-bit values 0x0-0xF) in a 32x32 resolution. Starting at memory location 0x0400 for Page 0 and 0x3800 for Page 1. 1 pixel per 8-bit address. Bits are as follows: 0b[Darkness,Red,Green,Blue], with 0b0 being black, 0b0111 being white, 0b1000 being dark grey and 0b1111 being light grey. With a 1 Darkness bit, colors are half as bright, so 0x0-0x7 represents 8 bright colors, while 0x8-0xF are their darker versions.
16 colors (4-bit values 0x0-0xF) in a 160x160 resolution. Starting at the same memory locations as low-res mode. 2 pixels per 8-bit address location, 4 bits per pixel.
Monochrome (white) 20x20 columns/rows of text. Using the graphics locations for rendering font pixels, each character uses an 8x8 pixel grid (64 pixels per character) with 2 pixels defined in each byte. A special text memory buffer is allocated at 0x0200 for Page 0 and 0x3600 for Page 1 which stores 1 byte per 1 character (values 0-255). In text mode, the information in the active text buffer page will be read and painted into the active graphics page based on the font character definitions at 0xF000-0xF7FF.
The letter '0' rendered in high-res graphics memory, 2 pixels per byte:
[x30]... (ASCII hex value for '0')
Code: Select all
[x00][x00][x00][x00]... +76 more bytes... [x00][x07][x77][x00]... etc [x00][x70][x00][x70]... [x00][x70][x07][x70]... [x00][x70][x70][x70]... [x00][x77][x00][x70]... [x00][x70][x00][x70]... [x00][x07][x77][x00]...
Each row (of the 8 rows) of that character is offset by 0x14 (20) vertically, thus each individual character is offset by 0xA0 (160) vertically within the text buffer page. An individual character is offset in address space by 0x01 (1) horizontally from one character to the next.
0x0200 (Row 0):
[0x30][0x30]... +18 more bytes
0x0214 (Row 1):
Custom Wasteland inspired fonts exist in the lower ASCII values normally control characters, while basic ASCII values are respected for alpha-numeric characters and symbols. The higher values will most likely be graphic shapes in the future, however is currently unused (or can be used for your own custom fonts). However, this data is stored at memory locations 0xF000-0xF7FF, allowing the programmer to create their own fonts and characters as desired.
The character '0', ASCII value 0x30, is offset from 0xF000 by 0x30*8 or by 0x0180, thus starts at 0xF180:
Code: Select all
[........] = [0x00] [...###..] = [0x1A] [..#...#.] = [0x22] [..#..##.] = [0x26] [..#.#.#.] = [0x2A] [..##..#.] = [0x32] [..#...#.] = [0x22] [...###..] = [0x1A]
Soft Switches have been created to set modes, clearing and filling page memory and double buffering management.
PRO TIP: You can display text from text page 0, then soft switch 0xFF07 to be in TextOR mode without clearing buffers, fill page 0 with an unused character (store 0xFF into 0xFF0D), then change the font character 0xFF's 8 bytes to all be 0x1, then loop on a delay and a bit-shift left 1 until the value is 0x80. This will have an effect of displaying a page of text, then the page wipes to solid white in a vertical blinds transition. I used this technique in the Snake game to clear the text when starting the game.
Remember: programs are loaded into address 0x7000 and run from there. When assembling your code, you will need to ensure your assembler sets the program's beginning address location to 0x7000.
I can't wait to see what people create!