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
133
134
|
.importzp sreg, ptr1, ptr2
.import popptr1, popax
.import _msg_text
.export _streq, _streq_i, _strneq_i, _lcase, _find_nick
; extern __fastcall__ char lcase(char c);
; extern __fastcall__ char streq(char *s1, char *s2);
; extern __fastcall__ char streq_i(char *s1, char *s2);
; extern __fastcall__ char strneq_i(char *s1, char *s2, char len);
; extern __fastcall__ char find_nick(void);
; these are fast and small replacements for standard C library functions.
; lcase() is a drop-in replacement for tolower().
; streq() is basically strcmp() except it returns true for equality,
; false for inequality (so you can't e.g. use it for sorting).
; also, it only supports strings up to 256 bytes long.
; streq_i() is the case-insensitive verson of streq().
; strneq_i() is case-insensitive and stops after 'len' characters.
; find_nick() does a case-insensitive search of msg_text for
; config.nick. returns 1 if found, 0 if not. NOTE: only searches the
; first 256 bytes of msg_text! this is a minor infelicity, but people
; rarely type that much text in one message...
limit = sreg+3 ; number of characters to compare (0 = 256)
insens = sreg ; bit 7 set = case insensitive, otherwise not
temp = sreg+1 ; nothing to see here, move along :)
temp2 = sreg+2
NICK = $0480 ; aka config.nick
_lcase:
cmp #'Z'+1
bcs lcret
cmp #'A'
bcc lcret
ora #$20
lcret:
rts
_strneq_i:
sta limit
jsr popax
ldy #$80
sty insens
jmp doit
_streq_i:
ldy #$80
.byte $2c ; BIT abs, skip next
_streq:
ldy #0
sty insens
ldy #0
sty limit
doit:
sta ptr2
stx ptr2+1
jsr popptr1 ; returns with Y=0
cmploop:
lda (ptr2),y
bit insens
bpl no_case_1
jsr _lcase
no_case_1:
sta temp
lda (ptr1),y
tax
bit insens
bpl no_case_2
jsr _lcase
no_case_2:
sec
sbc temp
bne ret0
txa
beq ret1
iny
cpy limit
bne cmploop
ret1:
lda #1
.byte $2c
ret0:
lda #0
tax
rts
_find_nick:
lda _msg_text
sta ptr1
lda _msg_text+1
sta ptr1+1
ldy #0
; loop over _msg_text, looking for the first character of NICK,
; but convert both to lowercase before comparing.
@l:
lda (ptr1),y
beq ret0 ; if we hit the end of _msg_text, we're done, no match.
jsr _lcase
sta temp ; temp = lcase(A)
lda NICK ; compare to lcase(NICK[0])
jsr _lcase
cmp temp
beq @found1 ; found a match for the first char, see if the rest matches.
@next:
iny
bne @l
beq ret0
@found1: ; found a case-insensitive match for the first char of NICL...
sty temp2 ; save Y so we can pick back up in the @l loop if this isn't a match.
iny ; start with _msg_text char after the initial match.
ldx #1 ; start with 2nd char of NICK
@l2:
lda (ptr1),y
jsr _lcase
sta temp
lda NICK,x
beq ret1 ; if we hit the null terminator of NICK, we have a successful match!
jsr _lcase
cmp temp
bne @nope ; no match, get out of @l2
iny
inx
bne @l2 ; matched a char, look at the next
@nope:
ldy temp2 ; restore Y
jmp @next ; jump to the bottom of the @l loop.
|