diff --git a/DEBUGGER.TXT b/DEBUGGER.TXT index d09e7b2..f48cdf9 100644 --- a/DEBUGGER.TXT +++ b/DEBUGGER.TXT @@ -301,9 +301,17 @@ CE1 | nc. | BS | Slt1 32/128KB | BS | BS CE2 | nc. | nc. | Slt2 32/128KB | Slt1 32/128KB | RAM 128KB NCE3 | nc. | RAM 128KB | nc. | Slt2 32KB-4MB | RAM 128KB +- Load Memory Data... + +The "Load Memory Data" dialog box allows loading memory dump files to the specified address inside the Saturn address area. The specified address must point to RAM, writing into ROM areas isn't possible. The memory dump file must be in packed data format, meaning each byte in file contain two Saturn data nibbles with the low nibble containing the even and the high nibble the following odd address. The disadvantage of packed files is that you cannot load memory files with an odd number of data nibbles, but the advantage is that you can directly load an assembler output to memory. + +- Save Memory Data... + +The "Save Memory Data" dialog box allows saving the data of the specified Saturn address area into a memory dump file. The memory dump file contain the data in packed data format, meaning each byte in file contain two Saturn data nibbles with the low nibble containing the even and the high nibble the following odd address. + - RPL Object Viewer... -This opens a small toolbox window showing the decompiled RPL object at the memory address marked by the cursor. If the toolbox window is already open the content will be updated. There's a problem if you want to select an address inside the marked two addresses. The easiest way to switch the address is the use of the + and - keys changing the memory position by one nibble under the cursor. +This opens a small toolbox window showing the decompiled RPL object in the selected memory map mode at the memory address marked by the cursor. If the toolbox window is already open the content will be updated. There's a problem if you want to select an address inside the marked two addresses. The easiest way to switch the address is the use of the + and - keys changing the memory position by one nibble under the cursor. 9.) Stack window @@ -346,4 +354,4 @@ The Miscellaneous window show you the internal state of the interrupt flag, the You can change the values by pressing the left mouse button over the old content. -04/04/09 (c) by Christoph Gießelink +05/02/12 (c) by Christoph Gießelink diff --git a/EMU48.EXE b/EMU48.EXE deleted file mode 100755 index fc3fab8..0000000 Binary files a/EMU48.EXE and /dev/null differ diff --git a/Emu48.exe b/Emu48.exe new file mode 100755 index 0000000..2547bdd Binary files /dev/null and b/Emu48.exe differ diff --git a/KML_20.DOC b/KML_20.DOC index d352c87..57e6624 100644 --- a/KML_20.DOC +++ b/KML_20.DOC @@ -1,12 +1,12 @@ -{\rtf1\ansi\ansicpg1252\deff0\deflang1031\deflangfe1031{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\fmodern\fprq1\fcharset0 Courier New;}{\f2\fswiss\fprq2\fcharset0 Arial;}} +{\rtf1\ansi\ansicpg1252\deff0\deflang1031\deflangfe1031{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\fmodern\fprq1\fcharset0 Courier New;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset2 Symbol;}} {\colortbl ;\red0\green0\blue0;\red0\green0\blue255;} {\*\generator Msftedit 5.41.15.1515;}\viewkind4\uc1\pard\nowidctlpar\qc\lang1033\f0\fs56 EmuXY and KML 2.0\par \pard\nowidctlpar\fs24\par \b\fs28 Introduction\b0\par \fs24\par -\pard\nowidctlpar\qj\tab This document explains in detail the KML 2.0 scripting files. KML, Keyboard Mapping Language, started of as a script that Emu48 used to map keyboard buttons with buttons of the emulator, now it has become much more. KML 2.0, also used by Emu10, Emu28 and Emu42, now makes it possible to change many advanced options of the way the emulator looks.\par +\pard\nowidctlpar\qj\tab This document explains in detail the KML 2.0 scripting files. KML, Keyboard Mapping Language, started as a script that Emu48 used to map keyboard buttons with buttons of the emulator, now it has become much more. KML 2.0, also used by Emu10, Emu28, Emu42 and Emu71, now makes it possible to change many advanced options of the way the emulator looks.\par \par -The description of Emu32 has been removed from this document. The development of Emu32 was quit, the emulated calculators are now emulated by Emu42. So Emu42 now emulates two quite different hardware platforms, the High End Pioneer and Clamshell series with a dot matrix display which base on the Lewis chip and the Mid Range Pioneer series with a semi dot matrix display which base on the Sacajawea chip. To distinguish both emulation platforms I use, if necessary, Emu42 (Lewis) and Emu42 (Sacajawea) in the further text.\par +The description of Emu32 has been removed from this document. The development of Emu32 has quit, the emulated calculators are now emulated by Emu42. So Emu42 now emulates two quite different hardware platforms, the High End Pioneer and Clamshell series with a dot matrix display which base on the Lewis chip and the Mid Range Pioneer series with a semi dot matrix display which base on the Sacajawea chip. To distinguish both emulation platforms I use, if necessary, Emu42 (Lewis) and Emu42 (Sacajawea) in the further text.\par \pard\nowidctlpar\par \b\fs40 Index\fs28\par \b0\fs24\par @@ -18,8 +18,8 @@ Digit\tab Page 9\par \lang1040 Annunciator\tab Page 10\par Button\tab Page 11\par \lang1036 OutIn Codes\tab Page 13\par -Scancode\tab Page 21\par -Conclusion\b\fs28\tab\b0\fs24 Page 24\par +Scancode\tab Page 22\par +Conclusion\b\fs28\tab\b0\fs24 Page 25\par \pard\nowidctlpar\b\fs28\par \lang1033 Basics\b0\par \fs24\par @@ -54,13 +54,15 @@ End\par \f0\fs24\par \pard\nowidctlpar\qj Hardware is the emulated calculator hardware. This definition is optional on Emu48. The parameter is necessary to separate the KML scripts from each emulator. Valid entries are\par \pard\nowidctlpar Emu10:\par -\f1\fs16\tab\lang1031 Hardware \ldblquote Bert\rdblquote\par +\f1\fs16\tab Hardware \ldblquote Bert\rdblquote\par \f0\fs24 Emu28:\par -\f1\fs16\tab\lang1033 Hardware \ldblquote Centipede\rdblquote\par +\f1\fs16\tab Hardware \ldblquote Centipede\rdblquote\par \f0\fs24 Emu42:\par \f1\fs16\tab Hardware \ldblquote Lewis\rdblquote\par \f0\fs24 Emu48:\par \f1\fs16\tab Hardware \ldblquote Yorke\rdblquote\par +\f0\fs24 Emu71:\par +\f1\fs16\tab Hardware \ldblquote Saturn\rdblquote\par \f0\fs24\par \pard\nowidctlpar\qj\page Model is the model of your emulated calculator inside the hardware family. The model entries differ from hardware to hardware. This setting groups KML files of the same hardware and ROM together.\cf1 When switching between KML scripts, it is the first character of the parameter that is checked against the type of the current document (which was set by the Model command in the KML file with which the document was created). Valid entries are:\par Emu10:\par @@ -85,8 +87,10 @@ Emu10:\par \ldblquote G\rdblquote = HP48G, HP48G+ or HP48GX\par \ldblquote S\rdblquote = HP48S or HP48SX\par \ldblquote X\rdblquote = HP49G\cf1\par -\pard\nowidctlpar\qj\cf0 Example:\par -\pard\nowidctlpar\f1\fs16\tab Model \ldblquote G\rdblquote\par +\pard\nowidctlpar\qj Emu71:\par +\pard\nowidctlpar\fi720\qj\cf0\lang1036\ldblquote T\rdblquote = HP71B\par +\pard\nowidctlpar\qj Example:\par +\pard\nowidctlpar\f1\fs16\tab\lang1033 Model \ldblquote G\rdblquote\par \f0\fs24\par \pard\nowidctlpar\qj Class is used for different calculators base on the same ROM for further distinction. For other models than listed below this argument can be omitted. \cf1 Valid entries are:\par Emu42:\par @@ -159,13 +163,13 @@ End\par \lang1031\f1\fs16 Lcd\par \tab Zoom INTEGER\par \tab Zoomxy INTEGER INTEGER\par -\tab Vertical INTEGER\par +\tab\lang1033 Vertical INTEGER\par \tab Offset INTEGER INTEGER\par \tab Color INTEGER INTEGER INTEGER INTEGER\par -\lang1033 End\par +End\par \f0\fs24\par \par -\pard\nowidctlpar\qj Zoom is the size of the pixels in the LCD screen. This command is only valid for Emu28, Emu42 (Lewis) and Emu48 and will be ignored on Emu10 and Emu42 (Sacajawea). Valid entries are 1, 2, 3 or 4. Zoom factor two is usually used by the dot matrix LCD types emulated by Emu28, Emu42 (Lewis) and Emu48.\par +\pard\nowidctlpar\qj Zoom is the size of the pixels in the LCD screen. This command is only valid for Emu28, Emu42 (Lewis) Emu48 and Emu71 and will be ignored on Emu10 and Emu42 (Sacajawea). Valid entries are 1, 2, 3 or 4. Zoom factor two is usually used by the dot matrix LCD types emulated by Emu28, Emu42 (Lewis), Emu48 and Emu71.\par \pard\nowidctlpar Example:\par \f1\fs16\tab Zoom 2\par \f0\fs24\par @@ -177,19 +181,22 @@ Example:\par \pard\nowidctlpar Example:\par \f1\fs16\tab Offset 20 20\par \f0\fs24\par -\pard\nowidctlpar\qj Color sets the color of the LCD display for different contrast settings. The first Integer is the contrast setting for each possible value. The number of settings depend on the hardware type.\par +\pard\nowidctlpar\qj Color sets the color of the LCD display for different contrast settings. The first Integer is the contrast setting value. The number of setting values depends on the hardware type.\par +\par Emu10:\par \pard\nowidctlpar\fi720\qj 0-7 = 0 is lightest, 7 is darkest\par -\pard\nowidctlpar\qj Emu42 (Sacajawea):\par +\pard\nowidctlpar\qj Emu42 (Sacajawea), Emu71:\par \pard\nowidctlpar\fi720\qj 0-15 = foreground colors (Pixel on), 0 is lightest, 15 is darkest\par 16-31 = background colors (Pixel off), 16 corresponds to 0, 17 to 1, \'85\par -unused number at background colors = transparent\par -\pard\nowidctlpar\qj Emu28, Emu42 (Lewis), Emu48:\par +\pard\nowidctlpar\qj Emu28, Emu42 (Lewis):\par \pard\nowidctlpar\fi720\qj 0-31 = foreground colors (Pixel on), 0 is lightest, 15 is darkest\par 32-63 = background colors (Pixel off), 32 corresponds to 0, 33 to 1, \'85\par -unused number at background colors = use color defined by setting 0\par +\pard\nowidctlpar\qj Emu48:\par +\pard\nowidctlpar\fi720\qj 0-31 = foreground colors (Pixel on), 0 is lightest, 15 is darkest\par +32-63 = background colors (Pixel off), 32 corresponds to 0, 33 to 1, \'85\par +unused value at background color = use color defined by setting 0\par \pard\nowidctlpar\qj\par -You should include one line for every foreground color setting. The other three integers are the RGB numbers (Red, Green, Blue). The RGB numbers range from 0 to 255. The background color number for the corresponding foreground color is always calculated by adding the first background number setting to the color value. If the background color for the contrast setting isn't defined, color 0 is used by the emulators Emu28, Emu42 (Lewis) and Emu48 and transparent mode by Emu10 and Emu42 (Sacajawea).\par +You should include one line for every foreground color setting. The other three integers are the RGB numbers (Red, Green, Blue). The RGB numbers range from 0 to 255. The background color number for the corresponding foreground color is always calculated by adding the first background number setting to the color value. At Emu42 for Pocket PC and Emu48 an undefined foreground color value 0 mean \ldblquote white\rdblquote else \ldblquote black\rdblquote , an undefined background color means using foreground color 0. At Emu10, Emu28, Emu42 (Sacajawea), Emu42 (Lewis) and Emu71 undefined contrast settings mean transparent mode showing the background image.\par \pard\nowidctlpar Example:\par \f1\fs16\tab Color 0 255 255 255\par \tab Color 1 220 220 220\par @@ -198,7 +205,7 @@ You should include one line for every foreground color setting. The other three \tab Color 31 0 0 0\par \tab Color 32 255 255 255\tab # optional background color for contrast setting\par \pard\nowidctlpar\qj\f0\fs24\par -But the calculator Rom bounds the contrast setting with the keyboard to useful values for each calculator model. The easiest way to generate reasonable contrast settings is to put the calculator to lowest possible darkness value by keyboard and enter the corresponding RGB values to your KML script at the lowest possible setting by ROM (background = pixel off color, foreground = near to background color). In the next step put the calculator to highest possible darkness value by keyboard and enter the corresponding RGB values to your KML script at the highest possible setting by ROM (background = pixel on color, foreground = near to background color). Next important point is the darkness reset value of the Rom because this should be the point of best contrast between fore- and background color. So in the first range between lowest darkness and reset point, use the pixel off color for all background colors and calculated RGB values by a nearly equal distance algorithm for each color part for the foreground colors. For the second range between reset point and highest darkness use the foreground pixel color of the reset point for all foreground colors and calculated RGB values by a nearly equal distance algorithm for each color part for the background colors.\par +But the calculator ROM bounds the contrast setting with the keyboard to useful values for each calculator model. The easiest way to generate reasonable contrast settings is to put the calculator to lowest possible darkness value by keyboard and enter the corresponding RGB values to your KML script at the lowest possible setting by ROM (background = pixel off color, foreground = near to background color). In the next step put the calculator to highest possible darkness value by keyboard and enter the corresponding RGB values to your KML script at the highest possible setting by ROM (background = pixel on color, foreground = near to background color). Next important point is the darkness reset value of the Rom because this should be the point of best contrast between fore- and background color. So in the first range between lowest darkness and reset point, use the pixel off color for all background colors and calculated RGB values by a nearly equal distance algorithm for each color part for the foreground colors. For the second range between reset point and highest darkness use the foreground pixel color of the reset point for all foreground colors and calculated RGB values by a nearly equal distance algorithm for each color part for the background colors.\par \par The contrast settings outside these areas (accessible by hardware so it\rquote s not useless) can be calculated by the distance between each color channel with saturation to no contrast at pixel off on one side, and pixel on the other side.\par \par @@ -223,13 +230,14 @@ The contrast settings outside these areas (accessible by hardware so it\rquote s \clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx1243\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx2410\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx3261\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx4111\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx4962\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx5812\pard\intbl\nowidctlpar HP42S\cell Emu42\cell 0-31\cell 22\cell 15\cell 31\cell\row\trowd\trgaph70\trleft-70\trbrdrl\brdrs\brdrw10 \trbrdrt\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trpaddl70\trpaddr70\trpaddfl3\trpaddfr3 \clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx1243\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx2410\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx3261\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx4111\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx4962\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx5812\pard\intbl\nowidctlpar HP48SX\cell Emu48\cell 0-31\cell 11\cell 3\cell 19\cell\row\trowd\trgaph70\trleft-70\trbrdrl\brdrs\brdrw10 \trbrdrt\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trpaddl70\trpaddr70\trpaddfl3\trpaddfr3 \clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx1243\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx2410\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx3261\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx4111\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx4962\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx5812\pard\intbl\nowidctlpar HP48GX\cell Emu48\cell 0-31\cell 14\cell 9\cell 24\cell\row\trowd\trgaph70\trleft-70\trbrdrl\brdrs\brdrw10 \trbrdrt\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trpaddl70\trpaddr70\trpaddfl3\trpaddfr3 -\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs\clbrdrb\brdrw15\brdrs \cellx1243\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs\clbrdrb\brdrw15\brdrs \cellx2410\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs\clbrdrb\brdrw15\brdrs \cellx3261\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs\clbrdrb\brdrw15\brdrs \cellx4111\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs\clbrdrb\brdrw15\brdrs \cellx4962\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs\clbrdrb\brdrw15\brdrs \cellx5812\pard\intbl\nowidctlpar HP49G\cell Emu48\cell 0-31\cell 14\cell 9\cell 24\cell\row\pard\nowidctlpar\qj\par +\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx1243\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx2410\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx3261\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx4111\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx4962\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx5812\pard\intbl\nowidctlpar HP49G\cell\lang1031 Emu48\cell 0-31\cell 14\cell 9\cell 24\cell\row\trowd\trgaph70\trleft-70\trbrdrl\brdrs\brdrw10 \trbrdrt\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trpaddl70\trpaddr70\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs\clbrdrb\brdrw15\brdrs \cellx1243\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs\clbrdrb\brdrw15\brdrs \cellx2410\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs\clbrdrb\brdrw15\brdrs \cellx3261\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs\clbrdrb\brdrw15\brdrs \cellx4111\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs\clbrdrb\brdrw15\brdrs \cellx4962\clbrdrl\brdrw15\brdrs\clbrdrr\brdrw15\brdrs\clbrdrb\brdrw15\brdrs \cellx5812\pard\intbl\nowidctlpar HP71B\cell Emu71\cell\lang1033 0-15\cell 9\cell 0\cell 15\cell\row\pard\nowidctlpar\qj\par Range\tab : hardware range (accessible by assembler)\par Reset\tab : contrast value after calculator reset\par Min\tab : min. adjustable contrast value by keyboard\par Max\tab : max. adjustable contrast value by keyboard\par \par -\pard\nowidctlpar On Emu28 and Emu42 (Lewis) the contrast setting of the annunciators depend on the current main display contrast setting and the contrast setting of each annunciator. In normal operation the annunciator color of an on annunciator is exactly the pixel on color of the current contrast. Modifying the annunciator contrast from the default setting will choose a color below or above the current pixel on contrast setting. To avoid any misbehaviors fill the complete display color table of the emulator with reasonable values please.\par +\pard\nowidctlpar On Emu28 and Emu42 (Lewis) the contrast setting of the annunciators depends on the current main display contrast setting and the contrast setting of each annunciator. In normal operation the annunciator color of an on annunciator is exactly the pixel on color of the current contrast. Modifying the annunciator contrast from the default setting will choose a color below or above the current pixel on contrast setting. To avoid any misbehaviors fill the complete display color table of the emulator with reasonable values please.\par \par \pard\nowidctlpar\qj Vertical is a special command only for the Pocket PC versions of Emu42 (Lewis) and Emu48 to rotate the display by 90\u730? clock or anticlockwise to allow skins in landscape mode. Valid entries are 0 for portrait, 1 for anticlockwise and 2 for clockwise rotated landscape mode. The default setting is portrait mode.\par \pard\nowidctlpar Example:\par @@ -237,12 +245,12 @@ Max\tab : max. adjustable contrast value by keyboard\par \f0\fs24\par \page\b\fs28 Digit\par \fs24\par -\pard\nowidctlpar\qj\b0\tab This section is only valid for Emu10 and Emu42 (Sacajawea) and describes the (alpha-) numeric part of the LCD screen. Emu10 and Emu42 (Sacajawea) use different methods for creating a numeric value.\b\par +\pard\nowidctlpar\qj\b0\tab This section is only valid for Emu10 and Emu42 (Sacajawea) and describes the (alpha-) numeric part of the LCD screen. Emu10 and Emu42 (Sacajawea) are using different methods for creating a numeric value.\b\par \pard\nowidctlpar\b0\par \lang1031\f1\fs16 Digit\par \tab Offset INTEGER INTEGER\par -\tab\lang1033 Size INTEGER INTEGER\par -\tab Distance INTEGER\par +\tab Size INTEGER INTEGER\par +\tab\lang1033 Distance INTEGER\par \tab Bitmap STRING\par End\par \f0\fs24\par @@ -260,7 +268,7 @@ The commands Offset and Size are unused.\par \f1\fs16\tab Bitmap \ldblquote mylcd.bmp\rdblquote\par \f0\fs24\par Emu42 (Sacajawea):\par -The mid range Pioneer series use a 5x7 pixel dot matrix for each digit.\par +The Mid Range Pioneer series use a 5x7 pixel dot matrix for each digit.\par \par Size is the size of one pixel in the LCD screen. Width Height.\par Example:\par @@ -280,17 +288,17 @@ Example:\par \f0\fs24\par \b\fs28\page Annunciator\par \b0\fs24\par -\pard\nowidctlpar\qj\tab Annunciators are the 23 (Emu10), 60 (Emu42 (Sacajawea)), six (Emu48) and seven (Emu28, Emu42 (Lewis)) status icons on the screen. You must specify one of these blocks for each annunciator.\par +\pard\nowidctlpar\qj\tab Annunciators are the 23 (Emu10), 60 (Emu42 (Sacajawea)), six (Emu48), seven (Emu28, Emu42 (Lewis)) and 32 (Emu71) status icons on the screen. You must specify one of these blocks for each annunciator.\par \pard\nowidctlpar\par \par -\lang1031\f1\fs16 Annunciator INTEGER\par +\f1\fs16 Annunciator INTEGER\par \tab Size INTEGER INTEGER\par \tab Offset INTEGER INTEGER\par -\tab\lang1033 Down INTEGER INTEGER\par +\tab Down INTEGER INTEGER\par End\par \f0\fs24\par \par -\pard\nowidctlpar\qj Annunciator tells which annunciator you are setting. Valid entries are emulator depending and can vary from 1 through 6, 7, 23 or 60. The annunciator symbol itself depends on the specific LCD of the calculator. Refer to existing KML scripts for getting the symbol of each annunciator.\par +\pard\nowidctlpar\qj Annunciator tells which annunciator you are setting. Valid entries are emulator depending and can vary from 1 through 6, 7, 23, 32 or 60. The annunciator symbol itself depends on the specific LCD of the calculator. Refer to existing KML scripts for getting the symbol of each annunciator.\par \pard\nowidctlpar Example:\par \pard\nowidctlpar\fi720\f1\fs16 Annunciator 1\par \pard\nowidctlpar\f0\fs24\par @@ -302,7 +310,7 @@ Offset is the position that the annunciator will be displayed. This is the blank Example:\par \f1\fs16\tab Offset 61 4\par \f0\fs24\par -\pard\nowidctlpar\qj Down is the position of the annunciator in the bitmap when it is on. There are some restrictions on the different emulators. On Emu10 and Emu42 (Sacajawea) the annunciators must be drawn in black on a white background. On Emu28 and Emu42 (Lewis) the pixel at the Down position must contain the background color, this is necessary for masking operation. Emu48 don\rquote t mask the background color, here the annunciator must have the background color of the target area.\par +\pard\nowidctlpar\qj Down is the position of the annunciator in the bitmap when it is on. There are some restrictions on the different emulators. On Emu10 and Emu42 (Sacajawea) the annunciators must draw in black on a white background. On Emu28 and Emu42 (Lewis) and Emu71 the pixel at the Down position must contain the background color, this is necessary for masking operation. Emu48 don\rquote t mask the background color, here the annunciator must have the background color of the target area.\par \pard\nowidctlpar Example:\par \f1\fs16\tab Down 16 485\par \f0\fs24\par @@ -310,11 +318,11 @@ Example:\par \b0\fs24\par \tab Button sets the position of the button and what the button does.\par \par -\lang1031\f1\fs16 Button INTEGER\par +\f1\fs16 Button INTEGER\par \tab Type INTEGER\par \tab Size INTEGER INTEGER\par \tab Offset INTEGER INTEGER\par -\tab\lang1033 Down INTEGER INTEGER\par +\tab Down INTEGER INTEGER\par \tab OutIn INTEGER INTEGER\par \tab Virtual\par \tab NoHold\par @@ -327,8 +335,8 @@ Example:\par End\par \f0\fs24\par \par -\pard\nowidctlpar\qj Button tells the number of the button you are creating. This can be any number. Most of the time this \cf1 is set to a number that represents the row and column of the button. Any number can be used, but only 256 buttons can be declared. If more buttons are declared, only the first 256 will be used, and the others will be ignored.\par -\pard\nowidctlpar Example:\par +\pard\nowidctlpar\qj Button tells the number of the button you are creating. This can be any number. Most times the number is chosen representing \cf1 the row and column number of the button.\cf0 \cf1 Any number can be used, but only 256 buttons can be declared. If more buttons are declared, only the first 256 will be used, and the others will be ignored.\cf0\par +\pard\nowidctlpar\cf1 Example:\par \cf0\f1\fs16\tab Button 11\par \f0\fs24\par \pard\nowidctlpar\qj\cf1 Type tells how the button will behave when it is pressed. Valid entries are 0, 1, 2, 3, 4, or 5.\par @@ -345,7 +353,7 @@ Type 4 is copying a part of the background bitmap with the dimension Size from t \par Type 5 is drawing a transparent circle inside the rectangle given by Size into the middle of the button area given by target position Offset and the dimension Size.\par \par -All other Type values are drawing a black rectangle with the dimension Size at the target position Offset. Remember that this behavior can change on introducing a new type. So don\rquote t use this type in public scripts.\par +\page All other Type values are drawing a black rectangle with the dimension Size at the target position Offset. Remember that this behavior can change on introducing a new type. So don\rquote t use this type in public scripts.\par \pard\nowidctlpar Example:\par \cf0\f1\fs16\tab Type 0\par \f0\fs24\par @@ -361,7 +369,7 @@ Example:\par \pard\nowidctlpar Example:\par \f1\fs16\tab Down 302 25\par \f0\fs24\par -\pard\nowidctlpar\qj OutIn tells the emulator which button is being pressed. A table of OutIn codes are on the next page of this document.\par +\pard\nowidctlpar\qj OutIn tells the emulator which button is being pressed. Tables of OutIn codes are on the next pages of this document.\par \pard\nowidctlpar Example:\par \pard\nowidctlpar\qj\f1\fs16\tab OutIn 1 16\par \f0\fs24\par @@ -680,8 +688,32 @@ Example:\par \clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx1179\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx2389\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx3598\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx4808\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx6018\pard\intbl\nowidctlpar\cf1\b0\fs20 7 4\cell 3 4\cell 2 4\cell 1 4\cell 0 4\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 \clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx1179\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx2389\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx3598\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx4808\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx6018\pard\intbl\nowidctlpar\cf2\b\fs24 /-.>\cell 1\cell 2\cell 3\cell +\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 \clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx1179\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx2389\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx3598\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx4808\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx6018\pard\intbl\nowidctlpar\cf1\b0\fs20 7 2\cell 3 2\cell 2 2\cell 1 2\cell 0 2\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 -\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx1179\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx2389\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx3598\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx4808\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx6018\pard\intbl\nowidctlpar\cf2\b\fs24 ON\cell 0\cell .\cell SPC\cell ENTER\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 -\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx1179\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx2389\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx3598\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx4808\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx6018\pard\intbl\nowidctlpar\cf1\b0\fs20 0 32768\cell 3 1\cell 2 1\cell 1 1\cell 0 1\cell\row\pard\nowidctlpar\cf0\b\f0\fs28\page Scancode\b0\fs24\par +\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx1179\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx2389\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx3598\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx4808\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx6018\pard\intbl\nowidctlpar\cf2\b\fs24 ON\cell\lang1036 0\cell .\cell SPC\cell ENTER\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx1179\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx2389\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx3598\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx4808\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx6018\pard\intbl\nowidctlpar\cf1\b0\fs20 0 32768\cell 3 1\cell 2 1\cell 1 1\cell 0 1\cell\row\pard\nowidctlpar\cf0\f0\fs24\par +\pard\nowidctlpar\qj\b\fs28 OutIn Codes HP71B\par +\pard\nowidctlpar\b0\fs24\par +\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx849\cellx1698\cellx2549\cellx3399\cellx4250\cellx5100\cellx5951\cellx6801\cellx7653\cellx8505\pard\intbl\nowidctlpar\cf2\lang1033\b\f2 Key\cell\b0\cell\cell\cell\cell\cell\cell\cell\cell\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx849\cellx1698\cellx2549\cellx3399\cellx4250\cellx5100\cellx5951\cellx6801\cellx7653\cellx8505\pard\intbl\nowidctlpar\cf1\b\fs20 OutIn\cell\b0\cell\cell\cell\cell\cell\cell\cell\cell\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\cellx849\cellx1698\cellx2549\cellx3399\cellx4250\cellx5100\cellx5951\cellx6801\cellx7653\cellx8505\pard\intbl\nowidctlpar\b\fs16\cell\b0\cell\cell\cell\cell\cell\cell\cell\cell\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx849\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx1698\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx2549\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx3399\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx4250\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx5100\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx5951\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx6801\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx7653\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx8505\pard\intbl\nowidctlpar\cf2\b\fs24 Q\cell\lang1040 W\cell E\cell R\cell\lang1036 T\cell Y\cell U\cell\lang1040 I\cell O\cell P\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx849\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx1698\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx2549\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx3399\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx4250\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx5100\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx5951\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx6801\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx7653\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx8505\pard\intbl\nowidctlpar\cf1\lang1033\b0\fs20 3 1\cell 3 2\cell 3 4\cell 3 8\cell 3 16\cell 3 32\cell 3 64\cell 3 128\cell 3 256\cell 3 512\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx849\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx1698\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx2549\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx3399\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx4250\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx5100\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx5951\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx6801\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx7653\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx8505\pard\intbl\nowidctlpar\cf2\b\fs24 A\cell S\cell D\cell F\cell G\cell H\cell\lang1031 J\cell K\cell L\cell =\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx849\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx1698\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx2549\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx3399\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx4250\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx5100\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx5951\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx6801\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx7653\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx8505\pard\intbl\nowidctlpar\cf1\b0\fs20 2 1\cell 2 2\cell 2 4\cell 2 8\cell 2 16\cell 2 32\cell 2 64\cell 2 128\cell 2 256\cell 2 512\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx849\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx1698\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx2549\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx3399\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx4250\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx5100\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx5951\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx6801\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx7653\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx8505\pard\intbl\nowidctlpar\cf2\b\fs24 Z\cell X\cell C\cell\lang1033 V\cell B\cell N\cell M\cell (\cell )\cell END\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx849\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx1698\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx2549\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx3399\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx4250\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx5100\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx5951\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx6801\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx7653\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx8505\pard\intbl\nowidctlpar\cf1\b0\fs20 1 1\cell 1 2\cell 1 4\cell 1 8\cell 1 16\cell 1 32\cell 1 64\cell 1 128\cell 1 256\cell\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx849\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx1698\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx2549\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx3399\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx4250\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx5100\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx5951\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx6801\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx7653\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx8505\pard\intbl\nowidctlpar\cf2\b\fs24 ON\cell F\cell G\cell RUN\cell <\cell >\cell SPC\cell\f3\'d9\f2\cell\f3\'da\f2\cell LINE\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx849\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx1698\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx2549\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx3399\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx4250\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx5100\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx5951\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx6801\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx7653\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx8505\pard\intbl\nowidctlpar\cf1\b0\fs20 0 32769\cell 0 2\cell 0 4\cell 0 8\cell 0 16\cell 0 32\cell 0 64\cell 0 128\cell 0 256\cell 1 512\cell\row\pard\nowidctlpar\cf0\b\f0\fs28\par +\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx851\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx1701\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx2552\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx3402\pard\intbl\nowidctlpar\cf2\f2\fs24 7\cell 8\cell 9\cell /\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx851\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx1701\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx2552\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx3402\pard\intbl\nowidctlpar\cf1\b0\fs20 3 1024\cell 3 2048\cell 3 4096\cell 3 8192\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx851\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx1701\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx2552\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx3402\pard\intbl\nowidctlpar\cf2\b\fs24 4\cell 5\cell 6\cell *\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx851\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx1701\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx2552\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx3402\pard\intbl\nowidctlpar\cf1\b0\fs20 2 1024\cell 2 2048\cell 2 4096\cell 2 8192\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx851\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx1701\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx2552\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx3402\pard\intbl\nowidctlpar\cf2\b\fs24 1\cell 2\cell 3\cell -\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx851\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx1701\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx2552\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx3402\pard\intbl\nowidctlpar\cf1\b0\fs20 1 1024\cell 1 2048\cell 1 4096\cell 1 8192\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx851\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx1701\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx2552\clbrdrl\brdrw30\brdrs\clbrdrt\brdrw30\brdrs\clbrdrr\brdrw30\brdrs \cellx3402\pard\intbl\nowidctlpar\cf2\b\fs24 0\cell .\cell ,\cell +\cell\row\trowd\trgaph30\trleft-30\trpaddl30\trpaddr30\trpaddfl3\trpaddfr3 +\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx851\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx1701\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx2552\clbrdrl\brdrw30\brdrs\clbrdrr\brdrw30\brdrs\clbrdrb\brdrw30\brdrs \cellx3402\pard\intbl\nowidctlpar\cf1\b0\fs20 0 1024\cell 0 2048\cell 0 4096\cell 0 8192\cell\row\pard\nowidctlpar\cf0\b\f0\fs28\par +\page Scancode\b0\fs24\par \par \pard\nowidctlpar\qj\tab The Scancode defines what the emulator will do when a certain key on the keyboard is pressed. Pressing a key that has no scancode defined will (only if debug mode is on) display a message box with the key's scancode number, so that you can write a Scancode block. The commands in the Scancode block are executed twice, first when the key is pressed and a second time when the key is released. Flags can help to transfer information (for example can be set to show that a shift key is pressed) from one Scancode block to another. Valid flags are 0-31.\par \pard\nowidctlpar\par @@ -703,16 +735,16 @@ or\par \tab\tab \par \tab End\par Or\par -\tab\lang1031 IfMem INTEGER INTEGER INTEGER\par -\tab\tab\lang1033 \par +\tab IfMem INTEGER INTEGER INTEGER\par +\tab\tab \par \tab Else\par \tab\tab \par \tab End\par or\par -\tab\lang1031 SetFlag INTEGER\par +\tab SetFlag INTEGER\par or\par \tab ResetFlag INTEGER\par -\lang1033 or\par +or\par \tab NotFlag INTEGER\par or\par \tab IfFlag INTEGER\par @@ -772,31 +804,32 @@ Example:\par \par \page MenuItem will open a menu (only if it\rquote s supported). The following values are accepted:\par \par -\pard\nowidctlpar\fi720\cf1\f1\fs16 FILE_NEW 1\par -FILE_OPEN 2\par -FILE_SAVE 3\par -FILE_SAVEAS 4\par -FILE_EXIT 5\par -EDIT_COPY_SCREEN 6\par -FILE_SETTINGS 7\par -EDIT_RESET 8\par -EDIT_LOAD_OBJECT 9\par -EDIT_SAVE_OBJECT 10\par -HELP_ABOUT 11\par -HELP_TOPICS 12\par -FILE_CLOSE 13\par -EDIT_BACKUP_SAVE 14\par -EDIT_BACKUP_RESTORE 15\par -EDIT_BACKUP_DELETE 16\par -VIEW_SCRIPT 17\par -EDIT_COPY_STRING 19\par -EDIT_PASTE_STRING 20\par -TOOL_DISASM 21\par -TOOL_DEBUG 22\par -TOOL_MACRO_RECORD 23\par -TOOL_MACRO_PLAY 24\par -TOOL_MACRO_STOP 25\par -TOOL_MACRO_SETTINGS 26\par +\pard\nowidctlpar\fi720\cf1\f1\fs16 FILE_NEW 1\par +FILE_OPEN 2\par +FILE_SAVE 3\par +FILE_SAVEAS 4\par +FILE_EXIT 5\par +EDIT_COPY_SCREEN 6\par +FILE_SETTINGS 7\par +EDIT_RESET 8\par +EDIT_LOAD_OBJECT 9\par +EDIT_SAVE_OBJECT 10\par +HELP_ABOUT 11\par +HELP_TOPICS 12\par +FILE_CLOSE 13\par +EDIT_BACKUP_SAVE 14\par +EDIT_BACKUP_RESTORE 15\par +EDIT_BACKUP_DELETE 16\par +VIEW_SCRIPT 17\par +EDIT_PORT_CONFIGURATION 18\par +EDIT_COPY_STRING 19\par +EDIT_PASTE_STRING 20\par +TOOL_DISASM 21\par +TOOL_DEBUG 22\par +TOOL_MACRO_RECORD 23\par +TOOL_MACRO_PLAY 24\par +TOOL_MACRO_STOP 25\par +TOOL_MACRO_SETTINGS 26\par \pard\nowidctlpar\f0\fs24\par \cf0\b\fs28\page Conclusion\par \b0\fs24\par @@ -814,6 +847,6 @@ The latest updates are available at:\par http://hp.giesselink.com/\par \pard\nowidctlpar\par \par -Release 14: September 9th, 2009\par +Release 16: May 18th, 2012\par } \ No newline at end of file diff --git a/PROBLEMS.TXT b/PROBLEMS.TXT index b8a2f51..22c63b7 100644 --- a/PROBLEMS.TXT +++ b/PROBLEMS.TXT @@ -1,4 +1,4 @@ -Known bugs and restrictions of Emu48 V1.50 +Known bugs and restrictions of Emu48 V1.53 ------------------------------------------ - the following I/O bits aren't emulated (incomplete) @@ -12,8 +12,7 @@ Known bugs and restrictions of Emu48 V1.50 SRQ1 (0x118) [ISQR] SRQ2 (0x119) [LSRQ] IRC (0x11A) [IRI EIRU EIRI IRE] - LCR (0x11C) [LED ELBE LBZ LBF] - LBR (0x11D) [LBO] + LCR (0x11C) [LBZ LBF] - the baudrates 1920, 3840, 7680 and 15360 aren't emulated on most operating systems Windows 95a 1920, 3840, 7680 work, 15360 fail @@ -41,7 +40,6 @@ Known bugs and restrictions of Emu48 V1.50 - no beeper support with OUT command -> all programs that aren't use the "=makebeep" subroutine, like alarm wake up, have no sound - beeper emulation, ATTN key doesn't work -- no infrared printer support - Shell OS: clock isn't synchronized with real time - HP49G: the flash memory is emulated now with some restrictions - no flash programming times, the flash state machine returns @@ -52,4 +50,4 @@ Known bugs and restrictions of Emu48 V1.50 - quitting the emulator while programming the flash isn't allowed, because the content of flash state machine isn't saved so far -07/27/10 (c) by Christoph Gießelink, c dot giesselink at gmx dot de +08/07/12 (c) by Christoph Gießelink, c dot giesselink at gmx dot de diff --git a/Sources/Emu48/CHANGES.TXT b/Sources/Emu48/CHANGES.TXT index 7a5bfe0..483d458 100644 --- a/Sources/Emu48/CHANGES.TXT +++ b/Sources/Emu48/CHANGES.TXT @@ -1,3 +1,362 @@ +Service Pack 53 for Emu48 Version 1.0 + +DEBUGGER.C +- removed structure MODEL_MAP_T, variables pbyNoMEM, MemMap[], + pbyMapData, dwMapDataSize and pMapping, the implementation behind + moved to module DISMEM.C +- changed function SetMappingMenu(), changed to DISMEM.C + implementation and added control of memory data menu items +- changed function GetMemCurAddr(), OnMemGoAdr(), OnKeyUpDown() and + OnKeyPlusMinus(), variable dwMapDataSize isn't global any more, + use function GetMemDataMask() instead +- changed function InitMemMap(), ViewMemWnd() and OnFindOK(), + changed to DISMEM.C implementation +- changed function ViewCodeWnd(), set disassembler to memory mapped + mode +- bugfix in function OnDblClick(), fixed buffer overflow when + converting a 2 byte hexadecimal string to a byte and added an + update of code window +- changed function Debugger(), changed disassembler mode setting and + added initialization of RPL object viewer get nibble function in + WM_INITDIALOG message and added calls of "Load Memory Data..." and + "Save Memory Data..." handling functions +- bugfix in function UpdateRplObjViewWnd(), show entry point names + only in mapped mode and end address for RPL object viewer depend + on the actual memory mapping mode and with the design change to + the DISMEM.C implementation in all debugger and disassembler + related parts, the RPL object viewer also works in all memory + mapping modes properly now +- added functions OnBrowseLoadMem(), OnBrowseSaveMem(), + LoadMemData(), SaveMemData(), GetAddr(), DebugMemLoad(), + OnMemLoadData(), DebugMemSave() and OnMemSaveData() to handle the + Load/Save Memory Data feature + +DISASM.C +- removed global variable disassembler_map +- removed functions rn_map(), rn_rom(), rn_ram(), rn_port1() and + rn_port2() +- changed function read_nibble(), call function GetMemNib() from the + new module DISMEM.C for mapping mode memory access and made + function static again + +DISMEM.C +- new module for accessing memory data for debug view purpose + +DISPLAY.C +- changed function GetLineCounterGray() to static + +DISRPL.C +- the get nibble function is not hard referenced as read_nibble() + call any more, it's now called over RplReadNibble() function + pointer +- changed function PrintTail(), expanded to handle 6 digit addresses + +DISRPL.H +- added extern declaration of RplReadNibble() function pointer + +EMU48.C +- changed function Disasm(), replaced the radio button + implementation for the memory mapping mode by a combo box + solution; the combo box solution don't work with the HP48 module + names any more, it now use the memory controller names used in the + debugger memory viewer for a more general approach for the non + HP48 calculator models +- changed function WinMain(), added more flexible CPU binding for + the Saturn core emulation thread on Windows NT4.0 and later + +EMU48.DSP +- added dismem.c sources + +EMU48.H +- replaced old "memory module definitions" by the enum MEM_MAPPING +- extern declaration of global functions +- removed extern declaration of global variables + +EMU48.RC +- changed IDD_DISASM dialog, replaced the radio buttons for the + memory mapping mode by a more general combo box +- added dialogs IDD_DEBUG_MEMSAVE and IDD_DEBUG_MEMLOAD +- added "Load Memory Data..." and "Save Memory Data..." menu entries + in debugger "Memory" context menu +- changed version + +KML.C +- bugfix in function ReloadButtons(), ON key button wasn't handled + +RESOURCE.H +- added several definitions +- deleted some radio button definitions from the IDD_DISASM dialog + +TIMER.C +- changed function SetHP48Time(), time calculation now work properly + for host system dates before 1970/01/01 and after 2106/02/07 + + +Service Pack 52 for Emu48 Version 1.0 + +DEBUGGER.C +- changed function ViewMemWnd(), removed initialized but unused + variable + +DISPLAY.C +- changed DIBPIXEL4() and DIBPIXEL3() define, generates the same + code on MSVC6.0 but made it GCC4 compiler compatible + +DISRPL.C +- changed function RplCreateObjView(), defined end pointer also as + constant + +EMU48.C +- added property sheet page handlers SettingsGeneralProc(), + SettingsMemoryProc() and SettingsPeripheralProc() +- removed function SettingsProc(), replaced by the property sheet + page handler functions +- bugfix in function OnDropFiles(), changed function prototype to + the correct structure type of dropped file names and initialized + the bSuccess variable for the case the wNumFiles variable is 0 +- added function PropSheetProc(), callback function for setup the + property sheet +- changed function OnViewSettings(), now creating a propery sheet + instead of a settings dialog +- changed function MainWndProc(), made correct type cast to argument + of function OnDropFiles() +- changed function WinMain(), replaced multiple class name usage + with atom variable, moved read settings before window creation, + and added check for setting "SingleInstance" to switch to an + already running program instance instead of creating a new one + +EMU48.H +- extern declaration of global variable and function + +EMU48.RC +- split IDD_SETTINGS dialog into the property pages IDD_SET_GENERAL, + IDD_SET_MEMORY and IDD_SET_PERIPHERAL and added item + "Single Instance" in the "General" property page +- removed IDD_SETTINGS dialog +- changed version and copyright + +FILES.C +- bugfix in function DecodeBmp() and DecodeGif(), a 2nd bitmap load + allocated and bound a 2nd palette to the main window, now only the + 1st bitmap (mostly the KML background bitmap) bound his palette to + the main window + +KML.C +- changed table pLexToken[], defined table as constant and changed + last token id table preset from constant number to member of token + id enumerator +- bugfix in function ParseString(), decoding the \" sequence as + quotation mark inside a string was incomplete, so every single '\' + character was also removed + +MRU.C +- changed function MruUpdateMenu(), changed variable type of + variable hMenu +- changed function MruReadList(), removed initialized but unused + variable + +RESOURCE.H +- removed IDD_SETTINGS definition +- added some definitions + +SETTINGS.C +- changed function ReadSettings(), moved CPU speed setting to + MainWndProc() +- changed function ReadSettings() and WriteSettings(), added item + "SingleInstance" in section [Emulator] in the INI-File + +UDP.C +- added function ResetUdp(), reset UDP address +- bugfix in function SendByteUdp(), fixed memory leak at error + condition and optimized IP address decoding + + +Service Pack 51 for Emu48 Version 1.0 + +DDESERV.C +- replaced all HeapAlloc() with malloc() memory requests + +DEBUGGER.C +- replaced all HeapAlloc() with malloc() memory requests +- changed function ToggleBreakpoint() and EditBreakpoint(), minor + code optimization purging breakpoint +- changed function Debugger(), removed all UpdateWindowStatus() + function calls +- bugfix in function LoadBreakpointList(), added check of breakpoint + entries against breakpoint table size + +DISRPL.C +- replaced all HeapAlloc() with malloc() memory requests +- bugfix in function BCDx(), fixed possible uninitialized bExpflag + variable +- bugfix in function DoRrp(), fixed possible uninitialized bErr + variable + +EMU48.C +- removed global variable hHeap +- replaced all HeapAlloc() with malloc() memory requests +- changed function SettingsProc(), added infrared printer settings +- changed function SaveChanges(), detect if document is available + now over the variable bDocumentAvail and not over the variable + pbyRom any more; in the case of an illegal KML script there maybe + a document loaded, but no ROM image, so pbyRom will be NULL in + this case +- renamed function UpdateWindowStatus() to OnInitMenu() and modified + it to a WM_INITMENU message handler +- changed function OnFileNew() and WinMain(), removed all + UpdateWindowStatus() function calls +- bugfix function OnViewScript(), when quitted the dialog "Choose + Your KML Script" with the Cancel button when chosen an invalid + script the function returned without the possibility of saving the + current document; now the function try to reload the primarily KML + script and if this also fails then the current document is saved +- changed function MainWndProc(), added WM_INITMENU message handler + and call of _CrtDumpMemoryLeaks() at end of program to detect + malloc() memory leaks + +EMU48.DSP +- changed the resource natural language to English +- added redeye.c and udp.c sources +- added library Ws2_32.lib + +EMU48.H +- removed extern declaration of hHeap +- extern declaration of global variables and functions +- removed declaration of global function UpdateWindowStatus() +- replaced all HeapAlloc() with malloc() memory requests + +EMU48.RC +- changed version and copyright + +ENGINE.C +- added global variable nOpcSlow to hold the number of CPU opcodes + slowing down the CPU core +- changed function AdjustSpeed(), added CPU opcode slow down + implementation +- added function InitAdjustSpeed(), initialize CPU slow down part + if necessary +- changed function AdjKeySpeed() and SetSpeed(), use function + InitAdjustSpeed() to initialize the CPU slow down variables +- changed function SwitchToState(), removed all UpdateWindowStatus() + function calls + +EXTERNAL.C +- replaced all HeapAlloc() with malloc() memory requests + +FILES.C +- replaced all HeapAlloc() with malloc() memory requests +- changed TREENODE structure, added prev element for a double linked + list +- changed function PatchNibble(), added prev element handling +- bugfix in function UpdatePatches(), in the case an address was + patched more than one time, the ROM was patched in wrong order and + moreover the original content of the double patched ROM address + was destroyed +- changed function CrcRom(), if no ROM available return without + modifying the checksum +- changed function MapRom(), removed using of memory mapped files + which has the major advantage that packed ROM files are also valid + now +- changed function UnmapRom(), adjusted to changed MapRom() function +- changed function ResetDocument(), OpenDocument(), + SaveDocumentAs(), SaveBackup(), RestoreBackup() and ResetBackup(), + removed all UpdateWindowStatus() function calls +- changed function ResetDocument(), NewDocument(), OpenDocument() + and RestoreBackup(), added state variable if document is available +- bugfix in function OpenDocument(), added check of KML script name + length against target buffer size +- changed function DibNumColors(), changed function prototype from + UINT to WORD return +- changed function CreateBIPalette(), changed variable + UINT nNumColors to WORD wNumColors to avoid variable overflow + loading palNumEntries of LOGPALETTE structure + +I28F160.C +- added functions WrDirtyPage(), EraseBlock(), WriteByte() and + ReadByte() for access to the ROM buffer +- changed function WrStateE8C(), WrState40D(), WrState20C(), + WrState30C() and RdStateData(), changed implementation using the + new ROM buffer access functions + +IO.H +- added LBR and LBO bit definitions + +KEYMACRO.C +- changed function OnToolMacroNew(), OnToolMacroPlay() and + OnToolMacroStop(), removed all UpdateWindowStatus() function calls +- changed function EventThread(), added minimum key hold time for + keyboard macro playing and subtract minimum key hold time from + saved waiting time, this is more accurate when the user has + selected a different minimum key hold time than the default one +- changed function KeyMacroRecord(), now saving the complete waiting + time including the key state holding time, the key state holding + time is now subtract in the player function thread EventThread() +- changed function OnToolMacroNew(), removed adding the key state + holding time to the reference time, this is not necessary any more + +KML.C +- replaced all HeapAlloc() with malloc() memory requests +- changed function ParseLines(), BOOL expression was missing in main + while() loop, worked because TOK_NONE is 0 +- bugfix in function ParseBlock(), string argument wasn't freed in + error case +- changed function KillKML(), removed UpdateWindowStatus() function + call +- changed function LoadKMLGlobal(), used wrong variable type for + variable eToken + +MOPS.C +- added function ReadT2Acc(), reading timer2 value with checking for + CPU speed measurement behaviour +- bugfix in function ReadIO(), added implementation of the LED and + ELBE bit in the LCR (0x11C) register and of the LBO bit in the LBR + (0x11D) register +- changed function ReadIO(), the timer2 register content is now read + by function ReadT2Acc() to analyze the read access scheme +- bugfix in function WriteIO(), added implementation of the ELBE bit + in the LCR (0x11C) register and of the LBO bit in the LBR (0x11D) + register + +MRU.C +- replaced all HeapAlloc() with malloc() memory requests + +OPS.H +- bugfix in function FASTPTR(), longest opcode calculation from + buffer size was wrong, so MMU boundary fixup wasn't working + properly + +PCH.H +- added include winsock2.h + +REDEYE.C +- new module for decoding the redeye data stream for a HP82240B + printer + +RESOURCE.H +- added some definitions + +RPL.C +- replaced all HeapAlloc() with malloc() memory requests + +SETTINGS.C +- changed function ReadSettings() and WriteSettings(), added item + "KeyMinDelay" in section [Macro] and the items "Address" and + "Port" in section [IrPrinter] in the INI-File + +STACK.C +- replaced all HeapAlloc() with malloc() memory requests +- bugfix in function RPL_GetBcd(), fixed possible uninitialized + bExpflag variable +- bugfix in function OnStackCopy(), fixed possible uninitialized + uClipboardFormat variable in DOCSTR case + +SYMBFILE.C +- replaced all HeapAlloc() with malloc() memory requests + +UDP.C +- new module for sending a byte over UDP + + Service Pack 50 for Emu48 Version 1.0 DEBUGGER.C diff --git a/Sources/Emu48/DDESERV.C b/Sources/Emu48/DDESERV.C index 884542b..162f87d 100644 --- a/Sources/Emu48/DDESERV.C +++ b/Sources/Emu48/DDESERV.C @@ -11,8 +11,8 @@ #include "io.h" HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv, - HSZ hsz1,HSZ hsz2,HDDEDATA hData, - DWORD dwData1,DWORD dwData2) + HSZ hsz1,HSZ hsz2,HDDEDATA hData, + DWORD dwData1,DWORD dwData2) { TCHAR *psz,szBuffer[32]; HDDEDATA hReturn; @@ -50,7 +50,7 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv, DdeUnaccessData(hData); // reserve memory - if ((lpData = HeapAlloc(hHeap,0,dwSize * 2)) == NULL) + if ((lpData = malloc(dwSize * 2)) == NULL) return (HDDEDATA) DDE_FNOTPROCESSED; SuspendDebugger(); // suspend debugger @@ -66,7 +66,7 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv, if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state { - HeapFree(hHeap,0,lpData); // free memory + free(lpData); // free memory hReturn = DDE_FNOTPROCESSED; goto cancel; } @@ -80,7 +80,7 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv, dwSize = dwIndex; dwSize = DdeGetData(hData,lpData+dwSize,dwSize,sizeof(DWORD)); bSuccess = (WriteStack(nStkLvl,lpData,dwSize) == S_ERR_NO); - HeapFree(hHeap,0,lpData); // free memory + free(lpData); // free memory SwitchToState(SM_RUN); // run state while (nState!=nNextState) Sleep(0); @@ -138,7 +138,7 @@ cancel: dwSize += dwIndex + sizeof(DWORD); // reserve memory - if ((lpData = HeapAlloc(hHeap,0,dwSize)) == NULL) + if ((lpData = malloc(dwSize)) == NULL) { SwitchToState(SM_RUN); // run state return NULL; @@ -156,7 +156,7 @@ cancel: // write data hReturn = DdeCreateDataHandle(idDdeInst,lpData,dwSize,0,hsz2,iFmt,0); - HeapFree(hHeap,0,lpData); + free(lpData); SwitchToState(SM_RUN); // run state while (nState!=nNextState) Sleep(0); diff --git a/Sources/Emu48/DEBUGGER.C b/Sources/Emu48/DEBUGGER.C index aff99b3..7bf028c 100644 --- a/Sources/Emu48/DEBUGGER.C +++ b/Sources/Emu48/DEBUGGER.C @@ -53,21 +53,6 @@ typedef struct // type of breakpoint table DWORD dwAddr; // breakpoint address } BP_T; -typedef struct // type of model memory mapping -{ - CONST BYTE byType; // calculator type - CONST LPBYTE *ppbyNCE1; // NCE1 data - CONST DWORD *pdwNCE1Size; // NCE1 size - CONST LPBYTE *ppbyNCE2; // NCE2 data - CONST DWORD *pdwNCE2Size; // NCE2 size - CONST LPBYTE *ppbyCE1; // CE1 data - CONST DWORD *pdwCE1Size; // CE1 size - CONST LPBYTE *ppbyCE2; // CE2 data - CONST DWORD *pdwCE2Size; // CE2 size - CONST LPBYTE *ppbyNCE3; // NCE3 data - CONST DWORD *pdwNCE3Size; // NCE3 size -} MODEL_MAP_T; - static CONST int nCol[] = { IDC_DEBUG_MEM_COL0, IDC_DEBUG_MEM_COL1, IDC_DEBUG_MEM_COL2, IDC_DEBUG_MEM_COL3, @@ -79,68 +64,6 @@ static CONST TCHAR cHex[] = { _T('0'),_T('1'),_T('2'),_T('3'), _T('8'),_T('9'),_T('A'),_T('B'), _T('C'),_T('D'),_T('E'),_T('F') }; -static CONST LPBYTE pbyNoMEM = NULL; // no memory module - -static CONST MODEL_MAP_T MemMap[] = -{ - { - 0, // default - &pbyNoMEM, NULL, // nc. - &pbyNoMEM, NULL, // nc. - &pbyNoMEM, NULL, // nc. - &pbyNoMEM, NULL, // nc. - &pbyNoMEM, NULL // nc. - }, - { - '6', // HP38G (64K) - &pbyRom, &dwRomSize, // ROM - &Port0, &Chipset.Port0Size, // RAM - &pbyNoMEM, NULL, // nc. - &pbyNoMEM, NULL, // nc. - &pbyNoMEM, NULL // nc. - }, - { - 'A', // HP38G - &pbyRom, &dwRomSize, // ROM - &Port0, &Chipset.Port0Size, // RAM - &pbyNoMEM, NULL, // nc. - &pbyNoMEM, NULL, // nc. - &pbyNoMEM, NULL // nc. - }, - { - 'E', // HP39/40G - &pbyRom, &dwRomSize, // ROM - &Port0, &Chipset.Port0Size, // RAM part 1 - &pbyNoMEM, NULL, // BS - &pbyNoMEM, NULL, // nc. - &Port2, &Chipset.Port2Size // RAM part 2 - }, - { - 'G', // HP48GX - &pbyRom, &dwRomSize, // ROM - &Port0, &Chipset.Port0Size, // RAM - &pbyNoMEM, NULL, // BS - &Port1, &Chipset.Port1Size, // Card slot 1 - &pbyPort2, &dwPort2Size // Card slot 2 - }, - { - 'S', // HP48SX - &pbyRom, &dwRomSize, // ROM - &Port0, &Chipset.Port0Size, // RAM - &Port1, &Chipset.Port1Size, // Card slot 1 - &pbyPort2, &dwPort2Size, // Card slot 2 - &pbyNoMEM, NULL // nc. - }, - { - 'X', // HP49G - &pbyRom, &dwRomSize, // Flash - &Port0, &Chipset.Port0Size, // RAM - &pbyNoMEM, NULL, // BS - &Port1, &Chipset.Port1Size, // Port 1 part 1 - &Port2, &Chipset.Port2Size // Port 1 part 2 - } -}; - static INT nDbgPosX = 0; // position of debugger window static INT nDbgPosY = 0; @@ -159,16 +82,12 @@ static UINT uIDFol = ID_DEBUG_MEM_FNONE; // follow mode static DWORD dwAdrMemFol = 0; // follow address memory window static UINT uIDMap = ID_DEBUG_MEM_MAP; // current memory view mode -static LPBYTE lbyMapData; // data -static DWORD dwMapDataSize; // data size static LONG lCharWidth; // width of a character (is a fix font) static HMENU hMenuCode,hMenuMem,hMenuStack;// handle of context menues static HWND hWndToolbar; // toolbar handle -static MODEL_MAP_T CONST *pMapping; // model specific memory mapping - static DWORD dwDbgRefCycles; // cpu cycles counter from last opcode static CHIPSET OldChipset; // old chipset content @@ -189,6 +108,8 @@ static BOOL OnEditBreakpoint(HWND hDlg); static BOOL OnInfoIntr(HWND hDlg); static BOOL OnInfoWoRegister(HWND hDlg); static VOID UpdateProfileWnd(HWND hDlg); +static BOOL OnMemLoadData(HWND hDlg); +static BOOL OnMemSaveData(HWND hDlg); //################ //# @@ -242,52 +163,53 @@ static VOID DisableMenuKeys(HWND hDlg) // static VOID SetMappingMenu(HWND hDlg,UINT uID) { + enum MEM_MAPPING eMode; LPTSTR szCaption; + UINT uEnable = MF_GRAYED; // disable Memory Data menu items + CheckMenuItem(hMenuMem,uIDMap,MF_UNCHECKED); switch (uID) { case ID_DEBUG_MEM_MAP: szCaption = _T("Memory"); - lbyMapData = NULL; // data - dwMapDataSize = 512; // data size + eMode = MEM_MMU; + uEnable = MF_ENABLED; // enable Memory Data menu items break; case ID_DEBUG_MEM_NCE1: szCaption = _T("Memory (NCE1)"); - lbyMapData = *pMapping->ppbyNCE1; - dwMapDataSize = *pMapping->pdwNCE1Size / 2048; // ROM size is always in nibbles + eMode = MEM_NCE1; break; case ID_DEBUG_MEM_NCE2: szCaption = _T("Memory (NCE2)"); - lbyMapData = *pMapping->ppbyNCE2; - dwMapDataSize = *pMapping->pdwNCE2Size; + eMode = MEM_NCE2; break; case ID_DEBUG_MEM_CE1: szCaption = _T("Memory (CE1)"); - lbyMapData = *pMapping->ppbyCE1; - dwMapDataSize = *pMapping->pdwCE1Size; + eMode = MEM_CE1; break; case ID_DEBUG_MEM_CE2: szCaption = _T("Memory (CE2)"); - lbyMapData = *pMapping->ppbyCE2; - dwMapDataSize = *pMapping->pdwCE2Size; + eMode = MEM_CE2; break; case ID_DEBUG_MEM_NCE3: szCaption = _T("Memory (NCE3)"); - lbyMapData = *pMapping->ppbyNCE3; - dwMapDataSize = *pMapping->pdwNCE3Size; + eMode = MEM_NCE3; break; default: _ASSERT(0); } - dwMapDataSize *= 2048; // size in nibble + VERIFY(SetMemMapType(eMode)); if (uIDMap != uID) dwAdrMem = 0; // view from address 0 uIDMap = uID; CheckMenuItem(hMenuMem,uIDMap,MF_CHECKED); + EnableMenuItem(hMenuMem,ID_DEBUG_MEM_LOAD,uEnable); + EnableMenuItem(hMenuMem,ID_DEBUG_MEM_SAVE,uEnable); + SetDlgItemText(hDlg,IDC_STATIC_MEMORY,szCaption); return; }; @@ -299,6 +221,7 @@ static DWORD GetMemCurAddr(HWND hDlg) { INT i,nPos; DWORD dwAddr = dwAdrMem; + DWORD dwMapDataMask = GetMemDataMask(); for (i = 0; i < MEMWNDMAX; ++i) // scan all memory cols { @@ -306,7 +229,7 @@ static DWORD GetMemCurAddr(HWND hDlg) if ((nPos = (INT) SendDlgItemMessage(hDlg,nCol[i],LB_GETCURSEL,0,0)) != LB_ERR) { dwAddr += (DWORD) (nPos * MEMWNDMAX + i) * 2; - dwAddr &= (dwMapDataSize - 1); + dwAddr &= dwMapDataMask; break; } } @@ -331,8 +254,7 @@ static __inline VOID ToggleBreakpoint(DWORD dwAddr) return; } - // purge breakpoint - for (++i; i < wBreakpointCount; ++i) + while (++i < wBreakpointCount) // purge breakpoint sBreakpoint[i-1] = sBreakpoint[i]; --wBreakpointCount; return; @@ -359,34 +281,23 @@ static __inline VOID ToggleBreakpoint(DWORD dwAddr) static __inline VOID InitMemMap(HWND hDlg) { BOOL bActive; - INT i; - pMapping = MemMap; // init default mapping - - // scan for all table entries - for (i = 0; i < ARRAYSIZEOF(MemMap); ++i) - { - if (MemMap[i].byType == cCurrentRomType) - { - pMapping = &MemMap[i]; // found entry - break; - } - } + SetMemRomType(cCurrentRomType); // set current model _ASSERT(hMenuMem); // enable menu mappings - EnableMenuItem(hMenuMem,ID_DEBUG_MEM_NCE1,(*pMapping->ppbyNCE1) ? MF_ENABLED : MF_GRAYED); - EnableMenuItem(hMenuMem,ID_DEBUG_MEM_NCE2,(*pMapping->ppbyNCE2) ? MF_ENABLED : MF_GRAYED); - EnableMenuItem(hMenuMem,ID_DEBUG_MEM_CE1, (*pMapping->ppbyCE1) ? MF_ENABLED : MF_GRAYED); - EnableMenuItem(hMenuMem,ID_DEBUG_MEM_CE2, (*pMapping->ppbyCE2) ? MF_ENABLED : MF_GRAYED); - EnableMenuItem(hMenuMem,ID_DEBUG_MEM_NCE3,(*pMapping->ppbyNCE3) ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hMenuMem,ID_DEBUG_MEM_NCE1,GetMemAvail(MEM_NCE1) ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hMenuMem,ID_DEBUG_MEM_NCE2,GetMemAvail(MEM_NCE2) ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hMenuMem,ID_DEBUG_MEM_CE1, GetMemAvail(MEM_CE1) ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hMenuMem,ID_DEBUG_MEM_CE2, GetMemAvail(MEM_CE2) ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hMenuMem,ID_DEBUG_MEM_NCE3,GetMemAvail(MEM_NCE3) ? MF_ENABLED : MF_GRAYED); - bActive = (ID_DEBUG_MEM_NCE1 == uIDMap && *pMapping->ppbyNCE1 != NULL) - || (ID_DEBUG_MEM_NCE2 == uIDMap && *pMapping->ppbyNCE2 != NULL) - || (ID_DEBUG_MEM_CE1 == uIDMap && *pMapping->ppbyCE1 != NULL) - || (ID_DEBUG_MEM_CE2 == uIDMap && *pMapping->ppbyCE2 != NULL) - || (ID_DEBUG_MEM_NCE3 == uIDMap && *pMapping->ppbyNCE3 != NULL); + bActive = (ID_DEBUG_MEM_NCE1 == uIDMap && GetMemAvail(MEM_NCE1)) + || (ID_DEBUG_MEM_NCE2 == uIDMap && GetMemAvail(MEM_NCE2)) + || (ID_DEBUG_MEM_CE1 == uIDMap && GetMemAvail(MEM_CE1)) + || (ID_DEBUG_MEM_CE2 == uIDMap && GetMemAvail(MEM_CE2)) + || (ID_DEBUG_MEM_NCE3 == uIDMap && GetMemAvail(MEM_NCE3)); SetMappingMenu(hDlg,bActive ? uIDMap : ID_DEBUG_MEM_MAP); return; @@ -452,6 +363,7 @@ static VOID StrToReg(BYTE *pReg, WORD wNib, LPTSTR lpszValue) // static INT ViewCodeWnd(HWND hWnd, DWORD dwAddress) { + enum MEM_MAPPING eMapMode; LPCTSTR lpszName; TCHAR szAddress[64]; DWORD dwNxtAddr; @@ -459,7 +371,9 @@ static INT ViewCodeWnd(HWND hWnd, DWORD dwAddress) nLinePC = -1; // PC not shown (no selection) - _ASSERT(disassembler_map == MEM_MAP); // disassemble in mapped mode + eMapMode = GetMemMapType(); // get current map mode + SetMemMapType(MEM_MMU); // disassemble in mapped mode + dwAddress &= 0xFFFFF; // adjust to Saturn address range SendMessage(hWnd,WM_SETREDRAW,FALSE,0); SendMessage(hWnd,LB_RESETCONTENT,0,0); @@ -509,6 +423,7 @@ static INT ViewCodeWnd(HWND hWnd, DWORD dwAddress) SendMessage(hWnd,LB_ADDSTRING,0,(LPARAM) szAddress); } SendMessage(hWnd,WM_SETREDRAW,TRUE,0); + SetMemMapType(eMapMode); // switch back to old map mode return nLinePC; } @@ -519,12 +434,14 @@ static VOID ViewMemWnd(HWND hDlg, DWORD dwAddress) { #define TEXTOFF 32 - INT i,j,k; + INT i,j; TCHAR szBuffer[16],szItem[4]; + DWORD dwMapDataMask; BYTE cChar; szItem[2] = 0; // end of string dwAdrMem = dwAddress; // save start address of memory window + dwMapDataMask = GetMemDataMask(); // size mask of data mapping // purge all list boxes SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_ADDR,LB_RESETCONTENT,0,0); @@ -538,28 +455,18 @@ static VOID ViewMemWnd(HWND hDlg, DWORD dwAddress) if (ID_DEBUG_MEM_MAP == uIDMap) // mapped memory content { - // fetch mapping data line - Npeek(byLineData, dwAddress, MAXMEMITEMS); - wsprintf(szBuffer,_T("%05lX"),dwAddress); } else // module memory content { - INT i; - - _ASSERT(lbyMapData); // valid module - - // fetch modul data line - for (i = 0; i < MAXMEMITEMS; ++i) - { - byLineData[i] = lbyMapData[(dwAddress + i) & (dwMapDataSize - 1)]; - } - wsprintf(szBuffer,_T("%06lX"),dwAddress); } SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_ADDR,LB_ADDSTRING,0,(LPARAM) szBuffer); - for (k = 0, j = 0; j < MAXMEMITEMS; ++j) + // fetch data line + GetMemPeek(byLineData, dwAddress, MAXMEMITEMS); + + for (j = 0; j < MAXMEMITEMS; ++j) { // read from fetched data line szItem[j&0x1] = cHex[byLineData[j]]; @@ -579,7 +486,7 @@ static VOID ViewMemWnd(HWND hDlg, DWORD dwAddress) szBuffer[j/2] = 0; // end of text string SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_TEXT,LB_ADDSTRING,0,(LPARAM) szBuffer); - dwAddress = (dwAddress + MAXMEMITEMS) & (dwMapDataSize - 1); + dwAddress = (dwAddress + MAXMEMITEMS) & dwMapDataMask; } return; #undef TEXTOFF @@ -967,7 +874,7 @@ static BOOL OnKeyF5(HWND hDlg) SetEvent(hEventDebug); // run emulation } return -1; // call windows default handler - UNREFERENCED_PARAMETER(hDlg); + UNREFERENCED_PARAMETER(hDlg); } // @@ -1001,7 +908,7 @@ static BOOL OnKeyF7(HWND hDlg) SetEvent(hEventDebug); // run emulation } return -1; // call windows default handler - UNREFERENCED_PARAMETER(hDlg); + UNREFERENCED_PARAMETER(hDlg); } // @@ -1031,7 +938,7 @@ static BOOL OnKeyF8(HWND hDlg) SetEvent(hEventDebug); // run emulation } return -1; // call windows default handler - UNREFERENCED_PARAMETER(hDlg); + UNREFERENCED_PARAMETER(hDlg); } // @@ -1049,7 +956,7 @@ static BOOL OnKeyF9(HWND hDlg) SetEvent(hEventDebug); // run emulation } return -1; // call windows default handler - UNREFERENCED_PARAMETER(hDlg); + UNREFERENCED_PARAMETER(hDlg); } // @@ -1061,7 +968,7 @@ static BOOL OnKeyF11(HWND hDlg) if (Chipset.Shutdn) // cpu thread stopped SetEvent(hEventShutdn); // goto debug session return -1; // call windows default handler - UNREFERENCED_PARAMETER(hDlg); + UNREFERENCED_PARAMETER(hDlg); } // @@ -1121,7 +1028,7 @@ static BOOL OnMemGoAdr(HWND hDlg) OnEnterAddress(hDlg, &dwAddress); if (dwAddress != -1) // not Cancel key - OnMemGoDx(hDlg,dwAddress & (dwMapDataSize - 1)); + OnMemGoDx(hDlg,dwAddress & GetMemDataMask()); return -1; // call windows default handler } @@ -1219,8 +1126,8 @@ static BOOL OnStackPush(HWND hDlg) // static BOOL OnStackPop(HWND hDlg) { - HWND hWnd; - INT i,j; + HWND hWnd; + INT i,j; if (nDbgState != DBG_STEPINTO) // not in single step mode return TRUE; @@ -1283,7 +1190,7 @@ static BOOL OnLButtonUp(HWND hDlg, LPARAM lParam) // handle of selected window hWnd = ChildWindowFromPointEx(hDlg,pt,CWP_SKIPDISABLED); - nId = GetDlgCtrlID(hWnd); // control ID of window + nId = GetDlgCtrlID(hWnd); // control ID of window GetWindowText(hWnd,szBuffer,ARRAYSIZEOF(szBuffer)); switch (nId) @@ -1400,19 +1307,22 @@ static BOOL OnLButtonUp(HWND hDlg, LPARAM lParam) // static BOOL OnDblClick(HWND hWnd, WORD wId) { + HWND hDlg,hWndCode; TCHAR szBuffer[4]; BYTE byData; INT i; DWORD dwAddress; + hDlg = GetParent(hWnd); // dialog window handle + hWndCode = GetDlgItem(hDlg,IDC_DEBUG_CODE); + if (wId == IDC_DEBUG_STACK) // stack list box { // get cpu address of selected item i = (INT) SendMessage(hWnd,LB_GETCURSEL,0,0); dwAddress = (DWORD) SendMessage(hWnd,LB_GETITEMDATA,i,0); - // show code of this address - ViewCodeWnd(GetDlgItem(GetParent(hWnd),IDC_DEBUG_CODE),dwAddress); + ViewCodeWnd(hWndCode,dwAddress); // show code of this address return TRUE; } @@ -1432,11 +1342,12 @@ static BOOL OnDblClick(HWND hWnd, WORD wId) // enter new value SendMessage(hWnd,LB_GETTEXT,i,(LPARAM) szBuffer); OnNewValue(szBuffer); - _stscanf(szBuffer,_T("%2X"), &byData); + byData = (BYTE) _tcstoul(szBuffer,NULL,16); byData = (byData >> 4) | (byData << 4); // change nibbles for writing - Write2(dwAddress, byData); // write data - ViewMemWnd(GetParent(hWnd),dwAdrMem); // update memory window + Write2(dwAddress,byData); // write data + ViewCodeWnd(hWndCode,dwAdrLine[0]); // update code window + ViewMemWnd(hDlg,dwAdrMem); // update memory window SendMessage(hWnd,LB_SETCURSEL,i,0); return FALSE; } @@ -1450,7 +1361,7 @@ static VOID OnContextMenu(HWND hDlg, LPARAM lParam, WPARAM wParam) INT nId; POINTSTOPOINT(pt,MAKEPOINTS(lParam)); // mouse position - nId = GetDlgCtrlID((HWND) wParam); // control ID of window + nId = GetDlgCtrlID((HWND) wParam); // control ID of window switch(nId) { @@ -1504,7 +1415,7 @@ static __inline BOOL OnKeyRightLeft(HWND hWnd, WPARAM wParam) WORD wX; INT nId; - nId = GetDlgCtrlID(hWnd); // control ID of window + nId = GetDlgCtrlID(hWnd); // control ID of window for (wX = 0; wX < MEMWNDMAX; ++wX) // scan all Id's if (nCol[wX] == nId) // found ID @@ -1527,10 +1438,10 @@ static __inline BOOL OnKeyRightLeft(HWND hWnd, WPARAM wParam) // static __inline BOOL OnKeyUpDown(HWND hWnd, WPARAM wParam) { - INT wX, wY; - INT nId; + INT wX, wY; + INT nId; - nId = GetDlgCtrlID(hWnd); // control ID of window + nId = GetDlgCtrlID(hWnd); // control ID of window for (wX = 0; wX < MEMWNDMAX; ++wX) // scan all Id's if (nCol[wX] == nId) // found ID @@ -1543,13 +1454,13 @@ static __inline BOOL OnKeyUpDown(HWND hWnd, WPARAM wParam) switch(LOWORD(wParam)) { case VK_NEXT: - dwAdrMem = (dwAdrMem + MAXMEMITEMS * MAXMEMLINES) & (dwMapDataSize - 1); + dwAdrMem = (dwAdrMem + MAXMEMITEMS * MAXMEMLINES) & GetMemDataMask(); ViewMemWnd(GetParent(hWnd),dwAdrMem); SendMessage(hWnd,LB_SETCURSEL,wY,0); return -2; case VK_PRIOR: - dwAdrMem = (dwAdrMem - MAXMEMITEMS * MAXMEMLINES) & (dwMapDataSize - 1); + dwAdrMem = (dwAdrMem - MAXMEMITEMS * MAXMEMLINES) & GetMemDataMask(); ViewMemWnd(GetParent(hWnd),dwAdrMem); SendMessage(hWnd,LB_SETCURSEL,wY,0); return -2; @@ -1557,7 +1468,7 @@ static __inline BOOL OnKeyUpDown(HWND hWnd, WPARAM wParam) case VK_DOWN: if (wY+1 >= MAXMEMLINES) { - dwAdrMem = (dwAdrMem + MAXMEMITEMS) & (dwMapDataSize - 1); + dwAdrMem = (dwAdrMem + MAXMEMITEMS) & GetMemDataMask(); ViewMemWnd(GetParent(hWnd),dwAdrMem); SendMessage(hWnd,LB_SETCURSEL,wY,0); return -2; @@ -1567,7 +1478,7 @@ static __inline BOOL OnKeyUpDown(HWND hWnd, WPARAM wParam) case VK_UP: if (wY == 0) { - dwAdrMem = (dwAdrMem - MAXMEMITEMS) & (dwMapDataSize - 1); + dwAdrMem = (dwAdrMem - MAXMEMITEMS) & GetMemDataMask(); ViewMemWnd(GetParent(hWnd),dwAdrMem); SendMessage(hWnd,LB_SETCURSEL,wY,0); return -2; @@ -1582,10 +1493,10 @@ static __inline BOOL OnKeyUpDown(HWND hWnd, WPARAM wParam) // static __inline BOOL OnKeyPlusMinus(HWND hWnd, WPARAM wParam) { - INT wX, wY; - INT nId; + INT wX, wY; + INT nId; - nId = GetDlgCtrlID(hWnd); // control ID of window + nId = GetDlgCtrlID(hWnd); // control ID of window for (wX = 0; wX < MEMWNDMAX; ++wX) // scan all Id's if (nCol[wX] == nId) // found ID @@ -1599,7 +1510,7 @@ static __inline BOOL OnKeyPlusMinus(HWND hWnd, WPARAM wParam) dwAdrMem++; else dwAdrMem--; - dwAdrMem &= (dwMapDataSize - 1); + dwAdrMem &= GetMemDataMask(); ViewMemWnd(GetParent(hWnd),dwAdrMem); // redraw memory view SendMessage(hWnd,LB_SETCURSEL,wY,0); // set focus at old position @@ -1705,7 +1616,7 @@ static __inline BOOL OnDrawCodeWnd(LPDRAWITEMSTRUCT lpdis) crTextColor = SetTextColor(lpdis->hDC,crTextColor); ExtTextOut(lpdis->hDC,(int)(lpdis->rcItem.left)+2,(int)(lpdis->rcItem.top), - ETO_OPAQUE,(LPRECT)&lpdis->rcItem,szBuf,lstrlen(szBuf),NULL); + ETO_OPAQUE,(LPRECT)&lpdis->rcItem,szBuf,lstrlen(szBuf),NULL); SetBkColor(lpdis->hDC,crBkColor); SetTextColor(lpdis->hDC,crTextColor); @@ -1803,7 +1714,7 @@ static __inline HWND CreateToolbar(HWND hWnd) HRSRC hRes; HGLOBAL hGlobal; CToolBarData *pData; - TBBUTTON *ptbb; + TBBUTTON *ptbb; INT i,j; HWND hWndToolbar = NULL; // toolbar window @@ -1822,12 +1733,12 @@ static __inline HWND CreateToolbar(HWND hWnd) _ASSERT(pData->wVersion == 1); // toolbar resource version // alloc memory for TBBUTTON stucture - if (!(ptbb = HeapAlloc(hHeap,0,pData->wItemCount*sizeof(TBBUTTON)))) + if (!(ptbb = malloc(pData->wItemCount*sizeof(TBBUTTON)))) goto unlock; // fill TBBUTTON stucture with resource data for (i = j = 0; i < pData->wItemCount; ++i) - { + { if (pData->aItems[i]) { ptbb[i].iBitmap = j++; @@ -1842,14 +1753,14 @@ static __inline HWND CreateToolbar(HWND hWnd) ptbb[i].fsState = TBSTATE_ENABLED; ptbb[i].dwData = 0; ptbb[i].iString = j; - } + } hWndToolbar = CreateToolbarEx(hWnd,WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS, IDR_DEBUG_TOOLBAR,j,hApp,IDR_DEBUG_TOOLBAR,ptbb,pData->wItemCount, pData->wWidth,pData->wHeight,pData->wWidth,pData->wHeight, sizeof(TBBUTTON)); - HeapFree(hHeap,0,ptbb); + free(ptbb); unlock: FreeResource(hGlobal); @@ -1862,7 +1773,7 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM static HMENU hMenuMainCode,hMenuMainMem,hMenuMainStack; WINDOWPLACEMENT wndpl; - TEXTMETRIC tm; + TEXTMETRIC tm; HDC hDC; HFONT hFont; HMENU hSysMenu; @@ -1924,7 +1835,7 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM SendDlgItemMessage(hDlg,IDC_STATIC_MISC, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); // init last instruction circular buffer - pdwInstrArray = HeapAlloc(hHeap,0,INSTRSIZE*sizeof(*pdwInstrArray)); + pdwInstrArray = malloc(INSTRSIZE*sizeof(*pdwInstrArray)); wInstrSize = INSTRSIZE; // size of last instruction array wInstrWp = wInstrRp = 0; // write/read pointer @@ -1937,7 +1848,7 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM InitBsArea(hDlg); // init bank switcher list box DisableMenuKeys(hDlg); // set debug menu keys into run state - disassembler_map = MEM_MAP; // disassemble with mapped modules + RplReadNibble = GetMemNib; // get nibble function for RPL object viewer dwDbgStopPC = -1; // no stop address for goto cursor dwDbgRplPC = -1; // no stop address for RPL breakpoint @@ -1949,7 +1860,6 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM if (Chipset.Shutdn) // cpu thread stopped SetEvent(hEventShutdn); // goto debug session - UpdateWindowStatus(); // disable application menu items OldChipset = Chipset; // save chipset values return TRUE; @@ -1960,7 +1870,7 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM SetEvent(hEventDebug); if (pdwInstrArray) // free last instruction circular buffer { - HeapFree(hHeap,0,pdwInstrArray); + free(pdwInstrArray); pdwInstrArray = NULL; } CloseHandle(hEventDebug); @@ -1973,8 +1883,6 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM DestroyMenu(hMenuMainCode); DestroyMenu(hMenuMainMem); DestroyMenu(hMenuMainStack); - _ASSERT(hWnd); - UpdateWindowStatus(); // enable application menu items hDlgDebug = NULL; // debugger windows closed break; @@ -2047,6 +1955,8 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM case ID_DEBUG_MEM_CE1: case ID_DEBUG_MEM_CE2: case ID_DEBUG_MEM_NCE3: return OnMemMapping(hDlg,LOWORD(wParam)); + case ID_DEBUG_MEM_LOAD: return OnMemLoadData(hDlg); + case ID_DEBUG_MEM_SAVE: return OnMemSaveData(hDlg); case ID_DEBUG_MEM_RPLVIEW: return OnRplObjView(hDlg); case ID_DEBUG_STACK_PUSH: return OnStackPush(hDlg); case ID_DEBUG_STACK_POP: return OnStackPop(hDlg); @@ -2138,7 +2048,7 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM // GetTextMetrics from "Courier New 8" font hFont = CreateFont(-MulDiv(8,GetDeviceCaps(hDC, LOGPIXELSY),72),0,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET, - OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_DONTCARE,_T("Courier New")); + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_DONTCARE,_T("Courier New")); hFont = SelectObject(hDC,hFont); GetTextMetrics(hDC,&tm); @@ -2157,7 +2067,7 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM LRESULT OnToolDebug(VOID) // debugger dialogbox call { if ((hDlgDebug = CreateDialog(hApp,MAKEINTRESOURCE(IDD_DEBUG),NULL, - (DLGPROC)Debugger)) == NULL) + (DLGPROC)Debugger)) == NULL) AbortMessage(_T("Debugger Dialog Box Creation Error !")); return 0; } @@ -2173,16 +2083,18 @@ static __inline BOOL OnFindOK(HWND hDlg,BOOL bASCII,DWORD *pdwAddrLast) { BYTE *lpbySearch; INT i,j; - DWORD dwAddr; + DWORD dwAddr,dwMapDataMask; BOOL bMatch; HWND hWnd = GetDlgItem(hDlg,IDC_FIND_DATA); + dwMapDataMask = GetMemDataMask(); // size mask of data mapping + i = GetWindowTextLength(hWnd) + 1; // text length incl. EOS j = bASCII ? 2 : sizeof(*(LPTSTR)0); // buffer width // allocate search buffer - if ((lpbySearch = HeapAlloc(hHeap,0,i * j)) != NULL) + if ((lpbySearch = malloc(i * j)) != NULL) { // get search text and real length i = GetWindowText(hWnd,(LPTSTR) lpbySearch,i); @@ -2200,7 +2112,7 @@ static __inline BOOL OnFindOK(HWND hDlg,BOOL bASCII,DWORD *pdwAddrLast) WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, szTmp, -1, lpbySearch, i+1, NULL, NULL); - HeapFree(hHeap,0,szTmp); + free(szTmp); } } #endif @@ -2245,26 +2157,19 @@ static __inline BOOL OnFindOK(HWND hDlg,BOOL bASCII,DWORD *pdwAddrLast) ++dwAddr; // scan mapping/module until match - for (; i && !bMatch && dwAddr <= dwAdrMem + dwMapDataSize; ++dwAddr) + for (; i && !bMatch && dwAddr <= dwAdrMem + dwMapDataMask + 1; ++dwAddr) { BYTE byC; // i = no. of nibbles that have to match for (bMatch = TRUE, j = 0;bMatch && j < i; ++j) { - if (ID_DEBUG_MEM_MAP == uIDMap) // mapped memory content - { - Npeek(&byC,(dwAddr + j) & 0xFFFFF,1); - } - else // module memory content - { - byC = lbyMapData[(dwAddr + j) & (dwMapDataSize - 1)]; - } + GetMemPeek(&byC,(dwAddr + j) & dwMapDataMask,1); bMatch = (byC == lpbySearch[j]); } } - dwAddr = (dwAddr - 1) & (dwMapDataSize - 1); // possible matching address - HeapFree(hHeap,0,lpbySearch); + dwAddr = (dwAddr - 1) & dwMapDataMask; // possible matching address + free(lpbySearch); // check match result if (bMatch) @@ -2447,10 +2352,13 @@ static VOID UpdateRplObjViewWnd(HWND hDlg, DWORD dwAddr) if (hDlg == NULL) return; // dialog not open + // show entry point name only in mapped mode + bRplViewName = (GetMemMapType() == MEM_MMU); + // create view string - szObjList = RplCreateObjView(dwAddr,0x100000,TRUE); + szObjList = RplCreateObjView(dwAddr,GetMemDataSize(),TRUE); SetDlgItemText(hDlg,IDC_RPLVIEW_DATA,szObjList); - HeapFree(hHeap,0,szObjList); + free(szObjList); return; } @@ -2480,7 +2388,6 @@ static INT_PTR CALLBACK RplObjView(HWND hDlg, UINT message, WPARAM wParam, LPARA _ASSERT(FALSE); } - bRplViewName = TRUE; // show entry point name bRplViewAddr = TRUE; // show address bRplViewBin = TRUE; // show binary data return TRUE; @@ -2535,7 +2442,7 @@ static VOID CopyEditToCombo(HWND hDlg,HWND hWndComboBox) if ((i = (INT) SendMessage(hWndComboBox,CB_GETCURSEL,0,0)) != CB_ERR) { // delete associated name - HeapFree(hHeap,0,(LPVOID) SendMessage(hWndComboBox,CB_GETITEMDATA,i,0)); + free((LPVOID) SendMessage(hWndComboBox,CB_GETITEMDATA,i,0)); // append actual name GetDlgItemText(hDlg,IDC_DEBUG_SET_FILE,szSymbFilename,ARRAYSIZEOF(szSymbFilename)); @@ -2700,7 +2607,7 @@ static INT_PTR CALLBACK Settings(HWND hDlg, UINT message, WPARAM wParam, LPARAM LPTSTR lpszFilename = (LPTSTR) SendMessage(hWnd,CB_GETITEMDATA,i,0); if (lpszFilename != NULL) { - HeapFree(hHeap,0,lpszFilename); + free(lpszFilename); } } EndDialog(hDlg,LOWORD(wParam)); @@ -2708,8 +2615,8 @@ static INT_PTR CALLBACK Settings(HWND hDlg, UINT message, WPARAM wParam, LPARAM } } return FALSE; - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); } static BOOL OnSettings(HWND hDlg) @@ -2772,7 +2679,7 @@ static INT_PTR CALLBACK NewValue(HWND hDlg, UINT message, WPARAM wParam, LPARAM } } return FALSE; - UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(wParam); } static INT_PTR OnNewValue(LPTSTR lpszValue) @@ -2843,7 +2750,7 @@ static INT_PTR CALLBACK EnterAddr(HWND hDlg, UINT message, WPARAM wParam, LPARAM } } return FALSE; - UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(wParam); } static VOID OnEnterAddress(HWND hDlg, DWORD *dwValue) @@ -2908,7 +2815,7 @@ static INT_PTR CALLBACK EnterBreakpoint(HWND hDlg, UINT message, WPARAM wParam, } } return FALSE; - UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(wParam); } static VOID OnEnterBreakpoint(HWND hDlg, BP_T *sValue) @@ -2955,7 +2862,7 @@ static __inline BOOL OnDrawBreakWnd(LPDRAWITEMSTRUCT lpdis) SendMessage(lpdis->hwndItem,LB_GETTEXT,lpdis->itemID,(LPARAM) szBuf); ExtTextOut(lpdis->hDC,(int)(lpdis->rcItem.left)+17,(int)(lpdis->rcItem.top), - ETO_OPAQUE,(LPRECT)&lpdis->rcItem,szBuf,lstrlen(szBuf),NULL); + ETO_OPAQUE,(LPRECT)&lpdis->rcItem,szBuf,lstrlen(szBuf),NULL); SetBkColor(lpdis->hDC,crBkColor); SetTextColor(lpdis->hDC,crTextColor); @@ -3099,7 +3006,7 @@ static INT_PTR CALLBACK EditBreakpoint(HWND hDlg, UINT message, WPARAM wParam, L // only modify memory breakpoints if ( ( sBreakpoint[i].bEnable == FALSE - && (sBreakpoint[i].nType & sBp.nType & (BP_EXEC | BP_RPL)) != 0) + && (sBreakpoint[i].nType & sBp.nType & (BP_EXEC | BP_RPL)) != 0) || ((sBreakpoint[i].nType & BP_ACCESS) && (sBp.nType & BP_ACCESS))) { // replace breakpoint type @@ -3156,7 +3063,7 @@ static INT_PTR CALLBACK EditBreakpoint(HWND hDlg, UINT message, WPARAM wParam, L } // remove breakpoint from breakpoint table - for (++i; i <= wBreakpointCount; ++i) + while (++i <= wBreakpointCount) sBreakpoint[i-1] = sBreakpoint[i]; } } @@ -3190,7 +3097,7 @@ static INT_PTR CALLBACK EditBreakpoint(HWND hDlg, UINT message, WPARAM wParam, L // GetTextMetrics from "Courier New 8" font hFont = CreateFont(-MulDiv(8,GetDeviceCaps(hDC, LOGPIXELSY),72),0,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET, - OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_DONTCARE,_T("Courier New")); + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_DONTCARE,_T("Courier New")); hFont = SelectObject(hDC,hFont); GetTextMetrics(hDC,&tm); @@ -3203,8 +3110,8 @@ static INT_PTR CALLBACK EditBreakpoint(HWND hDlg, UINT message, WPARAM wParam, L return TRUE; } return FALSE; - UNREFERENCED_PARAMETER(wParam); - UNREFERENCED_PARAMETER(lParam); + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); } static BOOL OnEditBreakpoint(HWND hDlg) @@ -3283,7 +3190,7 @@ static INT_PTR CALLBACK InfoIntr(HWND hDlg, UINT message, WPARAM wParam, LPARAM } } return FALSE; - UNREFERENCED_PARAMETER(lParam); + UNREFERENCED_PARAMETER(lParam); } static BOOL OnInfoIntr(HWND hDlg) @@ -3320,7 +3227,7 @@ static BOOL CALLBACK InfoWoRegister(HWND hDlg, UINT message, DWORD wParam, LONG } } return FALSE; - UNREFERENCED_PARAMETER(lParam); + UNREFERENCED_PARAMETER(lParam); } static BOOL OnInfoWoRegister(HWND hDlg) @@ -3346,7 +3253,9 @@ VOID LoadBreakpointList(HANDLE hFile) // NULL = clear breakpoint list // read number of breakpoints if (hFile) ReadFile(hFile, &wBreakpointCount, sizeof(wBreakpointCount), &lBytesRead, NULL); - if (lBytesRead) // breakpoints found + + // breakpoints found + if (lBytesRead == sizeof(wBreakpointCount) && wBreakpointCount < ARRAYSIZEOF(sBreakpoint)) { WORD wBreakpointSize; @@ -3363,7 +3272,7 @@ VOID LoadBreakpointList(HANDLE hFile) // NULL = clear breakpoint list wBreakpointCount = 0; // clear breakpoint list } } - else + else // no breakpoints or breakpoint buffer too small { wBreakpointCount = 0; // clear breakpoint list } @@ -3429,3 +3338,232 @@ VOID RestoreBackupBreakpointList(VOID) } return; } + + +//################ +//# +//# Load/Save Memory Data +//# +//################ + +static BOOL OnBrowseLoadMem(HWND hDlg) +{ + TCHAR szBuffer[MAX_PATH]; + OPENFILENAME ofn; + + ZeroMemory(&ofn, sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hDlg; + ofn.lpstrFilter = + _T("Memory Dump Files (*.MEM)\0*.MEM\0") + _T("All Files (*.*)\0*.*\0"); + ofn.lpstrDefExt = _T("MEM"); + ofn.nFilterIndex = 1; + ofn.lpstrFile = szBuffer; + ofn.lpstrFile[0] = 0; + ofn.nMaxFile = ARRAYSIZEOF(szBuffer); + ofn.Flags = OFN_EXPLORER|OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST; + if (GetOpenFileName(&ofn)) + { + SetDlgItemText(hDlg,IDC_DEBUG_DATA_FILE,szBuffer); + } + return 0; +} + +static BOOL OnBrowseSaveMem(HWND hDlg) +{ + TCHAR szBuffer[MAX_PATH]; + OPENFILENAME ofn; + + ZeroMemory(&ofn, sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hDlg; + ofn.lpstrFilter = + _T("Memory Dump Files (*.MEM)\0*.MEM\0") + _T("All Files (*.*)\0*.*\0"); + ofn.lpstrDefExt = _T("MEM"); + ofn.nFilterIndex = 1; + ofn.lpstrFile = szBuffer; + ofn.lpstrFile[0] = 0; + ofn.nMaxFile = ARRAYSIZEOF(szBuffer); + ofn.Flags = OFN_EXPLORER|OFN_HIDEREADONLY|OFN_CREATEPROMPT|OFN_OVERWRITEPROMPT; + if (GetSaveFileName(&ofn)) + { + SetDlgItemText(hDlg,IDC_DEBUG_DATA_FILE,szBuffer); + } + return 0; +} + +// +// write file to memory +// +static BOOL LoadMemData(LPCTSTR lpszFilename,DWORD dwStartAddr) +{ + HANDLE hFile; + DWORD dwRead; + BYTE byData; + + hFile = CreateFile(lpszFilename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); + if (hFile == INVALID_HANDLE_VALUE) // error, couldn't create a new file + return FALSE; + + while (TRUE) // read until EOF + { + ReadFile(hFile,&byData,sizeof(byData),&dwRead,NULL); + if (dwRead == 0) break; // EOF + + Write2(dwStartAddr,byData); // write byte in map mode + dwStartAddr += 2; + } + + CloseHandle(hFile); + return TRUE; +} + +// +// write memory data to file +// +static BOOL SaveMemData(LPCTSTR lpszFilename,DWORD dwStartAddr,DWORD dwEndAddr) +{ + HANDLE hFile; + DWORD dwAddr,dwWritten; + BYTE byData; + + hFile = CreateFile(lpszFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) // error, couldn't create a new file + return FALSE; + + for (dwAddr = dwStartAddr; dwAddr <= dwEndAddr; dwAddr += 2) + { + byData = Read2(dwAddr); // read byte in map mode + WriteFile(hFile,&byData,sizeof(byData),&dwWritten,NULL); + } + + CloseHandle(hFile); + return TRUE; +} + +// +// read edit control and decode content as hex number +// +static BOOL GetAddr(HWND hDlg, INT nID, DWORD *pdwAddr) +{ + TCHAR szBuffer[8]; + INT i; + + HWND hWnd = GetDlgItem(hDlg,nID); + + GetWindowText(hWnd,szBuffer,ARRAYSIZEOF(szBuffer)); + + // test if valid hex address + for (i = 0; i < (LONG) lstrlen(szBuffer); ++i) + { + if (_istxdigit(szBuffer[i]) == 0) + { + SendMessage(hWnd,EM_SETSEL,0,-1); + SetFocus(hWnd); // focus to edit control + return FALSE; + } + } + _stscanf(szBuffer,_T("%6X"),pdwAddr); + return TRUE; +} + +// +// memory load data +// +static INT_PTR CALLBACK DebugMemLoad(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + TCHAR szFilename[MAX_PATH]; + DWORD dwStartAddr; + + switch (message) + { + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_DEBUG_DATA_BUT: + return OnBrowseLoadMem(hDlg); + + case IDOK: + // get filename + GetDlgItemText(hDlg,IDC_DEBUG_DATA_FILE,szFilename,ARRAYSIZEOF(szFilename)); + + // decode address field + if (!GetAddr(hDlg,IDC_DEBUG_DATA_STARTADDR,&dwStartAddr)) + return FALSE; + + // load memory dump file + if (!LoadMemData(szFilename,dwStartAddr)) + return FALSE; + + // update memory window + UpdateMemoryWnd(GetParent(hDlg)); + + // no break + case IDCANCEL: + EndDialog(hDlg,LOWORD(wParam)); + return TRUE; + } + } + return FALSE; + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); +} + +static BOOL OnMemLoadData(HWND hDlg) +{ + if (DialogBox(hApp, MAKEINTRESOURCE(IDD_DEBUG_MEMLOAD), hDlg, (DLGPROC)DebugMemLoad) == -1) + AbortMessage(_T("DebugLoad Dialog Box Creation Error !")); + + return -1; +} + +// +// memory save data +// +static INT_PTR CALLBACK DebugMemSave(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + TCHAR szFilename[MAX_PATH]; + DWORD dwStartAddr,dwEndAddr; + + switch (message) + { + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_DEBUG_DATA_BUT: + return OnBrowseSaveMem(hDlg); + + case IDOK: + // get filename + GetDlgItemText(hDlg,IDC_DEBUG_DATA_FILE,szFilename,ARRAYSIZEOF(szFilename)); + + // decode address fields + if (!GetAddr(hDlg,IDC_DEBUG_DATA_STARTADDR,&dwStartAddr)) + return FALSE; + if (!GetAddr(hDlg,IDC_DEBUG_DATA_ENDADDR,&dwEndAddr)) + return FALSE; + + // save memory dump file + if (!SaveMemData(szFilename,dwStartAddr,dwEndAddr)) + return FALSE; + + // no break + case IDCANCEL: + EndDialog(hDlg,LOWORD(wParam)); + return TRUE; + } + } + return FALSE; + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); +} + +static BOOL OnMemSaveData(HWND hDlg) +{ + if (DialogBox(hApp, MAKEINTRESOURCE(IDD_DEBUG_MEMSAVE), hDlg, (DLGPROC)DebugMemSave) == -1) + AbortMessage(_T("DebugSave Dialog Box Creation Error !")); + + return -1; +} diff --git a/Sources/Emu48/DEBUGGER.H b/Sources/Emu48/DEBUGGER.H index 78224f5..1a9b694 100644 --- a/Sources/Emu48/DEBUGGER.H +++ b/Sources/Emu48/DEBUGGER.H @@ -11,7 +11,7 @@ #define BP_EXEC 0x01 // code breakpoint #define BP_READ 0x02 // read memory breakpoint #define BP_WRITE 0x04 // write memory breakpoint -#define BP_RPL 0x08 // RPL breakpoint +#define BP_RPL 0x08 // RPL breakpoint #define BP_ACCESS (BP_READ|BP_WRITE) // read/write memory breakpoint // breakpoint notify definitions @@ -24,8 +24,8 @@ #define DBG_OFF 0 #define DBG_RUN 1 #define DBG_STEPINTO 2 -#define DBG_STEPOVER 3 -#define DBG_STEPOUT 4 +#define DBG_STEPOVER 3 +#define DBG_STEPOUT 4 // debugger.c extern VOID UpdateDbgCycleCounter(VOID); diff --git a/Sources/Emu48/DISASM.C b/Sources/Emu48/DISASM.C index 944302a..71078e0 100644 --- a/Sources/Emu48/DISASM.C +++ b/Sources/Emu48/DISASM.C @@ -16,7 +16,6 @@ BOOL disassembler_mode = HP_MNEMONICS; BOOL disassembler_symb = FALSE; -WORD disassembler_map = MEM_MAP; static LPCTSTR hex[] = { @@ -215,82 +214,13 @@ static LPCTSTR hst_bits[8] = _T("xm"), _T("sb"), _T("sr"), _T("mp") }; - -// static functions - -static BYTE rn_map (DWORD *p) -{ - BYTE byVal; - - Npeek(&byVal, *p, 1); - *p = ++(*p) & 0xFFFFF; - return byVal; -} - -static BYTE rn_rom (DWORD *p) -{ - DWORD d = *p; - - *p = ++(*p) & (dwRomSize - 1); - - _ASSERT(d < dwRomSize); - return *(pbyRom + d); -} - -static BYTE rn_ram (DWORD *p) -{ - DWORD d = *p; - - *p = ++(*p) & (Chipset.Port0Size * 2048 - 1); - - _ASSERT(d < Chipset.Port0Size * 2048); - return *(Port0 + d); -} - -static BYTE rn_port1 (DWORD *p) -{ - DWORD d = *p; - - *p = ++(*p) & (Chipset.Port1Size * 2048 - 1); - - _ASSERT(d < Chipset.Port1Size * 2048); - return *(Port1 + d); -} - -static BYTE rn_port2 (DWORD *p) -{ - BYTE *pbyVal; - DWORD d = *p; - - if (Chipset.Port2Size) // HP39/40G, HP49G - { - *p = ++(*p) & (Chipset.Port2Size * 2048 - 1); - - _ASSERT(d < Chipset.Port2Size * 2048); - pbyVal = Port2; - } - else // HP48SX/GX - { - *p = ++(*p) & (((dwPort2Mask + 1) << 18) - 1); - - _ASSERT(d < ((dwPort2Mask + 1) << 18)); - pbyVal = pbyPort2; - } - return *(pbyVal + d); -} - -// global functions - -BYTE read_nibble (DWORD *p) -{ - BYTE (*pnread[])(DWORD *) = { rn_map, rn_rom, rn_ram, rn_port1, rn_port2 }; - - _ASSERT(disassembler_map < ARRAYSIZEOF(pnread)); - return pnread[disassembler_map](p); -} - // general functions +static BYTE read_nibble (DWORD *p) +{ + return GetMemNib(p); +} + static int read_int (DWORD *addr, int n) { int i, t; @@ -835,7 +765,7 @@ static LPTSTR disasm_8 (DWORD *addr, LPTSTR out) { case HP_MNEMONICS: wsprintf (buf, _T("%cBIT=%d"), (fn & 8) ? _T('C') : _T('A'), - (fn & 1) ? 1 : 0); + (fn & 1) ? 1 : 0); p = append_str (out, buf); p = append_tab (out); p = append_imm_nibble (p, addr, 1); @@ -909,7 +839,7 @@ static LPTSTR disasm_8 (DWORD *addr, LPTSTR out) { case HP_MNEMONICS: wsprintf (buf, (n == 0xf) ? _T("%c%cEX") : _T("%c=%c"), - (n == 0xd) ? _T('P') : _T('C'), (n == 0xd) ? _T('C') : _T('P')); + (n == 0xd) ? _T('P') : _T('C'), (n == 0xd) ? _T('C') : _T('P')); p = append_str (out, buf); p = append_tab (out); wsprintf (buf, _T("%d"), fn); @@ -919,7 +849,7 @@ static LPTSTR disasm_8 (DWORD *addr, LPTSTR out) p = append_str (out, (n == 0xf) ? _T("exg.1") : _T("move.1")); p = append_tab (out); wsprintf (buf, (n == 0xd) ? _T("p, c.%d") : _T("c.%d, p"), fn); - p = append_str (p, buf); + p = append_str (p, buf); break; default: p = append_str (out, _T("Unknown disassembler mode")); @@ -988,9 +918,9 @@ static LPTSTR disasm_8 (DWORD *addr, LPTSTR out) { case HP_MNEMONICS: wsprintf (buf, _T("%s=%s%cCON"), - op_str_81[(n & 3) + 4 * disassembler_mode], - op_str_81[(n & 3) + 4 * disassembler_mode], - (n < 8) ? _T('+') : _T('-')); + op_str_81[(n & 3) + 4 * disassembler_mode], + op_str_81[(n & 3) + 4 * disassembler_mode], + (n < 8) ? _T('+') : _T('-')); p = append_str (out, buf); p = append_tab (out); p = append_field (p, fn); @@ -1053,18 +983,18 @@ static LPTSTR disasm_8 (DWORD *addr, LPTSTR out) if (n == 2) { wsprintf (buf, _T("%cR%dEX.F"), ((int) c < 8) ? _T('A') : _T('C'), - (int) c & 7); + (int) c & 7); } else if (n == 1) { wsprintf (buf, _T("%c=R%d.F"), ((int) c < 8) ? _T('A') : _T('C'), - (int) c & 7); + (int) c & 7); } else { wsprintf (buf, _T("R%d=%c.F"), (int) c & 7, - ((int) c < 8) ? _T('A') : _T('C')); + ((int) c < 8) ? _T('A') : _T('C')); } p = append_str (out, buf); p = append_tab (out); @@ -1395,7 +1325,7 @@ DWORD disassemble (DWORD addr, LPTSTR out) { case HP_MNEMONICS: wsprintf (buf, op_str_0[(n & 7) + 8 * HP_MNEMONICS], - (n < 8) ? _T('&') : _T('!')); + (n < 8) ? _T('&') : _T('!')); p = append_str (out, buf); p = append_tab (out); p = append_field (p, fn); @@ -1609,10 +1539,10 @@ DWORD disassemble (DWORD addr, LPTSTR out) case HP_MNEMONICS: if ((c == 0) && (n >= 8)) wsprintf (buf, op_str_9[(n & 3) + 8 * HP_MNEMONICS + 4], - in_str_9[((n >> 2) & 3) + 4 * c + 8 * HP_MNEMONICS]); + in_str_9[((n >> 2) & 3) + 4 * c + 8 * HP_MNEMONICS]); else wsprintf (buf, op_str_9[(n & 3) + 8 * HP_MNEMONICS], - in_str_9[((n >> 2) & 3) + 4 * c + 8 * HP_MNEMONICS]); + in_str_9[((n >> 2) & 3) + 4 * c + 8 * HP_MNEMONICS]); p = append_str (out, buf); p = append_tab (out); p = append_field (p, fn); diff --git a/Sources/Emu48/DISMEM.C b/Sources/Emu48/DISMEM.C new file mode 100644 index 0000000..15313a3 --- /dev/null +++ b/Sources/Emu48/DISMEM.C @@ -0,0 +1,221 @@ +/* + * dismem.c + * + * This file is part of Emu48 + * + * Copyright (C) 2012 Christoph Gießelink + * + */ +#include "pch.h" +#include "Emu48.h" + +typedef struct // type of model memory mapping +{ + CONST BYTE byType; // calculator type + CONST LPBYTE *ppbyNCE1; // NCE1 data + CONST DWORD *pdwNCE1Size; // NCE1 size + CONST LPBYTE *ppbyNCE2; // NCE2 data + CONST DWORD *pdwNCE2Size; // NCE2 size + CONST LPBYTE *ppbyCE1; // CE1 data + CONST DWORD *pdwCE1Size; // CE1 size + CONST LPBYTE *ppbyCE2; // CE2 data + CONST DWORD *pdwCE2Size; // CE2 size + CONST LPBYTE *ppbyNCE3; // NCE3 data + CONST DWORD *pdwNCE3Size; // NCE3 size +} MODEL_MAP_T; + +static CONST LPBYTE pbyNoMEM = NULL; // no memory module + +static CONST MODEL_MAP_T MemMap[] = +{ + { + 0, // default + &pbyNoMEM, NULL, // nc. + &pbyNoMEM, NULL, // nc. + &pbyNoMEM, NULL, // nc. + &pbyNoMEM, NULL, // nc. + &pbyNoMEM, NULL // nc. + }, + { + '6', // HP38G (64K) + &pbyRom, &dwRomSize, // ROM + &Port0, &Chipset.Port0Size, // RAM + &pbyNoMEM, NULL, // nc. + &pbyNoMEM, NULL, // nc. + &pbyNoMEM, NULL // nc. + }, + { + 'A', // HP38G + &pbyRom, &dwRomSize, // ROM + &Port0, &Chipset.Port0Size, // RAM + &pbyNoMEM, NULL, // nc. + &pbyNoMEM, NULL, // nc. + &pbyNoMEM, NULL // nc. + }, + { + 'E', // HP39/40G + &pbyRom, &dwRomSize, // ROM + &Port0, &Chipset.Port0Size, // RAM part 1 + &pbyNoMEM, NULL, // BS + &pbyNoMEM, NULL, // nc. + &Port2, &Chipset.Port2Size // RAM part 2 + }, + { + 'G', // HP48GX + &pbyRom, &dwRomSize, // ROM + &Port0, &Chipset.Port0Size, // RAM + &pbyNoMEM, NULL, // BS + &Port1, &Chipset.Port1Size, // Card slot 1 + &pbyPort2, &dwPort2Size // Card slot 2 + }, + { + 'S', // HP48SX + &pbyRom, &dwRomSize, // ROM + &Port0, &Chipset.Port0Size, // RAM + &Port1, &Chipset.Port1Size, // Card slot 1 + &pbyPort2, &dwPort2Size, // Card slot 2 + &pbyNoMEM, NULL // nc. + }, + { + 'X', // HP49G + &pbyRom, &dwRomSize, // Flash + &Port0, &Chipset.Port0Size, // RAM + &pbyNoMEM, NULL, // BS + &Port1, &Chipset.Port1Size, // Port 1 part 1 + &Port2, &Chipset.Port2Size // Port 1 part 2 + } +}; + +static MODEL_MAP_T CONST *pMapping = MemMap; // model specific memory mapping +static enum MEM_MAPPING eMapType = MEM_MMU; // MMU memory mapping + +static LPBYTE pbyMapData = NULL; +static DWORD dwMapDataSize = 0; +static DWORD dwMapDataMask = 0; + +BOOL SetMemRomType(BYTE cCurrentRomType) +{ + INT i; + + pMapping = MemMap; // init default mapping + + // scan for all table entries + for (i = 0; i < ARRAYSIZEOF(MemMap); ++i) + { + if (MemMap[i].byType == cCurrentRomType) + { + pMapping = &MemMap[i]; // found entry + return TRUE; + } + } + return FALSE; +} + +BOOL SetMemMapType(enum MEM_MAPPING eType) +{ + BOOL bSucc = TRUE; + + eMapType = eType; + + switch (eMapType) + { + case MEM_MMU: + pbyMapData = NULL; // data + dwMapDataSize = 512 * 1024 * 2; // data size + dwMapDataMask = dwMapDataSize - 1; // size mask + break; + case MEM_NCE1: + pbyMapData = *pMapping->ppbyNCE1; + dwMapDataSize = *pMapping->pdwNCE1Size; // ROM size is always in nibbles + dwMapDataMask = dwMapDataSize - 1; // size mask + break; + case MEM_NCE2: + pbyMapData = *pMapping->ppbyNCE2; + dwMapDataSize = *pMapping->pdwNCE2Size * 1024 * 2; + dwMapDataMask = dwMapDataSize - 1; // size mask + break; + case MEM_CE1: + pbyMapData = *pMapping->ppbyCE1; + dwMapDataSize = *pMapping->pdwCE1Size * 1024 * 2; + dwMapDataMask = dwMapDataSize - 1; // size mask + break; + case MEM_CE2: + pbyMapData = *pMapping->ppbyCE2; + dwMapDataSize = *pMapping->pdwCE2Size * 1024 * 2; + dwMapDataMask = dwMapDataSize - 1; // size mask + break; + case MEM_NCE3: + pbyMapData = *pMapping->ppbyNCE3; + dwMapDataSize = *pMapping->pdwNCE3Size * 1024 * 2; + dwMapDataMask = dwMapDataSize - 1; // size mask + break; + default: _ASSERT(FALSE); + pbyMapData = NULL; + dwMapDataSize = 0; + dwMapDataMask = 0; + bSucc = FALSE; + } + return bSucc; +} + +enum MEM_MAPPING GetMemMapType(VOID) +{ + return eMapType; +} + +BOOL GetMemAvail(enum MEM_MAPPING eType) +{ + switch (eType) + { + case MEM_MMU: return TRUE; + case MEM_NCE1: return *pMapping->ppbyNCE1 != NULL; + case MEM_NCE2: return *pMapping->ppbyNCE2 != NULL; + case MEM_CE1: return *pMapping->ppbyCE1 != NULL; + case MEM_CE2: return *pMapping->ppbyCE2 != NULL; + case MEM_NCE3: return *pMapping->ppbyNCE3 != NULL; + default: _ASSERT(FALSE); + } + return FALSE; +} + +DWORD GetMemDataSize(VOID) +{ + return dwMapDataSize; +} + +DWORD GetMemDataMask(VOID) +{ + return dwMapDataMask; +} + +BYTE GetMemNib(DWORD *p) +{ + BYTE byVal; + + if (pbyMapData == NULL) + { + Npeek(&byVal, *p, 1); + } + else + { + byVal = pbyMapData[*p]; + } + *p = (*p + 1) & dwMapDataMask; + return byVal; +} + +VOID GetMemPeek(BYTE *a, DWORD d, UINT s) +{ + if (pbyMapData == NULL) + { + Npeek(a, d, s); + } + else + { + for (; s > 0; --s, ++d) + { + *a++ = pbyMapData[d & dwMapDataMask]; + } + } + return; +} diff --git a/Sources/Emu48/DISPLAY.C b/Sources/Emu48/DISPLAY.C index d97d930..6ab3d2d 100644 --- a/Sources/Emu48/DISPLAY.C +++ b/Sources/Emu48/DISPLAY.C @@ -34,8 +34,12 @@ |((((c)-1)>>1)<<8) \ |((((c)-1)>>1))) -#define DIBPIXEL4(d,p) *((DWORD*)(d)) = ((*((DWORD*)(d)) & dwGrayMask) << 1) | (p); (BYTE *) d += 4 -#define DIBPIXEL3(d,p) *(d+2) = *(d+1) = *d = ((*d & (BYTE) dwGrayMask) << 1) | (p); (BYTE *) d += 3 +#define DIBPIXEL4(d,p) *((DWORD*)(d)) = ((*((DWORD*)(d)) & dwGrayMask) << 1) | (p); \ + *((LPBYTE*) &(d)) += 4 +#define DIBPIXEL3(d,p) *((LPBYTE)(d)+2) = \ + *((LPBYTE)(d)+1) = \ + *((LPBYTE)(d)+0) = ((*(LPBYTE)(d) & (BYTE) dwGrayMask) << 1) | (p); \ + *((LPBYTE*) &(d)) += 3 BOOL bGrayscale = FALSE; UINT nBackgroundX = 0; @@ -882,7 +886,7 @@ static VOID CALLBACK LcdProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, } // LCD line counter calculation -BYTE GetLineCounterGray(VOID) +static BYTE GetLineCounterGray(VOID) { LARGE_INTEGER lLC; BYTE byTime; diff --git a/Sources/Emu48/DISRPL.C b/Sources/Emu48/DISRPL.C index b704550..93bd880 100644 --- a/Sources/Emu48/DISRPL.C +++ b/Sources/Emu48/DISRPL.C @@ -34,7 +34,7 @@ static VOID PutSn(String *str, LPCTSTR szVal, DWORD dwLen) if (str->dwSize == 0) // no buffer allocated { str->dwSize = ALLOCSIZE; // buffer size - VERIFY(str->szBuffer = HeapAlloc(hHeap,0,str->dwSize * sizeof(TCHAR))); + VERIFY(str->szBuffer = (LPTSTR) malloc(str->dwSize * sizeof(TCHAR))); str->dwPos = 0; } @@ -51,7 +51,7 @@ static VOID PutSn(String *str, LPCTSTR szVal, DWORD dwLen) dwMinSize *= ALLOCSIZE; str->dwSize += dwMinSize; // new buffer size - VERIFY(str->szBuffer = HeapReAlloc(hHeap,0,str->szBuffer,str->dwSize * sizeof(TCHAR))); + VERIFY(str->szBuffer = (LPTSTR) realloc(str->szBuffer,str->dwSize * sizeof(TCHAR))); } CopyMemory(&str->szBuffer[str->dwPos],szVal,dwLen * sizeof(TCHAR)); @@ -117,7 +117,7 @@ static DWORD Readx(DWORD *pdwAddr,DWORD n) DWORD i, t; for (i = 0, t = 0; i < n; ++i) - t |= read_nibble(pdwAddr) << (i * 4); + t |= RplReadNibble(pdwAddr) << (i * 4); return t; } @@ -145,6 +145,7 @@ static BOOL BCDx(BYTE CONST *pbyNum,INT nMantLen,INT nExpLen,String *str) lExp -= nMantLen - 1; // set decimal point to end of mantissa bPflag = FALSE; // show no decimal point + bExpflag = FALSE; // show no exponent // scan mantissa for (v = (LONG) nMantLen - 1; v >= 0 || bPflag; v--) @@ -214,10 +215,10 @@ static BOOL BINx(DWORD *pdwAddr,INT nBinLen,String *str) LPBYTE pbyNumber; INT i; - VERIFY(pbyNumber = HeapAlloc(hHeap,0,nBinLen)); + VERIFY(pbyNumber = (LPBYTE) malloc(nBinLen)); for (i = 0; i < nBinLen; ++i) // read data - pbyNumber[i] = read_nibble(pdwAddr); + pbyNumber[i] = RplReadNibble(pdwAddr); // strip leading zeros for (i = nBinLen - 1; pbyNumber[i] == 0 && i > 0; --i) { } @@ -227,7 +228,7 @@ static BOOL BINx(DWORD *pdwAddr,INT nBinLen,String *str) PutC(str,cHex[pbyNumber[i]]); } - HeapFree(hHeap,0,pbyNumber); + free(pbyNumber); return FALSE; } @@ -269,7 +270,7 @@ static BOOL DoHexStream(DWORD *pdwAddr,String *str,UINT *pnLevel) for (;dwLength > 0; --dwLength) { - PutC(str,cHex[read_nibble(pdwAddr)]); // write digit + PutC(str,cHex[RplReadNibble(pdwAddr)]); // write digit } return FALSE; } @@ -321,10 +322,10 @@ static BOOL DoIntStream(DWORD *pdwAddr,String *str,UINT *pnLevel) dwLength -= 5; // object length - VERIFY(pbyData = HeapAlloc(hHeap,0,dwLength)); + VERIFY(pbyData = (LPBYTE) malloc(dwLength)); for (i = 0; i < dwLength; ++i) // read data - pbyData[i] = read_nibble(pdwAddr); + pbyData[i] = RplReadNibble(pdwAddr); if (dwLength == 1) // special implementation for zero { @@ -343,7 +344,7 @@ static BOOL DoIntStream(DWORD *pdwAddr,String *str,UINT *pnLevel) } } - HeapFree(hHeap,0,pbyData); + free(pbyData); return FALSE; } @@ -369,7 +370,7 @@ static BOOL DoReal(DWORD *pdwAddr,String *str,UINT *pnLevel) // get real object content for (i = 0; i < ARRAYSIZEOF(byNumber); ++i) - byNumber[i] = read_nibble(pdwAddr); + byNumber[i] = RplReadNibble(pdwAddr); return BCDx(byNumber,12,3,str); } @@ -383,7 +384,7 @@ BOOL DoERel(DWORD *pdwAddr,String *str,UINT *pnLevel) // get extended real object content for (i = 0; i < ARRAYSIZEOF(byNumber); ++i) - byNumber[i] = read_nibble(pdwAddr); + byNumber[i] = RplReadNibble(pdwAddr); return BCDx(byNumber,15,5,str); } @@ -397,7 +398,7 @@ static BOOL DoCmp(DWORD *pdwAddr,String *str,UINT *pnLevel) // get real part of complex object content for (i = 0; i < ARRAYSIZEOF(byNumber); ++i) - byNumber[i] = read_nibble(pdwAddr); + byNumber[i] = RplReadNibble(pdwAddr); BCDx(byNumber,12,3,str); @@ -405,7 +406,7 @@ static BOOL DoCmp(DWORD *pdwAddr,String *str,UINT *pnLevel) // get imaginary part of complex object content for (i = 0; i < ARRAYSIZEOF(byNumber); ++i) - byNumber[i] = read_nibble(pdwAddr); + byNumber[i] = RplReadNibble(pdwAddr); return BCDx(byNumber,12,3,str); } @@ -419,7 +420,7 @@ static BOOL DoECmp(DWORD *pdwAddr,String *str,UINT *pnLevel) // get real part of extended complex object content for (i = 0; i < ARRAYSIZEOF(byNumber); ++i) - byNumber[i] = read_nibble(pdwAddr); + byNumber[i] = RplReadNibble(pdwAddr); BCDx(byNumber,15,5,str); @@ -427,7 +428,7 @@ static BOOL DoECmp(DWORD *pdwAddr,String *str,UINT *pnLevel) // get imaginary part of extended complex object content for (i = 0; i < ARRAYSIZEOF(byNumber); ++i) - byNumber[i] = read_nibble(pdwAddr); + byNumber[i] = RplReadNibble(pdwAddr); return BCDx(byNumber,15,5,str); } @@ -670,7 +671,7 @@ static BOOL DoHxs(DWORD *pdwAddr,String *str,UINT *pnLevel) for (i = 0; i < dwLength; ++i) { - byVal = read_nibble(pdwAddr); + byVal = RplReadNibble(pdwAddr); // remove leading zeros if (byVal == 0 && bRemove && i + 1 < dwLength) @@ -752,7 +753,7 @@ static BOOL Semi(DWORD *pdwAddr,String *str,UINT *pnLevel) static BOOL DoRrp(DWORD *pdwAddr,String *str,UINT *pnLevel) { DWORD dwOffset,dwObjStart,dwBufferPos,dwAddr; - BOOL bErr; + BOOL bErr = FALSE; dwObjStart = *pdwAddr; // remember start position of RRP dwBufferPos = str->dwPos; // insert address of text @@ -1254,10 +1255,13 @@ static BOOL FetchObj(DWORD *pdwAddr,String *str,UINT *pnLevel) return bErr; } +BYTE (*RplReadNibble)(DWORD *p) = NULL; // get nibble function pointer + DWORD RplSkipObject(DWORD dwAddr) { UINT nLevel = 1; // nest DOCOL objects + _ASSERT(RplReadNibble != NULL); // get nibble function defined FetchObj(&dwAddr,NULL,&nLevel); // decode object without output return dwAddr; } @@ -1269,12 +1273,14 @@ LPTSTR RplDecodeObject(DWORD dwAddr, DWORD *pdwNxtAddr) UINT nLevel = 0; // don't nest DOCOL objects dwNxtAddr = dwAddr; // init next address + + _ASSERT(RplReadNibble != NULL); // get nibble function defined FetchObj(&dwNxtAddr,&str,&nLevel); // decode object PutC(&str,0); // set EOS // release unnecessary allocated buffer memory - VERIFY(str.szBuffer = HeapReAlloc(hHeap,0,str.szBuffer,str.dwPos * sizeof(str.szBuffer[0]))); + VERIFY(str.szBuffer = (LPTSTR) realloc(str.szBuffer,str.dwPos * sizeof(str.szBuffer[0]))); // return address of next object if (pdwNxtAddr != NULL) *pdwNxtAddr = dwNxtAddr; @@ -1310,7 +1316,7 @@ static VOID PrintHead(DWORD dwStartAddr, DWORD dwEndAddr, String *str) if (dwStartAddr < dwEndAddr) // still show hex nibble { - c = cHex[read_nibble(&dwStartAddr)]; + c = cHex[RplReadNibble(&dwStartAddr)]; } PutC(str,c); // write data content @@ -1342,6 +1348,10 @@ static VOID PrintTail(DWORD dwStartAddr, DWORD dwEndAddr, String *str) { // spaces instead of show address PutS(str,_T(" ")); + + // address has 6 digit + if (dwActAddr >= 0x100000) + PutC(str,_T(' ')); } dwRemain = dwEndAddr - dwActAddr; @@ -1350,7 +1360,7 @@ static VOID PrintTail(DWORD dwStartAddr, DWORD dwEndAddr, String *str) for (; dwRemain > 0; --dwRemain) { // write data content - PutC(str,cHex[read_nibble(&dwActAddr)]); + PutC(str,cHex[RplReadNibble(&dwActAddr)]); } PutS(str,_T("\r\n")); @@ -1444,6 +1454,8 @@ LPTSTR RplCreateObjView(DWORD dwStartAddr, DWORD dwEndAddr, BOOL bSingleObj) LPTSTR lpszObject; DWORD dwLevel,dwAddr,dwNxtAddr; + _ASSERT(RplReadNibble != NULL); // get nibble function defined + lpszObject = NULL; // no memory allocated dwLevel = 0; // nesting level @@ -1465,15 +1477,14 @@ LPTSTR RplCreateObjView(DWORD dwStartAddr, DWORD dwEndAddr, BOOL bSingleObj) PutFS(&str,_T("=%s\r\n"),lpszName); } - PrintHead(dwAddr,dwAddr+5,&str); // write initial head + PrintHead(dwAddr,dwAddr+5,&str); // write initial head do { // check for special RRP handling if (_tcsncmp(lpszObject,_T("DIR\n"),4) == 0) { - LPCTSTR lpszStart; - LPTSTR lpszEnd; + LPCTSTR lpszStart,lpszEnd; lpszStart = lpszEnd = lpszObject; @@ -1525,13 +1536,12 @@ LPTSTR RplCreateObjView(DWORD dwStartAddr, DWORD dwEndAddr, BOOL bSingleObj) while (FALSE); PutS(&str,_T("\r\n")); - // write additional binary data - PrintTail(dwAddr+5,dwNxtAddr,&str); + PrintTail(dwAddr+5,dwNxtAddr,&str); // write additional binary data if (lstrcmp(lpszObject,_T("::")) == 0) ++dwLevel; - HeapFree(hHeap,0,lpszObject); // free object string + free(lpszObject); // free object string lpszObject = NULL; if ( (bSingleObj && dwLevel == 0) // single object decoding? @@ -1554,6 +1564,6 @@ LPTSTR RplCreateObjView(DWORD dwStartAddr, DWORD dwEndAddr, BOOL bSingleObj) PutC(&str,0); // set EOS // release unnecessary allocated buffer memory - VERIFY(str.szBuffer = HeapReAlloc(hHeap,0,str.szBuffer,str.dwPos * sizeof(str.szBuffer[0]))); + VERIFY(str.szBuffer = (LPTSTR) realloc(str.szBuffer,str.dwPos * sizeof(str.szBuffer[0]))); return str.szBuffer; } diff --git a/Sources/Emu48/DISRPL.H b/Sources/Emu48/DISRPL.H index f32fab5..ba2f5cd 100644 --- a/Sources/Emu48/DISRPL.H +++ b/Sources/Emu48/DISRPL.H @@ -19,6 +19,7 @@ extern BOOL bRplViewName; // show entry point name extern BOOL bRplViewAddr; // show adress extern BOOL bRplViewBin; // show binary data extern BOOL bRplViewAsm; // show ASM code instead of hex data +extern BYTE (*RplReadNibble)(DWORD *p); // read nibble function pointer extern DWORD RplSkipObject(DWORD dwAddr); extern LPTSTR RplDecodeObject(DWORD dwAddr, DWORD *pdwNxtAddr); extern LPTSTR RplCreateObjView(DWORD dwStartAddr, DWORD dwEndAddr, BOOL bSingleObj); diff --git a/Sources/Emu48/EMU48.C b/Sources/Emu48/EMU48.C index 8b0196f..cd910b5 100644 --- a/Sources/Emu48/EMU48.C +++ b/Sources/Emu48/EMU48.C @@ -13,7 +13,7 @@ #include "kml.h" #include "debugger.h" -#define VERSION "1.50" +#define VERSION "1.53" // #define MONOCHROME // CF_BITMAP clipboard format @@ -59,7 +59,6 @@ LARGE_INTEGER lFreq; // high performance counter frequency LARGE_INTEGER lAppStart; // high performance counter value at Appl. start DWORD idDdeInst; // DDE server id UINT uCF_HpObj; // DDE clipboard format -HANDLE hHeap; HANDLE hThread; DWORD lThreadId; HANDLE hEventShutdn; // event handle to stop cpu thread @@ -84,7 +83,7 @@ BOOL bAlwaysDisplayLog = TRUE; BOOL bLoadObjectWarning = TRUE; BOOL bAlwaysOnTop = FALSE; // emulator window always on top BOOL bActFollowsMouse = FALSE; // emulator window activation follows mouse - +BOOL bSingleInstance = FALSE; // multiple emulator instances allowed //################ @@ -95,7 +94,7 @@ BOOL bActFollowsMouse = FALSE; // emulator window activation follows VOID SetWindowTitle(LPCTSTR szString) { - if (szTitle) HeapFree(hHeap,0,szTitle); + if (szTitle) free(szTitle); _ASSERT(hWnd != NULL); if (szString) @@ -111,44 +110,6 @@ VOID SetWindowTitle(LPCTSTR szString) return; } -VOID UpdateWindowStatus(VOID) -{ - if (hWnd) // window open - { - // disable stack loading items on HP38G, HP39/40G - BOOL bStackEnable = cCurrentRomType!='6' && cCurrentRomType!='A' && cCurrentRomType!='E'; - BOOL bRun = nState == SM_RUN || nState == SM_SLEEP; - - UINT uStackEnable = (bRun && bStackEnable) ? MF_ENABLED : MF_GRAYED; - UINT uRun = bRun ? MF_ENABLED : MF_GRAYED; - UINT uBackup = bBackup ? MF_ENABLED : MF_GRAYED; - - HMENU hMenu = GetMenu(hWnd); // get menu handle - - EnableMenuItem(hMenu,ID_FILE_NEW,MF_ENABLED); - EnableMenuItem(hMenu,ID_FILE_OPEN,MF_ENABLED); - EnableMenuItem(hMenu,ID_FILE_SAVE,(bRun && szCurrentFilename[0]) ? MF_ENABLED : MF_GRAYED); - EnableMenuItem(hMenu,ID_FILE_SAVEAS,uRun); - EnableMenuItem(hMenu,ID_FILE_CLOSE,uRun); - EnableMenuItem(hMenu,ID_OBJECT_LOAD,uStackEnable); - EnableMenuItem(hMenu,ID_OBJECT_SAVE,uStackEnable); - EnableMenuItem(hMenu,ID_VIEW_COPY,uRun); - EnableMenuItem(hMenu,ID_STACK_COPY,uStackEnable); - EnableMenuItem(hMenu,ID_STACK_PASTE,uStackEnable); - EnableMenuItem(hMenu,ID_VIEW_RESET,uRun); - EnableMenuItem(hMenu,ID_BACKUP_SAVE,uRun); - EnableMenuItem(hMenu,ID_BACKUP_RESTORE,uBackup); - EnableMenuItem(hMenu,ID_BACKUP_DELETE,uBackup); - EnableMenuItem(hMenu,ID_VIEW_SCRIPT,uRun); - EnableMenuItem(hMenu,ID_TOOL_DISASM,uRun); - EnableMenuItem(hMenu,ID_TOOL_DEBUG,(bRun && nDbgState == DBG_OFF) ? MF_ENABLED : MF_GRAYED); - EnableMenuItem(hMenu,ID_TOOL_MACRO_RECORD,(bRun && nMacroState == MACRO_OFF) ? MF_ENABLED : MF_GRAYED); - EnableMenuItem(hMenu,ID_TOOL_MACRO_PLAY,(bRun && nMacroState == MACRO_OFF) ? MF_ENABLED : MF_GRAYED); - EnableMenuItem(hMenu,ID_TOOL_MACRO_STOP,(bRun && nMacroState != MACRO_OFF) ? MF_ENABLED : MF_GRAYED); - } - return; -} - VOID ForceForegroundWindow(HWND hWnd) { // force window to foreground @@ -178,7 +139,7 @@ VOID CopyItemsToClipboard(HWND hWnd) // save selected Listbox Items to Clipboar if ((i = (LONG) SendMessage(hWnd,LB_GETSELCOUNT,0,0)) == 0) return; // no items selected - if ((lpnCount = HeapAlloc(hHeap,0,i * sizeof(INT))) != NULL) + if ((lpnCount = malloc(i * sizeof(INT))) != NULL) { LPTSTR lpszData; HANDLE hClipObj; @@ -223,7 +184,7 @@ VOID CopyItemsToClipboard(HWND hWnd) // save selected Listbox Items to Clipboar GlobalFree(hClipObj); } } - HeapFree(hHeap,0,lpnCount); // free item table + free(lpnCount); // free item table } return; } @@ -327,16 +288,11 @@ static VOID SetCommList(HWND hDlg,LPCTSTR szWireSetting,LPCTSTR szIrSetting) return; } -static INT_PTR CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +static BOOL CALLBACK SettingsGeneralProc(HWND hDlg, UINT uMsg, DWORD wParam, LONG lParam) { HWND hWndInsertAfter; - LPCTSTR szActPort2Filename = _T(""); - - BOOL bPort2CfgChange = FALSE; - BOOL bPort2AttChange = FALSE; - - switch (message) + switch (uMsg) { case WM_INITDIALOG: // init speed checkbox @@ -344,6 +300,12 @@ static INT_PTR CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPA CheckDlgButton(hDlg,IDC_GRAYSCALE,bGrayscale); CheckDlgButton(hDlg,IDC_ALWAYSONTOP,bAlwaysOnTop); CheckDlgButton(hDlg,IDC_ACTFOLLOWSMOUSE,bActFollowsMouse); + #if defined _USRDLL // DLL version + CheckDlgButton(hDlg,IDC_SINGLEINSTANCE,FALSE); + EnableWindow(GetDlgItem(hDlg,IDC_SINGLEINSTANCE),FALSE); + #else + CheckDlgButton(hDlg,IDC_SINGLEINSTANCE,bSingleInstance); + #endif CheckDlgButton(hDlg,IDC_AUTOSAVE,bAutoSave); CheckDlgButton(hDlg,IDC_AUTOSAVEONEXIT,bAutoSaveOnExit); CheckDlgButton(hDlg,IDC_OBJECTLOADWARNING,bLoadObjectWarning); @@ -351,24 +313,58 @@ static INT_PTR CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPA // set disassebler mode CheckDlgButton(hDlg,(disassembler_mode == HP_MNEMONICS) ? IDC_DISASM_HP : IDC_DISASM_CLASS,BST_CHECKED); - - // set sound slider - SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_SETRANGE,FALSE,MAKELONG(0,255)); - SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_SETTICFREQ,256/8,0); - SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_SETPOS,TRUE,dwWaveVol); - - // set sound radio button - CheckDlgButton(hDlg,bWaveBeep ? IDC_SOUND_WAVE : IDC_SOUND_SPEAKER,BST_CHECKED); - EnableWindow(GetDlgItem(hDlg,IDC_SOUND_SLIDER),bWaveBeep); - - // set combobox parameter - SetCommList(hDlg,szSerialWire,szSerialIr); - if (bCommInit) // disable when port open + return TRUE; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->code) { - EnableWindow(GetDlgItem(hDlg,IDC_WIRE),FALSE); - EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE); - } + case PSN_KILLACTIVE: + // get speed checkbox value + bRealSpeed = IsDlgButtonChecked(hDlg,IDC_REALSPEED); + bAlwaysOnTop = IsDlgButtonChecked(hDlg,IDC_ALWAYSONTOP); + bActFollowsMouse = IsDlgButtonChecked(hDlg,IDC_ACTFOLLOWSMOUSE); + bSingleInstance = IsDlgButtonChecked(hDlg,IDC_SINGLEINSTANCE); + bAutoSave = IsDlgButtonChecked(hDlg,IDC_AUTOSAVE); + bAutoSaveOnExit = IsDlgButtonChecked(hDlg,IDC_AUTOSAVEONEXIT); + bLoadObjectWarning = IsDlgButtonChecked(hDlg,IDC_OBJECTLOADWARNING); + bAlwaysDisplayLog = IsDlgButtonChecked(hDlg,IDC_ALWAYSDISPLOG); + SetSpeed(bRealSpeed); // set speed + // LCD grayscale checkbox has been changed + if (bGrayscale != (BOOL) IsDlgButtonChecked(hDlg,IDC_GRAYSCALE)) + { + UINT nOldState = SwitchToState(SM_INVALID); + SetLcdMode(!bGrayscale); // set new display mode + SwitchToState(nOldState); + } + + // set disassembler mode + disassembler_mode = IsDlgButtonChecked(hDlg,IDC_DISASM_HP) ? HP_MNEMONICS : CLASS_MNEMONICS; + + // bAlwaysOnTop maybe changed, so set new window Z order + hWndInsertAfter = bAlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST; + SetWindowPos(hWnd,hWndInsertAfter,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE); + if (hDlgDebug != NULL) + { + SetWindowPos(hDlgDebug,hWndInsertAfter,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE); + } + return TRUE; + } + break; + } + return FALSE; + UNREFERENCED_PARAMETER(wParam); +} + +static BOOL CALLBACK SettingsMemoryProc(HWND hDlg, UINT uMsg, DWORD wParam, LONG lParam) +{ + LPCTSTR szActPort2Filename = _T(""); + + BOOL bPort2CfgChange = FALSE; + BOOL bPort2AttChange = FALSE; + + switch (uMsg) + { + case WM_INITDIALOG: // HP48SX/GX if (cCurrentRomType=='S' || cCurrentRomType=='G' || cCurrentRomType==0) { @@ -405,22 +401,11 @@ static INT_PTR CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPA EnableWindow(GetDlgItem(hDlg,IDC_PORT2WR),FALSE); EnableWindow(GetDlgItem(hDlg,IDC_PORT2),FALSE); EnableWindow(GetDlgItem(hDlg,IDC_PORT2LOAD),FALSE); - if (cCurrentRomType=='X') // HP49G - { - SendDlgItemMessage(hDlg,IDC_IR,CB_RESETCONTENT,0,0); - EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE); - } } return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { - case IDC_SOUND_SPEAKER: - EnableWindow(GetDlgItem(hDlg,IDC_SOUND_SLIDER),FALSE); - return TRUE; - case IDC_SOUND_WAVE: - EnableWindow(GetDlgItem(hDlg,IDC_SOUND_SLIDER),TRUE); - return TRUE; case IDC_PORT2LOAD: if (GetLoadObjectFilename(_T(BIN_FILTER),_T("BIN"))) { @@ -442,12 +427,17 @@ static INT_PTR CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPA CheckDlgButton(hDlg,IDC_PORT2WR,IsFileWriteable(szBufferFilename)); } return TRUE; - case IDOK: + } + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->code) + { + case PSN_KILLACTIVE: if (Chipset.Port1Size && cCurrentRomType!='X') { UINT nOldState = SwitchToState(SM_SLEEP); // save old card status - BYTE bCardsStatus = Chipset.cards_status; + BYTE byCardsStatus = Chipset.cards_status; // port1 disabled? Chipset.cards_status &= ~(PORT1_PRESENT | PORT1_WRITE); @@ -459,7 +449,7 @@ static INT_PTR CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPA } // changed card status in slot1? - if ( ((bCardsStatus ^ Chipset.cards_status) & (PORT1_PRESENT | PORT1_WRITE)) != 0 + if ( ((byCardsStatus ^ Chipset.cards_status) & (PORT1_PRESENT | PORT1_WRITE)) != 0 && (Chipset.IORam[CARDCTL] & ECDT) != 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0 ) { @@ -504,22 +494,7 @@ static INT_PTR CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPA bPort2CfgChange = TRUE; // slot2 configuration changed } } - // get speed checkbox value - bRealSpeed = IsDlgButtonChecked(hDlg,IDC_REALSPEED); - bAlwaysOnTop = IsDlgButtonChecked(hDlg,IDC_ALWAYSONTOP); - bActFollowsMouse = IsDlgButtonChecked(hDlg,IDC_ACTFOLLOWSMOUSE); - bAutoSave = IsDlgButtonChecked(hDlg,IDC_AUTOSAVE); - bAutoSaveOnExit = IsDlgButtonChecked(hDlg,IDC_AUTOSAVEONEXIT); - bLoadObjectWarning = IsDlgButtonChecked(hDlg,IDC_OBJECTLOADWARNING); - bAlwaysDisplayLog = IsDlgButtonChecked(hDlg,IDC_ALWAYSDISPLOG); - SetSpeed(bRealSpeed); // set speed - // LCD grayscale checkbox has been changed - if (bGrayscale != (BOOL) IsDlgButtonChecked(hDlg,IDC_GRAYSCALE)) - { - UINT nOldState = SwitchToState(SM_INVALID); - SetLcdMode(!bGrayscale); // set new display mode - SwitchToState(nOldState); - } + if (bPort2CfgChange) // slot2 configuration changed { UINT nOldState = SwitchToState(SM_INVALID); @@ -563,32 +538,83 @@ static INT_PTR CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPA } SwitchToState(nOldState); } - // set disassembler mode - disassembler_mode = IsDlgButtonChecked(hDlg,IDC_DISASM_HP) ? HP_MNEMONICS : CLASS_MNEMONICS; - // set sound data - dwWaveVol = (DWORD) SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_GETPOS,0,0); - bWaveBeep = IsDlgButtonChecked(hDlg,IDC_SOUND_WAVE); - // set combobox parameter - GetDlgItemText(hDlg,IDC_WIRE,szSerialWire,ARRAYSIZEOF(szSerialWire)); - if (cCurrentRomType!='X') // HP49G Ir port is not connected - GetDlgItemText(hDlg,IDC_IR,szSerialIr,ARRAYSIZEOF(szSerialIr)); - // set window Z order - hWndInsertAfter = bAlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST; - SetWindowPos(hWnd,hWndInsertAfter,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE); - if (hDlgDebug != NULL) - { - SetWindowPos(hDlgDebug,hWndInsertAfter,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE); - } - // no break - case IDCANCEL: - EndDialog(hDlg, LOWORD(wParam)); + return TRUE; } break; } return FALSE; - UNREFERENCED_PARAMETER(lParam); } +static BOOL CALLBACK SettingsPeripheralProc(HWND hDlg, UINT uMsg, DWORD wParam, LONG lParam) +{ + TCHAR cPort[8]; + + switch (uMsg) + { + case WM_INITDIALOG: + // set sound slider + SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_SETRANGE,FALSE,MAKELONG(0,255)); + SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_SETTICFREQ,256/8,0); + SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_SETPOS,TRUE,dwWaveVol); + + // set sound radio button + CheckDlgButton(hDlg,bWaveBeep ? IDC_SOUND_WAVE : IDC_SOUND_SPEAKER,BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_SOUND_SLIDER),bWaveBeep); + + // UDP infrared printer settings + SetDlgItemText(hDlg,IDC_IR_ADDR,szUdpServer); + wsprintf(cPort,_T("%u"),wUdpPort); + SetDlgItemText(hDlg,IDC_IR_PORT,cPort); + + // set combobox parameter + SetCommList(hDlg,szSerialWire,szSerialIr); + if (bCommInit) // disable when port open + { + EnableWindow(GetDlgItem(hDlg,IDC_WIRE),FALSE); + EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE); + } + + if (cCurrentRomType=='X') // HP49G + { + SendDlgItemMessage(hDlg,IDC_IR,CB_RESETCONTENT,0,0); + EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE); + } + return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_SOUND_SPEAKER: + EnableWindow(GetDlgItem(hDlg,IDC_SOUND_SLIDER),FALSE); + return TRUE; + case IDC_SOUND_WAVE: + EnableWindow(GetDlgItem(hDlg,IDC_SOUND_SLIDER),TRUE); + return TRUE; + } + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->code) + { + case PSN_KILLACTIVE: + // set sound data + dwWaveVol = (DWORD) SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_GETPOS,0,0); + bWaveBeep = IsDlgButtonChecked(hDlg,IDC_SOUND_WAVE); + // UDP infrared printer settings + GetDlgItemText(hDlg,IDC_IR_ADDR,szUdpServer,ARRAYSIZEOF(szUdpServer)); + GetDlgItemText(hDlg,IDC_IR_PORT,cPort,ARRAYSIZEOF(cPort)); + wUdpPort = (WORD) _ttoi(cPort); + ResetUdp(); // invalidate saved UDP address + // set combobox parameter + GetDlgItemText(hDlg,IDC_WIRE,szSerialWire,ARRAYSIZEOF(szSerialWire)); + if (cCurrentRomType!='X') // HP49G Ir port is not connected + GetDlgItemText(hDlg,IDC_IR,szSerialIr,ARRAYSIZEOF(szSerialIr)); + return TRUE; + } + break; + } + return FALSE; +} + + //################ //# @@ -607,7 +633,7 @@ static UINT SaveChanges(BOOL bAuto) { UINT uReply; - if (pbyRom == NULL) return IDNO; + if (bDocumentAvail == FALSE) return IDNO; if (bAuto) uReply = IDYES; @@ -755,14 +781,50 @@ static LRESULT OnPaint(HWND hWindow) return 0; } +// +// WM_INITMENU +// +static LRESULT OnInitMenu(HMENU hMenu) +{ + // disable stack loading items on HP38G, HP39/40G + BOOL bStackEnable = cCurrentRomType!='6' && cCurrentRomType!='A' && cCurrentRomType!='E'; + BOOL bRun = nState == SM_RUN || nState == SM_SLEEP; + + UINT uStackEnable = (bRun && bStackEnable) ? MF_ENABLED : MF_GRAYED; + UINT uRun = bRun ? MF_ENABLED : MF_GRAYED; + UINT uBackup = bBackup ? MF_ENABLED : MF_GRAYED; + + EnableMenuItem(hMenu,ID_FILE_NEW,MF_ENABLED); + EnableMenuItem(hMenu,ID_FILE_OPEN,MF_ENABLED); + EnableMenuItem(hMenu,ID_FILE_SAVE,(bRun && szCurrentFilename[0]) ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hMenu,ID_FILE_SAVEAS,uRun); + EnableMenuItem(hMenu,ID_FILE_CLOSE,uRun); + EnableMenuItem(hMenu,ID_OBJECT_LOAD,uStackEnable); + EnableMenuItem(hMenu,ID_OBJECT_SAVE,uStackEnable); + EnableMenuItem(hMenu,ID_VIEW_COPY,uRun); + EnableMenuItem(hMenu,ID_STACK_COPY,uStackEnable); + EnableMenuItem(hMenu,ID_STACK_PASTE,uStackEnable); + EnableMenuItem(hMenu,ID_VIEW_RESET,uRun); + EnableMenuItem(hMenu,ID_BACKUP_SAVE,uRun); + EnableMenuItem(hMenu,ID_BACKUP_RESTORE,uBackup); + EnableMenuItem(hMenu,ID_BACKUP_DELETE,uBackup); + EnableMenuItem(hMenu,ID_VIEW_SCRIPT,uRun); + EnableMenuItem(hMenu,ID_TOOL_DISASM,uRun); + EnableMenuItem(hMenu,ID_TOOL_DEBUG,(bRun && nDbgState == DBG_OFF) ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hMenu,ID_TOOL_MACRO_RECORD,(bRun && nMacroState == MACRO_OFF) ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hMenu,ID_TOOL_MACRO_PLAY,(bRun && nMacroState == MACRO_OFF) ? MF_ENABLED : MF_GRAYED); + EnableMenuItem(hMenu,ID_TOOL_MACRO_STOP,(bRun && nMacroState != MACRO_OFF) ? MF_ENABLED : MF_GRAYED); + return 0; +} + // // WM_DROPFILES // -static LRESULT OnDropFiles(HANDLE hFilesInfo) +static LRESULT OnDropFiles(HDROP hFilesInfo) { TCHAR szFileName[MAX_PATH]; WORD wNumFiles,wIndex; - BOOL bSuccess; + BOOL bSuccess = FALSE; // get number of files dropped wNumFiles = DragQueryFile (hFilesInfo,(UINT)-1,NULL,0); @@ -833,7 +895,6 @@ static LRESULT OnFileNew(VOID) SaveBackup(); } if (NewDocument()) SetWindowTitle(_T("Untitled")); - UpdateWindowStatus(); cancel: if (pbyRom) SwitchToState(SM_RUN); return 0; @@ -1028,7 +1089,7 @@ static LRESULT OnViewCopy(VOID) lpbi->biClrImportant = 0; // get bitmap color table and bitmap data GetDIBits(hBmpDC, hBmp, 0, lpbi->biHeight, (LPBYTE)lpbi + dwLen - dwSizeImage, - (LPBITMAPINFO)lpbi, DIB_RGB_COLORS); + (LPBITMAPINFO)lpbi, DIB_RGB_COLORS); GlobalUnlock(hClipObj); SetClipboardData(CF_DIB, hClipObj); @@ -1036,13 +1097,13 @@ static LRESULT OnViewCopy(VOID) GetObject(hPalette,sizeof(WORD),&wBits); // memory allocation for temporary palette data - if ((ppal = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,sizeof(LOGPALETTE) + wBits * sizeof(PALETTEENTRY))) != NULL) + if ((ppal = calloc(sizeof(LOGPALETTE) + wBits * sizeof(PALETTEENTRY),1)) != NULL) { ppal->palVersion = PALVERSION; ppal->palNumEntries = wBits; GetPaletteEntries(hPalette, 0, wBits, ppal->palPalEntry); SetClipboardData(CF_PALETTE, CreatePalette(ppal)); - HeapFree(hHeap,0,ppal); + free(ppal); } } DeleteDC(hBmpDC); @@ -1087,13 +1148,80 @@ static LRESULT OnViewReset(VOID) // // ID_VIEW_SETTINGS // +static INT_PTR CALLBACK PropSheetProc(HWND hwndPropSheet, UINT uMsg, LPARAM lParam) +{ + switch(uMsg) + { + // called before the dialog is created, hwndPropSheet = NULL, lParam points to dialog resource + case PSCB_PRECREATE: + { + LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE) lParam; + if(!(lpTemplate->style & WS_SYSMENU)) + { + lpTemplate->style |= WS_SYSMENU; + } + } + break; + + // called after the dialog is created + case PSCB_INITIALIZED: + break; + } + return 0; + UNREFERENCED_PARAMETER(hwndPropSheet); +} + static LRESULT OnViewSettings(VOID) { + PROPSHEETPAGE psp[3]; + PROPSHEETHEADER psh; + // not in nState = SM_INVALID or port2 file must be closed from document _ASSERT(nState != SM_INVALID || pbyPort2 == NULL); - if (DialogBox(hApp, MAKEINTRESOURCE(IDD_SETTINGS), hWnd, (DLGPROC)SettingsProc) == -1) - AbortMessage(_T("Settings Dialog Creation Error !")); + psp[0].dwSize = sizeof(PROPSHEETPAGE); + psp[0].dwFlags = PSP_DEFAULT; + psp[0].hInstance = hApp; + psp[0].pszTemplate = MAKEINTRESOURCE(IDD_SET_GENERAL); + psp[0].hIcon = NULL; + psp[0].pszTitle = NULL; + psp[0].pfnDlgProc = (DLGPROC) SettingsGeneralProc; + psp[0].lParam = 0; + psp[0].pfnCallback = NULL; + + psp[1].dwSize = sizeof(PROPSHEETPAGE); + psp[1].dwFlags = PSP_DEFAULT; + psp[1].hInstance = hApp; + psp[1].pszTemplate = MAKEINTRESOURCE(IDD_SET_MEMORY); + psp[1].hIcon = NULL; + psp[1].pszTitle = NULL; + psp[1].pfnDlgProc = (DLGPROC) SettingsMemoryProc; + psp[1].lParam = 0; + psp[1].pfnCallback = NULL; + + psp[2].dwSize = sizeof(PROPSHEETPAGE); + psp[2].dwFlags = PSP_DEFAULT; + psp[2].hInstance = hApp; + psp[2].pszTemplate = MAKEINTRESOURCE(IDD_SET_PERIPHERAL); + psp[2].hIcon = NULL; + psp[2].pszTitle = NULL; + psp[2].pfnDlgProc = (DLGPROC) SettingsPeripheralProc; + psp[2].lParam = 0; + psp[2].pfnCallback = NULL; + + psh.dwSize = sizeof(PROPSHEETHEADER); + psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK | PSH_NOAPPLYNOW; + psh.hwndParent = hWnd; + psh.hInstance = hApp; + psh.hIcon = NULL; + psh.pszCaption = _T("Settings"); + psh.nPages = ARRAYSIZEOF(psp); + psh.nStartPage = 0; + psh.ppsp = (LPCPROPSHEETPAGE) &psp; + psh.pfnCallback = (PFNPROPSHEETCALLBACK) PropSheetProc; + + if (PropertySheet(&psh) == -1) + AbortMessage(_T("Settings Property Sheet Creation Error!")); WriteSettings(); return 0; @@ -1104,6 +1232,9 @@ static LRESULT OnViewSettings(VOID) // static LRESULT OnViewScript(VOID) { + TCHAR szKmlFile[MAX_PATH]; + BOOL bKMLChanged,bSucc; + BYTE cType = cCurrentRomType; if (nState != SM_RUN) { @@ -1113,14 +1244,50 @@ static LRESULT OnViewScript(VOID) } SwitchToState(SM_INVALID); + // make a copy of the current KML script file name + _ASSERT(sizeof(szKmlFile) == sizeof(szCurrentKml)); + lstrcpyn(szKmlFile,szCurrentKml,ARRAYSIZEOF(szKmlFile)); + + bKMLChanged = FALSE; // KML script not changed + bSucc = TRUE; // KML script successful loaded + do { - if (!DisplayChooseKml(cType)) break; - } - while (!InitKML(szCurrentKml,FALSE)); + if (!DisplayChooseKml(cType)) // quit with Cancel + { + if (!bKMLChanged) // KML script not changed + break; // exit loop with current loaded KML script - SetWindowPathTitle(szCurrentFilename); // update window title line - if (pbyRom) SwitchToState(SM_RUN); + // restore KML script file name + lstrcpyn(szCurrentKml,szKmlFile,ARRAYSIZEOF(szCurrentKml)); + + // try to restore old KML script + if ((bSucc = InitKML(szCurrentKml,FALSE))) + break; // exit loop with success + + // restoring failed, save document + if (IDCANCEL != SaveChanges(bAutoSave)) + break; // exit loop with no success + + _ASSERT(bSucc == FALSE); // for continuing loop + } + else // quit with Ok + { + bKMLChanged = TRUE; // KML script changed + bSucc = InitKML(szCurrentKml,FALSE); + } + } + while (!bSucc); // retry if KML script is invalid + + if (bSucc) + { + if (pbyRom) SwitchToState(SM_RUN); // continue emulation + } + else + { + ResetDocument(); // close document + SetWindowTitle(NULL); + } return 0; } @@ -1271,58 +1438,74 @@ static INT_PTR CALLBACK Disasm(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP { static DWORD dwAddress,dwAddressMax; + enum MEM_MAPPING eMode; LONG i; DWORD dwNxtAddr; - TCHAR *cpStop,szAddress[256] = _T("0"); + TCHAR szAddress[256] = _T("0"); switch (message) { case WM_INITDIALOG: + VERIFY(SetMemRomType(cCurrentRomType)); // set current model + // set fonts & cursor SendDlgItemMessage(hDlg,IDC_DISASM_MODULE,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); - SendDlgItemMessage(hDlg,IDC_DISASM_MAP,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); - SendDlgItemMessage(hDlg,IDC_DISASM_ROM,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); - SendDlgItemMessage(hDlg,IDC_DISASM_RAM,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); - SendDlgItemMessage(hDlg,IDC_DISASM_PORT1,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); - SendDlgItemMessage(hDlg,IDC_DISASM_PORT2,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); - SendDlgItemMessage(hDlg,IDC_DISASM_MAP,BM_SETCHECK,1,0); + SendDlgItemMessage(hDlg,IDC_DISASM_MODE_TEXT,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDC_DISASM_MODE,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_ADDRESS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_DISASM_ADR,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_DISASM_NEXT,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_DISASM_COPY,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDCANCEL,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + + // fill disassembler mode combo box + { + // disassemble mode window + HWND hWnd = GetDlgItem(hDlg,IDC_DISASM_MODE); + + if (hDlgDebug == NULL) // debugger not open + { + LPCTSTR lpszModes[] = { _T("Map"), _T("NCE1"), _T("NCE2"), _T("CE1"), _T("CE2"), _T("NCE3") }; + + for (eMode = MEM_MMU; eMode <= MEM_NCE3; eMode = (enum MEM_MAPPING) (eMode + 1)) + { + if (GetMemAvail(eMode)) + { + _ASSERT(eMode < ARRAYSIZEOF(lpszModes)); + i = (LONG) SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM) lpszModes[eMode]); + SendMessage(hWnd,CB_SETITEMDATA,i,(LPARAM) eMode); + } + } + VERIFY(SendMessage(hWnd,CB_SETCURSEL,0,0) != LB_ERR); + + // disassemble with mapped modules + VERIFY(SetMemMapType(MEM_MMU)); + } + else // debugger open + { + EnableWindow(hWnd,FALSE); + } + } + SetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress); - disassembler_map = MEM_MAP; // disassemble with mapped modules - dwAddress = _tcstoul(szAddress,&cpStop,16); - dwAddressMax = 0x100000; // greatest address (mapped mode) + dwAddressMax = GetMemDataSize(); + dwAddress = _tcstoul(szAddress,NULL,16); return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { - // decode radio buttons - case IDC_DISASM_MAP: - disassembler_map = MEM_MAP; - dwAddressMax = 0x100000; - return TRUE; - case IDC_DISASM_ROM: - disassembler_map = MEM_ROM; - dwAddressMax = dwRomSize; - return TRUE; - case IDC_DISASM_RAM: - disassembler_map = MEM_RAM; - dwAddressMax = Chipset.Port0Size * 2048; - return TRUE; - case IDC_DISASM_PORT1: - disassembler_map = MEM_PORT1; - dwAddressMax = ((Chipset.cards_status & PORT1_PRESENT) != 0) ? (Chipset.Port1Size * 2048) : 0; - return TRUE; - case IDC_DISASM_PORT2: - disassembler_map = MEM_PORT2; - dwAddressMax = ((cCurrentRomType=='E' || cCurrentRomType=='X') - ? Chipset.Port2Size - : dwPort2Size) - * 2048; - return TRUE; + // decode memory mode combo box + case IDC_DISASM_MODE: + // new combo box item selected + if (HIWORD(wParam) == CBN_SELENDOK) + { + HWND hWnd = GetDlgItem(hDlg,IDC_DISASM_MODE); + i = (LONG) SendMessage(hWnd,CB_GETCURSEL,0,0); + eMode = (enum MEM_MAPPING) SendMessage(hWnd,CB_GETITEMDATA,i,0); + VERIFY(SetMemMapType(eMode)); + dwAddressMax = GetMemDataSize(); + } + break; case IDOK: SendDlgItemMessage(hDlg,IDC_DISASM_ADR,EM_SETSEL,0,-1); GetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress,ARRAYSIZEOF(szAddress)); @@ -1332,7 +1515,7 @@ static INT_PTR CALLBACK Disasm(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP if (_istxdigit(szAddress[i]) == FALSE) return FALSE; } - dwAddress = _tcstoul(szAddress,&cpStop,16); + dwAddress = _tcstoul(szAddress,NULL,16); // no break case IDC_DISASM_NEXT: if (dwAddress >= dwAddressMax) @@ -1403,7 +1586,7 @@ static LRESULT OnToolDisasm(VOID) // disasm dialogbox call { if (pbyRom) SwitchToState(SM_SLEEP); if (DialogBox(hApp, MAKEINTRESOURCE(IDD_DISASM), hWnd, (DLGPROC)Disasm) == -1) - AbortMessage(_T("Disassembler Dialog Box Creation Error !")); + AbortMessage(_T("Disassembler Dialog Box Creation Error!")); if (pbyRom) SwitchToState(SM_RUN); return 0; } @@ -1411,7 +1594,7 @@ static LRESULT OnToolDisasm(VOID) // disasm dialogbox call static LRESULT OnAbout(VOID) { if (DialogBox(hApp, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)About) == -1) - AbortMessage(_T("About Dialog Box Creation Error !")); + AbortMessage(_T("About Dialog Box Creation Error!")); return 0; } @@ -1479,7 +1662,8 @@ LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lPar case WM_CREATE: return OnCreate(hWindow); case WM_DESTROY: return OnDestroy(hWindow); case WM_PAINT: return OnPaint(hWindow); - case WM_DROPFILES: return OnDropFiles((HANDLE)wParam); + case WM_INITMENU: return OnInitMenu((HMENU) wParam); + case WM_DROPFILES: return OnDropFiles((HDROP) wParam); case WM_ACTIVATE: if (LOWORD(wParam)==WA_INACTIVE) break; case WM_QUERYNEWPALETTE: @@ -1557,12 +1741,16 @@ LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lPar int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { + typedef DWORD (WINAPI *LPFN_STIP)(HANDLE hThread,DWORD dwIdealProcessor); + MSG msg; WNDCLASS wc; + ATOM classAtom; RECT rectWindow; HACCEL hAccel; + LPFN_STIP fnSetThreadIdealProcessor; + DWORD dwProcessor; HSZ hszService, hszTopic; // variables for DDE server - DWORD_PTR dwAffMask; LPTSTR lpFilePart; hApp = hInst; @@ -1577,13 +1765,6 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC } #endif - hHeap = GetProcessHeap(); - if (hHeap == NULL) - { - AbortMessage(_T("Heap creation failed.")); - return FALSE; - } - wc.style = CS_BYTEALIGNCLIENT; wc.lpfnWndProc = (WNDPROC)MainWndProc; wc.cbClsExtra = 0; @@ -1595,7 +1776,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU); wc.lpszClassName = _T("CEmu48"); - if (!RegisterClass(&wc)) + if (!(classAtom = RegisterClass(&wc))) { AbortMessage( _T("CEmu48 class registration failed.\n") @@ -1603,6 +1784,21 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC return FALSE; } + // read emulator settings + GetCurrentDirectory(ARRAYSIZEOF(szCurrentDirectory),szCurrentDirectory); + ReadSettings(); + + // running an instance of me? + if (bSingleInstance && (hWnd = FindWindow(MAKEINTATOM(classAtom),NULL)) != NULL) + { + if (IsIconic(hWnd)) // window minimized + ShowWindow(hWnd,SW_RESTORE); // show window + + // put the window into foreground + ForceForegroundWindow(GetLastActivePopup(hWnd)); + return 0; // quit + } + // Create window rectWindow.left = 0; rectWindow.top = 0; @@ -1610,13 +1806,12 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC rectWindow.bottom = 0; AdjustWindowRect(&rectWindow, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, TRUE); - hWnd = CreateWindow(_T("CEmu48"), _T("Emu48"), + hWnd = CreateWindow(MAKEINTATOM(classAtom),_T("Emu48"), WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, CW_USEDEFAULT, CW_USEDEFAULT, rectWindow.right - rectWindow.left, rectWindow.bottom - rectWindow.top, - NULL,NULL,hApp,NULL - ); + NULL,NULL,hApp,NULL); if (hWnd == NULL) { @@ -1630,13 +1825,10 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC QueryPerformanceFrequency(&lFreq); // init high resolution counter QueryPerformanceCounter(&lAppStart); - GetCurrentDirectory(ARRAYSIZEOF(szCurrentDirectory), szCurrentDirectory); szCurrentKml[0] = 0; // no KML file selected - ReadSettings(); + SetSpeed(bRealSpeed); // set speed MruInit(4); // init MRU entries - UpdateWindowStatus(); - // create auto event handle hEventShutdn = CreateEvent(NULL,FALSE,FALSE,NULL); if (hEventShutdn == NULL) @@ -1656,17 +1848,26 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC DestroyWindow(hWnd); return FALSE; } + + // SetThreadIdealProcessor() is available since Windows NT4.0 + fnSetThreadIdealProcessor = (LPFN_STIP) GetProcAddress(GetModuleHandle(_T("kernel32")), + "SetThreadIdealProcessor"); + + // bind Saturn CPU emulation thread to current ideal processor + dwProcessor = (fnSetThreadIdealProcessor != NULL) // running on NT4.0 or later + ? fnSetThreadIdealProcessor(hThread,MAXIMUM_PROCESSORS) // get ideal processor no. + : 0; // select 1st processor + // on multiprocessor machines for QueryPerformanceCounter() - dwAffMask = SetThreadAffinityMask(hThread,1); - _ASSERT(dwAffMask != 0); + VERIFY(SetThreadAffinityMask(hThread,(DWORD_PTR) (1 << dwProcessor))); ResumeThread(hThread); // start thread while (nState!=nNextState) Sleep(0); // wait for thread initialized idDdeInst = 0; // initialize DDE server if (DdeInitialize(&idDdeInst,(PFNCALLBACK) &DdeCallback, - APPCLASS_STANDARD | - CBF_FAIL_EXECUTES | CBF_FAIL_ADVISES | - CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS,0)) + APPCLASS_STANDARD | + CBF_FAIL_EXECUTES | CBF_FAIL_ADVISES | + CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS,0)) { TerminateThread(hThread, 0); // kill emulation thread CloseHandle(hEventShutdn); // close event handle @@ -1720,9 +1921,9 @@ start: { if ( !TranslateAccelerator(hWnd, hAccel, &msg) && (hDlgDebug == NULL || !IsDialogMessage(hDlgDebug, &msg)) - && (hDlgFind == NULL || !IsDialogMessage(hDlgFind, &msg)) + && (hDlgFind == NULL || !IsDialogMessage(hDlgFind, &msg)) && (hDlgProfile == NULL || !IsDialogMessage(hDlgProfile, &msg)) - && (hDlgRplObjView == NULL || !IsDialogMessage(hDlgRplObjView, &msg))) + && (hDlgRplObjView == NULL || !IsDialogMessage(hDlgRplObjView, &msg))) { TranslateMessage(&msg); DispatchMessage(&msg); @@ -1753,6 +1954,7 @@ start: _ASSERT(pKml == NULL); // KML script not closed _ASSERT(szTitle == NULL); // freed allocated memory _ASSERT(hPalette == NULL); // freed resource memory + _CrtDumpMemoryLeaks(); // show memory leaks return (int) msg.wParam; UNREFERENCED_PARAMETER(lpCmdLine); diff --git a/Sources/Emu48/EMU48.DSP b/Sources/Emu48/EMU48.DSP index fe38c25..11ac5a7 100644 --- a/Sources/Emu48/EMU48.DSP +++ b/Sources/Emu48/EMU48.DSP @@ -7,21 +7,21 @@ CFG=Emu48 - Win32 Release !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "Emu48.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "Emu48.mak" CFG="Emu48 - Win32 Release" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE !MESSAGE "Emu48 - Win32 Release" (based on "Win32 (x86) Application") !MESSAGE "Emu48 - Win32 Debug" (based on "Win32 (x86) Application") !MESSAGE "Emu48 - Win32 Release Unicode" (based on "Win32 (x86) Application") !MESSAGE "Emu48 - Win32 Debug Unicode" (based on "Win32 (x86) Application") -!MESSAGE +!MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 @@ -48,14 +48,14 @@ RSC=rc.exe # ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "REGISTRY" /Yu"pch.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x40c /d "NDEBUG" -# ADD RSC /l 0x40c /d "NDEBUG" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib ws2_32.lib /nologo /subsystem:windows /machine:I386 !ELSEIF "$(CFG)" == "Emu48 - Win32 Debug" @@ -74,14 +74,14 @@ LINK32=link.exe # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "REGISTRY" /FR /Yu"pch.h" /FD /c # ADD BASE MTL /nologo /D "_DEBUG" /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x40c /d "_DEBUG" -# ADD RSC /l 0x40c /d "_DEBUG" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib ws2_32.lib /nologo /subsystem:windows /debug /machine:I386 !ELSEIF "$(CFG)" == "Emu48 - Win32 Release Unicode" @@ -101,14 +101,14 @@ LINK32=link.exe # ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "REGISTRY" /Yu"pch.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x40c /d "NDEBUG" -# ADD RSC /l 0x40c /d "NDEBUG" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib ws2_32.lib /nologo /subsystem:windows /machine:I386 !ELSEIF "$(CFG)" == "Emu48 - Win32 Debug Unicode" @@ -128,16 +128,17 @@ LINK32=link.exe # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "REGISTRY" /FR /Yu"pch.h" /FD /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x40c /d "_DEBUG" -# ADD RSC /l 0x40c /d "_DEBUG" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +# SUBTRACT RSC /x BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib ws2_32.lib /nologo /subsystem:windows /debug /machine:I386 -!ENDIF +!ENDIF # Begin Target @@ -166,6 +167,10 @@ SOURCE=.\disasm.c # End Source File # Begin Source File +SOURCE=.\dismem.c +# End Source File +# Begin Source File + SOURCE=.\display.c # End Source File # Begin Source File @@ -235,6 +240,10 @@ SOURCE=.\pch.c # End Source File # Begin Source File +SOURCE=.\redeye.c +# End Source File +# Begin Source File + SOURCE=.\rpl.c # End Source File # Begin Source File @@ -257,6 +266,10 @@ SOURCE=.\symbfile.c SOURCE=.\timer.c # End Source File +# Begin Source File + +SOURCE=.\udp.c +# End Source File # End Group # Begin Group "Header Files" diff --git a/Sources/Emu48/EMU48.H b/Sources/Emu48/EMU48.H index 4a0a6a0..b53fbba 100644 --- a/Sources/Emu48/EMU48.H +++ b/Sources/Emu48/EMU48.H @@ -35,24 +35,18 @@ #define SM_RETURN 2 #define SM_SLEEP 3 -#define S_ERR_NO 0 // stack errorcodes +#define S_ERR_NO 0 // stack errorcodes #define S_ERR_OBJECT 1 -#define S_ERR_BINARY 2 -#define S_ERR_ASCII 3 +#define S_ERR_BINARY 2 +#define S_ERR_ASCII 3 #define BAD_OB (0xFFFFFFFF) // bad object -#define NO_SERIAL "disabled" // port not open +#define NO_SERIAL "disabled" // port not open #define HP_MNEMONICS FALSE // disassembler mnenomics mode #define CLASS_MNEMONICS TRUE -#define MEM_MAP 0 // memory module definition -#define MEM_ROM 1 -#define MEM_RAM 2 -#define MEM_PORT1 3 -#define MEM_PORT2 4 - #define MACRO_OFF 0 // macro recorder off #define MACRO_NEW 1 #define MACRO_PLAY 2 @@ -62,12 +56,17 @@ #define DISP_MENUE 0x04 #define DISP_ANNUN 0x08 +#define ROMPAGESIZE (1<<12) // ROM dirty page size in nibbles + // macro to check for valid calculator model #define isModelValid(m) (m != 0 && strchr(MODELS,m) != NULL) // values for mapping area enum MMUMAP { M_IO, M_ROM, M_RAM, M_P1, M_P2, M_BS }; +// values for disassembler memory mapping modes +enum MEM_MAPPING { MEM_MMU, MEM_NCE1, MEM_NCE2, MEM_CE1, MEM_CE2, MEM_NCE3 }; + // Emu48.c extern HPALETTE hPalette; extern HPALETTE hOldPalette; @@ -90,7 +89,6 @@ extern LARGE_INTEGER lFreq; extern LARGE_INTEGER lAppStart; extern DWORD idDdeInst; extern UINT uCF_HpObj; -extern HANDLE hHeap; extern HINSTANCE hApp; extern HWND hWnd; extern HWND hDlgDebug; @@ -109,11 +107,11 @@ extern BOOL bAlwaysDisplayLog; extern BOOL bLoadObjectWarning; extern BOOL bAlwaysOnTop; extern BOOL bActFollowsMouse; +extern BOOL bSingleInstance; extern HANDLE hThread; extern DWORD lThreadId; extern VOID SetWindowTitle(LPCTSTR szString); extern VOID CopyItemsToClipboard(HWND hWnd); -extern VOID UpdateWindowStatus(VOID); extern VOID ForceForegroundWindow(HWND hWnd); // mru.c @@ -174,6 +172,7 @@ extern UINT nState; extern UINT nNextState; extern BOOL bRealSpeed; extern BOOL bKeySlow; +extern UINT nOpcSlow; extern BOOL bCommInit; extern CHIPSET Chipset; extern TCHAR szSerialWire[16]; @@ -198,6 +197,7 @@ extern WORD wInstrRp; extern VOID SuspendDebugger(VOID); extern VOID ResumeDebugger(VOID); extern VOID CheckSerial(VOID); +extern VOID InitAdjustSpeed(VOID); extern VOID AdjKeySpeed(VOID); extern VOID SetSpeed(BOOL bAdjust); extern VOID UpdateKdnBit(VOID); @@ -217,6 +217,7 @@ extern TCHAR szCurrentFilename[MAX_PATH]; extern TCHAR szBackupFilename[MAX_PATH]; extern TCHAR szBufferFilename[MAX_PATH]; extern TCHAR szPort2Filename[MAX_PATH]; +extern BOOL bDocumentAvail; extern BYTE cCurrentRomType; extern UINT nCurrentClass; extern LPBYTE Port0; @@ -225,6 +226,8 @@ extern LPBYTE Port2; extern LPBYTE pbyRom; extern BOOL bRomWriteable; extern DWORD dwRomSize; +extern LPBYTE pbyRomDirtyPage; +extern DWORD dwRomDirtyPageSize; extern WORD wRomCrc; extern LPBYTE pbyPort2; extern BOOL bPort2Writeable; @@ -309,12 +312,22 @@ extern VOID KeyboardEvent(BOOL bPress, UINT out, UINT in); extern INT nMacroState; extern INT nMacroTimeout; extern BOOL bMacroRealSpeed; +extern DWORD dwMacroMinDelay; extern VOID KeyMacroRecord(BOOL bPress, UINT out, UINT in); extern LRESULT OnToolMacroNew(VOID); extern LRESULT OnToolMacroPlay(VOID); extern LRESULT OnToolMacroStop(VOID); extern LRESULT OnToolMacroSettings(VOID); +// Redeye.c +extern VOID IrPrinter(BYTE c); + +// Udp.c +extern TCHAR szUdpServer[1024]; +extern WORD wUdpPort; +extern VOID ResetUdp(VOID); +extern BOOL SendByteUdp(BYTE byData); + // Stack.c extern BOOL bDetectClpObject; extern LRESULT OnStackCopy(VOID); @@ -339,11 +352,19 @@ extern VOID RCKBp(CHIPSET* w); // DDEserv.c extern HDDEDATA CALLBACK DdeCallback(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, DWORD, DWORD); +// Dismem.c +extern BOOL SetMemRomType(BYTE cCurrentRomType); +extern BOOL SetMemMapType(enum MEM_MAPPING eType); +extern enum MEM_MAPPING GetMemMapType(VOID); +extern BOOL GetMemAvail(enum MEM_MAPPING eType); +extern DWORD GetMemDataSize(VOID); +extern DWORD GetMemDataMask(VOID); +extern BYTE GetMemNib(DWORD *p); +extern VOID GetMemPeek(BYTE *a, DWORD d, UINT s); + // Disasm.c extern BOOL disassembler_mode; extern BOOL disassembler_symb; -extern WORD disassembler_map; -extern BYTE read_nibble(DWORD *p); extern DWORD disassemble(DWORD addr, LPTSTR out); // Symbfile.c @@ -385,7 +406,7 @@ static __inline int YesNoCancelMessage(LPCTSTR szMessage,UINT uStyle) {return Me static __inline LPTSTR DuplicateString(LPCTSTR szString) { UINT uLength = lstrlen(szString) + 1; - LPTSTR szDup = HeapAlloc(hHeap,0,uLength*sizeof(szDup[0])); + LPTSTR szDup = malloc(uLength*sizeof(szDup[0])); lstrcpy(szDup,szString); return szDup; } diff --git a/Sources/Emu48/EMU48.RC b/Sources/Emu48/EMU48.RC index e36e8f8..e67e8c1 100644 --- a/Sources/Emu48/EMU48.RC +++ b/Sources/Emu48/EMU48.RC @@ -77,12 +77,40 @@ BEGIN BOTTOMMARGIN, 145 END - IDD_SETTINGS, DIALOG + IDD_SET_GENERAL, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 160 - TOPMARGIN, 4 - BOTTOMMARGIN, 280 + RIGHTMARGIN, 244 + VERTGUIDE, 14 + VERTGUIDE, 161 + VERTGUIDE, 168 + VERTGUIDE, 237 + TOPMARGIN, 7 + BOTTOMMARGIN, 127 + END + + IDD_SET_MEMORY, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 244 + VERTGUIDE, 14 + VERTGUIDE, 237 + TOPMARGIN, 7 + BOTTOMMARGIN, 127 + END + + IDD_SET_PERIPHERAL, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 244 + VERTGUIDE, 14 + VERTGUIDE, 147 + VERTGUIDE, 154 + VERTGUIDE, 161 + VERTGUIDE, 237 + TOPMARGIN, 7 + BOTTOMMARGIN, 127 + HORZGUIDE, 82 END IDD_CHOOSEKML, DIALOG @@ -157,6 +185,22 @@ BEGIN BOTTOMMARGIN, 74 END + IDD_DEBUG_MEMSAVE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 257 + TOPMARGIN, 7 + BOTTOMMARGIN, 58 + END + + IDD_DEBUG_MEMLOAD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 257 + TOPMARGIN, 7 + BOTTOMMARGIN, 58 + END + IDD_DEBUG_SETTINGS, DIALOG BEGIN LEFTMARGIN, 7 @@ -252,69 +296,88 @@ FONT 8, "MS Sans Serif" BEGIN ICON IDI_EMU48,IDC_STATIC,7,6,20,20,SS_REALSIZEIMAGE LTEXT "",IDC_VERSION,29,6,151,8,NOT WS_GROUP - LTEXT "Copyright © 2010 Christoph Gießelink && Sébastien Carlier", + LTEXT "Copyright © 2012 Christoph Gießelink && Sébastien Carlier", IDC_STATIC,29,18,181,8 DEFPUSHBUTTON "OK",IDOK,215,12,39,14 EDITTEXT IDC_LICENSE,7,33,247,112,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY END -IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 167, 287 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Settings" +IDD_SET_GENERAL DIALOG DISCARDABLE 0, 0, 251, 134 +STYLE WS_CHILD | WS_VISIBLE | WS_CAPTION +CAPTION "General" FONT 8, "MS Sans Serif" BEGIN CONTROL "Authentic Calculator Speed",IDC_REALSPEED,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,13,100,10 + BS_AUTOCHECKBOX | WS_TABSTOP,14,17,133,10 CONTROL "Enable Virtual LCD Delay",IDC_GRAYSCALE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,25,100,10 - CONTROL "Always On Top",IDC_ALWAYSONTOP,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,37,65,10 - CONTROL "Activation Follows Mouse",IDC_ACTFOLLOWSMOUSE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,49,100,10 + BS_AUTOCHECKBOX | WS_TABSTOP,14,28,133,10 + CONTROL "Always On Top",IDC_ALWAYSONTOP,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,40,133,10 + CONTROL "Activation Follows Mouse",IDC_ACTFOLLOWSMOUSE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,14,52,133,10 + CONTROL "Single Instance",IDC_SINGLEINSTANCE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,14,64,133,10 CONTROL "Automatically Save Files",IDC_AUTOSAVE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,61,89,10 + BS_AUTOCHECKBOX | WS_TABSTOP,14,76,133,10 CONTROL "Automatically Save Files On Exit",IDC_AUTOSAVEONEXIT, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,73,114,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,88,133,10 CONTROL "Show Load Object Warning",IDC_OBJECTLOADWARNING,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,85,102,10 + BS_AUTOCHECKBOX | WS_TABSTOP,14,100,133,10 CONTROL "Always Show KML Compilation Result",IDC_ALWAYSDISPLOG, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,97,133,10 - GROUPBOX "General",IDC_STATIC,7,4,153,107 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,112,133,10 + GROUPBOX "General",IDC_STATIC,7,7,148,120 CONTROL "HP Mnemonics",IDC_DISASM_HP,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,13,125,65,11 + WS_GROUP | WS_TABSTOP,168,21,69,11 CONTROL "Class Mnemonics",IDC_DISASM_CLASS,"Button", - BS_AUTORADIOBUTTON,84,125,70,11 - GROUPBOX "Disassembler",IDC_STATIC,7,114,153,28 - LTEXT "Volume",IDC_STATIC,13,158,24,8 - CONTROL "Slider1",IDC_SOUND_SLIDER,"msctls_trackbar32", - TBS_AUTOTICKS | WS_TABSTOP,39,153,68,18 - CONTROL "Speaker",IDC_SOUND_SPEAKER,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,111,152,43,10 - CONTROL "Wave",IDC_SOUND_WAVE,"Button",BS_AUTORADIOBUTTON,111, - 163,43,10 - GROUPBOX "Sound",IDC_STATIC,7,144,153,34 + BS_AUTORADIOBUTTON,168,35,69,11 + GROUPBOX "Disassembler",IDC_STATIC,161,7,83,120 +END + +IDD_SET_MEMORY DIALOG DISCARDABLE 0, 0, 251, 134 +STYLE WS_CHILD | WS_VISIBLE | WS_CAPTION +CAPTION "Memory" +FONT 8, "MS Sans Serif" +BEGIN CONTROL "Port 1 is Plugged",IDC_PORT1EN,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,13,189,67,10 + WS_TABSTOP,14,20,67,10 CONTROL "Port 1 is Writeable",IDC_PORT1WR,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,84,189,69,10 + BS_AUTOCHECKBOX | WS_TABSTOP,124,20,69,10 CONTROL "Port 2 is Shared",IDC_PORT2ISSHARED,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,201,65,10 + BS_AUTOCHECKBOX | WS_TABSTOP,14,32,65,10 CONTROL "Port 2 is Writeable",IDC_PORT2WR,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,84,201,69,10 - LTEXT "Port 2 File :",IDC_STATIC,13,216,37,8 - EDITTEXT IDC_PORT2,51,214,94,12,ES_AUTOHSCROLL - PUSHBUTTON "...",IDC_PORT2LOAD,145,214,10,12 - GROUPBOX "Memory Cards",IDC_STATIC,7,180,153,51 - LTEXT "Wire:",IDC_STATIC,13,245,17,8 - COMBOBOX IDC_WIRE,31,243,48,42,CBS_DROPDOWNLIST | WS_VSCROLL | + BS_AUTOCHECKBOX | WS_TABSTOP,124,32,69,10 + LTEXT "Port 2 File :",IDC_STATIC,14,47,37,8 + EDITTEXT IDC_PORT2,52,45,175,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_PORT2LOAD,227,45,10,12 + GROUPBOX "Memory Cards",IDC_STATIC,7,7,237,58 +END + +IDD_SET_PERIPHERAL DIALOG DISCARDABLE 0, 0, 251, 134 +STYLE WS_CHILD | WS_VISIBLE | WS_CAPTION +CAPTION "Peripheral" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Volume",IDC_STATIC,14,21,24,8 + CONTROL "Slider1",IDC_SOUND_SLIDER,"msctls_trackbar32", + TBS_AUTOTICKS | WS_TABSTOP,40,16,84,18 + CONTROL "Speaker",IDC_SOUND_SPEAKER,"Button",BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP,135,20,43,10 + CONTROL "Wave",IDC_SOUND_WAVE,"Button",BS_AUTORADIOBUTTON,194,20, + 43,10 + GROUPBOX "Sound",IDC_STATIC,7,7,237,34 + LTEXT "IP Address:",IDC_STATIC,14,60,37,8 + LTEXT "Port:",IDC_STATIC,119,60,16,8 + EDITTEXT IDC_IR_ADDR,14,70,101,12,ES_AUTOHSCROLL + EDITTEXT IDC_IR_PORT,119,70,28,12,ES_NUMBER + GROUPBOX "Infrared Printer",IDC_STATIC,7,43,147,50 + LTEXT "Wire:",IDC_STATIC,168,58,17,8 + COMBOBOX IDC_WIRE,189,56,48,42,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "IR:",IDC_STATIC,89,245,9,8 - COMBOBOX IDC_IR,107,243,48,43,CBS_DROPDOWNLIST | WS_VSCROLL | + LTEXT "IR:",IDC_STATIC,168,74,9,8 + COMBOBOX IDC_IR,189,72,48,43,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - GROUPBOX "Serial Ports",IDC_STATIC,7,233,153,27 - DEFPUSHBUTTON "OK",IDOK,9,266,50,14 - PUSHBUTTON "Cancel",IDCANCEL,107,266,50,14 + GROUPBOX "Serial Ports",IDC_STATIC,161,43,83,50 END IDD_CHOOSEKML DIALOG DISCARDABLE 0, 0, 195, 66 @@ -362,19 +425,12 @@ BEGIN PUSHBUTTON "&Next Address",IDC_DISASM_NEXT,99,144,47,14 PUSHBUTTON "&Copy Data",IDC_DISASM_COPY,150,144,47,14 PUSHBUTTON "Cancel",IDCANCEL,201,144,47,14 + LTEXT "Mapping Mode:",IDC_DISASM_MODE_TEXT,12,17,45,8 + COMBOBOX IDC_DISASM_MODE,60,14,35,90,CBS_DROPDOWNLIST | + WS_TABSTOP GROUPBOX "Module",IDC_DISASM_MODULE,7,5,241,26 - CONTROL "Map",IDC_DISASM_MAP,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,14,16,37,10 - CONTROL "ROM",IDC_DISASM_ROM,"Button",BS_AUTORADIOBUTTON,61,16, - 37,10 - CONTROL "RAM",IDC_DISASM_RAM,"Button",BS_AUTORADIOBUTTON,108,16, - 37,10 - CONTROL "Port 1",IDC_DISASM_PORT1,"Button",BS_AUTORADIOBUTTON, - 155,16,37,10 - CONTROL "Port 2",IDC_DISASM_PORT2,"Button",BS_AUTORADIOBUTTON, - 202,16,37,10 - LISTBOX IDC_DISASM_WIN,7,37,241,100,NOT LBS_NOTIFY | - LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL | + LISTBOX IDC_DISASM_WIN,7,37,241,100,NOT LBS_NOTIFY | + LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP END @@ -543,6 +599,36 @@ BEGIN PUSHBUTTON "Cancel",IDCANCEL,93,60,50,14 END +IDD_DEBUG_MEMSAVE DIALOG DISCARDABLE 0, 0, 264, 65 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Save Memory Data" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "File:",IDC_STATIC,7,10,14,8 + EDITTEXT IDC_DEBUG_DATA_FILE,25,7,181,14,ES_AUTOHSCROLL + PUSHBUTTON "Browse",IDC_DEBUG_DATA_BUT,207,7,50,14 + LTEXT "Start Address (hexadecimal):",IDC_STATIC,7,30,90,8 + EDITTEXT IDC_DEBUG_DATA_STARTADDR,101,27,37,14 + LTEXT "End Address (hexadecimal):",IDC_STATIC,7,46,88,8 + EDITTEXT IDC_DEBUG_DATA_ENDADDR,101,44,37,14 + PUSHBUTTON "OK",IDOK,207,27,50,14 + PUSHBUTTON "Cancel",IDCANCEL,207,44,50,14 +END + +IDD_DEBUG_MEMLOAD DIALOG DISCARDABLE 0, 0, 264, 65 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Memory Data" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "File:",IDC_STATIC,7,10,14,8 + EDITTEXT IDC_DEBUG_DATA_FILE,25,7,181,14,ES_AUTOHSCROLL + PUSHBUTTON "Browse",IDC_DEBUG_DATA_BUT,207,7,50,14 + LTEXT "Start Address (hexadecimal):",IDC_STATIC,7,30,90,8 + EDITTEXT IDC_DEBUG_DATA_STARTADDR,101,27,37,14 + PUSHBUTTON "OK",IDOK,207,27,50,14 + PUSHBUTTON "Cancel",IDCANCEL,207,44,50,14 +END + IDD_DEBUG_SETTINGS DIALOG DISCARDABLE 0, 0, 184, 116 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Debugger Settings" @@ -602,8 +688,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,5,0,0 - PRODUCTVERSION 1,5,0,0 + FILEVERSION 1,5,3,0 + PRODUCTVERSION 1,5,3,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -620,12 +706,12 @@ BEGIN BEGIN VALUE "CompanyName", "Christoph Gießelink & Sebastien Carlier\0" VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0" - VALUE "FileVersion", "1, 5, 0, 0\0" + VALUE "FileVersion", "1, 5, 3, 0\0" VALUE "InternalName", "Emu48\0" - VALUE "LegalCopyright", "Copyright © 2010\0" + VALUE "LegalCopyright", "Copyright © 2012\0" VALUE "OriginalFilename", "Emu48.exe\0" VALUE "ProductName", "Emu48\0" - VALUE "ProductVersion", "1, 5, 0, 0\0" + VALUE "ProductVersion", "1, 5, 3, 0\0" END END BLOCK "VarFileInfo" @@ -791,6 +877,9 @@ BEGIN , GRAYED END MENUITEM SEPARATOR + MENUITEM "&Load Memory Data...", ID_DEBUG_MEM_LOAD + MENUITEM "S&ave Memory Data...", ID_DEBUG_MEM_SAVE + MENUITEM SEPARATOR MENUITEM "&RPL Object Viewer...", ID_DEBUG_MEM_RPLVIEW END END diff --git a/Sources/Emu48/ENGINE.C b/Sources/Emu48/ENGINE.C index b88b2d0..44a0367 100644 --- a/Sources/Emu48/ENGINE.C +++ b/Sources/Emu48/ENGINE.C @@ -19,6 +19,7 @@ UINT nState = SM_INVALID; UINT nNextState = SM_RUN; BOOL bRealSpeed = FALSE; BOOL bKeySlow = FALSE; // slow down for key emulation +UINT nOpcSlow = 0; // no. of opcodes to slow down BOOL bCommInit = FALSE; // COM port not open CHIPSET Chipset; @@ -275,7 +276,7 @@ static __inline VOID CheckDisp(BOOL bSync) static __inline VOID AdjustSpeed(VOID) // adjust emulation speed { - if (bCpuSlow || bKeySlow) // emulation slow down + if (bCpuSlow || bKeySlow || nOpcSlow > 0) // emulation slow down { DWORD dwCycles,dwTicks; @@ -298,6 +299,8 @@ static __inline VOID AdjustSpeed(VOID) // adjust emulation speed dwOldCyc += T2CYCLES; // adjust cycles reference dwSpeedRef += dwTickRef; // adjust reference time } + + if (nOpcSlow > 0) --nOpcSlow; // decr. slow down opcode counter } LeaveCriticalSection(&csSlowLock); } @@ -321,26 +324,34 @@ VOID CheckSerial(VOID) return; } +VOID InitAdjustSpeed(VOID) +{ + // slow down function not initalized + if (!bCpuSlow && !bKeySlow && nOpcSlow == 0) + { + LARGE_INTEGER lTime; // sample timer ticks + // save reference cycles + dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); + QueryPerformanceCounter(&lTime); // get timer ticks + dwSpeedRef = lTime.LowPart; // save reference time + } + return; +} + VOID AdjKeySpeed(VOID) // slow down key repeat { WORD i; BOOL bKey; - if (bCpuSlow) return; // no need to slow down - bKey = FALSE; // search for a pressed key for (i = 0;i < ARRAYSIZEOF(Chipset.Keyboard_Row) && !bKey;++i) bKey = (Chipset.Keyboard_Row[i] != 0); EnterCriticalSection(&csSlowLock); { - if (!bKeySlow && bKey) // key pressed, init variables + if (bKey) // key pressed { - LARGE_INTEGER lTime; // sample timer ticks - // save reference cycles - dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); - QueryPerformanceCounter(&lTime); // get timer ticks - dwSpeedRef = lTime.LowPart; // save reference time + InitAdjustSpeed(); // init variables if necessary } bKeySlow = bKey; // save new state } @@ -354,11 +365,7 @@ VOID SetSpeed(BOOL bAdjust) // set emulation speed { if (bAdjust) // switch to real speed { - LARGE_INTEGER lTime; // sample timer ticks - // save reference cycles - dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); - QueryPerformanceCounter(&lTime); // get timer ticks - dwSpeedRef = lTime.LowPart; // save reference time + InitAdjustSpeed(); // init variables if necessary } bCpuSlow = bAdjust; // save emulation speed } @@ -412,7 +419,6 @@ UINT SwitchToState(UINT nNewState) bInterrupt = TRUE; SuspendDebugger(); // suspend debugger while (nState!=nNextState) Sleep(0); - UpdateWindowStatus(); break; case SM_RETURN: // -> Return DisableDebugger(); // disable debugger @@ -425,7 +431,6 @@ UINT SwitchToState(UINT nNewState) nNextState = SM_RETURN; SetEvent(hEventShutdn); WaitForSingleObject(hThread,INFINITE); - UpdateWindowStatus(); break; case SM_SLEEP: // -> Sleep nNextState = SM_SLEEP; @@ -449,7 +454,6 @@ UINT SwitchToState(UINT nNewState) ResumeDebugger(); SetEvent(hEventShutdn); while (nState!=nNextState) Sleep(0); - UpdateWindowStatus(); break; case SM_RETURN: // -> Return DisableDebugger(); // disable debugger @@ -461,7 +465,6 @@ UINT SwitchToState(UINT nNewState) nNextState = SM_SLEEP; SetEvent(hEventShutdn); while (nState!=nNextState) Sleep(0); - UpdateWindowStatus(); break; } break; @@ -479,7 +482,6 @@ UINT SwitchToState(UINT nNewState) nNextState = SM_INVALID; SetEvent(hEventShutdn); while (nState!=nNextState) Sleep(0); - UpdateWindowStatus(); break; case SM_RETURN: // -> Return DisableDebugger(); // disable debugger @@ -489,7 +491,6 @@ UINT SwitchToState(UINT nNewState) nNextState = SM_RETURN; SetEvent(hEventShutdn); WaitForSingleObject(hThread,INFINITE); - UpdateWindowStatus(); break; } break; @@ -603,6 +604,7 @@ loop: dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); QueryPerformanceCounter(&lDummyInt); dwSpeedRef = lDummyInt.LowPart; + nOpcSlow = 0; // no opcodes to slow down } } if (Chipset.SoftInt) diff --git a/Sources/Emu48/EXTERNAL.C b/Sources/Emu48/EXTERNAL.C index 3021716..af00234 100644 --- a/Sources/Emu48/EXTERNAL.C +++ b/Sources/Emu48/EXTERNAL.C @@ -66,7 +66,7 @@ static __inline VOID BeepWave(DWORD dwFrequency,DWORD dwDuration) // (samp/sec) * msecs * (secs/msec) = samps wh.dwBufferLength = (DWORD) ((QWORD) MUSIC_FREQ * dwDuration / 1000); - VERIFY(wh.lpData = HeapAlloc(hHeap,0,wh.dwBufferLength)); + VERIFY(wh.lpData = malloc(wh.dwBufferLength)); wh.dwBytesRecorded = 0; wh.dwUser = 0; wh.dwFlags = 0; @@ -86,7 +86,7 @@ static __inline VOID BeepWave(DWORD dwFrequency,DWORD dwDuration) VERIFY(waveOutUnprepareHeader(hSoundDevice,&wh,sizeof(wh)) == MMSYSERR_NOERROR); VERIFY(waveOutClose(hSoundDevice) == MMSYSERR_NOERROR); - HeapFree(hHeap,0,wh.lpData); + free(wh.lpData); CloseHandle(hEventSound); return; } diff --git a/Sources/Emu48/FETCH.C b/Sources/Emu48/FETCH.C index b9a98d8..2260eb7 100644 --- a/Sources/Emu48/FETCH.C +++ b/Sources/Emu48/FETCH.C @@ -501,7 +501,7 @@ static const JMPTAB o8081_[] = static const JMPTAB o808_[] = { o8080, F, - o8081_, 4, + o8081_, 4, o8082X, F, o8083, F, o8084n, F, diff --git a/Sources/Emu48/FILES.C b/Sources/Emu48/FILES.C index 6083656..f1239ad 100644 --- a/Sources/Emu48/FILES.C +++ b/Sources/Emu48/FILES.C @@ -23,6 +23,8 @@ TCHAR szBackupFilename[MAX_PATH]; TCHAR szBufferFilename[MAX_PATH]; TCHAR szPort2Filename[MAX_PATH]; +BOOL bDocumentAvail = FALSE; // document not available + BYTE cCurrentRomType = 0; // Model -> hardware UINT nCurrentClass = 0; // Class -> derivate @@ -33,6 +35,8 @@ LPBYTE Port2 = NULL; LPBYTE pbyRom = NULL; BOOL bRomWriteable = TRUE; // flag if ROM writeable DWORD dwRomSize = 0; +LPBYTE pbyRomDirtyPage = NULL; +DWORD dwRomDirtyPageSize = 0; WORD wRomCrc = 0; // fingerprint of patched ROM LPBYTE pbyPort2 = NULL; @@ -45,7 +49,6 @@ WORD wPort2Crc = 0; // fingerprint of port2 BOOL bBackup = FALSE; static HANDLE hRomFile = NULL; -static HANDLE hRomMap = NULL; static HANDLE hPort2File = NULL; static HANDLE hPort2Map = NULL; @@ -61,6 +64,7 @@ static CHIPSET BackupChipset; static LPBYTE BackupPort0; static LPBYTE BackupPort1; static LPBYTE BackupPort2; +static BOOL bRomPacked; //################ //# @@ -209,6 +213,7 @@ typedef struct tnode DWORD dwAddress; // patch address BYTE byROM; // original ROM value BYTE byPatch; // patched ROM value + struct tnode *prev; // previous node struct tnode *next; // next node } TREENODE; @@ -219,14 +224,17 @@ static BOOL PatchNibble(DWORD dwAddress, BYTE byPatch) TREENODE *p; _ASSERT(pbyRom); // ROM defined - if ((p = HeapAlloc(hHeap,0,sizeof(TREENODE))) == NULL) + if ((p = malloc(sizeof(TREENODE))) == NULL) return TRUE; p->bPatch = TRUE; // address patched p->dwAddress = dwAddress; // save current values p->byROM = pbyRom[dwAddress]; p->byPatch = byPatch; + p->prev = NULL; p->next = nodePatch; // save node + + if (nodePatch) nodePatch->prev = p; // add as previous element nodePatch = p; pbyRom[dwAddress] = byPatch; // patch ROM @@ -244,7 +252,7 @@ static VOID RestorePatches(VOID) pbyRom[nodePatch->dwAddress] = nodePatch->byROM; p = nodePatch->next; // save pointer to next node - HeapFree(hHeap,0,nodePatch); // free node + free(nodePatch); // free node nodePatch = p; // new node } return; @@ -255,32 +263,42 @@ VOID UpdatePatches(BOOL bPatch) TREENODE *p = nodePatch; _ASSERT(pbyRom); // ROM defined - while (p != NULL) + if (bPatch) // patch ROM { - if (bPatch) // patch ROM + if (p) // something in patch list { - if (!p->bPatch) // patch only if not patched - { - // use original data for patch restore - p->byROM = pbyRom[p->dwAddress]; + // goto last element in list + for (; p->next != NULL; p = p->next) {} - // restore patch data - pbyRom[p->dwAddress] = p->byPatch; - p->bPatch = TRUE; // address patched - } - else + do { - _ASSERT(FALSE); // call ROM patch on a patched ROM + if (!p->bPatch) // patch only if not patched + { + // use original data for patch restore + p->byROM = pbyRom[p->dwAddress]; + + // restore patch data + pbyRom[p->dwAddress] = p->byPatch; + p->bPatch = TRUE; // address patched + } + else + { + _ASSERT(FALSE); // call ROM patch on a patched ROM + } + + p = p->prev; } + while (p != NULL); } - else // restore ROM + } + else // restore ROM + { + for (; p != NULL; p = p->next) { // restore original data pbyRom[p->dwAddress] = p->byROM; p->bPatch = FALSE; // address not patched } - - p = p->next; // next node } return; } @@ -311,7 +329,7 @@ BOOL PatchRom(LPCTSTR szFilename) CloseHandle(hFile); return FALSE; } - lpBuf = HeapAlloc(hHeap,0,dwFileSizeLow+1); + lpBuf = malloc(dwFileSizeLow+1); if (lpBuf == NULL) { CloseHandle(hFile); @@ -360,7 +378,7 @@ BOOL PatchRom(LPCTSTR szFilename) ++nPos; } } - HeapFree(hHeap,0,lpBuf); + free(lpBuf); return TRUE; } @@ -377,6 +395,8 @@ BOOL CrcRom(WORD *pwChk) // calculate fingerprint of ROM DWORD *pdwData,dwSize; DWORD dwChk = 0; + if (pbyRom == NULL) return TRUE; // ROM CRC isn't available + _ASSERT(pbyRom); // view on ROM pdwData = (DWORD *) pbyRom; @@ -398,34 +418,34 @@ BOOL CrcRom(WORD *pwChk) // calculate fingerprint of ROM BOOL MapRom(LPCTSTR szFilename) { - DWORD dwFileSizeHigh; + DWORD dwSize,dwFileSize,dwRead; // open ROM for writing - BOOL bWrite = (cCurrentRomType == 'X') ? bRomWriteable : FALSE; + BOOL bRomRW = (cCurrentRomType == 'X') ? bRomWriteable : FALSE; if (pbyRom != NULL) { return FALSE; } SetCurrentDirectory(szEmuDirectory); - if (bWrite) // ROM writeable + if (bRomRW) // ROM writeable { hRomFile = CreateFile(szFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, + FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hRomFile == INVALID_HANDLE_VALUE) { - bWrite = FALSE; // ROM not writeable + bRomRW = FALSE; // ROM not writeable hRomFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, + FILE_FLAG_SEQUENTIAL_SCAN, NULL); } } @@ -436,7 +456,7 @@ BOOL MapRom(LPCTSTR szFilename) FILE_SHARE_READ, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, + FILE_FLAG_SEQUENTIAL_SCAN, NULL); } SetCurrentDirectory(szCurrentDirectory); @@ -445,49 +465,136 @@ BOOL MapRom(LPCTSTR szFilename) hRomFile = NULL; return FALSE; } - dwRomSize = GetFileSize(hRomFile, &dwFileSizeHigh); - if (dwFileSizeHigh != 0) - { // file is too large. + dwRomSize = GetFileSize(hRomFile, NULL); + + if (dwRomSize <= 4) + { // file is too small. CloseHandle(hRomFile); hRomFile = NULL; dwRomSize = 0; return FALSE; } - hRomMap = CreateFileMapping(hRomFile, NULL, bWrite ? PAGE_READWRITE : PAGE_WRITECOPY, 0, dwRomSize, NULL); - if (hRomMap == NULL) - { - CloseHandle(hRomFile); - hRomFile = NULL; - dwRomSize = 0; - return FALSE; - } - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - AbortMessage(_T("Sharing file mapping handle.")); - } - pbyRom = MapViewOfFile(hRomMap, bWrite ? FILE_MAP_WRITE : FILE_MAP_COPY, 0, 0, dwRomSize); + + // read the first 4 bytes + ReadFile(hRomFile,&dwSize,sizeof(dwSize),&dwRead,NULL); + + dwFileSize = dwRomSize; // calculate ROM image buffer size + bRomPacked = (dwSize & 0xF0F0F0F0) != 0; // ROM image packed + if (bRomPacked) dwRomSize *= 2; // unpacked ROM image has double size + + pbyRom = VirtualAlloc(NULL,dwRomSize,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE); if (pbyRom == NULL) { - CloseHandle(hRomMap); CloseHandle(hRomFile); - hRomMap = NULL; hRomFile = NULL; dwRomSize = 0; return FALSE; } + + *(DWORD *) pbyRom = dwSize; // save first 4 bytes + + // load rest of file content + ReadFile(hRomFile,&pbyRom[sizeof(dwSize)],dwFileSize - sizeof(dwSize),&dwRead,NULL); + _ASSERT(dwFileSize - sizeof(dwSize) == dwRead); + + if (bRomRW) // ROM is writeable + { + // no. of dirty pages + dwRomDirtyPageSize = dwRomSize / ROMPAGESIZE; + + // alloc dirty page table + pbyRomDirtyPage = calloc(dwRomDirtyPageSize,sizeof(*pbyRomDirtyPage)); + if (pbyRomDirtyPage == NULL) + { + VirtualFree(pbyRom,0,MEM_RELEASE); // free ROM image + CloseHandle(hRomFile); + dwRomDirtyPageSize = 0; + pbyRom = NULL; + hRomFile = NULL; + dwRomSize = 0; + return FALSE; + } + } + else + { + dwRomDirtyPageSize = 0; + CloseHandle(hRomFile); + hRomFile = NULL; + } + + if (bRomPacked) // packed ROM image + { + dwSize = dwRomSize; // destination start address + while (dwFileSize > 0) // unpack source + { + BYTE byValue = pbyRom[--dwFileSize]; + pbyRom[--dwSize] = byValue >> 4; + pbyRom[--dwSize] = byValue & 0xF; + } + } return TRUE; } VOID UnmapRom(VOID) { - if (pbyRom == NULL) return; - RestorePatches(); // restore ROM Patches - UnmapViewOfFile(pbyRom); - CloseHandle(hRomMap); - CloseHandle(hRomFile); + if (pbyRom == NULL) return; // ROM not mapped + RestorePatches(); // restore ROM patches + if (hRomFile) // ROM file still open (only in R/W case) + { + DWORD i; + + _ASSERT(pbyRomDirtyPage != NULL); + + // scan for every dirty page + for (i = 0; i < dwRomDirtyPageSize; ++i) + { + if (pbyRomDirtyPage[i]) // page dirty + { + DWORD dwSize,dwLinPos,dwFilePos,dwWritten; + + dwLinPos = i * ROMPAGESIZE; // position inside emulator memory + + dwSize = ROMPAGESIZE; // bytes to write + while (i+1 < dwRomDirtyPageSize && pbyRomDirtyPage[i+1]) + { + dwSize += ROMPAGESIZE; // next page is also dirty + ++i; // skip next page in outer loop + } + + dwFilePos = dwLinPos; // ROM file position + + if (bRomPacked) // repack data + { + LPBYTE pbySrc,pbyDest; + DWORD j; + + dwSize /= 2; // adjust no. of bytes to write + dwFilePos /= 2; // linear pos in packed file + + // pack data in page + pbySrc = pbyDest = &pbyRom[dwLinPos]; + for (j = 0; j < dwSize; j++) + { + *pbyDest = *pbySrc++; + *pbyDest |= *pbySrc++ << 4; + pbyDest++; + } + } + + SetFilePointer(hRomFile,dwFilePos,NULL,FILE_BEGIN); + WriteFile(hRomFile,&pbyRom[dwLinPos],dwSize,&dwWritten,NULL); + } + } + + free(pbyRomDirtyPage); + CloseHandle(hRomFile); + pbyRomDirtyPage = NULL; + dwRomDirtyPageSize = 0; + hRomFile = NULL; + } + + VirtualFree(pbyRom,0,MEM_RELEASE); // free ROM image pbyRom = NULL; - hRomMap = NULL; - hRomFile = NULL; dwRomSize = 0; wRomCrc = 0; return; @@ -670,13 +777,13 @@ VOID ResetDocument(VOID) } szCurrentKml[0] = 0; szCurrentFilename[0]=0; - if (Port0) { HeapFree(hHeap,0,Port0); Port0 = NULL; } - if (Port1) { HeapFree(hHeap,0,Port1); Port1 = NULL; } - if (Port2) { HeapFree(hHeap,0,Port2); Port2 = NULL; } else UnmapPort2(); + if (Port0) { free(Port0); Port0 = NULL; } + if (Port1) { free(Port1); Port1 = NULL; } + if (Port2) { free(Port2); Port2 = NULL; } else UnmapPort2(); ZeroMemory(&Chipset,sizeof(Chipset)); ZeroMemory(&RMap,sizeof(RMap)); // delete MMU mappings ZeroMemory(&WMap,sizeof(WMap)); - UpdateWindowStatus(); + bDocumentAvail = FALSE; // document not available return; } @@ -746,21 +853,22 @@ BOOL NewDocument(VOID) // allocate port memory if (Chipset.Port0Size) { - Port0 = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,Chipset.Port0Size*2048); + Port0 = calloc(Chipset.Port0Size*2048,sizeof(*Port0)); _ASSERT(Port0 != NULL); } if (Chipset.Port1Size) { - Port1 = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,Chipset.Port1Size*2048); + Port1 = calloc(Chipset.Port1Size*2048,sizeof(*Port1)); _ASSERT(Port1 != NULL); } if (Chipset.Port2Size) { - Port2 = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,Chipset.Port2Size*2048); + Port2 = calloc(Chipset.Port2Size*2048,sizeof(*Port1)); _ASSERT(Port2 != NULL); } LoadBreakpointList(NULL); // clear debugger breakpoint list RomSwitch(0); // boot ROM view of HP49G and map memory + bDocumentAvail = TRUE; // document available return TRUE; restore: RestoreBackup(); @@ -843,10 +951,13 @@ BOOL OpenDocument(LPCTSTR szFilename) switch (pbyFileSignature[14]) { case 0xFE: // Win48 2.1 / Emu4x 0.99.x format + // read length of KML script name ReadFile(hFile,&nLength,sizeof(nLength),&lBytesRead,NULL); + // KML script name too long for file buffer + if (nLength >= ARRAYSIZEOF(szCurrentKml)) goto read_err; #if defined _UNICODE { - LPSTR szTmp = HeapAlloc(hHeap,0,nLength); + LPSTR szTmp = malloc(nLength); if (szTmp == NULL) { AbortMessage(_T("Memory Allocation Failure.")); @@ -855,7 +966,7 @@ BOOL OpenDocument(LPCTSTR szFilename) ReadFile(hFile, szTmp, nLength, &lBytesRead, NULL); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szTmp, lBytesRead, szCurrentKml, ARRAYSIZEOF(szCurrentKml)); - HeapFree(hHeap,0,szTmp); + free(szTmp); } #else { @@ -916,13 +1027,13 @@ BOOL OpenDocument(LPCTSTR szFilename) goto restore; } // reload old button state - ReloadButtons(Chipset.Keyboard_Row,sizeof(Chipset.Keyboard_Row)); + ReloadButtons(Chipset.Keyboard_Row,ARRAYSIZEOF(Chipset.Keyboard_Row)); FlashInit(); // init flash structure if (Chipset.Port0Size) { - Port0 = HeapAlloc(hHeap,0,Chipset.Port0Size*2048); + Port0 = malloc(Chipset.Port0Size*2048); if (Port0 == NULL) { AbortMessage(_T("Memory Allocation Failure.")); @@ -937,7 +1048,7 @@ BOOL OpenDocument(LPCTSTR szFilename) if (Chipset.Port1Size) { - Port1 = HeapAlloc(hHeap,0,Chipset.Port1Size*2048); + Port1 = malloc(Chipset.Port1Size*2048); if (Port1 == NULL) { AbortMessage(_T("Memory Allocation Failure.")); @@ -969,7 +1080,7 @@ BOOL OpenDocument(LPCTSTR szFilename) { if (Chipset.Port2Size) { - Port2 = HeapAlloc(hHeap,0,Chipset.Port2Size*2048); + Port2 = malloc(Chipset.Port2Size*2048); if (Port2 == NULL) { AbortMessage(_T("Memory Allocation Failure.")); @@ -1007,7 +1118,7 @@ BOOL OpenDocument(LPCTSTR szFilename) if (pEmuDocumentNotify) pEmuDocumentNotify(szCurrentFilename); #endif SetWindowPathTitle(szCurrentFilename); // update window title line - UpdateWindowStatus(); + bDocumentAvail = TRUE; // document available return TRUE; read_err: @@ -1058,14 +1169,14 @@ BOOL SaveDocument(VOID) WriteFile(hCurrentFile, &nLength, sizeof(nLength), &lBytesWritten, NULL); #if defined _UNICODE { - LPSTR szTmp = HeapAlloc(hHeap,0,nLength); + LPSTR szTmp = malloc(nLength); if (szTmp != NULL) { WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, szCurrentKml, nLength, szTmp, nLength, NULL, NULL); WriteFile(hCurrentFile, szTmp, nLength, &lBytesWritten, NULL); - HeapFree(hHeap,0,szTmp); + free(szTmp); } } #else @@ -1106,7 +1217,6 @@ BOOL SaveDocumentAs(LPCTSTR szFilename) if (pEmuDocumentNotify) pEmuDocumentNotify(szCurrentFilename); #endif SetWindowPathTitle(szCurrentFilename); // update window title line - UpdateWindowStatus(); // and draw it return SaveDocument(); // save current content } @@ -1135,23 +1245,22 @@ BOOL SaveBackup(VOID) lstrcpy(szBackupFilename, szCurrentFilename); lstrcpy(szBackupKml, szCurrentKml); - if (BackupPort0) HeapFree(hHeap,0,BackupPort0); - if (BackupPort1) HeapFree(hHeap,0,BackupPort1); - if (BackupPort2) HeapFree(hHeap,0,BackupPort2); + if (BackupPort0) free(BackupPort0); + if (BackupPort1) free(BackupPort1); + if (BackupPort2) free(BackupPort2); CopyMemory(&BackupChipset, &Chipset, sizeof(Chipset)); - BackupPort0 = HeapAlloc(hHeap,0,Chipset.Port0Size*2048); + BackupPort0 = malloc(Chipset.Port0Size*2048); CopyMemory(BackupPort0,Port0,Chipset.Port0Size*2048); - BackupPort1 = HeapAlloc(hHeap,0,Chipset.Port1Size*2048); + BackupPort1 = malloc(Chipset.Port1Size*2048); CopyMemory(BackupPort1,Port1,Chipset.Port1Size*2048); BackupPort2 = NULL; if (Chipset.Port2Size) // internal port2 { - BackupPort2 = HeapAlloc(hHeap,0,Chipset.Port2Size*2048); + BackupPort2 = malloc(Chipset.Port2Size*2048); CopyMemory(BackupPort2,Port2,Chipset.Port2Size*2048); } CreateBackupBreakpointList(); bBackup = TRUE; - UpdateWindowStatus(); return TRUE; } @@ -1182,13 +1291,13 @@ BOOL RestoreBackup(VOID) } } CopyMemory(&Chipset, &BackupChipset, sizeof(Chipset)); - Port0 = HeapAlloc(hHeap,0,Chipset.Port0Size*2048); + Port0 = malloc(Chipset.Port0Size*2048); CopyMemory(Port0,BackupPort0,Chipset.Port0Size*2048); - Port1 = HeapAlloc(hHeap,0,Chipset.Port1Size*2048); + Port1 = malloc(Chipset.Port1Size*2048); CopyMemory(Port1,BackupPort1,Chipset.Port1Size*2048); if (Chipset.Port2Size) // internal port2 { - Port2 = HeapAlloc(hHeap,0,Chipset.Port2Size*2048); + Port2 = malloc(Chipset.Port2Size*2048); CopyMemory(Port2,BackupPort2,Chipset.Port2Size*2048); } // map port2 @@ -1205,7 +1314,7 @@ BOOL RestoreBackup(VOID) SetWindowLocation(hWnd,Chipset.nPosX,Chipset.nPosY); RestoreBackupBreakpointList(); // restore the debugger breakpoint list if (bDbgOpen) OnToolDebug(); // reopen the debugger - UpdateWindowStatus(); + bDocumentAvail = TRUE; // document available return TRUE; } @@ -1214,12 +1323,11 @@ BOOL ResetBackup(VOID) if (!bBackup) return FALSE; szBackupFilename[0] = 0; szBackupKml[0] = 0; - if (BackupPort0) { HeapFree(hHeap,0,BackupPort0); BackupPort0 = NULL; } - if (BackupPort1) { HeapFree(hHeap,0,BackupPort1); BackupPort1 = NULL; } - if (BackupPort2) { HeapFree(hHeap,0,BackupPort2); BackupPort2 = NULL; } + if (BackupPort0) { free(BackupPort0); BackupPort0 = NULL; } + if (BackupPort1) { free(BackupPort1); BackupPort1 = NULL; } + if (BackupPort2) { free(BackupPort2); BackupPort2 = NULL; } ZeroMemory(&BackupChipset,sizeof(BackupChipset)); bBackup = FALSE; - UpdateWindowStatus(); return TRUE; } @@ -1413,7 +1521,7 @@ BOOL LoadObject(LPCTSTR szFilename) // separated stack writing part CloseHandle(hFile); return FALSE; } - lpBuf = HeapAlloc(hHeap,0,dwFileSizeLow*2); + lpBuf = malloc(dwFileSizeLow*2); if (lpBuf == NULL) { CloseHandle(hFile); @@ -1433,7 +1541,7 @@ BOOL LoadObject(LPCTSTR szFilename) // separated stack writing part if (wError == S_ERR_ASCII) AbortMessage(_T("The calculator does not have enough\nfree memory to load this text file.")); - HeapFree(hHeap,0,lpBuf); + free(lpBuf); return (wError == S_ERR_NO); } @@ -1490,7 +1598,7 @@ typedef struct _BmpFile LPBYTE pbyFile; // buffer } BMPFILE, FAR *LPBMPFILE, *PBMPFILE; -static __inline UINT DibNumColors(BITMAPINFOHEADER CONST *lpbi) +static __inline WORD DibNumColors(BITMAPINFOHEADER CONST *lpbi) { if (lpbi->biClrUsed != 0) return (UINT)lpbi->biClrUsed; @@ -1502,7 +1610,7 @@ static HPALETTE CreateBIPalette(BITMAPINFOHEADER CONST *lpbi) { LOGPALETTE* pPal; HPALETTE hpal = NULL; - UINT nNumColors; + WORD wNumColors; BYTE red; BYTE green; BYTE blue; @@ -1517,29 +1625,28 @@ static HPALETTE CreateBIPalette(BITMAPINFOHEADER CONST *lpbi) // Get a pointer to the color table and the number of colors in it pRgb = (RGBQUAD FAR *)((LPBYTE)lpbi + (WORD)lpbi->biSize); - nNumColors = DibNumColors(lpbi); + wNumColors = DibNumColors(lpbi); - if (nNumColors) + if (wNumColors) { // Allocate for the logical palette structure - pPal = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY)); - if (!pPal) - return NULL; + pPal = malloc(sizeof(LOGPALETTE) + wNumColors * sizeof(PALETTEENTRY)); + if (!pPal) return NULL; - pPal->palNumEntries = nNumColors; pPal->palVersion = 0x300; + pPal->palNumEntries = wNumColors; // Fill in the palette entries from the DIB color table and // create a logical color palette. - for (i = 0; i < nNumColors; i++) + for (i = 0; i < pPal->palNumEntries; i++) { pPal->palPalEntry[i].peRed = pRgb[i].rgbRed; pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen; pPal->palPalEntry[i].peBlue = pRgb[i].rgbBlue; - pPal->palPalEntry[i].peFlags = (BYTE)0; + pPal->palPalEntry[i].peFlags = 0; } hpal = CreatePalette(pPal); - HeapFree(hHeap,0,pPal); + free(pPal); } else { @@ -1547,12 +1654,12 @@ static HPALETTE CreateBIPalette(BITMAPINFOHEADER CONST *lpbi) // 16, 24 and 32 bitcount DIB's have no color table entries so, set the // number of to the maximum value (256). - nNumColors = 256; - pPal = HeapAlloc(hHeap,0,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY)); + wNumColors = 256; + pPal = malloc(sizeof(LOGPALETTE) + wNumColors * sizeof(PALETTEENTRY)); if (!pPal) return NULL; - pPal->palNumEntries = nNumColors; pPal->palVersion = 0x300; + pPal->palNumEntries = wNumColors; red = green = blue = 0; @@ -1570,7 +1677,7 @@ static HPALETTE CreateBIPalette(BITMAPINFOHEADER CONST *lpbi) blue += 64; } hpal = CreatePalette(pPal); - HeapFree(hHeap,0,pPal); + free(pPal); } return hpal; } @@ -1625,12 +1732,13 @@ static HBITMAP DecodeBmp(LPBMPFILE pBmp) pBmi, DIB_RGB_COLORS)); if (hBitmap == NULL) return NULL; - _ASSERT(hPalette == NULL); // resource free - hPalette = CreateBIPalette(&pBmi->bmiHeader); - // save old palette - hOldPalette = SelectPalette(hWindowDC, hPalette, FALSE); - RealizePalette(hWindowDC); - + if (hPalette == NULL) + { + hPalette = CreateBIPalette(&pBmi->bmiHeader); + // save old palette + hOldPalette = SelectPalette(hWindowDC, hPalette, FALSE); + RealizePalette(hWindowDC); + } return hBitmap; } @@ -1719,7 +1827,7 @@ static HBITMAP DecodeGif(LPBMPFILE pBmp) bmi.bmiHeader.biWidth = nWidth; bmi.bmiHeader.biHeight = nHeight; bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 24; // create a true color DIB + bmi.bmiHeader.biBitCount = 24; // create a true color DIB bmi.bmiHeader.biCompression = BI_RGB; ZeroMemory(&sGlb,sizeof(sGlb)); // init global color map @@ -2115,14 +2223,16 @@ static HBITMAP DecodeGif(LPBMPFILE pBmp) } } - _ASSERT(bDecoding == FALSE); // decoding successful + _ASSERT(bDecoding == FALSE); // decoding successful // normal decoding exit - _ASSERT(hPalette == NULL); // resource free - hPalette = CreateBIPalette((PBITMAPINFOHEADER) &bmi); - // save old palette - hOldPalette = SelectPalette(hWindowDC, hPalette, FALSE); - RealizePalette(hWindowDC); + if (hPalette == NULL) + { + hPalette = CreateBIPalette((PBITMAPINFOHEADER) &bmi); + // save old palette + hOldPalette = SelectPalette(hWindowDC, hPalette, FALSE); + RealizePalette(hWindowDC); + } quit: if (hBitmap != NULL && bDecoding) // creation failed diff --git a/Sources/Emu48/I28F160.C b/Sources/Emu48/I28F160.C index a239b13..a7145b9 100644 --- a/Sources/Emu48/I28F160.C +++ b/Sources/Emu48/I28F160.C @@ -187,6 +187,51 @@ static CONST BYTE byQueryTab[] = }; +// +// ROM buffer access functions +// + +static __inline void WrDirtyPage(DWORD d) +{ + if (pbyRomDirtyPage) // using dirty ROM page table + { + DWORD dwPage = d / ROMPAGESIZE; // this is the page + + _ASSERT(dwPage < dwRomDirtyPageSize); + pbyRomDirtyPage[dwPage] = TRUE; // page is dirty + } + return; +} + +static __inline void EraseBlock(DWORD d,DWORD dwNibSize) +{ + LPBYTE pbyAddr = pbyRom + d; + + while (dwNibSize--) + { + WrDirtyPage(d++); // make page dirty + *pbyAddr++ = 0x0F; // clear address + } + return; +} + +static __inline void WriteByte(DWORD d,BYTE byData) +{ + WrDirtyPage(d); // make page dirty + + _ASSERT(d+1 < dwRomSize); // address valid? + *(pbyRom+d) &= (byData & 0x0F); // write LSB + *(pbyRom+d+1) &= (byData >> 4); // write MSB + return; +} + +static __inline BYTE ReadByte(DWORD d) +{ + _ASSERT(d+1 < dwRomSize); // address valid? + return *(pbyRom+d)|(*(pbyRom+d+1)<<4); // get byte +} + + // // write state functions // @@ -367,8 +412,8 @@ static VOID WrStateE8C(BYTE a, DWORD d) _ASSERT(d+1 < dwRomSize); // address valid? // no error set in BWSLBS, because I could alway program a "0" - *(pbyRom+d++) &= (a & 0x0F); // write LSB - *(pbyRom+d++) &= (a >> 4); // write MSB + WriteByte(d,a); // write byte + d += 2; // next address } } else @@ -395,11 +440,8 @@ static VOID WrState40(DWORD d) // byte/word program data static VOID WrState40D(BYTE a, DWORD d) { - d <<= 1; // nibble start address - _ASSERT(d+1 < dwRomSize); // address valid? // no error set in BWSLBS, because I could alway program a "0" - *(pbyRom+d++) &= (a & 0x0F); // write LSB - *(pbyRom+d) &= (a >> 4); // write MSB + WriteByte(d << 1,a); // write byte WSMset.byStatusReg |= WSMS; // data written WSMset.uWrState = WRS_DATA; return; @@ -433,8 +475,7 @@ static VOID WrState20C(BYTE a, DWORD d) d &= ~(dwBlockSize-1); // start of block dwBlockSize *= 2; // block size in nibbles _ASSERT(d+dwBlockSize <= dwRomSize); // address valid? - // write 128K nibble - FillMemory(pbyRom + (d << 1),dwBlockSize,0x0F); + EraseBlock(d << 1,dwBlockSize); // erase 128K nibble } } else @@ -467,7 +508,7 @@ static VOID WrState30C(BYTE a, DWORD d) WORD wNoOfBlocks = (byQueryTab[0x2E] << 8) | byQueryTab[0x2D]; DWORD dwBlockSize = ((byQueryTab[0x30] << 8) | byQueryTab[0x2F]) * 256; - LPBYTE pbyBlock = pbyRom; + DWORD dwBlockAddr = 0; dwBlockSize *= 2; // block size in nibbles @@ -481,11 +522,11 @@ static VOID WrState30C(BYTE a, DWORD d) // clear block lock bit WSMset.dwLockCnfg &= ~(1<> 16) & 0xFF; BOOL bPress = (dwData >> 24) & 0xFF; - PlayKey(nOut,nIn,bPress); -// KeyboardEvent(bPress,nOut,nIn); + PlayKey(nOut,nIn,bPress); } dwTime = nMacroTimeout; // set default speed @@ -84,6 +82,13 @@ static DWORD WINAPI EventThread(LPVOID pParam) } continue; } + + // hold the key state the minimum macro play key hold time + if (dwTime < dwMacroMinDelay) dwTime = dwMacroMinDelay; + + dwTime -= dwKeyMinDelay; // remove the actual key hold time + // set negative number to zero + if ((dwTime & 0x80000000) != 0) dwTime = 0; break; // got key information } } @@ -102,9 +107,7 @@ VOID KeyMacroRecord(BOOL bPress, UINT out, UINT in) DWORD dwWritten; dwWritten = GetTickCount(); // time reference - Data.dwTime = (dwWritten - dwTimeRef - KEYHOLDTIME); - // set negative number to zero - if ((Data.dwTime & 0x80000000) != 0) Data.dwTime = 0; + Data.dwTime = (dwWritten - dwTimeRef); Data.dwTime |= 0x80000000; // set time marker dwTimeRef = dwWritten; @@ -161,14 +164,13 @@ LRESULT OnToolMacroNew(VOID) _ASSERT(dwWritten == sizeof(dwExtensionLength)); nMacroState = MACRO_NEW; - UpdateWindowStatus(); MessageBox(hWnd, _T("Press OK to begin to record the Macro."), _T("Macro Recorder"), MB_OK|MB_ICONINFORMATION); - dwTimeRef = GetTickCount() + KEYHOLDTIME; // time reference + dwTimeRef = GetTickCount(); // time reference return 0; } @@ -242,7 +244,6 @@ LRESULT OnToolMacroPlay(VOID) hEventPlay = CreateEvent(NULL,FALSE,FALSE,NULL); nMacroState = MACRO_PLAY; - UpdateWindowStatus(); // start playing thread VERIFY(hThreadEv = CreateThread(NULL,0,&EventThread,NULL,0,&dwThreadId)); @@ -273,7 +274,6 @@ LRESULT OnToolMacroStop(VOID) if (hMacroFile != INVALID_HANDLE_VALUE) CloseHandle(hMacroFile); nMacroState = MACRO_OFF; - UpdateWindowStatus(); } return 0; } diff --git a/Sources/Emu48/KML.C b/Sources/Emu48/KML.C index 444bec8..2bbcdba 100644 --- a/Sources/Emu48/KML.C +++ b/Sources/Emu48/KML.C @@ -59,7 +59,7 @@ static LPCTSTR szLexDelim[] = _T(" \t\r") // valid whitespaces for LEX_PARAM }; -static KmlToken pLexToken[] = +static CONST KmlToken pLexToken[] = { {TOK_ANNUNCIATOR,000001,11,_T("Annunciator")}, {TOK_BACKGROUND, 000000,10,_T("Background")}, @@ -104,7 +104,7 @@ static KmlToken pLexToken[] = {TOK_VGA, 000001, 3,_T("Vga")}, // for PPC compatibility reasons {TOK_LCD, 000000, 3,_T("Lcd")}, {TOK_END, 000000, 3,_T("End")}, - {0, 000000, 0,_T("")}, + {TOK_NONE, 000000, 0,_T("")} }; static CONST TokenId eIsGlobalBlock[] = @@ -146,7 +146,7 @@ static VOID ClearLog() nLogLength = 0; if (szLog != NULL) { - HeapFree(hHeap,0,szLog); + free(szLog); szLog = NULL; } return; @@ -158,7 +158,7 @@ static VOID AddToLog(LPCTSTR szString) if (szLog == NULL) { nLogLength = nLength + 1; // \0 - szLog = HeapAlloc(hHeap,0,nLogLength*sizeof(szLog[0])); + szLog = malloc(nLogLength*sizeof(szLog[0])); if (szLog==NULL) { nLogLength = 0; @@ -168,7 +168,7 @@ static VOID AddToLog(LPCTSTR szString) } else { - LPTSTR szLogTmp = HeapReAlloc(hHeap,0,szLog,(nLogLength+nLength)*sizeof(szLog[0])); + LPTSTR szLogTmp = realloc(szLog,(nLogLength+nLength)*sizeof(szLog[0])); if (szLogTmp == NULL) { ClearLog(); @@ -268,9 +268,9 @@ static VOID DestroyKmlList(VOID) while (pKmlList) { pList = pKmlList->pNext; - HeapFree(hHeap,0,pKmlList->szFilename); - HeapFree(hHeap,0,pKmlList->szTitle); - HeapFree(hHeap,0,pKmlList); + free(pKmlList->szFilename); + free(pKmlList->szTitle); + free(pKmlList); pKmlList = pList; } return; @@ -313,7 +313,7 @@ static VOID CreateKmlList(VOID) FreeBlocks(pBlock); continue; } - VERIFY(pScript = HeapAlloc(hHeap,0,sizeof(KmlScript))); + VERIFY(pScript = malloc(sizeof(KmlScript))); pScript->szFilename = DuplicateString(pFindFileData.cFileName); szTitle = GetStringParam(pBlock,TOK_GLOBAL,TOK_TITLE,0); if (szTitle == NULL) szTitle = pScript->szFilename; @@ -497,7 +497,7 @@ static LPTSTR MapKMLFile(HANDLE hFile) goto fail; } - lpBuf = HeapAlloc(hHeap,0,(dwFileSizeLow+1)*sizeof(lpBuf[0])); + lpBuf = malloc((dwFileSizeLow+1)*sizeof(lpBuf[0])); if (lpBuf == NULL) { PrintfToLog(_T("Cannot allocate %i bytes."), (dwFileSizeLow+1)*sizeof(lpBuf[0])); @@ -505,17 +505,17 @@ static LPTSTR MapKMLFile(HANDLE hFile) } #if defined _UNICODE { - LPSTR szTmp = HeapAlloc(hHeap,0,dwFileSizeLow+1); + LPSTR szTmp = malloc(dwFileSizeLow+1); if (szTmp == NULL) { - HeapFree(hHeap,0,lpBuf); + free(lpBuf); lpBuf = NULL; PrintfToLog(_T("Cannot allocate %i bytes."), dwFileSizeLow+1); goto fail; } ReadFile(hFile, szTmp, dwFileSizeLow, &lBytesRead, NULL); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szTmp, lBytesRead, lpBuf, dwFileSizeLow+1); - HeapFree(hHeap,0,szTmp); + free(szTmp); } #else { @@ -637,10 +637,10 @@ static TokenId ParseToken(UINT nMode) if (bDebug) // token not found { // allocate target string memory with token length - LPTSTR szToken = HeapAlloc(hHeap,0,(i+1) * sizeof(szToken[0])); + LPTSTR szToken = malloc((i+1) * sizeof(szToken[0])); lstrcpyn(szToken,szText,i+1); // copy token text and append EOS PrintfToLog(_T("%i: Undefined token %s"),nLexLine,szToken); - HeapFree(hHeap,0,szToken); + free(szToken); } return TOK_NONE; } @@ -665,21 +665,33 @@ static LPTSTR ParseString(VOID) szText++; // skip leading '"' nLength = 0; nBlock = 256; - lpszString = HeapAlloc(hHeap,0,nBlock * sizeof(lpszString[0])); + lpszString = malloc(nBlock * sizeof(lpszString[0])); while (*szText != _T('"')) { if (nLength == nBlock - 1) // ran out of buffer space { nBlock += 256; - lpszString = HeapReAlloc(hHeap,0,lpszString,nBlock * sizeof(lpszString[0])); + lpszString = realloc(lpszString,nBlock * sizeof(lpszString[0])); + } + + if (*szText == _T('\\')) // escape char + { + // skip a '\' escape char before a quotation to + // decode the \" sequence as a quotation mark inside text + switch (szText[1]) + { + case _T('\"'): + case _T('\\'): + ++szText; // skip escape char '\' + break; + } } - if (*szText == _T('\\')) szText++; // skip '\' escape char to decode \" if (*szText == 0) // EOS found inside string { lpszString[nLength] = 0; // set EOS PrintfToLog(_T("%i: Invalid string %s."), nLexLine, lpszString); - HeapFree(hHeap,0,lpszString); + free(lpszString); return NULL; } lpszString[nLength++] = *szText++; // save char @@ -688,7 +700,7 @@ static LPTSTR ParseString(VOID) lpszString[nLength] = 0; // set EOS // release unnecessary allocated bytes - return HeapReAlloc(hHeap,0,lpszString,(nLength+1) * sizeof(lpszString[0])); + return realloc(lpszString,(nLength+1) * sizeof(lpszString[0])); } static TokenId Lex(UINT nMode) @@ -736,7 +748,7 @@ static KmlLine* ParseLine(TokenId eCommand) } if (pLexToken[i].nLen == 0) return NULL; - pLine = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,sizeof(KmlLine)); + pLine = calloc(1,sizeof(KmlLine)); pLine->eCommand = eCommand; for (j = 0, nParams = pLexToken[i].nParams; TRUE; nParams >>= 3) @@ -779,18 +791,18 @@ static KmlLine* ParseLine(TokenId eCommand) } // if last argument was string, free it - if (eToken == TOK_STRING) HeapFree(hHeap,0,szLexString); + if (eToken == TOK_STRING) free(szLexString); nParams = pLexToken[i].nParams; // get argument types of command for (i = 0; i < j; ++i) // handle all scanned arguments { if ((nParams & 7) == TYPE_STRING) // string type { - HeapFree(hHeap,0,(LPVOID)pLine->nParam[i]); + free((LPVOID)pLine->nParam[i]); } nParams >>= 3; // next argument type } - HeapFree(hHeap,0,pLine); + free(pLine); return NULL; } @@ -833,7 +845,7 @@ static KmlLine* IncludeLines(LPCTSTR szFilename) nLexLine = uOldLine; szText = szOldText; - HeapFree(hHeap,0,lpbyBuf); + free(lpbyBuf); return pLine; } @@ -845,7 +857,7 @@ static KmlLine* ParseLines(VOID) TokenId eToken; UINT nLevel = 0; - while ((eToken = Lex(LEX_COMMAND))) + while ((eToken = Lex(LEX_COMMAND)) != TOK_NONE) { if (IsGlobalBlock(eToken)) // check for block command { @@ -871,7 +883,7 @@ static KmlLine* ParseLines(VOID) { pLine = pFirst = IncludeLines(szLexString); } - HeapFree(hHeap,0,szFilename); // free memory + free(szFilename); // free memory if (pLine == NULL) // parsing error goto abort; while (pLine->pNext) pLine=pLine->pNext; @@ -921,7 +933,7 @@ static KmlBlock* ParseBlock(TokenId eType) nLinesIncludeLevel = 0; - VERIFY(pBlock = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,sizeof(KmlBlock))); + VERIFY(pBlock = calloc(1,sizeof(KmlBlock))); pBlock->eType = eType; for (i = 0; pLexToken[i].nLen; ++i) // search for token @@ -937,8 +949,9 @@ static KmlBlock* ParseBlock(TokenId eType) eToken = Lex(LEX_PARAM); // decode argument if (eToken != TOK_INTEGER) { + if (eToken == TOK_STRING) free(szLexString); PrintfToLog(_T("%i: Block %s parameter must be an integer."), nLexLine, pLexToken[i].szName); - HeapFree(hHeap,0,pBlock); + free(pBlock); return NULL; } @@ -949,14 +962,14 @@ static KmlBlock* ParseBlock(TokenId eType) if (eToken != TOK_EOL) { PrintfToLog(_T("%i: Too many parameters for block %s."), nLexLine, pLexToken[i].szName); - HeapFree(hHeap,0,pBlock); + free(pBlock); return NULL; } pBlock->pFirstLine = ParseLines(); if (pBlock->pFirstLine == NULL) // break on ParseLines error { - HeapFree(hHeap,0,pBlock); + free(pBlock); pBlock = NULL; } @@ -1002,7 +1015,7 @@ static KmlBlock* IncludeBlocks(LPCTSTR szFilename) nLexLine = uOldLine; szText = szOldText; - HeapFree(hHeap,0,lpbyBuf); + free(lpbyBuf); return pFirst; } @@ -1029,7 +1042,7 @@ static KmlBlock* ParseBlocks(VOID) pBlock = pBlock->pNext = IncludeBlocks(szLexString); else pBlock = pFirst = IncludeBlocks(szLexString); - HeapFree(hHeap,0,szFilename); // free memory + free(szFilename); // free memory if (pBlock == NULL) // parsing error goto abort; while (pBlock->pNext) pBlock=pBlock->pNext; @@ -1445,13 +1458,13 @@ static VOID FreeLines(KmlLine* pLine) { if ((nParams&7) == TYPE_STRING) // string type { - HeapFree(hHeap,0,(LPVOID)pLine->nParam[i]); + free((LPVOID)pLine->nParam[i]); } i++; // incr. parameter buffer index nParams >>= 3; // next argument type } pLine = pLine->pNext; // get next line - HeapFree(hHeap,0,pThisLine); + free(pThisLine); } return; } @@ -1463,7 +1476,7 @@ VOID FreeBlocks(KmlBlock* pBlock) KmlBlock* pThisBlock = pBlock; pBlock = pBlock->pNext; FreeLines(pThisBlock->pFirstLine); - HeapFree(hHeap,0,pThisBlock); + free(pThisBlock); } return; } @@ -1481,11 +1494,8 @@ VOID KillKML(VOID) DestroyMainBitmap(); if (hPalette) { - BOOL err; - if (hWindowDC) SelectPalette(hWindowDC, hOldPalette, FALSE); - err = DeleteObject(hPalette); - _ASSERT(err != FALSE); // freed resource memory + VERIFY(DeleteObject(hPalette)); hPalette = NULL; } bClicking = FALSE; @@ -1508,7 +1518,6 @@ VOID KillKML(VOID) nLcdZoom = 1; cCurrentRomType = 0; nCurrentClass = 0; - UpdateWindowStatus(); ResizeWindow(); return; } @@ -1840,8 +1849,16 @@ VOID ReloadButtons(BYTE *Keyboard_Row, UINT nSize) { if (pButton[i].nOut < nSize) // valid out code { - // get state of button from keyboard matrix - pButton[i].bDown = ((Keyboard_Row[pButton[i].nOut] & pButton[i].nIn) != 0); + if (pButton[i].nIn == 0x8000) // ON key + { + // get state of ON button from interrupt line + pButton[i].bDown = (Chipset.IR15X != 0); + } + else + { + // get state of button from keyboard matrix + pButton[i].bDown = ((Keyboard_Row[pButton[i].nOut] & pButton[i].nIn) != 0); + } // any key pressed? bKeyPressed = bKeyPressed || pButton[i].bDown; @@ -1987,7 +2004,7 @@ VOID MouseButtonUpAt(UINT nFlags, DWORD x, DWORD y) bClicking = FALSE; uButtonClicked = 0; return; - UNREFERENCED_PARAMETER(nFlags); + UNREFERENCED_PARAMETER(nFlags); } VOID MouseMovesTo(UINT nFlags, DWORD x, DWORD y) @@ -2109,7 +2126,7 @@ static KmlBlock* LoadKMLGlobal(LPCTSTR szFilename) HANDLE hFile; LPTSTR lpBuf; KmlBlock* pBlock; - DWORD eToken; + TokenId eToken; SetCurrentDirectory(szEmuDirectory); hFile = CreateFile(szFilename, @@ -2137,7 +2154,7 @@ static KmlBlock* LoadKMLGlobal(LPCTSTR szFilename) } CleanLex(); ClearLog(); - HeapFree(hHeap,0,lpBuf); + free(lpBuf); return pBlock; } @@ -2173,7 +2190,7 @@ BOOL InitKML(LPCTSTR szFilename, BOOL bNoLog) pKml = ParseBlocks(); CleanLex(); - HeapFree(hHeap,0,lpBuf); + free(lpBuf); if (pKml == NULL) goto quit; pBlock = pKml; diff --git a/Sources/Emu48/MOPS.C b/Sources/Emu48/MOPS.C index 664c844..b1c6c62 100644 --- a/Sources/Emu48/MOPS.C +++ b/Sources/Emu48/MOPS.C @@ -987,6 +987,29 @@ VOID IOBit(DWORD d, BYTE b, BOOL s) // set/clear bit in I/O section LeaveCriticalSection(&csIOLock); } +static DWORD ReadT2Acc(VOID) +{ + static DWORD dwCyc = 0; // CPU cycle counter at last timer2 read access + + DWORD dwCycDif; + + // CPU cycles since last call + dwCycDif = (DWORD) (Chipset.cycles & 0xFFFFFFFF) - dwCyc; + dwCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); + + // maybe CPU speed measurement, slow down the next 10 CPU opcodes + if (dwCycDif < 150) + { + EnterCriticalSection(&csSlowLock); + { + InitAdjustSpeed(); // init variables if necessary + nOpcSlow = 10; // slow down next 10 opcodes + } + LeaveCriticalSection(&csSlowLock); + } + return ReadT2(); +} + VOID ReadIO(BYTE *a, DWORD d, DWORD s, BOOL bUpdate) { BOOL bNINT,bNINT2; @@ -1173,8 +1196,13 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s, BOOL bUpdate) #endif break; case 0x1B: *a = 0; break; - case 0x1C: *a = 0; break; // LED CONTROL - case 0x1D: *a = 0; break; // LED BUFFER + case 0x1C: // LED CONTROL + // put LBF and LBZ always to zero to indicate a free REDEYE buffer and formatter + *a = (Chipset.IORam[d] & (LED|ELBE)); + break; + case 0x1D: // LED BUFFER + *a = (Chipset.IORam[d] & LBO); + break; // case 0x1E: *a = Chipset.IORam[d]; break; // case 0x1F: *a = Chipset.IORam[d]; break; case 0x20: *a = 3; break; @@ -1227,14 +1255,14 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s, BOOL bUpdate) case 0x35: *a = 0; break; case 0x36: *a = 0; break; case 0x37: *a = ReadT1(); break; - case 0x38: Nunpack(a, ReadT2() , s); return; - case 0x39: Nunpack(a, ReadT2()>> 4, s); return; - case 0x3A: Nunpack(a, ReadT2()>> 8, s); return; - case 0x3B: Nunpack(a, ReadT2()>>12, s); return; - case 0x3C: Nunpack(a, ReadT2()>>16, s); return; - case 0x3D: Nunpack(a, ReadT2()>>20, s); return; - case 0x3E: Nunpack(a, ReadT2()>>24, s); return; - case 0x3F: Nunpack(a, ReadT2()>>28, s); return; + case 0x38: Nunpack(a, ReadT2Acc() , s); return; + case 0x39: Nunpack(a, ReadT2Acc()>> 4, s); return; + case 0x3A: Nunpack(a, ReadT2Acc()>> 8, s); return; + case 0x3B: Nunpack(a, ReadT2Acc()>>12, s); return; + case 0x3C: Nunpack(a, ReadT2Acc()>>16, s); return; + case 0x3D: Nunpack(a, ReadT2Acc()>>20, s); return; + case 0x3E: Nunpack(a, ReadT2Acc()>>24, s); return; + case 0x3F: Nunpack(a, ReadT2Acc()>>28, s); return; default: *a = Chipset.IORam[d]; } d++; a++; @@ -1589,12 +1617,27 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) } #endif } + if ((c^Chipset.IORam[d])&ELBE) // ELBE bit changed + { + // Led Service ReQuest on Led Buffer Empty enabled + BOOL bLSRQ = (c & (ELBE | LBF)) == ELBE; + + IOBit(SRQ2,LSRQ,bLSRQ); // update LSRQ bit + if (bLSRQ) // interrupt on Led Buffer Empty enabled + { + Chipset.SoftInt = TRUE; + bInterrupt = TRUE; + } + } Chipset.IORam[d]=c; break; // 0011D = NS:LBR // 0011D @ Led Buffer Register [0 0 0 LBO] (bits 1-3 read zero) - case 0x1D: Chipset.IORam[d]=c&1; break; + case 0x1D: + IrPrinter((BYTE)(c&LBO)); + Chipset.IORam[d]=c&LBO; + break; // 0011E = NS:SCRATCHPAD // 0011E @ Scratch pad diff --git a/Sources/Emu48/MRU.C b/Sources/Emu48/MRU.C index 82c62a9..a7a2f72 100644 --- a/Sources/Emu48/MRU.C +++ b/Sources/Emu48/MRU.C @@ -73,7 +73,7 @@ BOOL MruInit(INT nNum) if (nEntry > 0) // allocate MRU table { // create MRU table - if ((ppszFiles = HeapAlloc(hHeap,0,nEntry * sizeof(*ppszFiles))) == NULL) + if ((ppszFiles = malloc(nEntry * sizeof(*ppszFiles))) == NULL) return TRUE; // fill each entry @@ -104,12 +104,12 @@ VOID MruCleanup(VOID) for (i = 0; i < nEntry; ++i) // cleanup each entry { if (ppszFiles[i] != NULL) - HeapFree(hHeap,0,ppszFiles[i]); // cleanup entry + free(ppszFiles[i]); // cleanup entry } if (ppszFiles != NULL) // table defined { - HeapFree(hHeap,0,ppszFiles); // free table + free(ppszFiles); // free table ppszFiles = NULL; } return; @@ -140,7 +140,7 @@ VOID MruAdd(LPCTSTR lpszEntry) i = nEntry - 1; // last index if (ppszFiles[i] != NULL) - HeapFree(hHeap,0,ppszFiles[i]); // free oldest entry + free(ppszFiles[i]); // free oldest entry for (; i > 0; --i) // move old entries 1 line down { @@ -156,7 +156,7 @@ VOID MruAdd(LPCTSTR lpszEntry) VOID MruRemove(INT nIndex) { - HeapFree(hHeap,0,ppszFiles[nIndex]); // free entry + free(ppszFiles[nIndex]); // free entry for (; nIndex < nEntry - 1; ++nIndex) // move below entries 1 line up { @@ -198,10 +198,10 @@ LPCTSTR MruFilename(INT nIndex) VOID MruUpdateMenu(VOID) { - TCHAR szCurPath[MAX_PATH]; - HANDLE hMenu; - BOOL bEmpty; - INT i; + TCHAR szCurPath[MAX_PATH]; + HMENU hMenu; + BOOL bEmpty; + INT i; if (nEntry == 0) return; // no entries @@ -309,7 +309,6 @@ VOID MruReadList(VOID) { TCHAR szFilename[MAX_PATH]; TCHAR szItemname[32]; - LPTSTR lpszValue; INT i; _ASSERT(ppszFiles != NULL); // MRU not initialized @@ -321,9 +320,8 @@ VOID MruReadList(VOID) if (ppszFiles[i] != NULL) // already filled { - HeapFree(hHeap,0,ppszFiles[i]); // free entry + free(ppszFiles[i]); // free entry ppszFiles[i] = NULL; // clear last line - lpszValue = _T(""); } if (*szFilename) // read a valid entry diff --git a/Sources/Emu48/OPCODES.C b/Sources/Emu48/OPCODES.C index d616986..0b0f086 100644 --- a/Sources/Emu48/OPCODES.C +++ b/Sources/Emu48/OPCODES.C @@ -1040,7 +1040,7 @@ VOID o807(LPBYTE I) // SHUTDN // emulation of BS reset circuit in deep sleep // HP39/40G, HP48GX, HP49G, display off, card control off or in slow mode if ( (cCurrentRomType=='E' || cCurrentRomType=='G' || cCurrentRomType=='X') - && (w.IORam[BITOFFSET]&DON) == 0 + && (w.IORam[BITOFFSET]&DON) == 0 && ((w.IORam[CARDCTL]&(ECDT|RCDT)) != (ECDT|RCDT))) { // on HP48GX ROM must be selected (DA19=1) and @@ -2143,7 +2143,7 @@ VOID o8Fd5(LPBYTE I) // GOSBVL #ddddd return; } - // ?r=s f + // ?r=s f VOID o9a0(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.A, w.B, I[1]); GOYES3; } VOID o9a1(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.B, w.C, I[1]); GOYES3; } VOID o9a2(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.C, w.A, I[1]); GOYES3; } diff --git a/Sources/Emu48/OPS.H b/Sources/Emu48/OPS.H index 9ad24d2..20aebb5 100644 --- a/Sources/Emu48/OPS.H +++ b/Sources/Emu48/OPS.H @@ -48,7 +48,7 @@ static __inline LPBYTE FASTPTR(DWORD d) if ( !(Chipset.IOCfig && ((d & 0xFFFC0) == Chipset.IOBase)) && RMap[u] != NULL // page valid - && ( v < 0x1000 - ARRAYSIZEOF(lpbyPage) // complete opcode inside page + && ( v < 0x1000 - ARRAYSIZEOF(pbyNULL) // complete opcode inside page // or next page continue linear addressing || (RMap[u] + 0x1000 == RMap[(u+1) & (ARRAYSIZEOF(RMap)-1)]) ) @@ -59,7 +59,7 @@ static __inline LPBYTE FASTPTR(DWORD d) else { lpbyPage = pbyNULL; // memory allocation - Npeek(lpbyPage, d, ARRAYSIZEOF(lpbyPage)); // fill with data (LAHEX + 16 digits = longest opcode) + Npeek(lpbyPage, d, ARRAYSIZEOF(pbyNULL)); // fill with data (LAHEX + 16 digits = longest opcode) } return lpbyPage; } diff --git a/Sources/Emu48/PCH.H b/Sources/Emu48/PCH.H index 81dddc3..9ac2d85 100644 --- a/Sources/Emu48/PCH.H +++ b/Sources/Emu48/PCH.H @@ -4,7 +4,9 @@ #define _WIN32_IE 0x0200 #define _CRT_SECURE_NO_DEPRECATE +#define _CRTDBG_MAP_ALLOC +#include #include #include #include diff --git a/Sources/Emu48/REDEYE.C b/Sources/Emu48/REDEYE.C new file mode 100644 index 0000000..bd646fe --- /dev/null +++ b/Sources/Emu48/REDEYE.C @@ -0,0 +1,177 @@ +/* + * redeye.c + * + * This file is part of Emu48 + * + * Copyright (C) 2011 Christoph Gießelink + * + */ +#include "pch.h" +#include "Emu48.h" +#include "io.h" + +#define ERR_CHAR 127 // character for transfer error + +#define H1 0x78 +#define H2 0xE6 +#define H3 0xD5 +#define H4 0x8B + +// HP redeye correction masks +static CONST BYTE byEmask[] = { H1, H2, H3, H4 }; + +static __inline UINT MAX(UINT a, UINT b) +{ + return (a>b)?a:b; +} + +static __inline BYTE Parity(BYTE b) +{ + b ^= (b >> 4); + b ^= (b >> 2); + b ^= (b >> 1); + return b & 1; +} + +static __inline BYTE CreateCorrectionBits(BYTE b) +{ + INT i; + BYTE byVal = 0; + + for (i = 0; i < ARRAYSIZEOF(byEmask);++i) + { + byVal <<= 1; + byVal |= Parity((BYTE) (b & byEmask[i])); + } + return byVal; +} + +static __inline WORD CorrectData(WORD wData,WORD wMissed) +{ + while ((wMissed & 0xFF) != 0) // clear every missed bit in data area + { + BYTE byBitMask; + + // detect valid H(i) mask + WORD wMi = 0x800; // first M(i) bit + INT i = 0; // index to first H(i) mask + + while (TRUE) + { + if ((wMissed & wMi) == 0) // possible valid mask + { + _ASSERT(i < ARRAYSIZEOF(byEmask)); + + // select bit to correct + byBitMask = wMissed & byEmask[i]; + + if (Parity(byBitMask)) // only one bit set (parity odd) + break; // -> valid H(i) mask + } + + wMi >>= 1; // next M(i) bit + i++; // next H(i) mask + } + + // correct bit with H(i) mask + wMissed ^= byBitMask; // clear this missed bit + + // parity odd -> wrong data value + if (Parity((BYTE) ((wData & byEmask[i]) ^ ((wData & wMi) >> 8)))) + wData ^= byBitMask; // correct value + } + return wData & 0xFF; // only data byte is correct +} + +VOID IrPrinter(BYTE c) +{ + static INT nFrame = 0; // frame counter + static DWORD dwData = 0; // half bit data container + static INT nStart = 0; // frame counter disabled + + BOOL bLSRQ; + + dwData = (dwData << 1) | (c & LBO); // grab the last 32 bit send through IR + + // Led Service ReQuest on Led Buffer Empty enabled + bLSRQ = (Chipset.IORam[LCR] & ELBE) != 0; + + IOBit(SRQ2,LSRQ,bLSRQ); // update LSRQ bit + if (bLSRQ) // interrupt on Led Buffer Empty enabled + { + Chipset.SoftInt = TRUE; // execute interrupt + bInterrupt = TRUE; + } + + // HP40G and HP49G have no IR transmitter Led + if ((cCurrentRomType == 'E' && nCurrentClass == 40) || cCurrentRomType == 'X') + return; + + if (nFrame == 0) // waiting for start bit condition + { + if ((dwData & 0x3F) == 0x07) // start bit condition (000111 pattern) + { + nStart = 1; // enable frame counter + } + } + + if (nFrame == 24) // 24 half bit received + { + INT i; + + WORD wData = 0; // data container + WORD wMissed = 0; // missed bit container + INT nCount = 0; // no. of missed bits + + nFrame = 0; // reset for next character + nStart = 0; // disable frame counter + + // separate to data and missed bits + for (i = 0; i < 12; ++i) // 12 bit frames + { + BYTE b = (BYTE) (dwData & 3); // last 2 half bits + + if (b == 0x0 || b == 0x3) // illegal half bit combination + { + wMissed |= (1 << i); // this is a missed bit + ++nCount; // incr. number of missed bits + } + else // valid data bit + { + wData |= ((b >> 1) << i); // add data bit + } + dwData >>= 2; // next 2 half bits + } + + if (nCount <= 2) // error can be fixed + { + BYTE byOrgParity,byNewParity; + + byOrgParity = wData >> 8; // the original parity information with missed bits + byNewParity = ~(wMissed >> 8); // missed bit mask for recalculated parity + + if (nCount > 0) // error correction + { + wData = CorrectData(wData,wMissed); + } + + wData &= 0xFF; // remove parity information + + // recalculate parity data + byNewParity &= CreateCorrectionBits((BYTE) wData); + + // wrong parity + if (byOrgParity != byNewParity) + wData = ERR_CHAR; // character for transfer error + } + else + { + wData = ERR_CHAR; // character for transfer error + } + + SendByteUdp((BYTE) wData); // send data byte + return; + } + nFrame += nStart; // next frame + return; +} diff --git a/Sources/Emu48/RESOURCE.H b/Sources/Emu48/RESOURCE.H index f0ba17e..5339580 100644 --- a/Sources/Emu48/RESOURCE.H +++ b/Sources/Emu48/RESOURCE.H @@ -12,53 +12,57 @@ #define IDR_DEBUG_STACK 106 #define IDB_CHECKBOX 107 #define IDD_ABOUT 108 -#define IDD_SETTINGS 109 -#define IDD_CHOOSEKML 110 -#define IDD_KMLLOG 111 -#define IDD_DISASM 112 -#define IDD_DEBUG 113 -#define IDD_NEWVALUE 114 -#define IDD_ENTERADR 115 -#define IDD_BREAKEDIT 116 -#define IDD_ENTERBREAK 117 -#define IDD_INSTRUCTIONS 118 -#define IDD_WRITEONLYREG 119 -#define IDD_FIND 120 -#define IDD_PROFILE 121 -#define IDD_RPLVIEW 122 -#define IDD_MACROSET 123 -#define IDD_DEBUG_SETTINGS 124 +#define IDD_SET_GENERAL 109 +#define IDD_SET_MEMORY 110 +#define IDD_SET_PERIPHERAL 111 +#define IDD_CHOOSEKML 112 +#define IDD_KMLLOG 113 +#define IDD_DISASM 114 +#define IDD_DEBUG 115 +#define IDD_NEWVALUE 116 +#define IDD_ENTERADR 117 +#define IDD_BREAKEDIT 118 +#define IDD_ENTERBREAK 119 +#define IDD_INSTRUCTIONS 120 +#define IDD_WRITEONLYREG 121 +#define IDD_FIND 122 +#define IDD_PROFILE 123 +#define IDD_RPLVIEW 124 +#define IDD_MACROSET 125 +#define IDD_DEBUG_MEMSAVE 126 +#define IDD_DEBUG_MEMLOAD 127 +#define IDD_DEBUG_SETTINGS 128 #define IDC_REALSPEED 1000 #define IDC_GRAYSCALE 1001 #define IDC_ALWAYSONTOP 1002 #define IDC_ACTFOLLOWSMOUSE 1003 -#define IDC_AUTOSAVE 1004 -#define IDC_AUTOSAVEONEXIT 1005 -#define IDC_OBJECTLOADWARNING 1006 -#define IDC_ALWAYSDISPLOG 1007 -#define IDC_PORT1EN 1008 -#define IDC_PORT1WR 1009 -#define IDC_PORT2ISSHARED 1010 -#define IDC_PORT2WR 1011 -#define IDC_PORT2 1012 -#define IDC_PORT2LOAD 1013 -#define IDC_WIRE 1014 -#define IDC_IR 1015 -#define IDC_EMUDIR 1016 -#define IDC_EMUDIRSEL 1017 -#define IDC_UPDATE 1018 -#define IDC_KMLSCRIPT 1019 -#define IDC_AUTHOR 1020 -#define IDC_TITLE 1021 -#define IDC_KMLLOG 1022 -#define IDC_VERSION 1023 -#define IDC_LICENSE 1024 -#define IDC_DISASM_WIN 1025 -#define IDC_DISASM_MAP 1026 -#define IDC_DISASM_ROM 1027 -#define IDC_DISASM_RAM 1028 -#define IDC_DISASM_PORT1 1029 -#define IDC_DISASM_PORT2 1030 +#define IDC_SINGLEINSTANCE 1004 +#define IDC_AUTOSAVE 1005 +#define IDC_AUTOSAVEONEXIT 1006 +#define IDC_OBJECTLOADWARNING 1007 +#define IDC_ALWAYSDISPLOG 1008 +#define IDC_PORT1EN 1009 +#define IDC_PORT1WR 1010 +#define IDC_PORT2ISSHARED 1011 +#define IDC_PORT2WR 1012 +#define IDC_PORT2 1013 +#define IDC_PORT2LOAD 1014 +#define IDC_IR_ADDR 1015 +#define IDC_IR_PORT 1016 +#define IDC_WIRE 1017 +#define IDC_IR 1018 +#define IDC_EMUDIR 1019 +#define IDC_EMUDIRSEL 1020 +#define IDC_UPDATE 1021 +#define IDC_KMLSCRIPT 1022 +#define IDC_AUTHOR 1023 +#define IDC_TITLE 1024 +#define IDC_KMLLOG 1025 +#define IDC_VERSION 1026 +#define IDC_LICENSE 1027 +#define IDC_DISASM_WIN 1028 +#define IDC_DISASM_MODE_TEXT 1029 +#define IDC_DISASM_MODE 1030 #define IDC_DISASM_MODULE 1031 #define IDC_DISASM_HP 1032 #define IDC_DISASM_CLASS 1033 @@ -109,55 +113,59 @@ #define IDC_DEBUG_MEM_COL6 1078 #define IDC_DEBUG_MEM_COL7 1079 #define IDC_DEBUG_MEM_TEXT 1080 -#define IDC_DEBUG_STACK 1081 -#define IDC_STATIC_BREAKPOINT 1082 -#define IDC_BREAKEDIT_ADD 1083 -#define IDC_BREAKEDIT_DELETE 1084 -#define IDC_BREAKEDIT_WND 1085 -#define IDC_STATIC_MMU 1086 -#define IDC_MMU_IO_A 1087 -#define IDC_MMU_NCE2_A 1088 -#define IDC_MMU_CE1_A 1089 -#define IDC_MMU_CE2_A 1090 -#define IDC_MMU_NCE3_A 1091 -#define IDC_MMU_IO_S 1092 -#define IDC_MMU_CE1_S 1093 -#define IDC_MMU_CE2_S 1094 -#define IDC_MMU_NCE2_S 1095 -#define IDC_MMU_NCE3_S 1096 -#define IDC_STATIC_MISC 1097 -#define IDC_MISC_BS_TXT 1098 -#define IDC_INSTR_TEXT 1099 -#define IDC_INSTR_CODE 1100 -#define IDC_INSTR_COPY 1101 -#define IDC_INSTR_CLEAR 1102 -#define IDC_PROFILE_LASTCYCLES 1103 -#define IDC_PROFILE_LASTTIME 1104 -#define IDC_BPCODE 1105 -#define IDC_BPRPL 1106 -#define IDC_BPACCESS 1107 -#define IDC_BPREAD 1108 -#define IDC_BPWRITE 1109 -#define IDC_FIND_DATA 1110 -#define IDC_FIND_ASCII 1111 -#define IDC_FIND_CASE 1112 -#define IDC_ADDR20_24 1113 -#define IDC_ADDR25_27 1114 -#define IDC_ADDR28_29 1115 -#define IDC_ADDR30_34 1116 -#define IDC_RPLVIEW_DATA 1117 -#define IDC_MACRO_SLOW 1118 -#define IDC_MACRO_FAST 1119 -#define IDC_MACRO_SLIDER 1120 -#define IDC_MACRO_REAL 1121 -#define IDC_MACRO_MANUAL 1122 -#define IDC_SOUND_SLIDER 1123 -#define IDC_SOUND_SPEAKER 1124 -#define IDC_SOUND_WAVE 1125 -#define IDC_DEBUG_SET_SYMB 1126 -#define IDC_DEBUG_SET_MODEL 1127 -#define IDC_DEBUG_SET_FILE 1128 -#define IDC_DEBUG_SET_BROWSE 1129 +#define IDC_DEBUG_DATA_FILE 1081 +#define IDC_DEBUG_DATA_BUT 1082 +#define IDC_DEBUG_DATA_STARTADDR 1083 +#define IDC_DEBUG_DATA_ENDADDR 1084 +#define IDC_DEBUG_SET_SYMB 1085 +#define IDC_DEBUG_SET_MODEL 1086 +#define IDC_DEBUG_SET_FILE 1087 +#define IDC_DEBUG_SET_BROWSE 1088 +#define IDC_DEBUG_STACK 1089 +#define IDC_STATIC_BREAKPOINT 1090 +#define IDC_BREAKEDIT_ADD 1091 +#define IDC_BREAKEDIT_DELETE 1092 +#define IDC_BREAKEDIT_WND 1093 +#define IDC_STATIC_MMU 1094 +#define IDC_MMU_IO_A 1095 +#define IDC_MMU_NCE2_A 1096 +#define IDC_MMU_CE1_A 1097 +#define IDC_MMU_CE2_A 1098 +#define IDC_MMU_NCE3_A 1099 +#define IDC_MMU_IO_S 1100 +#define IDC_MMU_CE1_S 1101 +#define IDC_MMU_CE2_S 1102 +#define IDC_MMU_NCE2_S 1103 +#define IDC_MMU_NCE3_S 1104 +#define IDC_STATIC_MISC 1105 +#define IDC_MISC_BS_TXT 1106 +#define IDC_INSTR_TEXT 1107 +#define IDC_INSTR_CODE 1108 +#define IDC_INSTR_COPY 1109 +#define IDC_INSTR_CLEAR 1110 +#define IDC_PROFILE_LASTCYCLES 1111 +#define IDC_PROFILE_LASTTIME 1112 +#define IDC_BPCODE 1113 +#define IDC_BPRPL 1114 +#define IDC_BPACCESS 1115 +#define IDC_BPREAD 1116 +#define IDC_BPWRITE 1117 +#define IDC_FIND_DATA 1118 +#define IDC_FIND_ASCII 1119 +#define IDC_FIND_CASE 1120 +#define IDC_ADDR20_24 1121 +#define IDC_ADDR25_27 1122 +#define IDC_ADDR28_29 1123 +#define IDC_ADDR30_34 1124 +#define IDC_RPLVIEW_DATA 1125 +#define IDC_MACRO_SLOW 1126 +#define IDC_MACRO_FAST 1127 +#define IDC_MACRO_SLIDER 1128 +#define IDC_MACRO_REAL 1129 +#define IDC_MACRO_MANUAL 1130 +#define IDC_SOUND_SLIDER 1131 +#define IDC_SOUND_SPEAKER 1132 +#define IDC_SOUND_WAVE 1133 #define ID_FILE_NEW 40001 #define ID_FILE_OPEN 40002 #define ID_FILE_SAVE 40003 @@ -215,23 +223,25 @@ #define ID_DEBUG_MEM_CE1 40057 #define ID_DEBUG_MEM_CE2 40058 #define ID_DEBUG_MEM_NCE3 40059 -#define ID_DEBUG_MEM_RPLVIEW 40060 -#define ID_DEBUG_STACK_PUSH 40061 -#define ID_DEBUG_STACK_POP 40062 -#define ID_DEBUG_STACK_MODIFY 40063 -#define ID_INTR_STEPOVERINT 40064 -#define ID_INFO_LASTINSTRUCTIONS 40065 -#define ID_INFO_PROFILE 40066 -#define ID_INFO_WRITEONLYREG 40067 +#define ID_DEBUG_MEM_SAVE 40060 +#define ID_DEBUG_MEM_LOAD 40061 +#define ID_DEBUG_MEM_RPLVIEW 40062 +#define ID_DEBUG_STACK_PUSH 40063 +#define ID_DEBUG_STACK_POP 40064 +#define ID_DEBUG_STACK_MODIFY 40065 +#define ID_INTR_STEPOVERINT 40066 +#define ID_INFO_LASTINSTRUCTIONS 40067 +#define ID_INFO_PROFILE 40068 +#define ID_INFO_WRITEONLYREG 40069 #define ID_FILE_MRU_FILE1 40100 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 125 -#define _APS_NEXT_COMMAND_VALUE 40068 -#define _APS_NEXT_CONTROL_VALUE 1130 +#define _APS_NEXT_RESOURCE_VALUE 132 +#define _APS_NEXT_COMMAND_VALUE 40070 +#define _APS_NEXT_CONTROL_VALUE 1134 #define _APS_NEXT_SYMED_VALUE 108 #endif #endif diff --git a/Sources/Emu48/RPL.C b/Sources/Emu48/RPL.C index 21aecc9..76fcbec 100644 --- a/Sources/Emu48/RPL.C +++ b/Sources/Emu48/RPL.C @@ -390,10 +390,10 @@ DWORD RPL_CreateTemp(DWORD l) Write5(TEMPTOP, a+l); // adjust new end of top object Write5(RSKTOP, b+l); // adjust new end of rtn stack Write5(AVMEM, (c-b-l)/5); // calculate free memory (*5 nibbles) - p = HeapAlloc(hHeap,0,b-a); // move down rtn stack + p = malloc(b-a); // move down rtn stack Npeek(p,a,b-a); Nwrite(p,a+l,b-a); - HeapFree(hHeap,0,p); + free(p); Write5(a+l-5,l); // set object length field return (a+1); // return base address of new object } diff --git a/Sources/Emu48/SERIAL.C b/Sources/Emu48/SERIAL.C index 467748c..ea8b60e 100644 --- a/Sources/Emu48/SERIAL.C +++ b/Sources/Emu48/SERIAL.C @@ -113,11 +113,11 @@ BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort) _tcscat(szDevice,strPort); // device name hComm = CreateFile(szDevice, - GENERIC_READ | GENERIC_WRITE, + GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (hComm != INVALID_HANDLE_VALUE) @@ -140,7 +140,7 @@ BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort) hCThreadTxd = CreateThread(NULL,0,&TransmitThread,NULL,CREATE_SUSPENDED,&dwThreadId); _ASSERT(hCThreadTxd); SetThreadPriority(hCThreadTxd,THREAD_PRIORITY_ABOVE_NORMAL); - ResumeThread(hCThreadTxd); // start thread + ResumeThread(hCThreadTxd); // start thread // create Comm event handler bReading = FALSE; @@ -148,7 +148,7 @@ BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort) hCThreadEv = CreateThread(NULL,0,&EventThread,NULL,CREATE_SUSPENDED,&dwThreadId); _ASSERT(hCThreadEv); SetThreadPriority(hCThreadEv,THREAD_PRIORITY_ABOVE_NORMAL); - ResumeThread(hCThreadEv); // start thread + ResumeThread(hCThreadEv); // start thread while (!bReading) Sleep(0); // wait for SerialThread started } else diff --git a/Sources/Emu48/SETTINGS.C b/Sources/Emu48/SETTINGS.C index 8d60e8e..2458471 100644 --- a/Sources/Emu48/SETTINGS.C +++ b/Sources/Emu48/SETTINGS.C @@ -63,7 +63,7 @@ static VOID ReadReg(LPCTSTR lpSubKey, LPCTSTR lpValueName, LPBYTE lpData, DWORD lstrcat(lpKey, lpSubKey); // full registry key retCode = RegOpenKeyEx(HKEY_CURRENT_USER, - lpKey, + lpKey, 0, KEY_QUERY_VALUE, &hKey); @@ -91,9 +91,9 @@ static BOOL WriteReg(LPCTSTR lpSubKey, LPCTSTR lpValueName, DWORD dwType, CONST retCode = RegCreateKeyEx(HKEY_CURRENT_USER, lpKey, 0,_T(""), - REG_OPTION_NON_VOLATILE, + REG_OPTION_NON_VOLATILE, KEY_WRITE, - NULL, + NULL, &hKey, &dwDisposition); _ASSERT(retCode == ERROR_SUCCESS); @@ -113,7 +113,7 @@ static BOOL DelReg(LPCTSTR lpSubKey, LPCTSTR lpValueName) lstrcat(lpKey, lpSubKey); // full registry key retCode = RegOpenKeyEx(HKEY_CURRENT_USER, - lpKey, + lpKey, 0, KEY_SET_VALUE, &hKey); @@ -179,6 +179,7 @@ VOID ReadSettings(VOID) // Emulator bAlwaysOnTop = ReadInt(_T("Emulator"),_T("AlwaysOnTop"),bAlwaysOnTop); bActFollowsMouse = ReadInt(_T("Emulator"),_T("ActivationFollowsMouse"),bActFollowsMouse); + bSingleInstance = ReadInt(_T("Emulator"),_T("SingleInstance"),bSingleInstance); bRealSpeed = ReadInt(_T("Emulator"),_T("RealSpeed"),bRealSpeed); dwSXCycles = ReadInt(_T("Emulator"),_T("SXCycles"),dwSXCycles); dwGXCycles = ReadInt(_T("Emulator"),_T("GXCycles"),dwGXCycles); @@ -187,12 +188,15 @@ VOID ReadSettings(VOID) bGrayscale = ReadInt(_T("Emulator"),_T("Grayscale"),bGrayscale); bWaveBeep = ReadInt(_T("Emulator"),_T("WaveBeep"),bWaveBeep); dwWaveVol = ReadInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol); - SetSpeed(bRealSpeed); // set speed // LowBat bLowBatDisable = ReadInt(_T("LowBat"),_T("Disable"),bLowBatDisable); // Macro bMacroRealSpeed = ReadInt(_T("Macro"),_T("RealSpeed"),bMacroRealSpeed); nMacroTimeout = ReadInt(_T("Macro"),_T("ReplayTimeout"),nMacroTimeout); + dwMacroMinDelay = ReadInt(_T("Macro"),_T("KeyMinDelay"),dwMacroMinDelay); + // IrPrinter + ReadString(_T("IrPrinter"),_T("Address"),szUdpServer,szUdpServer,ARRAYSIZEOF(szUdpServer)); + wUdpPort = ReadInt(_T("IrPrinter"),_T("Port"),wUdpPort); // Serial ReadString(_T("Serial"),_T("Wire"),_T(NO_SERIAL),szSerialWire,ARRAYSIZEOF(szSerialWire)); ReadString(_T("Serial"),_T("Ir"),_T(NO_SERIAL),szSerialIr,ARRAYSIZEOF(szSerialIr)); @@ -222,6 +226,7 @@ VOID WriteSettings(VOID) // Emulator WriteInt(_T("Emulator"),_T("AlwaysOnTop"),bAlwaysOnTop); WriteInt(_T("Emulator"),_T("ActivationFollowsMouse"),bActFollowsMouse); + WriteInt(_T("Emulator"),_T("SingleInstance"),bSingleInstance); WriteInt(_T("Emulator"),_T("RealSpeed"),bRealSpeed); WriteInt(_T("Emulator"),_T("SXCycles"),dwSXCycles); WriteInt(_T("Emulator"),_T("GXCycles"),dwGXCycles); @@ -235,6 +240,10 @@ VOID WriteSettings(VOID) // Macro WriteInt(_T("Macro"),_T("RealSpeed"),bMacroRealSpeed); WriteInt(_T("Macro"),_T("ReplayTimeout"),nMacroTimeout); + WriteInt(_T("Macro"),_T("KeyMinDelay"),dwMacroMinDelay); + // IrPrinter + WriteString(_T("IrPrinter"),_T("Address"),szUdpServer); + WriteInt(_T("IrPrinter"),_T("Port"),wUdpPort); // Serial WriteString(_T("Serial"),_T("Wire"),szSerialWire); WriteString(_T("Serial"),_T("Ir"),szSerialIr); diff --git a/Sources/Emu48/STACK.C b/Sources/Emu48/STACK.C index 75b7eea..d10fd32 100644 --- a/Sources/Emu48/STACK.C +++ b/Sources/Emu48/STACK.C @@ -88,7 +88,7 @@ static INT RPL_SetZInt(LPCTSTR cp,LPBYTE pbyNum,INT nSize) } // nStrLen = no. of digits without sign - if (nStrLen >= nSize) // destination buffer too small + if (nStrLen >= nSize) // destination buffer too small return 0; nNumSize = nStrLen + 1; // no. of written data @@ -128,6 +128,7 @@ static INT RPL_GetBcd(BYTE CONST *pbyNum,INT nMantLen,INT nExpLen,CONST TCHAR cD i = 0; // first character bPflag = FALSE; // show no decimal point + bExpflag = FALSE; // show no exponent // scan mantissa for (v = (LONG) nMantLen - 1; v >= 0 || bPflag; v--) @@ -225,7 +226,7 @@ static INT RPL_SetBcd(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPBYT if (*cp != cDec) // no decimal point { // count integer part - while (*cp >= _T('0') && *cp <= _T('9')) + while (*cp >= _T('0') && *cp <= _T('9')) byNum[++nIp] = *cp++ - _T('0'); if (!nIp) return 0; } @@ -402,7 +403,7 @@ static INT RPL_SetComplex(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,L } } } - HeapFree(hHeap,0,pszData); + free(pszData); } return nLen; } @@ -460,12 +461,12 @@ static INT DoInt(DWORD dwAddress,LPTSTR cp,INT nSize) if (nIntLen <= 0) return 0; // error in calculator object nLength = 0; - if ((lpbyData = HeapAlloc(hHeap,0,nIntLen))) + if ((lpbyData = malloc(nIntLen))) { // get precisition integer object content and decode it Npeek(lpbyData,dwAddress+5,nIntLen); nLength = RPL_GetZInt(lpbyData,nIntLen,cp,nSize); - HeapFree(hHeap,0,lpbyData); + free(lpbyData); } return nLength; } @@ -551,7 +552,7 @@ LRESULT OnStackCopy(VOID) // copy data from stack if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,dwSize)) == NULL) goto error; - if ((lpbyData = GlobalLock(hClipObj))) + if ((lpbyData = (LPBYTE) GlobalLock(hClipObj))) { // copy data to memory CopyMemory(lpbyData,cBuffer,dwSize); @@ -572,7 +573,7 @@ LRESULT OnStackCopy(VOID) // copy data from stack if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,dwSize + 1)) == NULL) goto error; - if ((lpbyData = GlobalLock(hClipObj))) // lock memory + if ((lpbyData = (LPBYTE) GlobalLock(hClipObj))) // lock memory { // copy data into clipboard buffer for (dwAddress += 5;dwSize-- > 0;dwAddress += 2,++lpbyData) @@ -580,8 +581,8 @@ LRESULT OnStackCopy(VOID) // copy data from stack *lpbyData = 0; // set EOS GlobalUnlock(hClipObj); // unlock memory - uClipboardFormat = CF_TEXT; // always text } + uClipboardFormat = CF_TEXT; // always text break; default: MessageBeep(MB_OK); // error beep @@ -737,7 +738,7 @@ LRESULT OnStackPaste(VOID) // paste data to stack // any other format { DWORD dwSize = lstrlen(lpstrClipdata); - if ((lpbyData = HeapAlloc(hHeap,0,dwSize * 2))) + if ((lpbyData = malloc(dwSize * 2))) { LPBYTE lpbySrc,lpbyDest; DWORD dwLoop; @@ -776,7 +777,7 @@ LRESULT OnStackPaste(VOID) // paste data to stack // push object to stack RPL_Push(1,dwAddress); } - HeapFree(hHeap,0,lpbyData); + free(lpbyData); } } } diff --git a/Sources/Emu48/SYMBFILE.C b/Sources/Emu48/SYMBFILE.C index 3784887..f0d609d 100644 --- a/Sources/Emu48/SYMBFILE.C +++ b/Sources/Emu48/SYMBFILE.C @@ -171,7 +171,7 @@ BOOL RplLoadTable(LPCTSTR lpszFilename) *pcPtr = 0; // set EOS // allocate symbol memory - VERIFY(pData = HeapAlloc(hHeap,0,sizeof(RefData))); + VERIFY(pData = malloc(sizeof(RefData))); pData->lpszName = DuplicateString(szSymbolName); pData->dwAddr = GetBigEndian(byPage+dwPageIndex+38,sizeof(DWORD)); @@ -209,8 +209,8 @@ VOID RplDeleteTable(VOID) while (ppsBase[i] != NULL) // walk through all datasets { pData = ppsBase[i]->pNext; - HeapFree(hHeap,0,ppsBase[i]->lpszName); - HeapFree(hHeap,0,ppsBase[i]); + free(ppsBase[i]->lpszName); + free(ppsBase[i]); ppsBase[i] = pData; } } diff --git a/Sources/Emu48/TIMER.C b/Sources/Emu48/TIMER.C index fc830bf..678ad02 100644 --- a/Sources/Emu48/TIMER.C +++ b/Sources/Emu48/TIMER.C @@ -244,7 +244,6 @@ static void CALLBACK TimeProc(UINT uEventId, UINT uMsg, DWORD_PTR dwUser, DWORD_ UNREFERENCED_PARAMETER(dw2); } - VOID SetHP48Time(VOID) // set date and time { SYSTEMTIME ts; @@ -257,7 +256,7 @@ VOID SetHP48Time(VOID) // set date and time GetLocalTime(&ts); // local time, _ftime() cause memory/resource leaks - // calculate days until 01.01.1970 + // calculate days until 01.01.0000 (Erlang BIF localtime/0) dw = (DWORD) ts.wMonth; if (dw > 2) dw -= 3L; @@ -269,17 +268,18 @@ VOID SetHP48Time(VOID) // set date and time dw = (DWORD) ts.wDay + (153L * dw + 2L) / 5L; dw += (146097L * (((DWORD) ts.wYear) / 100L)) / 4L; dw += (1461L * (((DWORD) ts.wYear) % 100L)) / 4L; - dw -= 719469L; + dw += (-719469L + 719528L); // days from year 0 + + ticks = (ULONGLONG) dw; // convert to 64 bit // convert into seconds and add time - dw = dw * 24L + (DWORD) ts.wHour; - dw = dw * 60L + (DWORD) ts.wMinute; - dw = dw * 60L + (DWORD) ts.wSecond; + ticks = ticks * 24L + (ULONGLONG) ts.wHour; + ticks = ticks * 60L + (ULONGLONG) ts.wMinute; + ticks = ticks * 60L + (ULONGLONG) ts.wSecond; // create timerticks = (s + ms) * 8192 - ticks = ((ULONGLONG) dw << 13) | (((ULONGLONG) ts.wMilliseconds << 10) / 125); + ticks = (ticks << 13) | (((ULONGLONG) ts.wMilliseconds << 10) / 125); - ticks += UNIX_0_TIME; // add offset ticks from year 0 ticks += Chipset.t2; // add actual timer2 value time = ticks; // save for calc. timeout diff --git a/Sources/Emu48/UDP.C b/Sources/Emu48/UDP.C new file mode 100644 index 0000000..753066a --- /dev/null +++ b/Sources/Emu48/UDP.C @@ -0,0 +1,85 @@ +/* + * udp.c + * + * This file is part of Emu48 + * + * Copyright (C) 2011 Christoph Gießelink + * + */ +#include "pch.h" +#include "Emu48.h" + +TCHAR szUdpServer[1024] = _T("localhost"); +WORD wUdpPort = 5025; // scpi-raw + +static IN_ADDR ip_addr = { 255, 255, 255, 255 }; + +VOID ResetUdp(VOID) +{ + ip_addr.s_addr = INADDR_NONE; // invalidate saved UDP address + return; +} + +BOOL SendByteUdp(BYTE byData) +{ + WSADATA wsd; + SOCKET sClient; + SOCKADDR_IN sServer; + + BOOL bErr = TRUE; + + VERIFY(WSAStartup(MAKEWORD(1,1),&wsd) == 0); + + if (ip_addr.s_addr == INADDR_NONE) // IP address not specified + { + LPSTR lpszIpAddr; + + #if defined _UNICODE + DWORD dwLength = lstrlen(szUdpServer) + 1; + + if ((lpszIpAddr = (LPSTR) malloc(dwLength)) == NULL) + return TRUE; // server not found + + WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, + szUdpServer, dwLength, + lpszIpAddr, dwLength, NULL, NULL); + #else + lpszIpAddr = szUdpServer; + #endif + + ip_addr.s_addr = inet_addr(lpszIpAddr); + + // not a valid ip address -> try to get ip address from name server + if (ip_addr.s_addr == INADDR_NONE) + { + PHOSTENT host = gethostbyname(lpszIpAddr); + if (host == NULL) + { + #if defined _UNICODE + free(lpszIpAddr); + #endif + return TRUE; // server not found + } + + ip_addr.s_addr = ((PIN_ADDR) host->h_addr_list[0])->s_addr; + } + #if defined _UNICODE + free(lpszIpAddr); + #endif + } + + // create UDP socket + if ((sClient = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET) + { + sServer.sin_family = AF_INET; + sServer.sin_port = htons(wUdpPort); + sServer.sin_addr.s_addr = ip_addr.s_addr; + + // transmit data byte + bErr = sendto(sClient, (LPCCH) &byData, sizeof(byData), 0, (LPSOCKADDR) &sServer, sizeof(sServer)) == SOCKET_ERROR; + closesocket(sClient); + } + + WSACleanup(); // cleanup network stack + return bErr; +} diff --git a/Sources/GCCPatch/EMU48GCC.RC b/Sources/GCCPatch/EMU48GCC.RC index 533cae2..55dcc67 100644 --- a/Sources/GCCPatch/EMU48GCC.RC +++ b/Sources/GCCPatch/EMU48GCC.RC @@ -77,12 +77,40 @@ BEGIN BOTTOMMARGIN, 145 END - IDD_SETTINGS, DIALOG + IDD_SET_GENERAL, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 160 - TOPMARGIN, 4 - BOTTOMMARGIN, 280 + RIGHTMARGIN, 244 + VERTGUIDE, 14 + VERTGUIDE, 161 + VERTGUIDE, 168 + VERTGUIDE, 237 + TOPMARGIN, 7 + BOTTOMMARGIN, 127 + END + + IDD_SET_MEMORY, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 244 + VERTGUIDE, 14 + VERTGUIDE, 237 + TOPMARGIN, 7 + BOTTOMMARGIN, 127 + END + + IDD_SET_PERIPHERAL, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 244 + VERTGUIDE, 14 + VERTGUIDE, 147 + VERTGUIDE, 154 + VERTGUIDE, 161 + VERTGUIDE, 237 + TOPMARGIN, 7 + BOTTOMMARGIN, 127 + HORZGUIDE, 82 END IDD_CHOOSEKML, DIALOG @@ -157,6 +185,22 @@ BEGIN BOTTOMMARGIN, 74 END + IDD_DEBUG_MEMSAVE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 257 + TOPMARGIN, 7 + BOTTOMMARGIN, 58 + END + + IDD_DEBUG_MEMLOAD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 257 + TOPMARGIN, 7 + BOTTOMMARGIN, 58 + END + IDD_DEBUG_SETTINGS, DIALOG BEGIN LEFTMARGIN, 7 @@ -252,69 +296,88 @@ FONT 8, "MS Sans Serif" BEGIN ICON IDI_EMU48,IDC_STATIC,7,6,20,20,SS_REALSIZEIMAGE LTEXT "",IDC_VERSION,29,6,151,8,NOT WS_GROUP - LTEXT "Copyright © 2010 Christoph Gießelink && Sébastien Carlier", + LTEXT "Copyright © 2012 Christoph Gießelink && Sébastien Carlier", IDC_STATIC,29,18,181,8 DEFPUSHBUTTON "OK",IDOK,215,12,39,14 EDITTEXT IDC_LICENSE,7,33,247,112,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY END -IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 167, 287 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Settings" +IDD_SET_GENERAL DIALOG DISCARDABLE 0, 0, 251, 134 +STYLE WS_CHILD | WS_VISIBLE | WS_CAPTION +CAPTION "General" FONT 8, "MS Sans Serif" BEGIN CONTROL "Authentic Calculator Speed",IDC_REALSPEED,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,13,100,10 + BS_AUTOCHECKBOX | WS_TABSTOP,14,17,133,10 CONTROL "Enable Virtual LCD Delay",IDC_GRAYSCALE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,25,100,10 - CONTROL "Always On Top",IDC_ALWAYSONTOP,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,37,65,10 - CONTROL "Activation Follows Mouse",IDC_ACTFOLLOWSMOUSE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,49,100,10 + BS_AUTOCHECKBOX | WS_TABSTOP,14,28,133,10 + CONTROL "Always On Top",IDC_ALWAYSONTOP,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,40,133,10 + CONTROL "Activation Follows Mouse",IDC_ACTFOLLOWSMOUSE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,14,52,133,10 + CONTROL "Single Instance",IDC_SINGLEINSTANCE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,14,64,133,10 CONTROL "Automatically Save Files",IDC_AUTOSAVE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,61,89,10 + BS_AUTOCHECKBOX | WS_TABSTOP,14,76,133,10 CONTROL "Automatically Save Files On Exit",IDC_AUTOSAVEONEXIT, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,73,114,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,88,133,10 CONTROL "Show Load Object Warning",IDC_OBJECTLOADWARNING,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,85,102,10 + BS_AUTOCHECKBOX | WS_TABSTOP,14,100,133,10 CONTROL "Always Show KML Compilation Result",IDC_ALWAYSDISPLOG, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,97,133,10 - GROUPBOX "General",IDC_STATIC,7,4,153,107 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,112,133,10 + GROUPBOX "General",IDC_STATIC,7,7,148,120 CONTROL "HP Mnemonics",IDC_DISASM_HP,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,13,125,65,11 + WS_GROUP | WS_TABSTOP,168,21,69,11 CONTROL "Class Mnemonics",IDC_DISASM_CLASS,"Button", - BS_AUTORADIOBUTTON,84,125,70,11 - GROUPBOX "Disassembler",IDC_STATIC,7,114,153,28 - LTEXT "Volume",IDC_STATIC,13,158,24,8 - CONTROL "Slider1",IDC_SOUND_SLIDER,"msctls_trackbar32", - TBS_AUTOTICKS | WS_TABSTOP,39,153,68,18 - CONTROL "Speaker",IDC_SOUND_SPEAKER,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,111,152,43,10 - CONTROL "Wave",IDC_SOUND_WAVE,"Button",BS_AUTORADIOBUTTON,111, - 163,43,10 - GROUPBOX "Sound",IDC_STATIC,7,144,153,34 + BS_AUTORADIOBUTTON,168,35,69,11 + GROUPBOX "Disassembler",IDC_STATIC,161,7,83,120 +END + +IDD_SET_MEMORY DIALOG DISCARDABLE 0, 0, 251, 134 +STYLE WS_CHILD | WS_VISIBLE | WS_CAPTION +CAPTION "Memory" +FONT 8, "MS Sans Serif" +BEGIN CONTROL "Port 1 is Plugged",IDC_PORT1EN,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,13,189,67,10 + WS_TABSTOP,14,20,67,10 CONTROL "Port 1 is Writeable",IDC_PORT1WR,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,84,189,69,10 + BS_AUTOCHECKBOX | WS_TABSTOP,124,20,69,10 CONTROL "Port 2 is Shared",IDC_PORT2ISSHARED,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,201,65,10 + BS_AUTOCHECKBOX | WS_TABSTOP,14,32,65,10 CONTROL "Port 2 is Writeable",IDC_PORT2WR,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,84,201,69,10 - LTEXT "Port 2 File :",IDC_STATIC,13,216,37,8 - EDITTEXT IDC_PORT2,51,214,94,12,ES_AUTOHSCROLL - PUSHBUTTON "...",IDC_PORT2LOAD,145,214,10,12 - GROUPBOX "Memory Cards",IDC_STATIC,7,180,153,51 - LTEXT "Wire:",IDC_STATIC,13,245,17,8 - COMBOBOX IDC_WIRE,31,243,48,42,CBS_DROPDOWNLIST | WS_VSCROLL | + BS_AUTOCHECKBOX | WS_TABSTOP,124,32,69,10 + LTEXT "Port 2 File :",IDC_STATIC,14,47,37,8 + EDITTEXT IDC_PORT2,52,45,175,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_PORT2LOAD,227,45,10,12 + GROUPBOX "Memory Cards",IDC_STATIC,7,7,237,58 +END + +IDD_SET_PERIPHERAL DIALOG DISCARDABLE 0, 0, 251, 134 +STYLE WS_CHILD | WS_VISIBLE | WS_CAPTION +CAPTION "Peripheral" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Volume",IDC_STATIC,14,21,24,8 + CONTROL "Slider1",IDC_SOUND_SLIDER,"msctls_trackbar32", + TBS_AUTOTICKS | WS_TABSTOP,40,16,84,18 + CONTROL "Speaker",IDC_SOUND_SPEAKER,"Button",BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP,135,20,43,10 + CONTROL "Wave",IDC_SOUND_WAVE,"Button",BS_AUTORADIOBUTTON,194,20, + 43,10 + GROUPBOX "Sound",IDC_STATIC,7,7,237,34 + LTEXT "IP Address:",IDC_STATIC,14,60,37,8 + LTEXT "Port:",IDC_STATIC,119,60,16,8 + EDITTEXT IDC_IR_ADDR,14,70,101,12,ES_AUTOHSCROLL + EDITTEXT IDC_IR_PORT,119,70,28,12,ES_NUMBER + GROUPBOX "Infrared Printer",IDC_STATIC,7,43,147,50 + LTEXT "Wire:",IDC_STATIC,168,58,17,8 + COMBOBOX IDC_WIRE,189,56,48,42,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "IR:",IDC_STATIC,89,245,9,8 - COMBOBOX IDC_IR,107,243,48,43,CBS_DROPDOWNLIST | WS_VSCROLL | + LTEXT "IR:",IDC_STATIC,168,74,9,8 + COMBOBOX IDC_IR,189,72,48,43,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - GROUPBOX "Serial Ports",IDC_STATIC,7,233,153,27 - DEFPUSHBUTTON "OK",IDOK,9,266,50,14 - PUSHBUTTON "Cancel",IDCANCEL,107,266,50,14 + GROUPBOX "Serial Ports",IDC_STATIC,161,43,83,50 END IDD_CHOOSEKML DIALOG DISCARDABLE 0, 0, 195, 66 @@ -362,17 +425,10 @@ BEGIN PUSHBUTTON "&Next Address",IDC_DISASM_NEXT,99,144,47,14 PUSHBUTTON "&Copy Data",IDC_DISASM_COPY,150,144,47,14 PUSHBUTTON "Cancel",IDCANCEL,201,144,47,14 + LTEXT "Mapping Mode:",IDC_DISASM_MODE_TEXT,12,17,45,8 + COMBOBOX IDC_DISASM_MODE,60,14,35,90,CBS_DROPDOWNLIST | + WS_TABSTOP GROUPBOX "Module",IDC_DISASM_MODULE,7,5,241,26 - CONTROL "Map",IDC_DISASM_MAP,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,14,16,37,10 - CONTROL "ROM",IDC_DISASM_ROM,"Button",BS_AUTORADIOBUTTON,61,16, - 37,10 - CONTROL "RAM",IDC_DISASM_RAM,"Button",BS_AUTORADIOBUTTON,108,16, - 37,10 - CONTROL "Port 1",IDC_DISASM_PORT1,"Button",BS_AUTORADIOBUTTON, - 155,16,37,10 - CONTROL "Port 2",IDC_DISASM_PORT2,"Button",BS_AUTORADIOBUTTON, - 202,16,37,10 LISTBOX IDC_DISASM_WIN,7,37,241,100,NOT LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP @@ -404,7 +460,7 @@ BEGIN LTEXT "PC=00000",IDC_REG_PC,236,108,33,8 LTEXT "OUT=000",IDC_REG_OUT,192,119,29,8 LTEXT "IN=0000",IDC_REG_IN,240,119,29,8 - LTEXT "ST=0000",IDC_REG_ST,192,130,29,8 + LTEXT "ST=0000",IDC_REG_ST,192,130,29,8 LTEXT "CY=0",IDC_REG_CY,224,130,17,8 LTEXT "Mode=H",IDC_REG_MODE,244,130,25,8 LTEXT "MP=0",IDC_REG_MP,192,140,17,8 @@ -543,6 +599,36 @@ BEGIN PUSHBUTTON "Cancel",IDCANCEL,93,60,50,14 END +IDD_DEBUG_MEMSAVE DIALOG DISCARDABLE 0, 0, 264, 65 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Save Memory Data" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "File:",IDC_STATIC,7,10,14,8 + EDITTEXT IDC_DEBUG_DATA_FILE,25,7,181,14,ES_AUTOHSCROLL + PUSHBUTTON "Browse",IDC_DEBUG_DATA_BUT,207,7,50,14 + LTEXT "Start Address (hexadecimal):",IDC_STATIC,7,30,90,8 + EDITTEXT IDC_DEBUG_DATA_STARTADDR,101,27,37,14 + LTEXT "End Address (hexadecimal):",IDC_STATIC,7,46,88,8 + EDITTEXT IDC_DEBUG_DATA_ENDADDR,101,44,37,14 + PUSHBUTTON "OK",IDOK,207,27,50,14 + PUSHBUTTON "Cancel",IDCANCEL,207,44,50,14 +END + +IDD_DEBUG_MEMLOAD DIALOG DISCARDABLE 0, 0, 264, 65 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Load Memory Data" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "File:",IDC_STATIC,7,10,14,8 + EDITTEXT IDC_DEBUG_DATA_FILE,25,7,181,14,ES_AUTOHSCROLL + PUSHBUTTON "Browse",IDC_DEBUG_DATA_BUT,207,7,50,14 + LTEXT "Start Address (hexadecimal):",IDC_STATIC,7,30,90,8 + EDITTEXT IDC_DEBUG_DATA_STARTADDR,101,27,37,14 + PUSHBUTTON "OK",IDOK,207,27,50,14 + PUSHBUTTON "Cancel",IDCANCEL,207,44,50,14 +END + IDD_DEBUG_SETTINGS DIALOG DISCARDABLE 0, 0, 184, 116 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Debugger Settings" @@ -630,8 +716,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,5,0,0 - PRODUCTVERSION 1,5,0,0 + FILEVERSION 1,5,3,0 + PRODUCTVERSION 1,5,3,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -646,14 +732,14 @@ BEGIN BEGIN BLOCK "04090000" BEGIN - VALUE "CompanyName", "Sebastien Carlier & Christoph Gießelink\0" + VALUE "CompanyName", "Christoph Gießelink & Sebastien Carlier\0" VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0" - VALUE "FileVersion", "1, 5, 0, 0\0" + VALUE "FileVersion", "1, 5, 3, 0\0" VALUE "InternalName", "Emu48\0" - VALUE "LegalCopyright", "Copyright © 2010\0" + VALUE "LegalCopyright", "Copyright © 2012\0" VALUE "OriginalFilename", "Emu48.exe\0" VALUE "ProductName", "Emu48\0" - VALUE "ProductVersion", "1, 5, 0, 0\0" + VALUE "ProductVersion", "1, 5, 3, 0\0" END END BLOCK "VarFileInfo" @@ -819,7 +905,10 @@ BEGIN , GRAYED END MENUITEM SEPARATOR - MENUITEM "RPL Object Viewer...", ID_DEBUG_MEM_RPLVIEW + MENUITEM "&Load Memory Data...", ID_DEBUG_MEM_LOAD + MENUITEM "S&ave Memory Data...", ID_DEBUG_MEM_SAVE + MENUITEM SEPARATOR + MENUITEM "&RPL Object Viewer...", ID_DEBUG_MEM_RPLVIEW END END @@ -860,6 +949,13 @@ END #endif // APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// 24 +// + +1 24 MOVEABLE PURE "Emu48.xml" + ///////////////////////////////////////////////////////////////////////////// // // Accelerator @@ -890,14 +986,6 @@ BEGIN ID_BREAKPOINTS_CODEEDIT "Breakpoint List" END - -///////////////////////////////////////////////////////////////////////////// -// -// Manifest -// - -1 24 MOVEABLE PURE "Emu48.xml" - #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/Sources/GCCPatch/Makefile b/Sources/GCCPatch/Makefile index 3eddb8d..1b17bc0 100644 --- a/Sources/GCCPatch/Makefile +++ b/Sources/GCCPatch/Makefile @@ -22,13 +22,13 @@ TARGET=$(PRJ).exe RSRC=$(PRJ).rc RSRCOBJ=$(PRJ).o -OBJS=cursor.o ddeserv.o debugger.o disasm.o display.o disrpl.o \ +OBJS=cursor.o ddeserv.o debugger.o disasm.o dismem.o display.o disrpl.o \ emu48.o engine.o external.o fetch.o files.o i28f160.o keyboard.o \ - keymacro.o kml.o lowbat.o mru.o mops.o opcodes.o rpl.o serial.o \ - settings.o stack.o symbfile.o timer.o \ + keymacro.o kml.o lowbat.o mru.o mops.o opcodes.o redeye.o \ + rpl.o serial.o settings.o stack.o symbfile.o timer.o udp.o \ $(RSRCOBJ) -LIBS=-lwinmm -lcomctl32 +LIBS=-lwinmm -lcomctl32 -lws2_32 all: $(TARGET) @@ -58,6 +58,9 @@ debugger.o: debugger.c pch.h resource.h emu48.h \ disasm.o: disasm.c pch.h emu48.h types.h $(CC) $(CFLAGS) $(DEFINES) -c -o disasm.o disasm.c +dismem.o: dismem.c pch.h emu48.h + $(CC) $(CFLAGS) $(DEFINES) -c -o dismem.o dismem.c + display.o: display.c pch.h resource.h emu48.h \ types.h io.h kml.h $(CC) $(CFLAGS) $(DEFINES) -c -o display.o display.c @@ -112,6 +115,9 @@ opcodes.o: opcodes.c pch.h emu48.h types.h opcodes.h \ # pch.o: pch.c pch.h # $(CC) $(CFLAGS) $(DEFINES) -c -o pch.o pch.c +redeye.o: redeye.c pch.h emu48.h io.h + $(CC) $(CFLAGS) $(DEFINES) -c -o redeye.o redeye.c + rpl.o: rpl.c pch.h emu48.h types.h io.h $(CC) $(CFLAGS) $(DEFINES) -c -o rpl.o rpl.c @@ -130,6 +136,9 @@ symbfile.o: symbfile.c pch.h emu48.h timer.o: timer.c pch.h emu48.h types.h io.h $(CC) $(CFLAGS) $(DEFINES) -c -o timer.o timer.c +udp.o: udp.c pch.h io.h + $(CC) $(CFLAGS) $(DEFINES) -c -o udp.o udp.c + $(RSRCOBJ): $(RSRC) resource.h emu48.ico dbgtool.bmp checkbox.bmp Emu48.xml windres $(DEFINES) -i $(RSRC) -o $(RSRCOBJ) diff --git a/Sources/GCCPatch/PCH.H b/Sources/GCCPatch/PCH.H index c0ab333..d88913e 100644 --- a/Sources/GCCPatch/PCH.H +++ b/Sources/GCCPatch/PCH.H @@ -45,3 +45,4 @@ int __cdecl _outp(unsigned short, int); #if !defined _ASSERT #define _ASSERT(a) #endif +#define _CrtDumpMemoryLeaks() ((int)0) diff --git a/Sources/GCCPatch/README.TXT b/Sources/GCCPatch/README.TXT index 880055a..d95f105 100644 --- a/Sources/GCCPatch/README.TXT +++ b/Sources/GCCPatch/README.TXT @@ -2,7 +2,7 @@ * Emu48 GCC Version * ********************* -Emu48 is normally compiled with the Microsoft Visual C++ V6.0 compiler. An +Emu48 is normally compiled with the Microsoft Visual C++ 2005 compiler. An alternative is the GCC compiler from the GNU project. A great distribution of the compiler and the necessary files is MinGW at www.mingw.org. @@ -23,6 +23,20 @@ mingw32-make-3.81-20080326.tar.gz binutils-2.18.50-20080109-2.tar.gz gcc-core-3.4.5-20060117-1.tar.gz +or + +gcc-core-4.6.2-1-mingw32-bin.tar.lzma +binutils-2.22-1-mingw32-bin.tar.lzma +libgmp-5.0.1-1-mingw32-dll-10.tar.lzma +libmpc-0.8.1-1-mingw32-dll-2.tar.lzma +libmpfr-2.4.1-1-mingw32-dll-1.tar.lzma +libpthreadgc-2.9.0-mingw32-pre-20110507-2-dll-2.tar.lzma +mingwrt-3.20-mingw32-dev.tar.gz +mingwrt-3.20-mingw32-dll.tar.gz +pthreads-w32-2.9.0-mingw32-pre-20110507-2-dev.tar.lzma +w32api-3.17-2-mingw32-dev.tar.lzma +mingw32-make-3.81-20080326.tar.gz + Older versions of the MinGW package might not work, because there are several bug fixes, especially in the header files, made in the last time. @@ -34,4 +48,4 @@ Many thanks to Pedro A. Arranda Guti compatible. -07/27/10 (c) by Christoph Gießelink +05/03/12 (c) by Christoph Gießelink diff --git a/uninst.exe b/uninst.exe index 742cfe9..84f9566 100755 Binary files a/uninst.exe and b/uninst.exe differ