This commit is contained in:
drohne235@googlemail.com 2011-04-18 17:07:12 +00:00
parent 2e578781e3
commit ea7adb9397
76 changed files with 0 additions and 31195 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,311 +0,0 @@
FL
\ eeReadWord ( eeAddr -- n1 )
: eeReadWord mcwT0 2 eeReadPage if eeErr cr then mcwT0 w@ ;
\ eeWriteWord ( n1 eeAddr -- )
: eeWriteWord swap mcwT0 w! mcwT0 2 eeWritePage if eeErr cr then ;
\ eeReadByte ( eeAddr -- c1 )
: eeReadByte eeReadWord FF and ;
\ eeCopy ( addr1 addr2 u -- ) copy u bytes from addr1 to addr2, addr1 and addr2 must be on a 0x80 byte page boundary
\ clears the pad, so make sure no commands follow
\ and u must be a multiple of 0x80 and should not overlap
: eeCopy 7F invert and rot 7f invert and rot 7f invert and rot
0 do over i + dup . mcPad 80 eeReadPage if eeErr leave then
dup i + dup . mcPad 80 eeWritePage if eeErr leave then
i 3FF and 0= if cr then 80 +loop 2drop cogid cogPadclr ;
: _d1 cr over .word space dup .word _ecs bounds ;
: _d2 cr .word _ecs ;
: _d3 mcT 10 bounds do i c@ .byte space loop 2 spaces mcT 10 .str ;
\ dump ( adr cnt -- ) uses mcT
: dump _d1 do i _d2 i mcT 10 cmove _d3 10 +loop cr ;
\ rdump ( adr cnt -- ) uses mcwT1 - mcwT8
: rdump _d1 do i _d2 i mcT 10 eeReadPage if mcT 10 0 fill then _d3 10 +loop cr ;
\ adump ( adr cnt -- )
: adump cr over .word space dup .word _ecs bounds
do
cr i .word _ecs i 4 bounds
do i @ .long space loop
4 +loop cr ;
\ \ ( -- ) moves the parse pointer >in to the end of the line, tricky to redefine
\ CTL-E gets traslated to \ by fast_load
:  \
padsize mcw>in w! ; immediate exec
\ ' ( -- addr ) returns the execution token for the next name, if not found it returns 0
: ' parsebl if pad>in nextword find 0= if _udf cr drop 0 then else 0 then ;
\ cq ( -- addr ) returns the address of the counted string following this word and increments the IP past it
: cq r> dup c@++ + alignw >r ;
\ c" ( -- c-addr ) compiles the string delimited by ", runtime return the addr of the counted string ** valid only in that line
: c" compile?
if
cm_cq w, 1 mcw>in w+! 22 parse dup c, dup pad>in mswHere w@ rot cmove dup allot 1+ mcw>in w+! herewal
else
22 parse 1- pad>in 2dup c! swap 2+ mcw>in w+!
then ; immediate exec
\ the base address for the input buffer
wvariable fl_base
\ the number of buffered characters
wvariable fl_count
\ the old mswDictend
wvariable fl_top
\ the offset of the next byte in
wvariable fl_in
\ one fast load at a time
wvariable fl_lock
\ fl_buf ( -- t/f ) allocate all but 300 chars and load keys load true if successful
: fl_buf mswDictend w@ mswHere w@ - 300 - 0 fl_count w! lockdict fl_lock w@
if freedict cr 0 else -1 fl_lock w! freedict -1 then
\ ( u t/f -- ) true if successful so far
if
\ save the old mswDictend and initialize variables
mswDictend w@ dup fl_top w! swap - dup fl_base w! dup fl_in w! 1- mswDictend w!
0
begin dup mswKeyTO w@ 0
do
begin fkey?
if dup 5C = \ if a backslash, throw away keys
if drop begin keyto if D = else -1 then until else
\ drop all characters between { }
dup 7B = if drop begin keyto if 7D = else -1 then until else
\ translate CTL-E 05 to backspace 5C
dup 5 = if drop 5C then
fl_in w@ c! 1+ fl_in w@ 1+ dup fl_top w@ =
if _eoom clearkeys reset then fl_in w!
then
then 0
\ stay in begin until
else drop -1 then
\ no key, exit begin until
until
loop
swap over =
\ until count is the same
until
dup . ." chars" cr fl_count w! -1
else drop 0 then
;
\ fl_skeys ( n -- ) emit the keys in the fast buffer
: fl_skeys
fl_lock w@ fl_count w@ 0<> and
if
fl_base w@ fl_count w@ bounds
do
i dup c@ emit mswDictend w!
loop
fl_top w@ mswDictend w! 0 fl_count w! lockdict 0 fl_lock w! freedict
then
;
: loadee 2dup F andn bounds
do i mcT 10 eeReadPage drop mcT 10 bounds do i c@ emit loop 10 +loop
dup F andn rot + swap F and dup if bounds do i eeReadByte emit loop else 2drop then ;
: _caend c" cr " over cappend cogid over cappendnc c" 0 mcwEmitptr w! >cog" swap cappend ;
: FL fl_buf if c" fl_skeys" mcT ccopy mcT _caend mcT cogXO then ;
\ file area 8000 - FFFF
\ individual files start on 128 byte boundaries,
\ the first thing is the length as a 16 bit word, then a cstr which is the file name, and then the contents
\ of the file
8000 constant eeBot
10000 constant eeTop
\ f_fill ( c1 -- ) fill the eeprom file area with c1
: f_fill mcPad 80 rot fill eeTop eeBot
do i mcPad 80 eeWritePage if eeErr cr leave then 80 +loop
mcPad 80 bl fill ;
\ f_clear ( -- ) clear the eeprom file area, only writes the length word to FFFF
: f_clear eeTop eeBot do FFFF i eeWriteWord 80 +loop ;
: _fi mcNumpad dup w@ swap 2+ c@ + 2+ 1+ 80 u/mod swap if 1+ then 80 u* ;
\ list ( -- ) list the files names in the eeprom
: list eeTop eeBot
do
i mcNumpad numpadsize namemax 1+ 2+ min eeReadPage if eeErr leave then mcNumpad w@ FFFF =
if i . cr 80 leave else i . mcNumpad dup w@ . 2+ .cstr cr _fi then
+loop ;
\ f_find ( cstr -- n1 ) find the file, 0 if not found
: f_find 0 eeTop eeBot
do
i mcNumpad numpadsize namemax 1+ 2+ min eeReadPage if eeErr leave then mcNumpad w@ FFFF =
if nip 80 leave else over mcNumpad 2+ cstr= if drop i then _fi then
+loop ;
\ f_free ( -- n1 ) address of the first free file page, 0 if there are none
: f_free 0 eeTop eeBot
do
i mcNumpad 4 eeReadPage if eeErr leave then mcNumpad w@ FFFF =
if drop i 80 leave else _fi then
+loop ;
\ f_wfile ( -- ) write the file at fl_base for fl_count bytes, the format must be:
\ word length the number of bytes in the content
\ bytes cstr - filename
\ bytes file contents
: f_wfile f_free dup
if
dup fl_count w@ + eeTop <
if fl_base w@ fl_count w@ bounds
do dup
i fl_count w@ dup 80 min swap over - fl_count w! eeWritePage
if eeErr leave then
80 + 80 +loop drop
else drop _eoom then
else drop eeErr cr then ;
\ FW ( n1 -- ) like a fast load but write to the file area, first entry after a blank lines must be 3 periods followed by the filename
: FW fl_buf
if fl_count w@ 0
do
fl_base w@ c@ 2E =
if leave else fl_base w@ 1+ fl_base w! fl_count w@ 1- fl_count w! then
loop
fl_base w@ 3 + 20 bounds do i c@ bl <= lasti? or if i leave then loop fl_base w@ - dup
3 - fl_base w@ 2+ c!
fl_count w@ swap - dup fl_base w@ c! dup 8 rshift fl_base w@ 1+ c!
if f_wfile then
fl_top w@ mswDictend w! lockdict 0 fl_lock w! freedict
then ;
\ f_al ( addr1 -- n1 addr2) for file at addr1, get the length - n1, and the address of teh contents - addr2
: f_al dup eeReadWord over 2+ eeReadByte rot + 2+ 1+ ;
\ f_load ( cstr -- ) load the file name following from eeprom
: f_load f_find dup
if f_al 0 mcT c! mcT cappendnc mcT cappendnc c" loadee" mcT cappend mcT _caend mcT cogXO else drop then ;
\ load ( -- ) load the file name following from eeprom
: load parsenw dup if f_load else drop then ;
: version c" PropForth v2.5 2009OCT24 17:15 0" ;
\ free ( -- ) display free main bytes and current cog longs
: free mswDictend w@ mswHere w@ - . ." bytes free - " par mcwAhere w@ - . ." cog longs free" cr ;
\ saveforth( -- ) write the running image to eeprom
: saveforth
c" mswHere" find
if
version dup c@ + dup c@ 1+ swap c!
pfa>nfa mswHere w@ swap
\ 2e emit
begin dup w@ over eeWriteWord 2+ dup 7F and 0= until
do
ibound i - 80 min dup i dup rot
eeWritePage if leave then 2e emit
+loop
else drop then cr ;
\ _forget ( cstr -- ) wind the dictionary back to the word which follows - caution
: _forget dup
if
find if
pfa>nfa nfa>lfa dup mswHere w! w@ mswlastnfa w!
else .cstr ??? cr then
else drop then ;
\ forget ( -- ) wind the dictionary back to the word which follows - caution
: forget parsenw _forget ;
\ this constant is used at boot time to set the forth starting routine, if it is changed
\ it does not take effect until a reboot, a cog reset is not adequate
cm_fstart wconstant cm_fstart
\ fstart ( -- ) the start word
: fstart
cogid dup cogInbyte 10 lshift cm_entry 2 lshift or swap or resetDreg !
mcwInbyte m@ l>w swap
100 mcwInbyte w!
0 mcwEmitptr w!
fMask @ mcwDebugcmd w!
\ zero out cog data area
par @ 8 + F8 0 fill
\ initialize forth variables
hex
ca_varEnd mcwAhere w!
\ initiliaze the common variables
lockdict mswHere w@ 0=
if 0 fl_lock w! lastnfa nfa>pfa 2+ alignl 4+ mswHere w! 7FFF dup mswMemend w! mswDictend w! then
freedict rsTop 1- rsPtr !
FFFF = if 8 lshift cogid + vxcog w! else drop then
c" boot" mcT ccopy cogid mcT cappendn mcT find if execute else drop then
-1
begin
compile? 0= if ." Cog" cogid . ." ok" cr then
\ if the first time through set mcwDebugValue to -1 to let people know we are alive
if -1 mcwDebugvalue m! then
interpret
0 0 until ;
: boot6 cogid >cog cog+ ;
\ cog? ( -- ) display active forth cogs
: cog? ." Forth cogs: " ffcog w@ . 2D emit space lfcog w@ . cr ;
\ cog+ ( -- ) add a forth cog
: cog+ ffcog w@ 1- dup 0>= if dup ffcog w! cogreset else drop then cog? ;
\ cog- ( -- ) stop first forth cog, cannot be executed form the first forth cog
: cog- ffcog w@ dup cogid <> swap 1+ dup lfcog w@ <= rot and if dup 1- cogstop ffcog w! else drop then cog? ;
\ st? ( -- ) prints out the stack
: st? ." ST: " stPtr @ 2+ dup stTop < if stTop swap - 0 do stTop 2- i - @ .long space loop else drop then cr ;
\ sc ( -- ) clears the stack
: sc stTop stPtr @ - 3 - dup . ." items cleared" cr dup 0> if 0 do drop loop then ;
\ _pna ( addr -- ) print the address, contents and forth name
: _pna dup .word 3a emit w@ dup .word space pfa>nfa .strname space ;
\ pfa? ( addr -- t/f) true if addr is a pfa
: pfa? dup pfa>nfa dup c@ dup 80 and 0= swap namemax and 0<> rot nfa>pfa rot if w@ then rot = and ;
\ rs? ( -- ) prints out the return stack
: rs? ." RS: " rsTop rsPtr @ 1+ - 0 do rsTop 1- i - @ dup 2- w@ pfa? if 2- _pna else .long space then loop cr ;
\ lasm ( addr -- ) expects an address pointing to a structure in the following form
\ empty long, long upper address of the assembler routine, long lower address of the assembler routine
\ a series of longs which are the assembler codes
: lasm 4+ dup m@ swap 4+ swap over m@ dup mcwAhere w! do 4+ dup m@ a, loop drop ;
\ f_erase ( -- ) erase the word following from eeprom - DANGER - should be the last word only
\ or following words may get overwritten when a new file is written to eeprom
: f_erase parsenw dup if f_find dup if eeTop swap do FFFF i eeWriteWord 80 +loop else drop then else drop then ;
\ no more symbols available
\ mswlastnfa is generated by the forth spinmaker word

File diff suppressed because it is too large Load Diff

View File

@ -1,616 +0,0 @@
{
.sob linker
2009
April
10 Successfully linked two test programs
15 SOB1 format:
#args in exported pubs now just one byte
added byte to imports for possible future use with object "pointers"
rearranged fields in SOB file header so that longs are long-aligned in memory
June
9 Sphinxified
timestamp comparison
12 Removed /s and /t options
18 Don't stop on first out-of-date error.
To do:
removal of duplicate sobs
Usage: link sobname [options]
sobname is name of .sob file, with or without .sob suffix.
Options start with / or - and are case-insensitive:
/v <n> -- Sets verbosity level. Higher values of n => more verbose. Default is 0.
SOB file format
0 4 bytes: SOB file format version #
4 4 bytes: OBJ timestamp or version
8 4 bytes: hash of OBJ's binary code.
12 2 bytes: NUMEXPORTS
14 2 bytes: EXPORTSIZE
16 2 bytes: NUMIMPORTS
18 2 bytes: IMPORTSIZE
20 2 bytes: OBJBINSIZE (this is always a multiple of 4)
22 1 byte: checksum
23 1 byte: reserved
24 2 bytes: size of OBJ's VAR space.
26 EXPORTSIZE bytes: exported symbols: CONs, PUBs, maybe PRIs.
IMPORTSIZE bytes: OBJ's sub-OBJs.
OBJBINSIZE bytes: the compiled OBJ: header followed by methods.
Export record format
name + null + 0 + 4-byte int CON int
name + null + 1 + 4-byte float CON float
name + null + 2 + index + #args PUB
name + null + 3 + index + #args PRI (not exported)
Import record format
name + null + 2-byte count + reserved
Export and import names are uppercase. Import name must not include ".SOB" or other suffix.
}
SIZEOFSOBHEADER = 26
obj
term: "isxtv"
fs[2]: "sxfile"
str: "stringx"
pub Main | err
err := \Try
if err
if err > 0
term.str( err )
else
term.str( string("Error ") )
term.dec( err )
term.out( 13 )
fs[0].Close
fs[0].Open( string("sphinx.bin"), "R" )
fs[0].Execute( 0 )
dat
STACKSPACE long 500 ' in bytes; must be multiple of 4
TABLESPACE long 1000 ' in bytes; must be multiple of 4
WORKSPACE long 0
verbosity byte 0
outOfDate byte 0
ignoreOutOfDate byte 0
pri Try | nArgs, pTable, pWork, l, p, totalVarSize
fs.Open( string("args.d8a"), "R" )
nArgs := fs.ReadByte
ifnot nArgs--
abort string("usage: link sobname [options]")
fs.ReadStringUpperCase( @sobName, MAXFILENAMELENGTH )
l := strsize( @sobName )
if sobName[l-4] == "." and sobName[l-3] == "S" and sobName[l-2] == "O" and sobName[l-1] == "B"
sobName[l-4]~
if strsize( @sobName ) > 8
term.str( @sobName )
abort string(" -- sobname too long")
str.Copy( @outputName, @sobName )
' Process command line arguments
repeat while nArgs--
fs.ReadStringUpperCase( @stringBuffer, 20 )
if stringBuffer[0] == "-"
stringBuffer[0] := "/"
if strcomp( @stringBuffer, string("/V") )
ifnot nArgs--
abort string("/V must be followed by a number")
verbosity := fs.ReadNumber
elseif strcomp( @stringBuffer, string("/I") )
ignoreOutOfDate~~
{
elseif strcomp( @stringBuffer, string("/S") )
ifnot nArgs--
abort string("/S must be followed by a number")
STACKSPACE := fs.ReadNumber
if STACKSPACE & 3
abort string("/S argument must be a multiple of 4")
elseif strcomp( @stringBuffer, string("/T") )
ifnot nArgs--
abort string("/T must be followed by a number")
TABLESPACE := fs.ReadNumber
if TABLESPACE & 3
abort string("/T argument must be a multiple of 4")
}
'else
'ignore
fs.Close
if verbosity => 1
term.str( string("link 090627", 13) )
pTable := word[$000a] + STACKSPACE
pWork := pTable + TABLESPACE
WORKSPACE := 32768-pWork
if verbosity => 2
term.dec( WORKSPACE )
term.str( string(" bytes of work space", 13) )
if WORKSPACE =< 0
abort string("No work space")
SobInit( pTable, TABLESPACE )
AddSob( @sobName )
ProcessSob( pTable, true )
checksum~
totalVarSize := ComputeAddressAndTotalVarSize( pTable, $0010 )
word[@header][3] := $0010
word[@header[$08]] := objBinEndAddress
word[@header[$0a]] := objBinEndAddress + totalVarSize + 8
word[@header[$0c]] := firstPubOffset + $0010
word[@header[$0e]] := word[@header[$0a]] + firstPubLocalsSize + (firstPubNumArgs + 1) << 2
AddToChecksum( @header, $10 )
AddToChecksum( @footer, 8 )
header[5] := -checksum
if verbosity => 3
p := pTable
repeat while p
term.str( word[p +_pName] )
term.out( " " )
term.hex( word[p +_startAddress], 4 )
term.out( " " )
term.dec( word[p +_totalVarSize] )
term.out( " " )
term.hex( byte[p +_checksum], 2 )
term.out( 13 )
p := word[p +_pNextSorted]
if not outOfDate or ignoreOutOfDate
str.Append( @outputName, string(".BIN") )
if verbosity => 2
term.str( string("Writing ") )
term.str( @outputName )
term.out( 13 )
WriteBinaryFile( @outputName, pTable, pWork, WORKSPACE )
else
term.str( string("No .bin written", 13) )
pri WriteBinaryFile( pFilename, pSob, pBuff, buffsize ) | n, p, pImports, pCounts, interObjectOffset, varOffset
{{
Go down the priority-sorted list of sobs assigning them hub addresses such that they follow one
another in memory. On the way back up the list, compute each sob's total VAR size (the sob's
own VARs plus its imported sobs' VARs.)
Also updates checksum.
Return value is the current sob's total VAR size. Only the top object's return value is looked at.
}}
fs[0].Open( pFilename, "W" )
fs[0].Write( @header, 16 )
repeat while pSob
str.Copy( @stringBuffer, word[pSob +_pName] )
str.Append( @stringBuffer, string(".SOB") )
if verbosity => 2
term.str( @stringBuffer )
term.str( string(" -- copying", 13) )
n := word[pSob +_objBinSize]
if n > buffsize
abort string("work area too small")
fs[1].Open( @stringBuffer, "R" )
fs[1].SkipBytes( SIZEOFSOBHEADER + word[pSob +_exportImportSize] )
fs[1].Read( pBuff, n )
fs[1].Close
p := pBuff + byte[pBuff][2] << 2 ' byte[2] is index of 1st obj entry; multiply by 4 bytes/entry
varOffset := word[pSob +_varSize]
pImports := word[pSob +_pImports]
pCounts := word[pSob +_pCounts]
repeat word[pSob +_nImports]
interObjectOffset := word[ word[pImports] +_startAddress] - word[pSob +_startAddress]
repeat word[pCounts]
word[p] := interObjectOffset
p += 2
word[p] := varOffset
p += 2
varOffset += word[ word[pImports] +_totalVarSize]
pImports += 2
pCounts += 2
fs[0].Write( pBuff, n )
pSob := word[pSob +_pNextSorted]
fs[0].Close
{{
objBinEndAddress := address ' end address will point just beyond the last obj in hub memory.
' Here we're just overwriting as we go and keeping the last one.
ComputeAddressAndTotalVarSize( word[p +_pNextSorted], address )
checksum += byte[p +_checksum] ' this is the partial checksum of the obj (doesn't count its sub-object table because
' sub-object links are not known until link time (i.e., now))
totalVarSize := word[p +_varSize]
pImports := word[p +_pImports]
pCounts := word[p +_pCounts]
repeat word[p +_nImports] ' for each import, add the import's VAR size multiplied by its count
interObjectOffset := word[ word[pImports] +_startAddress] - word[p +_startAddress]
repeat word[pCounts]
AddToChecksum( @totalVarSize, 2 ) ' checksum needs to include this half of an object table entry
AddToChecksum( @interObjectOffset, 2 ) ' and this other half of an object table entry
totalVarSize += word[ word[pImports] +_totalVarSize]
pImports += 2
pCounts += 2
word[p +_totalVarSize] := totalVarSize
}}
var
word firstPubLocalsSize
word firstPubOffset
word firstPubNumArgs
word objBinEndAddress
byte checksum
long clk_freq
long xin_freq
long clk_mode
long free
long stack
pri ReadExports( numExports ) | firstPub, type, val, index, nArgs, i, p, f, frequency
f~
firstPub~~
stack := 16
frequency := 12_000_000
repeat numExports
fs.ReadStringUpperCase( @stringBuffer, MAXEXPORTLENGTH )
case type := fs.ReadByte
0, 1: ' int or float CON
val := fs.ReadLong
2, 3: ' PUB or PRI
index := fs.ReadByte
nArgs := fs.ReadByte
if firstPub~
firstPubNumArgs := nArgs
repeat i from 0 to 4
if strcomp( @stringBuffer, @@ptrs[i] )
if type
term.str( @stringBuffer )
abort string(" -- not an int CON")
clk_freq[i] := val
f |= |< i
f &= 7
if clk_mode & 3
f |= 8
case f ' four bits: rc|clkmode|xinfreq|clkfreq
%0000: ' none of clkmode/xinfreq/clkfreq specified
%0001..%0011: abort string("_CLKMODE must be specified")
%0100: abort string("_CLKFREQ or _XINFREQ must be specified")
%0101: frequency := clk_freq
%0110: frequency := xin_freq * ((clk_mode >> 6) #> 1)
%0111: if clk_freq <> xin_freq * ((clk_mode >> 6) #> 1)
abort string("conflicting _CLKFREQ and _XINFREQ")
%1000..%1011: ' these cases shouldn't happen
%1100: ' this case is OK
%1101..%1111: abort string("RCFAST/SLOW incompatible with _CLKFREQ/_XINFREQ")
long[@header] := frequency
header[4] := ComputeClkmodeByte( clk_mode )
pri ComputeClkmodeByte( mode ) : m | b1, b2, i
{
rcfast $001 exactly one 1 in 0000_0000_00xx incompatible with clkfreq/xinfreq
rcslow $002
or
xinput $004 exactly one 1 in 0000_00xx_xx00 and requires clkfreq/xinfreq
xtal1 $008 up to one 1 in 0xxx_xx00_0000
xtal2 $010
xtal3 $020
pll1x $040
pll2x $080
pll4x $100
pll8x $200
pll16x $400
}
b1 := -1 ' b1 is the position of the single 1 in mode[5..0].
repeat i from 0 to 5
if mode & |< i
if b1 <> -1
abort string("invalid _CLKMODE") ' only one 1 allowed
b1 := i
m := lookupz( b1: $00, $01, $22, $2a, $32, $3a )
b2 := -1 ' b2 is the position of single 1 in mode[10..6] (-1 if no 1 bit)
repeat i from 6 to 10
if mode & |< i
if b2 <> -1
abort string("invalid _CLKMODE (multiple PLL)") ' only one 1 allowed
b2 := i
if b1 < 2 ' RCFAST/RCSLOW?
if b2 <> -1 ' b2 better not be set
abort string("invalid _CLKMODE (RC+PLL)")
else ' one of the X-modes
if b2 <> -1
m |= $40 ' PLLENA
m += b2 - 5
dat
ptrs word @s0, @s1, @s2, @s3, @s4
s0 byte "_CLKFREQ", 0
s1 byte "_XINFREQ", 0
s2 byte "_CLKMODE", 0
s3 byte "_FREE", 0
s4 byte "_STACK", 0
dat
long
header byte 0[16]
footer byte $ff, $ff, $f9, $ff
byte $ff, $ff, $f9, $ff
con
MAXFILENAMELENGTH = 8 + 1 + 3 ' 8.3
MAXEXPORTLENGTH = 32
var
byte stringBuffer[MAXEXPORTLENGTH+1]
byte sobName[MAXFILENAMELENGTH+1]
byte outputName[MAXFILENAMELENGTH+1]
con
#0
_pNext[2]
_pNextSorted[2]
_pName[2]
_nImports[2]
_pImports[2]
_pCounts[2]
_startAddress[2]
_objBinSize[2]
_totalVarSize[2]
_varSize[2]
_timestamp[4]
_exportImportSize[2]
_checksum[1]
_[1] ' for alignment: _SIZEOFSOBINFO must be a multiple of 4
_SIZEOFSOBINFO
SOBFILEFORMATVERSION = "S" + "O" << 8 + "B" << 16 + "1" << 24 ' "SOB1"
dat
pSobSpace word 0
SOBSSIZE word 0
pDataSpace word 0
pFirst word 0
pLast word 0
pLastSorted word 0
pri SobInit( p, size )
pFirst := pSobSpace := p
SOBSSIZE := size
pDataSpace := pSobSpace + SOBSSIZE
pLastSorted := pLast := pFirst
word[pFirst +_pNext]~
word[pFirst +_pNextSorted]~
pri ComputeAddressAndTotalVarSize( p, address ) : totalVarSize | pImports, pCounts, interObjectOffset
{{
Go down the priority-sorted list of sobs assigning them hub addresses such that they follow one
another in memory. On the way back up the list, compute each sob's total VAR size (the sob's
own VARs plus its imported sobs' VARs.)
Also updates checksum.
Return value is the current sob's total VAR size. Only the top object's return value is looked at.
}}
ifnot p
return
word[p +_startAddress] := address
address += word[p +_objBinSize]
objBinEndAddress := address ' end address will point just beyond the last obj in hub memory.
' Here we're just overwriting as we go and keeping the last one.
ComputeAddressAndTotalVarSize( word[p +_pNextSorted], address )
checksum += byte[p +_checksum] ' this is the partial checksum of the obj (doesn't count its sub-object table because
' sub-object links are not known until link time (i.e., now))
totalVarSize := word[p +_varSize]
pImports := word[p +_pImports]
pCounts := word[p +_pCounts]
repeat word[p +_nImports] ' for each import, add the import's VAR size multiplied by its count
interObjectOffset := word[ word[pImports] +_startAddress] - word[p +_startAddress]
repeat word[pCounts]
AddToChecksum( @totalVarSize, 2 ) ' checksum needs to include this half of an object table entry
AddToChecksum( @interObjectOffset, 2 ) ' and this other half of an object table entry
totalVarSize += word[ word[pImports] +_totalVarSize]
pImports += 2
pCounts += 2
word[p +_totalVarSize] := totalVarSize
pri AddToChecksum( p, n )
repeat n
checksum += byte[p++]
pri AddSob( pName ) : p | n
{{
Copies name to data area, appends name to the sobs list, returns pointer to new sob entry.
}}
if verbosity => 2
term.str(string("adding "))
term.str(pName)
term.out(13)
p := pSobSpace
pSobSpace += _SIZEOFSOBINFO
n := strsize(pName) + 1
bytemove( Alloc(n), pName, n )
word[pLast +_pNext] := p
word[pLastSorted +_pNextSorted] := p
word[p +_pName] := pDataSpace
word[p +_pNext]~
word[p +_pNextSorted]~
pLast := p
pLastSorted := p
pri Alloc( n )
pDataSpace := (pDataSpace - n) & $fffffffc ' long-aligned
if pDataSpace < pSobSpace
abort string("Insufficient sob table space")
return pDataSpace
pri FindSob( pName ) : p | pPrev
{{
Search the sob list in priority order. If a sob in the list matches name,
update priority-order links to put the sob at the end and return a pointer to it.
Otherwise, return 0.
}}
p := pPrev := pFirst
repeat while p
if strcomp( word[p +_pName], pName )
if p <> pLastSorted
word[pPrev +_pNextSorted] := word[p +_pNextSorted]
word[pLastSorted +_pNextSorted] := p
word[p +_pNextSorted]~
pLastSorted := p
return
pPrev := p
p := word[p +_pNextSorted]
return 0
pri ProcessSob( p, top ) | len, numExports, exportSize, numImports, importSize, objBinSize, hash, pStart, temp, pImports, pCounts, ts0, ts1
{{
Reads the sob file identified by p, appends the sob's imports to the sob list,
then recursively processes the imported sobs.
top is true for the top sob, false for all other sobs.
}}
Str.Copy( @stringBuffer, word[p +_pName] )
Str.Append( @stringBuffer, string(".SOB") )
if verbosity => 2
term.str( string("Reading [") )
term.str( @stringBuffer )
term.out( "]" )
term.out( 13 )
fs.Open( @stringBuffer, "R" )
if fs.Readlong <> SOBFILEFORMATVERSION ' SOB file format version
abort string("Unrecognized SOB file format")
long[p +_timestamp] := fs.Readlong ' timestamp
hash := fs.ReadLong ' hash
numExports := fs.ReadWord ' number of exports
exportSize := fs.ReadWord ' size of exports segment
numImports := fs.ReadWord ' number of imports
importSize := fs.ReadWord ' size of imports segment
word[p +_objBinSize] := fs.ReadWord ' size of bytecode segment
byte[p +_checksum] := fs.ReadByte ' checksum
fs.ReadByte ' padding
word[p +_varSize] := fs.ReadWord ' size of sob's VAR space
ts0 := long[p +_timestamp]
if top
ReadExports( numExports )
else
fs.SkipBytes( exportSize )
word[p +_exportImportSize] := exportSize + importSize
word[p +_nImports] := numImports
word[p +_pImports] := pImports := Alloc( numImports << 1 ) ' points to an array of sob pointers
word[p +_pCounts] := pCounts := Alloc( numImports << 1 ) ' points to an array of sob counts
pStart := pLast
repeat numImports
fs.ReadStringUpperCase( @stringBuffer, 8 )
ts1 := GetTimestamp( @stringBuffer )
if ts0 and ts1 ' Only compare non-zero timestamps
if ts0 =< ts1
term.str( word[p+_pName] )
term.str( string(".SOB is older than ") )
term.str( @stringBuffer )
term.str( string(".SOB", 13) )
outOfDate~~
ifnot temp := FindSob( @stringBuffer )
temp := AddSob( @stringBuffer )
word[pImports] := temp
word[pCounts] := fs.ReadWord
fs.ReadByte ' reserved byte
if verbosity => 3
term.str( word[ word[pImports] +_pName] )
term.out( "*" )
term.dec( word[pCounts] )
term.out( 13 )
pImports += 2
pCounts += 2
if top
fs.SkipBytes( $4 ) ' look into the top sob's object header
firstPubOffset := fs.ReadWord ' and get offset to first pub
firstPubLocalsSize := fs.ReadWord ' and size of first pub's locals
fs.Close
' Process the imported sobs
pStart := word[pStart +_pNext]
repeat while pStart
ProcessSob( pStart, false )
pStart := word[pStart +_pNext]
if verbosity => 2
term.str( string("done with ") )
term.str( word[p +_pName] )
term.out( 13 )
pri GetTimestamp( pFilename )
str.Append( pFilename, string(".SOB") )
fs[1].Open( pFilename, "R" )
fs[1].ReadLong
result := fs[1].ReadLong
fs[1].Close
byte[pFilename][ strsize(pFilename) - 4 ]~ ' remove .SOB tail
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,238 +0,0 @@
obj
str: "stringx"
dat
cog long 0
pub Init( p0, p1 )
pFree := p0 ' leave some room for the stack, then free space.
pLimit := p1
Stop
sync~~
cog := cognew( @LookerUpper, @input ) + 1
ifnot cog
abort string("Couldn't start bintree cog")
repeat while sync
pub Stop
if cog
cogstop( cog~ - 1 )
pub FindInTable( s, p ) | d
{{
Finds string s in table pointed to by p.
Returns pointer to s's data area if s is found, 0 otherwise.
}}
input[0] := s
input[1] := p
sync~~
repeat while sync
return output
{
ifnot p
return 0
d := str.Compare( s, p+4 )
ifnot d
return p + 4 + strsize(s) + 1
if d < 0
return FindInTable( s, Peekw(p) )
' else
return FindInTable( s, Peekw(p+2) )
}
pub AddToTable( s, pP ) | p, d
{{
Adds string s to table. Note: pP is a pointer-to-pointer to table.
Returns a pointer to s's data area (actually pFree, so if you add
any data, increment pFree past it).
}}
ifnot p := PeekW( pP )
PokeW( pP, pFree )
PokeW( pFree, 0 )
pFree += 2
PokeW( pFree, 0 )
pFree += 2
str.Copy( pFree, s )
pFree += strsize(s) + 1
return pFree
d := str.Compare( s, p+4 )
{
term.dec(d)
term.out(13)
waitcnt( clkfreq + cnt )
}
ifnot d
abort string("Symbol already defined")
if d < 0
return AddToTable( s, @word[p][0] )
' else
return AddToTable( s, @word[p][1] )
pub PeekW( p )
return byte[p++] + byte[p] << 8
pub PokeW( p, w )
byte[p++] := w
byte[p] := w >> 8
pub PeekL( p ) : t
repeat 4
t := (t | byte[p++]) -> 8
pub PokeL( p, l )
repeat 4
byte[p++] := l
l >>= 8
dat
pFree long 0
pLimit long 0
pub Alloc( n )
result := pFree
if (pFree += n) > pLimit
abort string("Out of symbol table space")
dat
input long 0 ' rendezvous variables for LookerUpper
output long 0
sync long 1
{
This PASM routine is equivalent to the following:
pub FindInTable( s, p ) | d
{{
Finds string s in table pointed to by p.
Returns pointer to s's data area if s is found, 0 otherwise.
}}
ifnot p
return 0
d := str.Compare( s, p+4 )
ifnot d
return p + 4 + strsize(s) + 1
if d < 0
return FindInTable( s, Peekw(p) )
' else
return FindInTable( s, Peekw(p+2) )
}
dat org 0
LookerUpper
mov pInput, par ' Enter with par pointing to rendezvous area,
mov pOutput, par ' sync = 1
add pOutput, #4
mov pSync, par
add pSync, #8
rdlong pTable, pInput ' Save @tableStart
' and ack to inform Spin program that the cog is running.
Ack
wrlong retval, pOutput
mov temp, #0
wrlong temp, pSync
:wait ' Wait for caller to set sync to indicate that input is ready.
rdlong temp, pSync wz
if_z jmp #:wait
rdlong pString, pInput ' input[0] points to string to look up.
rdlong ptr, pOutput ' input[1] points to table. (input[1] = output)
mov retval, #0
:loop
tjz ptr, #Ack
mov pLeft, pString ' Compare string
mov pRight, ptr ' to string at current position in table
add pRight, #4 ' (bump up ptr by 4 to skip two link words).
call #StringCompare
if_e jmp #:equal
if_b jmp #:less
:greater ' If left > right,
add ptr, #2 ' use the 2nd link.
:less ' If left < right, use 1st link.
rdbyte temp, ptr ' Follow the link
add ptr, #1 ' It would be nice to just "rdword ptr, ptr" here
rdbyte ptr, ptr ' but ptr might be odd so we have to go through
shl ptr, #8 ' some extra gyrations.
add ptr, temp
jmp #:loop ' and recurse (well, just iterate).
:equal ' If left = right, return ptr + 4 + strsize(pString) + 1
mov retval, ptr
add retval, #5
:x
rdbyte temp, pString wz ' add strsize(pString)
if_z jmp #:y
add retval, #1
add pString, #1
jmp #:x
:y
jmp #Ack
StringCompare
' Compares zero-terminated strings pointed to by pLeft and pRight.
' On return, Z and C are set appropriately.
rdbyte temp, pLeft wz
add pLeft, #1
if_z jmp #:leftEnd
rdbyte temp1, pRight wz
add pRight, #1
if_z jmp #:rightEnd
cmp temp, temp1 wc, wz
if_e jmp #StringCompare ' If they match, try the next pair.
jmp #StringCompare_ret ' Otherwise, we're done.
:leftEnd rdbyte temp1, pRight wz ' If we're at the end of both strings,
if_z jmp #StringCompare_ret ' leave (with Z set).
' Otherwise, left string is shorter than the right
' and therefore less.
neg temp, #1
mov temp, temp wc, wz ' Set C=1 and Z=0 for "less than"
jmp #StringCompare_ret
:rightEnd ' Here we've reached the end of the right string.
' The left string is longer than the right
' and therefore greater.
mov temp, #1 wc, wz ' Set C=0 and Z=0 for "greater than"
StringCompare_ret
ret
temp res 1
temp1 res 1
ptr res 1
pLeft res 1
pRight res 1
pString res 1
pTable res 1
pInput res 1
pOutput res 1
pSync res 1
retval res 1
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,219 +0,0 @@
''***************************************
''* Floating-Point Math *
''* Single-precision IEEE-754 *
''* Author: Chip Gracey *
''* Copyright (c) 2006 Parallax, Inc. *
''* See end of file for terms of use. *
''***************************************
PUB FFloat(integer) : single | s, x, m
''Convert integer to float
if m := ||integer 'absolutize mantissa, if 0, result 0
s := integer >> 31 'get sign
x := >|m - 1 'get exponent
m <<= 31 - x 'msb-justify mantissa
m >>= 2 'bit29-justify mantissa
return Pack(@s) 'pack result
PUB FRound(single) : integer
''Convert float to rounded integer
return FInteger(single, 1) 'use 1/2 to round
PUB FTrunc(single) : integer
''Convert float to truncated integer
return FInteger(single, 0) 'use 0 to round
PUB FNeg(singleA) : single
''Negate singleA
return singleA ^ $8000_0000 'toggle sign bit
PUB FAbs(singleA) : single
''Absolute singleA
return singleA & $7FFF_FFFF 'clear sign bit
PUB FSqr(singleA) : single | s, x, m, root
''Compute square root of singleA
if singleA > 0 'if a =< 0, result 0
Unpack(@s, singleA) 'unpack input
m >>= !x & 1 'if exponent even, shift mantissa down
x ~>= 1 'get root exponent
root := $4000_0000 'compute square root of mantissa
repeat 31
result |= root
if result ** result > m
result ^= root
root >>= 1
m := result >> 1
return Pack(@s) 'pack result
PUB FAdd(singleA, singleB) : single | sa, xa, ma, sb, xb, mb
''Add singleA and singleB
Unpack(@sa, singleA) 'unpack inputs
Unpack(@sb, singleB)
if sa 'handle mantissa negation
-ma
if sb
-mb
result := ||(xa - xb) <# 31 'get exponent difference
if xa > xb 'shift lower-exponent mantissa down
mb ~>= result
else
ma ~>= result
xa := xb
ma += mb 'add mantissas
sa := ma < 0 'get sign
||ma 'absolutize result
return Pack(@sa) 'pack result
PUB FSub(singleA, singleB) : single
''Subtract singleB from singleA
return FAdd(singleA, FNeg(singleB))
PUB FMul(singleA, singleB) : single | sa, xa, ma, sb, xb, mb
''Multiply singleA by singleB
Unpack(@sa, singleA) 'unpack inputs
Unpack(@sb, singleB)
sa ^= sb 'xor signs
xa += xb 'add exponents
ma := (ma ** mb) << 3 'multiply mantissas and justify
return Pack(@sa) 'pack result
PUB FDiv(singleA, singleB) : single | sa, xa, ma, sb, xb, mb
''Divide singleA by singleB
Unpack(@sa, singleA) 'unpack inputs
Unpack(@sb, singleB)
sa ^= sb 'xor signs
xa -= xb 'subtract exponents
repeat 30 'divide mantissas
result <<= 1
if ma => mb
ma -= mb
result++
ma <<= 1
ma := result
return Pack(@sa) 'pack result
PRI FInteger(a, r) : integer | s, x, m
'Convert float to rounded/truncated integer
Unpack(@s, a) 'unpack input
if x => -1 and x =< 30 'if exponent not -1..30, result 0
m <<= 2 'msb-justify mantissa
m >>= 30 - x 'shift down to 1/2-lsb
m += r 'round (1) or truncate (0)
m >>= 1 'shift down to lsb
if s 'handle negation
-m
return m 'return integer
PRI Unpack(pointer, single) | s, x, m
'Unpack floating-point into (sign, exponent, mantissa) at pointer
s := single >> 31 'unpack sign
x := single << 1 >> 24 'unpack exponent
m := single & $007F_FFFF 'unpack mantissa
if x 'if exponent > 0,
m := m << 6 | $2000_0000 '..bit29-justify mantissa with leading 1
else
result := >|m - 23 'else, determine first 1 in mantissa
x := result '..adjust exponent
m <<= 7 - result '..bit29-justify mantissa
x -= 127 'unbias exponent
longmove(pointer, @s, 3) 'write (s,x,m) structure from locals
PRI Pack(pointer) : single | s, x, m
'Pack floating-point from (sign, exponent, mantissa) at pointer
longmove(@s, pointer, 3) 'get (s,x,m) structure into locals
if m 'if mantissa 0, result 0
result := 33 - >|m 'determine magnitude of mantissa
m <<= result 'msb-justify mantissa without leading 1
x += 3 - result 'adjust exponent
m += $00000100 'round up mantissa by 1/2 lsb
if not m & $FFFFFF00 'if rounding overflow,
x++ '..increment exponent
x := x + 127 #> -23 <# 255 'bias and limit exponent
if x < 1 'if exponent < 1,
m := $8000_0000 + m >> 1 '..replace leading 1
m >>= -x '..shift mantissa down by exponent
x~ '..exponent is now 0
return s << 31 | x << 23 | m >> 9 'pack result
{{
+------------------------------------------------------------------------------------------------------------------------------+
¦ 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

@ -1,534 +0,0 @@
''*****************************************
''* Floating-Point <-> Strings v 1.2 *
''* Single-precision IEEE-754 *
''* Authors: Chip Gracey and Cam Thompson *
''* (C) 2006 Parallax, Inc. *
''* See end of file for terms of use. *
''*****************************************
'' v1.0 - 01 May 2006 - original version
'' v1.1 - 12 Jul 2006 - added FloatToFormat routine
'' v1.2 - 06 Mar 2009 - added StringToFloat [mpark]
VAR
long p, digits, exponent, integer, tens, zeros, precision
long positive_chr, decimal_chr, thousands_chr, thousandths_chr
byte float_string[20]
OBJ
' The F object can be FloatMath, Float32 or Float32Full depending on the application
F : "FltMath"
PUB FloatToString(Single) : StringPtr
''Convert floating-point number to string
''
'' entry:
'' Single = floating-point number
''
'' exit:
'' StringPtr = pointer to resultant z-string
''
'' Magnitudes below 1e+12 and within 1e-12 will be expressed directly;
'' otherwise, scientific notation will be used.
''
'' examples results
'' -----------------------------------------
'' FloatToString(0.0) "0"
'' FloatToString(1.0) "1"
'' FloatToString(-1.0) "-1"
'' FloatToString(^^2.0) "1.414214"
'' FloatToString(2.34e-3) "0.00234"
'' FloatToString(-1.5e-5) "-0.000015"
'' FloatToString(2.7e+6) "2700000"
'' FloatToString(1e11) "100000000000"
'' FloatToString(1e12) "1.000000e+12"
'' FloatToString(1e-12) "0.000000000001"
'' FloatToString(1e-13) "1.000000e-13"
'perform initial setup
StringPtr := Setup(Single)
'eliminate trailing zeros
if integer
repeat until integer // 10
integer /= 10
tens /= 10
digits--
else
digits~
'express number according to exponent
case exponent
'in range left of decimal
11..0:
AddDigits(exponent + 1)
'in range right of decimal
-1..digits - 13:
zeros := -exponent
AddDigits(1)
'out of range, do scientific notation
other:
DoScientific
'terminate z-string
byte[p]~
PUB FloatToScientific(Single) : StringPtr
''Convert floating-point number to scientific-notation string
''
'' entry:
'' Single = floating-point number
''
'' exit:
'' StringPtr = pointer to resultant z-string
''
'' examples results
'' -------------------------------------------------
'' FloatToScientific(1e-9) "1.000000e-9"
'' FloatToScientific(^^2.0) "1.414214e+0"
'' FloatToScientific(0.00251) "2.510000e-3"
'' FloatToScientific(-0.0000150043) "-1.500430e-5"
'perform initial setup
StringPtr := Setup(Single)
'do scientific notation
DoScientific
'terminate z-string
byte[p]~
PUB FloatToMetric(Single, SuffixChr) : StringPtr | x, y
''Convert floating-point number to metric string
''
'' entry:
'' Single = floating-point number
'' SuffixChr = optional ending character (0=none)
''
'' exit:
'' StringPtr = pointer to resultant z-string
''
'' Magnitudes within the metric ranges will be expressed in metric
'' terms; otherwise, scientific notation will be used.
''
'' range name symbol
'' -----------------------
'' 1e24 yotta Y
'' 1e21 zetta Z
'' 1e18 exa E
'' 1e15 peta P
'' 1e12 tera T
'' 1e9 giga G
'' 1e6 mega M
'' 1e3 kilo k
'' 1e0 - -
'' 1e-3 milli m
'' 1e-6 micro u
'' 1e-9 nano n
'' 1e-12 pico p
'' 1e-15 femto f
'' 1e-18 atto a
'' 1e-21 zepto z
'' 1e-24 yocto y
''
'' examples results
'' ------------------------------------
'' metric(2000.0, "m") "2.000000km"
'' metric(-4.5e-5, "A") "-45.00000uA"
'' metric(2.7e6, 0) "2.700000M"
'' metric(39e31, "W") "3.9000e+32W"
'perform initial setup
StringPtr := Setup(Single)
'determine thousands exponent and relative tens exponent
x := (exponent + 45) / 3 - 15
y := (exponent + 45) // 3
'if in metric range, do metric
if ||x =< 8
'add digits with possible decimal
AddDigits(y + 1)
'if thousands exponent not 0, add metric indicator
if x
byte[p++] := " "
byte[p++] := metric[x]
'if out of metric range, do scientific notation
else
DoScientific
'if SuffixChr not 0, add SuffixChr
if SuffixChr
byte[p++] := SuffixChr
'terminate z-string
byte[p]~
PUB FloatToFormat(single, width, dp) : stringptr | n, w2
''Convert floating-point number to formatted string
''
'' entry:
'' Single = floating-point number
'' width = width of field
'' dp = number of decimal points
''
'' exit:
'' StringPtr = pointer to resultant z-string
''
'' asterisks are displayed for format errors
'' leading blank fill is used
' get string pointer
stringptr := p := @float_string
' width must be 1 to 9, dp must be 0 to width-1
w2 := width := width #> 1 <# 9
dp := dp #> 0 <# (width - 2)
if dp > 0
w2--
if single & $8000_0000 or positive_chr
w2--
' get positive scaled integer value
n := F.FRound(F.FMul(single & $7FFF_FFFF , F.FFloat(teni[dp])))
if n => teni[w2]
' if format error, display asterisks
repeat while width
if --width == dp
if decimal_chr
byte[p++] := decimal_chr
else
byte[p++] := "."
else
byte[p++] := "*"
byte[p]~
else
' store formatted number
p += width
byte[p]~
repeat width
byte[--p] := n // 10 + "0"
n /= 10
if --dp == 0
if decimal_chr
byte[--p] := decimal_chr
else
byte[--p] := "."
if n == 0 and dp < 0
quit
' store sign
if single & $80000000
byte[--p] := "-"
elseif positive_chr
byte[--p] := positive_chr
' leading blank fill
repeat while p <> stringptr
byte[--p] := " "
PUB SetPrecision(NumberOfDigits)
''Set precision to express floating-point numbers in
''
'' NumberOfDigits = Number of digits to round to, limited to 1..7 (7=default)
''
'' examples results
'' -------------------------------
'' SetPrecision(1) "1e+0"
'' SetPrecision(4) "1.000e+0"
'' SetPrecision(7) "1.000000e+0"
precision := NumberOfDigits
PUB SetPositiveChr(PositiveChr)
''Set lead character for positive numbers
''
'' PositiveChr = 0: no character will lead positive numbers (default)
'' non-0: PositiveChr will lead positive numbers (ie " " or "+")
''
'' examples results
'' ----------------------------------------
'' SetPositiveChr(0) "20.07" "-20.07"
'' SetPositiveChr(" ") " 20.07" "-20.07"
'' SetPositiveChr("+") "+20.07" "-20.07"
positive_chr := PositiveChr
PUB SetDecimalChr(DecimalChr)
''Set decimal point character
''
'' DecimalChr = 0: "." will be used (default)
'' non-0: DecimalChr will be used (ie "," for Europe)
''
'' examples results
'' ----------------------------
'' SetDecimalChr(0) "20.49"
'' SetDecimalChr(",") "20,49"
decimal_chr := DecimalChr
PUB SetSeparatorChrs(ThousandsChr, ThousandthsChr)
''Set thousands and thousandths separator characters
''
'' ThousandsChr =
'' 0: no character will separate thousands (default)
'' non-0: ThousandsChr will separate thousands
''
'' ThousandthsChr =
'' 0: no character will separate thousandths (default)
'' non-0: ThousandthsChr will separate thousandths
''
'' examples results
'' -----------------------------------------------------------
'' SetSeparatorChrs(0, 0) "200000000" "0.000729345"
'' SetSeparatorChrs(0, "_") "200000000" "0.000_729_345"
'' SetSeparatorChrs(",", 0) "200,000,000" "0.000729345"
'' SetSeparatorChrs(",", "_") "200,000,000" "0.000_729_345"
thousands_chr := ThousandsChr
thousandths_chr := ThousandthsChr
PUB StringToFloat(strptr) : flt | significand, ssign, places, exp, esign
{{
Converts string to floating-point number
entry:
strptr = pointer to z-string
exit:
flt = floating-point number
Assumes the following floating-point syntax: [-] [0-9]* [ . [0-9]* ] [ e|E [-|+] [0-9]* ]
+-- +----- +----------- +-------------------
¦ ¦ ¦ ¦ +---- +-----
Optional negative sign --------------------+ ¦ ¦ ¦ ¦ ¦
Digits ----------------------------------------+ ¦ ¦ ¦ ¦
Optional decimal point followed by digits ------------+ ¦ ¦ ¦
Optional exponent -------------------------------------------------+ ¦ ¦
optional exponent sign ------------------------------------------------+ ¦
exponent digits -------------------------------------------------------------+
Examples of recognized floating-point numbers:
"123", "-123", "123.456", "123.456e+09"
Conversion stops as soon as an invalid character is encountered. No error-checking.
Based on Ariba's StrToFloat in http://forums.parallax.com/forums/default.aspx?f=25&m=280607
Expanded by Michael Park
}}
significand~
ssign~
exp~
esign~
places~
repeat
case byte[strptr]
"-":
ssign~~
".":
places := 1
"0".."9":
significand := significand * 10 + byte[strptr] - "0"
if places
++places 'count decimal places
"e", "E":
++strptr ' skip over the e or E
repeat
case byte[strptr]
"+":
' ignore
"-":
esign~~
"0".."9":
exp := exp * 10 + byte[strptr] - "0"
other:
quit
++strptr
quit
other:
quit
++strptr
if ssign
-significand
flt := f.FFloat(significand)
ifnot esign ' tenf table is in decreasing order, so the sign of exp is reversed
-exp
if places
exp += places - 1
flt := f.FMul(flt, tenf[exp]) 'adjust flt's decimal point
PRI Setup(single) : stringptr
'limit digits to 1..7
if precision
digits := precision #> 1 <# 7
else
digits := 7
'initialize string pointer
p := @float_string
'add "-" if negative
if single & $80000000
byte[p++] := "-"
'otherwise, add any positive lead character
elseif positive_chr
byte[p++] := positive_chr
'clear sign and check for 0
if single &= $7FFFFFFF
'not 0, estimate exponent
exponent := ((single << 1 >> 24 - 127) * 77) ~> 8
'if very small, bias up
if exponent < -32
single := F.FMul(single, 1e13)
exponent += result := 13
'determine exact exponent and integer
repeat
integer := F.FRound(F.FMul(single, tenf[exponent - digits + 1]))
if integer < teni[digits - 1]
exponent--
elseif integer => teni[digits]
exponent++
else
exponent -= result
quit
'if 0, reset exponent and integer
else
exponent~
integer~
'set initial tens and clear zeros
tens := teni[digits - 1]
zeros~
'return pointer to string
stringptr := @float_string
PRI DoScientific
'add digits with possible decimal
AddDigits(1)
'add exponent indicator
byte[p++] := "e"
'add exponent sign
if exponent => 0
byte[p++] := "+"
else
byte[p++] := "-"
||exponent
'add exponent digits
if exponent => 10
byte[p++] := exponent / 10 + "0"
exponent //= 10
byte[p++] := exponent + "0"
PRI AddDigits(leading) | i
'add leading digits
repeat i := leading
AddDigit
'add any thousands separator between thousands
if thousands_chr
i--
if i and not i // 3
byte[p++] := thousands_chr
'if trailing digits, add decimal character
if digits
AddDecimal
'then add trailing digits
repeat while digits
'add any thousandths separator between thousandths
if thousandths_chr
if i and not i // 3
byte[p++] := thousandths_chr
i++
AddDigit
PRI AddDigit
'if leading zeros, add "0"
if zeros
byte[p++] := "0"
zeros--
'if more digits, add current digit and prepare next
elseif digits
byte[p++] := integer / tens + "0"
integer //= tens
tens /= 10
digits--
'if no more digits, add "0"
else
byte[p++] := "0"
PRI AddDecimal
if decimal_chr
byte[p++] := decimal_chr
else
byte[p++] := "."
DAT
long 1e+38, 1e+37, 1e+36, 1e+35, 1e+34, 1e+33, 1e+32, 1e+31
long 1e+30, 1e+29, 1e+28, 1e+27, 1e+26, 1e+25, 1e+24, 1e+23, 1e+22, 1e+21
long 1e+20, 1e+19, 1e+18, 1e+17, 1e+16, 1e+15, 1e+14, 1e+13, 1e+12, 1e+11
long 1e+10, 1e+09, 1e+08, 1e+07, 1e+06, 1e+05, 1e+04, 1e+03, 1e+02, 1e+01
tenf long 1e+00, 1e-01, 1e-02, 1e-03, 1e-04, 1e-05, 1e-06, 1e-07, 1e-08, 1e-09
long 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18, 1e-19
long 1e-20, 1e-21, 1e-22, 1e-23, 1e-24, 1e-25, 1e-26, 1e-27, 1e-28, 1e-29
long 1e-30, 1e-31, 1e-32, 1e-33, 1e-34, 1e-35, 1e-36, 1e-37, 1e-38
teni long 1, 10, 100, 1_000, 10_000, 100_000, 1_000_000, 10_000_000, 100_000_000, 1_000_000_000
byte "yzafpnum"
metric byte 0
byte "kMGTPEZY"
{{
+------------------------------------------------------------------------------------------------------------------------------+
¦ 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

@ -1,530 +0,0 @@
obj
bt: "bintree"
pub Init
tableStart += @tableStart
FixupTable( @tableStart + 2 )
pri FixupTable( p ) | q
q := bt.PeekW( p )
if q
bt.PokeW( p, q += @tableStart )
FixupTable( q )
q := bt.PeekW( p + 2 )
if q
bt.PokeW( p + 2, q += @tableStart )
FixupTable( q )
pub KeywordLookup( s )
return bt.FindInTable( s, tableStart )
con
{
31 (plain ID)
30 (int literal)
29 (float literal)
28 ?
27 unary
26 binary/postfix
25 pasm (TJZ, XOR)
24 cond (IF_Z, IF_E)
23 effect (WC, WZ)
22 stmtfn (BYTEMOVE, WAITCNT)
21 assignment op (-=, OR=)
20 intrinsic
19 prec3
18 prec2
17 d prec1
16 s prec0
15 pasmop spinop7
14 pasmop spinop6
13 pasmop spinop5 keyword
12 pasmop spinop4 uniquifier
11 pasmop spinop3 bits
10 pasmop spinop2 |
9 pasmop spinop1 | #args
8 pasmop spinop0 V #args
7 pasmop spinop7 id7 op
6 pasmop spinop6 id6 op
5 pasmop spinop5 id5 op
4 pasmop spinop4 id4 op
3 pasmop spinop3 cond3 id3 effect op
2 pasmop spinop2 cond2 id2 effect op
1 pasmop spinop1 cond1 id1 effect op
0 pasmop spinop0 cond0 id0 effect op
}
con ' The following is auto-generated. Do not edit.
kID = $80000000
kINTLITERAL = $40000000
kFLOATLITERAL = $20000000
kUNARY = $08000000
kBINARY = $04000000
kPOSTFIX = $04000000
kPASM = $02000000
kCOND = $01000000
kEFFECT = $00800000
kSTMTFN = $00400000
kASSIGNMENT = $00200000
kINTRINSIC = $00100000
' kBANG = $080100e7
' kOCTOTHORPRANGLE = $040700e4
' kAMPERSAND = $040300e8
' kSTAR = $040500f4
' kSTARSTAR = $040500f5
kPLUS = $040600ec
' kPLUSPLUS = $0c002820
kMINUS = $040600ed
' kMINUSMINUS = $0c003830
' kMINUSRANGLE = $040200e0
' kSLASH = $040500f6
' kSLASHSLASH = $040500f7
' kLANGLE = $040800f9
' kLANGLEOCTOTHORP = $040700e5
' kLANGLEMINUS = $040200e1
' kLANGLELANGLE = $040200e3
' kLANGLERANGLE = $040800fb
' kEQUALLANGLE = $040800fd
' kEQUALEQUAL = $040800fc
' kEQUALRANGLE = $040800fe
' kRANGLE = $040800fa
' kRANGLELANGLE = $040200ef
' kRANGLERANGLE = $040200e2
' kRANGLEBAR = $080100f1
kQUESTION = $0c000c08
kAT = $08000000
kATAT = $08000001
' kCARET = $040400eb
' kCARETCARET = $080100f8
kBAR = $040400ea
' kBARLANGLE = $080100f3
' kBARBAR = $080100e9
kTILDE = $0c001810
' kTILDERANGLE = $040200ee
kTILDETILDE = $0c001c14
kAND = $060a00f0
' kNOT = $080900ff
kOR = $060b00f2
' kABS = $0203a8bc
' kABSNEG = $0203acbc
' kADD = $020380bc
' kADDABS = $020388bc
' kADDS = $0203d0bc
' kADDSX = $0203d8bc
' kADDX = $0203c8bc
' kANDN = $020364bc
kCALL = $02015cfc
' kCMP = $0203843c
' kCMPS = $0203c03c
' kCMPSUB = $0203e0bc
' kCMPSX = $0203c43c
' kCMPX = $0203cc3c
' kDJNZ = $0203e4bc
' kHUBOP = $02030c3c
' kJMP = $02015c3c
' kJMPRET = $02035cbc
' kMAX = $02034cbc
' kMAXS = $020344bc
' kMIN = $020348bc
' kMINS = $020340bc
' kMOV = $0203a0bc
' kMOVD = $020354bc
' kMOVI = $020358bc
' kMOVS = $020350bc
' kMUXC = $020370bc
' kMUXNC = $020374bc
' kMUXNZ = $02037cbc
' kMUXZ = $020378bc
' kNEG = $0203a4bc
' kNEGC = $0203b0bc
' kNEGNC = $0203b4bc
' kNEGNZ = $0203bcbc
' kNEGZ = $0203b8bc
' kNOP = $02000000
' kRCL = $020334bc
' kRCR = $020330bc
' kRDBYTE = $020300bc
' kRDLONG = $020308bc
' kRDWORD = $020304bc
' kRET = $02005c7c
' kREV = $02033cbc
' kROL = $020324bc
' kROR = $020320bc
' kSAR = $020338bc
' kSHL = $02032cbc
' kSHR = $020328bc
' kSUB = $020384bc
' kSUBABS = $02038cbc
' kSUBS = $0203d4bc
' kSUBSX = $0203dcbc
' kSUBX = $0203ccbc
' kSUMC = $020390bc
' kSUMNC = $020394bc
' kSUMNZ = $02039cbc
' kSUMZ = $020398bc
' kTEST = $0203603c
' kTJNZ = $0203e83c
' kTJZ = $0203ec3c
' kWRBYTE = $0203003c
' kWRLONG = $0203083c
' kWRWORD = $0203043c
' kXOR = $02036cbc
kPAR = $00000001
' kCNT = $00000002
' kINA = $00000003
' kINB = $00000004
' kOUTA = $00000005
' kOUTB = $00000006
' kDIRA = $00000007
' kDIRB = $00000008
' kCTRA = $00000009
' kCTRB = $0000000a
' kFRQA = $0000000b
' kFRQB = $0000000c
' kPHSA = $0000000d
' kPHSB = $0000000e
' kVCFG = $0000000f
kVSCL = $00000010
' kIF_A = $01000001
' kIF_AE = $01000003
' kIF_ALWAYS = $0100000f
' kIF_B = $0100000c
' kIF_BE = $0100000e
' kIF_C = $0100000c
' kIF_C_AND_NZ = $01000004
' kIF_C_AND_Z = $01000008
' kIF_C_EQ_Z = $01000009
' kIF_C_NE_Z = $01000006
' kIF_C_OR_NZ = $0100000d
' kIF_C_OR_Z = $0100000e
' kIF_E = $0100000a
' kIF_NC = $01000003
' kIF_NC_AND_NZ = $01000001
' kIF_NC_AND_Z = $01000002
' kIF_NC_OR_NZ = $01000007
' kIF_NC_OR_Z = $0100000b
' kIF_NE = $01000005
' kIF_NEVER = $01000000
' kIF_NZ = $01000005
' kIF_NZ_AND_C = $01000004
' kIF_NZ_AND_NC = $01000001
' kIF_NZ_OR_C = $0100000e
' kIF_NZ_OR_NC = $0100000b
' kIF_Z = $0100000a
' kIF_Z_AND_C = $01000008
' kIF_Z_AND_NC = $01000002
' kIF_Z_EQ_C = $01000009
' kIF_Z_NE_C = $01000006
' kIF_Z_OR_C = $0100000e
' kIF_Z_OR_NC = $0100000b
' kNR = $00800008
' kWC = $00800002
' kWR = $00800001
' kWZ = $00800004
kCON = $00000011
kDAT = $00000012
kOBJ = $00000013
kPRI = $00000014
kPUB = $00000015
kVAR = $00000016
kBYTE = $00000017
kWORD = $00000018
kLONG = $00000019
' kBYTEFILL = $00400318
' kWORDFILL = $00400319
' kLONGFILL = $0040031a
' kBYTEMOVE = $0040031c
' kWORDMOVE = $0040031d
' kLONGMOVE = $0040031e
kCLKSET = $02400220
kCOGSTOP = $02400121
' kLOCKRET = $00400122
kWAITCNT = $02400123
kWAITPEQ = $0240031b
kWAITPNE = $0240031f
kWAITVID = $02400227
kOCTOTHORP = $0000001a
' kDOLLAR = $0000001b
kLPAREN = $0000001c
kRPAREN = $0000001d
kCOMMA = $0000001e
kDOT = $0000001f
kDOTDOT = $00000020
kCOLON = $00000021
kCOLONEQUAL = $00200022
kEQUAL = $00000023
kABORT = $00000024
kCASE = $00000025
kCHIPVER = $00100000
kCLKFREQ = $00100010
kCLKMODE = $00100020
kCOGID = $02100003
kCOGINIT = $02100004
kCOGNEW = $00100005
kREBOOT = $00100006
' kSTRCOMP = $00100172
' kSTRSIZE = $00100161
' kLOCKCLR = $0012b2f1
' kLOCKNEW = $001292d0
' kLOCKSET = $0012a2e1
' kLOOKDOWN = $00113111
' kLOOKDOWNZ = $00113110
' kLOOKUP = $00112101
' kLOOKUPZ = $00112100
kCONSTANT = $00000026
kELSE = $00000027
kELSEIF = $00000028
kELSEIFNOT = $00000029
' kFILE = $0000002a
kFIT = $0000002b
' kFLOAT = $0000002c
kFROM = $0000002d
kIF = $0000002e
kIFNOT = $0000002f
kNEXT = $00000030
kORG = $00000031
' kORGX = $00000032
kOTHER = $00000033
kQUIT = $00000034
kREPEAT = $00000035
kRES = $00000036
kRESULT = $00000037
kRETURN = $00000038
' kROUND = $00000039
kSPR = $0000003a
kSTEP = $0000003b
kSTRING = $0000003c
kTO = $0000003d
' kTRUNC = $0000003e
kUNTIL = $0000003f
kWHILE = $00000040
kLBRACKET = $00000041
kBACKSLASH = $00000042
kRBRACKET = $00000043
kLBRACE = $00000044
kRBRACE = $00000045
kEOL = $000000fd
kEOF = $000000fe
kUNKNOWN = $000000ff
dat
tableStart word $0002
byte $0e,$00,$63,$06,$49,$4e,$41,$00,$03,$00,$00,$00,$1c,$00,$d6,$02
byte $43,$4d,$50,$53,$58,$00,$3c,$c4,$03,$02,$27,$00,$57,$01,$3d,$3e
byte $00,$fe,$00,$08,$04,$32,$00,$c2,$00,$2d,$3e,$00,$e0,$00,$02,$04
byte $3c,$00,$83,$00,$2a,$00,$f4,$00,$05,$04,$46,$00,$65,$00,$24,$00
byte $1b,$00,$00,$00,$50,$00,$5a,$00,$23,$00,$1a,$00,$00,$00,$00,$00
byte $00,$00,$21,$00,$e7,$00,$01,$08,$00,$00,$00,$00,$23,$3e,$00,$e4
byte $00,$07,$04,$6f,$00,$79,$00,$28,$00,$1c,$00,$00,$00,$00,$00,$00
byte $00,$26,$00,$e8,$00,$03,$04,$00,$00,$00,$00,$29,$00,$1d,$00,$00
byte $00,$8d,$00,$ad,$00,$2c,$00,$1e,$00,$00,$00,$97,$00,$a2,$00,$2b
byte $00,$ec,$00,$06,$04,$00,$00,$00,$00,$2a,$2a,$00,$f5,$00,$05,$04
byte $00,$00,$00,$00,$2b,$2b,$00,$20,$28,$00,$0c,$b8,$00,$00,$00,$2d
byte $2d,$00,$30,$38,$00,$0c,$00,$00,$00,$00,$2d,$00,$ed,$00,$06,$04
byte $cd,$00,$16,$01,$3c,$23,$00,$e5,$00,$07,$04,$d8,$00,$f7,$00,$2f
byte $2f,$00,$f7,$00,$05,$04,$e3,$00,$ed,$00,$2e,$2e,$00,$20,$00,$00
byte $00,$00,$00,$00,$00,$2e,$00,$1f,$00,$00,$00,$00,$00,$00,$00,$2f
byte $00,$f6,$00,$05,$04,$02,$01,$0c,$01,$3a,$3d,$00,$22,$00,$20,$00
byte $00,$00,$00,$00,$3a,$00,$21,$00,$00,$00,$00,$00,$00,$00,$3c,$00
byte $f9,$00,$08,$04,$20,$01,$41,$01,$3d,$00,$23,$00,$00,$00,$2b,$01
byte $36,$01,$3c,$3c,$00,$e3,$00,$02,$04,$00,$00,$00,$00,$3c,$2d,$00
byte $e1,$00,$02,$04,$00,$00,$00,$00,$3c,$3e,$00,$fb,$00,$08,$04,$4c
byte $01,$00,$00,$3d,$3d,$00,$fc,$00,$08,$04,$00,$00,$00,$00,$3d,$3c
byte $00,$fd,$00,$08,$04,$64,$01,$0d,$02,$41,$44,$44,$58,$00,$bc,$c8
byte $03,$02,$72,$01,$bc,$01,$41,$42,$4f,$52,$54,$00,$24,$00,$00,$00
byte $7d,$01,$9d,$01,$3e,$7c,$00,$f1,$00,$01,$08,$88,$01,$92,$01,$3e
byte $3c,$00,$ef,$00,$02,$04,$00,$00,$00,$00,$3e,$00,$fa,$00,$08,$04
byte $00,$00,$00,$00,$3e,$3e,$00,$e2,$00,$02,$04,$a7,$01,$b1,$01,$40
byte $00,$00,$00,$00,$08,$00,$00,$00,$00,$3f,$00,$08,$0c,$00,$0c,$00
byte $00,$00,$00,$40,$40,$00,$01,$00,$00,$08,$cb,$01,$f2,$01,$41,$44
byte $44,$41,$42,$53,$00,$bc,$88,$03,$02,$da,$01,$e6,$01,$41,$42,$53
byte $4e,$45,$47,$00,$bc,$ac,$03,$02,$00,$00,$00,$00,$41,$42,$53,$00
byte $bc,$a8,$03,$02,$00,$00,$00,$00,$41,$44,$44,$00,$bc,$80,$03,$02
byte $00,$02,$00,$00,$41,$44,$44,$53,$58,$00,$bc,$d8,$03,$02,$00,$00
byte $00,$00,$41,$44,$44,$53,$00,$bc,$d0,$03,$02,$1d,$02,$7f,$02,$43
byte $48,$49,$50,$56,$45,$52,$00,$00,$00,$10,$00,$2e,$02,$54,$02,$42
byte $59,$54,$45,$46,$49,$4c,$4c,$00,$18,$03,$40,$00,$3b,$02,$47,$02
byte $41,$4e,$44,$4e,$00,$bc,$64,$03,$02,$00,$00,$00,$00,$41,$4e,$44
byte $00,$f0,$00,$0a,$06,$00,$00,$00,$00,$42,$59,$54,$45,$00,$17,$00
byte $00,$00,$61,$02,$72,$02,$43,$41,$4c,$4c,$00,$fc,$5c,$01,$02,$00
byte $00,$00,$00,$42,$59,$54,$45,$4d,$4f,$56,$45,$00,$1c,$03,$40,$00
byte $00,$00,$00,$00,$43,$41,$53,$45,$00,$25,$00,$00,$00,$8b,$02,$ba
byte $02,$43,$4d,$50,$00,$3c,$84,$03,$02,$9b,$02,$ab,$02,$43,$4c,$4b
byte $4d,$4f,$44,$45,$00,$20,$00,$10,$00,$00,$00,$00,$00,$43,$4c,$4b
byte $46,$52,$45,$51,$00,$10,$00,$10,$00,$00,$00,$00,$00,$43,$4c,$4b
byte $53,$45,$54,$00,$20,$02,$40,$02,$c9,$02,$00,$00,$43,$4d,$50,$53
byte $55,$42,$00,$bc,$e0,$03,$02,$00,$00,$00,$00,$43,$4d,$50,$53,$00
byte $3c,$c0,$03,$02,$e3,$02,$73,$04,$49,$46,$5f,$42,$00,$0c,$00,$00
byte $01,$f0,$02,$b0,$03,$45,$4c,$53,$45,$00,$27,$00,$00,$00,$01,$03
byte $63,$03,$43,$4f,$4e,$53,$54,$41,$4e,$54,$00,$26,$00,$00,$00,$11
byte $03,$38,$03,$43,$4f,$47,$49,$4e,$49,$54,$00,$04,$00,$10,$02,$1d
byte $03,$2a,$03,$43,$4e,$54,$00,$02,$00,$00,$00,$00,$00,$00,$00,$43
byte $4d,$50,$58,$00,$3c,$cc,$03,$02,$00,$00,$00,$00,$43,$4f,$47,$49
byte $44,$00,$03,$00,$10,$02,$48,$03,$57,$03,$43,$4f,$47,$53,$54,$4f
byte $50,$00,$21,$01,$40,$02,$00,$00,$00,$00,$43,$4f,$47,$4e,$45,$57
byte $00,$05,$00,$10,$00,$00,$00,$00,$00,$43,$4f,$4e,$00,$11,$00,$00
byte $00,$70,$03,$96,$03,$44,$49,$52,$41,$00,$07,$00,$00,$00,$7d,$03
byte $8a,$03,$43,$54,$52,$42,$00,$0a,$00,$00,$00,$00,$00,$00,$00,$43
byte $54,$52,$41,$00,$09,$00,$00,$00,$00,$00,$00,$00,$44,$41,$54,$00
byte $12,$00,$00,$00,$a3,$03,$00,$00,$44,$4a,$4e,$5a,$00,$bc,$e4,$03
byte $02,$00,$00,$00,$00,$44,$49,$52,$42,$00,$08,$00,$00,$00,$bd,$03
byte $1f,$04,$46,$52,$51,$42,$00,$0c,$00,$00,$00,$c9,$03,$f7,$03,$46
byte $49,$54,$00,$2b,$00,$00,$00,$db,$03,$ea,$03,$45,$4c,$53,$45,$49
byte $46,$4e,$4f,$54,$00,$29,$00,$00,$00,$00,$00,$00,$00,$45,$4c,$53
byte $45,$49,$46,$00,$28,$00,$00,$00,$00,$00,$00,$00,$46,$49,$4c,$45
byte $00,$2a,$00,$00,$00,$04,$04,$12,$04,$46,$52,$4f,$4d,$00,$2d,$00
byte $00,$00,$00,$00,$00,$00,$46,$4c,$4f,$41,$54,$00,$2c,$00,$00,$00
byte $00,$00,$00,$00,$46,$52,$51,$41,$00,$0b,$00,$00,$00,$2c,$04,$53
byte $04,$49,$46,$5f,$41,$00,$01,$00,$00,$01,$37,$04,$45,$04,$49,$46
byte $00,$2e,$00,$00,$00,$00,$00,$00,$00,$48,$55,$42,$4f,$50,$00,$3c
byte $0c,$03,$02,$00,$00,$00,$00,$49,$46,$4e,$4f,$54,$00,$2f,$00,$00
byte $00,$65,$04,$00,$00,$49,$46,$5f,$41,$4c,$57,$41,$59,$53,$00,$0f
byte $00,$00,$01,$00,$00,$00,$00,$49,$46,$5f,$41,$45,$00,$03,$00,$00
byte $01,$81,$04,$77,$05,$49,$46,$5f,$4e,$45,$00,$05,$00,$00,$01,$93
byte $04,$0c,$05,$49,$46,$5f,$43,$5f,$4f,$52,$5f,$5a,$00,$0e,$00,$00
byte $01,$a6,$04,$d5,$04,$49,$46,$5f,$43,$5f,$41,$4e,$44,$5f,$5a,$00
byte $08,$00,$00,$01,$b3,$04,$c1,$04,$49,$46,$5f,$43,$00,$0c,$00,$00
byte $01,$00,$00,$00,$00,$49,$46,$5f,$42,$45,$00,$0e,$00,$00,$01,$00
byte $00,$00,$00,$49,$46,$5f,$43,$5f,$41,$4e,$44,$5f,$4e,$5a,$00,$04
byte $00,$00,$01,$e7,$04,$f9,$04,$49,$46,$5f,$43,$5f,$4e,$45,$5f,$5a
byte $00,$06,$00,$00,$01,$00,$00,$00,$00,$49,$46,$5f,$43,$5f,$45,$51
byte $5f,$5a,$00,$09,$00,$00,$01,$00,$00,$00,$00,$49,$46,$5f,$43,$5f
byte $4f,$52,$5f,$4e,$5a,$00,$0d,$00,$00,$01,$20,$05,$50,$05,$49,$46
byte $5f,$4e,$43,$5f,$41,$4e,$44,$5f,$5a,$00,$02,$00,$00,$01,$2e,$05
byte $3b,$05,$49,$46,$5f,$4e,$43,$00,$03,$00,$00,$01,$00,$00,$00,$00
byte $49,$46,$5f,$45,$00,$0a,$00,$00,$01,$00,$00,$00,$00,$49,$46,$5f
byte $4e,$43,$5f,$41,$4e,$44,$5f,$4e,$5a,$00,$01,$00,$00,$01,$63,$05
byte $00,$00,$49,$46,$5f,$4e,$43,$5f,$4f,$52,$5f,$5a,$00,$0b,$00,$00
byte $01,$00,$00,$00,$00,$49,$46,$5f,$4e,$43,$5f,$4f,$52,$5f,$4e,$5a
byte $00,$07,$00,$00,$01,$84,$05,$f3,$05,$49,$46,$5f,$5a,$00,$0a,$00
byte $00,$01,$99,$05,$cc,$05,$49,$46,$5f,$4e,$5a,$5f,$41,$4e,$44,$5f
byte $4e,$43,$00,$01,$00,$00,$01,$a7,$05,$b8,$05,$49,$46,$5f,$4e,$5a
byte $00,$05,$00,$00,$01,$00,$00,$00,$00,$49,$46,$5f,$4e,$45,$56,$45
byte $52,$00,$00,$00,$00,$01,$00,$00,$00,$00,$49,$46,$5f,$4e,$5a,$5f
byte $41,$4e,$44,$5f,$43,$00,$04,$00,$00,$01,$e0,$05,$00,$00,$49,$46
byte $5f,$4e,$5a,$5f,$4f,$52,$5f,$4e,$43,$00,$0b,$00,$00,$01,$00,$00
byte $00,$00,$49,$46,$5f,$4e,$5a,$5f,$4f,$52,$5f,$43,$00,$0e,$00,$00
byte $01,$05,$06,$3e,$06,$49,$46,$5f,$5a,$5f,$4e,$45,$5f,$43,$00,$06
byte $00,$00,$01,$19,$06,$2c,$06,$49,$46,$5f,$5a,$5f,$41,$4e,$44,$5f
byte $4e,$43,$00,$02,$00,$00,$01,$00,$00,$00,$00,$49,$46,$5f,$5a,$5f
byte $41,$4e,$44,$5f,$43,$00,$08,$00,$00,$01,$00,$00,$00,$00,$49,$46
byte $5f,$5a,$5f,$45,$51,$5f,$43,$00,$09,$00,$00,$01,$51,$06,$00,$00
byte $49,$46,$5f,$5a,$5f,$4f,$52,$5f,$4e,$43,$00,$0b,$00,$00,$01,$00
byte $00,$00,$00,$49,$46,$5f,$5a,$5f,$4f,$52,$5f,$43,$00,$0e,$00,$00
byte $01,$72,$06,$84,$09,$52,$45,$54,$55,$52,$4e,$00,$38,$00,$00,$00
byte $80,$06,$1a,$08,$4e,$45,$47,$4e,$5a,$00,$bc,$bc,$03,$02,$8c,$06
byte $64,$07,$4d,$41,$58,$00,$bc,$4c,$03,$02,$99,$06,$00,$07,$4c,$4f
byte $4e,$47,$00,$19,$00,$00,$00,$a9,$06,$d0,$06,$4c,$4f,$43,$4b,$43
byte $4c,$52,$00,$f1,$b2,$12,$00,$b5,$06,$c1,$06,$4a,$4d,$50,$00,$3c
byte $5c,$01,$02,$00,$00,$00,$00,$49,$4e,$42,$00,$04,$00,$00,$00,$00
byte $00,$00,$00,$4a,$4d,$50,$52,$45,$54,$00,$bc,$5c,$03,$02,$e0,$06
byte $f0,$06,$4c,$4f,$43,$4b,$52,$45,$54,$00,$22,$01,$40,$00,$00,$00
byte $00,$00,$4c,$4f,$43,$4b,$4e,$45,$57,$00,$d0,$92,$12,$00,$00,$00
byte $00,$00,$4c,$4f,$43,$4b,$53,$45,$54,$00,$e1,$a2,$12,$00,$12,$07
byte $45,$07,$4c,$4f,$4f,$4b,$44,$4f,$57,$4e,$5a,$00,$10,$31,$11,$00
byte $23,$07,$34,$07,$4c,$4f,$4e,$47,$4d,$4f,$56,$45,$00,$1e,$03,$40
byte $00,$00,$00,$00,$00,$4c,$4f,$4e,$47,$46,$49,$4c,$4c,$00,$1a,$03
byte $40,$00,$00,$00,$00,$00,$4c,$4f,$4f,$4b,$44,$4f,$57,$4e,$00,$11
byte $31,$11,$00,$55,$07,$00,$00,$4c,$4f,$4f,$4b,$55,$50,$5a,$00,$00
byte $21,$11,$00,$00,$00,$00,$00,$4c,$4f,$4f,$4b,$55,$50,$00,$01,$21
byte $11,$00,$71,$07,$ca,$07,$4d,$55,$58,$43,$00,$bc,$70,$03,$02,$7d
byte $07,$a3,$07,$4d,$4f,$56,$00,$bc,$a0,$03,$02,$89,$07,$96,$07,$4d
byte $49,$4e,$00,$bc,$48,$03,$02,$00,$00,$00,$00,$4d,$41,$58,$53,$00
byte $bc,$44,$03,$02,$00,$00,$00,$00,$4d,$49,$4e,$53,$00,$bc,$40,$03
byte $02,$b0,$07,$bd,$07,$4d,$4f,$56,$49,$00,$bc,$58,$03,$02,$00,$00
byte $00,$00,$4d,$4f,$56,$44,$00,$bc,$54,$03,$02,$00,$00,$00,$00,$4d
byte $4f,$56,$53,$00,$bc,$50,$03,$02,$d6,$07,$ff,$07,$4e,$45,$47,$00
byte $bc,$a4,$03,$02,$e4,$07,$f2,$07,$4d,$55,$58,$4e,$5a,$00,$bc,$7c
byte $03,$02,$00,$00,$00,$00,$4d,$55,$58,$4e,$43,$00,$bc,$74,$03,$02
byte $00,$00,$00,$00,$4d,$55,$58,$5a,$00,$bc,$78,$03,$02,$0d,$08,$00
byte $00,$4e,$45,$47,$4e,$43,$00,$bc,$b4,$03,$02,$00,$00,$00,$00,$4e
byte $45,$47,$43,$00,$bc,$b0,$03,$02,$27,$08,$d5,$08,$50,$48,$53,$42
byte $00,$0e,$00,$00,$00,$33,$08,$87,$08,$4f,$52,$47,$00,$31,$00,$00
byte $00,$3f,$08,$65,$08,$4e,$4f,$54,$00,$ff,$00,$09,$08,$4c,$08,$59
byte $08,$4e,$45,$58,$54,$00,$30,$00,$00,$00,$00,$00,$00,$00,$4e,$45
byte $47,$5a,$00,$bc,$b8,$03,$02,$00,$00,$00,$00,$4e,$4f,$50,$00,$00
byte $00,$00,$02,$71,$08,$7c,$08,$4f,$42,$4a,$00,$13,$00,$00,$00,$00
byte $00,$00,$00,$4e,$52,$00,$08,$00,$80,$00,$00,$00,$00,$00,$4f,$52
byte $00,$f2,$00,$0b,$06,$94,$08,$bc,$08,$4f,$55,$54,$42,$00,$06,$00
byte $00,$00,$a2,$08,$af,$08,$4f,$54,$48,$45,$52,$00,$33,$00,$00,$00
byte $00,$00,$00,$00,$4f,$52,$47,$58,$00,$32,$00,$00,$00,$00,$00,$00
byte $00,$4f,$55,$54,$41,$00,$05,$00,$00,$00,$c9,$08,$00,$00,$50,$48
byte $53,$41,$00,$0d,$00,$00,$00,$00,$00,$00,$00,$50,$41,$52,$00,$01
byte $00,$00,$00,$e4,$08,$30,$09,$52,$44,$4c,$4f,$4e,$47,$00,$bc,$08
byte $03,$02,$f0,$08,$15,$09,$52,$43,$4c,$00,$bc,$34,$03,$02,$fc,$08
byte $08,$09,$50,$55,$42,$00,$15,$00,$00,$00,$00,$00,$00,$00,$50,$52
byte $49,$00,$14,$00,$00,$00,$00,$00,$00,$00,$51,$55,$49,$54,$00,$34
byte $00,$00,$00,$24,$09,$00,$00,$52,$44,$42,$59,$54,$45,$00,$bc,$00
byte $03,$02,$00,$00,$00,$00,$52,$43,$52,$00,$bc,$30,$03,$02,$3c,$09
byte $69,$09,$52,$45,$53,$00,$36,$00,$00,$00,$4b,$09,$5a,$09,$52,$45
byte $42,$4f,$4f,$54,$00,$06,$00,$10,$00,$00,$00,$00,$00,$52,$44,$57
byte $4f,$52,$44,$00,$bc,$04,$03,$02,$00,$00,$00,$00,$52,$45,$50,$45
byte $41,$54,$00,$35,$00,$00,$00,$75,$09,$00,$00,$52,$45,$54,$00,$7c
byte $5c,$00,$02,$00,$00,$00,$00,$52,$45,$53,$55,$4c,$54,$00,$37,$00
byte $00,$00,$91,$09,$0e,$0b,$56,$53,$43,$4c,$00,$10,$00,$00,$00,$9e
byte $09,$57,$0a,$53,$55,$42,$53,$00,$bc,$d4,$03,$02,$aa,$09,$00,$0a
byte $53,$50,$52,$00,$3a,$00,$00,$00,$b8,$09,$dc,$09,$52,$4f,$55,$4e
byte $44,$00,$39,$00,$00,$00,$c4,$09,$d0,$09,$52,$4f,$4c,$00,$bc,$24
byte $03,$02,$00,$00,$00,$00,$52,$45,$56,$00,$bc,$3c,$03,$02,$00,$00
byte $00,$00,$52,$4f,$52,$00,$bc,$20,$03,$02,$e8,$09,$f4,$09,$53,$48
byte $4c,$00,$bc,$2c,$03,$02,$00,$00,$00,$00,$53,$41,$52,$00,$bc,$38
byte $03,$02,$00,$00,$00,$00,$53,$48,$52,$00,$bc,$28,$03,$02,$10,$0a
byte $3c,$0a,$53,$54,$52,$53,$49,$5a,$45,$00,$61,$01,$10,$00,$20,$0a
byte $2d,$0a,$53,$54,$52,$43,$4f,$4d,$50,$00,$72,$01,$10,$00,$00,$00
byte $00,$00,$53,$54,$45,$50,$00,$3b,$00,$00,$00,$00,$00,$00,$00,$53
byte $54,$52,$49,$4e,$47,$00,$3c,$00,$00,$00,$4b,$0a,$00,$00,$53,$55
byte $42,$41,$42,$53,$00,$bc,$8c,$03,$02,$00,$00,$00,$00,$53,$55,$42
byte $00,$bc,$84,$03,$02,$64,$0a,$c2,$0a,$54,$4a,$4e,$5a,$00,$3c,$e8
byte $03,$02,$72,$0a,$9a,$0a,$53,$55,$4d,$4e,$43,$00,$bc,$94,$03,$02
byte $7f,$0a,$8d,$0a,$53,$55,$42,$58,$00,$bc,$cc,$03,$02,$00,$00,$00
byte $00,$53,$55,$42,$53,$58,$00,$bc,$dc,$03,$02,$00,$00,$00,$00,$53
byte $55,$4d,$43,$00,$bc,$90,$03,$02,$a7,$0a,$b5,$0a,$53,$55,$4d,$5a
byte $00,$bc,$98,$03,$02,$00,$00,$00,$00,$53,$55,$4d,$4e,$5a,$00,$bc
byte $9c,$03,$02,$00,$00,$00,$00,$54,$45,$53,$54,$00,$3c,$60,$03,$02
byte $d0,$0a,$f5,$0a,$55,$4e,$54,$49,$4c,$00,$3f,$00,$00,$00,$db,$0a
byte $e7,$0a,$54,$4f,$00,$3d,$00,$00,$00,$00,$00,$00,$00,$54,$4a,$5a
byte $00,$3c,$ec,$03,$02,$00,$00,$00,$00,$54,$52,$55,$4e,$43,$00,$3e
byte $00,$00,$00,$02,$0b,$00,$00,$56,$43,$46,$47,$00,$0f,$00,$00,$00
byte $00,$00,$00,$00,$56,$41,$52,$00,$16,$00,$00,$00,$1a,$0b,$e5,$0b
byte $58,$4f,$52,$00,$bc,$6c,$03,$02,$2b,$0b,$91,$0b,$57,$4f,$52,$44
byte $46,$49,$4c,$4c,$00,$19,$03,$40,$00,$3b,$0b,$6b,$0b,$57,$41,$49
byte $54,$56,$49,$44,$00,$27,$02,$40,$02,$4b,$0b,$5b,$0b,$57,$41,$49
byte $54,$50,$45,$51,$00,$1b,$03,$40,$02,$00,$00,$00,$00,$57,$41,$49
byte $54,$43,$4e,$54,$00,$23,$01,$40,$02,$00,$00,$00,$00,$57,$41,$49
byte $54,$50,$4e,$45,$00,$1f,$03,$40,$02,$79,$0b,$84,$0b,$57,$48,$49
byte $4c,$45,$00,$40,$00,$00,$00,$00,$00,$00,$00,$57,$43,$00,$02,$00
byte $80,$00,$00,$00,$00,$00,$57,$4f,$52,$44,$00,$18,$00,$00,$00,$a0
byte $0b,$cb,$0b,$57,$52,$4c,$4f,$4e,$47,$00,$3c,$08,$03,$02,$ab,$0b
byte $bc,$0b,$57,$52,$00,$01,$00,$80,$00,$00,$00,$00,$00,$57,$4f,$52
byte $44,$4d,$4f,$56,$45,$00,$1d,$03,$40,$00,$00,$00,$00,$00,$57,$52
byte $42,$59,$54,$45,$00,$3c,$00,$03,$02,$d6,$0b,$00,$00,$57,$5a,$00
byte $04,$00,$80,$00,$00,$00,$00,$00,$57,$52,$57,$4f,$52,$44,$00,$3c
byte $04,$03,$02,$ef,$0b,$2c,$0c,$7c,$00,$ea,$00,$04,$04,$f9,$0b,$17
byte $0c,$5e,$00,$eb,$00,$04,$04,$03,$0c,$0d,$0c,$5c,$00,$42,$00,$00
byte $00,$00,$00,$00,$00,$5b,$00,$41,$00,$00,$00,$00,$00,$00,$00,$5d
byte $00,$43,$00,$00,$00,$21,$0c,$00,$00,$7b,$00,$44,$00,$00,$00,$00
byte $00,$00,$00,$5e,$5e,$00,$f8,$00,$01,$08,$36,$0c,$56,$0c,$7e,$00
byte $10,$18,$00,$0c,$41,$0c,$4c,$0c,$7c,$7c,$00,$e9,$00,$01,$08,$00
byte $00,$00,$00,$7c,$3c,$00,$f3,$00,$01,$08,$00,$00,$00,$00,$7d,$00
byte $45,$00,$00,$00,$61,$0c,$00,$00,$7e,$7e,$00,$14,$1c,$00,$0c,$00
byte $00,$00,$00,$7e,$3e,$00,$ee,$00,$02,$04
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,7 +0,0 @@
{{ Output.spin }}
PUB Toggle
dira[24]~~
repeat
!outa[24]
waitcnt(3_000_000 + cnt)

View File

@ -1,564 +0,0 @@
{{
Lex
usage: lex filename [options]
Reads filename.spn on SD card, writes tokens to filename.tok.
}}
con
_stack = 1000
obj
ios: "ios"
kw: "keywords"
str: "stringx"
bt: "bintree"
floatString: "FltStr"
var
byte parastr[64]
pub Main | err, p
ios.start
err := \Try
if err
if err > 0
ios.print( err )
ios.printnl
else
ios.print( string("Error ") )
ios.printdec( err )
ios.printchar( 13 )
ios.printdec( TokLineNumber )
ios.printchar( "," )
ios.printdec( TokColumn + 1 )
ios.printchar( " " )
ios.printchar( "'" )
ios.print( pTokenText )
ios.printchar( "'" )
ios.printchar( 13 )
ios.sdclose
bt.Stop
ios.stop
var
long pTokenText
pri Try
bt.Init( 0, 0 )
ProcessCommandLine
if verbosity => 1
ios.print( string("version 100225", 13) )
Start
pri ProcessCommandLine | nArgs, l
ios.parastart
repeat while ios.paranext(@parastr) 'parameter einlesen
if byte[@parastr][0] == "/" 'option?
case byte[@parastr][1]
"?": ios.print(string("help: lex /i fn.spn /o fn.tok [options]")) '/?
ios.printnl
abort
"i": ifnot ios.paranext(@spinFilename) '/i fn.spn
ios.print(string("error: input-filname"))
ios.printnl
"o": ifnot ios.paranext(@outputFilename) '/o fn.tok
ios.print(string("error: output-filname"))
ios.printnl
"c": compile~~
"l": compile~~
"v": if ios.paranext(@parastr) '/v n
verbosity := str2dec(@parastr)
else
ios.print(string("error: verbosity-level"))
ios.printnl
else
ios.print(string("usage: lex /i fn.spn /o fn.tok [options]"))
pri str2dec(stradr)|buffer,counter
buffer := byte[stradr]
counter := (strsize(stradr) <# 11)
repeat while(counter--)
result *= 10
result += lookdownz(byte[stradr++]: "0".."9")
if(buffer == "-")
-result
con
MAXFILENAMELENGTH = 8 + 1 + 3 ' 8.3
MAXSTRINGBUFFERLENGTH = 32
var
byte spinFilename[MAXFILENAMELENGTH+1] ' input .spi file
byte outputFilename[MAXFILENAMELENGTH+1] ' output .tok file
byte stringBuffer[MAXSTRINGBUFFERLENGTH+1] ' temp string buffer
dat
verbosity byte 0 ' set by /V option
compile byte 0 ' set by /C or /L: if non-zero, run compile.bin automatically.
type long 0
lineNum word 0
column word 0
pri Start | v
kw.Init
pTokenText := TokGetPText
if verbosity => 2
ios.print( string("Reading ") )
ios.print( @spinFilename )
ios.printchar( 13 )
TokOpen( @spinFilename )
if verbosity => 2
ios.print( string("Writing ") )
ios.print( @outputFilename )
ios.printchar( 13 )
if ios.sdnewfile( @outputFilename )
abort string("can't open o-file")
ios.sdopen( "W", @outputFilename )
repeat
type := TokType
lineNum := TokLineNumber
column := Column
ios.sdputblk( 8, @type ) ' long + word + word
if type == kw#kINTLITERAL or type == kw#kFLOATLITERAL
v := TokValue
ios.sdputblk( 4, @v )
else
ios.sdputblk( strsize(pTokenText) + 1, pTokenText )
if TokType == kw#kEOF
quit
TokAdvance
ios.sdclose
dat 'TOKENIZER
pub TokOpen( pFilename )
if ios.sdopen( "R", pFilename ) <> 0
abort string("can't open file")
TokInitReadLine
insideDAT~
TokAdvance ' prime the pump
pub TokClose
ios.sdclose
{
bytes~
InitReadLine
GetNextToken ' prime the pump
t := cnt
repeat
case tokenType
EOL_TOKEN:
term.str( @tokenText )
EOF_TOKEN:
quit
ID_TOKEN:
term.str( @tokenText )
OP_TOKEN:
INT_TOKEN:
term.out( "#" )
term.dec( tokenValue )
FLOAT_TOKEN:
term.out( "F" )
term.str( floatString.FloatToString( tokenValue ) )
term.out( "\" )
GetNextToken
term.out( 13 )
'}
{ repeat while SkipWhitespace
term.dec( lineNo )
term.out( "," )
term.dec( cp+1 )
term.out( ":" )
if cp == lineLength
term.str( string("(eol)"))
else
term.out( lineBuffer[cp++] )
term.out( 13 )
'}
{
repeat
r := sdfat.pread( @buf, BUFFERSIZE )
if r < 0
quit
bytes += r
'}
{
repeat 100
r := sdfat.pgetc
if r < 0
quit
++bytes
term.dec(r)
term.out( "," )
'}
con
MAXTOKENLENGTH = 32
BUFFERSIZE = 200
var
byte tokenText[MAXTOKENLENGTH+1]
long tokenType
word tokenLineNumber
word tokenCol
long tokenValue
byte insideDAT
pub TokGetPText
return @tokenText
pub TokType
return tokenType
pub TokColumn
return tokenCol
pub TokLineNumber
return tokenLineNumber
pub TokValue
return tokenValue
pub TokAdvance | i, radix, fp, x, hack
if inStringLiteral
if comma
comma~
ifnot tokenValue
abort string("Unterminated string")
if lineBuffer[cp] <> $22 ' double-quote
tokenType := kw#kCOMMA
return
++cp
inStringLiteral~
else
comma~~
tokenType := kw#kINTLITERAL
tokenValue := lineBuffer[cp++]
return
if TokSkipWhitespace
if cp == lineLength
tokenType := kw#kEOL
bytemove( @tokenText, string("(EOL)"), 6 )
tokenLineNumber := lineNo
tokenCol := cp
elseif lineBuffer[cp] == $22 ' double-quote
tokenLineNumber := LineNo
tokenCol := cp
++cp
if LineBuffer[cp] == $22
abort string("Empty string")
comma~
inStringLiteral~~
TokAdvance
elseif lineBuffer[cp] == "%" or lineBuffer[cp] == "$"
tokenType := kw#kINTLITERAL
tokenLineNumber := lineNo
tokenCol := cp
if lineBuffer[cp] == "%"
if lineBuffer[cp+1] == "%"
radix := 4
++cp
else
radix := 2
else
radix := 16
++cp
ifnot TokIsDigit( lineBuffer[cp], radix, false )
abort string("Bad character in number")
tokenValue~
repeat while TokIsDigit( lineBuffer[cp], radix, true )
if lineBuffer[cp] <> "_"
tokenValue := tokenValue * radix + TokDigitValue( linebuffer[cp] )
++cp
elseif TokIsDigit( lineBuffer[cp], 10, false )
tokenLineNumber := lineNo
tokenCol := cp
i~
fp~ {0 => integer
1 => have seen .
2 => have seen e or E
3 => have seen + or - }
repeat while TokIsDigit( lineBuffer[cp], 10, true ) {
} or ( fp < 1 and lineBuffer[cp] == "." and lineBuffer[cp+1] <> "." ) {
} or ( fp < 2 and (lineBuffer[cp] == "e" or lineBuffer[cp] == "E") ) {
} or ( (fp == 1 or fp == 2) and (lineBuffer[cp] == "+" or lineBuffer[cp] == "-") )
if lineBuffer[cp] == "."
fp := 1
if lineBuffer[cp] == "e" or lineBuffer[cp] == "E"
fp := 2
if lineBuffer[cp] == "+" or lineBuffer[cp] == "-"
fp := 3
if lineBuffer[cp] <> "_"
if i => MAXTOKENLENGTH
abort string("Token too long")
tokenText[i++] := lineBuffer[cp]
++cp
tokenText[i]~
if fp
tokenType := kw#kFLOATLITERAL
tokenValue := floatString.StringToFloat( @tokenText )
else
tokenType := kw#kINTLITERAL
tokenValue~
i~
repeat while tokenText[i]
tokenValue := tokenValue * 10 + TokDigitValue( tokenText[i++] )
elseif TokIsAlpha( lineBuffer[cp] )
i~
tokenLineNumber := lineNo
tokenCol := cp
repeat while TokIsAlpha( lineBuffer[cp] ) or TokIsDigit( lineBuffer[cp], 10, true )
if i => MAXTOKENLENGTH
abort string("Token too long")
tokenText[i++] := TokToUpper( lineBuffer[cp++] )
tokenText[i]~
x := kw.KeywordLookup( @tokenText )
if x
tokenType := bt.PeekL( x )
if kw#kCON =< tokenType and tokenType =< kw#kVAR and tokenCol == 0
insideDAT := tokenType == kw#kDAT
else
tokenType := kw#kID
else ' non-alphanumeric
tokenLineNumber := lineNo
tokenCol := cp
i~
if lineBuffer[cp] < $20 or lineBuffer[cp] => $80
abort string("Illegal character (UNICODE?)")
if insideDat and lineBuffer[cp] == ":" and TokIsAlpha( lineBuffer[cp+1] )
tokenText[i++] := lineBuffer[cp++]
repeat while TokIsAlpha( lineBuffer[cp] ) or TokIsDigit( lineBuffer[cp], 10, true )
if i => MAXTOKENLENGTH
abort string("Token too long")
tokenText[i++] := TokToUpper( lineBuffer[cp++] )
tokenText[i]~
tokenType := kw#kID
else
repeat
if cp < lineLength
tokenText[i++] := lineBuffer[cp++]
else
tokenText[i++] := " "
++cp
tokenText[i]~
while x := kw.KeywordLookup( @tokenText )
if i > 1
tokenText[--i]~ ' shorten token by 1
--cp
tokenType := bt.PeekL( kw.KeywordLookup( @tokenText ) )
else
tokenType := kw#kUNKNOWN
if TokIsBinary ' This next block is a total hack to see if a binary op
hack := blankLine ' hack is followed by "=" making it an assignment op
TokSkipWhitespace ' It parses "and ==" as "(and=) =" instead of "(and)(==)"
if lineBuffer[cp] == "=" ' PropTool does the latter. So this is wrong, but hopefully
tokenText[i++] := lineBuffer[cp++] ' not *too* wrong.
tokenText[i]~
tokenType |= kw#kASSIGNMENT
else
blankLine := hack ' restore (this hack is necessary to reset the eol condition trigger in SkipWhitespace)
else
tokenType := kw#kEOF
bytemove( @tokenText, string("(EOF)"), 6 )
tokenLineNumber := lineNo
tokenCol := cp
pri TokToUpper( ch )
if "a" =< ch and ch =< "z"
ch += constant( "A" - "a" )
return ch
pri TokIsAlpha( ch )
return "a" =< ch and ch =< "z" or "A" =< ch and ch =< "Z" or ch == "_"
pri TokIsDigit( ch, radix, u ) | upper
{{
Returns non-zero if ch is an acceptable digit given radix (2, 4, 10, or 16), false otherwise.
Pass u = true if the underscore ("_") is an acceptable value for ch.
}}
if ch == "_"
return u
upper := constant("0"-1) + radix
if radix =< 10
return "0" =< ch and ch =< upper
' else radix == 16
return "0" =< ch and ch =< "9" or "a" =< ch and ch =< "f" or "A" =< ch and ch =< "F"
pri TokDigitValue( ch )
if ch =< "9"
return ch - "0"
if ch =< "F"
return ch + constant( 10 - "A" )
if ch =< "f"
return ch + constant( 10 - "a" )
pub TokIsBinary
{{
Returns non-zero (not necessarily -1) if token is a binary operator.
Returns 0 otherwise.
}}
return ( tokenType & constant(kw#kUNARY|kw#kBINARY) ) == kw#kBINARY
var
byte lineBuffer[BUFFERSIZE]
byte lineLength
byte lineRemainder
byte eolLength
word lineNo
byte cp
byte blankLine
byte inStringLiteral ' indicates we are splitting up a string literal
byte comma ' flag for returning commas when splitting up a string literal
pri TokSkipWhitespace
'' Returns true on success, false on failure (eof).
'' lineBuffer[cp] is the next non-whitespace character
'' (comments count as whitespace).
repeat
repeat while cp => lineLength
ifnot blankLine
blankLine~~
return true
ifnot TokReadLine
return false
if lineBuffer[cp] == 9
abort string("Illegal TAB character")
if lineBuffer[cp] == "'" ' quote comment?
cp := lineLength ' skip to end of line
elseif lineBuffer[cp] == "}"
abort string("Unexpected '}'")
elseif lineBuffer[cp] == "{"
TokSkipComment
elseif lineBuffer[cp] == " "
++cp
else ' non-blank character
blankLine~
return true
pri TokSkipComment | depth
if cp+1 < lineLength and lineBuffer[cp+1] == "{"
++cp
repeat
repeat while cp => lineLength
ifnot TokReadLine
abort string("Unterminated comment")
if cp+1 < lineLength and lineBuffer[cp] == "}" and lineBuffer[cp+1] == "}"
cp += 2
return
++cp
else
++cp
depth := 1
repeat
repeat while cp => lineLength
ifnot TokReadLine
abort string("Unterminated comment")
if lineBuffer[cp] == "{"
++cp
++depth
elseif lineBuffer[cp] == "}"
++cp
ifnot --depth
return
else
++cp
pri TokInitReadLine
lineLength~
lineRemainder~
eolLength~
lineNo~
cp~
blankLine~~
inStringLiteral~
{
|<--------------- BUFFERSIZE --------------->|
+--------------------------------------------+
| | | | |
+--------------------------------------------+
|<-lineLength ->| | |
eolLength ->| |<- |
|<- lineRemainder ->|
}
pri TokReadLine | bytes, i
'' Reads a line into lineBuff. Returns true on success, false on failure (eof)
'' The line in lineBuff is terminated with a null byte. Calling programs should
'' not modify any memory in lineBuff after the null (the "remainder" section in
'' the diagram above) because that's the following line(s).
' First, move remainder up to start of buffer
bytemove( @lineBuffer, @lineBuffer[lineLength+eolLength], lineRemainder )
' Fill the rest of the buffer with new data
bytes := ios.sdgetblk( BUFFERSIZE-lineRemainder, @lineBuffer[lineRemainder] )
' pread returns #bytes read, but after eof it returns negative numbers
if bytes > 0
lineRemainder += bytes
ifnot lineRemainder
++lineNo
cp~
return false
repeat i from 0 to (lineRemainder-2) #> 0
if lineBuffer[i] == 13 or lineBuffer[i] == 10
eolLength := 1 ' cr or lf
if lineBuffer[i] == 13 and lineBuffer[i+1] == 10
++eolLength ' cr+lf
lineBuffer[i]~ ' set terminating null
lineLength := i
lineRemainder -= lineLength + eolLength
++lineNo ' first line of file is line 1
cp~
return true
if lineRemainder < BUFFERSIZE
lineLength := lineRemainder~
lineBuffer[lineLength]~
++lineNo
cp~
return true
abort string("Input line too long")
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,43 +0,0 @@
pub Compare( p, q ) | lp, lq, d
{{
Compares two strings. Returns a negative number if first string is "less than" the second,
0 if they're identical, a positive number otherwise.
}}
lp := strsize(p)
lq := strsize(q)
repeat lp <# lq
if (d := byte[p++] - (byte[q++] & $7f))
return ~~d
return lp-lq
pub Copy( p, q )
bytemove( p, q, strsize(q) + 1 )
pub Append( p, q )
Copy( p + strsize(p), q )
pub ToUpper( p )
repeat while byte[p]
if "a" =< byte[p] and byte[p] =< "z"
byte[p] += constant( "A" - "a" )
++p
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,430 +0,0 @@
' 2009-05-02 Modified to detect when inside DAT, handle :<id> specially (for local labels)
con
_clkmode = xtal1 + pll8x
_xinfreq = 10_000_000
_stack = 1000
obj
f: "sxfile"
floatString: "FltStr"
kw: "keywords"
bt: "bintree"
pub Open( pFilename )
if f.Open( pFilename, "R") <> 0
abort string("can't open file")
InitReadLine
insideDAT~
Advance ' prime the pump
pub Close
f.Close
{
bytes~
InitReadLine
GetNextToken ' prime the pump
t := cnt
repeat
case tokenType
EOL_TOKEN:
term.str( @tokenText )
EOF_TOKEN:
quit
ID_TOKEN:
term.str( @tokenText )
OP_TOKEN:
INT_TOKEN:
term.out( "#" )
term.dec( tokenValue )
FLOAT_TOKEN:
term.out( "F" )
term.str( floatString.FloatToString( tokenValue ) )
term.out( "\" )
GetNextToken
term.out( 13 )
'}
{ repeat while SkipWhitespace
term.dec( lineNo )
term.out( "," )
term.dec( cp+1 )
term.out( ":" )
if cp == lineLength
term.str( string("(eol)"))
else
term.out( lineBuffer[cp++] )
term.out( 13 )
'}
{
repeat
r := sdfat.pread( @buf, BUFFERSIZE )
if r < 0
quit
bytes += r
'}
{
repeat 100
r := sdfat.pgetc
if r < 0
quit
++bytes
term.dec(r)
term.out( "," )
'}
con
MAXTOKENLENGTH = 32
BUFFERSIZE = 200
var
byte tokenText[MAXTOKENLENGTH+1]
long tokenType
word tokenLineNumber
word tokenCol
long tokenValue
byte insideDAT
pub GetPText
return @tokenText
pub Type
return tokenType
pub Column
return tokenCol
pub LineNumber
return tokenLineNumber
pub Value
return tokenValue
pub Advance | i, radix, fp, x, hack
if inStringLiteral
if comma
comma~
ifnot tokenValue
abort string("Unterminated string")
if lineBuffer[cp] <> $22 ' double-quote
tokenType := kw#kCOMMA
return
++cp
inStringLiteral~
else
comma~~
tokenType := kw#kINTLITERAL
tokenValue := lineBuffer[cp++]
return
if SkipWhitespace
if cp == lineLength
tokenType := kw#kEOL
bytemove( @tokenText, string("(EOL)"), 6 )
tokenLineNumber := lineNo
tokenCol := cp
elseif lineBuffer[cp] == $22 ' double-quote
tokenLineNumber := LineNo
tokenCol := cp
++cp
if LineBuffer[cp] == $22
abort string("Empty string")
comma~
inStringLiteral~~
Advance
elseif lineBuffer[cp] == "%" or lineBuffer[cp] == "$"
tokenType := kw#kINTLITERAL
tokenLineNumber := lineNo
tokenCol := cp
if lineBuffer[cp] == "%"
if lineBuffer[cp+1] == "%"
radix := 4
++cp
else
radix := 2
else
radix := 16
++cp
ifnot IsDigit( lineBuffer[cp], radix, false )
abort string("Bad character in number")
tokenValue~
repeat while IsDigit( lineBuffer[cp], radix, true )
if lineBuffer[cp] <> "_"
tokenValue := tokenValue * radix + DigitValue( linebuffer[cp] )
++cp
elseif IsDigit( lineBuffer[cp], 10, false )
tokenLineNumber := lineNo
tokenCol := cp
i~
fp~ {0 => integer
1 => have seen .
2 => have seen e or E
3 => have seen + or - }
repeat while IsDigit( lineBuffer[cp], 10, true ) {
} or ( fp < 1 and lineBuffer[cp] == "." and lineBuffer[cp+1] <> "." ) {
} or ( fp < 2 and (lineBuffer[cp] == "e" or lineBuffer[cp] == "E") ) {
} or ( (fp == 1 or fp == 2) and (lineBuffer[cp] == "+" or lineBuffer[cp] == "-") )
if lineBuffer[cp] == "."
fp := 1
if lineBuffer[cp] == "e" or lineBuffer[cp] == "E"
fp := 2
if lineBuffer[cp] == "+" or lineBuffer[cp] == "-"
fp := 3
if lineBuffer[cp] <> "_"
if i => MAXTOKENLENGTH
abort string("Token too long")
tokenText[i++] := lineBuffer[cp]
++cp
tokenText[i]~
if fp
tokenType := kw#kFLOATLITERAL
tokenValue := floatString.StringToFloat( @tokenText )
else
tokenType := kw#kINTLITERAL
tokenValue~
i~
repeat while tokenText[i]
tokenValue := tokenValue * 10 + DigitValue( tokenText[i++] )
elseif IsAlpha( lineBuffer[cp] )
i~
tokenLineNumber := lineNo
tokenCol := cp
repeat while IsAlpha( lineBuffer[cp] ) or IsDigit( lineBuffer[cp], 10, true )
if i => MAXTOKENLENGTH
abort string("Token too long")
tokenText[i++] := ToUpper( lineBuffer[cp++] )
tokenText[i]~
x := kw.KeywordLookup( @tokenText )
if x
tokenType := bt.PeekL( x )
if kw#kCON =< tokenType and tokenType =< kw#kVAR and tokenCol == 0
insideDAT := tokenType == kw#kDAT
else
tokenType := kw#kID
else ' non-alphanumeric
tokenLineNumber := lineNo
tokenCol := cp
i~
if lineBuffer[cp] < $20 or lineBuffer[cp] => $80
abort string("Illegal character (UNICODE?)")
if insideDat and lineBuffer[cp] == ":" and IsAlpha( lineBuffer[cp+1] )
tokenText[i++] := lineBuffer[cp++]
repeat while IsAlpha( lineBuffer[cp] ) or IsDigit( lineBuffer[cp], 10, true )
if i => MAXTOKENLENGTH
abort string("Token too long")
tokenText[i++] := ToUpper( lineBuffer[cp++] )
tokenText[i]~
tokenType := kw#kID
else
repeat
if cp < lineLength
tokenText[i++] := lineBuffer[cp++]
else
tokenText[i++] := " "
++cp
tokenText[i]~
while x := kw.KeywordLookup( @tokenText )
if i > 1
tokenText[--i]~ ' shorten token by 1
--cp
tokenType := bt.PeekL( kw.KeywordLookup( @tokenText ) )
else
tokenType := kw#kUNKNOWN
if IsBinary ' This next block is a total hack to see if a binary op
hack := blankLine ' hack is followed by "=" making it an assignment op
SkipWhitespace ' It parses "and ==" as "(and=) =" instead of "(and)(==)"
if lineBuffer[cp] == "=" ' PropTool does the latter. So this is wrong, but hopefully
tokenText[i++] := lineBuffer[cp++] ' not *too* wrong.
tokenText[i]~
tokenType |= kw#kASSIGNMENT
else
blankLine := hack ' restore (this hack is necessary to reset the eol condition trigger in SkipWhitespace)
else
tokenType := kw#kEOF
bytemove( @tokenText, string("(EOF)"), 6 )
tokenLineNumber := lineNo
tokenCol := cp
pri ToUpper( ch )
if "a" =< ch and ch =< "z"
ch += constant( "A" - "a" )
return ch
pri IsAlpha( ch )
return "a" =< ch and ch =< "z" or "A" =< ch and ch =< "Z" or ch == "_"
pri IsDigit( ch, radix, u ) | upper
{{
Returns non-zero if ch is an acceptable digit given radix (2, 4, 10, or 16), false otherwise.
Pass u = true if the underscore ("_") is an acceptable value for ch.
}}
if ch == "_"
return u
upper := constant("0"-1) + radix
if radix =< 10
return "0" =< ch and ch =< upper
' else radix == 16
return "0" =< ch and ch =< "9" or "a" =< ch and ch =< "f" or "A" =< ch and ch =< "F"
pri DigitValue( ch )
if ch =< "9"
return ch - "0"
if ch =< "F"
return ch + constant( 10 - "A" )
if ch =< "f"
return ch + constant( 10 - "a" )
pub IsBinary
{{
Returns non-zero (not necessarily -1) if token is a binary operator.
Returns 0 otherwise.
}}
return ( tokenType & constant(kw#kUNARY|kw#kBINARY) ) == kw#kBINARY
var
byte lineBuffer[BUFFERSIZE]
byte lineLength
byte lineRemainder
byte eolLength
word lineNo
byte cp
byte blankLine
byte inStringLiteral ' indicates we are splitting up a string literal
byte comma ' flag for returning commas when splitting up a string literal
pri SkipWhitespace
'' Returns true on success, false on failure (eof).
'' lineBuffer[cp] is the next non-whitespace character
'' (comments count as whitespace).
repeat
repeat while cp => lineLength
ifnot blankLine
blankLine~~
return true
ifnot ReadLine
return false
if lineBuffer[cp] == 9
abort string("Illegal TAB character")
if lineBuffer[cp] == "'" ' quote comment?
cp := lineLength ' skip to end of line
elseif lineBuffer[cp] == "}"
abort string("Unexpected '}'")
elseif lineBuffer[cp] == "{"
SkipComment
elseif lineBuffer[cp] == " "
++cp
else ' non-blank character
blankLine~
return true
pri SkipComment | depth
if cp+1 < lineLength and lineBuffer[cp+1] == "{"
++cp
repeat
repeat while cp => lineLength
ifnot ReadLine
abort string("Unterminated comment")
if cp+1 < lineLength and lineBuffer[cp] == "}" and lineBuffer[cp+1] == "}"
cp += 2
return
++cp
else
++cp
depth := 1
repeat
repeat while cp => lineLength
ifnot ReadLine
abort string("Unterminated comment")
if lineBuffer[cp] == "{"
++cp
++depth
elseif lineBuffer[cp] == "}"
++cp
ifnot --depth
return
else
++cp
pri InitReadLine
lineLength~
lineRemainder~
eolLength~
lineNo~
cp~
blankLine~~
inStringLiteral~
{
|<--------------- BUFFERSIZE --------------->|
+--------------------------------------------+
| | | | |
+--------------------------------------------+
|<-lineLength ->| | |
eolLength ->| |<- |
|<- lineRemainder ->|
}
pri ReadLine | bytes, i
'' Reads a line into lineBuff. Returns true on success, false on failure (eof)
'' The line in lineBuff is terminated with a null byte. Calling programs should
'' not modify any memory in lineBuff after the null (the "remainder" section in
'' the diagram above) because that's the following line(s).
' First, move remainder up to start of buffer
bytemove( @lineBuffer, @lineBuffer[lineLength+eolLength], lineRemainder )
' Fill the rest of the buffer with new data
bytes := f.Read( @lineBuffer[lineRemainder], BUFFERSIZE-lineRemainder )
' pread returns #bytes read, but after eof it returns negative numbers
if bytes > 0
lineRemainder += bytes
ifnot lineRemainder
++lineNo
cp~
return false
repeat i from 0 to (lineRemainder-2) #> 0
if lineBuffer[i] == 13 or lineBuffer[i] == 10
eolLength := 1 ' cr or lf
if lineBuffer[i] == 13 and lineBuffer[i+1] == 10
++eolLength ' cr+lf
lineBuffer[i]~ ' set terminating null
lineLength := i
lineRemainder -= lineLength + eolLength
++lineNo ' first line of file is line 1
cp~
return true
if lineRemainder < BUFFERSIZE
lineLength := lineRemainder~
lineBuffer[lineLength]~
++lineNo
cp~
return true
abort string("Input line too long")
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,235 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">/* Copyright 2008 Google. */ (function() { // Input 0
var a=window;
// Input 1
var b="start";function d(f){this.t={};this.tick=function(g,h,c){c=c?c:(new Date).getTime();this.t[g]=[c,h]};this.tick(b,null,f)}var e=new d;a.jstiming={Timer:d,load:e};try{var i=null;if(a.chrome&&a.chrome.csi)i=Math.floor(a.chrome.csi().pageT);if(i==null)if(a.gtbExternal)i=a.gtbExternal.pageT();if(i==null)if(a.external)i=a.external.pageT;if(i)a.jstiming.pt=i}catch(j){};
// Input 2
})()
</script>
<link rel="shortcut icon" type="image/x-icon" href="//www.google.com/images/icons/product/sites-16.ico" />
<link rel="apple-touch-icon" href="http://www.gstatic.com/sites/p/934749/system/app/images/apple-touch-icon.png" type="image/png" />
<script type="text/javascript">/* Copyright 2008 Google. */ (function() { var e=parseInt,h=window,i="length";function j(c){return document.getElementById(c)}h.byId=j;var k="";function l(c){return c.replace(/^\s+|\s+$/g,k)}h.trim=l;
var m="MSIE",n="6.0",o="string",p='id="',q='" ',r='class="',s='title="',t="display:inline-block;",u="left",v="float:left;",w="right",x="float:right;",y="cursor:hand;",z="<span ",A=' style="width:',B="px; height:",C="px;",D=";padding: 0;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='",E="', sizingMethod='scale');\"></span><span style=\"padding: ",F=" ",G=";",H="float:",I='"></span>';
h.ie6ImgFix=function(c){var b=h.navigator?navigator.userAgent:k;if(b.indexOf(m)!=-1&&typeof opera=="undefined"){var d=/MSIE\s+([^\);]+)(\)|;)/;d.test(b);b=RegExp.$1;if(b==n){var a=typeof c==o?j(c):c;c=a.id?p+a.id+q:k;b=a.className?r+a.className+q:k;d=a.title?s+a.title+q:s+a.alt+q;var f=t+a.style.cssText;if(a.align==u)f=v+f;if(a.align==w)f=x+f;if(a.parentElement.href)f=y+f;var g=a.currentStyle,L=a.width-e(g.paddingLeft,10)-e(g.paddingRight,10),M=a.height-e(g.paddingTop,10)-e(g.paddingBottom,10),N=
z+c+b+d+A+L+B+M+C+f+D+a.src+E+g.paddingTop+F+g.paddingRight+F+g.paddingBottom+F+g.paddingLeft+G+(g.styleFloat?H+g.styleFloat+G:k)+I;h.setTimeout(function(){a.outerHTML=N},1)}}};var J=[],K=0;h.JOT_addListener=function(c,b,d){var a=new String(K++);c={eventName:c,handler:b,compId:d,key:a};J.push(c);return a};h.JOT_removeListenerByKey=function(c){for(var b=0;b<J[i];b++)if(J[b].key==c){J.splice(b,1);break}};
h.JOT_removeAllListenersForName=function(c){for(var b=0;b<J[i];b++)J[b].eventName==c&&J.splice(b,1)};var O="function";h.JOT_postEvent=function(c,b,d){var a={eventName:c,eventSrc:b||{},payload:d||{}};if(h.JOT_fullyLoaded){b=J[i];for(d=0;d<b&&d<J[i];d++){var f=J[d];if(f&&f.eventName==c){a.listenerCompId=f.compId||k;(f=typeof f.handler==O?f.handler:h[f.handler])&&f(a)}}}else h.JOT_delayedEvents.push({eventName:c,eventSrc:b,payload:d})};h.JOT_delayedEvents=[];h.JOT_fullyLoaded=false;var P="__duration__";
h.JOT_formatRelativeToNow=function(c,b){var d=((new Date).getTime()-c)/6E4;if(d>=1440||d<0)return null;var a=0;if(d>=60){d/=60;a=2}d>=2&&a++;return b?h.JOT_siteRelTimeStrs[a].replace(P,Math.floor(d)):h.JOT_userRelTimeStrs[a].replace(P,Math.floor(d))}; })()
</script>
<script>
var webspace = {"signInUrl":"https://www.google.com/a/UniversalLogin?continue=http%3A%2F%2Fsites.google.com%2Fsite%2Fsphinxcompiler%2FHome%2Fsphinx-documentation%2Freference%2Fcodegenbin&service=jotspot","isConsumer":true,"termsUrl":"http://www.google.com/sites/help/intl/de/terms.html","enableAnalytics":false,"homePath":"/","sharingId":"jotspot","sharingPolicy":"OPENED","isAdsenseEnabled":true,"analyticsAccountId":"","baseUri":"","name":"sphinxcompiler","features":{"structuredDataGviz":false,"horizontalNavigationDropdownMenus":true,"subpageNav":false,"kixEditorPageType":false,"maestroIntegration":false,"newPageFinder":true,"pdfEmbedSupport":false,"experimental":{"displayEditorLockExceptions":false,"commonSharingExperiment":false},"useStandardEmbedsInSidebar":false,"pageLevelPermissions":false,"navadminperf":true,"adminInfo":false,"lazySiteHierarchy":true,"dragDropHierarchy":true,"headerAlignmentOptions":true,"horizontalNavigationBar":true,"keyboardShortcuts":true,"commonSharing":false,"spreadsheetsEmbedLoadRedirect":false,"structuredDataSchemas":false,"footerCustomOptions":true},"domain":"defaultdomain","adsensePublisherId":"ca-pub-9569899026815114","isStartPageEnabled":false,"domainAnalyticsAccountId":"","siteTitle":"sphinxcompiler"};
webspace.gadgets = {"isGadgetDirectoryEnabled":true,"baseUri":"/system/app/pages/gadgets","isGgsRenderingEnabled":true};
webspace.user = {"uid":"","hasAdminAccess":false,"guest_":true,"keyboardShortcuts":true,"domain":"","hasWriteAccess":false,"userName":"guest","dasherUser":false,"primaryEmail":"guest","sessionIndex":"","namespaceUser":false,"displayNameOrEmail":"guest"};
webspace.page = {"canDeleteWebspace":null,"locale":"de","state":"","wuid":"wuid:gx:339a17752b36feda","timeZone":"Europe/Paris","properties":{},"type":"text","canChangePath":true,"parentWuid":"wuid:gx:1acca89fde6198c7","revision":3,"title":"codegen.bin","isRtlLocale":false,"bidiEnabled":false,"siteLocale":"en","name":"codegenbin","path":"/Home/sphinx-documentation/reference/codegenbin","isSiteRtlLocale":false,"parentPath":"/Home/sphinx-documentation/reference"};
var editorResources = [
'http://www.gstatic.com/sites/p/934749/system/js/trog_edit__de.js',
'http://www.gstatic.com/sites/p/934749/system/app/css/trogedit.css',
'/_/rsrc/1287429563000/system/app/css/editor.css'
];
var JOT_clearDotPath = 'http://www.gstatic.com/sites/p/934749/system/app/images/cleardot.gif';
var JOT_userRelTimeStrs = ["vor einer Minute","vor __duration__ Minuten","vor einer Stunde","vor __duration__ Stunden"];
webspace.page.currentTemplate = {"title":"Webseite","path":"/system/app/pagetemplates/text"};
var JOT_siteRelTimeStrs = ["a minute ago","__duration__ minutes ago","an hour ago","__duration__ hours ago"];
</script>
<script type="text/javascript">
window.jstiming.load.tick('scl');
</script>
<link rel="stylesheet" type="text/css" href="http://www.gstatic.com/sites/p/934749/system/app/themes/simplywhite/standard-css-simplywhite-ltr-ltr.css" />
<link rel="stylesheet" type="text/css" href="/_/rsrc/1287429563000/system/app/css/overlay.css?cb=simplywhite100%250150goog-ws-left" />
<title>codegen.bin - sphinxcompiler</title>
<script type="text/javascript">
window.jstiming.load.tick('cl');
</script>
</head>
<body xmlns="http://www.google.com/ns/jotspot" id="body" class=" en">
<div id="sites-page-toolbar">
<div id="sites-status" class="sites-status" style="display:none;">
<div id="sites-notice" class="sites-notice"> </div>
</div>
</div>
<div id="sites-chrome-everything" style="direction: ltr">
<div id="sites-chrome-page-wrapper">
<div id="sites-chrome-page-wrapper-inside">
<div xmlns="http://www.w3.org/1999/xhtml" id="sites-chrome-header-wrapper">
<table id="sites-chrome-header" class="sites-layout-hbox" cellspacing="0">
<tr class="sites-header-primary-row">
<td id="sites-header-title">
<div class="sites-header-cell-buffer-wrapper">
<h2>
<a href="http://www.sphinxcompiler.com/" dir="ltr">sphinxcompiler</a>
</h2>
</div>
</td>
<td class="sites-layout-searchbox">
<div class="sites-header-cell-buffer-wrapper">
<div>
<form id="sites-searchbox-form" action="/system/app/pages/search">
<input type="text" onpropertychange="JOT_setTextDir(this)" oninput="JOT_setTextDir(this)" dir="" id="jot-ui-searchInput" name="q" size="20" />
<input type="hidden" id="sites-searchbox-scope" name="scope" value="search-site" />
<div class="goog-inline-block goog-button goog-button-base "><div class="goog-inline-block goog-button-base-outer-box TOP"><div class="goog-inline-block goog-button-base-inner-box"><div class="goog-button-base-pos"><div class="goog-button-base-top-shadow"> </div><div id="sites-searchbox-search-button" class="goog-button-base-content " style="" onclick=""><span id="sites-searchbox-search-button-label">Search this site</span></div></div></div></div></div>
</form>
</div>
</div>
</td>
</tr>
<tr class="sites-header-secondary-row">
<td colspan="2">
</td>
</tr>
</table>
</div>
<div id="sites-chrome-main-wrapper">
<div id="sites-chrome-main-wrapper-inside">
<table id="sites-chrome-main" class="sites-layout-hbox" cellspacing="0">
<tr>
<td id="sites-chrome-sidebar-left" class="sites-layout-sidebar-left">
</td>
<td id="sites-canvas-wrapper">
<div id="sites-canvas">
<div id="goog-ws-editor-toolbar-container"> </div>
<div xmlns="http://www.w3.org/1999/xhtml" id="title-crumbs" style="">
<A dir="ltr" href="/Home">Sphinx</A> &gt; <A dir="ltr" href="/Home/sphinx-documentation">Documentation</A> &gt; <A dir="ltr" href="/Home/sphinx-documentation/reference">Reference</A> &gt;
</div>
<h3 xmlns="http://www.w3.org/1999/xhtml" id="sites-page-title-header" style="" align="left">
<span id="sites-page-title" dir="ltr">codegen.bin</span>
</h3>
<div id="sites-canvas-main" class="sites-canvas-main">
<div id="sites-canvas-main-content">
<table xmlns="http://www.w3.org/1999/xhtml" cellspacing="0" class="sites-layout-name-one-column sites-layout-hbox"><tbody><tr><td class="sites-layout-tile sites-tile-name-content-1"><div dir="ltr"><div>Codegen.bin is the second phase of the compiler. It takes a .tok file generated by <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/lexbin">lex.bin</a> and compiles it to a .sob file. On successful completion, codegen.bin can automatically run <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/linkbin">link.bin</a> (of course, linking should only be done on the top object, not child objects, so don't use the /l option too freely).</div><div> </div><div>Typically you will never run codegen.bin directly. Instead you will use the <b>c</b> and <b>cl</b> commands (provided by <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/sphinxbin">sphinx.bin</a>) which run codegen.bin for you.<div><div> <div>Usage:</div><div><blockquote>codegen <i>filename</i> [options]</blockquote><div>Options:<div><ul><li>/l -- run link.bin automatically on successful completion.</li><li>/s <i>n</i> -- set stack size to <i>n</i> bytes (default is 2300). If codegen.bin fails because of stack overflow, run it again with a larger stack. <i>n</i> must be a multiple of 4.</li><li>/t <i>n</i> -- set symbol table size to <i>n</i> bytes (default is 6000). If codegen.bin fails because the symbol table becomes full, run it again with a larger symbol table. <i>n</i> must be a multiple of 4.</li><li>/v <i>n</i> -- set verbosity to 0, 1, 2, or higher (default is 0). The higher the verbosity, the more messages codegen.bin prints as it runs.</li></ul></div><div><div>Example:<div><blockquote>codegen howdy /v 3 /t 7000</blockquote><div>This command compiles howdy.tok and produces howdy.sob. While running, codegen.bin prints many informative(?) messages. The symbol table size is 7,000 bytes.<div>Note that you do not have to add ".tok" to the input filename. Codegen.bin will add it automatically.<div> <div> <div> </div></div></div></div></div></div></div></div></div></div></div></div></div></div></td></tr></tbody></table>
</div>
</div>
<div id="sites-canvas-bottom-panel">
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
<div id="sites-chrome-footer-wrapper">
<div id="sites-chrome-footer-wrapper-inside">
<div id="sites-chrome-footer">
</div>
</div>
</div>
</div>
</div>
<div xmlns="http://www.w3.org/1999/xhtml" class="sites-adminfooter">
<p>
 
<a href="https://www.google.com/a/UniversalLogin?continue=http%3A%2F%2Fsites.google.com%2Fsite%2Fsphinxcompiler%2FHome%2Fsphinx-documentation%2Freference%2Fcodegenbin&amp;service=jotspot" class="sites-system-link">Anmelden</a>
 
<a href="/system/app/pages/recentChanges" rel="nofollow" class="sites-system-link">Site-Aktivität in letzter Zeit</a>
 
<a href="javascript:void(window.open('http://www.google.com/sites/help/intl/de/terms.html'))" class="sites-system-link">Nutzungsbedingungen</a>
 
<a href="/system/app/pages/reportAbuse?src=/Home/sphinx-documentation/reference/codegenbin" rel="nofollow" target="_blank" class="sites-system-link">Missbrauch melden</a>
 
<a href="javascript:;" onclick="window.open(webspace.printUrl)" class="sites-system-link">Seite drucken</a>
 | 
<b class="powered-by">Powered by <a href="http://sites.google.com">Google Sites</a></b>
</p>
</div>
</div>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
window.jstiming.load.tick('sjl');
</script>
<script xmlns="http://www.w3.org/1999/xhtml" src="http://www.gstatic.com/sites/p/934749/system/js/jot_min_view__en.js"></script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
window.jstiming.load.tick('jl');
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
if (editorResources) {
//<![CDATA[
editorResources.unshift('/system/app/css/overlay.css?cb=simplywhite100%250150goog-ws-left');
editorResources.unshift('/_/rsrc/1287429563000/system/app/themes/simplywhite/standard-css-simplywhite-ltr-ltr.css');
//]]>
}
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
var searchBox = new gsites.Searchbox('sites-searchbox-search-button');
searchBox.initListeners();
searchBox.setScopesMenu(webspace.page.isSiteRtlLocale);
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
gsites.HoverPopupMenu.createHoverPopupMenu('sites-header-nav-dropdown');
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
window.onload = function() {
var loadTimer = window.jstiming.load;
loadTimer.tick("ol");
loadTimer["name"] = "load," + webspace.page.type;
window.jstiming.report(loadTimer);
}
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
JOT_insertAnalyticsCode(false);
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
JOT_insertTranslateCode('de', 'en');
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript" defer="true">
//<![CDATA[
// Fires delayed events.
(function() {
JOT_fullyLoaded = true;
var delayedEvents = JOT_delayedEvents;
for (var x = 0; x < delayedEvents.length; x++) {
var event = delayedEvents[x];
JOT_postEvent(event.eventName, event.eventSrc, event.payload);
}
JOT_delayedEvents = null;
JOT_postEvent('pageLoaded');
})();
// Decorate any fastUI buttons on the page with a class of 'goog-button'.
if (webspace.user.hasWriteAccess) {
JOT_decorateButtons();
}
//]]>
</script>
<div id="server-timer-div" style="display:none"> </div>
<script>
window.jstiming.load.tick('render');
</script>
</body>
</html>

View File

@ -1,235 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">/* Copyright 2008 Google. */ (function() { // Input 0
var a=window;
// Input 1
var b="start";function d(f){this.t={};this.tick=function(g,h,c){c=c?c:(new Date).getTime();this.t[g]=[c,h]};this.tick(b,null,f)}var e=new d;a.jstiming={Timer:d,load:e};try{var i=null;if(a.chrome&&a.chrome.csi)i=Math.floor(a.chrome.csi().pageT);if(i==null)if(a.gtbExternal)i=a.gtbExternal.pageT();if(i==null)if(a.external)i=a.external.pageT;if(i)a.jstiming.pt=i}catch(j){};
// Input 2
})()
</script>
<link rel="shortcut icon" type="image/x-icon" href="//www.google.com/images/icons/product/sites-16.ico" />
<link rel="apple-touch-icon" href="http://www.gstatic.com/sites/p/934749/system/app/images/apple-touch-icon.png" type="image/png" />
<script type="text/javascript">/* Copyright 2008 Google. */ (function() { var e=parseInt,h=window,i="length";function j(c){return document.getElementById(c)}h.byId=j;var k="";function l(c){return c.replace(/^\s+|\s+$/g,k)}h.trim=l;
var m="MSIE",n="6.0",o="string",p='id="',q='" ',r='class="',s='title="',t="display:inline-block;",u="left",v="float:left;",w="right",x="float:right;",y="cursor:hand;",z="<span ",A=' style="width:',B="px; height:",C="px;",D=";padding: 0;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='",E="', sizingMethod='scale');\"></span><span style=\"padding: ",F=" ",G=";",H="float:",I='"></span>';
h.ie6ImgFix=function(c){var b=h.navigator?navigator.userAgent:k;if(b.indexOf(m)!=-1&&typeof opera=="undefined"){var d=/MSIE\s+([^\);]+)(\)|;)/;d.test(b);b=RegExp.$1;if(b==n){var a=typeof c==o?j(c):c;c=a.id?p+a.id+q:k;b=a.className?r+a.className+q:k;d=a.title?s+a.title+q:s+a.alt+q;var f=t+a.style.cssText;if(a.align==u)f=v+f;if(a.align==w)f=x+f;if(a.parentElement.href)f=y+f;var g=a.currentStyle,L=a.width-e(g.paddingLeft,10)-e(g.paddingRight,10),M=a.height-e(g.paddingTop,10)-e(g.paddingBottom,10),N=
z+c+b+d+A+L+B+M+C+f+D+a.src+E+g.paddingTop+F+g.paddingRight+F+g.paddingBottom+F+g.paddingLeft+G+(g.styleFloat?H+g.styleFloat+G:k)+I;h.setTimeout(function(){a.outerHTML=N},1)}}};var J=[],K=0;h.JOT_addListener=function(c,b,d){var a=new String(K++);c={eventName:c,handler:b,compId:d,key:a};J.push(c);return a};h.JOT_removeListenerByKey=function(c){for(var b=0;b<J[i];b++)if(J[b].key==c){J.splice(b,1);break}};
h.JOT_removeAllListenersForName=function(c){for(var b=0;b<J[i];b++)J[b].eventName==c&&J.splice(b,1)};var O="function";h.JOT_postEvent=function(c,b,d){var a={eventName:c,eventSrc:b||{},payload:d||{}};if(h.JOT_fullyLoaded){b=J[i];for(d=0;d<b&&d<J[i];d++){var f=J[d];if(f&&f.eventName==c){a.listenerCompId=f.compId||k;(f=typeof f.handler==O?f.handler:h[f.handler])&&f(a)}}}else h.JOT_delayedEvents.push({eventName:c,eventSrc:b,payload:d})};h.JOT_delayedEvents=[];h.JOT_fullyLoaded=false;var P="__duration__";
h.JOT_formatRelativeToNow=function(c,b){var d=((new Date).getTime()-c)/6E4;if(d>=1440||d<0)return null;var a=0;if(d>=60){d/=60;a=2}d>=2&&a++;return b?h.JOT_siteRelTimeStrs[a].replace(P,Math.floor(d)):h.JOT_userRelTimeStrs[a].replace(P,Math.floor(d))}; })()
</script>
<script>
var webspace = {"signInUrl":"https://www.google.com/a/UniversalLogin?continue=http%3A%2F%2Fsites.google.com%2Fsite%2Fsphinxcompiler%2FHome%2Fsphinx-documentation%2Freference%2Flexbin&service=jotspot","isConsumer":true,"termsUrl":"http://www.google.com/sites/help/intl/de/terms.html","enableAnalytics":false,"homePath":"/","sharingId":"jotspot","sharingPolicy":"OPENED","isAdsenseEnabled":true,"analyticsAccountId":"","baseUri":"","name":"sphinxcompiler","features":{"structuredDataGviz":false,"horizontalNavigationDropdownMenus":true,"subpageNav":false,"kixEditorPageType":false,"maestroIntegration":false,"newPageFinder":true,"pdfEmbedSupport":false,"experimental":{"displayEditorLockExceptions":false,"commonSharingExperiment":false},"useStandardEmbedsInSidebar":false,"pageLevelPermissions":false,"navadminperf":true,"adminInfo":false,"lazySiteHierarchy":true,"dragDropHierarchy":true,"headerAlignmentOptions":true,"horizontalNavigationBar":true,"keyboardShortcuts":true,"commonSharing":false,"spreadsheetsEmbedLoadRedirect":false,"structuredDataSchemas":false,"footerCustomOptions":true},"domain":"defaultdomain","adsensePublisherId":"ca-pub-9569899026815114","isStartPageEnabled":false,"domainAnalyticsAccountId":"","siteTitle":"sphinxcompiler"};
webspace.gadgets = {"isGadgetDirectoryEnabled":true,"baseUri":"/system/app/pages/gadgets","isGgsRenderingEnabled":true};
webspace.user = {"uid":"","hasAdminAccess":false,"guest_":true,"keyboardShortcuts":true,"domain":"","hasWriteAccess":false,"userName":"guest","dasherUser":false,"primaryEmail":"guest","sessionIndex":"","namespaceUser":false,"displayNameOrEmail":"guest"};
webspace.page = {"canDeleteWebspace":null,"locale":"de","state":"","wuid":"wuid:gx:638d5971150d3922","timeZone":"Europe/Paris","properties":{},"type":"text","canChangePath":true,"parentWuid":"wuid:gx:1acca89fde6198c7","revision":4,"title":"lex.bin","isRtlLocale":false,"bidiEnabled":false,"siteLocale":"en","name":"lexbin","path":"/Home/sphinx-documentation/reference/lexbin","isSiteRtlLocale":false,"parentPath":"/Home/sphinx-documentation/reference"};
var editorResources = [
'http://www.gstatic.com/sites/p/934749/system/js/trog_edit__de.js',
'http://www.gstatic.com/sites/p/934749/system/app/css/trogedit.css',
'/_/rsrc/1287429563000/system/app/css/editor.css'
];
var JOT_clearDotPath = 'http://www.gstatic.com/sites/p/934749/system/app/images/cleardot.gif';
var JOT_userRelTimeStrs = ["vor einer Minute","vor __duration__ Minuten","vor einer Stunde","vor __duration__ Stunden"];
webspace.page.currentTemplate = {"title":"Webseite","path":"/system/app/pagetemplates/text"};
var JOT_siteRelTimeStrs = ["a minute ago","__duration__ minutes ago","an hour ago","__duration__ hours ago"];
</script>
<script type="text/javascript">
window.jstiming.load.tick('scl');
</script>
<link rel="stylesheet" type="text/css" href="http://www.gstatic.com/sites/p/934749/system/app/themes/simplywhite/standard-css-simplywhite-ltr-ltr.css" />
<link rel="stylesheet" type="text/css" href="/_/rsrc/1287429563000/system/app/css/overlay.css?cb=simplywhite100%250150goog-ws-left" />
<title>lex.bin - sphinxcompiler</title>
<script type="text/javascript">
window.jstiming.load.tick('cl');
</script>
</head>
<body xmlns="http://www.google.com/ns/jotspot" id="body" class=" en">
<div id="sites-page-toolbar">
<div id="sites-status" class="sites-status" style="display:none;">
<div id="sites-notice" class="sites-notice"> </div>
</div>
</div>
<div id="sites-chrome-everything" style="direction: ltr">
<div id="sites-chrome-page-wrapper">
<div id="sites-chrome-page-wrapper-inside">
<div xmlns="http://www.w3.org/1999/xhtml" id="sites-chrome-header-wrapper">
<table id="sites-chrome-header" class="sites-layout-hbox" cellspacing="0">
<tr class="sites-header-primary-row">
<td id="sites-header-title">
<div class="sites-header-cell-buffer-wrapper">
<h2>
<a href="http://www.sphinxcompiler.com/" dir="ltr">sphinxcompiler</a>
</h2>
</div>
</td>
<td class="sites-layout-searchbox">
<div class="sites-header-cell-buffer-wrapper">
<div>
<form id="sites-searchbox-form" action="/system/app/pages/search">
<input type="text" onpropertychange="JOT_setTextDir(this)" oninput="JOT_setTextDir(this)" dir="" id="jot-ui-searchInput" name="q" size="20" />
<input type="hidden" id="sites-searchbox-scope" name="scope" value="search-site" />
<div class="goog-inline-block goog-button goog-button-base "><div class="goog-inline-block goog-button-base-outer-box TOP"><div class="goog-inline-block goog-button-base-inner-box"><div class="goog-button-base-pos"><div class="goog-button-base-top-shadow"> </div><div id="sites-searchbox-search-button" class="goog-button-base-content " style="" onclick=""><span id="sites-searchbox-search-button-label">Search this site</span></div></div></div></div></div>
</form>
</div>
</div>
</td>
</tr>
<tr class="sites-header-secondary-row">
<td colspan="2">
</td>
</tr>
</table>
</div>
<div id="sites-chrome-main-wrapper">
<div id="sites-chrome-main-wrapper-inside">
<table id="sites-chrome-main" class="sites-layout-hbox" cellspacing="0">
<tr>
<td id="sites-chrome-sidebar-left" class="sites-layout-sidebar-left">
</td>
<td id="sites-canvas-wrapper">
<div id="sites-canvas">
<div id="goog-ws-editor-toolbar-container"> </div>
<div xmlns="http://www.w3.org/1999/xhtml" id="title-crumbs" style="">
<A dir="ltr" href="/Home">Sphinx</A> &gt; <A dir="ltr" href="/Home/sphinx-documentation">Documentation</A> &gt; <A dir="ltr" href="/Home/sphinx-documentation/reference">Reference</A> &gt;
</div>
<h3 xmlns="http://www.w3.org/1999/xhtml" id="sites-page-title-header" style="" align="left">
<span id="sites-page-title" dir="ltr">lex.bin</span>
</h3>
<div id="sites-canvas-main" class="sites-canvas-main">
<div id="sites-canvas-main-content">
<table xmlns="http://www.w3.org/1999/xhtml" cellspacing="0" class="sites-layout-name-one-column sites-layout-hbox"><tbody><tr><td class="sites-layout-tile sites-tile-name-content-1"><div dir="ltr">Lex.bin is the first phase of the compiler. It takes a .spn file as input, tokenizes it, and writes the result to a .tok file. On successful completion, lex.bin can automatically run <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/codegenbin">codegen.bin</a>, the next compiler phase.<div> <div>Usage:</div><div><blockquote>lex <em>filename</em> [options]</blockquote><div>Options:<div><ul><li>/c -- run codegen.bin automatically on successful completion.</li><li>/l -- run codegen.bin automatically on successful completion and tell it to run <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/linkbin">link.bin</a>.</li><li>/v <i>n</i> -- set verbosity to 0, 1, 2, or higher (default is 0). The higher the verbosity, the more messages lex.bin prints as it runs.</li></ul><div>Example:<div><blockquote>lex tv_text /c</blockquote><div>This command tokenizes tv_text.spn, producing tv_text.tok, and then runs codegen.bin. Note that you don't have to add ".spn" to the input filename. Lex.bin will add it automatically.<div> <div>You should never have to run lex.bin directly; instead, use the convenient  <b>c</b> command (provided by <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/sphinxbin">sphinx.bin</a>) which is equivalent to running lex with the /c option. <div> </div></div></div></div></div></div></div></div></div></div></div></td></tr></tbody></table>
</div>
</div>
<div id="sites-canvas-bottom-panel">
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
<div id="sites-chrome-footer-wrapper">
<div id="sites-chrome-footer-wrapper-inside">
<div id="sites-chrome-footer">
</div>
</div>
</div>
</div>
</div>
<div xmlns="http://www.w3.org/1999/xhtml" class="sites-adminfooter">
<p>
 
<a href="https://www.google.com/a/UniversalLogin?continue=http%3A%2F%2Fsites.google.com%2Fsite%2Fsphinxcompiler%2FHome%2Fsphinx-documentation%2Freference%2Flexbin&amp;service=jotspot" class="sites-system-link">Anmelden</a>
 
<a href="/system/app/pages/recentChanges" rel="nofollow" class="sites-system-link">Site-Aktivität in letzter Zeit</a>
 
<a href="javascript:void(window.open('http://www.google.com/sites/help/intl/de/terms.html'))" class="sites-system-link">Nutzungsbedingungen</a>
 
<a href="/system/app/pages/reportAbuse?src=/Home/sphinx-documentation/reference/lexbin" rel="nofollow" target="_blank" class="sites-system-link">Missbrauch melden</a>
 
<a href="javascript:;" onclick="window.open(webspace.printUrl)" class="sites-system-link">Seite drucken</a>
 | 
<b class="powered-by">Powered by <a href="http://sites.google.com">Google Sites</a></b>
</p>
</div>
</div>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
window.jstiming.load.tick('sjl');
</script>
<script xmlns="http://www.w3.org/1999/xhtml" src="http://www.gstatic.com/sites/p/934749/system/js/jot_min_view__en.js"></script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
window.jstiming.load.tick('jl');
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
if (editorResources) {
//<![CDATA[
editorResources.unshift('/system/app/css/overlay.css?cb=simplywhite100%250150goog-ws-left');
editorResources.unshift('/_/rsrc/1287429563000/system/app/themes/simplywhite/standard-css-simplywhite-ltr-ltr.css');
//]]>
}
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
var searchBox = new gsites.Searchbox('sites-searchbox-search-button');
searchBox.initListeners();
searchBox.setScopesMenu(webspace.page.isSiteRtlLocale);
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
gsites.HoverPopupMenu.createHoverPopupMenu('sites-header-nav-dropdown');
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
window.onload = function() {
var loadTimer = window.jstiming.load;
loadTimer.tick("ol");
loadTimer["name"] = "load," + webspace.page.type;
window.jstiming.report(loadTimer);
}
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
JOT_insertAnalyticsCode(false);
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
JOT_insertTranslateCode('de', 'en');
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript" defer="true">
//<![CDATA[
// Fires delayed events.
(function() {
JOT_fullyLoaded = true;
var delayedEvents = JOT_delayedEvents;
for (var x = 0; x < delayedEvents.length; x++) {
var event = delayedEvents[x];
JOT_postEvent(event.eventName, event.eventSrc, event.payload);
}
JOT_delayedEvents = null;
JOT_postEvent('pageLoaded');
})();
// Decorate any fastUI buttons on the page with a class of 'goog-button'.
if (webspace.user.hasWriteAccess) {
JOT_decorateButtons();
}
//]]>
</script>
<div id="server-timer-div" style="display:none"> </div>
<script>
window.jstiming.load.tick('render');
</script>
</body>
</html>

View File

@ -1,235 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">/* Copyright 2008 Google. */ (function() { // Input 0
var a=window;
// Input 1
var b="start";function d(f){this.t={};this.tick=function(g,h,c){c=c?c:(new Date).getTime();this.t[g]=[c,h]};this.tick(b,null,f)}var e=new d;a.jstiming={Timer:d,load:e};try{var i=null;if(a.chrome&&a.chrome.csi)i=Math.floor(a.chrome.csi().pageT);if(i==null)if(a.gtbExternal)i=a.gtbExternal.pageT();if(i==null)if(a.external)i=a.external.pageT;if(i)a.jstiming.pt=i}catch(j){};
// Input 2
})()
</script>
<link rel="shortcut icon" type="image/x-icon" href="//www.google.com/images/icons/product/sites-16.ico" />
<link rel="apple-touch-icon" href="http://www.gstatic.com/sites/p/934749/system/app/images/apple-touch-icon.png" type="image/png" />
<script type="text/javascript">/* Copyright 2008 Google. */ (function() { var e=parseInt,h=window,i="length";function j(c){return document.getElementById(c)}h.byId=j;var k="";function l(c){return c.replace(/^\s+|\s+$/g,k)}h.trim=l;
var m="MSIE",n="6.0",o="string",p='id="',q='" ',r='class="',s='title="',t="display:inline-block;",u="left",v="float:left;",w="right",x="float:right;",y="cursor:hand;",z="<span ",A=' style="width:',B="px; height:",C="px;",D=";padding: 0;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='",E="', sizingMethod='scale');\"></span><span style=\"padding: ",F=" ",G=";",H="float:",I='"></span>';
h.ie6ImgFix=function(c){var b=h.navigator?navigator.userAgent:k;if(b.indexOf(m)!=-1&&typeof opera=="undefined"){var d=/MSIE\s+([^\);]+)(\)|;)/;d.test(b);b=RegExp.$1;if(b==n){var a=typeof c==o?j(c):c;c=a.id?p+a.id+q:k;b=a.className?r+a.className+q:k;d=a.title?s+a.title+q:s+a.alt+q;var f=t+a.style.cssText;if(a.align==u)f=v+f;if(a.align==w)f=x+f;if(a.parentElement.href)f=y+f;var g=a.currentStyle,L=a.width-e(g.paddingLeft,10)-e(g.paddingRight,10),M=a.height-e(g.paddingTop,10)-e(g.paddingBottom,10),N=
z+c+b+d+A+L+B+M+C+f+D+a.src+E+g.paddingTop+F+g.paddingRight+F+g.paddingBottom+F+g.paddingLeft+G+(g.styleFloat?H+g.styleFloat+G:k)+I;h.setTimeout(function(){a.outerHTML=N},1)}}};var J=[],K=0;h.JOT_addListener=function(c,b,d){var a=new String(K++);c={eventName:c,handler:b,compId:d,key:a};J.push(c);return a};h.JOT_removeListenerByKey=function(c){for(var b=0;b<J[i];b++)if(J[b].key==c){J.splice(b,1);break}};
h.JOT_removeAllListenersForName=function(c){for(var b=0;b<J[i];b++)J[b].eventName==c&&J.splice(b,1)};var O="function";h.JOT_postEvent=function(c,b,d){var a={eventName:c,eventSrc:b||{},payload:d||{}};if(h.JOT_fullyLoaded){b=J[i];for(d=0;d<b&&d<J[i];d++){var f=J[d];if(f&&f.eventName==c){a.listenerCompId=f.compId||k;(f=typeof f.handler==O?f.handler:h[f.handler])&&f(a)}}}else h.JOT_delayedEvents.push({eventName:c,eventSrc:b,payload:d})};h.JOT_delayedEvents=[];h.JOT_fullyLoaded=false;var P="__duration__";
h.JOT_formatRelativeToNow=function(c,b){var d=((new Date).getTime()-c)/6E4;if(d>=1440||d<0)return null;var a=0;if(d>=60){d/=60;a=2}d>=2&&a++;return b?h.JOT_siteRelTimeStrs[a].replace(P,Math.floor(d)):h.JOT_userRelTimeStrs[a].replace(P,Math.floor(d))}; })()
</script>
<script>
var webspace = {"signInUrl":"https://www.google.com/a/UniversalLogin?continue=http%3A%2F%2Fsites.google.com%2Fsite%2Fsphinxcompiler%2FHome%2Fsphinx-documentation%2Freference%2Flinkbin&service=jotspot","isConsumer":true,"termsUrl":"http://www.google.com/sites/help/intl/de/terms.html","enableAnalytics":false,"homePath":"/","sharingId":"jotspot","sharingPolicy":"OPENED","isAdsenseEnabled":true,"analyticsAccountId":"","baseUri":"","name":"sphinxcompiler","features":{"structuredDataGviz":false,"horizontalNavigationDropdownMenus":true,"subpageNav":false,"kixEditorPageType":false,"maestroIntegration":false,"newPageFinder":true,"pdfEmbedSupport":false,"experimental":{"displayEditorLockExceptions":false,"commonSharingExperiment":false},"useStandardEmbedsInSidebar":false,"pageLevelPermissions":false,"navadminperf":true,"adminInfo":false,"lazySiteHierarchy":true,"dragDropHierarchy":true,"headerAlignmentOptions":true,"horizontalNavigationBar":true,"keyboardShortcuts":true,"commonSharing":false,"spreadsheetsEmbedLoadRedirect":false,"structuredDataSchemas":false,"footerCustomOptions":true},"domain":"defaultdomain","adsensePublisherId":"ca-pub-9569899026815114","isStartPageEnabled":false,"domainAnalyticsAccountId":"","siteTitle":"sphinxcompiler"};
webspace.gadgets = {"isGadgetDirectoryEnabled":true,"baseUri":"/system/app/pages/gadgets","isGgsRenderingEnabled":true};
webspace.user = {"uid":"","hasAdminAccess":false,"guest_":true,"keyboardShortcuts":true,"domain":"","hasWriteAccess":false,"userName":"guest","dasherUser":false,"primaryEmail":"guest","sessionIndex":"","namespaceUser":false,"displayNameOrEmail":"guest"};
webspace.page = {"canDeleteWebspace":null,"locale":"de","state":"","wuid":"wuid:gx:7897d1d4a3c749e6","timeZone":"Europe/Paris","properties":{},"type":"text","canChangePath":true,"parentWuid":"wuid:gx:1acca89fde6198c7","revision":4,"title":"link.bin","isRtlLocale":false,"bidiEnabled":false,"siteLocale":"en","name":"linkbin","path":"/Home/sphinx-documentation/reference/linkbin","isSiteRtlLocale":false,"parentPath":"/Home/sphinx-documentation/reference"};
var editorResources = [
'http://www.gstatic.com/sites/p/934749/system/js/trog_edit__de.js',
'http://www.gstatic.com/sites/p/934749/system/app/css/trogedit.css',
'/_/rsrc/1287429563000/system/app/css/editor.css'
];
var JOT_clearDotPath = 'http://www.gstatic.com/sites/p/934749/system/app/images/cleardot.gif';
var JOT_userRelTimeStrs = ["vor einer Minute","vor __duration__ Minuten","vor einer Stunde","vor __duration__ Stunden"];
webspace.page.currentTemplate = {"title":"Webseite","path":"/system/app/pagetemplates/text"};
var JOT_siteRelTimeStrs = ["a minute ago","__duration__ minutes ago","an hour ago","__duration__ hours ago"];
</script>
<script type="text/javascript">
window.jstiming.load.tick('scl');
</script>
<link rel="stylesheet" type="text/css" href="http://www.gstatic.com/sites/p/934749/system/app/themes/simplywhite/standard-css-simplywhite-ltr-ltr.css" />
<link rel="stylesheet" type="text/css" href="/_/rsrc/1287429563000/system/app/css/overlay.css?cb=simplywhite100%250150goog-ws-left" />
<title>link.bin - sphinxcompiler</title>
<script type="text/javascript">
window.jstiming.load.tick('cl');
</script>
</head>
<body xmlns="http://www.google.com/ns/jotspot" id="body" class=" en">
<div id="sites-page-toolbar">
<div id="sites-status" class="sites-status" style="display:none;">
<div id="sites-notice" class="sites-notice"> </div>
</div>
</div>
<div id="sites-chrome-everything" style="direction: ltr">
<div id="sites-chrome-page-wrapper">
<div id="sites-chrome-page-wrapper-inside">
<div xmlns="http://www.w3.org/1999/xhtml" id="sites-chrome-header-wrapper">
<table id="sites-chrome-header" class="sites-layout-hbox" cellspacing="0">
<tr class="sites-header-primary-row">
<td id="sites-header-title">
<div class="sites-header-cell-buffer-wrapper">
<h2>
<a href="http://www.sphinxcompiler.com/" dir="ltr">sphinxcompiler</a>
</h2>
</div>
</td>
<td class="sites-layout-searchbox">
<div class="sites-header-cell-buffer-wrapper">
<div>
<form id="sites-searchbox-form" action="/system/app/pages/search">
<input type="text" onpropertychange="JOT_setTextDir(this)" oninput="JOT_setTextDir(this)" dir="" id="jot-ui-searchInput" name="q" size="20" />
<input type="hidden" id="sites-searchbox-scope" name="scope" value="search-site" />
<div class="goog-inline-block goog-button goog-button-base "><div class="goog-inline-block goog-button-base-outer-box TOP"><div class="goog-inline-block goog-button-base-inner-box"><div class="goog-button-base-pos"><div class="goog-button-base-top-shadow"> </div><div id="sites-searchbox-search-button" class="goog-button-base-content " style="" onclick=""><span id="sites-searchbox-search-button-label">Search this site</span></div></div></div></div></div>
</form>
</div>
</div>
</td>
</tr>
<tr class="sites-header-secondary-row">
<td colspan="2">
</td>
</tr>
</table>
</div>
<div id="sites-chrome-main-wrapper">
<div id="sites-chrome-main-wrapper-inside">
<table id="sites-chrome-main" class="sites-layout-hbox" cellspacing="0">
<tr>
<td id="sites-chrome-sidebar-left" class="sites-layout-sidebar-left">
</td>
<td id="sites-canvas-wrapper">
<div id="sites-canvas">
<div id="goog-ws-editor-toolbar-container"> </div>
<div xmlns="http://www.w3.org/1999/xhtml" id="title-crumbs" style="">
<A dir="ltr" href="/Home">Sphinx</A> &gt; <A dir="ltr" href="/Home/sphinx-documentation">Documentation</A> &gt; <A dir="ltr" href="/Home/sphinx-documentation/reference">Reference</A> &gt;
</div>
<h3 xmlns="http://www.w3.org/1999/xhtml" id="sites-page-title-header" style="" align="left">
<span id="sites-page-title" dir="ltr">link.bin</span>
</h3>
<div id="sites-canvas-main" class="sites-canvas-main">
<div id="sites-canvas-main-content">
<table xmlns="http://www.w3.org/1999/xhtml" cellspacing="0" class="sites-layout-name-one-column sites-layout-hbox"><tbody><tr><td class="sites-layout-tile sites-tile-name-content-1"><div dir="ltr">Link.bin is the linker. It takes a top object .sob file and links it together with any child .sob files it requires, producing a .bin file.<div> <p>Usage:</p><div><blockquote>link <i>filename</i> [options]</blockquote><div>Options:<div><ul><li>/i -- ignore out-of-date errors.</li><li>/v <em>n</em> -- set verbosity to 0, 1, 2, or higher (default is 0). The higher the verbosity, the more messages link.bin prints as it runs.</li></ul></div><div> <div> <div> </div></div></div></div></div></div></div></td></tr></tbody></table>
</div>
</div>
<div id="sites-canvas-bottom-panel">
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
<div id="sites-chrome-footer-wrapper">
<div id="sites-chrome-footer-wrapper-inside">
<div id="sites-chrome-footer">
</div>
</div>
</div>
</div>
</div>
<div xmlns="http://www.w3.org/1999/xhtml" class="sites-adminfooter">
<p>
 
<a href="https://www.google.com/a/UniversalLogin?continue=http%3A%2F%2Fsites.google.com%2Fsite%2Fsphinxcompiler%2FHome%2Fsphinx-documentation%2Freference%2Flinkbin&amp;service=jotspot" class="sites-system-link">Anmelden</a>
 
<a href="/system/app/pages/recentChanges" rel="nofollow" class="sites-system-link">Site-Aktivität in letzter Zeit</a>
 
<a href="javascript:void(window.open('http://www.google.com/sites/help/intl/de/terms.html'))" class="sites-system-link">Nutzungsbedingungen</a>
 
<a href="/system/app/pages/reportAbuse?src=/Home/sphinx-documentation/reference/linkbin" rel="nofollow" target="_blank" class="sites-system-link">Missbrauch melden</a>
 
<a href="javascript:;" onclick="window.open(webspace.printUrl)" class="sites-system-link">Seite drucken</a>
 | 
<b class="powered-by">Powered by <a href="http://sites.google.com">Google Sites</a></b>
</p>
</div>
</div>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
window.jstiming.load.tick('sjl');
</script>
<script xmlns="http://www.w3.org/1999/xhtml" src="http://www.gstatic.com/sites/p/934749/system/js/jot_min_view__en.js"></script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
window.jstiming.load.tick('jl');
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
if (editorResources) {
//<![CDATA[
editorResources.unshift('/system/app/css/overlay.css?cb=simplywhite100%250150goog-ws-left');
editorResources.unshift('/_/rsrc/1287429563000/system/app/themes/simplywhite/standard-css-simplywhite-ltr-ltr.css');
//]]>
}
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
var searchBox = new gsites.Searchbox('sites-searchbox-search-button');
searchBox.initListeners();
searchBox.setScopesMenu(webspace.page.isSiteRtlLocale);
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
gsites.HoverPopupMenu.createHoverPopupMenu('sites-header-nav-dropdown');
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
window.onload = function() {
var loadTimer = window.jstiming.load;
loadTimer.tick("ol");
loadTimer["name"] = "load," + webspace.page.type;
window.jstiming.report(loadTimer);
}
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
JOT_insertAnalyticsCode(false);
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
JOT_insertTranslateCode('de', 'en');
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript" defer="true">
//<![CDATA[
// Fires delayed events.
(function() {
JOT_fullyLoaded = true;
var delayedEvents = JOT_delayedEvents;
for (var x = 0; x < delayedEvents.length; x++) {
var event = delayedEvents[x];
JOT_postEvent(event.eventName, event.eventSrc, event.payload);
}
JOT_delayedEvents = null;
JOT_postEvent('pageLoaded');
})();
// Decorate any fastUI buttons on the page with a class of 'goog-button'.
if (webspace.user.hasWriteAccess) {
JOT_decorateButtons();
}
//]]>
</script>
<div id="server-timer-div" style="display:none"> </div>
<script>
window.jstiming.load.tick('render');
</script>
</body>
</html>

View File

@ -1,271 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">/* Copyright 2008 Google. */ (function() { // Input 0
var a=window;
// Input 1
var b="start";function d(f){this.t={};this.tick=function(g,h,c){c=c?c:(new Date).getTime();this.t[g]=[c,h]};this.tick(b,null,f)}var e=new d;a.jstiming={Timer:d,load:e};try{var i=null;if(a.chrome&&a.chrome.csi)i=Math.floor(a.chrome.csi().pageT);if(i==null)if(a.gtbExternal)i=a.gtbExternal.pageT();if(i==null)if(a.external)i=a.external.pageT;if(i)a.jstiming.pt=i}catch(j){};
// Input 2
})()
</script>
<link rel="shortcut icon" type="image/x-icon" href="//www.google.com/images/icons/product/sites-16.ico" />
<link rel="apple-touch-icon" href="http://www.gstatic.com/sites/p/934749/system/app/images/apple-touch-icon.png" type="image/png" />
<script type="text/javascript">/* Copyright 2008 Google. */ (function() { var e=parseInt,h=window,i="length";function j(c){return document.getElementById(c)}h.byId=j;var k="";function l(c){return c.replace(/^\s+|\s+$/g,k)}h.trim=l;
var m="MSIE",n="6.0",o="string",p='id="',q='" ',r='class="',s='title="',t="display:inline-block;",u="left",v="float:left;",w="right",x="float:right;",y="cursor:hand;",z="<span ",A=' style="width:',B="px; height:",C="px;",D=";padding: 0;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='",E="', sizingMethod='scale');\"></span><span style=\"padding: ",F=" ",G=";",H="float:",I='"></span>';
h.ie6ImgFix=function(c){var b=h.navigator?navigator.userAgent:k;if(b.indexOf(m)!=-1&&typeof opera=="undefined"){var d=/MSIE\s+([^\);]+)(\)|;)/;d.test(b);b=RegExp.$1;if(b==n){var a=typeof c==o?j(c):c;c=a.id?p+a.id+q:k;b=a.className?r+a.className+q:k;d=a.title?s+a.title+q:s+a.alt+q;var f=t+a.style.cssText;if(a.align==u)f=v+f;if(a.align==w)f=x+f;if(a.parentElement.href)f=y+f;var g=a.currentStyle,L=a.width-e(g.paddingLeft,10)-e(g.paddingRight,10),M=a.height-e(g.paddingTop,10)-e(g.paddingBottom,10),N=
z+c+b+d+A+L+B+M+C+f+D+a.src+E+g.paddingTop+F+g.paddingRight+F+g.paddingBottom+F+g.paddingLeft+G+(g.styleFloat?H+g.styleFloat+G:k)+I;h.setTimeout(function(){a.outerHTML=N},1)}}};var J=[],K=0;h.JOT_addListener=function(c,b,d){var a=new String(K++);c={eventName:c,handler:b,compId:d,key:a};J.push(c);return a};h.JOT_removeListenerByKey=function(c){for(var b=0;b<J[i];b++)if(J[b].key==c){J.splice(b,1);break}};
h.JOT_removeAllListenersForName=function(c){for(var b=0;b<J[i];b++)J[b].eventName==c&&J.splice(b,1)};var O="function";h.JOT_postEvent=function(c,b,d){var a={eventName:c,eventSrc:b||{},payload:d||{}};if(h.JOT_fullyLoaded){b=J[i];for(d=0;d<b&&d<J[i];d++){var f=J[d];if(f&&f.eventName==c){a.listenerCompId=f.compId||k;(f=typeof f.handler==O?f.handler:h[f.handler])&&f(a)}}}else h.JOT_delayedEvents.push({eventName:c,eventSrc:b,payload:d})};h.JOT_delayedEvents=[];h.JOT_fullyLoaded=false;var P="__duration__";
h.JOT_formatRelativeToNow=function(c,b){var d=((new Date).getTime()-c)/6E4;if(d>=1440||d<0)return null;var a=0;if(d>=60){d/=60;a=2}d>=2&&a++;return b?h.JOT_siteRelTimeStrs[a].replace(P,Math.floor(d)):h.JOT_userRelTimeStrs[a].replace(P,Math.floor(d))}; })()
</script>
<script>
var webspace = {"signInUrl":"https://www.google.com/a/UniversalLogin?continue=http%3A%2F%2Fsites.google.com%2Fsite%2Fsphinxcompiler%2FHome%2Fsphinx-documentation%2Fsobstory&service=jotspot","isConsumer":true,"termsUrl":"http://www.google.com/sites/help/intl/de/terms.html","enableAnalytics":false,"homePath":"/","sharingId":"jotspot","sharingPolicy":"OPENED","isAdsenseEnabled":true,"analyticsAccountId":"","baseUri":"","name":"sphinxcompiler","features":{"structuredDataGviz":false,"horizontalNavigationDropdownMenus":true,"subpageNav":false,"kixEditorPageType":false,"maestroIntegration":false,"newPageFinder":true,"pdfEmbedSupport":false,"experimental":{"displayEditorLockExceptions":false,"commonSharingExperiment":false},"useStandardEmbedsInSidebar":false,"pageLevelPermissions":false,"navadminperf":true,"adminInfo":false,"lazySiteHierarchy":true,"dragDropHierarchy":true,"headerAlignmentOptions":true,"horizontalNavigationBar":true,"keyboardShortcuts":true,"commonSharing":false,"spreadsheetsEmbedLoadRedirect":false,"structuredDataSchemas":false,"footerCustomOptions":true},"domain":"defaultdomain","adsensePublisherId":"ca-pub-9569899026815114","isStartPageEnabled":false,"domainAnalyticsAccountId":"","siteTitle":"sphinxcompiler"};
webspace.gadgets = {"isGadgetDirectoryEnabled":true,"baseUri":"/system/app/pages/gadgets","isGgsRenderingEnabled":true};
webspace.user = {"uid":"","hasAdminAccess":false,"guest_":true,"keyboardShortcuts":true,"domain":"","hasWriteAccess":false,"userName":"guest","dasherUser":false,"primaryEmail":"guest","sessionIndex":"","namespaceUser":false,"displayNameOrEmail":"guest"};
webspace.page = {"canDeleteWebspace":null,"locale":"de","state":"","wuid":"wuid:gx:42b8839a5da5c6fb","timeZone":"Europe/Paris","properties":{},"type":"text","canChangePath":true,"parentWuid":"wuid:gx:6a8841c52faad061","revision":8,"title":"Compiling and linking: a SOB story","isRtlLocale":false,"bidiEnabled":false,"siteLocale":"en","name":"sobstory","path":"/Home/sphinx-documentation/sobstory","isSiteRtlLocale":false,"parentPath":"/Home/sphinx-documentation"};
var editorResources = [
'http://www.gstatic.com/sites/p/934749/system/js/trog_edit__de.js',
'http://www.gstatic.com/sites/p/934749/system/app/css/trogedit.css',
'/_/rsrc/1287429563000/system/app/css/editor.css'
];
var JOT_clearDotPath = 'http://www.gstatic.com/sites/p/934749/system/app/images/cleardot.gif';
var JOT_userRelTimeStrs = ["vor einer Minute","vor __duration__ Minuten","vor einer Stunde","vor __duration__ Stunden"];
webspace.page.currentTemplate = {"title":"Webseite","path":"/system/app/pagetemplates/text"};
var JOT_siteRelTimeStrs = ["a minute ago","__duration__ minutes ago","an hour ago","__duration__ hours ago"];
</script>
<script type="text/javascript">
window.jstiming.load.tick('scl');
</script>
<link rel="stylesheet" type="text/css" href="http://www.gstatic.com/sites/p/934749/system/app/themes/simplywhite/standard-css-simplywhite-ltr-ltr.css" />
<link rel="stylesheet" type="text/css" href="/_/rsrc/1287429563000/system/app/css/overlay.css?cb=simplywhite100%250150goog-ws-left" />
<title>Compiling and linking: a SOB story - sphinxcompiler</title>
<script type="text/javascript">
window.jstiming.load.tick('cl');
</script>
</head>
<body xmlns="http://www.google.com/ns/jotspot" id="body" class=" en">
<div id="sites-page-toolbar">
<div id="sites-status" class="sites-status" style="display:none;">
<div id="sites-notice" class="sites-notice"> </div>
</div>
</div>
<div id="sites-chrome-everything" style="direction: ltr">
<div id="sites-chrome-page-wrapper">
<div id="sites-chrome-page-wrapper-inside">
<div xmlns="http://www.w3.org/1999/xhtml" id="sites-chrome-header-wrapper">
<table id="sites-chrome-header" class="sites-layout-hbox" cellspacing="0">
<tr class="sites-header-primary-row">
<td id="sites-header-title">
<div class="sites-header-cell-buffer-wrapper">
<h2>
<a href="http://www.sphinxcompiler.com/" dir="ltr">sphinxcompiler</a>
</h2>
</div>
</td>
<td class="sites-layout-searchbox">
<div class="sites-header-cell-buffer-wrapper">
<div>
<form id="sites-searchbox-form" action="/system/app/pages/search">
<input type="text" onpropertychange="JOT_setTextDir(this)" oninput="JOT_setTextDir(this)" dir="" id="jot-ui-searchInput" name="q" size="20" />
<input type="hidden" id="sites-searchbox-scope" name="scope" value="search-site" />
<div class="goog-inline-block goog-button goog-button-base "><div class="goog-inline-block goog-button-base-outer-box TOP"><div class="goog-inline-block goog-button-base-inner-box"><div class="goog-button-base-pos"><div class="goog-button-base-top-shadow"> </div><div id="sites-searchbox-search-button" class="goog-button-base-content " style="" onclick=""><span id="sites-searchbox-search-button-label">Search this site</span></div></div></div></div></div>
</form>
</div>
</div>
</td>
</tr>
<tr class="sites-header-secondary-row">
<td colspan="2">
</td>
</tr>
</table>
</div>
<div id="sites-chrome-main-wrapper">
<div id="sites-chrome-main-wrapper-inside">
<table id="sites-chrome-main" class="sites-layout-hbox" cellspacing="0">
<tr>
<td id="sites-chrome-sidebar-left" class="sites-layout-sidebar-left">
</td>
<td id="sites-canvas-wrapper">
<div id="sites-canvas">
<div id="goog-ws-editor-toolbar-container"> </div>
<div xmlns="http://www.w3.org/1999/xhtml" id="title-crumbs" style="">
<A dir="ltr" href="/Home">Sphinx</A> &gt; <A dir="ltr" href="/Home/sphinx-documentation">Documentation</A> &gt;
</div>
<h3 xmlns="http://www.w3.org/1999/xhtml" id="sites-page-title-header" style="" align="left">
<span id="sites-page-title" dir="ltr">Compiling and linking: a SOB story</span>
</h3>
<div id="sites-canvas-main" class="sites-canvas-main">
<div id="sites-canvas-main-content">
<table xmlns="http://www.w3.org/1999/xhtml" cellspacing="0" class="sites-layout-name-one-column sites-layout-hbox"><tbody><tr><td class="sites-layout-tile sites-tile-name-content-1"><div dir="ltr"><div>The process of building a program with Sphinx is divided into two steps, compiling and linking. Compiling transforms a Spin source file into a Spin Object Binary (SOB) file. Linking converts a SOB and its sub-SOBs into an executable binary image.<br /></div>
<div>
<h3><a name="TOC-Compiling"></a>Compiling</h3></div>
<div>The Sphinx "compiler" proper actually consists of two programs, <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/lexbin">lex.bin</a> and <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/codegenbin">codegen.bin</a>, but they work so closely together that they are best considered a unit. Lex.bin reads a .spn file, tokenizes it, and produces an intermediate .tok file. Codegen.bin reads the .tok file, parses it, and generates object code which it saves in a .sob file.</div>
<div> </div>
<div>A SOB contains the Spin bytecodes for the object's PUB and PRI methods. In addition, it contains a list of the object's <i>imports</i> (sub-objects) and its <i>exports</i> (constants and PUB method signatures). A SOB is the compiled essence of an object. As far as Sphinx is concerned, a SOB contains the same information as its corresponding Spin file, just in convenient binary form. </div>
<div> </div>
<div>The compiler only compiles a single .spn file at a time. If the .spn file contains a sub-object, the compiler reads the .sob file for that sub-object and retrieves its exported information. This gives the compiler enough information to compile the .spn file without having to compile additional .spn files.</div>
<div> </div>
<div>This also means that programs have to be compiled from the bottom up. That is, sub-objects have to be compiled before any containing objects are compiled.</div>
<div> </div>
<div>Consider a simple program that prints "Hello, world" on the screen. The top object, <i>hello</i>, contains a sub-object, <i>tv_text</i>. <i>Tv_text</i> in turn contains sub-object <i>tv</i>. When you compile hello.spn, the compiler will need to read tv_text.sob, so you have to have compiled tv_text.spn beforehand. Similarly, before compiling tv_text.spn, you must compile tv.spn to produce tv.sob. So to compile <i>hello</i> from a standing start you must issue these commands:</div>
<div><font face="courier new,monospace">c tv</font></div>
<div><font face="courier new,monospace">c tv_text</font></div>
<div><font face="courier new,monospace">cl hello</font></div>
<div><font face="arial,sans-serif"> </font></div>
<div>Of course, subsequently you will not have to compile all three objects every time, just the objects that change.</div>
<div>
<h3><a name="TOC-Linking"></a>Linking</h3></div>
<div>You invoke the linker (<a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/linkbin">link.bin</a>) with the name of the top-level object. The linker reads the top-level SOB and goes through its list of imports (in other words, its sub-objects). The linker recursively reads the sub-SOBs and their sub-SOBs.</div>
<div> </div>
<div>Once all the SOBs are read, the linker determines how it will lay out all the objects' bytecode in memory and adjusts the various inter-object pointers so that they all refer to one another correctly. Then it writes an executable binary image (.bin file).</div><span lang="EN">
<h3><a name="TOC-Timestamps"></a>Timestamps</h3></span>
<div>Consider the following situation:
<ol>
<li>sub.spn is compiled, producing sub.sob.</li>
<li>top.spn is compiled using sub.sob, producing top.sob.</li>
<li>sub.spn is modified and recompiled, producing a new sub.sob.</li></ol>
<div>Now the top SOB is based on an old version of the sub-SOB. When the objects are linked, the resulting executable file may well fail because of that version mismatch.</div>
<div> </div>
<div>In order to detect such version mismatches, Sphinx maintains a 32-bit "timestamp" in a file named timestmp.d8a. Every time you compile an object, Sphinx increments the timestamp and stores it in the .sob file. (Of course an actual timestamp could be used, but Sphinx takes this approach so as not to require a real-time clock.)</div>
<div> </div>
<div>The linker compares timestamps and warns if any object being linked is out of date with respect to a sub-object.</div>
<div> </div>
<div>Note that this timestamp mechanism cannot detect when a .sob file is out of date with respect to its .spn counterpart. That is, Sphinx cannot tell if a .spn file has been modified after being compiled. If you edit a source file, it is your responsibility to remember to compile it.</div></div>
<div> </div>
<div style="text-align:right">Next: <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/the-sphinx-operating-environment">The Sphinx operating environment</a></div></div></td></tr></tbody></table>
</div>
</div>
<div id="sites-canvas-bottom-panel">
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
<div id="sites-chrome-footer-wrapper">
<div id="sites-chrome-footer-wrapper-inside">
<div id="sites-chrome-footer">
</div>
</div>
</div>
</div>
</div>
<div xmlns="http://www.w3.org/1999/xhtml" class="sites-adminfooter">
<p>
 
<a href="https://www.google.com/a/UniversalLogin?continue=http%3A%2F%2Fsites.google.com%2Fsite%2Fsphinxcompiler%2FHome%2Fsphinx-documentation%2Fsobstory&amp;service=jotspot" class="sites-system-link">Anmelden</a>
 
<a href="/system/app/pages/recentChanges" rel="nofollow" class="sites-system-link">Site-Aktivität in letzter Zeit</a>
 
<a href="javascript:void(window.open('http://www.google.com/sites/help/intl/de/terms.html'))" class="sites-system-link">Nutzungsbedingungen</a>
 
<a href="/system/app/pages/reportAbuse?src=/Home/sphinx-documentation/sobstory" rel="nofollow" target="_blank" class="sites-system-link">Missbrauch melden</a>
 
<a href="javascript:;" onclick="window.open(webspace.printUrl)" class="sites-system-link">Seite drucken</a>
 | 
<b class="powered-by">Powered by <a href="http://sites.google.com">Google Sites</a></b>
</p>
</div>
</div>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
window.jstiming.load.tick('sjl');
</script>
<script xmlns="http://www.w3.org/1999/xhtml" src="http://www.gstatic.com/sites/p/934749/system/js/jot_min_view__en.js"></script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
window.jstiming.load.tick('jl');
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
if (editorResources) {
//<![CDATA[
editorResources.unshift('/system/app/css/overlay.css?cb=simplywhite100%250150goog-ws-left');
editorResources.unshift('/_/rsrc/1287429563000/system/app/themes/simplywhite/standard-css-simplywhite-ltr-ltr.css');
//]]>
}
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
var searchBox = new gsites.Searchbox('sites-searchbox-search-button');
searchBox.initListeners();
searchBox.setScopesMenu(webspace.page.isSiteRtlLocale);
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
gsites.HoverPopupMenu.createHoverPopupMenu('sites-header-nav-dropdown');
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
window.onload = function() {
var loadTimer = window.jstiming.load;
loadTimer.tick("ol");
loadTimer["name"] = "load," + webspace.page.type;
window.jstiming.report(loadTimer);
}
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
JOT_insertAnalyticsCode(false);
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
JOT_insertTranslateCode('de', 'en');
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript" defer="true">
//<![CDATA[
// Fires delayed events.
(function() {
JOT_fullyLoaded = true;
var delayedEvents = JOT_delayedEvents;
for (var x = 0; x < delayedEvents.length; x++) {
var event = delayedEvents[x];
JOT_postEvent(event.eventName, event.eventSrc, event.payload);
}
JOT_delayedEvents = null;
JOT_postEvent('pageLoaded');
})();
// Decorate any fastUI buttons on the page with a class of 'goog-button'.
if (webspace.user.hasWriteAccess) {
JOT_decorateButtons();
}
//]]>
</script>
<div id="server-timer-div" style="display:none"> </div>
<script>
window.jstiming.load.tick('render');
</script>
</body>
</html>

View File

@ -1,235 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">/* Copyright 2008 Google. */ (function() { // Input 0
var a=window;
// Input 1
var b="start";function d(f){this.t={};this.tick=function(g,h,c){c=c?c:(new Date).getTime();this.t[g]=[c,h]};this.tick(b,null,f)}var e=new d;a.jstiming={Timer:d,load:e};try{var i=null;if(a.chrome&&a.chrome.csi)i=Math.floor(a.chrome.csi().pageT);if(i==null)if(a.gtbExternal)i=a.gtbExternal.pageT();if(i==null)if(a.external)i=a.external.pageT;if(i)a.jstiming.pt=i}catch(j){};
// Input 2
})()
</script>
<link rel="shortcut icon" type="image/x-icon" href="//www.google.com/images/icons/product/sites-16.ico" />
<link rel="apple-touch-icon" href="http://www.gstatic.com/sites/p/934749/system/app/images/apple-touch-icon.png" type="image/png" />
<script type="text/javascript">/* Copyright 2008 Google. */ (function() { var e=parseInt,h=window,i="length";function j(c){return document.getElementById(c)}h.byId=j;var k="";function l(c){return c.replace(/^\s+|\s+$/g,k)}h.trim=l;
var m="MSIE",n="6.0",o="string",p='id="',q='" ',r='class="',s='title="',t="display:inline-block;",u="left",v="float:left;",w="right",x="float:right;",y="cursor:hand;",z="<span ",A=' style="width:',B="px; height:",C="px;",D=";padding: 0;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='",E="', sizingMethod='scale');\"></span><span style=\"padding: ",F=" ",G=";",H="float:",I='"></span>';
h.ie6ImgFix=function(c){var b=h.navigator?navigator.userAgent:k;if(b.indexOf(m)!=-1&&typeof opera=="undefined"){var d=/MSIE\s+([^\);]+)(\)|;)/;d.test(b);b=RegExp.$1;if(b==n){var a=typeof c==o?j(c):c;c=a.id?p+a.id+q:k;b=a.className?r+a.className+q:k;d=a.title?s+a.title+q:s+a.alt+q;var f=t+a.style.cssText;if(a.align==u)f=v+f;if(a.align==w)f=x+f;if(a.parentElement.href)f=y+f;var g=a.currentStyle,L=a.width-e(g.paddingLeft,10)-e(g.paddingRight,10),M=a.height-e(g.paddingTop,10)-e(g.paddingBottom,10),N=
z+c+b+d+A+L+B+M+C+f+D+a.src+E+g.paddingTop+F+g.paddingRight+F+g.paddingBottom+F+g.paddingLeft+G+(g.styleFloat?H+g.styleFloat+G:k)+I;h.setTimeout(function(){a.outerHTML=N},1)}}};var J=[],K=0;h.JOT_addListener=function(c,b,d){var a=new String(K++);c={eventName:c,handler:b,compId:d,key:a};J.push(c);return a};h.JOT_removeListenerByKey=function(c){for(var b=0;b<J[i];b++)if(J[b].key==c){J.splice(b,1);break}};
h.JOT_removeAllListenersForName=function(c){for(var b=0;b<J[i];b++)J[b].eventName==c&&J.splice(b,1)};var O="function";h.JOT_postEvent=function(c,b,d){var a={eventName:c,eventSrc:b||{},payload:d||{}};if(h.JOT_fullyLoaded){b=J[i];for(d=0;d<b&&d<J[i];d++){var f=J[d];if(f&&f.eventName==c){a.listenerCompId=f.compId||k;(f=typeof f.handler==O?f.handler:h[f.handler])&&f(a)}}}else h.JOT_delayedEvents.push({eventName:c,eventSrc:b,payload:d})};h.JOT_delayedEvents=[];h.JOT_fullyLoaded=false;var P="__duration__";
h.JOT_formatRelativeToNow=function(c,b){var d=((new Date).getTime()-c)/6E4;if(d>=1440||d<0)return null;var a=0;if(d>=60){d/=60;a=2}d>=2&&a++;return b?h.JOT_siteRelTimeStrs[a].replace(P,Math.floor(d)):h.JOT_userRelTimeStrs[a].replace(P,Math.floor(d))}; })()
</script>
<script>
var webspace = {"signInUrl":"https://www.google.com/a/UniversalLogin?continue=http%3A%2F%2Fsites.google.com%2Fsite%2Fsphinxcompiler%2FHome%2Fsphinx-documentation%2Freference%2Fsphinxbin&service=jotspot","isConsumer":true,"termsUrl":"http://www.google.com/sites/help/intl/de/terms.html","enableAnalytics":false,"homePath":"/","sharingId":"jotspot","sharingPolicy":"OPENED","isAdsenseEnabled":true,"analyticsAccountId":"","baseUri":"","name":"sphinxcompiler","features":{"structuredDataGviz":false,"horizontalNavigationDropdownMenus":true,"subpageNav":false,"kixEditorPageType":false,"maestroIntegration":false,"newPageFinder":true,"pdfEmbedSupport":false,"experimental":{"displayEditorLockExceptions":false,"commonSharingExperiment":false},"useStandardEmbedsInSidebar":false,"pageLevelPermissions":false,"navadminperf":true,"adminInfo":false,"lazySiteHierarchy":true,"dragDropHierarchy":true,"headerAlignmentOptions":true,"horizontalNavigationBar":true,"keyboardShortcuts":true,"commonSharing":false,"spreadsheetsEmbedLoadRedirect":false,"structuredDataSchemas":false,"footerCustomOptions":true},"domain":"defaultdomain","adsensePublisherId":"ca-pub-9569899026815114","isStartPageEnabled":false,"domainAnalyticsAccountId":"","siteTitle":"sphinxcompiler"};
webspace.gadgets = {"isGadgetDirectoryEnabled":true,"baseUri":"/system/app/pages/gadgets","isGgsRenderingEnabled":true};
webspace.user = {"uid":"","hasAdminAccess":false,"guest_":true,"keyboardShortcuts":true,"domain":"","hasWriteAccess":false,"userName":"guest","dasherUser":false,"primaryEmail":"guest","sessionIndex":"","namespaceUser":false,"displayNameOrEmail":"guest"};
webspace.page = {"canDeleteWebspace":null,"locale":"de","state":"","wuid":"wuid:gx:3fe57315f2bb4ed6","timeZone":"Europe/Paris","properties":{},"type":"text","canChangePath":true,"parentWuid":"wuid:gx:1acca89fde6198c7","revision":8,"title":"sphinx.bin","isRtlLocale":false,"bidiEnabled":false,"siteLocale":"en","name":"sphinxbin","path":"/Home/sphinx-documentation/reference/sphinxbin","isSiteRtlLocale":false,"parentPath":"/Home/sphinx-documentation/reference"};
var editorResources = [
'http://www.gstatic.com/sites/p/934749/system/js/trog_edit__de.js',
'http://www.gstatic.com/sites/p/934749/system/app/css/trogedit.css',
'/_/rsrc/1287429563000/system/app/css/editor.css'
];
var JOT_clearDotPath = 'http://www.gstatic.com/sites/p/934749/system/app/images/cleardot.gif';
var JOT_userRelTimeStrs = ["vor einer Minute","vor __duration__ Minuten","vor einer Stunde","vor __duration__ Stunden"];
webspace.page.currentTemplate = {"title":"Webseite","path":"/system/app/pagetemplates/text"};
var JOT_siteRelTimeStrs = ["a minute ago","__duration__ minutes ago","an hour ago","__duration__ hours ago"];
</script>
<script type="text/javascript">
window.jstiming.load.tick('scl');
</script>
<link rel="stylesheet" type="text/css" href="http://www.gstatic.com/sites/p/934749/system/app/themes/simplywhite/standard-css-simplywhite-ltr-ltr.css" />
<link rel="stylesheet" type="text/css" href="/_/rsrc/1287429563000/system/app/css/overlay.css?cb=simplywhite100%250150goog-ws-left" />
<title>sphinx.bin - sphinxcompiler</title>
<script type="text/javascript">
window.jstiming.load.tick('cl');
</script>
</head>
<body xmlns="http://www.google.com/ns/jotspot" id="body" class=" en">
<div id="sites-page-toolbar">
<div id="sites-status" class="sites-status" style="display:none;">
<div id="sites-notice" class="sites-notice"> </div>
</div>
</div>
<div id="sites-chrome-everything" style="direction: ltr">
<div id="sites-chrome-page-wrapper">
<div id="sites-chrome-page-wrapper-inside">
<div xmlns="http://www.w3.org/1999/xhtml" id="sites-chrome-header-wrapper">
<table id="sites-chrome-header" class="sites-layout-hbox" cellspacing="0">
<tr class="sites-header-primary-row">
<td id="sites-header-title">
<div class="sites-header-cell-buffer-wrapper">
<h2>
<a href="http://www.sphinxcompiler.com/" dir="ltr">sphinxcompiler</a>
</h2>
</div>
</td>
<td class="sites-layout-searchbox">
<div class="sites-header-cell-buffer-wrapper">
<div>
<form id="sites-searchbox-form" action="/system/app/pages/search">
<input type="text" onpropertychange="JOT_setTextDir(this)" oninput="JOT_setTextDir(this)" dir="" id="jot-ui-searchInput" name="q" size="20" />
<input type="hidden" id="sites-searchbox-scope" name="scope" value="search-site" />
<div class="goog-inline-block goog-button goog-button-base "><div class="goog-inline-block goog-button-base-outer-box TOP"><div class="goog-inline-block goog-button-base-inner-box"><div class="goog-button-base-pos"><div class="goog-button-base-top-shadow"> </div><div id="sites-searchbox-search-button" class="goog-button-base-content " style="" onclick=""><span id="sites-searchbox-search-button-label">Search this site</span></div></div></div></div></div>
</form>
</div>
</div>
</td>
</tr>
<tr class="sites-header-secondary-row">
<td colspan="2">
</td>
</tr>
</table>
</div>
<div id="sites-chrome-main-wrapper">
<div id="sites-chrome-main-wrapper-inside">
<table id="sites-chrome-main" class="sites-layout-hbox" cellspacing="0">
<tr>
<td id="sites-chrome-sidebar-left" class="sites-layout-sidebar-left">
</td>
<td id="sites-canvas-wrapper">
<div id="sites-canvas">
<div id="goog-ws-editor-toolbar-container"> </div>
<div xmlns="http://www.w3.org/1999/xhtml" id="title-crumbs" style="">
<A dir="ltr" href="/Home">Sphinx</A> &gt; <A dir="ltr" href="/Home/sphinx-documentation">Documentation</A> &gt; <A dir="ltr" href="/Home/sphinx-documentation/reference">Reference</A> &gt;
</div>
<h3 xmlns="http://www.w3.org/1999/xhtml" id="sites-page-title-header" style="" align="left">
<span id="sites-page-title" dir="ltr">sphinx.bin</span>
</h3>
<div id="sites-canvas-main" class="sites-canvas-main">
<div id="sites-canvas-main-content">
<table xmlns="http://www.w3.org/1999/xhtml" cellspacing="0" class="sites-layout-name-one-column sites-layout-hbox"><tbody><tr><td class="sites-layout-tile sites-tile-name-content-1"><div dir="ltr">Sphinx.bin installs the Sphinx drivers for the keyboard, TV, and SD card. It also acts as a simple command-line shell.<div>A command line can take any of the following forms:<div><ul><li><i>filename arg<sub>1</sub> arg<sub>2</sub> ... arg<sub>n</sub></i></li><li><b>run</b> <i>filename arg<sub>1</sub> arg<sub>2</sub> ... arg<sub>n</sub></i></li><li><b>c</b> <i>filename arg<sub>1</sub> arg<sub>2</sub> ... arg<sub>n</sub></i></li><li><b>cl</b> <i>filename arg<sub>1</sub> arg<sub>2</sub> ... arg<sub>n</sub></i></li></ul><div>The first form loads and executes the file named <i>filename</i>. If <i>filename</i> ends with ".bin" or ".eep", sphinx.bin will execute the file of that name (if it exists, of course). Otherwise, sphinx.bin will attempt to execute <i>filename</i>.bin and, if that fails, <i>filename</i>.eep. <div> </div><div>The second form, the <b>run</b> command, also loads and runs <i>filename</i>. The difference between these two forms of command is that the first one leaves the Sphinx device driver cogs running, while the second stops all cogs (it effectively resets the Propeller). Use the first form to execute Sphinx-aware programs; use the <b>run</b> command to execute regular programs.</div><div> </div><div>The <b>c</b> command compiles <i>filename</i>.spn and generates <i>filename</i>.sob (assuming no errors). This command runs <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/lexbin">lex.bin</a> and <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/codegenbin">codegen.bin</a>, passing any command-line arguments to both programs (see below).<div> </div><div>The <b>cl</b> command compiles and links <i>filename</i>.spn, generating <i>filename</i>.sob and <i>filename</i>.bin (again, assuming no errors). This command runs <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/lexbin">lex.bin</a>, <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/codegenbin">codegen.bin</a>, and <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference/linkbin">link.bin</a>, passing its command-line arguments to all three programs.</div><div> </div><div>Sphinx.bin should be stored in EEPROM so that the Propeller boots into Sphinx. Sphinx.bin should also exist on the SD card so that Sphinx-aware programs can, once they've finished their work, load and execute sphinx.bin. <div><div><div><h3><a name="TOC-Command-line-arguments"></a>Command-line arguments</h3></div><div>Sphinx.bin stores arguments as ASCII strings in a file named "args.d8a". A program launched from Sphinx can read the argument strings from that file. The first byte of the file is the number of arguments; it is followed by that number of strings, each null-terminated.</div></div></div></div><div> </div><div>As noted earlier, the <strong>c</strong> and <strong>cl</strong> commands run several programs and each program receives the same arguments. This is because they do not modify args.d8a before executing the next program in the sequence. Each program pays attention to the arguments it understands and ignores any that it does not.</div></div></div></div></div></div></td></tr></tbody></table>
</div>
</div>
<div id="sites-canvas-bottom-panel">
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
<div id="sites-chrome-footer-wrapper">
<div id="sites-chrome-footer-wrapper-inside">
<div id="sites-chrome-footer">
</div>
</div>
</div>
</div>
</div>
<div xmlns="http://www.w3.org/1999/xhtml" class="sites-adminfooter">
<p>
 
<a href="https://www.google.com/a/UniversalLogin?continue=http%3A%2F%2Fsites.google.com%2Fsite%2Fsphinxcompiler%2FHome%2Fsphinx-documentation%2Freference%2Fsphinxbin&amp;service=jotspot" class="sites-system-link">Anmelden</a>
 
<a href="/system/app/pages/recentChanges" rel="nofollow" class="sites-system-link">Site-Aktivität in letzter Zeit</a>
 
<a href="javascript:void(window.open('http://www.google.com/sites/help/intl/de/terms.html'))" class="sites-system-link">Nutzungsbedingungen</a>
 
<a href="/system/app/pages/reportAbuse?src=/Home/sphinx-documentation/reference/sphinxbin" rel="nofollow" target="_blank" class="sites-system-link">Missbrauch melden</a>
 
<a href="javascript:;" onclick="window.open(webspace.printUrl)" class="sites-system-link">Seite drucken</a>
 | 
<b class="powered-by">Powered by <a href="http://sites.google.com">Google Sites</a></b>
</p>
</div>
</div>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
window.jstiming.load.tick('sjl');
</script>
<script xmlns="http://www.w3.org/1999/xhtml" src="http://www.gstatic.com/sites/p/934749/system/js/jot_min_view__en.js"></script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
window.jstiming.load.tick('jl');
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
if (editorResources) {
//<![CDATA[
editorResources.unshift('/system/app/css/overlay.css?cb=simplywhite100%250150goog-ws-left');
editorResources.unshift('/_/rsrc/1287429563000/system/app/themes/simplywhite/standard-css-simplywhite-ltr-ltr.css');
//]]>
}
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
var searchBox = new gsites.Searchbox('sites-searchbox-search-button');
searchBox.initListeners();
searchBox.setScopesMenu(webspace.page.isSiteRtlLocale);
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
gsites.HoverPopupMenu.createHoverPopupMenu('sites-header-nav-dropdown');
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
window.onload = function() {
var loadTimer = window.jstiming.load;
loadTimer.tick("ol");
loadTimer["name"] = "load," + webspace.page.type;
window.jstiming.report(loadTimer);
}
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
JOT_insertAnalyticsCode(false);
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
JOT_insertTranslateCode('de', 'en');
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript" defer="true">
//<![CDATA[
// Fires delayed events.
(function() {
JOT_fullyLoaded = true;
var delayedEvents = JOT_delayedEvents;
for (var x = 0; x < delayedEvents.length; x++) {
var event = delayedEvents[x];
JOT_postEvent(event.eventName, event.eventSrc, event.payload);
}
JOT_delayedEvents = null;
JOT_postEvent('pageLoaded');
})();
// Decorate any fastUI buttons on the page with a class of 'goog-button'.
if (webspace.user.hasWriteAccess) {
JOT_decorateButtons();
}
//]]>
</script>
<div id="server-timer-div" style="display:none"> </div>
<script>
window.jstiming.load.tick('render');
</script>
</body>
</html>

View File

@ -1,258 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">/* Copyright 2008 Google. */ (function() { // Input 0
var a=window;
// Input 1
var b="start";function d(f){this.t={};this.tick=function(g,h,c){c=c?c:(new Date).getTime();this.t[g]=[c,h]};this.tick(b,null,f)}var e=new d;a.jstiming={Timer:d,load:e};try{var i=null;if(a.chrome&&a.chrome.csi)i=Math.floor(a.chrome.csi().pageT);if(i==null)if(a.gtbExternal)i=a.gtbExternal.pageT();if(i==null)if(a.external)i=a.external.pageT;if(i)a.jstiming.pt=i}catch(j){};
// Input 2
})()
</script>
<link rel="shortcut icon" type="image/x-icon" href="//www.google.com/images/icons/product/sites-16.ico" />
<link rel="apple-touch-icon" href="http://www.gstatic.com/sites/p/934749/system/app/images/apple-touch-icon.png" type="image/png" />
<script type="text/javascript">/* Copyright 2008 Google. */ (function() { var e=parseInt,h=window,i="length";function j(c){return document.getElementById(c)}h.byId=j;var k="";function l(c){return c.replace(/^\s+|\s+$/g,k)}h.trim=l;
var m="MSIE",n="6.0",o="string",p='id="',q='" ',r='class="',s='title="',t="display:inline-block;",u="left",v="float:left;",w="right",x="float:right;",y="cursor:hand;",z="<span ",A=' style="width:',B="px; height:",C="px;",D=";padding: 0;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='",E="', sizingMethod='scale');\"></span><span style=\"padding: ",F=" ",G=";",H="float:",I='"></span>';
h.ie6ImgFix=function(c){var b=h.navigator?navigator.userAgent:k;if(b.indexOf(m)!=-1&&typeof opera=="undefined"){var d=/MSIE\s+([^\);]+)(\)|;)/;d.test(b);b=RegExp.$1;if(b==n){var a=typeof c==o?j(c):c;c=a.id?p+a.id+q:k;b=a.className?r+a.className+q:k;d=a.title?s+a.title+q:s+a.alt+q;var f=t+a.style.cssText;if(a.align==u)f=v+f;if(a.align==w)f=x+f;if(a.parentElement.href)f=y+f;var g=a.currentStyle,L=a.width-e(g.paddingLeft,10)-e(g.paddingRight,10),M=a.height-e(g.paddingTop,10)-e(g.paddingBottom,10),N=
z+c+b+d+A+L+B+M+C+f+D+a.src+E+g.paddingTop+F+g.paddingRight+F+g.paddingBottom+F+g.paddingLeft+G+(g.styleFloat?H+g.styleFloat+G:k)+I;h.setTimeout(function(){a.outerHTML=N},1)}}};var J=[],K=0;h.JOT_addListener=function(c,b,d){var a=new String(K++);c={eventName:c,handler:b,compId:d,key:a};J.push(c);return a};h.JOT_removeListenerByKey=function(c){for(var b=0;b<J[i];b++)if(J[b].key==c){J.splice(b,1);break}};
h.JOT_removeAllListenersForName=function(c){for(var b=0;b<J[i];b++)J[b].eventName==c&&J.splice(b,1)};var O="function";h.JOT_postEvent=function(c,b,d){var a={eventName:c,eventSrc:b||{},payload:d||{}};if(h.JOT_fullyLoaded){b=J[i];for(d=0;d<b&&d<J[i];d++){var f=J[d];if(f&&f.eventName==c){a.listenerCompId=f.compId||k;(f=typeof f.handler==O?f.handler:h[f.handler])&&f(a)}}}else h.JOT_delayedEvents.push({eventName:c,eventSrc:b,payload:d})};h.JOT_delayedEvents=[];h.JOT_fullyLoaded=false;var P="__duration__";
h.JOT_formatRelativeToNow=function(c,b){var d=((new Date).getTime()-c)/6E4;if(d>=1440||d<0)return null;var a=0;if(d>=60){d/=60;a=2}d>=2&&a++;return b?h.JOT_siteRelTimeStrs[a].replace(P,Math.floor(d)):h.JOT_userRelTimeStrs[a].replace(P,Math.floor(d))}; })()
</script>
<script>
var webspace = {"signInUrl":"https://www.google.com/a/UniversalLogin?continue=http%3A%2F%2Fsites.google.com%2Fsite%2Fsphinxcompiler%2FHome%2Fsphinx-documentation%2Fthe-sphinx-operating-environment&service=jotspot","isConsumer":true,"termsUrl":"http://www.google.com/sites/help/intl/de/terms.html","enableAnalytics":false,"homePath":"/","sharingId":"jotspot","sharingPolicy":"OPENED","isAdsenseEnabled":true,"analyticsAccountId":"","baseUri":"","name":"sphinxcompiler","features":{"structuredDataGviz":false,"horizontalNavigationDropdownMenus":true,"subpageNav":false,"kixEditorPageType":false,"maestroIntegration":false,"newPageFinder":true,"pdfEmbedSupport":false,"experimental":{"displayEditorLockExceptions":false,"commonSharingExperiment":false},"useStandardEmbedsInSidebar":false,"pageLevelPermissions":false,"navadminperf":true,"adminInfo":false,"lazySiteHierarchy":true,"dragDropHierarchy":true,"headerAlignmentOptions":true,"horizontalNavigationBar":true,"keyboardShortcuts":true,"commonSharing":false,"spreadsheetsEmbedLoadRedirect":false,"structuredDataSchemas":false,"footerCustomOptions":true},"domain":"defaultdomain","adsensePublisherId":"ca-pub-9569899026815114","isStartPageEnabled":false,"domainAnalyticsAccountId":"","siteTitle":"sphinxcompiler"};
webspace.gadgets = {"isGadgetDirectoryEnabled":true,"baseUri":"/system/app/pages/gadgets","isGgsRenderingEnabled":true};
webspace.user = {"uid":"","hasAdminAccess":false,"guest_":true,"keyboardShortcuts":true,"domain":"","hasWriteAccess":false,"userName":"guest","dasherUser":false,"primaryEmail":"guest","sessionIndex":"","namespaceUser":false,"displayNameOrEmail":"guest"};
webspace.page = {"canDeleteWebspace":null,"locale":"de","state":"","wuid":"wuid:gx:1271a3bf047a6b37","timeZone":"Europe/Paris","properties":{},"type":"text","canChangePath":true,"parentWuid":"wuid:gx:6a8841c52faad061","revision":10,"title":"The Sphinx operating environment","isRtlLocale":false,"bidiEnabled":false,"siteLocale":"en","name":"the-sphinx-operating-environment","path":"/Home/sphinx-documentation/the-sphinx-operating-environment","isSiteRtlLocale":false,"parentPath":"/Home/sphinx-documentation"};
var editorResources = [
'http://www.gstatic.com/sites/p/934749/system/js/trog_edit__de.js',
'http://www.gstatic.com/sites/p/934749/system/app/css/trogedit.css',
'/_/rsrc/1287429563000/system/app/css/editor.css'
];
var JOT_clearDotPath = 'http://www.gstatic.com/sites/p/934749/system/app/images/cleardot.gif';
var JOT_userRelTimeStrs = ["vor einer Minute","vor __duration__ Minuten","vor einer Stunde","vor __duration__ Stunden"];
webspace.page.currentTemplate = {"title":"Webseite","path":"/system/app/pagetemplates/text"};
var JOT_siteRelTimeStrs = ["a minute ago","__duration__ minutes ago","an hour ago","__duration__ hours ago"];
</script>
<script type="text/javascript">
window.jstiming.load.tick('scl');
</script>
<link rel="stylesheet" type="text/css" href="http://www.gstatic.com/sites/p/934749/system/app/themes/simplywhite/standard-css-simplywhite-ltr-ltr.css" />
<link rel="stylesheet" type="text/css" href="/_/rsrc/1287429563000/system/app/css/overlay.css?cb=simplywhite100%250150goog-ws-left" />
<title>The Sphinx operating environment - sphinxcompiler</title>
<script type="text/javascript">
window.jstiming.load.tick('cl');
</script>
</head>
<body xmlns="http://www.google.com/ns/jotspot" id="body" class=" en">
<div id="sites-page-toolbar">
<div id="sites-status" class="sites-status" style="display:none;">
<div id="sites-notice" class="sites-notice"> </div>
</div>
</div>
<div id="sites-chrome-everything" style="direction: ltr">
<div id="sites-chrome-page-wrapper">
<div id="sites-chrome-page-wrapper-inside">
<div xmlns="http://www.w3.org/1999/xhtml" id="sites-chrome-header-wrapper">
<table id="sites-chrome-header" class="sites-layout-hbox" cellspacing="0">
<tr class="sites-header-primary-row">
<td id="sites-header-title">
<div class="sites-header-cell-buffer-wrapper">
<h2>
<a href="http://www.sphinxcompiler.com/" dir="ltr">sphinxcompiler</a>
</h2>
</div>
</td>
<td class="sites-layout-searchbox">
<div class="sites-header-cell-buffer-wrapper">
<div>
<form id="sites-searchbox-form" action="/system/app/pages/search">
<input type="text" onpropertychange="JOT_setTextDir(this)" oninput="JOT_setTextDir(this)" dir="" id="jot-ui-searchInput" name="q" size="20" />
<input type="hidden" id="sites-searchbox-scope" name="scope" value="search-site" />
<div class="goog-inline-block goog-button goog-button-base "><div class="goog-inline-block goog-button-base-outer-box TOP"><div class="goog-inline-block goog-button-base-inner-box"><div class="goog-button-base-pos"><div class="goog-button-base-top-shadow"> </div><div id="sites-searchbox-search-button" class="goog-button-base-content " style="" onclick=""><span id="sites-searchbox-search-button-label">Search this site</span></div></div></div></div></div>
</form>
</div>
</div>
</td>
</tr>
<tr class="sites-header-secondary-row">
<td colspan="2">
</td>
</tr>
</table>
</div>
<div id="sites-chrome-main-wrapper">
<div id="sites-chrome-main-wrapper-inside">
<table id="sites-chrome-main" class="sites-layout-hbox" cellspacing="0">
<tr>
<td id="sites-chrome-sidebar-left" class="sites-layout-sidebar-left">
</td>
<td id="sites-canvas-wrapper">
<div id="sites-canvas">
<div id="goog-ws-editor-toolbar-container"> </div>
<div xmlns="http://www.w3.org/1999/xhtml" id="title-crumbs" style="">
<A dir="ltr" href="/Home">Sphinx</A> &gt; <A dir="ltr" href="/Home/sphinx-documentation">Documentation</A> &gt;
</div>
<h3 xmlns="http://www.w3.org/1999/xhtml" id="sites-page-title-header" style="" align="left">
<span id="sites-page-title" dir="ltr">The Sphinx operating environment</span>
</h3>
<div id="sites-canvas-main" class="sites-canvas-main">
<div id="sites-canvas-main-content">
<table xmlns="http://www.w3.org/1999/xhtml" cellspacing="0" class="sites-layout-name-one-column sites-layout-hbox"><tbody><tr><td class="sites-layout-tile sites-tile-name-content-1">
<div dir="ltr">
<div>Sphinx I/O is performed by device drivers that reside entirely in the Propeller's cogs, taking up almost no hub memory. For example, the video driver runs in a cog and maintains its screen buffer (13 lines of 40 characters) in its cog memory. It communicates with the rest of Sphinx through a single long memory location (known as a <i>rendezvous</i>, to use terminology borrowed from fsrw) at the top of hub RAM space. </div>
<div> </div>
<div>Similarly, the keyboard driver occupies no hub memory except for a rendezvous location.</div>
<div> </div>
<div>The SD card driver is somewhat more complicated. It takes up three cogs. One is a low-level SD SPI driver (fsrw's sdspiqasm, lightly modified). The other two cogs implement a very barebones FAT16 file system that provides basic read, write, and execute functionality. Programs can open multiple files but must allocate some hub memory for each file. Communication with the file system is through several rendezvous locations. The file system requires a 512-byte buffer for metadata.</div>
<div> </div>
<div>There are simple interface objects that hide the details of using the drivers.</div>
<div> </div>
<div>
<div style="text-align:center;zoom:1;display:block;margin-left:auto;margin-right:auto"><a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/the-sphinx-operating-environment/sphinx2.PNG?attredirects=0" imageanchor="1"><img border="0" src="http://www.sphinxcompiler.com/_/rsrc/1267121683014/Home/sphinx-documentation/the-sphinx-operating-environment/sphinx2.PNG" /></a></div></div>
<div style="text-align:center"><em>Sphinx memory and cog usage</em></div>
<div> </div>
<div>Sphinx.bin installs the drivers when it first boots up. From that point on, the drivers remain resident and running even as different programs execute in hub memory (as long as they are Sphinx-aware programs). For example, if you run link.bin by typing "link" at the command prompt, what happens is this:</div>
<div>
<ol>
<li>Sphinx.bin uses the Sphinx file system to load link.bin into hub memory and execute it while leaving all cogs running.</li>
<li>Link.bin runs, using the Sphinx drivers to perform TV, keyboard, and file I/O. Note that link.bin does not install any drivers.</li>
<li>When link.bin terminates, it uses the file system to load and execute sphinx.bin. Sphinx.bin determines that the drivers are already running and does not re-install them. It prints a prompt and awaits the next command.</li></ol></div>
<div>Sphinx-aware programs do not have to carry device driver code inside themselves; they can rely on Sphinx drivers. Sphinx-aware programs can execute other programs, typically sphinx.bin, but not necessarily (for example, lex.bin executes codegen.bin so that the two parts of the compiler run seamlessly). Running sphinx.bin puts up a command prompt immediately after a program ends, without the long delay that a reset would cause. This, coupled with the fact that the display accumulates the output from each program (rather than clearing between each program), gives the convincing illusion of a traditional command-line shell.</div>
<div> </div>
<div>Sphinx can also execute regular (that is, non-Sphinx-aware) programs by performing the equivalent of a reset before running the program. This shuts down the driver cogs. The program must perform its own I/O. When the program finishes, a reboot will presumably occur, either programmatically or manually. At that time, Sphinx will load in from EEPROM and install the Sphinx drivers.</div>
<div style="text-align:right">Next: <a href="http://www.sphinxcompiler.com/Home/sphinx-documentation/reference">Reference</a></div></div></td></tr></tbody></table>
</div>
</div>
<div id="sites-canvas-bottom-panel">
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
<div id="sites-chrome-footer-wrapper">
<div id="sites-chrome-footer-wrapper-inside">
<div id="sites-chrome-footer">
</div>
</div>
</div>
</div>
</div>
<div xmlns="http://www.w3.org/1999/xhtml" class="sites-adminfooter">
<p>
 
<a href="https://www.google.com/a/UniversalLogin?continue=http%3A%2F%2Fsites.google.com%2Fsite%2Fsphinxcompiler%2FHome%2Fsphinx-documentation%2Fthe-sphinx-operating-environment&amp;service=jotspot" class="sites-system-link">Anmelden</a>
 
<a href="/system/app/pages/recentChanges" rel="nofollow" class="sites-system-link">Site-Aktivität in letzter Zeit</a>
 
<a href="javascript:void(window.open('http://www.google.com/sites/help/intl/de/terms.html'))" class="sites-system-link">Nutzungsbedingungen</a>
 
<a href="/system/app/pages/reportAbuse?src=/Home/sphinx-documentation/the-sphinx-operating-environment" rel="nofollow" target="_blank" class="sites-system-link">Missbrauch melden</a>
 
<a href="javascript:;" onclick="window.open(webspace.printUrl)" class="sites-system-link">Seite drucken</a>
 | 
<b class="powered-by">Powered by <a href="http://sites.google.com">Google Sites</a></b>
</p>
</div>
</div>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
window.jstiming.load.tick('sjl');
</script>
<script xmlns="http://www.w3.org/1999/xhtml" src="http://www.gstatic.com/sites/p/934749/system/js/jot_min_view__en.js"></script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
window.jstiming.load.tick('jl');
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
if (editorResources) {
//<![CDATA[
editorResources.unshift('/system/app/css/overlay.css?cb=simplywhite100%250150goog-ws-left');
editorResources.unshift('/_/rsrc/1287429563000/system/app/themes/simplywhite/standard-css-simplywhite-ltr-ltr.css');
//]]>
}
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
var searchBox = new gsites.Searchbox('sites-searchbox-search-button');
searchBox.initListeners();
searchBox.setScopesMenu(webspace.page.isSiteRtlLocale);
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
gsites.HoverPopupMenu.createHoverPopupMenu('sites-header-nav-dropdown');
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
window.onload = function() {
var loadTimer = window.jstiming.load;
loadTimer.tick("ol");
loadTimer["name"] = "load," + webspace.page.type;
window.jstiming.report(loadTimer);
}
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript">
JOT_insertAnalyticsCode(false);
</script>
<script xmlns="http://www.w3.org/1999/xhtml">
JOT_insertTranslateCode('de', 'en');
</script>
<script xmlns="http://www.w3.org/1999/xhtml" type="text/javascript" defer="true">
//<![CDATA[
// Fires delayed events.
(function() {
JOT_fullyLoaded = true;
var delayedEvents = JOT_delayedEvents;
for (var x = 0; x < delayedEvents.length; x++) {
var event = delayedEvents[x];
JOT_postEvent(event.eventName, event.eventSrc, event.payload);
}
JOT_delayedEvents = null;
JOT_postEvent('pageLoaded');
})();
// Decorate any fastUI buttons on the page with a class of 'goog-button'.
if (webspace.user.hasWriteAccess) {
JOT_decorateButtons();
}
//]]>
</script>
<div id="server-timer-div" style="display:none"> </div>
<script>
window.jstiming.load.tick('render');
</script>
</body>
</html>

View File

@ -1,316 +0,0 @@
''***************************************
''* Full-Duplex Serial Driver v1.1 *
''* Author: Chip Gracey *
''* Copyright (c) 2006 Parallax, Inc. *
''* See end of file for terms of use. *
''***************************************
VAR
long cog 'cog flag/id
long rx_head '9 contiguous longs
long rx_tail
long tx_head
long tx_tail
long rx_pin
long tx_pin
long rxtx_mode
long bit_ticks
long buffer_ptr
byte rx_buffer[16] 'transmit and receive buffers
byte tx_buffer[16]
PUB start(rxpin, txpin, mode, baudrate) : okay
'' Start serial driver - starts a cog
'' returns false if no cog available
''
'' mode bit 0 = invert rx
'' mode bit 1 = invert tx
'' mode bit 2 = open-drain/source tx
'' mode bit 3 = ignore tx echo on rx
stop
longfill(@rx_head, 0, 4)
longmove(@rx_pin, @rxpin, 3)
bit_ticks := clkfreq / baudrate
buffer_ptr := @rx_buffer
okay := cog := cognew(@entry, @rx_head) + 1
PUB stop
'' Stop serial driver - frees a cog
if cog
cogstop(cog~ - 1)
longfill(@rx_head, 0, 9)
PUB rxflush
'' Flush receive buffer
repeat while rxcheck => 0
PUB rxcheck : rxbyte
'' Check if byte received (never waits)
'' returns -1 if no byte received, $00..$FF if byte
rxbyte--
if rx_tail <> rx_head
rxbyte := rx_buffer[rx_tail]
rx_tail := (rx_tail + 1) & $F
PUB rxtime(ms) : rxbyte | t
'' Wait ms milliseconds for a byte to be received
'' returns -1 if no byte received, $00..$FF if byte
t := cnt
repeat until (rxbyte := rxcheck) => 0 or (cnt - t) / (clkfreq / 1000) > ms
PUB rx : rxbyte
'' Receive byte (may wait for byte)
'' returns $00..$FF
repeat while (rxbyte := rxcheck) < 0
PUB tx(txbyte)
'' Send byte (may wait for room in buffer)
repeat until (tx_tail <> (tx_head + 1) & $F)
tx_buffer[tx_head] := txbyte
tx_head := (tx_head + 1) & $F
if rxtx_mode & %1000
rx
PUB str(stringptr)
'' Send string
repeat strsize(stringptr)
tx(byte[stringptr++])
PUB dec(value) | i
'' Print a decimal number
if value < 0
-value
tx("-")
i := 1_000_000_000
repeat 10
if value => i
tx(value / i + "0")
value //= i
result~~
elseif result or i == 1
tx("0")
i /= 10
PUB hex(value, digits)
'' Print a hexadecimal number
value <<= (8 - digits) << 2
repeat digits
tx(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
PUB bin(value, digits)
'' Print a binary number
value <<= 32 - digits
repeat digits
tx((value <-= 1) & 1 + "0")
DAT
'***********************************
'* Assembly language serial driver *
'***********************************
org
'
'
' Entry
'
entry mov t1,par 'get structure address
add t1,#4 << 2 'skip past heads and tails
rdlong t2,t1 'get rx_pin
mov rxmask,#1
shl rxmask,t2
add t1,#4 'get tx_pin
rdlong t2,t1
mov txmask,#1
shl txmask,t2
add t1,#4 'get rxtx_mode
rdlong rxtxmode,t1
add t1,#4 'get bit_ticks
rdlong bitticks,t1
add t1,#4 'get buffer_ptr
rdlong rxbuff,t1
mov txbuff,rxbuff
add txbuff,#16
test rxtxmode,#%100 wz 'init tx pin according to mode
test rxtxmode,#%010 wc
if_z_ne_c or outa,txmask
if_z or dira,txmask
mov txcode,#transmit 'initialize ping-pong multitasking
'
'
' Receive
'
receive jmpret rxcode,txcode 'run a chunk of transmit code, then return
test rxtxmode,#%001 wz 'wait for start bit on rx pin
test rxmask,ina wc
if_z_eq_c jmp #receive
mov rxbits,#9 'ready to receive byte
mov rxcnt,bitticks
shr rxcnt,#1
add rxcnt,cnt
:bit add rxcnt,bitticks 'ready next bit period
:wait jmpret rxcode,txcode 'run a chuck of transmit code, then return
mov t1,rxcnt 'check if bit receive period done
sub t1,cnt
cmps t1,#0 wc
if_nc jmp #:wait
test rxmask,ina wc 'receive bit on rx pin
rcr rxdata,#1
djnz rxbits,#:bit
shr rxdata,#32-9 'justify and trim received byte
and rxdata,#$FF
test rxtxmode,#%001 wz 'if rx inverted, invert byte
if_nz xor rxdata,#$FF
rdlong t2,par 'save received byte and inc head
add t2,rxbuff
wrbyte rxdata,t2
sub t2,rxbuff
add t2,#1
and t2,#$0F
wrlong t2,par
jmp #receive 'byte done, receive next byte
'
'
' Transmit
'
transmit jmpret txcode,rxcode 'run a chunk of receive code, then return
mov t1,par 'check for head <> tail
add t1,#2 << 2
rdlong t2,t1
add t1,#1 << 2
rdlong t3,t1
cmp t2,t3 wz
if_z jmp #transmit
add t3,txbuff 'get byte and inc tail
rdbyte txdata,t3
sub t3,txbuff
add t3,#1
and t3,#$0F
wrlong t3,t1
or txdata,#$100 'ready byte to transmit
shl txdata,#2
or txdata,#1
mov txbits,#11
mov txcnt,cnt
:bit test rxtxmode,#%100 wz 'output bit on tx pin according to mode
test rxtxmode,#%010 wc
if_z_and_c xor txdata,#1
shr txdata,#1 wc
if_z muxc outa,txmask
if_nz muxnc dira,txmask
add txcnt,bitticks 'ready next cnt
:wait jmpret txcode,rxcode 'run a chunk of receive code, then return
mov t1,txcnt 'check if bit transmit period done
sub t1,cnt
cmps t1,#0 wc
if_nc jmp #:wait
djnz txbits,#:bit 'another bit to transmit?
jmp #transmit 'byte done, transmit next byte
'
'
' Uninitialized data
'
t1 res 1
t2 res 1
t3 res 1
rxtxmode res 1
bitticks res 1
rxmask res 1
rxbuff res 1
rxdata res 1
rxbits res 1
rxcnt res 1
rxcode res 1
txmask res 1
txbuff res 1
txdata res 1
txbits res 1
txcnt res 1
txcode res 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

@ -1,80 +0,0 @@
SXTVRENDEZVOUS = $8000 - 4
SXKBRENDEZVOUS = SXTVRENDEZVOUS - 4
SDSPIRENDEZVOUS = SXKBRENDEZVOUS - 3 * 4
SXFS2RENDEZVOUS = SDSPIRENDEZVOUS - 4 * 4 ' four rendezvous variables
SXFSRENDEZVOUS = SXFS2RENDEZVOUS - 4 * 4 ' four rendezvous variables
METADATABUFFER = SXFSRENDEZVOUS - 512
_free = ($8000 - METADATABUFFER) / 4
SIZEOFFILESTUFF = 512 + 24
pCommand = SXFSRENDEZVOUS
pParam0 = pCommand+4
pParam1 = pCommand+8
pParam2 = pCommand+12
pub Open( pFilestuff, pFilename, mode ) | filenameBuffer[3], p, i
{{
mode is either "R" or "W".
Returns 0 on success, 1 if file not found (and opening for reading).
}}
return Command( "O", pFilestuff, pFilename, mode )
pub Close( pFilestuff )
Command( "C", pFilestuff, 0, 0 )
pub Read( pFilestuff, pBuffer, nBytes )
{{
Returns number of bytes actually read, -1 at EOF.
}}
long[pParam0] := pFilestuff
long[pParam1] := pBuffer
long[pParam2] := nBytes
long[pCommand] := "R"
repeat while long[pCommand]
if long[pParam0] < -2 ' don't abort for return code -1.
abort long[pParam0]
return long[pParam0]
pub Write( pFilestuff, pBuffer, nBytes )
return Command( "W", pFilestuff, pBuffer, nBytes )
pub Execute( pFilestuff, execmode )
{{
If execmode is non-0, all cogs are stopped except Spin interpreter.
If execmode is 0, running cogs are left running.
}}
Command( "X", pFilestuff, execmode, cogid )
pub Command( cmd, param0, param1, param2 )
long[pParam0] := param0
long[pParam1] := param1
long[pParam2] := param2
long[pCommand] := cmd
repeat while long[pCommand]
if long[pParam0] < 0
abort long[pParam0]
return long[pParam0]
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,370 +0,0 @@
{
_clkfreq = 96_000_000 ' Hybrid
_clkmode = xtal1 + pll16x
tvPins = 24
kbPins = 12
sdPins = 8
}
_clkfreq = 80_000_000 ' Hydra
_clkmode = xtal1 + pll8x
tvPins = 24
kbPins = 13
sdPins = 16
{
Simple command line
2009
April
15 Adding file transfer to/from PC via serial
16 0.02
SendFile bugfix (while blksize == 1024)
Tries to run .bin before .eep now.
June
4 Changing name from cl to sphinx. Converting to use sxfs, sxtv.
15 sxkb; adding c and cl commands
23 Corrected clock mode calculation.
2010
Feb
25 New version number
}
obj
kb: "sxkb"
term: "sxtv"
sxfs: "sxfs"
f: "sxfile"
ser: "fdserial"
con
SXTVRENDEZVOUS = $8000 - 4
SXKBRENDEZVOUS = SXTVRENDEZVOUS - 4
SDSPIRENDEZVOUS = SXKBRENDEZVOUS - 3 * 4
SXFS2RENDEZVOUS = SDSPIRENDEZVOUS - 4 * 4 ' four rendezvous variables
SXFSRENDEZVOUS = SXFS2RENDEZVOUS - 4 * 4 ' four rendezvous variables
METADATABUFFER = SXFSRENDEZVOUS - 512
_free = ($8000 - METADATABUFFER) / 4
pub Main | err, p
if term.start( tvPins, SXTVRENDEZVOUS )
term.str( string("============= Sphinx 100225 ============", 13) )
term.str( string("video @ pin ") )
term.dec( tvPins )
term.str( string(13, "keyboard @ pin ") )
term.dec( kbPins )
term.str( string(13, "SD @ pin ") )
term.dec( sdPins )
term.out( 13 )
sxfs.start( sdPins )
kb.start( kbPins )
repeat
if ina[31] ' USB cable connected?
ser.start( 31, 30, %0000, 19200 )
f.Close
err := \DoIt
if err
if err > 0
term.str( err )
else
term.str( string("Error ") )
term.dec( err )
term.out( 13 )
else
term.str( string("Normal exit") ) ' This never happens
pri DoIt | ch
term.out( ">" )
term.out( "_" )
term.out( 8 )
repeat
if kb.peekkey
EditCmdLine
Execute
term.out( ">" )
term.out( "_" )
term.out( 8 )
if (ch := ser.rxcheck) <> -1
term.out( 8 )
FileTransfer( ch )
term.out( ">" )
term.out( "_" )
term.out( 8 )
con
MAXCMDLINELENGTH = 78 ' some arbitray limit.
CR = $0d
BKSP = $c8
var
byte cmdLine[MAXCMDLINELENGTH+1] ' +1 for null terminator
long cmdLineLength
pri EditCmdLine | key
cmdLineLength~ ' cursor is always at end of command line
repeat
case key := kb.key
$20..$7f:
if cmdLineLength < MAXCMDLINELENGTH
cmdLine[ cmdLineLength++ ] := key
term.out( key )
term.out( "_" )
term.out( 8 )
CR:
term.out( " " )
term.out( 13 )
cmdLine[ cmdLineLength ]~
return true
BKSP:
if cmdLineLength
--cmdLineLength
term.out( " " )
term.out( 8 )
term.out( 8 )
term.out( "_" )
term.out( 8 )
pri FileTransfer( cmd ) | ch, i
if cmd <> "G" and cmd <> "P"
term.out( cmd )
abort string(" -- unrecognized command from PC")
i~
repeat
ch := RxSerByte
if i => FILENAMEBUFFERSIZE
abort string("Filename too long")
filename[i++] := ch
while ch
if cmd == "G"
term.str( string("sending ") )
term.str( @filename )
term.out( 13 )
SendFileToPC
else
term.str( string("receiving ") )
term.str( @filename )
term.out( 13 )
ReceiveFileFromPC
pri SendFileToPC | blksize, i, chksum, b, n
if f.Open( @filename, "R" ) <> 0
term.str( @filename )
abort string(" -- can't open file for reading")
TxSerByte( "A" ) ' ack
n~
repeat
blksize := f.Read( @buffer, 1024 )
if blksize == -1
blksize~
TxSerByte( blksize.byte[0] )
TxSerByte( blksize.byte[1] )
i~
chksum~
repeat blksize
b := buffer[i++]
chksum += b
TxSerByte( b )
n += blksize
if chksum & $ff <> RxSerByte
abort string("Checksum error")
while blksize == 1024
f.Close
term.dec( n )
term.str( string(" bytes sent", 13) )
pri ReceiveFileFromPC | blksize, i, chksum, b, n
if f.Open( @filename, "W" ) <> 0
term.str( @filename )
abort string(" -- can't open file for writing")
TxSerByte( "A" ) ' ack
n~
repeat
blksize~
blksize.byte[0] := RxSerByte
blksize.byte[1] := RxSerByte
if blksize > 1024
abort string("Block size > 1024")
i~
chksum~
repeat blksize
b := RxSerByte
buffer[i++] := b
chksum += b
n += blksize
f.Write( @buffer, blksize )
TxSerByte( chksum )
while blksize == 1024
f.Close
term.dec( n )
term.str( string(" bytes received", 13) )
pri RxSerByte : b
' ser.rx with timeout
b := ser.rxtime( TIMEOUT )
if b == -1
abort string("RxSerByte timed out")
pri TxSerByte( b )
' just for symmetry with RxSerByte
ser.tx( b )
con
TIMEOUT = 500
var
byte buffer[1024]
pri Execute | n, p, q, run, c
c~
ifnot n := ParseCmdLine
return
p := @cmdLine
ToUpper(p)
if run := strcomp( @cmdLine, string("RUN") )
--n
p += strsize(p) + 1
elseif strcomp( @cmdLine, string("C") )
c := 1
--n
p += strsize(p) + 1 ' command arg1 arg2...
elseif strcomp( @cmdLine, string("CL") ) ' run command arg1 arg2...
c := 2 ' c arg1 arg2...
--n ' cl arg1 arg2...
p += strsize(p) + 1
ifnot n
abort string("No file specified")
f.Open( string("args.d8a"), "W" ) ' write args
if c == 0
q := p + strsize(p) + 1 ' for run and plain command, skip first arg (command name)
--n
f.Write( @n, 1 )
repeat n
f.Write( q, strsize(q) + 1 )
q += strsize(q) + 1
else ' for c and cl,
++n ' add extra arg (/c or /l)
f.Write( @n, 1 )
repeat n-1
f.Write( p, strsize(p) + 1 )
p += strsize(p) + 1
if c == 1
f.Write( string("/c"), 3 )
else
f.Write( string("/l"), 3 )
n~
f.Write( @n, 1 ) ' final terminating null
f.Close
if c
if f.Open( string("lex.bin"), "R" ) <> 0
abort string("lex.bin not found")
ser.stop
f.Execute( 0 )
if EndsWith( p, string(".BIN") ) or EndsWith( p, string(".EEP") )
if f.Open( p, "R" ) <> 0
term.str( p )
abort string(" -- not found")
else
if strsize(p) > MAXFILENAMELENGTH - 4
term.str( p )
abort string(" -- filename too long")
bytemove( @filename, p, strsize(p) + 1 )
bytemove( @filename + strsize(p), string(".BIN"), 5 )
if f.Open( @filename, "R" ) <> 0
bytemove( @filename + strsize(p), string(".EEP"), 5 )
if f.Open( @filename, "R" ) <> 0
term.str( p )
abort string(" -- no .bin or .eep found")
ser.stop
f.Execute( run )
pri ToUpper( p )
repeat while byte[p]
if "a" =< byte[p] and byte[p] =< "z"
byte[p] += "A" - "a"
++p
pri EndsWith( p, s )
if strsize(p) < strsize(s)
return false
p += strsize(p) - strsize(s)
repeat while byte[p]
if byte[p++] <> byte[s++]
return false
return true
con
MAXFILENAMELENGTH = 12 ' 8 + . + 3
FILENAMEBUFFERSIZE = MAXFILENAMELENGTH + 1 ' 8 + . + 3 + null
CMDNAMEBUFFERSIZE = 9 ' 8 + null
var
byte filename[MAXFILENAMELENGTH+1] ' 8 + . + 3 + null
pri ParseCmdLine : n | pSrc, pDst, state
{{
Converts cmdLine from " ab de fg \" to "ab\de\fg\" ('\' = null).
Returns # of "words".
}}
{
state whitespace null other char
0 ++pSrc; append \0; quit append char; => 1
1 append \0; ++n; => 0 append \0; ++n; quit append char;
}
pSrc := @cmdLine
pDst := @cmdLine
state~
repeat
if state == 0
if byte[pSrc] == " "
++pSrc
elseif byte[pSrc] == 0
byte[pDst++]~
quit
else
byte[pDst++] := byte[pSrc++]
state := 1
elseif state == 1
if byte[pSrc] == " "
++pSrc
byte[pDst++]~
++n
state~
elseif byte[pSrc] == 0
byte[pDst++]~
++n
quit
else
byte[pDst++] := byte[pSrc++]
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,98 +0,0 @@
obj
isxfs: "isxfs"
var
long filestuff[isxfs#SIZEOFFILESTUFF / 4]
pub Open( pFilename, mode )
return isxfs.Open( @filestuff, pFilename, mode )
pub Close
isxfs.Close( @filestuff )
pub Read( ptr, n )
return isxfs.Read( @filestuff, ptr, n )
pub Write( ptr, n )
return isxfs.Write( @filestuff, ptr, n )
pub Length
{{
Only valid for files opened for reading.
}}
return long[@filestuff]
pub Execute( mode )
isxfs.Execute( @filestuff, mode )
isxfs.Close( @filestuff ) ' we only get here if Execute fails for some reason.
pub ReadString( p, MAXLENGTH ) | ch
repeat MAXLENGTH + 1
ch := ReadByte
ifnot byte[p++] := ch
return
abort string("ReadString: string too long")
pub ReadStringUpperCase( p, MAXLENGTH ) | ch
repeat MAXLENGTH + 1
ch := ReadByte
if "a" =< ch and ch =< "z"
ch -= constant("a" - "A")
ifnot byte[p++] := ch
return
abort string("ReadStringUpperCase: string too long")
pub WriteString( p )
Write( p, strsize(p) + 1 )
pub ReadNumber | ch
repeat
ifnot ch := ReadByte
return
if ch < "0" or ch > "9"
abort string("ReadNumber: non-numeric character")
result := result * 10 + ch - "0"
pub ReadByte : ch
Read( @ch, 1 )
pub WriteByte( b )
Write( @b, 1 )
pub ReadWord
return ReadByte + (ReadByte << 8)
pub WriteWord( w )
Write( @w, 2 )
pub ReadLong
return ReadByte + (ReadByte << 8) + (ReadByte << 16) + (ReadByte << 24)
pub WriteLong( l )
Write( @l, 4 )
pub SkipBytes( n )
repeat while n => 32768
Read( $8000, 32768 )
n -= 32768
Read( $8000, n )
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,874 +0,0 @@
' 2010-02-23 fixed duplicate file bug
SXTVRENDEZVOUS = $8000 - 4
SXKBRENDEZVOUS = SXTVRENDEZVOUS - 4
SDSPIRENDEZVOUS = SXKBRENDEZVOUS - 3 * 4
SXFS2RENDEZVOUS = SDSPIRENDEZVOUS - 4 * 4 ' four rendezvous variables
SXFSRENDEZVOUS = SXFS2RENDEZVOUS - 4 * 4 ' four rendezvous variables
METADATABUFFER = SXFSRENDEZVOUS - 512
_free = ($8000 - METADATABUFFER) / 4
{
sxfsrendezvous sdspirendezvous
--------+ +--------+ +-------+
| <===> command <===> | | <=====> command <=====> | |
Spin | | | | |
routines| <===> param0 <====> | SXFS | <=====> param <=====> | SDSPI |
| | cog | | cog |
| ----> param1 -----> | | ------> blockno ------> | |
| | | +-------+
| ----> param2 -----> | |
--------+ | | sxfs2rendezvous
| | +-------+
| | <====> command <======> | |
| | | | <==> (sxfsrendezvous)
| | <====> param0 <=======> | SXFS2 |
| | | cog | <==> (sdspirendezvous)
| | | |
+--------+ +-------+
SXFS cog handles file reading: open, read, close.
SXFS2 cog, under SXFS's direction, handles execute and file writing: write, close.
SDSPI cog handles SD card sector reading and writing.
SXFS cog communicates with main program via sxfsrendezvous and Spin interface routines.
SXFS cog communicates with SXFS2 cog via sxfs2rendezvous.
SXFS cog communicates with SDSPI cog via sdspirendezvous.
-1: eof, general error
-100: bad command
-101: not FAT16
-102: file not found
-104: bad mode
-106: file not closed
-107: directory full
-109: file not properly opened
-110: FAT full.
-113: bad filename
}
obj
sxfs2: "sxfs2"
sdspi : "sxsdspiq"
pub Start( sdPin ) | pbrSector
' Determine if sxfs cog and, by association, sxfs2 and sdspi cogs, are already running.
' If not, start them up.
' Returns true if the cogs needed to be started, false if the cogs were already running.
ifnot Ping
result~~
' start sdspi cog and initialize SD card
long[pSdspiCommand] := "I"
sdspi.start( sdPin, pSdspiCommand )
repeat while long[pSdspiCommand]
if long[pSdspiParam]
abort long[pSdspiParam]
pbrSector := ReadPbr
' start sxfs cog
long[pCommand] := "?"
if cognew( @sxfsEntry, 0 ) < 0
abort -1
repeat while long[pCommand]
' start sxfs2 cog
sxfs2.Start( pbrSector )
pri ReadPbr : pbrSector
repeat
sdspi.readblock( pbrSector, pMetadataBuffer )
if bytecompare( pMetadataBuffer+$36, string("FAT16"), 5 )
quit
if pbrSector
abort -101 ' not FAT16
pbrSector := PeekL( pMetadataBuffer + $1c6 )
bytesPerSector := PeekW( pMetadataBuffer + $0b )
sectorsPerCluster := byte[pMetadataBuffer][$0d]
clusterShift := >| sectorsPerCluster - 1
reservedSectors := PeekW( pMetadataBuffer + $0e )
numberOfFats := byte[pMetadataBuffer][$10]
sectorsPerFat := PeekW( pMetadataBuffer + $16 )
RootDirEntries := PeekW( pMetadataBuffer + $11 )
fatSector0 := pbrSector + reservedSectors
dirSector0 := fatSector0 + numberOfFats * sectorsPerFat
dataSector0 := dirSector0 + rootDirEntries >> 4
pri bytecompare( _p, _q, _n )
repeat _n
if byte[_p++] <> byte[_q++]
return
return true
pri PeekW( a )
return byte[a++] + byte[a] << 8
pri PeekL( a )
return byte[a++] + byte[a++] << 8 + byte[a++] << 16 + byte[a] << 24
pri Ping
{{
returns 1 if bmfs cog is active, 0 otherwise.
}}
long[pCommand] := "?"
if long[pCommand]
return 0
else
return 1
con
SECTORSIZE = 512
SECTORSHIFT = 9
DIRSIZE = 32
con
' filestuff definitions
' filestuff must be long-aligned
{ long } _length = 0
{ long } _leftInFile = 4
{ long } _sopDir = 8 ' sector/offset "pointer" to directory entry
{ long } _sopTail = 12 ' sector/offset "pointer" to last cluster# in FAT chain
{ word } _cluster = 16
{ word } _sector = 18 ' sector# within cluster; ranges from 0 to sectorsPerCluster-1
{ word } _bp = 20 ' byte pointer (actually an index into the sector buffer); range [0..511]
{ word } _mode = 22 ' 0: closed; "R": open for reading; "W": open for writing.
_buffer = 24 ' 512-byte buffer starts here
SIZEOFFILESTUFF = SECTORSIZE + 24
dat
{{
command param0 param1 param2
"?" -- -- -- Do nothing, but acknowledge to indicate that sxfs cog is active.
"O" filestuff filename mode Open a file, populate filestuff fields. mode is "R" or "W".
"R" filestuff buffer num Reads num bytes into buffer from file specified by filestuff.
"W" filestuff buffer num Writes num bytes from buffer to file specified by filestuff.
"C" filestuff -- -- Closes file specified by filestuff.
"X" filestuff execmode cog Executes file.
}}
org 0
SXFSEntry
AckNoReturnCode
mov temp, #0 ' clear return code
AckReturnCode ' enter here with temp = return code
wrlong temp, pParam0
mov temp, #0
wrlong temp, pCommand ' clear command to signal operation complete.
:ready ' wait for new command
rdlong temp, pCommand wz
if_z jmp #:ready
cmp temp, #"?" wz
if_e jmp #AckNoReturnCode
cmp temp, #"O" wz
if_e jmp #Open
cmp temp, #"R" wz
if_e jmp #Read
cmp temp, #"W" wz
if_e jmp #Write
cmp temp, #"C" wz
if_e jmp #Close
cmp temp, #"X" wz
if_e jmp #Execute
' else
neg temp, #100 ' -100: bad command
jmp #AckReturnCode
'*********************************************************************************************************************
'* *
'* Open stuff *
'* *
'*********************************************************************************************************************
Open ' ( param0 = pFilestuff, param1 = pFilename, param2 = mode )
{
Return value:
File found File not found Error
mode = "R" 0 1 < 0
mode = "W" 0 0 < 0
Mode W will either open an existing file or create a new file.
}
rdword pFilestuff, pParam0
rdword pFilename, pParam1
mov p, pFilestuff
add p, #_mode
rdword temp, p wz
if_nz neg temp, #106 ' -106: file not closed
if_nz jmp #AckReturnCode
call #MassageFilename
rdword temp, pParam2
cmp temp, #"R" wz
if_e jmp #:openForReading
cmp temp, #"W" wz
if_e jmp #:openForWriting
neg temp, #104 ' -104: bad mode
jmp #AckReturnCode
:openForReading
call #FindFile
mov p, pFilestuff
add p, #_sopDir ' pFilestuff->sopDir = 0 => file not found
rdlong temp, p wz
if_z mov temp, #1 ' return 1 to indicate file not found
if_z jmp #AckReturnCode
mov p, sop ' sop sector is still in memory
and p, #$1ff
add p, pMetadataBuffer
add p, #$1a ' point to cluster information
rdword temp, p
mov q, pFilestuff
add q, #_cluster
wrword temp, q
add p, #2 ' point to length information
rdlong temp, p
sub q, #_cluster-_length ' q points to length
wrlong temp, q
add q, #_leftInFile-_length ' q points to leftInFile
wrlong temp, q
add q, #_sector-_leftInFile ' q points to sector
mov temp, #0
wrword temp, q
add q, #_bp-_sector ' q points to bp
wrword k512, q
mov p, pFilestuff
add p, #_mode
mov temp, #"R"
wrword temp, p ' save mode
jmp #AckNoReturnCode
:openForWriting
mov sop, dirSector0 ' sop "points" to directory entries:
shl sop, #9 ' incremented by 32 each time through the loop.
mov sopDir, #0 ' sopDir "points" to the directory entry
' that will be used or reused for the file being opened.
mov i, rootDirEntries
:forEachDirEntry ' Loop through the directory entries, looking for a deleted entry,
' an empty entry, or an entry that matches pFilename.
mov sector, sop
shr sector, #9
call #ReadMetadataSector
mov p, sop
and p, #$1ff
add p, pMetadataBuffer ' p points to the current directory entry
add p, #$0b
rdbyte temp, p ' p[$0b] = attribute byte
sub p, #$0b
and temp, #$02 wz ' If hidden,
if_nz jmp #:next ' skip. Hidden dir entries include long name entries.
rdbyte temp, p ' p[0]
cmp temp, #$e5 wz ' = $e5? (deleted directory entry?)
if_e cmp sopDir, #0 wz ' save pointer in sopDir (just the first time)
if_e mov sopDir, sop
tjz temp, #:quit ' empty directory entry? We're done
mov q, pFilename ' matching filename? Done.
mov n, #11
call #ByteComp
if_e mov sopDir, sop ' 2010-02-23 duh
if_e jmp #:quit
:next
add sop, #DIRSIZE
djnz i, #:forEachDirEntry
:quit
cmp i, #0 wz ' did we go through the whole directory?
if_z neg temp, #107 ' -107: directory full
if_z jmp #AckReturnCode
cmp sopDir, #0 wz ' if sopDir hasn't been set yet,
if_e mov sopDir, sop ' set it to sop.
mov p, pFilestuff
add p, #_sopDir
wrlong sopDir, p ' pFilestuff->sopDir := sopDir
add p, #_sopTail-_sopDir
add sopDir, #$1a
wrlong sopDir, p ' pFilestuff->sopTail := sopDir + $1a
' (points to directory entry's cluster field).
mov sector, sopDir
shr sector, #9 ' Get the chosen directory entry into memory
call #ReadMetadataSector ' if it isn't already.
mov p, sopDir ' Recall that sopDir was changed
and p, #$1ff ' to point to the cluster field,
add p, pMetadataBuffer ' so p now points to the cluster field in the buffer.
rdword cluster, p ' Save the cluster field.
mov temp, #0
wrword temp, p ' Zero the cluster field.
sub p, #$1a ' Point to start of directory entry
rdbyte temp, p ' Check to see if this was a deleted dir entry.
cmp temp, #$e5 wz ' If it was, we definitely do not want to zero the
if_e mov cluster, #0 ' cluster chain, so set cluster to 0.
mov q, pFilename ' Store the filename in the directory entry.
mov n, #11
call #ByteCopy
mov temp, #$20 ' Set the attribute byte (immediately following name)
wrbyte temp, p
add p, #$10-$0b ' Point to creation date.
mov temp, aDate ' 2001/01/01
wrword temp, p
add p, #$12-$10 ' Point to last access date.
wrword temp, p
add p, #$18-$12 ' Point to last update date.
wrword temp, p
mov dirty, #1 ' We've modified metadata.
tjz cluster, #:done
:forEachClusterInList ' Traverse the cluster list and zero each link.
mov sector, cluster
shr sector, #8
add sector, fatSector0
call #ReadMetadataSector ' Read FAT sector for current cluster
mov p, cluster
and p, #$ff
shl p, #1
add p, pMetadataBuffer ' Point p at cluster entry in FAT
rdword cluster, p ' Get next cluster link.
cmp cluster, #1 wc, wz ' Break if cluster <= 1
if_be jmp #:done
mov temp, #0
wrword temp, p ' Zero the cluster link.
mov dirty, #1 ' We've modified metadata.
cmp cluster, kfff0 wc, wz ' repeat unless new cluster >= $fff0
if_b jmp #:forEachClusterInList
:done
mov p, pFilestuff
add p, #_sector
mov temp, #0
wrword temp, p ' pFilestuff->sector := 0
add p, #_bp-_sector
wrword temp, p ' pFilestuff->bp := 0
mov p, pFilestuff
mov temp, #0
wrlong temp, p ' pFilestuff->length := 0
add p, #_mode
mov temp, #"W"
wrword temp, p ' save mode
jmp #AckNoReturnCode
MassageFilename
{
Take the null-terminated 8.3 filename pointed to by pFilename,
move it into memory starting at pFilestuff->buffer and expand it to 11 characters;
change pFilename to point to the expanded filename.
}
mov p, pFilestuff
add p, #_buffer
mov q, p
add p, #1
mov temp, #" "
wrbyte temp, q
mov n, #10
call #ByteCopy
mov q, pFilename ' q is src
mov p, pFilestuff ' p is dst
add p, #_buffer
mov i, #9 ' Copy up to 8 chars (stop at . or null).
:upTo8
rdbyte temp, q
add q, #1
tjz temp, #:done
cmp temp, #"." wz
if_z jmp #:dot
call #ValidateChar
wrbyte temp, p
add p, #1
djnz i, #:upTo8
' If we fall through, we've copied 9 characters (tsk tsk).
neg temp, #113 ' -113: bad filename
jmp #AckReturnCode
:dot
mov p, pFilestuff
add p, #_buffer+8
mov i, #4 ' Copy up to 3 chars (stop at null).
:upTo3
rdbyte temp, q
add q, #1
tjz temp, #:done
call #ValidateChar
wrbyte temp, p
add p, #1
djnz i, #:upTo3
' If we fall through, we've copied 4 characters (tsk tsk ).
neg temp, #113 ' -113: bad filename
jmp #AckReturnCode
:done
mov pFilename, pFilestuff
add pFilename, #_buffer
MassageFilename_ret ret
FindFile
{
pFilename points to 11-character buffer (e.g. "BLAH TXT").
pFilestuff points to a filestuff structure.
Return value:
If file is found, pFilestuff->sopDir is disk address of directory entry.
If file is not found, pFilestuff->sopDir is 0.
}
mov sop, dirSector0 ' sop starts at dirSector0<<9, counts up by DIRSIZE
shl sop, #SECTORSHIFT
mov i, rootDirEntries
:loop
mov sector, sop
shr sector, #9
call #readMetadataSector
mov p, sop
and p, #$1ff
add p, pMetadataBuffer
rdbyte temp, p wz
if_z jmp #:notfound
add p, #$0b
rdbyte temp, p ' p[$0b] = attribute byte
sub p, #$0b
and temp, #$02 wz ' If hidden,
if_nz jmp #:next ' skip. Hidden dir entries include long name entries.
mov q, pFilename
mov n, #11
call #ByteComp
if_e jmp #:found
:next
add sop, #DIRSIZE
djnz i, #:loop
:notfound
mov sop, #0
:found
mov p, pFilestuff
add p, #_sopDir
wrlong sop, p
FindFile_ret ret
'*********************************************************************************************************************
'* *
'* Read stuff *
'* *
'*********************************************************************************************************************
Read ' ( param0 = pFilestuff, param1 = ptr, param2 = n )
{
Read n bytes from file described by pIoblock into memory starting at p.
Returns number of bytes actually read or -1 if attempting to read past EOF.
}
rdlong pFilestuff, pParam0
rdlong destPtr, pParam1
rdlong nBytes, pParam2
mov p, pFilestuff ' Verify that file was opened for reading.
add p, #_mode
rdword temp, p
cmp temp, #"R" wz
if_ne neg temp, #109 ' -109: file not properly opened
if_ne jmp #AckReturnCode
sub p, #_mode-_leftInFile
' Adjust nBytes depending on how much is left to read in file.
' E.g. if we're 10 bytes from EOF and we try to read 15 bytes,
' just read 10. If we're at EOF and try to read 15 bytes, return -1.
rdlong temp, p
max nBytes, temp ' nBytes is lesser of nBytes and leftInFile
tjnz temp, #:x
neg temp, #1 ' -1: eof
jmp #ackReturnCode
:x
mov retcode, nBytes
:while
mov leftInSector, k512 ' leftInSector = 512 - pFilestuff->bp
mov p, pFilestuff
add p, #_bp
rdword temp, p ' temp = bp
sub leftInSector, temp
cmp leftInSector, nBytes wc, wz
if_ae jmp #:endwhile
mov p, destPtr
mov q, pFilestuff
add q, #_buffer ' q points to buffer area
add q, temp ' offset by bp (= temp)
mov n, leftInSector
call #ByteCopy ' bytemove( p, q, n )
add destPtr, leftInSector ' destPtr += leftInSector
sub nBytes, leftInSector ' nBytes -= leftInSector
mov p, pFilestuff ' long[pIoblock+_leftInFile] -= leftInSector
add p, #_leftInFile
rdlong temp, p
sub temp, leftInSector
wrlong temp, p
' sdspi.readblock( dataSector0 + (word[pFilestuff+_cluster] - 2) << clusterShift + word[pFilestuff+_sector], pFilestuff+_buffer )
add p, #_cluster-_leftInFile
rdword temp, p ' temp = (cluster
sub temp, #2 ' - 2)
shl temp, clusterShift ' << clusterShift
add temp, dataSector0 ' + dataSector0
add p, #_sector-_cluster
rdword temp1, p
add temp, temp1 ' + cluster
wrlong temp, pSdspiBlockno ' Prepare to read sector
add p, #_buffer-_sector
wrlong p, pSdspiParam
mov temp, #"R"
call #SdspiCommand
' if ++word[pFilestuff+_sector] == sectorsPerCluster
mov p, pFilestuff
add p, #_sector
rdword temp, p
add temp, #1
wrword temp, p
cmp temp, sectorsPerCluster wz
if_ne jmp #:y
' word[pIoblock+_sector]~
mov temp, #0
wrword temp, p
' word[pFilestuff+_cluster] := NextCluster( word[pFilestuff+_cluster] )
sub p, #_sector-_cluster
rdword cluster, p
call #NextCluster '( cluster )
mov p, pFilestuff
add p, #_cluster
wrword cluster, p
:y
' word[pFilestuff+_bp]~
mov p, pFilestuff
add p, #_bp
mov temp, #0
wrword temp, p
jmp #:while
:endwhile
' bytemove( destPtr, pIoblock + word[pIoblock+_bp], n )
mov p, destPtr
mov q, pFilestuff
add q, #_bp
rdword temp, q
add q, #_buffer-_bp
add q, temp
mov n, nBytes
call #ByteCopy
' long[pIoblock+_leftInFile] -= n
mov p, pFilestuff
add p, #_leftInFile
rdlong temp, p
sub temp, nBytes
wrlong temp, p
' word[pIoblock+_bp] += n
add p, #_bp-_leftInFile
rdword temp, p
add temp, nBytes
wrword temp, p
mov temp, retcode
jmp #AckReturnCode
NextCluster ' ( cluster )
{
Given cluster, determines next cluster in FAT.
Result in cluster.
}
cmp cluster, #1 wc, wz
if_be jmp #NextCluster_ret
cmp cluster, kfff0 wc, wz
if_ae jmp #NextCluster_ret
mov sector, cluster
shr sector, #8
add sector, fatSector0
call #ReadMetadataSector
mov p, cluster
and p, #$ff
shl p, #1
add p, pMetadataBuffer
rdword cluster, p
NextCluster_ret ret
kfff0 long $fff0
'*********************************************************************************************************************
'* *
'* Write stuff *
'* *
'*********************************************************************************************************************
Write
rdlong p, pParam0 ' p = pFilestuff
add p, #_mode ' Verify that file was opened for writing.
rdword temp, p
cmp temp, #"W" wz
if_ne neg temp, #109 ' -109: file not properly opened
if_ne jmp #AckReturnCode
call #FlushMetadataSector
neg currentsector, #1 ' invalidate current sector 'cuz we're about to hand the reins
' to sxfs2 cog.
mov temp, #"W"
wrlong temp, pSxfs2Command
:wait rdlong temp, pSxfs2Command wz
if_nz jmp #:wait
rdlong temp, pSxfs2Param
jmp #AckReturnCode
'*********************************************************************************************************************
'* *
'* Close stuff *
'* *
'*********************************************************************************************************************
Close ' ( param0 = pFilestuff )
rdlong pFilestuff, pParam0
mov p, pFilestuff
add p, #_mode
rdword temp, p
cmp temp, #"W" wz
if_e jmp #:closew
' Files opened in mode "W" need special closing code, but for mode "R" or anything else
' (like file not even open) we can just do this:
mov temp, #0
wrword temp, p ' clear mode
jmp #AckNoReturnCode ' and we're done
:closew
mov temp, #0 ' clear mode
wrword temp, p
call #FlushMetadataSector
neg currentsector, #1 ' invalidate current sector 'cuz we're about to hand the reins
' to sxfs2 cog.
mov temp, #"C"
wrlong temp, pSxfs2Command
:wait rdlong temp, pSxfs2Command wz
if_nz jmp #:wait
rdlong temp, pSxfs2Param
jmp #AckReturnCode
'*********************************************************************************************************************
'* *
'* Execute stuff *
'* *
'*********************************************************************************************************************
Execute ' ( pFilestuff, execmode, cogid )
call #FlushMetadataSector
neg currentsector, #1 ' invalidate current sector 'cuz we're about to hand the reins
' to sxfs2 cog.
mov temp, #"X"
wrlong temp, pSxfs2Command
:wait rdlong temp, pSxfs2Command wz
if_nz jmp #:wait
rdlong temp, pSxfs2Param
jmp #AckReturnCode
'*********************************************************************************************************************
'* *
'* Utility stuff *
'* *
'*********************************************************************************************************************
ByteCopy ' ( p, q, n )
tjz n, #ByteCopy_ret
:loop rdbyte temp, q
add q, #1
wrbyte temp, p
add p, #1
djnz n, #:loop
ByteCopy_ret ret
ByteComp ' ( p, q, n )
{
Compares j bytes starting at p and q.
Returns Z if they match, NZ if they differ.
Destroys p, q, and j.
}
rdbyte temp, p
add p, #1
rdbyte temp1, q
add q, #1
cmp temp, temp1 wz
if_z djnz n, #ByteComp
ByteComp_ret ret
ValidateChar
{
Make sure that temp is a valid filename character (for our purposes, 0-9, A-Z, _).
}
cmp temp, #"a" wc, wz
if_b jmp #:notLowerCase
cmp temp, #"z" wc, wz
if_a jmp #:notLowerCase
sub temp, #"a"-"A" ' convert to upper-case
jmp #ValidateChar_ret
:notLowerCase
cmp temp, #"A" wc, wz
if_b jmp #:notAlpha
cmp temp, #"Z" wc, wz
if_be jmp #ValidateChar_ret
:notAlpha
cmp temp, #"0" wc, wz
if_b jmp #:notNumeric
cmp temp, #"9" wc, wz
if_be jmp #ValidateChar_ret
:notNumeric
cmp temp, #"_" wz
if_e jmp #ValidateChar_ret
mov temp, #113 ' -113: bad filename
jmp #AckReturnCode
ValidateChar_ret ret
ReadMetadataSector ' ( sector )
call #FlushMetadataSector
cmp sector, currentSector wz
if_e jmp #ReadMetadataSector_ret
wrlong pMetadataBuffer, pSdspiParam
wrlong sector, pSdspiBlockno
mov currentSector, sector
mov temp, #"R"
call #SdspiCommand
ReadMetadataSector_ret ret
FlushMetadataSector
tjz dirty, #FlushMetadataSector_ret
mov dirty, #0
' write current sector
wrlong pMetadataBuffer, pSdspiParam
wrlong currentSector, pSdspiBlockno
mov temp, #"W"
call #SdspiCommand
FlushMetadataSector_ret ret
SdspiCommand
wrlong temp, pSdspiCommand
:wait
rdlong temp, pSdspiCommand wz
if_nz jmp #:wait
rdlong temp, pSdspiParam wz
if_nz jmp #AckReturnCode
SdspiCommand_ret ret
kFAT1 long "F" + "A"<<8 + "T"<<16 + "1"<<24
k512 long 512
dirty long 0
currentSector long -1
aDate long $2a21
pMetadataBuffer long METADATABUFFER
pCommand long SXFSRENDEZVOUS+0
pParam0 long SXFSRENDEZVOUS+4
pParam1 long SXFSRENDEZVOUS+8
pParam2 long SXFSRENDEZVOUS+12
pSdspiCommand long SDSPIRENDEZVOUS+0
pSdspiParam long SDSPIRENDEZVOUS+4
pSdspiBlockno long SDSPIRENDEZVOUS+8
pSxfs2Command long SXFS2RENDEZVOUS+0
pSxfs2Param long SXFS2RENDEZVOUS+4
bytesPerSector long 0
sectorsPerCluster long 0
clusterShift long 0
reservedSectors long 0
numberOfFats long 0
sectorsPerFat long 0
rootDirEntries long 0
fatSector0 long 0
dirSector0 long 0
dataSector0 long 0
temp res 1
temp1 res 1
i res 1
j res 1
n res 1
p res 1
q res 1
sop res 1
byte4 res 0
sopDir res 1
sector res 1
cluster res 1
pFilename res 1
pFilestuff res 1
destPtr res 1
nBytes res 1
leftInFile res 1
leftInSector res 1
retcode res 1
fit
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,529 +0,0 @@
SXTVRENDEZVOUS = $8000 - 4
RESERVED = SXTVRENDEZVOUS - 4
SDSPIRENDEZVOUS = RESERVED - 3 * 4
SXFS2RENDEZVOUS = SDSPIRENDEZVOUS - 4 * 4 ' four rendezvous variables
SXFSRENDEZVOUS = SXFS2RENDEZVOUS - 4 * 4 ' four rendezvous variables
METADATABUFFER = SXFSRENDEZVOUS - 512
_free = ($8000 - METADATABUFFER) / 4
con
SECTORSIZE = 512
' filestuff definitions
' filestuff must be long-aligned
{ long } _length = 0
{ long } _leftInFile = 4
{ long } _sopDir = 8 ' sector/offset "pointer" to directory entry
{ long } _sopTail = 12 ' sector/offset "pointer" to last cluster# in FAT chain
{ word } _cluster = 16
{ word } _sector = 18 ' sector# within cluster; ranges from 0 to sectorsPerCluster-1
{ word } _bp = 20 ' byte pointer (actually an index into the sector buffer); range [0..511]
{ word } _mode = 22 ' 0: closed; "R": open for reading; "W": open for writing.
_buffer = 24 ' 512-byte buffer starts here
SIZEOFFILESTUFF = SECTORSIZE + 24
pub Start( pbrSector )
bytesPerSector := PeekW( pMetadataBuffer + $0b )
sectorsPerCluster := byte[pMetadataBuffer][$0d]
clusterShift := >| sectorsPerCluster - 1
reservedSectors := PeekW( pMetadataBuffer + $0e )
numberOfFats := byte[pMetadataBuffer][$10]
sectorsPerFat := PeekW( pMetadataBuffer + $16 )
RootDirEntries := PeekW( pMetadataBuffer + $11 )
fatSector0 := pbrSector + reservedSectors
dirSector0 := fatSector0 + numberOfFats * sectorsPerFat
dataSector0 := dirSector0 + rootDirEntries >> 4
' start sxfs2 cog
long[pCommand] := "?"
if cognew( @Sxfs2Entry, 0 ) < 0
abort -1
repeat while long[pCommand]
pri PeekW( a )
return byte[a++] + byte[a] << 8
pri PeekL( a )
return byte[a++] + byte[a++] << 8 + byte[a++] << 16 + byte[a] << 24
dat
org 0
Sxfs2Entry
AckNoReturnCode
mov temp, #0 ' clear return code
AckReturnCode ' enter here with temp = return code
wrlong temp, pParam
mov temp, #0
wrlong temp, pCommand ' clear command to signal operation complete.
mov dirty, temp ' Ensure that metatdata is flushed before coming here.
neg temp, #1
mov currentSector, temp
:ready ' wait for new command
rdlong temp, pCommand wz
if_z jmp #:ready
cmp temp, #"?" wz
if_e jmp #AckNoReturnCode
cmp temp, #"W" wz
if_e jmp #Write
cmp temp, #"C" wz
if_e jmp #Close
cmp temp, #"X" wz
if_e jmp #Execute
' else
neg temp, #100 ' return code -100 : bad command
jmp #AckReturnCode
'*********************************************************************************************************************
'* *
'* Write stuff *
'* *
'*********************************************************************************************************************
Write ' ( pFilestuff, ptr, n )
rdlong pFilestuff, pSxfsParam0
rdlong srcPtr, pSxfsParam1
rdlong nBytes, pSxfsParam2
mov retcode, nBytes
mov p, pFilestuff ' long[ pFilestuff+_length ] += n
'add p, #_length (unnecessary cuz _length = 0)
rdlong temp, p
add temp, nBytes
wrlong temp, p
' repeat while (leftInSector := SECTORSIZE - word[pIoblock+_bp]) < n
:while
mov p, pFilestuff
add p, #_bp ' p points to pFilestuff->bp
mov leftInSector, k512
rdword temp, p ' temp = pFilestuff->bp
sub leftInSector, temp
cmp leftInSector, nBytes wc, wz
if_ae jmp #:done
' bytemove( pFilestuff + _buffer + word[pFilestuff+_bp], ptr, leftInSector )
mov p, pFilestuff
add p, #_buffer
add p, temp ' p now points bp bytes into buffer.
mov q, srcPtr
mov n, leftInSector
call #ByteCopy
' ptr += leftInSector
add srcPtr, leftInSector ' advance the source pointer by #bytes written.
' n -= leftInSector
sub nBytes, leftInSector ' decrease #bytes to write by #bytes written.
' WriteNextSector( pIoblock )
call #WriteNextSector
jmp #:while
:done
' bytemove( pFilestuff + _buffer + word[pIoblock+_bp], ptr, n )
mov p, pFilestuff
add p, #_buffer
add p, temp ' temp = pFilestuff->bp
mov q, srcPtr
mov n, nBytes
call #ByteCopy
' word[pFilestuff+_bp] += n
mov p, pFilestuff
add p, #_bp
rdword temp, p
add temp, nBytes ' advance bp by #bytes written.
wrword temp, p
call #FlushMetadataSector
mov temp, retcode
jmp #AckReturnCode
WriteNextSector
mov p, pFilestuff
add p, #_sector
rdword temp, p wz
if_nz jmp #:writeSector ' sector# <> 0? Write that sector.
' Writing sector 0 implies that we're starting a new cluster, so find an empty slot in the FAT
mov cluster, #0
mov sector, fatSector0
mov i, sectorsPerFat
:forEachFatSector
call #ReadMetadataSector
mov p, pMetadataBuffer
mov j, #256
:forEachSlotInSector
rdword temp, p wz ' examine current slot
if_z jmp #:foundEmptySlot
add p, #2
add cluster, #1
djnz j, #:forEachSlotInSector
add sector, #1
djnz i, #:forEachFatSector
neg temp, #110 ' -110: FAT full.
jmp #AckReturnCode
:foundEmptySlot
neg temp, #1
wrword temp, p ' Claim empty slot by writing $ffff.
mov dirty, #1 ' We've modified metadata.
mov sop, sector
shl sop, #9
sub p, pMetadataBuffer
add sop, p ' sop "points" to slot.
mov p, pFilestuff
add p, #_cluster
wrword cluster, p ' save cluster# in pFilestuff->cluster
sub p, #_cluster-_sopTail ' p points to pFilestuff->sopTail
rdlong sopTail, p ' get "pointer" to end of cluster list.
mov sector, sopTail ' Read the sector that sopTail "points" to.
shr sector, #9
call #ReadMetadataSector
and sopTail, #$1ff
add sopTail, pMetadataBuffer ' Use sopTail as pointer into buffer.
wrword cluster, sopTail ' Now the word pointed to by pFilestuff->sopTail
' is updated with the new cluster#.
mov dirty, #1
wrlong sop, p ' p is still pointing to pFilestuff->sopTail so
' update pFilestuff->sopTail to point to new tail.
:writeSector
mov p, pFilestuff
add p, #_cluster ' p points to pFilestuff->cluster
rdword i, p ' using i for sector#
sub i, #2
shl i, clusterShift
add i, dataSector0 ' At this point, i is the first sector of the cluster.
add p, #_sector-_cluster ' p points to pFilestuff->sector
rdword temp, p
add i, temp ' Now i is the correct sector of the cluster.
add temp, #1
wrword temp, p ' Increment pFilestuff->sector
cmp temp, sectorsPerCluster wz
mov temp, #0 ' if pFilestuff->sector = sectorsPerCluster,
if_e wrword temp, p ' pFilestuff->sector := 0.
add p, #_bp-_sector ' p points to pFilestuff->bp
wrword temp, p ' pFilestuff->bp = 0.
wrlong i, pSdspiBlockno
add p, #_buffer-_bp
wrlong p, pSdspiParam
mov temp, #"W"
call #SdspiCommand
WriteNextSector_ret ret
'*********************************************************************************************************************
'* *
'* Close stuff *
'* *
'*********************************************************************************************************************
Close ' ( pFilestuff )
rdlong pFilestuff, pSxfsParam0
mov p, pFilestuff
add p, #_bp
rdword temp, p wz ' If there's stuff waiting to be written
if_nz call #WriteNextSector ' (i.e. bp <> 0), write it.
mov p, pFilestuff
add p, #_sopDir
rdlong sop, p ' sop "points" to directory entry.
mov sector, sop
shr sector, #9
call #ReadMetadataSector ' We want to update metadata length info.
and sop, #$1ff
add sop, pMetadataBuffer
add sop, #$1c ' sop points to length in metadata buffer.
mov p, pFilestuff ' p points to pFilestuff->length.
rdlong temp, p
wrlong temp, sop ' store length in metadata.
mov dirty, #1
call #FlushMetadataSector
jmp #AckNoReturnCode
'*********************************************************************************************************************
'* *
'* Execute stuff *
'* *
'*********************************************************************************************************************
Execute ' ( pFilestuff, execmode, cogid )
{
Loads 63 sectors from file and executes. Requires that the file be contiguous on the SD card,
which is generally accomplished by formatting the card with cluster size >= 32k.
This reads 63 sectors instead of 64 to avoid writing junk into the rendezvous areas.
It is conceivable that some executable files will not run because of this.
This routine does not handle clock speed changes.
If execmode is 0, start Spin interpreter in cog specified by cogid.
If execmode is 1, start Spin interpreter in cog specified by cogid and stop all other cogs.
}
call #FlushMetadataSector ' just in case
neg currentsector, #1 ' invalidate current sector 'cuz metadata buffer is about to be overwritten
rdlong pFilestuff, pSxfsParam0
rdlong filesize, pFilestuff wz ' length of file
if_z neg temp, #1 ' if file is empty, return -1: EOF
if_z jmp #AckReturnCode ' This is a bit of a hack. The Sphinx compiler really
' should delete outdated .bin or .eep files to force
' (re)linking, but since sxfs doesn't know how to
' delete files (yet(?)), the compiler just makes
' a file empty instead of deleting it. This test
' here catches empty executable files and bails,
' preventing a crash.
rdlong execmode, pSxfsParam1
rdbyte callingCog, pSxfsParam2 ' stop Spin interpreter
cogstop callingCog
rdlong oldClkfreq, #0 ' save clkfreq
rdbyte oldClkmode, #4 ' save clkmode
mov p, pFilestuff
add p, #_cluster
rdword temp, p ' temp = (cluster
sub temp, #2 ' - 2)
shl temp, clusterShift ' << clusterShift
add temp, dataSector0 ' + dataSector0
mov p, temp ' p repurposed here as sector#
mov i, #63 ' read 63 contiguous sectors
mov q, #0
:loop
wrlong p, pSdspiBlockno ' Prepare to read sector p
wrlong q, pSdspiParam ' to memory pointed to by q
mov temp, #"R"
call #SdspiCommand
add p, #1 ' Next sector
add q, k512 ' Next 512-byte block of memory
djnz i, #:loop
' clear memory above the loaded file
mov i, #1
shl i, #15 ' i = 32768
sub i, filesize wz ' - file size
if_z jmp #:z
mov temp, #0
:y
wrbyte temp, filesize ' repurpose filesize as pointer
add filesize, #1
djnz i, #:y
:z
' store those nutty $fff9ffff longs
rdword p, #$0a
sub p, #4
wrlong kfff9ffff, p
sub p, #4
wrlong kfff9ffff, p
tjz execmode, #:dontChangeClock ' execmode = 0? skip cog-killing and clock change
cogid temp
mov i, #0
mov j, #8
:cogkill
cmp i, temp wz ' kill all cogs except self
if_ne cogstop i ' (suicide comes later)
add i, #1
djnz j, #:cogkill
' The following code is borrowed liberally from sdspiFemto:
rdlong temp, #0 ' new clock frequency
cmp temp, oldClkfreq wz ' compared to old
rdbyte temp, #4 ' get new clock mode in advance
if_ne jmp #:changeClock
cmp temp, oldClkmode wz ' compare new clock mode to old
if_e jmp #:dontChangeClock
:changeClock and temp, #$f8 ' Force use of RCFAST clock while
clkset temp ' letting requested clock start
mov i, time_xtal
:startupDelay djnz i, #:startupDelay ' Allow 20ms@20MHz for xtal/pll to settle
rdbyte temp, #4 ' Then switch to selected clock
clkset temp
jmp #:x
:dontChangeClock
wrlong oldClkfreq, #0 ' Restore old clock frequency
wrbyte oldClkmode, #4 ' and mode.
:x
or interpreter, callingCog
coginit interpreter ' start new Spin interpreter in the same cog.
tjz execmode, #AckNoReturnCode ' execmode = 0? Done.
cogid temp ' kill
cogstop temp ' self
interpreter long ($0004 << 16) | ($F004 << 2) | %0000 ' Thanks to sdspiFemto
time_xtal long 20 * 20000 / 4 / 1 ' 20ms (@20MHz, 1 inst/loop)
'*********************************************************************************************************************
'* *
'* Utility stuff *
'* *
'*********************************************************************************************************************
{
Out'(outch) '''
:w rdbyte outtemp, pTerm wz
if_nz jmp #:w
wrbyte outch, pTerm
Out_ret ret
OutHex'(outx, outn) '''
mov outtemp, outn
sub outtemp, #1
shl outtemp, #2
ror outx, outtemp
:loop
mov outch, outx
and outch, #$0f
add outch, #"0"
cmp outch, #"9" wc, wz
if_a add outch, #"a"-"0"-10
call #out
rol outx, #4
djnz outn, #:loop
Outhex_ret ret
pTerm long $7ffc
outch long 0
outx long 0
outn long 0
outtemp long 0 '''
}
ByteCopy ' ( p, q, n )
tjz n, #ByteCopy_ret
:loop rdbyte temp, q
add q, #1
wrbyte temp, p
add p, #1
djnz n, #:loop
ByteCopy_ret ret
ReadMetadataSector ' ( sector )
call #FlushMetadataSector
cmp sector, currentSector wz
if_e jmp #ReadMetadataSector_ret
wrlong pMetadataBuffer, pSdspiParam
wrlong sector, pSdspiBlockno
mov currentSector, sector
mov temp, #"R"
call #SdspiCommand
ReadMetadataSector_ret ret
FlushMetadataSector
tjz dirty, #FlushMetadataSector_ret
mov dirty, #0
' write current sector
wrlong pMetadataBuffer, pSdspiParam
wrlong currentSector, pSdspiBlockno
mov temp, #"W"
call #SdspiCommand
FlushMetadataSector_ret ret
SdspiCommand
wrlong temp, pSdspiCommand
:wait
rdlong temp, pSdspiCommand wz
if_nz jmp #:wait
rdlong temp, pSdspiParam wz
if_nz jmp #AckReturnCode
SdspiCommand_ret ret
k512 long 512
kfff9ffff long $fff9ffff
dirty long 0
currentSector long -1
pMetadataBuffer long METADATABUFFER
pSxfsCommand long SXFSRENDEZVOUS+0
pSxfsParam0 long SXFSRENDEZVOUS+4
pSxfsParam1 long SXFSRENDEZVOUS+8
pSxfsParam2 long SXFSRENDEZVOUS+12
pSdspiCommand long SDSPIRENDEZVOUS+0
pSdspiParam long SDSPIRENDEZVOUS+4
pSdspiBlockno long SDSPIRENDEZVOUS+8
pCommand long SXFS2RENDEZVOUS+0
pParam long SXFS2RENDEZVOUS+4
bytesPerSector long 0
sectorsPerCluster long 0
clusterShift long 0
reservedSectors long 0
numberOfFats long 0
sectorsPerFat long 0
rootDirEntries long 0
fatSector0 long 0
dirSector0 long 0
dataSector0 long 0
temp res 1
i res 1
j res 1
n res 1
p res 1
q res 1
pFilestuff res 1
sop res 1
sopTail res 1
srcPtr res 1
nBytes res 1
cluster res 1
sector res 1
leftInSector res 1
filesize res 1
execmode res 1
callingCog res 1
oldClkfreq res 1
oldClkmode res 1
retcode res 1
fit
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,728 +0,0 @@
''*******************************
''* PS/2 Keyboard Driver v2.0 *
''* (C) 2004 Parallax, Inc. *
''* Modified by Michael Green *
''* to support Hydra as well *
''*******************************
{
Modified by Michael Park for Sphinx
2009/06/15
}
SXKBRENDEZVOUS = $7ff8
VAR
long cog
PUB start(pingroup) : okay
'' Start keyboard driver - starts a cog
'' returns false if no cog available
''
'' pingroup = 1st pin number for 2-pin group for PS/2 I/O
'' (1st - data signal, 2nd - clock signal)
'' Even number selects Demo Board I/O convention
''
'' 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
''
'' pingroup = 1st pin number for 4-pin group for PS/2 I/O
'' Odd number selects Hydra I/O convention
''
'' 1st pin drives NPN base for PS/2 'data' signal pull-down
'' 2nd pin reads PS/2 'data' signal
'' 3rd pin drives NPN base for PS/2 'clock' signal pull-down
'' 4th pin reads PS/2 'clock' signal
''
'' use 2.2K-ohm resistors between 1st/3rd pins and NPN bases
'' use 22K-ohm resistors between 2nd/4th pins and PS/2-side signals
'' use 2.2K-ohm resistors to pull PS/2-side signals to 5V
'' connect PS/2 power to 5V, PS/2 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(pingroup, %0_000_100, %01_01000)
PUB startx(pingroup, 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)
long[pRendezvous]~~ ' ping
if long[pRendezvous]~ == -1 ' no response
longmove(@_pingroup, @pingroup, 3)
okay := cog := cognew(@entry, 0) + 1
PUB peekkey
'' Returns a 0 if the buffer is empty
'' returns next key if buffer not empty
'' but doesn't remove the key from buffer
return long[pRendezvous]
PUB key : keycode
'' Get key (never waits)
'' returns key (0 if buffer empty)
if keycode := long[pRendezvous]
long[pRendezvous]~
PUB getkey : keycode
'' Get next key (may wait for keypress)
'' returns key
repeat until (keycode := key)
DAT
'******************************************
'* Assembly language PS/2 keyboard driver *
'******************************************
org
'
'
' Entry
'
entry
mov x,_pingroup 'get mask for 1st pin
andn x,#1
test _pingroup,#1 wz
mov dwmask,#1
shl dwmask,x
mov drmask,dwmask
if_nz shl drmask,#1
mov cwmask,drmask
shl cwmask,#1
mov crmask,cwmask
if_nz shl crmask,#1
if_nz or dira,dwmask 'set directions
if_nz or dira,cwmask
mov _head,#0 'reset output parameter _head
mov _tail, #0
'
'
' Reset keyboard
'
reset test _pingroup,#1 wz
if_nz andn outa,dwmask 'let PS/2 lines float (pulled up)
if_nz andn outa,cwmask
if_z mov dira,#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
call #Rendezvous
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
mov x, _tail 'if room in buffer and key valid, enter
sub x,#1
and x,#$F
cmp x,_head wz
if_e jmp #:z
test data,#$FF wz
if_z jmp #:z
mov x, #buffer
add x, _head
movd :store, x
nop
:store mov 0-0, data ' buffer[x] := data
add _head,#1
and _head,#$F
:z
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 test _pingroup,#1 wz
if_z or dira,cwmask
if_nz or outa,cwmask 'pull clock low
movs napshr,#13 'hold clock for ~128us (must be >100us)
call #nap
if_z or dira,dwmask
if_nz or outa,dwmask 'pull data low
movs napshr,#18 'hold data for ~4us
call #nap
if_z xor dira,cwmask
if_nz andn outa,cwmask '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
test _pingroup,#1 wz
if_z muxnc dira,dwmask
if_nz muxnc outa,dwmask
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
:waitpne
call #Rendezvous
mov x, ina 'wait indefinitely for initial clock low
and x, crmask
cmp x, crmask wz
if_e jmp #:waitpne
receive_ack mov x,#11 'ready 11 bits
receive_bit call #wait_c0 'wait until clock low
movs napshr,#16 'pause ~16us
call #nap
test drmask,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
'
'
' Communicate with the rest of the Propeller via "rendezvous" in hub memory.
'
Rendezvous
rdlong t, pRendezvous wz ' if rendezvous = 0 (location empty),
if_z jmp #:clearToSend ' go fill it with character in buffer.
add t, #1 wz ' if rendezvous = -1
if_nz jmp #Rendezvous_ret ' someone is pinging to see if sxkb cog is alive;
sub t, #2 ' set rendezvous to -2 to ack.
wrlong t, pRendezvous
jmp #Rendezvous_ret
:clearToSend
cmp _head, _tail wz
if_e jmp #Rendezvous_ret
mov x, _tail
add x, #buffer
movs :read, x
nop
:read mov data, 0-0 ' data := buffer[_tail]
wrlong data, pRendezvous
add _tail, #1
and _tail, #$0f
Rendezvous_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
test crmask,ina wc 'check required state(s)
test drmask,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,#0-0 'shr scales time (set to 13/16/18)
min t,#10 'ensure waitcnt won't snag (was 3 but snagged; upped to 10 [mp])
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, "+"
_pingroup long 0
_locks long 0
_auto long 0
pRendezvous long SXKBRENDEZVOUS
'
' Uninitialized data
'
buffer res 16
dwmask res 1 'output driver mask for data
drmask res 1 'input mask for data
cwmask res 1 'output driver mask for clock
crmask res 1 'input mask for data
stat res 1
data res 1
x res 1
y res 1
t res 1
_tail res 1
_head res 1 'write-only
_present res 1 'write-only
_states res 8 'write-only
fit
''
''
'' _________
'' 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

@ -1,334 +0,0 @@
' sdspi: SPI interface to a Secure Digital card.
'
' Copyright 2008 Radical Eye Software
' Modified 2009 by Michael Park: added pointer to rendezvous variables.
'
' See end of file for terms of use.
'
' You probably never want to call this; you want to use fsrw
' instead (which calls this); this is only the lowest layer.
'
' Assumes SD card is interfaced using four consecutive Propeller
' pins, as follows (assuming the base pin is pin 0):
' 3.3v
' | | | | | |
' R R R R R R 20k
' p0 --------*-+-+-+-+-+------ do
' p1 ----------*-+-+-+-+------ clk
' p2 ------------*-+-+-+------ di
' p3 --------------*-+-+------ cs (dat3)
' 150 +-+------ irq (dat1)
' +------ p9 (dat2)
'
' The 20k resistors
' are pullups, and should be there on all six lines (even
' the ones we don't drive).
'
' This code is not general-purpose SPI code; it's very specific
' to reading SD cards, although it can be used as an example.
'
' The code does not use CRC at the moment (this is the default).
' With some additional effort we can probe the card to see if it
' supports CRC, and if so, turn it on.
'
' All operations are guarded by a watchdog timer, just in case
' no card is plugged in or something else is wrong. If an
' operation does not complete in one second it is aborted.
'
con
sectorsize = 512
sectorshift = 9
var
long cog
long pCommand, pParam, pBlockno ' rendezvous between spin and assembly
pub stop
if cog
cogstop(cog~ - 1)
pub start(basepin, pRendezvous)
'
' Initialize the card! Send a whole bunch of
' clocks (in case the previous program crashed
' in the middle of a read command or something),
' then a reset command, and then wait until the
' card goes idle.
'
do := basepin++
clk := basepin++
di := basepin++
cs := basepin
stop
pCommand := pRendezvous
pParam := pRendezvous + 4
pBlockno := pRendezvous + 8
long[pCommand] := "I"
cog := 1 + cognew(@entry, pRendezvous)
repeat while long[pCommand]
if long[pParam]
abort long[pParam]
return 0
pub readblock(n, b)
'
' Read a single block. The "n" passed in is the
' block number (blocks are 512 bytes); the b passed
' in is the address of 512 blocks to fill with the
' data.
'
long[pParam] := b
long[pBlockno] := n
long[pCommand] := "R"
repeat while long[pCommand]
if long[pParam]
abort long[pParam]
return 0
pub writeblock(n, b)
'
' Write a single block. Mirrors the read above.
'
long[pParam] := b
long[pBlockno] := n
long[pCommand] := "W"
repeat while long[pCommand]
if long[pParam]
abort long[pParam]
return 0
dat
org
entry mov comptr,par
mov parptr,par
add parptr,#4
mov parptr2,parptr
add parptr2,#4
' set up
mov acca,#1
shl acca,di
or dira,acca
mov acca,#1
shl acca,clk
or dira,acca
mov acca,#1
shl acca,do
mov domask,acca
mov acca,#1
shl acca,cs
or dira,acca
mov csmask,acca
neg phsb,#1
mov frqb,#0
mov acca,nco
add acca,clk
mov ctra,acca
mov acca,nco
add acca,di
mov ctrb,acca
mov ctr2,onek
oneloop
call #sendiohi
djnz ctr2,#oneloop
mov starttime,cnt
mov cmdo,#0
mov cmdp,#0
call #cmd
or outa,csmask
call #sendiohi
initloop
mov cmdo,#55
call #cmd
mov cmdo,#41
call #cmd
or outa,csmask
cmp accb,#1 wz
if_z jmp #initloop
wrlong accb,parptr
' reset frqa and the clock
finished
mov frqa,#0
wrlong frqa,comptr
or outa,csmask
neg phsb,#1
call #sendiohi
pause
mov acca,#511
add acca,cnt
waitcnt acca,#0
waitloop
mov starttime,cnt
rdlong acca,comptr wz
cmp acca,#"B" wz
if_z jmp #byteio
mov ctr2,sector
cmp acca,#"R" wz
if_z jmp #rblock
cmp acca,#"W" wz
if_nz jmp #pause
wblock
mov starttime,cnt
mov cmdo,#24
rdlong cmdp,parptr2
call #cmd
mov phsb,#$fe
call #sendio
rdlong accb,parptr
neg frqa,#1
wbyte
rdbyte phsb,accb
shl phsb,#23
add accb,#1
mov ctr,#8
wbit mov phsa,#8
shl phsb,#1
djnz ctr,#wbit
djnz ctr2,#wbyte
neg phsb,#1
call #sendiohi
call #sendiohi
call #readresp
and accb,#$1f
sub accb,#5
wrlong accb,parptr
call #busy
jmp #finished
rblock
mov starttime,cnt
mov cmdo,#17
rdlong cmdp,parptr2
call #cmd
call #readresp
rdlong accb,parptr
sub accb,#1
rbyte
mov phsa,hifreq
mov frqa,freq
add accb,#1
test domask,ina wc
addx acca,acca
test domask,ina wc
addx acca,acca
test domask,ina wc
addx acca,acca
test domask,ina wc
addx acca,acca
test domask,ina wc
addx acca,acca
test domask,ina wc
addx acca,acca
test domask,ina wc
addx acca,acca
mov frqa,#0
test domask,ina wc
addx acca,acca
wrbyte acca,accb
djnz ctr2,#rbyte
mov frqa,#0
neg phsb,#1
call #sendiohi
call #sendiohi
or outa,csmask
wrlong ctr2,parptr
jmp #finished
byteio
rdlong phsb,parptr
call #sendio
wrlong accb,parptr
jmp #finished
sendio
rol phsb,#24
sendiohi
mov ctr,#8
neg frqa,#1
mov accb,#0
bit mov phsa,#8
test domask,ina wc
addx accb,accb
rol phsb,#1
djnz ctr,#bit
sendio_ret
sendiohi_ret
ret
checktime
mov duration,cnt
sub duration,starttime
cmp duration,clockfreq wc
checktime_ret
if_c ret
neg duration,#13
wrlong duration,parptr
jmp #finished
cmd
andn outa,csmask
neg phsb,#1
call #sendiohi
mov phsb,cmdo
add phsb,#$40
call #sendio
mov phsb,cmdp
shl phsb,#9
call #sendiohi
call #sendiohi
call #sendiohi
call #sendiohi
mov phsb,#$95
call #sendio
readresp
neg phsb,#1
call #sendiohi
call #checktime
cmp accb,#$ff wz
if_z jmp #readresp
cmd_ret
readresp_ret
ret
busy
neg phsb,#1
call #sendiohi
call #checktime
cmp accb,#$0 wz
if_z jmp #busy
busy_ret
ret
di long 0
do long 0
clk long 0
cs long 0
nco long $1000_0000
hifreq long $e0_00_00_00
freq long $20_00_00_00
clockfreq long 80_000_000
onek long 1000
sector long 512
domask res 1
csmask res 1
acca res 1
accb res 1
cmdo res 1
cmdp res 1
comptr res 1
parptr res 1
parptr2 res 1
ctr res 1
ctr2 res 1
starttime res 1
duration res 1
{{
' 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

@ -1,916 +0,0 @@
''***************************************
''* TV Driver v1.1 *
''* Author: Chip Gracey *
''* Copyright (c) 2004 Parallax, Inc. *
''* See end of file for terms of use. *
''***************************************
' v1.0 - 01 May 2006 - original version
' v1.1 - 17 May 2006 - pixel tile size can now be 16 x 32 to enable more efficient
' character displays utilizing the internal font - see 'tv_mode'
{
2009
May
11 Moved blank line tasks into one-time initialization section.
Difficulty: one task was flipping the interlace bit of _mode, necessitating a reload of _mode
every superfield. Removed the flip and changed the sense of the Z tests that depended on _mode<1>
being flipped.
12 Implemented simple scrolling terminal output in background task.
Difficulty: have to keep Z clear so that mainline interlaced code works properly.
June
9 Added "D"isable and "E"nable commands.
20 Changing ping response to include basepin.
}
CON
fntsc = 3_579_545 'NTSC color frequency
lntsc = 3640 'NTSC color cycles per line * 16
sntsc = 624 'NTSC color cycles per sync * 16
fpal = 4_433_618 'PAL color frequency
lpal = 4540 'PAL color cycles per line * 16
spal = 848 'PAL color cycles per sync * 16
paramcount = 14
' colortable = $180 'start of colortable inside cog
cols = 40
rows = 13
VAR
long cog
long rendezvous
PUB start(basepin, rv) | okay
'' Start TV driver - starts a cog if necessary
'' returns true if it had to start a cog, false if cog was already running.
''
_basepin := basepin
rendezvous := rv
long[rendezvous]~~ ' ping the sxtv cog (send -1)
waitcnt( clkfreq/10 + cnt )
if long[rendezvous] <> -1 ' if the cog is alive it'll set this to _basepin<<8
long[rendezvous]~
return false
_pins := (basepin & $38) << 1 | (basepin & 4 == 4) & %0101
if cog := cognew(@entry, rendezvous) + 1
return true
else
abort string("Couldn't start sxtv cog")
PUB stop
'' Stop TV driver - frees a cog
if cog
cogstop(cog~ - 1)
PUB GetBasepin
repeat while long[rendezvous]
long[rendezvous]~~ ' ping the sxtv cog (send -1)
repeat while long[rendezvous] == -1
return long[rendezvous]~ >> 8
PUB str(stringptr)
'' Print a zero-terminated string
repeat strsize(stringptr)
out(byte[stringptr++])
PUB dec(value) | _i
'' Print a decimal number
if value < 0
-value
out("-")
_i := 1_000_000_000
repeat 10
if value => _i
out(value / _i + "0")
value //= _i
result~~
elseif result or _i == 1
out("0")
_i /= 10
PUB hex(value, digits)
'' Print a hexadecimal number
value <<= (8 - digits) << 2
repeat digits
out(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
PUB bin(value, digits)
'' Print a binary number
value <<= 32 - digits
repeat digits
out((value <-= 1) & 1 + "0")
pub out( c )
repeat while byte[rendezvous]
byte[rendezvous] := c
DAT
'*******************************
'* Assembly language TV driver *
'*******************************
org
'
'
' Entry
'
entry
call #init
mov taskptr,#tasks 'reset tasks
'
'
' Superfield
'
superfield
test _mode,#%0001 wc 'if ntsc, set phaseflip
if_nc mov phaseflip,phasemask
test _mode,#%0010 wz 'get interlace into nz
mov temp, #0 wz ''' I messed something up and now Z has to be set, not clear.
'
'
' Field
'
field mov x,vinv 'do invisible back porch lines
:black call #hsync 'do hsync
waitvid burst,sync_high2 'do black
jmpret taskret,taskptr 'call task section (z undisturbed)
djnz x,#:black 'another black line?
' wrlong visible,par 'set status to visible
mov x,vb 'do visible back porch lines
call #blank_lines
mov y,_vt 'set vertical tiles
movs :getchars4, #text '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
:line
mov vx,_vx 'set vertical expand
mov t1,#32
mov chset, chset0
:vert
if_z xor interlace,#1 'interlace skip?
if_z tjz interlace,#:skip
call #hsync 'do hsync
mov vscl,hb 'do visible back porch pixels
xor tile,colortable
waitvid tile,#0
mov x,_ht 'set horizontal tiles
shr x, #2 'divide by 4
mov vscl,hx 'set horizontal expand
:getchars4 mov chars4, 0-0
mov t3, #4
:loop4
mov char, chars4
ror chars4, #8
and char, #$ff
shr char, #1 wc
shl char, #7
add char, chset
rdlong pixels16, char
' xor colors4, phaseflip
if_nc waitvid colortable, pixels16
if_c waitvid colortable+1, pixels16
djnz t3, #:loop4
add :getchars4, #1
djnz x, #:getchars4
mov vscl,hf 'do visible front porch pixels
mov tile,colortable'phaseflip
' xor tile,colortable
waitvid tile,#0
sub :getchars4, #10
:skip
add chset, #4
djnz t1, #:vert
add :getchars4, #10
djnz y,#:line 'another tile line?
if_z xor interlace,#1 wz 'get interlace and field1 into z
test _mode,#%0001 wc 'do visible front porch lines
mov x,vf
if_nz_and_c add x,#1
call #blank_lines
' if_z wrlong invisible,par 'unless interlace and field1, set status to invisible
if_z_eq_c call #hsync 'if required, do short line
if_z_eq_c mov vscl,hrest
if_z_eq_c waitvid burst,sync_high2
if_z_eq_c xor phaseflip,phasemask
call #vsync_high 'do high vsync pulses
movs vsync1,#sync_low1 'do low vsync pulses
movs vsync2,#sync_low2
call #vsync_low
call #vsync_high 'do high vsync pulses
if_nz mov vscl,hhalf 'if odd frame, do half line
if_nz waitvid burst,sync_high2
if_z jmp #field 'if interlace and field1, display field2
jmp #superfield 'else, new superfield
'
'
' Blank lines
'
blank_lines call #hsync 'do hsync
xor tile,colortable 'do background
waitvid tile,#0
djnz x,#blank_lines
blank_lines_ret ret
'
'
' Horizontal sync
'
hsync test _mode,#%0001 wc 'if pal, toggle phaseflip
' if_c xor phaseflip,phasemask
mov vscl,sync_scale1 'do hsync
mov tile,burst'phaseflip
' xor tile,burst
waitvid tile,sync_normal
mov vscl,hvis 'setup in case blank line
mov tile,#0'phaseflip
hsync_ret ret
'
'
' Vertical sync
'
vsync_high movs vsync1,#sync_high1 'vertical sync
movs vsync2,#sync_high2
vsync_low mov x,vrep
vsyncx mov vscl,sync_scale1
vsync1 waitvid burst,sync_high1
mov vscl,sync_scale2
vsync2 waitvid burst,sync_high2
djnz x,#vsyncx
vsync_low_ret
vsync_high_ret ret
'
'
' Tasks - performed in sections during invisible back porch lines
'
tasks
clearscreen
mov i, #14 ' clear 13 lines + 1 extra to make scrolling easier
:lines
mov j, #40/4 ' 40 columns, 4 chars at a time
:chars
:storem mov text, x20202020
add :storem, d0 ' inc dst
djnz j, #:chars
jmpret taskptr,taskret
djnz i, #:lines
waitforchar
mov temp, #0 ' clear buffer: ready to accept next byte
wrlong temp, par
waitnoclear
:wait
jmpret taskptr,taskret
rdlong ch, par
tjz ch, #:wait
' got a byte
mov temp, cmdPing ' roundabout comparisons to avoid changing Z.
sub temp, ch ' ch = -1 is just a ping to see if this cog is alive.
tjz temp, #ping
mov temp, cmdDisable
sub temp, ch
tjz temp, #disable
mov temp, cmdEnable
sub temp, ch
tjz temp, #enable
neg temp, #256 ' at this point, if ch is > 255, it must be _basepin<<8
and temp, ch ' as set by a previous ping, so we just ignore it
tjnz temp, #waitnoclear ' (leave the long pointed to by par undisturbed).
:char
mov temp, #8
sub temp, ch
tjz temp, #:bksp
mov temp, #13
sub temp, ch
tjnz temp, #:printchar
call #cr
jmp #waitforchar
:bksp
sub col, #1 ' warning: no error-checking
jmp #waitforchar
:printchar
mov temp, #40
sub temp, col
tjnz temp, #:nocr
call #cr
:nocr
mov temp, col
shr temp, #2
add temp, #text+12*40/4
movs :get4chars, temp
movd :put4chars, temp
mov i, col
and i, #3
shl i, #3 ' col&3 => 0, 8, 16, 24
:get4chars mov temp, 0-0
ror temp, i
andn temp, #$ff
or temp, ch
rol temp, i
:put4chars mov 0-0, temp
add col, #1
jmp #waitforchar
cr
movs :move4chars, #text + 40 / 4
movd :move4chars, #text
mov i, #13 ' copy 13 lines up. Since we have an extra blank line at the bottom
' (see clearscreen) the last visible line is automatically cleared.
:copyline
mov j, #40/4
:move4chars mov 0-0, 0-0
add :move4chars, d0s0
djnz j, #:move4chars
jmpret taskptr,taskret
djnz i, #:copyline
mov col, #0
cr_ret ret
ping
mov temp, _basepin
shl temp, #8
wrlong temp, par
jmp #waitnoclear
enable
mov dira, saveDira
mov dirb, saveDirb
jmp #waitforchar
disable
mov dira, #0
mov dirb, #0
jmp #waitforchar
'
'
' Initialized data
'
x20202020 long $20202020
chset0 long $8000
m8 long 8_000_000
m128 long 128_000_000
d0 long 1 << 9 << 0
d6 long 1 << 9 << 6
d0s0 long 1 << 9 << 0 + 1 << 0
d0s1 long 1 << 9 << 0 + 1 << 1
interlace long 0
invisible long 1
visible long 2
phaseflip long $00000000
phasemask long $F0F0F0F0
line long $00060000
lineinc long $10000000
linerot long 0
pins0 long %11110000_01110000_00001111_00000111
pins1 long %11111111_11110111_01111111_01110111
sync_high1 long %0101010101010101010101_101010_0101
sync_high2 long %01010101010101010101010101010101 'used for black
sync_low1 long %1010101010101010101010101010_0101
sync_low2 long %01_101010101010101010101010101010
colortable
' long $07_0a_07_0a ' white on blue
' long $07_07_0a_0a
' long $bc_02_bc_02 ' green on black
' long $bc_bc_02_02
' long $05_02_05_02 ' white on black
' long $05_05_02_02
long $02_05_02_05 ' black on white
long $02_02_05_05
' long $8a_8c_8a_8c ' black on yellow
' long $8a_8a_8c_8c
'
'
' NTSC/PAL metrics tables
' ntsc pal
' ----------------------------------------------
wtab word lntsc - sntsc, lpal - spal 'hvis
word lntsc / 2 - sntsc, lpal / 2 - spal 'hrest
word lntsc / 2, lpal / 2 'hhalf
word 243, 286 'vvis
word 10, 18 'vinv
word 6, 5 'vrep
word $02_8A, $02_AA 'burst
wtabx
ltab long fntsc 'fcolor
long fpal
long sntsc >> 4 << 12 + sntsc 'sync_scale1
long spal >> 4 << 12 + spal
long 67 << 12 + lntsc / 2 - sntsc 'sync_scale2
long 79 << 12 + lpal / 2 - spal
long %0101_00000000_01_10101010101010_0101 'sync_normal
long %010101_00000000_01_101010101010_0101
ltabx
cmdPing long -1
cmdEnable long "E"<<8
cmdDisable long "D"<<8
_basepin long 0
'
'
' Parameter buffer
'
_enable long 1 'enable
_pins long 0 'pins
_mode long %10010 'mode
_screen long 0 'screen
_colors long 0 'colors
_ht long cols 'hc
_vt long rows 'vc
_hx long 4 'hx
_vx long 1 'vx
_ho long 0 'ho
_vo long 0 'vo
_broadcast long 0 'broadcast
_auralcog long 0 'auralcog
'
'
' Uninitialized data
'
i long 0
j long 0
col long 0
ch long 0
temp long 0
char long 0
chset long 0
chars4 long 0
pixels16 long 0
taskptr long 0 'tasks
taskret long 0
t1 long 0
t2 long 0
t3 long 0
m1 long 0
m2 long 0
x long 0 'display
y long 0
hf long 0
hb long 0
vf long 0
vb long 0
hx long 0
vx long 0
hc2x long 0
screen long 0
tile long 0
pixels long 0
lineadd long 0
hvis long 0 'loaded from word table
hrest long 0
hhalf long 0
vvis long 0
vinv long 0
vrep long 0
burst long 0
fcolor long 0 'loaded from long table
sync_scale1 long 0
sync_scale2 long 0
sync_normal long 0
saveDira long 0
saveDirb long 0
text ' Cog memory from this point on will be reclaimed as text buffer.
init
mov t1,_pins 'set video pins and directions
test t1,#$08 wc
if_nc mov t2,pins0
if_c mov t2,pins1
test t1,#$40 wc
shr t1,#1
shl t1,#3
shr t2,t1
movs vcfg,t2
shr t1,#6
movd vcfg,t1
shl t1,#3
and t2,#$FF
shl t2,t1
if_nc mov dira,t2
if_nc mov saveDira, t2
if_nc mov dirb,#0
if_nc mov saveDirb, #0
if_c mov dira,#0
if_c mov saveDira, #0
if_c mov dirb,t2 '+18
if_c mov saveDirb, t2
movs :rd,#wtab 'load ntsc/pal metrics from word table
movd :wr,#hvis
mov t1,#wtabx - wtab
test _mode,#%0001 wc
:rd mov t2,0
add :rd,#1
if_nc shl t2,#16
shr t2,#16
:wr mov 0,t2
add :wr,d0
djnz t1,#:rd '+54
if_nc movs :ltab,#ltab 'load ntsc/pal metrics from long table
if_c movs :ltab,#ltab+1
movd :ltab,#fcolor
mov t1,#(ltabx - ltab) >> 1
:ltab mov 0,0
add :ltab,d0s1
djnz t1,#:ltab '+17
rdlong t1,#0 'get CLKFREQ
shr t1,#1 'if CLKFREQ < 16MHz, cancel _broadcast
cmp t1,m8 wc
if_c mov _broadcast,#0
shr t1,#1 'if CLKFREQ < color frequency * 4, disable
' cmp t1,fcolor wc
' if_c jmp #disabled '+11
mov t1,fcolor 'set ctra pll to fcolor * 16
call #divide 'if ntsc, set vco to fcolor * 32 (114.5454 MHz)
test _mode,#%0001 wc 'if pal, set vco to fcolor * 16 (70.9379 MHz)
if_c movi ctra,#%00001_111 'select fcolor * 16 output (ntsc=/2, pal=/1)
if_nc movi ctra,#%00001_110
if_nc shl t2,#1
mov frqa,t2 '+147
mov t1,_broadcast 'set ctrb pll to _broadcast
mov t2,#0 'if 0, turn off ctrb
tjz t1,#:off
min t1,m8 'limit from 8MHz to 128MHz
max t1,m128
mov t2,#%00001_100 'adjust _broadcast to be within 4MHz-8MHz
:scale shr t1,#1 '(vco will be within 64MHz-128MHz)
cmp m8,t1 wc
if_c add t2,#%00000_001
if_c jmp #:scale
:off movi ctrb,t2
call #divide
mov frqb,t2 '+165
mov t1,#%10100_000 'set video configuration
test _pins,#$01 wc '(swap broadcast/baseband output bits?)
if_c or t1,#%01000_000
test _mode,#%1000 wc '(strip chroma from broadcast?)
if_nc or t1,#%00010_000
test _mode,#%0100 wc '(strip chroma from baseband?)
if_nc or t1,#%00001_000
and _auralcog,#%111 '(set aural cog)
or t1,_auralcog
movi vcfg,t1 '+10
mov hx,_hx 'compute horizontal metrics
shl hx,#8
or hx,_hx
shl hx,#4
mov hc2x,_ht
shl hc2x,#1
mov t1,_ht
mov t2,_hx
call #multiply
mov hf,hvis
sub hf,t1
shr hf,#1 wc
mov hb,_ho
addx hb,hf
sub hf,_ho '+52
mov t1,_vt 'compute vertical metrics
mov t2,_vx
call #multiply
test _mode,#%10000 wc 'consider tile size
muxc linerot,#1
mov lineadd,lineinc
if_c shr lineadd,#1
if_c shl t1,#1
test _mode,#%0010 wc 'consider interlace
if_c shr t1,#1
mov vf,vvis
sub vf,t1
shr vf,#1 wc
neg vb,_vo
addx vb,vf
add vf,_vo '+53
init_ret ret
'
'
' Divide t1/CLKFREQ to get frqa or frqb value into t2
'
divide rdlong m1,#0 'get CLKFREQ
mov m2,#32+1
:loop cmpsub t1,m1 wc
rcl t2,#1
shl t1,#1
djnz m2,#:loop
divide_ret ret '+140
'
'
' Multiply t1 * t2 * 16 (t1, t2 = bytes)
'
multiply shl t2,#8+4-1
mov m1,#8
:loop shr t1,#1 wc
if_c add t1,t2
djnz m1,#:loop
multiply_ret ret '+37
''
''___
''VAR 'TV parameters - 14 contiguous longs
''
'' long tv_status '0/1/2 = off/invisible/visible read-only
'' long tv_enable '0/non-0 = off/on write-only
'' long tv_pins '%pppmmmm = pin group, pin group mode write-only
'' long tv_mode '%tccip = tile,chroma,interlace,ntsc/pal write-only
'' long tv_screen 'pointer to screen (words) write-only
'' long tv_colors 'pointer to colors (longs) write-only
'' long tv_ht 'horizontal tiles write-only
'' long tv_vt 'vertical tiles write-only
'' long tv_hx 'horizontal tile expansion write-only
'' long tv_vx 'vertical tile expansion write-only
'' long tv_ho 'horizontal offset write-only
'' long tv_vo 'vertical offset write-only
'' long tv_broadcast 'broadcast frequency (Hz) write-only
'' long tv_auralcog 'aural fm cog write-only
''
''The preceding VAR section may be copied into your code.
''After setting variables, do start(@tv_status) to start driver.
''
''All parameters are reloaded each superframe, allowing you to make live
''changes. To minimize flicker, correlate changes with tv_status.
''
''Experimentation may be required to optimize some parameters.
''
''Parameter descriptions:
'' _________
'' tv_status
''
'' driver sets this to indicate status:
'' 0: driver disabled (tv_enable = 0 or CLKFREQ < requirement)
'' 1: currently outputting invisible sync data
'' 2: currently outputting visible screen data
'' _________
'' tv_enable
''
'' 0: disable (pins will be driven low, reduces power)
'' non-0: enable
'' _______
'' tv_pins
''
'' bits 6..4 select pin group:
'' %000: pins 7..0
'' %001: pins 15..8
'' %010: pins 23..16
'' %011: pins 31..24
'' %100: pins 39..32
'' %101: pins 47..40
'' %110: pins 55..48
'' %111: pins 63..56
''
'' bits 3..0 select pin group mode:
'' %0000: %0000_0111 - baseband
'' %0001: %0000_0111 - broadcast
'' %0010: %0000_1111 - baseband + chroma
'' %0011: %0000_1111 - broadcast + aural
'' %0100: %0111_0000 broadcast -
'' %0101: %0111_0000 baseband -
'' %0110: %1111_0000 broadcast + aural -
'' %0111: %1111_0000 baseband + chroma -
'' %1000: %0111_0111 broadcast baseband
'' %1001: %0111_0111 baseband broadcast
'' %1010: %0111_1111 broadcast baseband + chroma
'' %1011: %0111_1111 baseband broadcast + aural
'' %1100: %1111_0111 broadcast + aural baseband
'' %1101: %1111_0111 baseband + chroma broadcast
'' %1110: %1111_1111 broadcast + aural baseband + chroma
'' %1111: %1111_1111 baseband + chroma broadcast + aural
'' -----------------------------------------------------------
'' active pins top nibble bottom nibble
''
'' the baseband signal nibble is arranged as:
'' bit 3: chroma signal for s-video (attach via 560-ohm resistor)
'' bits 2..0: baseband video (sum 270/560/1100-ohm resistors to form 75-ohm 1V signal)
''
'' the broadcast signal nibble is arranged as:
'' bit 3: aural subcarrier (sum 560-ohm resistor into network below)
'' bits 2..0: visual carrier (sum 270/560/1100-ohm resistors to form 75-ohm 1V signal)
'' _______
'' tv_mode
''
'' bit 4 selects between 16x16 and 16x32 pixel tiles:
'' 0: 16x16 pixel tiles (tileheight = 16)
'' 1: 16x32 pixel tiles (tileheight = 32)
''
'' bit 3 controls chroma mixing into broadcast:
'' 0: mix chroma into broadcast (color)
'' 1: strip chroma from broadcast (black/white)
''
'' bit 2 controls chroma mixing into baseband:
'' 0: mix chroma into baseband (composite color)
'' 1: strip chroma from baseband (black/white or s-video)
''
'' bit 1 controls interlace:
'' 0: progressive scan (243 display lines for NTSC, 286 for PAL)
'' less flicker, good for motion
'' 1: interlaced scan (486 display lines for NTSC, 572 for PAL)
'' doubles the vertical display lines, good for text
''
'' bit 0 selects NTSC or PAL format
'' 0: NTSC
'' 3016 horizontal display ticks
'' 243 or 486 (interlaced) vertical display lines
'' CLKFREQ must be at least 14_318_180 (4 * 3_579_545 Hz)*
'' 1: PAL
'' 3692 horizontal display ticks
'' 286 or 572 (interlaced) vertical display lines
'' CLKFREQ must be at least 17_734_472 (4 * 4_433_618 Hz)*
''
'' * driver will disable itself while CLKFREQ is below requirement
'' _________
'' tv_screen
''
'' pointer to words which define screen contents (left-to-right, top-to-bottom)
'' number of words must be tv_ht * tv_vt
'' each word has two bitfields: a 6-bit colorset ptr and a 10-bit pixelgroup ptr
'' bits 15..10: select the colorset* for the associated pixel tile
'' bits 9..0: select the pixelgroup** address %ppppppppppcccc00 (p=address, c=0..15)
''
'' * colorsets are longs which each define four 8-bit colors
''
'' ** pixelgroups are <tileheight> longs which define (left-to-right, top-to-bottom) the 2-bit
'' (four color) pixels that make up a 16x16 or a 32x32 pixel tile
'' _________
'' tv_colors
''
'' pointer to longs which define colorsets
'' number of longs must be 1..64
'' each long has four 8-bit fields which define colors for 2-bit (four color) pixels
'' first long's bottom color is also used as the screen background color
'' 8-bit color fields are as follows:
'' bits 7..4: chroma data (0..15 = blue..green..red..)*
'' bit 3: controls chroma modulation (0=off, 1=on)
'' bits 2..0: 3-bit luminance level:
'' values 0..1: reserved for sync - don't use
'' values 2..7: valid luminance range, modulation adds/subtracts 1 (beware of 7)
'' value 0 may be modulated to produce a saturated color toggling between levels 1 and 7
''
'' * because of TV's limitations, it doesn't look good when chroma changes abruptly -
'' rather, use luminance - change chroma only against a black or white background for
'' best appearance
'' _____
'' tv_ht
''
'' horizontal number pixel tiles - must be at least 1
'' practical limit is 40 for NTSC, 50 for PAL
'' _____
'' tv_vt
''
'' vertical number of pixel tiles - must be at least 1
'' practical limit is 13 for NTSC, 15 for PAL (26/30 max for interlaced NTSC/PAL)
'' _____
'' tv_hx
''
'' horizontal tile expansion factor - must be at least 3 for NTSC, 4 for PAL
''
'' make sure 16 * tv_ht * tv_hx + ||tv_ho + 32 is less than the horizontal display ticks
'' _____
'' tv_vx
''
'' vertical tile expansion factor - must be at least 1
''
'' make sure <tileheight> * tv_vt * tv_vx + ||tv_vo + 1 is less than the display lines
'' _____
'' tv_ho
''
'' horizontal offset in ticks - pos/neg value (0 for centered image)
'' shifts the display right/left
'' _____
'' tv_vo
''
'' vertical offset in lines - pos/neg value (0 for centered image)
'' shifts the display up/down
'' ____________
'' tv_broadcast
''
'' broadcast frequency expressed in Hz (ie channel 2 is 55_250_000)
'' if 0, modulator is turned off - saves power
''
'' broadcasting requires CLKFREQ to be at least 16_000_000
'' while CLKFREQ is below 16_000_000, modulator will be turned off
'' ___________
'' tv_auralcog
''
'' selects cog to supply aural fm signal - 0..7
'' uses ctra pll output from selected cog
''
'' in NTSC, the offset frequency must be 4.5MHz and the max bandwidth +-25KHz
'' in PAL, the offset frequency and max bandwidth vary by PAL type
{{
+------------------------------------------------------------------------------------------------------------------------------+
¦ 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

@ -1,27 +0,0 @@
_clkfreq = 80_000_000
_clkmode = xtal1 + pll8x
obj
term: "isxtv"
f: "sxfile"
pub CheckFreeCogs | i, x
x~
repeat 8
i := cognew( @nada, 0 )
if i < 0
quit
x |= |< i
repeat i from 0 to 7
if x & |< i
term.str( string("free ") )
cogstop( i )
else
term.str( string("busy ") )
term.out( 13 )
f.Open( string("sphinx.bin"), "R" )
f.Execute( 0 )
dat
org 0
nada
jmp #nada

View File

@ -1,68 +0,0 @@
SXTVRENDEZVOUS = $8000 - 4
SXKBRENDEZVOUS = SXTVRENDEZVOUS - 4
SDSPIRENDEZVOUS = SXKBRENDEZVOUS - 3 * 4
SXFS2RENDEZVOUS = SDSPIRENDEZVOUS - 4 * 4 ' four rendezvous variables
SXFSRENDEZVOUS = SXFS2RENDEZVOUS - 4 * 4 ' four rendezvous variables
METADATABUFFER = SXFSRENDEZVOUS - 512
_free = ($8000 - METADATABUFFER) / 4
obj
term: "isxtv"
kb: "isxkb"
f[2]: "sxfile"
pub main | err
err := \try
if err > 0
term.str( err )
term.out( 13 )
elseif err < 0
term.str( string("error ") )
term.dec( err )
term.out( 13 )
f[0].Close
f[0].Open( string("sphinx.bin"), "R" )
f[0].Execute( 0 )
con
FILENAMELENGTH = 12 ' 8 + . + 3
var
byte srcfilename[FILENAMELENGTH + 1] ' + null
byte dstfilename[FILENAMELENGTH + 1] ' + null
byte optionstring[3]
byte needConfirmation
pri try | length, ch
needConfirmation~~
f[0].Open( string("args.d8a"), "R" )
if f[0].ReadByte <> 2
abort string("usage: source destination")
f[0].ReadString( @srcfilename, FILENAMELENGTH )
f[0].ReadString( @dstfilename, FILENAMELENGTH )
f[0].Close
if f[0].Open( @srcfilename, "R" )
term.str( @srcfilename )
abort string(" -- not found" )
length := f[0].Length
if f[1].Open( @dstfilename, "R" ) == 0
term.str( @dstfilename )
term.str( string(" -- overwrite? ") )
ch := kb.getkey
term.out( ch )
term.out( 13 )
ifnot ch == "y" or ch == "Y"
return
f[1].Close
f[1].Open( @dstfilename, "W" )
repeat length
f[1].WriteByte( f[0].ReadByte ) ' Could probably improve on this
f[1].Close

View File

@ -1,246 +0,0 @@
' 2009-08-08 fixed off-by-one error in try
SXTVRENDEZVOUS = $8000 - 4
SXKBRENDEZVOUS = SXTVRENDEZVOUS - 4
SDSPIRENDEZVOUS = SXKBRENDEZVOUS - 3 * 4
SXFS2RENDEZVOUS = SDSPIRENDEZVOUS - 4 * 4 ' four rendezvous variables
SXFSRENDEZVOUS = SXFS2RENDEZVOUS - 4 * 4 ' four rendezvous variables
METADATABUFFER = SXFSRENDEZVOUS - 512
_free = ($8000 - METADATABUFFER) / 4
obj
term: "isxtv"
kb: "isxkb"
f: "sxfile"
pub main | err
err := \try
if err > 0
term.str( err )
term.out( 13 )
elseif err < 0
term.str( string("error ") )
term.dec( err )
term.out( 13 )
f.Close
f.Open( string("sphinx.bin"), "R" )
f.Execute( 0 )
con
ARGSTRINGLENGTH = 12 ' 8 + . + 3
DIRSTRINGLENGTH = 11 ' 8 + 3
var
byte argstring[ARGSTRINGLENGTH + 1] ' + null
byte dirstring[DIRSTRINGLENGTH + 1] ' + null (terminator not strictly necessary, but convenient for debug printing)
byte optionstring[3]
byte needConfirmation
pri try | nArgs
needConfirmation~~
f.Open( string("args.d8a"), "R" )
if nArgs := f.ReadByte
f.ReadString( @argstring, ARGSTRINGLENGTH )
if nArgs > 1
f.ReadStringUpperCase( @optionstring, 2 )
if strcomp( @optionstring, string("/Y") )
needConfirmation~
else
abort string("No files specified")
f.Close
ExpandWildcards
MyMount
Delete
FlushMetadata
pri ExpandWildcards | i, j
i~
j~
bytefill( @dirstring, " ", DIRSTRINGLENGTH )
dirstring[DIRSTRINGLENGTH]~
repeat while argstring[j]
if argstring[j] == "*"
if i < 8
repeat
dirstring[i++] := "?"
until i == 8
elseif i < 11
repeat
dirstring[i++] := "?"
until i == 11
else
abort string("bad wildcard")
elseif argstring[j] == "."
if i =< 8
i := 8
else
abort string("filename too long")
else
if i < DIRSTRINGLENGTH
dirstring[i++] := argstring[j]
else
abort string("filename too long")
++j
con
pCommand = SDSPIRENDEZVOUS
pParam = pCommand + 4
pBlockno = pCommand + 8
pri readblock(n, b)
'
' Read a single block. The "n" passed in is the
' block number (blocks are 512 bytes); the b passed
' in is the address of 512 blocks to fill with the
' data.
'
long[pParam] := b
long[pBlockno] := n
long[pCommand] := "R"
repeat while long[pCommand]
if long[pParam]
abort long[pParam]
return 0
pub writeblock(n, b)
'
' Write a single block. Mirrors the read above.
'
long[pParam] := b
long[pBlockno] := n
long[pCommand] := "W"
repeat while long[pCommand]
if long[pParam]
abort long[pParam]
return 0
con
SECTORSIZE = 512
SECTORSHIFT = 9
DIRSIZE = 32
DIRSHIFT = 5
con
{ long } _length = 0
{ long } _leftInFile = 4
{ long } _sopDir = 8 ' sector/offset "pointer" to directory entry
{ long } _sopTail = 12 ' sector/offset "pointer" to last cluster# in FAT chain
{ word } _cluster = 16
{ word } _sector = 18 ' sector# within cluster; ranges from 0 to sectorsPerCluster-1
{ word } _bp = 20 ' byte pointer (actually an index into the sector buffer); range [0..511]
_buffer = 24
SIZEOFIOBLOCK = SECTORSIZE + 24
dat
long
myMetadataBuffer byte 0[512]
myMetadataSector word -1
dirty byte 0
clusterShift byte 0
pri FlushMetadata
if dirty~
writeblock( myMetadataSector, @myMetadataBuffer )
pri ReadMetadataSector( s )
if myMetadataSector == s
return
FlushMetadata
readblock( myMetadataSector := s, @myMetadataBuffer )
var
word bytesPerSector
byte sectorsPerCluster
word reservedSectors
byte numberOfFats
word sectorsPerFat
word numberOfRootDirectoryEntries
long fat1[0]
long fatSector0
long dirSector0
long dataregion[0]
long dataSector0
pri Delete | s, p, ch
s := dirSector0
repeat numberOfRootDirectoryEntries >> 4
p := @myMetadataBuffer
repeat 16
ReadMetadataSector( s )
ifnot byte[p]
return
if byte[p] == $e5 ' already deleted?
p += 32
next
if byte[p][$0b] & $0f == 0 and Match( p, @dirstring, 11 )
ifnot needConfirmation
term.str( string("Deleting ") )
repeat 11
term.out( byte[p++] )
p -= 11
term.out( " " )
term.dec( PeekL( p + $1c ) )
if needConfirmation
term.str( string(" -- delete? ") )
ch := kb.getkey
term.out( ch )
else
ch := "y"
if ch == "y" or ch == "Y"
byte[p] := $e5 ' mark as deleted
dirty~~
term.out( 13 )
p += 32
++s
FlushMetadata
pri Match( p, q, n ) | c1, c2
repeat n
c1 := byte[p++]
c2 := byte[q++]
if "a" =< c1 and c1 =< "z"
c1 += "A" - "a"
if "a" =< c2 and c2 =< "z"
c2 += "A" - "a"
if c2 == "?"
next
if c1 <> c2
return false
return true
pri MyMount | pbrSector ,i
pbrSector~
repeat
ReadMetadataSector( pbrSector )
if bytecomp( @myMetadataBuffer+$36, string("FAT16"), 5 )
quit
if pbrSector
abort -20 ' not FAT16
pbrSector := PeekL( @myMetadataBuffer + $1c6 )
bytesPerSector := PeekW( @myMetadataBuffer + $0b )
sectorsPerCluster := myMetadataBuffer[$0d]
clusterShift := >| sectorsPerCluster - 1
reservedSectors := PeekW( @myMetadataBuffer + $0e )
numberOfFats := myMetadataBuffer[$10]
sectorsPerFat := PeekW( @myMetadataBuffer + $16 )
numberOfRootDirectoryEntries := PeekW( @myMetadataBuffer + $11 )
fatSector0 := pbrSector + reservedSectors
dirSector0 := fatSector0 + numberOfFats * sectorsPerFat
dataSector0 := dirSector0 + numberOfRootDirectoryEntries >> 4
pri bytecomp( p, q, n )
repeat n
if byte[p++] <> byte[q++]
return
return true
pri PeekW( a )
return byte[a++] + byte[a] << 8
pri PeekL( a )
return byte[a++] + byte[a++] << 8 + byte[a++] << 16 + byte[a] << 24

View File

@ -1,220 +0,0 @@
' 2009-08-08 fixed off-by-one error in try
SXTVRENDEZVOUS = $8000 - 4
SXKBRENDEZVOUS = SXTVRENDEZVOUS - 4
SDSPIRENDEZVOUS = SXKBRENDEZVOUS - 3 * 4
SXFS2RENDEZVOUS = SDSPIRENDEZVOUS - 4 * 4 ' four rendezvous variables
SXFSRENDEZVOUS = SXFS2RENDEZVOUS - 4 * 4 ' four rendezvous variables
METADATABUFFER = SXFSRENDEZVOUS - 512
_free = ($8000 - METADATABUFFER) / 4
obj
term: "isxtv"
f: "sxfile"
pub main | err
err := \try
if err > 0
term.str( err )
term.out( 13 )
elseif err < 0
term.str( string("error ") )
term.dec( err )
term.out( 13 )
f.Close
f.Open( string("sphinx.bin"), "R" )
f.Execute( 0 )
con
ARGSTRINGLENGTH = 12 ' 8 + . + 3
DIRSTRINGLENGTH = 11 ' 8 + 3
var
byte argstring[ARGSTRINGLENGTH + 1] ' + null
byte dirstring[DIRSTRINGLENGTH + 1] ' + null (terminator not strictly necessary, but convenient for debug printing)
pri try
f.Open( string("args.d8a"), "R" )
if f.ReadByte
f.ReadString( @argstring, ARGSTRINGLENGTH )
else
bytemove( @argstring, string("*.*"), 4 )
f.Close
ExpandWildcards
MyMount
PrintDir
pri ExpandWildcards | i, j
i~
j~
bytefill( @dirstring, " ", DIRSTRINGLENGTH )
dirstring[DIRSTRINGLENGTH]~
repeat while argstring[j]
if argstring[j] == "*"
if i < 8
repeat
dirstring[i++] := "?"
until i == 8
elseif i < 11
repeat
dirstring[i++] := "?"
until i == 11
else
abort string("bad wildcard")
elseif argstring[j] == "."
if i =< 8
i := 8
else
abort string("filename too long")
else
if i < DIRSTRINGLENGTH
dirstring[i++] := argstring[j]
else
abort string("filename too long")
++j
con
pCommand = SDSPIRENDEZVOUS
pParam = pCommand + 4
pBlockno = pCommand + 8
pri readblock(n, b)
'
' Read a single block. The "n" passed in is the
' block number (blocks are 512 bytes); the b passed
' in is the address of 512 blocks to fill with the
' data.
'
long[pParam] := b
long[pBlockno] := n
long[pCommand] := "R"
repeat while long[pCommand]
if long[pParam]
abort long[pParam]
return 0
pub writeblock(n, b)
'
' Write a single block. Mirrors the read above.
'
long[pParam] := b
long[pBlockno] := n
long[pCommand] := "W"
repeat while long[pCommand]
if long[pParam]
abort long[pParam]
return 0
con
SECTORSIZE = 512
SECTORSHIFT = 9
DIRSIZE = 32
DIRSHIFT = 5
con
{ long } _length = 0
{ long } _leftInFile = 4
{ long } _sopDir = 8 ' sector/offset "pointer" to directory entry
{ long } _sopTail = 12 ' sector/offset "pointer" to last cluster# in FAT chain
{ word } _cluster = 16
{ word } _sector = 18 ' sector# within cluster; ranges from 0 to sectorsPerCluster-1
{ word } _bp = 20 ' byte pointer (actually an index into the sector buffer); range [0..511]
_buffer = 24
SIZEOFIOBLOCK = SECTORSIZE + 24
dat
long
myMetadataBuffer byte 0[512]
myMetadataSector word -1
dirty byte 0
clusterShift byte 0
pri ReadMetadataSector( s )
if myMetadataSector == s
return
readblock( myMetadataSector := s, @myMetadataBuffer )
var
word bytesPerSector
byte sectorsPerCluster
word reservedSectors
byte numberOfFats
word sectorsPerFat
word numberOfRootDirectoryEntries
long fat1[0]
long fatSector0
long dirSector0
long dataregion[0]
long dataSector0
pri PrintDir | s, p, c
s := dirSector0
repeat numberOfRootDirectoryEntries >> 4
p := @myMetadataBuffer
repeat 16
ReadMetadataSector( s )
ifnot byte[p]
return
if byte[p] == $e5
p += 32
next
if byte[p][$0b] & $0f == 0 and Match( p, @dirstring, 11 )
repeat 11
term.out( byte[p++] )
p -= 11
term.out( " " )
term.dec( PeekL( p + $1c ) )
term.out( 13 )
p += 32
++s
pri Match( p, q, n ) | c1, c2
repeat n
c1 := byte[p++]
c2 := byte[q++]
if "a" =< c1 and c1 =< "z"
c1 += "A" - "a"
if "a" =< c2 and c2 =< "z"
c2 += "A" - "a"
if c2 == "?"
next
if c1 <> c2
return false
return true
pri MyMount | pbrSector ,i
pbrSector~
repeat
ReadMetadataSector( pbrSector )
if bytecomp( @myMetadataBuffer+$36, string("FAT16"), 5 )
quit
if pbrSector
abort -20 ' not FAT16
pbrSector := PeekL( @myMetadataBuffer + $1c6 )
bytesPerSector := PeekW( @myMetadataBuffer + $0b )
sectorsPerCluster := myMetadataBuffer[$0d]
clusterShift := >| sectorsPerCluster - 1
reservedSectors := PeekW( @myMetadataBuffer + $0e )
numberOfFats := myMetadataBuffer[$10]
sectorsPerFat := PeekW( @myMetadataBuffer + $16 )
numberOfRootDirectoryEntries := PeekW( @myMetadataBuffer + $11 )
fatSector0 := pbrSector + reservedSectors
dirSector0 := fatSector0 + numberOfFats * sectorsPerFat
dataSector0 := dirSector0 + numberOfRootDirectoryEntries >> 4
pri bytecomp( p, q, n )
repeat n
if byte[p++] <> byte[q++]
return
return true
pri PeekW( a )
return byte[a++] + byte[a] << 8
pri PeekL( a )
return byte[a++] + byte[a++] << 8 + byte[a++] << 16 + byte[a] << 24

View File

@ -1,41 +0,0 @@
_clkfreq = 80_000_000
_clkmode = xtal1 + pll8x
obj
term: "isxtv"
f: "sxfile"
pub Main | e
Err( \Echo )
Err( \Bye )
pri Err( e )
ifnot e
return
if e < 0
term.str( string("Error ") )
term.dec( e )
else
term.str( e )
term.out( 13 )
con MAXARGSSIZE = 40
pub Echo | p, n
if f.Open( string("args.d8a"), "R" ) <> 0
return
n := f.ReadByte
term.dec( n )
term.str( string(" args", 13) )
f.Read( @buffer, MAXARGSSIZE )
f.Close
p := @buffer
repeat while byte[p]
term.str( p )
term.out( 13 )
p += strsize(p) + 1
pub Bye
f.Open( string("sphinx.bin"), "R" )
f.Execute( 0 )
var byte buffer[MAXARGSSIZE]

View File

@ -1,569 +0,0 @@
{
Simple text editor
2009
March
5 started; basic screen drawing; cursor movement
6 InsertChar, InsertCR, DeleteLeft/Right
6 filename edit field
6 file load, save
June
9 Sphinxified
30 Page up/down, minor cursor movement improvement
2010
January
29 Bug: Was dropping last character when reading a file that didn't end with CR/LF. Fixed.
ENTER(CR) Carriage return
BKSP Delete to the left
DEL Delete to the right
?, ?, ?, ? Cursor movement
HOME Start of line
CTRL-HOME Start of file
END End of line
CTRL-END End of file
CTRL-O Open a file
CTRL-S Save to a file
CTRL-Q Quit to Sphinx
PGUP Page up
PGDN Page down
to do:
block select, cut/copy/paste, find/replace, undo/redo
}
obj
kb: "isxkb"
sxtv: "isxtv"
term: "tvtexted"
sd: "sxfile"
var
byte x[10]
pub Main | e
if e := \Try
if e > 0
sxtv.str( e )
else
sxtv.dec( e )
sxtv.out( 13 )
term.stop
sxtv.Enable
pub Try | i, key, refresh, blink, t, done
sxtv.Disable
term.start( sxtv.GetBasepin )
Init
Args
done~
blink~
t := cnt
repeat
refresh~
repeat while key := kb.key
refresh~~
blink~
case key
$20..$7f: InsertChar( key )
CR: InsertCR
BKSP: DeleteLeft
DEL: DeleteRight
LARROW: MoveCursorLeft
RARROW: MoveCursorRight
UARROW: MoveCursorUp( false )
DARROW: MoveCursorDown( false )
HOME: MoveToStartOfLine
CTRL+HOME: MoveToTop
END: MoveToEndOfLine
CTRL+END: MoveToBottom
CTRL+"o": FileOp( OPEN, FALSE )
CTRL+"s": FileOp( SAVE, FALSE )
CTRL+"q": FileOp( SAVE, FALSE )
done~~
PGUP: PageCursorUp
PGDN: PageCursorDown
other: refresh~
if cnt - t > 0
refresh~~
if refresh
RefreshScreen( blink ^= 1 )
t := cnt + clkfreq/10
until done
term.stop
sxtv.Enable
sd.Close
sd.Open( string("sphinx.bin"), "R" )
sd.Execute( 0 )
pri Args
if sd.Open( string("args.d8a"), "R" ) == 0
if sd.ReadByte
sd.ReadString( @filename, FILENAMEBUFFERSIZE-1 )
sd.Close
FileOp( OPEN, true )
sd.Close
con
VISIBLELINES = 13
VISIBLECOLUMNS = 40
con
CR = $0d
LARROW = $c0
RARROW = $c1
UARROW = $c2
DARROW = $c3
HOME = $c4
END = $c5
PGUP = $c6
PGDN = $c7
BKSP = $c8
DEL = $c9
ESC = $cb
CTRL = $0200
CTRL_ALT_DEL = $06c9
con
BUFFERSIZE = 20000
var
long nLines
long firstVisibleLine
long firstVisibleColumn
long bytesUsed
long cursorLine
long cursorColumn
long desiredColumn
long cp
long currentLineLength
long topPtr ' points to start of first visible line
pri InsertChar( ch ) | n
if cursorLine < nLines
if bytesUsed + 1 => BUFFERSIZE
return
else ' starting new line at end of file
if bytesUsed + 2 => BUFFERSIZE
return
buffer[bytesUsed++]~ ' terminating null for the new line
++nLines
n := bytesUsed - (cp - @buffer)
bytemove( cp+1, cp, n )
byte[cp] := ch
++bytesUsed
++currentLineLength
MoveCursorRight
pri InsertCR | n
if cursorLine < nLines
if bytesUsed + 1 => BUFFERSIZE
return
else ' starting new line at end of file
if bytesUsed + 2 => BUFFERSIZE
return
buffer[bytesUsed++]~ ' terminating null for the new line
++nLines
n := bytesUsed - (cp - @buffer)
bytemove( cp+1, cp, n )
byte[cp]~
++bytesUsed
++nLines
currentLineLength := cursorColumn
MoveCursorRight
pri DeleteLeft
if cursorLine or cursorColumn
MoveCursorLeft
DeleteRight
pri DeleteRight | n
if cursorLine == nLines ' can't delete if we're on the phantom line
return
if byte[cp] == 0 and cursorLine == nLines - 1 and cursorColumn
return ' can't delete if we're at the end of the last real line
' unless we're at the start (start = end => empty line
' which we can delete, making this line the new phantom line)
n := bytesUsed - (cp - @buffer) - 1
ifnot byte[cp]
--nLines
bytemove( cp, cp+1, n )
--bytesUsed
repeat while byte[--cp]
currentLineLength := strsize( ++cp )
cp += cursorColumn
AdjustVisibleColumn
pri MoveCursorLeft
if cursorColumn
desiredColumn := --cursorColumn
--cp
AdjustVisibleColumn
else
ifnot cursorLine
return
MoveCursorUp( true )
pri MoveCursorRight
if cursorColumn < currentLineLength
desiredColumn := ++cursorColumn
++cp
AdjustVisibleColumn
else
if cursorLine == nLines
return
MoveCursorDown( true )
pri MoveCursorDown( f )
' if f, also move cursor to start of line
if cursorLine == nLines
return
if ++cursorLine - firstVisibleLine => VISIBLELINES
++firstVisibleLine
repeat while byte[topPtr++]
MoveCpToNextLine
if f
cursorColumn~
desiredColumn~
elseif cursorLine < nLines
cursorColumn := currentLineLength <# desiredColumn
else
cursorColumn~
currentLineLength~
cp += cursorColumn
AdjustVisibleColumn
pri PageCursorDown
if firstVisibleLine + VISIBLELINES - 1 => nLines
return
repeat VISIBLELINES - 1
repeat while byte[topPtr++]
++firstVisibleLine
MoveCursorDown( false )
pri MoveCursorUp( f )
' if f, also move cursor to end of line
ifnot cursorLine
return
if --cursorLine < firstVisibleLine
--firstVisibleLine
repeat while byte[--topPtr]
repeat while byte[--topPtr]
++topPtr
MoveCpToPreviousLine
if f
cursorColumn := desiredColumn := currentLineLength
else
cursorColumn := currentLineLength <# desiredColumn
cp += cursorColumn
AdjustVisibleColumn
pri PageCursorUp | n
n := firstVisibleLine <# VISIBLELINES - 1
repeat n
repeat 2
repeat while byte[--topPtr]
++topPtr
--firstVisibleLine
MoveCursorUp( false )
pri MoveCpToNextLine
repeat while byte[cp++]
currentLineLength := strsize( cp )
pri MoveCpToPreviousLine
repeat while byte[--cp]
repeat while byte[--cp]
++cp
currentLineLength := strsize( cp )
pri MoveToStartOfLine
cp -= cursorColumn
cursorColumn~
desiredColumn~
AdjustVisibleColumn
pri MoveToEndOfLine
cp -= cursorColumn
cursorColumn := desiredColumn := currentLineLength
cp += currentLineLength
AdjustVisibleColumn
pri MoveToTop
cp := topPtr := @buffer[1]
currentLineLength := strsize( cp )
cursorLine~
cursorColumn~
desiredColumn~
firstVisibleLine~
firstVisibleColumn~
pri MoveToBottom ' cheesy implementation
MoveToTop
if nLines
repeat nLines-1
MoveCursorDown( false )
MoveToEndOfLine
pri AdjustVisibleColumn
firstVisibleColumn~
firstVisibleColumn #>= cursorColumn - VISIBLECOLUMNS + 1
var
byte buffer[BUFFERSIZE]
{ buffer contains nLines null-terminated strings, with sentinel nulls at the beginning and end:
+-+---------+-+--------+-+- ---------+-+-+
¦0¦ line0 0¦ line1 0¦ ... lineN-1 0¦0¦
+-+---------+-+--------+-+- ---------+-+-+
}
pri Init
nLines~
firstVisibleLine~
firstVisibleColumn~
bytesUsed := 2
buffer[0]~
buffer[1]~
cursorLine~
cursorColumn~
desiredColumn~
currentLineLength~
cp := topPtr := @buffer[1]
eolLength := 2
eol[0] := $0d
eol[1] := $0a
pri RefreshScreen( drawCursor ) | p, len, m, n, l, beyondEnd
p := topPtr
beyondEnd~
repeat l from 0 to VISIBLELINES-1
term.setXY( 0, l )
if firstVisibleLine + l => nLines
beyondEnd~~
len~
else
len := strsize( p )
if len > firstVisibleColumn
m := (len - firstVisibleColumn) <# VISIBLECOLUMNS
p += firstVisibleColumn
repeat m-1
term.out( byte[p++] )
term.printNoAdvance( byte[p++] )
term.setX( m )
n := VISIBLECOLUMNS - m
if n
repeat n-1
term.out( " " )
term.printNoAdvance( " " )
else
repeat VISIBLECOLUMNS-1
term.out( " " )
term.printNoAdvance( " " )
ifnot beyondEnd
repeat while byte[p++]
if drawCursor
term.setXY( cursorColumn-firstVisibleColumn, cursorLine-firstVisibleLine )
term.printNoAdvance( "_" )
con
#0, OPEN, SAVE ' File ops
' File errors
#1, FILE_TOO_BIG, CARD_FULL_MAYBE
FILENAMEBUFFERSIZE = 13 ' 8.3 + null
pri FileOp( op, t ) | e, i
if e := \_FileOp( op, t )
RefreshScreen( false ) ' cursor off
term.setXY( 0, VISIBLELINES-1 )
term.out( $0c ) ' set color
term.out( 1 )
repeat VISIBLECOLUMNS-1
term.out( " " )
term.printNoAdvance( " " )
term.setX( 0 )
case e
FILE_TOO_BIG: term.str( string("File too large") )
CARD_FULL_MAYBE: term.str( string("SD card full?") )
-13: term.str( string("Unable to mount SD card") )
other:
term.str( string("Error code ") )
term.dec( e )
kb.getkey
term.out( $0c ) ' set color
term.out( 0 )
pri _FileOp( op, t ) | r
case op
OPEN:
if t
ReadFile
elseif EditFilename
ReadFile
SAVE:
WriteFile
pri ReadFile | r, p, pEnd
sd.Close
if r := sd.Open( @filename, "R" ) <> 0
abort r
Init
r := sd.Read( @buffer[1], BUFFERSIZE-2 )
if r < 0
abort r
p := @buffer[1]
pEnd := @buffer[r+1]
repeat while p <> pEnd
if byte[p] == $0d or byte[p] == $0a ' change CR, LF, or CRLF
if byte[p] == $0d and byte[p+1] == $0a '
eolLength := 2 '
bytemove( p, p + 1, pEnd - p - 1 ) '
--pEnd '
else '
eolLength := 1 '
byte[p]~ ' to null
++nLines
++p
if byte[pEnd-1] ' if byte[pEnd-1] isn't null, that means that the file didn't
byte[pEnd++]~ ' end with CR, LF, or CRLF, so we have to fake it. (fixed 2010/01/29 mp)
++nLines
byte[pEnd]~ ' add final null
bytesUsed := pEnd + 1 - @buffer
currentLineLength := strsize( topPtr )
if r == BUFFERSIZE-2
abort FILE_TOO_BIG ' technically we don't know that it's too big at this point, but it's a good guess.
if r := sd.Close
abort r
pri WriteFile | p, len, r
ifnot EditFilename
return
sd.Close
if r := sd.Open( @filename, "W" )
abort r
p := @buffer[1]
repeat nLines
len := strsize( p )
r := sd.Write( p, len )
if r < 0
abort r
if r <> len ' Does this ever happen?
abort CARD_FULL_MAYBE
r := sd.Write( @eol, eolLength )
if r < 0
abort r
if r <> eolLength ' Does this ever happen?
abort CARD_FULL_MAYBE
p += len + 1
if (r := sd.Close) < 0
abort r
var
byte filename[FILENAMEBUFFERSIZE]
long filenameCursorColumn
long filenameLength
byte eolLength
byte eol[2]
con
EDITOFFSET = 10 ' filename edit field starts at column 10
pri EditFilename | t, key, blink, refresh
RefreshScreen( false ) ' cursor off
term.setXY( 0, VISIBLELINES-1 )
term.out( $0c ) ' set color
term.out( 2 )
repeat VISIBLECOLUMNS-1
term.out( " " )
term.printNoAdvance( " " )
term.setX( 0 )
term.str( string("Filename: ") )
filenameCursorColumn := filenameLength := strsize( @filename )
blink~
t := cnt
repeat
refresh~
repeat while key := kb.key
refresh~~
blink~
case key
$20..$7f: FilenameInsertChar( key )
CR:
term.out( $0c ) ' set color
term.out( 0 ) ' back to normal
return true
BKSP:
if filenameCursorColumn
filenameCursorColumn := (filenameCursorColumn - 1) #> 0
FilenameDeleteRight
DEL: FilenameDeleteRight
LARROW: filenameCursorColumn := (filenameCursorColumn - 1) #> 0
RARROW: filenameCursorColumn := (filenameCursorColumn + 1) <# filenameLength
ESC:
term.out( $0c ) ' set color
term.out( 0 ) ' back to normal
return false
other: refresh~
if cnt - t > 0
refresh~~
if refresh
RefreshFilename( blink ^= 1 )
t := cnt + clkfreq/10
pri RefreshFilename( drawCursor ) | i
term.setXY( EDITOFFSET, VISIBLELINES-1 )
repeat i from 0 to FILENAMEBUFFERSIZE-1
if drawCursor and i == filenameCursorColumn
term.out( "_" )
else
if i < filenameLength
term.out( filename[i] )
else
term.out( " " )
pri FilenameInsertChar( ch ) | n
if filenameLength => FILENAMEBUFFERSIZE-1
return
n := filenameLength - filenameCursorColumn + 1
bytemove( @filename[filenameCursorColumn+1], @filename[filenameCursorColumn], n )
++filenameLength
filename[filenameCursorColumn++] := ch
pri FilenameDeleteRight | n
ifnot filenameLength
return
ifnot n := filenameLength - filenameCursorColumn
return
bytemove( @filename[filenameCursorColumn], @filename[filenameCursorColumn+1], n )
--filenameLength
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,246 +0,0 @@
''*****************************
''* Graphics Demo v1.0 *
''* (C) 2005 Parallax, Inc. *
''*****************************
CON
_clkmode = xtal1 + pll8x
_xinfreq = 10_000_000 + 0000
_stack = ($3000 + $3000 + 100) >> 2 'accomodate display memory and stack
x_tiles = 16
y_tiles = 12
paramcount = 14
bitmap_base = $2000
display_base = $5000
lines = 5
thickness = 2
VAR
long mousex, mousey
long tv_status '0/1/2 = off/visible/invisible read-only
long tv_enable '0/? = off/on write-only
long tv_pins '%ppmmm = pins write-only
long tv_mode '%ccinp = chroma,interlace,ntsc/pal,swap write-only
long tv_screen 'pointer to screen (words) write-only
long tv_colors 'pointer to colors (longs) write-only
long tv_hc 'horizontal cells write-only
long tv_vc 'vertical cells write-only
long tv_hx 'horizontal cell expansion write-only
long tv_vx 'vertical cell expansion write-only
long tv_ho 'horizontal offset write-only
long tv_vo 'vertical offset write-only
long tv_broadcast 'broadcast frequency (Hz) write-only
long tv_auralcog 'aural fm cog write-only
word screen[x_tiles * y_tiles]
long colors[64]
byte x[lines]
byte y[lines]
byte xs[lines]
byte ys[lines]
OBJ
tv : "tv"
gr : "graphics"
mouse : "mouseiso"
PUB start | i, j, k, kk, dx, dy, pp, pq, rr, numx, numchr
'start tv
longmove(@tv_status, @tvparams, paramcount)
tv_screen := @screen
tv_colors := @colors
tv.start(@tv_status)
'init colors
repeat i from 0 to 64
colors[i] := $00001010 * (i+4) & $F + $2B060C02
'init tile screen
repeat dx from 0 to tv_hc - 1
repeat dy from 0 to tv_vc - 1
screen[dy * tv_hc + dx] := display_base >> 6 + dy + dx * tv_vc + ((dy & $3F) << 10)
'init bouncing lines
i := 1001
j := 123123
k := 8776434
repeat i from 0 to lines - 1
x[i] := ?j // 64
y[i] := k? // 48
repeat until xs[i] := k? ~> 29
repeat until ys[i] := ?j ~> 29
'start and setup graphics
gr.start
gr.setup(16, 12, 128, 96, bitmap_base)
'start mouse
mouse.start(2)
repeat
'clear bitmap
gr.clear
'draw falling stars
gr.colorwidth(1,0)
kk := 100000
repeat 8
gr.vec(?kk & $FF - 128, (kk>>8 - k<<2) & $FF - 128, kk>>16 & $3F #> 20, kk->24 + k<<7, @vecdef2)
'draw spinning triangles
gr.colorwidth(3,0)
repeat i from 1 to 8
gr.vec(0, 0, (k & $7F) << 3 + i << 5, k << 6 + i << 8, @vecdef)
'draw expanding mouse crosshairs
gr.colorwidth(2,k>>2)
mousex := mousex + mouse.delta_x #> -128 <# 127
mousey := mousey + mouse.delta_y #> -96 <# 95
gr.pix(mousex, mousey, k>>4 & $7, @pixdef)
'if left mouse button pressed, throw snowballs
if mouse.button(0)
gr.width(pq & $F)
gr.color(2)
pp := (pq & $F)*(pq & $F) + 5
pq++
gr.arc(mousex, mousey, pp, pp>>1, -k * 200, $200, 8, 0)
else
pq~
'if right mouse button pressed, pause
repeat while mouse.button(1)
'draw expanding pixel halo
gr.colorwidth(1,k)
gr.arc(0,0,80,30,-k<<5,$2000/9,9,0)
'step bouncing lines
repeat i from 0 to lines - 1
if ||~x[i] > 60
-xs[i]
if ||~y[i] > 40
-ys[i]
x[i] += xs[i]
y[i] += ys[i]
'draw bouncing lines
gr.colorwidth(1,thickness)
gr.plot(~x[0], ~y[0])
repeat i from 1 to lines - 1
gr.line(~x[i],~y[i])
gr.line(~x[0], ~y[0])
'draw spinning stars and revolving crosshairs and dogs
gr.colorwidth(2,0)
repeat i from 0 to 7
gr.vecarc(80,50,30,30,-(i<<10+k<<6),$40,-(k<<7),@vecdef2)
gr.pixarc(-80,-40,30,30,i<<10+k<<6,0,@pixdef2)
gr.pixarc(-80,-40,20,20,-(i<<10+k<<6),0,@pixdef)
'draw small box with text
gr.colorwidth(1,14)
gr.box(60,-80,60,16)
gr.textmode(1,1,6,5)
gr.colorwidth(2,0)
gr.text(90,-72,@pchip)
'draw incrementing digit
if not ++numx & 3
numchr++
if numchr < "0" or numchr > "9"
numchr := "0"
gr.textmode(8,8,6,5)
gr.colorwidth(1,8)
gr.text(-90,50,@numchr)
'copy bitmap to display
gr.copy(display_base)
'increment counter that makes everything change
k++
DAT
tvparams long 0 'status
long 1 'enable
long %011_0000 'pins
long %0000 'mode
long 0 'screen
long 0 'colors
long x_tiles 'hc
long y_tiles 'vc
long 10 'hx
long 1 'vx
long 0 'ho
long 0 'vo
long 60_000_000'_xinfreq<<4 'broadcast
long 0 'auralcog
vecdef word $4000+$2000/3*0 'triangle
word 50
word $8000+$2000/3*1+1
word 50
word $8000+$2000/3*2-1
word 50
word $8000+$2000/3*0
word 50
word 0
vecdef2 word $4000+$2000/12*0 'star
word 50
word $8000+$2000/12*1
word 20
word $8000+$2000/12*2
word 50
word $8000+$2000/12*3
word 20
word $8000+$2000/12*4
word 50
word $8000+$2000/12*5
word 20
word $8000+$2000/12*6
word 50
word $8000+$2000/12*7
word 20
word $8000+$2000/12*8
word 50
word $8000+$2000/12*9
word 20
word $8000+$2000/12*10
word 50
word $8000+$2000/12*11
word 20
word $8000+$2000/12*0
word 50
word 0
pixdef word 'crosshair
byte 2,7,3,3
word %%00333000,%%00000000
word %%03020300,%%00000000
word %%30020030,%%00000000
word %%32222230,%%00000000
word %%30020030,%%02000000
word %%03020300,%%22200000
word %%00333000,%%02000000
pixdef2 word 'dog
byte 1,4,0,3
word %%20000022
word %%02222222
word %%02222200
word %%02000200
pchip byte "Propeller",0 'text

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
_xinfreq = 6_000_000
_clkmode = xtal1 + pll16x
vidpin = 24
obj term : "tv_text"
pub Main
term.start( vidpin )
term.str( string("Howdy, <your name>") )
waitcnt( clkfreq*2 + cnt )
reboot

View File

@ -1,11 +0,0 @@
obj
term : "isxtv"
f : "sxfile"
pub Main
term.str( string("Howdy, <your name>") )
term.out( 13 )
f.Open( string("sphinx.bin"), "R" )
f.Execute( 0 )

View File

@ -1,245 +0,0 @@
''***************************************
''* TV Text 40x13 v1.0 *
''* Author: Chip Gracey *
''* Copyright (c) 2006 Parallax, Inc. *
''* See end of file for terms of use. *
''***************************************
' Modified for ed by Michael Park
CON
cols = 40
rows = 13
screensize = cols * rows
lastrow = screensize - cols
tv_count = 14
VAR
long col, row, color, flag
word screen[screensize]
long colors[8 * 2]
long tv_status '0/1/2 = off/invisible/visible read-only (14 longs)
long tv_enable '0/non-0 = off/on write-only
long tv_pins '%pppmmmm = pin group, pin group mode write-only
long tv_mode '%tccip = tile,chroma,interlace,ntsc/pal write-only
long tv_screen 'pointer to screen (words) write-only
long tv_colors 'pointer to colors (longs) write-only
long tv_ht 'horizontal tiles write-only
long tv_vt 'vertical tiles write-only
long tv_hx 'horizontal tile expansion write-only
long tv_vx 'vertical tile expansion write-only
long tv_ho 'horizontal offset write-only
long tv_vo 'vertical offset write-only
long tv_broadcast 'broadcast frequency (Hz) write-only
long tv_auralcog 'aural fm cog write-only
OBJ
tv : "tv"
PUB start(basepin) : okay
'' Start terminal - starts a cog
'' returns false if no cog available
setcolors(@palette)
out(0)
longmove(@tv_status, @tv_params, tv_count)
tv_pins := (basepin & $38) << 1 | (basepin & 4 == 4) & %0101
tv_screen := @screen
tv_colors := @colors
okay := tv.start(@tv_status)
PUB stop
'' Stop terminal - frees a cog
tv.stop
PUB str(stringptr)
'' Print a zero-terminated string
repeat strsize(stringptr)
out(byte[stringptr++])
PUB dec(value) | i
'' Print a decimal number
if value < 0
-value
out("-")
i := 1_000_000_000
repeat 10
if value => i
out(value / i + "0")
value //= i
result~~
elseif result or i == 1
out("0")
i /= 10
PUB hex(value, digits)
'' Print a hexadecimal number
value <<= (8 - digits) << 2
repeat digits
out(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
PUB bin(value, digits)
'' Print a binary number
value <<= 32 - digits
repeat digits
out((value <-= 1) & 1 + "0")
PUB out(c) | i, k
'' Output a character
''
'' $00 = clear screen
'' $01 = home
'' $08 = backspace
'' $09 = tab (8 spaces per)
'' $0A = set X position (X follows)
'' $0B = set Y position (Y follows)
'' $0C = set color (color follows)
'' $0D = return
'' others = printable characters
case flag
$00: case c
$00: wordfill(@screen, $220, screensize)
col := row := 0
$01: col := row := 0
$08: if col
col--
$09: repeat
print(" ")
while col & 7
$0A..$0C: flag := c
return
$0D: newline
other: print(c)
$0A: col := c // cols
$0B: row := c // rows
$0C: color := c & 7
flag := 0
PUB setcolors(colorptr) | i, fore, back
'' Override default color palette
'' colorptr must point to a list of up to 8 colors
'' arranged as follows:
''
'' fore back
'' ------------
'' palette byte color, color 'color 0
'' byte color, color 'color 1
'' byte color, color 'color 2
'' ...
repeat i from 0 to 7
fore := byte[colorptr][i << 1]
back := byte[colorptr][i << 1 + 1]
colors[i << 1] := fore << 24 + back << 16 + fore << 8 + back
colors[i << 1 + 1] := fore << 24 + fore << 16 + back << 8 + back
PUB printNoAdvance(c) ' mpark
screen[row * cols + col] := (color << 1 + c & 1) << 10 + $200 + c & $FE
PUB SetXY( x, y ) ' mpark
col := x
row := y
PUB SetX( x ) ' mpark
col := x
PUB SetY( y ) ' mpark
row := y
PRI print(c)
screen[row * cols + col] := (color << 1 + c & 1) << 10 + $200 + c & $FE
if ++col == cols
newline
PRI newline | i
col := 0
if ++row == rows
row--
wordmove(@screen, @screen[cols], lastrow) 'scroll lines
wordfill(@screen[lastrow], $220, cols) 'clear new line
DAT
tv_params long 0 'status
long 1 'enable
long 0 'pins
long %10010 'mode
long 0 'screen
long 0 'colors
long cols 'hc
long rows 'vc
long 4 'hx
long 1 'vx
long 0 'ho
long 0 'vo
long 0 'broadcast
long 0 'auralcog
' fore back
' color color
palette byte $07, $0A '0 white / dark blue
byte $07, $BB '1 white / red
byte $9E, $9B '2 yellow / brown
byte $04, $07 '3 grey / white
byte $3D, $3B '4 cyan / dark cyan
byte $6B, $6E '5 green / gray-green
byte $BB, $CE '6 red / pink
byte $3C, $0A '7 cyan / blue
{{
+------------------------------------------------------------------------------------------------------------------------------+
¦ 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

@ -1,238 +0,0 @@
obj
str: "stringx"
dat
cog long 0
pub Init( p0, p1 )
pFree := p0 ' leave some room for the stack, then free space.
pLimit := p1
Stop
sync~~
cog := cognew( @LookerUpper, @input ) + 1
ifnot cog
abort string("Couldn't start bintree cog")
repeat while sync
pub Stop
if cog
cogstop( cog~ - 1 )
pub FindInTable( s, p ) | d
{{
Finds string s in table pointed to by p.
Returns pointer to s's data area if s is found, 0 otherwise.
}}
input[0] := s
input[1] := p
sync~~
repeat while sync
return output
{
ifnot p
return 0
d := str.Compare( s, p+4 )
ifnot d
return p + 4 + strsize(s) + 1
if d < 0
return FindInTable( s, Peekw(p) )
' else
return FindInTable( s, Peekw(p+2) )
}
pub AddToTable( s, pP ) | p, d
{{
Adds string s to table. Note: pP is a pointer-to-pointer to table.
Returns a pointer to s's data area (actually pFree, so if you add
any data, increment pFree past it).
}}
ifnot p := PeekW( pP )
PokeW( pP, pFree )
PokeW( pFree, 0 )
pFree += 2
PokeW( pFree, 0 )
pFree += 2
str.Copy( pFree, s )
pFree += strsize(s) + 1
return pFree
d := str.Compare( s, p+4 )
{
term.dec(d)
term.out(13)
waitcnt( clkfreq + cnt )
}
ifnot d
abort string("Symbol already defined")
if d < 0
return AddToTable( s, @word[p][0] )
' else
return AddToTable( s, @word[p][1] )
pub PeekW( p )
return byte[p++] + byte[p] << 8
pub PokeW( p, w )
byte[p++] := w
byte[p] := w >> 8
pub PeekL( p ) : t
repeat 4
t := (t | byte[p++]) -> 8
pub PokeL( p, l )
repeat 4
byte[p++] := l
l >>= 8
dat
pFree long 0
pLimit long 0
pub Alloc( n )
result := pFree
if (pFree += n) > pLimit
abort string("Out of symbol table space")
dat
input long 0 ' rendezvous variables for LookerUpper
output long 0
sync long 1
{
This PASM routine is equivalent to the following:
pub FindInTable( s, p ) | d
{{
Finds string s in table pointed to by p.
Returns pointer to s's data area if s is found, 0 otherwise.
}}
ifnot p
return 0
d := str.Compare( s, p+4 )
ifnot d
return p + 4 + strsize(s) + 1
if d < 0
return FindInTable( s, Peekw(p) )
' else
return FindInTable( s, Peekw(p+2) )
}
dat org 0
LookerUpper
mov pInput, par ' Enter with par pointing to rendezvous area,
mov pOutput, par ' sync = 1
add pOutput, #4
mov pSync, par
add pSync, #8
rdlong pTable, pInput ' Save @tableStart
' and ack to inform Spin program that the cog is running.
Ack
wrlong retval, pOutput
mov temp, #0
wrlong temp, pSync
:wait ' Wait for caller to set sync to indicate that input is ready.
rdlong temp, pSync wz
if_z jmp #:wait
rdlong pString, pInput ' input[0] points to string to look up.
rdlong ptr, pOutput ' input[1] points to table. (input[1] = output)
mov retval, #0
:loop
tjz ptr, #Ack
mov pLeft, pString ' Compare string
mov pRight, ptr ' to string at current position in table
add pRight, #4 ' (bump up ptr by 4 to skip two link words).
call #StringCompare
if_e jmp #:equal
if_b jmp #:less
:greater ' If left > right,
add ptr, #2 ' use the 2nd link.
:less ' If left < right, use 1st link.
rdbyte temp, ptr ' Follow the link
add ptr, #1 ' It would be nice to just "rdword ptr, ptr" here
rdbyte ptr, ptr ' but ptr might be odd so we have to go through
shl ptr, #8 ' some extra gyrations.
add ptr, temp
jmp #:loop ' and recurse (well, just iterate).
:equal ' If left = right, return ptr + 4 + strsize(pString) + 1
mov retval, ptr
add retval, #5
:x
rdbyte temp, pString wz ' add strsize(pString)
if_z jmp #:y
add retval, #1
add pString, #1
jmp #:x
:y
jmp #Ack
StringCompare
' Compares zero-terminated strings pointed to by pLeft and pRight.
' On return, Z and C are set appropriately.
rdbyte temp, pLeft wz
add pLeft, #1
if_z jmp #:leftEnd
rdbyte temp1, pRight wz
add pRight, #1
if_z jmp #:rightEnd
cmp temp, temp1 wc, wz
if_e jmp #StringCompare ' If they match, try the next pair.
jmp #StringCompare_ret ' Otherwise, we're done.
:leftEnd rdbyte temp1, pRight wz ' If we're at the end of both strings,
if_z jmp #StringCompare_ret ' leave (with Z set).
' Otherwise, left string is shorter than the right
' and therefore less.
neg temp, #1
mov temp, temp wc, wz ' Set C=1 and Z=0 for "less than"
jmp #StringCompare_ret
:rightEnd ' Here we've reached the end of the right string.
' The left string is longer than the right
' and therefore greater.
mov temp, #1 wc, wz ' Set C=0 and Z=0 for "greater than"
StringCompare_ret
ret
temp res 1
temp1 res 1
ptr res 1
pLeft res 1
pRight res 1
pString res 1
pTable res 1
pInput res 1
pOutput res 1
pSync res 1
retval res 1
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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. |
+------------------------------------------------------------------------------------------------------------------------------+
}}

File diff suppressed because it is too large Load Diff

View File

@ -1,216 +0,0 @@
obj
kw : "kwdefs"
token : "tokenrdr"
bt : "bintree"
st : "symbols"
dat
pass byte 0
insideDAT byte 0
ignoreUndefined byte 0
evalSuccess byte 0
pGlobalLabel word 0
pub set_Pass( p )
pass := p
pub get_Pass
return pass
pub EnteringDat
insideDAT~~
pub LeavingDat
insideDAT~
pub Succeeded
return evalSuccess
pub TryToEvaluateExpression( _pGlobalLabel )
{{
}}
pGlobalLabel := _pGlobalLabel
ignoreUndefined~~
evalSuccess~~
return Evaluate( 13 )
pub EvaluateExpression( _pGlobalLabel )
pGlobalLabel := _pGlobalLabel
ignoreUndefined~
evalSuccess~~
return Evaluate( 13 )
pri Evaluate( rbp ) | prec, lbp, t
prec := token.GetPrecedence
if token.AdvanceIf( kw#kAT )
result := EvaluateSymbol( true )
elseif (token.IsUnaryOp and not token.IsPostfixOp) or token.Type == kw#kMINUS
t := token.Type
token.Advance
result := EvaluateUnary( t, prec )
elseif token.AdvanceIf( kw#kLPAREN )
result := Evaluate( 13 )
token.Eat( kw#kRPAREN )
elseif token.IsIntLiteral or token.IsFloatLiteral
result := token.Value
token.Advance
elseif token.IsReg
result := $1f0 + token.GetReg
token.Advance
else
result := EvaluateSymbol( false )
repeat
lbp := token.GetPrecedence
if rbp =< lbp
quit
t := token.Type
token.Advance
result := EvaluateBinary( t, result, Evaluate( lbp ) )
pri EvaluateSymbol( takeAddress ) | p, t, pObj, cogx4, pLocalLabels
{{
CON symbols evaluate as their defined values, as do OBJ#constants.
DAT symbols evaluate differently depending on context.
}}
if byte[token.Text] == ":" ' local label?
ifnot pGlobalLabel
abort string("Unknown local label(1)")
p := pGlobalLabel ' Search local label list for current token.
repeat
ifnot p := bt.PeekW( p + 6 ) ' p points to string part of local label
if ignoreUndefined
evalSuccess~
token.Advance
return -1 ' dummy value
abort string("Unknown local label(2)")
if strcomp( p, token.Text )
quit
p += strsize(p) + 1 ' Increment p past string part to data part
' On exit, we've found the local label.
p += strsize(p) + 1 ' Increment p past string part to data part
else
p := st.SymbolLookup( token.Text )
ifnot p
if ignoreUndefined
evalSuccess~
token.Advance
return -1
abort string("Unknown symbol")
t := byte[p]
if t == st#kINT_CON_SYMBOL or t == st#kFLOAT_CON_SYMBOL or t == st#kBUILTIN_INT_SYMBOL or t == st#kBUILTIN_FLOAT_SYMBOL
' TODO: should handle floats differently
if takeAddress
abort string("Can't take address of CON symbol")
token.Advance
return bt.PeekL( p+1 )
if t == st#kUNDEFINED_CON_SYMBOL
if ignoreUndefined
evalSuccess~
token.Advance
return -1 ' dummy value
abort string("Undefined CON symbol")
if t == st#kOBJ_SYMBOL
if takeAddress
abort string("Can't take address of OBJ symbol")
token.Advance
p := bt.PeekW( p+1 )
pObj := bt.PeekW( p + strsize(p) + 2 )
token.Eat( kw#kOCTOTHORP )
ifnot p := bt.FindInTable( token.Text, pObj )
abort string("CON symbol unknown in sub-object")
't := byte[p] -- at this point, t should be either kINT_CON_SYMBOL or kFLOAT_CON_SYMBOL
' TODO: should handle floats differently
token.Advance
return bt.PeekL( p+1 )
if t == st#kDAT_SYMBOL
if pass == 1
if ignoreUndefined
evalSuccess~
token.Advance
return -1 ' dummy value
if takeAddress
abort string("Can't take address of DAT symbol in pass 1")
if not insideDAT or takeAddress
token.Advance
return bt.PeekW( p+2 )
cogx4 := bt.PeekW( p+4 )
if cogx4 & 3
abort string("Address is not long")
token.Advance
return cogx4 >> 2
abort string("Invalid symbol in constant expression")
pri EvaluateUnary( t, prec )
{{
}}
result := Evaluate( prec )
case t & $ff
$ed: -result
$e7: !result
$ff: not result
$f3: |<result
$f1: >|result
$f8: ^^result
$e9: ||result
other: abort string("Syntax error in constant expression(1)")
pri EvaluateBinary( t, a, b )
case t & $ff
$ec: return a + b
$ed: return a - b
$f4: return a * b
$f6: return a / b
$f5: return a ** b
$f7: return a // b
$e0: return a -> b
$e1: return a <- b
$e2: return a >> b
$e3: return a << b
$ee: return a ~> b
$ef: return a >< b
$e8: return a & b
$ea: return a | b
$eb: return a ^ b
$e4: return a #> b
$e5: return a <# b
$f9: return a < b
$fa: return a > b
$fc: return a == b
$fb: return a <> b
$fd: return a =< b
$fe: return a => b
$f0: return a and b
$f2: return a or b
other: abort string("Syntax error in constant expression(2)")
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,219 +0,0 @@
''***************************************
''* Floating-Point Math *
''* Single-precision IEEE-754 *
''* Author: Chip Gracey *
''* Copyright (c) 2006 Parallax, Inc. *
''* See end of file for terms of use. *
''***************************************
PUB FFloat(integer) : single | s, x, m
''Convert integer to float
if m := ||integer 'absolutize mantissa, if 0, result 0
s := integer >> 31 'get sign
x := >|m - 1 'get exponent
m <<= 31 - x 'msb-justify mantissa
m >>= 2 'bit29-justify mantissa
return Pack(@s) 'pack result
PUB FRound(single) : integer
''Convert float to rounded integer
return FInteger(single, 1) 'use 1/2 to round
PUB FTrunc(single) : integer
''Convert float to truncated integer
return FInteger(single, 0) 'use 0 to round
PUB FNeg(singleA) : single
''Negate singleA
return singleA ^ $8000_0000 'toggle sign bit
PUB FAbs(singleA) : single
''Absolute singleA
return singleA & $7FFF_FFFF 'clear sign bit
PUB FSqr(singleA) : single | s, x, m, root
''Compute square root of singleA
if singleA > 0 'if a =< 0, result 0
Unpack(@s, singleA) 'unpack input
m >>= !x & 1 'if exponent even, shift mantissa down
x ~>= 1 'get root exponent
root := $4000_0000 'compute square root of mantissa
repeat 31
result |= root
if result ** result > m
result ^= root
root >>= 1
m := result >> 1
return Pack(@s) 'pack result
PUB FAdd(singleA, singleB) : single | sa, xa, ma, sb, xb, mb
''Add singleA and singleB
Unpack(@sa, singleA) 'unpack inputs
Unpack(@sb, singleB)
if sa 'handle mantissa negation
-ma
if sb
-mb
result := ||(xa - xb) <# 31 'get exponent difference
if xa > xb 'shift lower-exponent mantissa down
mb ~>= result
else
ma ~>= result
xa := xb
ma += mb 'add mantissas
sa := ma < 0 'get sign
||ma 'absolutize result
return Pack(@sa) 'pack result
PUB FSub(singleA, singleB) : single
''Subtract singleB from singleA
return FAdd(singleA, FNeg(singleB))
PUB FMul(singleA, singleB) : single | sa, xa, ma, sb, xb, mb
''Multiply singleA by singleB
Unpack(@sa, singleA) 'unpack inputs
Unpack(@sb, singleB)
sa ^= sb 'xor signs
xa += xb 'add exponents
ma := (ma ** mb) << 3 'multiply mantissas and justify
return Pack(@sa) 'pack result
PUB FDiv(singleA, singleB) : single | sa, xa, ma, sb, xb, mb
''Divide singleA by singleB
Unpack(@sa, singleA) 'unpack inputs
Unpack(@sb, singleB)
sa ^= sb 'xor signs
xa -= xb 'subtract exponents
repeat 30 'divide mantissas
result <<= 1
if ma => mb
ma -= mb
result++
ma <<= 1
ma := result
return Pack(@sa) 'pack result
PRI FInteger(a, r) : integer | s, x, m
'Convert float to rounded/truncated integer
Unpack(@s, a) 'unpack input
if x => -1 and x =< 30 'if exponent not -1..30, result 0
m <<= 2 'msb-justify mantissa
m >>= 30 - x 'shift down to 1/2-lsb
m += r 'round (1) or truncate (0)
m >>= 1 'shift down to lsb
if s 'handle negation
-m
return m 'return integer
PRI Unpack(pointer, single) | s, x, m
'Unpack floating-point into (sign, exponent, mantissa) at pointer
s := single >> 31 'unpack sign
x := single << 1 >> 24 'unpack exponent
m := single & $007F_FFFF 'unpack mantissa
if x 'if exponent > 0,
m := m << 6 | $2000_0000 '..bit29-justify mantissa with leading 1
else
result := >|m - 23 'else, determine first 1 in mantissa
x := result '..adjust exponent
m <<= 7 - result '..bit29-justify mantissa
x -= 127 'unbias exponent
longmove(pointer, @s, 3) 'write (s,x,m) structure from locals
PRI Pack(pointer) : single | s, x, m
'Pack floating-point from (sign, exponent, mantissa) at pointer
longmove(@s, pointer, 3) 'get (s,x,m) structure into locals
if m 'if mantissa 0, result 0
result := 33 - >|m 'determine magnitude of mantissa
m <<= result 'msb-justify mantissa without leading 1
x += 3 - result 'adjust exponent
m += $00000100 'round up mantissa by 1/2 lsb
if not m & $FFFFFF00 'if rounding overflow,
x++ '..increment exponent
x := x + 127 #> -23 <# 255 'bias and limit exponent
if x < 1 'if exponent < 1,
m := $8000_0000 + m >> 1 '..replace leading 1
m >>= -x '..shift mantissa down by exponent
x~ '..exponent is now 0
return s << 31 | x << 23 | m >> 9 'pack result
{{
+------------------------------------------------------------------------------------------------------------------------------+
¦ 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

@ -1,534 +0,0 @@
''*****************************************
''* Floating-Point <-> Strings v 1.2 *
''* Single-precision IEEE-754 *
''* Authors: Chip Gracey and Cam Thompson *
''* (C) 2006 Parallax, Inc. *
''* See end of file for terms of use. *
''*****************************************
'' v1.0 - 01 May 2006 - original version
'' v1.1 - 12 Jul 2006 - added FloatToFormat routine
'' v1.2 - 06 Mar 2009 - added StringToFloat [mpark]
VAR
long p, digits, exponent, integer, tens, zeros, precision
long positive_chr, decimal_chr, thousands_chr, thousandths_chr
byte float_string[20]
OBJ
' The F object can be FloatMath, Float32 or Float32Full depending on the application
F : "FltMath"
PUB FloatToString(Single) : StringPtr
''Convert floating-point number to string
''
'' entry:
'' Single = floating-point number
''
'' exit:
'' StringPtr = pointer to resultant z-string
''
'' Magnitudes below 1e+12 and within 1e-12 will be expressed directly;
'' otherwise, scientific notation will be used.
''
'' examples results
'' -----------------------------------------
'' FloatToString(0.0) "0"
'' FloatToString(1.0) "1"
'' FloatToString(-1.0) "-1"
'' FloatToString(^^2.0) "1.414214"
'' FloatToString(2.34e-3) "0.00234"
'' FloatToString(-1.5e-5) "-0.000015"
'' FloatToString(2.7e+6) "2700000"
'' FloatToString(1e11) "100000000000"
'' FloatToString(1e12) "1.000000e+12"
'' FloatToString(1e-12) "0.000000000001"
'' FloatToString(1e-13) "1.000000e-13"
'perform initial setup
StringPtr := Setup(Single)
'eliminate trailing zeros
if integer
repeat until integer // 10
integer /= 10
tens /= 10
digits--
else
digits~
'express number according to exponent
case exponent
'in range left of decimal
11..0:
AddDigits(exponent + 1)
'in range right of decimal
-1..digits - 13:
zeros := -exponent
AddDigits(1)
'out of range, do scientific notation
other:
DoScientific
'terminate z-string
byte[p]~
PUB FloatToScientific(Single) : StringPtr
''Convert floating-point number to scientific-notation string
''
'' entry:
'' Single = floating-point number
''
'' exit:
'' StringPtr = pointer to resultant z-string
''
'' examples results
'' -------------------------------------------------
'' FloatToScientific(1e-9) "1.000000e-9"
'' FloatToScientific(^^2.0) "1.414214e+0"
'' FloatToScientific(0.00251) "2.510000e-3"
'' FloatToScientific(-0.0000150043) "-1.500430e-5"
'perform initial setup
StringPtr := Setup(Single)
'do scientific notation
DoScientific
'terminate z-string
byte[p]~
PUB FloatToMetric(Single, SuffixChr) : StringPtr | x, y
''Convert floating-point number to metric string
''
'' entry:
'' Single = floating-point number
'' SuffixChr = optional ending character (0=none)
''
'' exit:
'' StringPtr = pointer to resultant z-string
''
'' Magnitudes within the metric ranges will be expressed in metric
'' terms; otherwise, scientific notation will be used.
''
'' range name symbol
'' -----------------------
'' 1e24 yotta Y
'' 1e21 zetta Z
'' 1e18 exa E
'' 1e15 peta P
'' 1e12 tera T
'' 1e9 giga G
'' 1e6 mega M
'' 1e3 kilo k
'' 1e0 - -
'' 1e-3 milli m
'' 1e-6 micro u
'' 1e-9 nano n
'' 1e-12 pico p
'' 1e-15 femto f
'' 1e-18 atto a
'' 1e-21 zepto z
'' 1e-24 yocto y
''
'' examples results
'' ------------------------------------
'' metric(2000.0, "m") "2.000000km"
'' metric(-4.5e-5, "A") "-45.00000uA"
'' metric(2.7e6, 0) "2.700000M"
'' metric(39e31, "W") "3.9000e+32W"
'perform initial setup
StringPtr := Setup(Single)
'determine thousands exponent and relative tens exponent
x := (exponent + 45) / 3 - 15
y := (exponent + 45) // 3
'if in metric range, do metric
if ||x =< 8
'add digits with possible decimal
AddDigits(y + 1)
'if thousands exponent not 0, add metric indicator
if x
byte[p++] := " "
byte[p++] := metric[x]
'if out of metric range, do scientific notation
else
DoScientific
'if SuffixChr not 0, add SuffixChr
if SuffixChr
byte[p++] := SuffixChr
'terminate z-string
byte[p]~
PUB FloatToFormat(single, width, dp) : stringptr | n, w2
''Convert floating-point number to formatted string
''
'' entry:
'' Single = floating-point number
'' width = width of field
'' dp = number of decimal points
''
'' exit:
'' StringPtr = pointer to resultant z-string
''
'' asterisks are displayed for format errors
'' leading blank fill is used
' get string pointer
stringptr := p := @float_string
' width must be 1 to 9, dp must be 0 to width-1
w2 := width := width #> 1 <# 9
dp := dp #> 0 <# (width - 2)
if dp > 0
w2--
if single & $8000_0000 or positive_chr
w2--
' get positive scaled integer value
n := F.FRound(F.FMul(single & $7FFF_FFFF , F.FFloat(teni[dp])))
if n => teni[w2]
' if format error, display asterisks
repeat while width
if --width == dp
if decimal_chr
byte[p++] := decimal_chr
else
byte[p++] := "."
else
byte[p++] := "*"
byte[p]~
else
' store formatted number
p += width
byte[p]~
repeat width
byte[--p] := n // 10 + "0"
n /= 10
if --dp == 0
if decimal_chr
byte[--p] := decimal_chr
else
byte[--p] := "."
if n == 0 and dp < 0
quit
' store sign
if single & $80000000
byte[--p] := "-"
elseif positive_chr
byte[--p] := positive_chr
' leading blank fill
repeat while p <> stringptr
byte[--p] := " "
PUB SetPrecision(NumberOfDigits)
''Set precision to express floating-point numbers in
''
'' NumberOfDigits = Number of digits to round to, limited to 1..7 (7=default)
''
'' examples results
'' -------------------------------
'' SetPrecision(1) "1e+0"
'' SetPrecision(4) "1.000e+0"
'' SetPrecision(7) "1.000000e+0"
precision := NumberOfDigits
PUB SetPositiveChr(PositiveChr)
''Set lead character for positive numbers
''
'' PositiveChr = 0: no character will lead positive numbers (default)
'' non-0: PositiveChr will lead positive numbers (ie " " or "+")
''
'' examples results
'' ----------------------------------------
'' SetPositiveChr(0) "20.07" "-20.07"
'' SetPositiveChr(" ") " 20.07" "-20.07"
'' SetPositiveChr("+") "+20.07" "-20.07"
positive_chr := PositiveChr
PUB SetDecimalChr(DecimalChr)
''Set decimal point character
''
'' DecimalChr = 0: "." will be used (default)
'' non-0: DecimalChr will be used (ie "," for Europe)
''
'' examples results
'' ----------------------------
'' SetDecimalChr(0) "20.49"
'' SetDecimalChr(",") "20,49"
decimal_chr := DecimalChr
PUB SetSeparatorChrs(ThousandsChr, ThousandthsChr)
''Set thousands and thousandths separator characters
''
'' ThousandsChr =
'' 0: no character will separate thousands (default)
'' non-0: ThousandsChr will separate thousands
''
'' ThousandthsChr =
'' 0: no character will separate thousandths (default)
'' non-0: ThousandthsChr will separate thousandths
''
'' examples results
'' -----------------------------------------------------------
'' SetSeparatorChrs(0, 0) "200000000" "0.000729345"
'' SetSeparatorChrs(0, "_") "200000000" "0.000_729_345"
'' SetSeparatorChrs(",", 0) "200,000,000" "0.000729345"
'' SetSeparatorChrs(",", "_") "200,000,000" "0.000_729_345"
thousands_chr := ThousandsChr
thousandths_chr := ThousandthsChr
PUB StringToFloat(strptr) : flt | significand, ssign, places, exp, esign
{{
Converts string to floating-point number
entry:
strptr = pointer to z-string
exit:
flt = floating-point number
Assumes the following floating-point syntax: [-] [0-9]* [ . [0-9]* ] [ e|E [-|+] [0-9]* ]
+-- +----- +----------- +-------------------
¦ ¦ ¦ ¦ +---- +-----
Optional negative sign --------------------+ ¦ ¦ ¦ ¦ ¦
Digits ----------------------------------------+ ¦ ¦ ¦ ¦
Optional decimal point followed by digits ------------+ ¦ ¦ ¦
Optional exponent -------------------------------------------------+ ¦ ¦
optional exponent sign ------------------------------------------------+ ¦
exponent digits -------------------------------------------------------------+
Examples of recognized floating-point numbers:
"123", "-123", "123.456", "123.456e+09"
Conversion stops as soon as an invalid character is encountered. No error-checking.
Based on Ariba's StrToFloat in http://forums.parallax.com/forums/default.aspx?f=25&m=280607
Expanded by Michael Park
}}
significand~
ssign~
exp~
esign~
places~
repeat
case byte[strptr]
"-":
ssign~~
".":
places := 1
"0".."9":
significand := significand * 10 + byte[strptr] - "0"
if places
++places 'count decimal places
"e", "E":
++strptr ' skip over the e or E
repeat
case byte[strptr]
"+":
' ignore
"-":
esign~~
"0".."9":
exp := exp * 10 + byte[strptr] - "0"
other:
quit
++strptr
quit
other:
quit
++strptr
if ssign
-significand
flt := f.FFloat(significand)
ifnot esign ' tenf table is in decreasing order, so the sign of exp is reversed
-exp
if places
exp += places - 1
flt := f.FMul(flt, tenf[exp]) 'adjust flt's decimal point
PRI Setup(single) : stringptr
'limit digits to 1..7
if precision
digits := precision #> 1 <# 7
else
digits := 7
'initialize string pointer
p := @float_string
'add "-" if negative
if single & $80000000
byte[p++] := "-"
'otherwise, add any positive lead character
elseif positive_chr
byte[p++] := positive_chr
'clear sign and check for 0
if single &= $7FFFFFFF
'not 0, estimate exponent
exponent := ((single << 1 >> 24 - 127) * 77) ~> 8
'if very small, bias up
if exponent < -32
single := F.FMul(single, 1e13)
exponent += result := 13
'determine exact exponent and integer
repeat
integer := F.FRound(F.FMul(single, tenf[exponent - digits + 1]))
if integer < teni[digits - 1]
exponent--
elseif integer => teni[digits]
exponent++
else
exponent -= result
quit
'if 0, reset exponent and integer
else
exponent~
integer~
'set initial tens and clear zeros
tens := teni[digits - 1]
zeros~
'return pointer to string
stringptr := @float_string
PRI DoScientific
'add digits with possible decimal
AddDigits(1)
'add exponent indicator
byte[p++] := "e"
'add exponent sign
if exponent => 0
byte[p++] := "+"
else
byte[p++] := "-"
||exponent
'add exponent digits
if exponent => 10
byte[p++] := exponent / 10 + "0"
exponent //= 10
byte[p++] := exponent + "0"
PRI AddDigits(leading) | i
'add leading digits
repeat i := leading
AddDigit
'add any thousands separator between thousands
if thousands_chr
i--
if i and not i // 3
byte[p++] := thousands_chr
'if trailing digits, add decimal character
if digits
AddDecimal
'then add trailing digits
repeat while digits
'add any thousandths separator between thousandths
if thousandths_chr
if i and not i // 3
byte[p++] := thousandths_chr
i++
AddDigit
PRI AddDigit
'if leading zeros, add "0"
if zeros
byte[p++] := "0"
zeros--
'if more digits, add current digit and prepare next
elseif digits
byte[p++] := integer / tens + "0"
integer //= tens
tens /= 10
digits--
'if no more digits, add "0"
else
byte[p++] := "0"
PRI AddDecimal
if decimal_chr
byte[p++] := decimal_chr
else
byte[p++] := "."
DAT
long 1e+38, 1e+37, 1e+36, 1e+35, 1e+34, 1e+33, 1e+32, 1e+31
long 1e+30, 1e+29, 1e+28, 1e+27, 1e+26, 1e+25, 1e+24, 1e+23, 1e+22, 1e+21
long 1e+20, 1e+19, 1e+18, 1e+17, 1e+16, 1e+15, 1e+14, 1e+13, 1e+12, 1e+11
long 1e+10, 1e+09, 1e+08, 1e+07, 1e+06, 1e+05, 1e+04, 1e+03, 1e+02, 1e+01
tenf long 1e+00, 1e-01, 1e-02, 1e-03, 1e-04, 1e-05, 1e-06, 1e-07, 1e-08, 1e-09
long 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18, 1e-19
long 1e-20, 1e-21, 1e-22, 1e-23, 1e-24, 1e-25, 1e-26, 1e-27, 1e-28, 1e-29
long 1e-30, 1e-31, 1e-32, 1e-33, 1e-34, 1e-35, 1e-36, 1e-37, 1e-38
teni long 1, 10, 100, 1_000, 10_000, 100_000, 1_000_000, 10_000_000, 100_000_000, 1_000_000_000
byte "yzafpnum"
metric byte 0
byte "kMGTPEZY"
{{
+------------------------------------------------------------------------------------------------------------------------------+
¦ 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

@ -1,80 +0,0 @@
SXTVRENDEZVOUS = $8000 - 4
SXKBRENDEZVOUS = SXTVRENDEZVOUS - 4
SDSPIRENDEZVOUS = SXKBRENDEZVOUS - 3 * 4
SXFS2RENDEZVOUS = SDSPIRENDEZVOUS - 4 * 4 ' four rendezvous variables
SXFSRENDEZVOUS = SXFS2RENDEZVOUS - 4 * 4 ' four rendezvous variables
METADATABUFFER = SXFSRENDEZVOUS - 512
_free = ($8000 - METADATABUFFER) / 4
SIZEOFFILESTUFF = 512 + 24
pCommand = SXFSRENDEZVOUS
pParam0 = pCommand+4
pParam1 = pCommand+8
pParam2 = pCommand+12
pub Open( pFilestuff, pFilename, mode ) | filenameBuffer[3], p, i
{{
mode is either "R" or "W".
Returns 0 on success, 1 if file not found (and opening for reading).
}}
return Command( "O", pFilestuff, pFilename, mode )
pub Close( pFilestuff )
Command( "C", pFilestuff, 0, 0 )
pub Read( pFilestuff, pBuffer, nBytes )
{{
Returns number of bytes actually read, -1 at EOF.
}}
long[pParam0] := pFilestuff
long[pParam1] := pBuffer
long[pParam2] := nBytes
long[pCommand] := "R"
repeat while long[pCommand]
if long[pParam0] < -2 ' don't abort for return code -1.
abort long[pParam0]
return long[pParam0]
pub Write( pFilestuff, pBuffer, nBytes )
return Command( "W", pFilestuff, pBuffer, nBytes )
pub Execute( pFilestuff, execmode )
{{
If execmode is non-0, all cogs are stopped except Spin interpreter.
If execmode is 0, running cogs are left running.
}}
Command( "X", pFilestuff, execmode, cogid )
pub Command( cmd, param0, param1, param2 )
long[pParam0] := param0
long[pParam1] := param1
long[pParam2] := param2
long[pCommand] := cmd
repeat while long[pCommand]
if long[pParam0] < 0
abort long[pParam0]
return long[pParam0]
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,96 +0,0 @@
''This file is an excerpt of tv.spin. Copyright and license are from tv.spin.
''***************************************
''* TV Driver v1.1 *
''* Author: Chip Gracey *
''* Copyright (c) 2004 Parallax, Inc. *
''* See end of file for terms of use. *
''***************************************
'' Modified for Sphinx by Michael Park
SXTVRENDEZVOUS = $8000 - 4
PUB GetBasepin
repeat while long[SXTVRENDEZVOUS]
long[SXTVRENDEZVOUS]~~ ' ping the sxtv cog (send -1)
repeat while long[SXTVRENDEZVOUS] == -1
return long[SXTVRENDEZVOUS]~ >> 8
PUB str(stringptr)
'' Print a zero-terminated string
repeat strsize(stringptr)
out(byte[stringptr++])
PUB dec(value) | i
'' Print a decimal number
if value < 0
-value
out("-")
i := 1_000_000_000
repeat 10
if value => i
out(value / i + "0")
value //= i
result~~
elseif result or i == 1
out("0")
i /= 10
PUB hex(value, digits)
'' Print a hexadecimal number
value <<= (8 - digits) << 2
repeat digits
out(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
PUB bin(value, digits)
'' Print a binary number
value <<= 32 - digits
repeat digits
out((value <-= 1) & 1 + "0")
pub out(ch)
repeat while long[SXTVRENDEZVOUS]
long[SXTVRENDEZVOUS] := ch
pub Ping
out( -1 )
pub Enable
out( "E"<<8 )
pub Disable
out( "D"<<8 )
{{
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,530 +0,0 @@
obj
bt: "bintree"
pub Init
tableStart += @tableStart
FixupTable( @tableStart + 2 )
pri FixupTable( p ) | q
q := bt.PeekW( p )
if q
bt.PokeW( p, q += @tableStart )
FixupTable( q )
q := bt.PeekW( p + 2 )
if q
bt.PokeW( p + 2, q += @tableStart )
FixupTable( q )
pub KeywordLookup( s )
return bt.FindInTable( s, tableStart )
con
{
31 (plain ID)
30 (int literal)
29 (float literal)
28 ?
27 unary
26 binary/postfix
25 pasm (TJZ, XOR)
24 cond (IF_Z, IF_E)
23 effect (WC, WZ)
22 stmtfn (BYTEMOVE, WAITCNT)
21 assignment op (-=, OR=)
20 intrinsic
19 prec3
18 prec2
17 d prec1
16 s prec0
15 pasmop spinop7
14 pasmop spinop6
13 pasmop spinop5 keyword
12 pasmop spinop4 uniquifier
11 pasmop spinop3 bits
10 pasmop spinop2 |
9 pasmop spinop1 | #args
8 pasmop spinop0 V #args
7 pasmop spinop7 id7 op
6 pasmop spinop6 id6 op
5 pasmop spinop5 id5 op
4 pasmop spinop4 id4 op
3 pasmop spinop3 cond3 id3 effect op
2 pasmop spinop2 cond2 id2 effect op
1 pasmop spinop1 cond1 id1 effect op
0 pasmop spinop0 cond0 id0 effect op
}
con ' The following is auto-generated. Do not edit.
kID = $80000000
kINTLITERAL = $40000000
kFLOATLITERAL = $20000000
kUNARY = $08000000
kBINARY = $04000000
kPOSTFIX = $04000000
kPASM = $02000000
kCOND = $01000000
kEFFECT = $00800000
kSTMTFN = $00400000
kASSIGNMENT = $00200000
kINTRINSIC = $00100000
' kBANG = $080100e7
' kOCTOTHORPRANGLE = $040700e4
' kAMPERSAND = $040300e8
' kSTAR = $040500f4
' kSTARSTAR = $040500f5
kPLUS = $040600ec
' kPLUSPLUS = $0c002820
kMINUS = $040600ed
' kMINUSMINUS = $0c003830
' kMINUSRANGLE = $040200e0
' kSLASH = $040500f6
' kSLASHSLASH = $040500f7
' kLANGLE = $040800f9
' kLANGLEOCTOTHORP = $040700e5
' kLANGLEMINUS = $040200e1
' kLANGLELANGLE = $040200e3
' kLANGLERANGLE = $040800fb
' kEQUALLANGLE = $040800fd
' kEQUALEQUAL = $040800fc
' kEQUALRANGLE = $040800fe
' kRANGLE = $040800fa
' kRANGLELANGLE = $040200ef
' kRANGLERANGLE = $040200e2
' kRANGLEBAR = $080100f1
kQUESTION = $0c000c08
kAT = $08000000
kATAT = $08000001
' kCARET = $040400eb
' kCARETCARET = $080100f8
kBAR = $040400ea
' kBARLANGLE = $080100f3
' kBARBAR = $080100e9
kTILDE = $0c001810
' kTILDERANGLE = $040200ee
kTILDETILDE = $0c001c14
kAND = $060a00f0
' kNOT = $080900ff
kOR = $060b00f2
' kABS = $0203a8bc
' kABSNEG = $0203acbc
' kADD = $020380bc
' kADDABS = $020388bc
' kADDS = $0203d0bc
' kADDSX = $0203d8bc
' kADDX = $0203c8bc
' kANDN = $020364bc
kCALL = $02015cfc
' kCMP = $0203843c
' kCMPS = $0203c03c
' kCMPSUB = $0203e0bc
' kCMPSX = $0203c43c
' kCMPX = $0203cc3c
' kDJNZ = $0203e4bc
' kHUBOP = $02030c3c
' kJMP = $02015c3c
' kJMPRET = $02035cbc
' kMAX = $02034cbc
' kMAXS = $020344bc
' kMIN = $020348bc
' kMINS = $020340bc
' kMOV = $0203a0bc
' kMOVD = $020354bc
' kMOVI = $020358bc
' kMOVS = $020350bc
' kMUXC = $020370bc
' kMUXNC = $020374bc
' kMUXNZ = $02037cbc
' kMUXZ = $020378bc
' kNEG = $0203a4bc
' kNEGC = $0203b0bc
' kNEGNC = $0203b4bc
' kNEGNZ = $0203bcbc
' kNEGZ = $0203b8bc
' kNOP = $02000000
' kRCL = $020334bc
' kRCR = $020330bc
' kRDBYTE = $020300bc
' kRDLONG = $020308bc
' kRDWORD = $020304bc
' kRET = $02005c7c
' kREV = $02033cbc
' kROL = $020324bc
' kROR = $020320bc
' kSAR = $020338bc
' kSHL = $02032cbc
' kSHR = $020328bc
' kSUB = $020384bc
' kSUBABS = $02038cbc
' kSUBS = $0203d4bc
' kSUBSX = $0203dcbc
' kSUBX = $0203ccbc
' kSUMC = $020390bc
' kSUMNC = $020394bc
' kSUMNZ = $02039cbc
' kSUMZ = $020398bc
' kTEST = $0203603c
' kTJNZ = $0203e83c
' kTJZ = $0203ec3c
' kWRBYTE = $0203003c
' kWRLONG = $0203083c
' kWRWORD = $0203043c
' kXOR = $02036cbc
kPAR = $00000001
' kCNT = $00000002
' kINA = $00000003
' kINB = $00000004
' kOUTA = $00000005
' kOUTB = $00000006
' kDIRA = $00000007
' kDIRB = $00000008
' kCTRA = $00000009
' kCTRB = $0000000a
' kFRQA = $0000000b
' kFRQB = $0000000c
' kPHSA = $0000000d
' kPHSB = $0000000e
' kVCFG = $0000000f
kVSCL = $00000010
' kIF_A = $01000001
' kIF_AE = $01000003
' kIF_ALWAYS = $0100000f
' kIF_B = $0100000c
' kIF_BE = $0100000e
' kIF_C = $0100000c
' kIF_C_AND_NZ = $01000004
' kIF_C_AND_Z = $01000008
' kIF_C_EQ_Z = $01000009
' kIF_C_NE_Z = $01000006
' kIF_C_OR_NZ = $0100000d
' kIF_C_OR_Z = $0100000e
' kIF_E = $0100000a
' kIF_NC = $01000003
' kIF_NC_AND_NZ = $01000001
' kIF_NC_AND_Z = $01000002
' kIF_NC_OR_NZ = $01000007
' kIF_NC_OR_Z = $0100000b
' kIF_NE = $01000005
' kIF_NEVER = $01000000
' kIF_NZ = $01000005
' kIF_NZ_AND_C = $01000004
' kIF_NZ_AND_NC = $01000001
' kIF_NZ_OR_C = $0100000e
' kIF_NZ_OR_NC = $0100000b
' kIF_Z = $0100000a
' kIF_Z_AND_C = $01000008
' kIF_Z_AND_NC = $01000002
' kIF_Z_EQ_C = $01000009
' kIF_Z_NE_C = $01000006
' kIF_Z_OR_C = $0100000e
' kIF_Z_OR_NC = $0100000b
' kNR = $00800008
' kWC = $00800002
' kWR = $00800001
' kWZ = $00800004
kCON = $00000011
kDAT = $00000012
kOBJ = $00000013
kPRI = $00000014
kPUB = $00000015
kVAR = $00000016
kBYTE = $00000017
kWORD = $00000018
kLONG = $00000019
' kBYTEFILL = $00400318
' kWORDFILL = $00400319
' kLONGFILL = $0040031a
' kBYTEMOVE = $0040031c
' kWORDMOVE = $0040031d
' kLONGMOVE = $0040031e
kCLKSET = $02400220
kCOGSTOP = $02400121
' kLOCKRET = $00400122
kWAITCNT = $02400123
kWAITPEQ = $0240031b
kWAITPNE = $0240031f
kWAITVID = $02400227
kOCTOTHORP = $0000001a
' kDOLLAR = $0000001b
kLPAREN = $0000001c
kRPAREN = $0000001d
kCOMMA = $0000001e
kDOT = $0000001f
kDOTDOT = $00000020
kCOLON = $00000021
kCOLONEQUAL = $00200022
kEQUAL = $00000023
kABORT = $00000024
kCASE = $00000025
kCHIPVER = $00100000
kCLKFREQ = $00100010
kCLKMODE = $00100020
kCOGID = $02100003
kCOGINIT = $02100004
kCOGNEW = $00100005
kREBOOT = $00100006
' kSTRCOMP = $00100172
' kSTRSIZE = $00100161
' kLOCKCLR = $0012b2f1
' kLOCKNEW = $001292d0
' kLOCKSET = $0012a2e1
' kLOOKDOWN = $00113111
' kLOOKDOWNZ = $00113110
' kLOOKUP = $00112101
' kLOOKUPZ = $00112100
kCONSTANT = $00000026
kELSE = $00000027
kELSEIF = $00000028
kELSEIFNOT = $00000029
' kFILE = $0000002a
kFIT = $0000002b
' kFLOAT = $0000002c
kFROM = $0000002d
kIF = $0000002e
kIFNOT = $0000002f
kNEXT = $00000030
kORG = $00000031
' kORGX = $00000032
kOTHER = $00000033
kQUIT = $00000034
kREPEAT = $00000035
kRES = $00000036
kRESULT = $00000037
kRETURN = $00000038
' kROUND = $00000039
kSPR = $0000003a
kSTEP = $0000003b
kSTRING = $0000003c
kTO = $0000003d
' kTRUNC = $0000003e
kUNTIL = $0000003f
kWHILE = $00000040
kLBRACKET = $00000041
kBACKSLASH = $00000042
kRBRACKET = $00000043
kLBRACE = $00000044
kRBRACE = $00000045
kEOL = $000000fd
kEOF = $000000fe
kUNKNOWN = $000000ff
dat
tableStart word $0002
byte $0e,$00,$63,$06,$49,$4e,$41,$00,$03,$00,$00,$00,$1c,$00,$d6,$02
byte $43,$4d,$50,$53,$58,$00,$3c,$c4,$03,$02,$27,$00,$57,$01,$3d,$3e
byte $00,$fe,$00,$08,$04,$32,$00,$c2,$00,$2d,$3e,$00,$e0,$00,$02,$04
byte $3c,$00,$83,$00,$2a,$00,$f4,$00,$05,$04,$46,$00,$65,$00,$24,$00
byte $1b,$00,$00,$00,$50,$00,$5a,$00,$23,$00,$1a,$00,$00,$00,$00,$00
byte $00,$00,$21,$00,$e7,$00,$01,$08,$00,$00,$00,$00,$23,$3e,$00,$e4
byte $00,$07,$04,$6f,$00,$79,$00,$28,$00,$1c,$00,$00,$00,$00,$00,$00
byte $00,$26,$00,$e8,$00,$03,$04,$00,$00,$00,$00,$29,$00,$1d,$00,$00
byte $00,$8d,$00,$ad,$00,$2c,$00,$1e,$00,$00,$00,$97,$00,$a2,$00,$2b
byte $00,$ec,$00,$06,$04,$00,$00,$00,$00,$2a,$2a,$00,$f5,$00,$05,$04
byte $00,$00,$00,$00,$2b,$2b,$00,$20,$28,$00,$0c,$b8,$00,$00,$00,$2d
byte $2d,$00,$30,$38,$00,$0c,$00,$00,$00,$00,$2d,$00,$ed,$00,$06,$04
byte $cd,$00,$16,$01,$3c,$23,$00,$e5,$00,$07,$04,$d8,$00,$f7,$00,$2f
byte $2f,$00,$f7,$00,$05,$04,$e3,$00,$ed,$00,$2e,$2e,$00,$20,$00,$00
byte $00,$00,$00,$00,$00,$2e,$00,$1f,$00,$00,$00,$00,$00,$00,$00,$2f
byte $00,$f6,$00,$05,$04,$02,$01,$0c,$01,$3a,$3d,$00,$22,$00,$20,$00
byte $00,$00,$00,$00,$3a,$00,$21,$00,$00,$00,$00,$00,$00,$00,$3c,$00
byte $f9,$00,$08,$04,$20,$01,$41,$01,$3d,$00,$23,$00,$00,$00,$2b,$01
byte $36,$01,$3c,$3c,$00,$e3,$00,$02,$04,$00,$00,$00,$00,$3c,$2d,$00
byte $e1,$00,$02,$04,$00,$00,$00,$00,$3c,$3e,$00,$fb,$00,$08,$04,$4c
byte $01,$00,$00,$3d,$3d,$00,$fc,$00,$08,$04,$00,$00,$00,$00,$3d,$3c
byte $00,$fd,$00,$08,$04,$64,$01,$0d,$02,$41,$44,$44,$58,$00,$bc,$c8
byte $03,$02,$72,$01,$bc,$01,$41,$42,$4f,$52,$54,$00,$24,$00,$00,$00
byte $7d,$01,$9d,$01,$3e,$7c,$00,$f1,$00,$01,$08,$88,$01,$92,$01,$3e
byte $3c,$00,$ef,$00,$02,$04,$00,$00,$00,$00,$3e,$00,$fa,$00,$08,$04
byte $00,$00,$00,$00,$3e,$3e,$00,$e2,$00,$02,$04,$a7,$01,$b1,$01,$40
byte $00,$00,$00,$00,$08,$00,$00,$00,$00,$3f,$00,$08,$0c,$00,$0c,$00
byte $00,$00,$00,$40,$40,$00,$01,$00,$00,$08,$cb,$01,$f2,$01,$41,$44
byte $44,$41,$42,$53,$00,$bc,$88,$03,$02,$da,$01,$e6,$01,$41,$42,$53
byte $4e,$45,$47,$00,$bc,$ac,$03,$02,$00,$00,$00,$00,$41,$42,$53,$00
byte $bc,$a8,$03,$02,$00,$00,$00,$00,$41,$44,$44,$00,$bc,$80,$03,$02
byte $00,$02,$00,$00,$41,$44,$44,$53,$58,$00,$bc,$d8,$03,$02,$00,$00
byte $00,$00,$41,$44,$44,$53,$00,$bc,$d0,$03,$02,$1d,$02,$7f,$02,$43
byte $48,$49,$50,$56,$45,$52,$00,$00,$00,$10,$00,$2e,$02,$54,$02,$42
byte $59,$54,$45,$46,$49,$4c,$4c,$00,$18,$03,$40,$00,$3b,$02,$47,$02
byte $41,$4e,$44,$4e,$00,$bc,$64,$03,$02,$00,$00,$00,$00,$41,$4e,$44
byte $00,$f0,$00,$0a,$06,$00,$00,$00,$00,$42,$59,$54,$45,$00,$17,$00
byte $00,$00,$61,$02,$72,$02,$43,$41,$4c,$4c,$00,$fc,$5c,$01,$02,$00
byte $00,$00,$00,$42,$59,$54,$45,$4d,$4f,$56,$45,$00,$1c,$03,$40,$00
byte $00,$00,$00,$00,$43,$41,$53,$45,$00,$25,$00,$00,$00,$8b,$02,$ba
byte $02,$43,$4d,$50,$00,$3c,$84,$03,$02,$9b,$02,$ab,$02,$43,$4c,$4b
byte $4d,$4f,$44,$45,$00,$20,$00,$10,$00,$00,$00,$00,$00,$43,$4c,$4b
byte $46,$52,$45,$51,$00,$10,$00,$10,$00,$00,$00,$00,$00,$43,$4c,$4b
byte $53,$45,$54,$00,$20,$02,$40,$02,$c9,$02,$00,$00,$43,$4d,$50,$53
byte $55,$42,$00,$bc,$e0,$03,$02,$00,$00,$00,$00,$43,$4d,$50,$53,$00
byte $3c,$c0,$03,$02,$e3,$02,$73,$04,$49,$46,$5f,$42,$00,$0c,$00,$00
byte $01,$f0,$02,$b0,$03,$45,$4c,$53,$45,$00,$27,$00,$00,$00,$01,$03
byte $63,$03,$43,$4f,$4e,$53,$54,$41,$4e,$54,$00,$26,$00,$00,$00,$11
byte $03,$38,$03,$43,$4f,$47,$49,$4e,$49,$54,$00,$04,$00,$10,$02,$1d
byte $03,$2a,$03,$43,$4e,$54,$00,$02,$00,$00,$00,$00,$00,$00,$00,$43
byte $4d,$50,$58,$00,$3c,$cc,$03,$02,$00,$00,$00,$00,$43,$4f,$47,$49
byte $44,$00,$03,$00,$10,$02,$48,$03,$57,$03,$43,$4f,$47,$53,$54,$4f
byte $50,$00,$21,$01,$40,$02,$00,$00,$00,$00,$43,$4f,$47,$4e,$45,$57
byte $00,$05,$00,$10,$00,$00,$00,$00,$00,$43,$4f,$4e,$00,$11,$00,$00
byte $00,$70,$03,$96,$03,$44,$49,$52,$41,$00,$07,$00,$00,$00,$7d,$03
byte $8a,$03,$43,$54,$52,$42,$00,$0a,$00,$00,$00,$00,$00,$00,$00,$43
byte $54,$52,$41,$00,$09,$00,$00,$00,$00,$00,$00,$00,$44,$41,$54,$00
byte $12,$00,$00,$00,$a3,$03,$00,$00,$44,$4a,$4e,$5a,$00,$bc,$e4,$03
byte $02,$00,$00,$00,$00,$44,$49,$52,$42,$00,$08,$00,$00,$00,$bd,$03
byte $1f,$04,$46,$52,$51,$42,$00,$0c,$00,$00,$00,$c9,$03,$f7,$03,$46
byte $49,$54,$00,$2b,$00,$00,$00,$db,$03,$ea,$03,$45,$4c,$53,$45,$49
byte $46,$4e,$4f,$54,$00,$29,$00,$00,$00,$00,$00,$00,$00,$45,$4c,$53
byte $45,$49,$46,$00,$28,$00,$00,$00,$00,$00,$00,$00,$46,$49,$4c,$45
byte $00,$2a,$00,$00,$00,$04,$04,$12,$04,$46,$52,$4f,$4d,$00,$2d,$00
byte $00,$00,$00,$00,$00,$00,$46,$4c,$4f,$41,$54,$00,$2c,$00,$00,$00
byte $00,$00,$00,$00,$46,$52,$51,$41,$00,$0b,$00,$00,$00,$2c,$04,$53
byte $04,$49,$46,$5f,$41,$00,$01,$00,$00,$01,$37,$04,$45,$04,$49,$46
byte $00,$2e,$00,$00,$00,$00,$00,$00,$00,$48,$55,$42,$4f,$50,$00,$3c
byte $0c,$03,$02,$00,$00,$00,$00,$49,$46,$4e,$4f,$54,$00,$2f,$00,$00
byte $00,$65,$04,$00,$00,$49,$46,$5f,$41,$4c,$57,$41,$59,$53,$00,$0f
byte $00,$00,$01,$00,$00,$00,$00,$49,$46,$5f,$41,$45,$00,$03,$00,$00
byte $01,$81,$04,$77,$05,$49,$46,$5f,$4e,$45,$00,$05,$00,$00,$01,$93
byte $04,$0c,$05,$49,$46,$5f,$43,$5f,$4f,$52,$5f,$5a,$00,$0e,$00,$00
byte $01,$a6,$04,$d5,$04,$49,$46,$5f,$43,$5f,$41,$4e,$44,$5f,$5a,$00
byte $08,$00,$00,$01,$b3,$04,$c1,$04,$49,$46,$5f,$43,$00,$0c,$00,$00
byte $01,$00,$00,$00,$00,$49,$46,$5f,$42,$45,$00,$0e,$00,$00,$01,$00
byte $00,$00,$00,$49,$46,$5f,$43,$5f,$41,$4e,$44,$5f,$4e,$5a,$00,$04
byte $00,$00,$01,$e7,$04,$f9,$04,$49,$46,$5f,$43,$5f,$4e,$45,$5f,$5a
byte $00,$06,$00,$00,$01,$00,$00,$00,$00,$49,$46,$5f,$43,$5f,$45,$51
byte $5f,$5a,$00,$09,$00,$00,$01,$00,$00,$00,$00,$49,$46,$5f,$43,$5f
byte $4f,$52,$5f,$4e,$5a,$00,$0d,$00,$00,$01,$20,$05,$50,$05,$49,$46
byte $5f,$4e,$43,$5f,$41,$4e,$44,$5f,$5a,$00,$02,$00,$00,$01,$2e,$05
byte $3b,$05,$49,$46,$5f,$4e,$43,$00,$03,$00,$00,$01,$00,$00,$00,$00
byte $49,$46,$5f,$45,$00,$0a,$00,$00,$01,$00,$00,$00,$00,$49,$46,$5f
byte $4e,$43,$5f,$41,$4e,$44,$5f,$4e,$5a,$00,$01,$00,$00,$01,$63,$05
byte $00,$00,$49,$46,$5f,$4e,$43,$5f,$4f,$52,$5f,$5a,$00,$0b,$00,$00
byte $01,$00,$00,$00,$00,$49,$46,$5f,$4e,$43,$5f,$4f,$52,$5f,$4e,$5a
byte $00,$07,$00,$00,$01,$84,$05,$f3,$05,$49,$46,$5f,$5a,$00,$0a,$00
byte $00,$01,$99,$05,$cc,$05,$49,$46,$5f,$4e,$5a,$5f,$41,$4e,$44,$5f
byte $4e,$43,$00,$01,$00,$00,$01,$a7,$05,$b8,$05,$49,$46,$5f,$4e,$5a
byte $00,$05,$00,$00,$01,$00,$00,$00,$00,$49,$46,$5f,$4e,$45,$56,$45
byte $52,$00,$00,$00,$00,$01,$00,$00,$00,$00,$49,$46,$5f,$4e,$5a,$5f
byte $41,$4e,$44,$5f,$43,$00,$04,$00,$00,$01,$e0,$05,$00,$00,$49,$46
byte $5f,$4e,$5a,$5f,$4f,$52,$5f,$4e,$43,$00,$0b,$00,$00,$01,$00,$00
byte $00,$00,$49,$46,$5f,$4e,$5a,$5f,$4f,$52,$5f,$43,$00,$0e,$00,$00
byte $01,$05,$06,$3e,$06,$49,$46,$5f,$5a,$5f,$4e,$45,$5f,$43,$00,$06
byte $00,$00,$01,$19,$06,$2c,$06,$49,$46,$5f,$5a,$5f,$41,$4e,$44,$5f
byte $4e,$43,$00,$02,$00,$00,$01,$00,$00,$00,$00,$49,$46,$5f,$5a,$5f
byte $41,$4e,$44,$5f,$43,$00,$08,$00,$00,$01,$00,$00,$00,$00,$49,$46
byte $5f,$5a,$5f,$45,$51,$5f,$43,$00,$09,$00,$00,$01,$51,$06,$00,$00
byte $49,$46,$5f,$5a,$5f,$4f,$52,$5f,$4e,$43,$00,$0b,$00,$00,$01,$00
byte $00,$00,$00,$49,$46,$5f,$5a,$5f,$4f,$52,$5f,$43,$00,$0e,$00,$00
byte $01,$72,$06,$84,$09,$52,$45,$54,$55,$52,$4e,$00,$38,$00,$00,$00
byte $80,$06,$1a,$08,$4e,$45,$47,$4e,$5a,$00,$bc,$bc,$03,$02,$8c,$06
byte $64,$07,$4d,$41,$58,$00,$bc,$4c,$03,$02,$99,$06,$00,$07,$4c,$4f
byte $4e,$47,$00,$19,$00,$00,$00,$a9,$06,$d0,$06,$4c,$4f,$43,$4b,$43
byte $4c,$52,$00,$f1,$b2,$12,$00,$b5,$06,$c1,$06,$4a,$4d,$50,$00,$3c
byte $5c,$01,$02,$00,$00,$00,$00,$49,$4e,$42,$00,$04,$00,$00,$00,$00
byte $00,$00,$00,$4a,$4d,$50,$52,$45,$54,$00,$bc,$5c,$03,$02,$e0,$06
byte $f0,$06,$4c,$4f,$43,$4b,$52,$45,$54,$00,$22,$01,$40,$00,$00,$00
byte $00,$00,$4c,$4f,$43,$4b,$4e,$45,$57,$00,$d0,$92,$12,$00,$00,$00
byte $00,$00,$4c,$4f,$43,$4b,$53,$45,$54,$00,$e1,$a2,$12,$00,$12,$07
byte $45,$07,$4c,$4f,$4f,$4b,$44,$4f,$57,$4e,$5a,$00,$10,$31,$11,$00
byte $23,$07,$34,$07,$4c,$4f,$4e,$47,$4d,$4f,$56,$45,$00,$1e,$03,$40
byte $00,$00,$00,$00,$00,$4c,$4f,$4e,$47,$46,$49,$4c,$4c,$00,$1a,$03
byte $40,$00,$00,$00,$00,$00,$4c,$4f,$4f,$4b,$44,$4f,$57,$4e,$00,$11
byte $31,$11,$00,$55,$07,$00,$00,$4c,$4f,$4f,$4b,$55,$50,$5a,$00,$00
byte $21,$11,$00,$00,$00,$00,$00,$4c,$4f,$4f,$4b,$55,$50,$00,$01,$21
byte $11,$00,$71,$07,$ca,$07,$4d,$55,$58,$43,$00,$bc,$70,$03,$02,$7d
byte $07,$a3,$07,$4d,$4f,$56,$00,$bc,$a0,$03,$02,$89,$07,$96,$07,$4d
byte $49,$4e,$00,$bc,$48,$03,$02,$00,$00,$00,$00,$4d,$41,$58,$53,$00
byte $bc,$44,$03,$02,$00,$00,$00,$00,$4d,$49,$4e,$53,$00,$bc,$40,$03
byte $02,$b0,$07,$bd,$07,$4d,$4f,$56,$49,$00,$bc,$58,$03,$02,$00,$00
byte $00,$00,$4d,$4f,$56,$44,$00,$bc,$54,$03,$02,$00,$00,$00,$00,$4d
byte $4f,$56,$53,$00,$bc,$50,$03,$02,$d6,$07,$ff,$07,$4e,$45,$47,$00
byte $bc,$a4,$03,$02,$e4,$07,$f2,$07,$4d,$55,$58,$4e,$5a,$00,$bc,$7c
byte $03,$02,$00,$00,$00,$00,$4d,$55,$58,$4e,$43,$00,$bc,$74,$03,$02
byte $00,$00,$00,$00,$4d,$55,$58,$5a,$00,$bc,$78,$03,$02,$0d,$08,$00
byte $00,$4e,$45,$47,$4e,$43,$00,$bc,$b4,$03,$02,$00,$00,$00,$00,$4e
byte $45,$47,$43,$00,$bc,$b0,$03,$02,$27,$08,$d5,$08,$50,$48,$53,$42
byte $00,$0e,$00,$00,$00,$33,$08,$87,$08,$4f,$52,$47,$00,$31,$00,$00
byte $00,$3f,$08,$65,$08,$4e,$4f,$54,$00,$ff,$00,$09,$08,$4c,$08,$59
byte $08,$4e,$45,$58,$54,$00,$30,$00,$00,$00,$00,$00,$00,$00,$4e,$45
byte $47,$5a,$00,$bc,$b8,$03,$02,$00,$00,$00,$00,$4e,$4f,$50,$00,$00
byte $00,$00,$02,$71,$08,$7c,$08,$4f,$42,$4a,$00,$13,$00,$00,$00,$00
byte $00,$00,$00,$4e,$52,$00,$08,$00,$80,$00,$00,$00,$00,$00,$4f,$52
byte $00,$f2,$00,$0b,$06,$94,$08,$bc,$08,$4f,$55,$54,$42,$00,$06,$00
byte $00,$00,$a2,$08,$af,$08,$4f,$54,$48,$45,$52,$00,$33,$00,$00,$00
byte $00,$00,$00,$00,$4f,$52,$47,$58,$00,$32,$00,$00,$00,$00,$00,$00
byte $00,$4f,$55,$54,$41,$00,$05,$00,$00,$00,$c9,$08,$00,$00,$50,$48
byte $53,$41,$00,$0d,$00,$00,$00,$00,$00,$00,$00,$50,$41,$52,$00,$01
byte $00,$00,$00,$e4,$08,$30,$09,$52,$44,$4c,$4f,$4e,$47,$00,$bc,$08
byte $03,$02,$f0,$08,$15,$09,$52,$43,$4c,$00,$bc,$34,$03,$02,$fc,$08
byte $08,$09,$50,$55,$42,$00,$15,$00,$00,$00,$00,$00,$00,$00,$50,$52
byte $49,$00,$14,$00,$00,$00,$00,$00,$00,$00,$51,$55,$49,$54,$00,$34
byte $00,$00,$00,$24,$09,$00,$00,$52,$44,$42,$59,$54,$45,$00,$bc,$00
byte $03,$02,$00,$00,$00,$00,$52,$43,$52,$00,$bc,$30,$03,$02,$3c,$09
byte $69,$09,$52,$45,$53,$00,$36,$00,$00,$00,$4b,$09,$5a,$09,$52,$45
byte $42,$4f,$4f,$54,$00,$06,$00,$10,$00,$00,$00,$00,$00,$52,$44,$57
byte $4f,$52,$44,$00,$bc,$04,$03,$02,$00,$00,$00,$00,$52,$45,$50,$45
byte $41,$54,$00,$35,$00,$00,$00,$75,$09,$00,$00,$52,$45,$54,$00,$7c
byte $5c,$00,$02,$00,$00,$00,$00,$52,$45,$53,$55,$4c,$54,$00,$37,$00
byte $00,$00,$91,$09,$0e,$0b,$56,$53,$43,$4c,$00,$10,$00,$00,$00,$9e
byte $09,$57,$0a,$53,$55,$42,$53,$00,$bc,$d4,$03,$02,$aa,$09,$00,$0a
byte $53,$50,$52,$00,$3a,$00,$00,$00,$b8,$09,$dc,$09,$52,$4f,$55,$4e
byte $44,$00,$39,$00,$00,$00,$c4,$09,$d0,$09,$52,$4f,$4c,$00,$bc,$24
byte $03,$02,$00,$00,$00,$00,$52,$45,$56,$00,$bc,$3c,$03,$02,$00,$00
byte $00,$00,$52,$4f,$52,$00,$bc,$20,$03,$02,$e8,$09,$f4,$09,$53,$48
byte $4c,$00,$bc,$2c,$03,$02,$00,$00,$00,$00,$53,$41,$52,$00,$bc,$38
byte $03,$02,$00,$00,$00,$00,$53,$48,$52,$00,$bc,$28,$03,$02,$10,$0a
byte $3c,$0a,$53,$54,$52,$53,$49,$5a,$45,$00,$61,$01,$10,$00,$20,$0a
byte $2d,$0a,$53,$54,$52,$43,$4f,$4d,$50,$00,$72,$01,$10,$00,$00,$00
byte $00,$00,$53,$54,$45,$50,$00,$3b,$00,$00,$00,$00,$00,$00,$00,$53
byte $54,$52,$49,$4e,$47,$00,$3c,$00,$00,$00,$4b,$0a,$00,$00,$53,$55
byte $42,$41,$42,$53,$00,$bc,$8c,$03,$02,$00,$00,$00,$00,$53,$55,$42
byte $00,$bc,$84,$03,$02,$64,$0a,$c2,$0a,$54,$4a,$4e,$5a,$00,$3c,$e8
byte $03,$02,$72,$0a,$9a,$0a,$53,$55,$4d,$4e,$43,$00,$bc,$94,$03,$02
byte $7f,$0a,$8d,$0a,$53,$55,$42,$58,$00,$bc,$cc,$03,$02,$00,$00,$00
byte $00,$53,$55,$42,$53,$58,$00,$bc,$dc,$03,$02,$00,$00,$00,$00,$53
byte $55,$4d,$43,$00,$bc,$90,$03,$02,$a7,$0a,$b5,$0a,$53,$55,$4d,$5a
byte $00,$bc,$98,$03,$02,$00,$00,$00,$00,$53,$55,$4d,$4e,$5a,$00,$bc
byte $9c,$03,$02,$00,$00,$00,$00,$54,$45,$53,$54,$00,$3c,$60,$03,$02
byte $d0,$0a,$f5,$0a,$55,$4e,$54,$49,$4c,$00,$3f,$00,$00,$00,$db,$0a
byte $e7,$0a,$54,$4f,$00,$3d,$00,$00,$00,$00,$00,$00,$00,$54,$4a,$5a
byte $00,$3c,$ec,$03,$02,$00,$00,$00,$00,$54,$52,$55,$4e,$43,$00,$3e
byte $00,$00,$00,$02,$0b,$00,$00,$56,$43,$46,$47,$00,$0f,$00,$00,$00
byte $00,$00,$00,$00,$56,$41,$52,$00,$16,$00,$00,$00,$1a,$0b,$e5,$0b
byte $58,$4f,$52,$00,$bc,$6c,$03,$02,$2b,$0b,$91,$0b,$57,$4f,$52,$44
byte $46,$49,$4c,$4c,$00,$19,$03,$40,$00,$3b,$0b,$6b,$0b,$57,$41,$49
byte $54,$56,$49,$44,$00,$27,$02,$40,$02,$4b,$0b,$5b,$0b,$57,$41,$49
byte $54,$50,$45,$51,$00,$1b,$03,$40,$02,$00,$00,$00,$00,$57,$41,$49
byte $54,$43,$4e,$54,$00,$23,$01,$40,$02,$00,$00,$00,$00,$57,$41,$49
byte $54,$50,$4e,$45,$00,$1f,$03,$40,$02,$79,$0b,$84,$0b,$57,$48,$49
byte $4c,$45,$00,$40,$00,$00,$00,$00,$00,$00,$00,$57,$43,$00,$02,$00
byte $80,$00,$00,$00,$00,$00,$57,$4f,$52,$44,$00,$18,$00,$00,$00,$a0
byte $0b,$cb,$0b,$57,$52,$4c,$4f,$4e,$47,$00,$3c,$08,$03,$02,$ab,$0b
byte $bc,$0b,$57,$52,$00,$01,$00,$80,$00,$00,$00,$00,$00,$57,$4f,$52
byte $44,$4d,$4f,$56,$45,$00,$1d,$03,$40,$00,$00,$00,$00,$00,$57,$52
byte $42,$59,$54,$45,$00,$3c,$00,$03,$02,$d6,$0b,$00,$00,$57,$5a,$00
byte $04,$00,$80,$00,$00,$00,$00,$00,$57,$52,$57,$4f,$52,$44,$00,$3c
byte $04,$03,$02,$ef,$0b,$2c,$0c,$7c,$00,$ea,$00,$04,$04,$f9,$0b,$17
byte $0c,$5e,$00,$eb,$00,$04,$04,$03,$0c,$0d,$0c,$5c,$00,$42,$00,$00
byte $00,$00,$00,$00,$00,$5b,$00,$41,$00,$00,$00,$00,$00,$00,$00,$5d
byte $00,$43,$00,$00,$00,$21,$0c,$00,$00,$7b,$00,$44,$00,$00,$00,$00
byte $00,$00,$00,$5e,$5e,$00,$f8,$00,$01,$08,$36,$0c,$56,$0c,$7e,$00
byte $10,$18,$00,$0c,$41,$0c,$4c,$0c,$7c,$7c,$00,$e9,$00,$01,$08,$00
byte $00,$00,$00,$7c,$3c,$00,$f3,$00,$01,$08,$00,$00,$00,$00,$7d,$00
byte $45,$00,$00,$00,$61,$0c,$00,$00,$7e,$7e,$00,$14,$1c,$00,$0c,$00
byte $00,$00,$00,$7e,$3e,$00,$ee,$00,$02,$04
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,274 +0,0 @@
pub blah
con ' The following is auto-generated. Do not edit.
kID = $80000000
kINTLITERAL = $40000000
kFLOATLITERAL = $20000000
kUNARY = $08000000
kBINARY = $04000000
kPOSTFIX = $04000000
kPASM = $02000000
kCOND = $01000000
kEFFECT = $00800000
kSTMTFN = $00400000
kASSIGNMENT = $00200000
kINTRINSIC = $00100000
' kBANG = $080100e7
' kOCTOTHORPRANGLE = $040700e4
' kAMPERSAND = $040300e8
' kSTAR = $040500f4
' kSTARSTAR = $040500f5
kPLUS = $040600ec
' kPLUSPLUS = $0c002820
kMINUS = $040600ed
' kMINUSMINUS = $0c003830
' kMINUSRANGLE = $040200e0
' kSLASH = $040500f6
' kSLASHSLASH = $040500f7
' kLANGLE = $040800f9
' kLANGLEOCTOTHORP = $040700e5
' kLANGLEMINUS = $040200e1
' kLANGLELANGLE = $040200e3
' kLANGLERANGLE = $040800fb
' kEQUALLANGLE = $040800fd
' kEQUALEQUAL = $040800fc
' kEQUALRANGLE = $040800fe
' kRANGLE = $040800fa
' kRANGLELANGLE = $040200ef
' kRANGLERANGLE = $040200e2
' kRANGLEBAR = $080100f1
kQUESTION = $0c000c08
kAT = $08000000
kATAT = $08000001
' kCARET = $040400eb
' kCARETCARET = $080100f8
kBAR = $040400ea
' kBARLANGLE = $080100f3
' kBARBAR = $080100e9
kTILDE = $0c001810
' kTILDERANGLE = $040200ee
kTILDETILDE = $0c001c14
kAND = $060a00f0
' kNOT = $080900ff
kOR = $060b00f2
' kABS = $0203a8bc
' kABSNEG = $0203acbc
' kADD = $020380bc
' kADDABS = $020388bc
' kADDS = $0203d0bc
' kADDSX = $0203d8bc
' kADDX = $0203c8bc
' kANDN = $020364bc
kCALL = $02015cfc
' kCMP = $0203843c
' kCMPS = $0203c03c
' kCMPSUB = $0203e0bc
' kCMPSX = $0203c43c
' kCMPX = $0203cc3c
' kDJNZ = $0203e4bc
' kHUBOP = $02030c3c
' kJMP = $02015c3c
' kJMPRET = $02035cbc
' kMAX = $02034cbc
' kMAXS = $020344bc
' kMIN = $020348bc
' kMINS = $020340bc
' kMOV = $0203a0bc
' kMOVD = $020354bc
' kMOVI = $020358bc
' kMOVS = $020350bc
' kMUXC = $020370bc
' kMUXNC = $020374bc
' kMUXNZ = $02037cbc
' kMUXZ = $020378bc
' kNEG = $0203a4bc
' kNEGC = $0203b0bc
' kNEGNC = $0203b4bc
' kNEGNZ = $0203bcbc
' kNEGZ = $0203b8bc
' kNOP = $02000000
' kRCL = $020334bc
' kRCR = $020330bc
' kRDBYTE = $020300bc
' kRDLONG = $020308bc
' kRDWORD = $020304bc
' kRET = $02005c7c
' kREV = $02033cbc
' kROL = $020324bc
' kROR = $020320bc
' kSAR = $020338bc
' kSHL = $02032cbc
' kSHR = $020328bc
' kSUB = $020384bc
' kSUBABS = $02038cbc
' kSUBS = $0203d4bc
' kSUBSX = $0203dcbc
' kSUBX = $0203ccbc
' kSUMC = $020390bc
' kSUMNC = $020394bc
' kSUMNZ = $02039cbc
' kSUMZ = $020398bc
' kTEST = $0203603c
' kTJNZ = $0203e83c
' kTJZ = $0203ec3c
' kWRBYTE = $0203003c
' kWRLONG = $0203083c
' kWRWORD = $0203043c
' kXOR = $02036cbc
kPAR = $00000001
' kCNT = $00000002
' kINA = $00000003
' kINB = $00000004
' kOUTA = $00000005
' kOUTB = $00000006
' kDIRA = $00000007
' kDIRB = $00000008
' kCTRA = $00000009
' kCTRB = $0000000a
' kFRQA = $0000000b
' kFRQB = $0000000c
' kPHSA = $0000000d
' kPHSB = $0000000e
' kVCFG = $0000000f
kVSCL = $00000010
' kIF_A = $01000001
' kIF_AE = $01000003
' kIF_ALWAYS = $0100000f
' kIF_B = $0100000c
' kIF_BE = $0100000e
' kIF_C = $0100000c
' kIF_C_AND_NZ = $01000004
' kIF_C_AND_Z = $01000008
' kIF_C_EQ_Z = $01000009
' kIF_C_NE_Z = $01000006
' kIF_C_OR_NZ = $0100000d
' kIF_C_OR_Z = $0100000e
' kIF_E = $0100000a
' kIF_NC = $01000003
' kIF_NC_AND_NZ = $01000001
' kIF_NC_AND_Z = $01000002
' kIF_NC_OR_NZ = $01000007
' kIF_NC_OR_Z = $0100000b
' kIF_NE = $01000005
' kIF_NEVER = $01000000
' kIF_NZ = $01000005
' kIF_NZ_AND_C = $01000004
' kIF_NZ_AND_NC = $01000001
' kIF_NZ_OR_C = $0100000e
' kIF_NZ_OR_NC = $0100000b
' kIF_Z = $0100000a
' kIF_Z_AND_C = $01000008
' kIF_Z_AND_NC = $01000002
' kIF_Z_EQ_C = $01000009
' kIF_Z_NE_C = $01000006
' kIF_Z_OR_C = $0100000e
' kIF_Z_OR_NC = $0100000b
' kNR = $00800008
' kWC = $00800002
' kWR = $00800001
' kWZ = $00800004
kCON = $00000011
kDAT = $00000012
kOBJ = $00000013
kPRI = $00000014
kPUB = $00000015
kVAR = $00000016
kBYTE = $00000017
kWORD = $00000018
kLONG = $00000019
' kBYTEFILL = $00400318
' kWORDFILL = $00400319
' kLONGFILL = $0040031a
' kBYTEMOVE = $0040031c
' kWORDMOVE = $0040031d
' kLONGMOVE = $0040031e
kCLKSET = $02400220
kCOGSTOP = $02400121
' kLOCKRET = $00400122
kWAITCNT = $02400123
kWAITPEQ = $0240031b
kWAITPNE = $0240031f
kWAITVID = $02400227
kOCTOTHORP = $0000001a
' kDOLLAR = $0000001b
kLPAREN = $0000001c
kRPAREN = $0000001d
kCOMMA = $0000001e
kDOT = $0000001f
kDOTDOT = $00000020
kCOLON = $00000021
kCOLONEQUAL = $00200022
kEQUAL = $00000023
kABORT = $00000024
kCASE = $00000025
kCHIPVER = $00100000
kCLKFREQ = $00100010
kCLKMODE = $00100020
kCOGID = $02100003
kCOGINIT = $02100004
kCOGNEW = $00100005
kREBOOT = $00100006
' kSTRCOMP = $00100172
' kSTRSIZE = $00100161
' kLOCKCLR = $0012b2f1
' kLOCKNEW = $001292d0
' kLOCKSET = $0012a2e1
' kLOOKDOWN = $00113111
' kLOOKDOWNZ = $00113110
' kLOOKUP = $00112101
' kLOOKUPZ = $00112100
kCONSTANT = $00000026
kELSE = $00000027
kELSEIF = $00000028
kELSEIFNOT = $00000029
' kFILE = $0000002a
kFIT = $0000002b
' kFLOAT = $0000002c
kFROM = $0000002d
kIF = $0000002e
kIFNOT = $0000002f
kNEXT = $00000030
kORG = $00000031
' kORGX = $00000032
kOTHER = $00000033
kQUIT = $00000034
kREPEAT = $00000035
kRES = $00000036
kRESULT = $00000037
kRETURN = $00000038
' kROUND = $00000039
kSPR = $0000003a
kSTEP = $0000003b
kSTRING = $0000003c
kTO = $0000003d
' kTRUNC = $0000003e
kUNTIL = $0000003f
kWHILE = $00000040
kLBRACKET = $00000041
kBACKSLASH = $00000042
kRBRACKET = $00000043
kLBRACE = $00000044
kRBRACE = $00000045
kEOL = $000000fd
kEOF = $000000fe
kUNKNOWN = $000000ff
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,166 +0,0 @@
{{
Lex
usage: lex filename [options]
Reads filename.spn on SD card, writes tokens to filename.tok.
}}
con
_clkmode = xtal1 + pll8x
_xinfreq = 10_000_000
tvPin = 24
sdPin = 16
obj
term: "isxtv"
token: "tokenizr"
kw: "keywords"
fs: "sxfile" ' used for writing .tok file
str: "stringx"
bt: "bintree"
pub Main | err, p
err := \Try
if err
if err > 0
term.str( err )
else
term.str( string("Error ") )
term.dec( err )
term.out( 13 )
term.dec( token.LineNumber )
term.out( "," )
term.dec( token.Column + 1 )
term.out( " " )
term.out( "'" )
term.str( pTokenText )
term.out( "'" )
term.out( 13 )
fs.Close
fs.Open( string("sphinx.bin"), "R" )
else
fs.Close
if compile
fs.Open( string("codegen.bin"), "R" )
else
fs.Open( string("sphinx.bin"), "R" )
bt.Stop
fs.Execute( 0 )
var
long pTokenText
pri Try
bt.Init( 0, 0 )
ProcessCommandLine
if verbosity => 1
term.str( string("lex 090627", 13) )
Start
pri ProcessCommandLine | nArgs, l
fs.Open( string("args.d8a"), "R" )
nArgs := fs.ReadByte
ifnot nArgs--
abort string("usage: lex spinfile [options]")
fs.ReadStringUpperCase( @spinFilename, MAXFILENAMELENGTH )
l := strsize( @spinFilename )
if spinFilename[l-4] == "." and spinFilename[l-3] == "S" and spinFilename[l-2] == "P" and spinFilename[l-1] == "N"
spinFilename[l-4]~
if strsize( @spinFilename ) > 8
term.str( @spinFilename )
abort string(" -- filename too long")
str.Copy( @outputFilename, @spinFilename )
str.Append( @spinFilename, string(".SPN") )
str.Append( @outputFilename, string(".TOK") )
' Process command line arguments
repeat while nArgs--
fs.ReadStringUpperCase( @stringBuffer, MAXSTRINGBUFFERLENGTH )
if stringBuffer[0] == "-"
stringBuffer[0] := "/"
if strcomp( @stringBuffer, string("/C") )
compile~~
elseif strcomp( @stringBuffer, string("/L") )
compile~~
elseif strcomp( @stringBuffer, string("/V") )
ifnot nArgs--
abort string("/V must be followed by a number")
verbosity := fs.ReadNumber
'else ignore
fs.Close
con
MAXFILENAMELENGTH = 8 + 1 + 3 ' 8.3
MAXSTRINGBUFFERLENGTH = 32
var
byte spinFilename[MAXFILENAMELENGTH+1] ' input .spi file
byte outputFilename[MAXFILENAMELENGTH+1] ' output .tok file
byte stringBuffer[MAXSTRINGBUFFERLENGTH+1] ' temp string buffer
dat
verbosity byte 0 ' set by /V option
compile byte 0 ' set by /C or /L: if non-zero, run compile.bin automatically.
type long 0
lineNum word 0
column word 0
pri Start | v
kw.Init
pTokenText := token.GetPText
if verbosity => 2
term.str( string("Reading ") )
term.str( @spinFilename )
term.out( 13 )
token.Open( @spinFilename )
if verbosity => 2
term.str( string("Writing ") )
term.str( @outputFilename )
term.out( 13 )
fs.Open( @outputFilename, "W" )
repeat
type := token.Type
lineNum := token.LineNumber
column := token.Column
fs.Write( @type, 8 ) ' long + word + word
if type == kw#kINTLITERAL or type == kw#kFLOATLITERAL
v := token.Value
fs.Write( @v, 4 )
else
fs.Write( pTokenText, strsize(pTokenText) + 1 )
if token.Type == kw#kEOF
quit
token.Advance
token.Close
fs.Close
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,616 +0,0 @@
{
.sob linker
2009
April
10 Successfully linked two test programs
15 SOB1 format:
#args in exported pubs now just one byte
added byte to imports for possible future use with object "pointers"
rearranged fields in SOB file header so that longs are long-aligned in memory
June
9 Sphinxified
timestamp comparison
12 Removed /s and /t options
18 Don't stop on first out-of-date error.
To do:
removal of duplicate sobs
Usage: link sobname [options]
sobname is name of .sob file, with or without .sob suffix.
Options start with / or - and are case-insensitive:
/v <n> -- Sets verbosity level. Higher values of n => more verbose. Default is 0.
SOB file format
0 4 bytes: SOB file format version #
4 4 bytes: OBJ timestamp or version
8 4 bytes: hash of OBJ's binary code.
12 2 bytes: NUMEXPORTS
14 2 bytes: EXPORTSIZE
16 2 bytes: NUMIMPORTS
18 2 bytes: IMPORTSIZE
20 2 bytes: OBJBINSIZE (this is always a multiple of 4)
22 1 byte: checksum
23 1 byte: reserved
24 2 bytes: size of OBJ's VAR space.
26 EXPORTSIZE bytes: exported symbols: CONs, PUBs, maybe PRIs.
IMPORTSIZE bytes: OBJ's sub-OBJs.
OBJBINSIZE bytes: the compiled OBJ: header followed by methods.
Export record format
name + null + 0 + 4-byte int CON int
name + null + 1 + 4-byte float CON float
name + null + 2 + index + #args PUB
name + null + 3 + index + #args PRI (not exported)
Import record format
name + null + 2-byte count + reserved
Export and import names are uppercase. Import name must not include ".SOB" or other suffix.
}
SIZEOFSOBHEADER = 26
obj
term: "isxtv"
fs[2]: "sxfile"
str: "stringx"
pub Main | err
err := \Try
if err
if err > 0
term.str( err )
else
term.str( string("Error ") )
term.dec( err )
term.out( 13 )
fs[0].Close
fs[0].Open( string("sphinx.bin"), "R" )
fs[0].Execute( 0 )
dat
STACKSPACE long 500 ' in bytes; must be multiple of 4
TABLESPACE long 1000 ' in bytes; must be multiple of 4
WORKSPACE long 0
verbosity byte 0
outOfDate byte 0
ignoreOutOfDate byte 0
pri Try | nArgs, pTable, pWork, l, p, totalVarSize
fs.Open( string("args.d8a"), "R" )
nArgs := fs.ReadByte
ifnot nArgs--
abort string("usage: link sobname [options]")
fs.ReadStringUpperCase( @sobName, MAXFILENAMELENGTH )
l := strsize( @sobName )
if sobName[l-4] == "." and sobName[l-3] == "S" and sobName[l-2] == "O" and sobName[l-1] == "B"
sobName[l-4]~
if strsize( @sobName ) > 8
term.str( @sobName )
abort string(" -- sobname too long")
str.Copy( @outputName, @sobName )
' Process command line arguments
repeat while nArgs--
fs.ReadStringUpperCase( @stringBuffer, 20 )
if stringBuffer[0] == "-"
stringBuffer[0] := "/"
if strcomp( @stringBuffer, string("/V") )
ifnot nArgs--
abort string("/V must be followed by a number")
verbosity := fs.ReadNumber
elseif strcomp( @stringBuffer, string("/I") )
ignoreOutOfDate~~
{
elseif strcomp( @stringBuffer, string("/S") )
ifnot nArgs--
abort string("/S must be followed by a number")
STACKSPACE := fs.ReadNumber
if STACKSPACE & 3
abort string("/S argument must be a multiple of 4")
elseif strcomp( @stringBuffer, string("/T") )
ifnot nArgs--
abort string("/T must be followed by a number")
TABLESPACE := fs.ReadNumber
if TABLESPACE & 3
abort string("/T argument must be a multiple of 4")
}
'else
'ignore
fs.Close
if verbosity => 1
term.str( string("link 090627", 13) )
pTable := word[$000a] + STACKSPACE
pWork := pTable + TABLESPACE
WORKSPACE := 32768-pWork
if verbosity => 2
term.dec( WORKSPACE )
term.str( string(" bytes of work space", 13) )
if WORKSPACE =< 0
abort string("No work space")
SobInit( pTable, TABLESPACE )
AddSob( @sobName )
ProcessSob( pTable, true )
checksum~
totalVarSize := ComputeAddressAndTotalVarSize( pTable, $0010 )
word[@header][3] := $0010
word[@header[$08]] := objBinEndAddress
word[@header[$0a]] := objBinEndAddress + totalVarSize + 8
word[@header[$0c]] := firstPubOffset + $0010
word[@header[$0e]] := word[@header[$0a]] + firstPubLocalsSize + (firstPubNumArgs + 1) << 2
AddToChecksum( @header, $10 )
AddToChecksum( @footer, 8 )
header[5] := -checksum
if verbosity => 3
p := pTable
repeat while p
term.str( word[p +_pName] )
term.out( " " )
term.hex( word[p +_startAddress], 4 )
term.out( " " )
term.dec( word[p +_totalVarSize] )
term.out( " " )
term.hex( byte[p +_checksum], 2 )
term.out( 13 )
p := word[p +_pNextSorted]
if not outOfDate or ignoreOutOfDate
str.Append( @outputName, string(".BIN") )
if verbosity => 2
term.str( string("Writing ") )
term.str( @outputName )
term.out( 13 )
WriteBinaryFile( @outputName, pTable, pWork, WORKSPACE )
else
term.str( string("No .bin written", 13) )
pri WriteBinaryFile( pFilename, pSob, pBuff, buffsize ) | n, p, pImports, pCounts, interObjectOffset, varOffset
{{
Go down the priority-sorted list of sobs assigning them hub addresses such that they follow one
another in memory. On the way back up the list, compute each sob's total VAR size (the sob's
own VARs plus its imported sobs' VARs.)
Also updates checksum.
Return value is the current sob's total VAR size. Only the top object's return value is looked at.
}}
fs[0].Open( pFilename, "W" )
fs[0].Write( @header, 16 )
repeat while pSob
str.Copy( @stringBuffer, word[pSob +_pName] )
str.Append( @stringBuffer, string(".SOB") )
if verbosity => 2
term.str( @stringBuffer )
term.str( string(" -- copying", 13) )
n := word[pSob +_objBinSize]
if n > buffsize
abort string("work area too small")
fs[1].Open( @stringBuffer, "R" )
fs[1].SkipBytes( SIZEOFSOBHEADER + word[pSob +_exportImportSize] )
fs[1].Read( pBuff, n )
fs[1].Close
p := pBuff + byte[pBuff][2] << 2 ' byte[2] is index of 1st obj entry; multiply by 4 bytes/entry
varOffset := word[pSob +_varSize]
pImports := word[pSob +_pImports]
pCounts := word[pSob +_pCounts]
repeat word[pSob +_nImports]
interObjectOffset := word[ word[pImports] +_startAddress] - word[pSob +_startAddress]
repeat word[pCounts]
word[p] := interObjectOffset
p += 2
word[p] := varOffset
p += 2
varOffset += word[ word[pImports] +_totalVarSize]
pImports += 2
pCounts += 2
fs[0].Write( pBuff, n )
pSob := word[pSob +_pNextSorted]
fs[0].Close
{{
objBinEndAddress := address ' end address will point just beyond the last obj in hub memory.
' Here we're just overwriting as we go and keeping the last one.
ComputeAddressAndTotalVarSize( word[p +_pNextSorted], address )
checksum += byte[p +_checksum] ' this is the partial checksum of the obj (doesn't count its sub-object table because
' sub-object links are not known until link time (i.e., now))
totalVarSize := word[p +_varSize]
pImports := word[p +_pImports]
pCounts := word[p +_pCounts]
repeat word[p +_nImports] ' for each import, add the import's VAR size multiplied by its count
interObjectOffset := word[ word[pImports] +_startAddress] - word[p +_startAddress]
repeat word[pCounts]
AddToChecksum( @totalVarSize, 2 ) ' checksum needs to include this half of an object table entry
AddToChecksum( @interObjectOffset, 2 ) ' and this other half of an object table entry
totalVarSize += word[ word[pImports] +_totalVarSize]
pImports += 2
pCounts += 2
word[p +_totalVarSize] := totalVarSize
}}
var
word firstPubLocalsSize
word firstPubOffset
word firstPubNumArgs
word objBinEndAddress
byte checksum
long clk_freq
long xin_freq
long clk_mode
long free
long stack
pri ReadExports( numExports ) | firstPub, type, val, index, nArgs, i, p, f, frequency
f~
firstPub~~
stack := 16
frequency := 12_000_000
repeat numExports
fs.ReadStringUpperCase( @stringBuffer, MAXEXPORTLENGTH )
case type := fs.ReadByte
0, 1: ' int or float CON
val := fs.ReadLong
2, 3: ' PUB or PRI
index := fs.ReadByte
nArgs := fs.ReadByte
if firstPub~
firstPubNumArgs := nArgs
repeat i from 0 to 4
if strcomp( @stringBuffer, @@ptrs[i] )
if type
term.str( @stringBuffer )
abort string(" -- not an int CON")
clk_freq[i] := val
f |= |< i
f &= 7
if clk_mode & 3
f |= 8
case f ' four bits: rc|clkmode|xinfreq|clkfreq
%0000: ' none of clkmode/xinfreq/clkfreq specified
%0001..%0011: abort string("_CLKMODE must be specified")
%0100: abort string("_CLKFREQ or _XINFREQ must be specified")
%0101: frequency := clk_freq
%0110: frequency := xin_freq * ((clk_mode >> 6) #> 1)
%0111: if clk_freq <> xin_freq * ((clk_mode >> 6) #> 1)
abort string("conflicting _CLKFREQ and _XINFREQ")
%1000..%1011: ' these cases shouldn't happen
%1100: ' this case is OK
%1101..%1111: abort string("RCFAST/SLOW incompatible with _CLKFREQ/_XINFREQ")
long[@header] := frequency
header[4] := ComputeClkmodeByte( clk_mode )
pri ComputeClkmodeByte( mode ) : m | b1, b2, i
{
rcfast $001 exactly one 1 in 0000_0000_00xx incompatible with clkfreq/xinfreq
rcslow $002
or
xinput $004 exactly one 1 in 0000_00xx_xx00 and requires clkfreq/xinfreq
xtal1 $008 up to one 1 in 0xxx_xx00_0000
xtal2 $010
xtal3 $020
pll1x $040
pll2x $080
pll4x $100
pll8x $200
pll16x $400
}
b1 := -1 ' b1 is the position of the single 1 in mode[5..0].
repeat i from 0 to 5
if mode & |< i
if b1 <> -1
abort string("invalid _CLKMODE") ' only one 1 allowed
b1 := i
m := lookupz( b1: $00, $01, $22, $2a, $32, $3a )
b2 := -1 ' b2 is the position of single 1 in mode[10..6] (-1 if no 1 bit)
repeat i from 6 to 10
if mode & |< i
if b2 <> -1
abort string("invalid _CLKMODE (multiple PLL)") ' only one 1 allowed
b2 := i
if b1 < 2 ' RCFAST/RCSLOW?
if b2 <> -1 ' b2 better not be set
abort string("invalid _CLKMODE (RC+PLL)")
else ' one of the X-modes
if b2 <> -1
m |= $40 ' PLLENA
m += b2 - 5
dat
ptrs word @s0, @s1, @s2, @s3, @s4
s0 byte "_CLKFREQ", 0
s1 byte "_XINFREQ", 0
s2 byte "_CLKMODE", 0
s3 byte "_FREE", 0
s4 byte "_STACK", 0
dat
long
header byte 0[16]
footer byte $ff, $ff, $f9, $ff
byte $ff, $ff, $f9, $ff
con
MAXFILENAMELENGTH = 8 + 1 + 3 ' 8.3
MAXEXPORTLENGTH = 32
var
byte stringBuffer[MAXEXPORTLENGTH+1]
byte sobName[MAXFILENAMELENGTH+1]
byte outputName[MAXFILENAMELENGTH+1]
con
#0
_pNext[2]
_pNextSorted[2]
_pName[2]
_nImports[2]
_pImports[2]
_pCounts[2]
_startAddress[2]
_objBinSize[2]
_totalVarSize[2]
_varSize[2]
_timestamp[4]
_exportImportSize[2]
_checksum[1]
_[1] ' for alignment: _SIZEOFSOBINFO must be a multiple of 4
_SIZEOFSOBINFO
SOBFILEFORMATVERSION = "S" + "O" << 8 + "B" << 16 + "1" << 24 ' "SOB1"
dat
pSobSpace word 0
SOBSSIZE word 0
pDataSpace word 0
pFirst word 0
pLast word 0
pLastSorted word 0
pri SobInit( p, size )
pFirst := pSobSpace := p
SOBSSIZE := size
pDataSpace := pSobSpace + SOBSSIZE
pLastSorted := pLast := pFirst
word[pFirst +_pNext]~
word[pFirst +_pNextSorted]~
pri ComputeAddressAndTotalVarSize( p, address ) : totalVarSize | pImports, pCounts, interObjectOffset
{{
Go down the priority-sorted list of sobs assigning them hub addresses such that they follow one
another in memory. On the way back up the list, compute each sob's total VAR size (the sob's
own VARs plus its imported sobs' VARs.)
Also updates checksum.
Return value is the current sob's total VAR size. Only the top object's return value is looked at.
}}
ifnot p
return
word[p +_startAddress] := address
address += word[p +_objBinSize]
objBinEndAddress := address ' end address will point just beyond the last obj in hub memory.
' Here we're just overwriting as we go and keeping the last one.
ComputeAddressAndTotalVarSize( word[p +_pNextSorted], address )
checksum += byte[p +_checksum] ' this is the partial checksum of the obj (doesn't count its sub-object table because
' sub-object links are not known until link time (i.e., now))
totalVarSize := word[p +_varSize]
pImports := word[p +_pImports]
pCounts := word[p +_pCounts]
repeat word[p +_nImports] ' for each import, add the import's VAR size multiplied by its count
interObjectOffset := word[ word[pImports] +_startAddress] - word[p +_startAddress]
repeat word[pCounts]
AddToChecksum( @totalVarSize, 2 ) ' checksum needs to include this half of an object table entry
AddToChecksum( @interObjectOffset, 2 ) ' and this other half of an object table entry
totalVarSize += word[ word[pImports] +_totalVarSize]
pImports += 2
pCounts += 2
word[p +_totalVarSize] := totalVarSize
pri AddToChecksum( p, n )
repeat n
checksum += byte[p++]
pri AddSob( pName ) : p | n
{{
Copies name to data area, appends name to the sobs list, returns pointer to new sob entry.
}}
if verbosity => 2
term.str(string("adding "))
term.str(pName)
term.out(13)
p := pSobSpace
pSobSpace += _SIZEOFSOBINFO
n := strsize(pName) + 1
bytemove( Alloc(n), pName, n )
word[pLast +_pNext] := p
word[pLastSorted +_pNextSorted] := p
word[p +_pName] := pDataSpace
word[p +_pNext]~
word[p +_pNextSorted]~
pLast := p
pLastSorted := p
pri Alloc( n )
pDataSpace := (pDataSpace - n) & $fffffffc ' long-aligned
if pDataSpace < pSobSpace
abort string("Insufficient sob table space")
return pDataSpace
pri FindSob( pName ) : p | pPrev
{{
Search the sob list in priority order. If a sob in the list matches name,
update priority-order links to put the sob at the end and return a pointer to it.
Otherwise, return 0.
}}
p := pPrev := pFirst
repeat while p
if strcomp( word[p +_pName], pName )
if p <> pLastSorted
word[pPrev +_pNextSorted] := word[p +_pNextSorted]
word[pLastSorted +_pNextSorted] := p
word[p +_pNextSorted]~
pLastSorted := p
return
pPrev := p
p := word[p +_pNextSorted]
return 0
pri ProcessSob( p, top ) | len, numExports, exportSize, numImports, importSize, objBinSize, hash, pStart, temp, pImports, pCounts, ts0, ts1
{{
Reads the sob file identified by p, appends the sob's imports to the sob list,
then recursively processes the imported sobs.
top is true for the top sob, false for all other sobs.
}}
Str.Copy( @stringBuffer, word[p +_pName] )
Str.Append( @stringBuffer, string(".SOB") )
if verbosity => 2
term.str( string("Reading [") )
term.str( @stringBuffer )
term.out( "]" )
term.out( 13 )
fs.Open( @stringBuffer, "R" )
if fs.Readlong <> SOBFILEFORMATVERSION ' SOB file format version
abort string("Unrecognized SOB file format")
long[p +_timestamp] := fs.Readlong ' timestamp
hash := fs.ReadLong ' hash
numExports := fs.ReadWord ' number of exports
exportSize := fs.ReadWord ' size of exports segment
numImports := fs.ReadWord ' number of imports
importSize := fs.ReadWord ' size of imports segment
word[p +_objBinSize] := fs.ReadWord ' size of bytecode segment
byte[p +_checksum] := fs.ReadByte ' checksum
fs.ReadByte ' padding
word[p +_varSize] := fs.ReadWord ' size of sob's VAR space
ts0 := long[p +_timestamp]
if top
ReadExports( numExports )
else
fs.SkipBytes( exportSize )
word[p +_exportImportSize] := exportSize + importSize
word[p +_nImports] := numImports
word[p +_pImports] := pImports := Alloc( numImports << 1 ) ' points to an array of sob pointers
word[p +_pCounts] := pCounts := Alloc( numImports << 1 ) ' points to an array of sob counts
pStart := pLast
repeat numImports
fs.ReadStringUpperCase( @stringBuffer, 8 )
ts1 := GetTimestamp( @stringBuffer )
if ts0 and ts1 ' Only compare non-zero timestamps
if ts0 =< ts1
term.str( word[p+_pName] )
term.str( string(".SOB is older than ") )
term.str( @stringBuffer )
term.str( string(".SOB", 13) )
outOfDate~~
ifnot temp := FindSob( @stringBuffer )
temp := AddSob( @stringBuffer )
word[pImports] := temp
word[pCounts] := fs.ReadWord
fs.ReadByte ' reserved byte
if verbosity => 3
term.str( word[ word[pImports] +_pName] )
term.out( "*" )
term.dec( word[pCounts] )
term.out( 13 )
pImports += 2
pCounts += 2
if top
fs.SkipBytes( $4 ) ' look into the top sob's object header
firstPubOffset := fs.ReadWord ' and get offset to first pub
firstPubLocalsSize := fs.ReadWord ' and size of first pub's locals
fs.Close
' Process the imported sobs
pStart := word[pStart +_pNext]
repeat while pStart
ProcessSob( pStart, false )
pStart := word[pStart +_pNext]
if verbosity => 2
term.str( string("done with ") )
term.str( word[p +_pName] )
term.out( 13 )
pri GetTimestamp( pFilename )
str.Append( pFilename, string(".SOB") )
fs[1].Open( pFilename, "R" )
fs[1].ReadLong
result := fs[1].ReadLong
fs[1].Close
byte[pFilename][ strsize(pFilename) - 4 ]~ ' remove .SOB tail
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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. |
+------------------------------------------------------------------------------------------------------------------------------+
}}

File diff suppressed because it is too large Load Diff

View File

@ -1,367 +0,0 @@
{
_clkfreq = 96_000_000 ' Hybrid
_clkmode = xtal1 + pll16x
tvPins = 24
kbPins = 12
sdPins = 8
}
_clkfreq = 80_000_000 ' Hydra
_clkmode = xtal1 + pll8x
tvPins = 24
kbPins = 13
sdPins = 16
{
Simple command line
2009
April
15 Adding file transfer to/from PC via serial
16 0.02
SendFile bugfix (while blksize == 1024)
Tries to run .bin before .eep now.
June
4 Changing name from cl to sphinx. Converting to use sxfs, sxtv.
15 sxkb; adding c and cl commands
23 Corrected clock mode calculation.
}
obj
kb: "sxkb"
term: "sxtv"
sxfs: "sxfs"
f: "sxfile"
ser: "fdserial"
con
SXTVRENDEZVOUS = $8000 - 4
SXKBRENDEZVOUS = SXTVRENDEZVOUS - 4
SDSPIRENDEZVOUS = SXKBRENDEZVOUS - 3 * 4
SXFS2RENDEZVOUS = SDSPIRENDEZVOUS - 4 * 4 ' four rendezvous variables
SXFSRENDEZVOUS = SXFS2RENDEZVOUS - 4 * 4 ' four rendezvous variables
METADATABUFFER = SXFSRENDEZVOUS - 512
_free = ($8000 - METADATABUFFER) / 4
pub Main | err, p
if term.start( tvPins, SXTVRENDEZVOUS )
term.str( string("============= Sphinx 090627 ============", 13) )
term.str( string("video @ pin ") )
term.dec( tvPins )
term.str( string(13, "keyboard @ pin ") )
term.dec( kbPins )
term.str( string(13, "SD @ pin ") )
term.dec( sdPins )
term.out( 13 )
sxfs.start( sdPins )
kb.start( kbPins )
repeat
if ina[31] ' USB cable connected?
ser.start( 31, 30, %0000, 19200 )
f.Close
err := \DoIt
if err
if err > 0
term.str( err )
else
term.str( string("Error ") )
term.dec( err )
term.out( 13 )
else
term.str( string("Normal exit") ) ' This never happens
pri DoIt | ch
term.out( ">" )
term.out( "_" )
term.out( 8 )
repeat
if kb.peekkey
EditCmdLine
Execute
term.out( ">" )
term.out( "_" )
term.out( 8 )
if (ch := ser.rxcheck) <> -1
term.out( 8 )
FileTransfer( ch )
term.out( ">" )
term.out( "_" )
term.out( 8 )
con
MAXCMDLINELENGTH = 78 ' some arbitray limit.
CR = $0d
BKSP = $c8
var
byte cmdLine[MAXCMDLINELENGTH+1] ' +1 for null terminator
long cmdLineLength
pri EditCmdLine | key
cmdLineLength~ ' cursor is always at end of command line
repeat
case key := kb.key
$20..$7f:
if cmdLineLength < MAXCMDLINELENGTH
cmdLine[ cmdLineLength++ ] := key
term.out( key )
term.out( "_" )
term.out( 8 )
CR:
term.out( " " )
term.out( 13 )
cmdLine[ cmdLineLength ]~
return true
BKSP:
if cmdLineLength
--cmdLineLength
term.out( " " )
term.out( 8 )
term.out( 8 )
term.out( "_" )
term.out( 8 )
pri FileTransfer( cmd ) | ch, i
if cmd <> "G" and cmd <> "P"
term.out( cmd )
abort string(" -- unrecognized command from PC")
i~
repeat
ch := RxSerByte
if i => FILENAMEBUFFERSIZE
abort string("Filename too long")
filename[i++] := ch
while ch
if cmd == "G"
term.str( string("sending ") )
term.str( @filename )
term.out( 13 )
SendFileToPC
else
term.str( string("receiving ") )
term.str( @filename )
term.out( 13 )
ReceiveFileFromPC
pri SendFileToPC | blksize, i, chksum, b, n
if f.Open( @filename, "R" ) <> 0
term.str( @filename )
abort string(" -- can't open file for reading")
TxSerByte( "A" ) ' ack
n~
repeat
blksize := f.Read( @buffer, 1024 )
if blksize == -1
blksize~
TxSerByte( blksize.byte[0] )
TxSerByte( blksize.byte[1] )
i~
chksum~
repeat blksize
b := buffer[i++]
chksum += b
TxSerByte( b )
n += blksize
if chksum & $ff <> RxSerByte
abort string("Checksum error")
while blksize == 1024
f.Close
term.dec( n )
term.str( string(" bytes sent", 13) )
pri ReceiveFileFromPC | blksize, i, chksum, b, n
if f.Open( @filename, "W" ) <> 0
term.str( @filename )
abort string(" -- can't open file for writing")
TxSerByte( "A" ) ' ack
n~
repeat
blksize~
blksize.byte[0] := RxSerByte
blksize.byte[1] := RxSerByte
if blksize > 1024
abort string("Block size > 1024")
i~
chksum~
repeat blksize
b := RxSerByte
buffer[i++] := b
chksum += b
n += blksize
f.Write( @buffer, blksize )
TxSerByte( chksum )
while blksize == 1024
f.Close
term.dec( n )
term.str( string(" bytes received", 13) )
pri RxSerByte : b
' ser.rx with timeout
b := ser.rxtime( TIMEOUT )
if b == -1
abort string("RxSerByte timed out")
pri TxSerByte( b )
' just for symmetry with RxSerByte
ser.tx( b )
con
TIMEOUT = 500
var
byte buffer[1024]
pri Execute | n, p, q, run, c
c~
ifnot n := ParseCmdLine
return
p := @cmdLine
ToUpper(p)
if run := strcomp( @cmdLine, string("RUN") )
--n
p += strsize(p) + 1
elseif strcomp( @cmdLine, string("C") )
c := 1
--n
p += strsize(p) + 1 ' command arg1 arg2...
elseif strcomp( @cmdLine, string("CL") ) ' run command arg1 arg2...
c := 2 ' c arg1 arg2...
--n ' cl arg1 arg2...
p += strsize(p) + 1
ifnot n
abort string("No file specified")
f.Open( string("args.d8a"), "W" ) ' write args
if c == 0
q := p + strsize(p) + 1 ' for run and plain command, skip first arg (command name)
--n
f.Write( @n, 1 )
repeat n
f.Write( q, strsize(q) + 1 )
q += strsize(q) + 1
else ' for c and cl,
++n ' add extra arg (/c or /l)
f.Write( @n, 1 )
repeat n-1
f.Write( p, strsize(p) + 1 )
p += strsize(p) + 1
if c == 1
f.Write( string("/c"), 3 )
else
f.Write( string("/l"), 3 )
n~
f.Write( @n, 1 ) ' final terminating null
f.Close
if c
if f.Open( string("lex.bin"), "R" ) <> 0
abort string("lex.bin not found")
ser.stop
f.Execute( 0 )
if EndsWith( p, string(".BIN") ) or EndsWith( p, string(".EEP") )
if f.Open( p, "R" ) <> 0
term.str( p )
abort string(" -- not found")
else
if strsize(p) > MAXFILENAMELENGTH - 4
term.str( p )
abort string(" -- filename too long")
bytemove( @filename, p, strsize(p) + 1 )
bytemove( @filename + strsize(p), string(".BIN"), 5 )
if f.Open( @filename, "R" ) <> 0
bytemove( @filename + strsize(p), string(".EEP"), 5 )
if f.Open( @filename, "R" ) <> 0
term.str( p )
abort string(" -- no .bin or .eep found")
ser.stop
f.Execute( run )
pri ToUpper( p )
repeat while byte[p]
if "a" =< byte[p] and byte[p] =< "z"
byte[p] += "A" - "a"
++p
pri EndsWith( p, s )
if strsize(p) < strsize(s)
return false
p += strsize(p) - strsize(s)
repeat while byte[p]
if byte[p++] <> byte[s++]
return false
return true
con
MAXFILENAMELENGTH = 12 ' 8 + . + 3
FILENAMEBUFFERSIZE = MAXFILENAMELENGTH + 1 ' 8 + . + 3 + null
CMDNAMEBUFFERSIZE = 9 ' 8 + null
var
byte filename[MAXFILENAMELENGTH+1] ' 8 + . + 3 + null
pri ParseCmdLine : n | pSrc, pDst, state
{{
Converts cmdLine from " ab de fg \" to "ab\de\fg\" ('\' = null).
Returns # of "words".
}}
{
state whitespace null other char
0 ++pSrc; append \0; quit append char; => 1
1 append \0; ++n; => 0 append \0; ++n; quit append char;
}
pSrc := @cmdLine
pDst := @cmdLine
state~
repeat
if state == 0
if byte[pSrc] == " "
++pSrc
elseif byte[pSrc] == 0
byte[pDst++]~
quit
else
byte[pDst++] := byte[pSrc++]
state := 1
elseif state == 1
if byte[pSrc] == " "
++pSrc
byte[pDst++]~
++n
state~
elseif byte[pSrc] == 0
byte[pDst++]~
++n
quit
else
byte[pDst++] := byte[pSrc++]
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,43 +0,0 @@
pub Compare( p, q ) | lp, lq, d
{{
Compares two strings. Returns a negative number if first string is "less than" the second,
0 if they're identical, a positive number otherwise.
}}
lp := strsize(p)
lq := strsize(q)
repeat lp <# lq
if (d := byte[p++] - (byte[q++] & $7f))
return ~~d
return lp-lq
pub Copy( p, q )
bytemove( p, q, strsize(q) + 1 )
pub Append( p, q )
Copy( p + strsize(p), q )
pub ToUpper( p )
repeat while byte[p]
if "a" =< byte[p] and byte[p] =< "z"
byte[p] += constant( "A" - "a" )
++p
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,98 +0,0 @@
obj
isxfs: "isxfs"
var
long filestuff[isxfs#SIZEOFFILESTUFF / 4]
pub Open( pFilename, mode )
return isxfs.Open( @filestuff, pFilename, mode )
pub Close
isxfs.Close( @filestuff )
pub Read( ptr, n )
return isxfs.Read( @filestuff, ptr, n )
pub Write( ptr, n )
return isxfs.Write( @filestuff, ptr, n )
pub Length
{{
Only valid for files opened for reading.
}}
return long[@filestuff]
pub Execute( mode )
isxfs.Execute( @filestuff, mode )
isxfs.Close( @filestuff ) ' we only get here if Execute fails for some reason.
pub ReadString( p, MAXLENGTH ) | ch
repeat MAXLENGTH + 1
ch := ReadByte
ifnot byte[p++] := ch
return
abort string("ReadString: string too long")
pub ReadStringUpperCase( p, MAXLENGTH ) | ch
repeat MAXLENGTH + 1
ch := ReadByte
if "a" =< ch and ch =< "z"
ch -= constant("a" - "A")
ifnot byte[p++] := ch
return
abort string("ReadStringUpperCase: string too long")
pub WriteString( p )
Write( p, strsize(p) + 1 )
pub ReadNumber | ch
repeat
ifnot ch := ReadByte
return
if ch < "0" or ch > "9"
abort string("ReadNumber: non-numeric character")
result := result * 10 + ch - "0"
pub ReadByte : ch
Read( @ch, 1 )
pub WriteByte( b )
Write( @b, 1 )
pub ReadWord
return ReadByte + (ReadByte << 8)
pub WriteWord( w )
Write( @w, 2 )
pub ReadLong
return ReadByte + (ReadByte << 8) + (ReadByte << 16) + (ReadByte << 24)
pub WriteLong( l )
Write( @l, 4 )
pub SkipBytes( n )
repeat while n => 32768
Read( $8000, 32768 )
n -= 32768
Read( $8000, n )
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,871 +0,0 @@
SXTVRENDEZVOUS = $8000 - 4
SXKBRENDEZVOUS = SXTVRENDEZVOUS - 4
SDSPIRENDEZVOUS = SXKBRENDEZVOUS - 3 * 4
SXFS2RENDEZVOUS = SDSPIRENDEZVOUS - 4 * 4 ' four rendezvous variables
SXFSRENDEZVOUS = SXFS2RENDEZVOUS - 4 * 4 ' four rendezvous variables
METADATABUFFER = SXFSRENDEZVOUS - 512
_free = ($8000 - METADATABUFFER) / 4
{
sxfsrendezvous sdspirendezvous
--------+ +--------+ +-------+
| <===> command <===> | | <=====> command <=====> | |
Spin | | | | |
routines| <===> param0 <====> | SXFS | <=====> param <=====> | SDSPI |
| | cog | | cog |
| ----> param1 -----> | | ------> blockno ------> | |
| | | +-------+
| ----> param2 -----> | |
--------+ | | sxfs2rendezvous
| | +-------+
| | <====> command <======> | |
| | | | <==> (sxfsrendezvous)
| | <====> param0 <=======> | SXFS2 |
| | | cog | <==> (sdspirendezvous)
| | | |
+--------+ +-------+
SXFS cog handles file reading: open, read, execute, close(?).
SXFS2 cog, under SXFS's direction, handles file writing: open, write, close.
SDSPI cog handles SD card sector reading and writing.
SXFS cog communicates with main program via sxfsrendezvous and Spin interface routines.
SXFS cog communicates with SXFS2 cog via sxfs2rendezvous.
SXFS cog communicates with SDSPI cog via sdspirendezvous.
-1: eof, general error
-100: bad command
-101: not FAT16
-102: file not found
-104: bad mode
-106: file not closed
-107: directory full
-109: file not properly opened
-110: FAT full.
-113: bad filename
}
obj
sxfs2: "sxfs2"
sdspi : "sxsdspiq"
pub Start( sdPin ) | pbrSector
' Determine if sxfs cog and, by association, sxfs2 and sdspi cogs, are already running.
' If not, start them up.
' Returns true if the cogs needed to be started, false if the cogs were already running.
ifnot Ping
result~~
' start sdspi cog and initialize SD card
long[pSdspiCommand] := "I"
sdspi.start( sdPin, pSdspiCommand )
repeat while long[pSdspiCommand]
if long[pSdspiParam]
abort long[pSdspiParam]
pbrSector := ReadPbr
' start sxfs cog
long[pCommand] := "?"
if cognew( @sxfsEntry, 0 ) < 0
abort -1
repeat while long[pCommand]
' start sxfs2 cog
sxfs2.Start( pbrSector )
pri ReadPbr : pbrSector
repeat
sdspi.readblock( pbrSector, pMetadataBuffer )
if bytecompare( pMetadataBuffer+$36, string("FAT16"), 5 )
quit
if pbrSector
abort -101 ' not FAT16
pbrSector := PeekL( pMetadataBuffer + $1c6 )
bytesPerSector := PeekW( pMetadataBuffer + $0b )
sectorsPerCluster := byte[pMetadataBuffer][$0d]
clusterShift := >| sectorsPerCluster - 1
reservedSectors := PeekW( pMetadataBuffer + $0e )
numberOfFats := byte[pMetadataBuffer][$10]
sectorsPerFat := PeekW( pMetadataBuffer + $16 )
RootDirEntries := PeekW( pMetadataBuffer + $11 )
fatSector0 := pbrSector + reservedSectors
dirSector0 := fatSector0 + numberOfFats * sectorsPerFat
dataSector0 := dirSector0 + rootDirEntries >> 4
pri bytecompare( _p, _q, _n )
repeat _n
if byte[_p++] <> byte[_q++]
return
return true
pri PeekW( a )
return byte[a++] + byte[a] << 8
pri PeekL( a )
return byte[a++] + byte[a++] << 8 + byte[a++] << 16 + byte[a] << 24
pri Ping
{{
returns 1 if bmfs cog is active, 0 otherwise.
}}
long[pCommand] := "?"
if long[pCommand]
return 0
else
return 1
con
SECTORSIZE = 512
SECTORSHIFT = 9
DIRSIZE = 32
con
' filestuff definitions
' filestuff must be long-aligned
{ long } _length = 0
{ long } _leftInFile = 4
{ long } _sopDir = 8 ' sector/offset "pointer" to directory entry
{ long } _sopTail = 12 ' sector/offset "pointer" to last cluster# in FAT chain
{ word } _cluster = 16
{ word } _sector = 18 ' sector# within cluster; ranges from 0 to sectorsPerCluster-1
{ word } _bp = 20 ' byte pointer (actually an index into the sector buffer); range [0..511]
{ word } _mode = 22 ' 0: closed; "R": open for reading; "W": open for writing.
_buffer = 24 ' 512-byte buffer starts here
SIZEOFFILESTUFF = SECTORSIZE + 24
dat
{{
command param0 param1 param2
"?" -- -- -- Do nothing, but acknowledge to indicate that sxfs cog is active.
"O" filestuff filename mode Open a file, populate filestuff fields. mode is "R" or "W".
"R" filestuff buffer num Reads num bytes into buffer from file specified by filestuff.
"W" filestuff buffer num Writes num bytes from buffer to file specified by filestuff.
"C" filestuff -- -- Closes file specified by filestuff.
"X" filestuff execmode cog Executes file.
}}
org 0
SXFSEntry
AckNoReturnCode
mov temp, #0 ' clear return code
AckReturnCode ' enter here with temp = return code
wrlong temp, pParam0
mov temp, #0
wrlong temp, pCommand ' clear command to signal operation complete.
:ready ' wait for new command
rdlong temp, pCommand wz
if_z jmp #:ready
cmp temp, #"?" wz
if_e jmp #AckNoReturnCode
cmp temp, #"O" wz
if_e jmp #Open
cmp temp, #"R" wz
if_e jmp #Read
cmp temp, #"W" wz
if_e jmp #Write
cmp temp, #"C" wz
if_e jmp #Close
cmp temp, #"X" wz
if_e jmp #Execute
' else
neg temp, #100 ' -100: bad command
jmp #AckReturnCode
'*********************************************************************************************************************
'* *
'* Open stuff *
'* *
'*********************************************************************************************************************
Open ' ( param0 = pFilestuff, param1 = pFilename, param2 = mode )
{
Return value:
File found File not found Error
mode = "R" 0 1 < 0
mode = "W" 0 0 < 0
Mode W will either open an existing file or create a new file.
}
rdword pFilestuff, pParam0
rdword pFilename, pParam1
mov p, pFilestuff
add p, #_mode
rdword temp, p wz
if_nz neg temp, #106 ' -106: file not closed
if_nz jmp #AckReturnCode
call #MassageFilename
rdword temp, pParam2
cmp temp, #"R" wz
if_e jmp #:openForReading
cmp temp, #"W" wz
if_e jmp #:openForWriting
neg temp, #104 ' -104: bad mode
jmp #AckReturnCode
:openForReading
call #FindFile
mov p, pFilestuff
add p, #_sopDir ' pFilestuff->sopDir = 0 => file not found
rdlong temp, p wz
if_z mov temp, #1 ' return 1 to indicate file not found
if_z jmp #AckReturnCode
mov p, sop ' sop sector is still in memory
and p, #$1ff
add p, pMetadataBuffer
add p, #$1a ' point to cluster information
rdword temp, p
mov q, pFilestuff
add q, #_cluster
wrword temp, q
add p, #2 ' point to length information
rdlong temp, p
sub q, #_cluster-_length ' q points to length
wrlong temp, q
add q, #_leftInFile-_length ' q points to leftInFile
wrlong temp, q
add q, #_sector-_leftInFile ' q points to sector
mov temp, #0
wrword temp, q
add q, #_bp-_sector ' q points to bp
wrword k512, q
mov p, pFilestuff
add p, #_mode
mov temp, #"R"
wrword temp, p ' save mode
jmp #AckNoReturnCode
:openForWriting
mov sop, dirSector0 ' sop "points" to directory entries:
shl sop, #9 ' incremented by 32 each time through the loop.
mov sopDir, #0 ' sopDir "points" to the directory entry
' that will be used or reused for the file being opened.
mov i, rootDirEntries
:forEachDirEntry ' Loop through the directory entries, looking for a deleted entry,
' an empty entry, or an entry that matches pFilename.
mov sector, sop
shr sector, #9
call #ReadMetadataSector
mov p, sop
and p, #$1ff
add p, pMetadataBuffer ' p points to the current directory entry
add p, #$0b
rdbyte temp, p ' p[$0b] = attribute byte
sub p, #$0b
and temp, #$02 wz ' If hidden,
if_nz jmp #:next ' skip. Hidden dir entries include long name entries.
rdbyte temp, p ' p[0]
cmp temp, #$e5 wz ' = $e5? (deleted directory entry?)
if_e cmp sopDir, #0 wz ' save pointer in sopDir (just the first time)
if_e mov sopDir, sop
tjz temp, #:quit ' empty directory entry? We're done
mov q, pFilename ' matching filename? Done.
mov n, #11
call #ByteComp
if_e jmp #:quit
:next
add sop, #DIRSIZE
djnz i, #:forEachDirEntry
:quit
cmp i, #0 wz ' did we go through the whole directory?
if_z neg temp, #107 ' -107: directory full
if_z jmp #AckReturnCode
cmp sopDir, #0 wz ' if sopDir hasn't been set yet,
if_e mov sopDir, sop ' set it to sop.
mov p, pFilestuff
add p, #_sopDir
wrlong sopDir, p ' pFilestuff->sopDir := sopDir
add p, #_sopTail-_sopDir
add sopDir, #$1a
wrlong sopDir, p ' pFilestuff->sopTail := sopDir + $1a
' (points to directory entry's cluster field).
mov sector, sopDir
shr sector, #9 ' Get the chosen directory entry into memory
call #ReadMetadataSector ' if it isn't already.
mov p, sopDir ' Recall that sopDir was changed
and p, #$1ff ' to point to the cluster field,
add p, pMetadataBuffer ' so p now points to the cluster field in the buffer.
rdword cluster, p ' Save the cluster field.
mov temp, #0
wrword temp, p ' Zero the cluster field.
sub p, #$1a ' Point to start of directory entry
rdbyte temp, p ' Check to see if this was a deleted dir entry.
cmp temp, #$e5 wz ' If it was, we definitely do not want to zero the
if_e mov cluster, #0 ' cluster chain, so set cluster to 0.
mov q, pFilename ' Store the filename in the directory entry.
mov n, #11
call #ByteCopy
mov temp, #$20 ' Set the attribute byte (immediately following name)
wrbyte temp, p
add p, #$10-$0b ' Point to creation date.
mov temp, aDate ' 2001/01/01
wrword temp, p
add p, #$12-$10 ' Point to last access date.
wrword temp, p
add p, #$18-$12 ' Point to last update date.
wrword temp, p
mov dirty, #1 ' We've modified metadata.
tjz cluster, #:done
:forEachClusterInList ' Traverse the cluster list and zero each link.
mov sector, cluster
shr sector, #8
add sector, fatSector0
call #ReadMetadataSector ' Read FAT sector for current cluster
mov p, cluster
and p, #$ff
shl p, #1
add p, pMetadataBuffer ' Point p at cluster entry in FAT
rdword cluster, p ' Get next cluster link.
cmp cluster, #1 wc, wz ' Break if cluster <= 1
if_be jmp #:done
mov temp, #0
wrword temp, p ' Zero the cluster link.
mov dirty, #1 ' We've modified metadata.
cmp cluster, kfff0 wc, wz ' repeat unless new cluster >= $fff0
if_b jmp #:forEachClusterInList
:done
mov p, pFilestuff
add p, #_sector
mov temp, #0
wrword temp, p ' pFilestuff->sector := 0
add p, #_bp-_sector
wrword temp, p ' pFilestuff->bp := 0
mov p, pFilestuff
mov temp, #0
wrlong temp, p ' pFilestuff->length := 0
add p, #_mode
mov temp, #"W"
wrword temp, p ' save mode
jmp #AckNoReturnCode
MassageFilename
{
Take the null-terminated 8.3 filename pointed to by pFilename,
move it into memory starting at pFilestuff->buffer and expand it to 11 characters;
change pFilename to point to the expanded filename.
}
mov p, pFilestuff
add p, #_buffer
mov q, p
add p, #1
mov temp, #" "
wrbyte temp, q
mov n, #10
call #ByteCopy
mov q, pFilename ' q is src
mov p, pFilestuff ' p is dst
add p, #_buffer
mov i, #9 ' Copy up to 8 chars (stop at . or null).
:upTo8
rdbyte temp, q
add q, #1
tjz temp, #:done
cmp temp, #"." wz
if_z jmp #:dot
call #ValidateChar
wrbyte temp, p
add p, #1
djnz i, #:upTo8
' If we fall through, we've copied 9 characters (tsk tsk).
neg temp, #113 ' -113: bad filename
jmp #AckReturnCode
:dot
mov p, pFilestuff
add p, #_buffer+8
mov i, #4 ' Copy up to 3 chars (stop at null).
:upTo3
rdbyte temp, q
add q, #1
tjz temp, #:done
call #ValidateChar
wrbyte temp, p
add p, #1
djnz i, #:upTo3
' If we fall through, we've copied 4 characters (tsk tsk ).
neg temp, #113 ' -113: bad filename
jmp #AckReturnCode
:done
mov pFilename, pFilestuff
add pFilename, #_buffer
MassageFilename_ret ret
FindFile
{
pFilename points to 11-character buffer (e.g. "BLAH TXT").
pFilestuff points to a filestuff structure.
Return value:
If file is found, pFilestuff->sopDir is disk address of directory entry.
If file is not found, pFilestuff->sopDir is 0.
}
mov sop, dirSector0 ' sop starts at dirSector0<<9, counts up by DIRSIZE
shl sop, #SECTORSHIFT
mov i, rootDirEntries
:loop
mov sector, sop
shr sector, #9
call #readMetadataSector
mov p, sop
and p, #$1ff
add p, pMetadataBuffer
rdbyte temp, p wz
if_z jmp #:notfound
add p, #$0b
rdbyte temp, p ' p[$0b] = attribute byte
sub p, #$0b
and temp, #$02 wz ' If hidden,
if_nz jmp #:next ' skip. Hidden dir entries include long name entries.
mov q, pFilename
mov n, #11
call #ByteComp
if_e jmp #:found
:next
add sop, #DIRSIZE
djnz i, #:loop
:notfound
mov sop, #0
:found
mov p, pFilestuff
add p, #_sopDir
wrlong sop, p
FindFile_ret ret
'*********************************************************************************************************************
'* *
'* Read stuff *
'* *
'*********************************************************************************************************************
Read ' ( param0 = pFilestuff, param1 = ptr, param2 = n )
{
Read n bytes from file described by pIoblock into memory starting at p.
Returns number of bytes actually read or -1 if attempting to read past EOF.
}
rdlong pFilestuff, pParam0
rdlong destPtr, pParam1
rdlong nBytes, pParam2
mov p, pFilestuff ' Verify that file was opened for reading.
add p, #_mode
rdword temp, p
cmp temp, #"R" wz
if_ne neg temp, #109 ' -109: file not properly opened
if_ne jmp #AckReturnCode
sub p, #_mode-_leftInFile
' Adjust nBytes depending on how much is left to read in file.
' E.g. if we're 10 bytes from EOF and we try to read 15 bytes,
' just read 10. If we're at EOF and try to read 15 bytes, return -1.
rdlong temp, p
max nBytes, temp ' nBytes is lesser of nBytes and leftInFile
tjnz temp, #:x
neg temp, #1 ' -1: eof
jmp #ackReturnCode
:x
mov retcode, nBytes
:while
mov leftInSector, k512 ' leftInSector = 512 - pFilestuff->bp
mov p, pFilestuff
add p, #_bp
rdword temp, p ' temp = bp
sub leftInSector, temp
cmp leftInSector, nBytes wc, wz
if_ae jmp #:endwhile
mov p, destPtr
mov q, pFilestuff
add q, #_buffer ' q points to buffer area
add q, temp ' offset by bp (= temp)
mov n, leftInSector
call #ByteCopy ' bytemove( p, q, n )
add destPtr, leftInSector ' destPtr += leftInSector
sub nBytes, leftInSector ' nBytes -= leftInSector
mov p, pFilestuff ' long[pIoblock+_leftInFile] -= leftInSector
add p, #_leftInFile
rdlong temp, p
sub temp, leftInSector
wrlong temp, p
' sdspi.readblock( dataSector0 + (word[pFilestuff+_cluster] - 2) << clusterShift + word[pFilestuff+_sector], pFilestuff+_buffer )
add p, #_cluster-_leftInFile
rdword temp, p ' temp = (cluster
sub temp, #2 ' - 2)
shl temp, clusterShift ' << clusterShift
add temp, dataSector0 ' + dataSector0
add p, #_sector-_cluster
rdword temp1, p
add temp, temp1 ' + cluster
wrlong temp, pSdspiBlockno ' Prepare to read sector
add p, #_buffer-_sector
wrlong p, pSdspiParam
mov temp, #"R"
call #SdspiCommand
' if ++word[pFilestuff+_sector] == sectorsPerCluster
mov p, pFilestuff
add p, #_sector
rdword temp, p
add temp, #1
wrword temp, p
cmp temp, sectorsPerCluster wz
if_ne jmp #:y
' word[pIoblock+_sector]~
mov temp, #0
wrword temp, p
' word[pFilestuff+_cluster] := NextCluster( word[pFilestuff+_cluster] )
sub p, #_sector-_cluster
rdword cluster, p
call #NextCluster '( cluster )
mov p, pFilestuff
add p, #_cluster
wrword cluster, p
:y
' word[pFilestuff+_bp]~
mov p, pFilestuff
add p, #_bp
mov temp, #0
wrword temp, p
jmp #:while
:endwhile
' bytemove( destPtr, pIoblock + word[pIoblock+_bp], n )
mov p, destPtr
mov q, pFilestuff
add q, #_bp
rdword temp, q
add q, #_buffer-_bp
add q, temp
mov n, nBytes
call #ByteCopy
' long[pIoblock+_leftInFile] -= n
mov p, pFilestuff
add p, #_leftInFile
rdlong temp, p
sub temp, nBytes
wrlong temp, p
' word[pIoblock+_bp] += n
add p, #_bp-_leftInFile
rdword temp, p
add temp, nBytes
wrword temp, p
mov temp, retcode
jmp #AckReturnCode
NextCluster ' ( cluster )
{
Given cluster, determines next cluster in FAT.
Result in cluster.
}
cmp cluster, #1 wc, wz
if_be jmp #NextCluster_ret
cmp cluster, kfff0 wc, wz
if_ae jmp #NextCluster_ret
mov sector, cluster
shr sector, #8
add sector, fatSector0
call #ReadMetadataSector
mov p, cluster
and p, #$ff
shl p, #1
add p, pMetadataBuffer
rdword cluster, p
NextCluster_ret ret
kfff0 long $fff0
'*********************************************************************************************************************
'* *
'* Write stuff *
'* *
'*********************************************************************************************************************
Write
rdlong p, pParam0 ' p = pFilestuff
add p, #_mode ' Verify that file was opened for writing.
rdword temp, p
cmp temp, #"W" wz
if_ne neg temp, #109 ' -109: file not properly opened
if_ne jmp #AckReturnCode
call #FlushMetadataSector
neg currentsector, #1 ' invalidate current sector 'cuz we're about to hand the reins
' to sxfs2 cog.
mov temp, #"W"
wrlong temp, pSxfs2Command
:wait rdlong temp, pSxfs2Command wz
if_nz jmp #:wait
rdlong temp, pSxfs2Param
jmp #AckReturnCode
'*********************************************************************************************************************
'* *
'* Close stuff *
'* *
'*********************************************************************************************************************
Close ' ( param0 = pFilestuff )
rdlong pFilestuff, pParam0
mov p, pFilestuff
add p, #_mode
rdword temp, p
cmp temp, #"W" wz
if_e jmp #:closew
' Files opened in mode "W" need special closing code, but for mode "R" or anything else
' (like file not even open) we can just do this:
mov temp, #0
wrword temp, p ' clear mode
jmp #AckNoReturnCode ' and we're done
:closew
mov temp, #0 ' clear mode
wrword temp, p
call #FlushMetadataSector
neg currentsector, #1 ' invalidate current sector 'cuz we're about to hand the reins
' to sxfs2 cog.
mov temp, #"C"
wrlong temp, pSxfs2Command
:wait rdlong temp, pSxfs2Command wz
if_nz jmp #:wait
rdlong temp, pSxfs2Param
jmp #AckReturnCode
'*********************************************************************************************************************
'* *
'* Execute stuff *
'* *
'*********************************************************************************************************************
Execute ' ( pFilestuff, execmode, cogid )
call #FlushMetadataSector
neg currentsector, #1 ' invalidate current sector 'cuz we're about to hand the reins
' to sxfs2 cog.
mov temp, #"X"
wrlong temp, pSxfs2Command
:wait rdlong temp, pSxfs2Command wz
if_nz jmp #:wait
rdlong temp, pSxfs2Param
jmp #AckReturnCode
'*********************************************************************************************************************
'* *
'* Utility stuff *
'* *
'*********************************************************************************************************************
ByteCopy ' ( p, q, n )
tjz n, #ByteCopy_ret
:loop rdbyte temp, q
add q, #1
wrbyte temp, p
add p, #1
djnz n, #:loop
ByteCopy_ret ret
ByteComp ' ( p, q, n )
{
Compares j bytes starting at p and q.
Returns Z if they match, NZ if they differ.
Destroys p, q, and j.
}
rdbyte temp, p
add p, #1
rdbyte temp1, q
add q, #1
cmp temp, temp1 wz
if_z djnz n, #ByteComp
ByteComp_ret ret
ValidateChar
{
Make sure that temp is a valid filename character (for our purposes, 0-9, A-Z, _).
}
cmp temp, #"a" wc, wz
if_b jmp #:notLowerCase
cmp temp, #"z" wc, wz
if_a jmp #:notLowerCase
sub temp, #"a"-"A" ' convert to upper-case
jmp #ValidateChar_ret
:notLowerCase
cmp temp, #"A" wc, wz
if_b jmp #:notAlpha
cmp temp, #"Z" wc, wz
if_be jmp #ValidateChar_ret
:notAlpha
cmp temp, #"0" wc, wz
if_b jmp #:notNumeric
cmp temp, #"9" wc, wz
if_be jmp #ValidateChar_ret
:notNumeric
cmp temp, #"_" wz
if_e jmp #ValidateChar_ret
mov temp, #113 ' -113: bad filename
jmp #AckReturnCode
ValidateChar_ret ret
ReadMetadataSector ' ( sector )
call #FlushMetadataSector
cmp sector, currentSector wz
if_e jmp #ReadMetadataSector_ret
wrlong pMetadataBuffer, pSdspiParam
wrlong sector, pSdspiBlockno
mov currentSector, sector
mov temp, #"R"
call #SdspiCommand
ReadMetadataSector_ret ret
FlushMetadataSector
tjz dirty, #FlushMetadataSector_ret
mov dirty, #0
' write current sector
wrlong pMetadataBuffer, pSdspiParam
wrlong currentSector, pSdspiBlockno
mov temp, #"W"
call #SdspiCommand
FlushMetadataSector_ret ret
SdspiCommand
wrlong temp, pSdspiCommand
:wait
rdlong temp, pSdspiCommand wz
if_nz jmp #:wait
rdlong temp, pSdspiParam wz
if_nz jmp #AckReturnCode
SdspiCommand_ret ret
kFAT1 long "F" + "A"<<8 + "T"<<16 + "1"<<24
k512 long 512
dirty long 0
currentSector long -1
aDate long $2a21
pMetadataBuffer long METADATABUFFER
pCommand long SXFSRENDEZVOUS+0
pParam0 long SXFSRENDEZVOUS+4
pParam1 long SXFSRENDEZVOUS+8
pParam2 long SXFSRENDEZVOUS+12
pSdspiCommand long SDSPIRENDEZVOUS+0
pSdspiParam long SDSPIRENDEZVOUS+4
pSdspiBlockno long SDSPIRENDEZVOUS+8
pSxfs2Command long SXFS2RENDEZVOUS+0
pSxfs2Param long SXFS2RENDEZVOUS+4
bytesPerSector long 0
sectorsPerCluster long 0
clusterShift long 0
reservedSectors long 0
numberOfFats long 0
sectorsPerFat long 0
rootDirEntries long 0
fatSector0 long 0
dirSector0 long 0
dataSector0 long 0
temp res 1
temp1 res 1
i res 1
j res 1
n res 1
p res 1
q res 1
sop res 1
byte4 res 0
sopDir res 1
sector res 1
cluster res 1
pFilename res 1
pFilestuff res 1
destPtr res 1
nBytes res 1
leftInFile res 1
leftInSector res 1
retcode res 1
fit
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,529 +0,0 @@
SXTVRENDEZVOUS = $8000 - 4
RESERVED = SXTVRENDEZVOUS - 4
SDSPIRENDEZVOUS = RESERVED - 3 * 4
SXFS2RENDEZVOUS = SDSPIRENDEZVOUS - 4 * 4 ' four rendezvous variables
SXFSRENDEZVOUS = SXFS2RENDEZVOUS - 4 * 4 ' four rendezvous variables
METADATABUFFER = SXFSRENDEZVOUS - 512
_free = ($8000 - METADATABUFFER) / 4
con
SECTORSIZE = 512
' filestuff definitions
' filestuff must be long-aligned
{ long } _length = 0
{ long } _leftInFile = 4
{ long } _sopDir = 8 ' sector/offset "pointer" to directory entry
{ long } _sopTail = 12 ' sector/offset "pointer" to last cluster# in FAT chain
{ word } _cluster = 16
{ word } _sector = 18 ' sector# within cluster; ranges from 0 to sectorsPerCluster-1
{ word } _bp = 20 ' byte pointer (actually an index into the sector buffer); range [0..511]
{ word } _mode = 22 ' 0: closed; "R": open for reading; "W": open for writing.
_buffer = 24 ' 512-byte buffer starts here
SIZEOFFILESTUFF = SECTORSIZE + 24
pub Start( pbrSector )
bytesPerSector := PeekW( pMetadataBuffer + $0b )
sectorsPerCluster := byte[pMetadataBuffer][$0d]
clusterShift := >| sectorsPerCluster - 1
reservedSectors := PeekW( pMetadataBuffer + $0e )
numberOfFats := byte[pMetadataBuffer][$10]
sectorsPerFat := PeekW( pMetadataBuffer + $16 )
RootDirEntries := PeekW( pMetadataBuffer + $11 )
fatSector0 := pbrSector + reservedSectors
dirSector0 := fatSector0 + numberOfFats * sectorsPerFat
dataSector0 := dirSector0 + rootDirEntries >> 4
' start sxfs2 cog
long[pCommand] := "?"
if cognew( @Sxfs2Entry, 0 ) < 0
abort -1
repeat while long[pCommand]
pri PeekW( a )
return byte[a++] + byte[a] << 8
pri PeekL( a )
return byte[a++] + byte[a++] << 8 + byte[a++] << 16 + byte[a] << 24
dat
org 0
Sxfs2Entry
AckNoReturnCode
mov temp, #0 ' clear return code
AckReturnCode ' enter here with temp = return code
wrlong temp, pParam
mov temp, #0
wrlong temp, pCommand ' clear command to signal operation complete.
mov dirty, temp ' Ensure that metatdata is flushed before coming here.
neg temp, #1
mov currentSector, temp
:ready ' wait for new command
rdlong temp, pCommand wz
if_z jmp #:ready
cmp temp, #"?" wz
if_e jmp #AckNoReturnCode
cmp temp, #"W" wz
if_e jmp #Write
cmp temp, #"C" wz
if_e jmp #Close
cmp temp, #"X" wz
if_e jmp #Execute
' else
neg temp, #100 ' return code -100 : bad command
jmp #AckReturnCode
'*********************************************************************************************************************
'* *
'* Write stuff *
'* *
'*********************************************************************************************************************
Write ' ( pFilestuff, ptr, n )
rdlong pFilestuff, pSxfsParam0
rdlong srcPtr, pSxfsParam1
rdlong nBytes, pSxfsParam2
mov retcode, nBytes
mov p, pFilestuff ' long[ pFilestuff+_length ] += n
'add p, #_length (unnecessary cuz _length = 0)
rdlong temp, p
add temp, nBytes
wrlong temp, p
' repeat while (leftInSector := SECTORSIZE - word[pIoblock+_bp]) < n
:while
mov p, pFilestuff
add p, #_bp ' p points to pFilestuff->bp
mov leftInSector, k512
rdword temp, p ' temp = pFilestuff->bp
sub leftInSector, temp
cmp leftInSector, nBytes wc, wz
if_ae jmp #:done
' bytemove( pFilestuff + _buffer + word[pFilestuff+_bp], ptr, leftInSector )
mov p, pFilestuff
add p, #_buffer
add p, temp ' p now points bp bytes into buffer.
mov q, srcPtr
mov n, leftInSector
call #ByteCopy
' ptr += leftInSector
add srcPtr, leftInSector ' advance the source pointer by #bytes written.
' n -= leftInSector
sub nBytes, leftInSector ' decrease #bytes to write by #bytes written.
' WriteNextSector( pIoblock )
call #WriteNextSector
jmp #:while
:done
' bytemove( pFilestuff + _buffer + word[pIoblock+_bp], ptr, n )
mov p, pFilestuff
add p, #_buffer
add p, temp ' temp = pFilestuff->bp
mov q, srcPtr
mov n, nBytes
call #ByteCopy
' word[pFilestuff+_bp] += n
mov p, pFilestuff
add p, #_bp
rdword temp, p
add temp, nBytes ' advance bp by #bytes written.
wrword temp, p
call #FlushMetadataSector
mov temp, retcode
jmp #AckReturnCode
WriteNextSector
mov p, pFilestuff
add p, #_sector
rdword temp, p wz
if_nz jmp #:writeSector ' sector# <> 0? Write that sector.
' Writing sector 0 implies that we're starting a new cluster, so find an empty slot in the FAT
mov cluster, #0
mov sector, fatSector0
mov i, sectorsPerFat
:forEachFatSector
call #ReadMetadataSector
mov p, pMetadataBuffer
mov j, #256
:forEachSlotInSector
rdword temp, p wz ' examine current slot
if_z jmp #:foundEmptySlot
add p, #2
add cluster, #1
djnz j, #:forEachSlotInSector
add sector, #1
djnz i, #:forEachFatSector
neg temp, #110 ' -110: FAT full.
jmp #AckReturnCode
:foundEmptySlot
neg temp, #1
wrword temp, p ' Claim empty slot by writing $ffff.
mov dirty, #1 ' We've modified metadata.
mov sop, sector
shl sop, #9
sub p, pMetadataBuffer
add sop, p ' sop "points" to slot.
mov p, pFilestuff
add p, #_cluster
wrword cluster, p ' save cluster# in pFilestuff->cluster
sub p, #_cluster-_sopTail ' p points to pFilestuff->sopTail
rdlong sopTail, p ' get "pointer" to end of cluster list.
mov sector, sopTail ' Read the sector that sopTail "points" to.
shr sector, #9
call #ReadMetadataSector
and sopTail, #$1ff
add sopTail, pMetadataBuffer ' Use sopTail as pointer into buffer.
wrword cluster, sopTail ' Now the word pointed to by pFilestuff->sopTail
' is updated with the new cluster#.
mov dirty, #1
wrlong sop, p ' p is still pointing to pFilestuff->sopTail so
' update pFilestuff->sopTail to point to new tail.
:writeSector
mov p, pFilestuff
add p, #_cluster ' p points to pFilestuff->cluster
rdword i, p ' using i for sector#
sub i, #2
shl i, clusterShift
add i, dataSector0 ' At this point, i is the first sector of the cluster.
add p, #_sector-_cluster ' p points to pFilestuff->sector
rdword temp, p
add i, temp ' Now i is the correct sector of the cluster.
add temp, #1
wrword temp, p ' Increment pFilestuff->sector
cmp temp, sectorsPerCluster wz
mov temp, #0 ' if pFilestuff->sector = sectorsPerCluster,
if_e wrword temp, p ' pFilestuff->sector := 0.
add p, #_bp-_sector ' p points to pFilestuff->bp
wrword temp, p ' pFilestuff->bp = 0.
wrlong i, pSdspiBlockno
add p, #_buffer-_bp
wrlong p, pSdspiParam
mov temp, #"W"
call #SdspiCommand
WriteNextSector_ret ret
'*********************************************************************************************************************
'* *
'* Close stuff *
'* *
'*********************************************************************************************************************
Close ' ( pFilestuff )
rdlong pFilestuff, pSxfsParam0
mov p, pFilestuff
add p, #_bp
rdword temp, p wz ' If there's stuff waiting to be written
if_nz call #WriteNextSector ' (i.e. bp <> 0), write it.
mov p, pFilestuff
add p, #_sopDir
rdlong sop, p ' sop "points" to directory entry.
mov sector, sop
shr sector, #9
call #ReadMetadataSector ' We want to update metadata length info.
and sop, #$1ff
add sop, pMetadataBuffer
add sop, #$1c ' sop points to length in metadata buffer.
mov p, pFilestuff ' p points to pFilestuff->length.
rdlong temp, p
wrlong temp, sop ' store length in metadata.
mov dirty, #1
call #FlushMetadataSector
jmp #AckNoReturnCode
'*********************************************************************************************************************
'* *
'* Execute stuff *
'* *
'*********************************************************************************************************************
Execute ' ( pFilestuff, execmode, cogid )
{
Loads 63 sectors from file and executes. Requires that the file be contiguous on the SD card,
which is generally accomplished by formatting the card with cluster size >= 32k.
This reads 63 sectors instead of 64 to avoid writing junk into the rendezvous areas.
It is conceivable that some executable files will not run because of this.
This routine does handle clock speed changes.
If execmode is 0, start Spin interpreter in cog specified by cogid.
If execmode is 1, start Spin interpreter in cog specified by cogid and stop all other cogs.
}
call #FlushMetadataSector ' just in case
neg currentsector, #1 ' invalidate current sector 'cuz metadata buffer is about to be overwritten
rdlong pFilestuff, pSxfsParam0
rdlong filesize, pFilestuff wz ' length of file
if_z neg temp, #1 ' if file is empty, return -1: EOF
if_z jmp #AckReturnCode ' This is a bit of a hack. The Sphinx compiler really
' should delete outdated .bin or .eep files to force
' (re)linking, but since sxfs doesn't know how to
' delete files (yet(?)), the compiler just makes
' a file empty instead of deleting it. This test
' here catches empty executable files and bails,
' preventing a crash.
rdlong execmode, pSxfsParam1
rdbyte callingCog, pSxfsParam2 ' stop Spin interpreter
cogstop callingCog
rdlong oldClkfreq, #0 ' save clkfreq
rdbyte oldClkmode, #4 ' save clkmode
mov p, pFilestuff
add p, #_cluster
rdword temp, p ' temp = (cluster
sub temp, #2 ' - 2)
shl temp, clusterShift ' << clusterShift
add temp, dataSector0 ' + dataSector0
mov p, temp ' p repurposed here as sector#
mov i, #63 ' read 63 contiguous sectors
mov q, #0
:loop
wrlong p, pSdspiBlockno ' Prepare to read sector p
wrlong q, pSdspiParam ' to memory pointed to by q
mov temp, #"R"
call #SdspiCommand
add p, #1 ' Next sector
add q, k512 ' Next 512-byte block of memory
djnz i, #:loop
' clear memory above the loaded file
mov i, #1
shl i, #15 ' i = 32768
sub i, filesize wz ' - file size
if_z jmp #:z
mov temp, #0
:y
wrbyte temp, filesize ' repurpose filesize as pointer
add filesize, #1
djnz i, #:y
:z
' store those nutty $fff9ffff longs
rdword p, #$0a
sub p, #4
wrlong kfff9ffff, p
sub p, #4
wrlong kfff9ffff, p
tjz execmode, #:dontChangeClock ' execmode = 0? skip cog-killing and clock change
cogid temp
mov i, #0
mov j, #8
:cogkill
cmp i, temp wz ' kill all cogs except self
if_ne cogstop i ' (suicide comes later)
add i, #1
djnz j, #:cogkill
' The following code is borrowed liberally from sdspiFemto:
rdlong temp, #0 ' new clock frequency
cmp temp, oldClkfreq wz ' compared to old
rdbyte temp, #4 ' get new clock mode in advance
if_ne jmp #:changeClock
cmp temp, oldClkmode wz ' compare new clock mode to old
if_e jmp #:dontChangeClock
:changeClock and temp, #$f8 ' Force use of RCFAST clock while
clkset temp ' letting requested clock start
mov i, time_xtal
:startupDelay djnz i, #:startupDelay ' Allow 20ms@20MHz for xtal/pll to settle
rdbyte temp, #4 ' Then switch to selected clock
clkset temp
jmp #:x
:dontChangeClock
wrlong oldClkfreq, #0 ' Restore old clock frequency
wrbyte oldClkmode, #4 ' and mode.
:x
or interpreter, callingCog
coginit interpreter ' start new Spin interpreter in the same cog.
tjz execmode, #AckNoReturnCode ' execmode = 0? Done.
cogid temp ' kill
cogstop temp ' self
interpreter long ($0004 << 16) | ($F004 << 2) | %0000 ' Thanks to sdspiFemto
time_xtal long 20 * 20000 / 4 / 1 ' 20ms (@20MHz, 1 inst/loop)
'*********************************************************************************************************************
'* *
'* Utility stuff *
'* *
'*********************************************************************************************************************
{
Out'(outch) '''
:w rdbyte outtemp, pTerm wz
if_nz jmp #:w
wrbyte outch, pTerm
Out_ret ret
OutHex'(outx, outn) '''
mov outtemp, outn
sub outtemp, #1
shl outtemp, #2
ror outx, outtemp
:loop
mov outch, outx
and outch, #$0f
add outch, #"0"
cmp outch, #"9" wc, wz
if_a add outch, #"a"-"0"-10
call #out
rol outx, #4
djnz outn, #:loop
Outhex_ret ret
pTerm long $7ffc
outch long 0
outx long 0
outn long 0
outtemp long 0 '''
}
ByteCopy ' ( p, q, n )
tjz n, #ByteCopy_ret
:loop rdbyte temp, q
add q, #1
wrbyte temp, p
add p, #1
djnz n, #:loop
ByteCopy_ret ret
ReadMetadataSector ' ( sector )
call #FlushMetadataSector
cmp sector, currentSector wz
if_e jmp #ReadMetadataSector_ret
wrlong pMetadataBuffer, pSdspiParam
wrlong sector, pSdspiBlockno
mov currentSector, sector
mov temp, #"R"
call #SdspiCommand
ReadMetadataSector_ret ret
FlushMetadataSector
tjz dirty, #FlushMetadataSector_ret
mov dirty, #0
' write current sector
wrlong pMetadataBuffer, pSdspiParam
wrlong currentSector, pSdspiBlockno
mov temp, #"W"
call #SdspiCommand
FlushMetadataSector_ret ret
SdspiCommand
wrlong temp, pSdspiCommand
:wait
rdlong temp, pSdspiCommand wz
if_nz jmp #:wait
rdlong temp, pSdspiParam wz
if_nz jmp #AckReturnCode
SdspiCommand_ret ret
k512 long 512
kfff9ffff long $fff9ffff
dirty long 0
currentSector long -1
pMetadataBuffer long METADATABUFFER
pSxfsCommand long SXFSRENDEZVOUS+0
pSxfsParam0 long SXFSRENDEZVOUS+4
pSxfsParam1 long SXFSRENDEZVOUS+8
pSxfsParam2 long SXFSRENDEZVOUS+12
pSdspiCommand long SDSPIRENDEZVOUS+0
pSdspiParam long SDSPIRENDEZVOUS+4
pSdspiBlockno long SDSPIRENDEZVOUS+8
pCommand long SXFS2RENDEZVOUS+0
pParam long SXFS2RENDEZVOUS+4
bytesPerSector long 0
sectorsPerCluster long 0
clusterShift long 0
reservedSectors long 0
numberOfFats long 0
sectorsPerFat long 0
rootDirEntries long 0
fatSector0 long 0
dirSector0 long 0
dataSector0 long 0
temp res 1
i res 1
j res 1
n res 1
p res 1
q res 1
pFilestuff res 1
sop res 1
sopTail res 1
srcPtr res 1
nBytes res 1
cluster res 1
sector res 1
leftInSector res 1
filesize res 1
execmode res 1
callingCog res 1
oldClkfreq res 1
oldClkmode res 1
retcode res 1
fit
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,728 +0,0 @@
''*******************************
''* PS/2 Keyboard Driver v2.0 *
''* (C) 2004 Parallax, Inc. *
''* Modified by Michael Green *
''* to support Hydra as well *
''*******************************
{
Modified by Michael Park for Sphinx
2009/06/15
}
SXKBRENDEZVOUS = $7ff8
VAR
long cog
PUB start(pingroup) : okay
'' Start keyboard driver - starts a cog
'' returns false if no cog available
''
'' pingroup = 1st pin number for 2-pin group for PS/2 I/O
'' (1st - data signal, 2nd - clock signal)
'' Even number selects Demo Board I/O convention
''
'' 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
''
'' pingroup = 1st pin number for 4-pin group for PS/2 I/O
'' Odd number selects Hydra I/O convention
''
'' 1st pin drives NPN base for PS/2 'data' signal pull-down
'' 2nd pin reads PS/2 'data' signal
'' 3rd pin drives NPN base for PS/2 'clock' signal pull-down
'' 4th pin reads PS/2 'clock' signal
''
'' use 2.2K-ohm resistors between 1st/3rd pins and NPN bases
'' use 22K-ohm resistors between 2nd/4th pins and PS/2-side signals
'' use 2.2K-ohm resistors to pull PS/2-side signals to 5V
'' connect PS/2 power to 5V, PS/2 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(pingroup, %0_000_100, %01_01000)
PUB startx(pingroup, 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)
long[pRendezvous]~~ ' ping
if long[pRendezvous]~ == -1 ' no response
longmove(@_pingroup, @pingroup, 3)
okay := cog := cognew(@entry, 0) + 1
PUB peekkey
'' Returns a 0 if the buffer is empty
'' returns next key if buffer not empty
'' but doesn't remove the key from buffer
return long[pRendezvous]
PUB key : keycode
'' Get key (never waits)
'' returns key (0 if buffer empty)
if keycode := long[pRendezvous]
long[pRendezvous]~
PUB getkey : keycode
'' Get next key (may wait for keypress)
'' returns key
repeat until (keycode := key)
DAT
'******************************************
'* Assembly language PS/2 keyboard driver *
'******************************************
org
'
'
' Entry
'
entry
mov x,_pingroup 'get mask for 1st pin
andn x,#1
test _pingroup,#1 wz
mov dwmask,#1
shl dwmask,x
mov drmask,dwmask
if_nz shl drmask,#1
mov cwmask,drmask
shl cwmask,#1
mov crmask,cwmask
if_nz shl crmask,#1
if_nz or dira,dwmask 'set directions
if_nz or dira,cwmask
mov _head,#0 'reset output parameter _head
mov _tail, #0
'
'
' Reset keyboard
'
reset test _pingroup,#1 wz
if_nz andn outa,dwmask 'let PS/2 lines float (pulled up)
if_nz andn outa,cwmask
if_z mov dira,#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
call #Rendezvous
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
mov x, _tail 'if room in buffer and key valid, enter
sub x,#1
and x,#$F
cmp x,_head wz
if_e jmp #:z
test data,#$FF wz
if_z jmp #:z
mov x, #buffer
add x, _head
movd :store, x
nop
:store mov 0-0, data ' buffer[x] := data
add _head,#1
and _head,#$F
:z
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 test _pingroup,#1 wz
if_z or dira,cwmask
if_nz or outa,cwmask 'pull clock low
movs napshr,#13 'hold clock for ~128us (must be >100us)
call #nap
if_z or dira,dwmask
if_nz or outa,dwmask 'pull data low
movs napshr,#18 'hold data for ~4us
call #nap
if_z xor dira,cwmask
if_nz andn outa,cwmask '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
test _pingroup,#1 wz
if_z muxnc dira,dwmask
if_nz muxnc outa,dwmask
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
:waitpne
call #Rendezvous
mov x, ina 'wait indefinitely for initial clock low
and x, crmask
cmp x, crmask wz
if_e jmp #:waitpne
receive_ack mov x,#11 'ready 11 bits
receive_bit call #wait_c0 'wait until clock low
movs napshr,#16 'pause ~16us
call #nap
test drmask,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
'
'
' Communicate with the rest of the Propeller via "rendezvous" in hub memory.
'
Rendezvous
rdlong t, pRendezvous wz ' if rendezvous = 0 (location empty),
if_z jmp #:clearToSend ' go fill it with character in buffer.
add t, #1 wz ' if rendezvous = -1
if_nz jmp #Rendezvous_ret ' someone is pinging to see if sxkb cog is alive;
sub t, #2 ' set rendezvous to -2 to ack.
wrlong t, pRendezvous
jmp #Rendezvous_ret
:clearToSend
cmp _head, _tail wz
if_e jmp #Rendezvous_ret
mov x, _tail
add x, #buffer
movs :read, x
nop
:read mov data, 0-0 ' data := buffer[_tail]
wrlong data, pRendezvous
add _tail, #1
and _tail, #$0f
Rendezvous_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
test crmask,ina wc 'check required state(s)
test drmask,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,#0-0 'shr scales time (set to 13/16/18)
min t,#10 'ensure waitcnt won't snag (was 3 but snagged; upped to 10 [mp])
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, "+"
_pingroup long 0
_locks long 0
_auto long 0
pRendezvous long SXKBRENDEZVOUS
'
' Uninitialized data
'
buffer res 16
dwmask res 1 'output driver mask for data
drmask res 1 'input mask for data
cwmask res 1 'output driver mask for clock
crmask res 1 'input mask for data
stat res 1
data res 1
x res 1
y res 1
t res 1
_tail res 1
_head res 1 'write-only
_present res 1 'write-only
_states res 8 'write-only
fit
''
''
'' _________
'' 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

@ -1,334 +0,0 @@
' sdspi: SPI interface to a Secure Digital card.
'
' Copyright 2008 Radical Eye Software
' Modified 2009 by Michael Park: added pointer to rendezvous variables.
'
' See end of file for terms of use.
'
' You probably never want to call this; you want to use fsrw
' instead (which calls this); this is only the lowest layer.
'
' Assumes SD card is interfaced using four consecutive Propeller
' pins, as follows (assuming the base pin is pin 0):
' 3.3v
' | | | | | |
' R R R R R R 20k
' p0 --------*-+-+-+-+-+------ do
' p1 ----------*-+-+-+-+------ clk
' p2 ------------*-+-+-+------ di
' p3 --------------*-+-+------ cs (dat3)
' 150 +-+------ irq (dat1)
' +------ p9 (dat2)
'
' The 20k resistors
' are pullups, and should be there on all six lines (even
' the ones we don't drive).
'
' This code is not general-purpose SPI code; it's very specific
' to reading SD cards, although it can be used as an example.
'
' The code does not use CRC at the moment (this is the default).
' With some additional effort we can probe the card to see if it
' supports CRC, and if so, turn it on.
'
' All operations are guarded by a watchdog timer, just in case
' no card is plugged in or something else is wrong. If an
' operation does not complete in one second it is aborted.
'
con
sectorsize = 512
sectorshift = 9
var
long cog
long pCommand, pParam, pBlockno ' rendezvous between spin and assembly
pub stop
if cog
cogstop(cog~ - 1)
pub start(basepin, pRendezvous)
'
' Initialize the card! Send a whole bunch of
' clocks (in case the previous program crashed
' in the middle of a read command or something),
' then a reset command, and then wait until the
' card goes idle.
'
do := basepin++
clk := basepin++
di := basepin++
cs := basepin
stop
pCommand := pRendezvous
pParam := pRendezvous + 4
pBlockno := pRendezvous + 8
long[pCommand] := "I"
cog := 1 + cognew(@entry, pRendezvous)
repeat while long[pCommand]
if long[pParam]
abort long[pParam]
return 0
pub readblock(n, b)
'
' Read a single block. The "n" passed in is the
' block number (blocks are 512 bytes); the b passed
' in is the address of 512 blocks to fill with the
' data.
'
long[pParam] := b
long[pBlockno] := n
long[pCommand] := "R"
repeat while long[pCommand]
if long[pParam]
abort long[pParam]
return 0
pub writeblock(n, b)
'
' Write a single block. Mirrors the read above.
'
long[pParam] := b
long[pBlockno] := n
long[pCommand] := "W"
repeat while long[pCommand]
if long[pParam]
abort long[pParam]
return 0
dat
org
entry mov comptr,par
mov parptr,par
add parptr,#4
mov parptr2,parptr
add parptr2,#4
' set up
mov acca,#1
shl acca,di
or dira,acca
mov acca,#1
shl acca,clk
or dira,acca
mov acca,#1
shl acca,do
mov domask,acca
mov acca,#1
shl acca,cs
or dira,acca
mov csmask,acca
neg phsb,#1
mov frqb,#0
mov acca,nco
add acca,clk
mov ctra,acca
mov acca,nco
add acca,di
mov ctrb,acca
mov ctr2,onek
oneloop
call #sendiohi
djnz ctr2,#oneloop
mov starttime,cnt
mov cmdo,#0
mov cmdp,#0
call #cmd
or outa,csmask
call #sendiohi
initloop
mov cmdo,#55
call #cmd
mov cmdo,#41
call #cmd
or outa,csmask
cmp accb,#1 wz
if_z jmp #initloop
wrlong accb,parptr
' reset frqa and the clock
finished
mov frqa,#0
wrlong frqa,comptr
or outa,csmask
neg phsb,#1
call #sendiohi
pause
mov acca,#511
add acca,cnt
waitcnt acca,#0
waitloop
mov starttime,cnt
rdlong acca,comptr wz
cmp acca,#"B" wz
if_z jmp #byteio
mov ctr2,sector
cmp acca,#"R" wz
if_z jmp #rblock
cmp acca,#"W" wz
if_nz jmp #pause
wblock
mov starttime,cnt
mov cmdo,#24
rdlong cmdp,parptr2
call #cmd
mov phsb,#$fe
call #sendio
rdlong accb,parptr
neg frqa,#1
wbyte
rdbyte phsb,accb
shl phsb,#23
add accb,#1
mov ctr,#8
wbit mov phsa,#8
shl phsb,#1
djnz ctr,#wbit
djnz ctr2,#wbyte
neg phsb,#1
call #sendiohi
call #sendiohi
call #readresp
and accb,#$1f
sub accb,#5
wrlong accb,parptr
call #busy
jmp #finished
rblock
mov starttime,cnt
mov cmdo,#17
rdlong cmdp,parptr2
call #cmd
call #readresp
rdlong accb,parptr
sub accb,#1
rbyte
mov phsa,hifreq
mov frqa,freq
add accb,#1
test domask,ina wc
addx acca,acca
test domask,ina wc
addx acca,acca
test domask,ina wc
addx acca,acca
test domask,ina wc
addx acca,acca
test domask,ina wc
addx acca,acca
test domask,ina wc
addx acca,acca
test domask,ina wc
addx acca,acca
mov frqa,#0
test domask,ina wc
addx acca,acca
wrbyte acca,accb
djnz ctr2,#rbyte
mov frqa,#0
neg phsb,#1
call #sendiohi
call #sendiohi
or outa,csmask
wrlong ctr2,parptr
jmp #finished
byteio
rdlong phsb,parptr
call #sendio
wrlong accb,parptr
jmp #finished
sendio
rol phsb,#24
sendiohi
mov ctr,#8
neg frqa,#1
mov accb,#0
bit mov phsa,#8
test domask,ina wc
addx accb,accb
rol phsb,#1
djnz ctr,#bit
sendio_ret
sendiohi_ret
ret
checktime
mov duration,cnt
sub duration,starttime
cmp duration,clockfreq wc
checktime_ret
if_c ret
neg duration,#13
wrlong duration,parptr
jmp #finished
cmd
andn outa,csmask
neg phsb,#1
call #sendiohi
mov phsb,cmdo
add phsb,#$40
call #sendio
mov phsb,cmdp
shl phsb,#9
call #sendiohi
call #sendiohi
call #sendiohi
call #sendiohi
mov phsb,#$95
call #sendio
readresp
neg phsb,#1
call #sendiohi
call #checktime
cmp accb,#$ff wz
if_z jmp #readresp
cmd_ret
readresp_ret
ret
busy
neg phsb,#1
call #sendiohi
call #checktime
cmp accb,#$0 wz
if_z jmp #busy
busy_ret
ret
di long 0
do long 0
clk long 0
cs long 0
nco long $1000_0000
hifreq long $e0_00_00_00
freq long $20_00_00_00
clockfreq long 80_000_000
onek long 1000
sector long 512
domask res 1
csmask res 1
acca res 1
accb res 1
cmdo res 1
cmdp res 1
comptr res 1
parptr res 1
parptr2 res 1
ctr res 1
ctr2 res 1
starttime res 1
duration res 1
{{
' 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

@ -1,916 +0,0 @@
''***************************************
''* TV Driver v1.1 *
''* Author: Chip Gracey *
''* Copyright (c) 2004 Parallax, Inc. *
''* See end of file for terms of use. *
''***************************************
' v1.0 - 01 May 2006 - original version
' v1.1 - 17 May 2006 - pixel tile size can now be 16 x 32 to enable more efficient
' character displays utilizing the internal font - see 'tv_mode'
{
2009
May
11 Moved blank line tasks into one-time initialization section.
Difficulty: one task was flipping the interlace bit of _mode, necessitating a reload of _mode
every superfield. Removed the flip and changed the sense of the Z tests that depended on _mode<1>
being flipped.
12 Implemented simple scrolling terminal output in background task.
Difficulty: have to keep Z clear so that mainline interlaced code works properly.
June
9 Added "D"isable and "E"nable commands.
20 Changing ping response to include basepin.
}
CON
fntsc = 3_579_545 'NTSC color frequency
lntsc = 3640 'NTSC color cycles per line * 16
sntsc = 624 'NTSC color cycles per sync * 16
fpal = 4_433_618 'PAL color frequency
lpal = 4540 'PAL color cycles per line * 16
spal = 848 'PAL color cycles per sync * 16
paramcount = 14
' colortable = $180 'start of colortable inside cog
cols = 40
rows = 13
VAR
long cog
long rendezvous
PUB start(basepin, rv) | okay
'' Start TV driver - starts a cog if necessary
'' returns true if it had to start a cog, false if cog was already running.
''
_basepin := basepin
rendezvous := rv
long[rendezvous]~~ ' ping the sxtv cog (send -1)
waitcnt( clkfreq/10 + cnt )
if long[rendezvous] <> -1 ' if the cog is alive it'll set this to _basepin<<8
long[rendezvous]~
return false
_pins := (basepin & $38) << 1 | (basepin & 4 == 4) & %0101
if cog := cognew(@entry, rendezvous) + 1
return true
else
abort string("Couldn't start sxtv cog")
PUB stop
'' Stop TV driver - frees a cog
if cog
cogstop(cog~ - 1)
PUB GetBasepin
repeat while long[rendezvous]
long[rendezvous]~~ ' ping the sxtv cog (send -1)
repeat while long[rendezvous] == -1
return long[rendezvous]~ >> 8
PUB str(stringptr)
'' Print a zero-terminated string
repeat strsize(stringptr)
out(byte[stringptr++])
PUB dec(value) | _i
'' Print a decimal number
if value < 0
-value
out("-")
_i := 1_000_000_000
repeat 10
if value => _i
out(value / _i + "0")
value //= _i
result~~
elseif result or _i == 1
out("0")
_i /= 10
PUB hex(value, digits)
'' Print a hexadecimal number
value <<= (8 - digits) << 2
repeat digits
out(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))
PUB bin(value, digits)
'' Print a binary number
value <<= 32 - digits
repeat digits
out((value <-= 1) & 1 + "0")
pub out( c )
repeat while byte[rendezvous]
byte[rendezvous] := c
DAT
'*******************************
'* Assembly language TV driver *
'*******************************
org
'
'
' Entry
'
entry
call #init
mov taskptr,#tasks 'reset tasks
'
'
' Superfield
'
superfield
test _mode,#%0001 wc 'if ntsc, set phaseflip
if_nc mov phaseflip,phasemask
test _mode,#%0010 wz 'get interlace into nz
mov temp, #0 wz ''' I messed something up and now Z has to be set, not clear.
'
'
' Field
'
field mov x,vinv 'do invisible back porch lines
:black call #hsync 'do hsync
waitvid burst,sync_high2 'do black
jmpret taskret,taskptr 'call task section (z undisturbed)
djnz x,#:black 'another black line?
' wrlong visible,par 'set status to visible
mov x,vb 'do visible back porch lines
call #blank_lines
mov y,_vt 'set vertical tiles
movs :getchars4, #text '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
:line
mov vx,_vx 'set vertical expand
mov t1,#32
mov chset, chset0
:vert
if_z xor interlace,#1 'interlace skip?
if_z tjz interlace,#:skip
call #hsync 'do hsync
mov vscl,hb 'do visible back porch pixels
xor tile,colortable
waitvid tile,#0
mov x,_ht 'set horizontal tiles
shr x, #2 'divide by 4
mov vscl,hx 'set horizontal expand
:getchars4 mov chars4, 0-0
mov t3, #4
:loop4
mov char, chars4
ror chars4, #8
and char, #$ff
shr char, #1 wc
shl char, #7
add char, chset
rdlong pixels16, char
' xor colors4, phaseflip
if_nc waitvid colortable, pixels16
if_c waitvid colortable+1, pixels16
djnz t3, #:loop4
add :getchars4, #1
djnz x, #:getchars4
mov vscl,hf 'do visible front porch pixels
mov tile,colortable'phaseflip
' xor tile,colortable
waitvid tile,#0
sub :getchars4, #10
:skip
add chset, #4
djnz t1, #:vert
add :getchars4, #10
djnz y,#:line 'another tile line?
if_z xor interlace,#1 wz 'get interlace and field1 into z
test _mode,#%0001 wc 'do visible front porch lines
mov x,vf
if_nz_and_c add x,#1
call #blank_lines
' if_z wrlong invisible,par 'unless interlace and field1, set status to invisible
if_z_eq_c call #hsync 'if required, do short line
if_z_eq_c mov vscl,hrest
if_z_eq_c waitvid burst,sync_high2
if_z_eq_c xor phaseflip,phasemask
call #vsync_high 'do high vsync pulses
movs vsync1,#sync_low1 'do low vsync pulses
movs vsync2,#sync_low2
call #vsync_low
call #vsync_high 'do high vsync pulses
if_nz mov vscl,hhalf 'if odd frame, do half line
if_nz waitvid burst,sync_high2
if_z jmp #field 'if interlace and field1, display field2
jmp #superfield 'else, new superfield
'
'
' Blank lines
'
blank_lines call #hsync 'do hsync
xor tile,colortable 'do background
waitvid tile,#0
djnz x,#blank_lines
blank_lines_ret ret
'
'
' Horizontal sync
'
hsync test _mode,#%0001 wc 'if pal, toggle phaseflip
' if_c xor phaseflip,phasemask
mov vscl,sync_scale1 'do hsync
mov tile,burst'phaseflip
' xor tile,burst
waitvid tile,sync_normal
mov vscl,hvis 'setup in case blank line
mov tile,#0'phaseflip
hsync_ret ret
'
'
' Vertical sync
'
vsync_high movs vsync1,#sync_high1 'vertical sync
movs vsync2,#sync_high2
vsync_low mov x,vrep
vsyncx mov vscl,sync_scale1
vsync1 waitvid burst,sync_high1
mov vscl,sync_scale2
vsync2 waitvid burst,sync_high2
djnz x,#vsyncx
vsync_low_ret
vsync_high_ret ret
'
'
' Tasks - performed in sections during invisible back porch lines
'
tasks
clearscreen
mov i, #14 ' clear 13 lines + 1 extra to make scrolling easier
:lines
mov j, #40/4 ' 40 columns, 4 chars at a time
:chars
:storem mov text, x20202020
add :storem, d0 ' inc dst
djnz j, #:chars
jmpret taskptr,taskret
djnz i, #:lines
waitforchar
mov temp, #0 ' clear buffer: ready to accept next byte
wrlong temp, par
waitnoclear
:wait
jmpret taskptr,taskret
rdlong ch, par
tjz ch, #:wait
' got a byte
mov temp, cmdPing ' roundabout comparisons to avoid changing Z.
sub temp, ch ' ch = -1 is just a ping to see if this cog is alive.
tjz temp, #ping
mov temp, cmdDisable
sub temp, ch
tjz temp, #disable
mov temp, cmdEnable
sub temp, ch
tjz temp, #enable
neg temp, #256 ' at this point, if ch is > 255, it must be _basepin<<8
and temp, ch ' as set by a previous ping, so we just ignore it
tjnz temp, #waitnoclear ' (leave the long pointed to by par undisturbed).
:char
mov temp, #8
sub temp, ch
tjz temp, #:bksp
mov temp, #13
sub temp, ch
tjnz temp, #:printchar
call #cr
jmp #waitforchar
:bksp
sub col, #1 ' warning: no error-checking
jmp #waitforchar
:printchar
mov temp, #40
sub temp, col
tjnz temp, #:nocr
call #cr
:nocr
mov temp, col
shr temp, #2
add temp, #text+12*40/4
movs :get4chars, temp
movd :put4chars, temp
mov i, col
and i, #3
shl i, #3 ' col&3 => 0, 8, 16, 24
:get4chars mov temp, 0-0
ror temp, i
andn temp, #$ff
or temp, ch
rol temp, i
:put4chars mov 0-0, temp
add col, #1
jmp #waitforchar
cr
movs :move4chars, #text + 40 / 4
movd :move4chars, #text
mov i, #13 ' copy 13 lines up. Since we have an extra blank line at the bottom
' (see clearscreen) the last visible line is automatically cleared.
:copyline
mov j, #40/4
:move4chars mov 0-0, 0-0
add :move4chars, d0s0
djnz j, #:move4chars
jmpret taskptr,taskret
djnz i, #:copyline
mov col, #0
cr_ret ret
ping
mov temp, _basepin
shl temp, #8
wrlong temp, par
jmp #waitnoclear
enable
mov dira, saveDira
mov dirb, saveDirb
jmp #waitforchar
disable
mov dira, #0
mov dirb, #0
jmp #waitforchar
'
'
' Initialized data
'
x20202020 long $20202020
chset0 long $8000
m8 long 8_000_000
m128 long 128_000_000
d0 long 1 << 9 << 0
d6 long 1 << 9 << 6
d0s0 long 1 << 9 << 0 + 1 << 0
d0s1 long 1 << 9 << 0 + 1 << 1
interlace long 0
invisible long 1
visible long 2
phaseflip long $00000000
phasemask long $F0F0F0F0
line long $00060000
lineinc long $10000000
linerot long 0
pins0 long %11110000_01110000_00001111_00000111
pins1 long %11111111_11110111_01111111_01110111
sync_high1 long %0101010101010101010101_101010_0101
sync_high2 long %01010101010101010101010101010101 'used for black
sync_low1 long %1010101010101010101010101010_0101
sync_low2 long %01_101010101010101010101010101010
colortable
' long $07_0a_07_0a ' white on blue
' long $07_07_0a_0a
' long $bc_02_bc_02 ' green on black
' long $bc_bc_02_02
' long $05_02_05_02 ' white on black
' long $05_05_02_02
long $02_05_02_05 ' black on white
long $02_02_05_05
' long $8a_8c_8a_8c ' black on yellow
' long $8a_8a_8c_8c
'
'
' NTSC/PAL metrics tables
' ntsc pal
' ----------------------------------------------
wtab word lntsc - sntsc, lpal - spal 'hvis
word lntsc / 2 - sntsc, lpal / 2 - spal 'hrest
word lntsc / 2, lpal / 2 'hhalf
word 243, 286 'vvis
word 10, 18 'vinv
word 6, 5 'vrep
word $02_8A, $02_AA 'burst
wtabx
ltab long fntsc 'fcolor
long fpal
long sntsc >> 4 << 12 + sntsc 'sync_scale1
long spal >> 4 << 12 + spal
long 67 << 12 + lntsc / 2 - sntsc 'sync_scale2
long 79 << 12 + lpal / 2 - spal
long %0101_00000000_01_10101010101010_0101 'sync_normal
long %010101_00000000_01_101010101010_0101
ltabx
cmdPing long -1
cmdEnable long "E"<<8
cmdDisable long "D"<<8
_basepin long 0
'
'
' Parameter buffer
'
_enable long 1 'enable
_pins long 0 'pins
_mode long %10010 'mode
_screen long 0 'screen
_colors long 0 'colors
_ht long cols 'hc
_vt long rows 'vc
_hx long 4 'hx
_vx long 1 'vx
_ho long 0 'ho
_vo long 0 'vo
_broadcast long 0 'broadcast
_auralcog long 0 'auralcog
'
'
' Uninitialized data
'
i long 0
j long 0
col long 0
ch long 0
temp long 0
char long 0
chset long 0
chars4 long 0
pixels16 long 0
taskptr long 0 'tasks
taskret long 0
t1 long 0
t2 long 0
t3 long 0
m1 long 0
m2 long 0
x long 0 'display
y long 0
hf long 0
hb long 0
vf long 0
vb long 0
hx long 0
vx long 0
hc2x long 0
screen long 0
tile long 0
pixels long 0
lineadd long 0
hvis long 0 'loaded from word table
hrest long 0
hhalf long 0
vvis long 0
vinv long 0
vrep long 0
burst long 0
fcolor long 0 'loaded from long table
sync_scale1 long 0
sync_scale2 long 0
sync_normal long 0
saveDira long 0
saveDirb long 0
text ' Cog memory from this point on will be reclaimed as text buffer.
init
mov t1,_pins 'set video pins and directions
test t1,#$08 wc
if_nc mov t2,pins0
if_c mov t2,pins1
test t1,#$40 wc
shr t1,#1
shl t1,#3
shr t2,t1
movs vcfg,t2
shr t1,#6
movd vcfg,t1
shl t1,#3
and t2,#$FF
shl t2,t1
if_nc mov dira,t2
if_nc mov saveDira, t2
if_nc mov dirb,#0
if_nc mov saveDirb, #0
if_c mov dira,#0
if_c mov saveDira, #0
if_c mov dirb,t2 '+18
if_c mov saveDirb, t2
movs :rd,#wtab 'load ntsc/pal metrics from word table
movd :wr,#hvis
mov t1,#wtabx - wtab
test _mode,#%0001 wc
:rd mov t2,0
add :rd,#1
if_nc shl t2,#16
shr t2,#16
:wr mov 0,t2
add :wr,d0
djnz t1,#:rd '+54
if_nc movs :ltab,#ltab 'load ntsc/pal metrics from long table
if_c movs :ltab,#ltab+1
movd :ltab,#fcolor
mov t1,#(ltabx - ltab) >> 1
:ltab mov 0,0
add :ltab,d0s1
djnz t1,#:ltab '+17
rdlong t1,#0 'get CLKFREQ
shr t1,#1 'if CLKFREQ < 16MHz, cancel _broadcast
cmp t1,m8 wc
if_c mov _broadcast,#0
shr t1,#1 'if CLKFREQ < color frequency * 4, disable
' cmp t1,fcolor wc
' if_c jmp #disabled '+11
mov t1,fcolor 'set ctra pll to fcolor * 16
call #divide 'if ntsc, set vco to fcolor * 32 (114.5454 MHz)
test _mode,#%0001 wc 'if pal, set vco to fcolor * 16 (70.9379 MHz)
if_c movi ctra,#%00001_111 'select fcolor * 16 output (ntsc=/2, pal=/1)
if_nc movi ctra,#%00001_110
if_nc shl t2,#1
mov frqa,t2 '+147
mov t1,_broadcast 'set ctrb pll to _broadcast
mov t2,#0 'if 0, turn off ctrb
tjz t1,#:off
min t1,m8 'limit from 8MHz to 128MHz
max t1,m128
mov t2,#%00001_100 'adjust _broadcast to be within 4MHz-8MHz
:scale shr t1,#1 '(vco will be within 64MHz-128MHz)
cmp m8,t1 wc
if_c add t2,#%00000_001
if_c jmp #:scale
:off movi ctrb,t2
call #divide
mov frqb,t2 '+165
mov t1,#%10100_000 'set video configuration
test _pins,#$01 wc '(swap broadcast/baseband output bits?)
if_c or t1,#%01000_000
test _mode,#%1000 wc '(strip chroma from broadcast?)
if_nc or t1,#%00010_000
test _mode,#%0100 wc '(strip chroma from baseband?)
if_nc or t1,#%00001_000
and _auralcog,#%111 '(set aural cog)
or t1,_auralcog
movi vcfg,t1 '+10
mov hx,_hx 'compute horizontal metrics
shl hx,#8
or hx,_hx
shl hx,#4
mov hc2x,_ht
shl hc2x,#1
mov t1,_ht
mov t2,_hx
call #multiply
mov hf,hvis
sub hf,t1
shr hf,#1 wc
mov hb,_ho
addx hb,hf
sub hf,_ho '+52
mov t1,_vt 'compute vertical metrics
mov t2,_vx
call #multiply
test _mode,#%10000 wc 'consider tile size
muxc linerot,#1
mov lineadd,lineinc
if_c shr lineadd,#1
if_c shl t1,#1
test _mode,#%0010 wc 'consider interlace
if_c shr t1,#1
mov vf,vvis
sub vf,t1
shr vf,#1 wc
neg vb,_vo
addx vb,vf
add vf,_vo '+53
init_ret ret
'
'
' Divide t1/CLKFREQ to get frqa or frqb value into t2
'
divide rdlong m1,#0 'get CLKFREQ
mov m2,#32+1
:loop cmpsub t1,m1 wc
rcl t2,#1
shl t1,#1
djnz m2,#:loop
divide_ret ret '+140
'
'
' Multiply t1 * t2 * 16 (t1, t2 = bytes)
'
multiply shl t2,#8+4-1
mov m1,#8
:loop shr t1,#1 wc
if_c add t1,t2
djnz m1,#:loop
multiply_ret ret '+37
''
''___
''VAR 'TV parameters - 14 contiguous longs
''
'' long tv_status '0/1/2 = off/invisible/visible read-only
'' long tv_enable '0/non-0 = off/on write-only
'' long tv_pins '%pppmmmm = pin group, pin group mode write-only
'' long tv_mode '%tccip = tile,chroma,interlace,ntsc/pal write-only
'' long tv_screen 'pointer to screen (words) write-only
'' long tv_colors 'pointer to colors (longs) write-only
'' long tv_ht 'horizontal tiles write-only
'' long tv_vt 'vertical tiles write-only
'' long tv_hx 'horizontal tile expansion write-only
'' long tv_vx 'vertical tile expansion write-only
'' long tv_ho 'horizontal offset write-only
'' long tv_vo 'vertical offset write-only
'' long tv_broadcast 'broadcast frequency (Hz) write-only
'' long tv_auralcog 'aural fm cog write-only
''
''The preceding VAR section may be copied into your code.
''After setting variables, do start(@tv_status) to start driver.
''
''All parameters are reloaded each superframe, allowing you to make live
''changes. To minimize flicker, correlate changes with tv_status.
''
''Experimentation may be required to optimize some parameters.
''
''Parameter descriptions:
'' _________
'' tv_status
''
'' driver sets this to indicate status:
'' 0: driver disabled (tv_enable = 0 or CLKFREQ < requirement)
'' 1: currently outputting invisible sync data
'' 2: currently outputting visible screen data
'' _________
'' tv_enable
''
'' 0: disable (pins will be driven low, reduces power)
'' non-0: enable
'' _______
'' tv_pins
''
'' bits 6..4 select pin group:
'' %000: pins 7..0
'' %001: pins 15..8
'' %010: pins 23..16
'' %011: pins 31..24
'' %100: pins 39..32
'' %101: pins 47..40
'' %110: pins 55..48
'' %111: pins 63..56
''
'' bits 3..0 select pin group mode:
'' %0000: %0000_0111 - baseband
'' %0001: %0000_0111 - broadcast
'' %0010: %0000_1111 - baseband + chroma
'' %0011: %0000_1111 - broadcast + aural
'' %0100: %0111_0000 broadcast -
'' %0101: %0111_0000 baseband -
'' %0110: %1111_0000 broadcast + aural -
'' %0111: %1111_0000 baseband + chroma -
'' %1000: %0111_0111 broadcast baseband
'' %1001: %0111_0111 baseband broadcast
'' %1010: %0111_1111 broadcast baseband + chroma
'' %1011: %0111_1111 baseband broadcast + aural
'' %1100: %1111_0111 broadcast + aural baseband
'' %1101: %1111_0111 baseband + chroma broadcast
'' %1110: %1111_1111 broadcast + aural baseband + chroma
'' %1111: %1111_1111 baseband + chroma broadcast + aural
'' -----------------------------------------------------------
'' active pins top nibble bottom nibble
''
'' the baseband signal nibble is arranged as:
'' bit 3: chroma signal for s-video (attach via 560-ohm resistor)
'' bits 2..0: baseband video (sum 270/560/1100-ohm resistors to form 75-ohm 1V signal)
''
'' the broadcast signal nibble is arranged as:
'' bit 3: aural subcarrier (sum 560-ohm resistor into network below)
'' bits 2..0: visual carrier (sum 270/560/1100-ohm resistors to form 75-ohm 1V signal)
'' _______
'' tv_mode
''
'' bit 4 selects between 16x16 and 16x32 pixel tiles:
'' 0: 16x16 pixel tiles (tileheight = 16)
'' 1: 16x32 pixel tiles (tileheight = 32)
''
'' bit 3 controls chroma mixing into broadcast:
'' 0: mix chroma into broadcast (color)
'' 1: strip chroma from broadcast (black/white)
''
'' bit 2 controls chroma mixing into baseband:
'' 0: mix chroma into baseband (composite color)
'' 1: strip chroma from baseband (black/white or s-video)
''
'' bit 1 controls interlace:
'' 0: progressive scan (243 display lines for NTSC, 286 for PAL)
'' less flicker, good for motion
'' 1: interlaced scan (486 display lines for NTSC, 572 for PAL)
'' doubles the vertical display lines, good for text
''
'' bit 0 selects NTSC or PAL format
'' 0: NTSC
'' 3016 horizontal display ticks
'' 243 or 486 (interlaced) vertical display lines
'' CLKFREQ must be at least 14_318_180 (4 * 3_579_545 Hz)*
'' 1: PAL
'' 3692 horizontal display ticks
'' 286 or 572 (interlaced) vertical display lines
'' CLKFREQ must be at least 17_734_472 (4 * 4_433_618 Hz)*
''
'' * driver will disable itself while CLKFREQ is below requirement
'' _________
'' tv_screen
''
'' pointer to words which define screen contents (left-to-right, top-to-bottom)
'' number of words must be tv_ht * tv_vt
'' each word has two bitfields: a 6-bit colorset ptr and a 10-bit pixelgroup ptr
'' bits 15..10: select the colorset* for the associated pixel tile
'' bits 9..0: select the pixelgroup** address %ppppppppppcccc00 (p=address, c=0..15)
''
'' * colorsets are longs which each define four 8-bit colors
''
'' ** pixelgroups are <tileheight> longs which define (left-to-right, top-to-bottom) the 2-bit
'' (four color) pixels that make up a 16x16 or a 32x32 pixel tile
'' _________
'' tv_colors
''
'' pointer to longs which define colorsets
'' number of longs must be 1..64
'' each long has four 8-bit fields which define colors for 2-bit (four color) pixels
'' first long's bottom color is also used as the screen background color
'' 8-bit color fields are as follows:
'' bits 7..4: chroma data (0..15 = blue..green..red..)*
'' bit 3: controls chroma modulation (0=off, 1=on)
'' bits 2..0: 3-bit luminance level:
'' values 0..1: reserved for sync - don't use
'' values 2..7: valid luminance range, modulation adds/subtracts 1 (beware of 7)
'' value 0 may be modulated to produce a saturated color toggling between levels 1 and 7
''
'' * because of TV's limitations, it doesn't look good when chroma changes abruptly -
'' rather, use luminance - change chroma only against a black or white background for
'' best appearance
'' _____
'' tv_ht
''
'' horizontal number pixel tiles - must be at least 1
'' practical limit is 40 for NTSC, 50 for PAL
'' _____
'' tv_vt
''
'' vertical number of pixel tiles - must be at least 1
'' practical limit is 13 for NTSC, 15 for PAL (26/30 max for interlaced NTSC/PAL)
'' _____
'' tv_hx
''
'' horizontal tile expansion factor - must be at least 3 for NTSC, 4 for PAL
''
'' make sure 16 * tv_ht * tv_hx + ||tv_ho + 32 is less than the horizontal display ticks
'' _____
'' tv_vx
''
'' vertical tile expansion factor - must be at least 1
''
'' make sure <tileheight> * tv_vt * tv_vx + ||tv_vo + 1 is less than the display lines
'' _____
'' tv_ho
''
'' horizontal offset in ticks - pos/neg value (0 for centered image)
'' shifts the display right/left
'' _____
'' tv_vo
''
'' vertical offset in lines - pos/neg value (0 for centered image)
'' shifts the display up/down
'' ____________
'' tv_broadcast
''
'' broadcast frequency expressed in Hz (ie channel 2 is 55_250_000)
'' if 0, modulator is turned off - saves power
''
'' broadcasting requires CLKFREQ to be at least 16_000_000
'' while CLKFREQ is below 16_000_000, modulator will be turned off
'' ___________
'' tv_auralcog
''
'' selects cog to supply aural fm signal - 0..7
'' uses ctra pll output from selected cog
''
'' in NTSC, the offset frequency must be 4.5MHz and the max bandwidth +-25KHz
'' in PAL, the offset frequency and max bandwidth vary by PAL type
{{
+------------------------------------------------------------------------------------------------------------------------------+
¦ 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

@ -1,83 +0,0 @@
obj
bt: "bintree"
dat
pSymbolTable word 0
pub Init
FixupTable( @table + 2 )
pSymbolTable := @table
bt.PokeW( pSymbolTable, @table + 2 )
pri FixupTable( p ) | q
q := bt.PeekW( p )
if q
bt.PokeW( p, q += @table )
FixupTable( q )
q := bt.PeekW( p + 2 )
if q
bt.PokeW( p + 2, q += @table )
FixupTable( q )
pub SymbolLookup( s )
return bt.FindInTable( s, bt.PeekW(pSymbolTable) )
pub AddToTable( s )
bt.AddToTable( s, pSymbolTable )
pub GetPSymbolTable
return pSymbolTable
con #0
' In the symbol table, the symbol's name (null-terminated) is followed by one of the following type bytes
' which is in turn followed by additional data:
{0} kINT_CON_SYMBOL ' followed by 4-byte constant
{1} kFLOAT_CON_SYMBOL ' followed by 4-byte constant
{2} kPUB_SYMBOL ' followed by 1-byte method index, 1-byte #params
{3} kPRI_SYMBOL ' followed by 1-byte method index, 1-byte #params
{4} kOBJ_SYMBOL ' followed by 2-byte pointer to child object's symbol table, 1-byte index, 2-byte count,
' 2-byte pointer to next OBJ in linked list
{5} kVAR_SYMBOL ' followed by 1-byte size (1, 2, 4), 2-byte var offset
{6} kDAT_SYMBOL ' followed by 1-byte size (1, 2, 4), 2-byte dat offset, 2-byte cog address * 4, 2-byte pointer to local labels
{7} kSOB_SYMBOL ' followed by 2-byte pointer to SOB's symbol table
{8} kUNDEFINED_CON_SYMBOL ' followed by 4-byte constant to be determined
{9} kBUILTIN_INT_SYMBOL ' followed by 4-byte constant
{10}kBUILTIN_FLOAT_SYMBOL ' followed by 4-byte constant
dat
table word 0
byte $10,$00,$85,$00,$50,$4f,$53,$58,$00,$09,$ff,$ff,$ff,$7f,$1f,$00
byte $58,$00,$50,$4c,$4c,$31,$58,$00,$09,$40,$00,$00,$00,$2b,$00,$48
byte $00,$50,$49,$00,$0a,$db,$0f,$49,$40,$39,$00,$00,$00,$4e,$45,$47
byte $58,$00,$09,$00,$00,$00,$80,$00,$00,$00,$00,$46,$41,$4c,$53,$45
byte $00,$09,$00,$00,$00,$00,$00,$00,$00,$00,$50,$4c,$4c,$31,$36,$58
byte $00,$09,$00,$04,$00,$00,$67,$00,$76,$00,$50,$4c,$4c,$34,$58,$00
byte $09,$00,$01,$00,$00,$00,$00,$00,$00,$50,$4c,$4c,$32,$58,$00,$09
byte $80,$00,$00,$00,$00,$00,$00,$00,$50,$4c,$4c,$38,$58,$00,$09,$00
byte $02,$00,$00,$95,$00,$c3,$00,$58,$49,$4e,$50,$55,$54,$00,$09,$04
byte $00,$00,$00,$a5,$00,$b5,$00,$52,$43,$53,$4c,$4f,$57,$00,$09,$02
byte $00,$00,$00,$00,$00,$00,$00,$52,$43,$46,$41,$53,$54,$00,$09,$01
byte $00,$00,$00,$00,$00,$00,$00,$54,$52,$55,$45,$00,$09,$ff,$ff,$ff
byte $ff,$d2,$00,$e1,$00,$58,$54,$41,$4c,$32,$00,$09,$10,$00,$00,$00
byte $00,$00,$00,$00,$58,$54,$41,$4c,$31,$00,$09,$08,$00,$00,$00,$00
byte $00,$00,$00,$58,$54,$41,$4c,$33,$00,$09,$20,$00,$00,$00
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,430 +0,0 @@
' 2009-05-02 Modified to detect when inside DAT, handle :<id> specially (for local labels)
con
_clkmode = xtal1 + pll8x
_xinfreq = 10_000_000
_stack = 1000
obj
f: "sxfile"
floatString: "FltStr"
kw: "keywords"
bt: "bintree"
pub Open( pFilename )
if f.Open( pFilename, "R") <> 0
abort string("can't open file")
InitReadLine
insideDAT~
Advance ' prime the pump
pub Close
f.Close
{
bytes~
InitReadLine
GetNextToken ' prime the pump
t := cnt
repeat
case tokenType
EOL_TOKEN:
term.str( @tokenText )
EOF_TOKEN:
quit
ID_TOKEN:
term.str( @tokenText )
OP_TOKEN:
INT_TOKEN:
term.out( "#" )
term.dec( tokenValue )
FLOAT_TOKEN:
term.out( "F" )
term.str( floatString.FloatToString( tokenValue ) )
term.out( "\" )
GetNextToken
term.out( 13 )
'}
{ repeat while SkipWhitespace
term.dec( lineNo )
term.out( "," )
term.dec( cp+1 )
term.out( ":" )
if cp == lineLength
term.str( string("(eol)"))
else
term.out( lineBuffer[cp++] )
term.out( 13 )
'}
{
repeat
r := sdfat.pread( @buf, BUFFERSIZE )
if r < 0
quit
bytes += r
'}
{
repeat 100
r := sdfat.pgetc
if r < 0
quit
++bytes
term.dec(r)
term.out( "," )
'}
con
MAXTOKENLENGTH = 32
BUFFERSIZE = 200
var
byte tokenText[MAXTOKENLENGTH+1]
long tokenType
word tokenLineNumber
word tokenCol
long tokenValue
byte insideDAT
pub GetPText
return @tokenText
pub Type
return tokenType
pub Column
return tokenCol
pub LineNumber
return tokenLineNumber
pub Value
return tokenValue
pub Advance | i, radix, fp, x, hack
if inStringLiteral
if comma
comma~
ifnot tokenValue
abort string("Unterminated string")
if lineBuffer[cp] <> $22 ' double-quote
tokenType := kw#kCOMMA
return
++cp
inStringLiteral~
else
comma~~
tokenType := kw#kINTLITERAL
tokenValue := lineBuffer[cp++]
return
if SkipWhitespace
if cp == lineLength
tokenType := kw#kEOL
bytemove( @tokenText, string("(EOL)"), 6 )
tokenLineNumber := lineNo
tokenCol := cp
elseif lineBuffer[cp] == $22 ' double-quote
tokenLineNumber := LineNo
tokenCol := cp
++cp
if LineBuffer[cp] == $22
abort string("Empty string")
comma~
inStringLiteral~~
Advance
elseif lineBuffer[cp] == "%" or lineBuffer[cp] == "$"
tokenType := kw#kINTLITERAL
tokenLineNumber := lineNo
tokenCol := cp
if lineBuffer[cp] == "%"
if lineBuffer[cp+1] == "%"
radix := 4
++cp
else
radix := 2
else
radix := 16
++cp
ifnot IsDigit( lineBuffer[cp], radix, false )
abort string("Bad character in number")
tokenValue~
repeat while IsDigit( lineBuffer[cp], radix, true )
if lineBuffer[cp] <> "_"
tokenValue := tokenValue * radix + DigitValue( linebuffer[cp] )
++cp
elseif IsDigit( lineBuffer[cp], 10, false )
tokenLineNumber := lineNo
tokenCol := cp
i~
fp~ {0 => integer
1 => have seen .
2 => have seen e or E
3 => have seen + or - }
repeat while IsDigit( lineBuffer[cp], 10, true ) {
} or ( fp < 1 and lineBuffer[cp] == "." and lineBuffer[cp+1] <> "." ) {
} or ( fp < 2 and (lineBuffer[cp] == "e" or lineBuffer[cp] == "E") ) {
} or ( (fp == 1 or fp == 2) and (lineBuffer[cp] == "+" or lineBuffer[cp] == "-") )
if lineBuffer[cp] == "."
fp := 1
if lineBuffer[cp] == "e" or lineBuffer[cp] == "E"
fp := 2
if lineBuffer[cp] == "+" or lineBuffer[cp] == "-"
fp := 3
if lineBuffer[cp] <> "_"
if i => MAXTOKENLENGTH
abort string("Token too long")
tokenText[i++] := lineBuffer[cp]
++cp
tokenText[i]~
if fp
tokenType := kw#kFLOATLITERAL
tokenValue := floatString.StringToFloat( @tokenText )
else
tokenType := kw#kINTLITERAL
tokenValue~
i~
repeat while tokenText[i]
tokenValue := tokenValue * 10 + DigitValue( tokenText[i++] )
elseif IsAlpha( lineBuffer[cp] )
i~
tokenLineNumber := lineNo
tokenCol := cp
repeat while IsAlpha( lineBuffer[cp] ) or IsDigit( lineBuffer[cp], 10, true )
if i => MAXTOKENLENGTH
abort string("Token too long")
tokenText[i++] := ToUpper( lineBuffer[cp++] )
tokenText[i]~
x := kw.KeywordLookup( @tokenText )
if x
tokenType := bt.PeekL( x )
if kw#kCON =< tokenType and tokenType =< kw#kVAR and tokenCol == 0
insideDAT := tokenType == kw#kDAT
else
tokenType := kw#kID
else ' non-alphanumeric
tokenLineNumber := lineNo
tokenCol := cp
i~
if lineBuffer[cp] < $20 or lineBuffer[cp] => $80
abort string("Illegal character (UNICODE?)")
if insideDat and lineBuffer[cp] == ":" and IsAlpha( lineBuffer[cp+1] )
tokenText[i++] := lineBuffer[cp++]
repeat while IsAlpha( lineBuffer[cp] ) or IsDigit( lineBuffer[cp], 10, true )
if i => MAXTOKENLENGTH
abort string("Token too long")
tokenText[i++] := ToUpper( lineBuffer[cp++] )
tokenText[i]~
tokenType := kw#kID
else
repeat
if cp < lineLength
tokenText[i++] := lineBuffer[cp++]
else
tokenText[i++] := " "
++cp
tokenText[i]~
while x := kw.KeywordLookup( @tokenText )
if i > 1
tokenText[--i]~ ' shorten token by 1
--cp
tokenType := bt.PeekL( kw.KeywordLookup( @tokenText ) )
else
tokenType := kw#kUNKNOWN
if IsBinary ' This next block is a total hack to see if a binary op
hack := blankLine ' hack is followed by "=" making it an assignment op
SkipWhitespace ' It parses "and ==" as "(and=) =" instead of "(and)(==)"
if lineBuffer[cp] == "=" ' PropTool does the latter. So this is wrong, but hopefully
tokenText[i++] := lineBuffer[cp++] ' not *too* wrong.
tokenText[i]~
tokenType |= kw#kASSIGNMENT
else
blankLine := hack ' restore (this hack is necessary to reset the eol condition trigger in SkipWhitespace)
else
tokenType := kw#kEOF
bytemove( @tokenText, string("(EOF)"), 6 )
tokenLineNumber := lineNo
tokenCol := cp
pri ToUpper( ch )
if "a" =< ch and ch =< "z"
ch += constant( "A" - "a" )
return ch
pri IsAlpha( ch )
return "a" =< ch and ch =< "z" or "A" =< ch and ch =< "Z" or ch == "_"
pri IsDigit( ch, radix, u ) | upper
{{
Returns non-zero if ch is an acceptable digit given radix (2, 4, 10, or 16), false otherwise.
Pass u = true if the underscore ("_") is an acceptable value for ch.
}}
if ch == "_"
return u
upper := constant("0"-1) + radix
if radix =< 10
return "0" =< ch and ch =< upper
' else radix == 16
return "0" =< ch and ch =< "9" or "a" =< ch and ch =< "f" or "A" =< ch and ch =< "F"
pri DigitValue( ch )
if ch =< "9"
return ch - "0"
if ch =< "F"
return ch + constant( 10 - "A" )
if ch =< "f"
return ch + constant( 10 - "a" )
pub IsBinary
{{
Returns non-zero (not necessarily -1) if token is a binary operator.
Returns 0 otherwise.
}}
return ( tokenType & constant(kw#kUNARY|kw#kBINARY) ) == kw#kBINARY
var
byte lineBuffer[BUFFERSIZE]
byte lineLength
byte lineRemainder
byte eolLength
word lineNo
byte cp
byte blankLine
byte inStringLiteral ' indicates we are splitting up a string literal
byte comma ' flag for returning commas when splitting up a string literal
pri SkipWhitespace
'' Returns true on success, false on failure (eof).
'' lineBuffer[cp] is the next non-whitespace character
'' (comments count as whitespace).
repeat
repeat while cp => lineLength
ifnot blankLine
blankLine~~
return true
ifnot ReadLine
return false
if lineBuffer[cp] == 9
abort string("Illegal TAB character")
if lineBuffer[cp] == "'" ' quote comment?
cp := lineLength ' skip to end of line
elseif lineBuffer[cp] == "}"
abort string("Unexpected '}'")
elseif lineBuffer[cp] == "{"
SkipComment
elseif lineBuffer[cp] == " "
++cp
else ' non-blank character
blankLine~
return true
pri SkipComment | depth
if cp+1 < lineLength and lineBuffer[cp+1] == "{"
++cp
repeat
repeat while cp => lineLength
ifnot ReadLine
abort string("Unterminated comment")
if cp+1 < lineLength and lineBuffer[cp] == "}" and lineBuffer[cp+1] == "}"
cp += 2
return
++cp
else
++cp
depth := 1
repeat
repeat while cp => lineLength
ifnot ReadLine
abort string("Unterminated comment")
if lineBuffer[cp] == "{"
++cp
++depth
elseif lineBuffer[cp] == "}"
++cp
ifnot --depth
return
else
++cp
pri InitReadLine
lineLength~
lineRemainder~
eolLength~
lineNo~
cp~
blankLine~~
inStringLiteral~
{
|<--------------- BUFFERSIZE --------------->|
+--------------------------------------------+
| | | | |
+--------------------------------------------+
|<-lineLength ->| | |
eolLength ->| |<- |
|<- lineRemainder ->|
}
pri ReadLine | bytes, i
'' Reads a line into lineBuff. Returns true on success, false on failure (eof)
'' The line in lineBuff is terminated with a null byte. Calling programs should
'' not modify any memory in lineBuff after the null (the "remainder" section in
'' the diagram above) because that's the following line(s).
' First, move remainder up to start of buffer
bytemove( @lineBuffer, @lineBuffer[lineLength+eolLength], lineRemainder )
' Fill the rest of the buffer with new data
bytes := f.Read( @lineBuffer[lineRemainder], BUFFERSIZE-lineRemainder )
' pread returns #bytes read, but after eof it returns negative numbers
if bytes > 0
lineRemainder += bytes
ifnot lineRemainder
++lineNo
cp~
return false
repeat i from 0 to (lineRemainder-2) #> 0
if lineBuffer[i] == 13 or lineBuffer[i] == 10
eolLength := 1 ' cr or lf
if lineBuffer[i] == 13 and lineBuffer[i+1] == 10
++eolLength ' cr+lf
lineBuffer[i]~ ' set terminating null
lineLength := i
lineRemainder -= lineLength + eolLength
++lineNo ' first line of file is line 1
cp~
return true
if lineRemainder < BUFFERSIZE
lineLength := lineRemainder~
lineBuffer[lineLength]~
++lineNo
cp~
return true
abort string("Input line too long")
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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

@ -1,272 +0,0 @@
obj
sxfs: "isxfs"
kw: "kwdefs"
bt: "bintree"
dat
long
filestuff byte 0[sxfs#SIZEOFFILESTUFF]
pub Open( pFilename )
if \sxfs.Open( @filestuff, pFilename, "R" ) <> 0
abort string("can't open file")
Advance ' prime the pump
pub Close
sxfs.Close( @filestuff )
con
MAXTOKENLENGTH = 32
dat
tokenType long 0
tokenValue long 0
tokenLineNumber word 0
tokenCol word 0
tokenText byte 0[MAXTOKENLENGTH+1]
pub Text
return @tokenText
pub Type
return tokenType
pub Column
return tokenCol
pub LineNumber
return tokenLineNumber
pub Value
return tokenValue
pub AdvanceIf( t )
{{
If current token's type is t, advance and return true;
otherwise return false without advancing.
t should be one of the specific token types, not a generic type like kCOND.
}}
if tokenType <> t
return false
Advance
return true
pub Eat( t )
{{
Like Advance, but asserts that the soon-to-be-previous token's type is t.
t should be one of the specific token types, not a generic type like kCOND.
}}
if tokenType <> t
abort string("Syntax error (unexpected)")
Advance
pub Advance
tokenType := ReadLong
tokenLineNumber := ReadWord
tokenCol := ReadWord
if tokenType == kw#kINTLITERAL or tokenType == kw#kFLOATLITERAL
sxfs.Read( @filestuff, @tokenValue, 4 )
else
ReadString( @tokenText, MAXTOKENLENGTH )
pub IsId
{{
Returns non-zero (not necessarily -1) if token is a plain old identifier.
Returns 0 otherwise.
}}
return tokenType & kw#kID
pub IsIntLiteral
{{
Returns non-zero (not necessarily -1) if token is an int literal.
Returns 0 otherwise.
}}
return tokenType & kw#kINTLITERAL
pub IsFloatLiteral
{{
Returns non-zero (not necessarily -1) if token is an float literal.
Returns 0 otherwise.
}}
return tokenType & kw#kFLOATLITERAL
pub IsUnaryOp
{{
Returns non-zero (not necessarily -1) if token is a unary operator.
Returns 0 otherwise.
}}
return tokenType & kw#kUNARY
pub IsBinaryOp
{{
Returns non-zero (not necessarily -1) if token is a binary operator.
Returns 0 otherwise.
}}
return ( tokenType & constant(kw#kUNARY|kw#kBINARY) ) == kw#kBINARY
pub IsPostfixOp
{{
Returns non-zero (not necessarily -1) if token is a postfix operator.
Returns 0 otherwise.
}}
return ( tokenType & constant(kw#kUNARY|kw#kPOSTFIX) ) == constant(kw#kUNARY|kw#kPOSTFIX)
pub IsAssignmentOp
{{
Returns non-zero (not necessarily -1) if token is an assignment operator.
Returns 0 otherwise.
}}
return tokenType & kw#kASSIGNMENT
pub GetPrecedence
{{
If token is an operator, returns its precedence.
If token isn't, returns 13.
}}
if tokenType & constant( kw#kBINARY | kw#kUNARY )
return (tokenType >> 16) & $0f
else
return 13
pub GetSpinOpcode
{{
If token is an operator or a statement function, returns its Spin opcode.
If token isn't, returns nonsense.
}}
return tokenType & $ff
pub GetSpinOpcode2
{{
If token is a postfix operator, returns its alternate Spin opcode.
If token isn't, returns nonsense.
}}
return (tokenType >> 8) & $ff
pub IsPasm
{{
Returns non-zero (not necessarily -1) if token is a PASM mnemonic.
Returns 0 otherwise.
}}
return tokenType & kw#kPASM
pub GetPasmOp
{{
If token is a PASM mnemonic, return its PASM opcode.
}}
return tokenType << 16
pub GetPasmDS
{{
If token is a PASM mnemonic, return its DS information.
}}
return (tokenType >> 16) & 3
pub IsCond
{{
Returns non-zero (not necessarily -1) if token is a PASM condition code (e.g., IF_A).
Returns 0 otherwise.
}}
return tokenType & kw#kCOND
pub GetCond
{{
Returns condition bits if token is a PASM condition code.
}}
return tokenType & $0f
pub IsEffect
{{
Returns non-zero (not necessarily -1) if token is a PASM effect (e.g., WC).
Returns 0 otherwise.
}}
return tokenType & kw#kEFFECT
pub GetEffect
{{
Returns effect bits if token is a PASM effect.
}}
return tokenType & $0f
pub IsReg
{{
Returns non-zero (not necessarily -1) if token is a special register (e.g., PHSA).
Returns 0 otherwise.
}}
return kw#kPAR =< tokenType and tokenType =< kw#kVSCL
pub GetReg
{{
Returns register# if token is a special register.
}}
return tokenType - kw#kPAR
pub IsBlockDesignator
{{
Returns true if token is a block designator (e.g., DAT).
}}
return kw#kCON =< tokenType and tokenType =< kw#kVAR
pub IsSize
{{
Returns true if token is BYTE, WORD, or LONG.
}}
return kw#kBYTE =< tokenType and tokenType =< kw#kLONG
pub IsStmtFn
{{
Returns non-zero (not necessarily -1) if token is a "statement function" (e.g. BYTEMOVE, WAITCNT).
Returns 0 otherwise.
}}
return tokenType & kw#kSTMTFN
pub GetNumArgs
{{
Returns #args if token is a "statement function".
}}
return (tokenType >> 8) & 3
pub IsIntrinsic
{{
Returns non-zero (not necessarily -1) if token is an intrinsic (e.g., COGNEW, LOOKUP).
Returns 0 otherwise.
}}
return tokenType & kw#kINTRINSIC
pri ReadString( p, MAXLENGTH ) | ch
repeat MAXLENGTH + 1
ch := ReadByte
if "a" =< ch and ch =< "z"
ch -= constant("a" - "A")
ifnot byte[p++] := ch
return
abort string("ReadString: string too long")
pri ReadByte : ch
sxfs.Read( @filestuff, @ch, 1 )
pri ReadWord
return ReadByte + (ReadByte << 8)
pri ReadLong
return ReadByte + (ReadByte << 8) + (ReadByte << 16) + (ReadByte << 24)
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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. |
+------------------------------------------------------------------------------------------------------------------------------+
}}