initial commit

This commit is contained in:
Jörg Deckert 2014-06-23 15:12:41 +02:00
commit 34d8b4106b
41 changed files with 12254 additions and 0 deletions

5
.gitattributes vendored Normal file
View File

@ -0,0 +1,5 @@
# Auto detect text files and perform LF normalization
* text=auto
*.bat text eol=crlf

106
GUI-Demo.md Normal file
View File

@ -0,0 +1,106 @@
GUI-DEMO
========
Text based UI Elements for Propeller for use with the VGA_HiRes_Text Driver
Demo / Text program
-------------------
GUIDemo.spin - the demo app
Files that comprise the UI Elements
-----------------------------------
FILE LONGS USED DESCRIPTION
PROG DATA
---------------------- ------ ------ -----------------------------------
GUIBase.spin 2,472 1,643 - UI control and infrastructure
InputField.spin 168 6 - Input Field object
MenuItem.spin 62 13 - Menu Item object
PushButton.spin 124 12 - Push Button object
RadioCheck.spin 78 13 - Radio Button and Check Box object
SimpleBox.spin 62 0 - Basic Box object
SpinBox.spin 191 12 - Spin Button object
TextBox.spin 206 4 - Text Box object
StatusLamp.spin 52 6 - Status Annunciator
Required Drivers
----------------
Vga_HiRes_Text.spin - VGA High Resolution Text Driver
Mouse.spin - PS2 Mouse driver
Keyboard.spin - PS2 Keyboard Driver
Description
-----------
This text based UI for the High Res VGA Driver will work in all resolutions that
the driver supports, the demo itself is setup for 800x600 but will show OK at
1024x768 too. At 640x480 it will not look right (needs to be repositioned and
re-sized), It is very much a fist principles implementation with no bells and
whistles. It supports a static UI and only the basic functionality. To use the
UI Elements the user must decide on a screen layout and then place the elements
there. You only need to include the objects that you plan to use, you do not
have to declare them all. This is done at the top of GUIBase.spin in the
constants where you delcare how mane of each element type you will need.
There are 6 simple steps to using these objects:
1. Configure the numbers and types of GUI elements you need in the GUI Element
Inventory section of the CON section of the GUIBase.spin file. See the top
of that file for simple directions.
2. Declare the GUI object in your application's OBJ section.
OBJ
GUI : "GUIBase"
3. Initialize the GUI object in your application's startup. You will need to
pass in the VGA, Mouse and Keyboard pin assignments you are using for each
of thise devices. This will initialise the GUI data structures and start the
VGA (High Res Text), Mouse, and Keyboard drivers.
GUI.Init( VGABase, MouseDat, MouseCLk, KeyboardDat, KeyboardClk )
4. Create the GUI Elements as required by your application by calling the
specific "Init" fucntion in GUIBase.spin. Note that all GUI interation and
control will be via the functions in GUIBase.spin, you will not need to
access the individual GUI Element files directly. For each element you
create you will need to have a variable in your VAR section to hold its
identifier. For example
PUSH1 := GUI.PUSHInit( ... )
Creates a new pushbutton object identified by the variable PUSH1 which was
declared as a byte in the VAR section. This variable will be used to pass
in to calls to handle the object and will be returned to you for action in
the event that the mouse is clicked on it.
5. Create a main loop for your application that will service both your
application and run the processing for the UI. The UI is processed via the
ProcessUI function in GUIBase.spin.
repeat
ProcessApplication
elem := GUI.ProcessUI
if elem <> -1
case elem
PUSH1: CallYourFunctionForPUSH1()
PUSH2: CallYourFunctionForPUSH1()
etc...
The ProcessUI function will handle the UI for you, highlighting elements as
the mouse passes over them, processing mouse clicks and keyboard entry, etc.
It will return -1 if no action is required (i.e. you did not click on
anything). If the user clicked on something (i.e. Push Button PUSH1 perhaps)
it will return the guid of the element that requires action (i.e. PUSH1).
In this case you will need to perform an action associated with the Push
Button. It is probably best to keep the main loop clean and call a function
to perform tha action rather than do it right in the loop. That makes it
easier to read and maintain.
6. Create your user action functions, one for each GUI Element that will do
something.

46
README.md Normal file
View File

@ -0,0 +1,46 @@
Toolbox 3
=========
Neues Futter für den Hive. Wie bei der ersten Toolbox genügt es den Inhalt des
Ordners "BIN/SDCARD" auf ein passendes Medium zu kopieren.
Inhalt: Ordner tbox-3
=====================
BOING
-----
Eine Icone der Retrokultur auf dem Hive als Musikplayer!
Basis ist der geniale Grafikcode von kuroneko.
- alle Dateien müssen sich in einem Verzeichis befinden
- weitere dmp-Dateien werden wie in einem Player abgespielt
Tastencodes:
[n] - nächster Titel
[p] - Pause
[esc] - Programmende
Graphics-Code: kuroneko
SIDcog: Ahle2
Hive-Code: drohne235
GUI-DEMO
--------
Demo von einem textbasierten GUI-Code
PLEXBUS
-------
Programmierbeispiele für den PlexBus und die Sepia-Karte
TRIBORG
-------
Soundplayer

58
make.bat Normal file
View File

@ -0,0 +1,58 @@
echo on
date /T
time /T
REM # Definitionen
REM set D="-D __DEBUG -D __LANG_EN"
REM set D="-D __LANG_EN"
set D="-D __LANG_DE"
REM # Pfade
set bin="..\Bin"
REM set bin="\home\ftp\hive"
set sdtbox="%bin%\sdcard\tbox-3"
set libpath="..\TriOS\lib"
set BSTC=bstc.exe
REM ----------------------------------------------------------------
REM Alte Versionen löschen
rmdir %sdtbox% /S /Q
mkdir %sdtbox%
mkdir %sdtbox%\boing
mkdir %sdtbox%\gui-demo
mkdir %sdtbox%\plexbus
mkdir %sdtbox%\triborg
REM del %sdsys%\xxxxxx
REM mkdir %sdsys%
REM ----------------------------------------------------------------
REM Bin-Dateien erzeugen, kopieren
%BSTC% -L %libpath% %D% -b -O a .\source\boing\boing-reg.spin
move boing-reg.binary "%sdtbox%\boing\boing.bin"
%BSTC% -L %libpath% %D% -b -O a .\source\boing\boing-bel.spin
move boing-bel.binary "%sdtbox%\boing\boing.bel"
%BSTC% -L %libpath% %D% -D __ADM_FAT -D __ADM_SID -b -O a ..\TriOS\flash\administra\admflash.spin
move admflash.binary "%sdtbox%\boing\boing.adm"
copy .\source\sid\boing.sid "%sdtbox%\boing\"
copy .\source\sid\*.dmp "%sdtbox%\boing\"
%BSTC% -L %libpath% %D% -b -O a .\source\triborg\triborg-reg.spin
move triborg-reg.binary "%sdtbox%\triborg\triborg.bin"
%BSTC% -L %libpath% %D% -b -O a .\source\triborg\triborg-bel.spin
move triborg-bel.binary "%sdtbox%\triborg\triborg.bel"
%BSTC% -L %libpath% %D% -D __ADM_FAT -D __ADM_SID -b -O a ..\TriOS\flash\administra\admflash.spin
move admflash.binary "%sdtbox%\triborg\triborg.adm"
copy .\source\sid\triborg.sid "%sdtbox%\triborg\"
copy .\source\sid\*.dmp "%sdtbox%\triborg\"
for %%x in (.\source\plexbus\*.spin) do %BSTC% -L %libpath% %D% -b -O a %%x
rename *.binary *.bin
move *.bin "%sdtbox%\plexbus\"
%BSTC% -L %libpath% %D% -e -O a .\source\gui-demo\guidemo.spin
move guidemo.eeprom "%sdtbox%\gui-demo\guidemo.bel"
echo off

58
make.sh Executable file
View File

@ -0,0 +1,58 @@
#! /bin/sh
# Definitionen
##D="-D __DEBUG -D __LANG_EN"
##D="-D __LANG_EN"
D="-D __LANG_DE"
# Pfade
bin="../Bin"
##bin="/home/ftp/hive"
sdtbox="${bin}/sdcard/tbox-3"
libpath="../TriOS/lib"
BSTC="bstc"
# ----------------------------------------------------------------
# Alte Versionen löschen
rm -rf ${sdtbox}
mkdir -p ${sdtbox}
mkdir ${sdtbox}/boing
mkdir ${sdtbox}/gui-demo
mkdir ${sdtbox}/plexbus
mkdir ${sdtbox}/triborg
##rm -f ${sdsys}/xxxxxx
##mkdir -p ${sdsys}
# ----------------------------------------------------------------
# Bin-Dateien erzeugen, kopieren
${BSTC} -L ${libpath} ${D} -b -O a source/boing/boing-reg.spin
mv boing-reg.binary "${sdtbox}/boing/boing.bin"
${BSTC} -L ${libpath} ${D} -b -O a source/boing/boing-bel.spin
mv boing-bel.binary "${sdtbox}/boing/boing.bel"
${BSTC} -L ${libpath} ${D} -D __ADM_FAT -D __ADM_SID -b -O a ../TriOS/flash/administra/admflash.spin
mv admflash.binary "${sdtbox}/boing/boing.adm"
cp source/sid/boing.sid "${sdtbox}/boing/"
cp source/sid/*.dmp "${sdtbox}/boing/"
${BSTC} -L ${libpath} ${D} -b -O a source/triborg/triborg-reg.spin
mv triborg-reg.binary "${sdtbox}/triborg/triborg.bin"
${BSTC} -L ${libpath} ${D} -b -O a source/triborg/triborg-bel.spin
mv triborg-bel.binary "${sdtbox}/triborg/triborg.bel"
${BSTC} -L ${libpath} ${D} -D __ADM_FAT -D __ADM_SID -b -O a ../TriOS/flash/administra/admflash.spin
mv admflash.binary "${sdtbox}/triborg/triborg.adm"
cp source/sid/triborg.sid "${sdtbox}/triborg/"
cp source/sid/*.dmp "${sdtbox}/triborg/"
for FILE in source/plexbus/*.spin ; do
${BSTC} -L ${libpath} ${D} -b -O a ${FILE}
BASE="`basename ${FILE} .spin`"
mv "${BASE}.binary" "${sdtbox}/plexbus/${BASE}.bin"
done
${BSTC} -L ${libpath} ${D} -e -O a source/gui-demo/guidemo.spin
mv guidemo.eeprom "${sdtbox}/gui-demo/guidemo.bel"

37
release.sh Executable file
View File

@ -0,0 +1,37 @@
#! /bin/sh
# Definitionen
VERSION="1.1"
# Pfade
ARCHIV="HIVE-Toolbox3-${VERSION}"
MAKE="./make.sh"
BIN="Bin"
# ----------------------------------------------------------------
# Alte Versionen löschen
rm -rf ../${BIN}
rm -f ../${ARCHIV}-bin.zip
rm -f ../${ARCHIV}-src.zip
# ----------------------------------------------------------------
# Binaries erstellen
${MAKE}
# ----------------------------------------------------------------
# Archive erstellen
mkdir .tmp
for file in *.md ; do cp "$file" .tmp/"${file/.md}".txt ; done
cd .tmp
zip -r9 ../../${ARCHIV}-bin.zip *
zip -r9 ../../${ARCHIV}-src.zip *
cd ..
rm -rf .tmp
zip -r9 ../${ARCHIV}-src.zip sounds source make*
cd ..
zip -r9 ${ARCHIV}-bin.zip ${BIN}

View File

@ -0,0 +1,224 @@
''
'' VGA scanline driver 400x300 - background renderer
''
'' Based on "Ball" demo for Gameduino
'' Copyright (c) 2011 by James Bowman <jamesb@excamera.com>
''
'' Author: Marko Lukat
'' Last modified: 2012/12/24
'' Version: 0.9
''
OBJ
system: "boing-bel-corecon"
PUB null
'' This is not a top level object.
PUB init(ID, mailbox)
return system.launch(ID, @entry, mailbox)
DAT org 0 ' background renderer
entry jmpret $, #setup ' once
rdlong indx, blnk ' |
cmpsub indx, scry wz ' |
if_ne jmp #$-2 ' waiting for last line to be fetched
' Skip 26 sync lines and advance by a further 161 hub windows. This pushes the
' first background renderer wrlong beyond the first video renderer line rdlong
' if it were to render scanline -1.
' After the waitcnt we have another 9 insn (36 + 18 + 10 = 64, 4 hub windows).
mov cnt, cnt
add cnt, $+1
long 13{18} + 10 + 132*16*26 + 16*(161 - 4)
loop waitcnt cnt, one ' initial sync point
call #fill ' fill background
add indx, #1 ' line done, advance
cmpsub indx, scry wz ' optionally wrap line index
if_z add cnt, two
one long 132*16*2 ' skip two scan lines
two long 132*16*28 ' skip all sync lines
jmp #loop
' support code
fill
mov addr, indx
shr addr, #1 wc
add read, addr
fill_ret long 0-0 ' pipeline
read mov addr, $+3
if_c shr addr, #16
jmpret read, addr ' render background
word eins[5], zwei[3]
word drei[21], zwei[3], drei[21], zwei[3], drei[21], zwei[3], drei[21], zwei[3]
word drei[21], zwei[3], drei[21], zwei[3], drei[21], zwei[3], drei[21], zwei[3]
word drei[21], zwei[3], drei[21], zwei[3], drei[21], zwei[3], drei[21], zwei[3]
word eins[4]
eins mov addr, base ' 100(A)
mov gindx, gindx0
mov gflag, #0
mov qcnt, #100
:loop wrlong ty_A, addr
add addr, #4
djnz qcnt, #:loop
jmp fill_ret
zwei mov addr, base ' AB(48(CC))DA
cmp gflag, #0 wz
if_z mov gflag, #1
if_z rdword gline0, gindx
if_z add gindx, #4
wrlong ty_A, addr
add addr, #4
wrlong ty_B, addr
add addr, #4
mov qcnt, #96/2
:loop wrlong ty_C, addr
add addr, #4
cmp qcnt, #1 wz ' last run?
wrlong ty_C, addr
add addr, #4
if_ne djnz qcnt, #:loop
wrlong ty_D, addr
add addr, #4
wrlong ty_A, addr
jmp fill_ret
drei mov addr, base ' AB(16(DAAAAB))DA
mov gline, gline0
mov gflag, #0
wrlong ty_A, addr
add addr, #4
wrlong ty_B, addr
add addr, #4
mov qcnt, #16
:loop mov ty_x1, ty_D ' leere punkte
mov ty_X2, ty_A
mov ty_X3, ty_B
shr gline,#1 wc
if_nc jmp #:empty
mov ty_X1, ty_C ' gefüllte punkte
mov ty_X2, ty_C
mov ty_X3, ty_C
:empty
wrlong ty_X1, addr
add addr, #4
cmp qcnt, #1 wz ' last run?
'---------------------
wrlong ty_X2, addr
add addr, #4
wrlong ty_X2, addr
add addr, #4
wrlong ty_X2, addr
add addr, #4
wrlong ty_X2, addr
add addr, #4
'---------------------
:end wrlong ty_X3, addr
add addr, #4
if_ne djnz qcnt, #:loop
wrlong ty_D, addr
add addr, #4
wrlong ty_A, addr
jmp fill_ret
' initialised data and/or presets
blnk long -4
base long NEGX
ty_A {----} long $01010101 * C0
ty_B {---#} long $00010101 * C0 + $01000000 * C1
ty_C {####} long $01010101 * C1
ty_D {##--} long $01010000 * C0 + $00000101 * C1
ty_X1 long 0
ty_X2 long 0
ty_X3 long 0
gindx0 long 400
gindx long 0
gline0 long 0
gline long 0
gflag long 0
' Stuff below is re-purposed for temporary storage.
setup add base, par ' scanline buffer (%%)
add blnk, base wc ' frame indicator
rdword indx, blnk wz ' (%%)
if_nz mov scry, indx wc ' (%%)
if_c_or_nz jmp #$-2 ' auto-detect res_y
' The loop is only left once a non-zero value has been written to scry
' and indx transitions to zero afterwards.
add gindx0, par
jmp %%0 ' return
fit
' uninitialised data and/or temporaries
scry res 1 ' must be 1st/2nd (%%)
indx res 1 ' |
addr res 1
qcnt res 1
tail fit
CON
C0 = %%2220 ' background
C1 = %%1110 ' grid
DAT
{{
TERMS OF USE: MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
}}
DAT

View File

@ -0,0 +1,42 @@
''
'' prerequisites, dependencies & Co
''
'' Author: Marko Lukat
'' Last modified: 2011/10/22
'' Version: 0.9
''
CON
_clkmode = XTAL1|PLL16X
_xinfreq = 5_000_000
CON
ID_0 = $30B3309C
ID_1 = $9ED2732B
ID_2 = $38343032 ' cog binary magic number (2048)
OVERLAY = %00000000_00000001 ' cog binary is an overlay
MAPPING = %00000000_00000010 ' translation table is present
PUB null
'' This is not a top level object.
PUB launch(ID, code, data)
'' PASM quick launch using a specific or the next available ID.
''
'' parameters
'' ID: cog ID
'' 0..7: coginit, otherwise cognew (may fail)
'' code: address of code fragment (4n)
'' data: cognew/coginit parameter (4n)
''
'' result
'' == 0: [ABORT] thread creation failed (cognew only)
'' <> 0: thread/cog ID + 1
ifnot (ID >> 3)
coginit(ID++, code, data)
elseifnot ID := cognew(code, data) + 1
abort
return ID
DAT

View File

@ -0,0 +1,553 @@
''
'' VGA scanline driver 400x300 (single cog) - video driver and pixel generator
''
'' Author: Marko Lukat
'' Last modified: 2013/01/11
'' Version: 0.10
''
'' - timing signalled as SVGA 800x600
'' - vertical blank start sets frame indicator (FI) to 0
'' - once the Nth scanline has been fetched the FI is set to N+1
''
'' 20121007: added minimal translation table
'' 20121229: now capable of using 64/256 colours (RRGGBBHV / RRGGBBgr + xxxxxxHV)
'' - 64c: $FC/2/2 (vpin/vgrp/sgrp)
'' - 256c: $FF/2/3
'' 20121230: simplified vertical blanking code
''
'' Note: With idle state being %00 {%hv} the switch code can be further simplified.
'' As this was the first converted driver I left the generic solution intact
'' so it can easily be adapted for other drivers (with non-zero idle state).
''
OBJ
system: "boing-bel-corecon"
PUB null
'' This is not a top level object.
PUB init(ID, mailbox)
return system.launch(ID, @driver, mailbox)
DAT org 0 ' cog binary header
header_2048 long system#ID_2 ' magic number for a cog binary
word header_size ' header size
word system#MAPPING ' flags
word 0, 0 ' start register, register count
word @__table - @header_2048 ' translation table byte offset
header_size fit 16
DAT org 0 ' video driver
driver jmpret $, #setup ' -4 once
mov dira, mask ' drive outputs
' horizontal timing 400(800) 20(40) 64(128) 44(88)
' vertical timing 300(600) 1(1) 4(4) 23(23)
vsync mov lcnt, #0 ' |
wrlong lcnt, blnk ' reset line counter (once)
mov vscl, full ' 32/528
' mov ecnt, #1
waitvid sync, #%%0011 ' front porch
' djnz ecnt, #$-1
xor sync, #$0101 ' active
mov ecnt, #4
waitvid sync, #%%0011 ' vertical sync
djnz ecnt, #$-1
xor sync, #$0101 ' inactive
mov ecnt, #23
waitvid sync, #%%0011 ' back porch
djnz ecnt, #$-1
' Vertical sync chain done, do visible area.
mov scnt, #res_y
:loop call #prefix ' sync and back porch
jmpret suffix_ret, #emit_0 ' visible line and front porch
call #prefix ' sync and back porch
jmpret suffix_ret, #emit_1 ' visible line and front porch
djnz scnt, #:loop ' repeat for all lines
jmp #vsync ' next frame
prefix mov vscl, slow ' 32/108
waitvid sync, #%%2011 ' latch sync and back porch
mov cnt, cnt ' cover sync pulse period (%%)
add cnt, #9{14}+(64 * 4) ' because we drive sync lines
waitcnt cnt, #135 ' manually next (%%)
mov outa, idle ' take over sync lines (##)
prefix_ret ret
suffix mov vscl, hs_f ' 1/20
waitvid sync, #%%02 ' latch front porch
' waitvid
' | S D e . . . R | mov vcfg | mov outa |
' clock 
' │ │ │ │
' PLL 
' pixel 1:4 │+4
' │ │ pixel %%2 │ pixel %%0 |
' outa 
mov vcfg, vcfg_sync ' drive/change sync lines (##)
mov outa, #0 ' stop interfering
if_nc wrlong lcnt, blnk ' report current line
suffix_ret ret
' Even line emitter (fetch & emit).
emit_0 waitcnt cnt, #0 ' re-sync after back porch (%%)
' At this point the video h/w is driving the sync lines low (colour %%2).
' outa has taken over long ago so we can switch configuration here.
mov vcfg, vcfg_norm ' -12 disconnect sync from video h/w (##)
mov addr, base ' -8 working copy
mov vscl, hvis ' -4 1/4
rdlong pal+$00, addr ' +0 =
cmp pal+$00, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$01, addr ' +0 =
cmp pal+$01, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$02, addr ' +0 =
cmp pal+$02, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$03, addr ' +0 =
cmp pal+$03, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$04, addr ' +0 =
cmp pal+$04, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$05, addr ' +0 =
cmp pal+$05, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$06, addr ' +0 =
cmp pal+$06, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$07, addr ' +0 =
cmp pal+$07, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$08, addr ' +0 =
cmp pal+$08, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$09, addr ' +0 =
cmp pal+$09, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$0A, addr ' +0 =
cmp pal+$0A, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$0B, addr ' +0 =
cmp pal+$0B, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$0C, addr ' +0 =
cmp pal+$0C, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$0D, addr ' +0 =
cmp pal+$0D, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$0E, addr ' +0 =
cmp pal+$0E, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$0F, addr ' +0 =
cmp pal+$0F, #%%3210 ' +8 WHOP
add addr, #4 ' -4 0..63
rdlong pal+$10, addr ' +0 =
cmp pal+$10, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$11, addr ' +0 =
cmp pal+$11, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$12, addr ' +0 =
cmp pal+$12, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$13, addr ' +0 =
cmp pal+$13, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$14, addr ' +0 =
cmp pal+$14, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$15, addr ' +0 =
cmp pal+$15, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$16, addr ' +0 =
cmp pal+$16, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$17, addr ' +0 =
cmp pal+$17, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$18, addr ' +0 =
cmp pal+$18, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$19, addr ' +0 =
cmp pal+$19, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$1A, addr ' +0 =
cmp pal+$1A, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$1B, addr ' +0 =
cmp pal+$1B, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$1C, addr ' +0 =
cmp pal+$1C, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$1D, addr ' +0 =
cmp pal+$1D, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$1E, addr ' +0 =
cmp pal+$1E, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$1F, addr ' +0 =
cmp pal+$1F, #%%3210 ' +8 WHOP
add addr, #4 ' -4 64..127
rdlong pal+$20, addr ' +0 =
cmp pal+$20, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$21, addr ' +0 =
cmp pal+$21, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$22, addr ' +0 =
cmp pal+$22, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$23, addr ' +0 =
cmp pal+$23, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$24, addr ' +0 =
cmp pal+$24, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$25, addr ' +0 =
cmp pal+$25, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$26, addr ' +0 =
cmp pal+$26, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$27, addr ' +0 =
cmp pal+$27, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$28, addr ' +0 =
cmp pal+$28, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$29, addr ' +0 =
cmp pal+$29, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$2A, addr ' +0 =
cmp pal+$2A, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$2B, addr ' +0 =
cmp pal+$2B, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$2C, addr ' +0 =
cmp pal+$2C, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$2D, addr ' +0 =
cmp pal+$2D, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$2E, addr ' +0 =
cmp pal+$2E, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$2F, addr ' +0 =
cmp pal+$2F, #%%3210 ' +8 WHOP
add addr, #4 ' -4 128..191
rdlong pal+$30, addr ' +0 =
cmp pal+$30, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$31, addr ' +0 =
cmp pal+$31, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$32, addr ' +0 =
cmp pal+$32, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$33, addr ' +0 =
cmp pal+$33, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$34, addr ' +0 =
cmp pal+$34, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$35, addr ' +0 =
cmp pal+$35, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$36, addr ' +0 =
cmp pal+$36, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$37, addr ' +0 =
cmp pal+$37, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$38, addr ' +0 =
cmp pal+$38, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$39, addr ' +0 =
cmp pal+$39, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$3A, addr ' +0 =
cmp pal+$3A, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$3B, addr ' +0 =
cmp pal+$3B, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$3C, addr ' +0 =
cmp pal+$3C, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$3D, addr ' +0 =
cmp pal+$3D, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$3E, addr ' +0 =
cmp pal+$3E, #%%3210 ' +8 WHOP
add addr,#4 ' -4
rdlong pal+$3F, addr ' +0 =
cmp pal+$3F, #%%3210 ' +8 WHOP
add addr, #4 ' -4 192..255
rdlong pal+$40, addr ' +0 =
cmp pal+$40, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$41, addr ' +0 =
cmp pal+$41, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$42, addr ' +0 =
cmp pal+$42, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$43, addr ' +0 =
cmp pal+$43, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$44, addr ' +0 =
cmp pal+$44, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$45, addr ' +0 =
cmp pal+$45, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$46, addr ' +0 =
cmp pal+$46, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$47, addr ' +0 =
cmp pal+$47, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$48, addr ' +0 =
cmp pal+$48, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$49, addr ' +0 =
cmp pal+$49, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$4A, addr ' +0 =
cmp pal+$4A, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$4B, addr ' +0 =
cmp pal+$4B, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$4C, addr ' +0 =
cmp pal+$4C, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$4D, addr ' +0 =
cmp pal+$4D, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$4E, addr ' +0 =
cmp pal+$4E, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$4F, addr ' +0 =
cmp pal+$4F, #%%3210 ' +8 WHOP
add addr, #4 ' -4 256..319
rdlong pal+$50, addr ' +0 =
cmp pal+$50, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$51, addr ' +0 =
cmp pal+$51, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$52, addr ' +0 =
cmp pal+$52, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$53, addr ' +0 =
cmp pal+$53, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$54, addr ' +0 =
cmp pal+$54, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$55, addr ' +0 =
cmp pal+$55, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$56, addr ' +0 =
cmp pal+$56, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$57, addr ' +0 =
cmp pal+$57, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$58, addr ' +0 =
cmp pal+$58, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$59, addr ' +0 =
cmp pal+$59, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$5A, addr ' +0 =
cmp pal+$5A, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$5B, addr ' +0 =
cmp pal+$5B, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$5C, addr ' +0 =
cmp pal+$5C, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$5D, addr ' +0 =
cmp pal+$5D, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$5E, addr ' +0 =
cmp pal+$5E, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$5F, addr ' +0 =
cmp pal+$5F, #%%3210 ' +8 WHOP
add addr, #4 ' -4 320..383
rdlong pal+$60, addr ' +0 =
cmp pal+$60, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$61, addr ' +0 =
cmp pal+$61, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$62, addr ' +0 =
cmp pal+$62, #%%3210 ' +8 WHOP
add addr, #4 ' -4
rdlong pal+$63, addr ' +0 =
cmp pal+$63, #%%3210 ' +8 WHOP
add lcnt, #1 ' -4 384..399, line has been fetched
jmpret $, #suffix wc,nr ' +0 = chain call (carry clear)
' Odd line emitter (emit only).
emit_1 waitcnt cnt, #0 ' re-sync after back porch (%%)
' At this point the video h/w is driving the sync lines low (colour %%2).
' outa has taken over long ago so we can switch configuration here.
mov vcfg, vcfg_norm ' -12 disconnect sync from video h/w (##)
movd :vid, #pal+$00 ' -8 colour buffer
mov vscl, hvis ' -4 1/4
mov ecnt, #100 -1 ' +0 = quad pixel count (last one separate)
test $, #1 wc ' +4 set carry
:vid cmp 0-0, #%%3210 ' +8 WHOP
addx $-1, #511{+C} ' -4
djnz ecnt, #:vid -1 ' +0 = maintain 16 cycle loop
cmp pal+$63, #%%3210 ' +8 WHOP
jmpret zero, #suffix wc,nr ' -4 chain call (carry set)
' initialised data and/or presets
idle long (hv_idle & $00FF) << (sgrp * 8)
sync long (hv_idle ^ $0200) & $FFFF
hvis long 1 << 12 | 4 ' 1/4
hs_f long 1 << 12 | 20 ' 1/20
slow long 32 << 12 | 108 ' 32/108
full long 32 << 12 | 528 ' 32/528
vcfg_norm long %0_01_1_00_000 << 23 | vgrp << 9 | vpin
vcfg_sync long %0_01_1_00_000 << 23 | sgrp << 9 | %11
mask long vpin << (vgrp * 8) | %11 << (sgrp * 8)
blnk long -4
base long +0
' Stuff below is re-purposed for temporary storage.
setup rdlong cnt, #0 ' +0 = clkfreq
add blnk, par ' +8 frame indicator
neg href, cnt ' -4 hub window reference
add base, par ' +0 = scanline buffer
' Upset video h/w and relatives.
movi ctra, #%0_00001_101 ' PLL, VCO/4
movi frqa, #%0001_00000 ' 5MHz * 16 / 4 = 20MHz
mov vscl, hvis ' 1/4
mov vcfg, vcfg_sync ' VGA, 4 colour mode
shr cnt, #10 ' ~1ms
add cnt, cnt
waitcnt cnt, #0 ' PLL needs to settle
' The first issued waitvid is a bit of a gamble if we don't know where the WHOP
' is located. We could do some fancy math or simply issue a dummy waitvid.
waitvid zero, #0 ' dummy (first one is unpredictable)
waitvid zero, #0 ' point of reference
add href, cnt ' get current sync slot
shr href, #2 ' 4 system clocks per pixel
neg href, href ' |
and href, #%11 ' calculate adjustment
' WHOP is reasonably far away so we can update vscl without re-sync.
add vscl, href ' |
waitvid zero, #0 ' stretch frame
sub vscl, href ' |
waitvid zero, #0 ' restore frame
' Setup complete, do the heavy lifting upstairs ...
jmp %%0 ' return
' uninitialised data and/or temporaries
org setup
href res 1 ' hub window reference
ecnt res 1 ' element count
lcnt res 1 ' line counter
scnt res 1 ' scanlines
addr res 1 ' colour buffer reference
pal res 100 ' colour buffer
tail fit
DAT ' translation table
__table word (@__names - @__table)/2
word res_x
word res_y
__names byte "res_x", 0
byte "res_y", 0
CON
zero = $1F0 ' par (dst only)
vpin = $0FC ' pin group mask
vgrp = 1 ' pin group
sgrp = 1 ' pin group sync
hv_idle = $01010101 * %00 {%hv} ' h/v sync inactive
res_x = 400 ' |
res_y = 300 ' UI support
DAT

View File

@ -0,0 +1,762 @@
''
'' VGA scanline driver 400x300 - image feeder
''
'' Based on "Ball" demo for Gameduino
'' Copyright (c) 2011 by James Bowman <jamesb@excamera.com>
''
'' Author: Marko Lukat
'' Last modified: 2013/01/03
'' Version: 0.6
''
'' 20121225: adjusted palette (brighter)
'' 20121226: 256 colour setup (RRGGBBgr)
'' 20130103: minor tweak to palette table
''
OBJ
system: "boing-bel-corecon"
VAR
long guard_before, buffer[BSIZE/4], guard_after
byte image[BSIZE*BSIZE]
long GD_srcp, GD_mask, GD_stack[32]
PUB null
'' This is not a top level object.
PUB init(ID, mailbox)
long[mailbox][-3] := @image{0} >< 32 | @buffer{0}
return system.launch(ID, @entry, mailbox)
PUB uncompress(wait{boolean})
ifnot wait
if cognew(GD_uncompress(256, @ball), @GD_stack{0}) +1
return
GD_uncompress(256, @ball)
PRI GD_uncompress(offs, srcp) | b_off, b_len, minlen, offset
GD_srcp := srcp
GD_mask := $01010101
b_off := GD_getn(4)
b_len := GD_getn(4)
minlen := GD_getn(2)
repeat GD_getn(16)
ifnot GD_get1
image[GD_translate(offs++)] := !GD_getn(8)
next
offset := offs - GD_getn(b_off) - 1
repeat GD_getn(b_len) + minlen
image[GD_translate(offs++)] := image[GD_translate(offset++)]
PRI GD_getn(n) : r
repeat n
r := r << 1 | GD_get1
PRI GD_get1 : r
if byte[GD_srcp] & GD_mask
r := 1
if (GD_mask <-= 1) == $01010101
GD_srcp++
PRI GD_translate(offs) : r
if offs => constant(256*(5+1))
offs += 256
if offs => constant(256*(40+2))
offs += 256
r := offs.byte[1]
return (r / 7)*constant(16*112) + (r // 7) << 4 + offs & 15 + (offs & $F0)*7
DAT org 0 ' image feeder
entry jmpret $, #setup ' once
rdlong indx, blnk ' |
cmpsub indx, scry wz ' |
if_ne jmp #$-2 ' waiting for last line to be fetched
' The foreground renderer starts reading the colour buffer after 26 sync lines
' and 161+5 hub windows. We have to be done before that happens. Using the assumed
' hubop (161 hub windows) as reference we simply go back by 112*2+4 hub windows.
mov cnt, cnt
add cnt, $+1
long 13{18} + 14 + 132*16*26 + 16*(161 - 2) - 228*16
loop waitcnt cnt, one ' initial sync point
' cogid $ nr ' assumed hubop
call #transfer ' palette translation
add indx, #1 ' line done, advance
cmpsub indx, scry wz ' optionally wrap line index
if_nz jmp #loop
' per frame updates (during the first frame mask is off-screen)
rdlong temp, blnk ' |
cmp temp, scry wz ' |
if_ne jmp #$-2 ' wait for ?/scry transition
rdword msky, crdy ' |
shl msky, #16 ' |
sar msky, #16 ' update and sign-extend mask coordinate
maxs msky, scry ' reasonable limit (off-screen)
mov mskc, msky ' |
add mskc, #BSIZE -1 ' bounding box setup
one long 132*16*2 ' skip two scan lines
two long 132*16*28 ' skip all sync lines
call #update ' update palette
add cnt, two
jmp #loop
' support code
transfer cmps indx, msky wc ' |
if_nc cmps mskc, indx wc ' |
if_c jmp transfer_ret ' vertical bounds check
rdlong addr, feed ' crs/dst
mov arg0, addr
rev arg0, #{32-}0 ' tsd/src
mov temp, indx '
sub temp, msky ' active row
mov arg1, temp
shl arg1, #3 ' *8
sub arg1, temp ' *7
shl arg1, #4 ' *112
add arg0, arg1 ' apply offset
mov ecnt, #BSIZE
rdbyte phsb, arg0
movd $+2, phsb
add arg0, #1
wrbyte phsb, addr
add addr, #1
djnz ecnt, #$-5 ' translate index to colour
transfer_ret ret
update mov arg0, #32*7 ' slot 7
call #cycle ' |
cmpsub arg0, #32*1 wz ' |
if_nz jmp #$-2 ' for all slots except 0
update_ret ret
cycle mov arg1, arg0 ' |
add arg1, #palette ' apply base
movd :cy2, arg1 ' head
add arg1, #30 ' |
movs :cy1, arg1 ' |
add arg1, #1 ' |
movd :cy1, arg1 ' body
movs :cy0, arg1 ' tail
mov ecnt, #32-1
:cy0 mov temp, 1-1 ' preserve last entry
:cy1 mov 1-1, 0-0 ' long rotate
sub $-1, d1s1
djnz ecnt, #:cy1
:cy2 mov 0-0, temp ' close rotate
cycle_ret ret
' initialised data and/or presets
feed long -12 ' |
crdy long -6 ' |
' quick access relative to par
blnk long -4 ' |
base long NEGX ' |
d1s1 long |< 9 | 1 ' dst/src +/- 1
long 0[$ & 1]
palette long $00[32] ' unused/transparent
long $FF[16], $C1[16] ' 1: $F0 - %111_1
long $FF[16], $C1[16] ' 2: $E0 %111_0
long $FC[16], $C0[16] ' 3: $D0 %110_1
long $FC[16], $C0[16] ' 4: $C0 %110_0
long $AB[16], $81[16] ' 5: $B0 %101_1
long $AB[16], $81[16] ' 6: $A0 %101_0
long $A8[16], $80[16] ' 7: $90 - %100_1
' Stuff below is re-purposed for temporary storage.
setup add crdy, par ' mask coordinate (%%)
add feed, par ' mask buffer location
add base, par ' scanline buffer
add blnk, base wc ' frame indicator
rdword indx, blnk wz ' (%%)
if_nz mov scry, indx wc ' (%%)
if_c_or_nz jmp #$-2 ' auto-detect res_y
' The loop is only left once a non-zero value has been written to scry
' and indx transitions to zero afterwards.
mov msky, scry ' move off-screen
movi ctrb, #%0_11111_000 ' LOGIC always (relocation support)
mov frqb, #palette >> 1 ' |
jmp %%0 ' return
fit
' uninitialised data and/or temporaries
org setup
scry res 1 ' must be 1st..4th (%%)
indx res 1 ' |
addr res 1 ' scanline reference
ecnt res 1 ' element count
mskc res 1 ' upper limit (inclusive)
mskx res 1 ' mask coordinates
msky res 1 ' signed 16bit
arg0 res 1
arg1 res 1
temp res 1
tail fit
CON
zero = $1F0 ' par (dst only)
BSIZE = 112 ' mask width/height (4n)
DAT
ball byte $c9, $a1, $dc, $f9, $0f, $e0, $41, $3c, $88, $07, $f1, $20, $1e, $c4, $83, $78
byte $10, $0f, $e2, $41, $3c, $88, $07, $71, $ff, $06, $ed, $85, $f2, $20, $68, $d8
byte $be, $5d, $5b, $c1, $df, $bf, $d1, $70, $60, $c7, $94, $8d, $e0, $6f, $d9, $bc
byte $59, $d3, $26, $4d, $18, $0b, $be, $d6, $2c, $99, $37, $63, $ca, $a4, $71, $63
byte $46, $82, $8f, $15, $8b, $e6, $82, $83, $89, $e0, $68, $38, $78, $5b, $b1, $10
byte $9c, $8d, $1a, $31, $6c, $28, $78, $da, $b4, $1c, $dc, $0d, $19, $0c, $1e, $36
byte $82, $7b, $b8, $30, $68, $c0, $bf, $f5, $e0, $9a, $14, $82, $93, $fd, $6a, $1f
byte $c4, $83, $b8, $1d, $9b, $d6, $ad, $5a, $0e, $b6, $06, $82, $a1, $35, $2b, $96
byte $2c, $5a, $08, $5e, $86, $ec, $d9, $0e, $8b, $c1, $ca, $9c, $d9, $e0, $61, $d0
byte $6e, $b0, $ab, $11, $66, $4c, $07, $eb, $28, $61, $39, $4a, $98, $0f, $07, $c1
byte $c1, $94, $1d, $5b, $36, $ac, $25, $8a, $38, $18, $ac, $5b, $40, $1c, $b2, $6c
byte $c9, $42, $38, $09, $0e, $c6, $c3, $41, $e2, $0a, $ee, $c6, $8c, $96, $6a, $7b
byte $76, $e3, $62, $b8, $0c, $ee, $76, $6c, $db, $b2, $69, $c3, $7a, $70, $30, $d2
byte $22, $0c, $84, $03, $3b, $c1, $25, $6e, $5a, $69, $11, $c1, $3d, $38, $58, $b5
byte $62, $d9, $80, $fd, $e0, $19, $8d, $83, $b3, $a5, $e0, $6e, $2d, $5a, $5a, $d6
byte $a4, $29, $dc, $59, $0f, $4e, $9a, $4b, $87, $ad, $8e, $59, $1c, $22, $45, $8a
byte $ca, $90, $d6, $cb, $b2, $e9, $ad, $b0, $0e, $97, $43, $15, $d8, $1c, $66, $8b
byte $dc, $3a, $cc, $06, $f6, $83, $7d, $e5, $8d, $b2, $c1, $32, $1c, $a6, $c3, $5a
byte $1c, $55, $ec, $05, $47, $dd, $17, $a3, $16, $46, $9d, $e0, $a0, $a7, $0c, $04
byte $cb, $70, $a7, $37, $67, $ea, $cc, $04, $d1, $3c, $5c, $e8, $b2, $a9, $d3, $48
byte $70, $29, $01, $7a, $83, $a3, $2d, $9d, $36, $82, $b3, $7e, $fb, $fa, $ec, $da
byte $d1, $6d, $3b, $3c, $e8, $b8, $17, $03, $50, $41, $70, $d4, $13, $ad, $74, $e8
byte $d0, $de, $20, $34, $5a, $50, $6f, $4f, $6f, $78, $d4, $15, $9e, $b4, $59, $0c
byte $8e, $e6, $d4, $99, $55, $a3, $3a, $5a, $85, $87, $e0, $a1, $c1, $bc, $7a, $75
byte $6a, $cd, $04, $0f, $53, $2a, $55, $da, $d0, $6e, $4d, $9b, $86, $68, $61, $4e
byte $6d, $78, $30, $ad, $4a, $95, $4a, $15, $ca, $95, $2b, $d3, $fa, $db, $83, $e8
byte $99, $7c, $45, $a1, $dd, $5e, $ff, $6e, $14, $46, $43, $ec, $9e, $56, $6e, $4c
byte $a9, $62, $43, $0a, $ed, $87, $a4, $52, $bc, $34, $15, $19, $54, $50, $28, $74
byte $87, $88, $cb, $50, $31, $ac, $69, $d5, $b2, $26, $34, $9a, $af, $19, $b6, $75
byte $6a, $6f, $10, $b9, $e0, $34, $6a, $b2, $a8, $a1, $30, $a8, $09, $1e, $3a, $0a
byte $86, $75, $6d, $e1, $b9, $74, $54, $42, $93, $2a, $4a, $a6, $55, $2d, $a7, $23
byte $3c, $55, $0a, $d5, $25, $43, $7b, $b8, $d0, $6a, $45, $b3, $26, $8d, $e1, $a1
byte $56, $d4, $82, $e0, $11, $2d, $c2, $4b, $7c, $a8, $0d, $6a, $6a, $a6, $b6, $e0
byte $90, $0e, $c2, $63, $2b, $0c, $0f, $c1, $2b, $19, $bc, $ca, $e8, $10, $fc, $c2
byte $73, $b2, $0c, $3e, $22, $55, $64, $cd, $5f, $10, $9e, $d5, $aa, $11, $1d, $3d
byte $44, $68, $89, $57, $c1, $5b, $8c, $6a, $d5, $f1, $b3, $ff, $07, $f1, $20, $1e
byte $c4, $83, $78, $10, $0f, $e2, $41, $3c, $88, $07, $f1, $20, $a2, $4d, $73, $08
byte $0f, $c2, $d6, $b4, $68, $52, $1f, $e2, $83, $a0, $72, $a5, $9a, $35, $aa, $53
byte $15, $e2, $fd, $07, $0f, $25, $8a, $34, $88, $0d, $e1, $c1, $43, $99, $12, $c5
byte $0a, $f5, $ab, $51, $a9, $24, $a2, $de, $04, $25, $82, $15, $2a, $90, $27, $5b
byte $44, $08, $15, $1e, $3e, $05, $29, $d0, $a7, $57, $96, $0e, $21, $11, $3a, $7c
byte $08, $55, $ac, $48, $a0, $7e, $b9, $ba, $65, $6a, $13, $2c, $27, $7d, $29, $0b
byte $de, $f2, $f4, $c8, $92, $a1, $55, $52, $08, $54, $2e, $4c, $a9, $60, $41, $0a
byte $05, $c8, $8b, $80, $d2, $a5, $48, $94, $5d, $ff, $83, $78, $10, $0f, $c2, $36
byte $82, $7b, $10, $b6, $69, $25, $f8, $07, $21, $5b, $56, $2c, $06, $ff, $20, $64
byte $d5, $92, $f9, $e0, $1f, $04, $ad, $59, $b2, $60, $36, $f8, $07, $01, $e3, $8a
byte $0d, $d8, $b3, $13, $fc, $fd, $9b, $54, $62, $d0, $be, $5d, $dd, $c1, $df, $bf
byte $51, $43, $fa, $f5, $da, $d6, $15, $fc, $a3, $85, $82, $68, $a1, $cb, $66, $f0
byte $53, $65, $c4, $60, $78, $d0, $ad, $b3, $f8, $1b, $53, $d4, $0b, $ec, $84, $07
byte $ed, $e1, $57, $85, $11, $85, $f6, $e3, $85, $4e, $1d, $da, $82, $6f, $78, $d4
byte $ab, $47, $97, $0d, $ed, $c1, $57, $45, $d6, $d0, $67, $27, $5e, $e8, $b0, $a6
byte $35, $fc, $18, $55, $94, $0c, $c2, $83, $8e, $f0, $a0, $c5, $86, $65, $0b, $e6
byte $cc, $98, $32, $61, $dc, $98, $11, $c3, $86, $0c, $1a, $b0, $6f, $2f, $38, $9b
byte $0c, $0e, $46, $83, $8b, $5d, $8b, $e1, $32, $38, $19, $09, $d7, $76, $ed, $98
byte $37, $6b, $da, $a4, $09, $63, $46, $a3, $65, $34, $b4, $17, $3c, $82, $43, $3c
byte $0c, $4e, $f1, $28, $38, $d8, $4e, $fa, $e1, $d1, $ae, $9e, $e6, $61, $cb, $a6
byte $75, $6b, $e1, $21, $1e, $5d, $0c, $3b, $7a, $74, $d7, $88, $82, $61, $55, $8b
byte $65, $4d, $1a, $15, $e8, $d7, $17, $1e, $6d, $b5, $80, $82, $61, $45, $b3, $25
byte $8b, $1a, $cc, $9b, $53, $ab, $26, $5c, $b4, $40, $6d, $e1, $41, $b3, $46, $0d
byte $ea, $d5, $a9, $55, $6b, $46, $b5, $2a, $95, $2a, $b4, $6b, $0d, $8f, $1a, $2d
byte $a8, $0f, $8f, $aa, $4d, $a9, $0c, $1e, $0d, $22, $5a, $84, $67, $35, $aa, $c3
byte $93, $f2, $68, $99, $0c, $a2, $53, $f0, $88, $16, $e1, $41, $b9, $16, $cd, $c1
byte $d1, $7c, $bc, $08, $af, $c1, $23, $6b, $86, $37, $15, $2a, $84, $2b, $0b, $4f
byte $e9, $30, $5a, $46, $07, $11, $ca, $95, $29, $ab, $89, $15, $c1, $86, $8d, $4a
byte $a0, $55, $4b, $69, $d2, $68, $c7, $76, $70, $b0, $19, $1c, $0a, $85, $55, $2b
byte $71, $42, $53, $e9, $b0, $1d, $3c, $c3, $a5, $b6, $f0, $90, $3b, $d2, $84, $05
byte $0d, $c1, $49, $7b, $cd, $68, $98, $49, $c2, $62, $11, $d4, $b5, $33, $36, $45
byte $29, $28, $4c, $85, $4b, $7d, $8b, $b2, $16, $ad, $72, $67, $b4, $c8, $12, $36
byte $37, $41, $b4, $48, $9b, $b9, $b3, $36, $a9, $d3, $b1, $0b, $ad, $b6, $4c, $4d
byte $d1, $ba, $72, $e8, $b0, $ae, $2d, $5a, $95, $a6, $ca, $18, $3c, $d2, $66, $b4
byte $0e, $af, $6a, $2b, $82, $52, $a5, $2d, $23, $3c, $8b, $57, $27, $6e, $62, $04
byte $4f, $25, $4a, $14, $2b, $d2, $a8, $51, $82, $fa, $89, $25, $46, $59, $78, $08
byte $8e, $82, $14, $2a, $50, $a0, $5e, $9c, $3a, $b1, $6a, $82, $a7, $10, $25, $82
byte $15, $29, $54, $28, $40, $bf, $7c, $7d, $72, $d5, $8a, $51, $1d, $de, $82, $87
byte $be, $03, $a0, $e7, $00, $08, $0d, $17, $8a, $a3, $45, $78, $d4, $2f, $4f, $ae
byte $5c, $39, $b2, $65, $ef, $01, $75, $6b, $69, $6d, $8e, $8b, $e1, $a8, $d4, $fc
byte $38, $5a, $5a, $26, $55, $28, $cf, $5a, $c1, $c1, $6c, $2e, $30, $bd, $95, $82
byte $c7, $b4, $50, $aa, $c4, $dc, $5a, $dc, $aa, $45, $f9, $72, $2e, $ed, $78, $25
byte $4c, $a9, $10, $c5, $6a, $a2, $c5, $19, $12, $19, $af, $a3, $83, $e0, $e0, $10
byte $5e, $b6, $86, $30, $65, $79, $23, $1f, $84, $27, $51, $8f, $33, $1d, $85, $c7
byte $e8, $a1, $46, $b4, $2a, $55, $d1, $22, $3c, $0a, $0b, $0f, $f1, $41, $50, $8d
byte $c8, $9a, $2a, $83, $c3, $95, $a8, $13, $c1, $a1, $49, $c4, $0b, $51, $57, $20
byte $1d, $c6, $ab, $f0, $a8, $48, $75, $74, $10, $29, $32, $3c, $09, $cd, $86, $e1
byte $41, $a0, $ea, $f0, $94, $8e, $85, $08, $11, $2c, $48, $91, $c0, $f0, $a0, $32
byte $bc, $8d, $0e, $41, $5d, $42, $54, $36, $50, $21, $42, $78, $bc, $14, $1a, $1e
byte $c2, $87, $40, $81, $ba, $64, $ca, $0c, $0e, $ca, $85, $55, $c5, $64, $19, $1e
byte $04, $44, $82, $b5, $a5, $7e, $6d, $94, $c1, $a8, $10, $17, $96, $e1, $3c, $58
byte $1b, $ea, $96, $66, $96, $6c, $14, $8a, $33, $e6, $da, $98, $06, $4b, $a1, $0a
byte $b6, $ca, $bd, $b0, $0e, $14, $ac, $4d, $bd, $7a, $3a, $53, $52, $58, $86, $02
byte $83, $87, $bc, $65, $b0, $34, $64, $c9, $52, $19, $3d, $14, $15, $04, $05, $02
byte $f6, $82, $de, $f0, $a1, $3b, $2b, $ca, $10, $1e, $2d, $c2, $e3, $51, $94, $13
byte $3e, $75, $ca, $d0, $21, $3d, $3c, $2a, $08, $0e, $f2, $f4, $ca, $d1, $2d, $3b
byte $7c, $c8, $90, $ae, $3d, $78, $5c, $e9, $e0, $21, $3b, $3e, $84, $0f, $e9, $d2
byte $2a, $44, $78, $90, $9f, $2c, $c3, $87, $ac, $2a, $11, $3e, $82, $87, $80, $e8
byte $72, $25, $82, $87, $8c, $e0, $15, $9e, $e5, $ea, $09, $1e, $f1, $31, $7c, $97
byte $8d, $e8, $14, $1f, $65, $06, $87, $f8, $21, $20, $1f, $06, $9f, $f8, $2c, $2d
byte $38, $24, $cb, $2f, $14, $5f, $b8, $05, $8f, $aa, $55, $8d, $a2, $83, $0c, $ee
byte $d2, $a4, $0e, $05, $a5, $0d, $51, $41, $4c, $d0, $2d, $4b, $86, $36, $c9, $12
byte $44, $4d, $89, $c9, $51, $b2, $62, $42, $0c, $90, $2e, $45, $92, $b8, $29, $70
byte $33, $26, $63, $22, $c8, $11, $32, $a5, $4b, $8d, $00, $97, $62, $76, $b6, $84
byte $e0, $91, $10, $65, $48, $8b, $00, $4b, $70, $35, $a6, $4a, $b9, $05, $22, $7f
byte $48, $e5, $fc, $28, $83, $87, $c2, $e0, $25, $27, $01, $a4, $0f, $29, $19, $e2
byte $34, $0a, $0c, $be, $32, $b8, $05, $4f, $29, $92, $05, $05, $1f, $d9, $3c, $13
byte $00, $d7, $f0, $11, $3c, $24, $49, $0c, $5f, $7c, $64, $cb, $e4, $91, $21, $a4
byte $4a, $0d, $5e, $12, $c4, $f3, $ab, $99, $bc, $2a, $00, $b7, $e0, $27, $8e, $6d
byte $f8, $08, $de, $52, $c2, $27, $47, $0e, $e2, $d9, $89, $15, $c3, $5a, $16, $4f
byte $e9, $e1, $23, $38, $70, $8e, $1f, $d1, $83, $1d, $db, $e0, $21, $8a, $25, $f7
byte $e0, $c1, $45, $b2, $24, $4e, $12, $39, $b0, $17, $27, $96, $0d, $6b, $56, $2c
byte $45, $30, $4b, $0e, $e1, $21, $78, $48, $60, $1f, $3d, $d8, $88, $0e, $1e, $2c
byte $98, $71, $8d, $1e, $c1, $21, $7e, $b1, $0d, $5f, $2c, $98, $fb, $0f, $e0, $41
byte $44, $44, $f0, $0f, $22, $62, $85, $85, $f0, $20, $2c, $9e, $b5, $e0, $10, $1e
byte $84, $24, $88, $65, $19, $fc, $83, $90, $24, $f6, $62, $52, $7e, $f0, $e6, $20
byte $96, $15, $d3, $08, $1f, $04, $38, $4b, $64, $cf, $46, $04, $a3, $10, $ee, $9f
byte $8b, $24, $09, $6c, $59, $31, $0b, $fe, $fe, $a5, $70, $e2, $c0, $8e, $3d, $0b
byte $c6, $21, $9c, $0b, $67, $8e, $ec, $d9, $92, $62, $c6, $3f, $84, $6d, $88, $e0
byte $c9, $9a, $05, $e1, $e0, $c7, $95, $73, $0c, $20, $c7, $86, $25, $33, $02, $21
byte $94, $2b, $97, $e0, $91, $21, $48, $11, $8f, $60, $4c, $99, $50, $e2, $48, $9e
byte $6d, $0c, $60, $1a, $41, $83, $07, $63, $86, $ec, $c9, $91, $26, $49, $8c, $50
byte $29, $0f, $02, $2a, $94, $28, $d4, $a7, $47, $b7, $4e, $1d, $da, $b4, $6a, $09
byte $d5, $ca, $14, $29, $d0, $ab, $47, $97, $0e, $ed, $da, $b4, $68, $0e, $5e, $2a
byte $c3, $83, $7e, $bd, $e1, $49, $6a, $f0, $51, $ae, $58, $41, $74, $d0, $a5, $33
byte $3c, $68, $d5, $ac, $29, $7c, $8a, $56, $aa, $28, $3c, $c8, $d6, $29, $43, $bb
byte $56, $29, $9a, $25, $05, $4f, $1d, $5a, $14, $ca, $8b, $17, $e1, $41, $5a, $b2
byte $90, $a4, $31, $78, $4a, $d3, $a4, $41, $ac, $1a, $59, $c9, $42, $5a, $bc, $b8
byte $12, $c1, $43, $b7, $56, $8d, $e2, $d5, $8a, $56, $29, $42, $58, $78, $90, $1c
byte $26, $82, $87, $0c, $29, $1a, $d5, $a9, $51, $a5, $52, $b9, $30, $a1, $8a, $9f
byte $60, $f0, $d0, $26, $39, $3a, $88, $11, $25, $42, $b8, $52, $25, $82, $15, $29
byte $14, $10, $3c, $a4, $4a, $52, $2f, $56, $b5, $4a, $15, $e1, $41, $88, $60, $81
byte $0a, $e4, $fb, $d7, $15, $1d, $c4, $a9, $11, $25, $52, $b8, $32, $a5, $e1, $41
byte $a0, $00, $fd, $fe, $65, $48, $96, $20, $4e, $8c, $aa, $e8, $20, $2c, $3c, $08
byte $0a, $1e, $e1, $43, $7b, $7c, $14, $2d, $4a, $85, $70, $a1, $f1, $21, $5e, $c8
byte $97, $e7, $5f, $9a, $24, $f1, $62, $45, $8b, $cc, $16, $42, $85, $84, $a7, $e0
byte $21, $55, $a2, $f8, $74, $11, $1f, $a2, $ab, $bc, $06, $a1, $51, $83, $7a, $75
byte $6a, $d5, $88, $2e, $10, $2a, $62, $41, $2a, $d0, $14, $1c, $c4, $07, $07, $31
byte $aa, $55, $a9, $12, $19, $1c, $95, $09, $6d, $10, $e1, $41, $5c, $78, $16, $11
byte $9e, $94, $46, $db, $f0, $11, $1e, $94, $d7, $44, $21, $1a, $25, $88, $0f, $2f
byte $d1, $49, $69, $cd, $48, $c6, $f1, $a1, $02, $44, $8b, $f0, $24, $44, $82, $7a
byte $71, $fd, $20, $1d, $86, $47, $61, $c9, $42, $89, $e2, $e0, $a0, $56, $6d, $78
byte $69, $10, $25, $a1, $66, $84, $67, $51, $d9, $40, $44, $b4, $10, $a6, $34, $38
byte $08, $ce, $07, $62, $c3, $73, $0b, $14, $da, $10, $05, $c9, $93, $ab, $47, $4c
byte $73, $a8, $1f, $c2, $93, $b5, $e0, $e0, $29, $47, $b7, $2c, $99, $f3, $42, $f8
byte $f0, $88, $0f, $82, $83, $87, $3e, $b9, $72, $64, $07, $0f, $19, $32, $82, $a7
byte $90, $01, $29, $28, $38, $06, $2f, $e9, $d2, $a4, $49, $4d, $96, $3d, $21, $3c
byte $cb, $94, $11, $3c, $a4, $4a, $95, $22, $59, $52, $f0, $8d, $0e, $c1, $53, $4a
byte $f0, $e4, $28, $31, $63, $2a, $12, $a4, $50, $81, $00, $f9, $fa, $f4, $fd, $84
byte $b4, $a8, $44, $88, $e2, $5d, $b1, $3a, $f5, $e7, $81, $b8, $a0, $5b, $b6, $ae
byte $45, $21, $28, $bc, $c8, $d3, $2b, $27, $4b, $ca, $0a, $af, $6b, $40, $6f, $78
byte $96, $55, $10, $37, $c3, $61, $90, $57, $39, $c3, $43, $9e, $3c, $85, $97, $32
byte $3c, $47, $47, $5d, $32, $2b, $84, $c2, $53, $a9, $2f, $59, $c9, $0e, $8f, $32
byte $b3, $41, $78, $c8, $06, $d1, $31, $59, $97, $81, $12, $11, $1e, $a3, $83, $dc
byte $da, $13, $bc, $04, $84, $f7, $d6, $11, $3c, $e2, $55, $78, $eb, $5c, $d1, $22
byte $bc, $25, $4b, $9e, $3c, $a4, $07, $7f, $d9, $bc, $c2, $13, $f7, $64, $cb, $47
byte $36, $ef, $e0, $10, $1e, $c2, $47, $b2, $e0, $2f, $8f, $5f, $3a, $08, $1e, $b2
byte $78, $c9, $4c, $16, $dc, $b9, $73, $90, $9f, $2c, $f9, $86, $c7, $e8, $10, $9e
byte $b8, $57, $08, $1d, $3a, $a4, $4b, $3f, $13, $83, $b3, $2a, $08, $8c, $17, $91
byte $70, $1a, $ce, $03, $29, $cb, $28, $78, $ea, $94, $19, $1e, $83, $c3, $3c, $9c
byte $57, $c9, $22, $61, $84, $07, $6d, $e1, $71, $1e, $04, $0f, $89, $12, $25, $c8
byte $5f, $8b, $6b, $7b, $19, $4a, $0a, $9e, $e2, $d7, $52, $74, $0d, $1e, $12, $38
byte $04, $8f, $74, $70, $14, $b7, $66, $74, $d8, $06, $12, $d8, $07, $ef, $a3, $28
byte $85, $b3, $24, $4e, $f1, $22, $3c, $04, $cf, $f0, $c8, $25, $59, $85, $07, $0e
byte $e1, $43, $5c, $74, $e4, $9a, $0d, $b8, $84, $27, $8e, $c1, $81, $3d, $3b, $ee
byte $dc, $92, $05, $d7, $f0, $10, $bc, $c2, $83, $f8, $e0, $f1, $06, $83, $43, $78
byte $90, $1c, $2f, $38, $72, $e0, $10, $1c, $c4, $85, $0f, $a9, $c1, $23, $59, $47
byte $47, $f1, $ec, $d8, $26, $8b, $f8, $10, $9e, $38, $85, $e7, $e0, $11, $1f, $a2
byte $13, $27, $49, $e9, $92, $7d, $74, $08, $9f, $5c, $b9, $86, $f7, $e0, $c1, $96
byte $ed, $36, $97, $c5, $b3, $0d, $70, $cf, $1a, $e3, $69, $3a, $f0, $5e, $16, $d3
byte $4a, $3a, $37, $ae, $d3, $e2, $2e, $5c, $a5, $79, $c1, $43, $46, $78, $90, $16
byte $bc, $f8, $ca, $99, $0f, $f3, $52, $c6, $3a, $08, $0f, $52, $d9, $8b, $bb, $8b
byte $d1, $29, $3e, $70, $8f, $8e, $52, $c5, $65, $04, $31, $fb, $88, $a7, $4c, $1e
byte $75, $31, $6b, $88, $13, $c7, $56, $0c, $1b, $d1, $ac, $d2, $65, $f0, $8c, $1e
byte $5c, $c2, $83, $d8, $e0, $c0, $5a, $14, $4b, $96, $2c, $a4, $27, $87, $a2, $19
byte $9e, $58, $b3, $66, $25, $32, $78, $30, $67, $1e, $1e, $a2, $07, $bb, $f0, $c0
byte $26, $3c, $b0, $0a, $0e, $2c, $98, $33, $63, $c6, $94, $09, $17, $b6, $d1, $89
byte $55, $f0, $23, $c2, $98, $2d, $9b, $f0, $10, $1d, $e2, $23, $73, $e2, $cc, $88
byte $86, $8f, $e0, $1d, $5e, $a2, $07, $53, $a2, $e1, $2b, $59, $b2, $22, $c9, $82
byte $04, $73, $62, $e1, $83, $09, $13, $c2, $d1, $81, $74, $74, $09, $1e, $e1, $21
byte $38, $04, $4f, $d6, $a4, $c2, $73, $7c, $8a, $0e, $8c, $b9, $70, $59, $8a, $4b
byte $62, $4e, $64, $8e, $c8, $99, $0b, $ae, $c4, $56, $d8, $c3, $59, $20, $78, $4f
byte $03, $ce, $4b, $71, $2e, $06, $4f, $52, $2c, $53, $45, $74, $5c, $1a, $7b, $b0
byte $71, $90, $09, $5f, $c4, $c3, $07, $a7, $f0, $15, $1c, $c2, $37, $8b, $e0, $c5
byte $71, $2f, $ac, $09, $b2, $79, $30, $73, $44, $0f, $ce, $f1, $89, $03, $f9, $e8
byte $44, $ba, $51, $90, $20, $1e, $7c, $c2, $57, $7c, $20, $55, $19, $82, $07, $25
byte $4e, $14, $c3, $43, $f0, $24, $13, $9e, $89, $45, $87, $e4, $40, $21, $38, $90
byte $63, $9b, $1e, $c2, $43, $74, $60, $c6, $98, $52, $72, $a0, $10, $1f, $c8, $06
byte $8f, $f0, $11, $1d, $89, $11, $66, $c4, $90, $40, $7e, $20, $47, $36, $7d, $90
byte $0e, $5f, $c4, $08, $11, $0a, $1e, $04, $f8, $47, $c7, $f8, $11, $bc, $19, $31
byte $22, $18, $1c, $e8, $d3, $a3, $1b, $1c, $c2, $2f, $c3, $e0, $41, $9f, $5f, $f0
byte $a0, $43, $9b, $56, $f4, $21, $c8, $80, $40, $78, $a4, $1b, $3c, $69, $d2, $44
byte $41, $1c, $19, $d1, $91, $c1, $90, $01, $3b, $36, $a4, $88, $13, $a1, $e7, $3f
byte $00, $ad, $c4, $18, $40, $8f, $0e, $29, $12, $44, $09, $06, $ef, $95, $c8, $88
byte $01, $7d, $be, $b4, $49, $66, $09, $ba, $21, $88, $59, $f4, $20, $94, $00, $e8
byte $d2, $a6, $49, $1c, $31, $fd, $e0, $45, $2c, $78, $30, $ca, $01, $c1, $93, $3a
byte $15, $84, $38, $43, $20, $33, $22, $84, $09, $11, $a4, $9f, $1e, $68, $d1, $c0
byte $4a, $09, $6f, $f0, $0c, $9f, $c1, $33, $05, $e0, $a2, $41, $0d, $33, $ba, $e0
byte $c9, $34, $7c, $07, $0f, $5a, $38, $82, $07, $86, $18, $98, $3e, $a2, $17, $3d
byte $3c, $b4, $71, $62, $a3, $82, $11, $75, $04, $08, $de, $f8, $c3, $07, $6e, $9a
byte $d8, $b1, $60, $44, $1b, $7c, $e9, $e3, $a3, $83, $1b, $27, $76, $ac, $98, $c0
byte $05, $6f, $44, $04, $c3, $07, $de, $e8, $11, $3c, $d1, $83, $f0, $1f, $bd, $10
byte $86, $0f, $bc, $e1, $0b, $32, $7a, $50, $fe, $91, $12, $41, $4c, $08, $61, $f8
byte $0c, $1e, $38, $b0, $62, $c6, $00, $3a, $7c, $20, $21, $8c, $88, $00, $7e, $7c
byte $e1, $13, $07, $34, $c8, $10, $c0, $04, $6f, $04, $c1, $07, $1b, $66, $8c, $60
byte $fd, $cb, $96, $22, $51, $9c, $18, $51, $22, $84, $0b, $15, $22, $58, $90, $40
byte $f9, $f2, $e4, $ca, $94, $22, $21, $f8, $09, $14, $10, $3c, $65, $48, $96, $20
byte $56, $b4, $48, $11, $c2, $c2, $47, $78, $08, $5e, $d2, $25, $8b, $0f, $9e, $c2
byte $83, $47, $74, $60, $28, $80, $bf, $3c, $be, $dc, $39, $89, $67, $2b, $9a, $a5
byte $70, $66, $42, $18, $c7, $47, $7e, $72, $f9, $48, $93, $c4, $5e, $0c, $2b, $91
byte $c9, $81, $89, $60, $46, $e1, $49, $0e, $b3, $e0, $25, $82, $b9, $d0, $e0, $11
byte $9d, $e5, $08, $63, $28, $8e, $8d, $28, $16, $cc, $99, $0a, $61, $24, $90, $81
byte $fc, $e8, $c9, $8c, $21, $3f, $3e, $c1, $83, $19, $53, $c6, $af, $83, $01, $7f
byte $7e, $7c, $a3, $47, $f0, $e4, $c5, $42, $18, $d3, $f8, $10, $3e, $d2, $05, $1f
byte $de, $e1, $8b, $17, $0f, $6e, $e1, $2b, $3c, $06, $1f, $9e, $c1, $83, $0b, $e7
byte $53, $11, $fc, $78, $f3, $e4, $ce, $2d, $78, $70, $a2, $10, $3c, $e8, $86, $0f
byte $e2, $0c, $e9, $f1, $a6, $c9, $9d, $1a, $17, $ca, $1c, $39, $b0, $67, $c7, $37
byte $78, $32, $0a, $5e, $e1, $93, $23, $05, $f6, $e4, $d8, $92, $e1, $45, $92, $50
byte $f6, $88, $1e, $d4, $a8, $70, $a6, $c8, $81, $3c, $3b, $32, $ac, $59, $c9, $91
byte $23, $5b, $96, $4c, $19, $d2, $a5, $49, $93, $ca, $45, $32, $67, $49, $12, $25
byte $06, $a7, $e0, $c1, $5d, $1a, $57, $a9, $52, $82, $83, $a4, $44, $20, $87, $b7
byte $2c, $9e, $32, $c2, $27, $57, $29, $c1, $93, $a3, $44, $0e, $e1, $83, $57, $78
byte $e4, $c6, $2d, $3a, $70, $96, $cc, $29, $3a, $70, $90, $2d, $9b, $57, $f8, $88
byte $0f, $d1, $99, $53, $74, $e0, $c0, $3b, $3c, $c8, $e4, $51, $3c, $c2, $43, $72
byte $08, $0e, $d1, $41, $7c, $78, $e2, $2e, $9d, $1b, $d7, $0a, $c0, $39, $78, $94
byte $cc, $f0, $51, $2f, $c2, $43, $7c, $cc, $16, $f1, $81, $43, $c5, $48, $4f, $c1
byte $83, $6b, $f8, $e4, $14, $1f, $d9, $b3, $4f, $16, $e1, $2b, $38, $b4, $40, $8e
byte $d1, $31, $78, $26, $8b, $f0, $19, $1f, $29, $05, $87, $86, $c0, $2e, $7c, $a4
byte $cb, $e4, $50, $3f, $a2, $53, $43, $0c, $1e, $34, $ba, $45, $7c, $a4, $cc, $89
byte $62, $74, $6c, $09, $b4, $e2, $4b, $f8, $88, $0e, $14, $29, $04, $07, $72, $c1
byte $83, $06, $75, $6e, $54, $e3, $4b, $74, $24, $c7, $92, $46, $fc, $a0, $c6, $95
byte $0a, $65, $4a, $d1, $23, $3c, $8c, $c8, $02, $21, $fe, $50, $dc, $86, $c6, $28
byte $b3, $71, $54, $41, $09, $e2, $d9, $89, $63, $cb, $a6, $57, $f0, $6a, $8d, $79
byte $8a, $7d, $f0, $10, $1b, $3c, $44, $b3, $16, $95, $07, $f3, $54, $78, $16, $c3
byte $7a, $0e, $88, $64, $c9, $42, $7a, $13, $dc, $04, $ec, $c4, $b2, $61, $13, $1c
byte $58, $05, $87, $57, $c1, $bc, $0c, $b0, $8f, $17, $d1, $21, $3c, $b2, $0c, $5e
byte $cc, $5e, $07, $3b, $76, $c1, $21, $3c, $84, $8f, $e0, $41, $82, $39, $73, $62
byte $c1, $8f, $15, $a9, $e8, $cc, $8c, $28, $d3, $f0, $10, $5d, $48, $b2, $08, $1f
byte $d1, $81, $28, $13, $76, $64, $d9, $9c, $0a, $d2, $c9, $82, $65, $70, $20, $4e
byte $8c, $69, $f0, $8c, $4f, $a4, $d2, $65, $7c, $0a, $9e, $64, $1f, $06, $eb, $f0
byte $40, $92, $24, $09, $16, $e1, $21, $3e, $30, $21, $12, $7c, $d2, $0d, $51, $a2
byte $44, $88, $84, $07, $36, $e1, $81, $54, $78, $20, $41, $9c, $78, $ba, $24, $42
byte $38, $ba, $24, $8b, $e8, $48, $2c, $3c, $12, $26, $4b, $86, $34, $e9, $f0, $10
byte $3e, $c2, $43, $70, $08, $5e, $47, $f2, $ac, $0e, $89, $aa, $91, $2c, $96, $e2
byte $5e, $bc, $ca, $e3, $a2, $6e, $9e, $a9, $3b, $31, $0d, $ae, $02, $f9, $ae, $10
byte $1e, $d8, $9c, $a9, $27, $45, $21, $3a, $92, $63, $9b, $2c, $82, $e7, $5e, $d8
byte $1a, $7b, $23, $3c, $46, $47, $32, $4c, $f7, $44, $74, $e4, $18, $1e, $82, $07
byte $39, $b2, $e1, $81, $4d, $85, $60, $4c, $f8, $2c, $06, $cf, $21, $19, $3c, $58
byte $13, $61, $42, $98, $11, $21, $86, $04, $8f, $42, $ba, $08, $1f, $5d, $81, $34
byte $93, $f0, $c0, $88, $20, $43, $02, $0c, $e8, $93, $eb, $13, $e1, $91, $74, $8d
byte $08, $4f, $04, $e8, $f3, $a7, $47, $8f, $2f, $99, $aa, $19, $1e, $08, $45, $87
byte $f0, $48, $9f, $1e, $5d, $ba, $74, $e8, $d0, $26, $45, $38, $3e, $10, $24, $48
byte $20, $7c, $84, $87, $e0, $49, $9b, $36, $2d, $c6, $e1, $21, $78, $d2, $0f, $0f
byte $e1, $23, $3c, $06, $8f, $74, $49, $90, $41, $78, $88, $ae, $b4, $70, $11, $26
byte $14, $dd, $e3, $05, $6e, $5a, $b4, $a2, $3b, $5e, $3a, $78, $e2, $23, $ce, $b3
byte $b9, $2e, $f6, $d1, $d9, $d8, $06, $f9, $80, $d0, $3e, $67, $36, $1d, $ab, $46
byte $f0, $24, $75, $35, $48, $1c, $c3, $65, $9d, $2e, $f6, $21, $ab, $e8, $b8, $0e
byte $96, $75, $b2, $08, $1e, $e1, $61, $59, $30, $3f, $06, $c1, $77, $1f, $3d, $85
byte $75, $79, $35, $92, $45, $3e, $dc, $06, $ac, $8f, $11, $b1, $f0, $1c, $bc, $ef
byte $66, $78, $0c, $de, $88, $08, $21, $4c, $17, $57, $fb, $18, $b5, $85, $aa, $79
byte $b6, $ee, $46, $74, $42, $42, $18, $31, $22, $82, $e1, $23, $3a, $23, $23, $86
byte $94, $48, $f0, $20, $14, $3c, $10, $d0, $a2, $59, $0c, $90, $67, $8b, $af, $10
byte $9e, $10, $22, $24, $40, $93, $26, $0d, $1a, $c4, $91, $21, $0b, $4f, $88, $93
byte $05, $42, $04, $34, $71, $e2, $a0, $8e, $9d, $1a, $55, $a2, $48, $90, $c4, $0b
byte $44, $c1, $01, $01, $ce, $f0, $80, $1d, $1b, $36, $ac, $58, $a9, $60, $26, $1c
byte $1c, $82, $07, $7e, $9a, $38, $c2, $07, $36, $6a, $58, $b1, $60, $c1, $8c, $09
byte $13, $46, $04, $08, $f0, $ef, $83, $65, $b4, $b4, $68, $45, $85, $38, $41, $6c
byte $99, $6c, $a5, $2c, $41, $23, $09, $60, $0d, $5e, $5b, $93, $0e, $6e, $da, $b8
byte $c2, $47, $f0, $8a, $4e, $f4, $e7, $41, $70, $08, $1f, $38, $d2, $44, $f8, $d8
byte $3a, $4b, $23, $3c, $a4, $85, $e0, $8d, $9f, $3e, $3e, $ba, $78, $a2, $47, $72
byte $c0, $11, $3f, $f2, $40, $74, $c4, $47, $0f, $6f, $78, $c0, $1d, $3e, $a2, $63
byte $f0, $40, $40, $00, $7f, $70, $08, $1f, $47, $22, $78, $17, $0e, $04, $f4, $f1
byte $47, $47, $3c, $e1, $b1, $0e, $c4, $47, $28, $e1, $11, $5f, $74, $08, $5e, $55
byte $00, $3b, $b4, $f0, $19, $1e, $82, $27, $ee, $f8, $0a, $15, $0b, $fe, $f8, $18
byte $3e, $82, $43, $7c, $80, $11, $1e, $a1, $04, $0f, $7c, $d1, $05, $66, $74, $80
byte $8e, $0d, $2a, $14, $cc, $d1, $05, $76, $ba, $84, $1e, $be, $20, $07, $0f, $bc
byte $78, $e1, $44, $07, $58, $30, $a3, $63, $72, $80, $02, $39, $3a, $c0, $c5, $93
byte $2e, $60, $e1, $c4, $09, $03, $3a, $b4, $e8, $00, $19, $32, $d2, $c5, $31, $2a
byte $f1, $85, $84, $04, $00, $0d, $32, $44, $b0, $c0, $a8, $ce, $86, $e0, $15, $13
byte $22, $00, $36, $28, $c1, $03, $c4, $e4, $0c, $df, $b0, $83, $07, $b4, $e0, $01
byte $0e, $c4, $e2, $98, $0d, $18, $f0, $a7, $c4, $e8, $19, $3c, $41, $86, $4f, $8c
byte $18, $c0, $a3, $c5, $03, $1b, $66, $f2, $88, $1f, $e0, $82, $27, $a4, $e0, $01
byte $0e, $2d, $18, $50, $38, $a1, $43, $0d, $3e, $98, $20, $a2, $0f, $5e, $20, $81
byte $07, $6f, $cc, $e1, $11, $3c, $3a, $b0, $e1, $23, $78, $00, $0d, $5f, $c1, $13
byte $02, $f8, $f0, $01, $1a, $14, $08, $e0, $40, $01, $03, $8c, $1f, $90, $a3, $03
byte $84, $e8, $01, $26, $f8, $00, $80, $0b, $32, $78, $81, $8f, $0e, $c1, $13, $58
byte $f8, $08, $1e, $30, $21, $c7, $0f, $08, $e0, $82, $27, $48, $10, $c0, $80, $00
byte $0a, $1e, $30, $20, $41, $8c, $8f, $c9, $29, $78, $c3, $09, $be, $d1, $21, $3d
byte $84, $4f, $f8, $70, $a0, $87, $ef, $e4, $0a, $10, $3e, $6c, $68, $c1, $33, $3e
byte $65, $17, $78, $b0, $a1, $f8, $27, $44, $8f, $0e, $4d, $ee, $dc, $a8, $70, $a2
byte $c8, $81, $3c, $5b, $32, $a4, $59, $f9, $27, $4c, $9f, $0f, $4d, $ea, $d4, $b8
byte $50, $e2, $48, $81, $1d, $59, $36, $a4, $49, $f9, $27, $42, $9f, $0e, $af, $e0
byte $41, $85, $12, $c5, $e0, $49, $86, $75, $f0, $20, $4a, $80, $0e, $2d, $1a, $d1
byte $8b, $02, $b9, $e8, $4d, $9c, $00, $dd, $e0, $41, $2d, $7c, $91, $23, $1b, $3f
byte $c2, $87, $7f, $82, $c1, $9b, $72, $f4, $08, $be, $88, $e8, $d1, $a6, $11, $3e
byte $82, $7f, $0a, $c0, $87, $9b, $26, $36, $2a, $c1, $df, $3f, $36, $fa, $78, $68
byte $62, $a7, $8a, $99, $22, $06, $72, $68, $c9, $a0, $8e, $9f, $fe, $11, $e2, $c1
byte $49, $1d, $2b, $65, $8c, $14, $d0, $91, $45, $43, $1a, $a5, $ff, $00, $80, $09
byte $2f, $2e, $ec, $58, $31, $63, $0a, $fe, $d8, $d0, $e1, $c6, $41, $0d, $13, $26
byte $0c, $e4, $d1, $a2, $41, $4d, $32, $7c, $fa, $c7, $80, $06, $05, $36, $2c, $c1
byte $03, $7d, $f0, $8c, $5e, $fe, $21, $a1, $45, $89, $2c, $f8, $a2, $0a, $5f, $fe
byte $c1, $a1, $42, $8e, $14, $33, $46, $f4, $e8, $a2, $47, $f0, $81, $08, $1a, $05
byte $50, $c4, $00, $83, $37, $49, $16, $c4, $b9, $51, $e3, $ca, $85, $33, $a5, $01
byte $c4, $be, $26, $b0, $24, $41, $9c, $18, $51, $aa, $e5, $a1, $7b, $34, $00, $f2
byte $e4, $82, $47, $f8, $64, $46, $94, $09, $11, $c2, $e1, $91, $42, $f0, $20, $4b
byte $96, $64, $f8, $0a, $0e, $84, $09, $11, $0c, $0e, $c1, $3f, $78, $10, $0a, $1e
byte $04, $e8, $07, $4f, $32, $e1, $37, $78, $d3, $a3, $47, $37, $f8, $13, $24, $18
byte $3e, $82, $03, $5d, $3c, $e1, $17, $51, $70, $40, $40, $1f, $1f, $5d, $bc, $74
byte $48, $20, $27, $86, $94, $28, $92, $e4, $80, $90, $00, $fe, $e0, $89, $07, $4f
byte $7a, $40, $16, $1c, $88, $20, $0e, $9f, $c1, $9b, $0e, $0a, $e2, $c1, $93, $30
byte $61, $44, $08, $11, $e0, $c7, $17, $3d, $f0, $e0, $46, $81, $1c, $19, $52, $24
byte $e1, $21, $7c, $c4, $47, $bc, $78, $83, $57, $fc, $08, $9e, $08, $c3, $57, $f0
byte $09, $df, $c1, $21, $7a, $86, $87, $e8, $1f, $7c, $71, $c7, $bf, $e8, $98, $3c
byte $e2, $23, $6c, $36, $2f, $93, $54, $2f, $c8, $0d, $bd, $91, $68, $eb, $24, $f3
byte $30, $49, $55, $82, $4e, $39, $18, $88, $04, $2f, $d2, $a4, $83, $43, $2d, $0c
byte $cf, $a5, $83, $50, $78, $0b, $5e, $b5, $a1, $74, $44, $f7, $ca, $10, $1d, $10
byte $37, $8e, $e0, $49, $12, $65, $2b, $a8, $95, $8d, $21, $7c, $20, $22, $44, $fb
byte $25, $04, $5f, $a4, $f1, $a2, $31, $d2, $c6, $45, $0b, $27, $89, $56, $58, $2b
byte $6b, $43, $67, $0c, $5e, $34, $70, $b4, $82, $5a, $41, $a4, $35, $21, $c4, $8d
byte $0b, $27, $4e, $1c, $d4, $b1, $63, $a3, $da, $29, $c3, $43, $6b, $c0, $1d, $1d
byte $82, $47, $70, $c0, $86, $15, $0b, $16, $cc, $c1, $0b, $57, $f8, $c0, $81, $23
byte $f8, $62, $c2, $d4, $18, $82, $17, $f6, $e0, $81, $35, $7c, $60, $c6, $8c, $09
byte $22, $46, $08, $f1, $29, $78, $43, $c1, $0c, $19, $13, $c6, $e0, $85, $03, $46
byte $78, $80, $16, $9f, $20, $85, $0f, $0c, $e1, $03, $66, $7c, $0c, $0e, $50, $a1
byte $40, $0e, $0f, $10, $21, $62, $00, $7f, $85, $ce, $04, $fd, $b3, $44, $27, $6f
byte $64, $83, $c7, $71, $24, $d6, $e2, $59, $c2, $5d, $36, $8a, $c6, $16, $b8, $12
byte $47, $82, $1e, $de, $3b, $11, $9e, $69, $86, $0f, $04, $e1, $65, $2d, $44, $87
byte $a2, $59, $21, $ee, $10, $be, $a5, $10, $1e, $ea, $72, $bc, $c4, $bf, $26, $de
byte $c0, $93, $08, $4f, $75, $a1, $42, $84, $0f, $7a, $e1, $61, $2b, $46, $67, $1c
byte $7b, $38, $3a, $c6, $27, $9c, $45, $03, $7a, $b2, $88, $8e, $77, $28, $bc, $04
byte $af, $cf, $71, $07, $61, $e3, $86, $15, $1e, $eb, $c2, $63, $c0, $0f, $0f, $2f
byte $dc, $64, $15, $bc, $a0, $63, $47, $00, $3f, $3c, $86, $0f, $d8, $b0, $61, $e1
byte $8a, $17, $30, $a0, $43, $c3, $10, $1e, $f0, $c1, $85, $83, $07, $36, $2e, $58
byte $30, $61, $06, $07, $ec, $d0, $d0, $83, $47, $07, $36, $3a, $c0, $8d, $17, $e1
byte $25, $78, $80, $0b, $1e, $60, $d1, $80, $8e, $0e, $e1, $29, $3a, $40, $03, $0f
byte $0e, $1c, $5a, $30, $60, $40, $83, $02, $05, $12, $46, $74, $08, $1e, $50, $f7
byte $06, $76, $ea, $eb, $60, $3c, $2d, $0b, $8c, $18, $92, $05, $0e, $1a, $eb, $68
byte $59, $cf, $8b, $f1, $80, $7e, $6b, $6c, $f3, $69, $81, $01, $3d, $b8, $e0, $b5
byte $8d, $21, $85, $a7, $6c, $70, $74, $b6, $c1, $3e, $5c, $96, $e1, $63, $6f, $42
byte $4d, $96, $eb, $20, $7c, $40, $88, $0f, $f9, $20, $5e, $41, $c5, $02, $19, $73
byte $70, $80, $08, $01, $7c, $78, $00, $5b, $21, $b0, $05, $87, $e8, $00, $29, $bc
byte $80, $0b, $9e, $58, $c3, $e3, $d1, $0a, $0f, $65, $03, $2c, $58, $68, $e1, $01
byte $4a, $78, $3a, $1b, $c1, $a3, $2a, $80, $05, $03, $2d, $59, $5c, $c5, $e8, $10
byte $2f, $82, $4f, $78, $4c, $16, $90, $21, $85, $a7, $e8, $d8, $24, $a0, $3e, $89
byte $f0, $11, $de, $db, $40, $f0, $7c, $13, $e1, $2d, $3e, $80, $0e, $ef, $7d, $30
byte $38, $06, $cf, $f0, $9e, $0d, $06, $e7, $3a, $c0, $0b, $67, $6b, $1e, $c9, $32
byte $11, $35, $d2, $c0, $b4, $08, $1e, $f3, $68, $2d, $e6, $85, $34, $19, $3c, $d0
byte $80, $41, $bd, $b6, $83, $63, $f0, $04, $3b, $2f, $40, $83, $46, $05, $12, $04
byte $f4, $b9, $19, $1c, $21, $a6, $8c, $75, $b0, $0c, $41, $00, $07, $16, $9d, $83
byte $67, $78, $58, $1b, $20, $82, $27, $50, $20, $80, $2b, $67, $ce, $0c, $cf, $e1
byte $23, $78, $02, $02, $08, $60, $6f, $81, $8c, $0f, $c1, $31, $f8, $46, $f7, $e8
byte $00, $28, $7c, $9d, $85, $f0, $0c, $2c, $bc, $c0, $0f, $ef, $e1, $01, $70, $78
byte $0c, $1e, $d9, $24, $bc, $c1, $8b, $8e, $d9, $24, $3e, $a6, $0b, $f8, $f0, $b2
byte $79, $b4, $86, $07, $b7, $68, $64, $63, $20, $e1, $35, $78, $96, $85, $a2, $17
byte $2d, $e0, $c2, $39, $95, $87, $60, $70, $44, $82, $14, $01, $18, $00, $3c, $58
byte $fe, $83, $77, $2a, $8c, $18, $40, $00, $01, $80, $0b, $33, $78, $4f, $c6, $58
byte $50, $3c, $00, $c1, $87, $03, $c3, $ff, $a1, $6c, $89, $29, $13, $28, $60, $80
byte $c1, $03, $7a, $f0, $e9, $81, $f1, $11, $20, $3c, $d8, $50, $83, $57, $74, $04
byte $19, $5f, $92, $83, $ff, $4b, $94, $1c, $e2, $63, $74, $8a, $0f, $fe, $73, $26
byte $98, $e8, $1e, $1f, $82, $47, $41, $80, $0d, $2b, $ba, $e4, $0b, $28, $fe, $fd
byte $d7, $88, $e3, $00, $73, $1f, $40, $ad, $0f, $f0, $f3, $65, $f0, $0a, $0f, $c1
byte $63, $6d, $40, $86, $08, $0e, $76, $74, $f4, $1f, $9d, $ce, $26, $14, $48, $10
byte $c0, $82, $02, $12, $1e, $82, $e7, $39, $80, $11, $9e, $c0, $83, $01, $11, $1c
byte $fd, $c7, $8b, $e0, $71, $16, $c2, $23, $38, $d0, $c0, $82, $4f, $b2, $3a, $02
byte $e0, $c1, $82, $0c, $4e, $fe, $93, $65, $78, $4c, $96, $a0, $81, $07, $ef, $40
byte $12, $0e, $90, $01, $41, $08, $00, $dd, $97, $00, $15, $7c, $c0, $83, $02, $8e
byte $04, $10, $02, $78, $78, $bf, $44, $24, $4d, $07, $dd, $03, $00, $7c, $bc, $f1
byte $22, $f8, $82, $07, $09, $ac, $05, $16, $03, $5c, $89, $0c, $0c, $f0, $e9, $09
byte $0f, $4e, $8f, $0c, $31, $10, $40, $02, $9d, $1f, $c1, $03, $76, $26, $8f, $00
byte $31, $28, $f8, $87, $8e, $08, $d8, $11, $82, $7f, $f0, $00, $0b, $fc, $00, $c2
byte $29, $e5, $41, $00, $54, $82, $88, $00, $c1, $3f, $08, $82, $88, $00, $70, $83
byte $7f, $10, $02, $76, $12, $82, $7f, $10, $02, $03, $04, $40, $f0, $0f, $c2, $20
byte $01, $05, $ff, $20, $d2, $cb, $43, $1f, $0a, $e0, $c8, $80, $22, $01, $8c, $08
byte $20, $02, $f8, $f8, $f6, $02, $1e, $d8, $b8, $50, $06, $2f, $c4, $80, $86, $01
byte $fe, $7e, $81, $17, $0e, $ee, $b3, $80, $1c, $18, $52, $20, $e1, $3b, $3c, $04
byte $af, $65, $f1, $25, $80, $84, $0f, $80, $c3, $00, $5f, $bf, $d8, $46, $38, $f6
byte $41, $f8, $8b, $0f, $57, $0b, $3a, $54, $28, $90, $01, $85, $cf, $27, $05, $eb
byte $1c, $06, $2f, $48, $10, $a3, $47, $f0, $81, $75, $8f, $8e, $03, $44, $08, $e0
byte $83, $37, $cc, $6b, $1d, $bc, $c1, $81, $4d, $4e, $b0, $61, $9e, $07, $a8, $c1
byte $17, $0c, $e8, $70, $11, $3c, $de, $55, $fc, $88, $1e, $e1, $23, $78, $80, $02
byte $b9, $21, $12, $40, $06, $08, $fe, $20, $e1, $c6, $c0, $1c, $98, $3c, $c3, $0f
byte $fc, $08, $08, $ad, $00, $04, $7f, $80, $11, $20, $01, $c7, $1f, $90, $bb, $20
byte $02, $64, $88, $04, $04, $3e, $7a, $26, $07, $10, $b8, $5a, $00, $74, $ec, $d0
byte $b0, $42, $c5, $82, $39, $17, $60, $8c, $95, $30, $71, $c2, $c0, $5e, $20, $b0
byte $42, $81, $82, $19, $52, $26, $c0, $10, $2b, $70, $c2, $c4, $01, $1d, $5b, $47
byte $48, $11, $25, $33, $3c, $82, $8f, $0e, $0d, $10, $6a, $8e, $0c, $3e, $e0, $e2
byte $63, $0d, $8c, $0e, $c1, $a1, $64, $66, $c2, $e0, $1f, $1c, $a2, $53, $f8, $82
byte $16, $5f, $21, $84, $c7, $e0, $1d, $9f, $d2, $65, $f0, $02, $0b, $23, $39, $c5
byte $27, $88, $d1, $39, $78, $40, $4f, $4e, $90, $07, $54, $74, $02, $0b, $22, $38
byte $c4, $a7, $e8, $04, $be, $26, $06, $0f, $e0, $c0, $e2, $73, $74, $02, $d7, $10
byte $41, $04, $0f, $a0, $40, $80, $44, $57, $b0, $60, $c1, $04, $6f, $c0, $80, $01
byte $25, $1b, $30, $c1, $f7, $78, $9c, $c0, $e8, $04, $3a, $3a, $dc, $cf, $f0, $10
byte $1c, $4e, $f0, $8a, $40, $9f, $30, $62, $01, $68, $d0, $43, $02, $24, $88, $b8
byte $50, $25, $23, $d1, $e6, $0c, $5e, $c0, $d3, $22, $d0, $f0, $3a, $25, $d3, $64
byte $5c, $8c, $ee, $c1, $21, $3c, $01, $29, $88, $d1, $39, $5e, $02, $0b, $8f, $40
byte $0a, $62, $b2, $89, $d7, $40, $00, $a7, $83, $f0, $1e, $9e, $82, $67, $78, $07
byte $5a, $07, $aa, $40, $85, $c8, $1b, $e9, $3c, $3a, $00, $8a, $16, $45, $3b, $de
byte $56, $81, $78, $1f, $af, $1b, $47, $f0, $7c, $04, $79, $37, $5c, $04, $8f, $64
byte $95, $77, $7b, $25, $40, $80, $f1, $7e, $14, $84, $27, $00, $c1, $33, $3c, $01
byte $cf, $5a, $d1, $02, $00, $80, $36, $16, $9e, $a2, $c5, $20, $b8, $f3, $7d, $08
byte $6c, $b4, $f8, $e2, $5d, $18, $14, $a8, $92, $f8, $46, $ba, $60, $d6, $ca, $c4
byte $00, $8e, $72, $59, $ce, $c4, $4b, $13, $de, $a2, $01, $b1, $16, $b7, $22, $7c
byte $78, $70, $e1, $c0, $81, $1d, $2f, $56, $01, $a0, $5c, $14, $1c, $83, $07, $6c
byte $d8, $b0, $60, $7e, $8b, $23, $1d, $5e, $82, $43, $f0, $80, $1e, $de, $c3, $45
byte $78, $fc, $07, $25, $0b, $5e, $bc, $8c, $36, $ff, $20, $99, $47, $6b, $68, $50
byte $1b, $44, $32, $81, $15, $ad, $83, $67, $70, $c8, $da, $69, $2b, $5a, $40, $85
byte $02, $3f, $ed, $c3, $08, $4e, $c1, $23, $5c, $e4, $c5, $68, $fd, $2e, $db, $45
byte $da, $cf, $0a, $f1, $20, $38, $40, $5a, $46, $6b, $61, $5c, $16, $c1, $b8, $54
byte $23, $f6, $52, $af, $cc, $83, $85, $69, $1e, $85, $8b, $e0, $0f, $7b, $2f, $7c
byte $a6, $4e, $d9, $33, $d3, $50, $f0, $0c, $0f, $40, $83, $5f, $a1, $00, $1e, $de
byte $e3, $15, $2c, $18, $c1, $23, $6d, $a5, $e3, $11, $50, $09, $73, $41, $c5, $88
byte $f7, $fd, $b3, $10, $43, $84, $00, $3e, $5a, $c3, $ac, $49, $90, $21, $ef, $40
byte $f0, $db, $e1, $68, $84, $87, $68, $15, $5c, $b7, $45, $59, $cc, $02, $35, $31
byte $5a, $1e, $23, $50, $79, $21, $2d, $00, $0a, $97, $c1, $73, $1f, $be, $81, $ac
byte $00, $04, $10, $80, $78, $1e, $2d, $5a, $03, $60, $80, $f0, $92, $0e, $98, $70
byte $01, $22, $38, $c1, $87, $13, $4f, $93, $36, $c0, $e0, $00, $1d, $76, $c1, $84
byte $1a, $0b, $20, $80, $05, $e5, $3f, $00, $57, $84, $82, $91, $31, $20, $82, $03
byte $0d, $3c, $f8, $84, $17, $f0, $60, $41, $06, $17, $ff, $15, $11, $0a, $24, $08
byte $e1, $dd, $3f, $8c, $8a, $00, $19, $62, $78, $8f, $04, $f1, $32, $3c, $01, $8d
byte $ae, $fe, $c3, $33, $18, $10, $c1, $cd, $7f, $bf, $08, $0f, $59, $2f, $14, $25
byte $63, $60, $e1, $dd, $7f, $32, $8c, $f6, $a1, $0a, $10, $7c, $b8, $30, $c3, $7d
byte $10, $04, $00, $17, $56, $70, $0f, $42, $f0, $60, $43, $0d, $fe, $41, $08, $36
byte $b4, $e0, $1e, $84, $a1, $07, $f7, $20, $1e, $c4, $83, $30, $94, $04, $d1, $30
byte $0a, $45, $c3, $58, $99, $93, $32, $64, $40, $ce, $10, $d0, $47, $c4, $e4, $08
byte $7e, $25, $01, $0c, $4c, $68, $95, $69, $13, $84, $ef, $58, $09, $3a, $02, $ac
byte $8e, $5e, $70, $92, $92, $c9, $b4, $80, $92, $00, $83, $7f, $28, $00, $0d, $0c
byte $f0, $24, $08, $fe, $91, $08, $68, $93, $00, $fb, $12, $86, $78, $48, $00, $7a
byte $0e, $e0, $3c, $8c, $b6, $df, $b6, $8f, $45, $39, $0f, $c2, $70, $fa, $7e, $63
byte $0f, $e2, $41, $3c, $88, $07, $f1, $20, $1e, $c4, $83, $78, $10, $0f, $a2, $c0
byte $81, $01, $05, $02, $04, $30, $20, $80, $00, $e0, $c3, $83, $07, $17, $0e, $6c
byte $d8, $c1, $2b, $38, $04, $6f, $b8, $c1, $13, $56, $f0, $09, $0f, $e1, $33, $3c
byte $05, $ff, $e8, $10, $9e, $61, $86, $bf, $e0, $19, $2f, $61, $05, $af, $64, $1d
byte $bc, $83, $03, $8c, $f0, $91, $6e, $93, $51, $f0, $4f, $36, $c1, $11, $7a, $f8
byte $0e, $ee, $30, $a0, $43, $df, $0a, $80, $8b, $51, $74, $82, $19, $1c, $a0, $9d
byte $6d, $00, $65, $29, $5a, $41, $fb, $86, $57, $07, $76, $70, $81, $d2, $98, $b6
byte $c4, $59, $8e, $0b, $50, $a1, $40, $6e, $ad, $57, $b2, $0d, $16, $09, $88, $dd
byte $3f, $08, $b4, $82, $34, $d8, $ff, $83, $28, $2c, $90, $20, $40, $34, $cc, $41
byte $d0, $4b, $e0, $c3, $cc, $85, $c0, $e2, $52, $a3, $2a, $9d, $c1, $31, $75, $35
byte $a2, $89, $5d, $b2, $a0, $66, $4e, $48, $90, $20, $ce, $e4, $8a, $58, $0a, $72
byte $03, $e4, $e0, $00, $01, $3c, $78, $70, $60, $e1, $04, $cf, $70, $11, $3c, $82
byte $63, $f0, $08, $0e, $60, $40, $c7, $c3, $68, $05, $11, $42, $70, $01, $0d, $2d
byte $5a, $85, $8b, $e0, $11, $0d, $c3, $05, $68, $50, $c1, $3d, $1a, $05, $07, $90
byte $d1, $38, $dc, $36, $82, $72, $90, $94, $82, $7b, $95, $cc, $c2, $e0, $a2, $51
byte $47, $ac, $83, $b9, $2b, $d8, $37, $ca, $cc, $12, $76, $6a, $d1, $9c, $4c, $95
byte $1d, $09, $c8, $2b, $82, $0b, $a3, $86, $a6, $0c, $f8, $1b, $01, $16, $0c, $a8
byte $e1, $f3, $76, $2c, $cd, $da, $9d, $0e, $5f, $4d, $a7, $6e, $d4, $b7, $75, $6d
byte $67, $ad, $68, $b8, $67, $21, $47, $cb, $46, $00, $fb, $88, $05, $17, $b0, $d9
byte $30, $a9, $15, $e5, $22, $57, $79, $cb, $f8, $c7, $8e, $9b, $65, $7a, $6b, $15
byte $47, $d8, $b9, $01, $5a, $4b, $ac, $4d, $f0, $4b, $67, $e6, $80, $0e, $15, $f2
byte $19, $8a, $5a, $b9, $23, $1c, $fe, $05, $70, $e1, $70, $77, $c2, $8d, $13, $30
byte $a0, $05, $cb, $57, $14, $15, $83, $35, $44, $b0, $2f, $29, $58, $45, $49, $c8
byte $e0, $df, $2f, $9c, $8e, $01, $0d, $f2, $2f, $0f, $e2, $41, $7c, $fa, $6c, $0e
byte $e0, $40, $01, $03, $84, $7f, $2f, $fc, $9f, $66, $50, $a5, $22, $38, $43, $8f
byte $0c, $6b, $3b, $b8, $42, $8b, $95, $60, $6f, $41, $b8, $85, $9d, $b0, $83, $43
byte $dc, $81, $17, $5c, $fc, $83, $0e, $0e, $c0, $e2, $06, $00, $b8, $30, $33, $2c
byte $c8, $16, $b0, $07, $00, $c0, $c9, $fe, $d0, $81, $42, $86, $08, $0e, $54, $e1
byte $f7, $0f, $15, $12, $04, $30, $a5, $3e, $08, $86, $83, $6a, $1e, $c4, $83, $78
byte $10, $0f, $e2, $41, $3c, $88, $07, $f1, $20, $1e, $c4, $83, $78, $10, $0f, $02
DAT
{{
TERMS OF USE: MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
}}
DAT

View File

@ -0,0 +1,505 @@
''
'' VGA scanline driver 400x300 - foreground renderer
''
'' Based on "Ball" demo for Gameduino
'' Copyright (c) 2011 by James Bowman <jamesb@excamera.com>
''
'' Author: Marko Lukat
'' Last modified: 2012/12/24
'' Version: 0.11
''
OBJ
system: "boing-bel-corecon"
PUB null
'' This is not a top level object.
PUB init(ID, mailbox)
return system.launch(ID, @entry, mailbox)
DAT org 0 ' foreground renderer
entry jmpret $, #setup ' once
rdlong indx, blnk ' |
cmpsub indx, scry wz ' |
if_ne jmp #$-2 ' waiting for last line to be fetched
' Skip 26 sync lines and advance by a further 161 hub windows. This pushes an
' assumed foreground renderer hubop beyond the first video renderer line rdlong
' if it were to render scanline -1.
' After the waitcnt we have no further insns (18 + 14 = 32, 2 hub windows).
mov cnt, cnt
add cnt, $+1
long 13{18} + 14 + 132*16*26 + 16*(161 - 2)
loop waitcnt cnt, eins ' initial sync point
' wrbyte indx, base ' assumed hubop
call #pixels ' fetch foreground data (~92 hub windows)
waitcnt cnt, zwei ' block until line is available
rdlong bflag, bfadr wz
if_nz call #shadow ' draw shadow
cmp bflag, #0 wz
if_nz call #solid ' draw ball
rol mask, #8 ' update shadow mask, it's unused
' during 1st frame (msky == scry)
add indx, #1 ' line done, advance
cmpsub indx, scry wz ' optionally wrap line index
if_nz jmp #loop
' per frame updates (during the first frame mask/shadow are off-screen)
rdlong temp, blnk ' |
cmp temp, scry wz ' |
if_ne jmp #$-2 ' wait for ?/scry transition
rdword mskx, crdx ' |
shl mskx, #16 ' |
sar mskx, #16 ' |
rdword msky, crdy ' |
shl msky, #16 ' |
sar msky, #16 ' update and sign-extend mask coordinates
maxs mskx, scrx ' |
maxs msky, scry ' reasonable limit(s) (off-screen)
mov shdx, mskx ' |
add shdx, #SOFFX ' |
mov shdy, msky ' |
add shdy, #SOFFY ' apply shadow offset(s)
mov mskc, msky ' |
add mskc, #BSIZE -1 ' |
mov shdc, shdy ' |
add shdc, #BSIZE -1 ' bounding box setup
long $00FF00FF ' |
mov mask, $-1 ' reset shadow mask (scry == 2n+?)
eins long 100*16 ' initial line fetch
zwei long 164*16 ' remainder of two scan lines
drei long 132*16*28 ' skip all sync lines
add cnt, drei
jmp #loop
' support code
pixels rdlong addr, feed wz ' get current buffer address
if_z mov msky, scry ' move off-screen (disabled)
if_z jmp pixels_ret ' early exit
mov ecnt, #BSIZE/4
movd :set, #data
mov temp, mskx ' |
and temp, #%11 wz ' observe alignment
shl temp, #3 ' [4..0]: 24/16/8/0
movs :two, temp
neg temp, temp ' [4..0]: 8/16/24/0
movs :one, temp
if_nz add ecnt, #1 ' need to process one more long
if_nz sub addr, #4 ' starting with addr[-1]
:loop rdlong arg0, addr ' +0 = 00: DDCCBBAA, 01: ------DD
add addr, #4 ' +8 10: ----DDCC, 11: --DDCCBB
if_z jmp #:set ' -4 faster if aligned
rdlong arg1, addr ' +0 = 00: n/a, 01: CCBBAA--
:two shl arg1, #0-0 ' +8 10: BBAA----, 11: AA------
:one shr arg0, #0-0 ' -4
or arg0, arg1 ' +0 =
:set mov 0-0, arg0 ' +4
add $-1, dst1 ' +8
djnz ecnt, #:loop ' -4
pixels_ret ret
solid cmps indx, msky wc ' |
if_nc cmps mskc, indx wc ' |
if_c jmp solid_ret ' vertical bounds check
mov temp, indx
sub temp, msky
cmp temp, #BSIZE/2 wc
if_nc neg temp, temp
if_nc add temp, #BSIZE-1
add temp, #table ' offset into table
movs $+2, temp
neg arg2, #1 ' pipeline
mov arg0, 0-0 ' fetch offset/length pair
mov arg1, arg0
shr arg1, #16 wz ' length
and arg0, #511 ' relative offset
add arg0, mskx ' absolute offset
add arg2, arg0 ' |
add arg2, arg1 ' right side inclusive
cmps arg2, #0 wc
if_nc cmps scrc, arg0 wc ' |
if_z_or_c jmp solid_ret ' horizontal bounds check
cmps arg0, #0 wc ' |
if_c subabs arg1, arg0 ' |
if_c mov arg0, #0 ' clipped left
cmps scrc, arg2 wc ' |
if_c mov arg1, scrx ' |
if_c sub arg1, arg0 ' clipped right side
' arg0..(arg0+arg1-1) fits into the scanline buffer, draw the line
mov addr, base
add addr, arg0 ' @byte[base][arg0]
mov arg2, mskx ' |
and arg2, #%11 ' |
add arg2, arg0 ' |
sub arg2, mskx ' byte offset into data array
shr arg1, #2 wz,nr ' special code for 1..3
if_nz jmpret zero, #:full wc,nr ' carry set if taken (##)
' do an unaligned load
mov arg0, arg2 ' remember for byte alignment
shr arg2, #2 ' long offset
add arg2, #data ' long address
movs $+2, arg2
add arg2, #1 ' pipeline
mov arg3, 0-0 ' load 1st long
movs $+2, arg2
test arg0, #%11 wz ' pipeline
mov arg2, 0-0 ' load 2nd long
if_nz shl arg0, #3 ' 00: DDCCBBAA, 01: --DDCCBB
if_nz shr arg3, arg0 ' 10: ----DDCC, 11: ------DD
if_nz neg arg0, arg0 ' 00: n/a, 01: AA------
if_nz shl arg2, arg0 ' 10: BBAA----, 11: CCBBAA--
if_nz or arg3, arg2 ' combine both longs
wrbyte arg3, addr
add addr, #1
shr arg3, #8
djnz arg1, #$-3 ' relaxed @ 2 hub windows/byte
jmp solid_ret
' length is prefix + 4n + suffix, split up and deal with it
:full shr arg2, #2 ' long offset
add arg2, #data ' long address
neg ecnt, arg0 ' 0123 >> 0321
and ecnt, #%11 wz ' pixels in prefix
sub arg1, ecnt ' update length
if_z jmp #:core
' handle prefix
shl arg0, #3 ' 1..3 >> 8..24
rcr ecnt, arg0 ' create reverse mask (##)
movs $+2, arg2 ' prefix data
rev ecnt, #0 ' adjust
mov arg3, 0-0 ' |
andn arg3, ecnt ' only keep masked data
rdlong quad, addr
and quad, ecnt
or quad, arg3 ' combine with background
wrlong quad, addr
add arg2, #1 ' advance src
add addr, #4 ' advance dst
andn addr, #%11 ' |
' handle 4
:core test arg1, #%100 wz
if_nz movd $+2, arg2
if_nz sub arg1, #4 ' update length
if_nz wrlong 0-0, addr
if_nz add addr, #4 ' advance dst
if_nz add arg2, #1 ' advance src
' handle 8n
mov ecnt, arg1 ' remember for tail (%-??)
shr arg1, #3 wz ' check 8n count
if_z jmp #:suffix ' skip body
mov frqb, addr
shr frqb, #1{/2}
add arg2, arg1 ' |
add arg2, arg1 ' advance src
movd :one, arg2
sub :one, dst1 ' data[n][-1]
movd :two, arg2
sub :two, dst2 ' data[n][-2]
mov phsb, arg1
shl phsb, #3
mov addr, phsb ' advance dst
sub phsb, #1 ' 8n - 1
:one wrlong 0-0, phsb
sub $-1, dst2
sub phsb, #7 wz
:two wrlong 0-0, phsb
sub $-1, dst2
if_nz djnz phsb, #:one
' handle suffix
:suffix and ecnt, #%11 wz ' suffix (unaligned)
if_z jmp solid_ret ' early exit
shl ecnt, #3 ' 1..3 >> 8..24
neg arg1, #1 ' create mask
movs $+2, arg2 ' suffix data
shl arg1, ecnt ' adjust
mov arg3, 0-0 ' |
andn arg3, arg1 ' only keep masked data
rdlong quad, addr
and quad, arg1
or quad, arg3 ' combine with background
wrlong quad, addr
solid_ret ret
shadow cmps indx, shdy wc ' |
if_nc cmps shdc, indx wc ' |
if_c jmp shadow_ret ' vertical bounds check
mov temp, indx
sub temp, shdy
cmp temp, #BSIZE/2 wc
if_nc neg temp, temp
if_nc add temp, #BSIZE-1
add temp, #table ' offset into table
movs $+2, temp
neg arg2, #1 ' pipeline
mov arg0, 0-0 ' fetch offset/length pair
mov arg1, arg0
shr arg1, #16 wz ' length
and arg0, #511 ' relative offset
add arg0, shdx ' absolute offset
add arg2, arg0 ' |
add arg2, arg1 ' right side inclusive
cmps arg2, #0 wc
if_nc cmps scrc, arg0 wc ' |
if_z_or_c jmp shadow_ret ' horizontal bounds check
cmps arg0, #0 wc ' |
if_c subabs arg1, arg0 ' |
if_c mov arg0, #0 ' clipped left
cmps scrc, arg2 wc ' |
if_c mov arg1, scrx ' |
if_c sub arg1, arg0 ' clipped right side
' arg0..(arg0+arg1-1) fits into the scanline buffer, draw the line
mov addr, base
add addr, arg0 ' @byte[base][arg0]
shr arg1, #2 wz,wc,nr ' special code for 1..3
if_nz jmpret zero, #:full wc,nr ' carry set if taken (##)
test arg0, #1 wz
if_nz rol mask, #8 ' odd bytes only
rdbyte quad, addr
and quad, mask
rol mask, #8
wrbyte quad, addr
add addr, #1
djnz arg1, #$-5
if_c_eq_z rol mask, #8 ' restore mask
jmp shadow_ret
:full neg ecnt, arg0 ' 0123 >> 0321
and ecnt, #%11 wz ' pixels in prefix
sub arg1, ecnt ' update length
if_z jmp #:core
shl arg0, #3 ' 1..3 >> 8..24
rcr ecnt, arg0 ' create reverse mask (##)
rev ecnt, #0 ' adjust
rdlong quad, addr
or ecnt, mask ' add shadow mask
and quad, ecnt
wrlong quad, addr
add addr, #4
'{rd/wrlong} andn addr, #%11
:core mov ecnt, arg1 ' remember for tail (%-??)
shr arg1, #2 wz ' check long count
if_z jmp #:tail ' skip body
rdlong quad, addr
and quad, mask
cmp arg1, #1 wz
wrlong quad, addr
add addr, #4
if_nz djnz arg1, #$-5
:tail and ecnt, #%11 wz ' suffix (unaligned)
if_z jmp shadow_ret ' early exit
shl ecnt, #3 ' 1..3 >> 8..24
neg arg1, #1 ' |
shl arg1, ecnt ' protect unused pixels
rdlong quad, addr
or arg1, mask ' add shadow mask
and quad, arg1
wrlong quad, addr
shadow_ret ret
' initialised data and/or presets
table word 48, 16, 43, 26, 39, 34, 36, 40, 34, 44, 32, 48, 30, 52, 28, 56
word 26, 60, 25, 62, 23, 66, 22, 68, 21, 70, 19, 74, 18, 76, 17, 78
word 16, 80, 15, 82, 14, 84, 13, 86, 13, 86, 12, 88, 11, 90, 10, 92
word 10, 92, 9, 94, 8, 96, 8, 96, 7, 98, 7, 98, 6, 100, 6, 100
word 5, 102, 5, 102, 4, 104, 4, 104, 3, 106, 3, 106, 3, 106, 2, 108
word 2, 108, 2, 108, 2, 108, 1, 110, 1, 110, 1, 110, 1, 110, 1, 110
word 0, 112, 0, 112, 0, 112, 0, 112, 0, 112, 0, 112, 0, 112, 0, 112
feed long -12 ' |
crdx long -8 ' |
crdy long -6 ' |
' quick access relative to par
blnk long -4 ' |
base long NEGX ' |
dst1 long 1 << 9 ' dst +/-= 1
dst2 long 2 << 9 ' dst +/-= 2
scrc long 399 ' upper limit (inclusive)
scrx long 400
bfadr long 448
bflag long 0
' Stuff below is re-purposed for temporary storage.
setup add crdx, par ' mask coordinates (%%)
add crdy, par ' |
add feed, par ' mask buffer location
add base, par ' scanline buffer
add blnk, base wc ' frame indicator
rdword indx, blnk wz ' (%%)
if_nz mov scry, indx wc ' (%%)
if_c_or_nz jmp #$-2 ' auto-detect res_y
' The loop is only left once a non-zero value has been written to scry
' and indx transitions to zero afterwards.
mov msky, scry ' move off-screen
mov shdy, scry ' |
movi ctrb, #%0_11111_000 ' LOGIC always (loader support)
add bfadr, par
jmp %%0 ' return
fit
' uninitialised data and/or temporaries
org setup
scry res 1 ' must be 1st..5th (%%)
indx res 1 ' |
addr res 1 ' scanline reference
ecnt res 1 ' element count
mask res 1 ' shadow mask
mskc res 1 ' upper limit (inclusive)
mskx res 1 ' mask coordinates
msky res 1 ' signed 16bit
shdc res 1 ' upper limit (inclusive)
shdx res 1 ' shadow coordinates
shdy res 1 ' signed 16bit
arg0 res 1
arg1 res 1
arg2 res 1
arg3 res 1
temp res 1
quad res 1
data res BSIZE/4 +1{unaligned}
tail fit
CON
zero = $1F0 ' par (dst only)
BSIZE = 112 ' mask width/height (4n)
SOFFX = 15 ' |
SOFFY = 15 ' shadow offset
DAT
{{
TERMS OF USE: MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
}}
DAT

286
source/boing/boing-bel.spin Normal file
View File

@ -0,0 +1,286 @@
''
'' VGA scanline driver 400x300 - demo
''
'' Based on "Ball" demo for Gameduino
'' Copyright (c) 2011 by James Bowman <jamesb@excamera.com>
''
'' Author: Marko Lukat
'' Last modified: 2012/12/24
'' Version: 0.10
''
'' A few notes on timing. A (double) scan line lasts 2*(100+32) hub windows.
'' The background renderer fills the scan line as soon as the video driver
'' has read the relevant quad. At the same time the foreground renderer
'' fetches its data line.
''
'' +-- video driver reads line N
'' +-- background renderer fills line N+1
'' +-- foreground renderer fetches data for line N+1
'' |
'' | +-- scanline N completely fetched
'' | +-- background renderer idle
'' | visible line area +-- foreground renderer draws shadow and ball
'' | |
'' ----------- 100 -----------#---32---
'' ----------- 100 -----------+---32---
'' ----------- 100 -----------#---32---
'' |
'' +-- video driver reads line N+1
''
CON
_clkmode = XTAL1|PLL16X
_xinfreq = 5_000_000
CON
res_x = driver#res_x
res_y = driver#res_y
OBJ
driver: "boing-bel-driver"
back: "boing-bel-background"
ball: "boing-bel-foreground"
anim: "boing-bel-feeder"
keyb: "bel-keyb"
gcon: "glob-con"
VAR
long feeder ' @scan[-3]
long coordinates ' @scan[-2]
long frame ' @scan[-1]
long scan[res_x / 4]
long grid[12]
long bflag
PUB main | cmd
init
' boing
repeat
case gc
1: pc(keyb.gotkey) 'tastaturstatus senden
2: pc(keyb.key) 'tastaturzeichen senden
3: coordinates.word[0] := gw
coordinates.word[1] := gw
4: waitVBL
5: boing
6: bars{gc,gc,gc}
7: grid_on
8: grid_off
9: show_on
10: bar_on
11: bflag := gc
12: grid[gc] := gw
99: reboot
PRI init
dira := db_in ' datenbus auf eingabe schalten
outa[gcon#bus_hs] := 1 ' handshake inaktiv
keyb.start(gcon#b_keybd, gcon#b_keybc) ' tastaturport starten
driver.init(-1, @scan{0}) ' scanline driver
back.init(-1, @scan{0}) ' background
ball.init(-1, @scan{0}) ' foreground
anim.init(-1, @scan{0}) ' image feeder
grid_on
bflag := 0
anim.uncompress(FALSE) ' uncompress image
CON ''------------------------------------------------- SUBPROTOKOLL-FUNKTIONEN
' hbeat --------+
' clk -------+|
' /wr ------+||
' /hs -----+||| +------------------------- /cs
' |||| | -------- d0..d7
DB_IN = %00001001_00000000_00000000_00000000 'maske: dbus-eingabe
DB_OUT = %00001001_00000000_00000000_11111111 'maske: dbus-ausgabe
M1 = %00000010_00000000_00000000_00000000
M2 = %00000010_10000000_00000000_00000000 'busclk=1? & /cs=0?
M3 = %00000000_00000000_00000000_00000000
M4 = %00000010_00000000_00000000_00000000 'busclk=0?
PUB pc(zeichen) 'chip: ein byte an regnatix senden
''funktionsgruppe : chip
''funktion : ein byte an regnatix senden
''eingabe : byte
''ausgabe : -
waitpeq(M1,M2,0) 'busclk=1? & prop2=0?
dira := db_out 'datenbus auf ausgabe stellen
outa[7..0] := zeichen 'daten ausgeben
outa[gcon#bus_hs] := 0 'daten gültig
waitpeq(M3,M4,0) 'busclk=0?
dira := db_in 'bus freigeben
outa[gcon#bus_hs] := 1 'daten ungültig
PUB gc:zeichen 'chip: ein byte von regnatix empfangen
''funktionsgruppe : chip
''funktion : ein byte von regnatix empfangen
''eingabe : -
''ausgabe : byte
waitpeq(M1,M2,0) 'busclk=1? & prop2=0?
zeichen := ina[7..0] 'daten einlesen
outa[gcon#bus_hs] := 0 'daten quittieren
waitpeq(M3,M4,0) 'busclk=0?
outa[gcon#bus_hs] := 1
PUB pw(wert) 'sub: word senden
''funktionsgruppe : sub
''funktion : subprotokoll um einen long-wert an regnatix zu senden
''eingabe : 16bit wert der gesendet werden soll
''ausgabe : -
''busprotokoll : [put.byte1][put.byte2]
'' : [ hsb ][ ]
pc(wert >> 8)
pc(wert)
PUB gw:wert 'sub: word empfangen
''funktionsgruppe : sub
''funktion : subprotokoll um einen 16bit-wert von regnatix zu empfangen
''eingabe : -
''ausgabe : 16bit-wert der empfangen wurde
''busprotokoll : [get.byte1][get.byte2]
'' : [ hsb ][ lsb ]
wert := gc << 8
wert := wert + gc
PUB gl:wert 'sub: long empfangen
''funktionsgruppe : sub
''funktion : subprotokoll um einen long-wert von regnatix zu empfangen
''eingabe : -
''ausgabe : 32bit-wert der empfangen wurde
''busprotokoll : [get.byte1][get.byte2][get.byte3][get.byte4]
'' : [ hsb ][ ][ ][ lsb ]
wert := gc << 24 '32 bit empfangen hsb/lsb
wert := wert + gc << 16
wert := wert + gc << 8
wert := wert + gc
CON ''------------------------------------------------- DEMO-FUNKTIONEN
LBASE = 0
RBASE = res_x - ball#BSIZE
YBASE = res_y - ball#BSIZE
MBAR = %00000000_11111111
BLINE = 1
PRI boing : r | bx, by, bxv, byv
bx := 0
by := 0
bxv := 2
byv := 1
repeat
bx += bxv
by += byv
if bx < LBASE
bx := constant(2*LBASE) - bx
-bxv
if bx > RBASE
bx := constant(2*RBASE) - bx
-bxv
if by > YBASE
by := constant(2*YBASE) - by
-byv
ifnot ++r & 7 ' add some gravity
byv++
repeat 1
waitVBL
coordinates.word{0} := bx ' |
coordinates.word[1] := by ' update coordinates
PRI bars
grid[BLINE ] := bar(gc)
grid[BLINE+2] := bar(gc)
grid[BLINE+4] := bar(gc)
PRI bar(level):b
b := MBAR
b := !(b >> (level & 7)) & MBAR
b := b | b >< 16
PRI grid_on|i
repeat i from 0 to 11
grid[i] := 0
PRI grid_off|i
repeat i from 0 to 11
grid[i] := $FFFF
PRI show_on|i,n
n := %00000000_11111111
repeat 19
repeat i from 11 to 0
grid[i] := grid[i-1]
n := n >> 1
grid[0] := n | n >< 16
waitcnt(cnt + clkfreq/30)
PRI bar_on
bar_up(BLINE )
waitcnt(cnt + clkfreq/3)
bar_up(BLINE+2)
waitcnt(cnt + clkfreq/3)
bar_up(BLINE+4)
waitcnt(cnt + clkfreq/3)
PRI bar_up(upline)|i
repeat i from 11 to upline
grid[(i+1) <# 11] := 0
grid[i] := %00000111_11100000
waitcnt(cnt+clkfreq/20)
PRI waitVBL
repeat
until frame == res_y ' last line has been fetched
repeat
until frame <> res_y ' vertical blank starts (res_y/0 transition)
DAT
{{
TERMS OF USE: MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
}}
DAT

272
source/boing/boing-reg.spin Normal file
View File

@ -0,0 +1,272 @@
{{
}}
OBJ
ios: "reg-ios"
CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
SIDMASK = %00000000_00000000_00000000_00010000
VAR
long dmpreg
long fcnt
long fpos
long datcnt 'zeiger für dateiliste
byte fl_bye 'flag player beenden
byte fn[12] 'puffer für dateinamen
long dmu 'marker des aktuellen userverzeichnisses
long bx,by,bxv,byv
PUB main | key
ios.start
ios.belload(string("boing.bel"))
ios.sdclose
ifnot (ios.admgetspec & SIDMASK)
ios.sddmset(ios#DM_USER) 'u-marker setzen
dmu := ios.sddmget(ios#DM_USER) 'usermarker von administra holen
ios.admload(string("boing.adm"))
ios.sddmput(ios#DM_USER,dmu) 'usermarker wieder in administra setzen
ios.sddmact(ios#DM_USER) 'u-marker aktivieren
play_count
repeat
intro
\boing(string("boing.sid"))
play_dir
ios.belreset
ios.admreset
waitcnt(cnt+clkfreq*2)
ios.stop
PRI esc_key
if ios.g0_keystat
case ios.g0_keycode
27:
'ESC - geordneter rücksturz zur erde... :)
ios.sid_dmpstop 'ok, erstmal die mucke aus
ios.sid_mute(3)
ios.belreset
ios.sddmset(ios#DM_USER) 'u-marker setzen
dmu := ios.sddmget(ios#DM_USER) 'usermarker von administra holen
ios.admreset
waitcnt(cnt+clkfreq*2)
ios.sddmput(ios#DM_USER,dmu) 'usermarker wieder in administra setzen
ios.sddmact(ios#DM_USER) 'u-marker aktivieren
credits
ios.stop
"n":
ios.sid_dmpstop
ios.sid_mute(3)
abort
"p":
ios.sid_dmppause
PRI credits
ios.curoff
ios.printcls
ios.printnl
ios.print(string("Bouncing Ball for Hive - 2013 ",$0d,$0d))
ios.print(string("Graphics-Code : kuroneko",$0d))
ios.print(string("SidCog : Ahle2 ",$0d))
ios.print(string("Hive-Code : drohne235",$0d,$0d))
ios.curon
CON 'sd-player
PRI play_dir|stradr,len,i 'alle songs auf der sd-card abspielen
datcnt := 0 'zum listenanfang
repeat i from 0 to fcnt-1 'dateiliste abspielen
fpos := i + 1
play_dir_rdlst(@fn)
\boing(@fn)
PRI play_count|stradr,i
ios.sddir 'kommando: verzeichnis öffnen
datcnt := 0 'zum listenanfang
fcnt := 0 'zähler für dateianzahl
fl_bye := 0
repeat while (stradr := ios.sdnext) 'dateiliste einlesen
if str_find(stradr,string(".DMP"))
fcnt++
play_dir_wrlst(stradr)
PRI play_dir_wrlst(stradr)|len,i 'kopiert dateinamen in liste
len := strsize(stradr)
repeat i from 0 to len-1
ios.ram_wrbyte(ios#usrmod,byte[stradr][i],datcnt++)
ios.ram_wrbyte(ios#usrmod,0,datcnt++)
PRI play_dir_rdlst(stradr)|i,n 'liest dateinamen aus list
i := 0
repeat
n := ios.ram_rdbyte(ios#usrmod,datcnt++)
byte[stradr][i++] := n
while n <> 0
PRI str_find(string_1, string_2) : buffer | counter 'sys: string suchen
'' ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
'' │ Searches a string of characters for the first occurence of the specified string of characters. │
'' │ │
'' │ Returns the address of that string of characters if found and zero if not found. │
'' │ │
'' │ string1 - A pointer to the string of characters to search. │
'' │ string2 - A pointer to the string of characters to find in the string of characters to search. │
'' └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
repeat strsize(string_1--)
if(byte[++string_1] == byte[string_2])
repeat counter from 0 to (strsize(string_2) - 1)
if(byte[string_1][counter] <> byte[string_2][counter])
buffer~~
ifnot(buffer~)
return string_1
CON
res_x = 400
res_y = 300
LBASE = 0
RBASE = res_x - 112
YBASE = res_y - 112
LSHIFT = 8
PRI intro
ball_on(0)
grid_on
pause(3)
bar_on
pause(3)
PRI boing(stradr)|r,b1,b2,b3,status
bx := 0
by := 0
bxv := 2
byv := 1
ball_on(1)
ios.sid_mdmpplay(stradr) ' läuft auf sid2
repeat
bx += bxv
by += byv
if bx < LBASE
bx := constant(2*LBASE) - bx
-bxv
if bx > RBASE
bx := constant(2*RBASE) - bx
-bxv
if by > YBASE
by := constant(2*YBASE) - by
-byv
ifnot ++r & 7 ' add some gravity
byv++
status := ios.sid_dmpstatus 'playerstatus abfragen
dmpreg := ios.sid_dmpreg
b1 := (word[dmpreg + 0]>>LSHIFT) #> 1
b2 := (word[dmpreg + 2]>>LSHIFT) #> 1
b3 := (word[dmpreg + 4]>>LSHIFT) #> 1
bars(b1,b2,b3)
setBall(bx,by)
esc_key
waitVBL
while status
ios.sid_dmpstop
PRI keystat : char
ios.bus_putchar2(1)
return ios.bus_getchar2
PRI waitVBL
ios.bus_putchar2(4)
PRI setBall(x,y)
ios.bus_putchar2(3)
ios.bus_putword2(x)
ios.bus_putword2(y)
PRI boing_test
ios.bus_putchar2(5)
PRI bars(b1,b2,b3)
ios.bus_putchar2(6)
ios.bus_putchar2(b1)
ios.bus_putchar2(b2)
ios.bus_putchar2(b3)
PRI grid_on
ios.bus_putchar2(7)
PRI grid_off
ios.bus_putchar2(8)
PRI show_on
ios.bus_putchar2(9)
PRI bar_on
ios.bus_putchar2(10)
PRI ball_on(bflag)
ios.bus_putchar2(11)
ios.bus_putchar2(bflag)
PRI grid(line,val)
ios.bus_putchar2(3)
ios.bus_putword2(line)
ios.bus_putword2(val)
PRI pause(sec)
waitcnt(cnt + clkfreq * sec)
DAT
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,938 @@
CON ''=====< GUI Base >=======================================================
''
'' ===========================================================================
'' VGA High-Res Text UI Elements Base UI Support Functions v1.2
''
'' File: GUIBase.spin
'' Author: Allen Marincak
'' Copyright (c) 2009 Allen MArincak
'' See end of file for terms of use
'' ===========================================================================
CON
'---------------------------------------------------------------------------
' GUI Element Inventory
'---------------------------------------------------------------------------
' User modifies these as required by the GUI application being written.
' These constants describe how many elements of each type are required. Set
' any you do not need to 1. You can't set it to 0 because there is no
' conditional compilation for SPIN so I can't avoid NULL references.
'--------------------------------------------------------------------------
GZ_SPIN = 2 'number of SPIN controls
GZ_CHKB = 4 'number of Check Boxes
GZ_RADB = 6 'number of Radio Buttons
GZ_TBOX = 3 'number of Text Boxes
GZ_MENU = 6 'number of Menu Items
GZ_INPF = 3 'number of Input Fields
GZ_PUSH = 3 'number of pushbuttons
GZ_STAT = 2 'number of Status Lamps
'---------------------------------------------------------------------------
' Do not modify any of the constants below
'---------------------------------------------------------------------------
GZ_TOTAL = GZ_SPIN+GZ_CHKB+GZ_RADB+GZ_TBOX+GZ_MENU+GZ_INPF+GZ_PUSH+GZ_STAT
GID_SPIN = $0100 'types
GID_CHKB = $0200
GID_RADB = $0300
GID_TBOX = $0400
GID_MENU = $0500
GID_INPF = $0600
GID_PUSH = $0700
GID_STAT = $0800
G_INIT = $8000
G_IMSK = $7F00
G_OMSK = $00FF
VGACOLS = SVGA#cols
VGAROWS = SVGA#rows
OBJ
'---------------------------------------------------------------------------
' required driver objects, keep these
'---------------------------------------------------------------------------
SVGA : "vga_hires_text"
MOUS : "mouse"
KEYB : "Keyboard" 'only needed if using the Input Field Object
'---------------------------------------------------------------------------
' UI element objects
'
' You will need to comment out elements for which you set the number to 0,
' the compiler will issue an error for 0 sized arrays.
'
' Note that the SBOX object (Simple Box) is used by several other objects so
' do not comment out that one (it is miniscule anyway)
'---------------------------------------------------------------------------
SPIN[GZ_SPIN] : "SpinBox"
CHKB[GZ_CHKB] : "RadioCheck"
RADB[GZ_RADB] : "RadioCheck"
TBOX[GZ_TBOX] : "TextBox"
MENU[GZ_MENU] : "MenuItem"
INPF[GZ_INPF] : "InputField"
PUSH[GZ_PUSH] : "PushButton"
STAT[GZ_STAT] : "StatusLamp"
SBOX : "SimpleBox"
VAR
long scrn[VGACOLS*VGAROWS/4] 'screen buffer - could be bytes, but longs allow more efficient scrolling
word colors[VGAROWS] 'row colors
long sync 'sync long - written to -1 by VGA driver after each screen refresh
byte cx0,cy0,cm0,cx1,cy1,cm1 'cursor control bytes
long liveINPF 'currently active Input Field (has keyboard focus)
word gz_elem[GZ_TOTAL] 'element management array
byte gz_groups[GZ_RADB] 'radio button group control
CON ''=====< GUI Base Functions >=============================================
'
' <!> NOTE <!> Do not modify anything below unless you wish ot add or
' make changes to the GUI functionality
'-------------------------------------------------------------------------
PUB Init( vgaBasePin, MouseDatPin, MouseClkPin, KeyboardDatPin, KeyboardClkPin ) | idx, gdx
'Initializes the VGA, Mouse and Keyboard Drivers as well as basic GUI parameters
'
' vgaBasePin - start of 8 consecutive pins where the VGA H/W interface is
' MouseDatPin - the pin driving the mouse data line
' MouseClkPin - the pin driving the mouse clock line
' KeyboardDatPin - the pin driving the keyboard data line
' KeyboardClkPin - the pin driving the keyboard clock line
'
'Returns the screen geometry in a WORD
' high byte = number of character rows
' low byte = number of cgaracter columns
'---------------------------------------------------------------------------
' Start VGA, Mouse and Keyboard Drivers
'---------------------------------------------------------------------------
cx1 := 0 'text cursor starting position
cy1 := 3 ' (but hidden at start)
SVGA.start(vgaBasePin,@scrn,@colors,@cx0,@sync) 'start VGA HI RES TEXT driver
MOUS.start(MouseDatPin, MouseClkPin) 'start mouse and set bound parameters
MOUS.bound_limits(0, 0, 0, VGACOLS - 1, VGAROWS - 1, 0)
MOUS.bound_scales(4, -7, 0) 'adjust speed/sensitivity to be a touch slower
MOUS.bound_preset(2, 6, 0) 'mouse starting position
KEYB.start( KeyboardDatPin, KeyboardClkPin ) 'start keyboard driver
cm0 := %001 'set mouse cursor to be a solid block
cm1 := %000 'set text cursor to be off for the moment
ClearScreen( %%020, %%000 ) 'green on black each is %%RGB 4 levels per R-G-B
'---------------------------------------------------------------------------
'Prepare management and control array. This array has an entry for each
'element declared it maintains the status of each element and indices into
'the individual element arrays
'
'WORD format: aabb
'
' where aa = type with msb 0 = free 1 = set (initialized)
' bb = index to element array
'---------------------------------------------------------------------------
gdx := 0
if GZ_SPIN
repeat idx from 0 to GZ_SPIN - 1
gz_elem[gdx] := GID_SPIN + idx
SPIN[idx].set_gzidx( gdx )
gdx++
if GZ_CHKB
repeat idx from 0 to GZ_CHKB - 1
gz_elem[gdx] := GID_CHKB + idx
CHKB[idx].set_gzidx( gdx )
gdx++
if GZ_RADB
repeat idx from 0 to GZ_RADB - 1
gz_elem[gdx] := GID_RADB + idx
RADB[idx].set_gzidx( gdx )
gdx++
if GZ_TBOX
repeat idx from 0 to GZ_TBOX - 1
gz_elem[gdx] := GID_TBOX + idx
TBOX[idx].set_gzidx( gdx )
gdx++
if GZ_MENU
repeat idx from 0 to GZ_MENU - 1
gz_elem[gdx] := GID_MENU + idx
MENU[idx].set_gzidx( gdx )
gdx++
if GZ_INPF
repeat idx from 0 to GZ_INPF - 1
gz_elem[gdx] := GID_INPF + idx
INPF[idx].set_gzidx( gdx )
gdx++
if GZ_PUSH
repeat idx from 0 to GZ_PUSH - 1
gz_elem[gdx] := GID_PUSH + idx
PUSH[idx].set_gzidx( gdx )
gdx++
if GZ_STAT
repeat idx from 0 to GZ_STAT - 1
gz_elem[gdx] := GID_STAT + idx
STAT[idx].set_gzidx( gdx )
gdx++
liveINPF := 0
return ( VGAROWS << 8 ) + VGACOLS
PUB ProcessUI | retVal, gdx_in, odx, idx, tmp
'This function is the UI processing and control funtion. It must be executed
'often, regularly, and quickly. It should be placed in the application main
'loop and be allowed to run as often as possible to ensure a responsive UI
'
'This function will manage the UI and will return the unique id of the GUI
'element that requires an action (i.e. user clicked on an item or pressed
'enter in an Input Field). The value returned ( a GUID ) is the same value
'that was returned when the element was created via "Init" function (i.e.
'from GUI.SPINInit() or GUI.PUSHInit(), etc)
retVal := -1
cx0 := MOUS.bound_x 'get mouse position to set cursor 0 position
cy0 := MOUS.bound_y 'ALWAYS do this first
'---------------------------------------------------------------------------
'check if mouse over a control
'---------------------------------------------------------------------------
gdx_in := IsIn( cx0, cy0 )
'---------------------------------------------------------------------------
'on mouse left click perform UI action for selected element (if any)
'---------------------------------------------------------------------------
if gdx_in <> -1 'if we are in a gui element
if MOUS.button(0) 'if mouse left-click
odx := gz_elem[gdx_in] & G_OMSK 'index to object array
case gz_elem[gdx_in] & G_IMSK
GID_SPIN: 'in Spin Control
if SPIN[odx].Clicked(cx0,cy0)<>-1 ' - execute click on spin
retVal := gdx_in
GID_CHKB: 'in Check Box
CHKB[odx].Select( -1 ) ' - toggle checkbox
retVal := gdx_in
GID_RADB: 'in Radio Button
idx := 0
repeat GZ_RADB 'for each radio button
if odx == idx
RADB[idx].Select( 1 ) ' - toggle ON the selected one
RADB[idx].DrawText( 1 )
else
if gz_groups[odx] == gz_groups[idx]
RADB[idx].Select( 0 ) ' - toggle OFF the others in this group
RADB[idx].DrawText( 0 )
idx++
retVal := gdx_in
GID_TBOX: 'in Text Box
retVal := gdx_in
GID_MENU: 'in Menu Item
retVal := gdx_in
GID_INPF: 'in Input Field
idx := 0
repeat GZ_INPF 'for each input field
if idx == odx
INPF[idx].Select(1,@cx1,@cy1)
liveINPF := idx
cm1 := %111 'turn text cursor on, underscore slow blink
else
INPF[idx].Select(0,@cx1,@cy1)
idx++
'note no return for selecting INPF
GID_PUSH: 'in Push Button
retVal := gdx_in
GID_STAT: 'in Status Lamp
retVal := gdx_in
repeat while MOUS.button(0) ' - wait for mouse release
'---------------------------------------------------------------------------
'Handle Keyboard input
'---------------------------------------------------------------------------
if KEYB.gotkey
idx := INPF[liveINPF].get_gzidx
if gz_elem[idx] & G_INIT == G_INIT 'is it set
tmp := INPF[liveINPF].Handler(KEYB.key)
if tmp & $80000000
retVal := INPF[liveINPF].get_gzidx 'if enter was pressed
return retVal
PUB GetMouseXY
'Returns the mouse location in a WORD
' high byte = x location
' low byte = y location
return ( cx0 << 8 ) + cy0
PRI IsIn( cx, cy ) | idx, gdx, retVal
'returns -1 if not in an element else a gui token (gz_elem[] array index)
retVal := -1
if GZ_SPIN
repeat idx from 0 to GZ_SPIN - 1
gdx := SPIN[idx].get_gzidx
if gz_elem[gdx] & G_INIT == G_INIT 'is it set
if SPIN[idx].IsIn( cx, cy )
retVal := SPIN[idx].get_gzidx
if GZ_CHKB
repeat idx from 0 to GZ_CHKB - 1
gdx := CHKB[idx].get_gzidx
if gz_elem[gdx] & G_INIT == G_INIT 'is it set
if CHKB[idx].IsIn( cx, cy )
retVal := CHKB[idx].get_gzidx
CHKB[idx].DrawText( 1 )
else
CHKB[idx].DrawText( 0 )
if GZ_RADB
repeat idx from 0 to GZ_RADB - 1
gdx := RADB[idx].get_gzidx
if gz_elem[gdx] & G_INIT == G_INIT 'is it set
if RADB[idx].IsIn( cx, cy )
retVal := RADB[idx].get_gzidx
RADB[idx].DrawText( 1 )
else
RADB[idx].DrawText( 0 )
if GZ_TBOX
repeat idx from 0 to GZ_TBOX - 1
gdx := TBOX[idx].get_gzidx
if gz_elem[gdx] & G_INIT == G_INIT 'is it set
if TBOX[idx].IsIn( cx, cy )
retVal := TBOX[idx].get_gzidx
if GZ_MENU
repeat idx from 0 to GZ_MENU - 1
gdx := MENU[idx].get_gzidx
if gz_elem[gdx] & G_INIT == G_INIT 'is it set
if MENU[idx].IsIn( cx, cy )
retVal := MENU[idx].get_gzidx
MENU[idx].DrawText( 1 )
else
MENU[idx].DrawText( 0 )
if GZ_INPF
repeat idx from 0 to GZ_INPF - 1
gdx := INPF[idx].get_gzidx
if gz_elem[gdx] & G_INIT == G_INIT 'is it set
if INPF[idx].IsIn( cx, cy )
retVal := INPF[idx].get_gzidx
if GZ_PUSH
repeat idx from 0 to GZ_PUSH - 1
gdx := PUSH[idx].get_gzidx
if gz_elem[gdx] & G_INIT == G_INIT 'is it set
if PUSH[idx].IsIn( cx, cy )
retVal := PUSH[idx].get_gzidx
PUSH[idx].DrawText( 1 )
else
PUSH[idx].DrawText( 0 )
if GZ_STAT
repeat idx from 0 to GZ_STAT - 1
gdx := STAT[idx].get_gzidx
if gz_elem[gdx] & G_INIT == G_INIT 'is it set
if STAT[idx].IsIn( cx, cy )
retVal := STAT[idx].get_gzidx
return retVal
CON ''=====< SIMPLE BOX INTERFACE FUNCTIONS >=================================
PUB SBOXInit( pRow, pCol, pWidth, pHeight, pTitlePtr )
'Creates box with specified width and text. Something like:
' -------------
' | | - title area ( non-existant if no title supplied)
' -------------
' | |
' | | - text area with optional scolling print capability
' | |
' -------------
'
' pRow = row upper location
' pCol = col left location
' pWidth = width
' pHeight = height
' pTitlePtr = title text (text must be 2 less than width)
'
' NOTE: Columns must be LONG aligned to take advantage of the most efficient
' scrolling (via LONGMOVE). The start column must be on a long boundary
' (multiple of 4) and the width must be a multiple of 4. If print scrolling
' is not required this restriction can be ignored.
'
' NOTE: There is NO RETURN value from this call. Simple Boxes are not tracked,
' they are viaual element but are not active elements
SBOX.DrawBox( pRow, pCol, pWidth, pHeight, pTitlePtr, @scrn, VGACOLS )
CON ''=====< SPIN BOX INTERFACE FUNCTIONS >===================================
PUB SPINInit( pRow, pCol, pWidth, pType, pNum, pDataPtr ) | idx, gdx, retVal
'Creates a spin button box with specified width and text. Something like:
' ---------------------
' | spin text |↑|↓|
' ---------------------
'
' pRow = row upper location
' pCol = col left location
' pWidth = width of the control in columns
' pType = 0 = text 1 = numeric
' pNum = number of data elements
' pDataPtr = pointer to data for spin control
'
' The Data for the spin control is stored in a DAT section. For text type
' the section will be a number of byte aligned strings, each with a null
' terminator. For numeric type the section will be a number of long aligned
' longs.
'
'Returns -1 if there are no more free elements in the SPIN object array
' guid on success which is unique and used to identify the specific
' instance of the control.
retVal := -1
repeat idx from 0 to GZ_TBOX - 1
gdx := SPIN[idx].get_gzidx
if gz_elem[gdx] & G_INIT == 0 'is it free
retVal := gdx
gz_elem[gdx] |= G_INIT 'mark it used
SPIN[idx].Init( pRow, pCol, pWidth, pType, pNum, pDataPtr, @scrn, VGACOLS )
quit
return retVal
PUB SPINIsIn( guid ) | odx
' returns true if the mouse is inside the spin control
' false otherwise
odx := gz_elem[guid] & G_OMSK
return SPIN[odx].IsIn( MOUS.bound_x, MOUS.bound_y )
PUB SPINClicked( guid ) | odx
'checks where the mouse click ocurred and returns -1 if not on an UP or DOWN
'arrow otherwise it returns the zero based data index of the currently
'displayed data
odx := gz_elem[guid] & G_OMSK
return SPIN[odx].Clicked( MOUS.bound_x, MOUS.bound_y )
PUB SPINGetDataIndex( guid ) | odx
'returns the zero based index of the currently displayed data item
odx := gz_elem[guid] & G_OMSK
return SPIN[odx].GetDataIndex
CON ''=====< CHECK BOX INTERFACE FUNCTIONS >==================================
PUB CHKBInit( pRow, pCol, pTextWidth, pTextPtr ) | idx, gdx, retVal
'Creates a checkbox box at the specified location.
'Something like:
'
' X Text here
'
' where X is a check box symbol
'
' pRow = row upper location
' pCol = col left location
' pTextWidth = width of button text (MAX 15 characters)
' pTextPtr = checkbox text (MAX 15 characters)
'
'Returns -1 if there are no more free elements in the CHKB object array
' guid on success which is unique and used to identify the specific
' instance of the control.
retVal := -1
repeat idx from 0 to GZ_CHKB - 1
gdx := CHKB[idx].get_gzidx
if gz_elem[gdx] & G_INIT == 0 'is it free
retVal := gdx
gz_elem[gdx] |= G_INIT 'mark it used
CHKB[idx].Init( pRow, pCol, pTextWidth, 0, pTextPtr, @scrn, VGACOLS )
quit
return retVal
PUB CHKBIsIn( guid ) | odx
' returns true if the mouse is inside the check box
' false otherwise
odx := gz_elem[guid] & G_OMSK
return CHKB[odx].IsIn( MOUS.bound_x, MOUS.bound_y )
PUB CHKBDrawText( guid, pMode ) | odx
' pMode 0 = 0 for normal
' = 1 for inverted
odx := gz_elem[guid] & G_OMSK
CHKB[odx].DrawText( pMode )
PUB CHKBSelect( guid, pSel ) | odx
'sel = 1 to select 0 to deselect -1 to toggle it
odx := gz_elem[guid] & G_OMSK
CHKB[odx].Select( pSel )
PUB CHKBIsSet( guid ) | odx
'returns the status of the button (set=true not set=false)
odx := gz_elem[guid] & G_OMSK
return CHKB[odx].isSet
CON ''=====< RADIO BUTTON INTERFACE FUNCTIONS >===============================
PUB RADBInit( pRow, pCol, pTextWidth, pTextPtr, pGroupID ) | idx, gdx, retVal
'Creates a radio button at the specified location.
'Something like:
'
' X Text here
'
' where X is a radio button symbol
'
' pRow = row upper location
' pCol = col left location
' pTextWidth = width of button text (MAX 15 characters)
' pTextPtr = checkbox text (MAX 15 characters)
' pGroupID = the id of the radio button group that this button belongs to
'
'Returns -1 if there are no more free elements in the RADB object array
' guid on success which is unique and used to identify the specific
' instance of the control.
retVal := -1
repeat idx from 0 to GZ_RADB - 1
gdx := RADB[idx].get_gzidx
if gz_elem[gdx] & G_INIT == 0 'is it free
retVal := gdx
gz_elem[gdx] |= G_INIT 'mark it used
RADB[idx].Init( pRow, pCol, pTextWidth, 1, pTextPtr, @scrn, VGACOLS )
gz_groups[idx] := pGroupID 'remember group button belongs to RB_GRP
quit
return retVal
PUB RADBIsIn( guid ) | odx
' returns true if the mouse inside the radio button
' false otherwise
odx := gz_elem[guid] & G_OMSK
return RADB[odx].IsIn( MOUS.bound_x, MOUS.bound_y )
PUB RADBDrawText( guid, pMode ) | odx
' pMode 0 = 0 for normal
' = 1 for inverted
odx := gz_elem[guid] & G_OMSK
RADB[odx].DrawText( pMode )
PUB RADBSelect( guid, pSel ) | odx
'sel = 1 to select 0 to deselect -1 to toggle it
odx := gz_elem[guid] & G_OMSK
RADB[odx].Select( pSel )
PUB RADBIsSet( guid ) | odx
'returns the status of the button (set=true not set=false)
odx := gz_elem[guid] & G_OMSK
return RADB[odx].isSet
CON ''=====< PUSH BUTTON INTERFACE FUNCTIONS >================================
PUB PUSHInit( pRow, pCol, pTextPtr ) | idx, gdx, retVal
'Creates a pushbutton at the specified location.
'Something like:
' ---------------
' |ttttttttttttttt|
' ---------------
'
' where t = button text (MAX 15 characters)
'
' pRow = row upper location
' pCol = col left location
' pTextPtr = push button text (MAX 15 characters + null terminator)
'
'Returns -1 if there are no more free elements in the PUSH object array
' guid on success which is unique and used to identify the specific
' instance of the control.
retVal := -1
repeat idx from 0 to GZ_PUSH - 1
gdx := PUSH[idx].get_gzidx
if gz_elem[gdx] & G_INIT == 0 'is it free
retVal := gdx
gz_elem[gdx] |= G_INIT 'mark it used
PUSH[idx].Init( pRow, pCol, pTextPtr, @scrn, VGACOLS )
quit
return retVal
PUB PUSHIsIn( guid ) | odx
' returns true if the mouse is inside the push button
' false otherwise
odx := gz_elem[guid] & G_OMSK
return PUSH[odx].IsIn( MOUS.bound_x, MOUS.bound_y )
PUB PUSHDrawText( guid, pMode ) | odx
'draws the pusbutton text in normal or inverted video.
' mode bit 0 = 0 for normal
' = 1 for inverted
odx := gz_elem[guid] & G_OMSK
PUSH[odx].DrawText( pMode )
PUB PUSHSetText( guid, pPtr ) | odx
'sets new text for the pushbutton
' pPtr points to the text, it MUST be the same size (or less) as the text
' it is replacing
odx := gz_elem[guid] & G_OMSK
PUSH[odx].SetText( pPtr )
CON ''=====< TEXT BOX INTERFACE FUNCTIONS >===================================
PUB TBOXInit( pRow, pCol, pWidth, pHeight, pWrap, pTitlePtr ) | idx, gdx, retVal
'Creates a box with specified width and text. Something like:
' -------------
' | | - title area ( non-existant if no title supplied)
' -------------
' | |
' | | - text area with optional scolling print capability
' | |
' -------------
'
' pRow = row upper location
' pCol = col left location
' pWidth = width
' pHeight = height
' pWrap = 0 = truncate 1 = wrap lines
' pTitlePtr = title text text (text must be 2 less than width ore 32 MAX)
'
'Returns -1 if there are no more free elements in the TBOX object array
' guid on success which is unique and used to identify the specific
' instance of the control.
'
' NOTE: Columns must be LONG aligned to take advantage of the most efficient
' scrolling (via LONGMOVE). The start column must be on a long boundary
' (multiple of 4) and the width must be a multiple of 4. If print scrolling
' is not required this restriction can be ignored.
retVal := -1
repeat idx from 0 to GZ_TBOX - 1
gdx := TBOX[idx].get_gzidx
if gz_elem[gdx] & G_INIT == 0 'is it free
retVal := gdx
gz_elem[gdx] |= G_INIT 'mark it used
TBOX[idx].Init( pRow, pCol, pWidth, pHeight, pWrap, pTitlePtr, @scrn, VGACOLS )
quit
return retVal
PUB TBOXIsIn( guid ) | odx
' returns true if the mouse is inside the text box text area
' (i.e. excluding title area if there is one)
' false otherwise
odx := gz_elem[guid] & G_OMSK
return TBOX[odx].IsIn( MOUS.bound_x, MOUS.bound_y )
PUB TBOXClear( guid ) | odx
'clears the text box.
odx := gz_elem[guid] & G_OMSK
TBOX[odx].Clear
PUB TBOXPrint( guid, pTxtPtr, pSize ) | odx
'Prints a line of text. Iif already at the last row the existing text is
'scrolled up one line first and the top line is removed. Inverted text is
'written with the high bit of each character set. If line wrap is enabled the
'lines that are wrapped are marked with a preceding inverted right arrow
'character (non-printable Ascii). Leading and trailing CRLF characters are
'stripped out. Any intra line CRLFs are ignored and will display as 'funny'
'characters.
'
' pTxtPtr = pointer to null terminated string
' size = 0 for null terminated strings
' = the string length for non-null terminated strings
odx := gz_elem[guid] & G_OMSK
TBOX[odx].Print( pTxtPtr, pSize )
PUB TBOXScroll( guid ) | odx
'scroll the test area up one line
odx := gz_elem[guid] & G_OMSK
TBOX[odx].Scroll
PUB TBOXTitle( guid, pTxtPtr ) | strIdx, vgaIdx, odx
'replace the original titlebar caption with new text. If no title was declared
'on initialization then this method will do nothing
'
' pTxtPtr = pointer to text to place in titlebar
odx := gz_elem[guid] & G_OMSK
TBOX[odx].Title( pTxtPtr )
CON ''=====< MENU ITEM INTERFACE FUNCTIONS >==================================
PUB MENUInit( pRow, pCol, pTextPtr ) | idx, gdx, retVal
'Creates a menu item at the specified location.
'Something like:
' StttttttttttttttS
'
' where S = space character
' t = character position (MAX 15 characters)
'
' pRow = row upper location
' pCol = col left location
' pTextPtr = menu item text (MAX 15 characters + null terminator)
'
'Returns -1 if there are no more free elements in the MENU object array
' guid on success which is unique and used to identify the specific
' instance of the control.
retVal := -1
repeat idx from 0 to GZ_MENU - 1
gdx := MENU[idx].get_gzidx
if gz_elem[gdx] & G_INIT == 0 'is it free
retVal := gdx
gz_elem[gdx] |= G_INIT 'mark it used
MENU[idx].Init( pRow, pCol, pTextPtr, @scrn, VGACOLS )
quit
return retVal
PUB MENUIsIn( guid ) | odx
' returns true if the mouse is inside the menu item
' false otherwise
odx := gz_elem[guid] & G_OMSK
return MENU[odx].IsIn( MOUS.bound_x, MOUS.bound_y )
PUB MENUDrawText( guid, pMode ) | odx
'draws the menu item text in normal or inverted video.
' mode bit 0 = 0 for normal
' = 1 for inverted
odx := gz_elem[guid] & G_OMSK
MENU[odx].DrawText( pMode )
PUB MENUSetText( guid, pPtr ) | odx
'Place new text on the menu item.
' pPtr points to the text, it MUST be the same size (or less) as the text
' it is replacing
odx := gz_elem[guid] & G_OMSK
MENU[odx].SetText( pPtr )
PUB MENUSetStatus( guid, pStat ) | odx
'set a user defined status BYTE (any value fro 0 to 255)
odx := gz_elem[guid] & G_OMSK
MENU[odx].SetStatus( pStat )
PUB MENUGetStatus( guid ) | odx
'get the use defined status
odx := gz_elem[guid] & G_OMSK
return MENU[odx].GetStatus
CON ''=====< INPUT FIELD INTERFACE FUNCTIONS >================================
PUB INPFInit(pRow, pCol, pWidth, pType, pTitlePtr ) | idx, gdx, retVal
'Creates an input field box with specified width and text. Something like:
' -----------------------
' |Title| input field |
' -----------------------
'
' pRow = row upper location
' pCol = col left location
' pWidth = width of the control in columns
' pType = 0 = standalone 1=tacked on to above
' pHeight = height of the control in rows
' pTitlePtr = title text ( remainder is used for the input field )
'
'Returns -1 if there are no more free elements in the SPIN object array
' guid on success which is unique and used to identify the specific
' instance of the control.
retVal := -1
repeat idx from 0 to GZ_INPF - 1
gdx := INPF[idx].get_gzidx
if gz_elem[gdx] & G_INIT == 0 'is it free
retVal := gdx
gz_elem[gdx] |= G_INIT 'mark it used
INPF[idx].Init( pRow, pCol, pWidth, pType, pTitlePtr, @scrn, VGACOLS )
quit
return retVal
PUB INPFIsIn( guid ) | odx
' returns true if the mouse is inside the input field
' false otherwise
odx := gz_elem[guid] & G_OMSK
return INPF[odx].IsIn( MOUS.bound_x, MOUS.bound_y )
PUB INPFClear( guid ) | odx
'clear the input field
odx := gz_elem[guid] & G_OMSK
INPF[odx].clear
PUB INPFSelect( guid, pSel ) | odx
'pSel = 1 to select 0 to deselect -1 to toggle it
odx := gz_elem[guid] & G_OMSK
INPF[odx].Select( pSel, @cx1, @cy1 )
liveINPF := odx
cm1 := %111 'turn text cursor on, underscore slow blink
PUB INPFGetString( guid, pBuf ) | odx, tmp, str, len
'places the string in the input field into the buffer provided then clears
'the input field.
odx := gz_elem[guid] & G_OMSK
tmp := INPF[odx].GetStringCode
str := ( tmp & $1FFF0000 ) >> 16
len := tmp & $000000FF
bytemove( pBuf, @scrn.byte[str], len )
byte[pBuf][len] := 0
INPFClear( guid )
CON ''=====< STATUS LAMP INTERFACE FUNCTIONS >================================
PUB STATInit( pRow, pCol, pWidth, pTitlePtr ) | idx, gdx, retVal
'Creates a status lamp with specified width and text. Something like:
'
' Title : XXXX
'
' where XXXX is user supplied condition status
'
' pRow = row upper location
' pCol = col left location
' pWidth = width of the control in columns
' pHeight = height of the control in rows
' pTitlePtr = title text text (text must be 7 less than width )
'
'Returns -1 if there are no more free elements in the SPIN object array
' guid on success which is unique and used to identify the specific
' instance of the control.
retVal := -1
repeat idx from 0 to GZ_STAT - 1
gdx := STAT[idx].get_gzidx
if gz_elem[gdx] & G_INIT == 0 'is it free
retVal := gdx
gz_elem[gdx] |= G_INIT 'mark it used
STAT[idx].Init( pRow, pCol, pWidth, pTitlePtr, @scrn, VGACOLS )
quit
return retVal
PUB STATIsIn( guid ) | odx
' returns true if the mouse is inside the menu item
' false otherwise
odx := gz_elem[guid] & G_OMSK
return STAT[odx].IsIn( MOUS.bound_x, MOUS.bound_y )
PUB STATSet( guid, pSet, pStrPtr ) | odx
'pSet = 0 = off mode (uses normal video)
' 1 = on mode (uses inverted video)
'pStr = pointer to status string (4 chars max)
odx := gz_elem[guid] & G_OMSK
STAT[odx].Set( pSet, pStrPtr )
PUB STATGetStatus( guid ) | odx
'returns the current status of the object (1=on 0=off)
odx := gz_elem[guid] & G_OMSK
return STAT[odx].GetStatus
CON ''===== START OF VGA HIGH RES TEXT SCREEN FUNCTIONS ======================
PUB PrintStr( prRow, prCol, strPtr, inv ) | strLen, vgaIdx, idx
'this places text anywhere on the screen and can overwrite UI elements
'
' prRow = row
' prCol = column
' strPtr = pointer to null terminated string
' inv = 0 for normal 1 for inverted video
if ( prRow < VGAROWS ) AND ( prCol < VGACOLS )
strLen := strsize( strPtr )
vgaIdx := prRow * VGACOLS + prCol
bytemove( @scrn.byte[vgaIdx], strPtr, strLen )
if inv
repeat idx from 1 to strLen
byte[@scrn][vgaIdx] += 128
vgaIdx++
PUB ClearScreen( ForeClr, BackClr ) | wdClr
' This clears the whole screen and sets all rows to the given colours
' ForeClr and BackClr are best represented as quaternary numbers (base 4)
' - these are represented as %%RGB where there are 4 levels for each ( R, G, B)
' - thus entering %%003 is brightest Green
wdClr := BackClr << 10 + ForeClr << 2
LONGFILL( @scrn, $20202020, VGACOLS*VGAROWS/4 ) '4 space characters in long
WORDFILL( @colors, wdClr, VGAROWS )
PUB SetLineColor( line, ForeClr, BackClr ) | wdClr
' This sets a single row to the given colours
' ForeClr and BackClr are best represented as quaternary numbers (base 4)
' - these are represented as %%RGB where there are 4 levels for each ( R, G, B)
' - thus entering %%003 is brightest Green
if line < VGAROWS
wdClr := BackClr << 10 + ForeClr << 2
colors[line] := wdClr
{{
┌────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy│
│of this software and associated documentation files (the "Software"), to │
│deal in the Software without restriction, including without limitation the │
│rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │
│sell copies of the Software, and to permit persons to whom the Software is │
│furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in │
│all copies or substantial portions of the Software. │
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
│IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
│FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
│AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
│LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │
│FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS│
│IN THE SOFTWARE. │
└────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,582 @@
CON 'Dokumentation, Lizenz
''***********************************/*********
''* VGA High-Res Text UI Elements Demo v1.2 *
''* *
''* File: GUIDemo.spin *
''* Author: Allen Marincak *
''* Copyright (c) 2009 Allen Marincak. *
''* See end of file for terms of use. *
''* *
''* Parts are from a demo by Chip Gracey *
''* Copyright (c) 2006 Parallax, Inc. *
''* Under the same MIT license *
''* ( see end of file ) *
''*********************************************
'
' Notes on the VGA High Res Driver from Chip Gracey's Demo program.
' ----------------------------------------------------------------------------
'
' 3 June 2006
'
' This program (a quick piece of junk) demonstrates the VGA_HIRES_TEXT
' object. It is meant for use on the Propeller Demo Board Rev C. You can
' plug in a mouse for screen action. The mouse driver has been upgraded
' to provided bounded mouse coordinates. This makes constrained and
' scaled mouse movement mindless.
'
' The VGA_HIRES_TEXT went through much metamorphosis before completion.
' Initially, it ran on five COGs! I thought this was a miracle, since I
' didn't think we'd be able to get such high-res displays on the current
' Propeller chip. It used four COGs to build scan lines, and a fifth COG
' to display them. I kept looking at the problem and realized that it
' all came down to how little monkeying could be done with the data in
' order to display it. The scan line building was reorganized so that a
' single RDLONG picks up four lines worth of pixels for a character, and
' then buffers them within the COG, to later output them with back-to-
' back 'WAITVID color,pixels' and 'SHR pixels,#8' instruction sequences.
' This was so much faster that only two COGs were required for the job!
' They had to be synchronized so that they could step seamlessly into
' eachother's shoes as they traded the tasks of building scan lines and
' then displaying them. Anyway, it all came together nicely.
' Note that the driver has different VGA mode settings which you can de-
' comment and try. Also, the driver contains its own font. You will see
' the character set printed out when you run the program. There are some
' characters within the font that provide quarter-character-cell block
' pixels (for 128x64 characters, you can get 256x128 'pixels'). They can
' be used for graphing or crude picture drawing, where text can be inter-
' mingled.
'
' If you have a 15" LCD monitor, you must see the 1024x768 mode on it.
' At least on my little Acer AL1511 monitor, every pixel locks perfectly.
'
'-----------------------------------------------------------------------------
'
' Allen Marincak Feb 2009 Demo program Notes
'
' Chip states above that this demo is for use on the Propeller Demo Board. It
' will however work on any Propeller board with VGA and Mouse driver
' functionality.
'
' The info above was from the VGA_HiRes_Text demo program Chip Gracey wrote.
' There is nothing of consequence left here of that file but the VGA Driver
' driver itself remains intact. *This* demo is setup to show how to use some
' very simple text based graphical user interface elements written for the VGA
' HiRes Text mode. It is an ultra trivial implementation, with virtually no
' error checking so heads up! I did this on purpose to keep it lean. After the
' VGA driver uses some 6K to 10K bytes of memory and 2 cogs to display text I
' did not want to use up most of the rest of the memory with a boatload of
' error checking and a fancier UI on its own COG. I opted to leave as much
' memory as possible for applications that could benefit from cheap and simple
' buttons, menus, text panels and such. Especially since one needs the Mouse
' and Keyboard drivers as well, each of these take up 1 more COG. After loading
' those drivers and creating 10 or so UI elements you will have 2/3 to 1/2 of
' available memory left for your application (depending on VGA Resolution
' desired, I tend to use 800x600 as a good compromise between memory and real
' estate).
'
' There are several UI elements implemented, you stitch together what you need
' and lay it out how you want to use it. There are 9 objects (well 8, the Radio
' Button and Check Box objects are both from the RadioCheck.spin object), and
' some glue functions in the package (in GUIBase.spin). The UI elements are
' rudimentary and lean but provide adequate funtionality for many control and
' monitoring applications. I did not implement repositioning the items, any
' buffering of data in text boxes, pop-up windows or drop down lists, etc.
' These would just use up more memory and I was after a simple light-weight
' (thereby static) UI to provide simple control and feedback for some of my
' projects.
'
'
' SimpleBox.spin
' - draws boxes in the area specified, with or without a "title bar"
' - useful to visually group and organize other control
'
' RadioCheck.spin
' - creates Check Box and Radio Button controls
'
' TextBox.spin
' - creates simple text windows controls that are line based.
' - truncates or wraps lines into the window pane
' - optional (but useful) titlebar avaiable
'
' MenuItem.spin
' - simple text "button" that to create a rudimentary menubar.
'
' PushButton.spin
' - creates a straightforward pushbutton
'
' InputField.spin
' - creates a one line input field with a caption / title. There is only
' simple editing via backspace.
' - keyboard input focus can be switched between controls on the fly with
' mouse click
'
' SpinBox.spin
' - created straight forward spin button controls
'
' StatusLamp.spin
' - a simple annunciator 'lamp' for condition feedback
'
' GUIBase.spin
' - This is actually the main interface to the GUI objects
' - you call functions here, not in the object files themselves
' - GUI initialization and processing is done with functions here
' - Init() starts VGA, Mouse, and Keyboard drivers and initializes
' data structures used by the UI
' - ProcessUI() manages the UI infrastructure you must call this in
' your main loop regularly for a responsive UI. It
' returns ID of elements that require actionm (i.e.
' the mouse was clicked on a Push Button, etc).
'
' Memory requirements with UI
' - 1/3 to 1/2 of RAM depending on VGA resolution
'
' COGS used
' - the UI does not use a new COG it runs out of the main app's COG.
' - 2 COGS for the High Res VGA Text driver
' - 1 COG for the Mouse Driver
' - 1 COG for the Keyboard Driver (optional, for Input Field Object only)
'
'-----------------------------------------------------------------------------
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
vga_base = 8 'VGA - VSync
mouse_dat = 19 'MOUSE data
mouse_clk = 18 'MOUSE clock
keyboard_dat = 17 'KEYBOARD data
keyboard_clk = 16 'KEYBOARD clock
OBJ
'---------------------------------------------------------------------------
' UI element objects YOU NEED THIS
'---------------------------------------------------------------------------
GUI : "GUIBase" 'starts VGA, Mouse, & Keyboard drivers
'---------------------------------------------------------------------------
' Auxiliary objects (these are just used in the demo app only)
'---------------------------------------------------------------------------
TMRS : "Timer"
NUMS : "simple_numbers"
VAR
'---------------------------------------------------------------------------
' UI element IDs YOU MUST HAVE THESE to remember the GUI ID's (guid) of the
' elements you create. In this demo APP there are 29 items,
' your application will have more or fewer (as required).
' These are returned by the element Init() calls
' ( i.e. CHKB1 := GUI.CHKBInit(..) )
'---------------------------------------------------------------------------
byte CHKB1
byte CHKB2
byte CHKB3
byte CHKB4
byte RADB1
byte RADB2
byte RADB3
byte RADB4
byte RADB5
byte RADB6
byte TBOX1
byte TBOX2
byte TBOX3
byte MENU1
byte MENU2
byte MENU3
byte MENU4
byte MENU5
byte MENU6
byte INPF1
byte INPF2
byte INPF3
byte PUSH1
byte PUSH2
byte PUSH3
byte STAT1
byte STAT2
byte SPIN1
byte SPIN2
'---------------------------------------------------------------------------
' Screen Geometry returned by call to GUI.Init() (may be useful)
'---------------------------------------------------------------------------
byte vga_rows, vga_cols
'---------------------------------------------------------------------------
' variables used by local main loop processing, not required by library
' functions. You can get rid of these when creating your own app.
'---------------------------------------------------------------------------
long cnt1 'line counter for textbox 1
long cnt2 'line counter for textbox 2
long clrCnt 'clear textbox counter
long random 'random number seed
long logging 'logging flag
byte strBuf[36]
byte strBuf2[64]
PUB start | gx, tmr1, tmr2, idx, str, tmp
'---------------------------------------------------------------------------
'Some houskeeping ... timers and "logging" status
'This TIMER object started here is used for this demo only. It is used to
'periodically trigger printing to text boxes to simulate "live text" comming
'in. It is not needed by the UI stuff and you don't need it in your program
'unless you want a timer object to do timed activity. Note that it uses a
'separate COG (so it is not cheap).
'---------------------------------------------------------------------------
TMRS.start( 10 ) 'start timer object (1/10 sec timer)
tmr1 := TMRS.register 'register 2 timers
tmr2 := TMRS.register
logging := 1 'logging is on to start
'---------------------------------------------------------------------------
' Create the UI
'---------------------------------------------------------------------------
CreateUI
'---------------------------------------------------------------------------
'some final non UI related houskeeping ...
'---------------------------------------------------------------------------
TMRS.set( tmr1, 10 ) 'start 1 second timeout
TMRS.set( tmr2, 17 ) 'start 1.7 second timeout
'---------------------------------------------------------------------------
' Everything is setup, now the MAIN LOOP begins ...
'---------------------------------------------------------------------------
repeat
gx := GUI.ProcessUI 'process the UI
case gx 'handle GUI Events ( Mouse click or Enter Key in Input Field )
CHKB1: UserDoSomethingFunction( gx )
CHKB2: UserDoSomethingFunction( gx )
CHKB3: UserDoSomethingFunction( gx )
CHKB4: UserDoSomethingFunction( gx )
RADB1: UserDoSomethingFunction( gx )
RADB2: UserDoSomethingFunction( gx )
RADB3: UserDoSomethingFunction( gx )
RADB4: UserDoSomethingFunction( gx )
RADB5: UserDoSomethingFunction( gx )
RADB6: UserDoSomethingFunction( gx )
MENU1: DoMenu1Action
MENU2: DoMenu2Action
MENU3: DoMenu3Action
MENU4: DoMenu4Action
MENU5: DoMenu5Action
MENU6: DoMenu6Action
PUSH1: UserDoSomethingFunction( gx )
PUSH2: UserDoSomethingFunction( gx )
PUSH3: UserDoSomethingFunction( gx )
SPIN1: UserDoSomethingFunction( gx )
SPIN2: UserDoSomethingFunction( gx )
INPF1: DoInputFieldAction( INPF1 )
INPF2: DoInputFieldAction( INPF2 )
INPF3: DoInputFieldAction( INPF3 )
'----------------------------------------------------------------------
'user application code goes here or after the ProcessUI call (but still
'within the REPEAT loop!).
'----------------------------------------------------------------------
idx := GUI.GetMouseXY
GUI.PrintStr( vga_rows-1, 15, NUMS.decf( idx >> 8, 2 ), 0 )
GUI.PrintStr( vga_rows-1, 20, NUMS.decf( idx & $FF, 2 ), 0 )
if TMRS.isClr( tmr2 ) 'if timer 2 expired write line text into textbox 2
TMRS.set( tmr2, 17 )
cnt2++
bytemove( @strBuf, string( "Text # " ), 7 )
str := NUMS.dec( cnt2 )
tmp := strsize( str ) + 1
bytemove( @strBuf[7], str, tmp )
GUI.TBOXPrint( TBOX2, @strBuf, 0 )
if logging == 1
if TMRS.isClr( tmr1 ) 'if timer 1 expired write line text into textbox 1
TMRS.set( tmr1, 10 )
cnt1++
bytemove( @strBuf, string( "This is line number " ), 20 )
str := NUMS.dec( cnt1 )
tmp := strsize( str ) + 1
bytemove( @strBuf[20], str, tmp )
GUI.TBOXPrint( TBOX1, @strBuf, 0 )
CON ''=====< START OF UI HELPER FUNTIONS >==================================
PRI CreateUI | tmp
'You create this function to create your GUI.
'
'This function is called during startup to create and position the UI elements
'that you will use. The total number of UI elements of each type must be
'declared in the OBJ section (i.e. if you need 5 pushbuttons, delcare an array
'of 5 pushbutton objects).
'---------------------------------------------------------------------------
'Initialize GUI, starts VGA, Mouse, and Keyboard Drivers
'
'YOU MUST DO THIS FIRST (saving screen geometry is optional)
'---------------------------------------------------------------------------
tmp := GUI.Init(vga_base, mouse_dat, mouse_clk, keyboard_dat, keyboard_clk )
vga_rows := ( tmp & $0000FF00 ) >> 8
vga_cols := tmp & $000000FF
'---------------------------------------------------------------------------
'setup screen colours
'---------------------------------------------------------------------------
GUI.ClearScreen( %%020, %%000 ) 'green on black each is %%RGB 4 levels per R-G-B
GUI.SetLineColor( 0, %%000, %%333 ) 'Menu Area colour Line 1
GUI.SetLineColor( 1, %%000, %%333 ) 'Menu Area colour Line 2
GUI.SetLineColor( 2, %%000, %%333 ) 'Menu Area colour Line 3
repeat tmp from 3 to vga_rows-16
GUI.SetLineColor( tmp, %%111, %%333 ) 'Console Window colour
repeat tmp from vga_rows-15 to vga_rows-2
GUI.SetLineColor( tmp, %%111, %%333 ) 'Console Window colour
GUI.SetLineColor(vga_rows-1,%%111,%%333) 'Status Line colour
'---------------------------------------------------------------------------
'put up some menu items
'---------------------------------------------------------------------------
GUI.SBOXInit( 0, 0, vga_cols, 3, 0 ) 'menu group box
MENU1 := GUI.MENUInit(1, 3,string(" Open Port ")) 'Menu Items setup
MENU2 := GUI.MENUInit(1,19,string("Stop Logging"))
MENU3 := GUI.MENUInit(1,35,string("New Text Box"))
MENU4 := GUI.MENUInit(1,51,string("Chk Battery "))
MENU5 := GUI.MENUInit(1,67,string("Read Sensors"))
MENU6 := GUI.MENUInit(1,83,string(" Clear Log "))
GUI.MENUSetStatus( MENU2, logging )
'---------------------------------------------------------------------------
'put up some check boxes
'---------------------------------------------------------------------------
GUI.SBOXInit( 11, 4, 18, 8, string("Terminal")) 'checkbox group box
CHKB1 := GUI.CHKBInit( 14, 6, 12, string( "7-bit ASCII" ) )
CHKB2 := GUI.CHKBInit( 15, 6, 12, string( "Show Cursor" ) )
CHKB3 := GUI.CHKBInit( 16, 6, 12, string( "Local Echo" ) )
CHKB4 := GUI.CHKBInit( 17, 6, 12, string( "Append LF" ) )
GUI.CHKBSelect( CHKB3, 1 ) 'select this one as the group's startup default
'---------------------------------------------------------------------------
'put up some radio buttons
'---------------------------------------------------------------------------
GUI.SBOXInit( 20, 4, 18, 10, string("Baud Rate")) 'radio button group box
RADB1 := GUI.RADBInit( 23, 6, 11, string( "115200" ), 0 )
RADB2 := GUI.RADBInit( 24, 6, 11, string( "57600 " ), 0 )
RADB3 := GUI.RADBInit( 25, 6, 11, string( "19200 " ), 0 )
RADB4 := GUI.RADBInit( 26, 6, 11, string( "9600 " ), 0 )
RADB5 := GUI.RADBInit( 27, 6, 11, string( "4800 " ), 0 )
RADB6 := GUI.RADBInit( 28, 6, 11, string( "1200 " ), 0 )
GUI.RADBSelect( RADB4, 1 ) 'select this one as the group's startup default
'---------------------------------------------------------------------------
'put up some status lamps
'---------------------------------------------------------------------------
GUI.SBOXInit( 4,4,18,6,string("Status") ) 'status lamp group box
STAT1 := GUI.STATInit( 7,6, 14, string( "Logging" ) )
STAT2 := GUI.STATInit( 8,6, 14, string( " Port" ) )
GUI.STATSet( STAT1, 1, string("ON") )
GUI.STATSet( STAT2, 0, string("OFF") )
'---------------------------------------------------------------------------
'put up some text boxes, one without a title
'---------------------------------------------------------------------------
TBOX1 := GUI.TBOXInit( 4,28,36,26,1,string("Logging Window") )
TBOX2 := GUI.TBOXInit(10,70,24,20,1,0 )
TBOX3 := GUI.TBOXInit(vga_rows-25,4,90,22,1,string("Console Window") )
cnt1 := 0 'line counter for textbox 1
cnt2 := 0 'line counter for textbox 2
clrCnt := 0 'clear textbox counter
random := 0 'random number seed
'---------------------------------------------------------------------------
'put up a couple of input fields
'---------------------------------------------------------------------------
INPF1 := GUI.INPFInit( 4, 70, 24, 0, string("Speed") )
INPF2 := GUI.INPFInit( 31, 4, 60, 0, string("Message") )
INPF3 := GUI.INPFInit( vga_rows-4, 4, 90, 1, string("Command") )
GUI.INPFSelect( INPF3, 1 )
'---------------------------------------------------------------------------
'put up some push buttons
'---------------------------------------------------------------------------
PUSH1 := GUI.PUSHInit( 7, 70, string( "Slower" ) )
PUSH2 := GUI.PUSHInit( 7, 78, string( " Stop " ) )
PUSH3 := GUI.PUSHInit( 7, 86, string( "Faster" ) )
'---------------------------------------------------------------------------
'put up some spin buttons
'---------------------------------------------------------------------------
SPIN1 := GUI.SPINInit( 31, 70, 24, 0, 4, @SpinDat0 ) 'languages
SPIN2 := GUI.SPINInit( 34, 70, 24, 1, 10, @SpinDat1 ) 'log scale
'---------------------------------------------------------------------------
'Put something in the status bar (just the mouse coordinates in this demo)
'---------------------------------------------------------------------------
GUI.PrintStr(vga_rows-1,0,string( "Status Line: X=xx Y=xx" ), 0 )
PRI UserDoSomethingFunction( val ) ' - USER ACTION FUNCTION
'this is a dummy ... in a real app the user would have one of these for each
'UI action that required some activity. For this Demo where the user would
'normally call their own function I just call this dummy placeholder instead.
GUI.TBOXPrint( TBOX3, string( "Normally a user function would be called." ), 0 )
return val
PRI DoMenu1Action | mStat
mStat := GUI.MENUGetStatus( MENU1 ) 'get current user status of menu item
if mStat == 0
GUI.TBOXPrint( TBOX3, string( "Opened port."), 0 ) 'announce activity to console window
GUI.MENUSetText( MENU1, string( "Close Port" ) ) 'change the menu item text
GUI.MENUSetStatus( MENU1, 1 ) 'set new status of the menu item
GUI.STATSet( STAT2, 1, string("OPEN") ) 'set status lamp ON
else
GUI.TBOXPrint( TBOX3, string( "Closed port." ), 0 ) 'announce activity to console window
GUI.MENUSetText( MENU1, string( " Open Port" ) ) 'change the menu item text
GUI.MENUSetStatus( MENU1, 0 ) 'set new status of the menu item
GUI.STATSet( STAT2, 0, string("OFF") ) 'set status lamp OFF
PRI DoMenu2Action | mStat
mStat := GUI.MENUGetStatus( MENU2 ) 'get current user status of menu item
if mStat == 0
GUI.TBOXPrint( TBOX3, string("Started Logging."),0) 'announce activity to console window
GUI.MENUSetText( MENU2, string( "Stop Logging" )) 'change the menu item text
GUI.MENUSetStatus( MENU2, 1 ) 'set new status of the menu item
GUI.STATSet( STAT1, 1, string("ON") ) 'set status lamp ON
logging := 1
else
GUI.TBOXPrint(TBOX3,string("Stopped logging." ),0) 'announce activity to console window
GUI.MENUSetText( MENU2, string( " Log Data " ) ) 'change the menu item text
GUI.MENUSetStatus( MENU2, 0 ) 'set new status of the menu item
GUI.STATSet( STAT1, 0, string("OFF") ) 'set status lamp OFF
logging := 0
PRI DoMenu3Action
GUI.TBOXPrint( TBOX1, @longstring, 0 )
GUI.TBOXPrint( TBOX2, @longstring, 0 )
GUI.SBOXInit( 12, 36, 14, 10, string("New Text Box")) 'create new simple box
PRI DoMenu4Action | rnd
rnd := ?random / 100_000_000
rnd *= rnd 'formulate a random number
bytemove( @strbuf, string( "Battery = 9." ), 12 )
bytemove( @strbuf[12], NUMS.decx( rnd, 3 ), 3 )
bytemove( @strbuf[15], string( " vdc." ), 4 )
strbuf[19] := 0
GUI.TBOXPrint(TBOX3, @strbuf, 0 ) 'display 'voltage' in console window
PRI DoMenu5Action
GUI.TBOXPrint(TBOX3,string("Sensors are not ready."),0) 'announce activity to console window
PRI DoMenu6Action | tmp
GUI.TBOXClear( TBOX1 ) 'ACTION: clear the text box
bytemove(@strBuf,string("Logging Window Cleared "),24) 'create new text box title
clrCnt++
bytemove(@strBuf[24],NUMS.decf(clrCnt,3),3) 'tack on cleared count
tmp := 16
repeat while strBuf[tmp] <> 0 'make cleared count text inverted
strBuf[tmp++] += 128
GUI.TBOXTitle( TBOX1, @strBuf ) 'put new title in text box
PRI DoInputFieldAction( guid )
GUI.INPFGetString( guid, @strBuf2 )
GUI.TBOXPrint(TBOX3, @strbuf2, 0 ) 'display 'voltage' in console window
DAT
longstring byte 13,10,"This is a long string. It will take up ",13,10,"several lines. The leading and trailing CRLF should be stripped off but not the one inside the string.",13,10,0
'-----------------------------------------------------------------------------
'Data for the spin buttons. Text type spin buttons will have an array of null
'terminated stings here. Numeric type spin buttons will have an array of long
'values.
'-----------------------------------------------------------------------------
SpinDat0 byte "English",0
byte "French",0
byte "Spanish", 0
byte "Slovak", 0
SpinDat1 long 1,2,5,10,20,50,100,200,500,1000
{{
┌────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy│
│of this software and associated documentation files (the "Software"), to │
│deal in the Software without restriction, including without limitation the │
│rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │
│sell copies of the Software, and to permit persons to whom the Software is │
│furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in │
│all copies or substantial portions of the Software. │
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
│IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
│FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
│AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
│LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │
│FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS│
│IN THE SOFTWARE. │
└────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,194 @@
'' ===========================================================================
'' VGA High-Res Text UI Elements Base UI Support Functions v1.2
''
'' File: InputField.spin
'' Author: Allen Marincak
'' Copyright (c) 2009 Allen MArincak
'' See end of file for terms of use
'' ===========================================================================
''
''============================================================================
'' Simple Keyboard Input Handler
''============================================================================
''
'' Creates a simple one line input field. The input field manages characters
'' from the keyboard. The contol was designed for simple commands or value
'' entry. The only editing is via the backspace key. The enter key signals
'' completion and it is up to the calling application to do as required with
'' the input.
OBJ
SBOX : "SimpleBox"
VAR
word varGdx 'GUI control variable
long varVgaPos 'screen location of start of input area
long varScreenPtr 'screen buffer pointer
long varCxPtr 'points to the text cursor x position variable
byte varRow 'top row location
byte varCol 'left col location
byte varCol2 'right col location
byte varWidth 'width ... text width is 2 less than total width
byte varTitleWidth 'number of rows used for title area ( 0 or 2 )
byte varStatus '0 = unselected 1 = selected
byte varColIdx 'index to current col to be written
byte varCursorCol 'column the text cursor is in
byte varVgaCols 'width of screen in columns
PUB Init ( pRow, pCol, pWidth, pType, pTitlePtr, pVgaPtr, pVgaWidth ) | vgaIdx
varVgaCols := pVgaWidth
varRow := pRow
varCol := pCol
varWidth := pWidth
varTitleWidth := strsize( pTitlePtr )
varColIdx := 0
varScreenPtr := pVgaPtr
varCol2 := varCol + varWidth
varCxPtr := 0
varCursorCol := varCol + varTitleWidth + varColIdx + 2
SBOX.DrawBox( pRow, pCol, pWidth, 3, 0, pVgaPtr, pVgaWidth )
vgaIdx := varRow * varVgaCols + varCol
if pType == 1
byte[varScreenPtr][vgaIdx] := 18 'left 'tee' char
byte[varScreenPtr][vgaIdx+pWidth-1] := 19 'right 'tee' char
vgaIdx += varTitleWidth + 1
byte[varScreenPtr][vgaIdx] := 16 'top 'tee' char
vgaIdx += varVgaCols
byte[varScreenPtr][vgaIdx] := 15 'vertical line char
vgaIdx += varVgaCols
byte[varScreenPtr][vgaIdx] := 17 'bottom 'tee' char
vgaIdx -= ( varVgaCols + varTitleWidth )
bytemove( @byte[varScreenPtr][vgaIdx], pTitlePtr, varTitleWidth )
varVgaPos := (varRow+1)*varVgaCols+varCol+2+varTitleWidth 'save input area start
PUB Handler( pKeyCode ) | retVal, vgaIdx
'Handles key codes for a basic one line input field intended for simple data
'or commands (it is not a text editor :-)). The control uses the screen as a
'buffer so no extra memory is required to pass back the data to the caller.
'When the user presses enter a return value is bitfield encoded containing
'the address and size of the text entered. The caller then must get or use the
'data entered and then call the CLEAR method to reset the input field.
'
' returns 0 = ok, no action required
' 1 = not selected
' MSB set = enter pressed, caller to read string and clear field
' Returned word is bitfield encoded to return the address
' and size of the string entered. Encoded as follows:
' %100a_aaaa_aaaa_aaaa_0000_0000_ssss_ssss
' a = 13bit address s = 8 bit size
'
retVal := 0
vgaIdx := varVgaPos + varColIdx
if varStatus == 0
retVal := 1
else
case pKeyCode
$20 .. $7E: 'standard ASCII characters
if varColIdx < varWidth - 3 - varTitleWidth
byte[varScreenPtr][vgaIdx] := pKeyCode
varColIdx++
varCursorCol++
byte[varCxPtr][0] := varCursorCol 'move text cursor
$0D: 'carriage return
retval := $80000000 ' set MSB
$C8: 'backspace
if ( varColIdx )
vgaIdx--
varColIdx--
varCursorCol--
byte[varScreenPtr][vgaIdx] := " "
byte[varCxPtr][0] := varCursorCol 'move text cursor
return retVal
PUB IsIn( pCx, pCy ) | retVal
retVal := false
if ( pCx => varCol ) AND ( pCx =< varCol2 )
if pCy == varRow + 1
retVal := true
return retVal
PUB clear
bytefill( @byte[varScreenPtr][varVgaPos], 32, varWidth - varTitleWidth - 3 )
varColIdx := 0
varCursorCol := varCol + varTitleWidth + varColIdx + 2
byte[varCxPtr][0] := varCursorCol 'move text cursor
PUB Select( pSel, pCxPtr, pCyPtr )
if pSel <> -1
varStatus := pSel
else
if varStatus == 0
varStatus := 1
else
varStatus := 0
if varStatus == 1
varCxPtr := pCxPtr
byte[varCxPtr][0] := varCursorCol
byte[pCyPtr][0] := varRow + 1
PUB GetStringCode | retval
retval := varVgaPos << 16 ' encode address
retval |= $80000000 ' set MSB
retval += varColIdx ' set size
return retval
PUB set_gzidx( gzidx )
varGdx := gzidx
PUB get_gzidx
return varGdx
{{
┌────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy│
│of this software and associated documentation files (the "Software"), to │
│deal in the Software without restriction, including without limitation the │
│rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │
│sell copies of the Software, and to permit persons to whom the Software is │
│furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in │
│all copies or substantial portions of the Software. │
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
│IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
│FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
│AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
│LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │
│FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS│
│IN THE SOFTWARE. │
└────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,736 @@
''***************************************
''* PS/2 Keyboard Driver v1.0.1 *
''* Author: Chip Gracey *
''* Copyright (c) 2004 Parallax, Inc. *
''* See end of file for terms of use. *
''***************************************
{-----------------REVISION HISTORY-----------------
v1.0.1 - Updated 6/15/2006 to work with Propeller Tool 0.96}
VAR
long cog
long par_tail 'key buffer tail read/write (19 contiguous longs)
long par_head 'key buffer head read-only
long par_present 'keyboard present read-only
long par_states[8] 'key states (256 bits) read-only
long par_keys[8] 'key buffer (16 words) read-only (also used to pass initial parameters)
PUB start(dpin, cpin) : okay
'' Start keyboard driver - starts a cog
'' returns false if no cog available
''
'' dpin = data signal on PS/2 jack
'' cpin = clock signal on PS/2 jack
''
'' use 100-ohm resistors between pins and jack
'' use 10K-ohm resistors to pull jack-side signals to VDD
'' connect jack-power to 5V, jack-gnd to VSS
''
'' all lock-keys will be enabled, NumLock will be initially 'on',
'' and auto-repeat will be set to 15cps with a delay of .5s
okay := startx(dpin, cpin, %0_000_100, %01_01000)
PUB startx(dpin, cpin, locks, auto) : okay
'' Like start, but allows you to specify lock settings and auto-repeat
''
'' locks = lock setup
'' bit 6 disallows shift-alphas (case set soley by CapsLock)
'' bits 5..3 disallow toggle of NumLock/CapsLock/ScrollLock state
'' bits 2..0 specify initial state of NumLock/CapsLock/ScrollLock
'' (eg. %0_001_100 = disallow ScrollLock, NumLock initially 'on')
''
'' auto = auto-repeat setup
'' bits 6..5 specify delay (0=.25s, 1=.5s, 2=.75s, 3=1s)
'' bits 4..0 specify repeat rate (0=30cps..31=2cps)
'' (eg %01_00000 = .5s delay, 30cps repeat)
stop
longmove(@par_keys, @dpin, 4)
okay := cog := cognew(@entry, @par_tail) + 1
PUB stop
'' Stop keyboard driver - frees a cog
if cog
cogstop(cog~ - 1)
longfill(@par_tail, 0, 19)
PUB present : truefalse
'' Check if keyboard present - valid ~2s after start
'' returns t|f
truefalse := -par_present
PUB key : keycode
'' Get key (never waits)
'' returns key (0 if buffer empty)
if par_tail <> par_head
keycode := par_keys.word[par_tail]
par_tail := ++par_tail & $F
PUB getkey : keycode
'' Get next key (may wait for keypress)
'' returns key
repeat until (keycode := key)
PUB newkey : keycode
'' Clear buffer and get new key (always waits for keypress)
'' returns key
par_tail := par_head
keycode := getkey
PUB gotkey : truefalse
'' Check if any key in buffer
'' returns t|f
truefalse := par_tail <> par_head
PUB clearkeys
'' Clear key buffer
par_tail := par_head
PUB keystate(k) : state
'' Get the state of a particular key
'' returns t|f
state := -(par_states[k >> 5] >> k & 1)
DAT
'******************************************
'* Assembly language PS/2 keyboard driver *
'******************************************
org
'
'
' Entry
'
entry movd :par,#_dpin 'load input parameters _dpin/_cpin/_locks/_auto
mov x,par
add x,#11*4
mov y,#4
:par rdlong 0,x
add :par,dlsb
add x,#4
djnz y,#:par
mov dmask,#1 'set pin masks
shl dmask,_dpin
mov cmask,#1
shl cmask,_cpin
test _dpin,#$20 wc 'modify port registers within code
muxc _d1,dlsb
muxc _d2,dlsb
muxc _d3,#1
muxc _d4,#1
test _cpin,#$20 wc
muxc _c1,dlsb
muxc _c2,dlsb
muxc _c3,#1
mov _head,#0 'reset output parameter _head
'
'
' Reset keyboard
'
reset mov dira,#0 'reset directions
mov dirb,#0
movd :par,#_present 'reset output parameters _present/_states[8]
mov x,#1+8
:par mov 0,#0
add :par,dlsb
djnz x,#:par
mov stat,#8 'set reset flag
'
'
' Update parameters
'
update movd :par,#_head 'update output parameters _head/_present/_states[8]
mov x,par
add x,#1*4
mov y,#1+1+8
:par wrlong 0,x
add :par,dlsb
add x,#4
djnz y,#:par
test stat,#8 wc 'if reset flag, transmit reset command
if_c mov data,#$FF
if_c call #transmit
'
'
' Get scancode
'
newcode mov stat,#0 'reset state
:same call #receive 'receive byte from keyboard
cmp data,#$83+1 wc 'scancode?
if_nc cmp data,#$AA wz 'powerup/reset?
if_nc_and_z jmp #configure
if_nc cmp data,#$E0 wz 'extended?
if_nc_and_z or stat,#1
if_nc_and_z jmp #:same
if_nc cmp data,#$F0 wz 'released?
if_nc_and_z or stat,#2
if_nc_and_z jmp #:same
if_nc jmp #newcode 'unknown, ignore
'
'
' Translate scancode and enter into buffer
'
test stat,#1 wc 'lookup code with extended flag
rcl data,#1
call #look
cmp data,#0 wz 'if unknown, ignore
if_z jmp #newcode
mov t,_states+6 'remember lock keys in _states
mov x,data 'set/clear key bit in _states
shr x,#5
add x,#_states
movd :reg,x
mov y,#1
shl y,data
test stat,#2 wc
:reg muxnc 0,y
if_nc cmpsub data,#$F0 wc 'if released or shift/ctrl/alt/win, done
if_c jmp #update
mov y,_states+7 'get shift/ctrl/alt/win bit pairs
shr y,#16
cmpsub data,#$E0 wc 'translate keypad, considering numlock
if_c test _locks,#%100 wz
if_c_and_z add data,#@keypad1-@table
if_c_and_nz add data,#@keypad2-@table
if_c call #look
if_c jmp #:flags
cmpsub data,#$DD wc 'handle scrlock/capslock/numlock
if_c mov x,#%001_000
if_c shl x,data
if_c andn x,_locks
if_c shr x,#3
if_c shr t,#29 'ignore auto-repeat
if_c andn x,t wz
if_c xor _locks,x
if_c add data,#$DD
if_c_and_nz or stat,#4 'if change, set configure flag to update leds
test y,#%11 wz 'get shift into nz
if_nz cmp data,#$60+1 wc 'check shift1
if_nz_and_c cmpsub data,#$5B wc
if_nz_and_c add data,#@shift1-@table
if_nz_and_c call #look
if_nz_and_c andn y,#%11
if_nz cmp data,#$3D+1 wc 'check shift2
if_nz_and_c cmpsub data,#$27 wc
if_nz_and_c add data,#@shift2-@table
if_nz_and_c call #look
if_nz_and_c andn y,#%11
test _locks,#%010 wc 'check shift-alpha, considering capslock
muxnc :shift,#$20
test _locks,#$40 wc
if_nz_and_nc xor :shift,#$20
cmp data,#"z"+1 wc
if_c cmpsub data,#"a" wc
:shift if_c add data,#"A"
if_c andn y,#%11
:flags ror data,#8 'add shift/ctrl/alt/win flags
mov x,#4 '+$100 if shift
:loop test y,#%11 wz '+$200 if ctrl
shr y,#2 '+$400 if alt
if_nz or data,#1 '+$800 if win
ror data,#1
djnz x,#:loop
rol data,#12
rdlong x,par 'if room in buffer and key valid, enter
sub x,#1
and x,#$F
cmp x,_head wz
if_nz test data,#$FF wz
if_nz mov x,par
if_nz add x,#11*4
if_nz add x,_head
if_nz add x,_head
if_nz wrword data,x
if_nz add _head,#1
if_nz and _head,#$F
test stat,#4 wc 'if not configure flag, done
if_nc jmp #update 'else configure to update leds
'
'
' Configure keyboard
'
configure mov data,#$F3 'set keyboard auto-repeat
call #transmit
mov data,_auto
and data,#%11_11111
call #transmit
mov data,#$ED 'set keyboard lock-leds
call #transmit
mov data,_locks
rev data,#-3 & $1F
test data,#%100 wc
rcl data,#1
and data,#%111
call #transmit
mov x,_locks 'insert locks into _states
and x,#%111
shl _states+7,#3
or _states+7,x
ror _states+7,#3
mov _present,#1 'set _present
jmp #update 'done
'
'
' Lookup byte in table
'
look ror data,#2 'perform lookup
movs :reg,data
add :reg,#table
shr data,#27
mov x,data
:reg mov data,0
shr data,x
jmp #rand 'isolate byte
'
'
' Transmit byte to keyboard
'
transmit
_c1 or dira,cmask 'pull clock low
movs napshr,#13 'hold clock for ~128us (must be >100us)
call #nap
_d1 or dira,dmask 'pull data low
movs napshr,#18 'hold data for ~4us
call #nap
_c2 xor dira,cmask 'release clock
test data,#$0FF wc 'append parity and stop bits to byte
muxnc data,#$100
or data,dlsb
mov x,#10 'ready 10 bits
transmit_bit call #wait_c0 'wait until clock low
shr data,#1 wc 'output data bit
_d2 muxnc dira,dmask
mov wcond,c1 'wait until clock high
call #wait
djnz x,#transmit_bit 'another bit?
mov wcond,c0d0 'wait until clock and data low
call #wait
mov wcond,c1d1 'wait until clock and data high
call #wait
call #receive_ack 'receive ack byte with timed wait
cmp data,#$FA wz 'if ack error, reset keyboard
if_nz jmp #reset
transmit_ret ret
'
'
' Receive byte from keyboard
'
receive test _cpin,#$20 wc 'wait indefinitely for initial clock low
waitpne cmask,cmask
receive_ack
mov x,#11 'ready 11 bits
receive_bit call #wait_c0 'wait until clock low
movs napshr,#16 'pause ~16us
call #nap
_d3 test dmask,ina wc 'input data bit
rcr data,#1
mov wcond,c1 'wait until clock high
call #wait
djnz x,#receive_bit 'another bit?
shr data,#22 'align byte
test data,#$1FF wc 'if parity error, reset keyboard
if_nc jmp #reset
rand and data,#$FF 'isolate byte
look_ret
receive_ack_ret
receive_ret ret
'
'
' Wait for clock/data to be in required state(s)
'
wait_c0 mov wcond,c0 '(wait until clock low)
wait mov y,tenms 'set timeout to 10ms
wloop movs napshr,#18 'nap ~4us
call #nap
_c3 test cmask,ina wc 'check required state(s)
_d4 test dmask,ina wz 'loop until got state(s) or timeout
wcond if_never djnz y,#wloop '(replaced with c0/c1/c0d0/c1d1)
tjz y,#reset 'if timeout, reset keyboard
wait_ret
wait_c0_ret ret
c0 if_c djnz y,#wloop '(if_never replacements)
c1 if_nc djnz y,#wloop
c0d0 if_c_or_nz djnz y,#wloop
c1d1 if_nc_or_z djnz y,#wloop
'
'
' Nap
'
nap rdlong t,#0 'get clkfreq
napshr shr t,#18/16/13 'shr scales time
min t,#3 'ensure waitcnt won't snag
add t,cnt 'add cnt to time
waitcnt t,#0 'wait until time elapses (nap)
nap_ret ret
'
'
' Initialized data
'
'
dlsb long 1 << 9
tenms long 10_000 / 4
'
'
' Lookup table
' ascii scan extkey regkey ()=keypad
'
table word $0000 '00
word $00D8 '01 F9
word $0000 '02
word $00D4 '03 F5
word $00D2 '04 F3
word $00D0 '05 F1
word $00D1 '06 F2
word $00DB '07 F12
word $0000 '08
word $00D9 '09 F10
word $00D7 '0A F8
word $00D5 '0B F6
word $00D3 '0C F4
word $0009 '0D Tab
word $0060 '0E `
word $0000 '0F
word $0000 '10
word $F5F4 '11 Alt-R Alt-L
word $00F0 '12 Shift-L
word $0000 '13
word $F3F2 '14 Ctrl-R Ctrl-L
word $0071 '15 q
word $0031 '16 1
word $0000 '17
word $0000 '18
word $0000 '19
word $007A '1A z
word $0073 '1B s
word $0061 '1C a
word $0077 '1D w
word $0032 '1E 2
word $F600 '1F Win-L
word $0000 '20
word $0063 '21 c
word $0078 '22 x
word $0064 '23 d
word $0065 '24 e
word $0034 '25 4
word $0033 '26 3
word $F700 '27 Win-R
word $0000 '28
word $0020 '29 Space
word $0076 '2A v
word $0066 '2B f
word $0074 '2C t
word $0072 '2D r
word $0035 '2E 5
word $CC00 '2F Apps
word $0000 '30
word $006E '31 n
word $0062 '32 b
word $0068 '33 h
word $0067 '34 g
word $0079 '35 y
word $0036 '36 6
word $CD00 '37 Power
word $0000 '38
word $0000 '39
word $006D '3A m
word $006A '3B j
word $0075 '3C u
word $0037 '3D 7
word $0038 '3E 8
word $CE00 '3F Sleep
word $0000 '40
word $002C '41 ,
word $006B '42 k
word $0069 '43 i
word $006F '44 o
word $0030 '45 0
word $0039 '46 9
word $0000 '47
word $0000 '48
word $002E '49 .
word $EF2F '4A (/) /
word $006C '4B l
word $003B '4C ;
word $0070 '4D p
word $002D '4E -
word $0000 '4F
word $0000 '50
word $0000 '51
word $0027 '52 '
word $0000 '53
word $005B '54 [
word $003D '55 =
word $0000 '56
word $0000 '57
word $00DE '58 CapsLock
word $00F1 '59 Shift-R
word $EB0D '5A (Enter) Enter
word $005D '5B ]
word $0000 '5C
word $005C '5D \
word $CF00 '5E WakeUp
word $0000 '5F
word $0000 '60
word $0000 '61
word $0000 '62
word $0000 '63
word $0000 '64
word $0000 '65
word $00C8 '66 BackSpace
word $0000 '67
word $0000 '68
word $C5E1 '69 End (1)
word $0000 '6A
word $C0E4 '6B Left (4)
word $C4E7 '6C Home (7)
word $0000 '6D
word $0000 '6E
word $0000 '6F
word $CAE0 '70 Insert (0)
word $C9EA '71 Delete (.)
word $C3E2 '72 Down (2)
word $00E5 '73 (5)
word $C1E6 '74 Right (6)
word $C2E8 '75 Up (8)
word $00CB '76 Esc
word $00DF '77 NumLock
word $00DA '78 F11
word $00EC '79 (+)
word $C7E3 '7A PageDn (3)
word $00ED '7B (-)
word $DCEE '7C PrScr (*)
word $C6E9 '7D PageUp (9)
word $00DD '7E ScrLock
word $0000 '7F
word $0000 '80
word $0000 '81
word $0000 '82
word $00D6 '83 F7
keypad1 byte $CA, $C5, $C3, $C7, $C0, 0, $C1, $C4, $C2, $C6, $C9, $0D, "+-*/"
keypad2 byte "0123456789.", $0D, "+-*/"
shift1 byte "{|}", 0, 0, "~"
shift2 byte $22, 0, 0, 0, 0, "<_>?)!@#$%^&*(", 0, ":", 0, "+"
'
'
' Uninitialized data
'
dmask res 1
cmask res 1
stat res 1
data res 1
x res 1
y res 1
t res 1
_head res 1 'write-only
_present res 1 'write-only
_states res 8 'write-only
_dpin res 1 'read-only at start
_cpin res 1 'read-only at start
_locks res 1 'read-only at start
_auto res 1 'read-only at start
''
''
'' _________
'' Key Codes
''
'' 00..DF = keypress and keystate
'' E0..FF = keystate only
''
''
'' 09 Tab
'' 0D Enter
'' 20 Space
'' 21 !
'' 22 "
'' 23 #
'' 24 $
'' 25 %
'' 26 &
'' 27 '
'' 28 (
'' 29 )
'' 2A *
'' 2B +
'' 2C ,
'' 2D -
'' 2E .
'' 2F /
'' 30 0..9
'' 3A :
'' 3B ;
'' 3C <
'' 3D =
'' 3E >
'' 3F ?
'' 40 @
'' 41..5A A..Z
'' 5B [
'' 5C \
'' 5D ]
'' 5E ^
'' 5F _
'' 60 `
'' 61..7A a..z
'' 7B {
'' 7C |
'' 7D }
'' 7E ~
''
'' 80-BF (future international character support)
''
'' C0 Left Arrow
'' C1 Right Arrow
'' C2 Up Arrow
'' C3 Down Arrow
'' C4 Home
'' C5 End
'' C6 Page Up
'' C7 Page Down
'' C8 Backspace
'' C9 Delete
'' CA Insert
'' CB Esc
'' CC Apps
'' CD Power
'' CE Sleep
'' CF Wakeup
''
'' D0..DB F1..F12
'' DC Print Screen
'' DD Scroll Lock
'' DE Caps Lock
'' DF Num Lock
''
'' E0..E9 Keypad 0..9
'' EA Keypad .
'' EB Keypad Enter
'' EC Keypad +
'' ED Keypad -
'' EE Keypad *
'' EF Keypad /
''
'' F0 Left Shift
'' F1 Right Shift
'' F2 Left Ctrl
'' F3 Right Ctrl
'' F4 Left Alt
'' F5 Right Alt
'' F6 Left Win
'' F7 Right Win
''
'' FD Scroll Lock State
'' FE Caps Lock State
'' FF Num Lock State
''
'' +100 if Shift
'' +200 if Ctrl
'' +400 if Alt
'' +800 if Win
''
'' eg. Ctrl-Alt-Delete = $6C9
''
''
'' Note: Driver will buffer up to 15 keystrokes, then ignore overflow.
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,125 @@
'' ===========================================================================
'' VGA High-Res Text UI Elements Base UI Support Functions v1.2
''
'' File: MenuItem.spin
'' Author: Allen Marincak
'' Copyright (c) 2009 Allen MArincak
'' See end of file for terms of use
'' ===========================================================================
''
''============================================================================
'' MenuItem Control
''============================================================================
''
'' Creates a menu item. This is really like a text button, but when placed with
'' others and inside a simple box it can look like a menu bar. User determined
'' state information may be assigned to it.
VAR
word varGdx 'GUI control variable
long varScreenPtr 'screen buffer pointer
long varVgaPos 'starting position of the menu item
byte varTextN[18] 'normal text, 15 chars MAX, with room for terminating Null and bracketing spaces
byte varTextI[18] 'inverted text, 15 chars MAX, with room for terminating Null and bracketing spaces
byte varRow 'top row location
byte varCol 'left col location
byte varCol2 'right col location
byte varWidth 'width of text
byte varStatus '0=normal else user defined value
byte varVgaCols 'width of screen in columns
PUB Init( pRow, pCol, pTextPtr, pVgaPtr, pVgaWidth ) | strIdx
varVgaCols := pVgaWidth
varRow := pRow
varCol := pCol
varScreenPtr := pVgaPtr
varStatus := 0
varWidth := strsize( pTextPtr ) + 2
varCol2 := varCol + varWidth - 1
varTextN[0] := 32
bytemove( @varTextN[1], pTextPtr, varWidth - 2 ) 'copy menu item text string
varTextN[varWidth - 1] := 32
varTextN[varWidth] := 0
strIdx := 0
repeat varWidth
varTextI[strIdx] := varTextN[strIdx]+128 'invert the string
strIdx++
varTextI[strIdx] := 0
varVgaPos := varRow * varVgaCols + varCol 'now draw the menu item
bytemove( @byte[varScreenPtr][varVgaPos], @varTextI, varWidth )
PUB DrawText( pMode )
if pMode & 1
bytemove( @byte[varScreenPtr][varVgaPos], @varTextN, varWidth )
else
bytemove( @byte[varScreenPtr][varVgaPos], @varTextI, varWidth )
PUB IsIn( pCx, pCy ) : qq
qq := false
if ( pCx => varCol ) AND ( pCx =< varCol2 )
if pCy == varRow
qq := true
return qq
PUB SetText( pPtr ) | strIdx
bytefill( @varTextN[1], 32, varWidth - 2 ) 'clear it first
bytemove( @varTextN[1], pPtr, strsize(pPtr) ) 'copy menu item text string
strIdx := 0
repeat varWidth
varTextI[strIdx] := varTextN[strIdx]+128 'invert the string
strIdx++
bytemove( @byte[varScreenPtr][varVgaPos], varTextI, varWidth )
PUB SetStatus( pStat )
varStatus := pStat 'user defined status value
Pub GetStatus
return varStatus
PUB set_gzidx( gzidx )
varGdx := gzidx
PUB get_gzidx
return varGdx
{{
┌────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy│
│of this software and associated documentation files (the "Software"), to │
│deal in the Software without restriction, including without limitation the │
│rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │
│sell copies of the Software, and to permit persons to whom the Software is │
│furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in │
│all copies or substantial portions of the Software. │
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
│IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
│FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
│AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
│LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │
│FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS│
│IN THE SOFTWARE. │
└────────────────────────────────────────────────────────────────────────────┘
}}

492
source/gui-demo/Mouse.spin Normal file
View File

@ -0,0 +1,492 @@
''***************************************
''* PS/2 Mouse Driver v1.1 *
''* Author: Chip Gracey *
''* Copyright (c) 2006 Parallax, Inc. *
''* See end of file for terms of use. *
''***************************************
' v1.0 - 01 May 2006 - original version
' v1.1 - 01 Jun 2006 - bound coordinates added to simplify upper objects
VAR
long cog
long oldx, oldy, oldz 'must be followed by parameters (10 contiguous longs)
long par_x 'absolute x read-only (7 contiguous longs)
long par_y 'absolute y read-only
long par_z 'absolute z read-only
long par_buttons 'button states read-only
long par_present 'mouse present read-only
long par_dpin 'data pin write-only
long par_cpin 'clock pin write-only
long bx_min, by_min, bz_min 'min/max must be contiguous
long bx_max, by_max, bz_max
long bx_div, by_div, bz_div
long bx_acc, by_acc, bz_acc
PUB start(dpin, cpin) : okay
'' Start mouse driver - starts a cog
'' returns false if no cog available
''
'' dpin = data signal on PS/2 jack
'' cpin = clock signal on PS/2 jack
''
'' use 100-ohm resistors between pins and jack
'' use 10K-ohm resistors to pull jack-side signals to VDD
'' connect jack-power to 5V, jack-gnd to VSS
stop
par_dpin := dpin
par_cpin := cpin
okay := cog := cognew(@entry, @par_x) + 1
PUB stop
'' Stop mouse driver - frees a cog
if cog
cogstop(cog~ - 1)
longfill(@oldx, 0, 10)
PUB present : type
'' Check if mouse present - valid ~2s after start
'' returns mouse type:
''
'' 3 = five-button scrollwheel mouse
'' 2 = three-button scrollwheel mouse
'' 1 = two-button or three-button mouse
'' 0 = no mouse connected
type := par_present
PUB button(b) : state
'' Get the state of a particular button
'' returns t|f
state := -(par_buttons >> b & 1)
PUB buttons : states
'' Get the states of all buttons
'' returns buttons:
''
'' bit4 = right-side button
'' bit3 = left-side button
'' bit2 = center/scrollwheel button
'' bit1 = right button
'' bit0 = left button
states := par_buttons
PUB abs_x : x
'' Get absolute-x
x := par_x
PUB abs_y : y
'' Get absolute-y
y := par_y
PUB abs_z : z
'' Get absolute-z (scrollwheel)
z := par_z
PUB delta_reset
'' Reset deltas
oldx := par_x
oldy := par_y
oldz := par_z
PUB delta_x : x | newx
'' Get delta-x
newx := par_x
x := newx - oldx
oldx := newx
PUB delta_y : y | newy
'' Get delta-y
newy := par_y
y := newy - oldy
oldy := newy
PUB delta_z : z | newz
'' Get delta-z (scrollwheel)
newz := par_z
z := newz - oldz
oldz := newz
PUB bound_limits(xmin, ymin, zmin, xmax, ymax, zmax) | i
'' Set bounding limits
longmove(@bx_min, @xmin, 6)
PUB bound_scales(x_scale, y_scale, z_scale)
'' Set bounding scales (usually +/-1's, bigger values divide)
longmove(@bx_div, @x_scale, 3)
PUB bound_preset(x, y, z) | i, d
'' Preset bound coordinates
repeat i from 0 to 2
d := ||bx_div[i]
bx_acc[i] := (x[i] - bx_min[i]) * d + d >> 1
PUB bound_x : x
'' Get bound-x
x := bound(0, delta_x)
PUB bound_y : y
'' Get bound-y
y := bound(1, delta_y)
PUB bound_z : z
'' Get bound-z
z := bound(2, delta_z)
PRI bound(i, delta) : b | d
d := bx_div[i]
b := bx_min[i] + (bx_acc[i] := bx_acc[i] + delta * (d < 0) | 1 #> 0 <# (bx_max[i] - bx_min[i] + 1) * ||d - 1) / ||d
DAT
'***************************************
'* Assembly language PS/2 mouse driver *
'***************************************
org
'
'
' Entry
'
entry mov p,par 'load input parameters:
add p,#5*4 '_dpin/_cpin
rdlong _dpin,p
add p,#4
rdlong _cpin,p
mov dmask,#1 'set pin masks
shl dmask,_dpin
mov cmask,#1
shl cmask,_cpin
test _dpin,#$20 wc 'modify port registers within code
muxc _d1,dlsb
muxc _d2,dlsb
muxc _d3,#1
muxc _d4,#1
test _cpin,#$20 wc
muxc _c1,dlsb
muxc _c2,dlsb
muxc _c3,#1
movd :par,#_x 'reset output parameters:
mov p,#5 '_x/_y/_z/_buttons/_present
:par mov 0,#0
add :par,dlsb
djnz p,#:par
'
'
' Reset mouse
'
reset mov dira,#0 'reset directions
mov dirb,#0
mov stat,#1 'set reset flag
'
'
' Update parameters
'
update movd :par,#_x 'update output parameters:
mov p,par '_x/_y/_z/_buttons/_present
mov q,#5
:par wrlong 0,p
add :par,dlsb
add p,#4
djnz q,#:par
test stat,#1 wc 'if reset flag, transmit reset command
if_c mov data,#$FF
if_c call #transmit
'
'
' Get data packet
'
mov stat,#0 'reset state
call #receive 'receive first byte
cmp data,#$AA wz 'powerup/reset?
if_z jmp #init
mov _buttons,data 'data packet, save buttons
call #receive 'receive second byte
test _buttons,#$10 wc 'adjust _x
muxc data,signext
add _x,data
call #receive 'receive third byte
test _buttons,#$20 wc 'adjust _y
muxc data,signext
add _y,data
and _buttons,#%111 'trim buttons
cmp _present,#2 wc 'if not scrollwheel mouse, update parameters
if_c jmp #update
call #receive 'scrollwheel mouse, receive fourth byte
cmp _present,#3 wz 'if 5-button mouse, handle two extra buttons
if_z test data,#$10 wc
if_z_and_c or _buttons,#%01000
if_z test data,#$20 wc
if_z_and_c or _buttons,#%10000
shl data,#28 'adjust _z
sar data,#28
sub _z,data
jmp #update 'update parameters
'
'
' Initialize mouse
'
init call #receive '$AA received, receive id
movs crate,#100 'try to enable 3-button scrollwheel type
call #checktype
movs crate,#200 'try to enable 5-button scrollwheel type
call #checktype
shr data,#1 'if neither, 3-button type
add data,#1
mov _present,data
movs srate,#200 'set 200 samples per second
call #setrate
mov data,#$F4 'enable data reporting
call #transmit
jmp #update
'
'
' Check mouse type
'
checktype movs srate,#200 'perform "knock" sequence to enable
call #setrate '..scrollwheel and extra buttons
crate movs srate,#200/100
call #setrate
movs srate,#80
call #setrate
mov data,#$F2 'read type
call #transmit
call #receive
checktype_ret ret
'
'
' Set sample rate
'
setrate mov data,#$F3
call #transmit
srate mov data,#0
call #transmit
setrate_ret ret
'
'
' Transmit byte to mouse
'
transmit
_c1 or dira,cmask 'pull clock low
movs napshr,#13 'hold clock for ~128us (must be >100us)
call #nap
_d1 or dira,dmask 'pull data low
movs napshr,#18 'hold data for ~4us
call #nap
_c2 xor dira,cmask 'release clock
test data,#$0FF wc 'append parity and stop bits to byte
muxnc data,#$100
or data,dlsb
mov p,#10 'ready 10 bits
transmit_bit call #wait_c0 'wait until clock low
shr data,#1 wc 'output data bit
_d2 muxnc dira,dmask
mov wcond,c1 'wait until clock high
call #wait
djnz p,#transmit_bit 'another bit?
mov wcond,c0d0 'wait until clock and data low
call #wait
mov wcond,c1d1 'wait until clock and data high
call #wait
call #receive_ack 'receive ack byte with timed wait
cmp data,#$FA wz 'if ack error, reset mouse
if_nz jmp #reset
transmit_ret ret
'
'
' Receive byte from mouse
'
receive test _cpin,#$20 wc 'wait indefinitely for initial clock low
waitpne cmask,cmask
receive_ack
mov p,#11 'ready 11 bits
receive_bit call #wait_c0 'wait until clock low
movs napshr,#16 'pause ~16us
call #nap
_d3 test dmask,ina wc 'input data bit
rcr data,#1
mov wcond,c1 'wait until clock high
call #wait
djnz p,#receive_bit 'another bit?
shr data,#22 'align byte
test data,#$1FF wc 'if parity error, reset mouse
if_nc jmp #reset
and data,#$FF 'isolate byte
receive_ack_ret
receive_ret ret
'
'
' Wait for clock/data to be in required state(s)
'
wait_c0 mov wcond,c0 '(wait until clock low)
wait mov q,tenms 'set timeout to 10ms
wloop movs napshr,#18 'nap ~4us
call #nap
_c3 test cmask,ina wc 'check required state(s)
_d4 test dmask,ina wz 'loop until got state(s) or timeout
wcond if_never djnz q,#wloop '(replaced with c0/c1/c0d0/c1d1)
tjz q,#reset 'if timeout, reset mouse
wait_ret
wait_c0_ret ret
c0 if_c djnz q,#wloop '(if_never replacements)
c1 if_nc djnz q,#wloop
c0d0 if_c_or_nz djnz q,#wloop
c1d1 if_nc_or_z djnz q,#wloop
'
'
' Nap
'
nap rdlong t,#0 'get clkfreq
napshr shr t,#18/16/13 'shr scales time
min t,#3 'ensure waitcnt won't snag
add t,cnt 'add cnt to time
waitcnt t,#0 'wait until time elapses (nap)
nap_ret ret
'
'
' Initialized data
'
dlsb long 1 << 9
tenms long 10_000 / 4
signext long $FFFFFF00
'
'
' Uninitialized data
'
dmask res 1
cmask res 1
stat res 1
data res 1
p res 1
q res 1
t res 1
_x res 1 'write-only
_y res 1 'write-only
_z res 1 'write-only
_buttons res 1 'write-only
_present res 1 'write-only
_dpin res 1 'read-only
_cpin res 1 'read-only
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,117 @@
'' ===========================================================================
'' VGA High-Res Text UI Elements Base UI Support Functions v1.2
''
'' File: PushButton.spin
'' Author: Allen Marincak
'' Copyright (c) 2009 Allen MArincak
'' See end of file for terms of use
'' ===========================================================================
''
''============================================================================
'' Push Button Control
''============================================================================
''
'' Creates a straight forward pushbutton control.
OBJ
SBOX : "SimpleBox"
VAR
word varGdx 'GUI control variable
long varScreenPtr 'screen buffer pointer
long varVgaPos 'starting position of the menu item
byte varTextN[16] 'normal text, 15 chars MAX, with room for terminating Null
byte varTextI[16] 'inverted text, 15 chars MAX, with room for terminating Null
byte varRow 'top row location
byte varCol 'left col location
byte varCol2 'right col location
byte varWidth 'width of text
byte varVgaCols 'width of screen in columns
PUB Init( pRow, pCol, pTextPtr, pVgaPtr, pVgaWidth ) | strIdx
varVgaCols := pVgaWidth
varRow := pRow
varCol := pCol
varScreenPtr := pVgaPtr
varWidth := strsize( pTextPtr )+ 2
varCol2 := varCol + varWidth - 1
SBOX.DrawBox( pRow, pCol, varWidth, 3, 0, pVgaPtr, pVgaWidth )
bytemove( @varTextN[0], pTextPtr, varWidth - 2 ) 'copy menu item text string
strIdx := 0
repeat varWidth-2
varTextI[strIdx] := varTextN[strIdx]+128 'invert the string
strIdx++
varVgaPos := varRow * varVgaCols + varCol + varVgaCols + 1
bytemove( @byte[varScreenPtr][varVgaPos], varTextI, varWidth - 2 )
PUB DrawText( pMode )
if pMode & 1
bytemove( @byte[varScreenPtr][varVgaPos], @varTextI, varWidth-2 )
else
bytemove( @byte[varScreenPtr][varVgaPos], @varTextN, varWidth-2 )
PUB IsIn( pCx, pCy ) : qq
qq := false
if ( pCx > varCol ) AND ( pCx < varCol2 )
if pCy == varRow+1
qq := true
return qq
PUB SetText( pPtr ) | strIdx
bytefill( @varTextN[0], 32, varWidth - 2 ) 'clear it first
bytemove( @varTextN[0], pPtr, strsize(pPtr) ) 'copy menu item text string
strIdx := 0
repeat varWidth-2
varTextI[strIdx] := varTextN[strIdx]+128 'invert the string
strIdx++
bytemove( @byte[varScreenPtr][varVgaPos], varTextN, varWidth-2 )
PUB set_gzidx( gzidx )
varGdx := gzidx
PUB get_gzidx
return varGdx
{{
┌────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy│
│of this software and associated documentation files (the "Software"), to │
│deal in the Software without restriction, including without limitation the │
│rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │
│sell copies of the Software, and to permit persons to whom the Software is │
│furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in │
│all copies or substantial portions of the Software. │
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
│IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
│FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
│AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
│LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │
│FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS│
│IN THE SOFTWARE. │
└────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,153 @@
'' ===========================================================================
'' VGA High-Res Text UI Elements Base UI Support Functions v1.2
''
'' File: RadioCheck.spin
'' Author: Allen Marincak
'' Copyright (c) 2009 Allen MArincak
'' See end of file for terms of use
'' ===========================================================================
''
''============================================================================
'' Button Control
''============================================================================
''
'' Creates Radio Buttons or Check Boxes
''
VAR
word varGdx 'GUI control variable
long varScreenPtr 'screen buffer pointer
long varVgaPos 'start location of the button
byte varTextN[16] 'normal text, 15 chars MAX, with room for terminating Null
byte varTextI[16] 'inverted text, 15 chars MAX, with room for terminating Null
byte varRow 'top row location
byte varCol 'left col location
byte varCol2 'right col location
byte varWidth 'width of text
byte varStatus 'status byte 0 = none 1 = active
byte varSelChar 'selected character
byte varUnselChar 'unselected character
byte varVgaCols 'width of screen in columns
PUB Init( pRow, pCol, pTextWidth, pStyle, pTextPtr, pVgaPtr, pVgaWidth ) | strIdx, vgaIdx
varVgaCols := pVgaWidth
varStatus := 0
varRow := pRow
varCol := pCol
varWidth := pTextWidth
varScreenPtr := pVgaPtr
varVgaPos := varRow * varVgaCols + varCol
varCol2 := varCol + varWidth + 1
if pStyle == 0
varSelChar := 7 'CheckBox Style
varUnselChar := 6
else
varSelChar := 5 'Radio Button Style
varUnselChar := 4
strIdx := strsize( pTextPtr )
bytemove( @varTextN, pTextPtr, strIdx ) 'copy checkbox text string
bytefill(@varTextN[strIdx],32,pTextWidth-strIdx) 'pad out with spaces
varTextN[pTextWidth] := 0
strIdx := 0
repeat pTextWidth
varTextI[strIdx] := varTextN[strIdx]+128 'create inverted string
strIdx++
varTextI[strIdx] := 0
vgaIdx := varVgaPos 'now draw the checkbox
byte[varScreenPtr][vgaIdx++] := varUnselChar 'empty bullet
byte[varScreenPtr][vgaIdx++] := 32
strIdx := strsize( @varTextN )
bytemove( @byte[varScreenPtr][vgaIdx], @varTextN, strIdx )
PUB DrawText( pMode ) | strIdx, vgaIdx
strIdx := strsize( @varTextN )
vgaIdx := varVgaPos 'bullet location
if varStatus == 1
byte[varScreenPtr][vgaIdx] := varSelChar 'selected bullet
else
byte[varScreenPtr][vgaIdx] := varUnselChar 'non-selected bullet
vgaIdx += 2 'checkbox text location
if pMode & 1
bytemove( @byte[varScreenPtr][vgaIdx], @varTextI, strIdx )
else
bytemove( @byte[varScreenPtr][vgaIdx], @varTextN, strIdx )
PUB IsIn( pCx, pCy ) | retVal
retVal := false
if ( pCx => varCol ) AND ( pCx =< varCol2 )
if pCy == varRow
retVal := true
return retVal
PUB Select( pSel )
if pSel <> -1
varStatus := pSel
else
if varStatus == 0
varStatus := 1
else
varStatus := 0
if varStatus == 1
byte[varScreenPtr][varVgaPos] := varSelChar 'selected bullet
else
byte[varScreenPtr][varVgaPos] := varUnselChar 'non-selected
PUB IsSet
if varStatus == 1
return true
else
return false
PUB set_gzidx( gzidx )
varGdx := gzidx
PUB get_gzidx
return varGdx
{{
┌────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy│
│of this software and associated documentation files (the "Software"), to │
│deal in the Software without restriction, including without limitation the │
│rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │
│sell copies of the Software, and to permit persons to whom the Software is │
│furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in │
│all copies or substantial portions of the Software. │
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
│IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
│FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
│AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
│LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │
│FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS│
│IN THE SOFTWARE. │
└────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,93 @@
'' ===========================================================================
'' VGA High-Res Text UI Elements Base UI Support Functions v1.2
''
'' File: SimpleBox.spin
'' Author: Allen Marincak
'' Copyright (c) 2009 Allen MArincak
'' See end of file for terms of use
'' ===========================================================================
''
''============================================================================
'' SimpleBox Control
''============================================================================
''
'' Just draws a box with optional title, plain and simple.
''
PUB DrawBox( pRow, pCol, pWidth, pHeight, pTitlePtr, pVgaPtr, pVgaWidth ) | idx, vgaIdx, rowCnt, tbTitle, vgaStartIdx
vgaStartIdx := pRow * pVgaWidth + pCol
vgaIdx := vgaStartIdx 'clear the area first
repeat pHeight
bytefill(@byte[pVgaPtr][vgaIdx],32,pWidth)
vgaIdx += pVgaWidth
vgaIdx := vgaStartIdx 'goto top left row/col
byte[pVgaPtr][vgaIdx++] := 10 'top left corner char
bytefill(@byte[pVgaPtr][vgaIdx],14,pWidth-2) 'horizontal line
vgaIdx += pWidth - 2
byte[pVgaPtr][vgaIdx++] := 11 'top right corner char
vgaIdx := vgaStartIdx + pVgaWidth 'move down to start of next row
if pTitlePtr <> 0 'if there is a title
byte[pVgaPtr][vgaIdx++] := 15 'vertical line char
idx := strsize( pTitlePtr )
bytemove( @byte[pVgaPtr][vgaIdx], pTitlePtr, idx )'place title
vgaIdx += pWidth - 2
byte[pVgaPtr][vgaIdx++] := 15 'vertical line char
vgaIdx := vgaStartIdx + 2 * pVgaWidth 'move down to start of next row
byte[pVgaPtr][vgaIdx++] := 18 'left 'tee' char
bytefill(@byte[pVgaPtr][vgaIdx],14,pWidth-2)'horizontal line
vgaIdx += pWidth - 2
byte[pVgaPtr][vgaIdx++] := 19 'right 'tee' char
rowCnt := 3 'row counter
else
rowCnt := 1 'row counter
vgaIdx := vgaStartIdx + pVgaWidth * rowCnt 'move down to start of next row
repeat pHeight - rowCnt - 1
byte[pVgaPtr][vgaIdx++] := 15 'vertical line char
vgaIdx += pWidth - 2
byte[pVgaPtr][vgaIdx++] := 15 'vertical line char
vgaIdx -= pWidth
vgaIdx += pVgaWidth
'the above left vgaIdx pointing to the start of the last line
byte[pVgaPtr][vgaIdx++] := 12 'bottom left corner char
bytefill(@byte[pVgaPtr][vgaIdx],14,pWidth-2) 'horizontal line
vgaIdx += pWidth - 2
byte[pVgaPtr][vgaIdx++] := 13 'bottom right corner char
{{
┌────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy│
│of this software and associated documentation files (the "Software"), to │
│deal in the Software without restriction, including without limitation the │
│rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │
│sell copies of the Software, and to permit persons to whom the Software is │
│furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in │
│all copies or substantial portions of the Software. │
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
│IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
│FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
│AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
│LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │
│FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS│
│IN THE SOFTWARE. │
└────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,197 @@
''****************************************
''* Simple_Numbers *
''* Authors: Chip Gracey, Jon Williams *
''* Copyright (c) 2006 Parallax, Inc. *
''* See end of file for terms of use. *
''****************************************
''
'' Provides simple numeric conversion methods; all methods return a pointer to
'' a string.
''
'' Updated... 29 APR 2006
CON
MAX_LEN = 64 ' 63 chars + zero terminator
VAR
long idx ' pointer into string
byte nstr[MAX_LEN] ' string for numeric data
PUB dec(value)
'' Returns pointer to signed-decimal string
clrstr(@nstr, MAX_LEN) ' clear output string
return decstr(value) ' return pointer to numeric string
PUB decf(value, width) | t_val, field
'' Returns pointer to signed-decimal, fixed-width (space padded) string
clrstr(@nstr, MAX_LEN)
width := 1 #> width <# constant(MAX_LEN - 1) ' qualify field width
t_val := ||value ' work with absolute
field~ ' clear field
repeat while t_val > 0 ' count number of digits
field++
t_val /= 10
field #>= 1 ' min field width is 1
if value < 0 ' if value is negative
field++ ' bump field for neg sign indicator
if field < width ' need padding?
repeat (width - field) ' yes
nstr[idx++] := " " ' pad with space(s)
return decstr(value)
PUB decx(value, digits) | div
'' Returns pointer to zero-padded, signed-decimal string
'' -- if value is negative, field width is digits+1
clrstr(@nstr, MAX_LEN)
digits := 1 #> digits <# 10
if (value < 0) ' negative value?
-value ' yes, make positive
nstr[idx++] := "-" ' and print sign indicator
div := 1_000_000_000 ' initialize divisor
if digits < 10 ' less than 10 digits?
repeat (10 - digits) ' yes, adjust divisor
div /= 10
value //= (div * 10) ' truncate unused digits
repeat digits
nstr[idx++] := (value / div + "0") ' convert digit to ASCII
value //= div ' update value
div /= 10 ' update divisor
return @nstr
PUB hex(value, digits)
'' Returns pointer to a digits-wide hexadecimal string
clrstr(@nstr, MAX_LEN)
return hexstr(value, digits)
PUB ihex(value, digits)
'' Returns pointer to a digits-wide, indicated (with $) hexadecimal string
clrstr(@nstr, MAX_LEN)
nstr[idx++] := "$"
return hexstr(value, digits)
PUB bin(value, digits)
'' Returns pointer to a digits-wide binary string
clrstr(@nstr, MAX_LEN)
return binstr(value, digits)
PUB ibin(value, digits)
'' Returns pointer to a digits-wide, indicated (with %) binary string
clrstr(@nstr, MAX_LEN)
nstr[idx++] := "%" ' preface with binary indicator
return binstr(value, digits)
PRI clrstr(strAddr, size)
' Clears string at strAddr
' -- also resets global character pointer (idx)
bytefill(strAddr, 0, size) ' clear string to zeros
idx~ ' reset index
PRI decstr(value) | div, z_pad
' Converts value to signed-decimal string equivalent
' -- characters written to current position of idx
' -- returns pointer to nstr
if (value < 0) ' negative value?
-value ' yes, make positive
nstr[idx++] := "-" ' and print sign indicator
div := 1_000_000_000 ' initialize divisor
z_pad~ ' clear zero-pad flag
repeat 10
if (value => div) ' printable character?
nstr[idx++] := (value / div + "0") ' yes, print ASCII digit
value //= div ' update value
z_pad~~ ' set zflag
elseif z_pad or (div == 1) ' printing or last column?
nstr[idx++] := "0"
div /= 10
return @nstr
PRI hexstr(value, digits)
' Converts value to digits-wide hexadecimal string equivalent
' -- characters written to current position of idx
' -- returns pointer to nstr
digits := 1 #> digits <# 8 ' qualify digits
value <<= (8 - digits) << 2 ' prep most significant digit
repeat digits
nstr[idx++] := lookupz((value <-= 4) & $F : "0".."9", "A".."F")
return @nstr
PRI binstr(value, digits)
' Converts value to digits-wide binary string equivalent
' -- characters written to current position of idx
' -- returns pointer to nstr
digits := 1 #> digits <# 32 ' qualify digits
value <<= 32 - digits ' prep MSB
repeat digits
nstr[idx++] := (value <-= 1) & 1 + "0" ' move digits (ASCII) to string
return @nstr
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,225 @@
'' ===========================================================================
'' VGA High-Res Text UI Elements Base UI Support Functions v1.2
''
'' File: SpinBox.spin
'' Author: Allen Marincak
'' Copyright (c) 2009 Allen MArincak
'' See end of file for terms of use
'' ===========================================================================
''
''============================================================================
'' Simple SpinBox
''============================================================================
''
'' Creates a simple spin box control. Data may be text or numeric.
CON
MAX_LEN = 16
OBJ
SBOX : "SimpleBox"
VAR
word varGdx 'GUI control variable
long varScreenPtr 'screen buffer pointer
long varDataPtr 'points to the display data (not the setup bytes)
long varDrawIdx 'vga index to start of display item area
long n_idx 'index into number string
word varUpIdx 'vga index of up arrow
word varDnIdx 'vga index of down arrow
byte n_str[MAX_LEN] 'string for numeric data
byte varRow 'top row location
byte varCol 'left col location
byte varCol2 'right col location
byte varWidth 'width ... info area is 6 less than total width
byte varVgaCols 'width of screen in columns
byte varNumData 'number of data items
byte varDataIdx 'current data item displayed
byte varType '0 = text 1 = numeric
PUB Init ( pRow, pCol, pWidth, pType, pNum, pDataPtr, pVgaPtr, pVgaWidth ) | vgaIdx
varVgaCols := pVgaWidth
varRow := pRow
varCol := pCol
varWidth := pWidth
varScreenPtr := pVgaPtr
varCol2 := varCol + varWidth
varDataPtr := pDataPtr
varType := pType
varNumData := pNum
varDataIdx := 0
varDrawIdx := varRow*varVgaCols+varVgaCols+varCol+1 'display item location
SBOX.DrawBox( pRow, pCol, pWidth, 3, 0, pVgaPtr, pVgaWidth )
vgaIdx := varRow * varVgaCols + varCol + varWidth - 3
byte[varScreenPtr][vgaIdx] := 16 'top 'tee' char
vgaIdx += varVgaCols
byte[varScreenPtr][vgaIdx] := 15 'vertical line char
varDnIdx := vgaIdx+1 'save position of DN arrow
byte[varScreenPtr][vgaIdx+1] := 3 'down arrow char
vgaIdx += varVgaCols
byte[varScreenPtr][vgaIdx] := 17 'bottom 'tee' char
vgaIdx := varRow * varVgaCols + varCol + varWidth - 5
byte[varScreenPtr][vgaIdx] := 16 'top 'tee' char
vgaIdx += varVgaCols
byte[varScreenPtr][vgaIdx] := 15 'vertical line char
varUpIdx := vgaIdx+1 'save position of UP arrow
byte[varScreenPtr][vgaIdx+1] := 2 'up arrow char
vgaIdx += varVgaCols
byte[varScreenPtr][vgaIdx] := 17 'bottom 'tee' char
DrawData( varDataIdx )
PUB IsIn( pCx, pCy ) | retVal
retVal := false
if ( pCx => varCol ) AND ( pCx =< varCol2 )
if pCy == varRow + 1
retVal := true
return retVal
PUB Clicked( pCx, pCy ) | idx, retVal
retVal := -1 'default return if neither arrow was pressed or at boundary
idx := pCy*varVgaCols+pCx
if idx == varUpIdx
if varDataIdx <> varNumData - 1
varDataIdx++
retVal := varDataIdx
if idx == varDnIdx
if varDataIdx <> 0
varDataIdx--
retVal := varDataIdx
if retVal <> -1
DrawData( varDataIdx )
return retVal
PUB GetDataIndex
'returns the zero based index of the currently displaying data
return varDataIdx
PUB set_gzidx( gzidx )
varGdx := gzidx
PUB get_gzidx
return varGdx
PRI DrawData( didx ) | tptr, strLen
'Draws the specified (by zero based index) data in the spin box display area.
' didx = index of data item to display
tptr := varDataPtr
bytefill(@byte[varScreenPtr][varDrawIdx],32,varWidth-6)
if varType == 0 '----<data is text>-----------
strLen := strsize( tptr )
repeat didx
tptr += strLen + 1
strLen := strsize( tptr )
bytemove(@byte[varScreenPtr][varDrawIdx], tptr, strLen )
else '----<data is numeric>--------
strLen := varWidth-6
strLen := 1 #> strLen <# constant(MAX_LEN - 1)
bytemove(@byte[varScreenPtr][varDrawIdx], decf(long[tptr][didx],strLen), strLen )
''=============================================================================
'' The routine that follows is taken from the Simple_Numbers.spin object.
'' However, I collapsed clrstr() and decstr() into this decf() function.
''
''****************************************
''* Simple_Numbers *
''* Authors: Chip Gracey, Jon Williams *
''* Copyright (c) 2006 Parallax, Inc. *
''* See end of file for terms of use. *
''****************************************
''=============================================================================
PRI decf(value, width) | t_val, field, div, z_pad
'' Converts value to signed-decimal string equivalent
'' - characters written to current position of n_idx
'' - returns pointer to n_str: signed-decimal, fixed-width, space padded string
n_idx~ ' reset index
t_val := ||value ' work with absolute
field~ ' clear field
bytefill(@n_str, 0, MAX_LEN) ' clear string to zeros
repeat while t_val > 0 ' count number of digits
field++
t_val /= 10
field #>= 1 ' min field width is 1
if value < 0 ' if value is negative
field++ ' - bump field for neg sign indicator
if field < width ' need padding?
repeat (width - field) ' yes
n_str[n_idx++] := " " ' - pad with space(s)
if (value < 0) ' negative value?
-value ' - yes, make positive
n_str[n_idx++] := "-" ' - and print sign indicator
div := 1_000_000_000 ' initialize divisor
z_pad~ ' clear zero-pad flag
repeat 10
if (value => div) ' printable character?
n_str[n_idx++] := (value / div + "0") ' - yes, print ASCII digit
value //= div ' - update value
z_pad~~ ' - set zflag
elseif z_pad or (div == 1) ' printing or last column?
n_str[n_idx++] := "0"
div /= 10
return @n_str
{{
┌────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy│
│of this software and associated documentation files (the "Software"), to │
│deal in the Software without restriction, including without limitation the │
│rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │
│sell copies of the Software, and to permit persons to whom the Software is │
│furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in │
│all copies or substantial portions of the Software. │
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
│IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
│FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
│AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
│LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │
│FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS│
│IN THE SOFTWARE. │
└────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,115 @@
'' ===========================================================================
'' VGA High-Res Text UI Elements Base UI Support Functions v1.2
''
'' File: StatusLamp.spin
'' Author: Allen Marincak
'' Copyright (c) 2009 Allen MArincak
'' See end of file for terms of use
'' ===========================================================================
''
''============================================================================
'' Status Lamp
''============================================================================
''
'' Creates status lamp to provide visual feedback of conditions.
''
'' You create this item with the Init() function then you must set a status
'' right away, on or off (or else it will not show anything).
VAR
word varGdx 'GUI control variable
long varVgaPos 'screen location of start of input area
long varScreenPtr 'screen buffer pointer
long varCxPtr 'points to the text cursor x position variable
byte varRow 'top row location
byte varCol 'left col location
byte varCol2 'right col location
byte varWidth 'width ... text width is 2 less than total width
byte varTitleWidth 'number of rows used for title area ( 0 or 2 )
byte varStatus '0 = off 1 = on
byte varVgaCols 'width of screen in columns
PUB Init ( pRow, pCol, pWidth, pTitlePtr, pVgaPtr, pVgaWidth ) | vgaIdx
varVgaCols := pVgaWidth
varRow := pRow
varCol := pCol
varWidth := pWidth
varTitleWidth := strsize( pTitlePtr )
varScreenPtr := pVgaPtr
varCol2 := varCol + varWidth
vgaIdx := varRow * varVgaCols + varCol
bytefill( @byte[varScreenPtr][vgaIdx], 32, varWidth )
bytemove( @byte[varScreenPtr][vgaIdx], pTitlePtr, varTitleWidth )
varVgaPos := varRow*varVgaCols+varCol+varWidth-4 'save status text area start
byte[varScreenPtr][varVgaPos-2] := ":"
PUB IsIn( pCx, pCy ) : qq
qq := false
if ( pCx => varCol ) AND ( pCx =< varCol2 )
if pCy == varRow
qq := true
return qq
PUB Set( pSet, pStr ) | strLen
varStatus := pSet
strLen := strsize( pStr )
strLen := 1 #> strLen <# 4
bytefill( @byte[varScreenPtr][varVgaPos], 32, 4 )
bytemove( @byte[varScreenPtr][varVgaPos], pStr, strLen )
if varStatus == 1
byte[varScreenPtr][varVgaPos+0] += 128
byte[varScreenPtr][varVgaPos+1] += 128
byte[varScreenPtr][varVgaPos+2] += 128
byte[varScreenPtr][varVgaPos+3] += 128
PUB GetStatus
return varStatus
PUB set_gzidx( gzidx )
varGdx := gzidx
PUB get_gzidx
return varGdx
{{
┌────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy│
│of this software and associated documentation files (the "Software"), to │
│deal in the Software without restriction, including without limitation the │
│rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │
│sell copies of the Software, and to permit persons to whom the Software is │
│furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in │
│all copies or substantial portions of the Software. │
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
│IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
│FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
│AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
│LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │
│FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS│
│IN THE SOFTWARE. │
└────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,195 @@
'' ===========================================================================
'' VGA High-Res Text UI Elements Base UI Support Functions v1.2
''
'' File: TextBox.spin
'' Author: Allen Marincak
'' Copyright (c) 2009 Allen MArincak
'' See end of file for terms of use
'' ===========================================================================
''
''============================================================================
'' TextBox Control
''============================================================================
''
'' Creates a simple text box with auto scrolling text area
''
'' This control is a text window that you can print ASCII strings to. You can
'' set it to truncate ot wrap long lines. If lines are wrapped all wrapped
'' lines will be prefixed with an inverted right arrow character to mark the
'' wrapping operation. Leading and trailing CRLF characters are stripped from
'' the string but CRLFs inside the string remain and will be print as "funny"
'' characters. A titlebar with a caption may optionally be applied.
OBJ
SBOX : "SimpleBox"
VAR
word varGdx 'GUI control variable
long varScreenPtr 'screen buffer pointer
byte varRow 'top row location
byte varRow2 'bottom row location
byte varCol 'left col location
byte varCol2 'right col location
byte varWidth 'width ... text width is 2 less than total width
byte varHeight 'height ... text height is 2 or 4 less than total height
byte varTitle 'number of rows used for title area ( 0 or 2 )
byte varRowIdx 'index to current row to be written
byte varVgaCols 'width of screen in columns
byte varWrap '0=truncate lines 1=wrap lines (marks wrapped lines)
PUB Init( pRow, pCol, pWidth, pHeight, pWrap, pTitlePtr, pVgaPtr, pVgaWidth )
varVgaCols := pVgaWidth
varRow := pRow
varCol := pCol
varWidth := pWidth
varHeight := pHeight
varWrap := pWrap
varRow2 := pRow + 2
varCol2 := pCol + pWidth - 1
varRowIdx := 0
varScreenPtr := pVgaPtr
if pTitlePtr == 0 'no title text ?
varTitle := 0
else
varTitle := 2
SBOX.DrawBox( pRow, pCol, pWidth, pHeight, pTitlePtr, pVgaPtr, pVgaWidth )
PUB IsIn( pCx, pCy ) : qq
qq := false
if ( pCx => varCol ) AND ( pCx =< varCol2 )
if ( pCy => ( varRow + varTitle ) ) AND ( pCy =< varRow2 )
qq := true
return qq
PUB Clear | tbRows, idx, vgaIdx
tbRows := varHeight - varTitle - 2
vgaIdx := ( varRow + varTitle + 1 ) * varVgaCols + varCol + 1
repeat tbRows
bytefill( @byte[varScreenPtr][vgaIdx], 32, varWidth - 2 )
vgaIdx += varVgaCols
varRowIdx := 0
PUB Print( pTxtPtr, pSize ) | strLen, tbRows, vgaIdx
tbRows := varHeight - varTitle - 2
if varRowIdx == tbRows 'if full, scroll up
Scroll
vgaIdx := (varRow+varTitle+varRowIdx+1)*varVgaCols+varCol+1 'index to screen
if pSize <> 0 'determine string size
strLen := pSize
else
strLen := strsize( pTxtPtr )
if strlen > 0 'strip leading CRLF
repeat while byte[pTxtPtr][0] < 32
strLen--
pTxtPtr++
if strLen == 0
quit
if strLen > 0 'strip trailing CRLF
repeat while byte[pTxtPtr][strLen-1] < 32
strLen--
if strLen == 0
quit
if varWrap == 0 'if not wrapping lines
strLen <#= (varWidth-2) ' - truncate line length to window width
if strLen =< varWidth-2
bytemove(@byte[varScreenPtr][vgaIdx],pTxtPtr,strLen)' - copy whole string
if varRowIdx < tbRows
varRowIdx++
else
bytemove(@byte[varScreenPtr][vgaIdx],pTxtPtr,varWidth-2)' - copy part string
if varRowIdx < tbRows
varRowIdx++
strlen -= varWidth-2
pTxtPtr += varWidth-2
repeat 'repeat till all of string done
if varRowIdx == tbRows 'scroll if required
Scroll
vgaIdx := (varRow+varTitle+varRowIdx+1)*varVgaCols+varCol+1 'index to screen
byte[varScreenPtr][vgaIdx] := $81 'inverted right arrow to show wrap
if strLen =< varWidth-3
bytemove(@byte[varScreenPtr][vgaIdx+1],pTxtPtr,strLen)' - copy remaining string
if varRowIdx < tbRows
varRowIdx++
quit
else
bytemove(@byte[varScreenPtr][vgaIdx+1],pTxtPtr,varWidth-3)' copy part string
strlen -= varWidth-3
pTxtPtr += varWidth-3
if varRowIdx < tbRows
varRowIdx++
PUB Scroll | vgaIdx, tbRows
tbRows := varHeight - varTitle - 2
vgaIdx := ( varRow + varTitle + 1 ) * varVgaCols + varCol
repeat tbRows - 1
longmove( @byte[varScreenPtr][vgaIdx], @byte[varScreenPtr][vgaIdx+varVgaCols], varWidth / 4 )
vgaIdx += varVgaCols
bytefill( @byte[varScreenPtr][vgaIdx+1], 32, varWidth - 2 )
varRowIdx--
PUB Title( pTxtPtr ) | strIdx, vgaIdx
if varTitle <> 0
strIdx := strSize( pTxtPtr )
vgaIdx := varRow * varVgaCols + varCol + varVgaCols +1 'title location
bytefill( @byte[varScreenPtr][vgaIdx], 32, varWidth - 2 )
bytemove( @byte[varScreenPtr][vgaIdx], pTxtPtr, strIdx )
PUB set_gzidx( gzidx )
varGdx := gzidx
PUB get_gzidx
return varGdx
{{
┌────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy│
│of this software and associated documentation files (the "Software"), to │
│deal in the Software without restriction, including without limitation the │
│rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │
│sell copies of the Software, and to permit persons to whom the Software is │
│furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in │
│all copies or substantial portions of the Software. │
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
│IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
│FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
│AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
│LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │
│FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS│
│IN THE SOFTWARE. │
└────────────────────────────────────────────────────────────────────────────┘
}}

128
source/gui-demo/Timer.spin Normal file
View File

@ -0,0 +1,128 @@
'' ===========================================================================
'' VGA High-Res Text UI Elements Base UI Support Functions v1.2
''
'' FILE: Timer.spin
'' Author: Allen Marincak
'' Copyright (c) 2009 Allen MArincak
'' See end of file for terms of use
'' ===========================================================================
''
'' ============================================================================
'' Timer function
'' ============================================================================
''
'' Starts a new cog to provide timing functionality.
''
'' There are 8 timers available, the code running on the new cog simply
'' decrements each timer value at the rate specified in the start() call.
''
'' Only the first object to create this needs to call the START method. That
'' will launch it on a new COG, other objects can reference it in the OBJ
'' section but do not need to start it, just call the public methods.
'' ============================================================================
DAT
' stack size determined StackLengthAJM.spin
cog long 0 'cog execute is running on
stack long 0,0,0,0,0,0,0,0,0,0,0,0 'stack space 12 longs
tmrs_used byte 0,0,0,0,0,0,0,0 'bitfield signifying timers in use
timers word 0,0,0,0,0,0,0,0 'timer values (16 bit)
PUB start( period ) : okay1
''
'' Launches TIMER TASK on new cog, returns 0 on error, else the cog that was
'' started up.
'' - period is the fractional part of a second to operate at
'' example: 10 = 1/10th of a second
'' 30 = 1/30th of a second
'' 100 = 1/100th of a second
wordfill( @timers, 0, 8 )
bytefill( @tmrs_used, 0, 8 )
cog := cognew( execute( period, @timers ), @stack ) + 1
okay1 := cog
PUB register : new_tmr | idx
'' Register a timer. Returns the first free timer (8 timers numbered 0 to 7)
'' or returns -1 if none are available.
repeat idx from 0 to 7
if tmrs_used[idx] == 0
tmrs_used[idx] := 1
new_tmr := idx
return
new_tmr := -1
PUB unregister( tmrid )
'' Unregisters a timer, frees it up for reuse.
if tmrs_used[tmrid] == 1
timers[tmrid] := 0
tmrs_used[tmrid] := 0
PUB set( tmrid, val )
'' Sets a registered timer with a 16 bit value.
if tmrs_used[tmrid] == 1
timers[tmrid] := val
PUB isClr( tmrid ): clr
'' Checks the status of the registered timer.
'' returns 1 if it has expired (zeroed)
'' 0 if is still running
clr := 0
if timers[tmrid] == 0
clr := 1
PUB read( tmrid )
'' returns the current count of a registered timer.
return timers[tmrid]
PRI execute( period, ptr_tmrs ) | idx, interval_cnt, time_base
'' new cog executes this, it just decrements the timers
interval_cnt := clkfreq / period
time_base := cnt
repeat
waitcnt( time_base += interval_cnt )
repeat idx from 0 to 7
if word[ptr_tmrs][idx] <> 0
word[ptr_tmrs][idx] -= 1
{{
┌────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy│
│of this software and associated documentation files (the "Software"), to │
│deal in the Software without restriction, including without limitation the │
│rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │
│sell copies of the Software, and to permit persons to whom the Software is │
│furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in │
│all copies or substantial portions of the Software. │
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │
│IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │
│FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │
│AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │
│LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │
│FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS│
│IN THE SOFTWARE. │
└────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,542 @@
''***************************************
''* VGA High-Res Text Driver v1.0 *
''* Author: Chip Gracey *
''* Copyright (c) 2006 Parallax, Inc. *
''* See end of file for terms of use. *
''***************************************
''
'' This object generates a 1024x768 VGA signal which contains 128 columns x 64
'' rows of 8x12 characters. Each row can have a unique forground/background
'' color combination and each character can be inversed. There are also two
'' cursors which can be independently controlled (ie. mouse and keyboard). A
'' sync indicator signals each time the screen is refreshed (you may ignore).
''
'' You must provide buffers for the screen, colors, cursors, and sync. Once
'' started, all interfacing is done via memory. To this object, all buffers are
'' read-only, with the exception of the sync indicator which gets written with
'' -1. You may freely write all buffers to affect screen appearance. Have fun!
''
CON
'{' 1024 x 768 @ 57Hz settings: 128 x 64 characters
hp = 1024 'horizontal pixels
vp = 768 'vertical pixels
hf = 16 'horizontal front porch pixels
hs = 96 'horizontal sync pixels
hb = 176 'horizontal back porch pixels
vf = 1 'vertical front porch lines
vs = 3 'vertical sync lines
vb = 28 'vertical back porch lines
hn = 1 'horizontal normal sync state (0|1)
vn = 1 'vertical normal sync state (0|1)
pr = 60 'pixel rate in MHz at 80MHz system clock (5MHz granularity)
'}
{' 800 x 600 @ 75Hz settings: 100 x 50 characters
hp = 800 'horizontal pixels
vp = 600 'vertical pixels
hf = 40 'horizontal front porch pixels
hs = 128 'horizontal sync pixels
hb = 88 'horizontal back porch pixels
vf = 1 'vertical front porch lines
vs = 4 'vertical sync lines
vb = 23 'vertical back porch lines
hn = 0 'horizontal normal sync state (0|1)
vn = 0 'vertical normal sync state (0|1)
pr = 50 'pixel rate in MHz at 80MHz system clock (5MHz granularity)
}
{' 640 x 480 @ 69Hz settings: 80 x 40 characters
hp = 640 'horizontal pixels
vp = 480 'vertical pixels
hf = 24 'horizontal front porch pixels
hs = 40 'horizontal sync pixels
hb = 128 'horizontal back porch pixels
vf = 9 'vertical front porch lines
vs = 3 'vertical sync lines
vb = 28 'vertical back porch lines
hn = 1 'horizontal normal sync state (0|1)
vn = 1 'vertical normal sync state (0|1)
pr = 30 'pixel rate in MHz at 80MHz system clock (5MHz granularity)
}
' columns and rows
cols = hp / 8
rows = vp / 12
VAR long cog[2]
PUB start(BasePin, ScreenPtr, ColorPtr, CursorPtr, SyncPtr) : okay | i, j
'' Start VGA driver - starts two COGs
'' returns false if two COGs not available
''
'' BasePin = VGA starting pin (0, 8, 16, 24, etc.)
''
'' ScreenPtr = Pointer to 8,192 bytes containing ASCII codes for each of the
'' 128x64 screen characters. Each byte's top bit controls color
'' inversion while the lower seven bits provide the ASCII code.
'' Screen memory is arranged left-to-right, top-to-bottom.
''
'' screen byte example: %1_1000001 = inverse "A"
''
'' ColorPtr = Pointer to 64 words which define the foreground and background
'' colors for each row. The lower byte of each word contains the
'' foreground RGB data for that row, while the upper byte
'' contains the background RGB data. The RGB data in each byte is
'' arranged as %RRGGBB00 (4 levels each).
''
'' color word example: %%0020_3300 = gold on blue
''
'' CursorPtr = Pointer to 6 bytes which control the cursors:
''
'' bytes 0,1,2: X, Y, and MODE of cursor 0
'' bytes 3,4,5: X, Y, and MODE of cursor 1
''
'' X and Y are in terms of screen characters
'' (left-to-right, top-to-bottom)
''
'' MODE uses three bottom bits:
''
'' %x00 = cursor off
'' %x01 = cursor on
'' %x10 = cursor on, blink slow
'' %x11 = cursor on, blink fast
'' %0xx = cursor is solid block
'' %1xx = cursor is underscore
''
'' cursor example: 127, 63, %010 = blinking block in lower-right
''
'' SyncPtr = Pointer to long which gets written with -1 upon each screen
'' refresh. May be used to time writes/scrolls, so that chopiness
'' can be avoided. You must clear it each time if you want to see
'' it re-trigger.
'if driver is already running, stop it
stop
'implant pin settings
reg_vcfg := $200000FF + (BasePin & %111000) << 6
i := $FF << (BasePin & %011000)
j := BasePin & %100000 == 0
reg_dira := i & j
reg_dirb := i & !j
'implant CNT value to sync COGs to
sync_cnt := cnt + $10000
'implant pointers
longmove(@screen_base, @ScreenPtr, 3)
font_base := @font
'implant unique settings and launch first COG
vf_lines.byte := vf
vb_lines.byte := vb
font_third := 1
cog[1] := cognew(@d0, SyncPtr) + 1
'allow time for first COG to launch
waitcnt($2000 + cnt)
'differentiate settings and launch second COG
vf_lines.byte := vf+4
vb_lines.byte := vb-4
font_third := 0
cog[0] := cognew(@d0, SyncPtr) + 1
'if both COGs launched, return true
if cog[0] and cog[1]
return true
'else, stop any launched COG and return false
else
stop
PUB stop | i
'' Stop VGA driver - frees two COGs
repeat i from 0 to 1
if cog[i]
cogstop(cog[i]~ - 1)
CON
#1, scanbuff[128], scancode[128*2-1+3], maincode 'enumerate COG RAM usage
main_size = $1F0 - maincode 'size of main program
hv_inactive = (hn << 1 + vn) * $0101 'H,V inactive states
DAT
'*****************************************************
'* Assembly language VGA high-resolution text driver *
'*****************************************************
' This program runs concurrently in two different COGs.
'
' Each COG's program has different values implanted for front-porch lines and
' back-porch lines which surround the vertical sync pulse lines. This allows
' timed interleaving of their active display signals during the visible portion
' of the field scan. Also, they are differentiated so that one COG displays
' even four-line groups while the other COG displays odd four-line groups.
'
' These COGs are launched in the PUB 'start' and are programmed to synchronize
' their PLL-driven video circuits so that they can alternately prepare sets of
' four scan lines and then display them. The COG-to-COG switchover is seemless
' due to two things: exact synchronization of the two video circuits and the
' fact that all COGs' driven output states get OR'd together, allowing one COG
' to output lows during its preparatory state while the other COG effectively
' drives the pins to create the visible and sync portions of its scan lines.
' During non-visible scan lines, both COGs output together in unison.
'
' COG RAM usage: $000 = d0 - used to inc destination fields for indirection
' $001-$080 = scanbuff - longs which hold 4 scan lines
' $081-$182 = scancode - stacked WAITVID/SHR for fast display
' $183-$1EF = maincode - main program loop which drives display
org 'set origin to $000 for start of program
d0 long 1 << 9 'd0 always resides here at $000, executes as NOP
' Initialization code and data - after execution, space gets reused as scanbuff
'Move main program into maincode area
:move mov $1EF,main_begin+main_size-1
sub :move,d0s0 '(do reverse move to avoid overwrite)
djnz main_ctr,#:move
'Build scanbuff display routine into scancode
:waitvid mov scancode+0,i0 'org scancode
:shr mov scancode+1,i1 'waitvid color,scanbuff+0
add :waitvid,d1 'shr scanbuff+0,#8
add :shr,d1 'waitvid color,scanbuff+1
add i0,#1 'shr scanbuff+1,#8
add i1,d0 '...
djnz scan_ctr,#:waitvid 'waitvid color,scanbuff+cols-1
mov scancode+cols*2-1,i2 'mov vscl,#hf
mov scancode+cols*2+0,i3 'waitvid hvsync,#0
mov scancode+cols*2+1,i4 'jmp #scanret
'Init I/O registers and sync COGs' video circuits
mov dira,reg_dira 'set pin directions
mov dirb,reg_dirb
movi frqa,#(pr / 5) << 2 'set pixel rate
mov vcfg,reg_vcfg 'set video configuration
mov vscl,#1 'set video to reload on every pixel
waitcnt sync_cnt,colormask 'wait for start value in cnt, add ~1ms
movi ctra,#%00001_110 'COGs in sync! enable PLLs now - NCOs locked!
waitcnt sync_cnt,#0 'wait ~1ms for PLLs to stabilize - PLLs locked!
mov vscl,#100 'insure initial WAITVIDs lock cleanly
'Jump to main loop
jmp #vsync 'jump to vsync - WAITVIDs will now be locked!
'Data
d0s0 long 1 << 9 + 1
d1 long 1 << 10
main_ctr long main_size
scan_ctr long cols
i0 waitvid x,scanbuff+0
i1 shr scanbuff+0,#8
i2 mov vscl,#hf
i3 waitvid hvsync,#0
i4 jmp #scanret
reg_dira long 0 'set at runtime
reg_dirb long 0 'set at runtime
reg_vcfg long 0 'set at runtime
sync_cnt long 0 'set at runtime
'Directives
fit scancode 'make sure initialization code and data fit
main_begin org maincode 'main code follows (gets moved into maincode)
' Main loop, display field - each COG alternately builds and displays four scan lines
vsync mov x,#vs 'do vertical sync lines
call #blank_vsync
vb_lines mov x,#vb 'do vertical back porch lines (# set at runtime)
call #blank_vsync
mov screen_ptr,screen_base 'reset screen pointer to upper-left character
mov color_ptr,color_base 'reset color pointer to first row
mov row,#0 'reset row counter for cursor insertion
mov fours,#rows * 3 / 2 'set number of 4-line builds for whole screen
'Build four scan lines into scanbuff
fourline mov font_ptr,font_third 'get address of appropriate font section
shl font_ptr,#7+2
add font_ptr,font_base
movd :pixa,#scanbuff-1 'reset scanbuff address (pre-decremented)
movd :pixb,#scanbuff-1
mov y,#2 'must build scanbuff in two sections because
mov vscl,vscl_line2x '..pixel counter is limited to twelve bits
:halfrow waitvid underscore,#0 'output lows to let other COG drive VGA pins
mov x,#cols/2 '..for 2 scan lines, ready for half a row
:column rdbyte z,screen_ptr 'get character from screen memory
ror z,#7 'get inverse flag into bit 0, keep chr high
shr z,#32-7-2 wc 'get inverse flag into c, chr into bits 8..2
add z,font_ptr 'add font section address to point to 8*4 pixels
add :pixa,d0 'increment scanbuff destination addresses
add :pixb,d0
add screen_ptr,#1 'increment screen memory address
:pixa rdlong scanbuff,z 'read pixel long (8*4) into scanbuff
:pixb if_nc xor scanbuff,longmask 'invert pixels according to inverse flag
djnz x,#:column 'another character in this half-row?
djnz y,#:halfrow 'loop to do 2nd half-row, time for 2nd WAITVID
sub screen_ptr,#cols 'back up to start of same row in screen memory
'Insert cursors into scanbuff
mov z,#2 'ready for two cursors
:cursor rdbyte x,cursor_base 'x in range?
add cursor_base,#1
cmp x,#cols wc
rdbyte y,cursor_base 'y match?
add cursor_base,#1
cmp y,row wz
rdbyte y,cursor_base 'get cursor mode
add cursor_base,#1
if_nc_or_nz jmp #:nocursor 'if cursor not in scanbuff, no cursor
add x,#scanbuff 'cursor in scanbuff, set scanbuff address
movd :xor,x
test y,#%010 wc 'get mode bits into flags
test y,#%001 wz
if_nc_and_z jmp #:nocursor 'if cursor disabled, no cursor
if_c_and_z test slowbit,cnt wc 'if blink mode, get blink state
if_c_and_nz test fastbit,cnt wc
test y,#%100 wz 'get box or underscore cursor piece
if_z mov x,longmask
if_nz mov x,underscore
if_nz cmp font_third,#2 wz 'if underscore, must be last font section
:xor if_nc_and_z xor scanbuff,x 'conditionally xor cursor into scanbuff
:nocursor djnz z,#:cursor 'second cursor?
sub cursor_base,#3*2 'restore cursor base
'Display four scan lines from scanbuff
rdword x,color_ptr 'get color pattern for current row
and x,colormask 'mask away hsync and vsync signal states
or x,hv 'insert inactive hsync and vsync states
mov y,#4 'ready for four scan lines
scanline mov vscl,vscl_chr 'set pixel rate for characters
jmp #scancode 'jump to scanbuff display routine in scancode
scanret mov vscl,#hs 'do horizontal sync pixels
waitvid hvsync,#1 '#1 makes hsync active
mov vscl,#hb 'do horizontal back porch pixels
waitvid hvsync,#0 '#0 makes hsync inactive
shr scanbuff+cols-1,#8 'shift last column's pixels right by 8
djnz y,#scanline 'another scan line?
'Next group of four scan lines
add font_third,#2 'if font_third + 2 => 3, subtract 3 (new row)
cmpsub font_third,#3 wc 'c=0 for same row, c=1 for new row
if_c add screen_ptr,#cols 'if new row, advance screen pointer
if_c add color_ptr,#2 'if new row, advance color pointer
if_c add row,#1 'if new row, increment row counter
djnz fours,#fourline 'another 4-line build/display?
'Visible section done, do vertical sync front porch lines
wrlong longmask,par 'write -1 to refresh indicator
vf_lines mov x,#vf 'do vertical front porch lines (# set at runtime)
call #blank
jmp #vsync 'new field, loop to vsync
'Subroutine - do blank lines
blank_vsync xor hvsync,#$101 'flip vertical sync bits
blank mov vscl,hx 'do blank pixels
waitvid hvsync,#0
mov vscl,#hf 'do horizontal front porch pixels
waitvid hvsync,#0
mov vscl,#hs 'do horizontal sync pixels
waitvid hvsync,#1
mov vscl,#hb 'do horizontal back porch pixels
waitvid hvsync,#0
djnz x,#blank 'another line?
blank_ret
blank_vsync_ret ret
'Data
screen_base long 0 'set at runtime (3 contiguous longs)
color_base long 0 'set at runtime
cursor_base long 0 'set at runtime
font_base long 0 'set at runtime
font_third long 0 'set at runtime
hx long hp 'visible pixels per scan line
vscl_line2x long (hp + hf + hs + hb) * 2 'total number of pixels per 2 scan lines
vscl_chr long 1 << 12 + 8 '1 clock per pixel and 8 pixels per set
colormask long $FCFC 'mask to isolate R,G,B bits from H,V
longmask long $FFFFFFFF 'all bits set
slowbit long 1 << 25 'cnt mask for slow cursor blink
fastbit long 1 << 24 'cnt mask for fast cursor blink
underscore long $FFFF0000 'underscore cursor pattern
hv long hv_inactive '-H,-V states
hvsync long hv_inactive ^ $200 '+/-H,-V states
'Uninitialized data
screen_ptr res 1
color_ptr res 1
font_ptr res 1
x res 1
y res 1
z res 1
row res 1
fours res 1
' 8 x 12 font - characters 0..127
'
' Each long holds four scan lines of a single character. The longs are arranged into
' groups of 128 which represent all characters (0..127). There are three groups which
' each contain a vertical third of all characters. They are ordered top, middle, and
' bottom.
'
' NOTE: MSB set inverts the character. i.e. $31 = a 1 $B1 = an inverted 1
'
' char 0 = ← left arrow
' char 1 = → right arrow
' char 2 = ↑ up arrow
' char 3 = ↓ down arrow
' char 4 = empty circle bullet (radio button)
' char 5 = filled circle bullet (radio button)
' char 6 = empty square bullet (check box)
' char 7 = filled square bullet (check box)
' char 8 = ▶ right triangle bullet
' char 9 = • small bullet
' char 10 = ┌ top left corner (but curved)
' char 11 = ┐ top right corner (but curved)
' char 12 = └ bottom left corner (but curved)
' char 13 = ┘ bottom right corner (but curved)
' char 14 = ─ horizontal line
' char 15 = │ vertical line
' char 16 = ┬ top 'tee'
' char 17 = ┴ bottom 'tee'
' char 18 = ├ left 'tee'
' char 19 = ┤ right 'tee'
' char 20 = ┼ cross point
font long
long $0C080000,$30100000,$7E3C1800,$18181800,$81423C00,$99423C00,$8181FF00,$E7C3FF00 'top
long $1E0E0602,$1C000000,$00000000,$00000000,$18181818,$18181818,$00000000,$18181818
long $00000000,$18181818,$18181818,$18181818,$18181818,$00FFFF00,$CC993366,$66666666
long $AA55AA55,$0F0F0F0F,$0F0F0F0F,$0F0F0F0F,$0F0F0F0F,$00000000,$00000000,$00000000
long $00000000,$3C3C1800,$77666600,$7F363600,$667C1818,$46000000,$1B1B0E00,$1C181800
long $0C183000,$180C0600,$66000000,$18000000,$00000000,$00000000,$00000000,$60400000
long $73633E00,$1E181000,$66663C00,$60663C00,$3C383000,$06067E00,$060C3800,$63637F00
long $66663C00,$66663C00,$1C000000,$00000000,$18306000,$00000000,$180C0600,$60663C00
long $63673E00,$66663C00,$66663F00,$63663C00,$66361F00,$06467F00,$06467F00,$63663C00
long $63636300,$18183C00,$30307800,$36666700,$06060F00,$7F776300,$67636300,$63361C00
long $66663F00,$63361C00,$66663F00,$66663C00,$185A7E00,$66666600,$66666600,$63636300
long $66666600,$66666600,$31637F00,$0C0C3C00,$03010000,$30303C00,$361C0800,$00000000
long $0C000000,$00000000,$06060700,$00000000,$30303800,$00000000,$0C6C3800,$00000000
long $06060700,$00181800,$00606000,$06060700,$18181E00,$00000000,$00000000,$00000000
long $00000000,$00000000,$00000000,$00000000,$0C080000,$00000000,$00000000,$00000000
long $00000000,$00000000,$00000000,$18187000,$18181800,$18180E00,$73DBCE00,$18180000
long $080C7E7E,$10307E7E,$18181818,$7E181818,$81818181,$99BDBDBD,$81818181,$E7BD99BD 'middle
long $1E3E7E3E,$1C3E3E3E,$30F0C000,$0C0F0300,$00C0F030,$00030F0C,$00FFFF00,$18181818
long $18FFFF00,$00FFFF18,$18F8F818,$181F1F18,$18FFFF18,$00FFFF00,$CC993366,$66666666
long $AA55AA55,$FFFF0F0F,$F0F00F0F,$0F0F0F0F,$00000F0F,$FFFF0000,$F0F00000,$0F0F0000
long $00000000,$0018183C,$00000033,$7F363636,$66603C06,$0C183066,$337B5B0E,$0000000C
long $0C060606,$18303030,$663CFF3C,$18187E18,$00000000,$00007E00,$00000000,$060C1830
long $676F6B7B,$18181818,$0C183060,$60603860,$307F3336,$60603E06,$66663E06,$0C183060
long $66763C6E,$60607C66,$1C00001C,$00001C1C,$180C060C,$007E007E,$18306030,$00181830
long $033B7B7B,$66667E66,$66663E66,$63030303,$66666666,$06263E26,$06263E26,$63730303
long $63637F63,$18181818,$33333030,$36361E36,$66460606,$63636B7F,$737B7F6F,$63636363
long $06063E66,$7B636363,$66363E66,$66301C06,$18181818,$66666666,$66666666,$366B6B63
long $663C183C,$18183C66,$43060C18,$0C0C0C0C,$30180C06,$30303030,$00000063,$00000000
long $0030381C,$333E301E,$6666663E,$0606663C,$3333333E,$067E663C,$0C0C3E0C,$3333336E
long $66666E36,$1818181C,$60606070,$361E3666,$18181818,$6B6B6B3F,$6666663E,$6666663C
long $6666663B,$3333336E,$066E7637,$300C663C,$0C0C0C7E,$33333333,$66666666,$6B6B6363
long $1C1C3663,$66666666,$0C30627E,$180C060C,$18181818,$18306030,$00000000,$0018187E
long $00000000,$00000000,$00001818,$0000183C,$00003C42,$00003C42,$0000FF81,$0000FFC3 'bottom
long $0002060E,$00000000,$18181818,$18181818,$00000000,$00000000,$00000000,$18181818
long $18181818,$00000000,$18181818,$18181818,$18181818,$00FFFF00,$CC993366,$66666666
long $AA55AA55,$FFFFFFFF,$F0F0F0F0,$0F0F0F0F,$00000000,$FFFFFFFF,$F0F0F0F0,$0F0F0F0F
long $00000000,$00001818,$00000000,$00003636,$0018183E,$00006266,$00006E3B,$00000000
long $00003018,$0000060C,$00000000,$00000000,$0C181C1C,$00000000,$00001C1C,$00000103
long $00003E63,$00007E18,$00007E66,$00003C66,$00007830,$00003C66,$00003C66,$00000C0C
long $00003C66,$00001C30,$0000001C,$0C181C1C,$00006030,$00000000,$0000060C,$00001818
long $00003E07,$00006666,$00003F66,$00003C66,$00001F36,$00007F46,$00000F06,$00007C66
long $00006363,$00003C18,$00001E33,$00006766,$00007F66,$00006363,$00006363,$00001C36
long $00000F06,$00603C36,$00006766,$00003C66,$00003C18,$00003C66,$0000183C,$00003636
long $00006666,$00003C18,$00007F63,$00003C0C,$00004060,$00003C30,$00000000,$FFFF0000
long $00000000,$00006E33,$00003B66,$00003C66,$00006E33,$00003C66,$00001E0C,$1E33303E
long $00006766,$00007E18,$3C666660,$00006766,$00007E18,$00006B6B,$00006666,$00003C66
long $0F063E66,$78303E33,$00000F06,$00003C66,$0000386C,$00006E33,$0000183C,$00003636
long $00006336,$1C30607C,$00007E46,$00007018,$00001818,$00000E18,$00000000,$0000007E
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,545 @@
{{
┌────────────────────────────────────────┬────────────────┬────────────────────────┬──────────────────┐
│ VGA 1024x768 Tile Driver v0.9 │ by Chip Gracey │ (C)2006 Parallax, Inc. │ 11 November 2006 │
├────────────────────────────────────────┴────────────────┴────────────────────────┴──────────────────┤
│ │
│ This object generates a 1024x768 VGA display from a 64x48 array of 16x16-pixel 4-color tiles. │
│ It requires two cogs (or three with optional cursor enabled) and at least 80 MHz. │
│ │
└─────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}
CON
' 1024 x 768 @ 60Hz settings
hp = 1024 'horizontal pixels
vp = 768 'vertical pixels
hf = 16 'horizontal front porch pixels
hs = 96 'horizontal sync pixels
hb = 176 'horizontal back porch pixels
vf = 1 'vertical front porch lines
vs = 3 'vertical sync lines
vb = 28 'vertical back porch lines
pr = 60 'pixel rate in MHz at 80MHz system clock (5MHz granularity)
ht = hp + hf + hs + hb 'total scan line pixels
' Tile array
xtiles = hp / 16
ytiles = vp / 16
COLS = 64
ROWS = 48
VAR
long cog[3]
long dira_ '9 contiguous longs
long dirb_
long vcfg_
long cnt_
long array_ptr_
long color_ptr_
long cursor_ptr_
long sync_ptr_
long mode_
PUB start(base_pin, array_ptr, color_ptr, cursor_ptr, sync_ptr, mode) : okay | i, j
'' Start driver - starts two or three cogs
'' returns false if cogs not available
''
'' base_pin = First of eight VGA pins, must be a multiple of eight (0, 8, 16, 24, etc):
''
'' 240Ω 240Ω 240Ω 240Ω
'' +7 ───┳─ Red +5 ───┳─ Green +3 ───┳─ Blue +1 ── H
'' 470Ω │ 470Ω │ 470Ω │ 240Ω
'' +6 ───┘ +4 ───┘ +2 ───┘ +0 ── V
''
'' array_ptr = Pointer to 3,072 long-aligned words, organized as 64 across by 48 down,
'' which will serve as the tile array. Each word specifies a tile bitmap and
'' a color palette for its tile area. The top 10 bits of each word form the
'' base address of a 16-long tile bitmap, while the lower 6 bits select a
'' color palette for the bitmap. For example, $B2E5 would specify the tile
'' bitmap spanning $B2C0..$B2FF and color palette $25.
''
'' color_ptr = Pointer to 64 longs which will define the 64 color palettes. The RGB data
'' in each long is arranged as %%RGBx_RGBx_RGBx_RGBx with the sub-bytes 3..0
'' providing the color data for pixel values %11..%00, respectively:
''
'' %%3330_0110_0020_3300: %11=white, %10=dark cyan, %01=blue, %00=gold
''
'' cursor_ptr = Pointer to 4 longs which will control the cursor, or 0 to disable the
'' cursor. If a pointer is given, an extra cog will be started to generate
'' the cursor overlay. Here are the 4 longs that control the cursor:
''
'' cursor_x - X position of cursor: ..0..1023.. (left to right)
'' cursor_y - Y position of cursor: ..0..767.. (bottom to top)
''
'' cursor_color - Cursor color to be OR'd to background color as %%RGBx:
'' %%3330=white, %%2220 or %%1110=translucent, %%0000=off
''
'' cursor_shape - 0 for arrow, 1 for crosshair, or pointer to a cursor
'' definition. A cursor definition consists of 32 longs
'' containing a 32x32 pixel cursor image, followed by two
'' bytes which define the X and Y center-pixel offsets
'' within the image.
''
'' sync_ptr = Pointer to a long which will be set to -1 after each refresh, or 0 to
'' disable this function. This is useful in advanced applications where
'' awareness of display timing is important.
''
'' mode = 0 for normal 16x16 pixel tiles or 1 for taller 16x32 pixel tiles. Mode 1
'' is useful for displaying the internal font while requiring half the array
'' memory; however, the 3-D bevel characters will not be usable because of
'' the larger vertical tile granularity of this mode.
'If driver is already running, stop it
stop
'Ready i/o settings
i := $FF << (base_pin & %011000)
j := base_pin & %100000 == 0
dira_ := i & j
dirb_ := i & !j
vcfg_ := $300000FF + (base_pin & %111000) << 6
'Ready cnt value to sync cogs by
cnt_ := cnt + $100000
'Ready pointers and mode
longmove(@array_ptr_, @array_ptr, 5)
'Launch cogs, abort if error
repeat i from 0 to 2
if i == 2 'cursor cog?
ifnot cursor_ptr 'cursor enabled?
quit 'if not, quit loop
waitcnt($2000 + cnt) 'cursor cog, allow prior cog to launch
vcfg_ ^= $10000000 'set two-color mode
array_ptr_~ 'flag cursor function
ifnot cog[i] := cognew(@entry, @dira_ + i << 15) + 1
stop
return {false}
'Successful
return true
PUB stop | i
'' Stop driver - frees cogs
'If already running, stop any VGA cogs
repeat i from 0 to 2
if cog[i]
cogstop(cog[i]~ - 1)
DAT
' ┌─────────────────────────────┐
' │ Initialization - all cogs │
' └─────────────────────────────┘
org
' Move field loop into position
entry mov field,field_code
add entry,d0s0_
djnz regs,#entry
' Acquire settings
mov regs,par 'dira_ ─ dira
cmpsub regs,bit15 wc 'dirb_ ─ dirb
:next movd :read,sprs 'vcfg_ ─ vcfg
or :read,d8_d4 'cnt_ ─ cnt
shr sprs,#4 'array_ptr_ ─ ctrb
:read rdlong dira,regs 'color_ptr_ ─ frqb
add regs,#4 'cursor_ptr_ ─ vscl
tjnz sprs,#:next 'sync_ptr_ ─ phsb
sumc vf_lines,#2 'alter scan line settings by cog
sumnc vb_lines,#2
sumnc tile_line,#2 * 4
rdlong regs,regs wz 'if mode not 0, set tile size to 16 x 32 pixels
if_nz movs tile_bytes,#32 * 4
if_nz shr array_bytes,#1
mov regs,vscl 'save cursor pointer
' Synchronize all cogs' video circuits so that waitvid's will be pixel-locked
movi frqa,#(pr / 5) << 2 'set pixel rate (VCO runs at 2x)
mov vscl,#1 'set video shifter to reload on every pixel
waitcnt cnt,d8_d4 'wait for sync count, add ~3ms - cogs locked!
movi ctra,#%00001_110 'enable PLLs now - NCOs locked!
waitcnt cnt,#0 'wait ~3ms for PLLs to stabilize - PLLs locked!
mov vscl,#100 'subsequent WAITVIDs will now be pixel-locked!
' Determine if this cog is to perform one of two field functions or the cursor function
tjnz ctrb,#vsync 'if array ptr, jump to field function
'else, cursor function follows
' ┌─────────────────────────┐
' │ Cursor Loop - one cog │
' └─────────────────────────┘
' Do vertical sync lines minus three
cursor mov par,#vf + vs + vb - 6
:loop mov vscl,vscl_line
:vsync waitvid ccolor,#0
djnz par,#:vsync
' Do three lines minus horizontal back porch pixels to buy a big block of time
mov vscl,vscl_three_lines_mhb
waitvid ccolor,#0
' Get cursor data
rdlong cx,regs 'get cursor x
add regs,#4
rdlong cy,regs 'get cursor y
add regs,#4
rdlong ccolor,regs 'get cursor color
add regs,#4
rdlong cshape,regs 'get cursor shape
sub regs,#3 * 4
and ccolor,#$FC 'trim and justify cursor color
shl ccolor,#8
' Build cursor pixels
mov par,#32 'ready for 32 cursor segments
movd :pix,#cpix
mov cnt,cshape
:pixloop cmp cnt,#1 wc, wz 'arrow, crosshair, or custom cursor?
if_a jmp #:custom
if_e jmp #:crosshair
cmp par,#32 wz 'arrow
cmp par,#32-21 wc
if_z mov cseg,h80000000
if_nz_and_nc sar cseg,#1
if_nz_and_c shl cseg,#2
mov coff,#0
jmp #:pix
:crosshair cmp par,#32-15 wz 'crosshair
if_ne mov cseg,h00010000
if_e neg cseg,#2
cmp par,#1 wz
if_e mov cseg,#0
mov coff,h00000F0F
jmp #:pix
:custom rdlong cseg,cshape 'custom
add cshape,#4
rdlong coff,cshape
:pix mov cpix,cseg 'save segment into pixels
add :pix,d0
djnz par,#:pixloop 'another segment?
' Compute cursor position
mov cseg,coff 'apply cursor center-pixel offsets
and cseg,#$FF
sub cx,cseg
shr coff,#8
and coff,#$FF
add cy,coff
cmps cx,neg31 wc 'if x out of range, hide cursor via y
if_nc cmps pixels_m1,cx wc
if_c neg cy,#1
mov cshr,#0 'adjust for left-edge clipping
cmps cx,#0 wc
if_c neg cshr,cx
if_c mov cx,#0
mov cshl,#0 'adjust for right-edge clipping
cmpsub cx,pixels_m32 wc
if_c mov cshl,cx
if_c mov cx,pixels_m32
add cx,#hb 'bias x and y for display
sub cy,lines_m1
' Do visible lines with cursor
mov par,lines 'ready for visible scan lines
:line andn cy,#$1F wz, nr 'check if scan line in cursor range
if_z movs :seg,cy 'if in range, get cursor pixels
if_z add :seg,#cpix
if_nz mov cseg,#0 'if out of range, use blank pixels
:seg if_z mov cseg,cpix
if_z rev cseg,#0 'reverse pixels so they map sensibly
if_z shr cseg,cshr 'perform any edge clipping on pixels
if_z shl cseg,cshl
mov vscl,cx 'do left blank pixels (hb+cx)
waitvid ccolor,#0
mov vscl,vscl_cursor 'do cursor pixels (32)
waitvid ccolor,cseg
mov vscl,vscl_line_m32 'do right blank pixels (hp+hf+hs-32-cx)
sub vscl,cx
waitvid ccolor,#0
add cy,#1 'another scan line?
djnz par,#:line
' Do horizontal back porch pixels and loop
mov vscl,#hb
waitvid ccolor,#0
mov par,#vf + vs + vb - 3 'ready to do vertical sync lines
jmp #:loop
' Cursor data
vscl_line long ht 'total pixels per scan line
vscl_three_lines_mhb long ht * 3 - hb 'total pixels per three scan lines minus hb
vscl_line_m32 long ht - 32 'total pixels per scan line minus 32
vscl_cursor long 1 << 12 + 32 '32 pixels per cursor with 1 clock per pixel
lines long vp 'visible scan lines
lines_m1 long vp - 1 'visible scan lines minus 1
pixels_m1 long hp - 1 'visible pixels minus 1
pixels_m32 long hp - 32 'visible pixels minus 32
neg31 long -31
h80000000 long $80000000 'arrow/crosshair cursor data
h00010000 long $00010000
h00000F0F long $00000F0F
' Initialization data
d0s0_ long 1 << 9 + 1 'd and s field increments
regs long $1F0 - field 'number of registers in field loop space
sprs long $DFB91E76 'phsb/vscl/frqb/ctrb/cnt/vcfg/dirb/dira nibbles
bit15 long $8000 'bit15 mask used to differentiate cogs in par
d8_d4 long $0003E000 'bit8..bit4 mask for d field
field_code 'field loop code begins at this offset
' Undefined cursor data
cx res 1
cy res 1
ccolor res 1
cshape res 1
coff res 1
cseg res 1
cshr res 1
cshl res 1
cpix res 32
' ┌─────────────────────────┐
' │ Field Loop - two cogs │
' └─────────────────────────┘
org
' Allocate buffers
palettes res 64 'palettes of colors
colors res xtiles 'colors for tile row
pixels0 res xtiles 'pixels for tile row line +0
pixels1 res xtiles 'pixels for tile row line +1
pixels2 res xtiles 'pixels for tile row line +2
pixels3 res xtiles 'pixels for tile row line +3
' Each cog alternately builds and displays four scan lines
field mov cnt,#ytiles * 4 / 2 'ready number of four-scan-line builds/displays
' Build four scan lines
build_4y movd col0,#colors+0 'reset pointers for scan line buffers
movd col1,#colors+1
movd pix0,#pixels0+0
movd pix1,#pixels1+0
movd pix2,#pixels2+0
movd pix3,#pixels3+0
movd pix4,#pixels0+1
movd pix5,#pixels1+1
movd pix6,#pixels2+1
movd pix7,#pixels3+1
mov ina,#2 'four scan lines require two waitvid's
build_32x mov vscl,vscl_two_lines 'output lows for two scan lines so other cog
:zero waitvid :zero,#0 '..can display while this cog builds (twice)
mov inb,#xtiles / 2 / 2 'build four scan lines for half a row
build_2x rdlong vscl,ctrb 'get pair of words from the tile array
movs col0,vscl 'get color bits from even tile
andn col0,#$1C0
andn vscl,#$3F 'strip color bits and add tile line offset
add vscl,tile_line
col0 mov colors+0,palettes 'get even tile color
add col0,d1
pix0 rdlong pixels0+0,vscl 'get line +0 even tile pixels
add pix0,d1
add vscl,#4
pix1 rdlong pixels1+0,vscl 'get line +1 even tile pixels
add pix1,d1
add vscl,#4
pix2 rdlong pixels2+0,vscl 'get line +2 even tile pixels
add pix2,d1
add vscl,#4
pix3 rdlong pixels3+0,vscl 'get line +3 even tile pixels
add pix3,d1
add ctrb,#2 * 2 'point to next pair of tile words
shr vscl,#16 'shift odd tile word into position
movs col1,vscl 'get color bits from odd tile
andn col1,#$1C0
andn vscl,#$3F 'strip color bits and add tile line offset
add vscl,tile_line
col1 mov colors+1,palettes 'get odd tile color
add col1,d1
pix4 rdlong pixels0+1,vscl 'get line +0 odd tile pixels
add pix4,d1
add vscl,#4
pix5 rdlong pixels1+1,vscl 'get line +1 odd tile pixels
add pix5,d1
add vscl,#4
pix6 rdlong pixels2+1,vscl 'get line +2 odd tile pixels
add pix6,d1
add vscl,#4
pix7 rdlong pixels3+1,vscl 'get line +3 odd tile pixels
add pix7,d1
djnz inb,#build_2x 'loop for next tile pair (48 inst/loop)
djnz ina,#build_32x 'if first half done, loop for 2nd waitvid
sub ctrb,#xtiles * 2 'back up to start of same row
' Display four scan lines
mov inb,#4 'ready for four scan lines
movs :waitvid,#pixels0 'reset waitvid pixel pointer
:line mov ina,#xtiles 'ready for tiles
movd :waitvid,#colors 'reset waitvid color pointer
mov vscl,vscl_tile 'set pixel rate for tiles
:tile cmp ina,#1 wz 'check if last tile
add :waitvid,d0s0 'advance pointers (waitvid already read)
:waitvid waitvid colors,pixels0 'do tile slice
if_nz djnz ina,#:tile 'strange loop allows hsync timing and ina=1
call #hsync 'do horizontal sync (ina=1)
djnz inb,#:line 'another scan line?
' Another four scan lines?
add tile_line,#8 * 4 'advance eight scan lines within tile row
tile_bytes cmpsub tile_line,#16 * 4 wc 'tile row done? (# doubled for mode 1)
if_c add ctrb,#xtiles * 2 'if done, advance array pointer to next row
djnz cnt,#build_4y 'another four scan lines?
sub ctrb,array_bytes 'display done, reset array pointer to top row
' Visible section done, handle sync indicator
cmp cnt,phsb wz 'sync enabled? (cnt=0)
if_nz wrlong neg1,phsb 'if so, write -1 to sync indicator
' Do vertical sync lines and loop
vf_lines mov ina,#vf + 2 'do vertical front porch lines (adjusted ±2)
call #blank
vsync mov ina,#vs 'do vertical sync lines
call #blank_vsync
vb_lines mov ina,#vb - 2 'do vertical back porch lines (adjusted ±2)
movs blank_vsync_ret,#field '(loop to field, blank_vsync follows)
' Subroutine - do blank lines
blank_vsync xor hv_sync,#$0101 'flip vertical sync bits
blank mov vscl,vscl_blank 'do horizontal blank pixels
waitvid hv_sync,#0
hsync mov vscl,#hf 'do horizontal front porch pixels
waitvid hv_sync,#0
mov vscl,#hs 'do horizontal sync pixels
waitvid hv_sync,#1
rdlong vscl,frqb 'update another palette
and vscl,color_mask
:palette mov palettes,vscl
add :palette,d0
add frqb,#4
add par,count_64 wc
if_c movd :palette,#palettes
if_c sub frqb,#64 * 4
mov vscl,#hb 'do horizontal back porch pixels
waitvid hv_sync,#0
djnz ina,#blank 'another blank line?
hsync_ret
blank_ret
blank_vsync_ret ret
' Data
d0s0 long 1 << 9 + 1 'd and s field increments
d0 long 1 << 9 'd field increment
d1 long 2 << 9 'd field double increment
tile_line long 2 * 4 'tile line offset (adjusted ±2 * 4)
array_bytes long xtiles * ytiles * 2 'number of bytes in tile array
vscl_two_lines long ht * 2 'total pixels per two scan lines
vscl_tile long 1 << 12 + 16 '16 pixels per tile with 1 clock per pixel
vscl_blank long hp 'visible pixels per scan line
hv_sync long $0200 '+/-H,-V states
count_64 long $04000000 'addend that sets carry every 64th addition
color_mask long $FCFCFCFC 'mask to isolate R,G,B bits from H,V
neg1 long $FFFFFFFF 'negative 1 to be written to sync indicator

View File

@ -0,0 +1,62 @@
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Autor: Ingo Kripahle │
│ Copyright (c) 2010 Ingo Kripahle │
│ See end of file for terms of use. │
│ Die Nutzungsbedingungen befinden sich am Ende der Datei │
└──────────────────────────────────────────────────────────────────────────────────────────────────────┘
Informationen : hive-project.de
Kontakt : drohne235@googlemail.com
System : TriOS
Name :
Chip : Regnatix
Typ : Programm
Version :
Subversion :
Funktion :
Komponenten : -
COG's : -
Logbuch :
Kommandoliste :
Notizen :
}}
OBJ
ios: "reg-ios"
CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
PUB main | j
ios.start
repeat
ios.printbin(ios.joy,8)
ios.printnl
until ios.key
ios.stop
DAT
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

91
source/plexbus/map.spin Normal file
View File

@ -0,0 +1,91 @@
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Autor: Ingo Kripahle │
│ Copyright (c) 2010 Ingo Kripahle │
│ See end of file for terms of use. │
│ Die Nutzungsbedingungen befinden sich am Ende der Datei │
└──────────────────────────────────────────────────────────────────────────────────────────────────────┘
Informationen : hive-project.de
Kontakt : drohne235@googlemail.com
System : TriOS
Name :
Chip : Regnatix
Typ : Programm
Version :
Subversion :
Funktion :
Komponenten : -
COG's : -
Logbuch :
Kommandoliste :
Notizen :
}}
OBJ
ios: "reg-ios"
CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
PUB main | ack,adr,n
' anzeige einer echtzeitkarte aller 128 slaves am bus
' praktisch um die bausteine zu korrekt zu jumpern
ios.start
ios.plxHalt
n := 0
ios.curoff
ios.printcls
repeat
ios.curhome
ios.printnl
ios.print(string(" 0123456789ABCDEF"))
ios.printnl
repeat adr from 0 to 127
'ios.plxstart
'ack := ios.plxwrite(adr<<1)
'ios.plxstop
ack := ios.plxping(adr)
if n == 0
ios.printhex(adr,2)
ios.printchar(" ")
if ack
ios.printqchar("┼")
else
ios.printqchar("•")
if n++ == 15
ios.printnl
n := 0
until ios.key
ios.stop
DAT
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,72 @@
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Autor: Ingo Kripahle │
│ Copyright (c) 2010 Ingo Kripahle │
│ See end of file for terms of use. │
│ Die Nutzungsbedingungen befinden sich am Ende der Datei │
└──────────────────────────────────────────────────────────────────────────────────────────────────────┘
Informationen : hive-project.de
Kontakt : drohne235@googlemail.com
System : TriOS
Name :
Chip : Regnatix
Typ : Programm
Version :
Subversion :
Funktion :
Komponenten : -
COG's : -
Logbuch :
Kommandoliste :
Notizen :
}}
OBJ
ios: "reg-ios"
CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
PUB main | n,p
ios.start
repeat
' paddle-wert einlesen
' obere 8 bit = digtale kontakte
' untere 8 bit = analogwert
n := ios.paddle
' gesamtwert anzeigen
ios.printhex(n,4)
'analogwert abtrenne
p := n & $0ff
'balken ausgeben
repeat p/5
ios.printchar("*")
ios.printnl
until ios.key
ios.stop
DAT
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,83 @@
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Autor: Ingo Kripahle │
│ Copyright (c) 2010 Ingo Kripahle │
│ See end of file for terms of use. │
│ Die Nutzungsbedingungen befinden sich am Ende der Datei │
└──────────────────────────────────────────────────────────────────────────────────────────────────────┘
Informationen : hive-project.de
Kontakt : drohne235@googlemail.com
System : TriOS
Name :
Chip : Regnatix
Typ : Programm
Version :
Subversion :
Funktion :
Komponenten : -
COG's : -
Logbuch :
Kommandoliste :
Notizen :
}}
OBJ
ios: "reg-ios"
CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
PUB main | n
' demo für die direkte ansteuerung der ports
' es wird port 1 eingelesen und an port 3 an den angeschlossenen
' led's ausgegeben/angezeigt
ios.start
'poller in administra anhalten und i2c-bus anfordern
ios.plxHalt
repeat
'port auslesen
n := ios.plxIn($20) 'pcf8574
'port aus led's ausgeben
ios.plxOut($22,n) 'pcf8574
'zusätzlich den wert auf dem screen ausgeben
ios.printbin(n,8)
ios.printnl
until ios.key
ios.stop
'wenn nach den i2c-operationen weiter automatisch joysticks etc.
'abgefragt werden, muss der bus wieder freigegeben werden
ios.plxRun
DAT
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

View File

@ -0,0 +1,112 @@
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Autor: Ingo Kripahle │
│ Copyright (c) 2010 Ingo Kripahle │
│ See end of file for terms of use. │
│ Die Nutzungsbedingungen befinden sich am Ende der Datei │
└──────────────────────────────────────────────────────────────────────────────────────────────────────┘
Informationen : hive-project.de
Kontakt : drohne235@googlemail.com
System : TriOS
Name :
Chip : Regnatix
Typ : Programm
Version :
Subversion :
Funktion :
Komponenten : -
COG's : -
Logbuch :
Kommandoliste :
Notizen :
}}
OBJ
ios: "reg-ios"
CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
PUB main | p1,p2,p3,a0,a1,a2,a3
ios.start
ios.plxHalt
ios.curoff
ios.printcls
repeat
ios.curhome
ios.printnl
p1 := ios.plxIn($20)
p2 := ios.plxIn($21)
p3 := ios.plxIn($22)
a0 := ios.plxch($48,0)
a1 := ios.plxch($48,1)
a2 := ios.plxch($48,2)
a3 := ios.plxch($48,3)
print_port(1,p1)
print_port(2,p2)
print_port(3,p3)
ios.printnl
print_chan(0,a0)
print_chan(1,a1)
print_chan(2,a2)
print_chan(3,a3)
ios.plxout($3A,!(cnt>>23))
until ios.key
ios.stop
PRI print_chan(cnr,wert)
ios.print(string("A/D "))
ios.printdec(cnr)
ios.printchar(" ")
ios.printhex(wert,2)
ios.printchar(" ")
ios.printchar("[")
repeat wert>>3
ios.printqchar("‣")
repeat (255-wert)>>3
ios.printqchar(" ")
ios.printchar("]")
ios.printnl
PRI print_port(pnr,wert)
ios.print(string("Port "))
ios.printdec(pnr)
ios.printchar(" ")
repeat 8
if wert & 1
ios.printqchar("‣")
else
ios.printqchar(" ")
wert := wert >> 1
ios.printnl
DAT
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}

BIN
source/sid/1startrk.dmp Normal file

Binary file not shown.

BIN
source/sid/2startrk.dmp Normal file

Binary file not shown.

Binary file not shown.

BIN
source/sid/boing.sid Normal file

Binary file not shown.

BIN
source/sid/triborg.sid Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,405 @@
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Autor: Ingo Kripahle │
│ Copyright (c) 2010 Ingo Kripahle │
│ See end of file for terms of use. │
│ Die Nutzungsbedingungen befinden sich am Ende der Datei │
└──────────────────────────────────────────────────────────────────────────────────────────────────────┘
Informationen : hive-project.de
Kontakt : drohne235@googlemail.com
System : TriOS
Name : TriBorg - SID-Player
Chip : Regnatix
Typ : Programm
Version :
Subversion :
Funktion :
Komponenten : -
COG's : -
Logbuch :
Kommandoliste :
Notizen :
}}
OBJ
ios: "reg-ios"
CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
SIDMASK = %00000000_00000000_00000000_00010000
XMAX = 256
YMAX = 192
x_tiles = 16
y_tiles = 12
bit_base = $2000
disp_base = $5000
len_colblk = (x_tiles * y_tiles) * 2 + 256
'ademo1
lines = 5
thickness = 2
s_obj = 200 'scale
d_obj = 64 'durchmesser
r_obj = d_obj/2 'radius
rotvar = 14 'rotationsvarianz
arcstep = 16
VAR
'achtung, folgende reihenfolge darf nicht verändert werden!
word screen[x_tiles * y_tiles] 'tilemap
long colortab[64] 'farbregister
long heap_len
long heap_use
long dmpreg
long fcnt
long fpos
long datcnt 'zeiger für dateiliste
byte fl_bye 'flag player beenden
' byte fn[12] 'puffer für dateinamen
long dmu 'marker des aktuellen userverzeichnisses
PUB main|i,x,y,n,len
ios.start
ios.belload(string("triborg.bel"))
ios.g0_dynamic
ios.g0_clear
ios.g0_copy
screenset1 'farben und tiles setzen
heap_len := ios.g0_datlen
ios.g0_datblk(@grdat,0,heap_len) 'heapdaten senden
ifnot (ios.admgetspec & SIDMASK)
ios.sddmset(ios#DM_USER) 'u-marker setzen
dmu := ios.sddmget(ios#DM_USER) 'usermarker von administra holen
ios.admload(string("triborg.adm"))
ios.sddmput(ios#DM_USER,dmu) 'usermarker wieder in administra setzen
ios.sddmact(ios#DM_USER) 'u-marker aktivieren
play_count
repeat
ios.sid_sdmpplay(string("triborg.sid"))
\phase1(400)
\phase2(445)
\phase3(250)
\phase4
play_dir
PRI esc_key
if ios.g0_keystat
case ios.g0_keycode
27:
'ESC - geordneter rücksturz zur erde... :)
ios.sid_dmpstop 'ok, erstmal die mucke aus
ios.sid_mute(3)
ios.g0_reboot 'grafiksubsystem neu im textmodus starten
ios.admreset 'administra neu starten
waitcnt(cnt+clkfreq*2) 'geben wir den damen noch ein wenig zeit...
reboot
"n":
ios.sid_dmpstop
ios.sid_mute(3)
abort
"p":
ios.sid_dmppause
ios.sid_mute(3)
repeat until ios.g0_keystat
PRI screenset1|i,tx,ty
'tilescreen setzen
repeat tx from 0 to x_tiles - 1
repeat ty from 0 to y_tiles - 1
screen[ty * x_tiles + tx] := disp_base >> 6 + ty + tx * y_tiles + ((ty & $3F) << 10)
'farbtabelle füllen
repeat i from 0 to 63
colortab[i] := $00001010 * (i<<1+4) & $F + $48060D02
ios.g0_colortab(@colortab)
ios.g0_screen(@screen)
PRI phase1(frcnt) | k
ios.g0_textmode(5,5,6,0)
ios.g0_colorwidth(2,8)
repeat frcnt
ios.g0_clear
ios.g0_text(15,k,@string4 - @grdat)
ios.g0_copy
k := k + 1 <# 60
esc_key
PRI phase2(frcnt) | k
ios.g0_textmode(5,5,6,0)
ios.g0_colorwidth(2,8)
k := 255
repeat frcnt
ios.g0_clear
ios.g0_text(15,60,@string4 - @grdat)
ios.g0_text(15,k,@string3 - @grdat)
ios.g0_copy
k := k - 1 #> 60
esc_key
PRI phase3(frcnt) | k
k := 0
ios.g0_textmode(5,5,6,0)
repeat frcnt
ios.g0_clear
ios.g0_colorwidth(2,8)
ios.g0_text(15,60,@string2 - @grdat)
cores1(400,ymax/2 - 5,cnt>>14,600 + k <# 1600,2)
ios.g0_colorwidth(2,8)
ios.g0_text(15,60,@string1 - @grdat)
ios.g0_copy
k := k + 5
esc_key
PRI phase4 | status
ios.g0_textmode(5,5,6,0)
repeat
dmpreg := ios.sid_dmpreg
status := ios.sid_dmpstatus
ios.g0_clear
ios.g0_colorwidth(2,8)
ios.g0_text(15,60,@string2 - @grdat)
cores2(400,ymax/2 - 5,cnt >> 14,2000,1)
ios.g0_colorwidth(2,8)
ios.g0_text(15,60,@string1 - @grdat)
ios.g0_copy
esc_key
while status
PRI phase5 | status
ios.g0_textmode(5,5,6,0)
repeat
dmpreg := ios.sid_dmpreg
status := ios.sid_dmpstatus
ios.g0_clear
ios.g0_colorwidth(2,8)
ios.g0_text(15,60,@string2 - @grdat)
cores2(400,ymax/2 - 5,cnt >> 14,2000,1)
ios.g0_colorwidth(2,8)
ios.g0_text(15,60,@string1 - @grdat)
ios.g0_copy
esc_key
while status
PRI play(stradr) | status,k
k := 0
ios.sid_sdmpplay(stradr) 'sound starten
ios.g0_datblk(@grdat,@fn - @grdat,12) 'dateinamen aktualisieren
repeat
k++
dmpreg := ios.sid_dmpreg 'sounddaten holen
status := ios.sid_dmpstatus 'playerstatus abfragen
ios.g0_clear
ios.g0_colorwidth(2,8)
ios.g0_textmode(5,5,6,0)
ios.g0_text(15,60,@string2 - @grdat)
cores2(400,ymax/2 - 5,cnt >> 14,2000,1)
ios.g0_colorwidth(2,8)
ios.g0_text(15,60,@string1 - @grdat)
if k < XMAX 'dateiname und zählerstand
ios.g0_textmode(2,1,6,0)
ios.g0_colorwidth(2,0)
ios.g0_text(k,5,@fn - @grdat)
ios.g0_printdec(70,150,fpos,4,@val1,@val1 - @grdat)
ios.g0_printdec(130,150,fcnt,4,@val2,@val2 - @grdat)
ios.g0_copy
esc_key
while status
ios.sid_dmpstop
PRI cores1(x,y,angle,radius,col)|x1,y1,x2,y2,x3,y3
x1 := x + sin(angle)/(radius)
y1 := y + cos(angle)/(radius)
x2 := x + sin(angle+2730)/(radius)
y2 := y + cos(angle+2730)/(radius)
x3 := x + sin(angle+5460)/(radius)
y3 := y + cos(angle+5460)/(radius)
ios.g0_colorwidth(0,0) 'startpunkt
ios.g0_plot(x1,y1)
ios.g0_colorwidth(col, 7) 'kreise
ios.g0_arc(x1, y1, 20, 20, 0, $1fff/(arcstep-1), arcstep, 2)
ios.g0_arc(x2, y2, 20, 20, 0, $1fff/(arcstep-1), arcstep, 2)
ios.g0_arc(x3, y3, 20, 20, 0, $1fff/(arcstep-1), arcstep, 2)
PRI cores2(x,y,angle,radius,col)|x1,y1,x2,y2,x3,y3,r1,r2,r3,xl,yl
x1 := x + sin(angle)/(radius - word[dmpreg + 0]>>6)
y1 := y + cos(angle)/(radius - word[dmpreg + 0]>>6)
x2 := x + sin(angle+2730)/(radius - word[dmpreg + 2]>>6)
y2 := y + cos(angle+2730)/(radius - word[dmpreg + 2]>>6)
x3 := x + sin(angle+5460)/(radius - word[dmpreg + 4]>>6)
y3 := y + cos(angle+5460)/(radius - word[dmpreg + 4]>>6)
r1 := byte[dmpreg + 1] >> 3
r2 := byte[dmpreg + 3] >> 3
r3 := byte[dmpreg + 5] >> 3
ios.g0_colorwidth(2,0) 'startpunkt
ios.g0_plot(x,y)
xl := x + sin(angle+2730)/(500 - word[dmpreg + 0]>>7)
yl := y + cos(angle+2730)/(500 - word[dmpreg + 0]>>7)
ios.g0_line(xl,yl)
ios.g0_colorwidth(0,0) 'startpunkt
ios.g0_plot(x1,y1)
ios.g0_colorwidth(col, 7) 'kreise
ios.g0_arc(x1, y1, r1, r1, 0, $1fff/(arcstep-1), arcstep, 2)
ios.g0_arc(x2, y2, r2, r2, 0, $1fff/(arcstep-1), arcstep, 2)
ios.g0_arc(x3, y3, r3, r3, 0, $1fff/(arcstep-1), arcstep, 2)
PRI cos(angle) : x
x := sin(angle + $800)
PRI sin(angle) : y
'' Get sine of angle (0-8191)
y := angle << 1 & $FFE ' address
if angle & $800
y := word[$F000 - y]
else
y := word[$E000 + y]
if angle & $1000
-y
CON 'sd-player
PRI play_count|stradr,i
ios.sddir 'kommando: verzeichnis öffnen
datcnt := 0 'zum listenanfang
fcnt := 0 'zähler für dateianzahl
fl_bye := 0
repeat while (stradr := ios.sdnext) 'dateiliste einlesen
if str_find(stradr,string(".DMP"))
fcnt++
play_dir_wrlst(stradr)
PRI play_dir|stradr,len,i 'alle songs auf der sd-card abspielen
datcnt := 0 'zum listenanfang
repeat i from 0 to fcnt-1 'dateiliste abspielen
fpos := i + 1
play_dir_rdlst(@fn)
\play(@fn)
PRI play_dir_wrlst(stradr)|len,i 'kopiert dateinamen in liste
len := strsize(stradr)
repeat i from 0 to len-1
ios.ram_wrbyte(ios#usrmod,byte[stradr][i],datcnt++)
ios.ram_wrbyte(ios#usrmod,0,datcnt++)
PRI play_dir_rdlst(stradr)|i,n 'liest dateinamen aus list
i := 0
repeat
n := ios.ram_rdbyte(ios#usrmod,datcnt++)
byte[stradr][i++] := n
while n <> 0
PRI str_find(string_1, string_2) : buffer | counter 'sys: string suchen
'' ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
'' │ Searches a string of characters for the first occurence of the specified string of characters. │
'' │ │
'' │ Returns the address of that string of characters if found and zero if not found. │
'' │ │
'' │ string1 - A pointer to the string of characters to search. │
'' │ string2 - A pointer to the string of characters to find in the string of characters to search. │
'' └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
repeat strsize(string_1--)
if(byte[++string_1] == byte[string_2])
repeat counter from 0 to (strsize(string_2) - 1)
if(byte[string_1][counter] <> byte[string_2][counter])
buffer~~
ifnot(buffer~)
return string_1
DAT 'heap-daten
grdat
DAT 'stringpuffer
val1 'stringpuffer für zahlenausgabe
byte "00000000",0 '8 digits
byte 0 'wichtig: auf wortgrenze auffüllen!
val2 'stringpuffer für zahlenausgabe
byte "00000000",0 '8 digits
byte 0 'wichtig: auf wortgrenze auffüllen!
strend
DAT 'strings
string1
byte " rg",0
string2
byte "TriBo",0
string3
byte "Tri",0
string4
byte " Borg",0
fn
byte "--------.---",0
grdatend
DAT
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}