1999-12-14: Updated to version 1.15

This commit is contained in:
Gwenhael Le Moine 2024-03-19 22:25:45 +01:00
parent dc12da9a17
commit 2e85d27e43
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
53 changed files with 10427 additions and 6247 deletions

View file

@ -1 +1 @@
017A6:81B1
017A6:81B1; =makebeep

View file

@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@ -305,7 +305,8 @@ the "copyright" line and a pointer to where the full notice is found.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.

189
DEBUGGER.TXT Normal file
View file

@ -0,0 +1,189 @@
Debugger in Emu48/Tools/Debugger...
-----------------------------------
This is a short description of the internal debugger of Emu48. The debugger is not perfect and/or complete. I provide it as it is. Please don't send me any suggestions or changes at the moment. If you have a better idea make it for yourself. Of course you're free to publish them or send me your changes.
The debugger was designed to help costumers inspecting assembler code objects, a part that cannot be handled satisfactorily by the JAZZ package. Thanks to Mika Heiskanen and all the others supporting this great program.
After starting the debugger the emulation will stop at the current PC position. The emulation will continue after closing the debugger window. Please remember that the clock now shows the wrong time.
1.) Menu Debug
- Run F5
Continue calculator emulation under debugger control. The emulation will stop at a breakpoint. Please remember that the emulation speed is slower than without debugger control.
- Step Into F7
Execute one code instruction.
- Step Over F8
Execute a GOSUB, GOSUBL or GOSBVL as one instruction. Normally the instruction cursor will set to the position behind the GOSUB instruction.
But this makes trouble in the following code part:
GOSUB +
NIBASC /Hello world/
+ C=RSTK
The program counter will never reach the address behind the GOSUB instruction. The debugger solve this problem by breaking the emulation when the stack has the same level before the GOSUB instruction. In this example the single step execution will continue after the C=RSTK instruction.
- Step Out F9
Continue the program until a RTI, RTN, RTNC, RTNCC, RTNNC, RTNSC, RTNSXN, RTNYES instruction is found above the current stack level.
At some code constructions (mostly used to save space on the hardware stack) like
C=RSTK
PC=C
and
C=RSTK
RSTK=C
RTN
the stop address will be wrong. The problem in both code fragments is the C=RSTK opcode. In the first example there is no RTN instruction to stop. In the second one the C=RSTK instruction purge the original return address and then the RSTK=C instruction is interpreted as a GOSUB instruction.
In opposite the following code will work fine:
RSTK=C
..
code <- F9 was pressed here
..
GOSUB -
C=RSTK
RTN <- emulation will stop after this instruction
- RTN
So be careful using the F9 key.
- Break F11
Stop the emulation started with F5.
2.) Menu Breakpoints
- Set breakpoint F2
Toggle a code breakpoint at the cursor position in the code window.
- Edit breakpoints...
You get a sorted list of the current code breakpoints. With "Add" you can add a new, with "Delete" you can delete an existing breakpoint. Addresses greater than #FFFFF are cutted after the fifths nibble.
- Clear all breakpoints
Clear all code breakpoints except the NOP3 ones.
- NOP3 code breakpoints
What are NOP3 code breakpoints? As you now user programs are loaded somewhere in memory and can be moved after a garbage collection. So it's very difficult to break a user program at a hard set breakpoint with F2. To solve this problem the debugger will stop emulation at a NOP3 opcode. So you can easily add a NOP3 command into your sources to force a break condition. To enable this you have to check this item.
NOP3 and NOP3, what's the difference? The Saturn CPU has no NOP command, so NOP3 is an opcode that is three nibbles long and doesn't change a register. In the HP SASM.DOC document two different opcodes are defined for NOP3:
Opcode 820 for HST=0 0
and
Opcode 420 for GOC + (next line)
In the assembler of the HPTOOLS 3.x package NOP3 is defined as opcode 820. The advantage of the opcode is that the execution time is always the same, independent from the carry flag. This code is used in the HP48 ROM as well. So I decided to use the GOC opcode for a code breakpoint condition.
A short example:
ASSEMBLE
NIBASC /HPHP48-E/
BREAK MACRO
CON(3) #024 NOP3
ENDM
RPL
CODE
BREAK code breakpoint
GOSBVL =SAVPTR save register
GOSUB + problem for step over
NIBASC /Hello world/
+ C=RSTK
GOVLNG =GETPTRLOOP
ENDCODE
3.) Code window
This windows shows you the disassembled code. The line with the current PC is marked with a "->" between the address and the disassembly.
You can use the UP, PAGE UP, DOWN and PAGE DOWN keys to scroll the window content. There is one strange behavior, when you move to higher addresses the debugger is able to disassemble the next line correctly, but when you move to cursor to lower addresses the debugger does not know if this address is at the begin or inside of an opcode. In result you get wrong disassembled lines.
Context menu pressing the right mouse button:
- Go to address... G
Moves the cursor to the specified code address.
- Go to PC
Sets the cursor to the actual position of the PC.
- Set breakpoint F2
Toggle a code breakpoint at the cursor position in the code window.
- Set PC to selection
Set the PC to the cursor position. Be careful with this command, you change the execution order of the commands!
4.) Register window
Here you can see the actual contents of the CPU registers. The values are only updated after a single step execution.
With the left mouse button you change the content of the register. On bit registers like CY and Mode the state changes immediately without any request.
5.) Memory window
This windows shows you the memory content.
You can use the arrow, PAGE UP and PAGE DOWN keys to move the cursor to a memory position. With a double click on the left mouse button you change the content of the two addresses. When the memory position is read only (ROM) the content wouldn't change.
Context menu pressing the right mouse button:
- Go to address... G
Moves the cursor to the specified memory address.
- Go to PC
Sets the cursor to the actual position of the PC.
- Go to D0
Sets the cursor to the actual position of the D0 register.
- Go to D1
Sets the cursor to the actual position of the D0 register.
- Go to Stack
Sets the cursor to the return address placed in the top level of the stack.
6.) Stack window
The content of the hardware stack is viewed here.
7.) Problems
The timers aren't updated in the single step mode at the moment. Please skip these parts with setting a code breakpoint behind the critical section and continue emulation with F5.
12/14/99 (c) by Christoph Gießelink, cgiess@swol.de

View file

@ -16,7 +16,7 @@ End
Lcd
Zoom 2
Offset 20 20
Color 0 255 255 255
Color 0 255 255 255 # character color table
Color 1 255 255 255
Color 2 255 255 255
Color 3 255 255 255
@ -24,22 +24,22 @@ Lcd
Color 5 255 255 255
Color 6 255 255 255
Color 7 255 255 255
Color 8 240 240 240
Color 9 225 225 225
Color 10 210 210 210
Color 11 195 195 195
Color 12 180 180 180
Color 13 165 165 165
Color 14 150 150 150
Color 15 135 135 135
Color 16 120 120 120
Color 17 105 105 105
Color 18 90 90 90
Color 19 75 75 75
Color 20 60 60 60
Color 21 45 45 45
Color 22 30 30 30
Color 23 15 15 15
Color 8 255 255 255
Color 9 223 223 223
Color 10 179 171 171
Color 11 135 135 135
Color 12 91 91 91
Color 13 47 47 47
Color 14 0 0 0
Color 15 0 0 0
Color 16 0 0 0
Color 17 0 0 0
Color 18 0 0 0
Color 19 0 0 0
Color 20 0 0 0
Color 21 0 0 0
Color 22 0 0 0
Color 23 0 0 0
Color 24 0 0 0
Color 25 0 0 0
Color 26 0 0 0
@ -48,6 +48,38 @@ Lcd
Color 29 0 0 0
Color 30 0 0 0
Color 31 0 0 0
Color 32 255 255 255 # background color table
Color 33 255 255 255
Color 34 255 255 255
Color 35 255 255 255
Color 36 255 255 255
Color 37 255 255 255
Color 38 255 255 255
Color 39 255 255 255
Color 40 255 255 255
Color 41 255 255 255
Color 42 255 255 255
Color 43 255 255 255
Color 44 255 255 255
Color 45 255 255 255
Color 46 255 255 255
Color 47 232 232 232
Color 48 209 209 209
Color 49 186 186 186
Color 50 163 163 163
Color 51 140 140 140
Color 52 117 117 117
Color 53 94 94 94
Color 54 71 71 71
Color 55 48 48 48
Color 56 25 25 25
Color 57 2 2 2
Color 58 0 0 0
Color 59 0 0 0
Color 60 0 0 0
Color 61 0 0 0
Color 62 0 0 0
Color 63 0 0 0
End
Annunciator 1

View file

@ -16,25 +16,25 @@ End
Lcd
Zoom 2
Offset 20 20
Color 0 255 255 255
Color 0 255 255 255 # character color table
Color 1 255 255 255
Color 2 255 255 255
Color 3 240 240 240
Color 4 225 225 225
Color 5 210 210 210
Color 6 195 195 195
Color 7 180 180 180
Color 8 165 165 165
Color 9 150 150 150
Color 10 135 135 135
Color 11 120 120 120
Color 12 105 105 105
Color 13 90 90 90
Color 14 75 75 75
Color 15 60 60 60
Color 16 45 45 45
Color 17 30 30 30
Color 18 15 15 15
Color 4 216 216 216
Color 5 192 192 192
Color 6 168 168 168
Color 7 144 144 144
Color 8 120 120 120
Color 9 96 96 96
Color 10 72 72 72
Color 11 48 48 48
Color 12 24 24 24
Color 13 0 0 0
Color 14 0 0 0
Color 15 0 0 0
Color 16 0 0 0
Color 17 0 0 0
Color 18 0 0 0
Color 19 0 0 0
Color 20 0 0 0
Color 21 0 0 0
@ -48,6 +48,38 @@ Lcd
Color 29 0 0 0
Color 30 0 0 0
Color 31 0 0 0
Color 32 255 255 255 # background color table
Color 33 255 255 255
Color 34 255 255 255
Color 35 255 255 255
Color 36 255 255 255
Color 37 255 255 255
Color 38 255 255 255
Color 39 255 255 255
Color 40 255 255 255
Color 41 255 255 255
Color 42 255 255 255
Color 43 255 255 255
Color 44 255 255 255
Color 45 255 255 255
Color 46 230 230 230
Color 47 205 205 205
Color 48 180 180 180
Color 49 155 155 155
Color 50 130 130 130
Color 51 105 105 105
Color 52 80 80 80
Color 53 55 55 55
Color 54 30 30 30
Color 55 5 5 5
Color 56 0 0 0
Color 57 0 0 0
Color 58 0 0 0
Color 59 0 0 0
Color 60 0 0 0
Color 61 0 0 0
Color 62 0 0 0
Color 63 0 0 0
End
Annunciator 1

BIN
EMU48.EXE

Binary file not shown.

449
EMU48.TXT
View file

@ -1,7 +1,7 @@
Emu48 - A freeware HP48 Emulator for Windows 95, 98 and NT
Emu48 - A freeware HP38/48/49 Emulator for Windows 9x, NT and 2000
@ -9,219 +9,405 @@
* INSTALLATION *
****************
Emu48 is now distributed in a single archive, named Emu48-1.xx.zip. This version
integrates the changed made by Christoph Giesselink in his service pack 10.
Emu48 is distributed in 1 archive:
- Emu48-1_15.zip All files and sources
To install Emu48, just unzip Emu48-1.xx.zip into an empty directory.
When you first run Emu48, it will detect the directory in which you
installed it, and will write its configuration to a file named Emu48.ini in
your Windows directory.
To install Emu48, just unzip Emu48-1_15.zip into an empty directory. When you
first run Emu48, it will detect the directory in which you installed it, and
will write its configuration to a file named Emu48.ini in your Windows
directory.
Note:
As of version 1.0, Emu48 will only run with Windows 95, 98 and NT.
Since the source code is provided, you can add features or port it to new
plateforms, but you are required to send me your changes.
You can also update your current version with the Unofficial Service Packs:
- E48BP1x.ZIP New EXE-File
- E48SP1x.ZIP Sources of the Service Pack
Replace the original EXE file please.
********************
* OPERATING SYSTEM *
********************
This version of Emu48 should work with all Intel Win32 platforms. You may
recompile the sources to run Emu48 with Windows NT on a DEC Alpha.
************************
* YOU NEED A ROM IMAGE *
************************
Emu48 needs an image of the ROM of YOUR calculator to be able to run.
Since the ROM is copyrighted by HP, I won't give you mine, and you should not
give yours or make it freely available.
To use the ROM software of a calculator, you must be the owner of this
calculator.
Emu48 needs an image of the ROM of YOUR calculator to be able to run. Since the
ROM is copyrighted by HP, I won't give you mine, and you should not give yours
or make it freely available. To use the ROM software of a calculator, you must
be the owner of this calculator.
- If you have already used another HP48 emulator, you can convert the ROM with
you were using with the Convert utility.
To do that, start a Command Promt while running Windows, and type :
Convert <old-file> ROM.48G
or Convert <old-file> ROM.48S
Where <old-file> is the path to your old ROM image. This will create a file
named ROM.48G or ROM.48S, depending on the version you own.
This tool should be able to read any style of ROM image, and will also check
its validity. Note than if you run it with only one parameter, no file will
be written, but it will still check the validity of the ROM.
- HP38:
To upload the ROM of your HP38G, you will need a special aplet called "ROM
UPLOAD", available at http://www.epita.fr/~avenar_j/hp. Once you've uploaded the
ROM, you have to convert it using the Convert utility.
- If you have never used an HP48 emulator, and don't have a ROM dump, you can
either use the old ROMDump utility and then Convert your dump, or you can
use my ROMDump Wizard, which will almost automatically get the ROM from your
HP48. However, this Wizard was written without a documentation on the
transfer protocol used by the HP48 (Kermit), so I cannot guarantee that it
will work. It worked on my computer, maybe it will work on yours. Try it !
To do that, start a Command Prompt while running Windows, and type:
Convert <rom-file> ROM.38G
WARNING: If you use ROMDump or the ROMDump Wizard, DO NOT INTERRUPT THE
PROCESS ! Your HP48 would lock, and the only way to reset it is
through the Reset hole.
Where <rom-file> is the path to your ROM image. This will create a file named
ROM.38G. This tool will also check its validity.
IMPORTANT: To save a lot of space, two DLLs needed by the Romdump Wizard
have not been included in the Romdump Wizard's distribution.
They are called MSVCRT40.DLL and MFC40.DLL, and are available
on the Web at the Emu48 Official Homepage :
http://www.geocities.com/CapeCanaveral/5948/index.html
These two files are freely distributable, and would be included
in this archive if they weren't so large (about 1.4Mb for both)
Note that they are NOT needed by Emu48 : only the Romdump Wizard
requires them.
- HP48:
If you have already used another HP48 emulator, you can convert the ROM using
the Convert utility.
* Once you have your ROM dump(s), SAVE THEM TO A FLOPPY DISK !
It will save you a lot of troubles if you were to lose them.
To do that, start a Command Prompt while running Windows, and type:
Convert <rom-file> ROM.48G
or Convert <rom-file> ROM.48S
Where <rom-file> is the path to your old ROM image. This will create a file
named ROM.48G or ROM.48S, depending on the version you own. This tool should be
able to read any style of ROM image, and will also check its validity. Note that
if you run it with only one parameter, no file will be written, but it will
still check the validity of the ROM.
If you have never used an HP48 emulator, and don't have a ROM dump, you can
either use Jean-Yves Avenard's ROMUPL.BIN or the ROMDump Wizard V1.x, which will
almost automatically get the ROM from your HP48. Don't use the ROMDump Wizard
versions V0.x any more please! After the download you may have to convert your
dump with the CONVERT utility into the Emu48 format.
You can find the latest version of the ROM dump programs on:
ROMUPL.BIN http://www.epita.fr/~avenar_j/hp/calcen.html
ROMDump Wizard http://privat.swol.de/ChristophGiesselink/index.htm
Once you have your ROM dump(s), SAVE THEM TO A FLOPPY DISK! It will save you a
lot of trouble if you were lose them.
- HP49:
There's no ROM download program available so far. But you can find a HP49G ROM
for emulators in the YorkeM emulator package or in the HP49G SDK on
http://www.hpcalc.org in the HP49 section.
****************
* HOW TO START *
****************
When Emu48 is installed and you have put the ROM image(s) in its directory, you
can start Emu48. You'll see a "Choose Your KML Script" box.
When Emu48 is installed and you have put the ROM image(s) in the Emu48
directory, you can start Emu48. You'll see a "Choose Your KML Script" box.
KML Scripts in fact define the visual aspect of Emu48, the behaviour of the
buttons, of the keyboard... It is a GREAT way to customize your copy of Emu48.
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.
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.
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.
Choose a KML script in the list box. If you have put a G/GX ROM dump in Emu48's
directory, choose a script for G/GX. If you have put a S/SX ROM dump in Emu48's
directory, choose a script for S/SX.
Several scripts are included in the archive :
Several scripts are included in the common archive:
* Emu48's Default Faceplate for HP48G/GX
* Emu48's Default Faceplate for HP48S/SX
These two are simple scripts, and they use the bitmap from Win48 2.05.
These two are simple scripts, good for 800x600 display resolution.
* Casey's Gx with Toolbar and Touch Screen
* Casey's Sx with Toolbar and Touch Screen
These script uses many advanced features, and is a good demonstration of
the power of Emu48's scripting language, KML. Try it, it is really great !
the power of Emu48's scripting language KML. Try it, it is really great!
* Floating buttons
This one looks really great.
* Small but realistic HP48 Gx
This one has been designed for small resolutions such as 640x480.
Note: some things in this script have to be be fixed.
Note: some things in this script have to be fixed.
If you want other great scripts, visit Casey's Emu48 homepage:
http://www.gulftel.com/~pattersc/emu48/
And if you are interested in writting new scripts, you'll want the KML 2.0
documentation, available on Casey's page and on my page :
http://www.geocities.com/CapeCanaveral/5948/kmlind.htm
And if you are interested in writing new scripts, get the KML 2.0 documentation
from Christoph's page at http://privat.swol.de/ChristophGiesselink/emu48.htm
Once you have selected a script, press Ok to start the emulator. While it is
running, you can use the View/Change Kml Script to change the visual aspect
of Emu48.
Once you have selected a script, press OK to start the emulator. While it's
running, you can use the View/Change KML Script... command to change the visual
aspect of Emu48.
***************
* KML SCRIPTS *
***************
In some cases you have to fix Color 0 in your KML script file, because the
colors red and blue has been swapped in the "Lcd" section (bugfix in a previous
version). Don't use TRUELCD.KMI for emulating display contrast in your scripts.
It's not fully correct. The hardware contrast values are in the area from 0 to
31. But the HP48 ROMs bounds them to useful values. The S(X) ROM use only
display contrast values between 3 and 19 and the G(X) ROM values between 9 and
24.
****************
* COMMAND LINE *
****************
The command line syntax is "Emu48 [E48file [Port2file]]". The first parameter
sets the filename for the emulation data, the second parameter the Port2 file.
You're not able to set a Port2 file without setting the emulation data file. The
arguments are optional.
*******************
* LOAD/SAVE FILES *
*******************
There are two ways to transfer files from or to the emulator. The one way is to
use the serial port to transfer the data directly from your HP48 to the
emulator. The second way is to load data, saved on your PC, into the stack of
the emulator. You can do this by using the Edit/Load Object... command or with
the file Drag and Drop feature. But there's one important restriction, the data
must a HP binary file (begin with HPHP48- or HPHP49-, this depends on your
emulated calculator)! If not, the data is load as string. The Edit/Save
Object... command will save the data in stack level 1 on the PC (always binary
mode). Be sure, when you use the second way for data transfer, that no program
is running on the emulator. The second way doesn't work on a HP38, because he
has no stack. So you can load aplets only from the serial port.
*****************
* DRAG AND DROP *
*****************
Dropping HP48 objects over the emulator window will load program files (like the
command "Load object...") on the stack. Be sure that the emulator isn't busy
before doing this.
*******************
* SHARED RAM CARD *
*******************
You can add a SHARED (I'll explain later) ram card of up to 4Mb. By default, no such
card will be created when you start Emu48. The MkShared.exe utility, included in the
registered version, will allow you to create it.
You can add a SHARED (I'll explain later) ram card of up to 4MB to a HP48. By
default, no such card will be created when you start Emu48. The MkShared.exe
utility will allow you to create it.
The syntax is:
MkShared <filename> <size_in_kilobytes>
For example, you can create a 4Mb RAM card name SHARED.BIN (in Emu48's directory) with
the following command :
For example, you can create a 4MB RAM card name SHARED.BIN (in Emu48's
directory) with the following command:
MkShared SHARED.BIN 4096
Valid sizes are 128, 256, 512, 1024, 2048 and 4096 kb.
When you have created this file, run Emu48, and use the Close menu item to close the
calculator state. Now select View/Settings. In the "Port 2" text area, type the name
of the file you created (if you don't include a path, it will be searched for in Emu48's
directory).
Valid sizes are 32, 128, 256, 512, 1024, 2048 and 4096 KB. If you use RAM cards
greater than 128 KB in a HP48SX, you can only see the first 128 KB of the card.
You can also tick the check box "Port 2 Is Shared".
When the box is cleared, only the first instance of Emu48 will allow you to use the RAM
card in Port 2.
When this box is ticked, the first instance of Emu48 will give you both read and write
access to this RAM card. If then you start Emu48 again, the RAM card in Port 2 will be
write-protected. You can thus transfer files very easily between two calculators. This
RAM card is used by both S/SX and G/GX types.
When you have created this file, run Emu48, and use the Close menu item to close
the calculator state. Now select File/Settings. In the "Port 2" text area, type
the name of the file you created (if you don't include a path, it will be
searched for in Emu48's directory).
Note that you have to close Emu48 and restart it if you modify these settings.
You can also tick the check box "Port 2 Is Shared". When the box is cleared,
only the first instance of Emu48 will allow you to use the RAM card in Port 2.
When this box is ticked, the first instance of Emu48 will give you both read and
write access to this RAM card. If then you start Emu48 again, the RAM card in
Port 2 will be write-protected. Thus you can transfer files very easily between
two calculators. This RAM card is used by both S/SX and G/GX types.
***********************
* COPY / PASTE STRING *
***********************
********************
* SPECIAL FEATURES *
********************
With the menu items "Copy String" and "Paste String" in the "Edit" menu you're
able to copy HP48 string objects from the stack to the PC clipboard and vice
versa.
Emu48 includes a backup feature (in the View menu). It save the complete state of the
calculator in the computer's memory. You might want to use it before doing something
risky, and if you don't want to save to the disk. It provides some kind of Undo feature.
It is also used by Emu48 when you want to save or load a new document, to restore its
old state if you cancel the operation or of something goes wrong.
**********
* BACKUP *
**********
Emu48 includes a backup feature (in the Edit menu). It save the complete state
of the calculator in the computer's memory. You might want to use it before
doing something risky, and if you don't want to save to the disk. It provides
some kind of Undo feature. It is also used by Emu48 when you want to save or
load a new document, to restore its old state if you cancel the operation or of
something goes wrong.
************
* KEYBOARD *
************
To enter a character to the emulator use the PC keyboard (key translation
depends on the used KML script) or the mouse. If you press the left mouse
button, the emulator key is pressed as long as you press the mouse button or
leaving the area of the emulator button. Sometimes you need to press more then
one key (contrast setting, warmstart, ...). To do this, press the right mouse
button. All "locked" buttons are released after enter a key with the left mouse
button.
*********
* CLOCK *
*********
The emulator time is synchronized with the PC time at startup of the emulator.
This may cause problems with other non original operating systems running on the
HP48. On S(X) calculators the address area #00052-#00070, on G(X) calculators
the address area #00058-#00076 in Port0 are rewritten with the actual time
information.
*************
* EMU48.INI *
*************
The section [Timers] in the Emu48.ini file isn't used any more. The variable
values are replaced by useful constants. You may delete this section if you
want. Starting an old version of Emu48 (V1.07 and earlier) will add this section
again.
************************
* REAL SPEED EMULATION *
************************
As you recognized the speed of the emulated HP48 is much faster than an original
HP48. The reason is, the assembler commands are emulated faster than the
original CPU can execute them. On one side this is a big advantage (faster
execution of programs) on the other side this cause many trouble. In Emu48 only
the timers work with the original speed. In result all commands like User-RPL
WAIT wait more or less the correct time. But many programs like shells or
editors use an own key handler to realize an autorepeat implementation. Normally
these programs use the execution time of each assembler command for waiting. On
Emu48 this time is much shorter, so the time between each key read is shorter as
well and you get a very fast key repetition. The editor ED from the JAZZ package
hasn't this problem, because the key input is synchronized with one of the
timers. To solve this problem Emu48 generally slow down emulation if a key is
pressed. To solve some other speed depending problems you are able to slow down
the whole emulation speed. There are two variables 'SXCycles=82' and
'GXCycles=123' defined in the Emu48.ini file, section [Emulator] which control
the "real" speed and key repetition slow down for each calculator type. Each
numeric value is representing the allowed CPU cycles in a 16384Hz time frame.
Because the used cycle statements (from SASM.DOC) in Emu48 doesn't correspond to
the real values of the CPU, the saved values are estimated by comparing the
execution time of a program to the real calculator. Increasing the value fitting
to your ROM will make the "real speed" HP faster and vice versa. No warranty to
the functionality of Emu48 when you go below the default values.
*************************
* SERIAL PORT EMULATION *
*************************
The serial ports are emulated as well now. You may choose the same serial port
for wire and IR. Remember that the IR port only work with 2400 Baud. If you want
to change the serial port settings, but they are disabled, close the serial port
with the command CLOSEIO or power cycle the HP48 first.
Now it's possible to make transfers between the HP48 and Emu48. If you have
problems with the connection please try the following. There's a simple way to
check if your serial port is used by another program. First disable the serial
settings in both combo boxes and very important close the settings dialog.
Reopen the settings dialog and choose the COM port in the wire combo box to the
port the HP48 is connected with. When you open this combo box you only see valid
(unused) serial ports. Don't use the IR combo box, it only works with 2400 Baud.
The next important thing are the serial settings of the HP48 and Emu48, they
must be equal. If this doesn't work then mostly there's a hardware or a resource
problem of the serial port. Check this with connecting the HP48 with a transfer
program you like on the same serial port.
****************
* DISASSEMBLER *
****************
With the internal disassembler you're able to disassemble the HP48 address area.
With the default Map setting the disassembler always see the mapped memory
address. If for example you configured the RAM at #00000 you will see the RAM
and not the ROM at this address. With the other Module settings you specify a
special module for disassembly. Each module will begin at address #00000 and
will not overlapped by other modules. For Port2 I use a linear address mode,
that means that the second port of a RAM card greater than 128KB is at address
#40000 (128 * 1024 * 2) and so on. The "Copy Data" button copies the selected
disassembler lines to the PC clipboard.
**************
* DDE SERVER *
**************
I implemented a DDE server in Emu48 to transmit data from and to the HP stack
with DDE. You have the same restrictions like with the commands "Load object..."
and "Save Object...", that a running program may corrupt memory. Take care to
transmit data only after the acknowledge of the last DDE transaction.
Technical data:
Servername: Emu48
Topicname: Stack
Item: Dummy (ignored, must be a nonzero string)
Clipboardformat: "CF_HPOBJ" (user defined)
The DDE commands CONNECT, POKE and REQUEST are supported.
The structure of the clipboard format "CF_HPOBJ":
+--------+------------------------------------+
| 4 Byte | HP object |
+--------+------------------------------------+
\ \
\ +--- normal HP object
+----------- length of object (LSB first)
********************
* TROUBLE SHOOTING *
********************
Q: The emulator display the keyboard, but the screen stays blank or is filled
with garbage.
A: Your ROM image is probably wrong. Check it with the Convert utility, and if
it says that the CRC is wrong, you should try to download your ROM again.
Q: What does this message mean :
"This file is missing or already loaded in another instance of Emu48."
A: Maybe you deleted or moved the files that the emulator tries to load when
starting (the last files you saved).
The other possibility is that you are running several instances of Emu48,
but you are trying to load the same file in both instances, which causes
a sharing violation.
Visit the Emu48 FAQ site at http://privat.swol.de/ChristophGiesselink/index.htm
to get more information please.
***********
* SUPPORT *
***********
I cannot provide individual support for Emu48, but I will read all the mails
that you send.
All informations about Emu48 will be on the Emu48 Official Homepage on the Web :
We cannot provide individual support for Emu48, but we will read all the mails
that you send. All informations about Emu48 will be on the Emu48 Official
Homepage on the Web:
http://www.epita.fr/~sebc/Emu48
http://www.epita.fr/~sebc/Emu48/index.html
Service packs are maintained by Christoph Gießelink :
or on the Emu48 FAQ at
http://privat.swol.de/ChristophGiesselink/
http://privat.swol.de/ChristophGiesselink/index.htm
Other graphics and scripts are available at Casey's Emu48 Graphics Page:
http://www.gulftel.com/~pattersc/emu48/
http://www.gulftel.com/~pattersc/emu48/
***************
* LEGAL STUFF *
***************
Emu48 - An HP48 Emulator
Copyright (C) 1997 Sebastien Carlier
Emu48 - An HP38/48/49 Emulator
Copyright (C) 1999 Sebastien Carlier & Christoph Gießelink
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) any later version.
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) any later
version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
**************
* The Author *
**************
***************
* The Authors *
***************
Paper Mail:
Sebastien Carlier
@ -233,4 +419,15 @@ E-Mail:
sebc@epita.fr
Homepage:
http://www.epita.fr/~sebc
http://www.epita.fr/~sebc/Emu48/index.html
Paper Mail:
Christoph Giesselink
GERMANY
E-Mail:
cgiess@swol.de
Homepage:
http://privat.swol.de/ChristophGiesselink/index.htm

View file

@ -1,137 +0,0 @@
Emu48 - A freeware HP48 Emulator for Windows 95 and NT
--- Changes and Additions of Emu48 V1.0 ---
Thank Sebastien Carlier for his emulator and that he made the sources public. Special thanks to Jean-Yves Avenard, Cyrille de Brebisson and Will Laughin for there suggestions, additions and fixes.
My first contact with this emulator (Shareware Win48) was in early 1997. At this time I worked with Windows NT 4.0. The emulator was unusable for me at this time. As well I had some problems with the latest version of Emu48 (Version 1.0). This was the beginning of the "Unofficial Service Packs".
********************
* OPERATING SYSTEM *
********************
This version of Emu48 should work with all Intel Win32 platforms. Several problems with Windows NT 4.0, Win95b and Win98 are fixed now. You may recompile the sources to run Emu48 on a DEC Alpha.
****************
* COMMAND LINE *
****************
The command line syntax is "Emu48 [E48file [Port2file]]". The first parameter sets the filename for the Emulation Data, the second parameter the Port2 file. You're not able to set a Port2 file without setting the Emulation Data file. The arguments are optional.
***********
* DISPLAY *
***********
The display emulation is now closer to the original. But there are several problems left, especially with the gray scale emulation.
********************
* KEYBOARD CHANGES *
********************
I changed the behavior for pressing more than one key. All keys will release, when you go outside the button area now. To hold down a key, you have to press the right mouse button. The key autorepeat emulation is working now.
*********
* CLOCK *
*********
The emulator time is synchronized with the PC time at startup of the emulator. This may cause problems with other non original operating systems running on the HP48. On S(X) calculators the address area #00052-#00070, on G(X) calculators the address area #00058-#00076 in Port0 are rewritten with the actual time information.
***************
* KML SCRIPTS *
***************
Your LCD contrast setting will be saved now. In some cases you have to fix Color 0 in your KML script file, because the colors red and blue has been swapped in the "Lcd" section. Don't use TRUELCD.KMI for emulating display contrast in your scripts. It's not fully correct. The hardware contrast values are in the area from 0 to 31. But the HP48 roms bounds them to useful values. The S(X) ROM use only display contrast values between 3 and 19 and the G(X) ROM values between 9 and 24.
You're able to define a different background color for each contrast value for a more realistic display emulation now. The background color entry for the corresponding color is calculated by adding 32 to the color value. That means the color definitions from 32 to 63 are background colors. If the background color for the contrast isn't defined, Color 0 is used.
You can use 4 as new value for "Zoom" in the "Lcd" section of the KML script for a very big display view now.
***********************
* COPY / PASTE STRING *
***********************
With the menu items "Copy String" and "Paste String" in the "Edit" menu you're able to copy HP48 string objects from the stack to the PC Clipboard and vice versa.
*****************
* DRAG AND DROP *
*****************
Dropping HP48 objects over the emulator window will load program files (like the command "Load object...") on the stack. Be sure that the emulator isn't busy before doing this.
*************
* EMU48.INI *
*************
The section [Timers] in the Emu48.ini file isn't used any more. The variable values are replaced by useful constants. You may delete this section if you want. Starting an old version of Emu48 (V1.07 and earlier) will add this section again.
************************
* REAL SPEED EMULATION *
************************
As you recognized the speed of the emulated HP48 is much faster than an original HP48. The reason is, the assembler commands are emulated faster than the original CPU can execute them. On one side this is a big advantage (faster execution of programs) on the other side this cause many trouble. In Emu48 only the timers work with the original speed. In result all commands like User-RPL WAIT wait more or less the correct time. But many programs like shells or editors use an own key handler to realize an autorepeat implementation. Normally these programs use the execution time of each assembler command for waiting. On Emu48 this time is much shorter, so the time between each key read is shorter as well and you get a very fast key repetition. The editor ED from the JAZZ package hasn't this problem, because the key input is synchronized with one of the timers. To solve this problem Emu48 generally slow down emulation if a key is pressed. To solve some other speed depending problems you are able to slow down the whole emulation speed. There are two variables 'SXCycles=82' and 'GXCycles=123' defined in the Emu48.ini file, section [Emulator] which control the "real" speed and key repetition slow down for each calculator type. Each numeric value is representing the allowed CPU cycles in a 16384Hz time frame. Because the used cycle statements (from SASM.DOC) in Emu48 doesn't correspond to the real values of the CPU, the saved values are estimated by comparing the execution time of a program to the real calculator. Increasing the value fitting to your ROM will make the "real speed" HP faster and vice versa. No warranty to the functionality of Emu48 when you go below the default values.
*************************
* SERIAL PORT EMULATION *
*************************
The serial ports are emulated as well now. You may choose the same serial port for wire and IR. Remember that the IR port only work with 2400 Baud. There's a problem known with the command RECX from the Library 1275: "XYMODEM v3.2 for S/G". On fast PC's this command doesn't work. Slow down emulation to run it. If you want to change the serial port settings, but they are disabled, close the serial port with the command CLOSEIO or power cycle the HP48 first.
Now it's possible to make transfers between the HP48 and Emu48. If you have problems with the connection please try the following. There's a simple way to check if your serial port is used by another program. First disable the serial settings in both combo boxes and very important close the settings dialog. Reopen the settings dialog and choose the COM port in the wire combo box to the port the HP48 is connected with. When you open this combo box you only see valid (unused) serial ports. Don't use the IR combo box, it only works with 2400 Baud. The next important thing are the serial settings of the HP48 and Emu48, they must be equal. If this doesn't work then mostly there's a hardware problem, check this with connecting the HP48 with a transfer program you like on the same serial port.
****************
* DISASSEMBLER *
****************
With the internal disassembler you're able to disassemble the HP48 address area. With the default Map setting the disassembler always see the mapped memory address. If for example you configured the RAM at #00000 you will see the RAM and not the ROM at this address. With the other Module settings you specify a special module for disassembly. Each module will begin at address #00000 and will not overlapped by other modules. For Port2 I use a linear address mode, that means that the second port of a RAM card greater than 128K is at address #40000 (128 * 1024 * 2) and so on. The "Copy Data" button copies the selected disassembler lines to the PC Clipboard.
**************
* DDE SERVER *
**************
I implemented a DDE server in Emu48 to transmit data from and to the HP stack with DDE. You have the same restrictions like with the commands "Load object..." and "Save Object...", that a running program may corrupt memory. Take care to transmit data only after the acknowledge of the last DDE transaction.
Technical data:
Servername: Emu48
Topicname: Stack
Item: Dummy (ignored, must be a nonzero string)
Clipboardformat: "CF_HPOBJ" (user defined)
The DDE commands CONNECT, POKE and REQUEST are supported.
The structure of the clipboard format "CF_HPOBJ":
+--------+------------------------------------+
| 4 Byte | HP object |
+--------+------------------------------------+
\ \
\ +--- normal HP object
+----------- length of object (LSB first)
********
* TIPS *
********
I hope some of your Emu48 problems has been solved as well. If you use a patched ROM version (i.e. to solve the auto off problem), try an unpatched one.
Christoph Gießelink, cgiess@swol.de
http://privat.swol.de/ChristophGiesselink

BIN
JC.BMP

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

364
JC.KML
View file

@ -1,364 +0,0 @@
Global
Title "Small but realistic HP48 Gx"
Author "Jeffery L. McMahan and Sebastien Carlier"
Print "Original picture by Jeffery L. McMahan"
Print "Modified for VGA by Sebastien Carlier"
Model "G"
Rom "ROM.48G"
Patch "BEEP.EXT"
Bitmap "jc.bmp"
Debug 1
End
Background
Offset 0 0
Size 165 353
End
Lcd
Zoom 1
Offset 17 43
Include "TrueLCD.kmi"
End
Annunciator 1
Size 8 6
Offset 40 45
Down 0 400
End
Annunciator 2
Size 8 6
Offset 60 45
Down 9 400
End
Annunciator 3
Size 8 6
Offset 80 45
Down 17 400
End
Annunciator 4
Size 10 6
Offset 100 45
Down 25 400
End
Annunciator 5
Size 5 6
Offset 120 45
Down 35 400
End
Annunciator 6
Size 7 6
Offset 140 45
Down 43 400
End
Button 11
Type 3
Size 16 10
Offset 17 139
OutIn 1 16
End
Button 12
Type 3
Size 16 10
Offset 40 139
OutIn 8 16
End
Button 13
Type 3
Size 16 10
Offset 63 139
OutIn 8 8
End
Button 14
Type 3
Size 16 10
Offset 86 139
OutIn 8 4
End
Button 15
Type 3
Size 16 10
Offset 109 139
OutIn 8 2
End
Button 16
Type 3
Size 16 10
Offset 132 139
OutIn 8 1
End
Button 21
Type 3
Size 16 12
Offset 17 162
OutIn 2 16
End
Button 22
Type 3
Size 16 12
Offset 40 162
OutIn 7 16
End
Button 23
Type 3
Size 16 12
Offset 63 162
OutIn 7 8
End
Button 24
Type 3
Size 16 12
Offset 86 162
OutIn 7 4
End
Button 25
Type 3
Size 16 12
Offset 109 162
OutIn 7 2
End
Button 26
Type 3
Size 16 12
Offset 132 162
OutIn 7 1
End
Button 31
Type 3
Size 16 12
Offset 17 184
OutIn 0 16
End
Button 32
Type 3
Size 16 12
Offset 40 184
OutIn 6 16
End
Button 33
Type 3
Size 16 12
Offset 63 184
OutIn 6 8
End
Button 34
Type 3
Size 16 12
Offset 86 184
OutIn 6 4
End
Button 35
Type 3
Size 16 12
Offset 109 184
OutIn 6 2
End
Button 36
Type 3
Size 16 12
Offset 132 184
OutIn 6 1
End
Button 41
Type 3
Size 16 12
Offset 17 207
OutIn 3 16
End
Button 42
Type 3
Size 16 12
Offset 40 207
OutIn 5 16
End
Button 43
Type 3
Size 16 12
Offset 63 207
OutIn 5 8
End
Button 44
Type 3
Size 16 12
Offset 86 207
OutIn 5 4
End
Button 45
Type 3
Size 16 12
Offset 109 207
OutIn 5 2
End
Button 46
Type 3
Size 16 12
Offset 132 207
OutIn 5 1
End
Button 51
Type 1
Size 39 12
Offset 17 229
OutIn 4 16
End
Button 52
Type 3
Size 16 10
Offset 70 229
OutIn 4 8
End
Button 53
Type 3
Size 16 10
Offset 95 229
OutIn 4 4
End
Button 54
Type 3
Size 16 10
Offset 121 229
OutIn 4 2
End
Button 55
Type 3
Size 16 10
Offset 147 229
OutIn 4 1
End
Button 61
Type 3
Size 16 10
Offset 19 252
OutIn 3 32
End
Button 62
Type 3
Size 21 12
Offset 43 252
OutIn 3 8
End
Button 63
Type 3
Size 21 12
Offset 79 252
OutIn 3 4
End
Button 64
Type 3
Size 21 12
Offset 110 252
OutIn 3 2
End
Button 65
Type 3
Size 21 12
Offset 141 252
OutIn 3 1
End
Button 71
Type 3
Size 16 10
Offset 19 274
OutIn 2 32
End
Button 72
Type 3
Size 21 12
Offset 48 274
OutIn 2 8
End
Button 73
Type 3
Size 21 12
Offset 79 274
OutIn 2 4
End
Button 74
Type 3
Size 21 12
Offset 110 274
OutIn 2 2
End
Button 75
Type 3
Size 21 12
Offset 141 274
OutIn 2 1
End
Button 81
Type 3
Size 16 10
Offset 19 297
OutIn 1 32
End
Button 82
Type 3
Size 21 12
Offset 48 297
OutIn 1 8
End
Button 83
Type 3
Size 21 12
Offset 79 297
OutIn 1 4
End
Button 84
Type 3
Size 21 12
Offset 110 297
OutIn 1 2
End
Button 85
Type 3
Size 21 12
Offset 141 297
OutIn 1 1
End
Button 91
Type 3
Size 16 10
Offset 19 319
OutIn 0 32768
End
Button 92
Type 3
Size 21 12
Offset 48 319
OutIn 0 8
End
Button 93
Type 3
Size 21 12
Offset 79 319
OutIn 0 4
End
Button 94
Type 3
Size 21 12
Offset 110 319
OutIn 0 2
End
Button 95
Type 3
Size 21 12
Offset 141 319
OutIn 0 1
End
Include "Keyboard.kmi"

BIN
JEMAC.BMP Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

View file

@ -16,38 +16,70 @@ End
Lcd
Zoom 2
Offset 34 86
Color 0 123 132 99
Color 0 123 132 99 # character color table
Color 1 123 132 99
Color 2 123 132 99
Color 3 123 132 99
Color 4 123 132 99
Color 5 123 132 99
Color 6 123 132 99
Color 7 123 132 99
Color 8 123 132 99
Color 7 121 132 99
Color 8 121 132 99
Color 9 116 124 96
Color 10 109 116 93
Color 11 102 108 90
Color 12 95 100 87
Color 13 88 92 84
Color 14 81 84 78
Color 15 74 76 75
Color 16 67 68 72
Color 17 60 60 69
Color 18 53 52 66
Color 19 46 44 63
Color 20 39 36 60
Color 21 32 28 57
Color 22 25 20 54
Color 23 18 12 51
Color 24 11 4 48
Color 25 4 0 45
Color 26 0 0 42
Color 27 0 0 39
Color 28 0 0 36
Color 29 0 0 33
Color 30 0 0 30
Color 31 0 0 27
Color 10 101 107 88
Color 11 86 90 80
Color 12 71 73 72
Color 13 56 56 64
Color 14 41 39 56
Color 15 26 22 48
Color 16 11 5 40
Color 17 11 5 40
Color 18 11 5 40
Color 19 11 5 40
Color 20 11 5 40
Color 21 11 5 40
Color 22 11 5 40
Color 23 11 5 40
Color 24 11 5 40 # last GX
Color 25 11 5 40
Color 26 11 5 40
Color 27 11 5 40
Color 28 11 5 40
Color 29 11 5 40
Color 30 11 5 40
Color 31 11 5 40
Color 32 123 132 99 # background color table
Color 33 123 132 99
Color 34 123 132 99
Color 35 123 132 99
Color 36 123 132 99
Color 37 121 132 99
Color 38 121 132 99
Color 39 123 132 99
Color 40 123 132 99
Color 41 123 132 99
Color 42 123 132 99
Color 43 123 132 99
Color 44 123 132 99
Color 45 123 132 99
Color 46 123 132 99
Color 47 123 132 99
Color 48 123 132 99
Color 49 111 119 95
Color 50 99 106 91
Color 51 87 93 87
Color 52 75 80 83
Color 53 63 67 79
Color 54 51 54 75
Color 55 39 41 72
Color 56 27 28 67
Color 57 15 15 62
Color 58 3 2 57
Color 59 0 0 52
Color 60 0 0 47
Color 61 0 0 42
Color 62 0 0 37
Color 63 0 0 32
End
Annunciator 1
@ -438,6 +470,10 @@ Scancode 40
Map 40 35
End
Scancode 48
Map 48 92
End
Scancode 49
IfFlag 0
Map 49 71

View file

@ -1,12 +1,18 @@
Known bugs and restrictions of Emu48 V1.10
Known bugs and restrictions of Emu48 V1.15
------------------------------------------
- input cursor blink frequency on stack view is wrong when a key is
hold down
- the POWERCTRL register (0x109) isn't emulated
- bit 3 [UCK] of the BAUD register (0x10D) isn't emulated
- the bits of the SRQ registers (0x118,0x119), except the KDN bit,
aren't emulated
- the following I/O bits aren't emulated (incomplete)
DTEST (0x102) [VDIG LID TRIM]
DSPCTL (0x103) [LRT LRTD LRTC BIN]
LPE (0x109) [ELBI EVLBI GRST RST]
IOC (0x110) [ERBZ]
RCS (0x111) [RX RER RBZ]
TCS (0x112) [BRK TBZ TBF]
SRQ1 (0x118) [ISQR VSRQ]
SRQ2 (0x119) [LSRQ]
IRC (0x11A) [IRI EIRU EIRI IRE]
LCR (0x11C) [LED ELBE LBZ LBF]
LBR (0x11D) [LBO]
- the baudrates 1920, 3840, 7680 and 15360 aren't emulated on most
operating systems
Windows 95a 1920, 3840, 7680 work, 15360 fail
@ -14,9 +20,6 @@ Known bugs and restrictions of Emu48 V1.10
Windows NT4.0 SP3 all baudrates fail
- System-RPL commands VERYVERYSLOW, VERYSLOW and SLOW depends on PC
speed (are realized as simple down counter in ROM)
- in all original KML scripts Color 7 is missing in the LCD section
- because of correcting the RGB order in SetLcdColor() the LCD
background color may be wrong in some KML scripts
- display updating differs from the real machine
- screen VBL counter values may skip after large display operations
like turning on or updating the whole display
@ -26,12 +29,16 @@ Known bugs and restrictions of Emu48 V1.10
because the emulator don't use a multiplexed AR18 / NCE3 data line
-> all programs that run on a real calculator will run as well,
programs with incorrect DA19 / BEN handling may run on the
emulator and will crash on a real calculator
emulator but will crash on a real calculator
- 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,
Windows 9x: plays only default sound event or standard system beep
- no infrared printer support
- memory window of debugger view some addresses in I/O register area
with invalid data
- Shell OS: clock isn't synchronized with real time
- HP49G: flash ROM is treated as ROM (no writing to flash memory)
-> writing to port 2:FLASH will crash the emulation!
03/11/99 (c) by Christoph Gießelink, cgiess@swol.de
12/14/99 (c) by Christoph Gießelink, cgiess@swol.de

BIN
REALGX.BMP Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

722
REALGX.KML Normal file
View file

@ -0,0 +1,722 @@
Global
Print "=========================================================="
Print ""
Print "This graphic is by Casey Patterson."
Print "pattersc@gulftel.com"
Print ""
Print "Come to my page to get more graphics for your Win48!!!"
Print ""
Print "http://www.gulftel.com/~pattersc/win48/"
Print ""
Print "=========================================================="
Title "Casey's Real Gx"
Author "Casey Patterson"
Model "G"
Rom "ROM.48G"
Patch "BEEP.EXT"
Bitmap "realgx.bmp"
Debug 0
End
Background
Offset 0 0
Size 183 400
End
Lcd
Zoom 1
Offset 27 53
Color 0 123 132 99
Color 1 123 132 99
Color 2 123 132 99
Color 3 123 132 99
Color 4 123 132 99
Color 5 123 132 99
Color 6 123 132 99
Color 7 123 132 99
Color 8 123 132 99
Color 9 116 124 96
Color 10 109 116 93
Color 11 102 108 90
Color 12 95 100 87
Color 13 88 92 84
Color 14 81 84 78
Color 15 74 76 75
Color 16 67 68 72
Color 17 60 60 69
Color 18 53 52 66
Color 19 46 44 63
Color 20 39 36 60
Color 21 32 28 57
Color 22 25 20 54
Color 23 18 12 51
Color 24 11 4 48
Color 25 4 0 45
Color 26 0 0 42
Color 27 0 0 39
Color 28 0 0 36
Color 29 0 0 33
Color 30 0 0 30
Color 31 0 0 27
End
Annunciator 1
Size 8 6
Offset 40 45
Down 0 400
End
Annunciator 2
Size 8 6
Offset 60 45
Down 9 400
End
Annunciator 3
Size 8 6
Offset 80 45
Down 17 400
End
Annunciator 4
Size 10 6
Offset 100 45
Down 25 400
End
Annunciator 5
Size 5 6
Offset 120 45
Down 35 400
End
Annunciator 6
Size 7 6
Offset 140 45
Down 43 400
End
Button 11
Type 1
Size 19 13
Offset 18 156
OutIn 1 16
End
Button 12
Type 1
Size 19 13
Offset 44 156
OutIn 8 16
End
Button 13
Type 1
Size 19 13
Offset 70 156
OutIn 8 8
End
Button 14
Type 1
Size 19 13
Offset 95 156
OutIn 8 4
End
Button 15
Type 1
Size 19 13
Offset 121 156
OutIn 8 2
End
Button 16
Type 1
Size 19 13
Offset 147 156
OutIn 8 1
End
Button 21
Type 1
Size 19 15
Offset 18 182
OutIn 2 16
End
Button 22
Type 1
Size 19 15
Offset 44 182
OutIn 7 16
End
Button 23
Type 1
Size 19 15
Offset 70 182
OutIn 7 8
End
Button 24
Type 1
Size 19 15
Offset 95 182
OutIn 7 4
End
Button 25
Type 1
Size 19 15
Offset 121 182
OutIn 7 2
End
Button 26
Type 1
Size 19 15
Offset 147 182
OutIn 7 1
End
Button 31
Type 1
Size 19 15
Offset 18 208
OutIn 0 16
End
Button 32
Type 1
Size 19 15
Offset 44 208
OutIn 6 16
End
Button 33
Type 1
Size 19 15
Offset 70 208
OutIn 6 8
End
Button 34
Type 1
Size 19 15
Offset 95 208
OutIn 6 4
End
Button 35
Type 1
Size 19 15
Offset 121 208
OutIn 6 2
End
Button 36
Type 1
Size 19 15
Offset 147 208
OutIn 6 1
End
Button 41
Type 1
Size 19 15
Offset 18 233
OutIn 3 16
End
Button 42
Type 1
Size 19 15
Offset 44 233
OutIn 5 16
End
Button 43
Type 1
Size 19 15
Offset 70 233
OutIn 5 8
End
Button 44
Type 1
Size 19 15
Offset 95 233
OutIn 5 4
End
Button 45
Type 1
Size 19 15
Offset 121 233
OutIn 5 2
End
Button 46
Type 1
Size 19 15
Offset 147 233
OutIn 5 1
End
Button 51
Type 1
Size 45 15
Offset 18 259
OutIn 4 16
End
Button 52
Type 1
Size 19 15
Offset 70 259
OutIn 4 8
End
Button 53
Type 1
Size 19 15
Offset 95 259
OutIn 4 4
End
Button 54
Type 1
Size 19 15
Offset 121 259
OutIn 4 2
End
Button 55
Type 1
Size 19 15
Offset 147 259
OutIn 4 1
End
Button 61
Type 1
Size 18 15
Offset 19 284
OutIn 3 32
End
Button 62
Type 1
Size 24 15
Offset 48 284
OutIn 3 8
End
Button 63
Type 1
Size 24 15
Offset 79 284
OutIn 3 4
End
Button 64
Type 1
Size 24 15
Offset 110 284
OutIn 3 2
End
Button 65
Type 1
Size 24 15
Offset 141 284
OutIn 3 1
End
Button 71
Type 1
Size 18 15
Offset 19 310
OutIn 2 32
End
Button 72
Type 1
Size 24 15
Offset 48 310
OutIn 2 8
End
Button 73
Type 1
Size 24 15
Offset 79 310
OutIn 2 4
End
Button 74
Type 1
Size 24 15
Offset 110 310
OutIn 2 2
End
Button 75
Type 1
Size 24 15
Offset 141 310
OutIn 2 1
End
Button 81
Type 1
Size 18 15
Offset 19 335
OutIn 1 32
End
Button 82
Type 1
Size 24 15
Offset 48 335
OutIn 1 8
End
Button 83
Type 1
Size 24 15
Offset 79 335
OutIn 1 4
End
Button 84
Type 1
Size 24 15
Offset 110 335
OutIn 1 2
End
Button 85
Type 1
Size 24 15
Offset 141 335
OutIn 1 1
End
Button 91
Type 1
Size 18 15
Offset 19 361
OutIn 0 32768
End
Button 92
Type 1
Size 24 15
Offset 48 361
OutIn 0 8
End
Button 93
Type 1
Size 24 15
Offset 79 361
OutIn 0 4
End
Button 94
Type 1
Size 24 15
Offset 110 361
OutIn 0 2
End
Button 95
Type 1
Size 24 15
Offset 141 361
OutIn 0 1
End
Scancode 8
Map 8 55
End
Scancode 13
Map 13 51
End
Scancode 16
IfPressed 16
SetFlag 0
Else
ResetFlag 0
End
End
Scancode 17
IfPressed 17
SetFlag 1
Else
ResetFlag 1
End
End
Scancode 27
Map 27 91
End
Scancode 37
Map 37 34
End
Scancode 38
Map 38 25
End
Scancode 39
Map 39 36
End
Scancode 40
Map 40 35
End
Scancode 49
IfFlag 0
Map 49 71
Map 49 54
Else
Map 49 82
End
End
Scancode 50
Map 50 83
End
Scancode 51
IfFlag 0
Map 51 81
Map 51 65
Else
Map 51 84
End
End
Scancode 52
Map 52 72
End
Scancode 53
Map 53 73
End
Scancode 54
Map 54 74
End
Scancode 55
Map 55 62
End
Scancode 56
IfFlag 0
Map 56 75
Else
Map 56 63
End
End
Scancode 57
IfFlag 0
Map 57 71
Map 57 65
Else
Map 57 64
End
End
Scancode 65
Map 65 11
End
Scancode 66
Map 66 12
End
Scancode 67
Map 67 13
End
Scancode 68
Map 68 14
End
Scancode 69
Map 69 15
End
Scancode 70
Map 70 16
End
Scancode 71
Map 71 21
End
Scancode 72
Map 72 22
End
Scancode 73
Map 73 23
End
Scancode 74
Map 74 24
End
Scancode 75
Map 75 25
End
Scancode 76
Map 76 26
End
Scancode 77
Map 77 31
End
Scancode 78
IfFlag 1
MenuItem 1
Else
Map 78 32
End
End
Scancode 79
Map 79 33
End
Scancode 80
Map 80 34
End
Scancode 81
Map 81 35
End
Scancode 82
Map 82 36
End
Scancode 83
Map 83 41
End
Scancode 84
Map 84 42
End
Scancode 85
Map 85 43
End
Scancode 86
Map 86 44
End
Scancode 87
Map 87 45
End
Scancode 88
Map 88 46
End
Scancode 89
Map 89 52
End
Scancode 90
Map 90 53
End
Scancode 96
Map 96 92
End
Scancode 97
Map 97 82
End
Scancode 98
Map 98 83
End
Scancode 99
Map 99 84
End
Scancode 100
Map 100 72
End
Scancode 101
Map 101 73
End
Scancode 102
Map 102 74
End
Scancode 103
Map 103 62
End
Scancode 104
Map 104 63
End
Scancode 105
Map 105 64
End
Scancode 106
Map 106 75
End
Scancode 107
Map 107 95
End
Scancode 109
Map 109 85
End
Scancode 110
Map 110 93
End
Scancode 111
Map 111 65
End
Scancode 186
IfFlag 0
Map 186 81
Map 186 95
End
End
Scancode 188
Map 188 71
Map 188 93
End
Scancode 190
Map 190 93
End
Scancode 191
IfFlag 0
Map 191 71
Map 191 55
Else
Map 191 65
End
End
Scancode 219
IfFlag 0
Map 219 71
Map 219 95
Else
Map 219 71
Map 219 75
End
End
Scancode 220
Map 220 54
End
Scancode 222
IfFlag 0
Map 222 81
Map 222 85
Else
Map 222 31
End
End

BIN
REALSX.BMP Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

722
REALSX.KML Normal file
View file

@ -0,0 +1,722 @@
Global
Print "=========================================================="
Print ""
Print "This graphic is by Casey Patterson."
Print "pattersc@gulftel.com"
Print ""
Print "Come to my page to get more graphics for your Win48!!!"
Print ""
Print "http://www.gulftel.com/~pattersc/win48/"
Print ""
Print "=========================================================="
Title "Casey's Real Sx"
Author "Casey Patterson"
Model "S"
Rom "ROM.48S"
Patch "BEEP.EXT"
Bitmap "realsx.bmp"
Debug 0
End
Background
Offset 0 0
Size 183 400
End
Lcd
Zoom 1
Offset 26 53
Color 0 161 173 130
Color 1 0 0 0
Color 2 0 0 0
Color 3 0 0 0
Color 4 0 0 0
Color 5 0 0 0
Color 6 0 0 0
Color 7 0 0 0
Color 8 0 0 0
Color 9 0 0 0
Color 10 0 0 0
Color 11 0 0 0
Color 12 0 0 0
Color 13 0 0 0
Color 14 0 0 0
Color 15 0 0 0
Color 16 0 0 0
Color 17 0 0 0
Color 18 0 0 0
Color 19 0 0 0
Color 20 0 0 0
Color 21 0 0 0
Color 22 0 0 0
Color 23 0 0 0
Color 24 0 0 0
Color 25 0 0 0
Color 26 0 0 0
Color 27 0 0 0
Color 28 0 0 0
Color 29 0 0 0
Color 30 0 0 0
Color 31 0 0 0
End
Annunciator 1
Size 8 6
Offset 40 45
Down 0 400
End
Annunciator 2
Size 8 6
Offset 60 45
Down 9 400
End
Annunciator 3
Size 8 6
Offset 80 45
Down 17 400
End
Annunciator 4
Size 10 6
Offset 100 45
Down 25 400
End
Annunciator 5
Size 5 6
Offset 120 45
Down 35 400
End
Annunciator 6
Size 7 6
Offset 140 45
Down 43 400
End
Button 11
Type 1
Size 19 13
Offset 18 156
OutIn 1 16
End
Button 12
Type 1
Size 19 13
Offset 44 156
OutIn 8 16
End
Button 13
Type 1
Size 19 13
Offset 70 156
OutIn 8 8
End
Button 14
Type 1
Size 19 13
Offset 95 156
OutIn 8 4
End
Button 15
Type 1
Size 19 13
Offset 121 156
OutIn 8 2
End
Button 16
Type 1
Size 19 13
Offset 147 156
OutIn 8 1
End
Button 21
Type 1
Size 19 15
Offset 18 182
OutIn 2 16
End
Button 22
Type 1
Size 19 15
Offset 44 182
OutIn 7 16
End
Button 23
Type 1
Size 19 15
Offset 70 182
OutIn 7 8
End
Button 24
Type 1
Size 19 15
Offset 95 182
OutIn 7 4
End
Button 25
Type 1
Size 19 15
Offset 121 182
OutIn 7 2
End
Button 26
Type 1
Size 19 15
Offset 147 182
OutIn 7 1
End
Button 31
Type 1
Size 19 15
Offset 18 208
OutIn 0 16
End
Button 32
Type 1
Size 19 15
Offset 44 208
OutIn 6 16
End
Button 33
Type 1
Size 19 15
Offset 70 208
OutIn 6 8
End
Button 34
Type 1
Size 19 15
Offset 95 208
OutIn 6 4
End
Button 35
Type 1
Size 19 15
Offset 121 208
OutIn 6 2
End
Button 36
Type 1
Size 19 15
Offset 147 208
OutIn 6 1
End
Button 41
Type 1
Size 19 15
Offset 18 233
OutIn 3 16
End
Button 42
Type 1
Size 19 15
Offset 44 233
OutIn 5 16
End
Button 43
Type 1
Size 19 15
Offset 70 233
OutIn 5 8
End
Button 44
Type 1
Size 19 15
Offset 95 233
OutIn 5 4
End
Button 45
Type 1
Size 19 15
Offset 121 233
OutIn 5 2
End
Button 46
Type 1
Size 19 15
Offset 147 233
OutIn 5 1
End
Button 51
Type 1
Size 45 15
Offset 18 259
OutIn 4 16
End
Button 52
Type 1
Size 19 15
Offset 70 259
OutIn 4 8
End
Button 53
Type 1
Size 19 15
Offset 95 259
OutIn 4 4
End
Button 54
Type 1
Size 19 15
Offset 121 259
OutIn 4 2
End
Button 55
Type 1
Size 19 15
Offset 147 259
OutIn 4 1
End
Button 61
Type 1
Size 18 15
Offset 19 284
OutIn 3 32
End
Button 62
Type 1
Size 24 15
Offset 48 284
OutIn 3 8
End
Button 63
Type 1
Size 24 15
Offset 79 284
OutIn 3 4
End
Button 64
Type 1
Size 24 15
Offset 110 284
OutIn 3 2
End
Button 65
Type 1
Size 24 15
Offset 141 284
OutIn 3 1
End
Button 71
Type 1
Size 18 15
Offset 19 310
OutIn 2 32
End
Button 72
Type 1
Size 24 15
Offset 48 310
OutIn 2 8
End
Button 73
Type 1
Size 24 15
Offset 79 310
OutIn 2 4
End
Button 74
Type 1
Size 24 15
Offset 110 310
OutIn 2 2
End
Button 75
Type 1
Size 24 15
Offset 141 310
OutIn 2 1
End
Button 81
Type 1
Size 18 15
Offset 19 335
OutIn 1 32
End
Button 82
Type 1
Size 24 15
Offset 48 335
OutIn 1 8
End
Button 83
Type 1
Size 24 15
Offset 79 335
OutIn 1 4
End
Button 84
Type 1
Size 24 15
Offset 110 335
OutIn 1 2
End
Button 85
Type 1
Size 24 15
Offset 141 335
OutIn 1 1
End
Button 91
Type 1
Size 18 15
Offset 19 361
OutIn 0 32768
End
Button 92
Type 1
Size 24 15
Offset 48 361
OutIn 0 8
End
Button 93
Type 1
Size 24 15
Offset 79 361
OutIn 0 4
End
Button 94
Type 1
Size 24 15
Offset 110 361
OutIn 0 2
End
Button 95
Type 1
Size 24 15
Offset 141 361
OutIn 0 1
End
Scancode 8
Map 8 55
End
Scancode 13
Map 13 51
End
Scancode 16
IfPressed 16
SetFlag 0
Else
ResetFlag 0
End
End
Scancode 17
IfPressed 17
SetFlag 1
Else
ResetFlag 1
End
End
Scancode 27
Map 27 91
End
Scancode 37
Map 37 34
End
Scancode 38
Map 38 25
End
Scancode 39
Map 39 36
End
Scancode 40
Map 40 35
End
Scancode 49
IfFlag 0
Map 49 71
Map 49 54
Else
Map 49 82
End
End
Scancode 50
Map 50 83
End
Scancode 51
IfFlag 0
Map 51 81
Map 51 65
Else
Map 51 84
End
End
Scancode 52
Map 52 72
End
Scancode 53
Map 53 73
End
Scancode 54
Map 54 74
End
Scancode 55
Map 55 62
End
Scancode 56
IfFlag 0
Map 56 75
Else
Map 56 63
End
End
Scancode 57
IfFlag 0
Map 57 71
Map 57 65
Else
Map 57 64
End
End
Scancode 65
Map 65 11
End
Scancode 66
Map 66 12
End
Scancode 67
Map 67 13
End
Scancode 68
Map 68 14
End
Scancode 69
Map 69 15
End
Scancode 70
Map 70 16
End
Scancode 71
Map 71 21
End
Scancode 72
Map 72 22
End
Scancode 73
Map 73 23
End
Scancode 74
Map 74 24
End
Scancode 75
Map 75 25
End
Scancode 76
Map 76 26
End
Scancode 77
Map 77 31
End
Scancode 78
IfFlag 1
MenuItem 1
Else
Map 78 32
End
End
Scancode 79
Map 79 33
End
Scancode 80
Map 80 34
End
Scancode 81
Map 81 35
End
Scancode 82
Map 82 36
End
Scancode 83
Map 83 41
End
Scancode 84
Map 84 42
End
Scancode 85
Map 85 43
End
Scancode 86
Map 86 44
End
Scancode 87
Map 87 45
End
Scancode 88
Map 88 46
End
Scancode 89
Map 89 52
End
Scancode 90
Map 90 53
End
Scancode 96
Map 96 92
End
Scancode 97
Map 97 82
End
Scancode 98
Map 98 83
End
Scancode 99
Map 99 84
End
Scancode 100
Map 100 72
End
Scancode 101
Map 101 73
End
Scancode 102
Map 102 74
End
Scancode 103
Map 103 62
End
Scancode 104
Map 104 63
End
Scancode 105
Map 105 64
End
Scancode 106
Map 106 75
End
Scancode 107
Map 107 95
End
Scancode 109
Map 109 85
End
Scancode 110
Map 110 93
End
Scancode 111
Map 111 65
End
Scancode 186
IfFlag 0
Map 186 81
Map 186 95
End
End
Scancode 188
Map 188 71
Map 188 93
End
Scancode 190
Map 190 93
End
Scancode 191
IfFlag 0
Map 191 71
Map 191 55
Else
Map 191 65
End
End
Scancode 219
IfFlag 0
Map 219 71
Map 219 95
Else
Map 219 71
Map 219 75
End
End
Scancode 220
Map 220 54
End
Scancode 222
IfFlag 0
Map 222 81
Map 222 85
Else
Map 222 31
End
End

Binary file not shown.

View file

@ -1,27 +1,28 @@
########################################
# #
# ROMDump Wizard #
# #
########################################
***********************
* ROMDump Wizard V1.1 *
***********************
This program is a rewritten version of the ROMDump Wizard from
Sebastien Carlier. It based on API calls and doesn't need the
MFC DLL's any more. It has been written to allow you to quickly
dump the rom from your HP48. The process is entirely automated,
and should work most of the time. However, I cannot guarantee
that it will work on your computer. It works perfectly on my
computer.
The ROMDump Wizard has been written to allow you to quickly dump the ROM from
your HP48. The process is entirely automated and can be interrupted at any time.
This program is a rewritten version of the ROMDump Wizard from Sebastien
Carlier. The download engine has changed and is now based on Jean-Yves Avenard's
great ROMUPL program.
My ROM copy times:
SX: 00:16:10 (OS: NT4.0 SP3)
SX: 00:15:38 (OS: Win95 4.00.950a)
GX: 00:30:47 (OS: Win95 4.00.950a)
SX: 00:06:08 (OS: NT4.0 SP3)
GX: 00:11:19 (OS: NT4.0 SP3)
After download you will find the rom file ROM.48S or ROM.48G in
the directory of the ROMDUMP.EXE utility. Be sure that there is
no older file with the used names in this directory before using!
In Step 2 you are asked for the "ROM format". Choose "x48/raw" for all-purpose
use and "Emu48" if you want to use the ROM dump for the Emu48 emulator (Win32
version). You can also use the CONVERT utility to convert "x48/raw" ROM dumps
into the Emu48 format. After downloading you will find the ROM file in the
directory of the ROMDUMP.EXE utility.
If you have any problems, please don't ask me. I'm busy enough
with my work.
In the "x48/raw" mode the file has the name 48SX_?.ROM or 48GX_?.ROM. The ? in
the name is a placeholder for the character of the ROM version you have. In the
"Emu48" mode the file has the name ROM.48S or ROM.48G; this depends on the
calculator you have. Be sure that there is no older file with the used names in
this directory before using!
-- Christoph Gießelink
07/01/99 (c) by Christoph Gießelink, cgiess@swol.de

View file

@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@ -305,7 +305,8 @@ the "copyright" line and a pointer to where the full notice is found.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.

View file

@ -1,7 +1,7 @@
Emu48 - A freeware HP48 Emulator for Windows 95 and NT
Emu48 - A freeware HP38/48/49 Emulator for Windows 9x, NT and 2000
@ -9,219 +9,405 @@
* INSTALLATION *
****************
Emu48 is distributed in 3 separate archives :
- Emu48-1.x-bin.zip All the executables files (REQUIRED)
- Emu48-1.x-src.zip The sources of Emu48 and some useful tools (OPTIONAL)
- Emu48-com.zip Files common to all 1.x versions (REQUIRES)
Emu48 is distributed in 1 archive:
- Emu48-1_15.zip All files and sources
To install Emu48, just unzip Emu48-1.x-bin.zip and Emu48-com.zip into an empty
directory. When you first run Emu48, it will detect the directory in which you
installed it, and will write its configuration to a file named Emu48.ini in
your Windows directory.
To install Emu48, just unzip Emu48-1_15.zip into an empty directory. When you
first run Emu48, it will detect the directory in which you installed it, and
will write its configuration to a file named Emu48.ini in your Windows
directory.
Note:
As of version 1.0, Emu48 will only run with Windows 95 and NT.
I am working on a port to Unix (XWindow). When this is finished,
I may port it to Windows 3.1 and OS/2.
Since the source code is provided, you can add features or port it to new
plateforms, but you are required to send me your changes.
You can also update your current version with the Unofficial Service Packs:
- E48BP1x.ZIP New EXE-File
- E48SP1x.ZIP Sources of the Service Pack
Replace the original EXE file please.
********************
* OPERATING SYSTEM *
********************
This version of Emu48 should work with all Intel Win32 platforms. You may
recompile the sources to run Emu48 with Windows NT on a DEC Alpha.
************************
* YOU NEED A ROM IMAGE *
************************
Emu48 needs an image of the ROM of YOUR calculator to be able to run.
Since the ROM is copyrighted by HP, I won't give you mine, and you should not
give yours or make it freely available.
To use the ROM software of a calculator, you must be the owner of this
calculator.
Emu48 needs an image of the ROM of YOUR calculator to be able to run. Since the
ROM is copyrighted by HP, I won't give you mine, and you should not give yours
or make it freely available. To use the ROM software of a calculator, you must
be the owner of this calculator.
- If you have already used another HP48 emulator, you can convert the ROM with
you were using with the Conver utility.
To do that, start a Command Promt while running Windows, and type :
Convert <old-file> ROM.48G
or Convert <old-file> ROM.48S
Where <old-file> is the path to your old ROM image. This will create a file
named ROM.48G or ROM.48S, depending on the version you own.
This tool should be able to read any style of ROM image, and will also check
its validity. Note than if you run it with only one parameter, no file will
be written, but it will still check the validity of the ROM.
- HP38:
To upload the ROM of your HP38G, you will need a special aplet called "ROM
UPLOAD", available at http://www.epita.fr/~avenar_j/hp. Once you've uploaded the
ROM, you have to convert it using the Convert utility.
- If you have never used an HP48 emulator, and don't have a ROM dump, you can
either use the old ROMDump utility and then Convert your dump, or you can
use my ROMDump Wizard, which will almost automatically get the ROM from your
HP48. However, this Wizard was written without a documentation on the
transfer protocol used by the HP48 (Kermit), so I cannot guarantee that it
will work. It worked on my computer, maybe it will work on yours. Try it !
To do that, start a Command Prompt while running Windows, and type:
Convert <rom-file> ROM.38G
WARNING: If you use ROMDump or the ROMDump Wizard, DO NOT INTERRUPT THE
PROCESS ! Your HP48 would lock, and the only way to reset it is
through the Reset hole.
Where <rom-file> is the path to your ROM image. This will create a file named
ROM.38G. This tool will also check its validity.
IMPORTANT: To save a lot of space, two DLLs needed by the Romdump Wizard
have not been included in the Romdump Wizard's distribution.
They are called MSVCRT40.DLL and MFC40.DLL, and are available
on the Web at the Emu48 Official Homepage :
http://www.geocities.com/CapeCanaveral/5948/index.html
These two files are freely distributable, and would be included
in this archive if they weren't so large (about 1.4Mb for both)
Note that they are NOT needed by Emu48 : only the Romdump Wizard
requires them.
- HP48:
If you have already used another HP48 emulator, you can convert the ROM using
the Convert utility.
* Once you have your ROM dump(s), SAVE THEM TO A FLOPPY DISK !
It will save you a lot of troubles if you were to lose them.
To do that, start a Command Prompt while running Windows, and type:
Convert <rom-file> ROM.48G
or Convert <rom-file> ROM.48S
Where <rom-file> is the path to your old ROM image. This will create a file
named ROM.48G or ROM.48S, depending on the version you own. This tool should be
able to read any style of ROM image, and will also check its validity. Note that
if you run it with only one parameter, no file will be written, but it will
still check the validity of the ROM.
If you have never used an HP48 emulator, and don't have a ROM dump, you can
either use Jean-Yves Avenard's ROMUPL.BIN or the ROMDump Wizard V1.x, which will
almost automatically get the ROM from your HP48. Don't use the ROMDump Wizard
versions V0.x any more please! After the download you may have to convert your
dump with the CONVERT utility into the Emu48 format.
You can find the latest version of the ROM dump programs on:
ROMUPL.BIN http://www.epita.fr/~avenar_j/hp/calcen.html
ROMDump Wizard http://privat.swol.de/ChristophGiesselink/index.htm
Once you have your ROM dump(s), SAVE THEM TO A FLOPPY DISK! It will save you a
lot of trouble if you were lose them.
- HP49:
There's no ROM download program available so far. But you can find a HP49G ROM
for emulators in the YorkeM emulator package or in the HP49G SDK on
http://www.hpcalc.org in the HP49 section.
****************
* HOW TO START *
****************
When Emu48 is installed and you have put the ROM image(s) in its directory, you
can start Emu48. You'll see a "Choose Your KML Script" box.
When Emu48 is installed and you have put the ROM image(s) in the Emu48
directory, you can start Emu48. You'll see a "Choose Your KML Script" box.
KML Scripts in fact define the visual aspect of Emu48, the behaviour of the
buttons, of the keyboard... It is a GREAT way to customize your copy of Emu48.
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.
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.
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.
Choose a KML script in the list box. If you have put a G/GX ROM dump in Emu48's
directory, choose a script for G/GX. If you have put a S/SX ROM dump in Emu48's
directory, choose a script for S/SX.
Several scripts are included in the common archive:
* Emu48's Default Faceplate for HP48G/GX
* Emu48's Default Faceplate for HP48S/SX
These two are simple scripts, and they use the bitmap from Win48 2.05.
These two are simple scripts, good for 800x600 display resolution.
* Casey's Gx with Toolbar and Touch Screen
* Casey's Sx with Toolbar and Touch Screen
These script uses many advanced features, and is a good demonstration of
the power of Emu48's scripting language, KML. Try it, it is really great !
the power of Emu48's scripting language KML. Try it, it is really great!
* Floating buttons
This one looks really great.
* Small but realistic HP48 Gx
This one has been designed for small resolutions such as 640x480.
Note: some things in this script have to be be fixed.
Note: some things in this script have to be fixed.
If you want other great scripts, visit Casey's Emu48 homepage:
http://www.gulftel.com/~pattersc/emu48/
And if you are interested in writting new scripts, you'll want the KML 2.0
documentation, available on Casey's page and on my page :
http://www.geocities.com/CapeCanaveral/5948/kmlind.htm
And if you are interested in writing new scripts, get the KML 2.0 documentation
from Christoph's page at http://privat.swol.de/ChristophGiesselink/emu48.htm
Once you have selected a script, press Ok to start the emulator. While it is
running, you can use the View/Change Kml Script to change the visual aspect
of Emu48.
Once you have selected a script, press OK to start the emulator. While it's
running, you can use the View/Change KML Script... command to change the visual
aspect of Emu48.
***************
* KML SCRIPTS *
***************
In some cases you have to fix Color 0 in your KML script file, because the
colors red and blue has been swapped in the "Lcd" section (bugfix in a previous
version). Don't use TRUELCD.KMI for emulating display contrast in your scripts.
It's not fully correct. The hardware contrast values are in the area from 0 to
31. But the HP48 ROMs bounds them to useful values. The S(X) ROM use only
display contrast values between 3 and 19 and the G(X) ROM values between 9 and
24.
****************
* COMMAND LINE *
****************
The command line syntax is "Emu48 [E48file [Port2file]]". The first parameter
sets the filename for the emulation data, the second parameter the Port2 file.
You're not able to set a Port2 file without setting the emulation data file. The
arguments are optional.
*******************
* LOAD/SAVE FILES *
*******************
There are two ways to transfer files from or to the emulator. The one way is to
use the serial port to transfer the data directly from your HP48 to the
emulator. The second way is to load data, saved on your PC, into the stack of
the emulator. You can do this by using the Edit/Load Object... command or with
the file Drag and Drop feature. But there's one important restriction, the data
must a HP binary file (begin with HPHP48- or HPHP49-, this depends on your
emulated calculator)! If not, the data is load as string. The Edit/Save
Object... command will save the data in stack level 1 on the PC (always binary
mode). Be sure, when you use the second way for data transfer, that no program
is running on the emulator. The second way doesn't work on a HP38, because he
has no stack. So you can load aplets only from the serial port.
*****************
* DRAG AND DROP *
*****************
Dropping HP48 objects over the emulator window will load program files (like the
command "Load object...") on the stack. Be sure that the emulator isn't busy
before doing this.
*******************
* SHARED RAM CARD *
*******************
You can add a SHARED (I'll explain later) ram card of up to 4Mb. By default, no such
card will be created when you start Emu48. The MkShared.exe utility, included in the
registered version, will allow you to create it.
You can add a SHARED (I'll explain later) ram card of up to 4MB to a HP48. By
default, no such card will be created when you start Emu48. The MkShared.exe
utility will allow you to create it.
The syntax is:
MkShared <filename> <size_in_kilobytes>
For example, you can create a 4Mb RAM card name SHARED.BIN (in Emu48's directory) with
the following command :
For example, you can create a 4MB RAM card name SHARED.BIN (in Emu48's
directory) with the following command:
MkShared SHARED.BIN 4096
Valid sizes are 128, 256, 512, 1024, 2048 and 4096 kb.
When you have created this file, run Emu48, and use the Close menu item to close the
calculator state. Now select View/Settings. In the "Port 2" text area, type the name
of the file you created (if you don't include a path, it will be searched for in Emu48's
directory).
Valid sizes are 32, 128, 256, 512, 1024, 2048 and 4096 KB. If you use RAM cards
greater than 128 KB in a HP48SX, you can only see the first 128 KB of the card.
You can also tick the check box "Port 2 Is Shared".
When the box is cleared, only the first instance of Emu48 will allow you to use the RAM
card in Port 2.
When this box is ticked, the first instance of Emu48 will give you both read and write
access to this RAM card. If then you start Emu48 again, the RAM card in Port 2 will be
write-protected. You can thus transfer files very easily between two calculators. This
RAM card is used by both S/SX and G/GX types.
When you have created this file, run Emu48, and use the Close menu item to close
the calculator state. Now select File/Settings. In the "Port 2" text area, type
the name of the file you created (if you don't include a path, it will be
searched for in Emu48's directory).
Note that you have to close Emu48 and restart it if you modify these settings.
You can also tick the check box "Port 2 Is Shared". When the box is cleared,
only the first instance of Emu48 will allow you to use the RAM card in Port 2.
When this box is ticked, the first instance of Emu48 will give you both read and
write access to this RAM card. If then you start Emu48 again, the RAM card in
Port 2 will be write-protected. Thus you can transfer files very easily between
two calculators. This RAM card is used by both S/SX and G/GX types.
***********************
* COPY / PASTE STRING *
***********************
********************
* SPECIAL FEATURES *
********************
With the menu items "Copy String" and "Paste String" in the "Edit" menu you're
able to copy HP48 string objects from the stack to the PC clipboard and vice
versa.
Emu48 includes a backup feature (in the View menu). It save the complete state of the
calculator in the computer's memory. You might want to use it before doing something
risky, and if you don't want to save to the disk. It provides some kind of Undo feature.
It is also used by Emu48 when you want to save or load a new document, to restore its
old state if you cancel the operation or of something goes wrong.
**********
* BACKUP *
**********
Emu48 includes a backup feature (in the Edit menu). It save the complete state
of the calculator in the computer's memory. You might want to use it before
doing something risky, and if you don't want to save to the disk. It provides
some kind of Undo feature. It is also used by Emu48 when you want to save or
load a new document, to restore its old state if you cancel the operation or of
something goes wrong.
************
* KEYBOARD *
************
To enter a character to the emulator use the PC keyboard (key translation
depends on the used KML script) or the mouse. If you press the left mouse
button, the emulator key is pressed as long as you press the mouse button or
leaving the area of the emulator button. Sometimes you need to press more then
one key (contrast setting, warmstart, ...). To do this, press the right mouse
button. All "locked" buttons are released after enter a key with the left mouse
button.
*********
* CLOCK *
*********
The emulator time is synchronized with the PC time at startup of the emulator.
This may cause problems with other non original operating systems running on the
HP48. On S(X) calculators the address area #00052-#00070, on G(X) calculators
the address area #00058-#00076 in Port0 are rewritten with the actual time
information.
*************
* EMU48.INI *
*************
The section [Timers] in the Emu48.ini file isn't used any more. The variable
values are replaced by useful constants. You may delete this section if you
want. Starting an old version of Emu48 (V1.07 and earlier) will add this section
again.
************************
* REAL SPEED EMULATION *
************************
As you recognized the speed of the emulated HP48 is much faster than an original
HP48. The reason is, the assembler commands are emulated faster than the
original CPU can execute them. On one side this is a big advantage (faster
execution of programs) on the other side this cause many trouble. In Emu48 only
the timers work with the original speed. In result all commands like User-RPL
WAIT wait more or less the correct time. But many programs like shells or
editors use an own key handler to realize an autorepeat implementation. Normally
these programs use the execution time of each assembler command for waiting. On
Emu48 this time is much shorter, so the time between each key read is shorter as
well and you get a very fast key repetition. The editor ED from the JAZZ package
hasn't this problem, because the key input is synchronized with one of the
timers. To solve this problem Emu48 generally slow down emulation if a key is
pressed. To solve some other speed depending problems you are able to slow down
the whole emulation speed. There are two variables 'SXCycles=82' and
'GXCycles=123' defined in the Emu48.ini file, section [Emulator] which control
the "real" speed and key repetition slow down for each calculator type. Each
numeric value is representing the allowed CPU cycles in a 16384Hz time frame.
Because the used cycle statements (from SASM.DOC) in Emu48 doesn't correspond to
the real values of the CPU, the saved values are estimated by comparing the
execution time of a program to the real calculator. Increasing the value fitting
to your ROM will make the "real speed" HP faster and vice versa. No warranty to
the functionality of Emu48 when you go below the default values.
*************************
* SERIAL PORT EMULATION *
*************************
The serial ports are emulated as well now. You may choose the same serial port
for wire and IR. Remember that the IR port only work with 2400 Baud. If you want
to change the serial port settings, but they are disabled, close the serial port
with the command CLOSEIO or power cycle the HP48 first.
Now it's possible to make transfers between the HP48 and Emu48. If you have
problems with the connection please try the following. There's a simple way to
check if your serial port is used by another program. First disable the serial
settings in both combo boxes and very important close the settings dialog.
Reopen the settings dialog and choose the COM port in the wire combo box to the
port the HP48 is connected with. When you open this combo box you only see valid
(unused) serial ports. Don't use the IR combo box, it only works with 2400 Baud.
The next important thing are the serial settings of the HP48 and Emu48, they
must be equal. If this doesn't work then mostly there's a hardware or a resource
problem of the serial port. Check this with connecting the HP48 with a transfer
program you like on the same serial port.
****************
* DISASSEMBLER *
****************
With the internal disassembler you're able to disassemble the HP48 address area.
With the default Map setting the disassembler always see the mapped memory
address. If for example you configured the RAM at #00000 you will see the RAM
and not the ROM at this address. With the other Module settings you specify a
special module for disassembly. Each module will begin at address #00000 and
will not overlapped by other modules. For Port2 I use a linear address mode,
that means that the second port of a RAM card greater than 128KB is at address
#40000 (128 * 1024 * 2) and so on. The "Copy Data" button copies the selected
disassembler lines to the PC clipboard.
**************
* DDE SERVER *
**************
I implemented a DDE server in Emu48 to transmit data from and to the HP stack
with DDE. You have the same restrictions like with the commands "Load object..."
and "Save Object...", that a running program may corrupt memory. Take care to
transmit data only after the acknowledge of the last DDE transaction.
Technical data:
Servername: Emu48
Topicname: Stack
Item: Dummy (ignored, must be a nonzero string)
Clipboardformat: "CF_HPOBJ" (user defined)
The DDE commands CONNECT, POKE and REQUEST are supported.
The structure of the clipboard format "CF_HPOBJ":
+--------+------------------------------------+
| 4 Byte | HP object |
+--------+------------------------------------+
\ \
\ +--- normal HP object
+----------- length of object (LSB first)
********************
* TROUBLE SHOOTING *
********************
Q: The emulator display the keyboard, but the screen stays blank or is filled
with garbage.
A: Your ROM image is probably wrong. Check it with the Convert utility, and if
it says that the CRC is wrong, you should try to download your ROM again.
Q: What does this message mean :
"This file is missing or already loaded in another instance of Emu48."
A: Maybe you deleted or moved the files that the emulator tries to load when
starting (the last files you saved).
The other possibility is that you are running several instances of Emu48,
but you are trying to load the same file in both instances, which causes
a sharing violation.
Visit the Emu48 FAQ site at http://privat.swol.de/ChristophGiesselink/index.htm
to get more information please.
***********
* SUPPORT *
***********
I cannot provide individual support for Emu48, but I will read all the mails
that you send.
All informations about Emu48 will be on the Emu48 Official Homepage on the Web :
We cannot provide individual support for Emu48, but we will read all the mails
that you send. All informations about Emu48 will be on the Emu48 Official
Homepage on the Web:
http://www.geocities.com/CapeCanaveral/5948/index.html
http://www.epita.fr/~sebc/Emu48/index.html
or on the Emu48 FAQ at
http://privat.swol.de/ChristophGiesselink/index.htm
Other graphics and scripts are available at Casey's Emu48 Graphics Page:
http://www.gulftel.com/~pattersc/emu48/
http://www.gulftel.com/~pattersc/emu48/
***************
* LEGAL STUFF *
***************
Emu48 - An HP48 Emulator
Copyright (C) 1997 Sebastien Carlier
Emu48 - An HP38/48/49 Emulator
Copyright (C) 1999 Sebastien Carlier & Christoph Gießelink
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) any later version.
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) any later
version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
**************
* The Author *
**************
***************
* The Authors *
***************
Paper Mail:
Sebastien Carlier
@ -231,7 +417,17 @@ Paper Mail:
E-Mail:
sebc@epita.fr
sebc@anet.fr
Homepage:
http://www.geocities.com/CapeCanaveral/5948/index.html
http://www.epita.fr/~sebc/Emu48/index.html
Paper Mail:
Christoph Giesselink
GERMANY
E-Mail:
cgiess@swol.de
Homepage:
http://privat.swol.de/ChristophGiesselink/index.htm

View file

@ -1,3 +1,393 @@
Service Pack 15 for Emu48 Version 1.0
DEBUGGER.C
- added emulation run flag
- added notify function for emulation stopped
- added color highlighting on changed registers
- added implementation of "Step Out" (exit function)
- bugfix in function ViewMemWnd(), use the Npeek() function for
reading memory data, so fixed some problems with reading invalid
data from the I/O register area
- changed function OnClearAll(), changed argument to dialog handle
- bugfix in function OnDblClick(), fixed swapped nibbles after enter
new data
- changed function OnKeyCodeWnd(), changed first argument to dialog
handle
- bugfix in function Debugger(), removed context menu resource leaks
and a call of GetDlgItem() with invalid arguments
DEBUGGER.H
- extern declaration of global functions
- moved WM_UPDATE definition to DEBUGGER.C
EMU48.C
- replaced __argc and __argv variables by process variables
- replaced INI file handling part
- changed address in GPL license string
- added HP38 stuff to function UpdateWindowStatus() and
SettingsProc()
- changed function SettingsProc(), replaced Port1_Writeable variable
- bugfix in function OnViewReset(), some registers wasn't reset,
call reset function now
- bugfix in function OnDestroy(), moved functions SwitchToState()
and WriteSettings() to main program, because emulation thread may
not run and settings aren't read so far when main window close
- removed function FlushMessages() and all references, because it's
useless and references made trouble at a WM_QUIT message
- removed several other resource leaks on error conditions
- made function MainWndProc() public
EMU48.DSP
- renamed serial.h into io.h in header definition
- added settings.c sources
EMU48.H
- extern declaration of global variable and functions
EMU48.RC
- changed language definition of dialog IDD_BREAKEDIT
- added Menuitem Debug "Step Out" in debugger menu
- changed version and copyright
ENGINE.C
- renamed header Serial.h into io.h
- renamed wShutdnWake to bShutdnWake in Chipset structure
- moved bRealSpeed variable and make it public
- solved bRealSpeed name conflict
- added DWORD casting from Chipset.cycles variable
- added part for debugger function "Step Out"
- changed notify function for update debugger window
EXTERNAL.C
- some minor changes for the HP38 beeper emulation
FILES.C
- added new document type for HP38G
- replaced __argc and __argv variables by process variables
- added function CrcRom() to get a fingerprint of the ROM
- changed function NewDocument(), deleted Port1_Writeable variable,
isn't used any more
- bugfix in function OpenDocument(), in restore situation add port2
only at HP48 emulation
- changed function OpenDocument(), check fingerprint of ROM
- changed function SaveDocument(), update fingerprint of ROM
- changed function SaveBackup(), save window position as well
- bugfix in function RestoreBackup(), lost port2 of a HP48
KEYBOARD.C
- renamed wShutdnWake to bShutdnWake in Chipset structure
- added DWORD casting from Chipset.cycles variable
KLM.C
- bugfix in function InitKML(), on a KML script syntax error only
continue with the Cancel button
IO.H
- old SERIAL.H, added I/O definitions
MOPS.C
- renamed header Serial.h into io.h
- renamed funtion CRC() to UpCRC()
- changed function UckBit(), removed unused variable
- changed function MapP1(), use cards_status instead of
Port1_Writeable variable
- bugfix in function RomSwitch(), lached address line A6 was always
zero -> no access to upper half of flash memory
- added function CpuReset() to set cpu registers after reset
- changed function Npeek(), return data from I/O register area as
well now (for debugger support)
- bugfix in function Nread(), reading from the timer2 MSB register
(0x13F) updates the CRC register (0x104-0x107)
- bugfix in function ReadIO(), update the USRQ bit in the SRQ1
register (0x118) after reading the RBR register (0x114,0x115)
- bugfix in function ReadIO(), update the NINT2 and NINT bits in the
SRQ2 register (0x119)
- bugfix in function WriteIO(), update the USRQ bit in the SRQ1
register (0x118) after writing the IOC register (0x110) or the
TBR register (0x116,0x117)
OPCODES.C
- added DWORD casting from w.cycles variable
- checked all undocumented cpu cycles and removed remarks
- bugfix in function o08(), o09(), o0A(), o0B(), o3X(), o8086n(),
o8087n(), o808An(), o808Bn() and o8Ed4(), changed number of cpu
cycles
RESOURCE.H
- added several definitions
SERIAL.C
- renamed header Serial.h into io.h
- renamed wShutdnWake to bShutdnWake in Chipset structure
- moved initialize/remove of Critical Section handler from the
function CommOpen() and CommClose() to main program
- added function UpdateUSRQ(), implements USRQ bit handling
- bugfix in function CommTransmit(), added LPB bit emulation in the
TCS register (0x112) and USRQ bit emulation in the SRQ1 register
(0x118)
- bugfix in function CommReceive(), only reject reading if com port
is closed and not whole operation and added USRQ bit emulation in
the SRQ1 register (0x118)
SERIAL.H
- renamed to IO.H
SETTINGS.C
- new modul to handle the INI file
TIMER.C
- removed timer I/O definitions, replaced by include file IO.H
- replaced INT define with INTR (conflict with C variable type INT)
- renamed wShutdnWake variable to bShutdnWake
- bugfix in function CheckT1() and CheckT2(), added TSRQ bit
emulation in the SRQ1 register (0x118)
TYPES.H
- changed variable type of wPosX and wPosY, position data is signed
- use position of wShutdnWake for wRomCrc
- use position of dwKdnCycles for cycles variable
- use position of Port1_Writeable for MSB of cycles variable
- use position of Port2_Writeable for dwKdnCycles variable
- use old position of the cycles variable for bShutdnWake
Service Pack 14 for Emu48 Version 1.0
COLOR.H
- new header with color definitions
DDESERV.C
- added different files headers for HP48/49
DEBUGGER.C
- new modul for debugger routines
DEBUGGER.H
- header file for debugger part
DISASM.C
- changed function append_r_addr() and append_pc_comment(), relative
jumps now can viewed with the target address instead of a relative
offset and target address in remark; implemented a local variable
- bugfix in function rn_port2(), calculated port2 mask was wrong
- added HP49 stuff to function rn_port2()
EMU48.DSP
- added debugger.c sources
EMU48.C
- added debugger menu entry
- added HP49 stuff to the disassembler
- added HP49 stuff to function SettingsProc()
- changed function OnViewSettings(), removed port2 open/close
handling, now done in the document handler
- deleted unused function OnSysClose()
- bugfix in function Disasm(), in entry IDC_DISASM_PORT2 the highest
useable address was always wrong
EMU48.RC
- added Menuitem Tools "Debugger..."
- changed version and copyright
EMU48.H
- extern declaration of global variable and functions
ENGINE.C
- moved inline function FASTPTR() to OPS.H
- added debug part in main emulation loop
EXTERNAL.C
- some minor changes for the HP49 beeper emulation
FILES.C
- added new document type for HP49G
- change in function WriteStack(), accept HP49 binary files now
- the port2 open/close handling is now controlled by the document
- several changes in port2 handling, the HP49 use an internal 128KB
RAM card instead of the external RAM card of the HP48
- changed function UnmapPort2(), added return value for unmap
success
- changed function PatchRom(), longer addresses than 5 nibbles can
be used now
- changed function OpenDocument(), restore HP49 ROM bank selection
after document load
- changed function InitKML(), removed initialization of MMU
KEYBOARD.C
- changed function ScanKeyboard(), added a flag for wake up from
SHUTDN mode
KML.C
- bugfix in function PressButton(), if button already pressed, do
nothing -> fixed a draw problem with KML button type 3
- bugfix in function RefreshButtons(), KML type 3 buttons, must
complete redraw before refresh them
MOPS.C
- added HP49 MMU parts
- bugfix in function ReadIO(), update the UCK bit in the BAU
register (0x10D)
OPS.H
- moved inline function FASTPTR() from ENGINE.C to header file
RESOURCE.H
- added several definitions
RPL.C
- added HP49 memory pointers
- added HP49 flash pointer object (=DOFASHP)
- added HP49 precision integer object (=DOINT)
- added HP49 precision real object (=DOLNGREAL)
- added HP49 precision complex object (=DOLNGCMP)
- added HP49 symbolic matrix object (=DOMATRIX)
- added HP49 aplet object (=DOAPLET)
- added HP49 mini font object (=DOMINIFONT)
SERIAL.C
- changed function SerialThread(), added a flag for wake up from
SHUTDN mode
TIMER.C
- changed functions CheckT1() and CheckT2(), added a flag for wake
up from SHUTDN mode
TYPES.H
- use position of the wUnused1 variable for SHUTDN wake up flag
Service Pack 13 for Emu48 Version 1.0
DISASM.C
- bugfix in function disasm_8(), the HS=0 n opcode was showed wrong
EMU48.DSP
- added fetch.c and opcodes.c sources
EMU48.C
- bugfix in function Disasm() and About(), handled messages must
return TRUE
EMU48.H
- added function prototypes
ENGINE.C
- moved several definitions to OPCODE.H
- made function AdjKeySpeed() public
- replaced opcode handling include files by a function call, decoder
now works with tables instead of case switching
- deleted unused code parts in modul
FETCH.C
- new modul with opcode dispatcher
FETCH.H
- file deleted, replaced by FETCH.C
FILES.C
- bugfix in function PatchRom(), no correct handling of remarks,
interpreter failed on lower case hex digits in arguments
OPCODES.C
- new modul with opcode implementation
OPCODES.H
- file content changed, replaced by OPCODES.C
Service Pack 12 for Emu48 Version 1.0
DISPLAY.C
- minor change in function UpdateMainDisplay()
- deleted remarked global variables and unused code parts in
function WriteToMainDisplay()
EMU48.C
- added auto event object for controlling the CPU thread
EMU48.H
- removed extern declaration of variable
- extern declaration of global variable and functions
ENGINE.C
- new function CheckDisp(), synchronize display update now with the
line update counter
- replaced all ResumeThread() with SetEvent() calls
- replaced all SuspendThread() with WaitForSingleObject() calls
KEYBOARD.C
- replaced all ResumeThread() with SetEvent() calls
- deleted unused code parts in function ScanKeyboard()
MOPS.C
- flag for updating display area is now global
- new function GetLineCounter() for getting the actual display
refresh line
- changed function WriteIO(), display isn't updated here any more
- use serial definitions from "serial.h" now
- deleted remarked functions Nread2(), Nwrite2(), Nread5() and
Nwrite5()
SERIAL.C
- replaced all ResumeThread() with SetEvent() calls
TIMER.C
- bugfix in function SetT1(), loading same timer value doesn't
restart timer period
- replaced all ResumeThread() with SetEvent() calls
Service Pack 11 for Emu48 Version 1.0
EMU48.C
- removed cards status definitions
- bugfix in function OnFileExit(), continuing the emulation failed
after pressing the "Cancel" button in save dialogbox
- removed function OnSysClose(), no difference to function
OnFileExit()
- changed message implementation WM_SYSCOMMAND/SC_CLOSE to function
OnFileExit()
EMU48.DSP
- added preprocessor definition "STRICT" to project
EMU48.H
- moved cards status definitions from EMU48.C to header file
- extern declaration of global function
EMU48.RC
- changed version and copyright
ENGINE.C
- bugfix in function WorkerThread(), after changing the port2 card
status the memory mapping must be updated
- update HP48 time now in function WorkerThread() and not in
function StartTimers()
FILES.C
- changed function MapPort2(), dwPort2Mask now shows the valid
address lines of the bank switcher FF
MOPS.C
- bugfix in function MapP1() and MapP2(), clear mapping area if port
is configured but not plugged
- bugfix in function MapP2(), odd bank switch values loaded the
wrong page of port2 and bank switcher must be disabled on S(X)
versions
- changed function Nread(), simulate an open data bus now (fix
value for even and odd address)
- bugfix in function Nread(), don't change bank switcher value if
RAM or CE2 is on the same address, because these modules have
higher access priority
- bugfix in function Nwrite(), bank switching now works with the
'datx=r fsd' command
TIMER.C
- renamed function SetAccesstime() to SetHP48Time() and made
function public
- removed update of HP48 time in function StartTimers()
Service Pack 10 for Emu48 Version 1.0
DISPLAY.C
@ -15,7 +405,7 @@ EMU48.C
- moved function DragAcceptFiles() to WM_CREATE handler
- added function DragAcceptFiles() to WM_DESTROY handler
- allow second command line parameter as port2 filename
- added Critical Section initialisation
- added Critical Section initialization
EMU48.H
- removed extern declaration of global function
@ -134,7 +524,7 @@ MOPS.C
- bugfix in function Nread(), bank switching now works with every
'r=datx fsd' command in the complete mapped bank switch control
area, an unconfigured bank switch area is now disabled and the
GX bank switch information (content of FlipFlop) is saved now
GX bank switch information (content of Flipflop) is saved now
- bugfix in function Nwrite(), at some conditions no update of the
display area and IO area couldn't be unconfigured
- removed functions Nread2(), Nwrite2(), Nread5() and Nwrite5()
@ -291,7 +681,7 @@ DISPLAY.C
EMU48.C
- added global variable
- added semaphor handling for key scan
- added semaphore handling for key scan
- added disassembler dialog box and menu entry
- bugfix in function OnViewCopy(), the clipboard wasn't closed when
EmptyClipboard() failed
@ -476,8 +866,8 @@ EMU48.RC
KEYBOARD.C
- bugfixes in 1 ms keyboard interrupt handler, keyboard interrupts
are generated at one of the following conditions: pressing the ON
key (non maskeable), pressing a key detected by the 1 ms keyboard
scan when enabled (maskeable), detect a key after an OUT command
key (non maskable), pressing a key detected by the 1 ms keyboard
scan when enabled (maskable), detect a key after an OUT command
or after the RSI command when a bit in the IN register is set
MOPS.C
@ -593,7 +983,7 @@ DISPLAY.C
EMU48.C
- version changed
- added global variable
- added semaphor handling to avoid GDI trouble with NT that prevent
- added semaphore handling to avoid GDI trouble with NT that prevent
graphic update sometimes
- added message for right mouse key
- bugfix of a parameter of GetPrivateProfileString()

27
sources/Emu48/COLOR.H Normal file
View file

@ -0,0 +1,27 @@
/*
* color.h
*
* This file is part of Emu48
*
* Copyright (C) 1999 Christoph Gießelink
*
*/
#define COLOR_BLACK 0x00000000
#define COLOR_MAROON 0x00000080
#define COLOR_GREEN 0x00008000
#define COLOR_OLIVE 0x00008080
#define COLOR_NAVY 0x00800000
#define COLOR_PURPLE 0x00800080
#define COLOR_TEAL 0x00808000
#define COLOR_GRAY 0x00808080
#define COLOR_SILVER 0x00C0C0C0
#define COLOR_RED 0x000000FF
#define COLOR_LIME 0x0000FF00
#define COLOR_YELLOW 0x0000FFFF
#define COLOR_BLUE 0x00FF0000
#define COLOR_FUCHSIA 0x00FF00FF
#define COLOR_AQUA 0x00FFFF00
#define COLOR_LTGRAY 0x00C0C0C0
#define COLOR_DKGRAY 0x00808080
#define COLOR_WHITE 0x00FFFFFF

View file

@ -15,7 +15,7 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv,
{
BYTE szBuffer[32];
HDDEDATA hReturn;
LPBYTE lpData;
LPBYTE lpData,lpHeader;
DWORD dwAddress,dwSize,dwLoop,dwIndex;
BOOL bSuccess;
@ -40,16 +40,15 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv,
if ((lpData = (LPBYTE) LocalAlloc(LMEM_FIXED,dwSize * 2)) == NULL)
return (HDDEDATA) DDE_FNOTPROCESSED;
if (!Chipset.dispon) // 25.08.98 cg, moved, HP off
if (!Chipset.dispon) // HP off
{
// turn on HP
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
// while(Chipset.Shutdn == FALSE) Sleep(0); // 25.08.98 cg, removed
}
if (WaitForSleepState()) // 16.06.98 cg, wait for cpu SHUTDN then sleep state
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{
LocalFree(lpData); // free memory
return (HDDEDATA) DDE_FNOTPROCESSED;
@ -86,7 +85,7 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv,
if (iFmt != uCF_HpObj || nState != 0)
return NULL;
if (WaitForSleepState()) // 16.06.98 cg, wait for cpu SHUTDN then sleep state
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
return NULL;
while (nState!=nNextState) Sleep(0);
@ -100,8 +99,10 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv,
}
dwLoop = dwSize = (RPL_SkipOb(dwAddress) - dwAddress + 1) / 2;
lpHeader = (Chipset.type != 'X') ? BINARYHEADER48 : BINARYHEADER49;
// length of binary header
dwIndex = sizeof(BINARYHEADER) - 1;
dwIndex = strlen(lpHeader);
// size of objectsize + header + object
dwSize += dwIndex + sizeof(DWORD);
@ -117,7 +118,7 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv,
*(DWORD *)lpData = dwLoop + dwIndex;
// copy header
memcpy(lpData + sizeof(DWORD),BINARYHEADER,dwIndex);
memcpy(lpData + sizeof(DWORD),lpHeader,dwIndex);
// copy data
for (dwIndex += sizeof(DWORD);dwLoop--;++dwIndex,dwAddress += 2)

1475
sources/Emu48/DEBUGGER.C Normal file

File diff suppressed because it is too large Load diff

31
sources/Emu48/DEBUGGER.H Normal file
View file

@ -0,0 +1,31 @@
/*
* debugger.h
*
* This file is part of Emu48
*
* Copyright (C) 1999 Christoph Gießelink
*
*/
// #define BP_EXEC 1 // code breakpoint
// #define BP_READ 2 // read memory breakpoint
// #define BP_WRITE 4 // write memory breakpoint
// #define BP_RANGE 8 // check address range
// 13.11.99 cg, new, debugger state definitions
#define DBG_RUN 0
#define DBG_STEPINTO 1
#define DBG_STEPOVER 2
#define DBG_STEPOUT 3
// debugger.c
extern HWND hDlgDebug;
extern HANDLE hEventDebug;
extern BOOL bDbgEnable;
extern INT nDbgState; // 13.11.99 cg, state of debugger
extern BOOL bDbgNOP3;
extern DWORD dwDbgRstkp;
extern DWORD dwDbgRstk; // 13.11.99 cg, possible return address
extern BOOL CheckBreakpoint(DWORD dwAddr);
extern VOID NotifyDebugger(VOID); // 10.11.99 cg, notify debugger emulation stopped
extern LRESULT OnToolDebug(VOID);

View file

@ -215,8 +215,6 @@ static char *hst_bits[8] =
// static functions
// 10.11.98 cg, added new mapping functions
static BYTE rn_map (DWORD *p)
{
DWORD d = *p;
@ -259,12 +257,24 @@ static BYTE rn_port1 (DWORD *p)
static BYTE rn_port2 (DWORD *p)
{
BYTE *pbyVal;
DWORD d = *p;
*p = ++(*p) & (((dwPort2Mask + 1) << 17) - 1);
if (cCurrentRomType=='X') // HP49G
{
*p = ++(*p) & (Chipset.Port2Size * 2048 - 1);
_ASSERT(d < ((dwPort2Mask + 1) << 17));
return *(pbyPort2 + d);
_ASSERT(d < Chipset.Port2Size * 2048);
pbyVal = Chipset.Port2;
}
else // HP48SX/GX
{
*p = ++(*p) & (((dwPort2Mask + 1) << 18) - 1);
_ASSERT(d < ((dwPort2Mask + 1) << 18));
pbyVal = pbyPort2;
}
return *(pbyVal + d);
}
static BYTE read_nibble (DWORD *p)
@ -324,13 +334,11 @@ static char *append_imm_nibble (char *buf, DWORD *addr, int n)
if (n > 1)
*buf++ = '$';
}
// 01.12.98 cg, bugfix, add hex header for hex numbers
else // HP Mnemonics
{
if (n > 1) // hex mode
*buf++ = '#'; // insert hex header
}
// 01.12.98 cg, end of bugfix
if (n > 1)
{
for (i = 0; i < n; i++)
@ -408,10 +416,12 @@ static char *append_r_addr (char *buf, DWORD * pc, long disp, int n, int offset)
return buf;
}
static char *append_pc_comment (char *buf, DWORD pc)
static char *append_pc_comment (char *buf, DWORD pc, BOOL view)
{
char *p = buf;
if (view == VIEW_LONG) // output of address in remarks
{
while (strlen (buf) < 4 * TAB_SKIP)
p = append_tab (buf);
@ -429,10 +439,17 @@ static char *append_pc_comment (char *buf, DWORD pc)
p = append_str (p, "Unknown disassembler mode");
break;
}
}
else // output of address in brackets
{
while (*p) ++p;
p = append_str (p, " [");
p = append_addr (p, pc);
p = append_str (p, "]");
}
return p;
}
static char *append_hst_bits (char *buf, int n)
{
int i;
@ -444,8 +461,6 @@ static char *append_hst_bits (char *buf, int n)
for (i = 0; i < 4; i++)
if (n & (1 << i))
{
if (p != buf)
p = append_str (p, "=");
p = append_str (p, hst_bits[i + 4 * disassembler_mode]);
}
break;
@ -739,7 +754,7 @@ static char *disasm_1 (DWORD *addr, char *out)
return p;
}
static char *disasm_8 (DWORD *addr, char *out)
static char *disasm_8 (DWORD *addr, char *out, BOOL view)
{
BYTE n;
BYTE fn;
@ -864,7 +879,7 @@ static char *disasm_8 (DWORD *addr, char *out)
{
p = append_str (p, ", GOYES ");
p = append_r_addr (p, &pc, disp, 2, 5);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
}
else
p = append_str (p, ", RTNYES");
@ -880,7 +895,7 @@ static char *disasm_8 (DWORD *addr, char *out)
{
p = append_str (p, ", ");
p = append_r_addr (p, &pc, disp, 2, 5);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
}
break;
default:
@ -1129,10 +1144,21 @@ static char *disasm_8 (DWORD *addr, char *out)
p = append_str (out, "CLRHST");
}
else
{
// when not only one bit is set the HS=0 opcode is used
if (n != 1 && n != 2 && n != 4 && n != 8)
{
p = append_str (out, "HS=0");
p = append_tab (out);
wsprintf (buf, "%d", n);
p = append_str (p, buf);
}
else
{
p = append_hst_bits (out, n);
p = append_str (p, "=0");
}
}
break;
case CLASS_MNEMONICS:
p = append_str (out, "clr.1");
@ -1162,7 +1188,7 @@ static char *disasm_8 (DWORD *addr, char *out)
{
p = append_str (p, "GOYES ");
p = append_r_addr (p, &pc, disp, 2, 3);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
}
else
p = append_str (p, "RTNYES");
@ -1177,7 +1203,7 @@ static char *disasm_8 (DWORD *addr, char *out)
{
p = append_str (p, ", ");
p = append_r_addr (p, &pc, disp, 2, 3);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
}
p = append_hst_bits (out, n);
break;
@ -1226,7 +1252,7 @@ static char *disasm_8 (DWORD *addr, char *out)
{
p = append_str (p, ", GOYES ");
p = append_r_addr (p, &pc, disp, 2, 3);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
}
else
p = append_str (p, ", RTNYES");
@ -1241,7 +1267,7 @@ static char *disasm_8 (DWORD *addr, char *out)
{
p = append_str (p, ", ");
p = append_r_addr (p, &pc, disp, 2, 3);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
}
break;
default:
@ -1267,7 +1293,7 @@ static char *disasm_8 (DWORD *addr, char *out)
{
p = append_str (p, ", GOYES ");
p = append_r_addr (p, &pc, disp, 2, 3);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
}
else
p = append_str (p, ", RTNYES");
@ -1282,7 +1308,7 @@ static char *disasm_8 (DWORD *addr, char *out)
{
p = append_str (p, ", ");
p = append_r_addr (p, &pc, disp, 2, 3);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
}
break;
default:
@ -1303,13 +1329,13 @@ static char *disasm_8 (DWORD *addr, char *out)
p = append_str (out, (fn == 0xc) ? "GOLONG" : "GOSUBL");
p = append_tab (out);
p = append_r_addr (p, &pc, disp, 4, (fn == 0xc) ? 2 : 6);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
break;
case CLASS_MNEMONICS:
p = append_str (out, (fn == 0xc) ? "bra.4" : "bsr.4");
p = append_tab (out);
p = append_r_addr (p, &pc, disp, 4, (fn == 0xc) ? 2 : 6);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
break;
default:
p = append_str (out, "Unknown disassembler mode");
@ -1347,7 +1373,7 @@ static char *disasm_8 (DWORD *addr, char *out)
// public functions
DWORD disassemble (DWORD addr, LPSTR out)
DWORD disassemble (DWORD addr, LPSTR out, BOOL view)
{
BYTE n;
BYTE fn;
@ -1396,12 +1422,10 @@ DWORD disassemble (DWORD addr, LPSTR out)
switch (disassembler_mode)
{
case HP_MNEMONICS:
// 21.01.99 cg, changed output format
p = append_str (out, "P=");
p = append_tab (out);
wsprintf (buf, "%d", n);
p = append_str (p, buf);
// 21.01.99 cg, end of changed output format
break;
case CLASS_MNEMONICS:
wsprintf (buf, "move.1 #%d, p", n);
@ -1462,7 +1486,7 @@ DWORD disassemble (DWORD addr, LPSTR out)
{
p = append_tab (out);
p = append_r_addr (p, &pc, disp, 2, 1);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
}
break;
@ -1478,7 +1502,7 @@ DWORD disassemble (DWORD addr, LPSTR out)
{
p = append_tab (out);
p = append_r_addr (p, &pc, disp, 2, 1);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
}
break;
@ -1507,7 +1531,7 @@ DWORD disassemble (DWORD addr, LPSTR out)
p = append_str (out, "GOTO");
p = append_tab (out);
p = append_r_addr (p, &pc, disp, 3, 1);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
break;
case CLASS_MNEMONICS:
@ -1524,7 +1548,7 @@ DWORD disassemble (DWORD addr, LPSTR out)
p = append_str (out, "bra.3");
p = append_tab (out);
p = append_r_addr (p, &pc, disp, 3, 1);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
break;
default:
@ -1542,14 +1566,14 @@ DWORD disassemble (DWORD addr, LPSTR out)
p = append_str (out, "GOSUB");
p = append_tab (out);
p = append_r_addr (p, &pc, disp, 3, 4);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
break;
case CLASS_MNEMONICS:
p = append_str (out, "bsr.3");
p = append_tab (out);
p = append_r_addr (p, &pc, disp, 3, 4);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
break;
default:
@ -1563,7 +1587,7 @@ DWORD disassemble (DWORD addr, LPSTR out)
--addr;
if (fn != 0xa && fn != 0xb)
{
p = disasm_8 (&addr, out);
p = disasm_8 (&addr, out, view);
break;
}
/* Fall through */
@ -1602,7 +1626,7 @@ DWORD disassemble (DWORD addr, LPSTR out)
if (disp != 0)
{
p = append_r_addr (p, &pc, disp, 2, 3);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
}
break;
@ -1619,7 +1643,7 @@ DWORD disassemble (DWORD addr, LPSTR out)
{
p = append_str (p, ", ");
p = append_r_addr (p, &pc, disp, 2, 3);
p = append_pc_comment (out, pc);
p = append_pc_comment (out, pc, view);
}
break;

View file

@ -13,7 +13,7 @@
#define LCD1_ROW 144
#define LCD2_ROW 288
#define LCD3_ROW 576 // 24.08.98 cg, new, X4 display
#define LCD3_ROW 576
UINT nBackgroundX = 0;
UINT nBackgroundY = 0;
@ -21,10 +21,10 @@ UINT nBackgroundW = 0;
UINT nBackgroundH = 0;
UINT nLcdX = 0;
UINT nLcdY = 0;
UINT nLcdDoubled = 1; // 24.08.98 cg, changed to integer var
UINT nLcdDoubled = 1;
LPBYTE pbyLcd;
HDC hLcdDC = NULL; // 22.01.98 cg, new, for security only
HDC hMainDC = NULL; // 22.01.98 cg, new, for security only
HDC hLcdDC = NULL;
HDC hMainDC = NULL;
static HBITMAP hLcdBitmap;
static HBITMAP hMainBitmap;
static HBITMAP hOldLcdBitmap;
@ -51,12 +51,9 @@ static struct
#undef W
#undef I
static DWORD Pattern[16]; // 29.01.99 cg, new, use only one pattern
// static DWORD Pattern4[16];
// static DWORD Pattern2[4];
// static DWORD Pattern1[2]; // 24.08.98 cg, new, pattern for X4
static DWORD Pattern[16];
VOID UpdateContrast(BYTE byContrast) // 23.02.99 cg, changed, new implementation
VOID UpdateContrast(BYTE byContrast)
{
DWORD c = byContrast;
DWORD b = byContrast + 0x20;
@ -101,8 +98,6 @@ VOID UpdateContrast(BYTE byContrast) // 23.02.99 cg, changed, new implementatio
VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue)
{
// 25.01.08 cg, bugfix, wrong bit position of red and blue
// 23.02.99 cg, changed, allow 64 colors now
bmiLcd.dwColor[nId&0x3F] = ((nRed&0xFF)<<16)|((nGreen&0xFF)<<8)|(nBlue&0xFF);
return;
}
@ -110,21 +105,19 @@ VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue)
VOID CreateLcdBitmap()
{
// create LCD bitmap
// 24.08.98 cg, changed implementation
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
bmiLcd.Lcd_bmih.biWidth = LCD1_ROW * nLcdDoubled;
bmiLcd.Lcd_bmih.biHeight = -64 * nLcdDoubled;
// 24.08.98 cg, end of changed implementation
hLcdDC = CreateCompatibleDC(hWindowDC);
hLcdBitmap = CreateDIBSection(hLcdDC, (BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS, (LPVOID*)&pbyLcd, NULL, 0);
hOldLcdBitmap = SelectObject(hLcdDC, hLcdBitmap);
UpdateContrast(Chipset.contrast); // 23.01.98 cg, bugfix, use saved contrast
UpdateContrast(Chipset.contrast);
}
VOID DestroyLcdBitmap()
{
WORD i;
// 23.02.99 cg, new, clear background colors
// clear background colors
for (i=32; i< 64; ++i) bmiLcd.dwColor[i] = 0xFFFFFFFF;
if (hLcdDC != NULL)
@ -177,14 +170,14 @@ VOID DestroyMainBitmap()
VOID UpdateDisplayPointers()
{
// 09.09.98 cg, bugfix, calculate display width
// calculate display width
Chipset.width = (34 + Chipset.loffset + (Chipset.boffset / 4) * 2) & 0xFFFFFFFE;
Chipset.end1 = Chipset.start1 + (Chipset.lcounter + 1) * Chipset.width;
if (Chipset.end1 < Chipset.start1)
{
// 09.09.98 cg, bugfix, calculate first address of main display
// calculate first address of main display
Chipset.start12 = Chipset.end1 - Chipset.width;
// 09.09.98 cg, bugfix, calculate last address of main display
// calculate last address of main display
Chipset.end1 = Chipset.start1 - Chipset.width;
}
else
@ -197,7 +190,7 @@ VOID UpdateDisplayPointers()
static BYTE Buf[36];
static BOOL bScreenIsClean = FALSE;
VOID UpdateMainDisplay() // 29.04.98 cg, bugfix, update display even if it's off
VOID UpdateMainDisplay()
{
UINT x, y;
INT nLines;
@ -210,16 +203,13 @@ VOID UpdateMainDisplay() // 29.04.98 cg, bugfix, update display even if it's
if (!bScreenIsClean)
{
bScreenIsClean = TRUE;
// 24.08.98 cg, changed parameter
// 05.01.99 cg, bugfix, with Zoom > 1 only a part of the display was cleared
FillMemory(pbyLcd, LCD1_ROW * nLcdDoubled * nLines * nLcdDoubled, 0);
ZeroMemory(pbyLcd, LCD1_ROW * nLcdDoubled * nLines * nLcdDoubled);
}
}
else
{
nLines = Chipset.lcounter + 1;
bScreenIsClean = FALSE;
// 24.08.98 cg, new, new part for X4
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
if (nLcdDoubled == 4)
{
@ -240,8 +230,7 @@ VOID UpdateMainDisplay() // 29.04.98 cg, bugfix, update display even if it's
d+=Chipset.width;
}
}
// 24.08.98 cg, end of new part
if (nLcdDoubled == 2) // 24.08.98 cg, new var type
if (nLcdDoubled == 2)
{
for (y=0; y<=Chipset.lcounter; y++)
{
@ -256,7 +245,7 @@ VOID UpdateMainDisplay() // 29.04.98 cg, bugfix, update display even if it's
d+=Chipset.width;
}
}
if (nLcdDoubled == 1) // 24.08.98 cg, new var type
if (nLcdDoubled == 1)
{
for (y=0; y<=Chipset.lcounter; y++)
{
@ -266,13 +255,12 @@ VOID UpdateMainDisplay() // 29.04.98 cg, bugfix, update display even if it's
}
}
}
EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
// 24.08.98 cg, use of new var type
BitBlt(hWindowDC, nLcdX, nLcdY, 131*nLcdDoubled, nLines*nLcdDoubled, hLcdDC, Chipset.boffset*nLcdDoubled, 0, SRCCOPY);
GdiFlush(); // 22.01.98 cg
GdiFlush();
}
LeaveCriticalSection(&csGDILock); // 22.01.98 cg
LeaveCriticalSection(&csGDILock);
return;
}
@ -284,15 +272,14 @@ VOID UpdateMenuDisplay()
if (!Chipset.dispon) return;
if (Chipset.lcounter==0x3F) return; // menu disabled
// 24.08.98 cg, new, new part for X4
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
// 18.01.99 cg, calculate offset once
// calculate offset once
p = pbyLcd + ((Chipset.lcounter+1)*nLcdDoubled*LCD1_ROW*nLcdDoubled);
if (nLcdDoubled == 4)
{
for (y=Chipset.lcounter+1; y<64; y++)
{
Npeek(Buf,d,34); // 01.02.99 cg, only 34 nibbles are viewed
Npeek(Buf,d,34); // 34 nibbles are viewed
for (x=0; x<36; x++)
{
*(((DWORD*)p)++)=Pattern[Buf[x]&1];
@ -307,12 +294,11 @@ VOID UpdateMenuDisplay()
d+=34;
}
}
// 24.08.98 cg, end of new part
if (nLcdDoubled == 2) // 24.08.98 cg, new var type
if (nLcdDoubled == 2)
{
for (y=Chipset.lcounter+1; y<64; y++)
{
Npeek(Buf,d,34); // 01.02.99 cg, only 34 nibbles are viewed
Npeek(Buf,d,34); // 34 nibbles are viewed
for (x=0; x<36; x++)
{
*(((DWORD*)p)++)=Pattern[Buf[x]&3];
@ -323,31 +309,28 @@ VOID UpdateMenuDisplay()
d+=34;
}
}
if (nLcdDoubled == 1) // 24.08.98 cg, new var type
if (nLcdDoubled == 1)
{
for (y=Chipset.lcounter+1; y<64; y++)
{
Npeek(Buf,d,34); // 01.02.99 cg, only 34 nibbles are viewed
Npeek(Buf,d,34); // 34 nibbles are viewed
for (x=0; x<36; x++) *(((DWORD*)p)++)=Pattern[Buf[x]];
d+=34;
}
}
EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
// 18.01.99 cg, use common output
BitBlt(hWindowDC, nLcdX, nLcdY+(Chipset.lcounter+1)*nLcdDoubled,
131*nLcdDoubled, (63-Chipset.lcounter)*nLcdDoubled,
hLcdDC, 0, (Chipset.lcounter+1)*nLcdDoubled, SRCCOPY);
GdiFlush(); // 22.01.98 cg
GdiFlush();
}
LeaveCriticalSection(&csGDILock); // 22.01.98 cg
LeaveCriticalSection(&csGDILock);
return;
}
VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
{
// 09.09.98 cg, new bugfixed implementation
// 09.03.99 cg, removed calculated corresponding source memory address
INT x0, x;
INT y0, y;
DWORD *p;
@ -441,141 +424,6 @@ VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
GdiFlush();
}
LeaveCriticalSection(&csGDILock);
#if 0
// 09.09.98 cg, removed
UINT x0, x;
UINT y0, y;
DWORD *p;
if (Chipset.width<0) return;
d -= Chipset.start1;
y0 = y = d / Chipset.width;
x0 = x = d % Chipset.width;
// 05.03.98 cg, bugfix, cut right border later
// if ((x0*4+Chipset.boffset)>=131) return;
// 24.08.98 cg, new, new part for X4
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
if (nLcdDoubled == 4)
{
p = (DWORD*)(pbyLcd + y0*LCD3_ROW*4 + x0*16);
while (s--)
{
if (x<36)
{
p[432] = p[288] = p[144] = p[0] = Pattern1[(*a)&1];
p[433] = p[289] = p[145] = p[1] = Pattern1[((*a)>>1) &1];
p[434] = p[290] = p[146] = p[2] = Pattern1[((*a)>>2) &1];
p[435] = p[291] = p[147] = p[3] = Pattern1[((*a)>>3) &1];
}
a++;
x++;
if ((x==(UINT)Chipset.width)&&s)
{
x=0;
y++;
if (y==(Chipset.lcounter+1)) break;
p=(DWORD*)(pbyLcd+y*LCD3_ROW*4);
} else p+=4;
}
EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems
{
if (y0!=y)
{
y+=3;
y0<<=2; y<<=2;
BitBlt(hWindowDC, nLcdX, nLcdY+y0, 524, y-y0, hLcdDC, Chipset.boffset*4, y0, SRCCOPY);
}
else
{
if (x0>0) --x0; // 09.03.98 cg, bugfix, draw left nibble
x0<<=4; x<<=4;
if (x0>524) x0=524; // 05.03.98 cg, bugfix, cut right border
if (x >524) x =524;
y0<<=2; // y<<=1; // 09.03.98 cg, removed
BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, 4, hLcdDC, x0+Chipset.boffset*4, y0, SRCCOPY);
}
GdiFlush(); // 22.01.98 cg
}
LeaveCriticalSection(&csGDILock); // 22.01.98 cg
}
// 24.08.98 cg, end of new part
if (nLcdDoubled == 2) // 24.08.98 cg, new var type
{
p = (DWORD*)(pbyLcd + y0*LCD2_ROW*2 + x0*8);
while (s--)
{
if (x<36)
{
p[72] = p[0] = Pattern2[(*a)&3];
p[73] = p[1] = Pattern2[(*a)>>2];
}
a++;
x++;
if ((x==(UINT)Chipset.width)&&s)
{
x=0;
y++;
if (y==(Chipset.lcounter+1)) break;
p=(DWORD*)(pbyLcd+y*LCD2_ROW*2);
} else p+=2;
}
EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems
{
if (y0!=y)
{
y++;
y0<<=1; y<<=1;
BitBlt(hWindowDC, nLcdX, nLcdY+y0, 262, y-y0, hLcdDC, Chipset.boffset*2, y0, SRCCOPY);
}
else
{
if (x0>0) --x0; // 09.03.98 cg, bugfix, draw left nibble
x0<<=3; x<<=3;
if (x0>262) x0=262; // 05.03.98 cg, bugfix, cut right border
if (x >262) x =262;
y0<<=1; // y<<=1; // 09.03.98 cg, removed
BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, 2, hLcdDC, x0+Chipset.boffset*2, y0, SRCCOPY);
}
GdiFlush(); // 22.01.98 cg
}
LeaveCriticalSection(&csGDILock); // 22.01.98 cg
}
if (nLcdDoubled == 1) // 24.08.98 cg, new var type
{
p = (DWORD*)(pbyLcd + y0*LCD1_ROW + x0*4);
while (s--)
{
if (x<36) *p = Pattern4[*a];
a++;
x++;
if ((x==(UINT)Chipset.width)&&s)
{
x=0;
y++;
if (y==(Chipset.lcounter+1)) break;
p=(DWORD*)(pbyLcd+y*LCD1_ROW);
} else p++;
}
EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems
{
if (y0!=y)
{
BitBlt(hWindowDC, nLcdX, nLcdY+y0, 131, y-y0+1, hLcdDC, Chipset.boffset, y0, SRCCOPY);
}
else
{
if (x0>0) --x0; // 09.03.98 cg, bugfix, draw left nibble
x0<<=2; x<<=2;
if (x0>131) x0=131; // 05.03.98 cg, bugfix, cut right border
if (x >131) x=131;
BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, 1, hLcdDC, x0+Chipset.boffset, y0, SRCCOPY);
}
GdiFlush(); // 22.01.98 cg
}
LeaveCriticalSection(&csGDILock); // 22.01.98 cg
}
#endif
return;
}
@ -585,13 +433,11 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
UINT y0, y;
DWORD *p;
// if (Chipset.width<0) return; // 09.09.98 cg, bugfix, allow menu update
if (Chipset.lcounter==0x3F) return; // menu disabled
d -= Chipset.start2;
y0 = y = (d / 34) + (Chipset.lcounter+1);
x0 = x = d % 34;
if (x0 > 32) return; // 01.02.99 cg, changed, position out of viewed area
// 24.08.98 cg, new, new part for X4
if (x0 > 32) return; // position out of viewed area
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
if (nLcdDoubled == 4)
{
@ -615,7 +461,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
p=(DWORD*)(pbyLcd+y*LCD3_ROW*4);
} else p+=4;
}
EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
if (y0!=y)
{
@ -629,12 +475,11 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
if (x>524) x=524;
BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, y-y0+4, hLcdDC, x0, y0, SRCCOPY);
}
GdiFlush(); // 22.01.98 cg
GdiFlush();
}
LeaveCriticalSection(&csGDILock); // 22.01.98 cg
LeaveCriticalSection(&csGDILock);
}
// 24.08.98 cg, new, new part for X4
if (nLcdDoubled == 2) // 24.08.98 cg, new var type
if (nLcdDoubled == 2)
{
p = (DWORD*)(pbyLcd + y0*LCD2_ROW*2 + x0*8);
while (s--)
@ -654,7 +499,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
p=(DWORD*)(pbyLcd+y*LCD2_ROW*2);
} else p+=2;
}
EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
if (y0!=y)
{
@ -668,11 +513,11 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
if (x>262) x=262;
BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, y-y0+2, hLcdDC, x0, y0, SRCCOPY);
}
GdiFlush(); // 22.01.98 cg
GdiFlush();
}
LeaveCriticalSection(&csGDILock); // 22.01.98 cg
LeaveCriticalSection(&csGDILock);
}
if (nLcdDoubled == 1) // 24.08.98 cg, new var type
if (nLcdDoubled == 1)
{
p = (DWORD*)(pbyLcd + y0*LCD1_ROW + x0*4);
while (s--)
@ -688,7 +533,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
p=(DWORD*)(pbyLcd+y*LCD1_ROW);
} else p++;
}
EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
if (y0!=y)
{
@ -700,9 +545,9 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
if (x>131) x=131;
BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, y-y0+1, hLcdDC, x0, y0, SRCCOPY);
}
GdiFlush(); // 22.01.98 cg
GdiFlush();
}
LeaveCriticalSection(&csGDILock); // 22.01.98 cg
LeaveCriticalSection(&csGDILock);
}
return;
}
@ -727,7 +572,7 @@ VOID ResizeWindow()
RECT rectWindow;
RECT rectClient;
if (hWnd == NULL) return; // 30.01.98 cg, bugfix, return if window closed
if (hWnd == NULL) return; // return if window closed
rectWindow.left = 0;
rectWindow.top = 0;

File diff suppressed because it is too large Load diff

View file

@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"pch.h" /FD /c
# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /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"
@ -68,7 +68,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"pch.h" /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /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"
@ -95,6 +95,10 @@ SOURCE=.\ddeserv.c
# End Source File
# Begin Source File
SOURCE=.\debugger.c
# End Source File
# Begin Source File
SOURCE=.\disasm.c
# End Source File
# Begin Source File
@ -126,6 +130,10 @@ SOURCE=.\external.c
# End Source File
# Begin Source File
SOURCE=.\fetch.c
# End Source File
# Begin Source File
SOURCE=.\files.c
# End Source File
# Begin Source File
@ -142,6 +150,10 @@ SOURCE=.\mops.c
# End Source File
# Begin Source File
SOURCE=.\opcodes.c
# End Source File
# Begin Source File
SOURCE=.\pch.c
# ADD CPP /Yc"pch.h"
# End Source File
@ -155,6 +167,10 @@ SOURCE=.\serial.c
# End Source File
# Begin Source File
SOURCE=.\settings.c
# End Source File
# Begin Source File
SOURCE=.\timer.c
# End Source File
# End Group
@ -163,15 +179,31 @@ SOURCE=.\timer.c
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
SOURCE=.\color.h
# End Source File
# Begin Source File
SOURCE=.\debugger.h
# End Source File
# Begin Source File
SOURCE=.\Emu48.h
# End Source File
# Begin Source File
SOURCE=.\io.h
# End Source File
# Begin Source File
SOURCE=.\kml.h
# End Source File
# Begin Source File
SOURCE=.\Ops.h
SOURCE=.\opcodes.h
# End Source File
# Begin Source File
SOURCE=.\ops.h
# End Source File
# Begin Source File

View file

@ -8,50 +8,79 @@
*/
#include "types.h"
#define BINARYHEADER "HPHP48-W" // 11.05.98 cg, new
// cards status
#define PORT1_PRESENT ((cCurrentRomType=='S')?0x1:0x2)
#define PORT1_WRITE ((cCurrentRomType=='S')?0x4:0x8)
#define PORT2_PRESENT ((cCurrentRomType=='S')?0x2:0x1)
#define PORT2_WRITE ((cCurrentRomType=='S')?0x8:0x4)
#define S_ERR_NO 0 // 11.05,98 cg, new, stack errorcodes
#define BINARYHEADER48 "HPHP48-W"
#define BINARYHEADER49 "HPHP49-W"
#define S_ERR_NO 0 // stack errorcodes
#define S_ERR_BINARY 1
#define S_ERR_ASCII 2
#define NO_SERIAL "disabled" // 22.05.98 cg, new, serial port not open
#define NO_SERIAL "disabled" // port not open
#define PORT_CLOSE 0 // 20.05.98 cg, new, COM port status
#define PORT_CLOSE 0 // COM port status
#define PORT_WIRE 1
#define PORT_IR 2
#define HP_MNEMONICS FALSE // 10.11.98 cg, new, disassembler mnenomics mode
#define HP_MNEMONICS FALSE // disassembler mnenomics mode
#define CLASS_MNEMONICS TRUE
#define MEM_MAP 0 // 10.11.98 cg, new, memory module definition
#define MEM_MAP 0 // memory module definition
#define MEM_ROM 1
#define MEM_RAM 2
#define MEM_PORT1 3
#define MEM_PORT2 4
#define VIEW_SHORT FALSE // view of disassembler output
#define VIEW_LONG TRUE
#define DISP_POINTER 0x01 // defines for display area
#define DISP_MAIN 0x02
#define DISP_MENUE 0x04
#define DISP_ANNUN 0x08
// Emu48.c
extern HPALETTE hPalette;
extern HPALETTE hOldPalette; // 11.09.98 cg, old palette of hWindowDC
extern LPSTR szAppName; // 13.05.98 cg, application name for DDE server
extern LPSTR szTopic; // 13.05.98 cg, topic for DDE server
extern HPALETTE hOldPalette;
extern HANDLE hEventShutdn;
extern LPSTR szAppName;
extern LPSTR szTopic;
extern LPSTR szTitle;
extern CRITICAL_SECTION csGDILock; // 22.01.98 cg, critical section for hWindowDC
extern CRITICAL_SECTION csKeyLock; // 02.09.98 cg, critical section for key scan
extern CRITICAL_SECTION csIOLock; // 24.02.99 cg, critical section for I/O access
extern CRITICAL_SECTION csT1Lock; // 21.04.98 cg, critical section for timer1 access
extern CRITICAL_SECTION csT2Lock; // 21.04.98 cg, critical section for timer2 access
extern LARGE_INTEGER lFreq; // 24.08.98 cg, counter frequency
extern DWORD idDdeInst; // 13.05.98 cg, DDE server id
extern UINT uCF_HpObj; // 13.05.98 cg, DDE clipboard format
extern HINSTANCE hApp; // 01.11.98 cg, wrong variable type
extern CRITICAL_SECTION csGDILock;
extern CRITICAL_SECTION csKeyLock;
extern CRITICAL_SECTION csIOLock;
extern CRITICAL_SECTION csT1Lock;
extern CRITICAL_SECTION csT2Lock;
extern CRITICAL_SECTION csRecvLock; // 24.10.99 cg, critical section for receive byte
extern INT nArgc; // 08.11.99 cg, no. of command line arguments
extern LPCTSTR *ppArgv; // 08.11.99 cg, command line arguments
extern LARGE_INTEGER lFreq;
extern DWORD idDdeInst;
extern UINT uCF_HpObj;
extern HINSTANCE hApp;
extern HWND hWnd;
extern HDC hWindowDC;
extern BOOL bPort2IsShared;
extern BOOL bAutoSave; // 11.12.99 cg, add declaration
extern BOOL bAutoSaveOnExit; // 11.12.99 cg, add declaration
extern BOOL bAlwaysDisplayLog;
extern UINT uTimer1Period;
// extern UINT uTimer1Period; // 11.12.99 cg, removed old definition
extern HANDLE hThread; // 11.12.99 cg, add declaration
extern DWORD lThreadId; // 11.12.99 cg, add declaration
extern VOID SetWindowTitle(LPSTR szString);
extern VOID UpdateWindowStatus(VOID);
// Settings.c
extern VOID ReadSettings(VOID); // 11.12.99 cg, moved from Emu48.c
extern VOID WriteSettings(VOID); // 11.12.99 cg, moved from Emu48.c
extern VOID ReadLastDocument(LPTSTR szFileName, DWORD nSize);
extern VOID WriteLastDocument(LPCTSTR szFilename);
// Display.c
extern UINT nBackgroundX;
extern UINT nBackgroundY;
@ -59,7 +88,7 @@ extern UINT nBackgroundW;
extern UINT nBackgroundH;
extern UINT nLcdX;
extern UINT nLcdY;
extern UINT nLcdDoubled; // 24.08.98 cg, changed to integer var
extern UINT nLcdDoubled;
extern LPBYTE pbyLcd;
extern HDC hLcdDC;
extern HDC hMainDC;
@ -81,21 +110,25 @@ extern VOID ResizeWindow(VOID);
extern BOOL bInterrupt;
extern UINT nState;
extern UINT nNextState;
extern BOOL bKeySlow; // 18.11.98 cg, slow down for key emulation
extern HANDLE hThread;
extern BOOL bRealSpeed; // 11.12.99 cg, new, real speed flag
extern BOOL bKeySlow;
extern CHIPSET Chipset;
extern char szSerialWire[16]; // 20.05.98 cg, devicename for wire port
extern char szSerialIr[16]; // 20.05.98 cg, devicename for IR port
extern DWORD dwSXCycles; // 23.04.98 cg, SX cpu cycles in 1/16384 Hz
extern DWORD dwGXCycles; // 23.04.98 cg, GX cpu cycles in 1/16384 Hz
extern VOID SetSpeed(BOOL bAdjust); // 23.04.98 cg, set emulation speed
extern VOID UpdateKdnBit(VOID); // 25.02.99 cg, update KDN bit
extern BOOL WaitForSleepState(VOID); // 16.06.98 cg, wait for cpu SHUTDN then sleep state
extern char szSerialWire[16];
extern char szSerialIr[16];
extern DWORD dwSXCycles;
extern DWORD dwGXCycles;
extern VOID AdjKeySpeed(VOID);
extern VOID SetSpeed(BOOL bAdjust);
extern VOID UpdateKdnBit(VOID);
extern BOOL WaitForSleepState(VOID);
extern UINT SwitchToState(UINT nNewState);
extern UINT WorkerThread(LPVOID pParam);
extern DWORD Npack(BYTE *a, UINT s);
extern VOID Nunpack(BYTE *a, DWORD b, UINT s);
// Fetch.c
extern VOID EvalOpcode(LPBYTE I);
// Files.c
extern char szEmu48Directory[260];
extern char szCurrentDirectory[260];
@ -111,11 +144,10 @@ extern char cCurrentRomType;
extern LPBYTE pbyPort2;
extern BOOL bPort2Writeable;
extern BOOL bPort2IsShared;
extern DWORD dwPort2Size; // 26.06.98 cg, size of mapped port2
extern DWORD dwPort2Size;
extern DWORD dwPort2Mask;
// extern UINT nPort2Bank; // 15.12.98 cg, removed, not used any more
extern BOOL bBackup;
extern WORD WriteStack(LPBYTE,DWORD); // 11.05.98 cg, write object to stack
extern WORD WriteStack(LPBYTE,DWORD);
extern BOOL MapRom(LPCSTR szFilename);
extern VOID UnmapRom(VOID);
extern BOOL MapPort2(LPCSTR szFilename);
@ -138,8 +170,7 @@ extern BOOL SaveObject(LPCSTR szFilename);
extern HBITMAP LoadBitmapFile(LPCSTR szFilename);
// Timer.c
// extern BOOL bAccurateTimer; // 10.11.98 cg, removed, not adjustable any more
// extern UINT uT1Period; // 10.11.98 cg, removed, not adjustable any more
extern VOID SetHP48Time(VOID);
extern VOID StartTimers(VOID);
extern VOID StopTimers(VOID);
extern DWORD ReadT2(VOID);
@ -148,32 +179,32 @@ extern BYTE ReadT1(VOID);
extern VOID SetT1(BYTE byValue);
// MOps.c
extern BOOL ioc_acc; // 17.05.98 cg, flag ioc changed
extern BOOL ir_ctrl_acc; // 17.05.98 cg, flag ir_ctl changed
extern BOOL ioc_acc;
extern BOOL ir_ctrl_acc;
extern BYTE disp;
extern LPBYTE RMap[256];
extern LPBYTE WMap[256];
extern VOID Map(BYTE a, BYTE b);
extern VOID RomSwitch(DWORD adr);
extern VOID Config(VOID);
extern VOID Uncnfg(VOID);
extern VOID Reset(VOID);
extern VOID C_Eq_Id(VOID);
extern VOID CpuReset(VOID); // 19.03.99 cg, register setting after Cpu Reset
extern BYTE GetLineCounter(VOID);
extern VOID Npeek(BYTE *a, DWORD d, UINT s);
extern VOID Nread(BYTE *a, DWORD d, UINT s);
extern VOID Nwrite(BYTE *a, DWORD d, UINT s);
// extern VOID Nread2(BYTE *a, DWORD d); // 15.12.98 cg, removed, repaced by Nread()
// extern VOID Nwrite2(BYTE *a, DWORD d);// 15.12.98 cg, removed, repaced by Nwrite()
// extern VOID Nread5(BYTE *a, DWORD d); // 15.12.98 cg, removed, repaced by Nread()
// extern VOID Nwrite5(BYTE *a, DWORD d);// 15.12.98 cg, removed, repaced by Nwite()
extern BYTE Read2(DWORD d);
extern DWORD Read5(DWORD d);
extern VOID Write5(DWORD d, DWORD n);
extern VOID IOBit(DWORD d, BYTE b, BOOL s);// 24.02.99 cg, set/clear bit in I/O section
extern VOID Write2(DWORD d, BYTE n);
extern VOID IOBit(DWORD d, BYTE b, BOOL s);
extern VOID ReadIO(BYTE *a, DWORD b, DWORD s);
extern VOID WriteIO(BYTE *a, DWORD b, DWORD s);
// Keyboard.c
// extern WORD Keyboard_GetIR(VOID); // 13.02.99 cg, is static now
extern VOID ScanKeyboard(BOOL bReset); // 02.09.98 cg, add flag for key state reset
extern VOID ScanKeyboard(BOOL bReset);
extern VOID KeyboardEvent(BOOL bPress, UINT out, UINT in);
// RPL.c
@ -193,13 +224,14 @@ extern HDDEDATA CALLBACK DdeCallback(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, DWOR
// Disasm.c
extern BOOL disassembler_mode;
extern WORD disassembler_map;
extern DWORD disassemble (DWORD addr, LPSTR out);
extern DWORD disassemble (DWORD addr, LPSTR out, BOOL view);
// Serial.c
extern WORD CommConnect(VOID);
extern VOID CommOpen(LPSTR strWirePort,LPSTR strIrPort);
extern VOID CommClose(VOID);
extern VOID CommSetBaud(VOID);
extern VOID UpdateUSRQ(VOID); // 25.10.99 cg, USRQ handling
extern VOID CommTransmit(VOID);
extern VOID CommReceive(VOID);
@ -213,7 +245,7 @@ static __inline int YesNoCancelMessage(LPCSTR szMessage) {return MessageBox(hWnd
static __inline LPSTR DuplicateString(LPCSTR szString)
{
UINT uLength = strlen(szString) + 1;
LPSTR szDup = LocalAlloc(LMEM_FIXED,uLength); // 27.01.98 cg, adjust memsize
LPSTR szDup = LocalAlloc(LMEM_FIXED,uLength);
CopyMemory(szDup,szString,uLength);
return szDup;
}

View file

@ -21,133 +21,86 @@ LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
#pragma code_page(1252)
#endif //_WIN32
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
// DESIGNINFO
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,1,0,0
PRODUCTVERSION 1,1,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x21L
#else
FILEFLAGS 0x20L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "00000000"
BEGIN
VALUE "CompanyName", "Sebastien Carlier\0"
VALUE "FileDescription", "HP48 Emulator\0"
VALUE "FileVersion", "1, 1, 0, 0\0"
VALUE "InternalName", "Emu48\0"
VALUE "LegalCopyright", "Copyright © 1999\0"
VALUE "OriginalFilename", "Emu48.exe\0"
VALUE "ProductName", "Emu48\0"
VALUE "ProductVersion", "1, 1, 0, 0\0"
VALUE "SpecialBuild", "Service Pack 10, Christoph Gießelink\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 0
END
END
#endif // !_MAC
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_EMU48 ICON DISCARDABLE "Emu48.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_MENU MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&New...", ID_FILE_NEW
MENUITEM "&Open...", ID_FILE_OPEN
MENUITEM "&Save", ID_FILE_SAVE, GRAYED
MENUITEM "Save &As...", ID_FILE_SAVEAS, GRAYED
MENUITEM "&Close", ID_FILE_CLOSE, GRAYED
MENUITEM SEPARATOR
MENUITEM "S&ettings...", ID_VIEW_SETTINGS
MENUITEM SEPARATOR
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&Edit"
BEGIN
MENUITEM "&Load Object...", ID_OBJECT_LOAD
MENUITEM "&Save Object...", ID_OBJECT_SAVE
MENUITEM SEPARATOR
MENUITEM "&Copy String", ID_STACK_COPY
MENUITEM "C&opy Screen", ID_VIEW_COPY
MENUITEM "&Paste String", ID_STACK_PASTE
MENUITEM SEPARATOR
MENUITEM "&Reset Calculator", ID_VIEW_RESET, GRAYED
POPUP "&Backup"
BEGIN
MENUITEM "&Save", ID_BACKUP_SAVE, GRAYED
MENUITEM "&Restore", ID_BACKUP_RESTORE
, GRAYED
MENUITEM "&Delete", ID_BACKUP_DELETE, GRAYED
END
END
POPUP "&View"
BEGIN
MENUITEM "Change &KML Script...", ID_VIEW_SCRIPT
END
POPUP "&Tools"
BEGIN
MENUITEM "&Disassembler...", ID_TOOL_DISASM
END
POPUP "&Help"
BEGIN
MENUITEM "&About Emu48...", ID_ABOUT
END
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
"resource.h\0"
IDD_BREAKEDIT, DIALOG
BEGIN
LEFTMARGIN, 5
RIGHTMARGIN, 105
TOPMARGIN, 5
BOTTOMMARGIN, 97
END
2 TEXTINCLUDE DISCARDABLE
IDD_ABOUT, DIALOG
BEGIN
"#include ""winres.h""\r\n"
"\0"
LEFTMARGIN, 7
RIGHTMARGIN, 254
TOPMARGIN, 6
BOTTOMMARGIN, 145
END
3 TEXTINCLUDE DISCARDABLE
IDD_SETTINGS, DIALOG
BEGIN
"\r\n"
"\0"
LEFTMARGIN, 7
RIGHTMARGIN, 160
TOPMARGIN, 4
BOTTOMMARGIN, 171
END
IDD_CHOOSEKML, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 59
END
IDD_KMLLOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 294
TOPMARGIN, 7
BOTTOMMARGIN, 160
END
IDD_DISASM, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 248
TOPMARGIN, 5
BOTTOMMARGIN, 158
END
IDD_DEBUG, DIALOG
BEGIN
LEFTMARGIN, 5
RIGHTMARGIN, 273
TOPMARGIN, 5
BOTTOMMARGIN, 212
END
IDD_NEWVALUE, DIALOG
BEGIN
LEFTMARGIN, 8
RIGHTMARGIN, 168
TOPMARGIN, 7
BOTTOMMARGIN, 43
END
IDD_ENTERADR, DIALOG
BEGIN
LEFTMARGIN, 8
RIGHTMARGIN, 149
TOPMARGIN, 7
BOTTOMMARGIN, 43
END
END
#endif // APSTUDIO_INVOKED
@ -156,6 +109,19 @@ END
// Dialog
//
IDD_BREAKEDIT DIALOG DISCARDABLE 0, 0, 110, 102
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Edit breakpoints"
FONT 8, "Courier New"
BEGIN
DEFPUSHBUTTON "OK",IDOK,77,83,28,14
LTEXT "Current breakpoints:",IDC_STATIC_BREAKPOINT,5,5,82,8
LISTBOX IDC_BREAKEDIT_WND,5,17,100,60,NOT LBS_NOTIFY | LBS_SORT |
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "&Add",IDC_BREAKEDIT_ADD,5,83,28,14
PUSHBUTTON "&Delete",IDC_BREAKEDIT_DELETE,41,83,28,14
END
IDD_ABOUT DIALOGEX 0, 0, 261, 160
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Emu48"
@ -270,39 +236,265 @@ BEGIN
WS_TABSTOP,WS_EX_NOPARENTNOTIFY
END
IDD_DEBUG DIALOGEX 0, 0, 278, 217
STYLE WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Debugger"
MENU IDR_DEBUG
FONT 8, "Courier New", 0, 0, 0x1
BEGIN
LISTBOX IDC_DEBUG_CODE,11,15,165,122,NOT LBS_NOTIFY |
LBS_OWNERDRAWFIXED | LBS_HASSTRINGS |
LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT |
WS_TABSTOP
GROUPBOX "Code",IDC_STATIC_CODE,5,5,177,138
LTEXT "A= 0000000000000000",IDC_REG_A,192,15,77,8
LTEXT "B= 0000000000000000",IDC_REG_B,192,22,77,8
LTEXT "C= 0000000000000000",IDC_REG_C,192,29,77,8
LTEXT "D= 0000000000000000",IDC_REG_D,192,36,77,8
LTEXT "R0=0000000000000000",IDC_REG_R0,192,46,77,8
LTEXT "R1=0000000000000000",IDC_REG_R1,192,53,77,8
LTEXT "R2=0000000000000000",IDC_REG_R2,192,60,77,8
LTEXT "R3=0000000000000000",IDC_REG_R3,192,67,77,8
LTEXT "R4=0000000000000000",IDC_REG_R4,192,74,77,8
LTEXT "D0=00000",IDC_REG_D0,192,85,33,8
LTEXT "D1=00000",IDC_REG_D1,236,85,33,8
LTEXT "P=0",IDC_REG_P,192,96,13,8
LTEXT "PC=00000",IDC_REG_PC,236,96,33,8
LTEXT "OUT=000",IDC_REG_OUT,192,107,29,8
LTEXT "IN=0000",IDC_REG_IN,240,107,29,8
LTEXT "ST=0000",IDC_REG_ST,192,118,29,8
LTEXT "CY=0",IDC_REG_CY,224,118,17,8
LTEXT "Mode=H",IDC_REG_MODE,244,118,25,8
LTEXT "MP=0",IDC_REG_MP,192,128,17,8
LTEXT "SR=0",IDC_REG_SR,212,128,17,8
LTEXT "SB=0",IDC_REG_SB,232,128,17,8
LTEXT "XM=0",IDC_REG_XM,252,128,17,8
GROUPBOX "Registers",IDC_STATIC_REGISTERS,186,5,87,138
CONTROL "",IDC_DEBUG_MEM,"Static",SS_WHITERECT | WS_GROUP,11,154,
165,52,WS_EX_CLIENTEDGE
LISTBOX IDC_DEBUG_MEM_ADDR,12,156,25,48,NOT LBS_NOTIFY |
LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_DISABLED | NOT
WS_BORDER
LISTBOX IDC_DEBUG_MEM_COL0,40,156,11,48,LBS_NOINTEGRALHEIGHT |
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER | WS_TABSTOP
LISTBOX IDC_DEBUG_MEM_COL1,52,156,11,48,LBS_NOINTEGRALHEIGHT |
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
LISTBOX IDC_DEBUG_MEM_COL2,64,156,11,48,LBS_NOINTEGRALHEIGHT |
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
LISTBOX IDC_DEBUG_MEM_COL3,76,156,11,48,LBS_NOINTEGRALHEIGHT |
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
LISTBOX IDC_DEBUG_MEM_COL4,88,156,11,48,LBS_NOINTEGRALHEIGHT |
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
LISTBOX IDC_DEBUG_MEM_COL5,100,156,11,48,LBS_NOINTEGRALHEIGHT |
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
LISTBOX IDC_DEBUG_MEM_COL6,112,156,11,48,LBS_NOINTEGRALHEIGHT |
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
LISTBOX IDC_DEBUG_MEM_COL7,124,156,11,48,LBS_NOINTEGRALHEIGHT |
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
LISTBOX IDC_DEBUG_MEM_TEXT,139,156,35,48,NOT LBS_NOTIFY |
LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_DISABLED | NOT
WS_BORDER
GROUPBOX "Memory",IDC_STATIC_MEMORY,5,144,177,68
LISTBOX IDC_DEBUG_STACK,192,154,75,52,NOT LBS_NOTIFY |
LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT |
WS_VSCROLL | WS_TABSTOP
GROUPBOX "Stack",IDC_STATIC_STACK,186,144,87,68
END
IDD_NEWVALUE DIALOG DISCARDABLE 0, 0, 175, 50
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "New Value"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "New value (hexdezimal):",IDC_STATIC,8,9,81,8
EDITTEXT IDC_NEWVALUE,91,7,77,12,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,21,29,50,14
PUSHBUTTON "Cancel",IDCANCEL,103,29,50,14
END
IDD_ENTERADR DIALOG DISCARDABLE 0, 0, 156, 50
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Enter address"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Enter address (hexdezimal):",IDC_STATIC,8,9,90,8
EDITTEXT IDC_ENTERADR,106,7,43,12,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,14,29,50,14
PUSHBUTTON "Cancel",IDCANCEL,92,29,50,14
END
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,1,5,0
PRODUCTVERSION 1,1,5,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x21L
#else
FILEFLAGS 0x20L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "00000000"
BEGIN
VALUE "CompanyName", "Sebastien Carlier\0"
VALUE "FileDescription", "HP38/48/49 Emulator\0"
VALUE "FileVersion", "1, 1, 5, 0\0"
VALUE "InternalName", "Emu48\0"
VALUE "LegalCopyright", "Copyright © 1999\0"
VALUE "OriginalFilename", "Emu48.exe\0"
VALUE "ProductName", "Emu48\0"
VALUE "ProductVersion", "1, 1, 5, 0\0"
VALUE "SpecialBuild", "Service Pack 15, Christoph Gießelink\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 0
END
END
#endif // !_MAC
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_EMU48 ICON DISCARDABLE "Emu48.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_MENU MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&New...", ID_FILE_NEW
MENUITEM "&Open...", ID_FILE_OPEN
MENUITEM "&Save", ID_FILE_SAVE, GRAYED
MENUITEM "Save &As...", ID_FILE_SAVEAS, GRAYED
MENUITEM "&Close", ID_FILE_CLOSE, GRAYED
MENUITEM SEPARATOR
MENUITEM "S&ettings...", ID_VIEW_SETTINGS
MENUITEM SEPARATOR
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&Edit"
BEGIN
MENUITEM "&Load Object...", ID_OBJECT_LOAD
MENUITEM "&Save Object...", ID_OBJECT_SAVE
MENUITEM SEPARATOR
MENUITEM "&Copy String", ID_STACK_COPY
MENUITEM "C&opy Screen", ID_VIEW_COPY
MENUITEM "&Paste String", ID_STACK_PASTE
MENUITEM SEPARATOR
MENUITEM "&Reset Calculator", ID_VIEW_RESET, GRAYED
POPUP "&Backup"
BEGIN
MENUITEM "&Save", ID_BACKUP_SAVE, GRAYED
MENUITEM "&Restore", ID_BACKUP_RESTORE
, GRAYED
MENUITEM "&Delete", ID_BACKUP_DELETE, GRAYED
END
END
POPUP "&View"
BEGIN
MENUITEM "Change &KML Script...", ID_VIEW_SCRIPT
END
POPUP "&Tools"
BEGIN
MENUITEM "D&isassembler...", ID_TOOL_DISASM
MENUITEM "&Debugger...", ID_TOOL_DEBUG
END
POPUP "&Help"
BEGIN
MENUITEM "&About Emu48...", ID_ABOUT
END
END
IDR_DEBUG MENU DISCARDABLE
BEGIN
POPUP "&Debug"
BEGIN
MENUITEM "&Run\tF5", ID_DEBUG_RUN
MENUITEM "&Step Into\tF7", ID_DEBUG_STEP
MENUITEM "Step &Over\tF8", ID_DEBUG_STEPOVER
MENUITEM "Step O&ut\tF9", ID_DEBUG_STEPOUT
MENUITEM "&Break\tF11", ID_DEBUG_BREAK
END
POPUP "&Breakpoints"
BEGIN
MENUITEM "Set &breakpoint\tF2", ID_BREAKPOINTS_SETBREAK
MENUITEM "&Edit breakpoints...", ID_BREAKPOINTS_CODEEDIT
MENUITEM "&Clear all breakpoints", ID_BREAKPOINTS_CLEARALL
MENUITEM SEPARATOR
MENUITEM "&NOP3 code breakpoints", ID_BREAKPOINTS_NOP3
END
END
IDR_DEBUG_CODE MENU DISCARDABLE
BEGIN
POPUP ""
BEGIN
MENUITEM "&Go to address...\tG", ID_DEBUG_CODE_GOADR
MENUITEM "Go to &PC", ID_DEBUG_CODE_GOPC
MENUITEM "Set &breakpoint\tF2", ID_BREAKPOINTS_SETBREAK
MENUITEM "&Set PC to selection", ID_DEBUG_CODE_SETPCTOSELECT
END
END
IDR_DEBUG_MEM MENU DISCARDABLE
BEGIN
POPUP ""
BEGIN
MENUITEM "&Go to address...\tG", ID_DEBUG_MEM_GOADR
MENUITEM "Go to &PC", ID_DEBUG_MEM_GOPC
MENUITEM "Go to D&0", ID_DEBUG_MEM_GOD0
MENUITEM "Go to D&1", ID_DEBUG_MEM_GOD1
MENUITEM "Go to &Stack", ID_DEBUG_MEM_GOSTACK
END
END
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
IDD_CHOOSEKML, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 59
"resource.h\0"
END
IDD_KMLLOG, DIALOG
2 TEXTINCLUDE DISCARDABLE
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 294
TOPMARGIN, 7
BOTTOMMARGIN, 160
"#include ""winres.h""\r\n"
"\0"
END
IDD_DISASM, DIALOG
3 TEXTINCLUDE DISCARDABLE
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 248
TOPMARGIN, 5
BOTTOMMARGIN, 158
END
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // French (France) resources

View file

@ -8,81 +8,72 @@
*/
#include "pch.h"
#include "Emu48.h"
#include "Serial.h"
#include "Opcodes.h"
#include "io.h" // 24.10.99 cg, renamed from Serial.h
#include "debugger.h"
// HST bits
#define XM 1
#define SB 2
#define SR 4
#define MP 8
#pragma intrinsic(memset,memcpy)
#define w Chipset
#define PCHANGED ((void)(F_s[0]=w.P,F_l[1]=w.P+1))
#define GOYES3 {if(w.carry)goto o_goyes3;else{w.pc+=2;continue;}}
#define GOYES5 {if(w.carry)goto o_goyes5;else{w.pc+=2;continue;}}
#define INTERRUPT ((void)(w.SoftInt=TRUE,bInterrupt=TRUE))
#define SAMPLE 16384 // 23.04.98 cg, new, speed adjust sample frequency
// 23.04.98 cg, new, cpu cycles for interval
#define T2CYCLES ((cCurrentRomType=='S')?dwSXCycles:dwGXCycles)
//#define FASTPTR(d) (RMap[d>>12]+(d&0xFFF))
static __inline LPBYTE FASTPTR(DWORD d)
{
// 17.12.98 cg, bugfix, code is running in IO area as well
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
return Chipset.IORam+d-Chipset.IOBase;
return RMap[d>>12]+(d&0xFFF);
}
#include "Ops.h"
#define SAMPLE 16384 // speed adjust sample frequency
BOOL bInterrupt = FALSE;
UINT nState = 1;
UINT nNextState = 0;
BOOL bKeySlow = FALSE; // 18.11.98 cg, new, slow down for key emulation
BOOL bRealSpeed = FALSE; // 11.12.99 cg, moved from Emu48.c
BOOL bKeySlow = FALSE; // slow down for key emulation
CHIPSET Chipset;
char szSerialWire[16]; // 20.05.98 cg, new, devicename for wire port
char szSerialIr[16]; // 20.05.98 cg, new, devicename for IR port
char szSerialWire[16]; // evicename for wire port
char szSerialIr[16]; // devicename for IR port
DWORD dwSXCycles = 82; // 23.04.98 cg, new, SX cpu cycles in interval
DWORD dwGXCycles = 123; // 23.04.98 cg, new, GX cpu cycles in interval
DWORD dwSXCycles = 82; // SX cpu cycles in interval
DWORD dwGXCycles = 123; // GX cpu cycles in interval
static BOOL bCommInit = FALSE; // 17.05.98 cg, new, COM port not open
static BOOL bRealSpeed = FALSE; // 23.04.98 cg, new, enable/disable real speed
static BOOL bCommInit = FALSE; // COM port not open
static BOOL bCpuSlow = FALSE; // 11.12.99 cg, renamed, enable/disable real speed
static DWORD dwOldCyc; // 23.04.98 cg, new, cpu cycles at last event
static DWORD dwSpeedRef; // 23.04.98 cg, new, timer value at last event
static DWORD dwTickRef; // 23.04.98 cg, new, sample timer ticks
static DWORD dwOldCyc; // cpu cycles at last event
static DWORD dwSpeedRef; // timer value at last event
static DWORD dwTickRef; // sample timer ticks
static __inline VOID CheckSerial(VOID) // 17.05.98 cg, new function
// 25.02.99 cg, changed, inline coded now
#include "Ops.h"
static __inline VOID CheckDisp(BOOL bSync)
{
if (disp == 0) return; // no display update need
// update display when drawing top line or display is off
if (bSync && GetLineCounter() != 0x3F && (Chipset.IORam[0x00]&8))
return;
_ASSERT((disp & DISP_POINTER) == 0); // display pointer already updated
if (disp & DISP_MAIN) UpdateMainDisplay();
if (disp & DISP_MENUE) UpdateMenuDisplay();
_ASSERT((disp & DISP_ANNUN) == 0); // annunciators already updated
disp = 0; // display updated
return;
}
static __inline VOID CheckSerial(VOID)
{
if (ioc_acc) // IOC changed
{
ioc_acc = FALSE;
// COM port closed and serial on
if (bCommInit == FALSE && (Chipset.IORam[IO_CTRL] & SON) != 0)
if (bCommInit == FALSE && (Chipset.IORam[IOC] & SON) != 0)
{
CommOpen(szSerialWire,szSerialIr); // open COM ports
bCommInit = CommConnect() != PORT_CLOSE;
}
// COM port opend and serial off
if (bCommInit == TRUE && (Chipset.IORam[IO_CTRL] & SON) == 0)
if (bCommInit == TRUE && (Chipset.IORam[IOC] & SON) == 0)
{
CommClose(); // close COM port
bCommInit = FALSE;
}
// Interrupt on recv buffer full and receive buffer full
if ((Chipset.IORam[IO_CTRL] & ERBF) && (Chipset.IORam[RCS] & RBF))
if ((Chipset.IORam[IOC] & ERBF) && (Chipset.IORam[RCS] & RBF))
{
Chipset.Shutdn = FALSE;
INTERRUPT;
@ -90,13 +81,13 @@ static __inline VOID CheckSerial(VOID) // 17.05.98 cg, new function
}
}
static __inline VOID AdjustSpeed(VOID) // 23.04.98 cg, new, adjust emulation speed
// 25.02.99 cg, changed, inline coded now
static __inline VOID AdjustSpeed(VOID) // adjust emulation speed
{
if (bRealSpeed || bKeySlow) // 18.11.98 cg, changed, slow down
if (bCpuSlow || bKeySlow) // 11.12.99 cg, changed, emulation slow down
{
// cycles elapsed for next check
if (Chipset.cycles-dwOldCyc >= (DWORD) T2CYCLES)
// 22.11.99 cg, changed, DWORD casting of Chipset.cycles
if ((DWORD) (Chipset.cycles & 0xFFFFFFFF)-dwOldCyc >= (DWORD) T2CYCLES)
{
LARGE_INTEGER lAct;
do
@ -113,14 +104,12 @@ static __inline VOID AdjustSpeed(VOID) // 23.04.98 cg, new, adjust emulation sp
return;
}
static VOID AdjKeySpeed(VOID) // 05.07.98 cg, new, slow down key repeat
// 18.11.98 cg, bugfix, slow down whole emulation,
// when key pressed
VOID AdjKeySpeed(VOID) // slow down key repeat
{
WORD i;
BOOL bKey;
if (bRealSpeed) return; // no need to slow down
if (bCpuSlow) return; // 11.12.99 cg, changed, no need to slow down
bKey = FALSE; // search for a pressed key
for (i = 0;i < sizeof(Chipset.Keyboard_Row) / sizeof(Chipset.Keyboard_Row[0]) && !bKey;++i)
@ -129,7 +118,9 @@ static VOID AdjKeySpeed(VOID) // 05.07.98 cg, new, slow down key repeat
if (!bKeySlow && bKey) // key pressed, init variables
{
LARGE_INTEGER lTime; // sample timer ticks
dwOldCyc = Chipset.cycles; // save reference cycles
// save reference cycles
// 22.11.99 cg, changed, DWORD casting
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
QueryPerformanceCounter(&lTime); // get timer ticks
dwSpeedRef = lTime.LowPart; // save reference time
}
@ -137,25 +128,28 @@ static VOID AdjKeySpeed(VOID) // 05.07.98 cg, new, slow down key repeat
return;
}
VOID SetSpeed(BOOL bAdjust) // 23.04.98 cg, new, set emulation speed
VOID SetSpeed(BOOL bAdjust) // set emulation speed
{
if (bAdjust) // 15.05.98 cg, changed, switch to real speed
if (bAdjust) // switch to real speed
{
LARGE_INTEGER lTime; // sample timer ticks
dwOldCyc = Chipset.cycles; // save reference cycles
// save reference cycles
// 22.11.99 cg, changed, DWORD casting
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
QueryPerformanceCounter(&lTime); // get timer ticks
dwSpeedRef = lTime.LowPart; // save reference time
}
bRealSpeed = bAdjust; // 15.05.98 cg, bugfix, save emulation speed
bCpuSlow = bAdjust; // 11.12.99 cg, changed, save emulation speed
}
VOID UpdateKdnBit(VOID) // 25.02.99 cg, new, update KDN bit
VOID UpdateKdnBit(VOID) // update KDN bit
{
if (Chipset.intk && Chipset.cycles - Chipset.dwKdnCycles > (DWORD) T2CYCLES * 16)
// 22.11.99 cg, changed, DWORD casting of Chipset.cycles
if (Chipset.intk && (DWORD) (Chipset.cycles & 0xFFFFFFFFF) - Chipset.dwKdnCycles > (DWORD) T2CYCLES * 16)
IOBit(0x19,8,Chipset.in != 0);
}
BOOL WaitForSleepState(VOID) // 16.06.98 cg, new, wait for cpu SHUTDN then sleep state
BOOL WaitForSleepState(VOID) // wait for cpu SHUTDN then sleep state
{
DWORD dwRefTime = timeGetTime();
@ -177,12 +171,17 @@ UINT SwitchToState(UINT nNewState)
switch (nState)
{
case 0: // Run
if (hDlgDebug) // debugger running
{
DestroyWindow(hDlgDebug); // then close debugger to renter emulation
hDlgDebug = NULL;
}
switch (nNewState)
{
case 1: // -> Invalid
nNextState = 1;
if (Chipset.Shutdn)
ResumeThread(hThread);
SetEvent(hEventShutdn);
else
bInterrupt = TRUE;
while (nState!=nNextState) Sleep(0);
@ -191,19 +190,19 @@ UINT SwitchToState(UINT nNewState)
case 2: // -> Return
nNextState = 1;
if (Chipset.Shutdn)
ResumeThread(hThread);
SetEvent(hEventShutdn);
else
bInterrupt = TRUE;
while (nState!=nNextState) Sleep(0);
nNextState = 2;
ResumeThread(hThread);
SetEvent(hEventShutdn);
while (nState!=nNextState) Sleep(0);
UpdateWindowStatus();
break;
case 3: // -> Sleep
nNextState = 3;
if (Chipset.Shutdn)
ResumeThread(hThread);
SetEvent(hEventShutdn);
else
bInterrupt = TRUE;
while (nState!=nNextState) Sleep(0);
@ -216,24 +215,18 @@ UINT SwitchToState(UINT nNewState)
case 0: // -> Run
nNextState = 0;
bInterrupt = FALSE;
// 16.05.98 cg, bugfix, wait until thread is down, then resume
while (ResumeThread(hThread)==0) Sleep(0);
// ResumeThread(hThread);
SetEvent(hEventShutdn);
while (nState!=nNextState) Sleep(0);
UpdateWindowStatus();
break;
case 2: // -> Return
nNextState = 2;
// 16.05.98 cg, bugfix, wait until thread is down, then resume
while (ResumeThread(hThread)==0) Sleep(0);
// ResumeThread(hThread);
SetEvent(hEventShutdn);
while (nState!=nNextState) Sleep(0);
break;
case 3: // -> Sleep
nNextState = 3;
// 16.05.98 cg, bugfix, wait until thread is down, then resume
while (ResumeThread(hThread)==0) Sleep(0);
// ResumeThread(hThread);
SetEvent(hEventShutdn);
while (nState!=nNextState) Sleep(0);
UpdateWindowStatus();
break;
@ -245,29 +238,20 @@ UINT SwitchToState(UINT nNewState)
case 0: // -> Run
nNextState = 0;
if (Chipset.Shutdn) bInterrupt=TRUE;
// 16.05.98 cg, bugfix, wait until thread is down, then resume
while (ResumeThread(hThread)==0) Sleep(0);
// ResumeThread(hThread);
//while (nState!=nNextState) Sleep(0);
SetEvent(hEventShutdn);
break;
case 1: // -> Invalid
nNextState = 1;
// 16.05.98 cg, bugfix, wait until thread is down, then resume
while (ResumeThread(hThread)==0) Sleep(0);
// ResumeThread(hThread);
SetEvent(hEventShutdn);
while (nState!=nNextState) Sleep(0);
UpdateWindowStatus();
break;
case 2: // -> Return
nNextState = 1;
// 16.05.98 cg, bugfix, wait until thread is down, then resume
while (ResumeThread(hThread)==0) Sleep(0);
// ResumeThread(hThread);
SetEvent(hEventShutdn);
while (nState!=nNextState) Sleep(0);
nNextState = 2;
// 16.05.98 cg, bugfix, wait until thread is down, then resume
while (ResumeThread(hThread)==0) Sleep(0);
// ResumeThread(hThread);
SetEvent(hEventShutdn);
while (nState!=nNextState) Sleep(0);
UpdateWindowStatus();
break;
@ -279,82 +263,140 @@ UINT SwitchToState(UINT nNewState)
UINT WorkerThread(LPVOID pParam)
{
LARGE_INTEGER lDummyInt; // 23.04.98 cg, new, sample timer ticks
QueryPerformanceFrequency(&lDummyInt); // 23.04.98 cg, new, init timer ticks
lDummyInt.QuadPart /= SAMPLE; // 23.04.98 cg, new, calculate sample ticks
dwTickRef = lDummyInt.LowPart; // 23.04.98 cg, new, sample timer ticks
_ASSERT(dwTickRef); // 23.04.98 cg, new, tick resolution error
LARGE_INTEGER lDummyInt; // sample timer ticks
QueryPerformanceFrequency(&lDummyInt); // init timer ticks
lDummyInt.QuadPart /= SAMPLE; // calculate sample ticks
dwTickRef = lDummyInt.LowPart; // sample timer ticks
_ASSERT(dwTickRef); // tick resolution error
loop:
while (nNextState == 1) // go into invalid state
{
CommClose(); // 17.05.98 cg, new, close COM port
bCommInit = FALSE; // 17.05.98 cg, new, COM port not open
CommClose(); // close COM port
bCommInit = FALSE; // COM port not open
nState = 1; // in invalid state
SuspendThread(hThread); // sleep thread
WaitForSingleObject(hEventShutdn,INFINITE);
if (nNextState == 2) // go into return state
{
nState = 2; // in return state
return 0; // kill thread
}
ioc_acc = TRUE; // 17.05.98 cg, new, test if UART on
ioc_acc = TRUE; // test if UART on
}
while (nNextState == 0)
{
if (nState!=0)
{
nState = 0;
if (Chipset.type == 'S')
// clear port2 status bits
Chipset.cards_status &= ~(PORT2_PRESENT | PORT2_WRITE);
if (pbyPort2 || Chipset.Port2) // card plugged in port2
{
Chipset.cards_status &= 0x5;
if (pbyPort2) Chipset.cards_status |= 0x2;
if (bPort2Writeable) Chipset.cards_status |= 0x8;
}
else
{
Chipset.cards_status &= 0xA;
if (pbyPort2) Chipset.cards_status |= 0x1;
if (bPort2Writeable) Chipset.cards_status |= 0x4;
Chipset.cards_status |= PORT2_PRESENT;
if (bPort2Writeable) // is card writeable
Chipset.cards_status |= PORT2_WRITE;
}
RomSwitch(Chipset.Bank_FF); // select HP49G ROM bank and update memory mapping
UpdateDisplayPointers();
UpdateMainDisplay();
UpdateMenuDisplay();
UpdateAnnunciators();
// 23.04.98 cg, new, init speed reference
dwOldCyc = Chipset.cycles;
// init speed reference
// 22.11.99 cg, changed, DWORD casting
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
QueryPerformanceCounter(&lDummyInt);
dwSpeedRef = lDummyInt.LowPart;
// 23.04.98 cg, end of init
SetHP48Time(); // update HP48 time & date
StartTimers();
}
PCHANGED;
while (!bInterrupt)
{
do
{
LPBYTE I = FASTPTR(w.pc);
#include "Fetch.h"
#include "Opcodes.h"
}
while(0); // 23.04.98 cg, workaround for continue
LPBYTE I = FASTPTR(Chipset.pc);
CheckSerial(); // 17.05.98 cg, serial support
AdjustSpeed(); // 23.04.98 cg, adjust emulation speed
}
if (Chipset.Shutdn)
if (bDbgEnable) // debugger active
{
bInterrupt = FALSE;
SuspendThread(hThread);
BOOL bStopEmulation;
// 13.11.99 cg, changed, check for step into
bStopEmulation = (nDbgState == DBG_STEPINTO);
// check for step over
bStopEmulation |= (nDbgState == DBG_STEPOVER) && dwDbgRstkp == Chipset.rstkp;
// 13.11.99 cg, new, check for step out, something was popped from hardware stack
if (nDbgState == DBG_STEPOUT && dwDbgRstkp == Chipset.rstkp)
{
_ASSERT(bStopEmulation == FALSE);
if ((bStopEmulation = (Chipset.pc == dwDbgRstk)) == FALSE)
{
// it was C=RSTK, check for next object popped from hardware stack
dwDbgRstkp = (Chipset.rstkp-1)&7;
dwDbgRstk = Chipset.rstk[dwDbgRstkp];
}
}
// 13.11.99 cg, end of step out implementation
// check for breakpoints
bStopEmulation |= CheckBreakpoint(Chipset.pc);
// NOP3, opcode #420 (GOC)
if (bDbgNOP3 && I[0] == 0x4 && I[1] == 0x2 && I[2] == 0x0)
bStopEmulation = TRUE;
if (bStopEmulation) // stop condition
{
StopTimers(); // hold timer values when emulator is stopped
OutputDebugString("Emulator stopped...\n");
NotifyDebugger(); // 10.11.99 cg, changed, update registers
WaitForSingleObject(hEventDebug,INFINITE);
OutputDebugString("Emulator running...\n");
// @todo add timer emulation
StartTimers(); // continue timers
Chipset.Shutdn = FALSE;
// 23.04.98 cg, new, init speed reference
dwOldCyc = Chipset.cycles;
Chipset.bShutdnWake = FALSE;
// init slow down part
// 22.11.99 cg, changed, DWORD casting
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
QueryPerformanceCounter(&lDummyInt);
dwSpeedRef = lDummyInt.LowPart;
// 23.04.98 cg, end of init
}
}
EvalOpcode(I);
CheckDisp(!Chipset.Shutdn); // check for display update
CheckSerial(); // serial support
AdjustSpeed(); // adjust emulation speed
}
bInterrupt = FALSE; // be sure to reenter opcode loop
// enter SHUTDN handler only in RUN mode
if (Chipset.Shutdn && !(nDbgState == DBG_STEPINTO || nDbgState == DBG_STEPOVER))
{
WaitForSingleObject(hEventShutdn,INFINITE);
if (Chipset.bShutdnWake) // waked up by timer, keyboard or serial
{
Chipset.bShutdnWake = FALSE;
Chipset.Shutdn = FALSE;
// init speed reference
// 22.11.99 cg, changed, DWORD casting
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
QueryPerformanceCounter(&lDummyInt);
dwSpeedRef = lDummyInt.LowPart;
}
}
if (Chipset.SoftInt)
{
bInterrupt = FALSE;
Chipset.SoftInt = FALSE;
if (Chipset.inte)
{
@ -372,7 +414,7 @@ loop:
while (nNextState == 3) // go into sleep state
{
nState = 3; // in sleep state
SuspendThread(hThread); // sleep thread
WaitForSingleObject(hEventShutdn,INFINITE);
}
goto loop;
UNREFERENCED_PARAMETER(pParam);

View file

@ -9,8 +9,20 @@
#include "pch.h"
#include "Emu48.h"
// 02.02.98 cg, new, memory address for flags -53 to -56
#define SFLAG53_56 ((cCurrentRomType=='S')?0x706D2:0x80850)
//| 38G | 48SX | 48GX | 49G | Name
//#F0E4F #706D2 #80850 #80F0F =SFLAG53_56
// memory address for flags -53 to -56
#define SFLAG53_56 ( (cCurrentRomType=='A') \
? 0xF0E4F \
: ( (cCurrentRomType!='X') \
? ( (cCurrentRomType=='S') \
? 0x706D2 \
: 0x80850 \
) \
: 0x80F0F \
) \
)
static __inline VOID Return(CHIPSET* w)
{
@ -20,12 +32,8 @@ static __inline VOID Return(CHIPSET* w)
return;
}
VOID External(CHIPSET* w)
VOID External(CHIPSET* w) // Beep patch
{
if (w->pc==0x017A6) // Beep
{
// begin with patch
// 02.02.98 cg, changed for better emulation
BYTE fbeep;
DWORD freq,dur;
@ -33,32 +41,25 @@ VOID External(CHIPSET* w)
dur = Npack(w->C,5); // duration in ms
Nread(&fbeep,SFLAG53_56,1); // fetch system flags -53 to -56
w->carry = TRUE; // 22.07.98 cg, setting of no beep
w->carry = TRUE; // setting of no beep
if (!(fbeep & 0x8) && freq) // bit -56 clear and frequency > 0 Hz
{
if (freq < 37) freq = 37; // low limit of freqency (NT)
if (freq > 4400) freq = 4400; // 22.07.98 cg, high limit of HP (SX)
if (freq > 4400) freq = 4400; // high limit of HP (SX)
if (dur > 1048575) // 22.07.98 cg, high limit of HP (SX)
if (dur > 1048575) // high limit of HP (SX)
dur = 1048575;
Beep(freq,dur); // NT: ok, Windows 95: default sound or standard system beep
// 22.07.98 cg, estimate cpu cycles for beeping time (2MHz / 4MHz)
// estimate cpu cycles for beeping time (2MHz / 4MHz)
w->cycles += dur * ((cCurrentRomType=='S') ? 2000 : 4000);
// original routine return with...
w->P = 0; // 22.07.98 cg, P=0
w->intk = TRUE; // 22.07.98 cg, INTON
w->carry = FALSE; // 22.07.98 cg, RTNCC
w->P = 0; // P=0
w->intk = TRUE; // INTON
w->carry = FALSE; // RTNCC
}
// MessageBeep(0xFFFFFFFF); // original, replaced
// continue with original part
//Beep(600,50);
Return(w);
return;
}
w->pc +=4;
return;
}

View file

@ -1,442 +0,0 @@
# Microsoft Developer Studio Generated NMAKE File, Format Version 40001
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
!IF "$(CFG)" == ""
CFG=Emu48 - Win32 Debug
!MESSAGE No configuration specified. Defaulting to Emu48 - Win32 Debug.
!ENDIF
!IF "$(CFG)" != "Emu48 - Win32 Release" && "$(CFG)" != "Emu48 - Win32 Debug"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE on this makefile
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "Emu48.mak" CFG="Emu48 - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "Emu48 - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "Emu48 - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE
!ERROR An invalid configuration is specified.
!ENDIF
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
################################################################################
# Begin Project
RSC=rc.exe
CPP=cl.exe
MTL=mktyplib.exe
!IF "$(CFG)" == "Emu48 - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
OUTDIR=.\Release
INTDIR=.\Release
ALL : "$(OUTDIR)\Emu48.exe"
CLEAN :
-@erase ".\Release\Emu48.exe"
-@erase ".\Release\timer.obj"
-@erase ".\Release\Emu48.pch"
-@erase ".\Release\rpl.obj"
-@erase ".\Release\pch.obj"
-@erase ".\Release\mops.obj"
-@erase ".\Release\kml.obj"
-@erase ".\Release\keyboard.obj"
-@erase ".\Release\files.obj"
-@erase ".\Release\external.obj"
-@erase ".\Release\engine.obj"
-@erase ".\Release\Emu48.obj"
-@erase ".\Release\display.obj"
-@erase ".\Release\Emu48.res"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"pch.h" /c
CPP_PROJ=/nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
/Fp"$(INTDIR)/Emu48.pch" /Yu"pch.h" /Fo"$(INTDIR)/" /c
CPP_OBJS=.\Release/
CPP_SBRS=
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /win32
MTL_PROJ=/nologo /D "NDEBUG" /win32
# ADD BASE RSC /l 0x40c /d "NDEBUG"
# ADD RSC /l 0x40c /d "NDEBUG"
RSC_PROJ=/l 0x40c /fo"$(INTDIR)/Emu48.res" /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
BSC32_FLAGS=/nologo /o"$(OUTDIR)/Emu48.bsc"
BSC32_SBRS=
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 winmm.lib /nologo /subsystem:windows /machine:I386
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib /nologo\
/subsystem:windows /incremental:no /pdb:"$(OUTDIR)/Emu48.pdb" /machine:I386\
/out:"$(OUTDIR)/Emu48.exe"
LINK32_OBJS= \
"$(INTDIR)/timer.obj" \
"$(INTDIR)/rpl.obj" \
"$(INTDIR)/pch.obj" \
"$(INTDIR)/mops.obj" \
"$(INTDIR)/kml.obj" \
"$(INTDIR)/keyboard.obj" \
"$(INTDIR)/files.obj" \
"$(INTDIR)/external.obj" \
"$(INTDIR)/engine.obj" \
"$(INTDIR)/Emu48.obj" \
"$(INTDIR)/display.obj" \
"$(INTDIR)/Emu48.res"
"$(OUTDIR)\Emu48.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "Emu48 - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
OUTDIR=.\Debug
INTDIR=.\Debug
ALL : "$(OUTDIR)\Emu48.exe"
CLEAN :
-@erase ".\Debug\Emu48.exe"
-@erase ".\Debug\timer.obj"
-@erase ".\Debug\Emu48.pch"
-@erase ".\Debug\rpl.obj"
-@erase ".\Debug\pch.obj"
-@erase ".\Debug\mops.obj"
-@erase ".\Debug\kml.obj"
-@erase ".\Debug\keyboard.obj"
-@erase ".\Debug\files.obj"
-@erase ".\Debug\external.obj"
-@erase ".\Debug\engine.obj"
-@erase ".\Debug\Emu48.obj"
-@erase ".\Debug\display.obj"
-@erase ".\Debug\Emu48.res"
-@erase ".\Debug\Emu48.ilk"
-@erase ".\Debug\Emu48.pdb"
-@erase ".\Debug\vc40.pdb"
-@erase ".\Debug\vc40.idb"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /Zp8 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"pch.h" /c
CPP_PROJ=/nologo /Zp8 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D\
"_WINDOWS" /Fp"$(INTDIR)/Emu48.pch" /Yu"pch.h" /Fo"$(INTDIR)/" /Fd"$(INTDIR)/"\
/c
CPP_OBJS=.\Debug/
CPP_SBRS=
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /win32
MTL_PROJ=/nologo /D "_DEBUG" /win32
# ADD BASE RSC /l 0x40c /d "_DEBUG"
# ADD RSC /l 0x40c /d "_DEBUG"
RSC_PROJ=/l 0x40c /fo"$(INTDIR)/Emu48.res" /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
BSC32_FLAGS=/nologo /o"$(OUTDIR)/Emu48.bsc"
BSC32_SBRS=
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 winmm.lib /nologo /subsystem:windows /debug /machine:I386
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib /nologo\
/subsystem:windows /incremental:yes /pdb:"$(OUTDIR)/Emu48.pdb" /debug\
/machine:I386 /out:"$(OUTDIR)/Emu48.exe"
LINK32_OBJS= \
"$(INTDIR)/timer.obj" \
"$(INTDIR)/rpl.obj" \
"$(INTDIR)/pch.obj" \
"$(INTDIR)/mops.obj" \
"$(INTDIR)/kml.obj" \
"$(INTDIR)/keyboard.obj" \
"$(INTDIR)/files.obj" \
"$(INTDIR)/external.obj" \
"$(INTDIR)/engine.obj" \
"$(INTDIR)/Emu48.obj" \
"$(INTDIR)/display.obj" \
"$(INTDIR)/Emu48.res"
"$(OUTDIR)\Emu48.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ENDIF
.c{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
.cpp{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
.cxx{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
.c{$(CPP_SBRS)}.sbr:
$(CPP) $(CPP_PROJ) $<
.cpp{$(CPP_SBRS)}.sbr:
$(CPP) $(CPP_PROJ) $<
.cxx{$(CPP_SBRS)}.sbr:
$(CPP) $(CPP_PROJ) $<
################################################################################
# Begin Target
# Name "Emu48 - Win32 Release"
# Name "Emu48 - Win32 Debug"
!IF "$(CFG)" == "Emu48 - Win32 Release"
!ELSEIF "$(CFG)" == "Emu48 - Win32 Debug"
!ENDIF
################################################################################
# Begin Source File
SOURCE=.\timer.c
DEP_CPP_TIMER=\
".\pch.h"\
".\Emu48.h"\
".\types.h"\
"$(INTDIR)\timer.obj" : $(SOURCE) $(DEP_CPP_TIMER) "$(INTDIR)"\
"$(INTDIR)\Emu48.pch"
# End Source File
################################################################################
# Begin Source File
SOURCE=.\rpl.c
DEP_CPP_RPL_C=\
".\pch.h"\
".\Emu48.h"\
".\types.h"\
"$(INTDIR)\rpl.obj" : $(SOURCE) $(DEP_CPP_RPL_C) "$(INTDIR)"\
"$(INTDIR)\Emu48.pch"
# End Source File
################################################################################
# Begin Source File
SOURCE=.\pch.c
DEP_CPP_PCH_C=\
".\pch.h"\
!IF "$(CFG)" == "Emu48 - Win32 Release"
# ADD CPP /Yc"pch.h"
BuildCmds= \
$(CPP) /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\
/Fp"$(INTDIR)/Emu48.pch" /Yc"pch.h" /Fo"$(INTDIR)/" /c $(SOURCE) \
"$(INTDIR)\pch.obj" : $(SOURCE) $(DEP_CPP_PCH_C) "$(INTDIR)"
$(BuildCmds)
"$(INTDIR)\Emu48.pch" : $(SOURCE) $(DEP_CPP_PCH_C) "$(INTDIR)"
$(BuildCmds)
!ELSEIF "$(CFG)" == "Emu48 - Win32 Debug"
# ADD CPP /Yc"pch.h"
BuildCmds= \
$(CPP) /nologo /Zp8 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D\
"_WINDOWS" /Fp"$(INTDIR)/Emu48.pch" /Yc"pch.h" /Fo"$(INTDIR)/" /Fd"$(INTDIR)/"\
/c $(SOURCE) \
"$(INTDIR)\pch.obj" : $(SOURCE) $(DEP_CPP_PCH_C) "$(INTDIR)"
$(BuildCmds)
"$(INTDIR)\Emu48.pch" : $(SOURCE) $(DEP_CPP_PCH_C) "$(INTDIR)"
$(BuildCmds)
!ENDIF
# End Source File
################################################################################
# Begin Source File
SOURCE=.\mops.c
DEP_CPP_MOPS_=\
".\pch.h"\
".\Emu48.h"\
".\types.h"\
"$(INTDIR)\mops.obj" : $(SOURCE) $(DEP_CPP_MOPS_) "$(INTDIR)"\
"$(INTDIR)\Emu48.pch"
# End Source File
################################################################################
# Begin Source File
SOURCE=.\kml.c
DEP_CPP_KML_C=\
".\pch.h"\
".\Emu48.h"\
".\kml.h"\
".\types.h"\
"$(INTDIR)\kml.obj" : $(SOURCE) $(DEP_CPP_KML_C) "$(INTDIR)"\
"$(INTDIR)\Emu48.pch"
# End Source File
################################################################################
# Begin Source File
SOURCE=.\keyboard.c
DEP_CPP_KEYBO=\
".\pch.h"\
".\Emu48.h"\
".\types.h"\
"$(INTDIR)\keyboard.obj" : $(SOURCE) $(DEP_CPP_KEYBO) "$(INTDIR)"\
"$(INTDIR)\Emu48.pch"
# End Source File
################################################################################
# Begin Source File
SOURCE=.\files.c
DEP_CPP_FILES=\
".\pch.h"\
".\Emu48.h"\
".\kml.h"\
".\types.h"\
"$(INTDIR)\files.obj" : $(SOURCE) $(DEP_CPP_FILES) "$(INTDIR)"\
"$(INTDIR)\Emu48.pch"
# End Source File
################################################################################
# Begin Source File
SOURCE=.\external.c
DEP_CPP_EXTER=\
".\pch.h"\
".\Emu48.h"\
".\types.h"\
"$(INTDIR)\external.obj" : $(SOURCE) $(DEP_CPP_EXTER) "$(INTDIR)"\
"$(INTDIR)\Emu48.pch"
# End Source File
################################################################################
# Begin Source File
SOURCE=.\engine.c
DEP_CPP_ENGIN=\
".\pch.h"\
".\Emu48.h"\
".\Ops.h"\
".\types.h"\
"$(INTDIR)\engine.obj" : $(SOURCE) $(DEP_CPP_ENGIN) "$(INTDIR)"\
"$(INTDIR)\Emu48.pch"
# End Source File
################################################################################
# Begin Source File
SOURCE=.\Emu48.c
DEP_CPP_EMU48=\
".\pch.h"\
".\Emu48.h"\
".\kml.h"\
".\types.h"\
"$(INTDIR)\Emu48.obj" : $(SOURCE) $(DEP_CPP_EMU48) "$(INTDIR)"\
"$(INTDIR)\Emu48.pch"
# End Source File
################################################################################
# Begin Source File
SOURCE=.\display.c
DEP_CPP_DISPL=\
".\pch.h"\
".\Emu48.h"\
".\kml.h"\
".\types.h"\
"$(INTDIR)\display.obj" : $(SOURCE) $(DEP_CPP_DISPL) "$(INTDIR)"\
"$(INTDIR)\Emu48.pch"
# End Source File
################################################################################
# Begin Source File
SOURCE=.\Emu48.rc
DEP_RSC_EMU48_=\
".\Emu48.ico"\
"$(INTDIR)\Emu48.res" : $(SOURCE) $(DEP_RSC_EMU48_) "$(INTDIR)"
$(RSC) $(RSC_PROJ) $(SOURCE)
# End Source File
# End Target
# End Project
################################################################################

Binary file not shown.

777
sources/Emu48/FETCH.C Normal file
View file

@ -0,0 +1,777 @@
/*
* fetch.c
*
* This file is part of Emu48
*
* Copyright (C) 1999 Christoph Gießelink
*
*/
#include "pch.h"
#include "Opcodes.h"
#define F 0xFF // F = function
typedef struct
{
const VOID *pLnk;
const DWORD dwTyp;
} JMPTAB;
// jump tables
static const JMPTAB oF_[] =
{
oF0, F,
oF1, F,
oF2, F,
oF3, F,
oF4, F,
oF5, F,
oF6, F,
oF7, F,
oF8, F,
oF9, F,
oFA, F,
oFB, F,
oFC, F,
oFD, F,
oFE, F,
oFF, F
};
static const JMPTAB oE_[] =
{
oE0, F,
oE1, F,
oE2, F,
oE3, F,
oE4, F,
oE5, F,
oE6, F,
oE7, F,
oE8, F,
oE9, F,
oEA, F,
oEB, F,
oEC, F,
oED, F,
oEE, F,
oEF, F
};
static const JMPTAB oD_[] =
{
oD0, F,
oD1, F,
oD2, F,
oD3, F,
oD4, F,
oD5, F,
oD6, F,
oD7, F,
oD8, F,
oD9, F,
oDA, F,
oDB, F,
oDC, F,
oDD, F,
oDE, F,
oDF, F
};
static const JMPTAB oC_[] =
{
oC0, F,
oC1, F,
oC2, F,
oC3, F,
oC4, F,
oC5, F,
oC6, F,
oC7, F,
oC8, F,
oC9, F,
oCA, F,
oCB, F,
oCC, F,
oCD, F,
oCE, F,
oCF, F
};
static const JMPTAB oBb_[] =
{
oBb0, F,
oBb1, F,
oBb2, F,
oBb3, F,
oBb4, F,
oBb5, F,
oBb6, F,
oBb7, F,
oBb8, F,
oBb9, F,
oBbA, F,
oBbB, F,
oBbC, F,
oBbD, F,
oBbE, F,
oBbF, F
};
static const JMPTAB oBa_[] =
{
oBa0, F,
oBa1, F,
oBa2, F,
oBa3, F,
oBa4, F,
oBa5, F,
oBa6, F,
oBa7, F,
oBa8, F,
oBa9, F,
oBaA, F,
oBaB, F,
oBaC, F,
oBaD, F,
oBaE, F,
oBaF, F
};
static const JMPTAB oB_[] =
{
oBa_, 2,
oBa_, 2,
oBa_, 2,
oBa_, 2,
oBa_, 2,
oBa_, 2,
oBa_, 2,
oBa_, 2,
oBb_, 2,
oBb_, 2,
oBb_, 2,
oBb_, 2,
oBb_, 2,
oBb_, 2,
oBb_, 2,
oBb_, 2
};
static const JMPTAB oAb_[] =
{
oAb0, F,
oAb1, F,
oAb2, F,
oAb3, F,
oAb4, F,
oAb5, F,
oAb6, F,
oAb7, F,
oAb8, F,
oAb9, F,
oAbA, F,
oAbB, F,
oAbC, F,
oAbD, F,
oAbE, F,
oAbF, F
};
static const JMPTAB oAa_[] =
{
oAa0, F,
oAa1, F,
oAa2, F,
oAa3, F,
oAa4, F,
oAa5, F,
oAa6, F,
oAa7, F,
oAa8, F,
oAa9, F,
oAaA, F,
oAaB, F,
oAaC, F,
oAaD, F,
oAaE, F,
oAaF, F
};
static const JMPTAB oA_[] =
{
oAa_, 2,
oAa_, 2,
oAa_, 2,
oAa_, 2,
oAa_, 2,
oAa_, 2,
oAa_, 2,
oAa_, 2,
oAb_, 2,
oAb_, 2,
oAb_, 2,
oAb_, 2,
oAb_, 2,
oAb_, 2,
oAb_, 2,
oAb_, 2
};
static const JMPTAB o9b_[] =
{
o9b0, F,
o9b1, F,
o9b2, F,
o9b3, F,
o9b4, F,
o9b5, F,
o9b6, F,
o9b7, F,
o9b8, F,
o9b9, F,
o9bA, F,
o9bB, F,
o9bC, F,
o9bD, F,
o9bE, F,
o9bF, F
};
static const JMPTAB o9a_[] =
{
o9a0, F,
o9a1, F,
o9a2, F,
o9a3, F,
o9a4, F,
o9a5, F,
o9a6, F,
o9a7, F,
o9a8, F,
o9a9, F,
o9aA, F,
o9aB, F,
o9aC, F,
o9aD, F,
o9aE, F,
o9aF, F
};
static const JMPTAB o9_[] =
{
o9a_, 2,
o9a_, 2,
o9a_, 2,
o9a_, 2,
o9a_, 2,
o9a_, 2,
o9a_, 2,
o9a_, 2,
o9b_, 2,
o9b_, 2,
o9b_, 2,
o9b_, 2,
o9b_, 2,
o9b_, 2,
o9b_, 2,
o9b_, 2
};
static const JMPTAB o8B_[] =
{
o8B0, F,
o8B1, F,
o8B2, F,
o8B3, F,
o8B4, F,
o8B5, F,
o8B6, F,
o8B7, F,
o8B8, F,
o8B9, F,
o8BA, F,
o8BB, F,
o8BC, F,
o8BD, F,
o8BE, F,
o8BF, F
};
static const JMPTAB o8A_[] =
{
o8A0, F,
o8A1, F,
o8A2, F,
o8A3, F,
o8A4, F,
o8A5, F,
o8A6, F,
o8A7, F,
o8A8, F,
o8A9, F,
o8AA, F,
o8AB, F,
o8AC, F,
o8AD, F,
o8AE, F,
o8AF, F
};
static const JMPTAB o81B_[] =
{
o_invalid4, F,
o81B1, F,
o81B2, F,
o81B3, F,
o81B4, F,
o81B5, F,
o81B6, F,
o81B7, F,
o_invalid4, F,
o_invalid4, F,
o_invalid4, F,
o_invalid4, F,
o_invalid4, F,
o_invalid4, F,
o_invalid4, F,
o_invalid4, F
};
static const JMPTAB o81Af2_[] =
{
o81Af20, F,
o81Af21, F,
o81Af22, F,
o81Af23, F,
o81Af24, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o81Af28, F,
o81Af29, F,
o81Af2A, F,
o81Af2B, F,
o81Af2C, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F
};
static const JMPTAB o81Af1_[] =
{
o81Af10, F,
o81Af11, F,
o81Af12, F,
o81Af13, F,
o81Af14, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o81Af18, F,
o81Af19, F,
o81Af1A, F,
o81Af1B, F,
o81Af1C, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F
};
static const JMPTAB o81Af0_[] =
{
o81Af00, F,
o81Af01, F,
o81Af02, F,
o81Af03, F,
o81Af04, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o81Af08, F,
o81Af09, F,
o81Af0A, F,
o81Af0B, F,
o81Af0C, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F
};
static const JMPTAB o81A_[] =
{
o81Af0_, 5,
o81Af1_, 5,
o81Af2_, 5,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F
};
static const JMPTAB o819_[] =
{
o819f0, F,
o819f1, F,
o819f2, F,
o819f3, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F
};
static const JMPTAB o818_[] =
{
o818f0x, F,
o818f1x, F,
o818f2x, F,
o818f3x, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o818f8x, F,
o818f9x, F,
o818fAx, F,
o818fBx, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F,
o_invalid6, F
};
static const JMPTAB o81_[] =
{
o810, F,
o811, F,
o812, F,
o813, F,
o814, F,
o815, F,
o816, F,
o817, F,
o818_, 4,
o819_, 4,
o81A_, 4,
o81B_, 3,
o81C, F,
o81D, F,
o81E, F,
o81F, F
};
static const JMPTAB o8081_[] =
{
o80810, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F,
o_invalid5, F
};
static const JMPTAB o808_[] =
{
o8080, F,
o8081_, 4,
o8082X, F,
o8083, F,
o8084n, F,
o8085n, F,
o8086n, F,
o8087n, F,
o8088n, F,
o8089n, F,
o808An, F,
o808Bn, F,
o808C, F,
o808D, F,
o808E, F,
o808F, F
};
static const JMPTAB o80_[] =
{
o800, F,
o801, F,
o802, F,
o803, F,
o804, F,
o805, F,
o806, F,
o807, F,
o808_, 3,
o809, F,
o80A, F,
o80B, F,
o80Cn, F,
o80Dn, F,
o80E, F,
o80Fn, F
};
static const JMPTAB o8_[] =
{
o80_, 2,
o81_, 2,
o82n, F,
o83n, F,
o84n, F,
o85n, F,
o86n, F,
o87n, F,
o88n, F,
o89n, F,
o8A_, 2,
o8B_, 2,
o8Cd4, F,
o8Dd5, F,
o8Ed4, F,
o8Fd5, F
};
static const JMPTAB o15_[] =
{
o150a, F,
o151a, F,
o152a, F,
o153a, F,
o154a, F,
o155a, F,
o156a, F,
o157a, F,
o158x, F,
o159x, F,
o15Ax, F,
o15Bx, F,
o15Cx, F,
o15Dx, F,
o15Ex, F,
o15Fx, F
};
static const JMPTAB o14_[] =
{
o140, F,
o141, F,
o142, F,
o143, F,
o144, F,
o145, F,
o146, F,
o147, F,
o148, F,
o149, F,
o14A, F,
o14B, F,
o14C, F,
o14D, F,
o14E, F,
o14F, F
};
static const JMPTAB o13_[] =
{
o130, F,
o131, F,
o132, F,
o133, F,
o134, F,
o135, F,
o136, F,
o137, F,
o138, F,
o139, F,
o13A, F,
o13B, F,
o13C, F,
o13D, F,
o13E, F,
o13F, F
};
static const JMPTAB o12_[] =
{
o120, F,
o121, F,
o122, F,
o123, F,
o124, F,
o_invalid3, F,
o_invalid3, F,
o_invalid3, F,
o128, F,
o129, F,
o12A, F,
o12B, F,
o12C, F,
o_invalid3, F,
o_invalid3, F,
o_invalid3, F
};
static const JMPTAB o11_[] =
{
o110, F,
o111, F,
o112, F,
o113, F,
o114, F,
o_invalid3, F,
o_invalid3, F,
o_invalid3, F,
o118, F,
o119, F,
o11A, F,
o11B, F,
o11C, F,
o_invalid3, F,
o_invalid3, F,
o_invalid3, F
};
static const JMPTAB o10_[] =
{
o100, F,
o101, F,
o102, F,
o103, F,
o104, F,
o_invalid3, F,
o_invalid3, F,
o_invalid3, F,
o108, F,
o109, F,
o10A, F,
o10B, F,
o10C, F,
o_invalid3, F,
o_invalid3, F,
o_invalid3, F
};
static const JMPTAB o1_[] =
{
o10_, 2,
o11_, 2,
o12_, 2,
o13_, 2,
o14_, 2,
o15_, 2,
o16x, F,
o17x, F,
o18x, F,
o19d2, F,
o1Ad4, F,
o1Bd5, F,
o1Cx, F,
o1Dd2, F,
o1Ed4, F,
o1Fd5, F
};
static const JMPTAB o0E_[] =
{
o0Ef0, F,
o0Ef1, F,
o0Ef2, F,
o0Ef3, F,
o0Ef4, F,
o0Ef5, F,
o0Ef6, F,
o0Ef7, F,
o0Ef8, F,
o0Ef9, F,
o0EfA, F,
o0EfB, F,
o0EfC, F,
o0EfD, F,
o0EfE, F,
o0EfF, F
};
static const JMPTAB o0_[] =
{
o00, F,
o01, F,
o02, F,
o03, F,
o04, F,
o05, F,
o06, F,
o07, F,
o08, F,
o09, F,
o0A, F,
o0B, F,
o0C, F,
o0D, F,
o0E_, 3,
o0F, F
};
static const JMPTAB o_[] =
{
o0_, 1,
o1_, 1,
o2n, F,
o3X, F,
o4d2, F,
o5d2, F,
o6d3, F,
o7d3, F,
o8_, 1,
o9_, 1,
oA_, 1,
oB_, 1,
oC_, 1,
oD_, 1,
oE_, 1,
oF_, 1
};
// opcode dispatcher
VOID EvalOpcode(LPBYTE I)
{
DWORD dwTemp,dwIndex = 0;
JMPTAB const *pJmpTab = o_;
do
{
dwTemp = I[dwIndex]; // table entry
dwIndex = pJmpTab[dwTemp].dwTyp; // next pointer type
pJmpTab = pJmpTab[dwTemp].pLnk; // next pointer to table/function
}
while (dwIndex != F); // reference to table? -> again
((VOID (*)(LPBYTE)) pJmpTab)(I); // call function
return;
}

View file

@ -1,675 +0,0 @@
/*
* fetch.h
*
* This file is part of Emu48
*
* Copyright (C) 1995 Sebastien Carlier
*
*/
switch(I[0])
{
case 0x0: goto o0_;
case 0x1: goto o1_;
case 0x2: goto o2n;
case 0x3: goto o3X;
case 0x4: goto o4d2;
case 0x5: goto o5d2;
case 0x6: goto o6d3;
case 0x7: goto o7d3;
case 0x8: goto o8_;
case 0x9: goto o9_;
case 0xA: goto oA_;
case 0xB: goto oB_;
case 0xC: goto oC_;
case 0xD: goto oD_;
case 0xE: goto oE_;
case 0xF: goto oF_;
default : goto o_invalid;
}
o0_:
switch(I[1])
{
case 0x0: goto o00;
case 0x1: goto o01;
case 0x2: goto o02;
case 0x3: goto o03;
case 0x4: goto o04;
case 0x5: goto o05;
case 0x6: goto o06;
case 0x7: goto o07;
case 0x8: goto o08;
case 0x9: goto o09;
case 0xA: goto o0A;
case 0xB: goto o0B;
case 0xC: goto o0C;
case 0xD: goto o0D;
case 0xE: goto o0E_;
case 0xF: goto o0F;
default : goto o_invalid;
}
o0E_:
switch(I[3])
{
case 0x0: goto o0Ef0;
case 0x1: goto o0Ef1;
case 0x2: goto o0Ef2;
case 0x3: goto o0Ef3;
case 0x4: goto o0Ef4;
case 0x5: goto o0Ef5;
case 0x6: goto o0Ef6;
case 0x7: goto o0Ef7;
case 0x8: goto o0Ef8;
case 0x9: goto o0Ef9;
case 0xA: goto o0EfA;
case 0xB: goto o0EfB;
case 0xC: goto o0EfC;
case 0xD: goto o0EfD;
case 0xE: goto o0EfE;
case 0xF: goto o0EfF;
default : goto o_invalid;
}
o1_:
switch(I[1])
{
case 0x0: goto o10_;
case 0x1: goto o11_;
case 0x2: goto o12_;
case 0x3: goto o13_;
case 0x4: goto o14_;
case 0x5: goto o15_;
case 0x6: goto o16x;
case 0x7: goto o17x;
case 0x8: goto o18x;
case 0x9: goto o19d2;
case 0xA: goto o1Ad4;
case 0xB: goto o1Bd5;
case 0xC: goto o1Cx;
case 0xD: goto o1Dd2;
case 0xE: goto o1Ed4;
case 0xF: goto o1Fd5;
default : goto o_invalid;
}
o10_:
switch(I[2])
{
case 0x0: goto o100;
case 0x1: goto o101;
case 0x2: goto o102;
case 0x3: goto o103;
case 0x4: goto o104;
case 0x8: goto o108;
case 0x9: goto o109;
case 0xA: goto o10A;
case 0xB: goto o10B;
case 0xC: goto o10C;
default : goto o_invalid3;
}
o11_:
switch(I[2])
{
case 0x0: goto o110;
case 0x1: goto o111;
case 0x2: goto o112;
case 0x3: goto o113;
case 0x4: goto o114;
case 0x8: goto o118;
case 0x9: goto o119;
case 0xA: goto o11A;
case 0xB: goto o11B;
case 0xC: goto o11C;
default : goto o_invalid3;
}
o12_:
switch(I[2])
{
case 0x0: goto o120;
case 0x1: goto o121;
case 0x2: goto o122;
case 0x3: goto o123;
case 0x4: goto o124;
case 0x8: goto o128;
case 0x9: goto o129;
case 0xA: goto o12A;
case 0xB: goto o12B;
case 0xC: goto o12C;
default : goto o_invalid3;
}
o13_:
switch(I[2])
{
case 0x0: goto o130;
case 0x1: goto o131;
case 0x2: goto o132;
case 0x3: goto o133;
case 0x4: goto o134;
case 0x5: goto o135;
case 0x6: goto o136;
case 0x7: goto o137;
case 0x8: goto o138;
case 0x9: goto o139;
case 0xA: goto o13A;
case 0xB: goto o13B;
case 0xC: goto o13C;
case 0xD: goto o13D;
case 0xE: goto o13E;
case 0xF: goto o13F;
default : goto o_invalid;
}
o14_:
switch(I[2])
{
case 0x0: goto o140;
case 0x1: goto o141;
case 0x2: goto o142;
case 0x3: goto o143;
case 0x4: goto o144;
case 0x5: goto o145;
case 0x6: goto o146;
case 0x7: goto o147;
case 0x8: goto o148;
case 0x9: goto o149;
case 0xA: goto o14A;
case 0xB: goto o14B;
case 0xC: goto o14C;
case 0xD: goto o14D;
case 0xE: goto o14E;
case 0xF: goto o14F;
default : goto o_invalid;
}
o15_:
switch(I[2]) {
case 0x0: goto o150a;
case 0x1: goto o151a;
case 0x2: goto o152a;
case 0x3: goto o153a;
case 0x4: goto o154a;
case 0x5: goto o155a;
case 0x6: goto o156a;
case 0x7: goto o157a;
case 0x8: goto o158x;
case 0x9: goto o159x;
case 0xA: goto o15Ax;
case 0xB: goto o15Bx;
case 0xC: goto o15Cx;
case 0xD: goto o15Dx;
case 0xE: goto o15Ex;
case 0xF: goto o15Fx;
default : goto o_invalid;
}
o8_:
switch(I[1])
{
case 0x0: goto o80_;
case 0x1: goto o81_;
case 0x2: goto o82n;
case 0x3: goto o83n;
case 0x4: goto o84n;
case 0x5: goto o85n;
case 0x6: goto o86n;
case 0x7: goto o87n;
case 0x8: goto o88n;
case 0x9: goto o89n;
case 0xA: goto o8A_;
case 0xB: goto o8B_;
case 0xC: goto o8Cd4;
case 0xD: goto o8Dd5;
case 0xE: goto o8Ed4;
case 0xF: goto o8Fd5;
default : goto o_invalid;
}
o80_:
switch(I[2])
{
case 0x0: goto o800;
case 0x1: goto o801;
case 0x2: goto o802;
case 0x3: goto o803;
case 0x4: goto o804;
case 0x5: goto o805;
case 0x6: goto o806;
case 0x7: goto o807;
case 0x8: goto o808_;
case 0x9: goto o809;
case 0xA: goto o80A;
case 0xB: goto o80B;
case 0xC: goto o80Cn;
case 0xD: goto o80Dn;
case 0xE: goto o80E;
case 0xF: goto o80Fn;
default : goto o_invalid;
}
o808_:
switch(I[3])
{
case 0x0: goto o8080;
case 0x1: if (I[4]) goto o_invalid5; goto o80810;
case 0x2: goto o8082X;
case 0x3: goto o8083;
case 0x4: goto o8084n;
case 0x5: goto o8085n;
case 0x6: goto o8086n;
case 0x7: goto o8087n;
case 0x8: goto o8088n;
case 0x9: goto o8089n;
case 0xA: goto o808An;
case 0xB: goto o808Bn;
case 0xC: goto o808C;
case 0xD: goto o808D;
case 0xE: goto o808E;
case 0xF: goto o808F;
default : goto o_invalid;
}
o81_:
switch(I[2])
{
case 0x0: goto o810;
case 0x1: goto o811;
case 0x2: goto o812;
case 0x3: goto o813;
case 0x4: goto o814;
case 0x5: goto o815;
case 0x6: goto o816;
case 0x7: goto o817;
case 0x8: goto o818_;
case 0x9: goto o819_;
case 0xA: goto o81A_;
case 0xB: goto o81B_;
case 0xC: goto o81C;
case 0xD: goto o81D;
case 0xE: goto o81E;
case 0xF: goto o81F;
default : goto o_invalid;
}
o818_:
switch(I[4])
{
case 0x0: goto o818f0x;
case 0x1: goto o818f1x;
case 0x2: goto o818f2x;
case 0x3: goto o818f3x;
case 0x8: goto o818f8x;
case 0x9: goto o818f9x;
case 0xA: goto o818fAx;
case 0xB: goto o818fBx;
default : goto o_invalid6;
}
o819_:
switch(I[4])
{
case 0x0: goto o819f0;
case 0x1: goto o819f1;
case 0x2: goto o819f2;
case 0x3: goto o819f3;
default : goto o_invalid5;
}
o81A_:
switch(I[4])
{
case 0x0: goto o81Af0_;
case 0x1: goto o81Af1_;
case 0x2: goto o81Af2_;
default : goto o_invalid6;
}
o81Af0_:
switch(I[5])
{
case 0x0: goto o81Af00;
case 0x1: goto o81Af01;
case 0x2: goto o81Af02;
case 0x3: goto o81Af03;
case 0x4: goto o81Af04;
case 0x8: goto o81Af08;
case 0x9: goto o81Af09;
case 0xA: goto o81Af0A;
case 0xB: goto o81Af0B;
case 0xC: goto o81Af0C;
default : goto o_invalid6;
}
o81Af1_:
switch(I[5])
{
case 0x0: goto o81Af10;
case 0x1: goto o81Af11;
case 0x2: goto o81Af12;
case 0x3: goto o81Af13;
case 0x4: goto o81Af14;
case 0x8: goto o81Af18;
case 0x9: goto o81Af19;
case 0xA: goto o81Af1A;
case 0xB: goto o81Af1B;
case 0xC: goto o81Af1C;
default : goto o_invalid6;
}
o81Af2_:
switch(I[5])
{
case 0x0: goto o81Af20;
case 0x1: goto o81Af21;
case 0x2: goto o81Af22;
case 0x3: goto o81Af23;
case 0x4: goto o81Af24;
case 0x8: goto o81Af28;
case 0x9: goto o81Af29;
case 0xA: goto o81Af2A;
case 0xB: goto o81Af2B;
case 0xC: goto o81Af2C;
default : goto o_invalid6;
}
o81B_:
switch(I[3])
{
//////// EXTENSIONS ////////
// case 0x0: goto o81B0; // 05.01.99 cg, removed, unused extension
case 0x1: goto o81B1;
////////////////////////////
case 0x2: goto o81B2;
case 0x3: goto o81B3;
case 0x4: goto o81B4;
case 0x5: goto o81B5;
case 0x6: goto o81B6;
case 0x7: goto o81B7;
default : goto o_invalid4;
}
o8A_:
switch(I[2])
{
case 0x0: goto o8A0;
case 0x1: goto o8A1;
case 0x2: goto o8A2;
case 0x3: goto o8A3;
case 0x4: goto o8A4;
case 0x5: goto o8A5;
case 0x6: goto o8A6;
case 0x7: goto o8A7;
case 0x8: goto o8A8;
case 0x9: goto o8A9;
case 0xA: goto o8AA;
case 0xB: goto o8AB;
case 0xC: goto o8AC;
case 0xD: goto o8AD;
case 0xE: goto o8AE;
case 0xF: goto o8AF;
default : goto o_invalid;
}
o8B_:
switch(I[2])
{
case 0x0: goto o8B0;
case 0x1: goto o8B1;
case 0x2: goto o8B2;
case 0x3: goto o8B3;
case 0x4: goto o8B4;
case 0x5: goto o8B5;
case 0x6: goto o8B6;
case 0x7: goto o8B7;
case 0x8: goto o8B8;
case 0x9: goto o8B9;
case 0xA: goto o8BA;
case 0xB: goto o8BB;
case 0xC: goto o8BC;
case 0xD: goto o8BD;
case 0xE: goto o8BE;
case 0xF: goto o8BF;
default : goto o_invalid;
}
o9_:
if (I[1]<8)
goto o9a_;
else
goto o9b_;
o9a_:
switch(I[2])
{
case 0x0: goto o9a0;
case 0x1: goto o9a1;
case 0x2: goto o9a2;
case 0x3: goto o9a3;
case 0x4: goto o9a4;
case 0x5: goto o9a5;
case 0x6: goto o9a6;
case 0x7: goto o9a7;
case 0x8: goto o9a8;
case 0x9: goto o9a9;
case 0xA: goto o9aA;
case 0xB: goto o9aB;
case 0xC: goto o9aC;
case 0xD: goto o9aD;
case 0xE: goto o9aE;
case 0xF: goto o9aF;
default : goto o_invalid;
}
o9b_:
switch(I[2])
{
case 0x0: goto o9b0;
case 0x1: goto o9b1;
case 0x2: goto o9b2;
case 0x3: goto o9b3;
case 0x4: goto o9b4;
case 0x5: goto o9b5;
case 0x6: goto o9b6;
case 0x7: goto o9b7;
case 0x8: goto o9b8;
case 0x9: goto o9b9;
case 0xA: goto o9bA;
case 0xB: goto o9bB;
case 0xC: goto o9bC;
case 0xD: goto o9bD;
case 0xE: goto o9bE;
case 0xF: goto o9bF;
default : goto o_invalid;
}
oA_:
if (I[1]<8)
goto oAa_;
else
goto oAb_;
oAa_:
switch(I[2])
{
case 0x0: goto oAa0;
case 0x1: goto oAa1;
case 0x2: goto oAa2;
case 0x3: goto oAa3;
case 0x4: goto oAa4;
case 0x5: goto oAa5;
case 0x6: goto oAa6;
case 0x7: goto oAa7;
case 0x8: goto oAa8;
case 0x9: goto oAa9;
case 0xA: goto oAaA;
case 0xB: goto oAaB;
case 0xC: goto oAaC;
case 0xD: goto oAaD;
case 0xE: goto oAaE;
case 0xF: goto oAaF;
default : goto o_invalid;
}
oAb_:
switch(I[2])
{
case 0x0: goto oAb0;
case 0x1: goto oAb1;
case 0x2: goto oAb2;
case 0x3: goto oAb3;
case 0x4: goto oAb4;
case 0x5: goto oAb5;
case 0x6: goto oAb6;
case 0x7: goto oAb7;
case 0x8: goto oAb8;
case 0x9: goto oAb9;
case 0xA: goto oAbA;
case 0xB: goto oAbB;
case 0xC: goto oAbC;
case 0xD: goto oAbD;
case 0xE: goto oAbE;
case 0xF: goto oAbF;
default : goto o_invalid;
}
oB_:
if (I[1]<8)
goto oBa_;
else
goto oBb_;
oBa_:
switch(I[2])
{
case 0x0: goto oBa0;
case 0x1: goto oBa1;
case 0x2: goto oBa2;
case 0x3: goto oBa3;
case 0x4: goto oBa4;
case 0x5: goto oBa5;
case 0x6: goto oBa6;
case 0x7: goto oBa7;
case 0x8: goto oBa8;
case 0x9: goto oBa9;
case 0xA: goto oBaA;
case 0xB: goto oBaB;
case 0xC: goto oBaC;
case 0xD: goto oBaD;
case 0xE: goto oBaE;
case 0xF: goto oBaF;
default : goto o_invalid;
}
oBb_:
switch(I[2])
{
case 0x0: goto oBb0;
case 0x1: goto oBb1;
case 0x2: goto oBb2;
case 0x3: goto oBb3;
case 0x4: goto oBb4;
case 0x5: goto oBb5;
case 0x6: goto oBb6;
case 0x7: goto oBb7;
case 0x8: goto oBb8;
case 0x9: goto oBb9;
case 0xA: goto oBbA;
case 0xB: goto oBbB;
case 0xC: goto oBbC;
case 0xD: goto oBbD;
case 0xE: goto oBbE;
case 0xF: goto oBbF;
default : goto o_invalid;
}
oC_:
switch(I[1])
{
case 0x0: goto oC0;
case 0x1: goto oC1;
case 0x2: goto oC2;
case 0x3: goto oC3;
case 0x4: goto oC4;
case 0x5: goto oC5;
case 0x6: goto oC6;
case 0x7: goto oC7;
case 0x8: goto oC8;
case 0x9: goto oC9;
case 0xA: goto oCA;
case 0xB: goto oCB;
case 0xC: goto oCC;
case 0xD: goto oCD;
case 0xE: goto oCE;
case 0xF: goto oCF;
default : goto o_invalid;
}
oD_:
switch(I[1])
{
case 0x0: goto oD0;
case 0x1: goto oD1;
case 0x2: goto oD2;
case 0x3: goto oD3;
case 0x4: goto oD4;
case 0x5: goto oD5;
case 0x6: goto oD6;
case 0x7: goto oD7;
case 0x8: goto oD8;
case 0x9: goto oD9;
case 0xA: goto oDA;
case 0xB: goto oDB;
case 0xC: goto oDC;
case 0xD: goto oDD;
case 0xE: goto oDE;
case 0xF: goto oDF;
default : goto o_invalid;
}
oE_:
switch(I[1])
{
case 0x0: goto oE0;
case 0x1: goto oE1;
case 0x2: goto oE2;
case 0x3: goto oE3;
case 0x4: goto oE4;
case 0x5: goto oE5;
case 0x6: goto oE6;
case 0x7: goto oE7;
case 0x8: goto oE8;
case 0x9: goto oE9;
case 0xA: goto oEA;
case 0xB: goto oEB;
case 0xC: goto oEC;
case 0xD: goto oED;
case 0xE: goto oEE;
case 0xF: goto oEF;
default : goto o_invalid;
}
oF_:
switch(I[1])
{
case 0x0: goto oF0;
case 0x1: goto oF1;
case 0x2: goto oF2;
case 0x3: goto oF3;
case 0x4: goto oF4;
case 0x5: goto oF5;
case 0x6: goto oF6;
case 0x7: goto oF7;
case 0x8: goto oF8;
case 0x9: goto oF9;
case 0xA: goto oFA;
case 0xB: goto oFB;
case 0xC: goto oFC;
case 0xD: goto oFD;
case 0xE: goto oFE;
case 0xF: goto oFF;
default : goto o_invalid;
}

View file

@ -30,12 +30,14 @@ static HANDLE hPort2Map = NULL;
LPBYTE pbyPort2 = NULL;
BOOL bPort2Writeable = FALSE;
BOOL bPort2IsShared = FALSE;
DWORD dwPort2Size = 0; // 26.06.98 cg, new, size of mapped port2
DWORD dwPort2Size = 0; // size of mapped port2
DWORD dwPort2Mask = 0;
// UINT nPort2Bank = 0; // 15.12.98 cg, removed, not used any more
// 01.12.99 cg, new, HP38G signature
static BYTE pbySignatureA[16] = "Emu38 Document\xFE";
static BYTE pbySignatureE[16] = "Emu48 Document\xFE";
static BYTE pbySignatureW[16] = "Win48 Document\xFE";
static BYTE pbySignatureV[16] = "Emu49 Document\xFE";
static HANDLE hCurrentFile = NULL;
static CHIPSET BackupChipset;
@ -47,7 +49,7 @@ BOOL bBackup = FALSE;
//#
//################
WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // 11.05.98 cg, new, separated from LoadObject()
WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // separated from LoadObject()
{
BOOL bBinary;
DWORD dwLength, dwAddress, i;
@ -57,7 +59,7 @@ WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // 11.05.98 cg, new, separated from L
&& (lpBuf[dwSize+2]=='H')
&& (lpBuf[dwSize+3]=='P')
&& (lpBuf[dwSize+4]=='4')
&& (lpBuf[dwSize+5]=='8')
&& (lpBuf[dwSize+5]==((cCurrentRomType!='X') ? '8' : '9'))
&& (lpBuf[dwSize+6]=='-'));
for (i=0; i<dwSize; i++)
@ -73,7 +75,6 @@ WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // 11.05.98 cg, new, separated from L
dwAddress = RPL_CreateTemp(dwLength);
if (dwAddress == 0) return S_ERR_BINARY;
// 23.05.98 cg, optimized
Nwrite(lpBuf+16, dwAddress, dwLength);
}
else
@ -87,7 +88,6 @@ WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // 11.05.98 cg, new, separated from L
Nwrite(lpHead,dwAddress,5);
Nunpack(lpHead,dwLength+5,5);
Nwrite(lpHead,dwAddress+5,5);
// 23.05.98 cg, optimized
Nwrite(lpBuf, dwAddress+10, dwLength);
}
RPL_Push(dwAddress);
@ -102,6 +102,23 @@ WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // 11.05.98 cg, new, separated from L
//#
//################
static WORD CrcRom(VOID) // 19.11.99 cg, new, calculate fingerprint of ROM
{
DWORD dwCount;
DWORD dwFileSize;
DWORD dwCrc = 0;
dwFileSize = GetFileSize(hRomFile, &dwCount); // get real filesize
_ASSERT(dwCount == 0); // isn't created by MapRom()
_ASSERT(pbyRom); // view on ROM
// use checksum, because it's faster
for (dwCount = 0;dwCount < dwFileSize; dwCount+=sizeof(dwCrc))
dwCrc += *((DWORD *) &pbyRom[dwCount]);
return (WORD) dwCrc;
}
BOOL MapRom(LPCSTR szFilename)
{
DWORD dwFileSizeHigh;
@ -151,7 +168,7 @@ BOOL MapRom(LPCSTR szFilename)
return TRUE;
}
VOID UnmapRom()
VOID UnmapRom(VOID)
{
if (pbyRom==NULL) return;
UnmapViewOfFile(pbyRom);
@ -172,13 +189,15 @@ VOID UnmapRom()
//#
//################
static WORD CrcPort2(VOID) // 20.02.99 cg, new, calculate fingerprint of port2
static WORD CrcPort2(VOID) // calculate fingerprint of port2
{
DWORD dwCount;
DWORD dwFileSize;
WORD wCrc = 0;
if (pbyPort2==NULL) return wCrc; // port2 isn't available
// port2 CRC isn't available
if (cCurrentRomType=='X' || pbyPort2==NULL) return wCrc;
dwFileSize = GetFileSize(hPort2File, &dwCount); // get real filesize
_ASSERT(dwCount == 0); // isn't created by MapPort2()
@ -192,12 +211,9 @@ BOOL MapPort2(LPCSTR szFilename)
DWORD dwFileSizeLo;
DWORD dwFileSizeHi;
if (pbyPort2 != NULL)
{
return FALSE;
}
if (pbyPort2 != NULL) return FALSE;
bPort2Writeable = TRUE;
dwPort2Size = 0; // 26.06.98 cg, new, reset size of port2
dwPort2Size = 0; // reset size of port2
SetCurrentDirectory(szEmu48Directory);
if (bPort2IsShared)
@ -245,7 +261,7 @@ BOOL MapPort2(LPCSTR szFilename)
bPort2Writeable = FALSE;
return FALSE;
}
dwPort2Mask = (dwFileSizeLo >> 17) - 1; // 26.06,98 cg, optimized, calculate bank switching mask
dwPort2Mask = (dwFileSizeLo >> 18) - 1; // mask for valid address lines of the BS-FF
if (bPort2Writeable)
hPort2Map = CreateFileMapping(hPort2File, NULL, PAGE_READWRITE, 0, dwFileSizeLo, NULL);
else
@ -272,12 +288,12 @@ BOOL MapPort2(LPCSTR szFilename)
bPort2Writeable = FALSE;
return FALSE;
}
dwPort2Size = dwFileSizeLo / 2048; // 26.06.98 cg, new, mapping size of port2
dwPort2Size = dwFileSizeLo / 2048; // mapping size of port2
if (dwPort2Size > 128) dwPort2Size = 128;
return TRUE;
}
VOID UnmapPort2()
VOID UnmapPort2(VOID)
{
if (pbyPort2==NULL) return;
UnmapViewOfFile(pbyPort2);
@ -286,7 +302,7 @@ VOID UnmapPort2()
pbyPort2 = NULL;
hPort2Map = NULL;
hPort2File = NULL;
dwPort2Size = 0; // 26.06.98 cg, new, reset size of port2
dwPort2Size = 0; // reset size of port2
dwPort2Mask = 0;
bPort2Writeable = FALSE;
return;
@ -311,23 +327,13 @@ static BYTE Asc2Nib(char c)
return 0;
}
static DWORD Asc2Nib5(LPSTR lpBuf)
{
return (
((DWORD)Asc2Nib(lpBuf[0])<<16)
|((DWORD)Asc2Nib(lpBuf[1])<<12)
|((DWORD)Asc2Nib(lpBuf[2])<<8)
|((DWORD)Asc2Nib(lpBuf[3])<<4)
|((DWORD)Asc2Nib(lpBuf[4])));
}
BOOL PatchRom(LPCSTR szFilename)
{
HANDLE hFile = NULL;
DWORD dwFileSizeLow = 0;
DWORD dwFileSizeHigh = 0;
DWORD lBytesRead = 0;
LPBYTE lpBuf = NULL;
LPBYTE lpStop,lpBuf = NULL;
DWORD dwAddress = 0;
UINT nPos = 0;
@ -359,19 +365,6 @@ BOOL PatchRom(LPCSTR szFilename)
nPos = 0;
while (lpBuf[nPos])
{
if (lpBuf[nPos]==';') // comment ?
{
do
{
if (lpBuf[nPos]=='\n') break;
nPos++;
} while (lpBuf[nPos]);
if (lpBuf[nPos]==0)
{
LocalFree(lpBuf);
return TRUE;
}
}
do // remove blank space
{
if ( (lpBuf[nPos]!=' ')
@ -380,28 +373,28 @@ BOOL PatchRom(LPCSTR szFilename)
&&(lpBuf[nPos]!='\t')) break;
nPos++;
} while (lpBuf[nPos]);
if (lpBuf[nPos] == 0) break;
if (lpBuf[nPos+5]!=':')
if (lpBuf[nPos]==';') // comment ?
{
do
{
nPos++;
continue;
if (lpBuf[nPos]=='\n')
{
nPos++;
break;
}
dwAddress = Asc2Nib5(lpBuf+nPos);
nPos+=6;
} while (lpBuf[nPos]);
}
if (lpBuf[nPos] == 0) break;
dwAddress = strtoul(&lpBuf[nPos],&lpStop,16);
nPos += lpStop-&lpBuf[nPos]+1;
if (*lpStop != ':' || *lpStop == 0)
continue;
while (lpBuf[nPos])
{
if (lpBuf[nPos]<'0') break;
if (lpBuf[nPos]>'9')
{
if (lpBuf[nPos]<'A') break;
if (lpBuf[nPos]>'F') break;
pbyRom[dwAddress] = lpBuf[nPos]-'A'+10;
}
else
{
pbyRom[dwAddress] = lpBuf[nPos]-'0';
}
dwAddress = (dwAddress+1)&0xFFFFF;
if (isxdigit(lpBuf[nPos]) == FALSE) break;
pbyRom[dwAddress] = Asc2Nib(lpBuf[nPos]);
dwAddress = (dwAddress+1)&(dwRomSize-1);
nPos++;
}
}
@ -417,7 +410,7 @@ BOOL PatchRom(LPCSTR szFilename)
//#
//################
VOID ResetDocument()
VOID ResetDocument(VOID)
{
if (szCurrentKml[0])
{
@ -432,24 +425,43 @@ VOID ResetDocument()
szCurrentFilename[0]=0;
if (Chipset.Port0) LocalFree(Chipset.Port0);
if (Chipset.Port1) LocalFree(Chipset.Port1);
if (cCurrentRomType == 'X')
{
if (Chipset.Port2) LocalFree(Chipset.Port2);
}
else
{
UnmapPort2();
}
FillMemory(&Chipset,sizeof(Chipset),0);
UpdateWindowStatus();
return;
}
BOOL NewDocument()
BOOL NewDocument(VOID)
{
SaveBackup();
ResetDocument();
if (!DisplayChooseKml(0)) goto restore;
if (!InitKML(szCurrentKml,FALSE)) goto restore;
Chipset.type = cCurrentRomType;
if (Chipset.type == 'S')
if (Chipset.type == 'A') // 01.12.99 cg, new, HP38G
{
Chipset.Port0Size = 32;
Chipset.Port1Size = 0;
Chipset.Port2Size = 0;
Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048);
_ASSERT(Chipset.Port0 != NULL);
FillMemory(Chipset.Port0, Chipset.Port0Size*2048, 0);
Chipset.Port1 = NULL;
Chipset.Port2 = NULL;
Chipset.cards_status = 0x0;
}
if (Chipset.type == 'S') // HP48SX
{
Chipset.Port0Size = 32;
Chipset.Port1Size = 128;
Chipset.Port1_Writeable = TRUE;
Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048);
_ASSERT(Chipset.Port0 != NULL);
FillMemory(Chipset.Port0, Chipset.Port0Size*2048, 0);
@ -457,12 +469,15 @@ BOOL NewDocument()
_ASSERT(Chipset.Port1 != NULL);
FillMemory(Chipset.Port1, Chipset.Port1Size*2048, 0);
Chipset.cards_status = 0x5;
// use 2nd command line argument if defined
// 08.11.99 cg, changed, replaced __argc and __argv variable
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
}
else
if (Chipset.type == 'G') // HP48GX
{
Chipset.Port0Size = 128;
Chipset.Port1Size = 128;
Chipset.Port1_Writeable = TRUE;
Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048);
_ASSERT(Chipset.Port0 != NULL);
FillMemory(Chipset.Port0, Chipset.Port0Size*2048, 0);
@ -470,15 +485,47 @@ BOOL NewDocument()
_ASSERT(Chipset.Port1 != NULL);
FillMemory(Chipset.Port1, Chipset.Port1Size*2048, 0);
Chipset.cards_status = 0xA;
// use 2nd command line argument if defined
// 08.11.99 cg, changed, replaced __argc and __argv variable
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
}
Map(0x00,0xFF);
if (Chipset.type == 'X') // HP49G
{
Chipset.Port0Size = 256;
Chipset.Port1Size = 128;
Chipset.Port2Size = 128;
Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048);
_ASSERT(Chipset.Port0 != NULL);
FillMemory(Chipset.Port0, Chipset.Port0Size*2048, 0);
Chipset.Port1 = (LPBYTE)LocalAlloc(0,Chipset.Port1Size*2048);
_ASSERT(Chipset.Port1 != NULL);
FillMemory(Chipset.Port1, Chipset.Port1Size*2048, 0);
Chipset.Port2 = (LPBYTE)LocalAlloc(0,Chipset.Port2Size*2048);
_ASSERT(Chipset.Port2 != NULL);
FillMemory(Chipset.Port2, Chipset.Port2Size*2048, 0);
bPort2Writeable = TRUE;
Chipset.cards_status = 0xF;
}
RomSwitch(0); // boot ROM view of HP49G and map memory
SaveBackup();
return TRUE;
restore:
RestoreBackup();
ResetBackup();
// 01.12.99 cg, changed, added HP38G
if(Chipset.type != 'A' && Chipset.type != 'X')
{
// use 2nd command line argument if defined
// 08.11.99 cg, changed, replaced __argc and __argv variable
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
}
if (pbyRom)
{
SetWindowPos(hWnd,NULL,(int)Chipset.wPosX,(int)Chipset.wPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
// 09.12.99 cg, changed, removed typecast of the position data
SetWindowPos(hWnd,NULL,Chipset.nPosX,Chipset.nPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
Map(0x00,0xFF);
}
return FALSE;
@ -490,6 +537,7 @@ BOOL OpenDocument(LPCSTR szFilename)
DWORD lBytesRead;
DWORD lSizeofChipset;
BYTE pbyFileSignature[16];
LPBYTE pbySig;
UINT ctBytesCompared;
UINT nLength;
@ -514,9 +562,13 @@ BOOL OpenDocument(LPCSTR szFilename)
switch (pbyFileSignature[0])
{
case 'E':
// 01.12.99 cg, changed, added HP38 signature
pbySig = (pbyFileSignature[3] == '3')
? pbySignatureA
: ((pbyFileSignature[4] == '8') ? pbySignatureE : pbySignatureV);
for (ctBytesCompared=0; ctBytesCompared<14; ctBytesCompared++)
{
if (pbyFileSignature[ctBytesCompared]!=pbySignatureE[ctBytesCompared])
if (pbyFileSignature[ctBytesCompared]!=pbySig[ctBytesCompared])
{
AbortMessage("This file is not a valid Emu48 document.");
goto restore;
@ -540,7 +592,7 @@ BOOL OpenDocument(LPCSTR szFilename)
switch (pbyFileSignature[14])
{
case 0xFE: // Win48 2.1 / Emu48 0.99.x format
case 0xFE: // Win48 2.1 / Emu4x 0.99.x format
ReadFile(hFile, &nLength, sizeof(nLength), &lBytesRead, NULL);
ReadFile(hFile, szCurrentKml, nLength, &lBytesRead, NULL);
if (nLength != lBytesRead) goto read_err;
@ -566,26 +618,21 @@ BOOL OpenDocument(LPCSTR szFilename)
if (lBytesRead != lSizeofChipset) goto read_err;
Chipset.Port0 = NULL;
Chipset.Port1 = NULL;
Chipset.Port2 = NULL;
// 26.01.98 cg, bugfix, WORD to int conversation failed with negative numbers
SetWindowPos(hWnd,NULL,(short)Chipset.wPosX,(short)Chipset.wPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
// 09.12.99 cg, changed, removed typecast of the position data
SetWindowPos(hWnd,NULL,Chipset.nPosX,Chipset.nPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
if (szCurrentKml == NULL)
{
if (!DisplayChooseKml(Chipset.type))
{
// CloseHandle(hFile); // 29.01.98 cg, bugfix, will be close at end of function
goto restore;
}
}
while (!InitKML(szCurrentKml,FALSE))
{
if (!DisplayChooseKml(Chipset.type))
{
// CloseHandle(hFile); // 29.01.98 cg, bugfix, will be close at end of function
goto restore;
}
}
if (Chipset.Port0Size)
{
@ -613,16 +660,49 @@ BOOL OpenDocument(LPCSTR szFilename)
if (lBytesRead != Chipset.Port1Size*2048) goto read_err;
}
if (Chipset.wPort2Crc != CrcPort2()) // 21.02.99 cg, new, port2 changed
if (cCurrentRomType!='X') // HP38G, HP48SX/GX
{
Chipset.HST |= 8; // 21.02.99 cg, new, set Module Pulled
Chipset.SoftInt = TRUE; // 21.02.99 cg, new, set interrupt
bInterrupt = TRUE; // 21.02.99 cg, new
if(cCurrentRomType!='A') // 01.12.99 cg, new, HP48SX/GX
{
// 08.11.99 cg, changed, replaced __argc and __argv variable
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
if (Chipset.wPort2Crc != CrcPort2())// port2 changed
{
Chipset.HST |= 8; // set Module Pulled
Chipset.SoftInt = TRUE; // set interrupt
bInterrupt = TRUE;
}
}
}
else // HP49G
{
if (Chipset.Port2Size)
{
Chipset.Port2 = (LPBYTE)LocalAlloc(0,Chipset.Port2Size*2048);
if (Chipset.Port2 == NULL)
{
AbortMessage("Memory Allocation Failure.");
goto restore;
}
ReadFile(hFile, Chipset.Port2, Chipset.Port2Size*2048, &lBytesRead, NULL);
if (lBytesRead != Chipset.Port2Size*2048) goto read_err;
bPort2Writeable = TRUE;
Chipset.cards_status = 0xF;
}
}
RomSwitch(Chipset.Bank_FF); // reload ROM view of HP49G and map memory
// 20.11.99 cg, new, check fingerprint of ROM
if (Chipset.wRomCrc != CrcRom()) // ROM changed
CpuReset();
// 20.11.99 cg, end of fingerprint check
lstrcpy(szCurrentFilename, szFilename);
_ASSERT(hCurrentFile == NULL);
hCurrentFile = hFile;
Map(0x00,0xFF);
SetWindowTitle(szCurrentFilename);
UpdateWindowStatus();
return TRUE;
@ -630,34 +710,48 @@ BOOL OpenDocument(LPCSTR szFilename)
read_err:
AbortMessage("This file must be truncated, and cannot be loaded.");
restore:
if (INVALID_HANDLE_VALUE != hFile) // 29.01.98 cg, bugfix, close if valid handle
if (INVALID_HANDLE_VALUE != hFile) // close if valid handle
CloseHandle(hFile);
RestoreBackup();
ResetBackup();
// 01.12.99 cg, bugfix, add port2 only on HP48 calculators
if(cCurrentRomType!='A' && cCurrentRomType!='X')
{
// use 2nd command line argument if defined
// 08.11.99 cg, changed, replaced __argc and __argv variable
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
}
return FALSE;
}
BOOL SaveDocument()
BOOL SaveDocument(VOID)
{
DWORD lBytesWritten;
DWORD lSizeofChipset;
LPBYTE pbySig;
UINT nLength;
RECT Rect;
if (hCurrentFile == NULL) return FALSE;
GetWindowRect(hWnd, &Rect);
Chipset.wPosX = (WORD)Rect.left;
Chipset.wPosY = (WORD)Rect.top;
GetWindowRect(hWnd, &Rect); // update saved window position
Chipset.nPosX = (SWORD)Rect.left;
Chipset.nPosY = (SWORD)Rect.top;
SetFilePointer(hCurrentFile,0,0,FILE_BEGIN);
if (!WriteFile(hCurrentFile, pbySignatureE, 16, &lBytesWritten, NULL))
// 01.12.99 cg, changed, added HP38G signature
pbySig = (Chipset.type=='A') ? pbySignatureA : ((Chipset.type!='X') ? pbySignatureE : pbySignatureV);
if (!WriteFile(hCurrentFile, pbySig, 16, &lBytesWritten, NULL))
{
AbortMessage("Could not write into file !");
return FALSE;
}
Chipset.wPort2Crc = CrcPort2(); // 21.02.99 cg, new, save fingerprint of port2
Chipset.wRomCrc = CrcRom(); // 20.11.99 cg, new, save fingerprint of ROM
Chipset.wPort2Crc = CrcPort2(); // save fingerprint of port2
nLength = strlen(szCurrentKml);
WriteFile(hCurrentFile, &nLength, sizeof(nLength), &lBytesWritten, NULL);
@ -667,34 +761,25 @@ BOOL SaveDocument()
WriteFile(hCurrentFile, &Chipset, lSizeofChipset, &lBytesWritten, NULL);
if (Chipset.Port0Size) WriteFile(hCurrentFile, Chipset.Port0, Chipset.Port0Size*2048, &lBytesWritten, NULL);
if (Chipset.Port1Size) WriteFile(hCurrentFile, Chipset.Port1, Chipset.Port1Size*2048, &lBytesWritten, NULL);
if (cCurrentRomType=='X' && Chipset.Port2Size) WriteFile(hCurrentFile, Chipset.Port2, Chipset.Port2Size*2048, &lBytesWritten, NULL);
return TRUE;
}
BOOL SaveDocumentAs(LPCTSTR szFilename)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hFile;
if (hCurrentFile) // already file in use
{
if (lstrcmpi(szFilename, szCurrentFilename)==0)
{
hFile = hCurrentFile; // same file, do not open a new one
CloseHandle(hCurrentFile); // close it, even it's same, so data always will be saved
hCurrentFile = NULL;
}
}
if (hFile == INVALID_HANDLE_VALUE) // not same file, open a new one
{
hFile = CreateFile(szFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
}
if (hFile == INVALID_HANDLE_VALUE) // error, couldn't create a new file
{
AbortMessage("This file must be currently used by another instance of Emu48.");
return FALSE;
}
if (hCurrentFile) // 02.10.98 cg, previous file in use
{
CloseHandle(hCurrentFile); // 02.10.98 cg, bugfix, close it
}
lstrcpy(szCurrentFilename, szFilename); // save new file name
hCurrentFile = hFile; // and the corresponding handle
SetWindowTitle(szCurrentFilename); // update window title line
@ -710,28 +795,44 @@ BOOL SaveDocumentAs(LPCTSTR szFilename)
//#
//################
BOOL SaveBackup()
BOOL SaveBackup(VOID)
{
RECT Rect;
if (pbyRom == NULL) return FALSE;
// 09.12.99 cg, changed, save window position
GetWindowRect(hWnd, &Rect); // update saved window position
Chipset.nPosX = (SWORD)Rect.left;
Chipset.nPosY = (SWORD)Rect.top;
// 09.12.99 cg, end of part
lstrcpy(szBackupFilename, szCurrentFilename);
lstrcpy(szBackupKml, szCurrentKml);
if (BackupChipset.Port0) LocalFree(BackupChipset.Port0);
if (BackupChipset.Port1) LocalFree(BackupChipset.Port1);
if (BackupChipset.Port2) LocalFree(BackupChipset.Port2);
CopyMemory(&BackupChipset, &Chipset, sizeof(Chipset));
BackupChipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048);
CopyMemory(BackupChipset.Port0, Chipset.Port0, Chipset.Port0Size*2048);
BackupChipset.Port1 = (LPBYTE)LocalAlloc(0,Chipset.Port1Size*2048);
CopyMemory(BackupChipset.Port1, Chipset.Port1, Chipset.Port1Size*2048);
BackupChipset.Port2 = NULL;
if (cCurrentRomType=='X') // HP49G
{
BackupChipset.Port2 = (LPBYTE)LocalAlloc(0,Chipset.Port2Size*2048);
CopyMemory(BackupChipset.Port2, Chipset.Port2, Chipset.Port2Size*2048);
}
bBackup = TRUE;
UpdateWindowStatus();
return TRUE;
}
BOOL RestoreBackup()
BOOL RestoreBackup(VOID)
{
if (!bBackup) return FALSE;
ResetDocument();
// 02.02.98 cg, moved, need chipset for contrast setting in InitKML()
// need chipset for contrast setting in InitKML()
CopyMemory(&Chipset, &BackupChipset, sizeof(Chipset));
if (!InitKML(szBackupKml,TRUE))
{
@ -749,25 +850,40 @@ BOOL RestoreBackup()
szCurrentFilename[0] = 0;
}
}
// 02.02.98 cg, removed, done before
// CopyMemory(&Chipset, &BackupChipset, sizeof(Chipset));
Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048);
CopyMemory(Chipset.Port0, BackupChipset.Port0, Chipset.Port0Size*2048);
Chipset.Port1 = (LPBYTE)LocalAlloc(0,Chipset.Port1Size*2048);
CopyMemory(Chipset.Port1, BackupChipset.Port1, Chipset.Port1Size*2048);
SetWindowPos(hWnd,NULL,(int)Chipset.wPosX,(int)Chipset.wPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
if (cCurrentRomType=='X') // HP49G
{
Chipset.Port2 = (LPBYTE)LocalAlloc(0,Chipset.Port2Size*2048);
CopyMemory(Chipset.Port2, BackupChipset.Port2, Chipset.Port2Size*2048);
}
// 09.12.99 cg, bugfix, map port2
else
{
if(cCurrentRomType!='A') // HP48SX/GX
{
// use 2nd command line argument if defined
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
}
}
// 09.12.99 cg, end of bugfix
// 09.12.99 cg, changed, removed typecast of the position data
SetWindowPos(hWnd,NULL,Chipset.nPosX,Chipset.nPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
UpdateWindowStatus();
Map(0x00,0xFF);
return TRUE;
}
BOOL ResetBackup()
BOOL ResetBackup(VOID)
{
if (!bBackup) return FALSE;
szBackupFilename[0] = 0;
szBackupKml[0] = 0;
if (BackupChipset.Port0) LocalFree(BackupChipset.Port0);
if (BackupChipset.Port1) LocalFree(BackupChipset.Port1);
if (BackupChipset.Port2) LocalFree(BackupChipset.Port2);
FillMemory(&BackupChipset,sizeof(BackupChipset),0);
bBackup = FALSE;
UpdateWindowStatus();
@ -791,17 +907,37 @@ static VOID InitializeOFN(LPOPENFILENAME ofn)
return;
}
BOOL GetOpenFilename()
BOOL GetOpenFilename(VOID)
{
OPENFILENAME ofn;
InitializeOFN(&ofn);
ofn.lpstrFilter =
"Emu38 Document (*.E38)\0*.E38\0"
"Emu48 Document (*.E48)\0*.E48\0"
"Emu49 Document (*.E49)\0*.E49\0"
"Win48 Document (*.W48)\0*.W48\0"
"\0\0";
ofn.lpstrDefExt = "E48";
if (cCurrentRomType!='X') // HP38G / HP48SX/GX
{
// 01.12.99 cg, new, HP38G support
if (cCurrentRomType=='A') // HP38G
{
ofn.lpstrDefExt = "E38";
ofn.nFilterIndex = 1;
}
else
// 01.12.99 cg, end
{
ofn.lpstrDefExt = "E48";
ofn.nFilterIndex = 2;
}
}
else // HP49G
{
ofn.lpstrDefExt = "E49";
ofn.nFilterIndex = 3;
}
ofn.lpstrFile = LocalAlloc(0,512);
ofn.lpstrFile[0] = 0;
ofn.nMaxFile = 512;
@ -816,17 +952,37 @@ BOOL GetOpenFilename()
return TRUE;
}
BOOL GetSaveAsFilename()
BOOL GetSaveAsFilename(VOID)
{
OPENFILENAME ofn;
InitializeOFN(&ofn);
ofn.lpstrFilter =
"Emu38 Document (*.E38)\0*.E38\0"
"Emu48 Document (*.E48)\0*.E48\0"
"Emu49 Document (*.E49)\0*.E49\0"
"Win48 Document (*.W48)\0*.W48\0"
"\0\0";
ofn.lpstrDefExt = "E48";
if (cCurrentRomType!='X') // HP38G / HP48SX/GX
{
// 01.12.99 cg, new, HP38G support
if (cCurrentRomType=='A') // HP38G
{
ofn.lpstrDefExt = "E38";
ofn.nFilterIndex = 1;
}
else
// 01.12.99 cg, end
{
ofn.lpstrDefExt = "E48";
ofn.nFilterIndex = 2;
}
}
else // HP49G
{
ofn.lpstrDefExt = "E49";
ofn.nFilterIndex = 3;
}
ofn.lpstrFile = LocalAlloc(0,512);
ofn.lpstrFile[0] = 0;
ofn.nMaxFile = 512;
@ -841,7 +997,7 @@ BOOL GetSaveAsFilename()
return TRUE;
}
BOOL GetLoadObjectFilename()
BOOL GetLoadObjectFilename(VOID)
{
OPENFILENAME ofn;
@ -862,7 +1018,7 @@ BOOL GetLoadObjectFilename()
return TRUE;
}
BOOL GetSaveObjectFilename()
BOOL GetSaveObjectFilename(VOID)
{
OPENFILENAME ofn;
@ -891,7 +1047,7 @@ BOOL GetSaveObjectFilename()
//#
//################
BOOL LoadObject(LPCSTR szFilename) // 11.05.98 cg, changed, separated stack writing part
BOOL LoadObject(LPCSTR szFilename) // separated stack writing part
{
HANDLE hFile;
DWORD dwFileSizeLow;
@ -928,9 +1084,10 @@ BOOL LoadObject(LPCSTR szFilename) // 11.05.98 cg, changed, separated stack wr
return (wError == S_ERR_NO);
}
BOOL SaveObject(LPCSTR szFilename) // 11.05.98 cg, changed, separated stack reading part
BOOL SaveObject(LPCSTR szFilename) // separated stack reading part
{
HANDLE hFile;
LPBYTE pbyHeader;
DWORD lBytesWritten;
DWORD dwAddress;
DWORD dwLength;
@ -950,7 +1107,9 @@ BOOL SaveObject(LPCSTR szFilename) // 11.05.98 cg, changed, separated stack re
return FALSE;
}
WriteFile(hFile, BINARYHEADER, 8, &lBytesWritten, NULL);
pbyHeader = (Chipset.type != 'X') ? BINARYHEADER48 : BINARYHEADER49;
WriteFile(hFile, pbyHeader, 8, &lBytesWritten, NULL);
while (dwLength--)
{
BYTE byByte = Read2(dwAddress);
@ -1078,18 +1237,18 @@ HBITMAP LoadBitmapFile(LPCSTR szFilename)
LPBITMAPFILEHEADER pBmfh;
LPBITMAPINFO pBmi;
if (hRomFile == NULL) return NULL; // 17.10.97 cg, bugfix, line moved and error case is NULL
if (hRomFile == NULL) return NULL;
SetCurrentDirectory(szEmu48Directory);
hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
SetCurrentDirectory(szCurrentDirectory);
// 19.01.98 cg, bugfix, opend with GENERIC_READ -> PAGE_READONLY
// opened with GENERIC_READ -> PAGE_READONLY
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMap == NULL)
{
CloseHandle(hFile);
return NULL;
}
// 19.01.98 cg, bugfix, opend with GENERIC_READ -> PAGE_READONLY -> FILE_MAP_READ
// opened with GENERIC_READ -> PAGE_READONLY -> FILE_MAP_READ
pbyFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
if (pbyFile == NULL)
{
@ -1103,9 +1262,9 @@ HBITMAP LoadBitmapFile(LPCSTR szFilename)
if (pBmfh->bfType != 0x4D42) goto quit; // "BM"
pBmi = (LPBITMAPINFO)(pbyFile+sizeof(BITMAPFILEHEADER));
_ASSERT(hPalette == NULL); // 11.09.98 cg, resource free
_ASSERT(hPalette == NULL); // resource free
hPalette = CreateBIPalette(&pBmi->bmiHeader);
// 11.09.98 cg, save old palette
// save old palette
hOldPalette = SelectPalette(hWindowDC, hPalette, FALSE);
RealizePalette(hWindowDC);

75
sources/Emu48/IO.H Normal file
View file

@ -0,0 +1,75 @@
/*
* io.h
*
* This file is part of Emu48
*
* Copyright (C) 1999 Christoph Gießelink
*
*/
// I/O addresses without mapping offset
#define CRC 0x04 // Crc (16 bit, LSB first)
#define BAUD 0x0d // Baudrate (Bit 2-0)
#define IOC 0x10 // IO CONTROL
#define RCS 0x11 // RCS
#define TCS 0x12 // TCS
#define CRER 0x13 // CRER
#define RBR_LSB 0x14 // RBR low nibble
#define RBR_MSB 0x15 // RBR high nibble
#define TBR_LSB 0x16 // TBR low nibble
#define TBR_MSB 0x17 // TBR high nibble
#define SRQ1 0x18 // SRQ1
#define SRQ2 0x19 // SRQ2
#define IR_CTRL 0x1a // IR CONTROL
#define TIMER1_CTRL 0x2e // Timer1 Control
#define TIMER2_CTRL 0x2f // Timer2 Control
#define TIMER1 0x37 // Timer1 (4 bit)
#define TIMER2 0x38 // Timer2 (32 bit, LSB first)
// 0x10 Serial I/O Control [SON ETBE ERBF ERBZ]
#define SON 0x08 // Serial on
#define ETBE 0x04 // Interrupt on transmit buffer empty
#define ERBF 0x02 // Interrupt on receive buffer full
#define ERBZ 0x01 // Interrupt on receiver busy
// 0x11 Serial Receive Control/Status [RX RER RBZ RBF]
#define RX 0x08 // Rx pin state (read-only)
#define RER 0x04 // Receiver error
#define RBZ 0x02 // Receiver busy
#define RBF 0x01 // Receive buffer full
// 0x12 Serial Transmit Control/Status [BRK LPB TBZ TBF]
#define BRK 0x08 // Break
#define LPB 0x04 // Loopback
#define TBZ 0x02 // Transmitter busy
#define TBF 0x01 // Transmit buffer full
// 0x18 Service Request Register 1 [ISRQ TSRQ USRQ VSRQ]
#define ISRQ 0x08 // IR receiver pulls NINT2
#define TSRQ 0x04 // Timer pulls NINT2
#define USRQ 0x02 // UART pulls NINT2
#define VSRQ 0x01 // VLBI pulls NINT2
// 0x19 Service Request Register 2 [KDN NINT2 NINT LSRQ]
#define KDN 0x08 // Bit set when ON Key or Key Interrupt
#define NINT2 0x04 // State of NINT2
#define NINT 0x02 // State of NINT
#define LSRQ 0x01 // LED driver pulls NINT2
// 0x1a IR Control Register [IRI EIRU EIRI IRE]
#define IRI 0x08 // IR input (read-only)
#define EIRU 0x04 // Enable IR UART mode
#define EIRI 0x02 // Enable IR interrupt
#define IRE 0x01 // IR event
// 0x2e Timer1 Control [SRQ WKE INT XTRA]
#define SRQ 0x08 // Service request
#define WKE 0x04 // Wake up
#define INTR 0x02 // Interrupt
#define XTRA 0x01 // Extra function
// 0x2f Timer2 Control [SRQ WKE INT RUN]
#define SRQ 0x08 // Service request
#define WKE 0x04 // Wake up
#define INTR 0x02 // Interrupt
#define RUN 0x01 // Timer run

View file

@ -9,7 +9,7 @@
#include "pch.h"
#include "Emu48.h"
static WORD Keyboard_GetIR(VOID) // 13.02.99 cg, make function static
static WORD Keyboard_GetIR(VOID)
{
WORD r = 0;
@ -26,9 +26,8 @@ static WORD Keyboard_GetIR(VOID) // 13.02.99 cg, make function static
return r;
}
VOID ScanKeyboard(BOOL bReset) // 02.09.98 cg, changed, add flag for key state reset
VOID ScanKeyboard(BOOL bReset)
{
// 02.09.98 cg, new, changed implementation
// bReset = TRUE -> Reset Chipset.in interrupt state register
// FALSE -> generate interrupt only for new pressed keys
@ -38,9 +37,9 @@ VOID ScanKeyboard(BOOL bReset) // 02.09.98 cg, changed, add flag for key stat
WORD wOldIn = Chipset.in; // save old Chipset.in state
// 26.02.99 cg, bugfix, update KDN bit
UpdateKdnBit();
Chipset.dwKdnCycles = Chipset.cycles;
UpdateKdnBit(); // update KDN bit
// 22.11.99 cg, changed, DWORD casting
Chipset.dwKdnCycles = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
// update Chipset.in register
Chipset.in = Keyboard_GetIR() | Chipset.IR15X;
@ -48,10 +47,10 @@ VOID ScanKeyboard(BOOL bReset) // 02.09.98 cg, changed, add flag for key stat
// interrrupt for any new pressed keys ?
bKbdInt = ((Chipset.in & (Chipset.in ^ wOldIn)) != 0) || bReset;
// 01.03.99 cg, bugfix, update keyboard interrupt pending flag
// update keyboard interrupt pending flag
Chipset.intd = Chipset.intd || (bKbdInt && !Chipset.intk);
// 28.02.99 cg, changed, keyboard interrupt enabled
// keyboard interrupt enabled
bKbdInt = bKbdInt && (Chipset.intk || Chipset.IR15X != 0) && Chipset.inte;
if (Chipset.in != 0) // any key pressed
@ -63,76 +62,18 @@ VOID ScanKeyboard(BOOL bReset) // 02.09.98 cg, changed, add flag for key stat
}
if (Chipset.Shutdn) // cpu sleeping
ResumeThread(hThread); // wake up
{
Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode
SetEvent(hEventShutdn); // wake up emulation thread
}
}
else
{
Chipset.intd = FALSE; // 01.03.99 cg, bugfix, no keyboard interrupt pending
Chipset.intd = FALSE; // no keyboard interrupt pending
}
}
LeaveCriticalSection(&csKeyLock);
#if 0
// 02.09.98 cg, removed
// 11.06.98 cg, new, changed implementation
// keyboard interrupt enabled
BOOL bKbdInt = (Chipset.intk || Chipset.IR15X != 0) && Chipset.inte && Chipset.in == 0;
// update Chipset.in register
Chipset.in = Keyboard_GetIR() | Chipset.IR15X;
if (Chipset.in != 0) // call interrupt ?
{
if (bKbdInt) // interrupt enabled
{
Chipset.SoftInt = TRUE; // interrupt request
bInterrupt = TRUE; // exit emulation loop
}
if (Chipset.Shutdn) // cpu sleeping
ResumeThread(hThread); // wake up
}
#endif
#if 0
// 11.06.98 cg, removed
WORD IR = Keyboard_GetIR();
Chipset.in = IR | Chipset.IR15X;
if (Chipset.IR15X)
{
if (Chipset.inte)
{
// PatBlt(hWindowDC,0,0,8,8,DSTINVERT);
Chipset.SoftInt = TRUE;
bInterrupt = TRUE;
}
if (Chipset.Shutdn)
{
// PatBlt(hWindowDC,8,0,8,8,DSTINVERT);
Chipset.Shutdn = FALSE; // Prevent another ResumeThread
ResumeThread(hThread);
}
}
if (IR != 0)
{
if ((Chipset.inte) && (Chipset.intk))
{
// PatBlt(hWindowDC,0,8,8,8,DSTINVERT);
Chipset.SoftInt = TRUE;
bInterrupt = TRUE;
}
if (Chipset.Shutdn)
{
// PatBlt(hWindowDC,8,8,8,8,DSTINVERT);
Chipset.Shutdn = FALSE; // Prevent another ResumeThread
ResumeThread(hThread);
}
}
#endif
return;
}
@ -148,17 +89,12 @@ VOID KeyboardEvent(BOOL bPress, UINT out, UINT in)
{
_ASSERT(out<9);
if (bPress) // key pressed
{
// 11.06.98 cg, removed, do interrupt handling in ScanKeyboard()
// if (((Chipset.Keyboard_Row[out]&in) == 0) && (Chipset.inte==FALSE) && (Chipset.intk))
// Chipset.intd = TRUE;
Chipset.Keyboard_Row[out] |= in; // set key marker in keyboard row
}
else
Chipset.Keyboard_Row[out] &= (~in); // clear key marker in keyboard row
}
ScanKeyboard(FALSE); // 02.09.98 cg, changed, update Chipset.in register
bKeySlow = FALSE; // 18.11.98 cg, new, break key slow down
Sleep(50); // 28.09.98 cg, hold key state for a definite time
ScanKeyboard(FALSE); // update Chipset.in register
bKeySlow = FALSE; // break key slow down
Sleep(50); // hold key state for a definite time
return;
}

View file

@ -116,8 +116,8 @@ static TokenId eIsBlock[] =
static BOOL bClicking = FALSE;
static UINT uButtonClicked = 0;
static BOOL bPressed = FALSE; // 01.10.97 cg, no key pressed
static UINT uLastPressedKey = 0; // 01.10.97 cg, var for last pressed key
static BOOL bPressed = FALSE; // no key pressed
static UINT uLastPressedKey = 0; // var for last pressed key
//################
//#
@ -339,7 +339,6 @@ static BOOL CALLBACK ChooseKMLProc(HWND hDlg, UINT message, DWORD wParam, LONG l
if (wParam == IDC_UPDATE)
{
DestroyKmlList();
// 01.02.98 cg, calculate size of buffer
GetDlgItemText(hDlg,IDC_EMU48DIR,szEmu48Directory,sizeof(szEmu48Directory));
CreateKmlList();
hList = GetDlgItem(hDlg,IDC_KMLSCRIPT);
@ -356,7 +355,6 @@ static BOOL CALLBACK ChooseKMLProc(HWND hDlg, UINT message, DWORD wParam, LONG l
}
if (wParam == IDOK)
{
// 01.02.98 cg, calculate size of buffer
GetDlgItemText(hDlg,IDC_EMU48DIR,szEmu48Directory,sizeof(szEmu48Directory));
hList = GetDlgItem(hDlg,IDC_KMLSCRIPT);
nIndex = SendMessage(hList, CB_GETCURSEL, 0, 0);
@ -623,7 +621,7 @@ loop:
if (eToken != TOK_EOL)
{
PrintfToLog("%i: Too many parameters (%i expected).", nLexLine, j);
goto errline; // 09.03.99 cg, bugfix, free memory of arguments
goto errline; // free memory of arguments
}
return pLine;
}
@ -632,7 +630,7 @@ loop:
if (eToken != TOK_INTEGER)
{
PrintfToLog("%i: Parameter %i of %s must be an integer.", nLexLine, j+1, pLexToken[i].szName);
goto errline; // 09.03.99 cg, bugfix, free memory of arguments
goto errline; // free memory of arguments
}
pLine->nParam[j++] = nLexInteger;
nParams >>= 3;
@ -643,7 +641,7 @@ loop:
if (eToken != TOK_STRING)
{
PrintfToLog("%i: Parameter %i of %s must be a string.", nLexLine, j+1, pLexToken[i].szName);
goto errline; // 09.03.99 cg, bugfix, free memory of arguments
goto errline; // free memory of arguments
}
pLine->nParam[j++] = (DWORD)szLexString;
nParams >>= 3;
@ -651,7 +649,6 @@ loop:
}
AddToLog("Oops...");
errline:
// 09.03.99 cg, bugfix, free memory of all string arguments
// if last argument was string, free it
if (eToken == TOK_STRING) LocalFree(szLexString);
@ -664,7 +661,6 @@ errline:
}
nParams >>= 3; // next argument type
}
// 09.03.99 cg, end of bugfix
LocalFree(pLine);
return NULL;
}
@ -738,15 +734,15 @@ static Line* ParseLines()
if (IsBlock(eToken)) nLevel++;
if (eToken == TOK_INCLUDE)
{
LPSTR szFilename; // 11.09.98 cg
LPSTR szFilename;
eToken = Lex(LEX_PARAM); // get include parameter in 'szLexString'
if (eToken != TOK_STRING) // not a string (token don't begin with ")
{
AddToLog("Include: string expected as parameter.");
FatalError(); // 09.03.99 cg, moved from abort part
FatalError();
goto abort;
}
szFilename = szLexString; // 11.09.98 cg, save pointer to allocated memory
szFilename = szLexString; // save pointer to allocated memory
if (pFirst)
{
pLine->pNext = IncludeLines(szLexString);
@ -755,8 +751,8 @@ static Line* ParseLines()
{
pLine = pFirst = IncludeLines(szLexString);
}
LocalFree(szFilename); // 11.09.98 cg, bugfix, free memory
if (pLine == NULL) // 09.03.99 cg, bugfix, parsing error
LocalFree(szFilename); // free memory
if (pLine == NULL) // parsing error
goto abort;
while (pLine->pNext) pLine=pLine->pNext;
continue;
@ -781,7 +777,7 @@ static Line* ParseLines()
{
pLine = pFirst = ParseLine(eToken);
}
if (pLine == NULL) // 09.03.99 cg, bugfix, parsing error
if (pLine == NULL) // parsing error
goto abort;
}
if (nLinesIncludeLevel)
@ -793,7 +789,6 @@ static Line* ParseLines()
abort:
if (pFirst)
{
// pLine->pNext = NULL; // 09.03.99 cg, bugfix, pLine == NULL !
FreeLines(pFirst);
}
return NULL;
@ -846,7 +841,7 @@ static Block* ParseBlock(TokenId eType)
pBlock->pFirstLine = ParseLines();
if (pBlock->pFirstLine == NULL) // 09.03.99 cg, bugfix, break on ParseLines error
if (pBlock->pFirstLine == NULL) // break on ParseLines error
{
LocalFree(pBlock);
pBlock = NULL;
@ -922,21 +917,21 @@ static Block* ParseBlocks()
{
if (eToken == TOK_INCLUDE)
{
LPSTR szFilename; // 11.09.98 cg
LPSTR szFilename;
eToken = Lex(LEX_PARAM); // get include parameter in 'szLexString'
if (eToken != TOK_STRING) // not a string (token don't begin with ")
{
AddToLog("Include: string expected as parameter.");
FatalError(); // 09.03.99 cg, moved from abort part
FatalError();
goto abort;
}
szFilename = szLexString; // 11.09.98 cg, save pointer to allocated memory
szFilename = szLexString; // save pointer to allocated memory
if (pFirst)
pBlock = pBlock->pNext = IncludeBlocks(szLexString);
else
pBlock = pFirst = IncludeBlocks(szLexString);
LocalFree(szFilename); // 11.09.98 cg, bugfix, free memory
if (pBlock == NULL) // 09.03.99 cg, bugfix, parsing error
LocalFree(szFilename); // free memory
if (pBlock == NULL) // parsing error
goto abort;
while (pBlock->pNext) pBlock=pBlock->pNext;
continue;
@ -948,7 +943,7 @@ static Block* ParseBlocks()
if (pBlock == NULL)
{
AddToLog("Invalid block.");
FatalError(); // 09.03.99 cg, moved from abort part
FatalError();
goto abort;
}
}
@ -1076,7 +1071,7 @@ static Line* InitLcd(Block* pBlock)
nLcdY = pLine->nParam[1];
break;
case TOK_ZOOM:
nLcdDoubled = pLine->nParam[0]; // 24.08.98 cg, changed var type
nLcdDoubled = pLine->nParam[0];
if (nLcdDoubled != 1 && nLcdDoubled != 2 && nLcdDoubled != 4)
nLcdDoubled = 1;
break;
@ -1327,10 +1322,9 @@ static VOID FreeLines(Line* pLine)
{
if ((nParams&7) == TYPE_STRING) // string type
{
// 09.03.99 cg, bugfix, free string without incr. parameter buffer
LocalFree((LPVOID)pLine->nParam[i]);
}
i++; // 09.03.99 cg, bugfix, incr. parameter buffer index
i++; // incr. parameter buffer index
nParams >>= 3; // next argument type
}
pLine = pLine->pNext; // get next line
@ -1368,7 +1362,7 @@ VOID KillKML()
// 11.09.98, bugfix, unlock hPalette
if (hWindowDC) SelectPalette(hWindowDC, hOldPalette, FALSE);
err = DeleteObject(hPalette);
_ASSERT(err != FALSE); // 11.09.98 cg, freed resource memory
_ASSERT(err != FALSE); // freed resource memory
hPalette = NULL;
}
bClicking = FALSE;
@ -1453,7 +1447,7 @@ static VOID DrawButton(UINT nId)
UINT x0 = pButton[nId].nOx;
UINT y0 = pButton[nId].nOy;
EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
switch (pButton[nId].nType)
{
@ -1533,14 +1527,16 @@ static VOID DrawButton(UINT nId)
else
BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, x0, y0, SRCCOPY);
}
GdiFlush(); // 22.01.98 cg
GdiFlush();
}
LeaveCriticalSection(&csGDILock); // 22.01.98 cg
LeaveCriticalSection(&csGDILock);
return;
}
static VOID PressButton(UINT nId)
{
if (pButton[nId].bDown) return; // key already pressed -> exit
pButton[nId].bDown = TRUE;
DrawButton(nId);
if (pButton[nId].nIn)
@ -1605,7 +1601,7 @@ static VOID ReleaseButtonById(UINT nId)
return;
}
static VOID ReleaseAllButtons(VOID) // 01.10.97 cg, new, release all buttons
static VOID ReleaseAllButtons(VOID) // release all buttons
{
UINT i;
for (i=0; i<nButtons; i++) // scan all buttons
@ -1624,7 +1620,16 @@ VOID RefreshButtons()
UINT i;
for (i=0; i<nButtons; i++)
{
if (pButton[i].bDown) DrawButton(i);
if (pButton[i].bDown)
{
if (pButton[i].nType == 3) // on button type 3 clear complete key area before drawing
{
UINT x0 = pButton[i].nOx;
UINT y0 = pButton[i].nOy;
BitBlt(hWindowDC, x0, y0, pButton[i].nCx, pButton[i].nCy, hMainDC, x0, y0, SRCCOPY);
}
DrawButton(i); // redraw pressed button
}
}
return;
}
@ -1640,7 +1645,7 @@ VOID DrawAnnunciator(UINT nId, BOOL bOn)
{
nId--;
if (nId>=6) return;
EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
if (bOn)
{
@ -1660,9 +1665,9 @@ VOID DrawAnnunciator(UINT nId, BOOL bOn)
pAnnunciator[nId].nOx, pAnnunciator[nId].nOy,
SRCCOPY);
}
GdiFlush(); // 22.01.98 cg
GdiFlush();
}
LeaveCriticalSection(&csGDILock); // 22.01.98 cg
LeaveCriticalSection(&csGDILock);
return;
}
@ -1691,7 +1696,7 @@ VOID MouseButtonDownAt(UINT nFlags, DWORD x, DWORD y)
{
if (pButton[i].dwFlags&BUTTON_NOHOLD)
{
if (nFlags&MK_LBUTTON) // 01.10.97 cg, use only with left mouse button
if (nFlags&MK_LBUTTON) // use only with left mouse button
{
bClicking = TRUE;
uButtonClicked = i;
@ -1702,13 +1707,13 @@ VOID MouseButtonDownAt(UINT nFlags, DWORD x, DWORD y)
}
if (pButton[i].dwFlags&BUTTON_VIRTUAL)
{
if (!(nFlags&MK_LBUTTON)) // 01.10.97 cg, use only with left mouse button
if (!(nFlags&MK_LBUTTON)) // use only with left mouse button
return;
bClicking = TRUE;
uButtonClicked = i;
}
bPressed = TRUE; // 01.10.97 cg, key pressed
uLastPressedKey = i; // 01.10.97 cg, save pressed key
bPressed = TRUE; // key pressed
uLastPressedKey = i; // save pressed key
PressButton(i);
return;
}
@ -1718,14 +1723,11 @@ VOID MouseButtonDownAt(UINT nFlags, DWORD x, DWORD y)
VOID MouseButtonUpAt(UINT nFlags, DWORD x, DWORD y)
{
UINT i;
// begin with patch
if (bPressed) // 01.10.97 cg, emulator key pressed
if (bPressed) // emulator key pressed
{
ReleaseAllButtons(); // 01.10.97 cg, release all buttons
ReleaseAllButtons(); // release all buttons
return;
}
// continue with original part to look for nohold buttons
for (i=0; i<nButtons; i++)
{
if (ClipButton(x,y,i))
@ -1743,12 +1745,10 @@ VOID MouseButtonUpAt(UINT nFlags, DWORD x, DWORD y)
VOID MouseMovesTo(UINT nFlags, DWORD x, DWORD y)
{
// begin with patch
if (!(nFlags&MK_LBUTTON)) return; // left mouse key not pressed -> quit
if ((bPressed) && !(ClipButton(x,y,uLastPressedKey))) // 01.10.97 cg, not on last pressed key
ReleaseAllButtons(); // 01.10.97 cg, release all buttons
if ((bPressed) && !(ClipButton(x,y,uLastPressedKey))) // not on last pressed key
ReleaseAllButtons(); // release all buttons
if (!bClicking) return; // normal emulation key -> quit
// continue with original part
if (pButton[uButtonClicked].dwFlags&BUTTON_NOHOLD)
{
@ -1861,7 +1861,7 @@ BOOL InitKML(LPCSTR szFilename, BOOL bNoLog)
DWORD lBytesRead;
LPBYTE lpBuf;
Block* pBlock;
BOOL bOk;
BOOL bOk = FALSE; // 08.12.99 cg, bugfix, variable not initialized at error condition
BYTE bySum = 0;
KillKML();
@ -1943,7 +1943,6 @@ BOOL InitKML(LPCSTR szFilename, BOOL bNoLog)
goto quit;
}
CreateLcdBitmap();
Map(0x00,0xFF);
PrintfToLog("%i Buttons Defined", nButtons);
PrintfToLog("%i Scancodes Defined", nScancodes);

File diff suppressed because it is too large Load diff

2415
sources/Emu48/OPCODES.C Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -24,8 +24,8 @@ static UINT F_l[16] = {1,1/*P+1*/,1,3,1,12,2,16,0,0,0,0,0,0,0,5};
#define NFor(a, b, f) Nor((a)+F_s[f], (b)+F_s[f], F_l[f])
#define NFzero(a,f) memset((a)+F_s[f], 0, F_l[f])
#define NFpack(a, f) Npack((a)+F_s[f], F_l[f])
#define NFinc(a, f) Ninc(a, F_l[f], F_s[f]) // 24.03.98 cg, changed
#define NFdec(a, f) Ndec(a, F_l[f], F_s[f]) // 24.03.98 cg, changed
#define NFinc(a, f) Ninc(a, F_l[f], F_s[f])
#define NFdec(a, f) Ndec(a, F_l[f], F_s[f])
#define NFnot(a, f) Nnot((a)+F_s[f], F_l[f])
#define NFneg(a, f) Nneg((a)+F_s[f], F_l[f])
#define NFsl(a, f) Nsl((a)+F_s[f], F_l[f])
@ -40,9 +40,16 @@ static UINT F_l[16] = {1,1/*P+1*/,1,3,1,12,2,16,0,0,0,0,0,0,0,5};
#define TFbe(a, b, f) Tbe((a)+F_s[f], (b)+F_s[f], F_l[f])
#define TFnz(a, f) Tnz((a)+F_s[f], F_l[f])
static __inline LPBYTE FASTPTR(DWORD d)
{
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
return Chipset.IORam+d-Chipset.IOBase;
return RMap[d>>12]+(d&0xFFF);
}
static __inline void rstkpush(DWORD d)
{
Chipset.rstk[Chipset.rstkp] = d;
Chipset.rstkp=(Chipset.rstkp+1)&7;
}
@ -80,7 +87,6 @@ static __inline void Nxchg(BYTE *a, BYTE *b, UINT s)
memcpy(a, X, s);
}
// 24.03.98 cg, changed, new implementation
static __inline void Ninc(BYTE *a, UINT s, UINT d)
{
UINT i;
@ -98,9 +104,7 @@ static __inline void Ninc(BYTE *a, UINT s, UINT d)
}
Chipset.carry = TRUE;
}
// 24.03.98 cg, end of new implementation
// 15.02.99 cg, new function
static __inline void Ninc16(BYTE *a, UINT s, UINT d)
{
UINT i;
@ -117,7 +121,6 @@ static __inline void Ninc16(BYTE *a, UINT s, UINT d)
}
Chipset.carry = TRUE;
}
// 15.02.98 cg, end of new function
static __inline void Nincx(BYTE *a, UINT s)
{
@ -132,7 +135,6 @@ static __inline void Nincx(BYTE *a, UINT s)
Chipset.carry=TRUE;
}
// 24.03.98 cg, changed, new implementation
static __inline void Ndec(BYTE *a, UINT s, UINT d)
{
UINT i;
@ -150,9 +152,7 @@ static __inline void Ndec(BYTE *a, UINT s, UINT d)
}
Chipset.carry = TRUE;
}
// 24.03.98 cg, end of new implementation
// 15.02.99 cg, new function
static __inline void Ndec16(BYTE *a, UINT s, UINT d)
{
UINT i;
@ -169,9 +169,7 @@ static __inline void Ndec16(BYTE *a, UINT s, UINT d)
}
Chipset.carry = TRUE;
}
// 15.02.98 cg, end of new function
// 25.03.98 cg, optimized, new implementation
static __inline void Nadd(BYTE *a, BYTE *b, UINT s)
{
UINT i;
@ -191,9 +189,7 @@ static __inline void Nadd(BYTE *a, BYTE *b, UINT s)
}
Chipset.carry = (c==1);
}
// 25.03.98 cg, end of new implementation
// 25.03.98 cg, optimized, new implementation
static __inline void Nsub(BYTE *a, BYTE *b, UINT s)
{
UINT i;
@ -213,9 +209,7 @@ static __inline void Nsub(BYTE *a, BYTE *b, UINT s)
}
Chipset.carry = (c==1);
}
// 25.03.98 cg, end of new implementation
// 25.03.98 cg, optimized, new implementation
static __inline void Nrsub(BYTE *a, BYTE *b, UINT s)
{
UINT i;
@ -235,7 +229,6 @@ static __inline void Nrsub(BYTE *a, BYTE *b, UINT s)
}
Chipset.carry = (c==1);
}
// 25.03.98 cg, end of new implementation
static __inline void Nand(BYTE *a, BYTE *b, UINT s)
{
@ -247,7 +240,6 @@ static __inline void Nor(BYTE *a, BYTE *b, UINT s)
while (s--) a[s]|=b[s];
}
// 25.03.98 cg, optimized, new implementation
static __inline void Nnot(BYTE *a, UINT s)
{
BYTE cBase = Chipset.mode_dec ? 9 : 15;
@ -255,9 +247,7 @@ static __inline void Nnot(BYTE *a, UINT s)
while (s--) a[s] = cBase - a[s];
Chipset.carry = FALSE;
}
// 25.03.98 cg, end of new implementation
// 25.03.98 cg, optimized, new implementation
static __inline void Nneg(BYTE *a, UINT s)
{
UINT i;
@ -271,7 +261,6 @@ static __inline void Nneg(BYTE *a, UINT s)
a[i] = cBase - a[i];
}
}
// 25.03.98 cg, end of new implementation
static __inline void Nsl(BYTE *a, UINT s)
{

View file

@ -4,14 +4,21 @@
//
#define IDI_EMU48 100
#define IDR_MENU 101
#define IDB_EMPTY 102
#define IDD_ABOUT 103
#define IDD_ABOUTS 104
#define IDD_SETTINGS 105
#define IDD_CHOOSEKML 106
#define IDD_KMLLOG 107
#define IDD_REGISTER 108
#define IDD_DISASM 109
#define IDR_DEBUG 102
#define IDR_DEBUG_CODE 103
#define IDR_DEBUG_MEM 104
#define IDB_EMPTY 105
#define IDD_ABOUT 106
#define IDD_ABOUTS 107
#define IDD_SETTINGS 108
#define IDD_CHOOSEKML 109
#define IDD_KMLLOG 110
#define IDD_REGISTER 111
#define IDD_DISASM 112
#define IDD_DEBUG 113
#define IDD_NEWVALUE 114
#define IDD_ENTERADR 115
#define IDD_BREAKEDIT 116
#define IDC_PORT1WR 1000
#define IDC_AUTOSAVE 1001
#define IDC_AUTOSAVEONEXIT 1002
@ -48,6 +55,51 @@
#define IDC_DISASM_ADR 1033
#define IDC_DISASM_NEXT 1034
#define IDC_DISASM_COPY 1035
#define IDC_DEBUG_CODE 1036
#define IDC_STATIC_CODE 1037
#define IDC_STATIC_REGISTERS 1038
#define IDC_STATIC_MEMORY 1039
#define IDC_STATIC_STACK 1040
#define IDC_REG_A 1041
#define IDC_REG_B 1042
#define IDC_REG_C 1043
#define IDC_REG_D 1044
#define IDC_REG_R0 1045
#define IDC_REG_R1 1046
#define IDC_REG_R2 1047
#define IDC_REG_R3 1048
#define IDC_REG_R4 1049
#define IDC_REG_D0 1050
#define IDC_REG_D1 1051
#define IDC_REG_P 1052
#define IDC_REG_PC 1053
#define IDC_REG_OUT 1054
#define IDC_REG_IN 1055
#define IDC_REG_ST 1056
#define IDC_REG_CY 1057
#define IDC_REG_MODE 1058
#define IDC_REG_MP 1059
#define IDC_REG_SR 1060
#define IDC_REG_SB 1061
#define IDC_REG_XM 1062
#define IDC_NEWVALUE 1063
#define IDC_ENTERADR 1064
#define IDC_DEBUG_MEM 1065
#define IDC_DEBUG_MEM_ADDR 1066
#define IDC_DEBUG_MEM_COL0 1067
#define IDC_DEBUG_MEM_COL1 1068
#define IDC_DEBUG_MEM_COL2 1069
#define IDC_DEBUG_MEM_COL3 1070
#define IDC_DEBUG_MEM_COL4 1071
#define IDC_DEBUG_MEM_COL5 1072
#define IDC_DEBUG_MEM_COL6 1073
#define IDC_DEBUG_MEM_COL7 1074
#define IDC_DEBUG_MEM_TEXT 1075
#define IDC_DEBUG_STACK 1076
#define IDC_STATIC_BREAKPOINT 1077
#define IDC_BREAKEDIT_ADD 1078
#define IDC_BREAKEDIT_DELETE 1079
#define IDC_BREAKEDIT_WND 1080
#define ID_FILE_NEW 40001
#define ID_FILE_OPEN 40002
#define ID_FILE_SAVE 40003
@ -67,14 +119,32 @@
#define ID_STACK_COPY 40019
#define ID_STACK_PASTE 40020
#define ID_TOOL_DISASM 40021
#define ID_TOOL_DEBUG 40022
#define ID_DEBUG_RUN 40024
#define ID_DEBUG_STEP 40025
#define ID_DEBUG_STEPOVER 40026
#define ID_DEBUG_BREAK 40027
#define ID_BREAKPOINTS_SETBREAK 40028
#define ID_BREAKPOINTS_CODEEDIT 40029
#define ID_BREAKPOINTS_CLEARALL 40030
#define ID_DEBUG_CODE_GOADR 40031
#define ID_DEBUG_CODE_GOPC 40032
#define ID_DEBUG_CODE_SETPCTOSELECT 40033
#define ID_DEBUG_MEM_GOADR 40034
#define ID_DEBUG_MEM_GOPC 40035
#define ID_DEBUG_MEM_GOD0 40036
#define ID_DEBUG_MEM_GOD1 40037
#define ID_DEBUG_MEM_GOSTACK 40038
#define ID_BREAKPOINTS_NOP3 40039
#define ID_DEBUG_STEPOUT 40040
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 110
#define _APS_NEXT_COMMAND_VALUE 40022
#define _APS_NEXT_CONTROL_VALUE 1036
#define _APS_NEXT_RESOURCE_VALUE 117
#define _APS_NEXT_COMMAND_VALUE 40041
#define _APS_NEXT_CONTROL_VALUE 1081
#define _APS_NEXT_SYMED_VALUE 108
#endif
#endif

View file

@ -9,20 +9,20 @@
#include "pch.h"
#include "Emu48.h"
//| SX | GX | Name
//#7056A #806E9 =TEMPOB
//#7056F #806EE =TEMPTOP
//#70574 #806F3 =RSKTOP (B)
//#70579 #806F8 =DSKTOP (D1)
//#7066E #807ED =AVMEM (D)
//#705B0 #8072F =INTRPPTR (D0)
//| 38G | 48SX | 48GX | 49G | Name
// #7056A #806E9 #806E9 =TEMPOB
// #7056F #806EE #806EE =TEMPTOP
//#F0692 #70574 #806F3 #806F3 =RSKTOP (B)
//#F0697 #70579 #806F8 #806F8 =DSKTOP (D1)
//#F0DEA #7066E #807ED #80E9B =AVMEM (D)
//#F0705 #705B0 #8072F #8076B =INTRPPTR (D0)
#define TEMPOB ((cCurrentRomType=='S')?0x7056A:0x806E9)
#define TEMPTOP ((cCurrentRomType=='S')?0x7056F:0x806EE)
#define RSKTOP ((cCurrentRomType=='S')?0x70574:0x806F3)
#define DSKTOP ((cCurrentRomType=='S')?0x70579:0x806F8)
#define AVMEM ((cCurrentRomType=='S')?0x7066E:0x807ED)
#define INTRPPTR ((cCurrentRomType=='S')?0x705B0:0x8072F)
#define AVMEM ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x7066E:0x807ED):0x80E9B)
#define INTRPPTR ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x705B0:0x8072F):0x8076B)
DWORD RPL_SkipOb(DWORD d)
{
@ -33,6 +33,7 @@ DWORD RPL_SkipOb(DWORD d)
n = Npack(X, 5); // read prolog
switch (n)
{
case 0x026AC: l = (cCurrentRomType!='X') ? 5 : 12; break; // Flash PTR (HP49G)
case 0x02911: l = 10; break; // System Binary
case 0x02933: l = 21; break; // Real
case 0x02955: l = 26; break; // Long Real
@ -41,6 +42,12 @@ DWORD RPL_SkipOb(DWORD d)
case 0x029BF: l = 7; break; // Character
case 0x02BAA: l = 15; break; // Extended Pointer
case 0x02E92: l = 11; break; // XLIB Name
case 0x02686: // Symbolic matrix (HP49G)
if (cCurrentRomType!='X')
{
l = 5;
break;
}
case 0x02A74: // List
case 0x02AB8: // Algebraic
case 0x02ADA: // Unit
@ -71,6 +78,14 @@ DWORD RPL_SkipOb(DWORD d)
n = Npack(X,2)*2 + 4;
return RPL_SkipOb(d+n);
}
case 0x02614: // Precision Integer (HP49G)
case 0x026D5: // Aplet (HP49G)
case 0x026FE: // Mini Font (HP49G)
if (cCurrentRomType!='X')
{
l = 5;
break;
}
case 0x029E8: // Array
case 0x02A0A: // Linked Array
case 0x02A2C: // String
@ -79,12 +94,30 @@ DWORD RPL_SkipOb(DWORD d)
case 0x02B40: // Library
case 0x02B62: // Backup
case 0x02B88: // Library Data
case 0x02BCC: // Reserved 1
case 0x02BCC: // Reserved 1, Font (HP49G)
case 0x02BEE: // Reserved 2
case 0x02C10: // Reserved 3
case 0x02DCC: // Code
l = 5+Read5(d+5);
break;
case 0x0263A: // Precision Real (HP49G)
l = 5;
if (cCurrentRomType=='X')
{
l += Read5(d+l);
l += Read5(d+l);
}
break;
case 0x02660: // Precision Complex (HP49G)
l = 5;
if (cCurrentRomType=='X')
{
l += Read5(d+l);
l += Read5(d+l);
l += Read5(d+l);
l += Read5(d+l);
}
break;
default: return d+5;
}
return d+l;
@ -97,6 +130,7 @@ DWORD RPL_ObjectSize(BYTE *o)
n = Npack(o, 5); // read prolog
switch (n)
{
case 0x026AC: l = (cCurrentRomType!='X') ? 5 : 12; break; // Flash PTR (HP49G)
case 0x02911: l = 10; break; // System Binary
case 0x02933: l = 21; break; // Real
case 0x02955: l = 26; break; // Long Real
@ -105,6 +139,12 @@ DWORD RPL_ObjectSize(BYTE *o)
case 0x029BF: l = 7; break; // Character
case 0x02BAA: l = 15; break; // Extended Pointer
case 0x02E92: l = 11; break; // XLIB Name
case 0x02686: // Symbolic matrix (HP49G)
if (cCurrentRomType!='X')
{
l = 5;
break;
}
case 0x02A74: // List
case 0x02AB8: // Algebraic
case 0x02ADA: // Unit
@ -134,6 +174,14 @@ DWORD RPL_ObjectSize(BYTE *o)
l += RPL_ObjectSize(o+l);
}
break;
case 0x02614: // Precision Integer (HP49G)
case 0x026D5: // Aplet (HP49G)
case 0x026FE: // Mini Font (HP49G)
if (cCurrentRomType!='X')
{
l = 5;
break;
}
case 0x029E8: // Array
case 0x02A0A: // Linked Array
case 0x02A2C: // String
@ -142,12 +190,30 @@ DWORD RPL_ObjectSize(BYTE *o)
case 0x02B40: // Library
case 0x02B62: // Backup
case 0x02B88: // Library Data
case 0x02BCC: // Reserved 1
case 0x02BCC: // Reserved 1, Font (HP49G)
case 0x02BEE: // Reserved 2
case 0x02C10: // Reserved 3
case 0x02DCC: // Code
l = 5 + Npack(o+5,5);
break;
case 0x0263A: // Precision Real (HP49G)
l = 5;
if (cCurrentRomType=='X')
{
l += Npack(o+l,5);
l += Npack(o+l,5);
}
break;
case 0x02660: // Precision Complex (HP49G)
l = 5;
if (cCurrentRomType=='X')
{
l += Npack(o+l,5);
l += Npack(o+l,5);
l += Npack(o+l,5);
l += Npack(o+l,5);
}
break;
default: l=5;
}
return l;
@ -178,13 +244,13 @@ DWORD RPL_Pick(UINT l)
{
DWORD stkp;
_ASSERT(l > 0); // 12.11.98 cg, new, first stack elememt is one
_ASSERT(l > 0); // first stack elememt is one
if (l==0) return 0;
stkp = Read5(DSKTOP) + (l-1)*5;
return Read5(stkp);
}
#if 0 // 12.11.98 cg, function not needed yet
#if 0 // function not needed yet
VOID RPL_Replace(DWORD n)
{
DWORD stkp;

View file

@ -8,10 +8,17 @@
*/
#include "pch.h"
#include "Emu48.h"
#include "Serial.h"
#include "io.h" // 24.10.99 cg, renamed from Serial.h
#define INTERRUPT ((void)(Chipset.SoftInt=TRUE,bInterrupt=TRUE))
// 25.10.99 cg, new, state of USRQ
#define NINT2ERBZ ((Chipset.IORam[IOC] & ERBZ) != 0 && (Chipset.IORam[RCS] & RBZ) != 0)
#define NINT2ERBF ((Chipset.IORam[IOC] & ERBF) != 0 && (Chipset.IORam[RCS] & RBF) != 0)
#define NINT2ETBE ((Chipset.IORam[IOC] & ETBE) != 0 && (Chipset.IORam[TCS] & TBF) == 0)
#define NINT2USRQ (NINT2ERBZ || NINT2ERBF || NINT2ETBE)
static OVERLAPPED os = { 0 };
static HANDLE hComm = NULL;
static HANDLE hCThread = NULL;
@ -19,7 +26,11 @@ static DWORD lSerialThreadId = 0;
static BOOL bReading = TRUE;
static WORD wPort = PORT_CLOSE;
static CRITICAL_SECTION csRecv; // 01.06.98 cg, new, critical section for receive byte
static BYTE cBuffer[128];
static WORD nRp;
static DWORD dwBytesRead = 0L;
// static CRITICAL_SECTION csRecv; // 24.10.99 cg, moved to main function
static DWORD WINAPI SerialThread(LPVOID pParam)
{
@ -34,7 +45,10 @@ static DWORD WINAPI SerialThread(LPVOID pParam)
CommReceive(); // get data
// interrupt request and emulation thread down
if (Chipset.SoftInt && Chipset.Shutdn)
ResumeThread(hThread); // wake up emulation thread
{
Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode
SetEvent(hEventShutdn); // wake up emulation thread
}
}
}
lSerialThreadId = 0; // signal serial thread is down
@ -42,7 +56,6 @@ static DWORD WINAPI SerialThread(LPVOID pParam)
UNREFERENCED_PARAMETER(pParam);
}
WORD CommConnect(VOID)
{
return wPort;
@ -54,6 +67,7 @@ VOID CommOpen(LPSTR strWirePort,LPSTR strIrPort)
LPSTR strPort = (Chipset.IORam[IR_CTRL] & EIRU) ? strIrPort : strWirePort;
_ASSERT(Chipset.IORam[IOC] & SON); // UART on
if (hComm != NULL) // port already open
CloseHandle(hComm);
@ -69,8 +83,7 @@ VOID CommOpen(LPSTR strWirePort,LPSTR strIrPort)
if(hComm != INVALID_HANDLE_VALUE)
{
// 01.06.98 cg, bugfix, initialize critical section
InitializeCriticalSection(&csRecv);
// InitializeCriticalSection(&csRecv);
wPort = (Chipset.IORam[IR_CTRL] & EIRU) ? PORT_IR : PORT_WIRE;
SetCommTimeouts(hComm,&CommTimeouts);
@ -92,6 +105,7 @@ VOID CommOpen(LPSTR strWirePort,LPSTR strIrPort)
OutputDebugString(buffer);
}
#endif
return;
}
VOID CommClose(VOID)
@ -106,9 +120,10 @@ VOID CommClose(VOID)
#if defined DEBUG_SERIAL
OutputDebugString("COM port closed.\n");
#endif
DeleteCriticalSection(&csRecv); // 01.06.98 cg, bugfix, release critical section
// DeleteCriticalSection(&csRecv);
wPort = PORT_CLOSE;
}
return;
}
VOID CommSetBaud(VOID)
@ -147,6 +162,13 @@ VOID CommSetBaud(VOID)
SetCommState(hComm,&dcb);
}
return;
}
VOID UpdateUSRQ(VOID) // 25.10.99 cg, new, USRQ handling
{
IOBit(SRQ1,USRQ,NINT2USRQ); // update USRQ bit
return;
}
VOID CommTransmit(VOID)
@ -166,36 +188,42 @@ VOID CommTransmit(VOID)
}
#endif
if (hComm != NULL) // wire com port open
// 23.10.99 cg, bugfix, add serial loopback support
if (Chipset.IORam[TCS] & LPB) // is loopback bit set
{
cBuffer[nRp+dwBytesRead] = tbr; // save character in receive buffer
++dwBytesRead;
CommReceive(); // receive byte available
}
// 23.10.99 cg, end of implementation
if (hComm != NULL) // com port open
WriteFile(hComm,(LPCVOID) &tbr,1,&dwWritten,&os);
Chipset.IORam[TCS] &= (~TBF); // clear transmit buffer
if (Chipset.IORam[IO_CTRL] & ETBE) // interrupt on transmit buffer empty
UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ bit
if (Chipset.IORam[IOC] & ETBE) // interrupt on transmit buffer empty
INTERRUPT;
return;
}
VOID CommReceive(VOID)
{
static BYTE cBuffer[128];
static WORD nRp;
static DWORD dwBytesRead = 0L;
if (hComm == NULL) // not open
return;
if (!(Chipset.IORam[IO_CTRL] & SON)) // UART off
if (!(Chipset.IORam[IOC] & SON)) // UART off
{
dwBytesRead = 0L; // no bytes received
return;
}
EnterCriticalSection(&csRecv); // 01.06.98 cg, bugfix, synchronize
EnterCriticalSection(&csRecvLock);
do
{
if (Chipset.IORam[RCS] & RBF) // receive buffer full
break;
if (dwBytesRead == 0L) // buffer empty
// 23.10.99 cg, bugfix, reject reading if com port is closed and not whole operation
if (hComm && dwBytesRead == 0L) // com port open and buffer empty
{
if(ReadFile(hComm,&cBuffer,sizeof(cBuffer),&dwBytesRead,&os) == FALSE)
dwBytesRead = 0L;
@ -223,9 +251,11 @@ VOID CommReceive(VOID)
--dwBytesRead;
Chipset.IORam[RCS] |= RBF; // receive buffer full
if (Chipset.IORam[IO_CTRL] & ERBF) // interrupt on recv buffer full
UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ bit
if (Chipset.IORam[IOC] & ERBF) // interrupt on recv buffer full
INTERRUPT;
}
while(0);
LeaveCriticalSection(&csRecv); // 01.06.98 cg
LeaveCriticalSection(&csRecvLock);
return;
}

View file

@ -1,44 +0,0 @@
/*
* Serial.h
*
* This file is part of Emu48
*
* Copyright (C) 1998 Christoph Gießelink
*
*/
// UART addresses without mapping offset
#define BAUD 0x0d // Baudrate (Bit 2-0)
#define IO_CTRL 0x10 // IO CONTROL
#define RCS 0x11 // RCS
#define TCS 0x12 // TCS
#define CRER 0x13 // CRER
#define RBR_LSB 0x14 // RBR low nibble
#define RBR_MSB 0x15 // RBR high nibble
#define TBR_LSB 0x16 // TBR low nibble
#define TBR_MSB 0x17 // TBR high nibble
#define IR_CTRL 0x1a // IR CONTROL
// 0x10 Serial I/O Control [SON ETBE ERBF ERBZ]
#define SON 0x08 // Serial on
#define ETBE 0x04 // Interrupt on transmit buffer empty
#define ERBF 0x02 // Interrupt on receive buffer full
#define ERBZ 0x01 // Interrupt on receiver busy
// 0x11 Serial Receive Control/Status [RX RER RBZ RBF]
#define RX 0x08 // ??? Rx pin high (read-only)
#define RER 0x04 // Receiver error
#define RBZ 0x02 // Receiver busy
#define RBF 0x01 // Receive buffer full
// 0x12 Serial Transmit Control/Status [BRK LPB TBZ TBF]
#define BRK 0x08
#define LPB 0x04
#define TBZ 0x02 // Transmitter busy
#define TBF 0x01 // Transmit buffer full
// 0x1a IR Control Register [IRI EIRU EIRI IRE]
#define IRI 0x08 // IR input (read-only)
#define EIRU 0x04 // Enable IR UART mode
#define EIRI 0x02 // Enable IR interrupt
#define IRE 0x01 // IR event

76
sources/Emu48/SETTINGS.C Normal file
View file

@ -0,0 +1,76 @@
/*
* settings.c
*
* This file is part of Emu48
*
* Copyright (C) 1995 Sebastien Carlier
* Copyright (C) 1999 Christoph Gießelink
*
*/
#include "pch.h"
#include "Emu48.h"
#define EMU48_INI "Emu48.ini"
static BOOL WritePrivateProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue, LPCTSTR lpszFilename)
{
char s[16];
wsprintf(s,"%i",nValue);
return WritePrivateProfileString(lpszSection, lpszEntry, s, lpszFilename);
}
VOID ReadSettings(VOID)
{
// Files
GetPrivateProfileString("Files","Emu48Directory",szCurrentDirectory,szEmu48Directory,
sizeof(szEmu48Directory),EMU48_INI);
bAutoSave = GetPrivateProfileInt("Files","AutoSave",bAutoSave,EMU48_INI);
bAutoSaveOnExit = GetPrivateProfileInt("Files","AutoSaveOnExit",bAutoSaveOnExit,EMU48_INI);
// Port2
bPort2IsShared = GetPrivateProfileInt("Port2","IsShared",0,EMU48_INI);
GetPrivateProfileString("Port2","Filename","SHARED.BIN",szPort2Filename,sizeof(szPort2Filename),EMU48_INI);
// KML
bAlwaysDisplayLog = GetPrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI);
// Emulator
bRealSpeed = GetPrivateProfileInt("Emulator","RealSpeed",0,EMU48_INI);
dwSXCycles = GetPrivateProfileInt("Emulator","SXCycles",82,EMU48_INI);
dwGXCycles = GetPrivateProfileInt("Emulator","GXCycles",123,EMU48_INI);
SetSpeed(bRealSpeed); // set speed
// Serial
GetPrivateProfileString("Serial","Wire",NO_SERIAL,szSerialWire,sizeof(szSerialWire),EMU48_INI);
GetPrivateProfileString("Serial","Ir",NO_SERIAL,szSerialIr,sizeof(szSerialIr),EMU48_INI);
return;
}
VOID WriteSettings(VOID)
{
// Files
WritePrivateProfileString("Files","Emu48Directory",szEmu48Directory,EMU48_INI);
WritePrivateProfileInt("Files","AutoSave",bAutoSave,EMU48_INI);
WritePrivateProfileInt("Files","AutoSaveOnExit",bAutoSaveOnExit,EMU48_INI);
// Port2
WritePrivateProfileInt("Port2","IsShared",bPort2IsShared,EMU48_INI);
WritePrivateProfileString("Port2","Filename",szPort2Filename,EMU48_INI);
// KML
WritePrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI);
// Emulator
WritePrivateProfileInt("Emulator","RealSpeed",bRealSpeed,EMU48_INI);
WritePrivateProfileInt("Emulator","SXCycles",dwSXCycles,EMU48_INI);
WritePrivateProfileInt("Emulator","GXCycles",dwGXCycles,EMU48_INI);
// Serial
WritePrivateProfileString("Serial","Wire",szSerialWire,EMU48_INI);
WritePrivateProfileString("Serial","Ir",szSerialIr,EMU48_INI);
return;
}
VOID ReadLastDocument(LPTSTR szFilename, DWORD nSize)
{
GetPrivateProfileString("Files","LastDocument","",szFilename,nSize,EMU48_INI);
return;
}
VOID WriteLastDocument(LPCTSTR szFilename)
{
WritePrivateProfileString("Files","LastDocument",szFilename,EMU48_INI);
return;
}

View file

@ -8,63 +8,198 @@
*/
#include "pch.h"
#include "Emu48.h"
#include "io.h" // 24.10.99 cg, new, I/O definitions
#define AUTO_OFF 10 // 25.02.98 cg, new, Time in minutes for 'auto off'
#define AUTO_OFF 10 // Time in minutes for 'auto off'
// 25.02.98 cg, new, Ticks for 01.01.1970 00:00:00
// Ticks for 01.01.1970 00:00:00
#define UNIX_0_TIME 0x0001cf2e8f800000
// 25.02.98 cg, new, Ticks for 'auto off'
// Ticks for 'auto off'
#define OFF_TIME ((LONGLONG) (AUTO_OFF * 60) << 13)
// 30.09.98 cg, new, memory address for clock and auto off
// S(X) = 0x70052-0x70070, G(X) = 0x80058-0x80076
// memory address for clock and auto off
// S(X) = 0x70052-0x70070, G(X) = 0x80058-0x80076, 49G = 0x80058-0x80076
#define RPLTIME ((cCurrentRomType=='S')?0x52:0x58)
#define T1_FREQ 62 // 10.11.98 cg, new, Timer1 1/frequency in ms
#define T2_FREQ 8192 // 06.04.98 cg, new, Timer2 frequency
// 27.02.98 cg, new, Timer definitions
// Timer addresses without mapping offset
#define TIMER1_CTRL 0x2e // Timer1 Control
#define TIMER2_CTRL 0x2f // Timer2 Control
#define TIMER1 0x37 // Timer1 (4 bit)
#define TIMER2 0x3f // Timer2 (32 bit, LSB first)
// 0x2e Timer1 Control [SRQ WKE INT XTRA]
#define SRQ 0x08 // Service request
#define WKE 0x04 // Wake up
#define INT 0x02 // Interrupt
#define XTRA 0x01 // Extra function
// 0x2f Timer2 Control [SRQ WKE INT RUN]
#define SRQ 0x08 // Service request
#define WKE 0x04 // Wake up
#define INT 0x02 // Interrupt
#define RUN 0x01 // Timer run
// BOOL bAccurateTimer = TRUE; // 10.11.98 cg, removed, not adjustable any more
// UINT uT1Period = 62; // 10.11.98 cg, removed, not adjustable any more
#define T1_FREQ 62 // Timer1 1/frequency in ms
#define T2_FREQ 8192 // Timer2 frequency
static BOOL bStarted = FALSE;
static BOOL bOutRange = FALSE; // 21.04.98 cg, new, flag if timer value out of range
static BOOL bOutRange = FALSE; // flag if timer value out of range
static UINT uT1TimerId = 0;
static UINT uT2TimerId = 0;
// static DWORD dwT1Ticks = 0; // 19.02.98 cg, removed, not used
// static DWORD dwT2Init = 0; // 06.04.98 cg, removed, not used any more
// static DWORD dwT2Step = 0; // 06.04.98 cg, removed, not used any more
// static DWORD dwT2Ticks = 0; // 06.04.98 cg, removed, not used any more
static BOOL bAccurateTimer; // 10.11.98 cg, new, flag if accurate timer is used
static LARGE_INTEGER lT2Ref; // 06.04.98 cg, new, counter value at timer2 start
static TIMECAPS tc; // 21.04.98 cg, new, timer information
static BOOL bNINT2T1 = FALSE; // 24.10.99 cg, new, state of NINT2 affected form Timer1
static BOOL bNINT2T2 = FALSE; // 24.10.99 cg, new, state of NINT2 affected form Timer2
static BOOL bAccurateTimer; // flag if accurate timer is used
static LARGE_INTEGER lT2Ref; // counter value at timer2 start
static TIMECAPS tc; // timer information
static __inline MAX(int a, int b) {return (a>b)?a:b;}
static void CALLBACK TimeProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2);
static VOID SetAccesstime(VOID) // 06.10.97 cg, new, set date and time
static DWORD CalcT2(VOID) // calculate timer2 value
{
DWORD dwT2 = Chipset.t2; // get value from chipset
if (bStarted) // timer2 running
{
LARGE_INTEGER lT2Act;
QueryPerformanceCounter(&lT2Act); // actual time
// calculate ticks since reference point
dwT2 -= (DWORD)
(((lT2Act.QuadPart - lT2Ref.QuadPart) * T2_FREQ)
/ lFreq.QuadPart);
}
return dwT2;
}
static VOID CheckT1(BYTE nT1)
{
// 24.10.99 cg, bugfix, implementation of TSRQ
bNINT2T1 = (Chipset.IORam[TIMER1_CTRL]&INTR) != 0 && (nT1&8) != 0;
IOBit(SRQ1,TSRQ,bNINT2T1 || bNINT2T2);
// 24.10.99 cg, end of implementation
if ((nT1&8) == 0) // timer1 MSB not set
{
Chipset.IORam[TIMER1_CTRL] &= ~SRQ; // clear SRQ bit
return;
}
_ASSERT((nT1&8) != 0); // timer1 MSB set
// timer MSB is one and either INT or WAKE is set
if ( (Chipset.IORam[TIMER1_CTRL]&WKE)
|| (Chipset.IORam[TIMER1_CTRL]&INTR))
Chipset.IORam[TIMER1_CTRL] |= SRQ; // set SRQ
// cpu not sleeping and T1 -> Interrupt
if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER1_CTRL]&WKE))
&& (Chipset.IORam[TIMER1_CTRL]&INTR))
{
Chipset.SoftInt = TRUE;
bInterrupt = TRUE;
}
// cpu sleeping and T1 -> Wake Up
if (Chipset.Shutdn && (Chipset.IORam[TIMER1_CTRL]&WKE))
{
Chipset.IORam[TIMER1_CTRL] &= ~WKE; // clear WKE bit
Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode
SetEvent(hEventShutdn); // wake up emulation thread
}
return;
}
static VOID CheckT2(DWORD dwT2)
{
// 24.10.99 cg, bugfix, implementation of TSRQ
bNINT2T2 = (Chipset.IORam[TIMER2_CTRL]&INTR) != 0 && (dwT2&0x80000000) != 0;
IOBit(SRQ1,TSRQ,bNINT2T1 || bNINT2T2);
// 24.10.99 cg, end of implementation
if ((dwT2&0x80000000) == 0) // timer2 MSB not set
{
Chipset.IORam[TIMER2_CTRL] &= ~SRQ; // clear SRQ bit
return;
}
_ASSERT((dwT2&0x80000000) != 0); // timer2 MSB set
// timer MSB is one and either INT or WAKE is set
if ( (Chipset.IORam[TIMER2_CTRL]&WKE)
|| (Chipset.IORam[TIMER2_CTRL]&INTR))
Chipset.IORam[TIMER2_CTRL] |= SRQ; // set SRQ
// cpu not sleeping and T2 -> Interrupt
if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER2_CTRL]&WKE))
&& (Chipset.IORam[TIMER2_CTRL]&INTR))
{
Chipset.SoftInt = TRUE;
bInterrupt = TRUE;
}
// cpu sleeping and T2 -> Wake Up
if (Chipset.Shutdn && (Chipset.IORam[TIMER2_CTRL]&WKE))
{
Chipset.IORam[TIMER2_CTRL] &= ~WKE; // clear WKE bit
Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode
SetEvent(hEventShutdn); // wake up emulation thread
}
return;
}
static VOID RescheduleT2(BOOL bRefPoint)
{
UINT uDelay;
_ASSERT(uT2TimerId == 0); // timer2 must stopped
if (bRefPoint) // save reference time
{
QueryPerformanceCounter(&lT2Ref); // time of corresponding Chipset.t2 value
uDelay = Chipset.t2; // timer value for delay
}
else // called without new refpoint, restart t2 with actual value
{
uDelay = CalcT2(); // actual timer value for delay
}
uDelay &= 0x7FFFFFFF; // execute timer2 event when MSB change
uDelay >>= 3; // timer delay in ms
uDelay = MAX(tc.wPeriodMin,uDelay); // wait minimum delay of timer
if (bOutRange = uDelay > tc.wPeriodMax) // delay greater maximum delay
uDelay = tc.wPeriodMax; // wait maximum delay time
// start timer2; schedule event, when Chipset.t2 will be zero (Chipset.t2 / 8 = time in ms)
uT2TimerId = timeSetEvent(uDelay,0,(LPTIMECALLBACK)&TimeProc,2,TIME_ONESHOT);
_ASSERT(uT2TimerId); // test if timer2 started
return;
}
static VOID AbortT2(VOID)
{
_ASSERT(uT2TimerId);
timeKillEvent(uT2TimerId); // kill event
uT2TimerId = 0; // then reset var
return;
}
static void CALLBACK TimeProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
_ASSERT(uEventId); // illegal EventId
if (!bStarted) // timer stopped
return; // -> quit
if (uEventId == uT1TimerId) // called from timer1 event (default period 16 Hz)
{
EnterCriticalSection(&csT1Lock);
{
Chipset.t1 = (Chipset.t1-1)&0xF;// decrement timer value
CheckT1(Chipset.t1); // test timer1 control bits
}
LeaveCriticalSection(&csT1Lock);
return;
}
if (uEventId == uT2TimerId) // called from timer2 event, Chipset.t2 should be zero
{
EnterCriticalSection(&csT2Lock);
{
uT2TimerId = 0; // single shot timer timer2 stopped
if (!bOutRange) // timer event elapsed
{
// timer2 overrun, test timer2 control bits else restart timer2
Chipset.t2 = CalcT2(); // calculate new timer2 value
CheckT2(Chipset.t2); // test timer2 control bits
}
RescheduleT2(!bOutRange); // restart timer2
}
LeaveCriticalSection(&csT2Lock);
return;
}
return;
UNREFERENCED_PARAMETER(uMsg);
UNREFERENCED_PARAMETER(dwUser);
UNREFERENCED_PARAMETER(dw1);
UNREFERENCED_PARAMETER(dw2);
}
VOID SetHP48Time(VOID) // set date and time
{
SYSTEMTIME ts;
LONGLONG ticks, time;
@ -104,188 +239,33 @@ static VOID SetAccesstime(VOID) // 06.10.97 cg, new, set date and time
time = ticks; // save for calc. timeout
time += OFF_TIME; // add 10 min for auto off
dw = RPLTIME; // 30.09.98, bugfix, HP addresses for clock in port0
dw = RPLTIME; // HP addresses for clock in port0
crc = 0x0; // reset crc value
for (i = 0; i < 13; ++i, ++dw) // write date and time
{
*p = (BYTE) ticks & 0xf;
crc = (crc >> 4) ^ (((crc ^ ((WORD) *p)) & 0xf) * 0x1081);
Chipset.Port0[dw] = *p; // 30.09.98, bugfix, always store in port0
Chipset.Port0[dw] = *p; // always store in port0
ticks >>= 4;
}
Nunpack(p,crc,4); // write crc
memcpy(Chipset.Port0+dw,p,4); // 30.09.98, bugfix, always store in port0
memcpy(Chipset.Port0+dw,p,4); // always store in port0
dw += 4; // HP addresses for timeout
for (i = 0; i < 13; ++i, ++dw) // write time for auto off
{
// 30.09.98, bugfix, always store in port0
// always store in port0
Chipset.Port0[dw] = (BYTE) time & 0xf;
time >>= 4;
}
Chipset.Port0[dw] = 0xf; // 30.09.98, bugfix, always store in port0
Chipset.Port0[dw] = 0xf; // always store in port0
return;
}
static DWORD CalcT2(VOID) // 21.04.98 cg, new, calculate timer2 value
{
DWORD dwT2 = Chipset.t2; // get value from chipset
if (bStarted) // timer2 running
{
LARGE_INTEGER lT2Act;
QueryPerformanceCounter(&lT2Act); // actual time
// calculate ticks since reference point
dwT2 -= (DWORD)
(((lT2Act.QuadPart - lT2Ref.QuadPart) * T2_FREQ)
/ lFreq.QuadPart);
}
return dwT2;
}
static VOID CheckT1(BYTE nT1) // 25.11.98 cg, bugfix, changed implementation
{
if ((nT1&8) == 0) // timer1 MSB not set
{
Chipset.IORam[TIMER1_CTRL] &= ~SRQ; // clear SRQ bit
return;
}
_ASSERT((nT1&8) != 0); // timer1 MSB set
// timer MSB is one and either INT or WAKE is set
if ( (Chipset.IORam[TIMER1_CTRL]&WKE)
|| (Chipset.IORam[TIMER1_CTRL]&INT))
Chipset.IORam[TIMER1_CTRL] |= SRQ; // set SRQ
// cpu not sleeping and T1 -> Interrupt
if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER1_CTRL]&WKE))
&& (Chipset.IORam[TIMER1_CTRL]&INT))
{
Chipset.SoftInt = TRUE;
bInterrupt = TRUE;
}
// cpu sleeping and T1 -> Wake Up
if (Chipset.Shutdn && (Chipset.IORam[TIMER1_CTRL]&WKE))
{
Chipset.IORam[TIMER1_CTRL] &= ~WKE; // clear WKE bit
ResumeThread(hThread); // wake up emulation thread
}
return;
}
static VOID CheckT2(DWORD dwT2) // 25.11.98 cg, bugfix, changed implementation
{
if ((dwT2&0x80000000) == 0) // timer2 MSB not set
{
Chipset.IORam[TIMER2_CTRL] &= ~SRQ; // clear SRQ bit
return;
}
_ASSERT((dwT2&0x80000000) != 0); // timer2 MSB set
// timer MSB is one and either INT or WAKE is set
if ( (Chipset.IORam[TIMER2_CTRL]&WKE)
|| (Chipset.IORam[TIMER2_CTRL]&INT))
Chipset.IORam[TIMER2_CTRL] |= SRQ; // set SRQ
// cpu not sleeping and T2 -> Interrupt
if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER2_CTRL]&WKE))
&& (Chipset.IORam[TIMER2_CTRL]&INT))
{
Chipset.SoftInt = TRUE;
bInterrupt = TRUE;
}
// cpu sleeping and T2 -> Wake Up
if (Chipset.Shutdn && (Chipset.IORam[TIMER2_CTRL]&WKE))
{
Chipset.IORam[TIMER2_CTRL] &= ~WKE; // clear WKE bit
ResumeThread(hThread); // wake up emulation thread
}
return;
}
static VOID RescheduleT2(BOOL bRefPoint) // 21.04.98 cg, add function parameter
{
UINT uDelay;
_ASSERT(uT2TimerId == 0); // timer2 must stopped
// 29.09.98 cg, bugfix, changed implementation
if (bRefPoint) // save reference time
{
QueryPerformanceCounter(&lT2Ref); // time of corresponding Chipset.t2 value
uDelay = Chipset.t2; // timer value for delay
}
else // called without new refpoint, restart t2 with actual value
{
uDelay = CalcT2(); // actual timer value for delay
}
uDelay &= 0x7FFFFFFF; // 24.11.98 cg, bugfix, execute timer2 event when MSB change
uDelay >>= 3; // timer delay in ms
uDelay = MAX(tc.wPeriodMin,uDelay); // wait minimum delay of timer
if (bOutRange = uDelay > tc.wPeriodMax) // delay greater maximum delay
uDelay = tc.wPeriodMax; // wait maximum delay time
// 29.09.98 cg, end of changed implementation
// dwT2Init = timeGetTime(); // 06.04.98 cg, not used any more
// dwT2Ticks = dwT2Init; // 06.04.98 cg, not used any more
// start timer2; schedule event, when Chipset.t2 will be zero (Chipset.t2 / 8 = time in ms)
uT2TimerId = timeSetEvent(uDelay,0,(LPTIMECALLBACK)&TimeProc,2,TIME_ONESHOT);
_ASSERT(uT2TimerId); // 21.04.98 cg, new, test if timer2 started
return;
}
static VOID AbortT2(VOID)
{
_ASSERT(uT2TimerId);
timeKillEvent(uT2TimerId); // 09.10.97 cg, bugfix, first kill event
uT2TimerId = 0; // 09.10.97 cg, bugfix, then reset var
return;
}
static void CALLBACK TimeProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
_ASSERT(uEventId); // 16.03.98 cg, new, illegal EventId
if (!bStarted) // timer stopped
return; // -> quit
// called from timer1 event (default period 16 Hz)
// if ((uT1TimerId!=0) && (uEventId == uT1TimerId))
if (uEventId == uT1TimerId) // 16.03.98 cg, removed useless part
{
EnterCriticalSection(&csT1Lock); // 21.04.98 cg, bugfix, synchronize
{
Chipset.t1 = (Chipset.t1-1)&0xF;// decrement timer value
CheckT1(Chipset.t1); // test timer1 control bits
}
LeaveCriticalSection(&csT1Lock); // 21.04.98 cg
return;
}
// called from timer2 event, Chipset.t2 should be zero
// if ((uT2TimerId!=0) && (uEventId == uT2TimerId))
if (uEventId == uT2TimerId) // 16.03.98 cg, removed useless part
{
EnterCriticalSection(&csT2Lock); // 21.04.98 cg, bugfix, synchronize
{
uT2TimerId = 0; // 30.11.98 cg, bugfix, single shot timer timer2 stopped
if (!bOutRange) // 21.04.98 cg, timer event elapsed
{
// timer2 overrun, test timer2 control bits else restart timer2
// 16.11.98 cg, bugfix, don't wait for timer2 overrun any more
Chipset.t2 = CalcT2(); // calculate new timer2 value
CheckT2(Chipset.t2); // test timer2 control bits
}
RescheduleT2(!bOutRange); // restart timer2
}
LeaveCriticalSection(&csT2Lock); // 21.04.98 cg
return;
}
return;
UNREFERENCED_PARAMETER(uMsg);
UNREFERENCED_PARAMETER(dwUser); // 19.02.98 cg, added unreferenced parameter declarations
UNREFERENCED_PARAMETER(dw1);
UNREFERENCED_PARAMETER(dw2);
}
VOID StartTimers(VOID)
{
if (bStarted) // timer running
@ -293,18 +273,16 @@ VOID StartTimers(VOID)
if (Chipset.IORam[TIMER2_CTRL]&RUN) // start timer1 and timer2 ?
{
bStarted = TRUE; // flag timer running
SetAccesstime(); // 06.10.97 cg, set date and time
// 10.11.98 cg, changed, use always accurate timer
// if (bAccurateTimer) // box "Accurate timer" checked
// {
// 21.04.98 cg, optimized, set timer resolution to 1 ms, if failed don't use "Accurate timer"
// 24.10.99 cg, new, initialisation of NINT2 lines
bNINT2T1 = (Chipset.IORam[TIMER1_CTRL]&INTR) != 0 && (Chipset.t1 & 8) != 0;
bNINT2T2 = (Chipset.IORam[TIMER2_CTRL]&INTR) != 0 && (Chipset.t2 & 0x80000000) != 0;
// 24.10.99 cg, end of initialisation
// set timer resolution to 1 ms, if failed don't use "Accurate timer"
bAccurateTimer = (timeBeginPeriod(1) == TIMERR_NOERROR);
// }
timeGetDevCaps(&tc,sizeof(tc)); // 21.04.98 cg, get timer resolution
timeGetDevCaps(&tc,sizeof(tc)); // get timer resolution
// set timer1 with given period
// 10.11.98 cg, changed, use fix event time
uT1TimerId = timeSetEvent(T1_FREQ,0,(LPTIMECALLBACK)&TimeProc,1,TIME_PERIODIC);
_ASSERT(uT1TimerId); // 16.03.98 cg, new, test if timer1 started
_ASSERT(uT1TimerId); // test if timer1 started
RescheduleT2(TRUE); // start timer2
}
return;
@ -314,23 +292,21 @@ VOID StopTimers(VOID)
{
if (!bStarted) // timer stopped
return; // -> quit
// Chipset.t2 = ReadT2(); // 21.04.98 cg, removed, read timer2 value later
if (uT1TimerId != 0) // timer1 running
{
// 02.12.98 cg, bugfix, Critical Section handler may cause a dead lock
// Critical Section handler may cause a dead lock
timeKillEvent(uT1TimerId); // stop timer1
uT1TimerId = 0; // set flag timer1 stopped
// 02.12.98 cg, end of bugfix
}
if (uT2TimerId != 0) // timer2 running
{
EnterCriticalSection(&csT2Lock); // 21.04.98 cg, bugfix, synchronize
EnterCriticalSection(&csT2Lock);
{
Chipset.t2 = CalcT2(); // 21.04.98 cg, update chipset timer2 value
// AbortT2(); // 02.12.98 cg, removed, stop timer2 later
Chipset.t2 = CalcT2(); // update chipset timer2 value
// AbortT2(); // removed, stop timer2 later
}
LeaveCriticalSection(&csT2Lock); // 21.04.98 cg
AbortT2(); // 02.12.98 cg, bugfix, stop timer2 here
LeaveCriticalSection(&csT2Lock);
AbortT2(); // stop timer2 here
}
bStarted = FALSE;
if (bAccurateTimer) // "Accurate timer" running
@ -342,13 +318,12 @@ VOID StopTimers(VOID)
DWORD ReadT2(VOID)
{
// 21.04.98 cg, changed implementation
DWORD dwT2;
EnterCriticalSection(&csT2Lock);
{
// 16.12.98 cg, bugfix, calculate timer2 value or if stopped last timer value
// calculate timer2 value or if stopped last timer value
dwT2 = bStarted ? CalcT2() : Chipset.t2;
CheckT2(dwT2); // 25.11.98 cg, new, update timer2 control bits
CheckT2(dwT2); // update timer2 control bits
}
LeaveCriticalSection(&csT2Lock);
return dwT2;
@ -357,15 +332,12 @@ DWORD ReadT2(VOID)
VOID SetT2(DWORD dwValue)
{
// calling AbortT2() inside Critical Section handler may cause a dead lock
if (uT2TimerId != 0) // 02.12.98 cg, bugfix, timer2 running
AbortT2(); // 02.12.98 cg, bugfix, stop timer2
// 21.04.98 cg, changed implementation
if (uT2TimerId != 0) // timer2 running
AbortT2(); // stop timer2
EnterCriticalSection(&csT2Lock);
{
// if (uT2TimerId != 0) // 02.12.98 cg, removed, done before
// AbortT2(); // 02.12.98 cg, removed, done before
Chipset.t2 = dwValue; // set new value
CheckT2(Chipset.t2); // 25.11.98 cg, readded, test timer2 control bits
CheckT2(Chipset.t2); // test timer2 control bits
if (bStarted) // timer running
RescheduleT2(TRUE); // restart timer2
}
@ -376,28 +348,32 @@ VOID SetT2(DWORD dwValue)
BYTE ReadT1(VOID)
{
BYTE nT1;
EnterCriticalSection(&csT1Lock); // 21.04.98 cg, bugfix, synchronize
EnterCriticalSection(&csT1Lock);
{
nT1 = Chipset.t1; // read timer1 value
CheckT1(nT1); // 25.11.98 cg, new, update timer1 control bits
CheckT1(nT1); // update timer1 control bits
}
LeaveCriticalSection(&csT1Lock); // 21.04.98 cg
LeaveCriticalSection(&csT1Lock);
return nT1;
}
VOID SetT1(BYTE byValue)
{
timeKillEvent(uT1TimerId); // 11.06.98 cg, bugfix, stop timer1
uT1TimerId = 0; // 11.06.98 cg, new, set flag timer1 stopped
EnterCriticalSection(&csT1Lock); // 21.04.98 cg, bugfix, synchronize
_ASSERT(byValue < 0x10); // timer1 is only a 4bit counter
if (Chipset.t1 == byValue) // same value doesn't restart timer period
return;
timeKillEvent(uT1TimerId); // stop timer1
uT1TimerId = 0; // set flag timer1 stopped
EnterCriticalSection(&csT1Lock);
{
Chipset.t1 = byValue&0xF; // set new timer1 value
CheckT1(Chipset.t1); // 25.11.98 cg, readded, test timer1 control bits
Chipset.t1 = byValue; // set new timer1 value
CheckT1(Chipset.t1); // test timer1 control bits
}
LeaveCriticalSection(&csT1Lock); // 21.04.98 cg
// 11.06.98 cg, bugfix, restart timer1
// 10.11.98 cg, changed, use fix event time
LeaveCriticalSection(&csT1Lock);
// restart timer1 to get full period of frequency
uT1TimerId = timeSetEvent(T1_FREQ,0,(LPTIMECALLBACK)&TimeProc,1,TIME_PERIODIC);
_ASSERT(uT1TimerId); // 11.06.98 cg, new, test if timer1 started
_ASSERT(uT1TimerId); // test if timer1 started
return;
}

View file

@ -7,16 +7,19 @@
*
*/
#define SWORD SHORT // 09.12.99 cg, new, signed 16 Bit variable
#define QWORD ULONGLONG // 22.11.99 cg, new, unsigned 64 Bit variable
#define CHIPSET Chipset_t
typedef struct
{
WORD wPosX;
WORD wPosY;
SWORD nPosX; // 09.12.99 cg, bugfix, is a signed number
SWORD nPosY; // 09.12.99 cg, bugfix, is a signed number
BYTE type;
DWORD Port0Size; // real size of module im KB
DWORD Port1Size; // real size of module im KB
DWORD Port2Size; // 27.06.98 cg, not used any more
DWORD Port0Size; // real size of module in KB
DWORD Port1Size; // real size of module in KB
DWORD Port2Size; // real size of module in KB (HP49G only)
LPBYTE Port0;
LPBYTE Port1;
LPBYTE Port2;
@ -49,15 +52,15 @@ typedef struct
BOOL carry;
WORD crc;
// UINT uUnused1; // 21.02.99 cg, removed, not used
WORD wPort2Crc; // 21.02.99 cg, new, fingerprint of port2
WORD wUnused1; // 21.02.99 cg, new, dummy to fill rest of old variable
// UINT Port2_Size; // 25.02.99 cg, removed, not used
DWORD dwKdnCycles; // 25.02.99 cg, cpu cycles at start of 1ms key handler
BOOL Port1_Writeable;
BOOL Port2_Writeable; // 30.05.98 cg, not used
UINT Port2_Bank; // 15.12.98 cg, new, save state of GX port2 FF
UINT Port2_NBanks; // 30.05.98 cg, not used
WORD wPort2Crc; // fingerprint of port2
WORD wRomCrc; // 20.11.99 cg, new, fingerprint of ROM
// QWORD cycles; // 22.11.99 cg, changed, oscillator cycles
DWORD cycles; // 22.11.99 cg, moved, oscillator cycles
DWORD cycles_reserved; // 22.11.99 cg, reserved for MSB of oscillator cycles
DWORD dwKdnCycles; // 22.11.99 cg, moved, cpu cycles at start of 1ms key handler
UINT Bank_FF; // save state of HP48GX port2 or state of HP49G ROM FF
UINT Port2_NBanks; // not used
BYTE cards_status;
BYTE IORam[64]; // I/O hardware register
UINT IOBase; // address of I/O modules page
@ -70,19 +73,18 @@ typedef struct
BYTE t1;
DWORD t2;
// DWORD t2_ticks; // 03.03.98 cg, removed, not used
DWORD cycles; // 03.03.98 cg, new, oscillator cycles
BOOL bShutdnWake; // 20.11.99 cg, moved, flag for wake up from SHUTDN mode
BYTE Keyboard_Row[9];
WORD IR15X;
UINT Keyboard_State; // 30.05.98 cg, not used
UINT Keyboard_State; // not used
signed short loffset;
signed int width;
UINT boffset;
UINT lcounter;
UINT sync; // 24.08.98 cg, not used
UINT sync; // not used
BYTE contrast;
BOOL dispon;
DWORD start1;