2019-10-16: Updated to version 61
Signed-off-by: Gwenhael Le Moine <gwenhael.le.moine@gmail.com>
This commit is contained in:
parent
9ed4c0cec5
commit
b29959b1f3
17 changed files with 4397 additions and 4454 deletions
|
@ -87,28 +87,32 @@ h3 { color:red; font-size:1.1em; }
|
|||
</div>
|
||||
<div id="main">
|
||||
<h1><a name=s1>1. General</a></h1>
|
||||
<p>Emu48 is an emulator for the Hewlett Packard HP38G, HP39G,
|
||||
HP40G, HP48SX, HP48GX and HP49G calculator hardware. These calculators
|
||||
are based on the 1LT8 Clarke (HP48SX) and on the Yorke chip.</p>
|
||||
<p><a href="http://hp.giesselink.com/emu42.htm">Emu48</a> is an
|
||||
emulator for the Hewlett Packard HP38G, HP39G, HP40G, HP48SX, HP48GX
|
||||
and HP49G calculator hardware. These calculators are based on the
|
||||
1LT8 Clarke (HP48SX) and on the Yorke chip.</p>
|
||||
<h1><a name=s2>2. Acknowledgements</a></h1>
|
||||
<p>First of all a big thank to Sébastien Carlier for publishing
|
||||
Emu48 v1.0 under the GPL. Without this decision newer versions of the
|
||||
emulator wouldn't have been possible or ports to other similar
|
||||
calculators wouldn't have been made. Also a big thank to Jean-Yves
|
||||
Avenard for his technical assistance in the beginning. Lode Vandevenne
|
||||
spend the PNG image decoder and finally I want to thank all the
|
||||
spent the PNG image decoder and finally I want to thank all the
|
||||
unnamed authors for publishing material about these calculators.</p>
|
||||
<h1><a name=s3>3. ROM Images</a></h1>
|
||||
<p>Emu48 needs an image of a calculator ROM to be able to run. ROM
|
||||
images are valid in a packed (even address lower nibble, odd address
|
||||
higher nibble) or unpacked (one nibble per byte with even address first)
|
||||
<p>Emu48 needs a <a href="https://en.wikipedia.org/wiki/ROM_image">ROM
|
||||
image</a> for each calculator model you want to emulate. ROM images
|
||||
are valid in a packed (even address lower nibble, odd address higher
|
||||
nibble) or unpacked (one nibble per byte with even address first)
|
||||
form.</p>
|
||||
<p>Since fall 2000 the emulator ROM's for the HP38, 39, 40, 48 and 49
|
||||
are freely available on different Internet sites. Because there's no
|
||||
license for the distribution of the ROM images, they aren't included
|
||||
in the Emu48 package. You can still use the classic way extracting
|
||||
them from your own calculator. But in mostly all cases you have to
|
||||
convert the ROM files into the Emu48 ROM format.</p>
|
||||
in the Emu48 package. Since accepting packed ROM images, in most cases
|
||||
converting the given ROM format (which is regulary a packed ROM image)
|
||||
into the native Emu48 ROM format is not necessary any more. You can
|
||||
still use the classic way extracting them from your own calculator.
|
||||
</p>
|
||||
<ul>
|
||||
<li>HP38
|
||||
<p>To upload the ROM of your HP38G, you will need a special aplet
|
||||
|
@ -178,24 +182,24 @@ h3 { color:red; font-size:1.1em; }
|
|||
<p>To install Emu48 you may use the installer package which contain,
|
||||
among the binaries, some HP48 KML scripts or just unzip the emulator
|
||||
and the required emulator skins from archives into an empty directory.
|
||||
Finally you have to copy your ROM images into this directory and
|
||||
adjust the ROM image name to the name used in the corresponding KML
|
||||
script. When you first run Emu48, it will detect the directory in
|
||||
which you installed it, and will write the configuration to the
|
||||
registry at <i>HKCU\Software\Emu48</i>.</p>
|
||||
Finally copy your ROM images into this directory and adjust the ROM
|
||||
image name to the name used in the corresponding KML script. When you
|
||||
first run Emu48, it will detect the directory in which you installed
|
||||
it, and will write the configuration to the registry at
|
||||
<i>HKCU\Software\Emu48</i>.</p>
|
||||
<h1><a name=s5>5. How to Start</a></h1>
|
||||
<p>When Emu48 is installed and you have put valid KML scripts and the
|
||||
corresponding ROM image(s) into your Emu48 installation directory, you
|
||||
can start Emu48. You'll see a "Choose Your KML Script"
|
||||
box.</p>
|
||||
<p>KML scripts in fact define the visual aspect of Emu48, the behavior of
|
||||
the buttons, of the keyboard, ... It's a GREAT way to customize your copy
|
||||
of Emu48.</p>
|
||||
<p>Check that the path in the "Emu48 Directory" text area is
|
||||
correct. Modify it if the directory in which you installed Emu48 is not
|
||||
the directory displayed. Click the refresh button ("V") after
|
||||
modifying it to update the list box or use the ("...") button to
|
||||
start the directory browser.</p>
|
||||
<p>KML (Keyboard Mapping Language) scripts define the visual aspect
|
||||
of Emu48, the behaviour of the buttons, of the keyboard, ... It's a
|
||||
<b>great</b> way to customize your copy of Emu48.</p>
|
||||
<p>Check in this dialog that the path in the "Emu48 Directory"
|
||||
text area points to the directory in which you installed the Emu48 KML
|
||||
files. Click the refresh button ("V") after modifying the
|
||||
directory path manually to update the list box or use the
|
||||
("...") button to start a directory browser.</p>
|
||||
<p>Choose a KML script in the list box for your calculator ROM you put
|
||||
into Emu48's directory.</p>
|
||||
<p>Several HP48 scripts are included in the Emu48 archive:</p>
|
||||
|
@ -218,19 +222,21 @@ h3 { color:red; font-size:1.1em; }
|
|||
</ul>
|
||||
<p>If you want other great scripts, visit Rechlin's great HP archive
|
||||
<a href="http://www.hpcalc.org/"></a></p>
|
||||
<p>And if you are interested in writing new scripts, get the KML 2.0
|
||||
<p>If you are interested in writing new scripts, get the KML 2.0
|
||||
documentation from <a href="http://hp.giesselink.com/emu48.htm">the
|
||||
authors Emu48 page</a>.</p>
|
||||
<p>Once you have selected a script, press OK to start the emulator. In
|
||||
most cases, when Emu48 crash after pressing the OK button, you are using
|
||||
an invalid ROM image. While it's running, you can use the View/Change KML
|
||||
Script... command to change the visual aspect of Emu48.</p>
|
||||
<p>Having selected a script, press OK to start the emulator. In most
|
||||
cases, when Emu48 crash after pressing the OK button, you are using
|
||||
an invalid ROM image. While it's running, you can use the
|
||||
"<a href="#ss10.1">View/Change KML Script...</a>" command to
|
||||
change the visual aspect of Emu48.</p>
|
||||
<h1><a name=s6>6. Command Line</a></h1>
|
||||
<p>The command line syntax is "<i>Emu48 [E48file [Port2file]]</i>".
|
||||
The first parameter sets the filename for the emulation data
|
||||
independent from the "LastDocument" setting, the second
|
||||
parameter the Port2 file. You're not able to set a Port 2 file without
|
||||
setting the emulation data file. The arguments are optional.</p>
|
||||
The first parameter sets the filename of the emulation data
|
||||
independent from the "LastDocument" setting, normally
|
||||
reponsible for opening the last used state file. The second parameter
|
||||
the Port2 file. You're not able to set a Port 2 file without setting
|
||||
the emulation data file. The arguments are optional.</p>
|
||||
<h1><a name=s7>7. Virtual Keyboard</a></h1>
|
||||
<p>There are two ways to use the virtual keyboard on the emulated
|
||||
calculator:</p>
|
||||
|
@ -239,38 +245,41 @@ h3 { color:red; font-size:1.1em; }
|
|||
<li><a href="#keyboard">by PC keyboard</a></li>
|
||||
</ol>
|
||||
<p><a name=mouse></a>
|
||||
The easiest way to use the emulated calculator is using the mouse. The KML
|
||||
script define buttons with an area where mouse input is active. The mouse
|
||||
cursor change from an arrow to a hand cursor in these areas. The state of
|
||||
the virtual key follow the state of your left mouse button. When the mouse
|
||||
cursor leaves the virtual key area the virtual button automatically
|
||||
release. In some cases you need to press more than one key on the
|
||||
emulator. For these cases press the virtual key with the right mouse
|
||||
button. When you release the mouse button or leave the area of the virtual
|
||||
key, the key is still hold. To release all hold virtual buttons, just use
|
||||
the left mouse button again. A single release of a hold virtual key isn't
|
||||
possible.</p>
|
||||
The easiest way to use the emulated calculator is by using the mouse. The
|
||||
KML script defines buttons with an area where mouse clicks take effect.
|
||||
The active area is indicated by changing the cursor from an arrow to a
|
||||
hand cursor. Pressing the left mouse button over an active area will
|
||||
press the virtual button. When the mouse cursor leaves the virtual key
|
||||
area with still the left mouse button pressed, the virtual button is
|
||||
automatically released. The visual aspect of a pressed or released
|
||||
virtual button is defined in the KML script. In some cases you need to
|
||||
press more than one key on the emulator. For these cases press the
|
||||
virtual key with the right mouse button. When you release the mouse
|
||||
button or leave the area of the virtual key, the key is still held.
|
||||
To release all held virtual buttons, just use the left mouse button
|
||||
again. A single release of a hold virtual key isn't possible.</p>
|
||||
<p><a name=keyboard></a>
|
||||
Another convenient way is using the PC keyboard. The KML script language
|
||||
support a large variety of commands to implement this feature. So keyboard
|
||||
usage depends on your used KML script and not on the emulator. Because of
|
||||
this it's impossible to say what's happen when you press a key on the PC
|
||||
keyboard. For further details read the KML 2.0 documentation mentioned
|
||||
before please.</p>
|
||||
supports a large variety of commands to implement this feature. So
|
||||
keyboard usage mostly depends on your used KML script and not on the
|
||||
emulator. Because of this it's impossible to say what's happen when you
|
||||
press a key on the PC keyboard. Some Windows specific accelerator keys
|
||||
like F10 cannot be overloaded by the KML script. For further details
|
||||
read the KML 2.0 documentation mentioned before please.</p>
|
||||
<h1><a name=s8>8. File Menu</a></h1>
|
||||
<h2><a name=ss8.1>8.1 New...</a></h2>
|
||||
<p>Creates a new emulation session. You're asked for a new KML script
|
||||
where you can select the calculator type and skin to emulate.</p>
|
||||
<p>Creates a new emulation session. You're asked for a KML script where
|
||||
you can select the calculator type and skin to emulate.</p>
|
||||
<h2><a name=ss8.2>8.2 Open...</a></h2>
|
||||
<p>Opens an existing emulation session. The emulation continues at the
|
||||
same position where the loaded session was aborted. Loading emulation
|
||||
<p>Opens a previously saved emulation session. The emulation continues
|
||||
at the same position where the session was aborted. Loading emulation
|
||||
sessions made with a different ROM revision may <u>destroy</u> the memory
|
||||
content or may cause other unpredictable results.</p>
|
||||
<h2><a name=ss8.3>8.3 Save</a></h2>
|
||||
<p>Saves the current running session with the actual name.</p>
|
||||
<p>Saves the current session with the actual name.</p>
|
||||
<h2><a name=ss8.4>8.4 Save As...</a></h2>
|
||||
<p>Saves the current running session with a new name. You're also get in
|
||||
this dialog when you Exit a new session without a state file name.</p>
|
||||
<p>Saves the current session with a new name. You're also get this
|
||||
dialog when you Exit a new session without a state file name.</p>
|
||||
<h2><a name=ss8.5>8.5 Close</a></h2>
|
||||
<p>Closes the current session without closing the emulator.</p>
|
||||
<h2><a name=ss8.6>8.6 Settings</a></h2>
|
||||
|
@ -294,10 +303,10 @@ h3 { color:red; font-size:1.1em; }
|
|||
mouse is moved over the emulator window, the emulator is getting the
|
||||
focus and popping up into foreground.</p></li>
|
||||
<li><i>Single Instance</i>
|
||||
<p>When this option is checked, the program is only allowed to run in
|
||||
a single instance. If another running instance is detected, the detected
|
||||
<p>When this option is checked, only one instance of the emulator can
|
||||
be started. If another running instance is detected, the detected
|
||||
instance is set into foreground as active window and get a request to
|
||||
change his state file to the given one by the current instance. Finally
|
||||
change his state file to the given one by the current instance. Then
|
||||
the current instance is terminated.</p></li>
|
||||
<li><i>Automatically Save Files</i>
|
||||
<p>When this option is checked, the current state file will automatically
|
||||
|
@ -305,14 +314,15 @@ h3 { color:red; font-size:1.1em; }
|
|||
emulator program.</p></li>
|
||||
<li><i>Automatically Save Files On Exit</i>
|
||||
<p>When this option is checked, the current state file will be saved
|
||||
automatically at the end when the emulator program is closed.</p></li>
|
||||
automatically when the emulator program is closed.</p></li>
|
||||
<li><i>Show Load Object Warning</i>
|
||||
<p>When this option is checked, you'll get a warning message box when you
|
||||
try to load an object with the <i>Load Object...</i> menu command. If
|
||||
this option is unchecked, the warning will be skipped.</p></li>
|
||||
<li><i>Always Show KML Compilation Result</i>
|
||||
<p>When this option is checked, you see the results of the KML
|
||||
(Keyboard Macro Language) interpreter at every KML script load.</p></li>
|
||||
(Keyboard Mapping Language) interpreter at every KML script load.
|
||||
</p></li>
|
||||
</ul>
|
||||
<h4>8.6.1.2 Section Style</h4>
|
||||
<ul>
|
||||
|
@ -385,21 +395,24 @@ h3 { color:red; font-size:1.1em; }
|
|||
</ul>
|
||||
<h3><a name=ss8.6.3>8.6.3 Settings Peripheral</a></h3>
|
||||
<h4>8.6.3.1 Section Sound</h4>
|
||||
<p>A new implementation of the sound engine made ROM patches for sound
|
||||
output obsolete. The new sound engine emulates the behavior of the beeper
|
||||
output ports and only work in connection with a sound card. Using the
|
||||
internal PC speaker isn't possible any more. The old beeper method with a
|
||||
ROM patch is still working but deprecated, it's strongly recommended to
|
||||
remove all beep patches from your current KML scripts to enable the new
|
||||
sound engine. The support of the old sound implementation by a ROM patch
|
||||
maybe removed in later versions of the emulator and remaining beep
|
||||
patches will corrupt the ROM with an illegal opcode then.
|
||||
<p>A new implementation of the sound engine made ROM patches for sound
|
||||
output obsolete. The new sound engine emulates the behaviour of the
|
||||
beeper output ports and only work in connection with a sound card.
|
||||
Using the legacy PC speaker mode isn't possible any more. The old
|
||||
beeper method with a ROM patch is still working but deprecated, it's
|
||||
strongly recommended to remove all beep patches from your current KML
|
||||
scripts to enable the new sound engine. The support of the old sound
|
||||
implementation by a ROM patch maybe removed in later versions of the
|
||||
emulator and remaining beep patches will corrupt the ROM with an
|
||||
illegal opcode then. Actually the program informs you when
|
||||
detecting ROM beep patches by opening the "KML Script Compilation
|
||||
Result" dialog. To prevent this, remove the ROM beep patches
|
||||
from the KML script.
|
||||
</p>
|
||||
<p>
|
||||
For the sound generation the calculator must know his own CPU strobe
|
||||
<p>For the sound generation the calculator must know his own CPU strobe
|
||||
frequency. On the real calculator the speed depends on various settings
|
||||
like component tolerances, actual temperature, humidity and other
|
||||
variables. The resulting speed is measured by the calculator firmware
|
||||
variables. The actual speed is measured by the calculator firmware
|
||||
at a cold- or at a warmstart and stored in the =CSPEED variable. The
|
||||
content of this calculator variable has direct influence on the
|
||||
resulting frequency and duration. On the emulator the HP48SX CPU
|
||||
|
@ -414,27 +427,24 @@ h3 { color:red; font-size:1.1em; }
|
|||
frequency registry content has been changed since the last
|
||||
measurement, the =CSPEED variable of this session file may contain
|
||||
a wrong frequency value. You easily may discover this by measuring
|
||||
the real duration of a 10s beep. Is the difference to 10s less
|
||||
than 1s everything is ok, if not, you should perform a
|
||||
<u style="color:red">warmstart</u> of the calculator in this
|
||||
session file. Alternatively you may execute a
|
||||
<a href=#ss9.6>Reset Calculator</a>. This recalls the measuring
|
||||
routine and save the result in the speed variable. Both restart
|
||||
variants purge the stack content!
|
||||
the real duration of a 10s beep. A deviance less than 1s is ok,
|
||||
otherwise you should perform a <u style="color:red">warmstart</u>
|
||||
of the calculator in this session file. Alternatively you may
|
||||
execute a <a href=#ss9.6>Reset Calculator</a>. This recalls the
|
||||
measuring routine and save the result in the speed variable. Both
|
||||
restart variants purge the stack content!
|
||||
</p>
|
||||
<ul>
|
||||
<li><i>Volume</i>
|
||||
<p>The output volume can be selected with the Volume slider relative to
|
||||
the Master Volume control.
|
||||
<p>The output volume can be set with the Volume slider relative to
|
||||
the Windows Master Volume control.
|
||||
</p></li>
|
||||
<li><i>Device</i>
|
||||
<p>By default the sound device is set to "Standard Audio", but
|
||||
you can also manually choose the output device. The device name is
|
||||
somehow cut since Window Vista, but the method of reading the device
|
||||
name is used for backwards compatibility to older versions of the
|
||||
Operating System. When you change the Standard Audio device in the
|
||||
Operating System settings dialog, the internal device numbering may
|
||||
change, and so the manually selected audio device.</p></li>
|
||||
<p>By default the sound device is set to "Standard Audio",
|
||||
but you can also manually choose the output device. When you change
|
||||
the Standard Audio device in the Operating System settings dialog,
|
||||
the internal device numbering may change, and so the manually selected
|
||||
audio device.</p></li>
|
||||
</ul>
|
||||
<h4>8.6.3.2 Section Infrared Printer</h4>
|
||||
<p>The emulator has the ability to print data to a HP82240A/B printer
|
||||
|
@ -475,34 +485,34 @@ h3 { color:red; font-size:1.1em; }
|
|||
<h2><a name=ss9.3>9.3 Copy Screen</a></h2>
|
||||
<p>Copy the screen content as bitmap to the clipboard.</p>
|
||||
<h2><a name=ss9.4>9.4 Copy Stack</a></h2>
|
||||
<p>This is only valid for the HP48SX, HP48GX and the HP49G emulation.</p>
|
||||
<p>This menu item is enabled for the HP48SX, HP48GX and the HP49G
|
||||
emulation.</p>
|
||||
<p>Copy a "Real Number", "Complex Number" or
|
||||
"String" object in stack level 1 to the clipboard. On all
|
||||
other objects, the command will be ignored. This prevents sending
|
||||
binary objects to the clipboard.</p>
|
||||
<p>The decimal point (radix mark) of "Real Numbers" in the
|
||||
clipboard is equal to the calculator setting. This point maybe
|
||||
important when you try to paste the numbers into a program using the
|
||||
locale settings of the host operating system.</p>
|
||||
clipboard is equal to the calculator setting. This is important when
|
||||
you try to paste the numbers into a program using the locale settings
|
||||
of the host operating system.</p>
|
||||
<h2><a name=ss9.5>9.5 Paste Stack</a></h2>
|
||||
<p>This is only valid for the HP48SX, HP48GX and the HP49G emulation.</p>
|
||||
<p>This menu item is enabled for the HP48SX, HP48GX and the HP49G
|
||||
emulation.</p>
|
||||
<p>Paste the text field content of the clipboard to stack level 1 of
|
||||
the emulated calculator. If the clipboard content is representing a
|
||||
real number, the number will be saved as "Real Number"
|
||||
object. Is the content a complex number object, the number will be
|
||||
saved as "Complex Number" object, in all other cases as
|
||||
saved as "Complex Number" object, otherwise cases as
|
||||
"String" object.</p>
|
||||
<p>To import "Real or Complex Numbers" from the clipboard,
|
||||
the decimal point (radix mark) of the clipboard and calculator
|
||||
<u>must</u> be equal. A real or complex number is only detected in the
|
||||
case of valid real number characters in the clipboard. Especially
|
||||
heading and tailing white spaces aren't valid number characters
|
||||
also.</p>
|
||||
<p>Complex numbers must be in the form <i>(a,b)</i> when using the
|
||||
point radix mark or in the form <i>(a;b)</i> when using the comma
|
||||
radix mark. The Cartesian or algebraic form <i>a+bi</i> is not
|
||||
supported.</p>
|
||||
<h2><a name=ss9.6>9.6 Reset Calculator</a></h2>
|
||||
<p>To import "Real or Complex Numbers" from the clipboard, the
|
||||
decimal point (radix mark) of the clipboard and calculator <u>must</u>
|
||||
match. A real or complex number is only detected in the case of valid
|
||||
real number characters in the clipboard. Especially heading and tailing
|
||||
white spaces aren't valid number characters also.</p>
|
||||
<p>Complex numbers must be in the form <i>(a,b)</i> when using the point
|
||||
radix mark or in the form <i>(a;b)</i> when using the comma radix mark.
|
||||
The Cartesian or algebraic form <i>a+bi</i> is not supported.</p>
|
||||
<h2><a name=ss9.6>9.6 Reset Calculator</a></h2>
|
||||
<p>This emulates the Reset pin of the internal CPU.</p>
|
||||
<h2><a name=ss9.7>9.7 Backup</a></h2>
|
||||
<h3><a name=ss9.7.1>9.7.1 Backup Save</a></h3>
|
||||
|
@ -511,7 +521,7 @@ h3 { color:red; font-size:1.1em; }
|
|||
<h3><a name=ss9.7.2>9.7.2 Backup Restore</a></h3>
|
||||
<p>This restores a previous saved emulator status without request. If you
|
||||
changed the calculator model meanwhile, the emulator will switch back to
|
||||
the old model.</p>
|
||||
the model used in the backup.</p>
|
||||
<h3><a name=ss9.7.3>9.7.3 Backup Delete</a></h3>
|
||||
<p>This deletes the data in the backup slot.</p>
|
||||
<h1><a name=s10>10. View Menu</a></h1>
|
||||
|
@ -525,22 +535,22 @@ h3 { color:red; font-size:1.1em; }
|
|||
<p>Enter the address to disassemble in hexadecimal into the "Address
|
||||
(HEX)" field and press <Return>. With the "Next Address"
|
||||
button the next opcode is disassembled. With the "Copy Data" button
|
||||
you can copy all selected lines inside the list box to the clipboard.</p>
|
||||
you can copy all selected lines from the list box to the clipboard.</p>
|
||||
<h2><a name=ss11.2>11.2 Debugger...</a></h2>
|
||||
<p>The assembler code debugger of the emulator. For more details refer to the
|
||||
extra documentation of the debugger please.</p>
|
||||
<h2><a name=ss11.3>11.3 Macro</a></h2>
|
||||
<p>The keyboard macro recorder unit.</p>
|
||||
<h3><a name=ss11.3.1>11.3.1 Macro Record...</a></h3>
|
||||
<h3><a name=ss11.3.1>11.3.1 Macro Record...</a></h3>
|
||||
<p>Prompts a dialog to enter the macro file for the data to record. After
|
||||
accepting the confirm message, every key event is recorded into the macro
|
||||
file with it's time information.</p>
|
||||
<h3><a name=ss11.3.2>11.3.2 Macro Play...</a></h3>
|
||||
<h3><a name=ss11.3.2>11.3.2 Macro Play...</a></h3>
|
||||
<p>Prompts a dialog box to ask for the keyboard macro file to play. The
|
||||
replay starts immediately after selecting the file.</p>
|
||||
<h3><a name=ss11.3.3>11.3.3 Macro Stop</a></h3>
|
||||
replay starts immediately after opening the selected file.</p>
|
||||
<h3><a name=ss11.3.3>11.3.3 Macro Stop</a></h3>
|
||||
<p>Stops recording or replaying a keyboard macro file.</p>
|
||||
<h3><a name=ss11.3.4>11.3.4 Macro Settings...</a></h3>
|
||||
<h3><a name=ss11.3.4>11.3.4 Macro Settings...</a></h3>
|
||||
<p>Settings for the Macro Replay mode</p>
|
||||
<ul>
|
||||
<li><i>Real</i>
|
||||
|
@ -550,9 +560,9 @@ h3 { color:red; font-size:1.1em; }
|
|||
</ul>
|
||||
<h1><a name=s12>12. Help Menu</a></h1>
|
||||
<h2><a name=ss12.1>12.1 Help Topics</a></h2>
|
||||
<p>Call this document.</p>
|
||||
<p>Show this document.</p>
|
||||
<h2><a name=ss12.2>12.2 About Emu48...</a></h2>
|
||||
<p>The version, copyright and license message...</p>
|
||||
<p>Show the version, copyright and license message...</p>
|
||||
<h1><a name=s13>13. DDE Server</a></h1>
|
||||
<p>Emu48 has an integrated DDE server to transmit data from and to the HP
|
||||
stack. Because only the HP48 and HP49 have a stack, all DDE transfers
|
||||
|
@ -591,7 +601,7 @@ h3 { color:red; font-size:1.1em; }
|
|||
</table>
|
||||
<h1><a name=s14>14. License</a></h1>
|
||||
<p>Emu48 - A HP38G/39G/40G/48SX/48GX/49G Emulator<br>
|
||||
Copyright (C) 2018 Christoph Gießelink</p>
|
||||
Copyright (C) 2019 Christoph Gießelink</p>
|
||||
<p>This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option)
|
BIN
Emu48.dll
BIN
Emu48.dll
Binary file not shown.
BIN
Emu48.exe
BIN
Emu48.exe
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
Known bugs and restrictions of Emu48 V1.61
|
||||
Known bugs and restrictions of Emu48 V1.62
|
||||
------------------------------------------
|
||||
|
||||
- the following I/O bits aren't emulated (incomplete)
|
||||
|
@ -47,4 +47,4 @@ Known bugs and restrictions of Emu48 V1.61
|
|||
- quitting the emulator while programming the flash isn't allowed,
|
||||
because the content of flash state machine isn't saved so far
|
||||
|
||||
08/14/18 (c) by Christoph Gießelink, c dot giesselink at gmx dot de
|
||||
10/15/19 (c) by Christoph Gießelink, c dot giesselink at gmx dot de
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
Service Pack 59+ based on Emu48 Service Pack 61
|
||||
Service Pack 61+ based on Emu48 Service Pack 62
|
||||
|
||||
See CHANGES.TXT in Emu48 for full history.
|
||||
Only changes specifically made to Emu48+ are shown below.
|
||||
|
||||
Service Pack 60+ for Emu48 Version 1.0
|
||||
|
||||
DISPLAY.C
|
||||
- bugfix in function WriteToMainDisplay() to fix display corruption
|
||||
|
||||
Service Pack 55+ for Emu48 Version 1.0
|
||||
|
||||
DEBUGDLL.C
|
||||
|
@ -42,7 +47,7 @@ MOPS.C
|
|||
bit in the LCR (0x11C) register for apples; the Saturnator has no
|
||||
ELBE bit simulation so the LSRQ bit in SRQ2 register is untouched
|
||||
|
||||
Service Pack 51 for Emu48 Version 1.0
|
||||
Service Pack 51+ for Emu48 Version 1.0
|
||||
|
||||
EMU48DLL.C
|
||||
- bugfix in function DLLCreateWnd(), when starting an emulator
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
|
||||
#define CODELABEL 0x80000000 // label in code window
|
||||
|
||||
// trace log file modes
|
||||
enum TRACE_MODE { TRACE_FILE_NEW = 0, TRACE_FILE_APPEND };
|
||||
|
||||
typedef struct CToolBarData
|
||||
{
|
||||
WORD wVersion;
|
||||
|
@ -81,6 +84,14 @@ static DWORD dwAdrMemFol = 0; // follow address memory window
|
|||
|
||||
static UINT uIDMap = ID_DEBUG_MEM_MAP; // current memory view mode
|
||||
|
||||
static BOOL bDbgTrace = FALSE; // enable trace output
|
||||
static HANDLE hLogFile = NULL; // log file handle
|
||||
static TCHAR szTraceFilename[MAX_PATH] = _T("trace.log"); // filename for trace file
|
||||
static UINT uTraceMode = TRACE_FILE_NEW; // trace log file mode
|
||||
static BOOL bTraceReg = TRUE; // enable register logging
|
||||
static BOOL bTraceMmu = FALSE; // disable MMU logging
|
||||
static BOOL bTraceOpc = TRUE; // enable opcode logging
|
||||
|
||||
static LONG lCharWidth; // width of a character (is a fix font)
|
||||
|
||||
static HMENU hMenuCode,hMenuMem,hMenuStack;// handle of context menues
|
||||
|
@ -108,6 +119,12 @@ static BOOL OnInfoWoRegister(HWND hDlg);
|
|||
static VOID UpdateProfileWnd(HWND hDlg);
|
||||
static BOOL OnMemLoadData(HWND hDlg);
|
||||
static BOOL OnMemSaveData(HWND hDlg);
|
||||
static VOID StartTrace(VOID);
|
||||
static VOID StopTrace(VOID);
|
||||
static VOID FlushTrace(VOID);
|
||||
static VOID OutTrace(VOID);
|
||||
static BOOL OnTraceSettings(HWND hDlg);
|
||||
static BOOL OnTraceEnable(HWND hDlg);
|
||||
|
||||
//################
|
||||
//#
|
||||
|
@ -1768,6 +1785,7 @@ BOOL CheckBreakpoint(DWORD dwAddr, DWORD dwRange, UINT nType)
|
|||
VOID NotifyDebugger(INT nType) // update registers
|
||||
{
|
||||
nRplBreak = nType; // save breakpoint type
|
||||
FlushTrace(); // flush trace buffer
|
||||
_ASSERT(hDlgDebug); // debug dialog box open
|
||||
PostMessage(hDlgDebug,WM_UPDATE,0,0);
|
||||
return;
|
||||
|
@ -1861,6 +1879,7 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM
|
|||
HDC hDC;
|
||||
HFONT hFont;
|
||||
HMENU hSysMenu;
|
||||
HMENU hDbgMenu;
|
||||
INT i;
|
||||
|
||||
switch (message)
|
||||
|
@ -1870,6 +1889,15 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM
|
|||
if (bAlwaysOnTop) SetWindowPos(hDlg,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
|
||||
SendMessage(hDlg,WM_SETICON,ICON_BIG,(LPARAM) LoadIcon(hApp,MAKEINTRESOURCE(IDI_EMU48)));
|
||||
|
||||
bDbgTrace = FALSE; // disable file trace
|
||||
|
||||
// load file trace settings
|
||||
ReadSettingsString(_T("Debugger"),_T("TraceFile"),szTraceFilename,szTraceFilename,ARRAYSIZEOF(szTraceFilename));
|
||||
uTraceMode = ReadSettingsInt(_T("Debugger"),_T("TraceFileMode"),uTraceMode);
|
||||
bTraceReg = ReadSettingsInt(_T("Debugger"),_T("TraceRegister"),bTraceReg);
|
||||
bTraceMmu = ReadSettingsInt(_T("Debugger"),_T("TraceMMU"),bTraceMmu);
|
||||
bTraceOpc = ReadSettingsInt(_T("Debugger"),_T("TraceOpcode"),bTraceOpc);
|
||||
|
||||
// add Settings item to sysmenu
|
||||
_ASSERT((IDM_DEBUG_SETTINGS & 0xFFF0) == IDM_DEBUG_SETTINGS);
|
||||
_ASSERT(IDM_DEBUG_SETTINGS < 0xF000);
|
||||
|
@ -1879,11 +1907,17 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM
|
|||
VERIFY(AppendMenu(hSysMenu,MF_STRING,IDM_DEBUG_SETTINGS,_T("Debugger Settings...")));
|
||||
}
|
||||
|
||||
hDbgMenu = GetMenu(hDlg); // menu of debugger dialog
|
||||
hWndToolbar = CreateToolbar(hDlg); // add toolbar
|
||||
CheckMenuItem(GetMenu(hDlg),ID_BREAKPOINTS_NOP3, bDbgNOP3 ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(GetMenu(hDlg),ID_BREAKPOINTS_DOCODE,bDbgCode ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(GetMenu(hDlg),ID_BREAKPOINTS_RPL, bDbgRPL ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(GetMenu(hDlg),ID_INTR_STEPOVERINT, bDbgSkipInt ? MF_CHECKED : MF_UNCHECKED);
|
||||
|
||||
CheckMenuItem(hDbgMenu,ID_BREAKPOINTS_NOP3, bDbgNOP3 ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hDbgMenu,ID_BREAKPOINTS_DOCODE,bDbgCode ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hDbgMenu,ID_BREAKPOINTS_RPL, bDbgRPL ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hDbgMenu,ID_INTR_STEPOVERINT, bDbgSkipInt ? MF_CHECKED : MF_UNCHECKED);
|
||||
CheckMenuItem(hDbgMenu,ID_TRACE_ENABLE, bDbgTrace ? MF_CHECKED : MF_UNCHECKED);
|
||||
|
||||
EnableMenuItem(hDbgMenu,ID_TRACE_SETTINGS,bDbgTrace ? MF_GRAYED : MF_ENABLED);
|
||||
|
||||
hDlgDebug = hDlg; // handle for debugger dialog
|
||||
hEventDebug = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||
if (hEventDebug == NULL)
|
||||
|
@ -1931,6 +1965,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
|
||||
|
||||
fnOutTrace = OutTrace; // function for file trace
|
||||
RplReadNibble = GetMemNib; // get nibble function for RPL object viewer
|
||||
|
||||
dwDbgStopPC = -1; // no stop address for goto cursor
|
||||
|
@ -1949,6 +1984,7 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM
|
|||
case WM_DESTROY:
|
||||
// SetHP48Time(); // update time & date
|
||||
nDbgState = DBG_OFF; // debugger inactive
|
||||
StopTrace(); // finish trace
|
||||
bInterrupt = TRUE; // exit opcode loop
|
||||
SetEvent(hEventDebug);
|
||||
if (pdwInstrArray) // free last instruction circular buffer
|
||||
|
@ -1965,6 +2001,14 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM
|
|||
GetWindowPlacement(hDlg, &wndpl);
|
||||
nDbgPosX = wndpl.rcNormalPosition.left;
|
||||
nDbgPosY = wndpl.rcNormalPosition.top;
|
||||
|
||||
// save file trace settings
|
||||
WriteSettingsString(_T("Debugger"),_T("TraceFile"),szTraceFilename);
|
||||
WriteSettingsInt(_T("Debugger"),_T("TraceFileMode"),uTraceMode);
|
||||
WriteSettingsInt(_T("Debugger"),_T("TraceRegister"),bTraceReg);
|
||||
WriteSettingsInt(_T("Debugger"),_T("TraceMMU"),bTraceMmu);
|
||||
WriteSettingsInt(_T("Debugger"),_T("TraceOpcode"),bTraceOpc);
|
||||
|
||||
RplDeleteTable(); // delete rpl symbol table
|
||||
DeleteObject(hFontBold); // delete bold font
|
||||
DestroyMenu(hMenuMainCode);
|
||||
|
@ -2023,6 +2067,8 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM
|
|||
case ID_BREAKPOINTS_NOP3: return OnToggleMenuItem(hDlg,LOWORD(wParam),&bDbgNOP3);
|
||||
case ID_BREAKPOINTS_DOCODE: return OnToggleMenuItem(hDlg,LOWORD(wParam),&bDbgCode);
|
||||
case ID_BREAKPOINTS_RPL: return OnToggleMenuItem(hDlg,LOWORD(wParam),&bDbgRPL);
|
||||
case ID_TRACE_SETTINGS: return OnTraceSettings(hDlg);
|
||||
case ID_TRACE_ENABLE: return OnTraceEnable(hDlg);
|
||||
case ID_INFO_LASTINSTRUCTIONS: return OnInfoIntr(hDlg);
|
||||
case ID_INFO_PROFILE: return OnProfile(hDlg);
|
||||
case ID_INFO_WRITEONLYREG: return OnInfoWoRegister(hDlg);
|
||||
|
@ -2199,7 +2245,7 @@ static __inline BOOL OnFindOK(HWND hDlg,BOOL bASCII,DWORD *pdwAddrLast,INT nSear
|
|||
#if defined _UNICODE
|
||||
{
|
||||
// Unicode to byte translation
|
||||
LPTSTR szTmp = DuplicateString((LPTSTR) lpbySearch);
|
||||
LPTSTR szTmp = DuplicateString((LPCTSTR) lpbySearch);
|
||||
if (szTmp != NULL)
|
||||
{
|
||||
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,
|
||||
|
@ -2719,7 +2765,6 @@ static INT_PTR CALLBACK Settings(HWND hDlg, UINT message, WPARAM wParam, LPARAM
|
|||
}
|
||||
}
|
||||
return FALSE;
|
||||
UNREFERENCED_PARAMETER(wParam);
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
}
|
||||
|
||||
|
@ -2783,7 +2828,6 @@ static INT_PTR CALLBACK NewValue(HWND hDlg, UINT message, WPARAM wParam, LPARAM
|
|||
}
|
||||
}
|
||||
return FALSE;
|
||||
UNREFERENCED_PARAMETER(wParam);
|
||||
}
|
||||
|
||||
static INT_PTR OnNewValue(LPTSTR lpszValue)
|
||||
|
@ -2835,7 +2879,6 @@ static INT_PTR CALLBACK EnterAddr(HWND hDlg, UINT message, WPARAM wParam, LPARAM
|
|||
}
|
||||
}
|
||||
return FALSE;
|
||||
UNREFERENCED_PARAMETER(wParam);
|
||||
}
|
||||
|
||||
static VOID OnEnterAddress(HWND hDlg, DWORD *dwValue)
|
||||
|
@ -2888,7 +2931,6 @@ static INT_PTR CALLBACK EnterBreakpoint(HWND hDlg, UINT message, WPARAM wParam,
|
|||
}
|
||||
}
|
||||
return FALSE;
|
||||
UNREFERENCED_PARAMETER(wParam);
|
||||
}
|
||||
|
||||
static VOID OnEnterBreakpoint(HWND hDlg, BP_T *sValue)
|
||||
|
@ -3183,7 +3225,6 @@ static INT_PTR CALLBACK EditBreakpoint(HWND hDlg, UINT message, WPARAM wParam, L
|
|||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
UNREFERENCED_PARAMETER(wParam);
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
}
|
||||
|
||||
|
@ -3569,7 +3610,6 @@ static INT_PTR CALLBACK DebugMemLoad(HWND hDlg, UINT message, WPARAM wParam, LPA
|
|||
}
|
||||
}
|
||||
return FALSE;
|
||||
UNREFERENCED_PARAMETER(wParam);
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
}
|
||||
|
||||
|
@ -3577,7 +3617,6 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -3625,7 +3664,6 @@ static INT_PTR CALLBACK DebugMemSave(HWND hDlg, UINT message, WPARAM wParam, LPA
|
|||
}
|
||||
}
|
||||
return FALSE;
|
||||
UNREFERENCED_PARAMETER(wParam);
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
}
|
||||
|
||||
|
@ -3633,6 +3671,337 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Trace Log
|
||||
//#
|
||||
//################
|
||||
|
||||
static VOID StartTrace(VOID)
|
||||
{
|
||||
if (hLogFile == NULL)
|
||||
{
|
||||
SetCurrentDirectory(szEmuDirectory);
|
||||
hLogFile = CreateFile(
|
||||
szTraceFilename,
|
||||
GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
(uTraceMode == TRACE_FILE_NEW) ? CREATE_ALWAYS : OPEN_ALWAYS,
|
||||
0,
|
||||
NULL);
|
||||
SetCurrentDirectory(szCurrentDirectory);
|
||||
if (hLogFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
InfoMessage(_T("Unable to create trace log file."));
|
||||
hLogFile = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// goto end of file
|
||||
SetFilePointer(hLogFile,0L,NULL,FILE_END);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static VOID StopTrace(VOID)
|
||||
{
|
||||
if (hLogFile != NULL)
|
||||
{
|
||||
CloseHandle(hLogFile);
|
||||
}
|
||||
hLogFile = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
static VOID FlushTrace(VOID)
|
||||
{
|
||||
if (hLogFile != NULL)
|
||||
{
|
||||
VERIFY(FlushFileBuffers(hLogFile));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static __inline void __cdecl PrintTrace(LPCTSTR lpFormat, ...)
|
||||
{
|
||||
TCHAR cOutput[1024];
|
||||
DWORD dwWritten, dwRead;
|
||||
va_list arglist;
|
||||
|
||||
va_start(arglist,lpFormat);
|
||||
dwWritten = (DWORD) wvsprintf(cOutput,lpFormat,arglist);
|
||||
va_end(arglist);
|
||||
#if defined _UNICODE
|
||||
{
|
||||
// Unicode to byte translation
|
||||
LPTSTR szTmp = DuplicateString(cOutput);
|
||||
if (szTmp != NULL)
|
||||
{
|
||||
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,
|
||||
szTmp, -1,
|
||||
(LPSTR) cOutput, sizeof(cOutput), NULL, NULL);
|
||||
free(szTmp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
WriteFile(hLogFile,cOutput,dwWritten,&dwRead,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
static VOID OutTrace(VOID)
|
||||
{
|
||||
enum MEM_MAPPING eMapMode;
|
||||
LPCTSTR lpszName;
|
||||
LPTSTR s,d;
|
||||
TCHAR szBuffer[128];
|
||||
TCHAR szOpc[8];
|
||||
DWORD dwNxtAddr,dwOpcAddr;
|
||||
UINT i;
|
||||
|
||||
if (hLogFile != NULL) // log file opened
|
||||
{
|
||||
if (bTraceReg) // show regs
|
||||
{
|
||||
INT nPos;
|
||||
|
||||
nPos = wsprintf(szBuffer,_T("\r\n A=%s"),RegToStr(Chipset.A,16));
|
||||
nPos += wsprintf(&szBuffer[nPos],_T(" B=%s"),RegToStr(Chipset.B,16));
|
||||
nPos += wsprintf(&szBuffer[nPos],_T(" C=%s"),RegToStr(Chipset.C,16));
|
||||
wsprintf(&szBuffer[nPos],_T(" D=%s\r\n"),RegToStr(Chipset.D,16));
|
||||
PrintTrace(szBuffer);
|
||||
|
||||
nPos = wsprintf(szBuffer,_T(" R0=%s"),RegToStr(Chipset.R0,16));
|
||||
nPos += wsprintf(&szBuffer[nPos],_T(" R1=%s"),RegToStr(Chipset.R1,16));
|
||||
nPos += wsprintf(&szBuffer[nPos],_T(" R2=%s"),RegToStr(Chipset.R2,16));
|
||||
wsprintf(&szBuffer[nPos],_T(" R3=%s\r\n"),RegToStr(Chipset.R3,16));
|
||||
PrintTrace(szBuffer);
|
||||
|
||||
PrintTrace(_T(" R4=%s D0=%05X D1=%05X P=%X CY=%d Mode=%c OUT=%03X IN=%04X\r\n"),
|
||||
RegToStr(Chipset.R4,16),Chipset.d0,Chipset.d1,Chipset.P,Chipset.carry,
|
||||
Chipset.mode_dec ? _T('D') : _T('H'),Chipset.out,Chipset.in);
|
||||
|
||||
PrintTrace(_T(" ST=%s MP=%d SR=%d SB=%d XM=%d IntrEn=%d KeyScan=%d BS=%02X\r\n"),
|
||||
RegToStr(Chipset.ST,4),
|
||||
(Chipset.HST & MP) != 0,(Chipset.HST & SR) != 0,(Chipset.HST & SB) != 0,(Chipset.HST & XM) != 0,
|
||||
Chipset.inte,Chipset.intk,Chipset.Bank_FF & 0x7F);
|
||||
|
||||
// hardware stack content
|
||||
PrintTrace(_T(" Stack="));
|
||||
for (i = 1; i <= ARRAYSIZEOF(Chipset.rstk); ++i)
|
||||
{
|
||||
PrintTrace(_T(" %05X"), Chipset.rstk[(Chipset.rstkp-i)&7]);
|
||||
}
|
||||
PrintTrace(_T("\r\n"));
|
||||
}
|
||||
|
||||
if (bTraceMmu) // show MMU
|
||||
{
|
||||
TCHAR szSize[8],szAddr[8];
|
||||
|
||||
if (!bTraceReg) // no regs
|
||||
{
|
||||
PrintTrace(_T("\r\n")); // add separator line
|
||||
}
|
||||
|
||||
wsprintf(szAddr, Chipset.IOCfig ? _T("%05X") : _T("-----"),Chipset.IOBase);
|
||||
PrintTrace(_T(" I/O=%s"),szAddr);
|
||||
|
||||
wsprintf(szSize, Chipset.P0Cfg2 ? _T("%05X") : _T("-----"),(Chipset.P0Size^0xFF)<<12);
|
||||
wsprintf(szAddr, Chipset.P0Cfig ? _T("%05X") : _T("-----"),Chipset.P0Base<<12);
|
||||
PrintTrace(_T(" NCE2=%s/%s"),szSize,szAddr);
|
||||
|
||||
if (cCurrentRomType=='S')
|
||||
{
|
||||
wsprintf(szSize, Chipset.P1Cfg2 ? _T("%05X") : _T("-----"),(Chipset.P1Size^0xFF)<<12);
|
||||
wsprintf(szAddr, Chipset.P1Cfig ? _T("%05X") : _T("-----"),Chipset.P1Base<<12);
|
||||
}
|
||||
else
|
||||
{
|
||||
wsprintf(szSize, Chipset.BSCfg2 ? _T("%05X") : _T("-----"),(Chipset.BSSize^0xFF)<<12);
|
||||
wsprintf(szAddr, Chipset.BSCfig ? _T("%05X") : _T("-----"),Chipset.BSBase<<12);
|
||||
}
|
||||
PrintTrace(_T(" CE1=%s/%s"),szSize,szAddr);
|
||||
|
||||
if (cCurrentRomType=='S')
|
||||
{
|
||||
wsprintf(szSize, Chipset.P2Cfg2 ? _T("%05X") : _T("-----"),(Chipset.P2Size^0xFF)<<12);
|
||||
wsprintf(szAddr, Chipset.P2Cfig ? _T("%05X") : _T("-----"),Chipset.P2Base<<12);
|
||||
}
|
||||
else
|
||||
{
|
||||
wsprintf(szSize, Chipset.P1Cfg2 ? _T("%05X") : _T("-----"),(Chipset.P1Size^0xFF)<<12);
|
||||
wsprintf(szAddr, Chipset.P1Cfig ? _T("%05X") : _T("-----"),Chipset.P1Base<<12);
|
||||
}
|
||||
PrintTrace(_T(" CE2=%s/%s"),szSize,szAddr);
|
||||
|
||||
if (cCurrentRomType=='S')
|
||||
{
|
||||
wsprintf(szSize, Chipset.BSCfg2 ? _T("%05X") : _T("-----"),(Chipset.BSSize^0xFF)<<12);
|
||||
wsprintf(szAddr, Chipset.BSCfig ? _T("%05X") : _T("-----"),Chipset.BSBase<<12);
|
||||
}
|
||||
else
|
||||
{
|
||||
wsprintf(szSize, Chipset.P2Cfg2 ? _T("%05X") : _T("-----"),(Chipset.P2Size^0xFF)<<12);
|
||||
wsprintf(szAddr, Chipset.P2Cfig ? _T("%05X") : _T("-----"),Chipset.P2Base<<12);
|
||||
}
|
||||
PrintTrace(_T(" NCE3=%s/%s\r\n"),szSize,szAddr);
|
||||
}
|
||||
|
||||
// disassemble line
|
||||
eMapMode = GetMemMapType(); // get current map mode
|
||||
SetMemMapType(MEM_MMU); // disassemble in mapped mode
|
||||
|
||||
// entry has a name
|
||||
if (disassembler_symb && (lpszName = RplGetName(Chipset.pc)) != NULL)
|
||||
{
|
||||
PrintTrace(_T("=%s\r\n"),lpszName); // print address as label
|
||||
}
|
||||
dwNxtAddr = disassemble(Chipset.pc,szBuffer);
|
||||
|
||||
// in disassembly replace space characters
|
||||
// between Opcode and Modifier with one TAB
|
||||
if ((s = _tcschr(szBuffer,_T(' '))) != NULL)
|
||||
{
|
||||
// skip blanks
|
||||
for (d = s; *d == _T(' '); ++d) { }
|
||||
|
||||
if (d == &szBuffer[8]) // on TAB position
|
||||
{
|
||||
*s++ = _T('\t'); // replace with TAB
|
||||
|
||||
// move the opcode modifier
|
||||
while ((*s++ = *d++) != 0) { }
|
||||
}
|
||||
}
|
||||
|
||||
if (bTraceOpc) // show opcode nibbles
|
||||
{
|
||||
dwOpcAddr = Chipset.pc; // init address
|
||||
|
||||
// show opcode nibbles in a block of 5
|
||||
for (i = 0; i < 5 && dwOpcAddr < dwNxtAddr; ++i)
|
||||
{
|
||||
szOpc[i] = cHex[GetMemNib(&dwOpcAddr)];
|
||||
}
|
||||
|
||||
if (i == 1) // only 1 nibble written
|
||||
{
|
||||
szOpc[i++] = _T('\t'); // one additional TAB necessary
|
||||
}
|
||||
szOpc[i] = 0; // EOS
|
||||
|
||||
PrintTrace(_T("%05lX %s\t%s\r\n"),Chipset.pc,szOpc,szBuffer);
|
||||
|
||||
while (dwOpcAddr < dwNxtAddr) // decode rest of opcode
|
||||
{
|
||||
// show opcode nibbles in a block of 5
|
||||
for (i = 0; i < 5 && dwOpcAddr < dwNxtAddr; ++i)
|
||||
{
|
||||
szOpc[i] = cHex[GetMemNib(&dwOpcAddr)];
|
||||
}
|
||||
szOpc[i] = 0; // EOS
|
||||
|
||||
PrintTrace(_T(" %s\r\n"),szOpc);
|
||||
}
|
||||
}
|
||||
else // without opcode nibbles
|
||||
{
|
||||
PrintTrace(_T("%05lX\t%s\r\n"),Chipset.pc,szBuffer);
|
||||
}
|
||||
|
||||
SetMemMapType(eMapMode); // switch back to old map mode
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// trace settings dialog
|
||||
//
|
||||
static BOOL OnBrowseTraceSettings(HWND hDlg)
|
||||
{
|
||||
TCHAR szBuffer[MAX_PATH];
|
||||
OPENFILENAME ofn;
|
||||
|
||||
// get current content of file edit box
|
||||
GetDlgItemText(hDlg,IDC_TRACE_FILE,szBuffer,ARRAYSIZEOF(szBuffer));
|
||||
|
||||
ZeroMemory(&ofn, sizeof(OPENFILENAME));
|
||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||
ofn.hwndOwner = hDlg;
|
||||
ofn.lpstrFilter =
|
||||
_T("Trace Log Files (*.log)\0*.log\0")
|
||||
_T("All Files (*.*)\0*.*\0");
|
||||
ofn.lpstrDefExt = _T("log");
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.lpstrFile = szBuffer;
|
||||
ofn.nMaxFile = ARRAYSIZEOF(szBuffer);
|
||||
ofn.Flags = OFN_EXPLORER|OFN_HIDEREADONLY|OFN_CREATEPROMPT|OFN_OVERWRITEPROMPT;
|
||||
if (GetSaveFileName(&ofn))
|
||||
{
|
||||
SetDlgItemText(hDlg,IDC_TRACE_FILE,szBuffer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// trace settings
|
||||
//
|
||||
static INT_PTR CALLBACK TraceSettings(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
SetDlgItemText(hDlg,IDC_TRACE_FILE,szTraceFilename);
|
||||
CheckDlgButton(hDlg,(uTraceMode == TRACE_FILE_NEW) ? IDC_TRACE_NEW : IDC_TRACE_APPEND,BST_CHECKED);
|
||||
CheckDlgButton(hDlg,IDC_TRACE_REGISTER,bTraceReg);
|
||||
CheckDlgButton(hDlg,IDC_TRACE_MMU,bTraceMmu);
|
||||
CheckDlgButton(hDlg,IDC_TRACE_OPCODE,bTraceOpc);
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDC_TRACE_BROWSE:
|
||||
return OnBrowseTraceSettings(hDlg);
|
||||
|
||||
case IDOK:
|
||||
// get filename
|
||||
GetDlgItemText(hDlg,IDC_TRACE_FILE,szTraceFilename,ARRAYSIZEOF(szTraceFilename));
|
||||
|
||||
// trace mode
|
||||
uTraceMode = IsDlgButtonChecked(hDlg,IDC_TRACE_NEW) ? TRACE_FILE_NEW : TRACE_FILE_APPEND;
|
||||
|
||||
// trace content
|
||||
bTraceReg = IsDlgButtonChecked(hDlg,IDC_TRACE_REGISTER);
|
||||
bTraceMmu = IsDlgButtonChecked(hDlg,IDC_TRACE_MMU);
|
||||
bTraceOpc = IsDlgButtonChecked(hDlg,IDC_TRACE_OPCODE);
|
||||
|
||||
// no break
|
||||
case IDCANCEL:
|
||||
EndDialog(hDlg,LOWORD(wParam));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
}
|
||||
|
||||
static BOOL OnTraceSettings(HWND hDlg)
|
||||
{
|
||||
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_TRACE), hDlg, (DLGPROC)TraceSettings) == -1)
|
||||
AbortMessage(_T("TraceSettings Dialog Box Creation Error !"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
static BOOL OnTraceEnable(HWND hDlg)
|
||||
{
|
||||
OnToggleMenuItem(hDlg,ID_TRACE_ENABLE,&bDbgTrace);
|
||||
bDbgTrace ? StartTrace() : StopTrace();
|
||||
EnableMenuItem(GetMenu(hDlg),ID_TRACE_SETTINGS,bDbgTrace ? MF_GRAYED : MF_ENABLED);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -214,7 +214,7 @@ BOOL CreateMainBitmap(LPCTSTR szFilename)
|
|||
_ASSERT(hWindowDC != NULL);
|
||||
VERIFY(hMainDC = CreateCompatibleDC(hWindowDC));
|
||||
if (hMainDC == NULL) return FALSE; // quit if failed
|
||||
hMainBitmap = LoadBitmapFile(szFilename);
|
||||
hMainBitmap = LoadBitmapFile(szFilename,TRUE);
|
||||
if (hMainBitmap == NULL)
|
||||
{
|
||||
DeleteDC(hMainDC);
|
||||
|
@ -249,7 +249,7 @@ BOOL CreateAnnunBitmap(LPCTSTR szFilename)
|
|||
_ASSERT(hWindowDC != NULL);
|
||||
VERIFY(hAnnunDC = CreateCompatibleDC(hWindowDC));
|
||||
if (hAnnunDC == NULL) return FALSE; // quit if failed
|
||||
hAnnunBitmap = LoadBitmapFile(szFilename);
|
||||
hAnnunBitmap = LoadBitmapFile(szFilename,FALSE);
|
||||
if (hAnnunBitmap == NULL)
|
||||
{
|
||||
DeleteDC(hAnnunDC);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "kml.h"
|
||||
#include "debugger.h"
|
||||
|
||||
#define VERSION "1.60+"
|
||||
#define VERSION "1.61+"
|
||||
|
||||
#ifdef _DEBUG
|
||||
LPCTSTR szNoTitle = _T("Emu48 ")_T(VERSION)_T(" Debug");
|
||||
|
@ -41,6 +41,7 @@ static const LPCTSTR szLicence =
|
|||
|
||||
static BOOL bOwnCursor = FALSE;
|
||||
static BOOL bTitleBar = TRUE;
|
||||
static BOOL bMouseButton = FALSE;
|
||||
|
||||
|
||||
CRITICAL_SECTION csGDILock; // critical section for hWindowDC
|
||||
|
@ -1787,28 +1788,19 @@ static VOID OnContextMenu(LPARAM lParam)
|
|||
return;
|
||||
}
|
||||
|
||||
static BOOL OnNcHitTest(LPARAM lParam)
|
||||
{
|
||||
if (!bTitleBar || bClientWinMove) // no title bar or window movement over client enabled
|
||||
{
|
||||
POINT pt;
|
||||
|
||||
POINTSTOPOINT(pt,MAKEPOINTS(lParam)); // mouse position
|
||||
VERIFY(ScreenToClient(hWnd,&pt)); // convert mouse into client position
|
||||
|
||||
if (pt.y >= 0) // client area
|
||||
{
|
||||
// hit area not over a button
|
||||
return !MouseIsButton(pt.x,pt.y);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static LRESULT OnLButtonDown(UINT nFlags, WORD x, WORD y)
|
||||
{
|
||||
if (nMacroState == MACRO_PLAY) return 0; // playing macro
|
||||
if (nState == SM_RUN) MouseButtonDownAt(nFlags, x,y);
|
||||
|
||||
bMouseButton = MouseIsButton(x,y); // mouse is over button hit area
|
||||
|
||||
// no title bar or window movement over client enabled and hit area not over a button
|
||||
if ((!bTitleBar || bClientWinMove) && nFlags == MK_LBUTTON && !bMouseButton)
|
||||
{
|
||||
// move window while holding the left mouse button
|
||||
PostMessage(hWnd,WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(x,y));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1816,6 +1808,7 @@ static LRESULT OnLButtonUp(UINT nFlags, WORD x, WORD y)
|
|||
{
|
||||
if (nMacroState == MACRO_PLAY) return 0; // playing macro
|
||||
if (nState == SM_RUN) MouseButtonUpAt(nFlags, x,y);
|
||||
bMouseButton = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1851,6 +1844,7 @@ static LRESULT OnKeyDown(int nVirtKey, LPARAM lKeyData)
|
|||
// call RunKey() only once (suppress autorepeat feature)
|
||||
if (nState == SM_RUN && (lKeyData & 0x40000000) == 0)
|
||||
RunKey((BYTE)nVirtKey, TRUE);
|
||||
bMouseButton = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1994,12 +1988,18 @@ LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
case SC_CLOSE: return OnFileExit();
|
||||
}
|
||||
break;
|
||||
case WM_CONTEXTMENU:
|
||||
case WM_NCRBUTTONUP:
|
||||
OnContextMenu(lParam);
|
||||
case WM_ENDSESSION:
|
||||
// session will end and any auto saving is enabled
|
||||
if (wParam == TRUE && (bAutoSave || bAutoSaveOnExit))
|
||||
{
|
||||
SwitchToState(SM_INVALID); // hold emulation thread
|
||||
if (szCurrentFilename[0] != 0) // has current filename
|
||||
SaveDocument();
|
||||
SwitchToState(SM_RUN); // on cancel restart emulation thread
|
||||
}
|
||||
break;
|
||||
case WM_NCHITTEST:
|
||||
if (OnNcHitTest(lParam)) return HTCAPTION;
|
||||
case WM_CONTEXTMENU:
|
||||
if (!bMouseButton) OnContextMenu(lParam);
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_LBUTTONDOWN: return OnLButtonDown((UINT) wParam, LOWORD(lParam), HIWORD(lParam));
|
||||
|
|
|
@ -282,7 +282,7 @@ SOURCE=.\kml.c
|
|||
# Begin Source File
|
||||
|
||||
SOURCE=.\lodepng.c
|
||||
# ADD CPP /D "LODEPNG_NO_COMPILE_ENCODER" /D "LODEPNG_NO_COMPILE_DISK" /D "LODEPNG_NO_COMPILE_ERROR_TEXT" /D "LODEPNG_NO_COMPILE_CPP"
|
||||
# ADD CPP /D "LODEPNG_NO_COMPILE_ENCODER" /D "LODEPNG_NO_COMPILE_DISK" /D "LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS" /D "LODEPNG_NO_COMPILE_ERROR_TEXT" /D "LODEPNG_NO_COMPILE_CPP"
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -218,6 +218,7 @@ extern DWORD *pdwInstrArray;
|
|||
extern WORD wInstrSize;
|
||||
extern WORD wInstrWp;
|
||||
extern WORD wInstrRp;
|
||||
extern VOID (*fnOutTrace)(VOID);
|
||||
extern VOID SuspendDebugger(VOID);
|
||||
extern VOID ResumeDebugger(VOID);
|
||||
extern VOID CheckSerial(VOID);
|
||||
|
@ -290,7 +291,7 @@ extern BOOL LoadObject(LPCTSTR szFilename);
|
|||
extern BOOL SaveObject(LPCTSTR szFilename);
|
||||
extern BOOL LoadIconFromFile(LPCTSTR szFilename);
|
||||
extern VOID LoadIconDefault(VOID);
|
||||
extern HBITMAP LoadBitmapFile(LPCTSTR szFilename);
|
||||
extern HBITMAP LoadBitmapFile(LPCTSTR szFilename,BOOL bPalette);
|
||||
extern HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol);
|
||||
|
||||
// Timer.c
|
||||
|
|
|
@ -206,6 +206,14 @@ BEGIN
|
|||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 109
|
||||
END
|
||||
|
||||
IDD_TRACE, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 240
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 106
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
@ -654,6 +662,30 @@ BEGIN
|
|||
PUSHBUTTON "Cancel",IDCANCEL,122,95,50,14
|
||||
END
|
||||
|
||||
IDD_TRACE DIALOG DISCARDABLE 0, 0, 247, 113
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Trace Settings"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
LTEXT "Log File:",IDC_STATIC,7,13,28,8
|
||||
EDITTEXT IDC_TRACE_FILE,39,11,180,12,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "...",IDC_TRACE_BROWSE,220,11,20,12
|
||||
CONTROL "&New",IDC_TRACE_NEW,"Button",BS_AUTORADIOBUTTON |
|
||||
WS_GROUP | WS_TABSTOP,16,49,41,10
|
||||
CONTROL "&Append",IDC_TRACE_APPEND,"Button",BS_AUTORADIOBUTTON,
|
||||
16,64,41,10
|
||||
GROUPBOX "File Mode",IDC_STATIC,7,32,113,53
|
||||
CONTROL "&Register",IDC_TRACE_REGISTER,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,140,45,43,10
|
||||
CONTROL "&MMU",IDC_TRACE_MMU,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,140,57,43,10
|
||||
CONTROL "&Opcode",IDC_TRACE_OPCODE,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,140,69,43,10
|
||||
GROUPBOX "Logging",IDC_STATIC,127,32,113,53
|
||||
DEFPUSHBUTTON "OK",IDOK,62,92,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,135,92,50,14
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -691,8 +723,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,6,0,0
|
||||
PRODUCTVERSION 1,6,0,0
|
||||
FILEVERSION 1,6,1,0
|
||||
PRODUCTVERSION 1,6,1,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -709,12 +741,12 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Christoph Gießelink & Sebastien Carlier\0"
|
||||
VALUE "FileDescription", "HP38/39/40/48/49/50 Emulator\0"
|
||||
VALUE "FileVersion", "1, 6, 0, 0\0"
|
||||
VALUE "FileVersion", "1, 6, 1, 0\0"
|
||||
VALUE "InternalName", "Emu48\0"
|
||||
VALUE "LegalCopyright", "Copyright © 2019\0"
|
||||
VALUE "OriginalFilename", "Emu48.exe\0"
|
||||
VALUE "ProductName", "Emu48\0"
|
||||
VALUE "ProductVersion", "1, 6, 0, 0\0"
|
||||
VALUE "ProductVersion", "1, 6, 1, 0\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -896,6 +928,11 @@ BEGIN
|
|||
BEGIN
|
||||
MENUITEM "&Step Over Interrupts", ID_INTR_STEPOVERINT
|
||||
END
|
||||
POPUP "&Trace"
|
||||
BEGIN
|
||||
MENUITEM "&Settings...", ID_TRACE_SETTINGS
|
||||
MENUITEM "&Enable", ID_TRACE_ENABLE
|
||||
END
|
||||
POPUP "&Info"
|
||||
BEGIN
|
||||
MENUITEM "&Last Instructions...", ID_INFO_LASTINSTRUCTIONS
|
||||
|
|
|
@ -59,6 +59,8 @@ WORD wInstrSize = 256; // size of last instruction array
|
|||
WORD wInstrWp; // write pointer of instruction array
|
||||
WORD wInstrRp; // read pointer of instruction array
|
||||
|
||||
VOID (*fnOutTrace)(VOID) = NULL; // callback function for file trace
|
||||
|
||||
static INT nDbgRplBreak = BN_ASM; // flag for RPL breakpoint detection
|
||||
static INT nDbgOldState = DBG_OFF; // old state of debugger for suspend/resume
|
||||
|
||||
|
@ -99,6 +101,10 @@ static __inline VOID Debugger(VOID) // debugger part
|
|||
UpdateDbgCycleCounter(); // update 64 bit cpu cycle counter
|
||||
|
||||
SaveInstrAddr(Chipset.pc); // save pc in last instruction buffer
|
||||
if (fnOutTrace != NULL) // has a trace function
|
||||
{
|
||||
fnOutTrace(); // write file trace
|
||||
}
|
||||
|
||||
nDbgRplBreak = BN_ASM; // notify ASM breakpoint
|
||||
|
||||
|
|
|
@ -855,6 +855,7 @@ BOOL NewDocument(VOID)
|
|||
if (!DisplayChooseKml(0)) goto restore;
|
||||
if (!InitKML(szCurrentKml,FALSE)) goto restore;
|
||||
Chipset.type = cCurrentRomType;
|
||||
CrcRom(&Chipset.wRomCrc); // save fingerprint of loaded ROM
|
||||
|
||||
if (Chipset.type == '6' || Chipset.type == 'A') // HP38G
|
||||
{
|
||||
|
@ -1805,7 +1806,7 @@ static HPALETTE CreateBIPalette(BITMAPINFOHEADER CONST *lpbi)
|
|||
return hpal;
|
||||
}
|
||||
|
||||
static HBITMAP DecodeBmp(LPBMPFILE pBmp)
|
||||
static HBITMAP DecodeBmp(LPBMPFILE pBmp,BOOL bPalette)
|
||||
{
|
||||
LPBITMAPFILEHEADER pBmfh;
|
||||
LPBITMAPINFO pBmi;
|
||||
|
@ -1855,7 +1856,7 @@ static HBITMAP DecodeBmp(LPBMPFILE pBmp)
|
|||
pBmi, DIB_RGB_COLORS));
|
||||
if (hBitmap == NULL) return NULL;
|
||||
|
||||
if (hPalette == NULL)
|
||||
if (bPalette && hPalette == NULL)
|
||||
{
|
||||
hPalette = CreateBIPalette(&pBmi->bmiHeader);
|
||||
// save old palette
|
||||
|
@ -1886,7 +1887,7 @@ static BOOL ReadGifWord(LPBMPFILE pGif, INT *n)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static HBITMAP DecodeGif(LPBMPFILE pBmp,DWORD *pdwTransparentColor)
|
||||
static HBITMAP DecodeGif(LPBMPFILE pBmp,DWORD *pdwTransparentColor,BOOL bPalette)
|
||||
{
|
||||
// this implementation base on the GIF image file
|
||||
// decoder engine of Free42 (c) by Thomas Okken
|
||||
|
@ -2380,7 +2381,7 @@ static HBITMAP DecodeGif(LPBMPFILE pBmp,DWORD *pdwTransparentColor)
|
|||
_ASSERT(bDecoding == FALSE); // decoding successful
|
||||
|
||||
// normal decoding exit
|
||||
if (hPalette == NULL)
|
||||
if (bPalette && hPalette == NULL)
|
||||
{
|
||||
hPalette = CreateBIPalette((PBITMAPINFOHEADER) &bmi);
|
||||
// save old palette
|
||||
|
@ -2397,7 +2398,7 @@ quit:
|
|||
return hBitmap;
|
||||
}
|
||||
|
||||
static HBITMAP DecodePng(LPBMPFILE pBmp)
|
||||
static HBITMAP DecodePng(LPBMPFILE pBmp,BOOL bPalette)
|
||||
{
|
||||
// this implementation use the PNG image file decoder
|
||||
// engine of Copyright (c) 2005-2018 Lode Vandevenne
|
||||
|
@ -2422,7 +2423,7 @@ static HBITMAP DecodePng(LPBMPFILE pBmp)
|
|||
if (uError) goto quit;
|
||||
|
||||
ZeroMemory(&bmi,sizeof(bmi)); // init bitmap info
|
||||
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = (LONG) uWidth;
|
||||
bmi.bmiHeader.biHeight = (LONG) uHeight;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
|
@ -2460,7 +2461,7 @@ static HBITMAP DecodePng(LPBMPFILE pBmp)
|
|||
_ASSERT((DWORD) (pbyLine - pbyPixels) <= bmi.bmiHeader.biSizeImage);
|
||||
}
|
||||
|
||||
if (hPalette == NULL)
|
||||
if (bPalette && hPalette == NULL)
|
||||
{
|
||||
hPalette = CreateBIPalette((PBITMAPINFOHEADER) &bmi);
|
||||
// save old palette
|
||||
|
@ -2482,7 +2483,7 @@ quit:
|
|||
return hBitmap;
|
||||
}
|
||||
|
||||
HBITMAP LoadBitmapFile(LPCTSTR szFilename)
|
||||
HBITMAP LoadBitmapFile(LPCTSTR szFilename,BOOL bPalette)
|
||||
{
|
||||
HANDLE hFile;
|
||||
HANDLE hMap;
|
||||
|
@ -2513,7 +2514,7 @@ HBITMAP LoadBitmapFile(LPCTSTR szFilename)
|
|||
// check for bitmap file header "BM"
|
||||
if (Bmp.dwFileSize >= 2 && *(WORD *) Bmp.pbyFile == 0x4D42)
|
||||
{
|
||||
hBitmap = DecodeBmp(&Bmp);
|
||||
hBitmap = DecodeBmp(&Bmp,bPalette);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2521,14 +2522,14 @@ HBITMAP LoadBitmapFile(LPCTSTR szFilename)
|
|||
if ( Bmp.dwFileSize >= 6
|
||||
&& (memcmp(Bmp.pbyFile,"GIF87a",6) == 0 || memcmp(Bmp.pbyFile,"GIF89a",6) == 0))
|
||||
{
|
||||
hBitmap = DecodeGif(&Bmp,&dwTColor);
|
||||
hBitmap = DecodeGif(&Bmp,&dwTColor,bPalette);
|
||||
break;
|
||||
}
|
||||
|
||||
// check for PNG file header
|
||||
if (Bmp.dwFileSize >= 8 && memcmp(Bmp.pbyFile,"\x89PNG\r\n\x1a\n",8) == 0)
|
||||
{
|
||||
hBitmap = DecodePng(&Bmp);
|
||||
hBitmap = DecodePng(&Bmp,bPalette);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
12
source/KML.C
12
source/KML.C
|
@ -895,6 +895,8 @@ static KmlLine* ParseLines(BOOL bInclude)
|
|||
if (eToken == TOK_INCLUDE)
|
||||
{
|
||||
LPTSTR szFilename;
|
||||
UINT nLexLineKml;
|
||||
|
||||
eToken = Lex(LEX_PARAM); // get include parameter in 'szLexString'
|
||||
if (eToken != TOK_STRING) // not a string (token don't begin with ")
|
||||
{
|
||||
|
@ -903,6 +905,7 @@ static KmlLine* ParseLines(BOOL bInclude)
|
|||
}
|
||||
szFilename = szLexString; // save pointer to allocated memory
|
||||
szLexString = NULL;
|
||||
nLexLineKml = nLexLine; // save line number
|
||||
eToken = Lex(LEX_PARAM); // decode argument
|
||||
if (eToken != TOK_EOL)
|
||||
{
|
||||
|
@ -925,7 +928,10 @@ static KmlLine* ParseLines(BOOL bInclude)
|
|||
}
|
||||
free(szFilename); // free filename string
|
||||
if (pLine == NULL) // parsing error
|
||||
{
|
||||
nLexLine = nLexLineKml; // restore line number
|
||||
goto abort;
|
||||
}
|
||||
while (pLine->pNext) pLine=pLine->pNext;
|
||||
continue;
|
||||
}
|
||||
|
@ -1096,6 +1102,8 @@ static KmlBlock* ParseBlocks(BOOL bInclude, BOOL bEndTokenEn)
|
|||
if (eToken == TOK_INCLUDE)
|
||||
{
|
||||
LPTSTR szFilename;
|
||||
UINT nLexLineKml;
|
||||
|
||||
eToken = Lex(LEX_PARAM); // get include parameter in 'szLexString'
|
||||
if (eToken != TOK_STRING) // not a string (token don't begin with ")
|
||||
{
|
||||
|
@ -1104,6 +1112,7 @@ static KmlBlock* ParseBlocks(BOOL bInclude, BOOL bEndTokenEn)
|
|||
}
|
||||
szFilename = szLexString; // save pointer to allocated memory
|
||||
szLexString = NULL;
|
||||
nLexLineKml = nLexLine; // save line number
|
||||
eToken = Lex(LEX_PARAM); // decode argument
|
||||
if (eToken != TOK_EOL)
|
||||
{
|
||||
|
@ -1117,7 +1126,10 @@ static KmlBlock* ParseBlocks(BOOL bInclude, BOOL bEndTokenEn)
|
|||
pBlock = pFirst = IncludeBlocks(bInclude,szFilename);
|
||||
free(szFilename); // free filename string
|
||||
if (pBlock == NULL) // parsing error
|
||||
{
|
||||
nLexLine = nLexLineKml; // restore line number
|
||||
goto abort;
|
||||
}
|
||||
while (pBlock->pNext) pBlock = pBlock->pNext;
|
||||
continue;
|
||||
}
|
||||
|
|
4163
source/LODEPNG.C
4163
source/LODEPNG.C
File diff suppressed because it is too large
Load diff
3877
source/LODEPNG.H
3877
source/LODEPNG.H
File diff suppressed because it is too large
Load diff
|
@ -33,6 +33,7 @@
|
|||
#define IDD_DEBUG_MEMSAVE 127
|
||||
#define IDD_DEBUG_MEMLOAD 128
|
||||
#define IDD_DEBUG_SETTINGS 129
|
||||
#define IDD_TRACE 130
|
||||
#define IDC_REALSPEED 1000
|
||||
#define IDC_GRAYSCALE 1001
|
||||
#define IDC_ALWAYSONTOP 1002
|
||||
|
@ -169,6 +170,13 @@
|
|||
#define IDC_MACRO_MANUAL 1133
|
||||
#define IDC_SOUND_SLIDER 1134
|
||||
#define IDC_SOUND_DEVICE 1135
|
||||
#define IDC_TRACE_FILE 1136
|
||||
#define IDC_TRACE_BROWSE 1137
|
||||
#define IDC_TRACE_NEW 1138
|
||||
#define IDC_TRACE_APPEND 1139
|
||||
#define IDC_TRACE_REGISTER 1140
|
||||
#define IDC_TRACE_MMU 1141
|
||||
#define IDC_TRACE_OPCODE 1142
|
||||
#define ID_FILE_NEW 40001
|
||||
#define ID_FILE_OPEN 40002
|
||||
#define ID_FILE_SAVE 40003
|
||||
|
@ -239,15 +247,17 @@
|
|||
#define ID_INFO_LASTINSTRUCTIONS 40069
|
||||
#define ID_INFO_PROFILE 40070
|
||||
#define ID_INFO_WRITEONLYREG 40071
|
||||
#define ID_TRACE_SETTINGS 40072
|
||||
#define ID_TRACE_ENABLE 40073
|
||||
#define ID_FILE_MRU_FILE1 40100
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 130
|
||||
#define _APS_NEXT_COMMAND_VALUE 40072
|
||||
#define _APS_NEXT_CONTROL_VALUE 1136
|
||||
#define _APS_NEXT_RESOURCE_VALUE 131
|
||||
#define _APS_NEXT_COMMAND_VALUE 40074
|
||||
#define _APS_NEXT_CONTROL_VALUE 1143
|
||||
#define _APS_NEXT_SYMED_VALUE 109
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue