1 // BOCHS ENHANCED DEBUGGER Ver 1.0
2 // (C) Chourdakis Michael, 2008
3 // http://www.turboirc.com
5 // Modified by Bruce Ewing
10 #include "win32dialog.h"
11 #include "wenhdbg_h.h"
15 extern HWND hDebugDialog
;
16 extern char *debug_cmd
;
17 extern BOOL debug_cmd_ready
;
19 INT_PTR CALLBACK
A_DP(HWND hh2
,UINT mm
,WPARAM ww
,LPARAM ll
)
21 static ASKTEXT
* as
= 0;
26 SetWindowText(hh2
,as
->ti
);
27 SetWindowText(GetDlgItem(hh2
,101),as
->as
);
28 SetWindowText(GetDlgItem(hh2
,102),as
->re
);
30 SetTimer(hh2
,1,as
->DefT
*1000,0);
33 PostMessage(hh2
,WM_COMMAND
,IDOK
,0);
37 if (HIWORD(ww
) == EN_UPDATE
)
40 if (LOWORD(ww
) == IDOK
)
42 GetWindowText(GetDlgItem(hh2
,102),as
->re
,100);
46 if (LOWORD(ww
) == IDCANCEL
)
48 EndDialog(hh2
,IDCANCEL
);
55 bx_bool
AskText(HWND hh
,const TCHAR
* ti
,TCHAR
* as
,TCHAR
* re
,int DefT
)
57 ASKTEXT a
= {ti
,as
,re
,DefT
};
59 // The dialog box needs a caret, and will destroy the one in hE_I.
60 // So destroy it myself, cleanly, and let it be recreated cleanly.
61 CallWindowProc(*wEdit
, hE_I
,WM_KILLFOCUS
,(WPARAM
) 0,0);
62 if (DialogBoxParam(GetModuleHandle(0),"DIALOG_AT",hh
,A_DP
,(LPARAM
)&a
) == IDOK
)
64 // recreate the caret in the Input window
65 CallWindowProc(*wEdit
, hE_I
,WM_SETFOCUS
,(WPARAM
) 0,0);
66 SetFocus(hE_O
); // kludge to finish taking focus away from dialog box
74 #define MATCH_ABORT -1
77 #define OPTIMIZE_JUST_STAR
84 while (--i
>= 0) // make an upper case translation table
85 UCtable
[i
]= toupper(i
);
86 p
= AsciiHex
; // then also make a "hex" table
87 for ( i
= 0; i
< 256; i
++)
91 c
+= 'A' - 10; // do all hex in uppercase
104 int DoMatch(const char *text
, const char *p
, bx_bool IsCaseSensitive
)
106 // probably the MOST DIFFICULT FUNCTION in TurboIRC
107 // Thanks to BitchX for copying this function
114 for (; p
[pP
] != '\0'; pP
++, pT
++)
116 if (text
[pT
] == '\0' && p
[pP
] != '*')
120 // case '\\': // Match with following char
125 if (IsCaseSensitive
!= FALSE
)
127 if (text
[pT
] != p
[pP
])
132 // if (toupper(text[pT]) != toupper(p[pP]))
133 if (UCtable
[(int) text
[pT
]] != UCtable
[(int) p
[pP
]])
145 while (text
[pT
] != FALSE
)
147 matched
= DoMatch(text
+ pT
++, p
+ pP
, FALSE
);
148 if (matched
!= MATCH_FALSE
)
155 return (text
[pT
] == '\0');
158 // This will be called from the other funcs
159 int VMatching(const char *text
, const char *p
, bx_bool IsCaseSensitive
)
161 #ifdef OPTIMIZE_JUST_STAR
162 if (p
[0] == '*' && p
[1] == '\0')
165 return (DoMatch(text
, p
, IsCaseSensitive
) == MATCH_TRUE
);
168 int IsMatching(const char *text
, const char *p
, bx_bool IsCaseSensitive
)
170 return VMatching(text
, p
, IsCaseSensitive
);
173 // utility function for list resizing operation -- set LoX and HiX
174 // the resize operation exits if the mouse moves beyond LoX or HiX
175 void SetHorzLimits(int i
)
177 if (i
< BarScrx
[0] + 10) // is it the left or right bar?
179 Resize_LoX
= OneCharWide
<< 2; // set horizontal limits
180 i
= ListWidthPix
[(DockOrder
>> 8) -1]; // col1 width
181 // calculate end of col2 - 4 charwidths in parent coordinates
182 Resize_HiX
= i
+ ListWidthPix
[CurCenterList
] - (OneCharWide
<< 2);
185 else if (i
> BarScrx
[1] - 10)
187 i
= ListWidthPix
[(DockOrder
>> 8) -1]; // col1 width
188 Resize_LoX
= i
+ (OneCharWide
<< 2); // set horizontal limits
189 // calculate total width - 4 charwidths in parent coordinates
190 i
= ListWidthPix
[0] + ListWidthPix
[1] + ListWidthPix
[2];
191 Resize_HiX
= i
- (OneCharWide
<< 2);
194 SetCursor(hCursResize
);
197 void DockResize (HWND hh
, LPARAM ll
) // ll is a child coordinate mouse-style Lparam
199 int i
= 2; // assume either data or tree window is destination
200 void MoveLists(HWND
);
202 i
= 0; // i = ListView destination index
203 else if (hh
== hL
[1])
206 if (Sizing
>= 10) // dock operation
208 Sizing
-= 10; // calculate which list initiated dock = moving window
209 if (Sizing
!= i
) // moving window = destination window is a no-op
211 // Convert Sizing and i into a table lookup index (j)
212 // -- otherwise, the "algorithm" to compute new DockOrder is annoying
213 int j
= (Sizing
*2 + ((Sizing
| i
) & 1)) *6;
215 j
= (Sizing
*4 + (i
& 2)) *3;
217 // convert current DockOrder to a number from 0 to 5, add to j
218 j
+= ((DockOrder
>> 7) - 2) &6;
219 if (((DockOrder
>> 4) &3) > (DockOrder
& 3))
221 DockOrder
= nDock
[j
];
226 else // resize operation
232 ClientToScreen(hh
,&pt
);
233 ScreenToClient(hY
,&pt
); // convert to parent's coordinates
236 idx
= (DockOrder
>> 8) -1; // sizing the left bar
237 totpix
= ListWidthPix
[idx
] + ListWidthPix
[CurCenterList
];
238 ListWidthPix
[idx
] = pt
.x
;
239 ListWidthPix
[CurCenterList
] = totpix
- pt
.x
; // reset the widths of the left and center windows
243 pt
.x
-= ListWidthPix
[(DockOrder
>> 8) -1]; // caclulate new width of center window
244 idx
= (DockOrder
& 3) -1;
245 totpix
= ListWidthPix
[idx
] + ListWidthPix
[CurCenterList
];
246 ListWidthPix
[CurCenterList
] = pt
.x
;
247 ListWidthPix
[idx
] = totpix
- pt
.x
; // reset the widths of the right and center windows
254 // Subclass the edit controls
255 LRESULT CALLBACK
ThisEditProc(HWND hh
, UINT mm
, WPARAM ww
, LPARAM ll
)
258 if (hh
== hE_O
) i
= 1; // easy way to detect which edit window
262 // turn off any sizing operation if the cursor strays off the listviews
264 // also turn off any half-completed mouseclicks
267 case WM_SETFOCUS
: // force the Input window to always have the caret
268 return 0; // SETFOCUS/KILLFOCUS commands are sent directly to the hE_I defProc
271 case WM_SHOWWINDOW
: // Note: This doesn't work ... on an unhide, it didn't even GET this message!
272 if (ww
== 0) // fall through to SetFocus on Output when Input window is "shown"
275 SetFocus(hE_O
); // this does more than just send a SETFOCUS message ...
279 // throw away all Enter keys (bell problems)
282 // force all typed input to the Input window (wEdit[0] = Input)
283 CallWindowProc((WNDPROC
) *wEdit
, hE_I
, mm
, ww
, ll
);
287 // simply let parent know about all keys hit in these edit boxes
288 SendMessage(GetParent(hh
),mm
,ww
,ll
);
289 // the following keys cause annoying "bells" if sent on to the Original proc
290 // -- so throw them away (return 0)
291 if (ww
== VK_RETURN
|| ww
== VK_DOWN
|| ww
== VK_UP
)
294 if (wEdit
[i
] != NULL
)
295 return (CallWindowProc(wEdit
[i
], hh
, mm
, ww
, ll
));
300 // Subclass all the button controls together
301 LRESULT CALLBACK
BtnProc(HWND hh
, UINT mm
, WPARAM ww
, LPARAM ll
)
306 // turn off any sizing operation if the cursor strays off the listviews
308 // also turn off any half-completed mouseclicks
312 // throw away any Enter keys (potential bell problems?)
315 // force any typed input to the Input window
316 CallWindowProc((WNDPROC
) *wEdit
, hE_I
, mm
, ww
, ll
);
320 // pass to parent any keys
321 SendMessage(GetParent(hh
),mm
,ww
,ll
);
322 if (ww
== ' ') // space chars cause buttons to activate
325 return (CallWindowProc(wBtn
, hh
, mm
, ww
, ll
));
328 // the subclassed tree-view uses the same handler that the listview does
329 // subclass all the listviews at once
330 // Note: the Sizing varaible keeps track of whether the program is in resize or dock mode, and
331 // which windows are involved. It's complicated. If you don't like how I use the variable, tough.
332 LRESULT CALLBACK
LVProc(HWND hh
, UINT mm
, WPARAM ww
, LPARAM ll
)
339 // throw away all Enter keys (or use them for something)
340 if (ww
!= VK_RETURN
&& *wEdit
!= NULL
)
341 // force all typed input to the Input window
342 CallWindowProc(*wEdit
, hE_I
, mm
, ww
, ll
);
345 case WM_MOUSEMOVE
: // need to play with the cursor during resize/dock operations
347 pt
.x
= LOWORD(ll
); // get the listview client's X coord of the mouse
348 if (xClick
>= 0) // saw a lbutton mousedown recently? (pre-dock mode)
350 // cancel an impending "click" and go to dock (drag) mode if mouse is moving too much
351 i
= (OneCharWide
>> 1);
352 if (pt
.x
> xClick
+ i
|| pt
.x
< xClick
- i
)
354 else if (pt
.y
> yClick
+ i
|| pt
.y
< yClick
- i
)
356 // go into dock mode (without canceling the click) on a .5s time delay
357 i
= CurTimeStamp
+ 500;
358 if (xClick
< 0 || GetMessageTime() > i
) // Start a "dock" operation?
359 Sizing
= SizeList
; // Sizing tells which ListView is being moved
361 // if "drag" did not turn off, then I will get only one mousemove, with VK_LBUTTON showing UP
362 i
= GetKeyState(VK_LBUTTON
);
363 if (i
>= 0 && Sizing
!= 0)
368 ClientToScreen(hh
,&pt
);
369 ScreenToClient(hY
,&pt
); // convert to parent's coordinates
370 i
= GetKeyState(VK_LBUTTON
);
371 // verify horizontal limits of the current resize or dock operation
372 if (pt
.x
> Resize_HiX
|| pt
.x
< Resize_LoX
)
374 else if (i
>= 0 && Sizing
> 0)
377 SetCursor(hCursDock
);
379 SetCursor(hCursResize
);
383 case WM_NCMOUSEMOVE
: // more cursor games
386 if (ww
== HTBORDER
) // mouse is hovering or dragging over a resize bar or border
388 i
= LOWORD(ll
); // get the screen X coord of the mouse
389 if (i
< BarScrx
[0] + 10) // is it the left or right bar?
391 else if (i
> BarScrx
[1] - 10)
393 Resize_LoX
= BarClix
[Sizing
+ 2] - OneCharWide
; // set horizontal limits
394 Resize_HiX
= BarClix
[Sizing
+ 2] + OneCharWide
;
397 if (Sizing
>= 10) // docking operation?
398 SetCursor(hCursDock
);
399 else if (Sizing
!= 0)
402 pt
.x
= LOWORD(ll
); // get the screen X coord of the mouse
403 ScreenToClient(hY
,&pt
); // convert to parent's coordinates
404 // verify horizontal limits of the current resize operation
405 if (pt
.x
> Resize_HiX
|| pt
.x
< Resize_LoX
)
408 SetCursor(hCursResize
);
412 case WM_NCLBUTTONDOWN
:
413 if (Sizing
< 0) // doing a resize?
414 SetHorzLimits((int) LOWORD(ll
)); // NC messages are in Screen coordinates
415 SetFocus(hE_O
); // helps to make keystrokes go to Input window
419 Sizing
= 0; // a mouseup on a border can't be interpreted -- cancel everything
424 if (Sizing
< 0) // doing a resize?
426 GetCursorPos(&pt
); // Screen coordinates
427 SetHorzLimits((int) pt
.x
);
429 else // set "pre-dock" mode
432 SizeList
= 10; // remember which list to dock
433 else if (hh
== hL
[1])
437 Resize_LoX
= OneCharWide
<< 2; // set horizontal limits
438 i
= ListWidthPix
[0] + ListWidthPix
[1] + ListWidthPix
[2];
439 Resize_HiX
= i
- (OneCharWide
<< 2);
440 CurTimeStamp
= GetMessageTime();
444 SetFocus(hE_O
); // helps to make keystrokes go to Input window
445 // prevent default drag operations by returning 0
446 // unfortunately, this also prevents clicks from happening automatically
450 // the mouseup COMPLETES a "click" or drag
453 else if (xClick
>= 0)
457 // verify the mouseup was within a tight circle of the mousedown
458 i
= (OneCharWide
>> 1) +1;
459 if (pt
.x
< xClick
+ i
&& pt
.x
> xClick
- i
&& pt
.y
< yClick
+ i
&& pt
.y
> yClick
- i
)
462 lvi
.stateMask
= LVIS_SELECTED
;
465 // emulate a regular click, for Trees or Lists
468 TV_HITTESTINFO TreeHT
;
469 TreeHT
.pt
.x
= pt
.x
; // find out which tree button got clicked
472 hTreeEnt
= (HTREEITEM
) CallWindowProc(wTreeView
,hT
,TVM_HITTEST
,(WPARAM
) 0,(LPARAM
) &TreeHT
);
473 // then simulate a click on that button
474 if (hTreeEnt
!= NULL
) // make sure the click is actually on an entry
475 CallWindowProc(wTreeView
,hT
,TVM_EXPAND
,(WPARAM
) TVE_TOGGLE
,(LPARAM
) hTreeEnt
);
478 return 0; // eat all the Tree mouseups
480 i
= 0; // deal with List Focus
481 DumpHasFocus
= FALSE
;
484 else if (hh
!= hL
[0])
488 EnableMenuItem (hCmdMenu
, CMD_BRKPT
, MF_GRAYED
);
491 EnableMenuItem (hCmdMenu
, CMD_WPTWR
, MF_ENABLED
);
492 EnableMenuItem (hCmdMenu
, CMD_WPTRD
, MF_ENABLED
);
496 EnableMenuItem (hCmdMenu
, CMD_WPTWR
, MF_GRAYED
);
497 EnableMenuItem (hCmdMenu
, CMD_WPTRD
, MF_GRAYED
);
500 if (DumpHasFocus
== FALSE
)
502 EnableMenuItem (hCmdMenu
, CMD_BRKPT
, MF_ENABLED
);
503 EnableMenuItem (hCmdMenu
, CMD_WPTWR
, MF_GRAYED
);
504 EnableMenuItem (hCmdMenu
, CMD_WPTRD
, MF_GRAYED
);
506 if (GetFocus() != hh
)
508 CallWindowProc(wListView
, hh
, WM_SETFOCUS
, (WPARAM
) 0, (LPARAM
) 0);
510 CallWindowProc(wListView
, hL
[0], WM_KILLFOCUS
, (WPARAM
) 0, (LPARAM
) 0);
512 CallWindowProc(wListView
, hL
[1], WM_KILLFOCUS
, (WPARAM
) 0, (LPARAM
) 0);
514 CallWindowProc(wListView
, hL
[2], WM_KILLFOCUS
, (WPARAM
) 0, (LPARAM
) 0);
517 lvht
.pt
.x
= LOWORD(ll
); // do a hit test to get the iItem to select
518 lvht
.pt
.y
= HIWORD(ll
);
519 i
= CallWindowProc(wListView
, hh
, LVM_HITTEST
, (WPARAM
) 0, (LPARAM
) &lvht
);
520 // i is a copy of the iItem number -- ignore anything <= 0
521 // deselect anyything that's selected
522 int j
= CallWindowProc(wListView
, hh
, LVM_GETNEXTITEM
, (WPARAM
) -1, MAKELPARAM(LVNI_SELECTED
, 0));
525 // cancel the item's "selection"
526 CallWindowProc(wListView
, hh
, LVM_SETITEMSTATE
, (WPARAM
)j
, (LPARAM
)&lvi
);
527 // and get the next one
528 j
= CallWindowProc(wListView
, hh
, LVM_GETNEXTITEM
, (WPARAM
) -1, MAKELPARAM(LVNI_SELECTED
, 0));
530 if (i
>= 0) // then select the one that got clicked
532 lvi
.state
= lvi
.stateMask
; // value = "selected"
533 CallWindowProc(wListView
, hh
, LVM_SETITEMSTATE
, (WPARAM
)lvht
.iItem
, (LPARAM
)&lvi
);
536 // if this was a MemDump click -- need to get the "Selected Address"
537 SelectedDataAddress
= DumpStart
+ (i
<<4);
538 // Clicked a Subitem? column numbers = byte offsets + 1
539 CallWindowProc(wListView
, hh
, LVM_SUBITEMHITTEST
, 0, (LPARAM
)&lvht
);
540 if (lvht
.iSubItem
> 0)
541 SelectedDataAddress
+= lvht
.iSubItem
- 1;
546 xClick
= -1; // all drags/clicks have been processed, so reset
548 return 0; // eat all the mouseups
550 if (hh
== hT
) // if this is a param_tree message, use the proper windowProc
551 return (CallWindowProc(wTreeView
, hh
, mm
, ww
, ll
));
553 return (CallWindowProc(wListView
, hh
, mm
, ww
, ll
));
557 bx_bool
SpListView() // Superclasses a ListView control
560 GetClassInfo(GetModuleHandle(0), WC_LISTVIEW
, &wClass
);
561 wListView
= wClass
.lpfnWndProc
;
562 wClass
.hInstance
= GetModuleHandle(0);
563 wClass
.lpszClassName
= "sLV";
564 wClass
.lpfnWndProc
= LVProc
;
565 if (RegisterClass(&wClass
) == 0)
570 bx_bool
SpBtn() // Superclasses a button control
573 GetClassInfo(GetModuleHandle(0), "button", &wClass
);
574 wBtn
= wClass
.lpfnWndProc
;
575 wClass
.hInstance
= GetModuleHandle(0);
576 wClass
.lpszClassName
= "sBtn";
577 wClass
.lpfnWndProc
= BtnProc
;
578 if (RegisterClass(&wClass
) == 0)
583 // Convert a string (except for the 0x in a hex number) to uppercase
590 if (*p
== '0' && p
[1] == 'x')
594 *p
= UCtable
[(int) *p
]; // use the lookup table created by MakeXlatTables
600 // create EFLAGS display for Status line
603 Bit32u Efl
= (Bit32u
) rV
[EFL_Rnum
];
605 char *cp
= tmpcb
+ 6;
607 sprintf(tmpcb
,"IOPL=%1u", (Efl
& 0x3000) >> 12);
611 strcpy (cp
, EflBName
[i
]); // copy the name of the bitflag
612 if ((Efl
& EflBitVal
[i
]) != 0) // if the bit is set, put the name in uppercase
614 cp
+= EflBNameLen
[i
];
618 // change the display on the status line if anything has changed
621 if (StatusChange
== FALSE
) return; // avoid sending unnecessary messages/invalidations
622 StatusChange
= FALSE
;
624 if (AtBreak
!= FALSE
) // modify status line only during a break
626 ShowEflags(); // prints flags into tmpcb
627 SendMessage(hS_S
,SB_SETTEXT
,3,(LPARAM
)tmpcb
); // display eflags
629 if (CpuModeChange
!= FALSE
) // Did CR0 bits or EFER bits change value?
631 CpuModeChange
= FALSE
;
633 case BX_MODE_IA32_REAL
:
634 if (In32Mode
== FALSE
)
635 SendMessage(hS_S
,SB_SETTEXT
,1,(LPARAM
)"CPU: Real Mode (16)");
637 SendMessage(hS_S
,SB_SETTEXT
,1,(LPARAM
)"CPU: Real Mode (32)");
639 case BX_MODE_IA32_V8086
:
640 SendMessage(hS_S
,SB_SETTEXT
,1,(LPARAM
)"CPU: V8086 Mode");
642 case BX_MODE_IA32_PROTECTED
:
643 if (In32Mode
== FALSE
) {
645 SendMessage(hS_S
,SB_SETTEXT
,1,(LPARAM
)"CPU: PMode (16) (PG)");
647 SendMessage(hS_S
,SB_SETTEXT
,1,(LPARAM
)"CPU: PMode (16)");
651 SendMessage(hS_S
,SB_SETTEXT
,1,(LPARAM
)"CPU: PMode (32) (PG)");
653 SendMessage(hS_S
,SB_SETTEXT
,1,(LPARAM
)"CPU: PMode (32)");
656 case BX_MODE_LONG_COMPAT
:
657 SendMessage(hS_S
,SB_SETTEXT
,1,(LPARAM
)"CPU: Compatibility Mode");
659 case BX_MODE_LONG_64
:
660 SendMessage(hS_S
,SB_SETTEXT
,1,(LPARAM
)"CPU: Long Mode");
666 // set window color (active or gray), depending on AtBreak value
667 if (AtBreak
!= PrevAtBreak
)
669 PrevAtBreak
= AtBreak
;
670 COLORREF c
= RGB(255,255,255);
671 if (AtBreak
== FALSE
)
673 SendMessage(hS_S
,SB_SETTEXT
,0,(LPARAM
)"Running");
674 c
= RGB(210,210,210); // emulation running -> gui inactive
677 SendMessage(hS_S
,SB_SETTEXT
,0,(LPARAM
)"Break");
679 // this sets the background color OUTSIDE the area of the list, for A, D, R
680 CallWindowProc(wListView
, hL
[2],LVM_SETBKCOLOR
,0,c
);
681 CallWindowProc(wListView
, hL
[1],LVM_SETBKCOLOR
,0,c
);
682 CallWindowProc(wListView
, hL
[0],LVM_SETBKCOLOR
,0,c
);
684 InvalidateRect(hL
[2],0,TRUE
);
685 InvalidateRect(hL
[1],0,TRUE
);
686 InvalidateRect(hL
[0],0,TRUE
);
690 // Read a copy of some emulated linear bochs memory
691 // Note: laddr + len must not cross a 4K boundary -- otherwise, there are no limits
692 bx_bool
ReadBxLMem(Bit64u laddr
, unsigned len
, Bit8u
*buf
)
694 bx_phy_address paddr
;
695 bx_bool retval
= TRUE
;
697 // on same physical page as the last access?
698 if (laddr
< ladrmin
|| laddr
> ladrmax
)
700 // No -- create a new translation offset for the new page.
701 if (laddr
> (Bit64u
) 0xffffffff && In64Mode
== FALSE
)
703 bx_address la_4K
= (bx_address
) laddr
& (~0xfff);
705 ladrmax
= la_4K
+ 0xfff;
706 retval
= BX_CPU(CurrentCPU
)->dbg_xlate_linear2phy(la_4K
, &paddr
);
709 l_p_offset
= la_4K
- paddr
;
711 paddr
= (bx_phy_address
)(laddr
- l_p_offset
);
713 retval
= bx_mem
.dbg_fetch_mem(BX_CPU(CurrentCPU
), paddr
, len
, buf
);
718 // "singlestep" disassembly lines from the internal debugger are sometimes ignored
719 bx_bool
isSSDisasm(char *s
)
721 if (ignSSDisasm
== FALSE
) // ignoring those lines?
724 while (*s
== ' ') // need to parse the line to see if it is ASM
726 if (*s
!= '(') // first char must be (
728 while (*s
!= '[' && *s
!= 0) // then there must be a [
732 while (*s
!= 0 && (*s
!= ')' || s
[1] != ':' || s
[2] != ' '))
736 while (*s
!= ';' && *s
!= 0) // last, there must be a ;
743 // dump output from the bochs internal debugger to hE_O output window
744 void ParseUnknown(char *x
)
750 while (*s
!=0 && *s
!= '\r' && *s
!= '\n' && DbgAppendPtr
< tmpcb
)
751 *(DbgAppendPtr
++)= *(s
++); // append the chars from x into the bigbuf
752 if (DbgAppendPtr
>= tmpcb
) // overflow error?
754 MessageBox(hY
,"Debugger output cannot be parsed -- buffer overflow",0,MB_OK
);
755 DbgAppendPtr
= bigbuf
; // throw away the line
760 if (*s
== 0) // automatically process only complete lines further
762 PO_Tdelay
= 2; // wait a half second, then force display of partial lines
765 PO_Tdelay
= 0; // line completed -- cancel any partial output time delay
767 // restart DbgAppendPtr at the beginning of a new line buffer
768 s
= DbgAppendPtr
= bigbuf
; // s -> raw register text line from debugger
769 if (ignoreNxtT
!= FALSE
)
771 if (strncmp(s
,"Next at t",9) == 0)
774 if (isSSDisasm(s
) != FALSE
)
777 while ((*s
>= ' ' || *s
== '\t') && i
< 204) // scan out to eol, count chars
782 if (i
> 203) // max out at 203 chars per line (should never happen)
788 if ((i
+overflow
+3) > OutWinCnt
) // amt needed vs. space available
790 s
= OutWindow
; // need to toss lines off beginning of OutWindow
791 int j
= OutWinCnt
- overflow
- 3;
792 while (j
< i
) // throw away one line at a time
794 // stop on any unprintable char < ' '
795 while ((unsigned char)*s
>= ' ' || *s
== '\t')
798 ++j
; // increase available space as chars are tossed
800 // in reality, s must be pointing at a CRLF
804 OutWinCnt
= j
+ overflow
+ 3;
805 j
= OutWinSIZE
- OutWinCnt
; // chars to copy, without the terminal zero
806 while (j
-- > 0) // recopy the OutWindow buffer up
810 p
= OutWindow
+ OutWinSIZE
- OutWinCnt
;
811 OutWinCnt
-= i
+ overflow
+ 2;
812 *(p
++) = '\r'; // end of buf only had a 0 in it,
813 *(p
++) = '\n'; // and needs CRLFs to display properly
815 while (i
-- > 0) // copy the new output line onto the buffer
819 *(p
++) = '.'; // just for fun, if the line overflows
824 SetWindowText(hE_O
,OutWindow
); // replace all text with modified buffer
825 // SendMessage(hE_O,EM_SETSEL,0,-1); // invisibly selects all, sets caret to end
826 CallWindowProc(wEdit
[1], hE_O
,EM_SETSEL
,OutWinSIZE
,OutWinSIZE
+1); // sets caret to end only
827 CallWindowProc(wEdit
[1], hE_O
,EM_SCROLLCARET
,0,0); // scrolls window to caret
828 // Note: the caret is never actually visible in the Output window
831 // load appropriate register values from simulation into local rV[] array
834 int i
= EFER_Rnum
+ 1; // EFER is the highest reg # in rV
837 if (RegObject
[CurrentCPU
][i
] != NULL
)
838 rV
[i
] = RegObject
[CurrentCPU
][i
]->get64();
840 #if BX_SUPPORT_X86_64 == 0
841 // copy RIP, RSP from EIP, ESP -- so LAs for both are always easily available
842 rV
[RIP_Rnum
] = rV
[EIP_Rnum
];
843 rV
[RSP_Rnum
] = rV
[ESP_Rnum
];
845 // copy the lower dwords of RAX - RBP to EAX - EBP (with 32bit truncation)
848 rV
[i
+ (EAX_Rnum
- RAX_Rnum
)] = GET32L(rV
[i
]);
850 if (RegObject
[CurrentCPU
][GDTR_Lim
] != NULL
) // get the limits on GDT and IDT
851 GDT_Len
= RegObject
[CurrentCPU
][GDTR_Lim
]->get();
852 if (RegObject
[CurrentCPU
][IDTR_Lim
] != NULL
)
853 IDT_Len
= RegObject
[CurrentCPU
][IDTR_Lim
]->get();
855 // Check CR0 bit 31 -- Paging bit
856 Bit32u NewPg
= (Bit32u
) rV
[CR0_Rnum
] & 0x80000000;
857 if (InPaging
!= NewPg
)
860 EnableMenuItem (hViewMenu
, CMD_PAGEV
, MF_GRAYED
);
862 EnableMenuItem (hViewMenu
, CMD_PAGEV
, MF_ENABLED
);
868 // grab linear breakpoints out of internal debugger's bx_guard structures, and sort them
871 extern bx_guard_t bx_guard
;
874 int i
= bx_guard
.iaddr
.num_linear
;
877 if (bx_guard
.iaddr
.lin
[i
].enabled
!= FALSE
)
879 BrkLAddr
[j
] = bx_guard
.iaddr
.lin
[i
].addr
;
880 BrkIdx
[j
] = bx_guard
.iaddr
.lin
[i
].bpoint_id
;
885 // sort the breakpoint list (linear sort), to make it faster to search
891 if (BrkLAddr
[j
] > BrkLAddr
[k
]) // find the next biggest
896 bx_address h
= BrkLAddr
[i
]; // do the swap on BOTH arrays
898 BrkLAddr
[i
] = BrkLAddr
[k
];
899 BrkIdx
[i
] = BrkIdx
[k
];
906 // this routine is only called if debugger already knows SSE is supported
907 // -- but it might not be "turned on", either
908 int FillSSE(int LineCount
)
914 lviG
.pszText
= tmpce
;
918 if ((rV
[CR0_Rnum
] & 0xc) != 0) // TS or EM flags in CR0 temporarily disable SSE
920 strcpy (tmpce
, "SSE-off");
921 lviG
.iItem
= LineCount
;
922 RitemToRnum
[LineCount
] = XMM0_Rnum
;
923 CallWindowProc(wListView
,hL
[0],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
927 // format: XMM[#] 00000000:00000000 (each 16 hex digits)
928 LV_ITEM lvi
= {LVIF_TEXT
,0,2,0,0,(LPSTR
) tmpcf
,80,0,0};
929 strcpy (tmpce
, "XMM[0]");
930 for (i
= 0; i
< BX_XMM_REGISTERS
; i
++)
935 tmpce
[5] = i
- 10 + '0';
941 lviG
.iItem
= LineCount
;
942 RitemToRnum
[LineCount
] = i
+ XMM0_Rnum
;
943 CallWindowProc(wListView
,hL
[0],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
945 p
= RegObject
[CurrentCPU
][XMM0_hi
+ i
];
947 val
= p
->get64(); // get the value of "xmm(i)_hi" register
950 *tmpcf
= '0'; // I'm putting a hex value in the decimal column -- more room there!
952 sprintf (tmpcf
+ 2,Fmt64b
[UprCase
],val
);
953 strcpy (tmpcf
+ 18, " : ");
954 p
= RegObject
[CurrentCPU
][XMM0_Rnum
+ i
];
956 val
= p
->get64(); // "SSE.xmm[i]_lo"
959 sprintf (tmpcf
+ 21,Fmt64b
[UprCase
], val
);
960 lvi
.iItem
= LineCount
;
961 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) LineCount
,(LPARAM
) &lvi
);
968 // this routine is only called if debugger already knows FPU is supported
969 // -- but it might not be active
970 int FillMMX(int LineCount
)
972 static double scale_factor
= pow(2.0, -63.0);
977 unsigned short exponent
[8];
979 lviG
.pszText
= tmpce
;
983 if ((rV
[CR0_Rnum
] & 0xc) != 0) // TS or EM flags in CR0 temporarily disable MMX/FPU/SSE
985 strcpy (tmpce
, "FPU-off");
986 lviG
.iItem
= LineCount
;
987 RitemToRnum
[LineCount
] = ST0_Rnum
;
988 CallWindowProc(wListView
,hL
[0],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
992 // format: MM#|ST# 00000000:00000000 then FPU float value in "decimal" column
993 LV_ITEM lvi
= {LVIF_TEXT
,0,0,0,0,(LPSTR
) tmpcf
,80,0,0};
994 strcpy (tmpce
, "MM0-ST0");
996 for (i
= 0; i
< 8; i
++)
1000 lviG
.iItem
= LineCount
;
1001 RitemToRnum
[LineCount
] = i
+ ST0_Rnum
;
1002 CallWindowProc(wListView
,hL
[0],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1003 p
= RegObject
[CurrentCPU
][ST0_Rnum
+ i
];
1005 mmreg
= p
->get64(); // get the value of "mmx(i)" register
1008 sprintf (tmpcf
,Fmt32b
[UprCase
],GET32H(mmreg
));
1009 strcpy (tmpcf
+ 8, " : ");
1010 sprintf (tmpcf
+ 11,Fmt32b
[UprCase
], GET32L(mmreg
));
1011 lvi
.iItem
= LineCount
;
1013 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) LineCount
,(LPARAM
) &lvi
);
1014 p
= RegObject
[CurrentCPU
][ST0_exp
+ i
];
1016 exp
= (Bit16u
) p
->get64(); // get the exponent for this FPU register
1019 exponent
[i
] = exp
; // save each one temporarily
1020 double f
= pow(2.0, ((0x7fff & exp
) - 0x3fff));
1024 f
*= (double)(signed __int64
)(mmreg
>>1) * scale_factor
* 2;
1026 f
*= mmreg
*scale_factor
;
1028 sprintf (tmpcf
,"%.3e",f
);
1030 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) LineCount
,(LPARAM
) &lvi
);
1033 strcpy (tmpce
, "ST0.exp");
1034 for (i
= 0; i
< 8; i
++)
1037 lviG
.iItem
= LineCount
;
1038 RitemToRnum
[LineCount
] = i
+ ST0_exp
;
1039 CallWindowProc(wListView
,hL
[0],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1040 sprintf (tmpcf
,Fmt16b
[UprCase
], exponent
[i
]);
1041 lvi
.iItem
= LineCount
;
1043 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) LineCount
,(LPARAM
) &lvi
);
1044 sprintf (tmpcf
,"%u", exponent
[i
]);
1046 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) LineCount
,(LPARAM
) &lvi
);
1052 // get values of Debug registers from simulation
1053 int FillDebugRegs(int itemnum
)
1055 bx_param_num_c
*bxp
;
1058 LV_ITEM lvi
= {LVIF_TEXT
,0,1,0,0,(LPSTR
) tmpcf
,80,0,0};
1059 strcpy (tmpce
,"dr0");
1060 if (UprCase
!= FALSE
)
1065 lviG
.pszText
= tmpce
;
1066 for(i
= 0 ; i
< 6 ; i
++)
1068 bxp
= RegObject
[CurrentCPU
][DR0_Rnum
+ i
];
1071 val
[i
] = bxp
->get();
1072 RitemToRnum
[itemnum
] = i
+ DR0_Rnum
;
1073 lviG
.iItem
= itemnum
;
1077 CallWindowProc(wListView
,hL
[0],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1078 sprintf(tmpcf
,Fmt32b
[UprCase
],val
[i
]);
1079 lvi
.iItem
= itemnum
;
1080 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) itemnum
,(LPARAM
) &lvi
);
1081 ++tmpce
[2]; // change the name, the cheap way
1082 if (i
== 3) tmpce
[2] += 2; // jump from "DR3" to "DR6"
1088 // Disassemble a linear memory area, in a loop, loading text into ASM window
1089 // completely update the ASM display with new data
1090 void FillAsm(Bit64u LAddr
, int MaxLines
)
1092 Bit64u ReadAddr
= LAddr
;
1098 char *p
= bigbuf
; // just to avoid a compiler warning
1099 LV_ITEM lvi
= {LVIF_TEXT
,0,0,0,0,(LPSTR
) 0,80,0,0};
1101 AsmLineCount
= 0; // initialize for disasm window update
1102 CallWindowProc(wListView
,hL
[1],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
1103 if (MaxLines
> MAX_ASM
) // just for protection
1108 // copydown buffer -- buffer size must be 4K + 16
1110 i
= BufLen
; // BufLen is guaranteed < 16
1113 // load buffer, up to the next 4k boundary
1114 len
= 4096 - (((int) ReadAddr
) & 0xfff); // calculate read amount
1115 Go
= ReadBxLMem (ReadAddr
, len
, (Bit8u
*) s
);
1121 p
= bigbuf
; // start at the beginning of the new buffer
1122 while (AsmLineCount
< MaxLines
&& BufEmpty
== FALSE
)
1124 // disassemble 1 line with a direct call, into tmpcf
1125 len
= bx_disassemble
.disasm(In32Mode
, In64Mode
, (bx_address
) 0,
1126 (bx_address
) LAddr
, (Bit8u
*) p
, tmpcf
);
1127 if (len
<= BufLen
) // disassembly was successful?
1129 AsmLA
[AsmLineCount
] = LAddr
; // save, and
1130 if (In64Mode
== FALSE
) // "display" linear addy of the opcode
1131 sprintf (tmpce
,Fmt32b
[UprCase
],LAddr
);
1133 sprintf (tmpce
,Fmt64b
[UprCase
],LAddr
);
1135 // create a new list entry
1137 lvi
.pszText
= tmpce
;
1138 lvi
.iItem
= AsmLineCount
;
1139 CallWindowProc(wListView
,hL
[1],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lvi
);
1140 BufLen
-= len
; // used up len bytes from buffer
1141 LAddr
+= len
; // calculate next LAddr
1143 // then build the "bytes" column entry
1145 *(s
++) = '('; // begin with the bytecount in parens
1149 *(s
++)= '1'; // len < 16, so convert to decimal the easy way
1157 i
= (unsigned char) *(p
++);
1158 *(s
++) = AsciiHex
[ 2* i
];
1159 *(s
++) = AsciiHex
[ 1+ 2*i
];
1161 *s
= 0; // zero terminate the "bytes" string
1163 CallWindowProc(wListView
,hL
[1],LVM_SETITEMTEXT
,(WPARAM
) AsmLineCount
,(LPARAM
) &lvi
);
1164 // display the ASM text
1165 if (UprCase
!= FALSE
) // do any requested uppercase conversion on the text
1168 lvi
.pszText
= tmpcf
;
1169 CallWindowProc(wListView
,hL
[1],LVM_SETITEMTEXT
,(WPARAM
) AsmLineCount
,(LPARAM
) &lvi
);
1175 if (AsmLineCount
>= MaxLines
) // disassembled enough lines?
1181 // Reload the entire Register window (hL[0]) with data
1184 int i
, itemnum
; // TODO: This routine needs a big rewrite to make it pretty
1185 bx_bool showEreg
= TRUE
;
1186 // ShowWindow(hL[0],SW_HIDE); // Hiding the windows causes way too much flicker
1187 FillRegs(); // get new values for rV local register array
1188 CallWindowProc(wListView
,hL
[0],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0); // destroy list
1189 // set general purpose Register ListView Item "group" = 0
1190 // groupId sets a little text header in the Listview -- but is not Pre-WinXP compatible
1195 LV_ITEM lvi
= {LVIF_TEXT
,0,0,0,0,(LPSTR
) tmpce
,80,0,0};
1196 // Display GP registers -- 64 bit registers first, if they exist
1198 if (In64Mode
!= FALSE
)
1200 showEreg
= SeeReg
[0]; // get user option setting for EAX, etc.
1201 for (i
= RAX_Rnum
; i
<= R15_Rnum
; i
++)
1203 RitemToRnum
[itemnum
] = i
; // always recreate the register -> itemnum mapping
1204 lviG
.iItem
= itemnum
;
1205 lviG
.pszText
= RDispName
[i
];
1206 CallWindowProc(wListView
,hL
[0],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1208 lvi
.iItem
= itemnum
;
1209 sprintf(tmpce
,"%I64d",rV
[i
]); // print the decimal column
1211 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) itemnum
,(LPARAM
) &lvi
);
1213 sprintf(tmpce
,Fmt64b
[UprCase
],rV
[i
]); // and hex
1215 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) itemnum
,(LPARAM
) &lvi
);
1221 // then 32bit GP registers (if appropriate)
1222 if (showEreg
!= FALSE
)
1224 for (i
= EAX_Rnum
; i
<= EIP_Rnum
; i
++)
1226 RitemToRnum
[itemnum
] = i
;
1227 lviG
.iItem
= itemnum
;
1228 lviG
.pszText
= RDispName
[i
];
1230 if (In32Mode
== FALSE
&& i
== 26) // Check for Real Mode (Pmode is TRUE in Long Mode)
1232 rV
[EIP_Rnum
] &= 0xffff; // in Real Mode, mask IP to 2 bytes
1233 ++(lviG
.pszText
); // and shorten name to 2 letters
1235 CallWindowProc(wListView
,hL
[0],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1237 lvi
.iItem
= itemnum
;
1238 sprintf(tmpce
,"%I64d",rV
[i
]); // print the decimal column
1240 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) itemnum
,(LPARAM
) &lvi
);
1242 sprintf(tmpce
,Fmt32b
[UprCase
],(Bit32u
)rV
[i
]); // and hex
1244 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) itemnum
,(LPARAM
) &lvi
);
1248 // always insert eflags next
1249 RitemToRnum
[itemnum
] = EFL_Rnum
;
1250 lviG
.iItem
= itemnum
;
1251 lviG
.pszText
= RDispName
[EFL_Rnum
];
1252 CallWindowProc(wListView
,hL
[0],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1254 sprintf(tmpce
,Fmt32b
[UprCase
],(Bit32u
)rV
[EFL_Rnum
]);
1255 lvi
.iItem
= itemnum
; // SubItem is already 1
1256 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) itemnum
,(LPARAM
) &lvi
);
1259 if (rV
[EFL_Rnum
] != PV
[EFL_Rnum
])
1260 StatusChange
= TRUE
; // if eflags changed, force a status update
1262 // display Segment registers (if requested)
1268 for(i
= CS_Rnum
; i
<= GS_Rnum
; i
++) // segment registers
1270 RitemToRnum
[itemnum
] = i
;
1271 lviG
.iItem
= itemnum
;
1272 lviG
.pszText
= RDispName
[i
];
1273 CallWindowProc(wListView
,hL
[0],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1274 sprintf(tmpce
,Fmt16b
[UprCase
], rV
[i
] & 0xffff);
1275 lvi
.iItem
= itemnum
; // SubItem is already 1
1276 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) itemnum
,(LPARAM
) &lvi
);
1280 // display System regsiters (if requested)
1281 // displaying these once is necessary for column resizing
1282 if (SeeReg
[2] || ResizeColmns
)
1288 if (In32Mode
== FALSE
) // don't show lgdt or tr in Real mode
1290 for(i
= GDTRnum
; i
<= j
; i
++)
1292 RitemToRnum
[itemnum
] = i
;
1293 lviG
.iItem
= itemnum
;
1294 lviG
.pszText
= RDispName
[i
];
1295 CallWindowProc(wListView
,hL
[0],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1297 if (i
== GDTRnum
|| i
== IDTRnum
)
1299 Bit16u limit
= GDT_Len
;
1302 if (In64Mode
== FALSE
)
1303 sprintf(tmpce
,xDT32Fmt
[UprCase
],(Bit32u
)rV
[i
],limit
);
1305 sprintf(tmpce
,xDT64Fmt
[UprCase
],rV
[i
],limit
);
1309 sprintf(tmpce
,Fmt16b
[UprCase
], rV
[i
] & 0xffff); // lgdt, tr
1311 lvi
.iItem
= itemnum
; // SubItem is already 1
1312 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) itemnum
,(LPARAM
) &lvi
);
1316 // display Control Registers (if requested)
1322 for(i
= CR0_Rnum
; i
<= EFER_Rnum
; i
++)
1324 RitemToRnum
[itemnum
] = i
;
1325 lviG
.iItem
= itemnum
;
1326 lviG
.pszText
= RDispName
[i
];
1327 CallWindowProc(wListView
,hL
[0],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1329 sprintf(tmpce
,"%08X",(Bit32u
)rV
[i
]);
1330 lvi
.iItem
= itemnum
; // SubItem is already 1
1331 CallWindowProc(wListView
,hL
[0],LVM_SETITEMTEXT
,(WPARAM
) itemnum
,(LPARAM
) &lvi
);
1336 // set the register background colors for rV
1337 i
= EFER_Rnum
+ 1; // total number of registers stored in rV
1340 if (rV
[i
] != PV
[i
]) // set the "red" flag if value changed
1341 RegColor
[i
] |= 0x80;
1343 RegColor
[i
] &= 0x7f;
1345 // Load any optional STi, MMX, SSE, DRx, TRx register info into the Register window (hL[0])
1347 // MMX-FPU registers
1348 if (SeeReg
[4] != FALSE
)
1349 itemnum
= FillMMX(itemnum
);
1354 if (SeeReg
[5] != FALSE
)
1355 itemnum
= FillSSE(itemnum
);
1358 // Internal x86 Debug Registers
1359 if (SeeReg
[6] != FALSE
)
1360 itemnum
= FillDebugRegs(itemnum
);
1362 // if (SeeReg[7] != FALSE) // Test registers are not supported yet in bochs
1363 // FillTRXRegs(itemnum);
1365 if (ResizeColmns
!= FALSE
) // resize Hex Value column sometimes
1366 CallWindowProc(wListView
, hL
[0], LVM_SETCOLUMNWIDTH
, 1, LVSCW_AUTOSIZE
);
1368 ShowWindow(hL
[0],SW_SHOW
);
1371 // scroll ASM window so that the current line is in the "middle"
1375 int CurTopIdx
= CallWindowProc(wListView
,hL
[1],LVM_GETTOPINDEX
,(WPARAM
) 0,(LPARAM
) 0);
1377 // Can the current line be displayed at all?
1378 if (CurrentAsmLA
< *AsmLA
|| CurrentAsmLA
> AsmLA
[AsmLineCount
-1])
1380 // convert from LA to a Line Index (nli) with a search
1381 j
= CurTopIdx
; // try to start at CurTopIdx
1382 if (AsmLA
[j
] > CurrentAsmLA
)
1384 while (nli
< 0 && j
< AsmLineCount
&& AsmLA
[j
] <= CurrentAsmLA
)
1386 if (AsmLA
[j
] == CurrentAsmLA
)
1390 // not found -> CurrentAsmLA is an illegal opcode address
1393 // is the current line ALREADY in the middle of the window?
1394 if (nli
< CurTopIdx
|| nli
>= CurTopIdx
+ AsmPgSize
- bottommargin
)
1397 int ScrollLines
= nli
- CurTopIdx
- topmargin
;
1398 j
= AsmLineCount
- CurTopIdx
- AsmPgSize
;
1399 // limit ScrollLines by the theoretical max and min
1400 if (ScrollLines
> j
)
1401 ScrollLines
= j
+ 1; // just a little extra to make sure
1402 if (ScrollLines
< -CurTopIdx
)
1403 ScrollLines
= -CurTopIdx
- 1; // just a little extra to make sure
1404 // convert # of scroll lines to pixels
1405 CallWindowProc(wListView
,hL
[1],LVM_SCROLL
,(WPARAM
) 0,(LPARAM
) (ScrollLines
* ListLineRatio
));
1407 InvalidateRect(hL
[1],0,TRUE
); // "current opcode" in ASM window needs redrawing
1410 // try to find a Linear Address to start a "pretty" autodisassembly
1411 void CanDoLA(Bit64u
*h
)
1414 if (TopAsmLA
> *h
|| *h
> AsmLA
[AsmLineCount
-1]) // is it hopeless?
1416 if (bottommargin
> AsmLineCount
)
1419 index
= AsmLineCount
- bottommargin
;
1420 while (++index
< AsmLineCount
)
1422 if (AsmLA
[index
] == *h
)
1424 *h
= AsmLA
[index
- topmargin
];
1430 void InitRegObjects()
1432 bx_list_c
*cpu_list
;
1433 extern bx_list_c
*root_param
;
1435 // get the param tree interface objects for every single register on all CPUs
1438 // RegObject[j]s are all initted to NULL when allocated in the BSS area
1439 // but it doesn't hurt anything to do it again, once
1440 int i
= TOT_REG_NUM
+ EXTRA_REGS
;
1442 RegObject
[j
][i
] = (bx_param_num_c
*) NULL
;
1443 sprintf (tmpce
,"bochs.cpu%d",j
); // set the "cpu number" for cpu_list
1444 cpu_list
= (bx_list_c
*) SIM
->get_param(tmpce
,root_param
);
1445 // TODO: in the next version, put all the names in an array, and loop
1446 // -- but that method is not compatible with bochs 2.3.7 or earlier
1447 #if BX_SUPPORT_X86_64 == 0
1448 RegObject
[j
][EAX_Rnum
] = SIM
->get_param_num("EAX", cpu_list
);
1449 RegObject
[j
][EBX_Rnum
] = SIM
->get_param_num("EBX", cpu_list
);
1450 RegObject
[j
][ECX_Rnum
] = SIM
->get_param_num("ECX", cpu_list
);
1451 RegObject
[j
][EDX_Rnum
] = SIM
->get_param_num("EDX", cpu_list
);
1452 RegObject
[j
][ESI_Rnum
] = SIM
->get_param_num("ESI", cpu_list
);
1453 RegObject
[j
][EDI_Rnum
] = SIM
->get_param_num("EDI", cpu_list
);
1454 RegObject
[j
][EBP_Rnum
] = SIM
->get_param_num("EBP", cpu_list
);
1455 RegObject
[j
][ESP_Rnum
] = SIM
->get_param_num("ESP", cpu_list
);
1456 RegObject
[j
][EIP_Rnum
] = SIM
->get_param_num("EIP", cpu_list
);
1458 RegObject
[j
][RAX_Rnum
] = SIM
->get_param_num("RAX", cpu_list
);
1459 RegObject
[j
][RBX_Rnum
] = SIM
->get_param_num("RBX", cpu_list
);
1460 RegObject
[j
][RCX_Rnum
] = SIM
->get_param_num("RCX", cpu_list
);
1461 RegObject
[j
][RDX_Rnum
] = SIM
->get_param_num("RDX", cpu_list
);
1462 RegObject
[j
][RSI_Rnum
] = SIM
->get_param_num("RSI", cpu_list
);
1463 RegObject
[j
][RDI_Rnum
] = SIM
->get_param_num("RDI", cpu_list
);
1464 RegObject
[j
][RBP_Rnum
] = SIM
->get_param_num("RBP", cpu_list
);
1465 RegObject
[j
][RSP_Rnum
] = SIM
->get_param_num("RSP", cpu_list
);
1466 RegObject
[j
][RIP_Rnum
] = SIM
->get_param_num("RIP", cpu_list
);
1467 RegObject
[j
][R8_Rnum
] = SIM
->get_param_num("R8", cpu_list
);
1468 RegObject
[j
][R9_Rnum
] = SIM
->get_param_num("R9", cpu_list
);
1469 RegObject
[j
][R10_Rnum
] = SIM
->get_param_num("R10", cpu_list
);
1470 RegObject
[j
][R11_Rnum
] = SIM
->get_param_num("R11", cpu_list
);
1471 RegObject
[j
][R12_Rnum
] = SIM
->get_param_num("R12", cpu_list
);
1472 RegObject
[j
][R13_Rnum
] = SIM
->get_param_num("R13", cpu_list
);
1473 RegObject
[j
][R14_Rnum
] = SIM
->get_param_num("R14", cpu_list
);
1474 RegObject
[j
][R15_Rnum
] = SIM
->get_param_num("R15", cpu_list
);
1476 RegObject
[j
][EFL_Rnum
]= SIM
->get_param_num("EFLAGS", cpu_list
);
1477 RegObject
[j
][CS_Rnum
]= SIM
->get_param_num("CS.selector", cpu_list
);
1478 RegObject
[j
][DS_Rnum
]= SIM
->get_param_num("DS.selector", cpu_list
);
1479 RegObject
[j
][ES_Rnum
]= SIM
->get_param_num("ES.selector", cpu_list
);
1480 RegObject
[j
][SS_Rnum
]= SIM
->get_param_num("SS.selector", cpu_list
);
1481 RegObject
[j
][FS_Rnum
]= SIM
->get_param_num("FS.selector", cpu_list
);
1482 RegObject
[j
][GS_Rnum
]= SIM
->get_param_num("GS.selector", cpu_list
);
1483 RegObject
[j
][GDTRnum
]= SIM
->get_param_num("GDTR.base", cpu_list
);
1484 RegObject
[j
][GDTR_Lim
]= SIM
->get_param_num("GDTR.limit", cpu_list
);
1485 RegObject
[j
][IDTRnum
]= SIM
->get_param_num("IDTR.base", cpu_list
);
1486 RegObject
[j
][IDTR_Lim
]= SIM
->get_param_num("IDTR.limit", cpu_list
);
1487 RegObject
[j
][LDTRnum
]= SIM
->get_param_num("LDTR.base", cpu_list
);
1488 RegObject
[j
][TRRnum
]= SIM
->get_param_num("TR.base", cpu_list
);
1489 RegObject
[j
][CR0_Rnum
]= SIM
->get_param_num("CR0", cpu_list
);
1490 RegObject
[j
][CR3_Rnum
]= SIM
->get_param_num("CR3", cpu_list
);
1491 #if BX_CPU_LEVEL >= 4
1492 RegObject
[j
][CR4_Rnum
] = SIM
->get_param_num("CR4", cpu_list
);
1494 #if BX_SUPPORT_X86_64
1495 RegObject
[j
][EFER_Rnum
]= SIM
->get_param_num("MSR.EFER", cpu_list
);
1498 RegObject
[j
][ST0_Rnum
]= SIM
->get_param_num("FPU.st0.fraction", cpu_list
);
1499 RegObject
[j
][ST1_Rnum
]= SIM
->get_param_num("FPU.st1.fraction", cpu_list
);
1500 RegObject
[j
][ST2_Rnum
]= SIM
->get_param_num("FPU.st2.fraction", cpu_list
);
1501 RegObject
[j
][ST3_Rnum
]= SIM
->get_param_num("FPU.st3.fraction", cpu_list
);
1502 RegObject
[j
][ST4_Rnum
]= SIM
->get_param_num("FPU.st4.fraction", cpu_list
);
1503 RegObject
[j
][ST5_Rnum
]= SIM
->get_param_num("FPU.st5.fraction", cpu_list
);
1504 RegObject
[j
][ST6_Rnum
]= SIM
->get_param_num("FPU.st6.fraction", cpu_list
);
1505 RegObject
[j
][ST7_Rnum
]= SIM
->get_param_num("FPU.st7.fraction", cpu_list
);
1506 RegObject
[j
][ST0_exp
]= SIM
->get_param_num("FPU.st0.exp", cpu_list
);
1507 RegObject
[j
][ST1_exp
]= SIM
->get_param_num("FPU.st1.exp", cpu_list
);
1508 RegObject
[j
][ST2_exp
]= SIM
->get_param_num("FPU.st2.exp", cpu_list
);
1509 RegObject
[j
][ST3_exp
]= SIM
->get_param_num("FPU.st3.exp", cpu_list
);
1510 RegObject
[j
][ST4_exp
]= SIM
->get_param_num("FPU.st4.exp", cpu_list
);
1511 RegObject
[j
][ST5_exp
]= SIM
->get_param_num("FPU.st5.exp", cpu_list
);
1512 RegObject
[j
][ST6_exp
]= SIM
->get_param_num("FPU.st6.exp", cpu_list
);
1513 RegObject
[j
][ST7_exp
]= SIM
->get_param_num("FPU.st7.exp", cpu_list
);
1516 RegObject
[j
][XMM0_Rnum
]= SIM
->get_param_num("SSE.xmm00_lo", cpu_list
);
1517 RegObject
[j
][XMM1_Rnum
]= SIM
->get_param_num("SSE.xmm01_lo", cpu_list
);
1518 RegObject
[j
][XMM2_Rnum
]= SIM
->get_param_num("SSE.xmm02_lo", cpu_list
);
1519 RegObject
[j
][XMM3_Rnum
]= SIM
->get_param_num("SSE.xmm03_lo", cpu_list
);
1520 RegObject
[j
][XMM4_Rnum
]= SIM
->get_param_num("SSE.xmm04_lo", cpu_list
);
1521 RegObject
[j
][XMM5_Rnum
]= SIM
->get_param_num("SSE.xmm05_lo", cpu_list
);
1522 RegObject
[j
][XMM6_Rnum
]= SIM
->get_param_num("SSE.xmm06_lo", cpu_list
);
1523 RegObject
[j
][XMM7_Rnum
]= SIM
->get_param_num("SSE.xmm07_lo", cpu_list
);
1524 RegObject
[j
][XMM0_hi
]= SIM
->get_param_num("SSE.xmm00_hi", cpu_list
);
1525 RegObject
[j
][XMM1_hi
]= SIM
->get_param_num("SSE.xmm01_hi", cpu_list
);
1526 RegObject
[j
][XMM2_hi
]= SIM
->get_param_num("SSE.xmm02_hi", cpu_list
);
1527 RegObject
[j
][XMM3_hi
]= SIM
->get_param_num("SSE.xmm03_hi", cpu_list
);
1528 RegObject
[j
][XMM4_hi
]= SIM
->get_param_num("SSE.xmm04_hi", cpu_list
);
1529 RegObject
[j
][XMM5_hi
]= SIM
->get_param_num("SSE.xmm05_hi", cpu_list
);
1530 RegObject
[j
][XMM6_hi
]= SIM
->get_param_num("SSE.xmm06_hi", cpu_list
);
1531 RegObject
[j
][XMM7_hi
]= SIM
->get_param_num("SSE.xmm07_hi", cpu_list
);
1532 #if BX_SUPPORT_X86_64
1533 RegObject
[j
][XMM8_Rnum
]= SIM
->get_param_num("SSE.xmm08_lo", cpu_list
);
1534 RegObject
[j
][XMM9_Rnum
]= SIM
->get_param_num("SSE.xmm09_lo", cpu_list
);
1535 RegObject
[j
][XMMA_Rnum
]= SIM
->get_param_num("SSE.xmm10_lo", cpu_list
);
1536 RegObject
[j
][XMMB_Rnum
]= SIM
->get_param_num("SSE.xmm11_lo", cpu_list
);
1537 RegObject
[j
][XMMC_Rnum
]= SIM
->get_param_num("SSE.xmm12_lo", cpu_list
);
1538 RegObject
[j
][XMMD_Rnum
]= SIM
->get_param_num("SSE.xmm13_lo", cpu_list
);
1539 RegObject
[j
][XMME_Rnum
]= SIM
->get_param_num("SSE.xmm14_lo", cpu_list
);
1540 RegObject
[j
][XMMF_Rnum
]= SIM
->get_param_num("SSE.xmm15_lo", cpu_list
);
1541 RegObject
[j
][XMM8_hi
]= SIM
->get_param_num("SSE.xmm08_hi", cpu_list
);
1542 RegObject
[j
][XMM9_hi
]= SIM
->get_param_num("SSE.xmm09_hi", cpu_list
);
1543 RegObject
[j
][XMMA_hi
]= SIM
->get_param_num("SSE.xmm00_hi", cpu_list
);
1544 RegObject
[j
][XMMB_hi
]= SIM
->get_param_num("SSE.xmm11_hi", cpu_list
);
1545 RegObject
[j
][XMMC_hi
]= SIM
->get_param_num("SSE.xmm12_hi", cpu_list
);
1546 RegObject
[j
][XMMD_hi
]= SIM
->get_param_num("SSE.xmm13_hi", cpu_list
);
1547 RegObject
[j
][XMME_hi
]= SIM
->get_param_num("SSE.xmm14_hi", cpu_list
);
1548 RegObject
[j
][XMMF_hi
]= SIM
->get_param_num("SSE.xmm15_hi", cpu_list
);
1551 RegObject
[j
][DR0_Rnum
]= SIM
->get_param_num("DR0", cpu_list
);
1552 RegObject
[j
][DR1_Rnum
]= SIM
->get_param_num("DR1", cpu_list
);
1553 RegObject
[j
][DR2_Rnum
]= SIM
->get_param_num("DR2", cpu_list
);
1554 RegObject
[j
][DR3_Rnum
]= SIM
->get_param_num("DR3", cpu_list
);
1555 RegObject
[j
][DR6_Rnum
]= SIM
->get_param_num("DR6", cpu_list
);
1556 RegObject
[j
][DR7_Rnum
]= SIM
->get_param_num("DR7", cpu_list
);
1557 // is there an #if for whether the test registers are supported?
1558 // RegObject[j][71]= SIM->get_param_num("TR3", cpu_list);
1559 // {"TR3","TR4","TR5","TR6","TR7"};
1564 // set all TRUE flags to checked in the Options menu, gray out unsupported features
1568 doOneTimeInit
= FALSE
;
1569 EnableMenuItem (hOptMenu
, CMD_EREG
, MF_GRAYED
);
1570 EnableMenuItem (hCmdMenu
, CMD_WPTWR
, MF_GRAYED
);
1571 EnableMenuItem (hCmdMenu
, CMD_WPTRD
, MF_GRAYED
);
1572 // 32bit registers are always displayed until longmode is active
1575 if (SeeReg
[i
] != FALSE
)
1576 CheckMenuItem (hOptMenu
, i
+ CMD_EREG
, MF_CHECKED
);
1578 if (ShowButtons
!= FALSE
)
1579 CheckMenuItem (hOptMenu
, CMD_SBTN
, MF_CHECKED
);
1581 CheckMenuItem (hOptMenu
, CMD_UCASE
, MF_CHECKED
);
1582 if (isLittleEndian
!= FALSE
)
1583 CheckMenuItem (hOptMenu
, CMD_LEND
, MF_CHECKED
);
1584 if (ignSSDisasm
!= FALSE
)
1585 CheckMenuItem (hOptMenu
, CMD_IGNSA
, MF_CHECKED
);
1586 if (ignoreNxtT
!= FALSE
)
1587 CheckMenuItem (hOptMenu
, CMD_IGNNT
, MF_CHECKED
);
1588 if (SeeRegColors
!= FALSE
)
1589 CheckMenuItem (hOptMenu
, CMD_RCLR
, MF_CHECKED
);
1590 if ((DumpInAsciiMode
& 2) != 0)
1591 CheckMenuItem (hOptMenu
, CMD_MHEX
, MF_CHECKED
);
1592 if ((DumpInAsciiMode
& 1) != 0)
1593 CheckMenuItem (hOptMenu
, CMD_MASCII
, MF_CHECKED
);
1594 if (ShowIOWindows
!= FALSE
)
1595 CheckMenuItem (hOptMenu
, CMD_IOWIN
, MF_CHECKED
);
1597 HMENU wsMenu
= GetSubMenu (hOptMenu
, WS_POPUP_IDX
);
1598 CheckMenuItem (wsMenu
, CMD_WS_1
, MF_CHECKED
);
1599 EnableMenuItem (hOptMenu
, CMD_TREG
, MF_GRAYED
); // not currently supported by bochs
1600 EnableMenuItem (hViewMenu
, CMD_PAGEV
, MF_GRAYED
);
1601 #if BX_SUPPORT_FPU == 0
1602 EnableMenuItem (hOptMenu
, CMD_FPUR
, MF_GRAYED
);
1605 #if BX_SUPPORT_SSE == 0
1606 EnableMenuItem (hOptMenu
, CMD_XMMR
, MF_GRAYED
);
1613 if (doOneTimeInit
!= FALSE
)
1615 // begin an autoupdate of Register and Asm windows
1616 LoadRegList(); // build and show ListView
1617 ParseBkpt(); // get the linear breakpoint list
1618 if (DViewMode
== VIEW_STACK
) // in stack view mode, keep the stack updated
1620 CurrentAsmLA
= BX_CPU(CurrentCPU
)->get_laddr(BX_SEG_REG_CS
, (bx_address
) rV
[RIP_Rnum
]);
1621 // ShowWindow(hL[1],SW_HIDE); // Hiding the windows causes way too much flicker
1622 if (CurrentAsmLA
< BottomAsmLA
|| CurrentAsmLA
> TopAsmLA
)
1624 Bit64u h
= CurrentAsmLA
;
1625 // generate a startLA (= h) that overlaps by topmargin, if possible
1628 FillAsm(h
, DefaultAsmLines
);
1629 if (ResizeColmns
!= FALSE
)
1631 // recalculate # of list items per page for all list windows
1632 AsmPgSize
= CallWindowProc(wListView
,hL
[1],LVM_GETCOUNTPERPAGE
,(WPARAM
) 0,(LPARAM
) 0);
1634 ListLineRatio
= ListVerticalPix
/ AsmPgSize
;
1635 CallWindowProc(wListView
, hL
[1], LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE
);
1638 // Set the scroll position for the new ASM window
1639 BottomAsmLA
= *AsmLA
;
1640 int j
= bottommargin
; // try to use this bottom margin on ASM window
1641 if (j
> AsmLineCount
)
1643 TopAsmLA
= AsmLA
[AsmLineCount
- j
]; //TopAsmLA is the scroll point
1645 doAsmScroll(); // ASM window may need to scroll
1646 ShowWindow(hL
[1],SW_SHOW
);
1647 ResizeColmns
= FALSE
; // done with reformatting, if it was needed
1648 UpdateStatus(); // Mode and Eflags may have changed status
1651 // squish the MemDump columns to 0 width, in preparation for resizing
1654 int i
= 17; // never change the size of the last column
1656 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, i
, 0);
1659 // Fill the GDT ListView, reading GDT data directly from bochs linear mem
1664 unsigned int k
= (GDT_Len
+ 1) / 8;
1667 LV_ITEM lvi
= {LVIF_TEXT
,0,0,0,0,(LPSTR
) 0,100,0,0};
1668 doDumpRefresh
= FALSE
;
1670 laddr
= rV
[GDTRnum
] & (~7); // recover the GDT base address (force 8b align)
1671 CallWindowProc(wListView
,hL
[2],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
1674 for(i
= 0 ; i
< k
; i
++)
1676 // read 2 dwords from bochs linear mem into "buffer"
1678 lviG
.pszText
= tmpce
;
1679 sprintf(tmpce
,"%02u (Selector 0x%04X)",i
,i
<< 3);
1680 CallWindowProc(wListView
,hL
[2],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1682 lvi
.pszText
= tmpce
;
1683 if (ReadBxLMem(laddr
, 8, gdtbuf
) == FALSE
) // abort the current GDT dump on a memory error
1685 sprintf (tmpce
,"illegal address");
1687 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) i
,(LPARAM
) &lvi
);
1692 // enforce proper littleendianness on the gdtbuf bytes
1693 Bit32u limit
= gdtbuf
[0] | ((Bit32u
) gdtbuf
[1] << 8);
1694 limit
|= ((Bit32u
)gdtbuf
[6] & 0xf) << 16;
1695 if ((gdtbuf
[6] & 0x80) != 0) // 'Granularity' bit = 4K limit multiplier
1696 limit
= limit
* 4096 + 4095; // and the bottom 12 bits aren't tested
1698 info
= GDTsT
[0]; // default info string is blank
1699 j
= 8; // default GDT type (group) is blank
1700 if ((gdtbuf
[5] & 0x10) == 0) // 'S' bit clear = System segment
1704 if (limit
== 0 && (gdtbuf
[5] & 0x80) == 0) // 'P' (present) bit
1707 // point to the approprate info string for the GDT system segment type
1708 info
= GDTsT
[(int) (gdtbuf
[5] & 0xf)];
1710 else // it's an 'executable' code or data segment
1712 j
= (gdtbuf
[6] & 0x60) >> 5; // get the 'L' and 'D/B' bits
1713 if (j
== 3) // both bits set is illegal
1715 else if ((gdtbuf
[5] & 0x8) == 0)
1716 j
+= 3; // data = 3 to 5, code = 0 to 2
1719 lviG
.iGroupId
= j
; // use GroupIDs on XP and higher systems
1721 info
= GDTt2
[j
]; // otherwise, put descriptive text in "info" column
1725 // enforce proper littleendianness on the gdtbuf bytes
1726 Bit32u base
= gdtbuf
[2] | ((Bit32u
) gdtbuf
[3] << 8);
1727 base
|= (Bit32u
) gdtbuf
[4] << 16;
1728 base
|= (Bit32u
) gdtbuf
[7] << 24;
1729 if ((gdtbuf
[6] & 0x60) == 0x20) // test for longmode segment
1731 base
= 0; // the base is always 0 in longmode, with "no" limit
1732 sprintf(tmpcf
,"0xFFFFFFFFFFFFFFFF");
1735 sprintf(tmpcf
,"0x%X",limit
);
1737 sprintf(tmpce
,"0x%X",base
);
1739 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) i
,(LPARAM
) &lvi
);
1741 sprintf(tmpce
,"%u", (gdtbuf
[5] & 0x60) >> 5);
1743 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) i
,(LPARAM
) &lvi
);
1746 lvi
.pszText
= tmpcf
;
1747 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) i
,(LPARAM
) &lvi
);
1750 info
= GDTt2
[7]; // call "Null" selector "unused"
1753 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) i
,(LPARAM
) &lvi
);
1755 // 2 of the GDT columns are too narrow with a regular Autosize
1756 LV_COLUMN lvgc
= {LVCF_TEXT
,0,0,tmpce
};
1757 strcpy (tmpce
,"Index"); // header for col 0
1758 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 0,(LPARAM
) &lvgc
);
1759 strcpy (tmpce
,"Base"); // header for col 1
1760 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 1,(LPARAM
) &lvgc
);
1761 strcpy (tmpce
,"Size"); // header for col 2
1762 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 2,(LPARAM
) &lvgc
);
1763 strcpy (tmpce
,"DPL"); // header for col 3
1764 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 3,(LPARAM
) &lvgc
);
1765 strcpy (tmpce
,"Info"); // header for col 4 (17)
1766 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 17,(LPARAM
) &lvgc
);
1767 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, 1, LVSCW_AUTOSIZE_USEHEADER
);
1768 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, 3, LVSCW_AUTOSIZE_USEHEADER
);
1769 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE
);
1770 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, 2, LVSCW_AUTOSIZE
);
1771 ShowWindow(hL
[2],SW_SHOW
);
1775 // Fills the IDT ListView, reading IDT data directly from bochs linear mem
1784 LV_ITEM lvi
= {LVIF_TEXT
,0,17,0,0,(LPSTR
) tmpce
,100,0,0};
1785 unsigned int mode
= 0;
1786 if (In32Mode
!= FALSE
)
1788 if (In64Mode
!= FALSE
)
1790 doDumpRefresh
= FALSE
;
1792 entrysize
= 4 << mode
; // calculate the bytesize of the entries
1793 unsigned int k
= (IDT_Len
+ 1) / entrysize
;
1794 CallWindowProc(wListView
,hL
[2],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
1795 // force all column widths to 0
1797 // recover the IDT linear base address (aligned)
1798 laddr
= rV
[IDTRnum
] & (~(entrysize
- 1));
1800 for(i
= 0 ; i
< k
; i
++)
1802 // sprintf(info,"0x%02X",i);
1803 *tmpce
= AsciiHex
[ 2* i
];
1804 tmpce
[1] = AsciiHex
[ 1+ 2*i
];
1807 lviG
.pszText
= tmpce
;
1809 lviG
.iGroupId
= 8; // IDT "group" is always blank
1811 int L
= CallWindowProc(wListView
,hL
[2],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1812 if (ReadBxLMem(laddr
, entrysize
, idtbuf
) == FALSE
) // abort the current IDT dump on a memory error
1814 sprintf (tmpce
,"illegal address");
1815 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) L
,(LPARAM
) &lvi
);
1819 // enforce proper littleendianness on the idtbuf bytes
1820 ofs
= idtbuf
[0] | ((Bit32u
) idtbuf
[1] << 8);
1821 sel
= idtbuf
[2] | ((Bit16u
) idtbuf
[3] << 8);
1825 case 0: // Real Mode
1826 sprintf(tmpce
,"0x%04X:0x%04X", sel
, ofs
);
1830 ofs
|= ((Bit32u
) idtbuf
[6] << 16) | ((Bit32u
) idtbuf
[7] << 24);
1831 sprintf(tmpce
,"0x%04X:0x%08X", sel
, ofs
);
1832 // TODO: also print some flags from idtbuf[5], maybe, in another column
1836 Bit64u off64
= (Bit64u
)(ofs
| ((Bit32u
) idtbuf
[6] << 16) | ((Bit32u
) idtbuf
[7] << 24));
1837 off64
|= ((Bit64u
) idtbuf
[8] << 32) | ((Bit64u
) idtbuf
[9] << 40);
1838 off64
|= ((Bit64u
) idtbuf
[10] << 48) | ((Bit64u
) idtbuf
[11] << 56);
1839 sprintf(tmpce
,"0x%04X:0x%016I64X", sel
, off64
);
1840 // TODO: also print some flags from idtbuf[5], maybe, in another column
1845 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) L
,(LPARAM
) &lvi
);
1847 LV_COLUMN lvgc
= {LVCF_TEXT
,0,0,tmpce
};
1848 strcpy (tmpce
,"Interrupt"); // header for col 0
1849 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 0,(LPARAM
) &lvgc
);
1850 strcpy (tmpce
,"L.Address"); // header for col 1 (17)
1851 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 17,(LPARAM
) &lvgc
);
1852 // redo col0 to handle the wide header
1853 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE_USEHEADER
);
1854 ShowWindow(hL
[2],SW_SHOW
);
1857 // insert one entry into the Paging data list -- col0 in tmpce, col1 in tmpcf
1858 void AddPagingLine(int LC
)
1860 LV_ITEM lvi
= {LVIF_TEXT
,LC
,17,0,0,(LPSTR
) tmpcf
,80,0,0};
1862 lviG
.pszText
= tmpce
;
1863 CallWindowProc(wListView
,hL
[2],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1864 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) LC
,(LPARAM
) &lvi
);
1867 // lifted from bx_dbg_dump_table in dbg_main of the internal debugger
1870 Bit32u lin
, start_lin
, curlin
; // show only low 32 bit
1872 Bit64u start_phy
, phy64
;
1874 doDumpRefresh
= FALSE
;
1876 lviG
.iGroupId
= 8; // Paging "group" is always blank
1879 CallWindowProc(wListView
,hL
[2],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
1880 curlin
= lin
= 0; // always start at linear address 0
1881 start_lin
= 1; // force a mismatch on the first line
1883 while (LineCount
< 1024 && curlin
!= 0xfffff000)
1885 // get translation lin -> phys, and verify mapping is legal
1886 if (BX_CPU(CurrentCPU
)->dbg_xlate_linear2phy(lin
, &phy
) != FALSE
)
1889 if ((lin
- start_lin
) != (phy64
- start_phy
))
1893 sprintf (tmpce
,"0x%08X - 0x%08X",start_lin
, lin
- 1);
1894 sprintf (tmpcf
,"0x%016I64X - 0x%016I64X",start_phy
, start_phy
+ (lin
-1-start_lin
));
1895 AddPagingLine (LineCount
);
1906 sprintf (tmpce
,"0x%08X - 0x%08X",start_lin
, lin
- 1);
1907 sprintf (tmpcf
,"0x%016I64X - 0x%016I64X",start_phy
, start_phy
+ (lin
-1-start_lin
));
1908 AddPagingLine (LineCount
);
1915 lin
+= 0x1000; // then test the next 4K page in the loop
1917 if (start_lin
!= 1) // need to output one last line?
1919 sprintf (tmpce
,"0x%08X - 0x%08X", start_lin
, -1);
1920 sprintf (tmpcf
,"0x%016I64X - 0x%016I64X",start_phy
, start_phy
-1 -start_lin
);
1921 AddPagingLine (LineCount
);
1924 LV_COLUMN lvgc
= {LVCF_TEXT
,0,0,tmpce
};
1925 strcpy (tmpce
,"L.Address"); // header for col 0
1926 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 0,(LPARAM
) &lvgc
);
1927 strcpy (tmpce
,"is mapped to P.Address"); // header for col 1 (17)
1928 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 17,(LPARAM
) &lvgc
);
1929 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE
);
1930 ShowWindow(hL
[2],SW_SHOW
);
1934 // build the stack display
1937 Bit64u StackLA
, EndLA
;
1938 unsigned int len
, i
, wordsize
, overlap
;
1941 bx_bool HasNeg
= FALSE
;
1945 doDumpRefresh
= FALSE
;
1946 lviG
.pszText
= tmpcf
;
1947 StackLA
= (Bit64u
) BX_CPU(CurrentCPU
)->get_laddr(BX_SEG_REG_SS
, (bx_address
) rV
[RSP_Rnum
]);
1949 if (PStackLA
== 1) // illegal value requests a full refresh
1950 PStackLA
= StackLA
^ 0x4000; // force a non-match below
1952 wordsize
= 4; // assume Pmode
1953 if (In32Mode
== FALSE
)
1955 else if (In64Mode
!= FALSE
)
1957 len
= STACK_ENTRIES
* wordsize
;
1959 // TODO: enforce that tmpce is wordsize aligned
1960 // also -- enforce that StackLA is wordsize aligned
1962 i
= (unsigned int) StackLA
& 0xfff; // where is stack bottom, in its 4K memory page?
1963 if (i
> 0x1000 - len
) // does len cross a 4K boundary?
1965 unsigned int ReadSize
= 0x1000 - i
;
1966 // read up to the 4K boundary, then try to read the last chunk
1967 if (ReadBxLMem (StackLA
, ReadSize
, (Bit8u
*) cp
) == FALSE
)
1969 // no data to show -- just an error message
1970 sprintf (tmpcf
,"illegal address");
1971 CallWindowProc(wListView
,hL
[2],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
1972 CallWindowProc(wListView
,hL
[2],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
1973 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE
);
1976 LglAddy
= ReadBxLMem (StackLA
+ ReadSize
, len
+ i
- 0x1000, (Bit8u
*) cp
+ ReadSize
);
1977 if (LglAddy
== FALSE
)
1981 ReadBxLMem (StackLA
, len
, (Bit8u
*) cp
);
1983 UpdateDisp
= CpuModeChange
; // calculate which stack entries have changed
1986 j
= overlap
= len
/ wordsize
;
1988 StackEntChg
[j
] = TRUE
; // assume that all lines have changed
1989 if (PStackLA
> StackLA
) // calculate the overlap between the prev and current stacks
1991 EndLA
= PStackLA
- StackLA
;
1994 i
= (unsigned int) (EndLA
/ wordsize
);
1998 i
= overlap
; // force the next loop to exit
2002 EndLA
= StackLA
- PStackLA
;
2006 j
= (int) (EndLA
/ wordsize
);
2007 cpp
+= j
* wordsize
;
2011 i
= overlap
; // force the next loop to exit
2015 j
= wordsize
; // if the two entries match, cancel the EntryChange flag for that entry
2016 while (j
> 0 && *cp
== *cpp
)
2023 StackEntChg
[i
] = FALSE
; // got a match on all bytes
2026 cp
+= j
; // bump the pointers to the next stack entry
2033 UpdateDisp
|= StackEntChg
[j
];
2034 if (UpdateDisp
== FALSE
) // Don't need to update the list? (no changes?)
2036 if (StkInvOnce
== FALSE
)
2037 InvalidateRect(hL
[2],0,TRUE
); // Invalidate ONCE to turn off all the red stuff
2041 CallWindowProc(wListView
,hL
[2],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
2048 *(cpp
++)= *(cp
++); // copy the stack to the Prev buffer
2049 j
= STACK_ENTRIES
* 8 - len
;
2051 *(cpp
++)= 0; // zero out the unused tail end of the prev buffer
2052 cp
= tmpce
; // the following display loop runs on the cp pointer
2055 lviG
.iGroupId
= 8; // Stack "group" is always blank
2057 LV_ITEM lvi
= {LVIF_TEXT
,0,0,0,0,(LPSTR
) tmpcf
,0,0,0};
2058 EndLA
= StackLA
+ len
- 1;
2060 while (StackLA
< EndLA
)
2065 if (In64Mode
== FALSE
)
2068 sprintf (tmpcf
,Fmt32b
[1],StackLA
);
2069 CallWindowProc(wListView
,hL
[2],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
2070 if (In32Mode
== FALSE
)
2071 tmp
= *((Bit16s
*) cp
);
2073 tmp
= *((Bit32s
*) cp
);
2076 sprintf (tmpcf
,"0x%X",tmp
);
2077 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) i
,(LPARAM
) &lvi
);
2078 sprintf (tmpcf
,"%d",tmp
);
2082 Bit64s tmp
= *((Bit64s
*) cp
);
2083 // don't bother testing negative -- 64b values are all the same length
2084 sprintf (tmpcf
,Fmt64b
[1],StackLA
);
2085 CallWindowProc(wListView
,hL
[2],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
2086 sprintf (tmpcf
,Fmt64b
[1],tmp
);
2087 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) i
,(LPARAM
) &lvi
);
2088 sprintf (tmpcf
,"%I64d",tmp
);
2091 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) i
,(LPARAM
) &lvi
);
2092 StackLA
+= wordsize
;
2096 if (StackSized
== 0 || (StackSized
== 1 && HasNeg
!= FALSE
))
2098 // force all column widths to 0
2100 LV_COLUMN lvgc
= {LVCF_TEXT
,0,0,tmpce
};
2101 strcpy (tmpce
,"L.Address"); // header for col 0
2102 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 0,(LPARAM
) &lvgc
);
2103 strcpy (tmpce
,"Value"); // header for col 1
2104 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 1,(LPARAM
) &lvgc
);
2105 strcpy (tmpce
,"(dec.)"); // header for col 2 (17)
2106 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 17,(LPARAM
) &lvgc
);
2107 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE
);
2108 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, 1, LVSCW_AUTOSIZE
);
2109 StackSized
= 1; // may need to resize a second time
2110 if (HasNeg
!= FALSE
)
2113 ShowWindow(hL
[2],SW_SHOW
);
2117 // recurse displaying each leaf/branch of param_tree -- with values for each leaf
2118 void MakeBL(HTREEITEM h_P
, bx_param_c
*p
)
2121 bx_list_c
*as_list
= NULL
;
2123 strcpy (tmpce
, p
->get_name());
2124 int j
= strlen (tmpce
);
2125 tvis
.item
.cChildren
= 0;
2126 switch (p
->get_type())
2129 if (((bx_param_num_c
*)p
)->get_base() == BASE_DEC
)
2130 sprintf (tmpce
+ j
,": %I64d",((bx_param_num_c
*)p
)->get64());
2132 sprintf (tmpce
+ j
,": 0x%0I64X",((bx_param_num_c
*)p
)->get64());
2135 as_list
= (bx_list_c
*)p
;
2136 tvis
.item
.cChildren
= 1;
2137 i
= as_list
->get_size();
2139 case BXT_PARAM_BOOL
:
2140 sprintf (tmpce
+ j
,": %s",((bx_param_bool_c
*)p
)->get()?"true":"false");
2142 case BXT_PARAM_ENUM
:
2143 sprintf (tmpce
+ j
,": %s",((bx_param_enum_c
*)p
)->get_selected());
2145 case BXT_PARAM_STRING
:
2146 if (((bx_param_string_c
*)p
)->get_options()->get() & bx_param_string_c::RAW_BYTES
)
2148 char *cp
= tmpce
+ j
;
2149 unsigned char *rp
= (unsigned char *)((bx_param_string_c
*)p
)->getptr();
2150 char sc
= ((bx_param_string_c
*)p
)->get_separator();
2151 int k
= ((bx_param_string_c
*)p
)->get_maxsize();
2156 *(cp
++) = AsciiHex
[2* *rp
];
2157 *(cp
++) = AsciiHex
[2* *rp
+ 1];
2160 *--cp
= 0; // overwrite the last separator char
2163 sprintf (tmpce
+ j
,": %s",((bx_param_string_c
*)p
)->getptr());
2165 case BXT_PARAM_DATA
:
2166 sprintf (tmpce
+ j
,": binary data, size=%d",((bx_shadow_data_c
*)p
)->get_size());
2168 tvis
.hParent
= h_P
; // create leaves/recurse branches
2169 h_new
= (HTREEITEM
) CallWindowProc(wTreeView
,hT
,TVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &tvis
);
2173 MakeBL(h_new
, as_list
->get(i
));
2174 // sort this level of the tree alphabetically
2175 // CallWindowProc(wTreeView,hT,TVM_SORTCHILDREN,(WPARAM) 0,(LPARAM) h_new);
2184 extern bx_list_c
*root_param
;
2185 // Note: don't multithread this display -- the user expects it to complete
2186 doDumpRefresh
= FALSE
;
2187 ShowWindow(hL
[2],SW_HIDE
);
2188 TreeView_DeleteAllItems(hT
);
2189 strcpy (tmpce
, "bochs parameter tree");
2190 tvis
.hParent
= NULL
; // create the root node
2191 tvis
.item
.mask
= TVIF_TEXT
| TVIF_CHILDREN
| TVIF_STATE
;
2192 tvis
.hInsertAfter
= (HTREEITEM
)TVI_FIRST
;
2193 tvis
.item
.pszText
= tmpce
;
2194 tvis
.item
.cchTextMax
= 250;
2195 tvis
.item
.cChildren
= 1;
2196 tvis
.item
.state
= TVIS_EXPANDED
; // it must be expanded to show the first layer
2197 tvis
.item
.stateMask
= TVIS_EXPANDED
;
2198 h_PTroot
= TreeView_InsertItem(hT
,&tvis
);
2199 tvis
.item
.mask
= TVIF_TEXT
| TVIF_CHILDREN
; // don't expand any other layers
2200 i
= root_param
->get_size();
2202 MakeBL(h_PTroot
, root_param
->get(i
));
2203 // sort this level of the tree alphabetically
2204 // CallWindowProc(wTreeView,hT,TVM_SORTCHILDREN,(WPARAM) 0,(LPARAM) h_PTroot);
2205 ShowWindow(hT
,SW_SHOW
);
2209 // performs endian byteswapping the hard way, for a Data dump
2210 void FillDataX(char* t
,char C
,bx_bool doHex
)
2212 char *d
= tmpce
+ 100; // the beginning of tmpce is being used by ShowData/SD_Thread
2213 if (isLittleEndian
== FALSE
|| doHex
== FALSE
)
2214 d
= t
+ strlen(t
); // bigendian can always be appended directly
2217 if (isprint(C
) == 0)
2222 *d
= AsciiHex
[ 2* (unsigned char)C
];
2223 d
[1] = AsciiHex
[ 1+ 2* (unsigned char)C
];
2225 if (isLittleEndian
!= FALSE
) // little endian => reverse hex digits
2228 strcpy(t
,d
); // so append the new bytes to the FRONT of t
2233 // do the ShowData display work asynchronously, as a thread
2238 LV_ITEM lvi
= {LVIF_TEXT
,0,0,0,0,(LPSTR
) 0,80,0,0};
2240 doDumpRefresh
= FALSE
;
2241 // ShowWindow(hL[2],SW_HIDE); // Hiding the windows causes way too much flash
2242 CallWindowProc(wListView
,hL
[2],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
2244 lviG
.pszText
= tmpce
;
2246 lviG
.iGroupId
= 8; // MemDump "group" is always blank
2248 x
= DataDump
; // data dumps are ALWAYS 4K
2249 for(i
= 0 ; i
< 4096 ; i
+= 16)
2251 if (In64Mode
== FALSE
)
2252 sprintf(tmpce
,"0x%08X",(Bit32u
) (DumpStart
+ i
));
2254 sprintf(tmpce
,"0x%016I64X",DumpStart
+ i
);
2256 int L
= CallWindowProc(wListView
,hL
[2],LVM_INSERTITEM
,(WPARAM
) 0,(LPARAM
) &lviG
);
2261 for(unsigned int y
= 0 ; y
< 16 ; y
++)
2263 if ((DumpInAsciiMode
& 1) != 0)
2264 FillDataX(tmpcf
,x
[y
],FALSE
);
2266 if ((DumpInAsciiMode
& 2) != 0)
2268 FillDataX(tmpce
,x
[y
],TRUE
);
2269 if (((y
+ 1) & (DumpAlign
- 1)) == 0)
2271 lvi
.pszText
= tmpce
;
2272 lvi
.iSubItem
= y
+2-DumpAlign
;
2273 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) L
,(LPARAM
) &lvi
);
2274 *tmpce
= 0; // FillDataX APPENDS, so you need to clear the buffer
2278 lvi
.pszText
= tmpcf
;
2280 if ((DumpInAsciiMode
& 1) != 0)
2281 CallWindowProc(wListView
,hL
[2],LVM_SETITEMTEXT
,(WPARAM
) L
,(LPARAM
) &lvi
);
2282 x
+= 16; // bump to the next row of data
2285 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE
);
2286 if (PrevDAD
!= DumpAlign
)
2288 for(i
= 1 ; i
< 17 ; i
++)
2290 // if dumping ONLY in ascii, 0 out ALL the other columns
2291 if (((i
- 1) & (DumpAlign
- 1)) == 0 && (DumpInAsciiMode
& 2) != 0)
2292 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, i
, LVSCW_AUTOSIZE
);
2293 else // force the width of unused columns to 0
2294 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, i
, 0);
2297 PrevDAD
= DumpAlign
;
2298 ShowWindow(hL
[2],SW_SHOW
);
2302 // build Register "display" names from lower case names
2303 // (must build the pointer list while building the names)
2308 p
= RDispName
[0]; // first storage location
2309 for (int i
=0; i
< 41; i
++)
2311 RDispName
[i
] = p
; // create the Name pointer
2312 c
= RegLCName
[i
]; // Register name in lower case
2317 *(p
++) = UCtable
[(int) *(c
++)]; // use lookup tbl for uppercase
2328 // generic initialization routine -- called once, only at startup
2336 BX_CPU(i
)->mode_break
= FALSE
;
2337 // divide up the pre-allocated char buffer into smaller pieces
2338 p
= bigbuf
+ outbufSIZE
; // point at the end of preallocated mem
2339 p
-= 200; // 200 bytes is enough for all the register names
2342 DataDump
= p
; // storage for 4K memory dumps
2343 p
-= OutWinCnt
; // 10K for Output Window buffer
2348 p
-= 80; // command history buffers are 80b each
2349 CmdHistory
[i
] = p
; // set up 64 of them (5120b)
2350 *p
= 0; // and clear each one
2352 p
-= STACK_ENTRIES
* 8; // usually a 400 byte buffer for the stack values
2361 AsciiHex
= p
; // storage for the binary->ascii table
2362 p
-= 512; // 2 "hex" bytes per byte value
2365 i
= TOT_REG_NUM
; // fake up a color table -- there are just enough, currently
2366 int j
= 7; // color 7 = orange
2369 // change color when the loop goes below the base register number
2370 // if (i == TRXR) --j; // 5 TRX registers -- currently don't exist
2371 if (i
== DR0_Rnum
) --j
; // 6 Debug
2372 else if (i
== XMM0_Rnum
) --j
; // 8 or 16 XMM
2373 else if (i
== ST0_Rnum
) --j
; // 8 MMX/FPU
2374 else if (i
== CR0_Rnum
) --j
; // EFER and CR
2375 else if (i
== GDTRnum
) --j
; // Sys Registers
2376 else if (i
== CS_Rnum
) --j
; // Segments
2377 else if (i
== EAX_Rnum
) --j
; // GP Registers (32b)
2378 // below EAX is 64bit GP Registers and EFLAGS
2382 MakeXlatTables(); // create UpperCase and AsciiHex translation tables
2383 MakeRDnames(); // create Rnames from lower-case register names
2384 InitRegObjects(); // get/store all the bx_param_num_c objects for the registers
2387 // Autosize "fixed size" ListView columns, every time the font changes.
2388 // This also runs once during the init sequence.
2391 ResizeColmns
= TRUE
; // force the "variable size" columns to resize, too
2392 // resize the "fixed size" columns (once only, perhaps)
2393 if (doOneTimeInit
== TRUE
)
2394 CallWindowProc(wListView
, hL
[1], LVM_SETCOLUMNWIDTH
, 1, LVSCW_AUTOSIZE_USEHEADER
); // "bytes" column
2395 CallWindowProc(wListView
, hL
[0], LVM_SETCOLUMNWIDTH
, 0, LVSCW_AUTOSIZE_USEHEADER
); // RegName column
2397 for (int i
= 0; i
< 17; i
++)
2398 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, i
, LVSCW_AUTOSIZE_USEHEADER
);
2401 // exit GDT/IDT/Paging/Stack/Tree -- back to the MemDump window
2404 LV_COLUMN lvgc
= {LVCF_TEXT
,0,0,tmpcb
};
2405 ShowWindow(hT
,SW_HIDE
);
2406 ShowWindow(hL
[2],SW_SHOW
);
2407 DViewMode
= VIEW_MEMDUMP
; // returning to MemDump mode
2408 CallWindowProc(wTreeView
,hT
,TVM_DELETEITEM
,(WPARAM
) 0,(LPARAM
) TVI_ROOT
);
2409 // need to fix the MemDump column "names"
2410 strcpy (tmpcb
,"0"); // rebuild header for col 1
2411 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 1,(LPARAM
) &lvgc
);
2412 // headers for cols 1 to 5, are just numbers 0 to 4
2414 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 2,(LPARAM
) &lvgc
);
2416 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 3,(LPARAM
) &lvgc
);
2417 strcpy (tmpcb
,"Ascii"); // rebuild header for col 17
2418 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 17,(LPARAM
) &lvgc
);
2419 if (DumpInitted
== FALSE
)
2421 // GDT/IDT/PAGING data may be in the window
2422 CallWindowProc(wListView
,hL
[2],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
2423 strcpy (tmpcb
,"Address"); // "generic" header for col 0
2424 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 0,(LPARAM
) &lvgc
);
2425 int i
= 17; // never change the size of the last column
2426 while (--i
>= 0) // can't repopulate -- just resize
2427 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, i
, LVSCW_AUTOSIZE_USEHEADER
);
2431 strcpy (tmpcb
,DC0txt
[DumpMode
]); // "real" header for col 0
2432 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 0,(LPARAM
) &lvgc
);
2433 PrevDAD
= 0; // force a column resize
2434 ShowData(); // repopulates & resizes all columns
2439 // refill whichever "data window" (hL[2]) is active -- or param_tree
2440 void RefreshDataWin()
2445 if (DumpInitted
!= FALSE
)
2448 ShowWindow(hL
[2],SW_SHOW
);
2460 PStackLA
= 1; // flag to force a full stack refresh
2468 // performs tasks whenever the simulation "breaks"
2471 int i
= EFER_Rnum
+ 1;
2472 // check if Ptime has changed
2473 NewPtime
= bx_pc_system
.time_ticks();
2474 if (PrevPtime
== NewPtime
) // if not, nothing really changed
2476 UpdateStatus(); // Updates if there really was a status change, at least
2479 // display the new ptime on the status bar
2480 sprintf (tmpcb
,"t= %I64d",NewPtime
);
2481 SendMessage(hS_S
,SB_SETTEXT
,2,(LPARAM
) tmpcb
);
2482 PrevPtime
= NewPtime
;
2484 // remember register values from before the last run
2487 ladrmin
= ladrmax
; // invalidate any old linear->phys mapping
2489 // then detect current CPU mode the *right* way -- look for changes
2490 // TODO: create param Objects for CS.d_b and cpu_mode for each CPU
2491 CpuMode
= BX_CPU(CurrentCPU
)->get_cpu_mode();
2492 if (CpuMode
== BX_MODE_LONG_64
)
2494 if (In64Mode
== FALSE
) // Entering LongMode?
2496 CpuModeChange
= TRUE
;
2498 In32Mode
= TRUE
; // In32Mode must be TRUE in LongMode
2499 ResizeColmns
= TRUE
; // if so, some formatting has changed
2505 bx_bool d_b
= BX_CPU(CurrentCPU
)->sregs
[BX_SEG_REG_CS
].cache
.u
.segment
.d_b
;
2506 if (In32Mode
!= d_b
|| In64Mode
!= FALSE
)
2508 CpuModeChange
= TRUE
;
2513 if (CpuModeChange
!= FALSE
)
2515 if (In64Mode
== FALSE
)
2516 EnableMenuItem (hOptMenu
, CMD_EREG
, MF_GRAYED
);
2518 EnableMenuItem (hOptMenu
, CMD_EREG
, MF_ENABLED
);
2519 BottomAsmLA
= ~0; // force an ASM autoload
2520 StatusChange
= TRUE
;
2522 doUpdate(); // do a full "autoupdate"
2523 if (doDumpRefresh
!= FALSE
)
2527 int HexFromAsk(char* ask
,char* b
) // this routine converts a user-typed hex string into binary bytes
2528 { // it ignores any bigendian issues -- binary is converted front to end as chars
2534 if (strlen(ask
+ i
) < 2)
2536 if (!sscanf(ask
+ i
,"%02X",&C
))
2544 bx_bool
FindHex(unsigned char* b1
,int bs
,unsigned char* b2
,int by
)
2546 // search bs bytes of b1
2547 for(int i
= 0 ; i
< bs
; i
++) // TODO: this loop could be a little more efficient.
2548 { // -- it just scans an input byte string against DataDump memory
2549 bx_bool Match
= TRUE
;
2550 for(int y
= 0 ; y
< by
; y
++)
2552 if (b1
[i
+ y
] != b2
[y
])
2564 // load new memory for a MemDump
2565 // newDS = illegal (1) is a flag to ask the user for a DumpStart address
2566 bx_bool
InitDataDump(int dType
, Bit64u newDS
)
2568 bx_bool retval
= TRUE
;
2569 bx_bool MsgOnErr
= FALSE
;
2571 if (((int) newDS
& 0xf) != 0) // legal addys must be on 16byte boundary
2573 if (In64Mode
== FALSE
)
2574 sprintf(tmpcb
,"0x%X",(Bit32u
) DumpStart
);
2576 sprintf(tmpcb
,"0x%I64X",DumpStart
);
2577 if (AskText(hY
,"4K Memory Dump","4K Memory Dump -- Enter Address (use 0x for hex):",tmpcb
,0) == FALSE
)
2580 while (*s
== ' ') // allow user to enter whitespace
2582 if (*s
== '0' && (s
[1] =='X' || s
[1] == 'x')) // and either hex or decimal
2583 sscanf (s
+2,"%I64X",&newDS
);
2585 sscanf (s
,"%I64d",&newDS
);
2586 newDS
&= ~15; // force Mem Dump to be 16b aligned
2590 // load 4k DataDump array from bochs emulated linear (dType=0) or physical memory
2593 // cannot read linear mem across a 4K boundary -- so break the read in two
2594 // -- calculate location of 4K boundary (h):
2595 unsigned int len
= (int) newDS
& 0xfff;
2596 unsigned int i
= 4096 - len
;
2597 Bit64u h
= newDS
+ i
;
2598 retval
= ReadBxLMem (newDS
,i
,(Bit8u
*)DataDump
);
2599 if (retval
!= FALSE
&& len
!= 0)
2600 retval
= ReadBxLMem (h
,len
,(Bit8u
*)DataDump
+ i
);
2603 retval
= (bx_bool
) bx_mem
.dbg_fetch_mem( BX_CPU(CurrentCPU
),
2604 (bx_phy_address
)newDS
, 4096, (Bit8u
*)DataDump
);
2605 if (retval
== FALSE
)
2607 // assume that the DataDump array is still valid -- fetch_mem should error without damage
2608 if (MsgOnErr
!= FALSE
)
2609 MessageBox (hY
,"Address range was not legal memory","Memory Error", MB_ICONERROR
);
2612 EnableMenuItem (hCmdMenu
, CMD_WPTWR
, MF_GRAYED
);
2613 EnableMenuItem (hCmdMenu
, CMD_WPTRD
, MF_GRAYED
);
2614 DumpInitted
= TRUE
; // OK to refresh the Dump window in the future (it has data)
2616 DumpMode
= dType
; // finalize dump mode, since it worked
2617 // update column 0 to say whether its physmem or linear
2618 LV_COLUMN lvgc
= {LVCF_TEXT
,0,0,DC0txt
[DumpMode
]};
2619 CallWindowProc(wListView
,hL
[2],LVM_SETCOLUMN
,(WPARAM
) 0,(LPARAM
) &lvgc
);
2620 ShowMemData(); // Display DataDump using preset parameters
2624 void SetSizeIOS(int WinSizeX
, int WinSizeY
)
2628 // calculate the height/width of typical "glyphs" in the font
2629 HDC hdc
= GetDC (hS_S
);
2630 GetTextMetrics (hdc
, &tm
);
2631 ReleaseDC (hS_S
, hdc
);
2632 OneCharWide
= tm
.tmAveCharWidth
;
2633 j
= tm
.tmAveCharWidth
* 72; // status bar contains about 72 char positions (without eflags)
2634 if (j
> WinSizeX
/2) // leave half the status bar for the eflags
2636 i
= j
*5 / 12; // predefined proportions of Status "subwindows" = 2:5:5
2638 int ptimepos
= modepos
+ i
;
2639 int eflpos
= ptimepos
+ i
;
2640 int p
[4] = {modepos
,ptimepos
,eflpos
,-1};
2642 // then set the dimensions of the I, O, and S child windows
2643 j
= tm
.tmHeight
+ tm
.tmExternalLeading
; // input window is the height of a char
2645 int sY
= j
+ i
; // status window and buttons are 50% taller
2647 if (ShowButtons
!= FALSE
)
2649 // position the 5 command buttons
2652 SetWindowPos(hBTN
[1],0,0,0,i
,LstTop
,SWP_SHOWWINDOW
);
2653 SetWindowPos(hBTN
[2],0,i
,0,i
,LstTop
,SWP_SHOWWINDOW
);
2654 SetWindowPos(hBTN
[3],0,i
*2,0,i
,LstTop
,SWP_SHOWWINDOW
);
2655 SetWindowPos(hBTN
[4],0,i
*3,0,i
,LstTop
,SWP_SHOWWINDOW
);
2656 SetWindowPos(hBTN
[0],0,i
*4,0,WinSizeX
- 4*i
,LstTop
,SWP_SHOWWINDOW
);
2660 ShowWindow(hBTN
[0],SW_HIDE
);
2661 ShowWindow(hBTN
[1],SW_HIDE
);
2662 ShowWindow(hBTN
[2],SW_HIDE
);
2663 ShowWindow(hBTN
[3],SW_HIDE
);
2664 ShowWindow(hBTN
[4],SW_HIDE
);
2668 // MultiCPU simulation -- need CPU button row, too.
2670 unsigned int CPUn
= 0;
2671 i
= WinSizeX
/ TotCPUs
;
2672 while (CPUn
< TotCPUs
- 1)
2674 SetWindowPos(hCPUt
[CPUn
],0,HorPos
,LstTop
,i
,sY
,SWP_SHOWWINDOW
);
2678 // use up any extra pixels on the last button
2679 SetWindowPos(hCPUt
[CPUn
],0,HorPos
,LstTop
,WinSizeX
-HorPos
,sY
,SWP_SHOWWINDOW
);
2682 // The status win may not use all of its space: overlap lists or Input by STATUS_WIN_OVERLAP pixels
2683 i
= WinSizeY
- sY
- j
;
2684 if (ShowIOWindows
== FALSE
)
2686 // need to keep caret functions in PAIRS
2687 CallWindowProc(*wEdit
, hE_I
,WM_KILLFOCUS
,(WPARAM
) 0,0); // destroy Input caret
2688 ShowWindow(hE_I
,SW_HIDE
);
2689 ShowWindow(hE_O
,SW_HIDE
);
2690 ListVerticalPix
= WinSizeY
- sY
- LstTop
+ STATUS_WIN_OVERLAP
;
2694 CallWindowProc(*wEdit
, hE_I
,WM_SETFOCUS
,(WPARAM
) 0,0); // create Input caret
2695 ListVerticalPix
= (WinSizeY
* 3) >> 2; // 3/4 height
2696 SetWindowPos(hE_I
,0,2,i
+ STATUS_WIN_OVERLAP
,WinSizeX
,j
,SWP_SHOWWINDOW
);
2697 SetWindowPos(hE_O
,0,0,ListVerticalPix
+ LstTop
,WinSizeX
,
2698 i
- ListVerticalPix
- LstTop
+ (STATUS_WIN_OVERLAP
/2),SWP_SHOWWINDOW
);
2700 SetWindowPos(hS_S
,0,0,WinSizeY
- sY
,WinSizeX
,sY
,SWP_SHOWWINDOW
);
2701 SendMessage(hS_S
,SB_SETPARTS
,4,(LPARAM
)p
);
2702 SetFocus(hE_O
); // focus on Output window works best
2705 // hh is the handle to the main parent window -- hY may not work yet
2706 void MoveLists(HWND hh
)
2709 unsigned int StrtCol
[3] = {0,0,0};
2710 // use DockOrder to figure out the start columns of each list
2711 // starting column of 2nd list = width of first list
2712 i
= ListWidthPix
[(DockOrder
>> 8) -1];
2713 j
= ((DockOrder
>>4)& 3) -1; // index of 2nd list
2716 k
= i
+ ListWidthPix
[j
]; // width of first + second
2717 StrtCol
[(DockOrder
& 3) -1] = k
;
2719 // the center listview must be the only one with a border
2720 if (CurCenterList
!= j
)
2722 // remove the border on the previous center list, and put it on the new one
2723 SetWindowLong ( hL
[CurCenterList
], GWL_STYLE
, LVStyle
[CurCenterList
]);
2724 SetWindowLong ( hL
[j
], GWL_STYLE
, LVStyle
[j
] | WS_BORDER
);
2726 // the tree window should have the same border as the data window --
2727 // but unfortunately, SetWindowLong does not work properly on the treeview!
2729 // k=SetWindowLong ( hT, GWL_STYLE, TVS_DISABLEDRAGDROP | TVS_HASLINES | TVS_HASBUTTONS | WS_CHILD | WS_BORDER );
2731 // k=SetWindowLong ( hT, GWL_STYLE, TVS_DISABLEDRAGDROP | TVS_HASLINES | TVS_HASBUTTONS | WS_CHILD );
2734 // On at least some versions of Win, you cannot mess with the positions
2735 // of subclassed ListView controls that still HAVE DATA IN THEM.
2736 // Therefore, delete all ListView data --
2737 // then refresh the 3 main ListView windows afterward
2739 CallWindowProc(wListView
,hL
[2],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
2740 CallWindowProc(wListView
,hL
[1],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
2741 CallWindowProc(wListView
,hL
[0],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
2743 SetWindowPos(hL
[0],0,StrtCol
[0],LstTop
,ListWidthPix
[0],ListVerticalPix
,SWP_HIDEWINDOW
);
2744 SetWindowPos(hL
[1],0,StrtCol
[1],LstTop
,ListWidthPix
[1],ListVerticalPix
,SWP_HIDEWINDOW
);
2745 SetWindowPos(hL
[2],0,StrtCol
[2],LstTop
,ListWidthPix
[2],ListVerticalPix
,SWP_HIDEWINDOW
);
2746 // tree window = same size/position as dump window
2747 SetWindowPos(hT
,0,StrtCol
[2],LstTop
,ListWidthPix
[2],ListVerticalPix
,SWP_HIDEWINDOW
);
2749 // calculate the SCREEN coordinates of the two "divider bars"
2753 ClientToScreen(hh
,&pt
);
2754 BarScrx
[0] = (unsigned short) pt
.x
;
2757 ClientToScreen(hh
,&pt
);
2758 BarScrx
[1] = (unsigned short) pt
.x
;
2760 // size the last column of each list = total width of that list
2761 CallWindowProc(wListView
, hL
[0], LVM_SETCOLUMNWIDTH
, 2, ListWidthPix
[0]);
2762 CallWindowProc(wListView
, hL
[1], LVM_SETCOLUMNWIDTH
, 2, ListWidthPix
[1]);
2763 CallWindowProc(wListView
, hL
[2], LVM_SETCOLUMNWIDTH
, 17, ListWidthPix
[2]);
2764 doAutoSize(); // autosize all other ListView columns for the new width
2765 BottomAsmLA
= ~0; // force an ASM autoload next time, to resize it
2766 PrevDAD
= 0; // force Data list autosize on next refresh
2767 doDumpRefresh
= TRUE
; // force a data window refresh on a break
2768 if (AtBreak
!= FALSE
) // can't refresh the windows until a break!
2770 doUpdate(); // refresh the ASM and Register windows
2771 RefreshDataWin(); // and whichever data window is up
2774 BottomAsmLA
= ~0; // force an ASM autoload, to repaint
2777 // redraw/recalculate everything if the old window sizes are invalid
2778 void doShowAll(HWND hh
)
2781 GetClientRect(hh
,&rc
);
2782 SetSizeIOS((int)rc
.right
,(int)rc
.bottom
); // window sizes are font-dependent
2783 // must clear listviews before MoveLists()
2784 CallWindowProc(wListView
,hL
[2],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
2785 CallWindowProc(wListView
,hL
[1],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
2786 CallWindowProc(wListView
,hL
[0],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
2791 // User is changing which registers are displaying in the Register list
2792 void ToggleSeeReg(int LW
)
2794 int i
= LW
- CMD_EREG
;
2797 if (i
== 4 || i
== 5)
2798 ResizeColmns
= TRUE
; // may need to resize the register value column
2801 if (SeeReg
[i
] == FALSE
)
2802 CheckMenuItem (hOptMenu
, LW
, MF_UNCHECKED
);
2804 CheckMenuItem (hOptMenu
, LW
, MF_CHECKED
);
2805 if (AtBreak
!= FALSE
)
2806 LoadRegList(); // do a register window update
2810 void doNewWSize(int i
)
2812 // DumpAlign is the "wordsize" in bytes -- need to "calculate" the power of 2
2814 if (DumpAlign
== 2) j
= 1;
2815 else if (DumpAlign
== 4) j
= 2;
2816 else if (DumpAlign
== 8) j
= 3;
2817 else if (DumpAlign
== 16) j
= 4;
2820 // the wordsize popup is the 11th entry in the Opt menu -- COUNTING SEPARATORS
2821 HMENU wsMenu
= GetSubMenu (hOptMenu
, WS_POPUP_IDX
);
2822 CheckMenuItem (wsMenu
, j
, MF_UNCHECKED
| MF_BYPOSITION
);
2823 CheckMenuItem (wsMenu
, i
, MF_CHECKED
| MF_BYPOSITION
);
2825 if (DViewMode
== VIEW_MEMDUMP
&& DumpInitted
!= FALSE
)
2832 EnableMenuItem (hCmdMenu
, CMD_WPTWR
, MF_GRAYED
);
2833 EnableMenuItem (hCmdMenu
, CMD_WPTRD
, MF_GRAYED
);
2834 if (DViewMode
== VIEW_GDT
|| (GDT_Len
& 7) != 7 || (unsigned) GDT_Len
>= 0x10000)
2836 if (DViewMode
!= VIEW_GDT
)
2837 MessageBox(hY
,"GDT limit is illegal",0,MB_OK
);
2842 ShowWindow(hT
,SW_HIDE
);
2843 CallWindowProc(wTreeView
,hT
,TVM_DELETEITEM
,(WPARAM
) 0,(LPARAM
) TVI_ROOT
);
2844 // force all column widths to 0, then autosize later
2846 DViewMode
= VIEW_GDT
; // displaying a GDT
2852 EnableMenuItem (hCmdMenu
, CMD_WPTWR
, MF_GRAYED
);
2853 EnableMenuItem (hCmdMenu
, CMD_WPTRD
, MF_GRAYED
);
2854 if (DViewMode
== VIEW_IDT
|| (IDT_Len
& 3) != 3 || (unsigned) IDT_Len
>= 0x10000)
2856 if (DViewMode
!= VIEW_IDT
)
2857 MessageBox(hY
,"IDT limit is illegal",0,MB_OK
);
2862 ShowWindow(hT
,SW_HIDE
);
2863 CallWindowProc(wTreeView
,hT
,TVM_DELETEITEM
,(WPARAM
) 0,(LPARAM
) TVI_ROOT
);
2865 DViewMode
= VIEW_IDT
; // displaying an IDT
2871 EnableMenuItem (hCmdMenu
, CMD_WPTWR
, MF_GRAYED
);
2872 EnableMenuItem (hCmdMenu
, CMD_WPTRD
, MF_GRAYED
);
2873 if (DViewMode
== VIEW_PAGING
)
2877 ShowWindow(hT
,SW_HIDE
);
2878 CallWindowProc(wTreeView
,hT
,TVM_DELETEITEM
,(WPARAM
) 0,(LPARAM
) TVI_ROOT
);
2880 DViewMode
= VIEW_PAGING
; // currently displaying Paging info
2886 EnableMenuItem (hCmdMenu
, CMD_WPTWR
, MF_GRAYED
);
2887 EnableMenuItem (hCmdMenu
, CMD_WPTRD
, MF_GRAYED
);
2888 if (DViewMode
== VIEW_STACK
)
2892 ShowWindow(hT
,SW_HIDE
);
2893 CallWindowProc(wTreeView
,hT
,TVM_DELETEITEM
,(WPARAM
) 0,(LPARAM
) TVI_ROOT
);
2894 StackSized
= 0; // need to autosize the stack display columns
2895 PStackLA
= 1; // flag to force a full refresh
2897 DViewMode
= VIEW_STACK
; // currently displaying stack
2903 EnableMenuItem (hCmdMenu
, CMD_WPTWR
, MF_GRAYED
);
2904 EnableMenuItem (hCmdMenu
, CMD_WPTRD
, MF_GRAYED
);
2905 if (DViewMode
== VIEW_PTREE
)
2909 DViewMode
= VIEW_PTREE
; // currently displaying param_tree
2910 CallWindowProc(wListView
,hL
[2],LVM_DELETEALLITEMS
,(WPARAM
) 0,(LPARAM
) 0);
2911 FillPTree(); // get all info from param_tree into tree-view window
2920 // prepare to read ASM column 2, then set Selected state of each line on/off
2921 LV_ITEM lvi
= {LVIF_STATE
,0,2,0,LVIS_SELECTED
,(LPSTR
) tmpcb
,100,0,0};
2922 if (DumpHasFocus
== FALSE
)
2924 if (AskText(hY
,"Find text in mnemonic lines","ASM Search text:",tmpcb
,0) == FALSE
)
2926 if (strchr(tmpcb
,'*') == 0 && strchr(tmpcb
,'?') == 0)
2927 sprintf(tmpcd
,"*%s*",tmpcb
);
2929 strcpy(tmpcd
,tmpcb
);
2931 if (UprCase
!= FALSE
) // convert search string to uppercase if ASM is that way
2933 L
= CallWindowProc(wListView
,hL
[1],LVM_GETITEMCOUNT
,(WPARAM
) 0,(LPARAM
) 0);
2934 for(i
= 0 ; i
< L
; i
++)
2936 lvi
.mask
= LVIF_TEXT
;
2938 // get column 2 text from ASM window
2939 CallWindowProc(wListView
,hL
[1],LVM_GETITEMTEXT
,(WPARAM
) i
,(LPARAM
) &lvi
);
2940 lvi
.mask
= LVIF_STATE
;
2941 lvi
.state
= 0; // assume unselected
2942 // if it's a match, set the state to Selected
2943 if (IsMatching(tmpcb
,tmpcd
,TRUE
))
2944 lvi
.state
= LVIS_SELECTED
;
2945 CallWindowProc(wListView
,hL
[1],LVM_SETITEMSTATE
,(WPARAM
) i
,(LPARAM
) &lvi
);
2950 if (AskText(hY
,"Memory Dump Search",
2951 "Sequential hex bytes (e.g 00FEFA - no spaces), or ascii string (max. 16b):",tmpcb
,0) == FALSE
)
2954 int by
= HexFromAsk(tmpcb
,tmpcd
); // by = len of binary search string
2956 // Find in all rows of 16 bytes -- must do rows, so they can be selected
2957 for(i
= 0,L
= 0 ; i
< 4096 ; i
+= 16, L
++)
2960 lvi
.state
= 0; // assume unselected
2961 // if it's a match, change state to Selected
2962 if (by
!= 0 && FindHex((unsigned char *)DataDump
+ i
,16,(unsigned char *)tmpcd
,by
))
2963 lvi
.state
= LVIS_SELECTED
;
2964 CallWindowProc(wListView
,hL
[2],LVM_SETITEMSTATE
,(WPARAM
) L
,(LPARAM
) &lvi
);
2967 // Try ascii for additional matches and selected lines
2968 lvi
.state
= LVIS_SELECTED
;
2969 strcpy(tmpcd
,tmpcb
);
2971 for(i
= 0,L
= 0 ; i
< 4096 ; i
+= 16, L
++)
2974 if (by
!= 0 && FindHex((unsigned char *)DataDump
+ i
,16,(unsigned char *)tmpcd
,by
))
2975 CallWindowProc(wListView
,hL
[2],LVM_SETITEMSTATE
,(WPARAM
) L
,(LPARAM
) &lvi
);
2984 sprintf (tmpcb
,"%d",PrevStepNSize
);
2985 if (AskText(hY
,"Singlestep N times","Number of steps (use 0x for hex):",tmpcb
,0) == FALSE
)
2987 while (*s
== ' ') // allow user to enter whitespace
2989 if (*s
== '0' && (s
[1] =='X' || s
[1] == 'x')) // and either hex or decimal
2990 sscanf (s
+2,"%x",&i
);
2997 StatusChange
= TRUE
;
2998 bx_dbg_stepN_command(i
);
3000 StatusChange
= TRUE
;
3007 MessageBox(hY
,"With more than 1000 lines in the ASM window, be careful not to minimize the app.\r\nIt will be very slow to reopen.",
3008 "Friendly warning:",MB_ICONINFORMATION
);
3011 // User wants a custom disassembly
3015 int NumLines
= DefaultAsmLines
;
3017 sprintf (tmpcb
,"0x%I64X",CurrentAsmLA
);
3018 if (AskText(hY
,"Disassemble",
3019 "Disassemble -- Enter Linear Start Address (use 0x for hex):",tmpcb
,0) == FALSE
)
3021 while (*s
== ' ') // allow user to enter whitespace
3023 if (*s
== '0' && (s
[1] =='X' || s
[1] == 'x')) // and either hex or decimal
3024 sscanf (s
+2,"%I64x",&h
);
3026 sscanf (s
,"%I64d",&h
);
3027 sprintf (tmpcb
,"%d",NumLines
);
3028 if (AskText(hY
,"Disassemble","Number of lines: (Max. 2048)",tmpcb
,0) == FALSE
)
3030 sscanf (tmpcb
,"%d",&NumLines
);
3031 if (NumLines
<= 0 || NumLines
> 2048)
3033 if (NumLines
> 1000 && FWflag
== FALSE
)
3035 FillAsm(h
, NumLines
);
3036 // Set the scroll limits for the new ASM window
3037 BottomAsmLA
= *AsmLA
;
3038 int j
= bottommargin
; // try to use this bottom margin on ASM window
3039 if (j
> AsmLineCount
)
3041 TopAsmLA
= AsmLA
[AsmLineCount
- j
]; //TopAsmLA is the scroll point
3045 // Toggle all "selected" items as linear breakpoint on the ASM window
3048 int L
= CallWindowProc(wListView
, hL
[1], LVM_GETNEXTITEM
,(WPARAM
) -1,MAKELPARAM(LVNI_SELECTED
, 0));
3053 while (i
< BreakCount
&& iExist
< 0)
3055 if (BrkLAddr
[i
] == AsmLA
[L
])
3062 bx_dbg_del_lbreak(BrkIdx
[iExist
]);
3063 i
= iExist
; // also compress it out of the local list
3064 while (++i
< BreakCount
)
3066 BrkLAddr
[i
-1] = BrkLAddr
[i
];
3067 BrkIdx
[i
-1] = BrkIdx
[i
];
3073 bx_address nbrk
= (bx_address
) AsmLA
[L
];
3074 // Set a "regular" bochs linear breakpoint to that address
3075 int BpId
= bx_dbg_lbreakpoint_command(bkRegular
, nbrk
);
3078 // insertion sort the new Brkpt into the local list
3080 while (i
>= 0 && BrkLAddr
[i
] > nbrk
)
3082 BrkLAddr
[i
+1] = BrkLAddr
[i
];
3083 BrkIdx
[i
+1] = BrkIdx
[i
];
3086 BrkLAddr
[i
+1] = nbrk
;
3091 // start the next search at item L
3092 L
= CallWindowProc(wListView
, hL
[1], LVM_GETNEXTITEM
,(WPARAM
) L
,MAKELPARAM(LVNI_SELECTED
, 0));
3096 void SetWatchpoint(unsigned * num_watchpoints
, bx_phy_address
* watchpoint
)
3099 int i
= (int) *num_watchpoints
;
3100 // the list is unsorted -- test all of them
3103 if (watchpoint
[i
] == SelectedDataAddress
)
3111 // existing watchpoint, remove by copying the list down
3112 while (++iExist1
< (int) *num_watchpoints
)
3113 watchpoint
[iExist1
- 1] = watchpoint
[iExist1
];
3114 -- *num_watchpoints
;
3118 // Set a watchpoint to last clicked address -- the list is not sorted
3119 if (*num_watchpoints
>= 16)
3120 MessageBox (hY
,"Too many of that type of watchpoint. Max. 16",
3121 "Table Overflow", MB_ICONERROR
) ;
3123 watchpoint
[(*num_watchpoints
)++] = (bx_phy_address
) SelectedDataAddress
;
3127 // Main Window Proc for our Dialog
3128 LRESULT CALLBACK
B_WP(HWND hh
,UINT mm
,WPARAM ww
,LPARAM ll
)
3131 extern unsigned num_write_watchpoints
;
3132 extern unsigned num_read_watchpoints
;
3133 extern bx_phy_address write_watchpoint
[];
3134 extern bx_phy_address read_watchpoint
[];
3140 HFONT hF
= (HFONT
)GetStockObject(OEM_FIXED_FONT
);
3141 HFONT hF2
= (HFONT
)GetStockObject(DEFAULT_GUI_FONT
);
3144 char* txt0
[] = {"Reg Name","Hex Value","Decimal"};
3145 LV_COLUMN lvc
= {LVCF_SUBITEM
| LVCF_TEXT
,LVCFMT_LEFT
,0,txt0
[0]};
3146 hL
[0] = CreateWindowEx(0,"sLV","",LVStyle
[0],0,0,1,1,hh
,(HMENU
)1001,GetModuleHandle(0),0);
3147 // Note; WM_CREATE only happens once, so don't bother eliminating these SendMessage macros
3148 ListView_InsertColumn(hL
[0],0,&lvc
);
3149 lvc
.pszText
= txt0
[1];
3150 ListView_InsertColumn(hL
[0],1,&lvc
);
3151 lvc
.pszText
= txt0
[2];
3152 ListView_InsertColumn(hL
[0],2,&lvc
);
3154 // Enable the groupID's for the register window
3156 // GroupID's are only supported on XP or higher -- verify Win Version
3157 // the group stuff may COMPILE correctly, but still may fail at runtime
3158 Bit8u MajWinVer
, MinWinVer
;
3159 Bit32u PackedVer
= GetVersion();
3160 bx_bool Group_OK
= TRUE
;
3161 MajWinVer
= (Bit8u
)(PackedVer
& 0xff); // Major version # is in the LOW byte
3162 MinWinVer
= (Bit8u
)((PackedVer
>>8) & 0xff);
3163 if (MajWinVer
> 5 || (MajWinVer
== 5 && MinWinVer
>= 1) // is it XP or higher?
3165 wchar_t* txt
[] = {L
"General Purpose",L
"Segment",L
"Control",L
"MMX",L
"SSE",L
"Debug",L
"Test",L
"Other"};
3166 ListView_EnableGroupView(hL
[0],TRUE
);
3167 for(i
= 0 ; i
< 8 ; i
++)
3169 LVGROUP group1
= {0};
3170 group1
.cbSize
= sizeof(LVGROUP
);
3171 group1
.mask
= LVGF_HEADER
| LVGF_GROUPID
;
3172 group1
.pszHeader
= txt
[i
];
3173 group1
.iGroupId
= i
;
3174 ListView_InsertGroup(hL
[0], -1, &group1
);
3180 SendMessage(hL
[0], LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_FULLROWSELECT
| LVS_EX_DOUBLEBUFFER
,
3181 LVS_EX_FULLROWSELECT
| LVS_EX_DOUBLEBUFFER
);
3185 hL
[1] = CreateWindowEx(0,"sLV","",LVStyle
[1] | WS_BORDER
,0,0,1,1,hh
,(HMENU
)1000,GetModuleHandle(0),0);
3186 CurCenterList
= 1; // ASM window starts with the border
3187 char* txt3
[] = {"L.Address","Bytes","Mnemonic"};
3189 lvc
.pszText
= txt3
[0];
3190 ListView_InsertColumn(hL
[1],0,&lvc
);
3191 lvc
.pszText
= txt3
[1];
3192 ListView_InsertColumn(hL
[1],1,&lvc
);
3193 lvc
.pszText
= txt3
[2];
3194 ListView_InsertColumn(hL
[1],2,&lvc
);
3195 SendMessage(hL
[1], LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_FULLROWSELECT
| LVS_EX_DOUBLEBUFFER
,
3196 LVS_EX_FULLROWSELECT
| LVS_EX_DOUBLEBUFFER
);
3200 hE_I
= CreateWindowEx(0,"edit","",WS_CHILD
| WS_VISIBLE
,0,0,1,1,hh
,(HMENU
)1004,GetModuleHandle(0),0);
3201 // without AUTOHSCROLL, output window text is always supposed to wordwrap
3202 hE_O
= CreateWindowEx(0,"edit","",WS_VSCROLL
| WS_BORDER
| WS_CHILD
| WS_VISIBLE
| ES_MULTILINE
,0,0,1,1,hh
,(HMENU
)1003,GetModuleHandle(0),0);
3203 SendMessage(hE_I
,WM_SETFONT
,(WPARAM
)hF2
,MAKELPARAM(TRUE
,0));
3204 SendMessage(hE_O
,WM_SETFONT
,(WPARAM
)hF
,MAKELPARAM(TRUE
,0));
3205 // subclass both the edit windows together
3206 *wEdit
= (WNDPROC
) SetWindowLong (hE_I
,GWL_WNDPROC
,(long) ThisEditProc
);
3207 wEdit
[1] = (WNDPROC
) SetWindowLong (hE_O
,GWL_WNDPROC
,(long) ThisEditProc
);
3210 hS_S
= CreateWindowEx(0,STATUSCLASSNAME
,"",WS_CHILD
| WS_VISIBLE
,0,0,1,1,hh
,(HMENU
)1006,GetModuleHandle(0),0);
3211 SendMessage(hS_S
,WM_SETFONT
,(WPARAM
)hF2
,MAKELPARAM(TRUE
,0));
3212 int p
[4] = {100,250,400,-1};
3213 SendMessage(hS_S
,SB_SETPARTS
,4,(LPARAM
)p
);
3216 hL
[2] = CreateWindowEx(0,"sLV","",LVStyle
[2],0,0,1,1,hh
,(HMENU
)1002,GetModuleHandle(0),0);
3217 //SendMessage(hL[2],WM_SETFONT,(WPARAM)hF2,MAKELPARAM(TRUE,0));
3218 strcpy (bigbuf
, "Address");
3219 lvc
.pszText
= bigbuf
;
3220 ListView_InsertColumn(hL
[2],0,&lvc
);
3221 bigbuf
[1] = 0; // use bigbuf to create 1 byte "strings"
3222 for(i
= 1 ; i
< 17 ; i
++)
3225 *bigbuf
= i
- 1 + '0';
3227 *bigbuf
= i
- 11 + 'A';
3228 ListView_InsertColumn(hL
[2],i
,&lvc
);
3230 strcpy (bigbuf
, "Ascii");
3231 ListView_InsertColumn(hL
[2],17,&lvc
);
3232 SendMessage(hL
[2], LVM_SETEXTENDEDLISTVIEWSTYLE
, LVS_EX_FULLROWSELECT
| LVS_EX_DOUBLEBUFFER
,
3233 LVS_EX_FULLROWSELECT
| LVS_EX_DOUBLEBUFFER
);
3238 wchar_t* txt5
[] = {L
"16-bit code",L
"64-bit code",L
"32-bit code",L
"16-bit data",L
"64-bit data",L
"32-bit data",L
"Illegal"};
3239 ListView_EnableGroupView(hL
[2],TRUE
);
3240 LVGROUP group1
= {0};
3241 group1
.cbSize
= sizeof(LVGROUP
);
3242 group1
.mask
= LVGF_HEADER
| LVGF_GROUPID
;
3243 for(int i
= 0 ; i
< 9 ; i
++)
3245 group1
.pszHeader
= txt5
[i
];
3246 group1
.iGroupId
= i
;
3247 ListView_InsertGroup(hL
[2], -1, &group1
);
3251 hT
= CreateWindowEx(0,WC_TREEVIEW
,"",TVS_DISABLEDRAGDROP
| TVS_HASLINES
| TVS_HASBUTTONS
| WS_CHILD
| WS_BORDER
,
3252 0,0,1,1,hh
,(HMENU
)1010,GetModuleHandle(0),0);
3253 //SendMessage(hT,WM_SETFONT,(WPARAM)hF2,MAKELPARAM(TRUE,0));
3254 // Use the same messagehandler for the tree window as for ListViews
3255 wTreeView
= (WNDPROC
) SetWindowLong (hT
,GWL_WNDPROC
,(long) LVProc
);
3257 /* TotCPUs = SIM->get_param_num(BXPN_CPU_NPROCESSORS)->get() *
3258 SIM->get_param_num(BXPN_CPU_NCORES)->get() *
3259 SIM->get_param_num(BXPN_CPU_NTHREADS)->get();
3260 if (TotCPUs == 0 || TotCPUs > BX_MAX_SMP_THREADS_SUPPORTED)
3261 TotCPUs = 1; // this case will never happen
3263 TotCPUs
= BX_SMP_PROCESSORS
;
3265 // create button rows
3268 Bit32u WStyle
= WS_CHILD
| WS_VISIBLE
| BS_PUSHBUTTON
;
3273 sprintf (bigbuf
, "cpu%d",j
); // number all the CPU buttons
3274 hCPUt
[j
] = CreateWindowEx(0,"sBtn",bigbuf
,WStyle
,0,0,1,1,hh
,(HMENU
)(1030+j
),GetModuleHandle(0),0);
3276 strcpy (bigbuf
, "CPU0"); // Handle CPU0 specially -- it is "selected"
3277 hCPUt
[0] = CreateWindowEx(0,"sBtn",bigbuf
,WStyle
,0,0,1,1,hh
,(HMENU
)MULTICPU_BTN_BASE
,GetModuleHandle(0),0);
3281 hBTN
[j
] = CreateWindowEx(0,"sBtn",BTxt
[j
],WStyle
,0,0,1,1,hh
,(HMENU
)(BTN_BASE
+j
),GetModuleHandle(0),0);
3283 hCursResize
= LoadCursor (NULL
,IDC_SIZEWE
);
3284 hCursDock
= LoadCursor (NULL
,IDC_CROSS
);
3285 SetTimer(hh
,2,500,NULL
); // get timer ticks every half a second (update VGAW)
3286 DoAllInit(); // any custom GUI initialization goes in here
3287 SetFocus(hE_O
); // focus on Output window works best
3296 // Mapping mode is MM_TEXT (Def), so Yvalues increase DOWN, all values are in pixels.
3297 GetClientRect(hh
,&rc
);
3298 // don't resize child windows on a minimize, or if client window is too small
3299 // TODO: save the prev size values -- no resize if they are the same
3300 // -- also can skip some resizing steps if horizontal size does not change
3301 if (rc
.bottom
> 100 && rc
.right
> 150)
3303 // set up the Input/Output/Status windows
3304 SetSizeIOS((int)rc
.right
,(int)rc
.bottom
);
3306 // need to recalculate List widths, with the same proportions as before
3307 i
= ListWidthPix
[0] + ListWidthPix
[1] + ListWidthPix
[2];
3310 j
= (ListWidthPix
[2] * rc
.right
) / i
;
3311 k
= (ListWidthPix
[1] * rc
.right
) / i
;
3312 ListWidthPix
[0] = rc
.right
- k
- j
; // Register list
3313 ListWidthPix
[1] = k
; // Asm
3314 ListWidthPix
[2] = j
; // MemDump
3320 case WM_SYSKEYDOWN
: // ww == key + ALT
3332 else if (ww
== VK_F2
)
3335 else if (ww
== VK_F3
) ToggleSeeReg(139); // MMX/FPU toggle
3337 else if (ww
== VK_F7
) // Alt+F7 memdump hex toggle
3339 i
= DumpInAsciiMode
;
3343 DumpInAsciiMode
= i
;
3344 if ((DumpInAsciiMode
& 2) != 0)
3345 CheckMenuItem (hOptMenu
, 122, MF_CHECKED
);
3347 CheckMenuItem (hOptMenu
, 122, MF_UNCHECKED
);
3348 PrevDAD
= 0; // force columns to resize
3357 int Control
= GetKeyState(VK_CONTROL
); // key is down if val is negative
3358 int Shift
= GetKeyState(VK_SHIFT
);
3363 CommandHistoryIdx
= 0;
3364 SetWindowText(hE_I
,"");
3365 ShowMemData(); // force a "normal" MemDump window
3369 // History from nextmost previous command
3370 CommandHistoryIdx
= (CommandHistoryIdx
- 1) & 63; // wrap -1 to 63 (circular)
3371 SetWindowText(hE_I
,CmdHistory
[(CmdHInsert
+ CommandHistoryIdx
) & 63]);
3372 CallWindowProc(*wEdit
, hE_I
, EM_SETSEL
,(WPARAM
) -1,(LPARAM
) -1);
3373 CallWindowProc(*wEdit
, hE_I
, EM_SCROLLCARET
,(WPARAM
) 0,(LPARAM
) 0);
3377 // Next History command
3378 CommandHistoryIdx
= (CommandHistoryIdx
+ 1) & 63; // wrap -1 to 63 (circular)
3379 SetWindowText(hE_I
,CmdHistory
[(CmdHInsert
+ CommandHistoryIdx
) & 63]);
3380 CallWindowProc(*wEdit
, hE_I
, EM_SETSEL
,(WPARAM
) -1,(LPARAM
) -1);
3381 CallWindowProc(*wEdit
, hE_I
, EM_SCROLLCARET
,(WPARAM
) 0,(LPARAM
) 0);
3385 // Page up on the MemDump window by 2K
3386 if (DumpInitted
!= FALSE
)
3387 InitDataDump(DumpMode
, DumpStart
- 2048);
3391 // Page down on the MemDump window by 2K
3392 if (DumpInitted
!= FALSE
)
3393 InitDataDump(DumpMode
, DumpStart
+ 2048);
3405 case VK_F3
: // ^F3 = param tree, F3 = toggle syntax
3410 Bit64u h
= CurrentAsmLA
;
3411 bx_disassemble
.toggle_syntax_mode();
3412 // do the standard ASM window fill sequence
3414 FillAsm(h
, DefaultAsmLines
);
3419 if (Shift
< 0) // Debug register toggle
3420 ToggleSeeReg(CMD_DREG
);
3421 else if (Control
>= 0) // Refresh
3423 BottomAsmLA
= ~0; // force an ASM autoload
3424 doDumpRefresh
= TRUE
; // force a data window refresh on a break
3425 if (AtBreak
!= FALSE
) // can't refresh the windows until a break!
3427 doUpdate(); // refresh the ASM and Register windows
3428 RefreshDataWin(); // and whichever data window is up
3432 else ToggleSeeReg(CMD_XMMR
); // SSE toggle
3437 // can't continue until everything is ready
3438 if (AtBreak
!= FALSE
&& debug_cmd_ready
== FALSE
&& dbgOn
)
3440 // The VGAW *MUST* be refreshed periodically -- it's best to use the timer.
3441 // Which means that the sim cannot be directly run from this msglp thread.
3442 *debug_cmd
= 'c'; // send a fake "continue" command to the internal debugger
3444 debug_cmd_ready
= TRUE
;
3446 StatusChange
= TRUE
;
3452 InitDataDump(0,(Bit64u
) 1); // ^F7 = PhysDump
3453 else if (Shift
< 0) // ShiftF7 = ascii toggle
3455 i
= DumpInAsciiMode
;
3459 DumpInAsciiMode
= i
;
3460 if ((DumpInAsciiMode
& 1) != 0)
3461 CheckMenuItem (hOptMenu
, CMD_MASCII
, MF_CHECKED
);
3463 CheckMenuItem (hOptMenu
, CMD_MASCII
, MF_UNCHECKED
);
3464 PrevDAD
= 0; // force columns to resize
3469 InitDataDump(1,(Bit64u
) 1); // F7 = LinDump
3473 if (Control
< 0) // ^F6 = Read Watchpt
3475 if (DumpHasFocus
!= FALSE
)
3476 SetWatchpoint(&num_read_watchpoints
,read_watchpoint
);
3478 else if (Shift
< 0) // ShiftF6 = Modechange brk toggle
3480 // toggle mode_break on cpu0, use that value to reset all CPUs
3481 bx_bool nmb
= BX_CPU(0)->mode_break
^ TRUE
;
3484 BX_CPU(j
)->mode_break
= nmb
;
3486 CheckMenuItem (hOptMenu
, CMD_MODEB
, MF_CHECKED
);
3488 CheckMenuItem (hOptMenu
, CMD_MODEB
, MF_UNCHECKED
);
3492 if (DumpHasFocus
== FALSE
) // F6 Brkpt / Write Watchpt
3495 SetWatchpoint(&num_write_watchpoints
,write_watchpoint
);
3500 if (AtBreak
!= FALSE
&& debug_cmd_ready
== FALSE
&& dbgOn
)
3502 bx_dbg_stepN_command(1); // singlestep
3503 StatusChange
= TRUE
;
3508 // can't run sim until everything is ready
3509 if (AtBreak
!= FALSE
&& debug_cmd_ready
== FALSE
&& dbgOn
)
3510 doStepN(); // ask user for a step #
3513 case 'C': // ^c = break
3530 case VK_RIGHT
: // send a few virtual movement keys back into the Input window
3534 CallWindowProc (*wEdit
, hE_I
, mm
, ww
, ll
);
3538 // can't do a command until everything is ready
3539 if (AtBreak
!= FALSE
&& debug_cmd_ready
== FALSE
&& dbgOn
)
3542 GetWindowText(hE_I
,tmpcb
,200);
3543 if (*tmpcb
== 0) // Hitting <CR> on a blank line means SINGLESTEP
3545 bx_dbg_stepN_command(1); // singlestep
3549 // deal with the command history:
3550 if (strlen(tmpcb
) > 79)
3551 MessageBox (hY
,"Running command, but history has an 80 char Max.",
3552 "Command history overflow", MB_OK
);
3555 strcpy (CmdHistory
[CmdHInsert
], tmpcb
);
3556 CmdHInsert
= (CmdHInsert
+ 1) & 63; // circular buffer, 0 to 63
3558 strcpy (debug_cmd
,tmpcb
); // send the command into the bochs internal debugger
3559 debug_cmd_ready
= TRUE
;
3561 SetWindowText(hE_I
,""); // clear the "input" window for the next command
3562 CommandHistoryIdx
= 0; // and reset the history queue to the new end
3564 StatusChange
= TRUE
;
3571 int LW
= LOWORD(ww
);
3573 if (LW
>= BTN_BASE
&& LW
<= BTN_BASE
+4) // convert button IDs to command IDs
3574 LW
= BtnLkup
[LW
- BTN_BASE
];
3575 else if (LW
>= MULTICPU_BTN_BASE
&& LW
< MULTICPU_BTN_BASE
+ BX_MAX_SMP_THREADS_SUPPORTED
)
3577 unsigned int newCPU
= LW
- MULTICPU_BTN_BASE
;
3578 if (CurrentCPU
!= newCPU
)
3580 // change text on CurrentCPU button to lowercase
3581 strcpy (tmpcb
, "cpu0");
3582 tmpcb
[3] = CurrentCPU
+ '0';
3583 SendMessage (hCPUt
[CurrentCPU
],WM_SETTEXT
,(WPARAM
) 0 ,(LPARAM
) tmpcb
);
3584 // change text on newCPU button to UPPERCASE
3585 strcpy (tmpcb
, "CPU0");
3586 tmpcb
[3] = newCPU
+ '0';
3587 SendMessage (hCPUt
[newCPU
],WM_SETTEXT
,(WPARAM
) 0 ,(LPARAM
) tmpcb
);
3588 CurrentCPU
= newCPU
;
3589 BottomAsmLA
= ~0; // force an ASM autoload, to repaint
3590 PrevPtime
= 0; // force a full update
3591 if (AtBreak
!= FALSE
) // if at a break, pretend it just happened
3592 OnBreak(); // refresh the ASM and Register windows
3596 if (LW
>= CMD_BREAK
&& LW
< CMD_MODEB
) // Does not include "Step"s or Options
3598 if (AtBreak
== FALSE
)
3600 SIM
->debug_break(); // On a menu click always break (with some exceptions)
3607 case CMD_CONT
: // run/go/continue
3608 if (AtBreak
!= FALSE
&& debug_cmd_ready
== FALSE
&& dbgOn
)
3610 // The VGAW *MUST* be refreshed periodically -- it's best to use the timer.
3611 // Which means that the sim cannot be directly run from this msglp thread.
3612 *debug_cmd
= 'c'; // send a fake "continue" command to the internal debugger
3614 debug_cmd_ready
= TRUE
;
3616 StatusChange
= TRUE
;
3620 case CMD_STEP1
: // step 1
3621 if (AtBreak
!= FALSE
&& debug_cmd_ready
== FALSE
&& dbgOn
)
3623 bx_dbg_stepN_command(1); // singlestep
3624 StatusChange
= TRUE
;
3628 case CMD_STEPN
: // step N
3629 // can't run sim until everything is ready
3630 if (AtBreak
!= FALSE
&& debug_cmd_ready
== FALSE
&& dbgOn
)
3634 case CMD_BREAK
: // break/stop the sim
3635 // SIM->debug_break() only "break"s the internal debugger
3639 case CMD_BRKPT
: // set or delete a breakpoint at the selected address
3643 case CMD_WPTWR
: // set or delete a data write watchpoint
3644 SetWatchpoint(&num_write_watchpoints
,write_watchpoint
);
3647 case CMD_WPTRD
: // set or delete a data read watchpoint
3648 SetWatchpoint(&num_read_watchpoints
,read_watchpoint
);
3651 case CMD_FIND
: // find -- Control-F
3655 case CMD_RFRSH
: // force an update/refresh
3656 BottomAsmLA
= ~0; // force an ASM autoload
3657 doDumpRefresh
= TRUE
; // force a data window refresh on a break
3658 if (AtBreak
!= FALSE
) // can't refresh the windows until a break!
3660 doUpdate(); // refresh the ASM and Register windows
3661 RefreshDataWin(); // and whichever data window is up
3665 case CMD_PHYDMP
: // "physical mem" data dump
3666 InitDataDump(0,(Bit64u
) 1);
3669 case CMD_LINDMP
: // "linear memory" data dump
3670 InitDataDump(1,(Bit64u
) 1);
3673 case CMD_STACK
: // toggle display of Stack
3677 case CMD_GDTV
: // toggle display of GDT
3681 case CMD_IDTV
: // toggle display of IDT
3685 case CMD_PAGEV
: // display paging info
3689 case CMD_CMEM
: // view current MemDump -- acts like "cancel"
3690 CommandHistoryIdx
= 0;
3691 SetWindowText(hE_I
,"");
3692 ShowMemData(); // force a "normal" MemDump window
3699 case CMD_DISASM
: // disassemble starting at a particular address
3703 case CMD_MODEB
: // toggle the simulation's Mode-Change-Break flag
3705 // toggle mode_break on cpu0, use that value to reset all CPUs
3706 bx_bool nmb
= BX_CPU(0)->mode_break
^ TRUE
;
3709 BX_CPU(j
)->mode_break
= nmb
;
3711 CheckMenuItem (hOptMenu
, CMD_MODEB
, MF_CHECKED
);
3713 CheckMenuItem (hOptMenu
, CMD_MODEB
, MF_UNCHECKED
);
3717 case CMD_DADEF
: // set default # of disassembly lines in a list
3718 sprintf (tmpcb
,"%d",DefaultAsmLines
);
3719 if (AskText(hh
,"Disassembly default linecount","Max. 2048:",tmpcb
,0) == FALSE
)
3721 sscanf (tmpcb
,"%d",&i
);
3722 if (i
> 0 && i
<= 2048)
3723 DefaultAsmLines
= i
;
3724 if (i
> 1000 && FWflag
== FALSE
) // friendly warning
3728 case CMD_ATTI
: // Toggle ASM Syntax
3730 bx_disassemble
.toggle_syntax_mode();
3731 // do the standard ASM window fill sequence
3732 Bit64u h
= CurrentAsmLA
;
3734 FillAsm(h
, DefaultAsmLines
);
3738 case CMD_IOWIN
: // toggle display of internal debugger Input and Output windows
3739 ShowIOWindows
^= TRUE
;
3740 if (ShowIOWindows
!= 0)
3741 CheckMenuItem (hOptMenu
, CMD_IOWIN
, MF_CHECKED
);
3743 CheckMenuItem (hOptMenu
, CMD_IOWIN
, MF_UNCHECKED
);
3747 case CMD_SBTN
: // Toggle showing top pushbutton-row
3748 ShowButtons
^= TRUE
;
3749 if (ShowButtons
!= 0)
3750 CheckMenuItem (hOptMenu
, CMD_SBTN
, MF_CHECKED
);
3752 CheckMenuItem (hOptMenu
, CMD_SBTN
, MF_UNCHECKED
);
3756 case CMD_UCASE
: // Toggle showing everything in uppercase
3760 CheckMenuItem (hOptMenu
, CMD_UCASE
, MF_CHECKED
);
3762 CheckMenuItem (hOptMenu
, CMD_UCASE
, MF_UNCHECKED
);
3764 // the ASM window will be updated when it gets updated
3766 // do the standard ASM window fill sequence
3767 Bit64u h
= CurrentAsmLA
;
3769 FillAsm(h
, DefaultAsmLines
);
3773 case CMD_MHEX
: // Toggle showing hex in Dump window
3774 i
= DumpInAsciiMode
;
3778 DumpInAsciiMode
= i
;
3779 if ((DumpInAsciiMode
& 2) != 0)
3780 CheckMenuItem (hOptMenu
, CMD_MHEX
, MF_CHECKED
);
3782 CheckMenuItem (hOptMenu
, CMD_MHEX
, MF_UNCHECKED
);
3783 PrevDAD
= 0; // force columns to resize
3784 if (DViewMode
== VIEW_MEMDUMP
&& DumpInitted
!= FALSE
)
3789 case CMD_MASCII
: // Toggle showing ASCII in Dump window
3790 i
= DumpInAsciiMode
;
3794 DumpInAsciiMode
= i
;
3795 if ((DumpInAsciiMode
& 1) != 0)
3796 CheckMenuItem (hOptMenu
, CMD_MASCII
, MF_CHECKED
);
3798 CheckMenuItem (hOptMenu
, CMD_MASCII
, MF_UNCHECKED
);
3799 PrevDAD
= 0; // force columns to resize
3800 if (DViewMode
== VIEW_MEMDUMP
&& DumpInitted
!= FALSE
)
3805 case CMD_LEND
: // Toggle Endianness for the MemDumps
3806 isLittleEndian
^= TRUE
;
3807 if (isLittleEndian
!= FALSE
)
3808 CheckMenuItem (hOptMenu
, CMD_LEND
, MF_CHECKED
);
3810 CheckMenuItem (hOptMenu
, CMD_LEND
, MF_UNCHECKED
);
3811 if (DViewMode
== VIEW_MEMDUMP
&& DumpInitted
!= FALSE
)
3815 case CMD_WS_1
: // set memory dump "wordsize"
3816 // "Align" = "wordsize" -- from 1 to 16
3836 case CMD_IGNSA
: // Toggle ID disassembly output ignoring
3837 ignSSDisasm
^= TRUE
;
3838 if (ignSSDisasm
!= FALSE
)
3839 CheckMenuItem (hOptMenu
, CMD_IGNSA
, MF_CHECKED
);
3841 CheckMenuItem (hOptMenu
, CMD_IGNSA
, MF_UNCHECKED
);
3844 case CMD_IGNNT
: // Toggle NextT ignoring
3846 if (ignoreNxtT
!= FALSE
)
3847 CheckMenuItem (hOptMenu
, CMD_IGNNT
, MF_CHECKED
);
3849 CheckMenuItem (hOptMenu
, CMD_IGNNT
, MF_UNCHECKED
);
3852 case CMD_RCLR
: // Toggle Register Coloring
3853 SeeRegColors
^= TRUE
;
3854 if (SeeRegColors
!= FALSE
)
3855 CheckMenuItem (hOptMenu
, CMD_RCLR
, MF_CHECKED
);
3857 CheckMenuItem (hOptMenu
, CMD_RCLR
, MF_UNCHECKED
);
3862 case CMD_EREG
: // Show Registers of various types
3873 case CMD_ABOUT
: // "About" box
3874 MessageBox(hh
,"Bochs Enhanced Debugger, Version 1.0\r\nCopyright (C) Chourdakis Michael.\r\nModified by Bruce Ewing",
3875 "About",MB_OK
| MB_ICONINFORMATION
);
3878 case CMD_FONT
: // font
3879 HFONT hF
= (HFONT
) CallWindowProc(*wEdit
,hE_I
,WM_GETFONT
,0,0);
3881 GetObject(hF
,sizeof(lf
),&lf
);
3882 CHOOSEFONT cF
= {0};
3883 cF
.lStructSize
= sizeof(cF
);
3886 cF
.Flags
= CF_SCREENFONTS
| CF_EFFECTS
| CF_INITTOLOGFONTSTRUCT
;
3887 if (ChooseFont(&cF
) == FALSE
)
3890 ShowWindow(hL
[0],SW_HIDE
);
3891 ShowWindow(hL
[1],SW_HIDE
);
3892 ShowWindow(hL
[2],SW_HIDE
);
3893 ShowWindow(hS_S
,SW_HIDE
);
3894 ShowWindow(hE_I
,SW_HIDE
);
3895 if (CustomFont
!= NULL
)
3896 DeleteObject (CustomFont
);
3897 CustomFont
= CreateFontIndirect(&lf
);
3899 CallWindowProc(wListView
,hL
[0],WM_SETFONT
,(WPARAM
)CustomFont
,MAKELPARAM(TRUE
,0));
3900 CallWindowProc(wListView
,hL
[1],WM_SETFONT
,(WPARAM
)CustomFont
,MAKELPARAM(TRUE
,0));
3901 CallWindowProc(wListView
,hL
[2],WM_SETFONT
,(WPARAM
)CustomFont
,MAKELPARAM(TRUE
,0));
3902 CallWindowProc(*wEdit
,hE_I
,WM_SETFONT
,(WPARAM
)CustomFont
,MAKELPARAM(TRUE
,0));
3903 SendMessage(hS_S
,WM_SETFONT
,(WPARAM
)CustomFont
,MAKELPARAM(TRUE
,0));
3911 NMHDR
* n
= (NMHDR
*)ll
;
3912 if (n
->code
== LVN_KEYDOWN
)
3914 NMLVKEYDOWN
* key
= (NMLVKEYDOWN
*)ll
; // pass any keystrokes from listview up to parent
3915 SendMessage(hh
,WM_KEYDOWN
,key
->wVKey
,0);
3917 if (n
->code
== NM_CUSTOMDRAW
&& n
->hwndFrom
== hL
[1]) // custom drawing of ASM window
3919 // highlight the breakpoints, and current opcode, if any
3920 NMLVCUSTOMDRAW
*d
= (NMLVCUSTOMDRAW
*) ll
;
3921 if (d
->nmcd
.dwDrawStage
== CDDS_PREPAINT
)
3922 return CDRF_NOTIFYITEMDRAW
;
3924 if (d
->nmcd
.dwDrawStage
== CDDS_ITEMPREPAINT
) // select the "active" ASM line
3926 d
->clrTextBk
= RGB(255,255,255); // background is white
3928 d
->clrTextBk
= RGB(210,210,210); // unless sim is "running"
3930 unsigned char r
=0, g
=0, b
=0; // normal text color is black
3932 bx_address h
= (bx_address
) AsmLA
[d
->nmcd
.dwItemSpec
];
3933 if (h
== CurrentAsmLA
)
3934 g
= 100; // current opcode is colored dark green
3936 while (--j
>= 0) // loop over all breakpoints
3938 // brk list is sorted -- if the value goes too low, end the loop
3939 // And I know for a fact that some complers are soooo stupid that they
3940 // will repeat the following test twice, unless you force them not to.
3941 register bx_address i
= BrkLAddr
[j
] - h
;
3942 // if (BrkLAddr[j] < h)
3944 j
= 0; // force the loop to end if it goes too far
3945 // else if (BrkLAddr[j] == h)
3949 if (h
== CurrentAsmLA
)
3950 b
= 200; // breakpoint @ current opcode = blue
3952 r
= 150; // active breakpoint is red
3955 d
->clrText
= RGB(r
,g
,b
);
3959 if (n
->code
== NM_CUSTOMDRAW
&& n
->hwndFrom
== hL
[2]) // custom drawing of data window
3961 NMLVCUSTOMDRAW
*d
= (NMLVCUSTOMDRAW
*) ll
;
3962 if (d
->nmcd
.dwDrawStage
== CDDS_PREPAINT
)
3963 return CDRF_NOTIFYITEMDRAW
;
3965 d
->clrTextBk
= RGB(255,255,255); // background is white
3967 d
->clrTextBk
= RGB(210,210,210); // unless sim is "running"
3969 else if (DViewMode
== VIEW_STACK
&& d
->nmcd
.dwDrawStage
== CDDS_ITEMPREPAINT
)
3971 // highlight changed lines in stack
3972 int j
= d
->nmcd
.dwItemSpec
;
3973 if (j
< 0 || j
>= STACK_ENTRIES
) // make sure the line # is legal
3975 else if (StackEntChg
[j
] != FALSE
)
3976 d
->clrText
= RGB(255,0,0); // changed entry = red
3979 if (DumpAlign
!= 1 || DumpMode
!= 0 || DViewMode
!= VIEW_MEMDUMP
)
3982 // highlight any physical watchpoints in physical DumpMode
3983 if (d
->nmcd
.dwDrawStage
== CDDS_ITEMPREPAINT
)
3985 SetWindowLong(hh
, DWL_MSGRESULT
, CDRF_NOTIFYSUBITEMDRAW
);
3986 return CDRF_NOTIFYSUBITEMDRAW
;
3989 if (d
->nmcd
.dwDrawStage
== (CDDS_SUBITEM
| CDDS_ITEMPREPAINT
))
3991 d
->clrText
= RGB(0,0,0); // assume black text
3992 if (d
->iSubItem
!= 0)
3994 // For each subitem, calculate its equivalent physmem address
3995 bx_phy_address h
= (bx_phy_address
) DumpStart
+
3996 16*(d
->nmcd
.dwItemSpec
) + d
->iSubItem
-1;
3997 int j
= num_write_watchpoints
;
3998 int i
= num_read_watchpoints
;
4001 if (write_watchpoint
[--j
] == h
)
4003 d
->clrTextBk
= RGB(0,0,0); // black background
4004 d
->clrText
= RGB(255,0,150); // write watchpoint
4005 j
= -1; // on a match j<0 -- else j == 0
4010 if (read_watchpoint
[i
] == h
)
4012 if (j
< 0) // BOTH read and write
4013 d
->clrText
= RGB(0,170,255);
4016 d
->clrTextBk
= RGB(0,0,0); // black background
4017 d
->clrText
= RGB(130,255,0); // read watchpoint
4019 i
= 0; // end the loop on a match
4026 if (n
->code
== NM_CUSTOMDRAW
&& n
->hwndFrom
== hL
[0]) // custom drawing of register window
4028 // highlight changed registers
4029 NMLVCUSTOMDRAW
*d
= (NMLVCUSTOMDRAW
*) ll
;
4030 if (d
->nmcd
.dwDrawStage
== CDDS_PREPAINT
)
4031 return CDRF_NOTIFYITEMDRAW
;
4033 if (d
->nmcd
.dwDrawStage
== CDDS_ITEMPREPAINT
)
4035 int i
= d
->nmcd
.dwItemSpec
;
4036 Bit8u ClrFlgs
= RegColor
[ RitemToRnum
[i
] ];
4037 d
->clrText
= RGB(0,0,0);
4038 d
->clrTextBk
= RGB(255,255,255);
4040 // RitemToRnum converts a ListView row number to the corresponding Register number.
4041 // RegColor has the 0x80 bit set if the register is supposed to be red.
4042 // Background color index is in the low nibble of ClrFlgs/RegColor.
4043 if (SeeRegColors
!= FALSE
)
4044 d
->clrTextBk
= ColorList
[ClrFlgs
&7];
4045 if ((ClrFlgs
& 0x80) != 0) // should this register be red?
4046 d
->clrText
= RGB(255,0,0);
4048 d
->clrTextBk
= RGB(210,210,210); // gray out the background if "running"
4053 if (n
->code
== NM_DBLCLK
)
4055 if (AtBreak
== FALSE
)
4058 if (n
->hwndFrom
== hL
[0])
4060 // Change a register
4061 int L
= CallWindowProc(wListView
, hL
[0], LVM_GETNEXTITEM
,(WPARAM
) -1,MAKELPARAM(LVNI_SELECTED
, 0));
4062 if (L
== -1 || L
>= TOT_REG_NUM
)
4063 break; // should be impossible
4065 int i
= RitemToRnum
[L
];
4066 if (i
> EFER_Rnum
) // only able to do up to EFER for now
4070 sprintf (tmpcb
,"0x%I64X", rV
[i
]);
4071 if (AskText(hh
,"Change Register Value",d1
,tmpcb
,0))
4075 while (*s
== ' ') // allow user to enter whitespace
4077 if (*s
== '0' && (s
[1] =='X' || s
[1] == 'x')) // and either hex or decimal
4078 sscanf (s
+2,"%I64X",&val
);
4080 sscanf(tmpcb
,"%I64d",&val
);
4081 RegObject
[CurrentCPU
][i
]->set(val
); // the set function should be a bool, not a void
4082 // bx_bool worked = RegObject[CurrentCPU][i]->set(val);
4083 // if (worked == FALSE)
4084 // MessageBox (hh,"Bochs does not allow you to set that register","Selection Error", MB_ICONERROR) ;
4086 LoadRegList(); // update the register window
4089 if (n
->hwndFrom
== hL
[1]) // doubleclick a breakpoint on ASM window
4092 if (n
->hwndFrom
== hL
[2] && DViewMode
== VIEW_MEMDUMP
) // Change values in memory locations
4094 int L
= CallWindowProc(wListView
, hL
[2], LVM_GETNEXTITEM
,(WPARAM
) -1,MAKELPARAM(LVNI_SELECTED
, 0));
4095 i
= 0; // flag if setting watchpoints
4096 if (GetKeyState(VK_SHIFT
) < 0)
4099 SetWatchpoint(&num_write_watchpoints
,write_watchpoint
);
4101 if (GetKeyState(VK_CONTROL
) < 0)
4104 SetWatchpoint(&num_read_watchpoints
,read_watchpoint
);
4106 if (L
== -1 || i
!= 0) // L should never be -1, Exit after a watchpoint.
4109 // get base address of "line" of data -- each line (L) is 16 bytes
4110 Bit64u h
= DumpStart
+ (L
<<4);
4113 sprintf(tmpcb
,"Physical Address: 0x%I64X",h
);
4115 sprintf(tmpcb
,"Linear Address: 0x%I64X",h
);
4117 unsigned char *u
= (unsigned char *)(DataDump
+ (L
<<4)); // important that it be unsigned!
4118 sprintf(tmpcd
,"%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
4119 *u
,u
[1],u
[2],u
[3],u
[4],u
[5],u
[6],u
[7],u
[8],u
[9],u
[10],u
[11],u
[12],u
[13],u
[14],u
[15]);
4121 if (AskText(hh
,"Change Memory Values",tmpcb
,tmpcd
,0))
4126 upr(x
); // force input string to uppercase
4128 if (DumpMode
!= 0) // is h is a LINEAR address? Convert to physical!
4130 // use the ReadBx function to calculate the lin->phys offset
4131 if (ReadBxLMem (h
,0,(Bit8u
*)tmpcb
) == FALSE
) // "read" 0 bytes
4134 h
-= l_p_offset
; // convert h to a physmem address
4137 while (*x
!= 0 && err
== 0)
4140 // verify that the next 2 chars are hex digits
4141 if ((*x
< '0' || *x
> '9') && (*x
< 'A' || *x
> 'F'))
4146 if ((*x
< '0' || *x
> '9') && (*x
< 'A' || *x
> 'F'))
4151 if (*x
!= ' ' && *x
!= 0) // followed by a space or 0
4157 // convert the hex to a byte, and try to store the byte in bochs physmem
4158 sscanf (s
,"%2X",&newval
);
4159 if ( bx_mem
.dbg_set_mem( (bx_phy_address
) h
, 1, &newval
) == FALSE
)
4161 ++h
; // bump to the next mem address
4162 while (*x
== ' ') // scan past whitespace
4170 MessageBox (hh
,"Improper char hex format","Input Format Error", MB_ICONERROR
);
4172 MessageBox (hh
,"Illegal memory address error?","Memory Error", MB_ICONERROR
);
4174 ShowData(); // refresh the data dump, even if there were errors
4182 if (PO_Tdelay
> 0) // output window is delaying display of a partial line?
4184 if (--PO_Tdelay
== 0) // on a timeout, add a lf to complete the line
4185 ParseUnknown ("\n");
4191 case WM_NCMOUSEMOVE
:
4193 // turn off any sizing operation if the cursor strays off the listviews
4195 // also turn off any half-completed mouseclicks
4204 if (CustomFont
!= NULL
)
4205 DeleteObject (CustomFont
);
4206 DestroyWindow(hDebugDialog
);
4207 hDebugDialog
= NULL
;
4208 UnregisterClass("sLV",GetModuleHandle(0));
4213 // ww == 0x1234, ll = 0 - bochs started running a command
4214 // 11 = 1 - bochs stopped on some type of break
4215 // ll = 2 - bochs is ready to run a command
4216 // ww == 0x5678 - output text from debugger in available in lparam
4218 if (ww
== 0x1234 && ll
== 2)
4219 dbgOn
= TRUE
; // bochs internal debugger is able to accept commands now
4221 if (ww
!= 0x1234 || ll
!= 0)
4223 // Sim is at a "break".
4224 if (AtBreak
== FALSE
)
4227 StatusChange
= TRUE
;
4229 if (doDumpRefresh
!= FALSE
)
4234 if (ww
== 0x5678) // bochs internal debugger produced some text?
4236 if (strstr((char*)ll
,"HALTED"))
4239 ParseUnknown((char*)ll
); // Process all debugger text output
4244 return DefWindowProc(hh
,mm
,ww
,ll
);
4249 InitCommonControls();
4252 WNDCLASSEX wC
= {0};
4253 wC
.cbSize
= sizeof(wC
);
4254 wC
.hbrBackground
= (HBRUSH
)GetStockObject(WHITE_BRUSH
);
4255 hCursArrow
= LoadCursor(NULL
,IDC_ARROW
);
4256 wC
.hCursor
= hCursArrow
;
4257 wC
.hInstance
= GetModuleHandle(0);
4258 wC
.style
= CS_HREDRAW
| CS_VREDRAW
| CS_GLOBALCLASS
| CS_DBLCLKS
;
4259 wC
.lpfnWndProc
= B_WP
;
4260 wC
.cbWndExtra
= sizeof(void*);
4261 wC
.lpszClassName
= "bochs_dbg_x";
4262 wC
.hIcon
= LoadIcon(GetModuleHandle(0),"ICON_D");
4263 wC
.hIconSm
= LoadIcon(GetModuleHandle(0),"ICON_D");
4264 ATOM P1
= RegisterClassEx(&wC
);
4268 void RefreshDebugDialog()
4272 void InitDebugDialog(HWND mainwnd
)
4275 HMENU hTopMenu
= LoadMenu(GetModuleHandle(0),"MENU_1");
4276 hOptMenu
= GetSubMenu (hTopMenu
, 2);
4277 hViewMenu
= GetSubMenu (hTopMenu
, 1);
4278 hCmdMenu
= GetSubMenu (hTopMenu
, 0);
4279 hY
= CreateWindowEx(0,"bochs_dbg_x","Bochs Enhanced Debugger (Type 2)",
4280 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,CW_USEDEFAULT
,CW_USEDEFAULT
,CW_USEDEFAULT
,CW_USEDEFAULT
,
4281 0,hTopMenu
,GetModuleHandle(0),0);