This commit is contained in:
parent
2e578781e3
commit
ea7adb9397
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
||||
|
|
@ -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. ¦
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
|
@ -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. ¦
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
|
@ -1,7 +0,0 @@
|
|||
{{ Output.spin }}
|
||||
|
||||
PUB Toggle
|
||||
dira[24]~~
|
||||
repeat
|
||||
!outa[24]
|
||||
waitcnt(3_000_000 + cnt)
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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> > <A dir="ltr" href="/Home/sphinx-documentation">Documentation</A> > <A dir="ltr" href="/Home/sphinx-documentation/reference">Reference</A> >
|
||||
</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&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>
|
|
@ -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> > <A dir="ltr" href="/Home/sphinx-documentation">Documentation</A> > <A dir="ltr" href="/Home/sphinx-documentation/reference">Reference</A> >
|
||||
</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&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>
|
|
@ -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> > <A dir="ltr" href="/Home/sphinx-documentation">Documentation</A> > <A dir="ltr" href="/Home/sphinx-documentation/reference">Reference</A> >
|
||||
</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&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>
|
|
@ -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> > <A dir="ltr" href="/Home/sphinx-documentation">Documentation</A> >
|
||||
</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&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>
|
|
@ -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> > <A dir="ltr" href="/Home/sphinx-documentation">Documentation</A> > <A dir="ltr" href="/Home/sphinx-documentation/reference">Reference</A> >
|
||||
</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&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>
|
|
@ -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> > <A dir="ltr" href="/Home/sphinx-documentation">Documentation</A> >
|
||||
</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&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>
|
|
@ -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. ¦
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
|
@ -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.
|
||||
}}
|
|
@ -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. ¦
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
Binary file not shown.
|
@ -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
|
Binary file not shown.
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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]
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
Binary file not shown.
|
@ -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
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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 )
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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. ¦
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
|
@ -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
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. ¦
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
|
@ -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. ¦
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
|
@ -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.
|
||||
}}
|
|
@ -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. ¦
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
||||
|
|
@ -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. |
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
}}
|
Loading…
Reference in New Issue