====================================================================================================
    Picotron User Manual
====================================================================================================

Picotron v0.1.0d
https://www.picotron.net
(c) Copyright 2024 Lexaloffle Games LLP
Author: Joseph White // hey@lexaloffle.com

Picotron is built with:
 
    SDL2 http://www.libsdl.org
    Lua 5.4 http://www.lua.org  // see license.txt
    lz4 by Yann Collet https://www.lz4.org // see license.txt
    z8lua by Sam Hocevar https://github.com/samhocevar/z8lua

Latest version of this manual (as html, txt):

https://www.lexaloffle.com/picotron.php?page=resources

:: Welcome to Picotron

    Picotron is a Fantasy Workstation for making pixelart games, animations, music, demos and other 
    curiosities.  It can also be used to create tools that run inside Picotron itself, and to 
    customise things like live wallpapers and screensavers. It has a toy operating system designed 
    to be a cosy creative space, but runs on top of Windows,  MacOS or Linux. Picotron apps can be 
    made with built-in tools, and shared with other users in a special 256k png  cartridge format.

:: Specifications

    Display:  480x270 / 240x135 64 definable colours
    Graphics: Blend tables, tline3d, stencil clipping
    Audio:    64-node synth and 8-channel tracker
    Code:     Lua 5.4 w/ PICO-8 compat features
    CPU:      8M vm insts / second
    Cart:     .p64.png (256k) / .p64 (unlimited) 

====================================================================================================
    Getting Started
====================================================================================================

----------------------------------------------------------------------------------------------------
 Mounting a Drive
----------------------------------------------------------------------------------------------------

    Picotron looks for a configuration files in the following locations:

    Windows: C:/Users/Yourname/AppData/Roaming/Picotron/picotron_config.txt OSX:     
    /Users/Yourname/Library/Application Support/Picotron/picotron_config.txt Linux:   
    ~/.lexaloffle/Picotron/picotron_config.txt

    If none is found, then a default configuration is created that maps the root folder of Picotron 
    to a directory:

    mount / C:/Users/Yourname/AppData/Roaming/Picotron/drive

    By default, the /system folder exists only in memory and any changes made to it during the 
    session will be lost. To save cartridges, cd / first and put them in a regular folder.

----------------------------------------------------------------------------------------------------
 Shortcuts
----------------------------------------------------------------------------------------------------

    ALT+ENTER:       Toggle Fullscreen
    ALT+F4:          Fast Quit (Windows)
    CTRL-Q:          Fast Quit (Mac, Linux)
    CTRL-R:          Reload / Run / Restart cartridge
    CTRL-S:          Quick-Save working cartridge
    ALT+LEFT/RIGHT   Change Workspace
    ESCAPE:          Toggle between desktop / terminal

----------------------------------------------------------------------------------------------------
 Creating a Cartridge
----------------------------------------------------------------------------------------------------

    Picotron is a cartridge-orientated workstation. A cartridge is like an application bundle, or a 
    project folder: it is a collection of Lua source code files, graphics, audio and any other data 
    files the cartridge needs to run. On the host operating system cartridges are a single .p64 
    file, but inside picotron they are treated like folders. The current working cartridge is 
    always in a RAM  folder named /ram/cart.

    Click on the code editor workspace at top right, which looks like this: ()

    Paste in a program (select here, ctrl+c, and then ctrl+v inside Picotron)

    function _init()
        bunny = unpod(
        "b64:bHo0AEIAAABZAAAA-wpweHUAQyAQEAQgF1AXQDcwNzAHHxcHM"..
        "AceBAAHc7cwFwFnAQcGAPAJZx8OJ0CXcF8dkFeQFy4HkBcuB5AXEBdA"
        )
        x = 232
        y = 127
        hflip = false
    end
     
    function _draw()
        cls(3)   -- clear the screen to colour 3 (green)
        srand(0) -- reset the random number generator sequence
        for i=1,50 do
            print("\\|/",rnd(480),rnd(270),19) -- grass
            print("*",rnd(480),rnd(270),rnd{8,10,14,23}) -- flower
        end
        ovalfill(x+2,y+15,x+12,y+18, 19) -- shadow
        spr(bunny, x, y - (flr(hop)&2), hflip) -- bunny
    end
     
    function _update()
        if (btn(0)) x -= 2 hflip = true
        if (btn(1)) x += 2 hflip = false
        if (btn(2)) y -= 2
        if (btn(3)) y += 2
        if (btn()>0) then
            hop += .2 -- any button pressed -> hop
        else
            hop = 0
        end
    end

    Now, press CTRL+R to run it. CTRL+R runs whatever is in /ram/cart, and the entry point in the 
    cartridge is always main.lua (the file you were editing).

    After hopping around with the cursor keys, you can halt the program by pressing ESCAPE, and 
    then ESCAPE once more to get back to the code editor.

    There is a lot going on here! The _init() function is always called once when the program 
    starts, and here it creates an image stored as text (a "pod"), and then sets  the bunny's 
    initial x,y position.

    _draw() is called whenever a frame is drawn (at 60fps or 30fps if there isn't enough available 
    cpu). _update() is always called at 60fps, so is a good place to put code that updates the 
    world at a consistent speed.

----------------------------------------------------------------------------------------------------
 Adding Graphics
----------------------------------------------------------------------------------------------------

    Normally graphics are stored in .gfx files included in the cartridge at gfx/*.gfx

    Click on the second workspace to draw a sprite. By default, the sprite editor has 
    /ram/cart/gfx/0.gfx open which is a spritebank that is automatically loaded when a cartridge is 
    run.

    Now, instead of using the "bunny" image, the index of the sprite can be used:

    spr(0, x, y, hflip) -- hflip controls horizontal flipping

    The map works the same way: map/0.map is automatically loaded, and can be drawn with:

    map()

    To add a camera that follow the player around, try this at the start of _draw():

    camera(x - 240, y - 135)

----------------------------------------------------------------------------------------------------
 Saving a Cartridge
----------------------------------------------------------------------------------------------------

    To save a cartridge to disk, open a terminal from the picotron menu (top left), and type:

    save mycart.p64

    (or just "save mycart" ~ the .p64 extension will be added automatically)

    The save command here simply copies the contents of /ram/cart to mycart.p64.

    Note that you can not save the cart while you are inside /ram/cart (e.g. after you press escape 
    to halt a program). That would mean copying a folder somewhere inside itself!

    Once a cartridge has been saved, the filename is set as the "present working cartridge", and 
    subsequent saves can be issued with the shortcut: CTRL-S. To get information about the current 
    cartridge, type "info" at the terminal prompt.

    Note that when editing code and graphics files inside a cartridge, those individual files are 
    auto-saved to /ram/cart so that ctrl+R will run the current version (there's no need to save 
    before each run).

    When using an editor to edit a file that is outside /ram/cart, CTRL+S saves that individual 
    file.

    Picotron is still in alpha -- please keep plenty of backups and save often!	If an editor 
    crashes but the window manager is still running, there is a good chance you can still save to 
    disk with CTRL+S.

----------------------------------------------------------------------------------------------------
 Terminal Commands
----------------------------------------------------------------------------------------------------

    Some handy commands:

    ls           list the current directory (folder)
    cd foo       change directory (e.g. cd /desktop)
    mkdir foo    create a folder 
    folder       open the current folder in your Host OS
    open .       open the current folder in filenav
    open fn      open a file with an associated editor
    rm filename  remove a file or folder (be careful!)
    info         information about the current cartridge
    load cart    load a cartridge into /ram/cart
    save cart    save a cartridge 

    To create your own commands, put .p64 or .lua files in /appdata/system/util.

----------------------------------------------------------------------------------------------------
 Using External Editors
----------------------------------------------------------------------------------------------------

    The simplest way to use a text editor is to store the files outside of a cartidge and then 
    include() then:

    cd("/myproj/src")
    include("src/draw.lua")
    include("src/monster.lua")

    Just remember to copy them back inside the cartridge (and commenting the cd(..)) before 
    releasing it!

    cp /myproj/src /ram/cart/src

    // as a general rule, cartridges should be self-contained and not depend on anything except for 
    /system

----------------------------------------------------------------------------------------------------
 Creating Windowed Programs 
----------------------------------------------------------------------------------------------------

    Each process can have a single window. To set the window:

    window(320,200)

    Additional attributes can be passed in using a table:

    window{
        width  = 320,
        height = 200,
        resizeable = false,
        title = "Bunny Example"
    }

----------------------------------------------------------------------------------------------------
Uploading a Cartridge to the BBS
----------------------------------------------------------------------------------------------------

    Cartridges can be shared on the lexaloffle BBS: 

    https://www.lexaloffle.com/bbs/?cat=8

    First, capture a label while your cart is running with ctrl+7. For windowed programs, the label 
    will include a screenshot of your desktop, so make sure you don't have anything personal lying 
    around!

    You can give the cartridge some metadata (title, version, author, notes) using about:

    > about /ram/cart

    Then save a copy of your cartridge in .p64.png by copying it:

    > cp mycart.p64 releaseable.p64.png

    The label will be printed on the front along with the title, author and version metadata if it 
    exists.  You can check the output by opening the folder you saved to, and then double clicking 
    on releaseable.p64.png (it is just a regular png)

    > folder .

    Finally, choose the 'Submit' on the BBS webpage to upload the cartridge. Cartridges are not 
    publically visible until a BBS post has been made including the cartridge (unless someone can 
    guess the cartridge id that you give it). Cartridges can be loaded directly from the BBS using:

    > load #bbs_cart_id

    Or a specific version of the cart with the revision suffix:

    > load #bbs_cart_id-0

====================================================================================================
    Customising your Machine
====================================================================================================

----------------------------------------------------------------------------------------------------
 Desktop Customisation
----------------------------------------------------------------------------------------------------

Open the system settings via the Picotron menu (top left) or by typing "settings" at the prompt.

To create your own lists of themes, wallpapers and screensavers, create the following folders:

    /appdata/system/themes
    /appdata/system/wallpapers
    /appdata/system/screensavers

Wallpapers and screensavers are regular .p64 cartridges -- you can copy anything in there that runs 
in fullscreen.

Widgets are programs that run in the slide-out tooltray (pull the toolbar down from the top), and 
are windowed programs that are not moveable and do not have a frame. See /system/startup.lua for 
examples of how to launch widgets. Additional widgets and other programs can be launched at startup 
by creating /appdata/system/startup.lua (which is run after /system/startup.lua).

----------------------------------------------------------------------------------------------------
 Keyboard Layout
----------------------------------------------------------------------------------------------------

    Text input (using peektext() / readtext()) defaults to the host OS keyboard layout / text entry 
    method.

    Key states used for things like ctrl+key shortcuts (e.g. key("ctrl") and keyp("c")) are also 
    mapped  to the host OS keyboard layout by default, but can be further configured by creating a 
    file called  /appdata/system/keycodes.pod which assigns each keyname to a new scancode. The raw 
    names of keys  (same as US layout) can alternatively be used on the RHS of each assignment, as 
    shown in this example  that patches a US layout with AZERTY mappings:

    store("/appdata/system/keycodes.pod", {a="q",z="w",q="a",w="z",m=";",[";"]=",",[","]="m"})

    note for 0.1.0d: you probably don't need need to do this! The default layout should work in 
    most cases.

    Raw scancodes themselves can also be remapped in a similar way using 
    /appdata/system/scancodes.pod, but is normally not needed. The raw mapping is used in 
    situations where the physical location of the key mappers, such as the piano-like keyboard 
    layout in the tracker. See /system/lib/events.lua for more details.

----------------------------------------------------------------------------------------------------
 Time Zone
----------------------------------------------------------------------------------------------------

    Time zones are not yet configurable and all dates and times are shown in GMT.

    As a temporary work-around please only use Picotron while you are located in Greenwich.

----------------------------------------------------------------------------------------------------
 Custom Commands
----------------------------------------------------------------------------------------------------

    To create your own commands, put .p64 or .lua files in /appdata/system/util.

====================================================================================================
    Editors
====================================================================================================

----------------------------------------------------------------------------------------------------
Code Editor
----------------------------------------------------------------------------------------------------

    Hold shift to select (or click and drag with mouse)
    CTRL-X, C, V to cut copy or paste selected
    CTRL-Z, Y to undo, redo
    CTRL-F to search for text in the current tab
    CTRL-LEFT, RIGHT to jump by word
    TAB to indent a selection (shift to un-indent)
    Double click to select a word

----------------------------------------------------------------------------------------------------
GFX Editor
----------------------------------------------------------------------------------------------------

The second workspace is a sprite editor. Each .gfx file contains up to 256 sprites, and if the 
filename starts with a number, it can be indexed by the map editor.

Don't forget to save your cartridge after drawing something -- the default filenames all point to 
/ram/cart and isn't actually stored to disk until you use the save command (or CTRL-S to save the 
current cartridge)

    S          shortcut for the select tool (hold down)
    SPACE      shortcut for the pan tool 
    CTRL-A     select all
    ENTER      deselect
    CURSORS    move selection
    BACKSPACE  delete selection
    CTRL-C     copy selection
    CTRL-V     paste to current sprite
    CTRL-B     paste big (2x2)
    TAB        toggle RH pane
    -,+        navigate sprites
    CTRL       modify some draw tools (fill)
    RMB        pick up colour
    F/V        flip selection horizontally or vertically

Draw sprites from your program with spr(index, x, y). 0.gfx is loaded automatically.

----------------------------------------------------------------------------------------------------
Map Editor
----------------------------------------------------------------------------------------------------

Changes made to /ram/cart/gfx/0.gfx automatically show up in the map editor.

The map editor uses similar shortcuts, with a few changes in meaning. For example, F and V also 
flip selected tiles, but also set special bits on those tiles to indicate that the tile itself 
should also be drawn flipped. The map() command also observes those bits.

----------------------------------------------------------------------------------------------------
SFX Editor
----------------------------------------------------------------------------------------------------

[coming soon]

====================================================================================================
    API Reference
====================================================================================================

[coming soon]

Please see the PICO-8 API reference for now:

https://www.lexaloffle.com/dl/docs/pico-8_manual.html#API_Reference

For newer parts of the API, you can find WIP design documents via the FAQ page:

https://www.lexaloffle.com/picotron.php?page=faq



--------------------------------------------------------------------------------------------
	PICOTRON VERSION HISTORY
--------------------------------------------------------------------------------------------

	0.1.0d

		Added: default keyboard mapping for key()/keyp() uses host OS layout by default
		Added: can map multiple physical keys to a single virtual key
		Added: sfx len (becomes loop0 when loop1 > len)
		Added: warning on startup when the /system version does not match the build version
		Changed: about.p64 now shows/edits the metadata of /ram/cart by default (i.e. just type: about)
		Changed: rename triplane.p64 to biplane.p64 (need to re-select it again from wallpapers)
		Fixed: /system rom in 0.1.0c was the wrong version! (caused map drawing and other things to break)
		Fixed: (Windows) rm does not delete host folders 
		Fixed: (Mac) crashes after ~13.5 minutes


	0.1.0c

		Added: custom map tile sizes (taken from sprite 0)
		Added: layer naming and ordering (the first layer in the list is now drawn on top)
		Added: mget(), mset(), ceil()
		Added: async remote fetch (put it in a coroutine)
		Added: /system/util: shutdown pwd info
		Added: right click on desktop to create new file / get file info
		Added: /appdata/system/keycodes.pod to map virtual key (to a raw name or directly to scancode)
			// store("/appdata/system/keycodes.pod", {a="q",z="w",q="a",w="z",m=51})
		Added: future version checking; a separate runtime version number is stored with each cart.
		Added: delete file menu item in filenav (moves a single file to /ram/compost)
		Added: send_message(pid, {msg=..., _delay = 2}) to send a delayed message (_delay is in seconds)		
		Changed: filenames can contain hyphens
		Changed: terminal searches for commands in current path /after/ standard paths (/system/util, ..)
		Changed: added more undo checkpoints to the text editor
		Changed: gui elements must explicitly :set_keyboard_focus(true) on click to consume textinput events
		Changed: screenshots and untitled cart filenames are given an integer suffix to reduce collisions 
		Changed: when saving a file with no extension, wrangler automatically adds the default filename extension
		Changed: track (sfx) length can be specified pico-8 style by increasing loop0 (memory layout doesn't change)
		Fixed: load #bbs_id twice over the same local file -> fails to unmount the first cartridge
		Fixed: audio lock causing random crashes on Mac (tentative ~ not sure if that was the cause or the only cause)
		Fixed: cp allows copying to inside self (-> crash; e.g. when save cart to /ram/cart)
		Fixed: reset() does not reset scanline palette selection bits at 0x5400
		Fixed: (Mac) vertical red line junk on letterboxed area in fullscreen mode
		Fixed: (Windows) printh doesn't send anything to terminal
		Fixed: drop file into a folder exactly when it opens --> hard freeze (wm crashes)
		Fixed: when dragging files and move mouse quickly, offset from mouse doesn't match original position
		Fixed: flr("garbage") causes runtime error (should return 0 to match PICO-8 behaviour)
		Fixed: text editor operations (undo, indent, double click select) stop working after using search
		Fixed: width/height fields dump earlier keypress junk + no way to delete characters
		Fixed: msg.has_pointer not always set when it should be (--> cursor not changing on window title)
		Fixed: msg.mx, msg.my absolute values for draw callbacks; should be relative to gui element 
		Fixed: no printh output under Windows (switched to using SDL_Log)
		Fixed: ctrl+6 screenshot while in video mode 3 or 4 is not scaled to cover the 480x270 output
		Fixed: flashing when windowed cartridge runs at < 60fps with a custom display palette (e.g. inst editor)
		Fixed: flashing when video mode 3 or 4 running at < 60fps
		Fixed: filenav selects .loc files (drive.loc) as target to save over instead of opening it like a folder
		Fixed: corrupted /desktop/drive.loc due to aforementioned bug -- now automatically mended on startup
		Fixed: run bells.p64 and then enter tracker -> audio is mixed from left over junk state 
		Fixed: note entry sometimes does not play in pattern editing mode 
		Fixed: can edit track that is not currently visible
		Fixed: ASDR release is calculated incorrectly (is way too long) when played in track view
		Fixed: clipping: tline3d (w is wrong), spr() when flipped


	0.1.0b

		Added: system event logging in log.txt (same folder as picotron_config.txt)
		Added: /appdata/system/scancodes.pod to remap physical key scancode
				// e.g. store("/appdata/system/scancodes.pod", {lctrl=57})
		Changed: apple option / windows menu keys are mapped to "ctrl"
		Fixed: Default mapping of lctrl is wrong
		Fixed: Windows file saving generating corrupt data (opened in text instead of binary mode)
		Fixed: Crash when reading corrupted lz4 pods -- now returns a nil object 
				// (& deals with existing corrupt settings.pod)
		Fixed: Windows BSOD on boot
		Fixed: Button mappings wrong for controller index 1 and above


	0.1.0 First release of binaries


