-
Notifications
You must be signed in to change notification settings - Fork 0
/
padmap_parser.spin2
132 lines (116 loc) · 3.05 KB
/
padmap_parser.spin2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
OBJ {{
PADMAP.TXT parser library for usbnew EmuPad.
See spec here: https://github.com/Wuerfel21/usbnew/wiki/PADMAP.TXT-Format-and-the-reference-gamepad
}}
CON
MAX_BUTTONS = 10
RULE_SIZE = 4+1+MAX_BUTTONS
TAB = 9
LF = 10
CR = 13
VAR
long unget_chr,last_chr
long get_func,get_arg
'' Parse gamepad map rules
''
'' buffer_ptr: Pointer to usbnew's rule buffer
'' buffer_max: Value of EMUPAD_MAX_RULES
'' get_function: Method pointer for reading from the File.
'' MUST return -1 at end of file.
'' get_argument: Opaque argument passed to get_function (normally this is your FILE object)
'' appname: Your application name as a string pointer. ASCII letters and numbers only.
''
PUB parse(buffer_ptr,buffer_max,get_function,get_argument,appname)
unget_chr := -1
get_func := get_function
get_arg := get_argument
repeat ' Loop over rules
parse_rule(buffer_ptr,buffer_max,appname)
skip_line()
if getc() == -1 ' Check EOF
return
else
unget()
PRI {++opt(spin-relax-memory)} parse_rule(buffer_ptr,buffer_max,appname) : r | tmp, chr, i, devid, byte rule_type, byte buttons[MAX_BUTTONS]
skip_whitespace()
' Check for generic rule
if getc() == "*"
ifnot is_space(getc())
return -1 ' wrong app
rule_type := 1
else
unget()
' Check app name
repeat strsize(appname)
ifnot getc() == byte[appname++]
unget()
return -1 ' wrong app
ifnot is_space(getc())
unget()
return -1 ' wrong app
rule_type := 3
skip_whitespace()
' Parse ID
repeat 8
devid <<= 4
case chr:=getc()
"0".."9": devid += chr-"0"
"A".."F": devid += chr-"A"+10
other:
unget()
return -2 ' syntax error
' Parse buttons
i := 0
repeat
ifnot is_space(getc())
unget()
quit
skip_whitespace()
tmp := 0
repeat
case chr:=getc()
"0".."9": tmp := tmp*10 + chr-"0"
" ",TAB,-1,CR,LF,"#":
unget()
quit
other:
unget()
return -2 ' syntax error
if tmp > 255
return -2 ' syntax error
if i < MAX_BUTTONS
buttons[i++] := tmp
repeat while i < MAX_BUTTONS
buttons[i++] := 0
' Try to insert rule into buffer
repeat buffer_max
tmp := byte[buffer_ptr][4] ' rule type
if tmp == 0 || (tmp <= rule_type && long[buffer_ptr][0] == devid)
' Could use one bytemove, but flexspin bugs
long[buffer_ptr][0] := devid
byte[buffer_ptr][4] := rule_type
bytemove(buffer_ptr+5,@buttons,MAX_BUTTONS)
return rule_type
buffer_ptr += RULE_SIZE
return 0 ' Rule didn't fit
PRI is_space(chr) : r
return chr == " " || chr == TAB
PRI skip_whitespace()
repeat
ifnot is_space(getc())
unget()
return
PRI skip_line() | chr
repeat
chr := getc()
if chr < 0 || chr == CR || chr == LF
quit
PRI getc() : chr
if (chr:=unget_chr) >= 0
unget_chr := -1 ' Technically conflicts with EOF but doesn't matter
last_chr := chr
return
else
return last_chr := get_func(get_arg):1
PRI unget()
unget_chr := last_chr