[IO]
# =============================================================================
# IO (FRAMEWORK FILE) VERSION 2025-11-29
# =============================================================================
# HYBRIX PROGRAMS INTERACT WITH THE VIRTUAL COMPUTER'S HARDWARE USING
# MEMORY-MAPPED INPUT/OUTPUT (MMIO), WHICH MEANS READING/WRITING SPECIAL
# MEMORY ADDRESSES. FOR EXAMPLE, WRITING A 1 BYTE TO $D0_0011 WILL ENABLE
# THE JAMDAC SYNTHESIZER, OR READING FROM $D0_0300 CAN TELL YOU THE CURRENT
# BACKGROUND COLOR. THIS FILE DEFINES ALL THE MMIO LOCATIONS.
# -----------------------------------------------------------------------------
CLASS IO_THEME # SIZE 64
# MAPS A PALETTE INDEX TO A THEMED PALETTE INDEX
INSET COLOR_MAP: BYTE[SIZE 64]
END CLASS
# -----------------------------------------------------------------------------
CLASS IO_SPRITE # SIZE 16
# SCREEN COORDINATES OF UPPER-LEFT CORNER OF SPRITE
VAR X: PAIR, Y: PAIR
# POSSIBLE VALUES: 8, 16, 32, 48
VAR WIDTH: BYTE, HEIGHT: BYTE
# LAYER:
# 0 = IN FRONT OF ALL TILEMAPS
# 1 = BEHIND TILEMAP A, IN FRONT OF B
# 2 = BEHIND TILEMAP B, IN FRONT OF C
# 3 = BEHIND ALL TILEMAPS
#
# TRANSFORM:
# +4 = FLIP X (HORIZONTAL)
# +8 = FLIP Y (VERTICAL)
# +16 = ROTATE CLOCKWISE 90 DEGREES, ONLY IF SPRITE IS SQUARE
VAR FLAGS: BYTE
# THE THEME IS AN INDEX (0..31) INTO IO::THEMES
VAR THEME: BYTE
# THE ADDRESS OF THE PIXEL BUFFER. TO HIDE THE SPRITE, SET PIXELS_ADDRESS=0
VAR PIXELS_ADDRESS: INT
VAR RESERVED: INT
END CLASS
# -----------------------------------------------------------------------------
CLASS IO_TILEMAP # SIZE 16
# SCREEN COORDINATES OF UPPER-LEFT CORNER OF TILEMAP
VAR X: PAIR, Y: PAIR
# POSSIBLE VALUES: 16, 32, 64, 128, 256
VAR COL_COUNT: PAIR, ROW_COUNT: PAIR
# A POINTER TO A GRID OF TILE CODES ARRANGED IN LEFT-TO-RIGHT ROWS,
# STARTING FROM THE TOP ROW. THE ARRAY INDEX IS ROW*COL_COUNT+COL.
# EACH TILE CODE IS A 16-BIT PAIR:
# BITS 0..9 ENCODE THE TILE INDEX (0..1023) FROM THE TILESET
# BITS 10..14 ENCODE THE THEME INDEX (0..31) INTO IO::THEMES
# BIT 15 IF SET, IO::MATTE_COLOR REPLACES ANY CLEAR PIXELS IN THIS TILE
VAR TILE_CODES_ADDRESS: INT
# 0 = WRAP: THE MAP WRAPS AROUND, REPEATING INFINITELY IN EVERY DIRECTION
# 1 = CLIP: CELLS OUTSIDE THE MAP BOUNDS ARE TRANSPARENT
VAR EDGE_MODE: BYTE
# ------------------
# TILESET PROPERTIES
# 0 = TILES ARE 8 X 8 PIXELS
# 1 = TILES ARE 16 X 16 PIXELS
VAR JUMBO: BYTE
# 0 < TILE_COUNT <= 1024
VAR TILE_COUNT: PAIR
END CLASS
# -----------------------------------------------------------------------------
CLASS IO_INPUT_EVENT # SIZE 4
# 0 = KEY DOWN
# 1 = KEY REPEAT
# 2 = KEY UP
# 3 = RESYNC; ALL KEYS UP
VAR KIND: BYTE
# IDENTIFIES THE KEYBOARD BUTTON, OR 0 FOR ALTERNATE INPUT SOURCES
VAR KEYID: BYTE
# IDENTIFIES THE TRANSLATED HASCII, OR 0 FOR KEYS THAT DON'T TYPE ANYTHING
# RIGHT NOW THE HIGH BYTE IS ALWAYS 0, BUT IN THE FUTURE IT WILL BE USED
# FOR UTF-16 CHARACTERS
VAR HASCII: PAIR
END CLASS
# -----------------------------------------------------------------------------
CLASS IO_HAND_CONTROLLER # SIZE 8
# 0 = DISABLED
# 1 = GAMEPAD
# 16 = MOUSE (X AND Y ARE ROLLING COUNTERS)
VAR KIND: BYTE
# +1 = A / MOUSE MAIN BUTTON
# +2 = B / MOUSE MIDDLE BUTTON
# +4 = C / MOUSE SECONDARY BUTTON
# +8 = D
VAR BUTTONS: BYTE
# GAMEPAD: (LEFT) -1023 .. +1023 (RIGHT)
VAR X: PAIR
# GAMEPAD: (UP) -1023 .. +1023 (DOWN)
VAR Y: PAIR
VAR RESERVED: PAIR
END CLASS
# =============================================================================
# IO MODULE
# =============================================================================
# MMIO LOCATION MAPPINGS FOR ALL HARDWARE INTERFACES.
# -----------------------------------------------------------------------------
MODULE IO
# MEMORY SEGMENT LAYOUT
VAR RAM_END_ADDRESS: INT LOCATED AT $D0_0000 # 001X_XXXX
VAR ROM_END_ADDRESS: INT LOCATED AT $D0_0004 # 00CX_XXXX
VAR IO_END_ADDRESS: INT LOCATED AT $D0_0008 # 00DX_XXXX
# USED WITH IRQ_WAKE_MASK BELOW. WHENEVER THE SPECIFIED EVENT OCCURS,
# THE HARDWARE SETS THE CORRESPONDING BIT. THE PROGRAM CAN CLEAR A BIT
# BY SETTING IT (THE "WRITE 1 TO CLEAR" OR "W1C" CONVENTION).
# +1 = WHENEVER PALIX PAINTS A VIDEO FRAME (BUFFERED OR UNBUFFERED)
# +2 = WHENEVER JAMDAC ADVANCES AN IO_AUDIO_QUEUE::READ_ADDRESS
VAR IRQ_PENDING: BYTE LOCATED AT $D0_0010
# TO SAVE ELECTRICITY, THE CPU CAN BE TEMPORARY PAUSED USING THE "SLEEP"
# INSTRUCTION. THE CPU WILL WAKE UP AGAIN WHEN IRQ_PENDING MATCHES ANY OF
# THE IRQ_WAKE_MASK BITS (LEVEL TRIGGERING).
VAR IRQ_WAKE_MASK: BYTE LOCATED AT $D0_0012
# CUSTOM HANDLING FOR "FAIL", "TRACE", "REQUEST" AND OTHER CPU EVENTS
VAR CPU_EVENT_FLAGS: BYTE LOCATED AT $D0_0013
VAR CPU_EVENT_IP: INT LOCATED AT $D0_0014
VAR CPU_EVENT_FP: INT LOCATED AT $D0_0018
VAR CPU_EVENT_VALUE: INT LOCATED AT $D0_001C
VAR CPU_FAIL_HANDLER: INT LOCATED AT $D0_0020
VAR CPU_TRACE_HANDLER: INT LOCATED AT $D0_0024
VAR CPU_REQUEST_HANDLER: INT LOCATED AT $D0_0028
# REAL TIME CLOCK
VAR CLOCK_YEAR: PAIR LOCATED AT $D0_0030
VAR CLOCK_MONTH: BYTE LOCATED AT $D0_0032
VAR CLOCK_DAY: BYTE LOCATED AT $D0_0033
VAR CLOCK_DAY_OF_WEEK: BYTE LOCATED AT $D0_0034
VAR CLOCK_HOURS: BYTE LOCATED AT $D0_0035
VAR CLOCK_MINUTES: BYTE LOCATED AT $D0_0036
VAR CLOCK_SECONDS: BYTE LOCATED AT $D0_0037
# STARTS FROM 0, INCREMENTING EVERY MILLISECOND. YOUR PROGRAM CAN MODIFY IT.
VAR CLOCK_MS: INT LOCATED AT $D0_0038
# +1 = FLOATING POINT ADD-ON
VAR PRODUCT_FEATURES: BYTE LOCATED AT $D0_003C
# 0 = DISABLED; 1 = STACK FAULT WHEN SP > GP
VAR STACK_GUARD: BYTE LOCATED AT $D0_003D
# 0 = DISABLE JAMDAC; 1 = ENABLE JAMDAC, REBOOTING ITS CPU
VAR JAMDAC_ENABLE: BYTE LOCATED AT $D0_003E
# (INPUT_QUEUE_END_INDEX IS AT $D0_003F)
# SERIAL PORT OUTPUT
#
# (SEE STATUS CODES BELOW)
VAR TRANSMIT_STATUS: BYTE LOCATED AT $D0_0040
# 0 = CANCEL TRANSMIT (CAN BE SET BEFORE A FINAL STATUS IS RECEIVED)
# 1 = START TRANSMIT
VAR TRANSMIT_COMMAND: BYTE LOCATED AT $D0_0041
VAR TRANSMIT_CHANNEL: BYTE LOCATED AT $D0_0042
VAR TRANSMIT_NEXT_WRITE_INDEX: BYTE LOCATED AT $D0_0043
VAR TRANSMIT_NEXT_READ_INDEX: BYTE LOCATED AT $D0_0044
# SERIAL PORT INPUT
#
# (SEE STATUS CODES BELOW)
VAR RECEIVE_STATUS: BYTE LOCATED AT $D0_0048
# 0 = CANCEL LISTENING (CAN BE SET BEFORE A FINAL STATUS IS RECEIVED)
# 1 = START LISTENING
VAR RECEIVE_COMMAND: BYTE LOCATED AT $D0_0049
VAR RECEIVE_CHANNEL: BYTE LOCATED AT $D0_004A
VAR RECEIVE_NEXT_WRITE_INDEX: BYTE LOCATED AT $D0_004B
VAR RECEIVE_NEXT_READ_INDEX: BYTE LOCATED AT $D0_004C
# STORAGE CONTROLLER
#
# (SEE STATUS CODES BELOW)
VAR DRIVE_STATUS: BYTE LOCATED AT $D0_0050
# 1 = GET INFO
# 2 = READ SECTOR
# 3 = WRITE SECTOR
VAR DRIVE_COMMAND: BYTE LOCATED AT $D0_0051
# 0 = FLASH CHIP
VAR DRIVE_VOLUME: BYTE LOCATED AT $D0_0052
# 1 = FLASH CHIP, SECTOR SIZE IS 1024, 4 SECTORS TOTAL PER CARTRIDGE
VAR DRIVE_INFO_TYPE: BYTE LOCATED AT $D0_0053
VAR DRIVE_INFO_TOTAL_SECTORS: INT LOCATED AT $D0_0054
VAR DRIVE_SECTOR_NUM: INT LOCATED AT $D0_0058
VAR DRIVE_DMA_ADDRESS: INT LOCATED AT $D0_005C
# STATUS CODES REPORTED BY: TRANSMIT_STATUS, RECEIVE_STATUS, DRIVE_STATUS
#
# 0 = DONE
# 8 = ERROR: DEVICE NOT PRESENT
# 9 = ERROR: DEVICE NOT PRESENT, REACHED END
# 10 = ERROR: INVALID COMMAND
# 11 = ERROR: INVALID SECTOR NUMBER
# 12 = ERROR: MEMORY FAULT
#
# 128 = START COMMAND - WRITTEN BY PROGRAM TO START AN OPERATION
# 129 = BUSY - WILL CHANGE TO A "READY CODE" (< 128) AFTER THE WORK IS DONE
INSET GAMEPAD_0: IO_HAND_CONTROLLER LOCATED AT $D0_0060
INSET GAMEPAD_1: IO_HAND_CONTROLLER LOCATED AT $D0_0068
INSET GAMEPADS: IO_HAND_CONTROLLER[INSET 2] LOCATED AT $D0_0060
INSET MOUSE: IO_HAND_CONTROLLER LOCATED AT $D0_0078
# $D0_0080 - $D0_00BF ARE RESERVED FOR KERNEL GLOBALS
VAR KERNEL_HEAP_START_ADDRESS: INT LOCATED AT $D0_0080
# CONVENTIONALLY, THE HEAP END IS THE STACK START
VAR KERNEL_STACK_START_ADDRESS: INT LOCATED AT $D0_0084
VAR KERNEL_STACK_END_ADDRESS: INT LOCATED AT $D0_0088
# KEYBOARD
VAR INPUT_QUEUE_END_INDEX: BYTE LOCATED AT $D0_003F
INSET INPUT_QUEUE: IO_INPUT_EVENT[INSET 16] LOCATED AT $D0_00C0 # ..$D0_00FF
# SERIAL BUFFERS
INSET TRANSMIT_BUFFER: BYTE[SIZE 256] LOCATED AT $D0_0100
INSET RECEIVE_BUFFER: BYTE[SIZE 256] LOCATED AT $D0_0200
# PALIX VIDEO SYSTEM
VAR BACKGROUND_COLOR: BYTE LOCATED AT $D0_0300
VAR MATTE_COLOR: BYTE LOCATED AT $D0_0301
# INCREMENTS FOR EACH VIDEO FRAME, EVEN IF PAINTING IS SKIPPED.
# THE REFRESH RATE IS 30 FRAMES/SEC = 33.333 MS/FRAME
VAR FRAME_COUNTER: PAIR LOCATED AT $D0_0302
# 0 = UNBUFFERED
# 1 = BUFFERED
# 3 = BUFFERED, PAINT REQUESTED; AFTERWARDS THE VALUE REVERTS TO 1
VAR PAINT_MODE: BYTE LOCATED AT $D0_0304
INSET TILEMAP_A: IO_TILEMAP LOCATED AT $D0_0310 # ..$D0_031F
INSET TILEMAP_B: IO_TILEMAP LOCATED AT $D0_0320 # ..$D0_032F
INSET TILEMAP_C: IO_TILEMAP LOCATED AT $D0_0330 # ..$D0_033F
INSET SPRITES: IO_SPRITE[INSET 64] LOCATED AT $D0_0400 # ..$D0_07FF
INSET THEMES: IO_THEME[INSET 32] LOCATED AT $D0_0800 # ..$D0_0FFF
INSET TILESET_A_ADDRESSES: INT[SIZE 1024] LOCATED AT $D0_1000 # ..$D0_1FFF
INSET TILESET_B_ADDRESSES: INT[SIZE 1024] LOCATED AT $D0_2000 # ..$D0_2FFF
INSET TILESET_C_ADDRESSES: INT[SIZE 1024] LOCATED AT $D0_3000 # ..$D0_3FFF
# JAMDAC
INSET AUDIO_QUEUES: IO_AUDIO_QUEUE[INSET 6] LOCATED AT $D0_4000 # ..$D0_4BFF
END MODULE