2 ; ca65 Macro-Pack for Self Modifying Code (SMC)
\r
4 ; (c) Christian Krüger, latest change: 09-Nov-2011
\r
6 ; This software is provided 'as-is', without any expressed or implied
\r
7 ; warranty. In no event will the authors be held liable for any damages
\r
8 ; arising from the use of this software.
\r
10 ; Permission is granted to anyone to use this software for any purpose,
\r
11 ; including commercial applications, and to alter it and redistribute it
\r
12 ; freely, subject to the following restrictions:
\r
14 ; 1. The origin of this software must not be misrepresented; you must not
\r
15 ; claim that you wrote the original software. If you use this software
\r
16 ; in a product, an acknowledgment in the product documentation would be
\r
17 ; appreciated but is not required.
\r
18 ; 2. Altered source versions must be plainly marked as such, and must not
\r
19 ; be misrepresented as being the original software.
\r
20 ; 3. This notice may not be removed or altered from any source
\r
24 .define _SMCDesignator .mid(0, .tcount(label) - 1, label) .ident(.concat(.string(.right(1, label)), "_SMC"))
\r
25 .define _SMCAlias .mid(0, .tcount(alias) - 1, alias) .ident(.concat(.string(.right(1, alias)), "_SMC"))
\r
26 .define SMC_AbsAdr $FADE
\r
27 .define SMC_ZpAdr $00
\r
28 .define SMC_Opcode nop
\r
29 .define SMC_Value $42
\r
31 .macro SMC_OperateOnValue opcode, label
\r
32 opcode _SMCDesignator+1
\r
35 .macro SMC_OperateOnLowByte opcode, label
\r
36 SMC_OperateOnValue opcode, label
\r
39 .macro SMC_OperateOnHighByte opcode, label
\r
40 opcode _SMCDesignator + 2
\r
43 .macro SMC_Import alias
\r
47 .macro SMC_Export alias, label
\r
48 .export _SMCAlias := _SMCDesignator
\r
51 .macro SMC label, statement
\r
52 _SMCDesignator: statement
\r
55 .macro SMC_TransferOpcode label, opcode, register
\r
56 .if .paramcount = 2 .or .match ({register}, a)
\r
59 .elseif .match ({register}, x)
\r
62 .elseif .match ({register}, y)
\r
68 .macro SMC_LoadOpcode label, register
\r
69 .if .paramcount = 1 .or .match ({register}, a)
\r
71 .elseif .match ({register}, x)
\r
73 .elseif .match ({register}, y)
\r
78 .macro SMC_StoreOpcode label, register
\r
79 .if .paramcount = 1 .or .match ({register}, a)
\r
81 .elseif .match ({register}, x)
\r
83 .elseif .match ({register}, y)
\r
88 .macro SMC_ChangeBranch label, destination, register
\r
89 .if .paramcount = 2 .or .match ({register}, a)
\r
90 lda #(destination - _SMCDesignator -2)
\r
91 sta _SMCDesignator+1
\r
92 .elseif .match ({register}, x)
\r
93 ldx #(destination - _SMCDesignator - 2)
\r
94 stx _SMCDesignator+1
\r
95 .elseif .match ({register}, y)
\r
96 ldy #(destination - _SMCDesignator - 2)
\r
97 sty _SMCDesignator+1
\r
101 .macro SMC_TransferValue label, value, register
\r
102 .if .paramcount = 2 .or .match ({register}, a)
\r
104 sta _SMCDesignator+1
\r
105 .elseif .match ({register}, x)
\r
107 stx _SMCDesignator+1
\r
108 .elseif .match ({register}, y)
\r
110 sty _SMCDesignator+1
\r
114 .macro SMC_LoadValue label, register
\r
115 .if .paramcount = 1 .or .match ({register}, a)
\r
116 lda _SMCDesignator+1
\r
117 .elseif .match ({register}, x)
\r
118 ldx _SMCDesignator+1
\r
119 .elseif .match ({register}, y)
\r
120 ldy _SMCDesignator+1
\r
124 .macro SMC_StoreValue label, register
\r
125 .if .paramcount = 1 .or .match ({register}, a)
\r
126 sta _SMCDesignator+1
\r
127 .elseif .match ({register}, x)
\r
128 stx _SMCDesignator+1
\r
129 .elseif .match ({register}, y)
\r
130 sty _SMCDesignator+1
\r
135 .macro SMC_TransferLowByte label, value, register
\r
136 SMC_TransferValue label, value, register
\r
139 .macro SMC_LoadLowByte label, register
\r
140 SMC_LoadValue label, register
\r
143 .macro SMC_StoreLowByte label, register
\r
144 SMC_StoreValue label, register
\r
147 .macro SMC_TransferHighByte label, value, register
\r
148 .if .paramcount = 2 .or .match ({register}, a)
\r
150 sta _SMCDesignator+2
\r
151 .elseif .match ({register}, x)
\r
153 stx _SMCDesignator+2
\r
154 .elseif .match ({register}, y)
\r
156 sty _SMCDesignator+2
\r
160 .macro SMC_LoadHighByte label, register
\r
161 .if .paramcount = 1 .or .match ({register}, a)
\r
162 lda _SMCDesignator+2
\r
163 .elseif .match ({register}, x)
\r
164 ldx _SMCDesignator+2
\r
165 .elseif .match ({register}, y)
\r
166 ldy _SMCDesignator+2
\r
170 .macro SMC_StoreHighByte label, register
\r
171 .if .paramcount = 1 .or .match ({register}, a)
\r
172 sta _SMCDesignator+2
\r
173 .elseif .match ({register}, x)
\r
174 stx _SMCDesignator+2
\r
175 .elseif .match ({register}, y)
\r
176 sty _SMCDesignator+2
\r
180 .macro SMC_TransferAddressSingle label, address, register
\r
181 .if .paramcount = 2 .or .match ((register), a)
\r
182 .if (.match (.left (1, {address}), #))
\r
184 lda #<(.right (.tcount ({address})-1, {address}))
\r
185 sta _SMCDesignator+1
\r
186 lda #>(.right (.tcount ({address})-1, {address}))
\r
187 sta _SMCDesignator+2
\r
189 ; assume absolute or zero page
\r
191 sta _SMCDesignator+1
\r
193 sta _SMCDesignator+2
\r
195 .elseif .match ((register), x)
\r
196 .if (.match (.left (1, {address}), #))
\r
198 ldx #<(.right (.tcount ({address})-1, {address}))
\r
199 stx _SMCDesignator+1
\r
200 ldx #>(.right (.tcount ({address})-1, {address}))
\r
201 stx _SMCDesignator+2
\r
203 ; assume absolute or zero page
\r
205 stx _SMCDesignator+1
\r
207 stx _SMCDesignator+2
\r
209 .elseif .match ((register), y)
\r
210 .if (.match (.left (1, {address}), #))
\r
212 ldy #<(.right (.tcount ({address})-1, {address}))
\r
213 sty _SMCDesignator+1
\r
214 ldy #>(.right (.tcount ({address})-1, {address}))
\r
215 sty _SMCDesignator+2
\r
217 ; assume absolute or zero page
\r
219 sty _SMCDesignator+1
\r
221 sty _SMCDesignator+2
\r
226 .macro SMC_TransferAddress label, address
\r
227 .if (.match (.left (1, {address}), #))
\r
229 lda #<(.right (.tcount ({address})-1, {address}))
\r
230 sta _SMCDesignator+1
\r
231 ldx #>(.right (.tcount ({address})-1, {address}))
\r
232 stx _SMCDesignator+2
\r
234 ; assume absolute or zero page
\r
236 sta _SMCDesignator+1
\r
238 stx _SMCDesignator)+2
\r
242 .macro SMC_StoreAddress label
\r
243 sta _SMCDesignator+1
\r
244 stx _SMCDesignator+2
\r