home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / µSim 1.1 / source / Disasm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-25  |  13.2 KB  |  507 lines  |  [TEXT/CWIE]

  1. /*
  2. Copyright © 1993-1997 Fabrizio Oddone
  3. ••• ••• ••• ••• ••• ••• ••• ••• ••• •••
  4. This source code is distributed as freeware:
  5. you may copy, exchange, modify this code.
  6. You may include this code in any kind of application: freeware,
  7. shareware, or commercial, provided that full credits are given.
  8. You may not sell or distribute this code for profit.
  9. */
  10.  
  11.  
  12. #pragma fourbyteints on
  13. #include    <stdlib.h>
  14. #pragma fourbyteints reset
  15. #include    <string.h>
  16.  
  17. #include    <Limits.h>
  18.  
  19. #include    "UtilsSys7.h"
  20. #include    "Conversions.h"
  21. #include    "FabWList.h"
  22. #include    "Independents.h"
  23. #include    "SimResIDs.h"
  24.  
  25. #include    "Globals.h"
  26. #include    "Assembler.h"
  27. #include    "Compares.h"
  28. #include    "Disasm.h"
  29. #include    "Dump.h"
  30. #include    "Main.h"
  31. #include    "Microprogram_Ed.h"
  32. #include    "Input.h"
  33. #include    "Registers.h"
  34. #include    "TrackThumb.h"
  35. #include    "DragManSim.h"
  36. #include    "SimUtils.h"
  37.  
  38. #if defined(FabSystem7orlater)
  39.  
  40.  
  41. static ControlRef    disasmVScroll;
  42. static WindowRef    curPosW;
  43. static short    disasmLineHeight, disasmFromTop, disasmCWidMax;
  44.  
  45. static short *DisasmInstruction(const short *inst, Ptr dest, ROpcDisasmPtr instrTbl, Size TblSize);
  46. static void ThumbActionProc(ControlHandle control, short value);
  47. static pascal void DisasmActionProc(ControlHandle control, short part);
  48.  
  49.  
  50. #pragma segment Init
  51. /* Init_Disasm: initializes the Disassembler window */
  52.  
  53. OSErr Init_Disasm(void)
  54. {
  55. FMetricRec    theMetrics;
  56. FabWindowPtr    thefabw;
  57. Fixed    tempFix;
  58. WindowPtr    window;
  59. OSErr    err = appMemFullErr;
  60.  
  61. gWPtr_Disasm = window = GetNewWindow(kWIND_Disasm, nil, (WindowPtr)-1L);
  62. if (window) {
  63.     SetPortWindowPort(window);
  64.     if (gPrefs.remembWind)
  65.         if (IsOnScreenWeak(gPrefs.DisasmTopLeft))
  66.             MoveWindow(window, gPrefs.DisasmTopLeft.h, gPrefs.DisasmTopLeft.v, false);
  67.     if (disasmVScroll = GetNewControl(kCNTL_disasmVScroll, window)) {
  68.         TextFont(monaco);
  69.         TextSize(9);
  70.         TextMode(srcCopy);
  71.         FontMetrics(&theMetrics);
  72.         tempFix = theMetrics.descent + theMetrics.ascent + theMetrics.leading;
  73.         tempFix = mySwap(tempFix);
  74.         disasmLineHeight = (short)tempFix;
  75.         disasmFromTop = *(short *)&theMetrics.ascent;
  76.         disasmCWidMax = *(short *)&theMetrics.widMax;
  77.         tempFix = FixMul(theMetrics.widMax, kMaxCharsInOneDisasmLineFixed);
  78.         tempFix = mySwap(tempFix);
  79.         SizeWindow(window, (short)tempFix + kScrollbarWidth + kDIST_FROMLEFT,
  80.             gPrefs.remembWind ? gPrefs.DisasmHeight :
  81.                 ((PRCT_B(window) - PRCT_T(window)) / disasmLineHeight) * disasmLineHeight, false);
  82.         SetupVertScrollBar(window, disasmVScroll);
  83.         SetupDisasmCtlMax(disasmVScroll);
  84.         if (gPrefs.remembWind)
  85.             SetControlValue(disasmVScroll, gPrefs.DisasmScrollVal);
  86.  
  87.         thefabw = AddWindowToList(window);
  88.         SetActivate(thefabw, Activate_Disasm);
  89.         SetUpdate(thefabw, Update_Disasm);
  90.         SetGrow(thefabw, Grow_Disasm);
  91.         SetGoAway(thefabw, CloseDisasm);
  92.         SetContent(thefabw, Do_Disasm);
  93.         SetGetDragRect(thefabw, getDragRectDisasm);
  94.  
  95.         InstallRgnHandler(thefabw, NewRgn(), RecalcDump, nil,
  96.                 toMenu(kBalloons_Dump, kBDisasm_Contents), 0, 0);
  97.  
  98.         ResizeObjects(window);
  99.         RecalcGlobalCoords(thefabw);
  100.  
  101.         if (gDragManagerActive)
  102.             (void) MyInstallHWindow(window);
  103.         err = noErr;
  104.         }
  105.     }
  106. return err;
  107. }
  108.  
  109.  
  110. #pragma segment Main
  111.  
  112. /*
  113. GetDisasmVScrollValue: accessor */
  114.  
  115. short GetDisasmVScrollValue(void)
  116. {
  117. return GetControlValue(disasmVScroll);
  118. }
  119.  
  120.  
  121. void ScrollDisasmTo(short newPos)
  122. {
  123. SetControlValue(disasmVScroll, newPos);
  124. InvalDisasm();
  125. }
  126.  
  127. void DisasmHome(void)
  128. {
  129. SetControlValue(disasmVScroll, GetControlMinimum(disasmVScroll));
  130. InvalDisasm();
  131. }
  132.  
  133. void DisasmEnd(void)
  134. {
  135. SetControlValue(disasmVScroll, GetControlMaximum(disasmVScroll));
  136. InvalDisasm();
  137. }
  138.  
  139. void DisasmPgUp(void)
  140. {
  141. DisasmActionProc(disasmVScroll, kControlPageUpPart);
  142. }
  143.  
  144. void DisasmPgDn(void)
  145. {
  146. DisasmActionProc(disasmVScroll, kControlPageDownPart);
  147. }
  148.  
  149. /* DisasmInstruction: disassembles an instruction, returns a pointer to
  150. the next one. */
  151.  
  152. static short *DisasmInstruction(const short *inst, Ptr dest, ROpcDisasmPtr instrTbl, Size TblSize)
  153. {
  154. Str15    tempS;
  155. ROpcDisasmPtr    found;
  156. char *tempcPtr;
  157. short *newpos;
  158. short    theOperand;
  159.  
  160. newpos = inst + 1;    /* at least two bytes per instruction */
  161. tempcPtr = (char *)bsearch(inst, &instrTbl->first, TblSize, sizeof(ROpcDisasm), CompareFirstLast);
  162. if (tempcPtr) {
  163.     tempcPtr -= ((char *)&instrTbl->first - (char *)instrTbl);
  164.     found = (ROpcDisasmPtr)tempcPtr;
  165.     *(OSType *)dest = found->instr;
  166.     if (found->classe != kCLASS_16_0) {    /* there is an operand */
  167.         /* extra word ? */
  168.         theOperand = (found->classe == kCLASS_16_16 || found->classe == kCLASS_16_16_REL) ?
  169.                         *newpos++ : *inst & (found->last - found->first);
  170.         switch (found->classe) {    /* sign extensions for 12 & 11 bit operands */
  171.             case kCLASS_4_12:
  172.             case kCLASS_4_12_REL:
  173.                 theOperand <<= 4;
  174.                 theOperand >>= 4;
  175.                 break;
  176.             case kCLASS_5_11:
  177.                 theOperand <<= 5;
  178.                 theOperand >>= 5;
  179.                 break;
  180.             }
  181.         if (found->classe == kCLASS_4_12)
  182.             ShortToHexString(theOperand, tempS);
  183.         else
  184.             MyNumToString(theOperand, tempS);
  185.         tempcPtr = dest + 5;
  186.         if (found->classe == kCLASS_4_12)    /* hex value */
  187.             *tempcPtr++ = '$';
  188.         if (found->classe >= kCLASS_16_16_REL) {    /* relative jumps */
  189.             *tempcPtr++ = '*';
  190.             if (theOperand > 0)    /* wanna a plus sign before positive values */
  191.                 *tempcPtr++ = '+';
  192.             }
  193.         memcpy(tempcPtr, &tempS[1], tempS[0]);
  194.         tempcPtr += tempS[0];
  195.         if (found->classe >= kCLASS_16_16_REL) {    /* relative jumps */
  196.             *tempcPtr++ = ' ';
  197.             *tempcPtr++ = '(';
  198.             *tempcPtr++ = '$';
  199.             tempcPtr = ShortToHexText(PTR2MEMWORD(newpos) + theOperand, tempcPtr);
  200.             *tempcPtr++ = ')';
  201.             }
  202.         }
  203.     }
  204. else {    // illegal instruction
  205.     *(OSType *)dest = 'ILL*';
  206.     }
  207. return newpos;
  208. }
  209.  
  210. /* Activate_Disasm: handles activate events */
  211.  
  212. void Activate_Disasm(EventRecord */*evt*/, WindowPtr w, Handle, short, Boolean becomingActive)
  213. {
  214. Rect    growRect;
  215.  
  216. /* the growbox needs to be redrawn on activation: */
  217. botRight(growRect) = botRight(w->portRect);
  218. /* adjust for the scrollbars */
  219. growRect.top = growRect.bottom - kScrollbarAdjust + 1;
  220. growRect.left = growRect.right - kScrollbarAdjust + 1;
  221. InvalRect(&growRect);    /* we cannot avoid grow box flicker */
  222. if (becomingActive) {
  223.     if ((*disasmVScroll)->contrlVis == 0) {
  224.         ShowControl(disasmVScroll);
  225.         ValidRect(&(*disasmVScroll)->contrlRect);
  226.         }
  227.     }
  228. else {
  229. /* the control must be redrawn on deactivation: */
  230.     HideControl(disasmVScroll);
  231.     }
  232. } /*Activate*/
  233.  
  234. /* Grow_Disasm: handles resizing */
  235.  
  236. void Grow_Disasm(WindowPtr w, EventRecord *event)
  237. {
  238. Rect    tempRect, updateRect;
  239. long    growResult;
  240.  
  241. tempRect.right = tempRect.left = PRCT_R(w) + 1;
  242. tempRect.bottom = SHRT_MAX;        /* set up limiting values */
  243. tempRect.top = kMinDocDim + 30;
  244. updateRect = w->portRect;
  245. updateRect.top = updateRect.bottom - kScrollbarAdjust;
  246. /* see if it really changed size */
  247. if (growResult = GrowWindow(w, event->where, &tempRect)) {
  248.     SizeWindow(w, LoWrd(growResult),
  249.                 (HiWrd(growResult) / disasmLineHeight) * disasmLineHeight, true);
  250.     SizeControl(disasmVScroll, kScrollbarWidth, PRCT_B(w) - PRCT_T(w) - 13);
  251.     if (HiWrd(growResult) > updateRect.bottom)
  252.         /* enlarged */
  253.         InvalRect(&updateRect);
  254.     else /* reduced */ {
  255.         updateRect.bottom = PRCT_B(w);
  256.         updateRect.right = PRCT_R(w);
  257.         updateRect.top = updateRect.bottom - kScrollbarAdjust + 1;
  258.         updateRect.left = updateRect.right - kScrollbarAdjust + 1;
  259.         InvalRect(&updateRect);
  260.         }
  261.     ValidRect(&(*disasmVScroll)->contrlRect);
  262.     SetupDisasmCtlMax(disasmVScroll);
  263.     }
  264. }
  265.  
  266. /* Update_Disasm: handles window updates. */
  267.  
  268. void Update_Disasm(WindowPtr w, short)
  269. {
  270. Rect    growRect;
  271. RgnHandle    oldClip;
  272.  
  273. if (EmptyRgn(w->visRgn) == false) {    /* draw if updating needs to be done */
  274.     DrawDisasm(w);
  275.     oldClip = NewRgn();
  276.     GetClip(oldClip);
  277.     growRect = w->portRect;
  278.     growRect.left = growRect.right - kScrollbarAdjust;
  279.     ClipRect(&growRect);
  280.     DrawGrowIcon(w);
  281.     SetClip(oldClip);
  282.     DisposeRgn(oldClip);
  283.     UpdateControls(w, w->visRgn);
  284.     }
  285. }
  286.  
  287. /* Do_Disasm: we handle mouse clicks in scrollbars */
  288.  
  289. void Do_Disasm(WindowPtr w, EventRecord *event)
  290. {
  291. Rect    tempRect;
  292. GrafPtr    savePort;
  293. ControlHandle    control;
  294. Point    mouse;
  295. short    part;
  296.  
  297. mouse = event->where;        /* get the click position */
  298. GlobalToLocal(&mouse);
  299. /* see if we are in the disasm area; if so, we won’t check the controls */
  300. tempRect = w->portRect;
  301. tempRect.right -= kScrollbarAdjust;
  302. //if (PtInRect(mouse, &tempRect)) {
  303.     /* handle editing click */
  304. /*    if ((offset = mouse.h - disasmCWidMax * 6 - kDIST_FROMLEFT) >= 0)
  305.         if ((offset /= disasmCWidMax) % 5 != 4) {
  306.             tempRect.top = (mouse.v /= dumpLineHeight) * dumpLineHeight;
  307.             tempRect.left = ((offset / 5) * 5) * dumpCWidMax + dumpCWidMax * 6 + kDIST_FROMLEFT;
  308.             tempRect.bottom = tempRect.top + dumpLineHeight;
  309.             tempRect.right = tempRect.left + (dumpCWidMax << 2);
  310.             if (TrackObject(&tempRect)) {
  311.                 clickAddr = ((unsigned long)(GetDumpVScrollValue() + mouse.v) << 4)
  312.                             + ((offset / 5) << 1);
  313.                 if (DoEditDump((short *)(mMemory + clickAddr), clickAddr >> 1))
  314.                     DrawDump();
  315.                 UnloadSeg(DoEditDump);
  316.                 }
  317.             }*/
  318. //    }
  319. /*else*/ {
  320.     part = FindControl(mouse, w, &control);
  321.     switch ( part ) {
  322.         case 0:        /* do nothing for viewRect case */
  323.             break;
  324.         case kControlIndicatorPart:
  325.             GetPort(&savePort);
  326.             curPosW = GetNewWindow(kWIND_CurPos, nil, (WindowPtr)-1L);
  327.             SetPortWindowPort(curPosW);
  328.             TextMode(srcCopy);
  329.             TextFont(monaco);
  330.             TextSize(9);
  331.             SetPort(savePort);
  332. // Apple would like us not to use GhostWindow, but in this case we avoid
  333. // plenty of useless activate/deactivate events, so we don’t feel guilty.
  334.  
  335.             savePort = (GrafPtr)LMGetGhostWindow();
  336.             LMSetGhostWindow(curPosW);
  337.             ShowWindow(curPosW);
  338.             (void) TrackThumb(control, mouse, ThumbActionProc);
  339.             DisposeWindow(curPosW);
  340.             LMSetGhostWindow(savePort);
  341.             InvalDisasm();
  342.             break;
  343.         default:    /* clicked in an arrow, so track & scroll */
  344.             {
  345.             ControlActionUPP DisasmActionProcUPP = NewControlActionProc(DisasmActionProc);
  346.  
  347.             (void) TrackControl(control, mouse, DisasmActionProcUPP);
  348.             if (DisasmActionProcUPP)
  349.                 DisposeRoutineDescriptor(DisasmActionProcUPP);
  350.             }
  351.             break;
  352.         }
  353.     }
  354. }
  355.  
  356. /* ThumbActionProc: continuously called while we drag the scroll box */
  357.  
  358. static void ThumbActionProc(ControlHandle , short value)
  359. {
  360. Str15    tempS;
  361. GrafPtr    savePort;
  362.  
  363. ShortToHexString(value << 1, tempS);
  364. GetPort(&savePort);
  365. SetPort(curPosW);
  366. MoveTo(kDIST_FROMLEFT,12);
  367. DrawString(tempS);
  368. SetPort(savePort);
  369. }
  370.  
  371. /* DisasmActionProc: called when we hold mouse button down in some
  372. parts of the scroll bar. */
  373.  
  374. static pascal void DisasmActionProc(ControlHandle control, short part)
  375. {
  376. WindowPtr    w;
  377. short    amount, oldAmount;
  378.  
  379. if ( part ) {        /* if it was actually in the control */
  380.     w = (*control)->contrlOwner;
  381.     switch ( part ) {
  382.         case kControlUpButtonPart:
  383.             amount = -1;
  384.             break;
  385.         case kControlDownButtonPart:
  386.             amount = 1;
  387.             break;
  388.         case kControlPageUpPart:
  389.             amount = (PRCT_T(w) - PRCT_B(w)) / (disasmLineHeight * 2) + 1;
  390.             break;
  391.         case kControlPageDownPart:
  392.             amount = (PRCT_B(w) - PRCT_T(w)) / (disasmLineHeight * 2) - 1;
  393.             break;
  394.         }
  395.     SetControlValue(control, (oldAmount = GetControlValue(control)) + amount);
  396.     if (oldAmount != GetControlValue(control))
  397.         DrawDisasm(w);
  398.     }
  399. } /* DisasmActionProc */
  400.  
  401. /* DrawDisasm: redraws the entire Disassembler window */
  402.  
  403. void DrawDisasm(WindowPtr w)
  404. {
  405. Str27    disassembledText;
  406. Rect    tempRect, ToBeInverted;
  407. GrafPtr    savePort;
  408. Handle    tH;
  409. Point    tempPoint;
  410. short *addr;
  411. long *clrptr;
  412. short *textPtr;
  413. long    spaces = 0L;
  414. short    j, HilitePC;
  415. SignedByte    savedState;
  416.  
  417. GetPort(&savePort);
  418. SetPort(w);
  419. savedState = WantThisHandleSafe(tH = Get1Resource(krInstructions, kOPCODES));
  420. tempRect = w->portRect;
  421. tempRect.bottom += disasmLineHeight;
  422. spaces = GetControlValue(disasmVScroll);
  423. addr = (short *)&gMMemory[spaces << 2];
  424. for(tempPoint.h = kDIST_FROMLEFT, j = disasmFromTop;
  425.     tempPoint.v = j, PtInRect(tempPoint, &tempRect);
  426.     j += disasmLineHeight) {
  427.  
  428.     MoveTo(PRCT_L(w) + kDIST_FROMLEFT, j);
  429.     clrptr = (long *)&disassembledText;
  430.     spaces = '    ';
  431.     *clrptr++ = spaces;
  432.     *clrptr++ = spaces;
  433.     *clrptr++ = spaces;
  434.     *clrptr++ = spaces;
  435.     *clrptr++ = spaces;
  436.     *clrptr++ = spaces;
  437.     *clrptr = spaces;
  438.     textPtr = (short *)ShortToHexText(HilitePC = PTR2MEMWORD(addr), (Ptr)&disassembledText);
  439.     *textPtr++ = ': ';
  440.     addr = DisasmInstruction(addr, (Ptr)textPtr, (ROpcDisasmPtr)((*tH) + 2), *(unsigned short *)*tH + 1);
  441.  
  442.     DrawText(&disassembledText, 0L, 28L);
  443.     if (HilitePC == gRegs[kREG_PC]) {
  444.         ToBeInverted.top = j - disasmLineHeight + 1;
  445.         ToBeInverted.left = PRCT_L(w) + kDIST_FROMLEFT;
  446.         ToBeInverted.bottom = j + 1;
  447.         ToBeInverted.right = ToBeInverted.left + disasmCWidMax * kMaxCharsInOneDisasmLine;
  448.         LMSetHiliteMode(LMGetHiliteMode() & 0x7F);
  449.         InvertRect(&ToBeInverted);
  450.         }
  451.     }
  452. HSetState(tH, savedState);
  453. SetPort(savePort);
  454. }
  455.  
  456. /* SetupDisasmCtlMax: sets up the CtlMax value of our scroll bar */
  457.  
  458. void SetupDisasmCtlMax(ControlHandle theControl)
  459. {
  460. enum {
  461. kAdjustForPleasantGrow = 3
  462. };
  463.  
  464. WindowRef    wind;
  465. short    newmax;
  466.  
  467. wind = (*theControl)->contrlOwner;
  468. newmax = SHRT_MAX - (PRCT_B(wind) - PRCT_T(wind) - kAdjustForPleasantGrow) / (disasmLineHeight << 1);
  469. if (newmax != GetControlMaximum(theControl)) {
  470.     SetControlMaximum(theControl, newmax);
  471.     InvalDisasm();
  472.     }
  473. }
  474.  
  475. /* InvalDisasm: invalidates the entire window contents
  476. (excluding the scrollbar) */
  477.  
  478. void InvalDisasm(void)
  479. {
  480. Rect    tempRect;
  481. GrafPtr    savePort;
  482.  
  483. GetPort(&savePort);
  484. SetPortWindowPort(gWPtr_Disasm);
  485. tempRect = gWPtr_Disasm->portRect;
  486. tempRect.right -= kScrollbarWidth;
  487. InvalRect(&tempRect);
  488. SetPort(savePort);
  489. }
  490.  
  491. /* procedure called when closing the Disasm window */
  492.  
  493. void CloseDisasm(WindowPtr w)
  494. {
  495. DoCloseWindow(w, kMItem_Disasm);
  496. }
  497.  
  498. void getDragRectDisasm(WindowPtr w, RectPtr r)
  499. {
  500. *r = w->portRect;
  501. r->right -= kScrollbarAdjust;
  502. }
  503.  
  504.  
  505. #endif
  506.  
  507.