Boulderdash correction (charsets ans line andings), use only one tv driver code

This commit is contained in:
Joerg Deckert 2014-05-03 18:12:00 +02:00
parent 5a2714014a
commit a292f62843
13 changed files with 3127 additions and 5599 deletions

10
make.sh
View File

@ -40,10 +40,10 @@ cp -r sounds/* ${sdsnd}
${BSTC} -L ${libpath} ${D} -b -O a source/3dmulti/3dmulti.spin ${BSTC} -L ${libpath} ${D} -b -O a source/3dmulti/3dmulti.spin
mv 3dmulti.binary "${sdtbox}/demo/3dmulti.bel" mv 3dmulti.binary "${sdtbox}/demo/3dmulti.bel"
${BSTC} -L ${libpath} ${D} -b -O a source/boulder/bellatrix/bd_pal.spin ${BSTC} -L ${libpath} ${D} -D __TV_NTSC -b -O a source/boulder/bellatrix/bd_tv.spin
${BSTC} -L ${libpath} ${D} -b -O a source/boulder/bellatrix/bd_ntsc.spin mv bd_tv.binary "${sdtbox}/boulder/bd_ntsc.bel"
mv bd_pal.binary "${sdtbox}/boulder/bd_pal.bin" ${BSTC} -L ${libpath} ${D} -D __TV_PAL -b -O a source/boulder/bellatrix/bd_tv.spin
mv bd_ntsc.binary "${sdtbox}/boulder/bd_ntsc.bin" mv bd_tv.binary "${sdtbox}/boulder/bd_pal.bel"
${BSTC} -L ${libpath} ${D} -b -O a source/boulder/regnatix/bd.spin ${BSTC} -L ${libpath} ${D} -b -O a source/boulder/regnatix/bd.spin
mv bd.binary "${sdtbox}/boulder/bd.bin" mv bd.binary "${sdtbox}/boulder/bd.bin"
cp source/boulder/musik/bd.wav "${sdtbox}/boulder/" cp source/boulder/musik/bd.wav "${sdtbox}/boulder/"
@ -58,7 +58,7 @@ ${BSTC} -L ${libpath} ${D} -b -O a source/vecdem/vecdem.spin
mv vecdem.binary "${sdtbox}/demo/vecdem.bel" mv vecdem.binary "${sdtbox}/demo/vecdem.bel"
${BSTC} -L ${libpath} ${D} -b -O a source/stracker/bellatrix/stint.spin ${BSTC} -L ${libpath} ${D} -b -O a source/stracker/bellatrix/stint.spin
cp stint.binary "${sdsnd}/hss/stint.bin" cp stint.binary "${sdsnd}/hss/stint.bel"
mv stint.binary "${sdtbox}/stracker/stint.bel" mv stint.binary "${sdtbox}/stracker/stint.bel"
${BSTC} -L ${libpath} ${D} -b -O a source/stracker/regnatix/stplay.spin ${BSTC} -L ${libpath} ${D} -b -O a source/stracker/regnatix/stplay.spin
cp stplay.binary "${sdsnd}/hss/stplay.bin" cp stplay.binary "${sdsnd}/hss/stplay.bin"

File diff suppressed because one or more lines are too long

View File

@ -1 +1,76 @@
con GP_RIGHT = %00000001 GP_LEFT = %00000010 GP_DOWN = %00000100 GP_UP = %00001000 GP_START = %00010000 GP_SELECT = %00100000 GP_B = %01000000 GP_A = %10000000 var long stack[6] long nes_bitspub start nes_bits := 0 'cognew(process, @stack)pub read 'return nes_bits return processpub process | i, bits ' set I/O ports to proper direction ' P3 = JOY_CLK (4) ' P4 = JOY_SH/LDn (5) ' P5 = JOY_DATAOUT0 (6) ' P6 = JOY_DATAOUT1 (7) ' NES Bit Encoding ' step 1: set I/Os DIRA[3] := 1 ' output DIRA[4] := 1 ' output DIRA[5] := 0 ' input DIRA[6] := 0 ' input repeat ' step 2: set clock and latch to 0 OUTA[3] := 0 ' JOY_CLK = 0 OUTA[4] := 0 ' JOY_SH/LDn = 0 'Delay(1) ' step 3: set latch to 1 OUTA[4] := 1 ' JOY_SH/LDn = 1 'Delay(1) ' step 4: set latch to 0 OUTA[4] := 0 ' JOY_SH/LDn = 0 ' step 5: read first bit of each game pad ' data is now ready to shift out ' first bit is ready ' left controller bits := INA[5] | (INA[6] << 8) ' step 7: read next 7 bits repeat i from 0 to 6 OUTA[3] := 1 ' JOY_CLK = 1 'Delay(1) OUTA[3] := 0 ' JOY_CLK = 0 bits := (bits << 1) bits := bits | INA[5] | (INA[6] << 8) 'Delay(1) ' invert bits to make positive logic and store result nes_bits := (!bits & $FFFF) return nes_bits con
GP_RIGHT = %00000001
GP_LEFT = %00000010
GP_DOWN = %00000100
GP_UP = %00001000
GP_START = %00010000
GP_SELECT = %00100000
GP_B = %01000000
GP_A = %10000000
var
long stack[6]
long nes_bits
pub start
nes_bits := 0
'cognew(process, @stack)
pub read
'return nes_bits
return process
pub process | i, bits
' set I/O ports to proper direction
' P3 = JOY_CLK (4)
' P4 = JOY_SH/LDn (5)
' P5 = JOY_DATAOUT0 (6)
' P6 = JOY_DATAOUT1 (7)
' NES Bit Encoding
' step 1: set I/Os
DIRA[3] := 1 ' output
DIRA[4] := 1 ' output
DIRA[5] := 0 ' input
DIRA[6] := 0 ' input
repeat
' step 2: set clock and latch to 0
OUTA[3] := 0 ' JOY_CLK = 0
OUTA[4] := 0 ' JOY_SH/LDn = 0
'Delay(1)
' step 3: set latch to 1
OUTA[4] := 1 ' JOY_SH/LDn = 1
'Delay(1)
' step 4: set latch to 0
OUTA[4] := 0 ' JOY_SH/LDn = 0
' step 5: read first bit of each game pad
' data is now ready to shift out
' first bit is ready
' left controller
bits := INA[5] | (INA[6] << 8)
' step 7: read next 7 bits
repeat i from 0 to 6
OUTA[3] := 1 ' JOY_CLK = 1
'Delay(1)
OUTA[3] := 0 ' JOY_CLK = 0
bits := (bits << 1)
bits := bits | INA[5] | (INA[6] << 8)
'Delay(1)
' invert bits to make positive logic and store result
nes_bits := (!bits & $FFFF)
return nes_bits

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -111,7 +111,11 @@ con
TV_NTSC = 0 TV_NTSC = 0
TV_PAL = 1 TV_PAL = 1
TV_MODE = TV_PAL ' <--- Select your TV system here -- NTSC or PAL ---<<< #ifdef __TV_NTSC
TV_MODE = TV_NTSC
#else
TV_MODE = TV_PAL
#endif
' Game controller codes ' Game controller codes
GP_RIGHT = %00000001 '(Right arrow) Move right GP_RIGHT = %00000001 '(Right arrow) Move right
@ -3809,4 +3813,4 @@ tiles word %%0_0_0_0_0_0_0_0 ' $00 space
word %%0_0_0_2_2_0_0_0 word %%0_0_0_2_2_0_0_0
word %%0_0_0_2_2_0_0_0 word %%0_0_0_2_2_0_0_0
word %%0_0_2_2_0_0_0_0 word %%0_0_2_2_0_0_0_0

View File

@ -1,23 +0,0 @@
BST Propeller Archive
Created by Brads Spin Tool Compiler v0.15.4-pre5 - Copyright 2008,2009,2010 All rights reserved
Compiled for i386 Win32 at 14:24:31 on 2010/03/10
Archive Created at 15:34:27 On 01/05/10
Included Objects :
shoot1
|
+--tv
|
+--graphics
|
+--mouse
|
+--yma_hss_v1.2
,
- shoot1.spin
- TV.spin
- Graphics.spin
- Mouse.spin
- yma_hss_v1.2.spin
,

View File

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

View File

@ -1,470 +0,0 @@
''*****************************
''* PS/2 Mouse Driver v1.1 *
''* (C) 2006 Parallax, Inc. *
''*****************************
' v1.0 - 01 May 2006 - original version
' v1.1 - 01 Jun 2006 - bound coordinates added to simplify upper objects
VAR
long cog
long oldx, oldy, oldz 'must be followed by parameters (10 contiguous longs)
long par_x 'absolute x read-only (7 contiguous longs)
long par_y 'absolute y read-only
long par_z 'absolute z read-only
long par_buttons 'button states read-only
long par_present 'mouse present read-only
long par_dpin 'data pin write-only
long par_cpin 'clock pin write-only
long bx_min, by_min, bz_min 'min/max must be contiguous
long bx_max, by_max, bz_max
long bx_div, by_div, bz_div
long bx_acc, by_acc, bz_acc
PUB start(dpin, cpin) : okay
'' Start mouse driver - starts a cog
'' returns false if no cog available
''
'' dpin = data signal on PS/2 jack
'' cpin = clock signal on PS/2 jack
''
'' use 100-ohm resistors between pins and jack
'' use 10K-ohm resistors to pull jack-side signals to VDD
'' connect jack-power to 5V, jack-gnd to VSS
stop
par_dpin := dpin
par_cpin := cpin
okay := cog := cognew(@entry, @par_x) + 1
PUB stop
'' Stop mouse driver - frees a cog
if cog
cogstop(cog~ - 1)
longfill(@oldx, 0, 10)
PUB present : type
'' Check if mouse present - valid ~2s after start
'' returns mouse type:
''
'' 3 = five-button scrollwheel mouse
'' 2 = three-button scrollwheel mouse
'' 1 = two-button or three-button mouse
'' 0 = no mouse connected
type := par_present
PUB button(b) : state
'' Get the state of a particular button
'' returns t|f
state := -(par_buttons >> b & 1)
PUB buttons : states
'' Get the states of all buttons
'' returns buttons:
''
'' bit4 = right-side button
'' bit3 = left-side button
'' bit2 = center/scrollwheel button
'' bit1 = right button
'' bit0 = left button
states := par_buttons
PUB abs_x : x
'' Get absolute-x
x := par_x
PUB abs_y : y
'' Get absolute-y
y := par_y
PUB abs_z : z
'' Get absolute-z (scrollwheel)
z := par_z
PUB delta_reset
'' Reset deltas
oldx := par_x
oldy := par_y
oldz := par_z
PUB delta_x : x | newx
'' Get delta-x
newx := par_x
x := newx - oldx
oldx := newx
PUB delta_y : y | newy
'' Get delta-y
newy := par_y
y := newy - oldy
oldy := newy
PUB delta_z : z | newz
'' Get delta-z (scrollwheel)
newz := par_z
z := newz - oldz
oldz := newz
PUB bound_limits(xmin, ymin, zmin, xmax, ymax, zmax) | i
'' Set bounding limits
longmove(@bx_min, @xmin, 6)
PUB bound_scales(x_scale, y_scale, z_scale)
'' Set bounding scales (usually +/-1's, bigger values divide)
longmove(@bx_div, @x_scale, 3)
PUB bound_preset(x, y, z) | i, d
'' Preset bound coordinates
repeat i from 0 to 2
d := ||bx_div[i]
bx_acc[i] := (x[i] - bx_min[i]) * d + d >> 1
PUB bound_x : x
'' Get bound-x
x := bound(0, delta_x)
PUB bound_y : y
'' Get bound-y
y := bound(1, delta_y)
PUB bound_z : z
'' Get bound-z
z := bound(2, delta_z)
PRI bound(i, delta) : b | d
d := bx_div[i]
b := bx_min[i] + (bx_acc[i] := bx_acc[i] + delta * (d < 0) | 1 #> 0 <# (bx_max[i] - bx_min[i] + 1) * ||d - 1) / ||d
DAT
'***************************************
'* Assembly language PS/2 mouse driver *
'***************************************
org
'
'
' Entry
'
entry mov p,par 'load input parameters:
add p,#5*4 '_dpin/_cpin
rdlong _dpin,p
add p,#4
rdlong _cpin,p
mov dmask,#1 'set pin masks
shl dmask,_dpin
mov cmask,#1
shl cmask,_cpin
test _dpin,#$20 wc 'modify port registers within code
muxc _d1,dlsb
muxc _d2,dlsb
muxc _d3,#1
muxc _d4,#1
test _cpin,#$20 wc
muxc _c1,dlsb
muxc _c2,dlsb
muxc _c3,#1
movd :par,#_x 'reset output parameters:
mov p,#5 '_x/_y/_z/_buttons/_present
:par mov 0,#0
add :par,dlsb
djnz p,#:par
'
'
' Reset mouse
'
reset mov dira,#0 'reset directions
mov dirb,#0
mov stat,#1 'set reset flag
'
'
' Update parameters
'
update movd :par,#_x 'update output parameters:
mov p,par '_x/_y/_z/_buttons/_present
mov q,#5
:par wrlong 0,p
add :par,dlsb
add p,#4
djnz q,#:par
test stat,#1 wc 'if reset flag, transmit reset command
if_c mov data,#$FF
if_c call #transmit
'
'
' Get data packet
'
mov stat,#0 'reset state
call #receive 'receive first byte
cmp data,#$AA wz 'powerup/reset?
if_z jmp #init
mov _buttons,data 'data packet, save buttons
call #receive 'receive second byte
test _buttons,#$10 wc 'adjust _x
muxc data,signext
add _x,data
call #receive 'receive third byte
test _buttons,#$20 wc 'adjust _y
muxc data,signext
add _y,data
and _buttons,#%111 'trim buttons
cmp _present,#2 wc 'if not scrollwheel mouse, update parameters
if_c jmp #update
call #receive 'scrollwheel mouse, receive fourth byte
cmp _present,#3 wz 'if 5-button mouse, handle two extra buttons
if_z test data,#$10 wc
if_z_and_c or _buttons,#%01000
if_z test data,#$20 wc
if_z_and_c or _buttons,#%10000
shl data,#28 'adjust _z
sar data,#28
sub _z,data
jmp #update 'update parameters
'
'
' Initialize mouse
'
init call #receive '$AA received, receive id
movs crate,#100 'try to enable 3-button scrollwheel type
call #checktype
movs crate,#200 'try to enable 5-button scrollwheel type
call #checktype
shr data,#1 'if neither, 3-button type
add data,#1
mov _present,data
movs srate,#200 'set 200 samples per second
call #setrate
mov data,#$F4 'enable data reporting
call #transmit
jmp #update
'
'
' Check mouse type
'
checktype movs srate,#200 'perform "knock" sequence to enable
call #setrate '..scrollwheel and extra buttons
crate movs srate,#200/100
call #setrate
movs srate,#80
call #setrate
mov data,#$F2 'read type
call #transmit
call #receive
checktype_ret ret
'
'
' Set sample rate
'
setrate mov data,#$F3
call #transmit
srate mov data,#0
call #transmit
setrate_ret ret
'
'
' Transmit byte to mouse
'
transmit
_c1 or dira,cmask 'pull clock low
movs napshr,#13 'hold clock for ~128us (must be >100us)
call #nap
_d1 or dira,dmask 'pull data low
movs napshr,#18 'hold data for ~4us
call #nap
_c2 xor dira,cmask 'release clock
test data,#$0FF wc 'append parity and stop bits to byte
muxnc data,#$100
or data,dlsb
mov p,#10 'ready 10 bits
transmit_bit call #wait_c0 'wait until clock low
shr data,#1 wc 'output data bit
_d2 muxnc dira,dmask
mov wcond,c1 'wait until clock high
call #wait
djnz p,#transmit_bit 'another bit?
mov wcond,c0d0 'wait until clock and data low
call #wait
mov wcond,c1d1 'wait until clock and data high
call #wait
call #receive_ack 'receive ack byte with timed wait
cmp data,#$FA wz 'if ack error, reset mouse
if_nz jmp #reset
transmit_ret ret
'
'
' Receive byte from mouse
'
receive test _cpin,#$20 wc 'wait indefinitely for initial clock low
waitpne cmask,cmask
receive_ack
mov p,#11 'ready 11 bits
receive_bit call #wait_c0 'wait until clock low
movs napshr,#16 'pause ~16us
call #nap
_d3 test dmask,ina wc 'input data bit
rcr data,#1
mov wcond,c1 'wait until clock high
call #wait
djnz p,#receive_bit 'another bit?
shr data,#22 'align byte
test data,#$1FF wc 'if parity error, reset mouse
if_nc jmp #reset
and data,#$FF 'isolate byte
receive_ack_ret
receive_ret ret
'
'
' Wait for clock/data to be in required state(s)
'
wait_c0 mov wcond,c0 '(wait until clock low)
wait mov q,tenms 'set timeout to 10ms
wloop movs napshr,#18 'nap ~4us
call #nap
_c3 test cmask,ina wc 'check required state(s)
_d4 test dmask,ina wz 'loop until got state(s) or timeout
wcond if_never djnz q,#wloop '(replaced with c0/c1/c0d0/c1d1)
tjz q,#reset 'if timeout, reset mouse
wait_ret
wait_c0_ret ret
c0 if_c djnz q,#wloop '(if_never replacements)
c1 if_nc djnz q,#wloop
c0d0 if_c_or_nz djnz q,#wloop
c1d1 if_nc_or_z djnz q,#wloop
'
'
' Nap
'
nap rdlong t,#0 'get clkfreq
napshr shr t,#18/16/13 'shr scales time
min t,#3 'ensure waitcnt won't snag
add t,cnt 'add cnt to time
waitcnt t,#0 'wait until time elapses (nap)
nap_ret ret
'
'
' Initialized data
'
dlsb long 1 << 9
tenms long 10_000 / 4
signext long $FFFFFF00
'
'
' Uninitialized data
'
dmask res 1
cmask res 1
stat res 1
data res 1
p res 1
q res 1
t res 1
_x res 1 'write-only
_y res 1 'write-only
_z res 1 'write-only
_buttons res 1 'write-only
_present res 1 'write-only
_dpin res 1 'read-only
_cpin res 1 'read-only

View File

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