~rabbits/dexe

8625bcd979ce10ad97bc7e9cd7553b138a212903 — neauoire a month ago 47f0c12
Starting back again from scratch
4 files changed, 1227 insertions(+), 29 deletions(-)

M .gitignore
M build.sh
A etc/dexe.c
A src/main.tal
M .gitignore => .gitignore +4 -1
@@ 6,4 6,7 @@
dexe
untitled.chr
dexe-*
bin/
\ No newline at end of file
bin/

.theme
.snarf
\ No newline at end of file

M build.sh => build.sh +7 -28
@@ 1,38 1,11 @@
#!/usr/bin/env bash

# format code
# clang-format -i dexe.c

# remove old
# rm ./dexe

# debug(slow)
# cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined dexe.c -L/usr/local/lib -lSDL2 -o dexe

# build(fast)
# cc dexe.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -L/usr/local/lib -lSDL2 -o dexe

# Size
# echo "Size: $(du -sk ./dexe)"

# Install
# if [ -d "$HOME/bin" ] && [ -e ./dexe ]
# then
	# cp ./dexe $HOME/bin
    # echo "Installed: $HOME/bin" 
# fi

# run
# ./dexe example.chr
# ./dexe example.bmp


echo "Cleaning.."
rm -rf bin
mkdir bin

echo "Assembling.."
uxnasm dexe.tal bin/dexe.rom 
uxnasm src/main.tal bin/dexe.rom 

echo "Installing.."
if [ -d "$HOME/roms" ] && [ -e ./bin/dexe.rom ]


@@ 41,5 14,11 @@ then
    echo "Installed in $HOME/roms" 
fi

if [ "${1}" = '--push' ]; 
then
	echo "Pushing.."
	~/Applications/butler push bin/dexe.rom hundredrabbits/dexe:uxn
fi

echo "Running.."
uxnemu bin/dexe.rom

A etc/dexe.c => etc/dexe.c +806 -0
@@ 0,0 1,806 @@
#include <SDL2/SDL.h>
#include <stdio.h>

/* 
Copyright (c) 2020 Devine Lu Linvega

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/

#define HOR 32
#define VER 16
#define PAD 2
#define SZ 512 * 16

typedef unsigned char Uint8;

typedef struct {
	int unsaved;
	char name[256];
	Uint8 data[SZ];
} Document;

typedef struct Brush {
	int x, y, i, swap, view;
	Uint8 clip;
} Cursor;

int WIDTH = 8 * HOR + 8 * PAD * 2;
int HEIGHT = 8 * (VER + 2) + 8 * PAD * 2;
int FPS = 30, GUIDES = 1, ZOOM = 2;

Document doc;
Cursor cursor;

Uint32 theme[] = {
	0x000000,
	0xFFFFFF,
	0x72DEC2,
	0x666666,
	0x222222};

Uint8 icons[][8] = {
	{0x38, 0x44, 0x82, 0x82, 0x82, 0x44, 0x38, 0x00}, /* color:blank */
	{0x38, 0x7c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x00}, /* color:full */
	{0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00}, /* blank */
	{0x7c, 0x82, 0x92, 0xba, 0x92, 0x82, 0x7c, 0x00}, /* incr */
	{0x7c, 0x82, 0x82, 0xba, 0x82, 0x82, 0x7c, 0x00}, /* decr */
	{0x1c, 0x22, 0x42, 0x84, 0x42, 0x22, 0x1c, 0x00}, /* ror */
	{0x70, 0x88, 0x84, 0x42, 0x84, 0x88, 0x70, 0x00}, /* rol */
	{0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00}, /* view:grid */
	{0xee, 0x92, 0x82, 0x54, 0x82, 0x92, 0xee, 0x00}, /* view:bigpixels */
	{0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xe0, 0x10, 0x00}, /* clip:blank */
	{0x82, 0xc5, 0xe2, 0xf0, 0xf8, 0xe0, 0x10, 0x00}, /* clip:active */
	{0x00, 0x00, 0x00, 0x82, 0x44, 0x38, 0x00, 0x00}, /* eye open */
	{0x00, 0x38, 0x44, 0x92, 0x28, 0x10, 0x00, 0x00}, /* eye closed */
	{0x10, 0x54, 0x28, 0xc6, 0x28, 0x54, 0x10, 0x00}  /* unsaved */
};

Uint8 font[][8] = {
	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x24, 0x00, 0x7e, 0x3c, 0x00, 0x00},
	{0x00, 0x00, 0x24, 0x00, 0x3c, 0x42, 0x00, 0x00},
	{0x00, 0x00, 0x6c, 0x7c, 0x7c, 0x38, 0x10, 0x00},
	{0x00, 0x10, 0x38, 0x7c, 0x7c, 0x38, 0x10, 0x00},
	{0x00, 0x38, 0x38, 0x7c, 0x6c, 0x10, 0x38, 0x00},
	{0x00, 0x10, 0x38, 0x7c, 0x7c, 0x10, 0x38, 0x00},
	{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00},
	{0x00, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x00},
	{0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x00, 0x00},
	{0x00, 0x3c, 0x66, 0x5a, 0x5a, 0x66, 0x3c, 0x00},
	{0x00, 0x1e, 0x06, 0x3a, 0x4a, 0x48, 0x30, 0x00},
	{0x00, 0x38, 0x44, 0x6c, 0x10, 0x7c, 0x10, 0x00},
	{0x00, 0x0e, 0x08, 0x08, 0x08, 0x38, 0x38, 0x00},
	{0x00, 0x3e, 0x3e, 0x22, 0x22, 0x66, 0x66, 0x00},
	{0x00, 0x00, 0x10, 0x44, 0x00, 0x44, 0x10, 0x00},
	{0x00, 0x00, 0x10, 0x18, 0x1c, 0x18, 0x10, 0x00},
	{0x00, 0x00, 0x08, 0x18, 0x38, 0x18, 0x08, 0x00},
	{0x00, 0x08, 0x1c, 0x00, 0x00, 0x1c, 0x08, 0x00},
	{0x00, 0x28, 0x28, 0x28, 0x28, 0x00, 0x28, 0x00},
	{0x00, 0x3e, 0x4a, 0x4a, 0x3a, 0x0a, 0x0a, 0x00},
	{0x00, 0x0c, 0x30, 0x46, 0x62, 0x0c, 0x30, 0x00},
	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff},
	{0x00, 0x10, 0x38, 0x00, 0x38, 0x10, 0x00, 0x38},
	{0x00, 0x10, 0x38, 0x54, 0x10, 0x10, 0x10, 0x00},
	{0x00, 0x10, 0x10, 0x10, 0x54, 0x38, 0x10, 0x00},
	{0x00, 0x00, 0x08, 0x04, 0x7e, 0x04, 0x08, 0x00},
	{0x00, 0x00, 0x10, 0x20, 0x7e, 0x20, 0x10, 0x00},
	{0x00, 0x00, 0x40, 0x40, 0x7e, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0x24, 0x66, 0x24, 0x00, 0x00},
	{0x00, 0x00, 0x10, 0x38, 0x7c, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0x7c, 0x38, 0x10, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
	{0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00},
	{0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00},
	{0x00, 0x24, 0x7e, 0x24, 0x24, 0x7e, 0x24, 0x00},
	{0x00, 0x08, 0x1e, 0x28, 0x1c, 0x0a, 0x3c, 0x08},
	{0x00, 0x62, 0x64, 0x08, 0x10, 0x26, 0x46, 0x00},
	{0x00, 0x30, 0x48, 0x32, 0x4c, 0x44, 0x3a, 0x00},
	{0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
	{0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x00},
	{0x00, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00},
	{0x00, 0x00, 0x14, 0x08, 0x3e, 0x08, 0x14, 0x00},
	{0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00},
	{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10},
	{0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00},
	{0x00, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00},
	{0x00, 0x3c, 0x46, 0x4a, 0x52, 0x62, 0x3c, 0x00},
	{0x00, 0x18, 0x28, 0x08, 0x08, 0x08, 0x3e, 0x00},
	{0x00, 0x3c, 0x42, 0x02, 0x3c, 0x40, 0x7e, 0x00},
	{0x00, 0x3c, 0x42, 0x1c, 0x02, 0x42, 0x3c, 0x00},
	{0x00, 0x08, 0x18, 0x28, 0x48, 0x7e, 0x08, 0x00},
	{0x00, 0x7e, 0x40, 0x7c, 0x02, 0x42, 0x3c, 0x00},
	{0x00, 0x3c, 0x40, 0x7c, 0x42, 0x42, 0x3c, 0x00},
	{0x00, 0x7e, 0x02, 0x04, 0x08, 0x10, 0x10, 0x00},
	{0x00, 0x3c, 0x42, 0x3c, 0x42, 0x42, 0x3c, 0x00},
	{0x00, 0x3c, 0x42, 0x42, 0x3e, 0x02, 0x3c, 0x00},
	{0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00},
	{0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20},
	{0x00, 0x00, 0x08, 0x10, 0x20, 0x10, 0x08, 0x00},
	{0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00},
	{0x00, 0x00, 0x10, 0x08, 0x04, 0x08, 0x10, 0x00},
	{0x00, 0x3c, 0x42, 0x0c, 0x10, 0x00, 0x10, 0x00},
	{0x00, 0x3c, 0x42, 0x52, 0x5e, 0x40, 0x3c, 0x00},
	{0x00, 0x3c, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x00},
	{0x00, 0x7c, 0x42, 0x7c, 0x42, 0x42, 0x7c, 0x00},
	{0x00, 0x3c, 0x42, 0x40, 0x40, 0x42, 0x3c, 0x00},
	{0x00, 0x78, 0x44, 0x42, 0x42, 0x44, 0x78, 0x00},
	{0x00, 0x7e, 0x40, 0x7c, 0x40, 0x40, 0x7e, 0x00},
	{0x00, 0x7e, 0x40, 0x40, 0x7c, 0x40, 0x40, 0x00},
	{0x00, 0x3c, 0x42, 0x40, 0x4e, 0x42, 0x3c, 0x00},
	{0x00, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x00},
	{0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00},
	{0x00, 0x02, 0x02, 0x02, 0x42, 0x42, 0x3c, 0x00},
	{0x00, 0x44, 0x48, 0x70, 0x48, 0x44, 0x42, 0x00},
	{0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7e, 0x00},
	{0x00, 0x42, 0x66, 0x5a, 0x42, 0x42, 0x42, 0x00},
	{0x00, 0x42, 0x62, 0x52, 0x4a, 0x46, 0x42, 0x00},
	{0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00},
	{0x00, 0x7c, 0x42, 0x42, 0x7c, 0x40, 0x40, 0x00},
	{0x00, 0x3c, 0x42, 0x42, 0x52, 0x4a, 0x3c, 0x00},
	{0x00, 0x7c, 0x42, 0x42, 0x7c, 0x44, 0x42, 0x00},
	{0x00, 0x3c, 0x40, 0x3c, 0x02, 0x42, 0x3c, 0x00},
	{0x00, 0xfe, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00},
	{0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00},
	{0x00, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00},
	{0x00, 0x42, 0x42, 0x42, 0x5a, 0x66, 0x42, 0x00},
	{0x00, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x00},
	{0x00, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x00},
	{0x00, 0x7e, 0x04, 0x08, 0x10, 0x20, 0x7e, 0x00},
	{0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00},
	{0x00, 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00},
	{0x00, 0x70, 0x10, 0x10, 0x10, 0x10, 0x70, 0x00},
	{0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff},
	{0x00, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x38, 0x04, 0x3c, 0x44, 0x3c, 0x00},
	{0x00, 0x20, 0x20, 0x3c, 0x22, 0x22, 0x3c, 0x00},
	{0x00, 0x00, 0x1c, 0x20, 0x20, 0x20, 0x1c, 0x00},
	{0x00, 0x04, 0x04, 0x3c, 0x44, 0x44, 0x3c, 0x00},
	{0x00, 0x00, 0x38, 0x44, 0x78, 0x40, 0x3c, 0x00},
	{0x00, 0x0c, 0x10, 0x1c, 0x10, 0x10, 0x10, 0x00},
	{0x00, 0x00, 0x38, 0x44, 0x44, 0x3c, 0x04, 0x38},
	{0x00, 0x40, 0x40, 0x58, 0x64, 0x44, 0x44, 0x00},
	{0x00, 0x10, 0x00, 0x30, 0x10, 0x10, 0x0c, 0x00},
	{0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x48, 0x30},
	{0x00, 0x20, 0x20, 0x28, 0x30, 0x28, 0x24, 0x00},
	{0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0c, 0x00},
	{0x00, 0x00, 0x68, 0x54, 0x54, 0x54, 0x54, 0x00},
	{0x00, 0x00, 0x58, 0x64, 0x44, 0x44, 0x44, 0x00},
	{0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00},
	{0x00, 0x00, 0x78, 0x44, 0x44, 0x78, 0x40, 0x40},
	{0x00, 0x00, 0x3c, 0x44, 0x44, 0x3c, 0x04, 0x06},
	{0x00, 0x00, 0x2c, 0x30, 0x20, 0x20, 0x20, 0x00},
	{0x00, 0x00, 0x38, 0x40, 0x38, 0x04, 0x78, 0x00},
	{0x00, 0x10, 0x10, 0x3c, 0x10, 0x10, 0x0c, 0x00},
	{0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00},
	{0x00, 0x00, 0x44, 0x44, 0x28, 0x28, 0x10, 0x00},
	{0x00, 0x00, 0x44, 0x54, 0x54, 0x54, 0x28, 0x00},
	{0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00},
	{0x00, 0x00, 0x44, 0x44, 0x44, 0x3c, 0x04, 0x38},
	{0x00, 0x00, 0x7c, 0x08, 0x10, 0x20, 0x7c, 0x00},
	{0x00, 0x0e, 0x08, 0x30, 0x08, 0x08, 0x0e, 0x00},
	{0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00},
	{0x00, 0x70, 0x10, 0x0c, 0x10, 0x10, 0x70, 0x00},
	{0x00, 0x32, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00},
	{0x3c, 0x42, 0x99, 0xa1, 0xa1, 0x99, 0x42, 0x3c},
	{0x00, 0x3c, 0x42, 0x40, 0x42, 0x3c, 0x10, 0x70},
	{0x00, 0x44, 0x00, 0x44, 0x44, 0x44, 0x38, 0x00},
	{0x08, 0x10, 0x38, 0x44, 0x78, 0x40, 0x3c, 0x00},
	{0x10, 0x28, 0x00, 0x3c, 0x44, 0x4c, 0x34, 0x00},
	{0x00, 0x24, 0x00, 0x3c, 0x44, 0x4c, 0x34, 0x00},
	{0x00, 0x20, 0x10, 0x3c, 0x44, 0x4c, 0x34, 0x00},
	{0x10, 0x28, 0x10, 0x3c, 0x44, 0x4c, 0x34, 0x00},
	{0x00, 0x00, 0x1c, 0x20, 0x20, 0x1c, 0x08, 0x18},
	{0x10, 0x28, 0x38, 0x44, 0x78, 0x40, 0x3c, 0x00},
	{0x28, 0x00, 0x38, 0x44, 0x78, 0x40, 0x3c, 0x00},
	{0x20, 0x10, 0x3c, 0x44, 0x78, 0x40, 0x3c, 0x00},
	{0x00, 0x28, 0x00, 0x30, 0x10, 0x10, 0x0c, 0x00},
	{0x10, 0x28, 0x00, 0x30, 0x10, 0x10, 0x0c, 0x00},
	{0x20, 0x10, 0x00, 0x30, 0x10, 0x10, 0x0c, 0x00},
	{0x42, 0x3c, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x00},
	{0x08, 0x14, 0x3c, 0x42, 0x7e, 0x42, 0x42, 0x00},
	{0x08, 0x10, 0x7e, 0x40, 0x7c, 0x40, 0x7e, 0x00},
	{0x00, 0x00, 0x6c, 0x12, 0x3c, 0x50, 0x6e, 0x00},
	{0x00, 0x3e, 0x50, 0x7c, 0x50, 0x50, 0x5e, 0x00},
	{0x10, 0x28, 0x00, 0x38, 0x44, 0x44, 0x38, 0x00},
	{0x28, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00},
	{0x20, 0x10, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00},
	{0x10, 0x28, 0x00, 0x44, 0x44, 0x44, 0x38, 0x00},
	{0x20, 0x10, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00},
	{0x44, 0x00, 0x44, 0x44, 0x44, 0x3c, 0x04, 0x38},
	{0x42, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00},
	{0x42, 0x00, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00},
	{0x00, 0x10, 0x38, 0x40, 0x40, 0x38, 0x10, 0x00},
	{0x00, 0x1c, 0x22, 0x78, 0x20, 0x20, 0x7e, 0x00},
	{0x00, 0x44, 0x28, 0x7c, 0x10, 0x7c, 0x10, 0x00},
	{0x00, 0x7c, 0x42, 0x52, 0x7c, 0x50, 0x4c, 0x00},
	{0x00, 0x0c, 0x10, 0x7c, 0x10, 0x10, 0x60, 0x00},
	{0x08, 0x10, 0x00, 0x3c, 0x44, 0x4c, 0x34, 0x00},
	{0x08, 0x10, 0x00, 0x30, 0x10, 0x10, 0x0c, 0x00},
	{0x08, 0x10, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00},
	{0x08, 0x10, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00},
	{0x32, 0x4c, 0x00, 0x5c, 0x62, 0x42, 0x42, 0x00},
	{0x32, 0x4c, 0x00, 0x62, 0x52, 0x4a, 0x46, 0x00},
	{0x38, 0x48, 0x58, 0x28, 0x00, 0x78, 0x00, 0x00},
	{0x30, 0x48, 0x48, 0x30, 0x00, 0x78, 0x00, 0x00},
	{0x00, 0x08, 0x00, 0x08, 0x30, 0x42, 0x3c, 0x00},
	{0x00, 0x00, 0x00, 0x00, 0x7c, 0x40, 0x40, 0x00},
	{0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x00},
	{0x44, 0x48, 0x50, 0x2c, 0x42, 0x04, 0x0e, 0x00},
	{0x44, 0x48, 0x50, 0x24, 0x54, 0x1e, 0x04, 0x00},
	{0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00},
	{0x00, 0x00, 0x12, 0x24, 0x48, 0x24, 0x12, 0x00},
	{0x00, 0x00, 0x48, 0x24, 0x12, 0x24, 0x48, 0x00},
	{0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11},
	{0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55},
	{0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11},
	{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
	{0x10, 0x10, 0x10, 0x10, 0xf0, 0x10, 0x10, 0x10},
	{0x10, 0x10, 0x10, 0xf0, 0x10, 0xf0, 0x10, 0x10},
	{0x28, 0x28, 0x28, 0x28, 0xe8, 0x28, 0x28, 0x28},
	{0x00, 0x00, 0x00, 0x00, 0xf8, 0x28, 0x28, 0x28},
	{0x00, 0x00, 0x00, 0xf0, 0x10, 0xf0, 0x10, 0x10},
	{0x28, 0x28, 0x28, 0xe8, 0x08, 0xe8, 0x28, 0x28},
	{0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28},
	{0x00, 0x00, 0x00, 0xf8, 0x08, 0xe8, 0x28, 0x28},
	{0x28, 0x28, 0x28, 0xe8, 0x08, 0xf8, 0x00, 0x00},
	{0x28, 0x28, 0x28, 0x28, 0xf8, 0x00, 0x00, 0x00},
	{0x10, 0x10, 0x10, 0xf0, 0x10, 0xf0, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0x00, 0xf0, 0x10, 0x10, 0x10},
	{0x10, 0x10, 0x10, 0x10, 0x1f, 0x00, 0x00, 0x00},
	{0x10, 0x10, 0x10, 0x10, 0xff, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0x00, 0xff, 0x10, 0x10, 0x10},
	{0x10, 0x10, 0x10, 0x10, 0x1f, 0x10, 0x10, 0x10},
	{0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00},
	{0x10, 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10},
	{0x10, 0x10, 0x10, 0x1f, 0x10, 0x1f, 0x10, 0x10},
	{0x28, 0x28, 0x28, 0x28, 0x2f, 0x28, 0x28, 0x28},
	{0x28, 0x28, 0x28, 0x2f, 0x20, 0x3f, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0x3f, 0x20, 0x2f, 0x28, 0x28},
	{0x28, 0x28, 0x28, 0xef, 0x00, 0xff, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0xff, 0x00, 0xef, 0x28, 0x28},
	{0x28, 0x28, 0x28, 0x2f, 0x20, 0x2f, 0x28, 0x28},
	{0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00},
	{0x28, 0x28, 0x28, 0xef, 0x00, 0xef, 0x28, 0x28},
	{0x10, 0x10, 0x10, 0xff, 0x00, 0xff, 0x00, 0x00},
	{0x28, 0x28, 0x28, 0x28, 0xff, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x10, 0x10},
	{0x00, 0x00, 0x00, 0x00, 0xff, 0x28, 0x28, 0x28},
	{0x28, 0x28, 0x28, 0x28, 0x3f, 0x00, 0x00, 0x00},
	{0x10, 0x10, 0x10, 0x1f, 0x10, 0x1f, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0x1f, 0x10, 0x1f, 0x10, 0x10},
	{0x00, 0x00, 0x00, 0x00, 0x3f, 0x28, 0x28, 0x28},
	{0x28, 0x28, 0x28, 0x28, 0xef, 0x28, 0x28, 0x28},
	{0x10, 0x10, 0x10, 0xff, 0x00, 0xff, 0x10, 0x10},
	{0x10, 0x10, 0x10, 0x10, 0xf0, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0x00, 0x1f, 0x10, 0x10, 0x10},
	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
	{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff},
	{0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0},
	{0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f},
	{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x32, 0x4a, 0x44, 0x44, 0x3a, 0x00},
	{0x00, 0x38, 0x44, 0x5c, 0x42, 0x62, 0x5c, 0x40},
	{0x00, 0x7e, 0x42, 0x40, 0x40, 0x40, 0x40, 0x00},
	{0x00, 0x00, 0x7c, 0x28, 0x28, 0x28, 0x24, 0x00},
	{0x00, 0x7e, 0x22, 0x10, 0x10, 0x22, 0x7e, 0x00},
	{0x00, 0x00, 0x3e, 0x44, 0x44, 0x44, 0x38, 0x00},
	{0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x7a, 0x40},
	{0x00, 0x00, 0x7c, 0x10, 0x10, 0x10, 0x08, 0x00},
	{0x00, 0x10, 0x38, 0x54, 0x54, 0x38, 0x10, 0x00},
	{0x00, 0x3c, 0x42, 0x42, 0x7e, 0x42, 0x3c, 0x00},
	{0x00, 0x3c, 0x42, 0x42, 0x42, 0x24, 0x66, 0x00},
	{0x78, 0x20, 0x18, 0x44, 0x44, 0x44, 0x38, 0x00},
	{0x00, 0x00, 0x6c, 0x92, 0x92, 0x6c, 0x00, 0x00},
	{0x00, 0x00, 0x18, 0x54, 0x54, 0x38, 0x10, 0x00},
	{0x00, 0x3e, 0x40, 0x7e, 0x40, 0x40, 0x3e, 0x00},
	{0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00},
	{0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x7e, 0x00},
	{0x00, 0x08, 0x08, 0x3e, 0x08, 0x00, 0x3e, 0x00},
	{0x00, 0x10, 0x08, 0x04, 0x08, 0x10, 0x3c, 0x00},
	{0x00, 0x08, 0x10, 0x20, 0x10, 0x08, 0x3c, 0x00},
	{0x00, 0x00, 0x08, 0x14, 0x10, 0x10, 0x10, 0x10},
	{0x10, 0x10, 0x10, 0x10, 0x50, 0x20, 0x00, 0x00},
	{0x00, 0x00, 0x08, 0x00, 0x3e, 0x00, 0x08, 0x00},
	{0x00, 0x00, 0x32, 0x4c, 0x00, 0x32, 0x4c, 0x00},
	{0x00, 0x18, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},
	{0x00, 0x0e, 0x08, 0x08, 0x48, 0x28, 0x18, 0x00},
	{0x00, 0x50, 0x68, 0x48, 0x48, 0x00, 0x00, 0x00},
	{0x00, 0x60, 0x10, 0x20, 0x70, 0x00, 0x00, 0x00},
	{0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00},
	{0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00}};

SDL_Window *gWindow;
SDL_Renderer *gRenderer;
SDL_Texture *gTexture;
Uint32 *pixels;

#pragma mark - HELPERS

int
clamp(int val, int min, int max)
{
	return (val >= min) ? (val <= max) ? val : max : min;
}

char *
scpy(char *src, char *dst, int len)
{
	int i = 0;
	while((dst[i] = src[i]) && i < len - 2)
		i++;
	dst[i + 1] = '\0';
	return dst;
}

#pragma mark - DRAW

void
clear(Uint32 *dst)
{
	int v, h;
	for(v = 0; v < HEIGHT; v++)
		for(h = 0; h < WIDTH; h++)
			dst[v * WIDTH + h] = theme[0];
}

void
putpixel(Uint32 *dst, int x, int y, int color)
{
	if(x >= 0 && x < WIDTH - 8 && y >= 0 && y < HEIGHT - 8)
		dst[(y + PAD * 8) * WIDTH + (x + PAD * 8)] = theme[color];
}

void
drawchr(Uint32 *dst, int x, int y, Uint8 *sprite)
{
	int v, h;
	for(v = 0; v < 8; v++)
		for(h = 0; h < 8; h++) {
			int ch1 = ((sprite[v] >> h) & 0x1);
			int ch2 = (((sprite[v + 8] >> h) & 0x1) << 1);
			putpixel(dst, x + 7 - h, y + v, ch1 + ch2);
		}
}

void
drawicn(Uint32 *dst, int x, int y, Uint8 *sprite, int fg, int bg)
{
	int v, h;
	for(v = 0; v < 8; v++)
		for(h = 0; h < 8; h++) {
			int ch1 = (sprite[v] >> (7 - h)) & 0x1;
			putpixel(dst, x + h, y + v, ch1 ? fg : bg);
		}
}

int
gethexfont(int v)
{
	if(v >= 0 && v <= 9)
		return 48 + v;
	if(v >= 10 && v <= 15)
		return 55 + v;
	return 46;
}

void
drawui(Uint32 *dst)
{
	int bottom = VER * 8 + 8;
	drawicn(dst, 0 * 8, bottom, icons[3], 2, 0);
	drawicn(dst, 1 * 8, bottom, icons[4], 2, 0);
	drawicn(dst, 2 * 8, bottom, icons[5], 2, 0);
	drawicn(dst, 3 * 8, bottom, icons[6], 2, 0);
	drawicn(dst, 5 * 8, bottom, icons[GUIDES ? 12 : 11], GUIDES ? 1 : 2, 0);
	drawicn(dst, (HOR - 1) * 8, bottom, icons[13], doc.unsaved ? 2 : 3, 0);
	drawicn(dst, 15 * 8, bottom, font[gethexfont((cursor.i >> 12) & 0xf)], 3, 0);
	drawicn(dst, 16 * 8, bottom, font[gethexfont((cursor.i >> 8) & 0xf)], 3, 0);
	drawicn(dst, 17 * 8, bottom, font[gethexfont((cursor.i >> 4) & 0xf)], 3, 0);
	drawicn(dst, 18 * 8, bottom, font[gethexfont(cursor.i & 0xf)], 3, 0);
}

void
drawline(Uint32 *dst, int y, int id)
{
	int b = 0;
	if(id >= SZ)
		return;
	for(b = 0; b < 8; ++b) {
		int x = b * 2 + ((b % 8) / 2);
		int k = id + b;
		int b0 = gethexfont(doc.data[k] >> 4 & 0xf);
		int b1 = gethexfont(doc.data[k] & 0xf);
		int bc = doc.data[k];
		int sel = cursor.i == k;
		int linesel = GUIDES && cursor.y == id / 8;
		int pagesel = id % 256 == 0;
		drawicn(dst, x * 8, y, font[b0], sel ? 0 : linesel + pagesel + 1, sel ? 2 : 0);
		drawicn(dst, x * 8 + 8, y, font[b1], sel ? 0 : linesel + pagesel + 1, sel ? 2 : 0);
		drawicn(dst, (19 + (k % 8)) * 8 + 8, y, bc ? font[bc] : icons[2], bc ? 1 : 3, sel ? 4 : 0);
	}
	drawicn(dst, 29 * 8, y, &doc.data[id], 1, 0);
	if(id % 16 == 0)
		drawchr(dst, 31 * 8, y, &doc.data[id]);
}

void
redraw(Uint32 *dst)
{
	int y;
	clear(dst);
	for(y = 0; y < VER; ++y)
		drawline(dst, y * 8, (cursor.view + y) * 8);
	drawui(dst);
	SDL_UpdateTexture(gTexture, NULL, dst, WIDTH * sizeof(Uint32));
	SDL_RenderClear(gRenderer);
	SDL_RenderCopy(gRenderer, gTexture, NULL, NULL);
	SDL_RenderPresent(gRenderer);
}

#pragma mark - OPTIONS

int
error(char *msg, const char *err)
{
	printf("Error %s: %s\n", msg, err);
	return 0;
}

void
savemode(int *i, int v)
{
	*i = v;
	redraw(pixels);
}

void
makedoc(Document *d, char *name)
{
	int i;
	for(i = 0; i < SZ; ++i)
		d->data[i] = 0x00;
	d->unsaved = 0;
	scpy(name, d->name, 256);
	printf("Made: %s\n", d->name);
	redraw(pixels);
}

int
savedoc(Document *d, char *name)
{
	FILE *f = fopen(name, "w");
	if(!fwrite(d->data, sizeof(d->data), 1, f))
		return error("Save", "Failure");
	d->unsaved = 0;
	scpy(name, d->name, 256);
	fclose(f);
	printf("Saved: %s\n", d->name);
	redraw(pixels);
	return 1;
}

int
opendoc(Document *d, char *name)
{
	FILE *f = fopen(name, "r");
	if(!f)
		return error("Load", "Invalid input file");
	fread(doc.data, sizeof(doc.data), 1, f);
	d->unsaved = 0;
	scpy(name, doc.name, 256);
	fclose(f);
	printf("Loaded: %s\n", doc.name);
	redraw(pixels);
	return 1;
}

int
printdoc(Document *d)
{
	int i;
	FILE *f = fopen("exed-output.c", "w");
	fprintf(f, "{");
	for(i = 0; i < SZ; ++i) {
		if(i > 0 && i % 16 == 0)
			fprintf(f, "},\n{");
		fprintf(f, "0x%02x", doc.data[i]);
		if(i % 16 < 15)
			fprintf(f, ", ");
	}
	fprintf(f, "}");
	fclose(f);
	puts("Saved exed-output.c");
	return 1;
}

int
printline(Document *d, int id)
{
	int i;
	FILE *f = fopen("exed-output-selection.c", "w");
	fprintf(f, "{");
	for(i = 0; i < 8; ++i) {
		fprintf(f, "0x%02x", doc.data[id + i]);
		if(i % 8 < 7)
			fprintf(f, ", ");
	}
	fprintf(f, "}");
	fclose(f);
	puts("Saved exed-output-selection.c");
	return 1;
}

void
copyclip(int i)
{
	cursor.clip = doc.data[i];
}

void
pasteclip(int i)
{
	doc.data[i] = cursor.clip;
	redraw(pixels);
}

void
cutclip(int i)
{
	copyclip(i);
	doc.data[i] = 0x00;
	redraw(pixels);
}

void
select(int x, int y)
{
	cursor.x = clamp(x, 0, 7);
	cursor.y = clamp(y, 0, SZ / 8 - 1);
	cursor.i = cursor.x % 8 + (cursor.y * 8);
	if(cursor.y >= cursor.view + VER)
		cursor.view = clamp(cursor.y - VER + 1, 0, SZ - 4);
	if(cursor.y <= cursor.view)
		cursor.view = clamp(cursor.y, 0, SZ - 4);
	cursor.swap = 0;
	redraw(pixels);
}

void
insert(int v)
{
	if(!cursor.swap)
		doc.data[cursor.i] = v * 16 + (doc.data[cursor.i] & 0xf);
	else
		doc.data[cursor.i] = (doc.data[cursor.i] / 16 * 16) + v;
	cursor.swap = !cursor.swap;
	redraw(pixels);
}

char
doincr(char c)
{
	return c + 1;
}

char
dodecr(char c)
{
	return c - 1;
}

void
transform(int key, char (*fn)(char))
{
	doc.data[key] = fn(doc.data[key]);
	doc.unsaved = 1;
	redraw(pixels);
}

void
selectoption(int option)
{
	switch(option) {
	case 0: transform(cursor.i, doincr); break;
	case 1: transform(cursor.i, dodecr); break;
	case 2:
		doc.data[cursor.i] = doc.data[cursor.i] << 2;
		redraw(pixels);
		break;
	case 3:
		doc.data[cursor.i] = doc.data[cursor.i] >> 2;
		redraw(pixels);
		break;
	case 5: savemode(&GUIDES, !GUIDES); break;
	case HOR - 1: savedoc(&doc, doc.name); break;
	}
}

void
selectcell(int x, int y)
{
	if(GUIDES) {
		if(x == 4 || x == 9 || x == 14)
			return;
		if(x > 4)
			x--;
		if(x > 9)
			x--;
		if(x > 13)
			x--;
		x /= 2;
	} else
		x /= 3;
	select(x, y + cursor.view);
}

void
quit(void)
{
	free(pixels);
	SDL_DestroyTexture(gTexture);
	gTexture = NULL;
	SDL_DestroyRenderer(gRenderer);
	gRenderer = NULL;
	SDL_DestroyWindow(gWindow);
	gWindow = NULL;
	SDL_Quit();
	exit(0);
}

#pragma mark - TRIGGERS

void
domouse(SDL_Event *event)
{
	switch(event->type) {
	case SDL_MOUSEBUTTONUP:
		break;
	case SDL_MOUSEBUTTONDOWN:
		if(event->motion.y / ZOOM / 8 - PAD == VER + 1) {
			selectoption(event->motion.x / ZOOM / 8 - PAD);
			return;
		}
		selectcell(
			event->motion.x / ZOOM / 8 - PAD,
			event->motion.y / ZOOM / 8 - PAD);
		break;
	case SDL_MOUSEMOTION:

		break;
	}
}

void
dokey(SDL_Event *event)
{
	int shift = SDL_GetModState() & KMOD_LSHIFT || SDL_GetModState() & KMOD_RSHIFT;
	int ctrl = SDL_GetModState() & KMOD_LCTRL || SDL_GetModState() & KMOD_RCTRL;
	if(ctrl) {
		switch(event->key.keysym.sym) {
		/* Generic */
		case SDLK_n: makedoc(&doc, "untitled.chr"); break;
		case SDLK_r: opendoc(&doc, doc.name); break;
		case SDLK_s: savedoc(&doc, doc.name); break;
		case SDLK_x: cutclip(cursor.i); break;
		case SDLK_c: copyclip(cursor.i); break;
		case SDLK_v: pasteclip(cursor.i); break;
		case SDLK_p: shift ? printline(&doc, cursor.y * 8) : printdoc(&doc); break;
		case SDLK_h: savemode(&GUIDES, !GUIDES); break;
		case SDLK_UP: transform(cursor.i, doincr); break;
		case SDLK_DOWN: transform(cursor.i, dodecr); break;
		}
	} else {
		switch(event->key.keysym.sym) {
		case SDLK_UP: select(cursor.x, cursor.y - 1); break;
		case SDLK_DOWN: select(cursor.x, cursor.y + 1); break;
		case SDLK_LEFT: select(cursor.x - 1, cursor.y); break;
		case SDLK_RIGHT: select(cursor.x + 1, cursor.y); break;
		case SDLK_PAGEUP: select(cursor.x, cursor.y - 16); break;
		case SDLK_PAGEDOWN: select(cursor.x, cursor.y + 16); break;
		case SDLK_BACKSPACE: insert(0); break;
		}
	}
}

void
dotext(SDL_Event *event)
{
	int i;
	if(SDL_GetModState() & KMOD_LCTRL || SDL_GetModState() & KMOD_RCTRL)
		return;
	for(i = 0; i < SDL_TEXTINPUTEVENT_TEXT_SIZE; ++i) {
		char c = event->text.text[i];
		if(c < ' ' || c > '~')
			break;
		if(c < '0' || c > 'f')
			break;
		if(c >= '0' && c <= '9')
			insert(c - '0');
		if(c >= 'a' && c <= 'f')
			insert(c - 'a' + 10);
	}
}

void
dowheel(SDL_Event *event)
{
	select(cursor.x, cursor.y - event->wheel.y);
}

int
init(void)
{
	if(SDL_Init(SDL_INIT_VIDEO) < 0)
		return error("Init", SDL_GetError());
	gWindow = SDL_CreateWindow("Exed",
		SDL_WINDOWPOS_UNDEFINED,
		SDL_WINDOWPOS_UNDEFINED,
		WIDTH * ZOOM,
		HEIGHT * ZOOM,
		SDL_WINDOW_SHOWN);
	if(gWindow == NULL)
		return error("Window", SDL_GetError());
	gRenderer = SDL_CreateRenderer(gWindow, -1, 0);
	if(gRenderer == NULL)
		return error("Renderer", SDL_GetError());
	gTexture = SDL_CreateTexture(gRenderer,
		SDL_PIXELFORMAT_ARGB8888,
		SDL_TEXTUREACCESS_STATIC,
		WIDTH,
		HEIGHT);
	if(gTexture == NULL)
		return error("Texture", SDL_GetError());
	pixels = (Uint32 *)malloc(WIDTH * HEIGHT * sizeof(Uint32));
	if(pixels == NULL)
		return error("Pixels", "Failed to allocate memory");
	clear(pixels);
	return 1;
}

int
main(int argc, char **argv)
{
	int ticknext = 0;
	if(!init())
		return error("Init", "Failure");
	if(argc > 1) {
		if(!opendoc(&doc, argv[1]))
			makedoc(&doc, argv[1]);
	} else
		makedoc(&doc, "untitled.chr");
	select(0, 0);
	while(1) {
		int tick = SDL_GetTicks();
		SDL_Event event;
		if(tick < ticknext)
			SDL_Delay(ticknext - tick);
		ticknext = tick + (1000 / FPS);
		while(SDL_PollEvent(&event) != 0) {
			switch(event.type) {
			case SDL_QUIT: quit(); break;
			case SDL_MOUSEBUTTONUP:
			case SDL_MOUSEBUTTONDOWN:
			case SDL_MOUSEMOTION: domouse(&event); break;
			case SDL_MOUSEWHEEL: dowheel(&event); break;
			case SDL_TEXTINPUT: dotext(&event); break;
			case SDL_KEYDOWN: dokey(&event); break;
			case SDL_WINDOWEVENT:
				if(event.window.event == SDL_WINDOWEVENT_EXPOSED)
					redraw(pixels);
				break;
			}
		}
	}
	quit();
	return 0;
}

A src/main.tal => src/main.tal +410 -0
@@ 0,0 1,410 @@
(
	app/dexe : hex editor
	
	arrows     - move selection
	enter      - insert byte
	backspace  - delete byte
	left-click - select bytes

	TODO:
		copy/paste
		scrollbar
)

%+  { ADD } %-   { SUB }  %*  { MUL } %/   { DIV }
%<  { LTH } %>   { GTH }  %=  { EQU } %!   { NEQ }
%++ { ADD2 } %-- { SUB2 } %** { MUL2 } %// { DIV2 }
%<< { LTH2 } %>> { GTH2 } %== { EQU2 } %!! { NEQ2 }

%DEBUG  { ;print-hex/byte JSR2 #0a .Console/write DEO }
%DEBUG2 { ;print-hex/short JSR2 #0a .Console/write DEO }

%RTN  { JMP2r }
%SWP2? { #01 JCN SWP }

%2*   { #10 SFT }
%8*   { #30 SFT }
%20*  { #50 SFT } 
%40*  { #60 SFT }
%2**  { #10 SFT2 } %2// { #01 SFT2 }
%4**  { #20 SFT2 } %4// { #02 SFT2 }
%8**  { #30 SFT2 } %8// { #03 SFT2 }
%10** { #40 SFT2 }

%TOS  { #00 SWP } %TOB { SWP POP }
%INCR { SWP #01 + SWP }
%TOGGLE { DUP LDZ #00 = SWP STZ }
%INCR2 { SWP2 #0001 ++ SWP2 }
%DECR2 { SWP2 #0001 -- SWP2 }

%ASCII-FONT { TOS #0008 ** ;font-hex ++ }
%RELEASE-MOUSE { #00 .Mouse/state DEO }
%RESET-SELECTION { #0000 DUP2 .selection/from STZ2 .selection/to STZ2 }

( devices )

|00 @System     &vector $2 &pad     $6 &r      $2 &g     $2 &b     $2
|10 @Console    &vector $2 &read    $1 &pad    $5 &write $1 
|20 @Screen     &vector $2 &width   $2 &height $2 &auto  $1 &pad   $1 &x     $2 &y $2 &addr $2 &pixel $1 &sprite $1
|80 @Controller &vector $2 &button  $1 &key    $1
|90 @Mouse      &vector $2 &x       $2 &y      $2 &state $1 &chord $1 &wheel $1
|a0 @File       &vector $2 &success $2 &offset $2 &pad   $2 &name  $2 &length $2 &load $2 &save $2

( variables )

|0000

@scroll $2
@cursor 
	&x $2 &y $2 
@state
	&timer $1
	&trap $1
	&blink $1
@pointer
	&x $2 
	&y $2
	&last $1
@selection
	&from $2
	&to $2
	&scroll $2
	&nibble $1
@path 
	&length $1
	&name $20
@frame
	&x $2 &y $2 &x2 $2 &y2 $2 

( program )

|0100
	
	( theme )
	#0f77 .System/r DEO2 
	#0fc7 .System/g DEO2 
	#0f97 .System/b DEO2

	( vectors ) 
	;on-button .Controller/vector DEO2
	;on-mouse .Mouse/vector DEO2
	;on-frame    .Screen/vector DEO2

	( set size )

	( frame )
	.Screen/width DEI2 2// #0080 -- DUP2 .frame/x STZ2
		#0100 ++ .frame/x2 STZ2
	.Screen/height DEI2 2// #0080 -- DUP2 .frame/y STZ2
		#0100 ++ .frame/y2 STZ2

	( load bytes )
	;untitled-txt .File/name DEO2
	#1000         .File/length DEO2
	;MEMORY       .File/load DEO2

	#0000 .scroll STZ2
	;redraw JSR2

BRK

@on-frame ( -> )
	
BRK

@on-button ( -> )

BRK

@on-mouse ( -> )

	( clear last cursor )
	.cursor/x LDZ2 .Screen/x DEO2
	.cursor/y LDZ2 .Screen/y DEO2
	#40 .Screen/sprite DEO

	( draw new cursor )
	.Mouse/x DEI2 DUP2 .cursor/x STZ2 .Screen/x DEO2
	.Mouse/y DEI2 DUP2 .cursor/y STZ2 .Screen/y DEO2
	;cursor-icn .Screen/addr DEO2
	.Mouse/state DEI #00 ! #41 + .Screen/sprite DEO
	
BRK

@redraw ( -- )

	#0020 #0000 
	&loop
		( addr ) DUP2 8** ;MEMORY ++ STH2
		( y ) DUP2 8** .frame/y LDZ2 ++
		STH2r ;draw-row JSR2
		INC2 GTH2k ,&loop JCN
	POP2 POP2

RTN

@draw-row ( y* id* -- )

	;&row STA2
	;&y STA2

	#08 #00
	&bytes-loop
		( color ) #01 STH
		( byte ) DUP TOS ;&row LDA2 ++ LDA DUP DEBUG STH
		( y ) ;&y LDA2 STH2
		( x-block ) DUP TOS ;byte-spacing ++ LDA TOS 8** .frame/x LDZ2 ++
		STH2r STHr STHr ;draw-byte JSR2
		INC GTHk ,&bytes-loop JCN
	POP2

	#08 #00
	&chars-loop
		( color ) #08 STH
		( byte ) DUP TOS ;&row LDA2 ++ LDA STH
		( y ) ;&y LDA2 STH2
		( x-block ) DUP TOS 8** .frame/x LDZ2 ++ #00a0 ++
		STH2r STHr STHr ;draw-char JSR2
		INC GTHk ,&chars-loop JCN
	POP2

	#00e8 .frame/x LDZ2 ++ .Screen/x DEO2
	;&row LDA2 .Screen/addr DEO2
	#01 .Screen/sprite DEO

RTN
	&y $2 &row $2

@draw-byte ( x* y* byte color -- )

	STH STH
	.Screen/y DEO2
	.Screen/x DEO2
	STHr
	DUP
		( hn )
		#0f AND TOS 8** ;font-hex ++ .Screen/addr DEO2
		STHkr .Screen/sprite DEO
	.Screen/x DEI2 #0008 ++ .Screen/x DEO2
		( ln )
		#04 SFT TOS 8** ;font-hex ++ .Screen/addr DEO2
		STHr .Screen/sprite DEO

RTN

@draw-char ( x* y* char color -- )

	STH STH
	.Screen/y DEO2
	.Screen/x DEO2
	STHr
	TOS 8** ;font ++ .Screen/addr DEO2
	STHr .Screen/sprite DEO

RTN

@line-rect ( rect color -- )

	STH STH
	( y2 ) STHkr #06 + LDZ2
	( y1 ) STHkr #02 + LDZ2 #0001 -- ( flip sign ) GTH2k SWP2?
	&ver
		( save ) DUP2 .Screen/y DEO2
		( x1 ) STHkr LDZ2 #0001 -- .Screen/x DEO2 
		OVRr STHr .Screen/pixel DEO
		( x2 ) STHkr #04 + LDZ2 .Screen/x DEO2 
		OVRr STHr .Screen/pixel DEO
		( incr )
		INC2 GTH2k ,&ver JCN
	POP2
	( x2 ) STHkr #04 + LDZ2
	( x1 ) STHkr LDZ2 #0001 -- ( flip sign ) GTH2k SWP2?
	&hor
		( save ) DUP2 .Screen/x DEO2
		( y1 ) STHkr #02 + LDZ2 #0001 -- .Screen/y DEO2 
		OVRr STHr .Screen/pixel DEO
		( y2 ) STHkr #06 + LDZ2 .Screen/y DEO2 
		OVRr STHr .Screen/pixel DEO
		( incr )
		INC2 GTH2k ,&hor JCN
	POP2
	POPr 
	.Screen/x DEO2
	.Screen/y DEO2 
	STHr .Screen/pixel DEO

RTN

@print-hex ( value* -- )
	
	&short ( value* -- )
		SWP ,&echo JSR 
	&byte ( value -- )
		,&echo JSR
	RTN

	&echo ( value -- )
	STHk #04 SFT ,&parse JSR .Console/write DEO
	STHr #0f AND ,&parse JSR .Console/write DEO
	RTN
	&parse ( value -- char )
		DUP #09 GTH ,&above JCN #30 + RTN &above #09 - #60 + RTN

RTN

@byte-spacing
	0002 0507 0a0c 0f11
	1416 191b 1e20 2325

@untitled-txt  "example.chr $1
@cursor-icn    80c0 e0f0 f8e0 1000

@scrollbar_icn
	aa55 aa55 aa55 aa55 ( bg )
	ffff ffff ffff ffff ( fg )
	0010 387c fe10 1010 ( up )
	0010 1010 fe7c 3810 ( down )

@font-hex
	007c 8282 8282 827c 0030 1010 1010 1010
	007c 8202 7c80 80fe 007c 8202 1c02 827c
	000c 1424 4484 fe04 00fe 8080 7c02 827c
	007c 8280 fc82 827c 007c 8202 1e02 0202
	007c 8282 7c82 827c 007c 8282 7e02 827c
	007c 8202 7e82 827e 00fc 8282 fc82 82fc
	007c 8280 8080 827c 00fc 8282 8282 82fc
	007c 8280 f080 827c 007c 8280 f080 8080 

@font ( specter8 font )
	0000 0000 0000 0000 0000 2400 7e3c 0000
	0000 2400 3c42 0000 0000 6c7c 7c38 1000
	0010 387c 7c38 1000 0038 387c 6c10 3800
	0010 387c 7c10 3800 0000 0018 1800 0000
	007e 4242 4242 7e00 0000 1824 2418 0000
	003c 665a 5a66 3c00 001e 063a 4a48 3000
	0038 446c 107c 1000 000e 0808 0838 3800
	003e 3e22 2266 6600 0000 1044 0044 1000
	0000 1018 1c18 1000 0000 0818 3818 0800
	0008 1c00 001c 0800 0028 2828 2800 2800
	003e 4a4a 3a0a 0a00 000c 3046 620c 3000
	0000 0000 0000 ffff 0010 3800 3810 0038
	0010 3854 1010 1000 0010 1010 5438 1000
	0000 0804 7e04 0800 0000 1020 7e20 1000
	0000 4040 7e00 0000 0000 0024 6624 0000
	0000 1038 7c00 0000 0000 007c 3810 0000
	0000 0000 0000 0000 0008 0808 0800 0800
	0014 1400 0000 0000 0024 7e24 247e 2400
	0008 1e28 1c0a 3c08 0000 2204 0810 2200
	0030 4832 4c44 3a00 0008 1000 0000 0000
	0004 0808 0808 0400 0020 1010 1010 2000
	0000 2214 0814 2200 0000 0808 3e08 0800
	0000 0000 0000 0810 0000 0000 3e00 0000
	0000 0000 0000 0800 0000 0204 0810 2000
	003c 464a 5262 3c00 0018 0808 0808 1c00
	003c 4202 3c40 7e00 003c 421c 0242 3c00
	000c 1424 447e 0400 007e 407c 0242 3c00
	003c 407c 4242 3c00 007e 0204 0810 1000
	003c 423c 4242 3c00 003c 4242 3e02 3c00
	0000 0010 0000 1000 0000 1000 0010 1020
	0000 0810 2010 0800 0000 003e 003e 0000
	0000 1008 0408 1000 003c 420c 1000 1000
	003c 4232 4a42 3c00 003c 4242 7e42 4200
	007c 427c 4242 7c00 003c 4240 4042 3c00
	007c 4242 4242 7c00 007e 4078 4040 7e00
	007e 4078 4040 4000 003c 4240 4642 3c00
	0042 427e 4242 4200 001c 0808 0808 1c00
	007e 0202 0242 3c00 0042 4478 4442 4200
	0040 4040 4040 7e00 0042 665a 4242 4200
	0042 6252 4a46 4200 003c 4242 4242 3c00
	007c 4242 7c40 4000 003c 4242 4244 3a00
	007c 4242 7c44 4200 003e 403c 0242 3c00
	007e 0808 0808 1000 0042 4242 4244 3a00
	0042 4242 4224 1800 0042 4242 5a66 4200
	0042 423c 4242 4200 0042 423e 0242 3c00
	007e 020c 3040 7e00 000c 0808 0808 0c00
	0040 2010 0804 0200 0030 1010 1010 3000
	0008 1400 0000 0000 0000 0000 0000 7e00
	0008 0400 0000 0000 0000 3c02 3e42 3a00
	0040 407c 4242 7c00 0000 3c42 4042 3c00
	0002 023e 4242 3e00 0000 3c42 7e40 3e00
	0000 3e40 7840 4000 0000 3c42 3e02 3c00
	0040 405c 6242 4200 0008 0018 0808 0400
	0008 0018 0808 4830 0040 4244 7844 4200
	0010 1010 1010 0c00 0000 6c52 5252 5200
	0000 5c62 4242 4200 0000 3c42 4242 3c00
	0000 7c42 427c 4040 0000 3e42 423e 0202
	0000 5c62 4040 4000 0000 3e40 3c02 7c00
	0008 7e08 0808 1000 0000 4242 4244 3a00
	0000 4242 4224 1800 0000 5252 5252 2e00
	0000 4224 1824 4200 0000 4242 3e02 7c00
	0000 7e02 3c40 7e00 000c 0810 1008 0c00
	0008 0808 0808 0800 0030 1008 0810 3000
	0000 0032 4c00 0000 3c42 99a1 a199 423c
	003c 4240 423c 1070 0044 0044 4444 3800
	0810 3844 7840 3c00 0814 3c02 3e42 3a00
	1400 3c02 3e42 3a00 0804 3c02 3e42 3a00
	0814 2c02 3e42 3a00 0000 1c20 201c 0818
	1028 3844 7840 3c00 2800 3844 7840 3c00
	2010 3c44 7840 3c00 0028 0030 1010 0c00
	1028 0030 1010 0c00 2010 0030 1010 0c00
	423c 4242 7e42 4200 0814 3c42 7e42 4200
	0810 7e40 7c40 7e00 0000 6c12 3c50 6e00
	003e 507c 5050 5e00 1028 0038 4444 3800
	2800 3844 4444 3800 2010 3844 4444 3800
	1028 0044 4444 3800 2010 4444 4444 3800
	4400 4444 443c 0438 423c 4242 4242 3c00
	4200 4242 4242 3c00 0010 3840 4038 1000
	001c 2278 2020 7e00 0044 287c 107c 1000
	007c 4252 7c50 4c00 000c 107c 1010 6000
	0810 3c02 3e42 3a00 0810 0030 1010 0c00
	0810 3844 4444 3800 0810 4444 4444 3800
	324c 005c 6242 4200 324c 0062 524a 4600
	3848 5828 0078 0000 3048 4830 0078 0000
	0008 0008 3042 3c00 0000 0000 7c40 4000
	0000 0000 7c04 0400 4448 502c 4204 0e00
	4448 5024 541e 0400 0010 0010 1010 1000
	0000 1224 4824 1200 0000 4824 1224 4800
	8844 2211 8844 2211 aa55 aa55 aa55 aa55
	4411 4411 4411 4411 1010 1010 1010 1010
	1010 1010 f010 1010 1010 10f0 10f0 1010
	2828 2828 e828 2828 0000 0000 f828 2828
	0000 00f0 10f0 1010 2828 28e8 08e8 2828
	2828 2828 2828 2828 0000 00f8 08e8 2828
	2828 28e8 08f8 0000 2828 2828 f800 0000
	1010 10f0 10f0 0000 0000 0000 f010 1010
	1010 1010 1f00 0000 1010 1010 ff00 0000
	0000 0000 ff10 1010 1010 1010 1f10 1010
	0000 0000 ff00 0000 1010 1010 ff10 1010
	1010 101f 101f 1010 2828 2828 2f28 2828
	2828 282f 203f 0000 0000 003f 202f 2828
	2828 28ef 00ff 0000 0000 00ff 00ef 2828
	2828 282f 202f 2828 0000 00ff 00ff 0000
	2828 28ef 00ef 2828 1010 10ff 00ff 0000
	2828 2828 ff00 0000 0000 00ff 00ff 1010
	0000 0000 ff28 2828 2828 2828 3f00 0000
	1010 101f 101f 0000 0000 001f 101f 1010
	0000 0000 3f28 2828 2828 2828 ef28 2828
	1010 10ff 00ff 1010 1010 1010 f000 0000
	0000 0000 1f10 1010 ffff ffff ffff ffff
	0000 0000 ffff ffff f0f0 f0f0 f0f0 f0f0
	0f0f 0f0f 0f0f 0f0f ffff ffff 0000 0000
	0000 324a 4444 3a00 0038 445c 4262 5c40
	007e 4240 4040 4000 0000 7c28 2828 2400
	007e 2210 1022 7e00 0000 3e44 4444 3800
	0000 4444 4444 7a40 0000 7c10 1010 0800
	0010 3854 5438 1000 003c 4242 7e42 3c00
	003c 4242 4224 6600 7820 1844 4444 3800
	0000 6c92 926c 0000 0000 1854 5438 1000
	003e 407e 4040 3e00 003c 4242 4242 4200
	0000 7e00 7e00 7e00 0008 083e 0800 3e00
	0010 0804 0810 3c00 0008 1020 1008 3c00
	0000 0814 1010 1010 1010 1010 5020 0000
	0000 0800 3e00 0800 0000 324c 0032 4c00
	0018 2424 1800 0000 0000 0018 1800 0000
	0000 0000 1000 0000 000e 0808 4828 1800
	0050 6848 4800 0000 0060 1020 7000 0000
	0000 3c3c 3c3c 0000 0000 3c3c 3c3c 0000

@MEMORY-LEN $2

@MEMORY
\ No newline at end of file