-
-
Notifications
You must be signed in to change notification settings - Fork 498
The TIC-80 has 96kb of addressable "hardware" memory.
.-----------------------------------.
| 96KB RAM LAYOUT |
|-----------------------------------|
| ADDR | INFO | BYTES |
|-------+-------------------+-------|
| 00000 | <VRAM> | 16384 | Video RAM (see table below)
| 04000 | TILES | 8192 | 256 8x8 4bit bg sprites (tiles) - #0 to #255
| 06000 | SPRITES | 8192 | 256 8x8 4bit fg sprites - #256 to #511
| 08000 | MAP | 32640 | 240x136 map cells - holds index of tile/sprite
| 0FF80 | GAMEPADS | 4 | state for 4 gamepads
| 0FF84 | MOUSE | 4 | mouse state X / Y / buttons / scroll
| 0FF88 | KEYBOARD | 4 | keyboard state, codes for 4 pressed buttons
| 0FF8C | SFX STATE | 16 |
| 0FF9C | SOUND REGISTERS | 72 | ...
| 0FFE4 | WAVEFORMS | 256 | 16 waveforms, each 32 x 4bit values
| 100E4 | SFX | 4224 | ...
| 11164 | MUSIC PATTERNS | 11520 | ...
| 13E64 | MUSIC TRACKS | 408 | ...
| 13FFC | SOUND STATE | 4 | ...
| 14000 | STEREO VOLUME | 4 |
| 14004 | PERSISTENT MEMORY | 1024 | 256 32-bit values, unique per cartridge
| 14404 | SPRITE FLAGS | 512 |
| 14604 | SYSTEM FONT | 2048 | 256 8x8 1bit font (used by print)
| 14E04 | ... (free) | 12796 |
'-----------------------------------'
.-----------------------------------.
| 16KB VRAM LAYOUT |
|-----------------------------------|
| ADDR | INFO | BYTES |
|-------+-------------------+-------|
| 00000 | SCREEN | 16320 | 240x136 = 32640 4bit pixels
| 03FC0 | PALETTE | 48 | 16 x 24bit RGB color values
| 03FF0 | PALETTE MAP | 8 | 16 x 4bit color indexes (for palette swapping of individual sprites)
| 03FF8 | BORDER COLOR | 4bit | (lo nibble) 4bit color value
| 03FF8 | RESERVED | 4bit | (hi nibble) 4bit reserved for the future use
| 03FF9 | SCREEN OFFSET | 2 | horz/vert screen offset [-128...+127]
| 03FFB | MOUSE CURSOR | 1 | sprite to use for mouse pointer
| 03FFC | BLIT SEGMENT | 1 | (lo nibble) 4bit BLIT segment value
| 03FFC | RESERVED | 1 | (hi nibble) 4bit reserved for the future use
| 03FFD | RESERVED | 3 | reserved for the future use
'-----------------------------------'
Example of reading the BORDER
register:
peek(0x03FF8) -- => 0x21
-- 0x01 is the border color
-- 0x02 is reserved value
PALETTE
stores the currently active palette. Each entry in the palette includes a red, green, and blue component - allowing over 16 million colors (24-bit color).
.----------------------------------.
| PALETTE |
|----------------------------------|
| .-------------------------. |
| | red component | 8bit | |
| | green component | 8bit | x 16 | = 48 bytes
| | blue component | 8bit | |
| '-------------------------' |
'----------------------------------'
PALETTE MAP
controls how palette indexes are applied when writing to VRAM. This can be used to easily swap palette colors. The mapped color index (not the original) is written to the SCREEN
. With sprite-drawing functions (spr
, map
, textri
), this color swap is done when reading the color from sprite memory.
transparent
index parameters are applied on source colors, swapping out color indices before remapping. (?)
For an example see Swapping Palette Colors.
BLIT SEGMENT
controls how sprite drawing functions will read sprites in memory. It specifies the amount of bits per pixel and the position of the spritesheet.
See Blit Segment and BPP for more information.
MOUSE CURSOR
specifies which cursor to use:
0 = Disabled
1...127 = Sprite (#257 to #383 in 4bpp mode)
128 = ARROW
129 = HAND
130 = IBEAM
131...255 = Reserved
SPRITES: Each sprite/tile is laid out sequentially in memory. Each sprite/tile is 32 bytes long, so sprite #i starts at 0x4000+(32*i)
. Each byte in the sprite represents a pair of pixels (since each pixel is 4 bits). The low 4 bits are the left pixel, and the high 4 bits are the right pixel. Pixels are laid out from left to right, top to bottom row.
Example sprite Representation
(each hex digit
represents a pixel)
01234567 0x10 0x32 0x54 0x76
89abcdef 0x98 0xba 0xdc 0xfe
01234567 0x10 0x32 0x54 0x76
89abcdef 0x98 0xba 0xdc 0xfe
01234567 0x10 0x32 0x54 0x76
89abcdef 0x98 0xba 0xdc 0xfe
01234567 0x10 0x32 0x54 0x76
89abcdef 0x98 0xba 0xdc 0xfe
Sprites 0 to 255 are "background sprites" that can be part of a map; 256 to 511 are "foreground sprites" that cannot be on the map (but can still be drawn by spr
and other means.) Background sprites are also called "tiles".
The MAP
is a grid of 240x136 tiles. Each byte represents a single tile of the map. Like the sprites, the map's tiles are laid out from left to right, top to bottom row. Convenience functions mset and mget are provided for working with map data.
.-------------------.
| MOUSE |
|-------------------|
| x position | 8bit |
| y position | 8bit |
| left | 1bit |
| middle | 1bit | = 4 bytes
| right | 1bit |
| h scroll | 6bit |
| v scroll | 6bit |
| (reserved) | 1bit |
'-------------------'
The X and Y position values represent where in the TIC-80 screen the mouse is pointing to, but they may exceed the 240x136 range of the screen.
The H and V scroll values are used for the horizontal and vertical mouse wheel deltas. These represent the amount of "steps" they had moved in the last frame. These are two's complement numbers, with their sign indicating which direction they're scrolling.
This data is most easily accessed using the mouse function.
.-----------------------.
| SOUND REGISTER |
|-----------------------|
| frequency | 12bit | x 4 channels = 72 bytes
| volume | 4bit |
| waveform | 32 x 4bit |
'-----------------------'
The frequency value is converted to a period value (clamped to 10...4096) suited for a virtual 2,088,960 Hz clock. This period value produces an update frequency that is close to 32*frequency
(for waveform envelopes) or 16*frequency
(for noise output). At the update frequency, the 32-step counter pointing to the current waveform step will increment, or the noise LFSR will update.
TIC-80 updates the volume value in correspondence with SFX volume envelopes only, independent of the sfx()
volume parameter and Mxy
commands in the tracker.
Noise output occurs when the waveform is empty (zero-filled). This produces a pseudo-random binary output sequence, with a length of 32,767 samples. The noise sequence is the same as the NES/Famicom "white noise" mode.
You can update the Sound Registers every tick (60 times per second) to generate sound independently from the built-in API functions. To read the frequency and volume, use the following code:
value = peek(0xFF9C+18*channel+1)<<8|peek(0xFF9C+18*channel)
frequency = (value&0x0fff)
volume = (value&0xf000)>>12
.--------------------------.
| SFX |
|--------------------------|
| |
| .-----------------. |
| | volume | 4bit | |
| | wave | 4bit | x 30 |
| | arpeggio | 4bit | |
| | pitch | 4bit | |
| '-----------------' |
| |
| .---------------------. |
| | octave | 3bit | |
| | pitch16x | 1bit | |
| | speed | 3bit | | x 64 = 4224 bytes
| | reverse | 1bit | |
| | note | 4bit | |
| | stereo_left | 1bit | |
| | stereo_right | 1bit | |
| | temp | 2bit | |
| '---------------------' |
| |
| .--------------. |
| | LOOP | |
| |--------------| x 4 |
| | start | 4bit | |
| | size | 4bit | |
| '--------------' |
| |
'--------------------------'
Volume is inverted, so volumes 15...0 in the volume macro editor are treated as values 0...15 in these volume values.
The octave value is one lower than described in the editor. As such, values 0...7 correspond with SFX octaves 1...8.
The speed value and the pitch values are all two's complement numbers.
Note numbers 0...11 are mapped to C...B. Note numbers 12...15 are mapped to C...D# on the next higher octave, which is an "unintended" SFX feature.
stereo_left
and stereo_right
force the left/right playback volume of the SFX to be 0 when set.
There are four loop fields, each with a start index and loop size. The order of the fields is: Wave, Volume, Arpeggio, Pitch
The MUSIC PATTERNS
stores the tracker pattern data.
.---------------------------.
| MUSIC PATTERN |
|---------------------------|
| |
| .------------------. |
| | PATTERN ROW | |
| |------------------| |
| | note | 4bit | |
| | param1 | 4bit | x 64 | x 60 = 11520 bytes
| | param2 | 4bit | |
| | command | 3bit | |
| | sfx | 6bit | |
| | octave | 3bit | |
| '------------------' |
| |
'---------------------------'
Please also see the source for tic_track_row.
note
describes which note to play.
0 = No Action
1 = Note Off
2,3 = Reserved (same as 0)
4...15 = Notes C...B
command
is a SFX command (such as volume, slide, pitch, etc). See the source.
param1
and param2
are the X
and Y
parameters for the various SFX commands.
sfx
refers to the SFX id of the sound to use to play the given note.
One should be careful when setting/reading sfx
with simple bit shifts (as it crosses a byte boundary). Bit offset 15 contains the high bit of sfx
while bit offsets 16-20 contain the remaining bits. If done incorrectly you'll end up with the LSB in offset 15, instead of the MSB, which is incorrect. For example, SFX indexes 05
and 33
in the tracker come back as 10 and 3 when read incorrectly.
The octave
value is one lower than described in the tracker. As such, values 0...7 correspond with octaves 1...8.
The MUSIC TRACKS
stores the track data.
.-----------------------------.
| MUSIC TRACK |
|-----------------------------|
| |
| .--------------------. |
| | pattern ch0 | 6bit | |
| | pattern ch1 | 6bit | x 16 |
| | pattern ch2 | 6bit | |
| | pattern ch3 | 6bit | |
| '--------------------' | x 8 tracks = 408 bytes
| |
| .--------------. |
| | tempo | 8bit | |
| | rows | 8bit | |
| | speed | 8bit | |
| '--------------' |
| |
'-----------------------------'
The TEMPO
(32..255) of the music track is 150 plus the value of tempo
.
The number of ROWS
(1..64) in the music track is 64 minus the value of rows
.
The SPD
(1..31) of the music track is 6 plus the value of speed
.
.--------------------.
| SOUND STATE |
|--------------------|
| track | 8bit |
| frame | 8bit |
| row | 8bit |
|--------------------|
| |
| .----------------. | = 4 bytes
| | FLAGS | |
| |----------------| |
| | mode | 3bit | |
| | sustain | 1bit | |
| | ... | 4bit | |
| '----------------' |
| |
'--------------------'
The track value is 255 (-1) when no track is playing.
The mode value affects how music tracks are played and looped:
0,1 = Music stopped
2 = Play single frame once
3 = Loop single frame
4 = Play track once
5 = Loop track
6,7 = Reserved (same as 3)
Stores the left and right volumes of each channel.
.-------------------------------.
| STEREO VOLUME |
|-------------------------------|
| |
| .--------------. |
| | left | 4bit | x 4 channels | = 4 bytes
| | right | 4bit | |
| '--------------' |
| |
'-------------------------------'
Stores the sprite flags in RAM. See fset and fget.
Stores the default system font which is used by print. A game can modify this font by simply updating this area of RAM.
- 256 characters (default includes two fonts, the second in ASCII 128-255)
- 1 bit, 8x8 pixel font (ie, 8 bytes per character)
The letter 'A'.
Binary Lit Pixels
00000100 .....*..
00001010 ....*.*.
00011111 ...*****
00010001 ...*...*
00010001 ...*...*
00000000 ........
00000000 ........
00000000 ........
See the font demo.
Every cartridge has 1 KB of persistent memory. This is useful for saving high-scores, level advancement or achievements. This memory can be updated directly using poke and automatically persists across restarts of your cartridge.
This memory can also be retrieved and updating using the pmem function. The pmem function divides this RAM into 256 individual 32-bit slots storing unsigned integers (from 0 to 4294967295).
TIC-80 tiny computer https://tic80.com | Twitter | Telegram | Terms
Built-in Editors
Console
Platform
RAM & VRAM | Display | Palette | Bits per Pixel (BPP) |
.tic
Format | Supported Languages
Other
Tutorials | Code Snippets | Libraries | External Tools | FFT
API
- BDR (0.90)
- BOOT (1.0)
- MENU
- OVR (deprecated)
- SCN (deprecated)
- TIC
- btn & btnp
- circ & circb
- clip
- cls
- elli & ellib (0.90)
- exit
- fget & fset (0.80)
- font
- key & keyp
- line
- map
- memcpy & memset
- mget & mset
- mouse
- music
- peek, peek4
- peek1, peek2 (1.0)
- pix
- pmem
- poke, poke4
- poke1, poke2 (1.0)
- rect & rectb
- reset
- sfx
- spr
- sync
- ttri (1.0)
- time
- trace
- tri & trib (0.90)
- tstamp (0.80)
- vbank (1.0)