2 * Scout - The Amiga System Monitor
4 *------------------------------------------------------------------
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *------------------------------------------------------------------
22 * @author Andreas Gelhausen
23 * @author Richard Körber <rkoerber@gmx.de>
24 * @author Pavel Fedin <sonic_amiga@mail.ru>
27 #include "system_headers.h"
29 struct FunctionsWinData
{
30 TEXT fwd_Title
[WINDOW_TITLE_LENGTH
];
31 APTR fwd_FunctionsList
;
32 APTR fwd_FunctionsText
;
33 APTR fwd_FunctionsCount
;
34 APTR fwd_DisassembleButton
;
37 struct MUIP_FunctionsWin_ShowFunctionsMessage
{
38 STACKED ULONG MethodID
;
39 STACKED ULONG nodeType
;
44 struct FunctionsEntry
{
46 TEXT fe_AddressStr
[ADDRESS_LENGTH
];
48 TEXT fe_OffsetDec
[ADDRESS_LENGTH
];
49 TEXT fe_OffsetHex
[ADDRESS_LENGTH
];
50 TEXT fe_FuncName
[FILENAME_LENGTH
];
53 HOOKPROTONHNO(funclist_con2func
, IPTR
, struct NList_ConstructMessage
*msg
)
55 return AllocListEntry(msg
->pool
, msg
->entry
, sizeof(struct FunctionsEntry
));
57 MakeStaticHook(funclist_con2hook
, funclist_con2func
);
59 HOOKPROTONHNO(funclist_des2func
, void, struct NList_DestructMessage
*msg
)
61 FreeListEntry(msg
->pool
, &msg
->entry
);
63 MakeStaticHook(funclist_des2hook
, funclist_des2func
);
65 HOOKPROTONHNO(funclist_dsp2func
, void, struct NList_DisplayMessage
*msg
)
67 struct FunctionsEntry
*fe
= (struct FunctionsEntry
*)msg
->entry
;
70 msg
->strings
[0] = fe
->fe_OffsetDec
;
71 msg
->strings
[1] = fe
->fe_OffsetHex
;
72 msg
->strings
[2] = fe
->fe_AddressStr
;
73 msg
->strings
[3] = fe
->fe_FuncName
;
75 msg
->strings
[0] = txtOffset
;
76 msg
->strings
[1] = txtHexadecimal
;
77 msg
->strings
[2] = txtAddress
;
78 msg
->strings
[3] = txtName
;
79 msg
->preparses
[0] = (STRPTR
)MUIX_B
;
80 msg
->preparses
[1] = (STRPTR
)MUIX_B
;
81 msg
->preparses
[2] = (STRPTR
)MUIX_B
;
82 msg
->preparses
[3] = (STRPTR
)MUIX_B
;
85 MakeStaticHook(funclist_dsp2hook
, funclist_dsp2func
);
87 STATIC LONG
funclist_cmp2colfunc( struct FunctionsEntry
*fe1
,
88 struct FunctionsEntry
*fe2
,
94 case 1: return (IPTR
)fe1
->fe_Offset
- (IPTR
)fe2
->fe_Offset
;
95 case 2: return (IPTR
)fe1
->fe_Address
- (IPTR
)fe2
->fe_Address
;
96 case 3: return stricmp(fe1
->fe_FuncName
, fe2
->fe_FuncName
);
100 HOOKPROTONHNO(funclist_cmp2func
, LONG
, struct NList_CompareMessage
*msg
)
103 struct FunctionsEntry
*fe1
, *fe2
;
106 fe1
= (struct FunctionsEntry
*)msg
->entry1
;
107 fe2
= (struct FunctionsEntry
*)msg
->entry2
;
108 col1
= msg
->sort_type
& MUIV_NList_TitleMark_ColMask
;
109 col2
= msg
->sort_type2
& MUIV_NList_TitleMark2_ColMask
;
111 if ((ULONG
)msg
->sort_type
== MUIV_NList_SortType_None
) return 0;
113 if (msg
->sort_type
& MUIV_NList_TitleMark_TypeMask
) {
114 cmp
= funclist_cmp2colfunc(fe2
, fe1
, col1
);
116 cmp
= funclist_cmp2colfunc(fe1
, fe2
, col1
);
119 if (cmp
!= 0 || col1
== col2
) return cmp
;
121 if (msg
->sort_type2
& MUIV_NList_TitleMark2_TypeMask
) {
122 cmp
= funclist_cmp2colfunc(fe2
, fe1
, col2
);
124 cmp
= funclist_cmp2colfunc(fe1
, fe2
, col2
);
129 MakeStaticHook(funclist_cmp2hook
, funclist_cmp2func
);
131 STATIC IPTR
mNew( struct IClass
*cl
,
135 APTR funclist
, functext
, funccount
, disasmButton
, exitButton
;
137 if ((obj
= (Object
*)DoSuperNew(cl
, obj
,
138 MUIA_Window_ID
, MakeID('.','L','F','T'),
139 WindowContents
, VGroup
,
140 Child
, (IPTR
)MyNListviewObject(&funclist
, MakeID('F','T','L','V'), "BAR P=" MUIX_R
",BAR P=" MUIX_R
",BAR,BAR", &funclist_con2hook
, &funclist_des2hook
, &funclist_dsp2hook
, &funclist_cmp2hook
, TRUE
),
141 Child
, (IPTR
)MyBelowListview(&functext
, &funccount
),
143 Child
, (IPTR
)MyVSpace(4),
145 Child
, (IPTR
)HGroup
, MUIA_Group_SameSize
, TRUE
,
146 Child
, (IPTR
)(disasmButton
= MakeButton(txtDisassemble
)),
147 Child
, (IPTR
)(exitButton
= MakeButton(txtExit
)),
150 TAG_MORE
, msg
->ops_AttrList
)) != NULL
)
152 struct FunctionsWinData
*fwd
= INST_DATA(cl
, obj
);
155 fwd
->fwd_FunctionsList
= funclist
;
156 fwd
->fwd_FunctionsText
= functext
;
157 fwd
->fwd_FunctionsCount
= funccount
;
158 fwd
->fwd_DisassembleButton
= disasmButton
;
160 parent
= (APTR
)GetTagData(MUIA_Window_ParentWindow
, (IPTR
)NULL
, msg
->ops_AttrList
);
162 set(obj
, MUIA_Window_DefaultObject
, funclist
);
163 set(disasmButton
, MUIA_Disabled
, TRUE
);
165 DoMethod(parent
, MUIM_Window_AddChildWindow
, obj
);
166 DoMethod(obj
, MUIM_Notify
, MUIA_Window_CloseRequest
, TRUE
, MUIV_Notify_Application
, 5, MUIM_Application_PushMethod
, parent
, 2, MUIM_Window_RemChildWindow
, obj
);
167 DoMethod(funclist
, MUIM_Notify
, MUIA_NList_DoubleClick
, MUIV_EveryTime
, obj
, 1, MUIM_FunctionsWin_Disassemble
);
168 DoMethod(funclist
, MUIM_Notify
, MUIA_NList_Active
, MUIV_EveryTime
, obj
, 1, MUIM_FunctionsWin_ListChange
);
169 DoMethod(disasmButton
, MUIM_Notify
, MUIA_Pressed
, FALSE
, obj
, 1, MUIM_FunctionsWin_Disassemble
);
170 DoMethod(exitButton
, MUIM_Notify
, MUIA_Pressed
, FALSE
, obj
, 3, MUIM_Set
, MUIA_Window_CloseRequest
, TRUE
);
171 DoMethod(funclist
, MUIM_NList_Sort3
, MUIV_NList_Sort3_SortType_1
, MUIV_NList_SortTypeAdd_None
, MUIV_NList_Sort3_SortType_Both
);
177 STATIC IPTR
mDispose( struct IClass
*cl
,
181 struct FunctionsWinData
*fwd
= INST_DATA(cl
, obj
);
183 set(obj
, MUIA_Window_Open
, FALSE
);
184 DoMethod(fwd
->fwd_FunctionsList
, MUIM_NList_Clear
);
186 return (DoSuperMethodA(cl
, obj
, msg
));
189 STATIC IPTR
mShowFunctions( struct IClass
*cl
,
193 struct FunctionsWinData
*fwd
= INST_DATA(cl
, obj
);
194 struct MUIP_FunctionsWin_ShowFunctionsMessage
*sfm
= (struct MUIP_FunctionsWin_ShowFunctionsMessage
*)msg
;
196 if (sfm
->nodeType
!= MUIV_FunctionsWin_NodeType_Resource
||
197 (stricmp(sfm
->name
, FSRNAME
) != 0 &&
198 //stricmp(sfm->name, CARDRESNAME) != 0 &&
199 stricmp(sfm
->name
, KEYMAPRESNAME
) != 0)) {
201 struct FunctionsEntry
*fe
;
203 if ((fe
= tbAllocVecPooled(globalPool
, sizeof(struct FunctionsEntry
))) != NULL
) {
204 struct Library
*lib
= (struct Library
*)sfm
->base
;
206 BOOL useIdLib
= (IdentifyBase
!= NULL
);
208 max
= lib
->lib_NegSize
;
210 set(fwd
->fwd_FunctionsList
, MUIA_NList_Quiet
, TRUE
);
214 for (offset
= LIB_VECTSIZE
; offset
<= max
; offset
+= LIB_VECTSIZE
) {
216 fe
->fe_Address
= __AROS_GETVECADDR (lib
, offset
/ LIB_VECTSIZE
);
218 if (fe
->fe_Address
) {
219 if (points2ram(fe
->fe_Address
)) {
220 _snprintf(fe
->fe_AddressStr
, sizeof(fe
->fe_AddressStr
), MUIX_PH ADDRESS_FORMAT MUIX_PT
, fe
->fe_Address
);
222 _snprintf(fe
->fe_AddressStr
, sizeof(fe
->fe_AddressStr
), ADDRESS_FORMAT
, fe
->fe_Address
);
225 fe
->fe_Address
= (APTR
)-1;
226 stccpy(fe
->fe_AddressStr
, txtNoJump
, sizeof(fe
->fe_AddressStr
));
229 struct JumpEntry
*je
;
231 je
= (struct JumpEntry
*)((UBYTE
*)lib
- offset
);
234 if (je
->je_JMPInstruction
== 0x4ef9 || je
->je_JMPInstruction
== 0x4afc) {
236 if (je
->je_JMPInstruction
== 0x4ef9) {
238 fe
->fe_Address
= je
->je_JumpAddress
;
239 if (points2ram(je
->je_JumpAddress
)) {
240 _snprintf(fe
->fe_AddressStr
, sizeof(fe
->fe_AddressStr
), MUIX_PH
"$%08lx" MUIX_PT
, je
->je_JumpAddress
);
242 _snprintf(fe
->fe_AddressStr
, sizeof(fe
->fe_AddressStr
), "$%08lx", je
->je_JumpAddress
);
245 fe
->fe_Address
= (APTR
)-1;
246 stccpy(fe
->fe_AddressStr
, txtNoJump
, sizeof(fe
->fe_AddressStr
));
250 fe
->fe_Offset
= offset
;
251 _snprintf(fe
->fe_OffsetDec
, sizeof(fe
->fe_OffsetDec
), "-%ld", offset
);
252 _snprintf(fe
->fe_OffsetHex
, sizeof(fe
->fe_OffsetHex
), "-$%04lx", offset
);
254 if ((offset
<= LIB_VECTSIZE
* 6 && sfm
->nodeType
== MUIV_FunctionsWin_NodeType_Device
) ||
255 (offset
<= LIB_VECTSIZE
* 4 && sfm
->nodeType
== MUIV_FunctionsWin_NodeType_Library
)) {
259 case LIB_VECTSIZE
* 1: help
= "Open"; break;
260 case LIB_VECTSIZE
* 2: help
= "Close"; break;
261 case LIB_VECTSIZE
* 3: help
= "Expunge"; break;
262 case LIB_VECTSIZE
* 4: help
= "ExtFunc"; break;
263 case LIB_VECTSIZE
* 5: help
= "BeginIO"; break;
264 case LIB_VECTSIZE
* 6: help
= "AbortIO"; break;
265 default: help
= ""; break;
267 stccpy(fe
->fe_FuncName
, (TEXT
*)help
, sizeof(fe
->fe_FuncName
));
268 } else if (useIdLib
) {
274 /* identify.library on AROS assumes LIB_VECTSIZE of 6 */
275 id_offset
= (offset
/ LIB_VECTSIZE
) * 6;
279 if (stricmp(sfm
->name
, CIAANAME
) == 0 || stricmp(sfm
->name
, CIABNAME
) == 0) {
280 error
= IdFunctionTags((STRPTR
)"cia.resource", id_offset
,
281 IDTAG_FuncNameStr
, (IPTR
)fe
->fe_FuncName
,
282 IDTAG_StrLength
, sizeof(fe
->fe_FuncName
),
284 } else if (stricmp(sfm
->name
, CARDRESNAME
) == 0) {
285 error
= IdFunctionTags((STRPTR
)"cardres.resource", id_offset
,
286 IDTAG_FuncNameStr
, (IPTR
)fe
->fe_FuncName
,
287 IDTAG_StrLength
, sizeof(fe
->fe_FuncName
),
290 error
= IdFunctionTags(sfm
->name
, id_offset
,
291 IDTAG_FuncNameStr
, (IPTR
)fe
->fe_FuncName
,
292 IDTAG_StrLength
, sizeof(fe
->fe_FuncName
),
297 stccpy(fe
->fe_FuncName
, txtNoFDFile
, sizeof(fe
->fe_FuncName
));
301 fe
->fe_FuncName
[0] = 0x00;
306 stccpy(fe
->fe_FuncName
, txtNoFunctionEntry
, sizeof(fe
->fe_FuncName
));
310 stccpy(fe
->fe_FuncName
, txtNoFDFile
, sizeof(fe
->fe_FuncName
));
313 fe
->fe_FuncName
[0] = 0x00;
316 InsertBottomEntry(fwd
->fwd_FunctionsList
, fe
);
321 set(fwd
->fwd_FunctionsList
, MUIA_NList_Quiet
, FALSE
);
322 SetCountText(fwd
->fwd_FunctionsCount
, max
/ LIB_VECTSIZE
);
324 set(obj
, MUIA_Window_Title
, MyGetChildWindowTitle(txtFunctionsTitle
, sfm
->name
, fwd
->fwd_Title
, sizeof(fwd
->fwd_Title
)));
327 tbFreeVecPooled(globalPool
, fe
);
330 set(obj
, MUIA_Window_Open
, TRUE
);
335 STATIC IPTR
mListChange( struct IClass
*cl
,
339 struct FunctionsWinData
*fwd
= INST_DATA(cl
, obj
);
340 struct FunctionsEntry
*fe
;
342 if ((fe
= (struct FunctionsEntry
*)GetActiveEntry(fwd
->fwd_FunctionsList
)) != NULL
) {
343 if (fe
->fe_FuncName
[0] == '<') {
344 MySetContents(fwd
->fwd_FunctionsText
, "%s %s", fe
->fe_OffsetDec
, fe
->fe_FuncName
);
346 MySetContents(fwd
->fwd_FunctionsText
, "%s %s()", fe
->fe_OffsetDec
, fe
->fe_FuncName
);
348 set(fwd
->fwd_DisassembleButton
, MUIA_Disabled
, (clientstate
|| fe
->fe_Address
== (APTR
)-1 || fe
->fe_Address
== NULL
));
354 STATIC IPTR
mDisassemble( struct IClass
*cl
,
358 struct FunctionsWinData
*fwd
= INST_DATA(cl
, obj
);
359 struct FunctionsEntry
*fe
;
361 if ((fe
= (struct FunctionsEntry
*)GetActiveEntry(fwd
->fwd_FunctionsList
)) != NULL
) {
364 if ((disasmWin
= (Object
*)DisassemblerWindowObject
,
365 MUIA_Window_ParentWindow
, (IPTR
)obj
,
366 MUIA_DisassemblerWin_Address
, (IPTR
)fe
->fe_Address
,
369 DoMethod(disasmWin
, MUIM_DisassemblerWin_Disassemble
);
370 set(disasmWin
, MUIA_Window_Open
, TRUE
);
378 DISPATCHER(FunctionsWinDispatcher
)
380 switch (msg
->MethodID
) {
381 case OM_NEW
: return (mNew(cl
, obj
, (APTR
)msg
));
382 case OM_DISPOSE
: return (mDispose(cl
, obj
, (APTR
)msg
));
383 case MUIM_FunctionsWin_ShowFunctions
: return (mShowFunctions(cl
, obj
, (APTR
)msg
));
384 case MUIM_FunctionsWin_ListChange
: return (mListChange(cl
, obj
, (APTR
)msg
));
385 case MUIM_FunctionsWin_Disassemble
: return (mDisassemble(cl
, obj
, (APTR
)msg
));
388 return (DoSuperMethodA(cl
, obj
, msg
));
391 APTR
MakeFunctionsWinClass( void )
393 return MUI_CreateCustomClass(NULL
, NULL
, ParentWinClass
, sizeof(struct FunctionsWinData
), ENTRY(FunctionsWinDispatcher
));