2000-07-16: Updated to version 1.20
This commit is contained in:
parent
2e85d27e43
commit
0f41d8fed0
43 changed files with 4176 additions and 1408 deletions
BIN
CARDCOPY.EXE
Normal file
BIN
CARDCOPY.EXE
Normal file
Binary file not shown.
57
CARDCOPY.TXT
Normal file
57
CARDCOPY.TXT
Normal file
|
@ -0,0 +1,57 @@
|
|||
CARDCOPY - A HP48 Port1 Import/Export Tool for Emu48
|
||||
05/23/00 (c) by Christoph Gießelink, cgiess@swol.de
|
||||
|
||||
|
||||
************
|
||||
* CARDCOPY *
|
||||
************
|
||||
|
||||
Emu48, when emulating a HP48, save the user, the port1 memory and other
|
||||
information in one file (*.E48). But sometimes it's useful to import or to
|
||||
export port1 data. CARDCOPY now allows you to import/export a 128KB card file
|
||||
into/from the port1 memory of an Emu48 state file. The program can handle
|
||||
HP48SX/GX state and 128KB card files (file size 256KB) as source or destination.
|
||||
On all other file types you'll get an error. It's recommended to switch off the
|
||||
emulated HP48 before importing port1 data into a state file. So you're sure that
|
||||
the HP48 wasn't busy and, when you switch on the emulated calculator, the
|
||||
changed card will be detected.
|
||||
|
||||
Remember: Don't import data when port1 is merged! This will corrupt memory.
|
||||
Second, when you import data, all files that are saved in port1 are purged.
|
||||
|
||||
The syntax is: CARDCOPY <Sourcefile> <Destinationfile>
|
||||
|
||||
Some examples:
|
||||
|
||||
- SX.E48 , an Emu48 state file for a HP48SX
|
||||
- GX.E48 , an Emu48 state file for a HP48GX
|
||||
- RPLTOOLS.BIN , a 128KB port2 file
|
||||
|
||||
If you want to
|
||||
- export the port1 content of SX.E48 to RPLTOOLS.BIN then type
|
||||
CARDCOPY SX.E48 RPLTOOLS.BIN
|
||||
- import the RPLTOOLS.BIN as port1 into GX.E48 then type
|
||||
CARDCOPY RPLTOOLS.BIN GX.E48
|
||||
- export the port1 content of SX.E48 to GX.48 then type
|
||||
CARDCOPY SX.E48 GX.E48
|
||||
|
||||
|
||||
***************
|
||||
* LEGAL STUFF *
|
||||
***************
|
||||
|
||||
CARDCOPY - A HP48 Port1 Import/Export Tool for Emu48
|
||||
Copyright (C) 2000 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 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 license with this program in the file
|
||||
"COPYING". If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
66
CP_48G3.KML
66
CP_48G3.KML
|
@ -34,7 +34,7 @@ End
|
|||
Lcd
|
||||
Zoom 2
|
||||
Offset 20 52
|
||||
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
|
||||
|
@ -42,22 +42,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
|
||||
|
@ -66,6 +66,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
|
||||
|
|
64
CP_48S3.KML
64
CP_48S3.KML
|
@ -26,25 +26,25 @@ End
|
|||
Lcd
|
||||
Zoom 2
|
||||
Offset 20 52
|
||||
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
|
||||
|
@ -58,6 +58,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
Convert.exe
BIN
Convert.exe
Binary file not shown.
66
DEBUGGER.TXT
66
DEBUGGER.TXT
|
@ -1,7 +1,7 @@
|
|||
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.
|
||||
This is a short description of the internal assembly 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.
|
||||
|
||||
|
@ -73,15 +73,20 @@ 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.
|
||||
You get a sorted list of the current code and memory 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. When adding a new breakpoint, you must select if this is a "Code", "Memory Access", "Memory Read" or "Memory Write" breakpoint.
|
||||
|
||||
- "Code" stop before opcode execution on this address
|
||||
- "Memory Access" stop before reading or writing to the selected address
|
||||
- "Memory Read" stop before reading the selected address
|
||||
- "Memory Write" stop before writing to the selected address
|
||||
|
||||
- Clear all breakpoints
|
||||
|
||||
Clear all code breakpoints except the NOP3 ones.
|
||||
Clear all 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.
|
||||
What are NOP3 code breakpoints? As you know 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:
|
||||
|
||||
|
@ -115,8 +120,28 @@ CODE
|
|||
GOVLNG =GETPTRLOOP
|
||||
ENDCODE
|
||||
|
||||
- RPL breakpoints
|
||||
|
||||
3.) Code window
|
||||
If this item is checked, the debugger stops program execution on every A=DAT0 A, D0=D0+ 5, PC=(A) sequence. This is the typical RPL exit sequence, so you're able to jump easily to the end of any RPL command.
|
||||
|
||||
|
||||
3.) Menu Interrupts
|
||||
|
||||
- Step Over Interrupts
|
||||
|
||||
If this item is checked, interrupt handler code will be skipped. This option is useful when you don't want to debug the interrupt handler. But be careful, when you disable the interrupts all code until interrupt enable belong to the interrupt handler code and could't executed in single step any more. Code and memory breakpoints are still active.
|
||||
|
||||
You can also use this option if you want to quit the interrupt handler. Just check this option, press F7 for "Step Into", and uncheck the option again. The debugger stopped behind the RTI instruction.
|
||||
|
||||
|
||||
4.) Menu Info
|
||||
|
||||
- Last Instructions...
|
||||
|
||||
This is a short viewer for the last 255 executed CPU addresses. The disassembled opcode maybe wrong, because only the CPU address of each command was saved and memory mapping may have changed meanwhile.
|
||||
|
||||
|
||||
5.) 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.
|
||||
|
||||
|
@ -141,16 +166,16 @@ Toggle a code breakpoint at the cursor position in the code window.
|
|||
Set the PC to the cursor position. Be careful with this command, you change the execution order of the commands!
|
||||
|
||||
|
||||
4.) Register window
|
||||
6.) 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
|
||||
7.) Memory window
|
||||
|
||||
This windows shows you the memory content.
|
||||
This windows shows 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.
|
||||
|
||||
|
@ -177,13 +202,30 @@ Sets the cursor to the actual position of the D0 register.
|
|||
Sets the cursor to the return address placed in the top level of the stack.
|
||||
|
||||
|
||||
6.) Stack window
|
||||
8.) Stack window
|
||||
|
||||
The content of the hardware stack is viewed here.
|
||||
|
||||
|
||||
7.) Problems
|
||||
9.) MMU window
|
||||
|
||||
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.
|
||||
The configuration of the memory controllers is viewed here. The viewed addresses are the first configured addresses of the modules and may differ from the given address in the CONFIG command.
|
||||
|
||||
12/14/99 (c) by Christoph Gießelink, cgiess@swol.de
|
||||
This example
|
||||
|
||||
LC(5) #C0000 128KB size
|
||||
CONFIG
|
||||
LC(5) #98765 start address of modul
|
||||
CONFIG
|
||||
|
||||
will config a 128KB modul at address #80000 and not at the given address. So the MMU viewer will show you address #80000.
|
||||
|
||||
|
||||
10.) Miscellaneous window
|
||||
|
||||
The Miscellaneous window show you the internal state of the interrupt flag, the 1ms keyboard handler and the contents of the Bank Switcher latch. The Bank Switcher item is only enabled on a HP48GX and a HP49G calculator. Only these versions have a latch inside. You see the loaded value of the address lines A6-A0. You have to ignore the last bit (A0), because it isn't wired to the six bit latch.
|
||||
|
||||
You can change the values by pressing the left mouse button over the old content.
|
||||
|
||||
|
||||
06/13/00 (c) by Christoph Gießelink, cgiess@swol.de
|
||||
|
|
BIN
EMU48.EXE
BIN
EMU48.EXE
Binary file not shown.
150
EMU48.TXT
150
EMU48.TXT
|
@ -10,16 +10,16 @@
|
|||
****************
|
||||
|
||||
Emu48 is distributed in 1 archive:
|
||||
- Emu48-1_15.zip All files and sources
|
||||
- Emu48-1_20.zip All files and sources
|
||||
|
||||
To install Emu48, just unzip Emu48-1_15.zip into an empty directory. When you
|
||||
To install Emu48, just unzip Emu48-1_20.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.
|
||||
|
||||
You can also update your current version with the Unofficial Service Packs:
|
||||
- E48BP1x.ZIP New EXE-File
|
||||
- E48SP1x.ZIP Sources of the Service Pack
|
||||
- E48BP2x.ZIP New EXE-File
|
||||
- E48SP2x.ZIP Sources of the Service Pack
|
||||
|
||||
Replace the original EXE file please.
|
||||
|
||||
|
@ -136,9 +136,9 @@ 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.
|
||||
31. But the ROMs bounds them to useful values. The HP48 S(X) ROM use only
|
||||
display contrast values between 3 and 19 and the HP48 G(X) ROM values between 9
|
||||
and 24.
|
||||
|
||||
|
||||
****************
|
||||
|
@ -147,8 +147,8 @@ display contrast values between 3 and 19 and the G(X) ROM values between 9 and
|
|||
|
||||
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.
|
||||
You're not able to set a Port 2 file without setting the emulation data file.
|
||||
The arguments are optional.
|
||||
|
||||
|
||||
*******************
|
||||
|
@ -156,23 +156,23 @@ arguments are optional.
|
|||
*******************
|
||||
|
||||
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.
|
||||
use the serial port to transfer the data directly from your HP 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
|
||||
Dropping HP 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.
|
||||
|
||||
|
@ -209,12 +209,28 @@ 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.
|
||||
|
||||
|
||||
***********************
|
||||
* FLASH ROM EMULATION *
|
||||
***********************
|
||||
|
||||
The HP49G save the operation system a reprogramable memory, a so called flash
|
||||
memory. The flash memory is divided into two parts, into the Operating System
|
||||
and into a User Data area. The User Data area is viewed as Port 2 in the HP49G.
|
||||
Emu48 saves the Port 2 data in the ROM file (normally ROM.E49). As default
|
||||
setting the ROM file is writeable in the first instance of Emu48. When you open
|
||||
another instance of a HP49G emulation the Port 2 area is READ ONLY, that mean
|
||||
all changes in Port 2 are lost when you exit this instance. If you don't want to
|
||||
save data in Port 2 and want to protect the operating systems from overwriting,
|
||||
you're able protect the ROM file. To do this, close all Emu48 instances and set
|
||||
the variable 'Writeable' defined in the Emu48.ini file, section [ROM] to zero.
|
||||
|
||||
|
||||
***********************
|
||||
* 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
|
||||
able to copy HP string objects from the stack to the PC clipboard and vice
|
||||
versa.
|
||||
|
||||
|
||||
|
@ -249,9 +265,9 @@ button.
|
|||
|
||||
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.
|
||||
HP. On HP48 S(X) calculators the address area #00052-#00070, on all other
|
||||
emulated calculators the address area #00058-#00076 in Port 0 are rewritten with
|
||||
the actual time information.
|
||||
|
||||
|
||||
*************
|
||||
|
@ -268,28 +284,28 @@ 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.
|
||||
As you recognized the speed of the emulated HP is much faster than an original
|
||||
one. 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.
|
||||
|
||||
|
||||
*************************
|
||||
|
@ -299,33 +315,33 @@ the functionality of Emu48 when you go below the default values.
|
|||
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.
|
||||
with the command CLOSEIO or power cycle the HP 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.
|
||||
Now it's possible to make transfers between the real calculator 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 HP 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 real calculator
|
||||
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 HP 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
|
||||
With the internal disassembler you're able to disassemble the Saturn chip
|
||||
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 use a linear address mode,
|
||||
beginning at address #00000 and will not overlapped by other modules. So, for
|
||||
example, you can access the second port of a HP48 RAM card greater than 128KB at
|
||||
address #40000 (128 * 1024 * 2). The "Copy Data" button copies the selected
|
||||
disassembler lines to the PC clipboard.
|
||||
|
||||
|
||||
|
@ -389,7 +405,7 @@ Other graphics and scripts are available at Casey's Emu48 Graphics Page:
|
|||
***************
|
||||
|
||||
Emu48 - An HP38/48/49 Emulator
|
||||
Copyright (C) 1999 Sebastien Carlier & Christoph Gießelink
|
||||
Copyright (C) 2000 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
|
||||
|
|
41
PROBLEMS.TXT
41
PROBLEMS.TXT
|
@ -1,18 +1,18 @@
|
|||
Known bugs and restrictions of Emu48 V1.15
|
||||
Known bugs and restrictions of Emu48 V1.20
|
||||
------------------------------------------
|
||||
|
||||
- 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]
|
||||
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
|
||||
|
@ -30,15 +30,26 @@ Known bugs and restrictions of Emu48 V1.15
|
|||
-> all programs that run on a real calculator will run as well,
|
||||
programs with incorrect DA19 / BEN handling may run on the
|
||||
emulator but will crash on a real calculator
|
||||
- no MP interrupt on card control circuit or timer restart
|
||||
- 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
|
||||
- problem with timer2 (8192Hz) emulation in Windows 2000, timer2
|
||||
values may skip, so an emulated delay loop may take very very long
|
||||
- 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!
|
||||
- HP49G: the flash memory is emulated now with some restrictions
|
||||
- first implementation, at the moment the flash memory is more a
|
||||
simulation than an emulation
|
||||
- no flash programming times, the flash state machine returns
|
||||
immediately the ready signal
|
||||
- only one write buffer, second not needed because of prior reason
|
||||
- not fully tested, especially the status byte may sometimes
|
||||
return incorrect values (error bits)
|
||||
- quitting the emulator while programming the flash isn't allowed,
|
||||
because the content of flash state machine isn't saved so far
|
||||
|
||||
12/14/99 (c) by Christoph Gießelink, cgiess@swol.de
|
||||
07/10/00 (c) by Christoph Gießelink, cgiess@swol.de
|
||||
|
|
139
sources/Cardcopy/CARDCOPY.C
Normal file
139
sources/Cardcopy/CARDCOPY.C
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* cardcopy, (c) 2000 Christoph Giesselink (cgiess@swol.de)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_EXTRA_LEAN
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define VERSION "1.0"
|
||||
|
||||
#define FT_ERR 0 // illegal format
|
||||
#define FT_NEW 1 // empty file
|
||||
#define FT_SXGX 2 // Emu48 HP48SX/GX state file
|
||||
#define FT_PORT 3 // 128KB port file
|
||||
|
||||
#define PORT1SIZE (128*1024*2) // file size of 128KB file
|
||||
#define HP48SIG "Emu48 Document\xFE" // HP48 state file signature
|
||||
|
||||
UINT CheckType(char *lpszFileName)
|
||||
{
|
||||
BYTE pbyFileSignature[16];
|
||||
HANDLE hFile;
|
||||
DWORD FileSizeHigh,FileSizeLow;
|
||||
|
||||
UINT nType = FT_ERR;
|
||||
|
||||
hFile = CreateFile(lpszFileName,GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
return FT_NEW;
|
||||
|
||||
// check filesize
|
||||
FileSizeLow = GetFileSize(hFile,&FileSizeHigh);
|
||||
if (FileSizeHigh == 0 && FileSizeLow == PORT1SIZE)
|
||||
nType = FT_PORT;
|
||||
|
||||
// Read and Compare signature
|
||||
ReadFile(hFile,pbyFileSignature,sizeof(pbyFileSignature),&FileSizeLow,NULL);
|
||||
if (FileSizeLow == sizeof(pbyFileSignature) && strcmp(pbyFileSignature,HP48SIG) == 0)
|
||||
nType = FT_SXGX;
|
||||
|
||||
CloseHandle(hFile);
|
||||
return nType;
|
||||
}
|
||||
|
||||
BOOL CopyData(HANDLE hFileSource,HANDLE hFileDest)
|
||||
{
|
||||
BYTE byBuffer[16];
|
||||
INT i;
|
||||
DWORD lBytes;
|
||||
|
||||
assert(PORT1SIZE % sizeof(byBuffer) == 0);
|
||||
for (i = PORT1SIZE / sizeof(byBuffer); i > 0; --i)
|
||||
{
|
||||
ReadFile(hFileSource,byBuffer,sizeof(byBuffer),&lBytes,NULL);
|
||||
if (lBytes != sizeof(byBuffer)) return TRUE;
|
||||
|
||||
WriteFile(hFileDest,byBuffer,sizeof(byBuffer),&lBytes,NULL);
|
||||
if (lBytes != sizeof(byBuffer)) return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UINT main(int argc, char *argv[])
|
||||
{
|
||||
HANDLE hFileSource,hFileDest;
|
||||
UINT nSourceType,nDestType;
|
||||
|
||||
printf("HP48 Port1 Import/Export Tool for Emu48 V" VERSION "\n");
|
||||
if (argc != 3)
|
||||
{
|
||||
printf("\nUsage:\n\t%s <SourceFile> <DestinationFile>\n\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check source file type
|
||||
nSourceType = CheckType(argv[1]);
|
||||
if (nSourceType == FT_ERR)
|
||||
{
|
||||
printf("Error: Illegal source file type\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
// check destination file type
|
||||
nDestType = CheckType(argv[2]);
|
||||
if (nDestType == FT_ERR)
|
||||
{
|
||||
printf("Error: Illegal destination file type\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
// open source file
|
||||
hFileSource = CreateFile(argv[1],GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
|
||||
if (hFileSource != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hFileDest = CreateFile(argv[2],GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_ALWAYS,0,NULL);
|
||||
if (hFileDest != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (nSourceType == FT_SXGX) SetFilePointer(hFileSource,-PORT1SIZE,NULL,FILE_END);
|
||||
if (nDestType == FT_SXGX) SetFilePointer(hFileDest ,-PORT1SIZE,NULL,FILE_END);
|
||||
|
||||
CopyData(hFileSource,hFileDest);
|
||||
puts("Copy successful.");
|
||||
|
||||
CloseHandle(hFileDest);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: Can't open destination file %s\n",argv[2]);
|
||||
return 4;
|
||||
}
|
||||
|
||||
CloseHandle(hFileSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: Can't open source file %s\n",argv[1]);
|
||||
return 5;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
100
sources/Cardcopy/CARDCOPY.DSP
Normal file
100
sources/Cardcopy/CARDCOPY.DSP
Normal file
|
@ -0,0 +1,100 @@
|
|||
# Microsoft Developer Studio Project File - Name="CARDCOPY" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=CARDCOPY - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "CARDCOPY.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "CARDCOPY.mak" CFG="CARDCOPY - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "CARDCOPY - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "CARDCOPY - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "CARDCOPY - 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 ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x407 /d "NDEBUG"
|
||||
# ADD RSC /l 0x407 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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:console /machine:I386
|
||||
# ADD 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 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:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "CARDCOPY - 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 ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x407 /d "_DEBUG"
|
||||
# ADD RSC /l 0x407 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 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:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD 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 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:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "CARDCOPY - Win32 Release"
|
||||
# Name "CARDCOPY - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CARDCOPY.C
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
29
sources/Cardcopy/CARDCOPY.DSW
Normal file
29
sources/Cardcopy/CARDCOPY.DSW
Normal file
|
@ -0,0 +1,29 @@
|
|||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "CARDCOPY"=.\CARDCOPY.DSP - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
|
@ -4,20 +4,15 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define HP38G 0
|
||||
#define HP48S 1
|
||||
#define HP48G 2
|
||||
|
||||
HANDLE hFile;
|
||||
HANDLE hMap;
|
||||
HANDLE hOut;
|
||||
LPBYTE pIn;
|
||||
LPBYTE pRom;
|
||||
DWORD dwSizeLo, dwSizeHi;
|
||||
BYTE szVersion[16];
|
||||
BOOL bUnpack = FALSE;
|
||||
BOOL bSwap = FALSE;
|
||||
BOOL bText = FALSE;
|
||||
DWORD dwWritten;
|
||||
WORD wCRC;
|
||||
BOOL bIsGx;
|
||||
WORD wType;
|
||||
|
||||
static WORD crc_table[16] =
|
||||
{
|
||||
|
@ -36,7 +31,7 @@ BOOL CheckCRC()
|
|||
UINT i;
|
||||
DWORD dwBase = 0x00000;
|
||||
UINT nPass = 0;
|
||||
UINT nPasses = bIsGx?2:1;
|
||||
UINT nPasses = (wType != HP48S)?2:1;
|
||||
|
||||
again:
|
||||
|
||||
|
@ -94,32 +89,58 @@ static DWORD Asc2Nib5(LPSTR lpBuf)
|
|||
|((DWORD)Asc2Nib(lpBuf[4])));
|
||||
}
|
||||
|
||||
static BOOL IsHP(DWORD dwAddress)
|
||||
{
|
||||
char cH = (pRom[dwAddress + 1] << 4) | pRom[dwAddress];
|
||||
char cP = (pRom[dwAddress + 3] << 4) | pRom[dwAddress + 2];
|
||||
return cH == 'H' && cP == 'P';
|
||||
}
|
||||
|
||||
UINT main(int argc, char *argv[])
|
||||
{
|
||||
HANDLE hFile;
|
||||
HANDLE hMap;
|
||||
HANDLE hOut;
|
||||
LPBYTE pIn;
|
||||
DWORD dwSizeLo;
|
||||
BYTE szVersion[16];
|
||||
DWORD dwWritten;
|
||||
UINT i,uLen;
|
||||
DWORD dwAddress;
|
||||
|
||||
DWORD dwAddrOffset = 0x00000;
|
||||
|
||||
BOOL bFormatDetected = FALSE;
|
||||
|
||||
BOOL bUnpack = FALSE;
|
||||
BOOL bSwap = FALSE;
|
||||
BOOL bText = FALSE;
|
||||
BOOL bDA19 = FALSE;
|
||||
|
||||
if ((argc!=2)&&(argc!=3))
|
||||
{
|
||||
printf("Usage:\n\t%s <old-rom-dump> [<new-rom-dump>]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pRom = LocalAlloc(0,1048576);
|
||||
pRom = LocalAlloc(LMEM_FIXED,512*1024*2);
|
||||
if (pRom == NULL)
|
||||
{
|
||||
printf("Memory Allocation Failed !");
|
||||
return 1;
|
||||
}
|
||||
|
||||
hFile = CreateFile(argv[1],GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
|
||||
hFile = CreateFile(argv[1],GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
LocalFree(pRom);
|
||||
printf("Cannot open file %s.\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
dwSizeLo = GetFileSize(hFile, &dwSizeHi);
|
||||
dwSizeLo = GetFileSize(hFile, NULL);
|
||||
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (hMap == NULL)
|
||||
{
|
||||
LocalFree(pRom);
|
||||
CloseHandle(hFile);
|
||||
puts("CreateFileMapping failed.");
|
||||
return 1;
|
||||
|
@ -127,42 +148,65 @@ UINT main(int argc, char *argv[])
|
|||
pIn = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
||||
if (pIn == NULL)
|
||||
{
|
||||
LocalFree(pRom);
|
||||
CloseHandle(hMap);
|
||||
CloseHandle(hFile);
|
||||
puts("MapViewOfFile failed.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (pIn[0])
|
||||
for (i = 0; i < 2 && !bFormatDetected; ++i)
|
||||
{
|
||||
case '0':
|
||||
if (pIn[1]!='0') break;
|
||||
if (pIn[2]!='0') break;
|
||||
if (pIn[3]!='0') break;
|
||||
if (pIn[4]!='0') break;
|
||||
if (pIn[5]!=':') break;
|
||||
bText = TRUE;
|
||||
break;
|
||||
case 0x23:
|
||||
bUnpack = TRUE;
|
||||
bSwap = TRUE;
|
||||
break;
|
||||
case 0x32:
|
||||
bUnpack = TRUE;
|
||||
break;
|
||||
case 0x02:
|
||||
break;
|
||||
case 0x03:
|
||||
if (pIn[1] == 0x02)
|
||||
switch (pIn[0+dwAddrOffset])
|
||||
{
|
||||
case '0':
|
||||
if (pIn[1+dwAddrOffset]!='0') break;
|
||||
if (pIn[2+dwAddrOffset]!='0') break;
|
||||
if (pIn[3+dwAddrOffset]!='0') break;
|
||||
if (pIn[4+dwAddrOffset]!='0') break;
|
||||
if (pIn[5+dwAddrOffset]!=':') break;
|
||||
bText = TRUE;
|
||||
bFormatDetected = TRUE;
|
||||
break;
|
||||
case 0x23:
|
||||
bUnpack = TRUE;
|
||||
bSwap = TRUE;
|
||||
bFormatDetected = TRUE;
|
||||
break;
|
||||
case 0x32:
|
||||
bUnpack = TRUE;
|
||||
bFormatDetected = TRUE;
|
||||
break;
|
||||
case 0x03:
|
||||
bSwap = TRUE;
|
||||
case 0x02:
|
||||
if (pIn[1+dwAddrOffset] == (bSwap ? 0x02 : 0x03))
|
||||
{
|
||||
bFormatDetected = TRUE;
|
||||
break;
|
||||
}
|
||||
bSwap = FALSE;
|
||||
default:
|
||||
dwAddrOffset = dwSizeLo / 2;
|
||||
bDA19 = TRUE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!bFormatDetected)
|
||||
{
|
||||
LocalFree(pRom);
|
||||
UnmapViewOfFile(pIn);
|
||||
CloseHandle(hMap);
|
||||
CloseHandle(hFile);
|
||||
printf("Stopped, unknown format.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bUnpack) printf("Unpacking nibbles.\n");
|
||||
if (bSwap) printf("Swapping nibbles.\n");
|
||||
if (bText) printf("Reading text file.\n");
|
||||
if (bDA19) printf("Swapping banks.\n");
|
||||
|
||||
if (bText)
|
||||
{
|
||||
|
@ -200,8 +244,9 @@ UINT main(int argc, char *argv[])
|
|||
DWORD i;
|
||||
for (i=0; i<dwSizeLo; i++)
|
||||
{
|
||||
pRom[(i<<1) ] = pIn[i]>>4;
|
||||
pRom[(i<<1)+1] = pIn[i]&0xF;
|
||||
BYTE byC = pIn[(i+dwAddrOffset)&(dwSizeLo-1)];
|
||||
pRom[(i<<1) ] = byC>>4;
|
||||
pRom[(i<<1)+1] = byC&0xF;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -209,8 +254,9 @@ UINT main(int argc, char *argv[])
|
|||
DWORD i;
|
||||
for (i=0; i<dwSizeLo; i++)
|
||||
{
|
||||
pRom[(i<<1) ] = pIn[i]&0xF;
|
||||
pRom[(i<<1)+1] = pIn[i]>>4;
|
||||
BYTE byC = pIn[(i+dwAddrOffset)&(dwSizeLo-1)];
|
||||
pRom[(i<<1) ] = byC&0xF;
|
||||
pRom[(i<<1)+1] = byC>>4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -222,15 +268,24 @@ UINT main(int argc, char *argv[])
|
|||
for (i=0; i<dwSizeLo; i+=2)
|
||||
{
|
||||
BYTE a, b;
|
||||
a = pIn[i];
|
||||
b = pIn[i+1];
|
||||
pRom[i] = a;
|
||||
pRom[i+1] = b;
|
||||
a = pIn[(i+dwAddrOffset)&(dwSizeLo-1)];
|
||||
b = pIn[(i+1+dwAddrOffset)&(dwSizeLo-1)];
|
||||
pRom[i] = b;
|
||||
pRom[i+1] = a;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyMemory(pRom, pIn, dwSizeLo);
|
||||
if(bDA19)
|
||||
{
|
||||
assert(dwAddrOffset == dwSizeLo/2);
|
||||
CopyMemory(&pRom[0] , &pIn[dwAddrOffset], dwAddrOffset);
|
||||
CopyMemory(&pRom[dwAddrOffset], &pIn[0] , dwAddrOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyMemory(pRom, pIn, dwSizeLo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -239,38 +294,48 @@ UINT main(int argc, char *argv[])
|
|||
CloseHandle(hMap);
|
||||
CloseHandle(hFile);
|
||||
|
||||
if (bText||bUnpack||bSwap)
|
||||
if (bText||bUnpack||bSwap||bDA19)
|
||||
{
|
||||
printf("File converted.");
|
||||
printf("File converted.\n\n");
|
||||
}
|
||||
|
||||
bIsGx = (pRom[0x29] == 0x00);
|
||||
|
||||
printf("ROM Model Detected : HP48%c\n", bIsGx?'G':'S');
|
||||
|
||||
if (bIsGx)
|
||||
do
|
||||
{
|
||||
UINT i;
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
szVersion[i] = pRom[0x7FFBF + (i<<1) + 1] << 4;
|
||||
szVersion[i] |= pRom[0x7FFBF + (i<<1) ];
|
||||
}
|
||||
// HP38G
|
||||
wType = HP38G;
|
||||
dwAddress = 0x7FFAF;
|
||||
uLen = 10;
|
||||
if (IsHP(dwAddress)) break;
|
||||
|
||||
// HP48SX
|
||||
wType = HP48S;
|
||||
dwAddress = 0x7FFF0;
|
||||
uLen = 6;
|
||||
if (IsHP(dwAddress)) break;
|
||||
|
||||
// HP48GX
|
||||
wType = HP48G;
|
||||
dwAddress = 0x7FFBF;
|
||||
uLen = 6;
|
||||
if (IsHP(dwAddress)) break;
|
||||
|
||||
// unknown
|
||||
uLen = 0;
|
||||
}
|
||||
else
|
||||
while (0);
|
||||
|
||||
printf("ROM Model Detected : HP%c8%c\n",(wType == HP38G)?'3':'4',(wType != HP48S)?'G':'S');
|
||||
|
||||
for (i=0; i<uLen; ++i)
|
||||
{
|
||||
UINT i;
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
szVersion[i] = pRom[0x7FFF0 + (i<<1) + 1] << 4;
|
||||
szVersion[i] |= pRom[0x7FFF0 + (i<<1) ];
|
||||
}
|
||||
szVersion[i] = pRom[dwAddress + (i<<1) + 1] << 4;
|
||||
szVersion[i] |= pRom[dwAddress + (i<<1)];
|
||||
}
|
||||
szVersion[6] = 0;
|
||||
szVersion[i] = 0;
|
||||
|
||||
printf("ROM Version : %s\n", szVersion);
|
||||
|
||||
FillMemory(pRom+0x100, 0x40, 0);
|
||||
ZeroMemory(pRom+0x100, 0x40); // clear IO register area
|
||||
|
||||
if (CheckCRC())
|
||||
{
|
||||
|
@ -283,14 +348,14 @@ UINT main(int argc, char *argv[])
|
|||
|
||||
if (argc == 3)
|
||||
{
|
||||
hOut = CreateFile(argv[2],GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
|
||||
hOut = CreateFile(argv[2],GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
LocalFree(pRom);
|
||||
printf("Cannot open file %s.\n", argv[2]);
|
||||
return 1;
|
||||
}
|
||||
WriteFile(hOut,pRom,bIsGx?1048576:524288,&dwWritten,NULL);
|
||||
WriteFile(hOut,pRom,(wType != HP48S)?(512*1024*2):(256*1024*2),&dwWritten,NULL);
|
||||
CloseHandle(hOut);
|
||||
}
|
||||
|
|
@ -10,16 +10,16 @@
|
|||
****************
|
||||
|
||||
Emu48 is distributed in 1 archive:
|
||||
- Emu48-1_15.zip All files and sources
|
||||
- Emu48-1_20.zip All files and sources
|
||||
|
||||
To install Emu48, just unzip Emu48-1_15.zip into an empty directory. When you
|
||||
To install Emu48, just unzip Emu48-1_20.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.
|
||||
|
||||
You can also update your current version with the Unofficial Service Packs:
|
||||
- E48BP1x.ZIP New EXE-File
|
||||
- E48SP1x.ZIP Sources of the Service Pack
|
||||
- E48BP2x.ZIP New EXE-File
|
||||
- E48SP2x.ZIP Sources of the Service Pack
|
||||
|
||||
Replace the original EXE file please.
|
||||
|
||||
|
@ -136,9 +136,9 @@ 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.
|
||||
31. But the ROMs bounds them to useful values. The HP48 S(X) ROM use only
|
||||
display contrast values between 3 and 19 and the HP48 G(X) ROM values between 9
|
||||
and 24.
|
||||
|
||||
|
||||
****************
|
||||
|
@ -147,8 +147,8 @@ display contrast values between 3 and 19 and the G(X) ROM values between 9 and
|
|||
|
||||
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.
|
||||
You're not able to set a Port 2 file without setting the emulation data file.
|
||||
The arguments are optional.
|
||||
|
||||
|
||||
*******************
|
||||
|
@ -156,23 +156,23 @@ arguments are optional.
|
|||
*******************
|
||||
|
||||
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.
|
||||
use the serial port to transfer the data directly from your HP 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
|
||||
Dropping HP 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.
|
||||
|
||||
|
@ -209,12 +209,28 @@ 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.
|
||||
|
||||
|
||||
***********************
|
||||
* FLASH ROM EMULATION *
|
||||
***********************
|
||||
|
||||
The HP49G save the operation system a reprogramable memory, a so called flash
|
||||
memory. The flash memory is divided into two parts, into the Operating System
|
||||
and into a User Data area. The User Data area is viewed as Port 2 in the HP49G.
|
||||
Emu48 saves the Port 2 data in the ROM file (normally ROM.E49). As default
|
||||
setting the ROM file is writeable in the first instance of Emu48. When you open
|
||||
another instance of a HP49G emulation the Port 2 area is READ ONLY, that mean
|
||||
all changes in Port 2 are lost when you exit this instance. If you don't want to
|
||||
save data in Port 2 and want to protect the operating systems from overwriting,
|
||||
you're able protect the ROM file. To do this, close all Emu48 instances and set
|
||||
the variable 'Writeable' defined in the Emu48.ini file, section [ROM] to zero.
|
||||
|
||||
|
||||
***********************
|
||||
* 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
|
||||
able to copy HP string objects from the stack to the PC clipboard and vice
|
||||
versa.
|
||||
|
||||
|
||||
|
@ -249,9 +265,9 @@ button.
|
|||
|
||||
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.
|
||||
HP. On HP48 S(X) calculators the address area #00052-#00070, on all other
|
||||
emulated calculators the address area #00058-#00076 in Port 0 are rewritten with
|
||||
the actual time information.
|
||||
|
||||
|
||||
*************
|
||||
|
@ -268,28 +284,28 @@ 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.
|
||||
As you recognized the speed of the emulated HP is much faster than an original
|
||||
one. 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.
|
||||
|
||||
|
||||
*************************
|
||||
|
@ -299,33 +315,33 @@ the functionality of Emu48 when you go below the default values.
|
|||
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.
|
||||
with the command CLOSEIO or power cycle the HP 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.
|
||||
Now it's possible to make transfers between the real calculator 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 HP 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 real calculator
|
||||
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 HP 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
|
||||
With the internal disassembler you're able to disassemble the Saturn chip
|
||||
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 use a linear address mode,
|
||||
beginning at address #00000 and will not overlapped by other modules. So, for
|
||||
example, you can access the second port of a HP48 RAM card greater than 128KB at
|
||||
address #40000 (128 * 1024 * 2). The "Copy Data" button copies the selected
|
||||
disassembler lines to the PC clipboard.
|
||||
|
||||
|
||||
|
@ -389,7 +405,7 @@ Other graphics and scripts are available at Casey's Emu48 Graphics Page:
|
|||
***************
|
||||
|
||||
Emu48 - An HP38/48/49 Emulator
|
||||
Copyright (C) 1999 Sebastien Carlier & Christoph Gießelink
|
||||
Copyright (C) 2000 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
|
||||
|
|
|
@ -1,3 +1,353 @@
|
|||
Service Pack 20 for Emu48 Version 1.0
|
||||
|
||||
DEBUGGER.C
|
||||
- changed function UpdateStackWnd(), index of topmost item is now
|
||||
saved at content update
|
||||
- changed function CheckBreakpoint(), allow breakpoints in an area
|
||||
now (used by memory breakpoints to get all touched addresses on a
|
||||
r=DATx fs access)
|
||||
|
||||
DEBUGGER.H
|
||||
- changed prototype of function CheckBreakpoint()
|
||||
|
||||
EMU48.C
|
||||
- use semaphores to avoid GDI trouble with NT in OnPaint()
|
||||
- specify processor affinity for the cpu emulation thread to avoid
|
||||
problems with the QueryPerformanceCounter() function
|
||||
|
||||
EMU48.H
|
||||
- extern declaration of global variable
|
||||
|
||||
EMU48.RC
|
||||
- fixed multiple use of accelerator key in debugger menu
|
||||
- changed version and copyright
|
||||
|
||||
ENGINE.C
|
||||
- bugfix in function Debugger(), check complete address range of
|
||||
memory access area
|
||||
- workaround for Win2k in function AdjustSpeed(), when command
|
||||
sequence took over 50ms new synchronizing of the emulation slow
|
||||
down part
|
||||
- bugfix in function WorkerThread(), update NINT and NINT2 lines
|
||||
after port status changing
|
||||
|
||||
KML.C
|
||||
- use semaphores to avoid GDI trouble with NT in RefreshButtons()
|
||||
|
||||
MOPS.C
|
||||
- bugfix in function UckBit() and F4096Hz(), depending on clock
|
||||
value functions returned wrong results
|
||||
|
||||
OPCODES.C
|
||||
- moved address field start and length array from OPS.H and made
|
||||
them public
|
||||
|
||||
OPCODES.H
|
||||
- extern declaration of global address field start and length
|
||||
variables
|
||||
|
||||
OPS.H
|
||||
- moved address field start and length array to OPCODES.C
|
||||
- bugfix in function FASTPTR(), address area is only 5 nibbles long
|
||||
|
||||
RESOURCE.H
|
||||
- deleted several unused definitions
|
||||
|
||||
RPL.C
|
||||
- added function Metakernel() to detect MK2.30 and prior
|
||||
- changed function RPL_Pick() and RPL_Push() to support
|
||||
"Save/Load Object" with a stack incompatible Metakernel versions
|
||||
|
||||
SERIAL.C
|
||||
- use own OVERLAPPED stucture for reading and writing
|
||||
- bugfix in function CommClose(), added additional delay to fix
|
||||
problems with some Kermit server
|
||||
- bugfix in function CommTransmit(), wait until write completed
|
||||
|
||||
SETTINGS.C
|
||||
- changed function ReadSettings(), use variable content as default
|
||||
|
||||
|
||||
Service Pack 19 for Emu48 Version 1.0
|
||||
|
||||
DISPLAY.C
|
||||
- added io.h in header definition
|
||||
- bugfix in function CreateMainBitmap(), check error condition and
|
||||
realize palette also in memory DC
|
||||
- bugfix in CreateLcdBitmap(), must set color palette for LCD DC
|
||||
- bugfix in function UpdateAnnunciators(), annunciators are off if
|
||||
timer2 is stopped
|
||||
|
||||
DEBUGGER.C
|
||||
- several modifications for memory breakpoint handling
|
||||
- added step over interrupt code part setting
|
||||
- bugfix in function NewValue(), at wrong input numbers ignore input
|
||||
string at <CANCEL> and set focus to edit control
|
||||
- bugfix in function EnterAddr(), at wrong input numbers set focus
|
||||
to edit control
|
||||
|
||||
DEBUGGER.H
|
||||
- added breakpoint type defines
|
||||
- extern declaration of global variable
|
||||
- changed prototype of function CheckBreakpoint()
|
||||
|
||||
EMU48.C
|
||||
- added io.h in header definition
|
||||
- changed function SettingsProc(), added HP/Class mnemonic setting
|
||||
- bugfix in function SettingsProc(), new implementation of card
|
||||
detection port 1
|
||||
- moved initialize/remove of the Critical Section part from main
|
||||
program to message handler
|
||||
- changed function OnDropFiles(), OnStackCopy(), OnStackPaste(),
|
||||
OnObjectLoad() and OnObjectSave(), don't wait for changed state
|
||||
after function WaitForSleepState()
|
||||
- bugfix in function OnObjectSave(), set info message when emulator
|
||||
is busy
|
||||
- changed function Disasm(), removed HP/Class mnemonic setting
|
||||
- bugfix in function Disasm(), addresses > 0x1869F showed in wrong
|
||||
format
|
||||
- bugfix in function WinMain(), synchronized thread start
|
||||
|
||||
EMU48.H
|
||||
- changed definition of PORT1_PRESENT, PORT1_WRITE, PORT2_PRESENT
|
||||
and PORT2_WRITE
|
||||
|
||||
EMU48.RC
|
||||
- added HP/Class mnemonics in "Settings" dialog
|
||||
- added "Interrupts" part in debugger menu
|
||||
- added "Enter breakpoint" dialog
|
||||
- changed version and copyright
|
||||
|
||||
ENGINE.C
|
||||
- moved debugger part from function WorkerThread() to own function
|
||||
- added C=DAT0 A, D0=D0+ 5, PC=(C) code sequence detection for RPL
|
||||
breakpoint in debugger
|
||||
- added step over interrupt code part handler in debugger section
|
||||
- bugfix in function SwitchToState(), when switch from Invalid into
|
||||
Run state then don't enter opcode loop on interrupt request or in
|
||||
SHUTDN mode
|
||||
- changed function WorkerThread(), added memory breakpoint handler
|
||||
- bugfix in function WorkerThread(), timer emulation in debugger
|
||||
part must check the timer RUN bit
|
||||
- bugfix in function WorkerThread(), must set wakeup flag on SHUTDN
|
||||
on interrupt request condition
|
||||
- changed function WorkerThread(), minor optimization
|
||||
|
||||
FILES.C
|
||||
- added io.h in header definition
|
||||
- bugfix in function OpenDocument(), check card detection only if
|
||||
enabled and set NINT line to low on a MP interrupt
|
||||
- changed function DibNumColors(), optimized by removing case switch
|
||||
|
||||
IO.H
|
||||
- added ANNCTRL and CARDSTAT definitions
|
||||
|
||||
MOPS.C
|
||||
- removed conditional compiling with WSMSET
|
||||
- bugfix in function RomSwitch(), mirror smaller ROMs than 2MB
|
||||
- bugfix in function Npeek(), wrong content of SRQ2 register (0x119)
|
||||
- bugfix in function ReadIO(), wrong implementation of the SMP and
|
||||
SWINT bit in the CARDCTL register (0x10E)
|
||||
- bugfix in function ReadIO(), wrong implementation of the NINT2 and
|
||||
NINT bit in the SRQ2 register (0x119)
|
||||
- bugfix in function WriteIO(), wrong implementation of the SMP and
|
||||
ECDT bit and removed some wrong stuff in the CARDCTL register
|
||||
(0x10E)
|
||||
- bugfix in function WriteIO(), the DA19 bit in the LINECOUNT
|
||||
register (0x129) is also available in the Clarke hardware
|
||||
- bugfix in function WriteIO(), the RUN bit in the TIMER2CTRL
|
||||
register (0x12F) has an affection to the display annunciators
|
||||
|
||||
OPCODES.C
|
||||
- added io.h in header definition
|
||||
- bugfix in RTI command, low NINT2 or NINT line reenter interrupt
|
||||
- bugfix in function o808C() and o808E(), opcodes PC=(A) and PC=(C)
|
||||
modify the CRC register
|
||||
|
||||
OPCODES.H
|
||||
- moved HST bit definition to TYPES.H
|
||||
|
||||
RESOURCE.H
|
||||
- added several definitions
|
||||
|
||||
SETTINGS.C
|
||||
- changed function ReadSettings() and WriteSettings(), added section
|
||||
[Disassembler] in INI-File
|
||||
|
||||
TYPES.H
|
||||
- added definition of HST bits
|
||||
|
||||
|
||||
Service Pack 18 for Emu48 Version 1.0
|
||||
|
||||
EMU48.RC
|
||||
- changed version and copyright
|
||||
|
||||
ENGINE.C
|
||||
- bugfix in function WorkerThread(), ignore SHUTDN on interrupt
|
||||
request
|
||||
|
||||
SERIAL.C
|
||||
- bugfix in function CommOpen(), must wait for EV_RXCHAR event
|
||||
thread directly after opening the serial port
|
||||
|
||||
|
||||
Service Pack 17 for Emu48 Version 1.0
|
||||
|
||||
DEBUGGER.C
|
||||
- bugfix in function StrToReg() and OnLButtonUp(), wrong string to
|
||||
HEX conversation with lowercase letters
|
||||
- bugfix in function Debugger(), used wrong background color in
|
||||
WM_CTLCOLORSTATIC message handler
|
||||
|
||||
EMU48.C
|
||||
- bugfix in function SettingsProc(), don't overwite Serial-Ir
|
||||
setting in HP49 mode
|
||||
|
||||
EMU48.DSP
|
||||
- added i28f160.c sources
|
||||
|
||||
EMU48.H
|
||||
- extern declaration of global variable and functions
|
||||
|
||||
EMU48.RC
|
||||
- changed version and copyright
|
||||
|
||||
FILES.C
|
||||
- added new functions in the ROM patch part
|
||||
- changed function PatchRom(), original content of patched address
|
||||
is saved now
|
||||
- changed function MapRom(), added ROM writing feature
|
||||
- changed function UnmapRom(), restore original content before
|
||||
closing
|
||||
- bugfix in function MapPort2(), shared mode now works, when first
|
||||
program instance opened the file with Read/Write access
|
||||
- changed function NewDocument() and OpenDocument(), initialize
|
||||
flash memory structure
|
||||
|
||||
I28F160.C
|
||||
- new modul with I28F160 flash memory implementation
|
||||
|
||||
I28F160.H
|
||||
- header file for flash memory implementation
|
||||
|
||||
MOPS.C
|
||||
- changed function MapROM(), added flash register mode
|
||||
- changed function Npeek(), added flash access part
|
||||
- changed function Nread(), completed flash access part
|
||||
- changed function Nwrite(), completed flash access part
|
||||
|
||||
OPS.H
|
||||
- bugfix in function FASTPTR(), handle NULL pointer pages now
|
||||
- bugfix in function Ninc(), Ndec(), Nadd(), Nsub(), Nrsub(), Nnot()
|
||||
and Nneg(), wrong results in dec mode with illegal decimal number
|
||||
entry
|
||||
|
||||
SETTINGS.C
|
||||
- changed function ReadSettings() and WriteSettings(), added section
|
||||
[ROM] in INI-File
|
||||
|
||||
TIMER.C
|
||||
- bugfix in function CalcT2(), workaround to minimize skipping
|
||||
timer2 values
|
||||
|
||||
|
||||
Service Pack 16 for Emu48 Version 1.0
|
||||
|
||||
DEBUGGER.C
|
||||
- added "MMU" and "Miscellaneous" view in debugger dialog
|
||||
- added RPL exit breakpoint on A=DAT0 A, D0=D0+ 5, PC=(A) sequence
|
||||
- added last instruction viewer in debugger
|
||||
- renamed funtion name ViewStackWnd() to UpdateStackWnd()
|
||||
- bugfix in function UpdateRegisterWnd() and OnCtlColorStatic(),
|
||||
fixed problems of register update in RUN mode
|
||||
- bugfix in function OnKeyF11(), in sleep mode break hasn't worked
|
||||
- bugfix in function OnLButtonUp(), register setting wasn't disabled
|
||||
in running state
|
||||
- changed function NotifyDebugger(), added argument to detect RPL
|
||||
breakpoint
|
||||
- bugfix in function Debugger(), code disassembler wasn't reset to
|
||||
mapped mode at startup and fixed a resource leak
|
||||
- bugfix in function EditBreakpoint(), added breakpoint buffer
|
||||
overflow check at add breakpoint command
|
||||
|
||||
DEBUGGER.H
|
||||
- extern declaration of global variables
|
||||
|
||||
DISASM.C
|
||||
- bugfix in function disasm_1(), the C=ss, ss=C and CssEX opcodes
|
||||
showed always as A=ss, ss=A and AssEX opcodes
|
||||
- bugfix in function disasm_8(), the r register in the rSRB.F fs
|
||||
opcodes and the opcode lenght was wrong
|
||||
|
||||
EMU48.C
|
||||
- new function CopyItemsToClipboard(), copy selected items from
|
||||
listbox to clipboard, extracted from function Disasm()
|
||||
- added HP38G64K stuff to function UpdateWindowStatus() and
|
||||
SettingsProc()
|
||||
- changed function Disasm(), call function CopyItemsToClipboard()
|
||||
now
|
||||
|
||||
EMU48.H
|
||||
- extern declaration of global functions
|
||||
|
||||
EMU48.RC
|
||||
- added "MMU" and "Miscellaneous" part in debugger dialog
|
||||
- changed copyright date in IDD_ABOUT
|
||||
- changed version and copyright
|
||||
|
||||
ENGINE.C
|
||||
- added RPL breakpoint handling
|
||||
- added last instruction buffer update handling
|
||||
- changed function WorkerThread(), added timer emulation in debugger
|
||||
mode
|
||||
- bugfix infunction WorkerThread(), in debugger mode Chipset.pc may
|
||||
have been changed, so the FASTPTR access must be updated as well
|
||||
|
||||
EXTERNAL.C
|
||||
- some minor changes for the HP38G64K beeper emulation
|
||||
|
||||
FILES.C
|
||||
- added new document type for HP38G64K
|
||||
|
||||
IO.H
|
||||
- added CARDCTL and LCR definitions
|
||||
|
||||
KEYBOARD.C
|
||||
- bugfix in function ScanKeyboard(), update keyboard status only on
|
||||
timer running and keyboard interrupt only occur on the rising edge
|
||||
of "logic or" of IR[8:0] and not on the rising edge of each line;
|
||||
the IRX15 interrupt (ON key) is level sensitive
|
||||
|
||||
MOPS.C
|
||||
- added function MapData() to detect the memory controller handle
|
||||
the given address, needed for function Npeek(), Nread() and
|
||||
Nwrite()
|
||||
- bugfix in function MapROM(), no difference between Clarke and
|
||||
Yorke chip in DA19 bit behavior, depends on ROM size
|
||||
- bugfix in function Map(), on a HP49 NCE3 may mapped to ROM
|
||||
- changed function CpuReset(), reset WSM state of flash memory
|
||||
- bugfix in function Npeek(), update card status register in I/O
|
||||
register area before reading and simulate an open data bus
|
||||
- bugfix in function Nread(), loaded wrong bank switcher FF value
|
||||
for a HP49
|
||||
- bugfix in function Nwrite(), loaded wrong bank switcher FF value
|
||||
when writing on slot2 enabled (GX only)
|
||||
- changed function Nread() and Nwrite(), added Flash memory access
|
||||
detection part
|
||||
- bugfix in function ReadIO(), the CARDSTATUS register (0x10F)
|
||||
return zero when card detection is disabled
|
||||
- bugfix in function WriteIO(), on a HP49 force new memory mapping
|
||||
on changing the LED bit in the LCR register (0x11C)
|
||||
|
||||
RESOURCE.H
|
||||
- added several definitions
|
||||
|
||||
TYPES.H
|
||||
- conditional compiling of cycle counter (32bit EXE/64bit DLL)
|
||||
- use position of Port2_NBanks for flash memory WSM state variable
|
||||
|
||||
|
||||
Service Pack 15 for Emu48 Version 1.0
|
||||
|
||||
DEBUGGER.C
|
||||
|
@ -200,7 +550,7 @@ EXTERNAL.C
|
|||
- some minor changes for the HP49 beeper emulation
|
||||
|
||||
FILES.C
|
||||
- added new document type for HP49G
|
||||
- added new document type for HP49
|
||||
- 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
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,12 +7,13 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// #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
|
||||
// breakpoint type definitions
|
||||
#define BP_EXEC 1 // code breakpoint
|
||||
#define BP_READ 2 // read memory breakpoint
|
||||
#define BP_WRITE 4 // write memory breakpoint
|
||||
#define BP_ACCESS (BP_READ|BP_WRITE) // read/write memory breakpoint
|
||||
|
||||
// 13.11.99 cg, new, debugger state definitions
|
||||
// debugger state definitions
|
||||
#define DBG_RUN 0
|
||||
#define DBG_STEPINTO 1
|
||||
#define DBG_STEPOVER 2
|
||||
|
@ -22,10 +23,16 @@
|
|||
extern HWND hDlgDebug;
|
||||
extern HANDLE hEventDebug;
|
||||
extern BOOL bDbgEnable;
|
||||
extern INT nDbgState; // 13.11.99 cg, state of debugger
|
||||
extern INT nDbgState;
|
||||
extern BOOL bDbgNOP3;
|
||||
extern BOOL bDbgRPL;
|
||||
extern BOOL bDbgSkipInt;
|
||||
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 DWORD dwDbgRstk;
|
||||
extern DWORD *pdwInstrArray;
|
||||
extern WORD wInstrSize;
|
||||
extern WORD wInstrWp;
|
||||
extern WORD wInstrRp;
|
||||
extern BOOL CheckBreakpoint(DWORD dwAddr, DWORD wRange, UINT nType);
|
||||
extern VOID NotifyDebugger(BOOL bType);
|
||||
extern LRESULT OnToolDebug(VOID);
|
||||
|
|
|
@ -503,13 +503,14 @@ static char *disasm_1 (DWORD *addr, char *out)
|
|||
case 0:
|
||||
case 1:
|
||||
fn = read_nibble (addr);
|
||||
fn = (fn & 7);
|
||||
if (fn > 4)
|
||||
fn -= 4;
|
||||
c = (fn < 8); // flag for operand register
|
||||
fn = (fn & 7); // get register number
|
||||
if (fn > 4) // illegal opcode
|
||||
break; // no output
|
||||
switch (disassembler_mode)
|
||||
{
|
||||
case HP_MNEMONICS:
|
||||
c = (char) ((fn < 8) ? 'A' : 'C');
|
||||
c = (char) (c ? 'A' : 'C');
|
||||
if (n == 0)
|
||||
wsprintf (buf, "R%d=%c", fn, c);
|
||||
else
|
||||
|
@ -519,7 +520,7 @@ static char *disasm_1 (DWORD *addr, char *out)
|
|||
case CLASS_MNEMONICS:
|
||||
p = append_str (out, "move.w");
|
||||
p = append_tab (out);
|
||||
c = (char) ((fn < 8) ? 'a' : 'c');
|
||||
c = (char) (c ? 'a' : 'c');
|
||||
if (n == 0)
|
||||
wsprintf (buf, "%c, r%d", c, fn);
|
||||
else
|
||||
|
@ -534,20 +535,21 @@ static char *disasm_1 (DWORD *addr, char *out)
|
|||
|
||||
case 2:
|
||||
fn = read_nibble (addr);
|
||||
fn = (fn & 7);
|
||||
if (fn > 4)
|
||||
fn -= 4;
|
||||
c = (fn < 8); // flag for operand register
|
||||
fn = (fn & 7); // get register number
|
||||
if (fn > 4) // illegal opcode
|
||||
break; // no output
|
||||
switch (disassembler_mode)
|
||||
{
|
||||
case HP_MNEMONICS:
|
||||
c = (char) ((fn < 8) ? 'A' : 'C');
|
||||
c = (char) (c ? 'A' : 'C');
|
||||
wsprintf (buf, "%cR%dEX", c, fn);
|
||||
p = append_str (out, buf);
|
||||
break;
|
||||
case CLASS_MNEMONICS:
|
||||
p = append_str (out, "exg.w");
|
||||
p = append_tab (out);
|
||||
c = (char) ((fn < 8) ? 'a' : 'c');
|
||||
c = (char) (c ? 'a' : 'c');
|
||||
wsprintf (buf, "%c, r%d", c, fn);
|
||||
p = append_str (p, buf);
|
||||
break;
|
||||
|
@ -1020,6 +1022,8 @@ static char *disasm_8 (DWORD *addr, char *out, BOOL view)
|
|||
break;
|
||||
|
||||
case 9:
|
||||
fn = read_nibble (addr); // get field selector
|
||||
n = read_nibble (addr); // get register selector
|
||||
switch (disassembler_mode)
|
||||
{
|
||||
case HP_MNEMONICS:
|
||||
|
@ -1027,11 +1031,11 @@ static char *disasm_8 (DWORD *addr, char *out, BOOL view)
|
|||
op_str_81[(n & 3) + 4 * disassembler_mode]);
|
||||
p = append_str (out, buf);
|
||||
p = append_tab (out);
|
||||
p = append_field (p, read_nibble (addr));
|
||||
p = append_field (p, fn);
|
||||
break;
|
||||
case CLASS_MNEMONICS:
|
||||
p = append_str (out, "lsr");
|
||||
p = append_field (p, read_nibble (addr));
|
||||
p = append_field (p, fn);
|
||||
p = append_tab (out);
|
||||
p = append_str (p, "#1, ");
|
||||
p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "pch.h"
|
||||
#include "resource.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h"
|
||||
#include "kml.h"
|
||||
|
||||
#define LCD1_ROW 144
|
||||
|
@ -109,8 +110,13 @@ VOID CreateLcdBitmap()
|
|||
bmiLcd.Lcd_bmih.biWidth = LCD1_ROW * nLcdDoubled;
|
||||
bmiLcd.Lcd_bmih.biHeight = -64 * nLcdDoubled;
|
||||
hLcdDC = CreateCompatibleDC(hWindowDC);
|
||||
_ASSERT(hLcdDC != NULL);
|
||||
hLcdBitmap = CreateDIBSection(hLcdDC, (BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS, (LPVOID*)&pbyLcd, NULL, 0);
|
||||
_ASSERT(hLcdBitmap != NULL);
|
||||
hOldLcdBitmap = SelectObject(hLcdDC, hLcdBitmap);
|
||||
_ASSERT(hPalette != NULL);
|
||||
SelectPalette(hLcdDC, hPalette, FALSE); // set palette for LCD DC
|
||||
RealizePalette(hLcdDC); // realize palette
|
||||
UpdateContrast(Chipset.contrast);
|
||||
}
|
||||
|
||||
|
@ -135,7 +141,12 @@ VOID DestroyLcdBitmap()
|
|||
|
||||
BOOL CreateMainBitmap(LPSTR szFilename)
|
||||
{
|
||||
HPALETTE hAssertPalette;
|
||||
|
||||
_ASSERT(hWindowDC != NULL);
|
||||
hMainDC = CreateCompatibleDC(hWindowDC);
|
||||
_ASSERT(hMainDC != NULL);
|
||||
if (hMainDC == NULL) return FALSE; // quit if failed
|
||||
hMainBitmap = LoadBitmapFile(szFilename);
|
||||
if (hMainBitmap == NULL)
|
||||
{
|
||||
|
@ -143,7 +154,10 @@ BOOL CreateMainBitmap(LPSTR szFilename)
|
|||
return FALSE;
|
||||
}
|
||||
hOldMainBitmap = SelectObject(hMainDC, hMainBitmap);
|
||||
SelectPalette(hMainDC, hPalette, FALSE);
|
||||
_ASSERT(hPalette != NULL);
|
||||
hAssertPalette = SelectPalette(hMainDC, hPalette, FALSE);
|
||||
_ASSERT(hAssertPalette != NULL);
|
||||
RealizePalette(hMainDC);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -556,14 +570,17 @@ VOID UpdateAnnunciators()
|
|||
{
|
||||
BYTE c;
|
||||
|
||||
c = (BYTE)(Chipset.IORam[0xB] | (Chipset.IORam[0xC]<<4));
|
||||
if (!(c&0x80)) c=0;
|
||||
DrawAnnunciator(1,c&0x01);
|
||||
DrawAnnunciator(2,c&0x02);
|
||||
DrawAnnunciator(3,c&0x04);
|
||||
DrawAnnunciator(4,c&0x08);
|
||||
DrawAnnunciator(5,c&0x10);
|
||||
DrawAnnunciator(6,c&0x20);
|
||||
c = (BYTE)(Chipset.IORam[ANNCTRL] | (Chipset.IORam[ANNCTRL+1]<<4));
|
||||
// switch annunciators off if timer stopped
|
||||
if ((c & AON) == 0 || (Chipset.IORam[TIMER2_CTRL] & RUN) == 0)
|
||||
c=0;
|
||||
|
||||
DrawAnnunciator(1,c&LA1);
|
||||
DrawAnnunciator(2,c&LA2);
|
||||
DrawAnnunciator(3,c&LA3);
|
||||
DrawAnnunciator(4,c&LA4);
|
||||
DrawAnnunciator(5,c&LA5);
|
||||
DrawAnnunciator(6,c&LA6);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,10 +9,11 @@
|
|||
#include "pch.h"
|
||||
#include "resource.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h"
|
||||
#include "kml.h"
|
||||
#include "debugger.h"
|
||||
|
||||
#define VERSION "1.15" // 23.10.99 cg, changed version
|
||||
#define VERSION "1.20"
|
||||
#define CF_HPOBJ "CF_HPOBJ" // clipboard format for DDE
|
||||
|
||||
#define MAXPORTS 16 // number of COM ports
|
||||
|
@ -28,7 +29,7 @@ LPSTR szAppName = "Emu48"; // application name for DDE server
|
|||
LPSTR szTopic = "Stack"; // topic for DDE server
|
||||
LPSTR szTitle = NULL;
|
||||
|
||||
static const char szLicence[] = // 30.11.99 cg, changed, update of address
|
||||
static const char szLicence[] =
|
||||
"This program is free software; you can redistribute it and/or modify\r\n"
|
||||
"it under the terms of the GNU General Public License as published by\r\n"
|
||||
"the Free Software Foundation; either version 2 of the License, or\r\n"
|
||||
|
@ -49,10 +50,11 @@ CRITICAL_SECTION csKeyLock; // critical section for key scan
|
|||
CRITICAL_SECTION csIOLock; // critical section for I/O access
|
||||
CRITICAL_SECTION csT1Lock; // critical section for timer1 access
|
||||
CRITICAL_SECTION csT2Lock; // critical section for timer2 access
|
||||
CRITICAL_SECTION csRecvLock; // 24.10.99 cg, moved, critical section for receive byte
|
||||
INT nArgc; // 08.11.99 cg, new, no. of command line arguments
|
||||
LPCTSTR *ppArgv; // 08.11.99 cg, new, command line arguments
|
||||
LARGE_INTEGER lFreq; // counter frequency
|
||||
CRITICAL_SECTION csRecvLock; // critical section for receive byte
|
||||
INT nArgc; // no. of command line arguments
|
||||
LPCTSTR *ppArgv; // command line arguments
|
||||
LARGE_INTEGER lFreq; // high performance counter frequency
|
||||
LARGE_INTEGER lAppStart; // high performance counter value at Appl. start
|
||||
DWORD idDdeInst; // DDE server id
|
||||
UINT uCF_HpObj; // DDE clipboard format
|
||||
HANDLE hThread;
|
||||
|
@ -110,10 +112,9 @@ VOID UpdateWindowStatus()
|
|||
|
||||
if ((nState == 0)||(nState == 3))
|
||||
{
|
||||
// 02.12.99 cg, new, disable stack loading items on HP38G
|
||||
UINT uStackEnable = (cCurrentRomType!='A') ? MF_ENABLED : MF_GRAYED;
|
||||
// disable stack loading items on HP38G
|
||||
UINT uStackEnable = (cCurrentRomType!='6' && cCurrentRomType!='A') ? MF_ENABLED : MF_GRAYED;
|
||||
|
||||
// 02.12.99 cg, changed implementation
|
||||
EnableMenuItem(hMenu,ID_FILE_SAVE,(szCurrentFilename[0]) ? MF_ENABLED : MF_GRAYED);
|
||||
EnableMenuItem(hMenu,ID_FILE_SAVEAS,MF_ENABLED);
|
||||
EnableMenuItem(hMenu,ID_FILE_CLOSE,MF_ENABLED);
|
||||
|
@ -121,12 +122,10 @@ VOID UpdateWindowStatus()
|
|||
EnableMenuItem(hMenu,ID_BACKUP_SAVE,MF_ENABLED);
|
||||
EnableMenuItem(hMenu,ID_VIEW_COPY,MF_ENABLED);
|
||||
EnableMenuItem(hMenu,ID_VIEW_RESET,MF_ENABLED);
|
||||
// 02.12.99 cg, new, added HP38G part
|
||||
EnableMenuItem(hMenu,ID_OBJECT_LOAD,uStackEnable);
|
||||
EnableMenuItem(hMenu,ID_OBJECT_SAVE,uStackEnable);
|
||||
EnableMenuItem(hMenu,ID_STACK_COPY,uStackEnable);
|
||||
EnableMenuItem(hMenu,ID_STACK_PASTE,uStackEnable);
|
||||
// 02.12.99 cg, end of added part
|
||||
EnableMenuItem(hMenu,ID_TOOL_DISASM,MF_ENABLED);
|
||||
}
|
||||
else
|
||||
|
@ -158,6 +157,70 @@ VOID UpdateWindowStatus()
|
|||
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Clipboard Tool
|
||||
//#
|
||||
//################
|
||||
|
||||
VOID CopyItemsToClipboard(HWND hWnd) // save selected Listbox Items to Clipboard
|
||||
{
|
||||
LONG i;
|
||||
LPINT lpnCount;
|
||||
|
||||
// get number of selections
|
||||
if ((i = SendMessage(hWnd,LB_GETSELCOUNT,0,0)) == 0)
|
||||
return; // no items selected
|
||||
|
||||
if ((lpnCount = (LPINT) LocalAlloc(LMEM_FIXED,i * sizeof(INT))) != NULL)
|
||||
{
|
||||
HANDLE hClipObj;
|
||||
LONG j,lMem = 0;
|
||||
|
||||
// get indexes of selected items
|
||||
i = SendMessage(hWnd,LB_GETSELITEMS,i,(LPARAM) lpnCount);
|
||||
for (j = 0;j < i;++j) // scan all selected items
|
||||
{
|
||||
// calculate total amount of needed memory
|
||||
lMem += SendMessage(hWnd,LB_GETTEXTLEN,lpnCount[j],0) + 2;
|
||||
}
|
||||
// allocate clipboard data
|
||||
if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,lMem + 1)) != NULL)
|
||||
{
|
||||
LPBYTE lpData;
|
||||
|
||||
if (lpData = GlobalLock(hClipObj))
|
||||
{
|
||||
for (j = 0;j < i;++j) // scan all selected items
|
||||
{
|
||||
lpData += SendMessage(hWnd,LB_GETTEXT,lpnCount[j],(LPARAM) lpData);
|
||||
*lpData++ = '\r';
|
||||
*lpData++ = '\n';
|
||||
}
|
||||
*lpData = 0; // set end of string
|
||||
GlobalUnlock(hClipObj); // unlock memory
|
||||
}
|
||||
|
||||
if (OpenClipboard(hWnd))
|
||||
{
|
||||
if (EmptyClipboard())
|
||||
SetClipboardData(CF_TEXT,hClipObj);
|
||||
else
|
||||
GlobalFree(hClipObj);
|
||||
CloseClipboard();
|
||||
}
|
||||
else // clipboard open failed
|
||||
{
|
||||
GlobalFree(hClipObj);
|
||||
}
|
||||
}
|
||||
LocalFree(lpnCount); // free item table
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Settings
|
||||
|
@ -210,6 +273,9 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP
|
|||
CheckDlgButton(hDlg,IDC_AUTOSAVEONEXIT,bAutoSaveOnExit);
|
||||
CheckDlgButton(hDlg,IDC_ALWAYSDISPLOG,bAlwaysDisplayLog);
|
||||
|
||||
// set disassebler mode
|
||||
CheckDlgButton(hDlg,(disassembler_mode == HP_MNEMONICS) ? IDC_DISASM_HP : IDC_DISASM_CLASS,BST_CHECKED);
|
||||
|
||||
// set combobox parameter
|
||||
SetCommList(hDlg,IDC_WIRE,szSerialWire);
|
||||
SetCommList(hDlg,IDC_IR,szSerialIr);
|
||||
|
@ -219,12 +285,11 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP
|
|||
EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE);
|
||||
}
|
||||
|
||||
// 01.12.99 cg, HP48SX/GX
|
||||
if (cCurrentRomType!='A' && cCurrentRomType!='X')
|
||||
// HP48SX/GX
|
||||
if (cCurrentRomType!='6' && cCurrentRomType!='A' && cCurrentRomType!='X')
|
||||
{
|
||||
// init port1 enable checkbox
|
||||
CheckDlgButton(hDlg,IDC_PORT1EN,(Chipset.cards_status & PORT1_PRESENT) != 0);
|
||||
// 19.11.99 cg, changed, use cards_status variable now
|
||||
CheckDlgButton(hDlg,IDC_PORT1WR,(Chipset.cards_status & PORT1_WRITE) != 0);
|
||||
// init port2 shared checkbox and set port2 filename
|
||||
CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared);
|
||||
|
@ -245,7 +310,7 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP
|
|||
CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared);
|
||||
SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename);
|
||||
}
|
||||
if (cCurrentRomType=='X') // 01.12.99 cg, HP48SX/GX
|
||||
if (cCurrentRomType=='X') // HP49G
|
||||
{
|
||||
SendDlgItemMessage(hDlg,IDC_IR,CB_RESETCONTENT,0,0);
|
||||
EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE);
|
||||
|
@ -264,19 +329,27 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP
|
|||
if (Chipset.Port1Size && cCurrentRomType!='X')
|
||||
{
|
||||
UINT nOldState = SwitchToState(3);
|
||||
// port1 disabled ?;
|
||||
// save old card status
|
||||
BYTE bCardsStatus = Chipset.cards_status;
|
||||
|
||||
// port1 disabled?
|
||||
Chipset.cards_status &= ~(PORT1_PRESENT | PORT1_WRITE);
|
||||
if (IsDlgButtonChecked(hDlg, IDC_PORT1EN))
|
||||
{
|
||||
Chipset.cards_status |= PORT1_PRESENT;
|
||||
// 19.11.99 cg, changed, use dialog variable now
|
||||
if (IsDlgButtonChecked(hDlg, IDC_PORT1WR))
|
||||
Chipset.cards_status |= PORT1_WRITE;
|
||||
}
|
||||
if (Chipset.inte)
|
||||
|
||||
// changed card status in slot1?
|
||||
if ( ((bCardsStatus ^ Chipset.cards_status) & (PORT1_PRESENT | PORT1_WRITE)) != 0
|
||||
&& (Chipset.IORam[CARDCTL] & ECDT) != 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0
|
||||
)
|
||||
{
|
||||
Chipset.Shutdn = FALSE;
|
||||
Chipset.SoftInt = TRUE;
|
||||
|
||||
Chipset.HST |= MP; // set Module Pulled
|
||||
IOBit(SRQ2,NINT,FALSE); // set NINT to low
|
||||
Chipset.SoftInt = TRUE; // set interrupt
|
||||
bInterrupt = TRUE;
|
||||
}
|
||||
Map(0x00,0xFF);
|
||||
|
@ -293,9 +366,12 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP
|
|||
bPort2IsShared = IsDlgButtonChecked(hDlg,IDC_PORT2ISSHARED);
|
||||
GetDlgItemText(hDlg,IDC_PORT2,szPort2Filename,sizeof(szPort2Filename));
|
||||
}
|
||||
// set disassebler mode
|
||||
disassembler_mode = IsDlgButtonChecked(hDlg,IDC_DISASM_HP) ? HP_MNEMONICS : CLASS_MNEMONICS;
|
||||
// set combobox parameter
|
||||
GetDlgItemText(hDlg,IDC_WIRE,szSerialWire,sizeof(szSerialWire));
|
||||
GetDlgItemText(hDlg,IDC_IR ,szSerialIr ,sizeof(szSerialIr));
|
||||
if (cCurrentRomType!='X') // HP49G Ir port is not connected
|
||||
GetDlgItemText(hDlg,IDC_IR,szSerialIr,sizeof(szSerialIr));
|
||||
EndDialog(hDlg, wParam);
|
||||
}
|
||||
if (wParam == IDCANCEL)
|
||||
|
@ -340,7 +416,7 @@ static UINT SaveChanges(BOOL bAuto)
|
|||
uReply = GetSaveAsFilename();
|
||||
if (uReply != IDOK) return uReply;
|
||||
if (!SaveDocumentAs(szBufferFilename)) return IDCANCEL;
|
||||
WriteLastDocument(szCurrentFilename); // 11.12.99 cg, changed, call function
|
||||
WriteLastDocument(szCurrentFilename);
|
||||
return IDYES;
|
||||
}
|
||||
|
||||
|
@ -361,6 +437,13 @@ static UINT SaveChanges(BOOL bAuto)
|
|||
//
|
||||
static LRESULT OnCreate(HWND hWindow)
|
||||
{
|
||||
InitializeCriticalSection(&csGDILock);
|
||||
InitializeCriticalSection(&csKeyLock);
|
||||
InitializeCriticalSection(&csIOLock);
|
||||
InitializeCriticalSection(&csT1Lock);
|
||||
InitializeCriticalSection(&csT2Lock);
|
||||
InitializeCriticalSection(&csRecvLock);
|
||||
|
||||
hWnd = hWindow;
|
||||
hWindowDC = GetDC(hWnd);
|
||||
DragAcceptFiles(hWnd,TRUE); // support dropped files
|
||||
|
@ -373,12 +456,18 @@ static LRESULT OnCreate(HWND hWindow)
|
|||
static LRESULT OnDestroy(HWND hWindow)
|
||||
{
|
||||
DragAcceptFiles(hWnd,FALSE); // no WM_DROPFILES message any more
|
||||
// SwitchToState(2); // 01.12.99 cg, removed, doing in main program now
|
||||
// WriteSettings(); // 01.12.99 cg, removed, doing in main program now
|
||||
ReleaseDC(hWnd, hWindowDC);
|
||||
SetWindowTitle(NULL); // free memory of title
|
||||
hWindowDC = NULL; // hWindowDC isn't valid any more
|
||||
hWnd = NULL;
|
||||
|
||||
DeleteCriticalSection(&csGDILock);
|
||||
DeleteCriticalSection(&csKeyLock);
|
||||
DeleteCriticalSection(&csIOLock);
|
||||
DeleteCriticalSection(&csT1Lock);
|
||||
DeleteCriticalSection(&csT2Lock);
|
||||
DeleteCriticalSection(&csRecvLock);
|
||||
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
UNREFERENCED_PARAMETER(hWindow);
|
||||
|
@ -395,7 +484,12 @@ static LRESULT OnPaint(HWND hWindow)
|
|||
hPaintDC = BeginPaint(hWindow, &Paint);
|
||||
if (hMainDC != NULL)
|
||||
{
|
||||
BitBlt(hPaintDC, 0, 0, nBackgroundW, nBackgroundH, hMainDC, nBackgroundX, nBackgroundY, SRCCOPY);
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
BitBlt(hPaintDC, 0, 0, nBackgroundW, nBackgroundH, hMainDC, nBackgroundX, nBackgroundY, SRCCOPY);
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
if ((nState==0)||(nState==3))
|
||||
{
|
||||
UpdateMainDisplay();
|
||||
|
@ -417,7 +511,8 @@ static LRESULT OnDropFiles(HANDLE hFilesInfo)
|
|||
WORD wNumFiles,wIndex;
|
||||
BOOL bSuccess;
|
||||
|
||||
if (cCurrentRomType=='A') return 0; // 06.12.99 cg, new, HP38 has no stack, ignore
|
||||
// HP38 has no stack, ignore
|
||||
if (cCurrentRomType=='6' || cCurrentRomType=='A') return 0;
|
||||
|
||||
// get number of files dropped
|
||||
wNumFiles = DragQueryFile (hFilesInfo,(UINT)-1,NULL,0);
|
||||
|
@ -438,7 +533,6 @@ static LRESULT OnDropFiles(HANDLE hFilesInfo)
|
|||
return 0;
|
||||
}
|
||||
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
_ASSERT(nState==3);
|
||||
|
||||
// get each name and load it into the emulator
|
||||
|
@ -547,7 +641,7 @@ static LRESULT OnFileSaveAs()
|
|||
SwitchToState(0);
|
||||
return 0;
|
||||
}
|
||||
WriteLastDocument(szCurrentFilename); // 11.12.99 cg, changed, call function
|
||||
WriteLastDocument(szCurrentFilename);
|
||||
|
||||
SwitchToState(0);
|
||||
return 0;
|
||||
|
@ -606,7 +700,6 @@ static LRESULT OnStackCopy() // copy data from stack
|
|||
return 0;
|
||||
}
|
||||
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
_ASSERT(nState==3);
|
||||
|
||||
if ((dwAddress = RPL_Pick(1)) == 0) // pick address of level1 object
|
||||
|
@ -682,7 +775,6 @@ static LRESULT OnStackPaste() // paste data to stack
|
|||
return 0;
|
||||
}
|
||||
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
_ASSERT(nState==3);
|
||||
|
||||
if (OpenClipboard(hWnd))
|
||||
|
@ -848,7 +940,7 @@ static LRESULT OnViewReset()
|
|||
if (YesNoMessage("Are you sure you want to press the Reset Button ?")==IDYES)
|
||||
{
|
||||
SwitchToState(3);
|
||||
CpuReset(); // 19.03.99 cg, changed, register setting after Cpu Reset
|
||||
CpuReset(); // register setting after Cpu Reset
|
||||
SwitchToState(0);
|
||||
}
|
||||
return 0;
|
||||
|
@ -963,7 +1055,6 @@ static LRESULT OnObjectLoad()
|
|||
return 0;
|
||||
}
|
||||
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
_ASSERT(nState==3);
|
||||
|
||||
if (bWarning)
|
||||
|
@ -971,7 +1062,7 @@ static LRESULT OnObjectLoad()
|
|||
UINT uReply = YesNoCancelMessage(
|
||||
"Warning: Trying to load an object while the emulator is busy \n"
|
||||
"will certainly result in a memory lost. Before loading an object \n"
|
||||
"you should be sure that the HP48 is not doing anything. \n"
|
||||
"you should be sure that the calculator is not doing anything. \n"
|
||||
"Do you want to see this warning next time you try to load an object ?");
|
||||
switch (uReply)
|
||||
{
|
||||
|
@ -1020,9 +1111,11 @@ static LRESULT OnObjectSave()
|
|||
}
|
||||
|
||||
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
|
||||
{
|
||||
InfoMessage("The emulator is busy.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
_ASSERT(nState==3);
|
||||
|
||||
if (!GetSaveObjectFilename())
|
||||
|
@ -1046,7 +1139,6 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
|
|||
static DWORD dwAddress, dwAddressMax;
|
||||
|
||||
LONG i;
|
||||
LPINT lpnCount;
|
||||
char *cpStop,szAddress[256] = "0";
|
||||
|
||||
switch (message)
|
||||
|
@ -1059,11 +1151,7 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
|
|||
SendDlgItemMessage(hDlg,IDC_DISASM_RAM,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
||||
SendDlgItemMessage(hDlg,IDC_DISASM_PORT1,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
||||
SendDlgItemMessage(hDlg,IDC_DISASM_PORT2,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
||||
SendDlgItemMessage(hDlg,IDC_DISASM_MNEMONICS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
||||
SendDlgItemMessage(hDlg,IDC_DISASM_HP,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
||||
SendDlgItemMessage(hDlg,IDC_DISASM_CLASS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
||||
SendDlgItemMessage(hDlg,IDC_DISASM_MAP,BM_SETCHECK,1,0);
|
||||
SendDlgItemMessage(hDlg,IDC_DISASM_HP,BM_SETCHECK,1,0);
|
||||
SendDlgItemMessage(hDlg,IDC_ADDRESS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
||||
SendDlgItemMessage(hDlg,IDC_DISASM_ADR,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
||||
SendDlgItemMessage(hDlg,IDC_DISASM_NEXT,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
||||
|
@ -1071,7 +1159,6 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
|
|||
SendDlgItemMessage(hDlg,IDCANCEL,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
||||
SetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress);
|
||||
disassembler_map = MEM_MAP; // disassemble with mapped modules
|
||||
disassembler_mode = HP_MNEMONICS; // use HP mnemonics for disassembling
|
||||
dwAddress = strtoul(szAddress,&cpStop,16);
|
||||
dwAddressMax = 0x100000; // greatest address (mapped mode)
|
||||
return TRUE;
|
||||
|
@ -1101,12 +1188,6 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
|
|||
? (Chipset.Port2Size * 2048)
|
||||
: ((dwPort2Mask != 0) ? ((dwPort2Mask + 1) << 18) : (dwPort2Size * 2048));
|
||||
return TRUE;
|
||||
case IDC_DISASM_HP:
|
||||
disassembler_mode = HP_MNEMONICS;
|
||||
return TRUE;
|
||||
case IDC_DISASM_CLASS:
|
||||
disassembler_mode = CLASS_MNEMONICS;
|
||||
return TRUE;
|
||||
case IDOK:
|
||||
SendDlgItemMessage(hDlg,IDC_DISASM_ADR,EM_SETSEL,0,-1);
|
||||
GetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress,sizeof(szAddress));
|
||||
|
@ -1121,7 +1202,7 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
|
|||
case IDC_DISASM_NEXT:
|
||||
if (dwAddress >= dwAddressMax)
|
||||
return FALSE;
|
||||
i = wsprintf(szAddress,(dwAddress <= 99999) ? "%05lX " : "%06lX ",dwAddress);
|
||||
i = wsprintf(szAddress,(dwAddress <= 0xFFFFF) ? "%05lX " : "%06lX ",dwAddress);
|
||||
dwAddress = disassemble(dwAddress,&szAddress[i],VIEW_LONG);
|
||||
i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_ADDSTRING,0,(LPARAM) szAddress);
|
||||
SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_SELITEMRANGE,FALSE,MAKELPARAM(0,i));
|
||||
|
@ -1129,54 +1210,8 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
|
|||
SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_SETTOPINDEX,i,0);
|
||||
return TRUE;
|
||||
case IDC_DISASM_COPY:
|
||||
// get number of selections
|
||||
if ((i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETSELCOUNT,0,0)) == 0)
|
||||
break; // no items selected
|
||||
|
||||
if ((lpnCount = (LPINT) LocalAlloc(LMEM_FIXED,i * sizeof(INT))) != NULL)
|
||||
{
|
||||
HANDLE hClipObj;
|
||||
LONG j,lMem = 0;
|
||||
|
||||
// get indexes of selected items
|
||||
i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETSELITEMS,i,(LPARAM) lpnCount);
|
||||
for (j = 0;j < i;++j) // scan all selected items
|
||||
{
|
||||
// calculate total amount of needed memory
|
||||
lMem += SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETTEXTLEN,lpnCount[j],0) + 2;
|
||||
}
|
||||
// allocate clipboard data
|
||||
if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,lMem + 1)) != NULL)
|
||||
{
|
||||
LPBYTE lpData;
|
||||
|
||||
if (lpData = GlobalLock(hClipObj))
|
||||
{
|
||||
for (j = 0;j < i;++j) // scan all selected items
|
||||
{
|
||||
lpData += SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETTEXT,lpnCount[j],(LPARAM) lpData);
|
||||
*lpData++ = '\r';
|
||||
*lpData++ = '\n';
|
||||
}
|
||||
*lpData = 0; // set end of string
|
||||
GlobalUnlock(hClipObj); // unlock memory
|
||||
}
|
||||
|
||||
if (OpenClipboard(hWnd))
|
||||
{
|
||||
if (EmptyClipboard())
|
||||
SetClipboardData(CF_TEXT,hClipObj);
|
||||
else
|
||||
GlobalFree(hClipObj);
|
||||
CloseClipboard();
|
||||
}
|
||||
else // clipboard open failed
|
||||
{
|
||||
GlobalFree(hClipObj);
|
||||
}
|
||||
}
|
||||
LocalFree(lpnCount); // free item table
|
||||
}
|
||||
// copy selected items to clipboard
|
||||
CopyItemsToClipboard(GetDlgItem(hDlg,IDC_DISASM_WIN));
|
||||
return TRUE;
|
||||
case IDCANCEL:
|
||||
EndDialog(hDlg, wParam);
|
||||
|
@ -1335,29 +1370,17 @@ LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
return DefWindowProc(hWindow, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
#if 0 // 01.12.99 cg, removed
|
||||
static BOOL FlushMessages(LPMSG msg)
|
||||
{
|
||||
while (PeekMessage(msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg->message == WM_QUIT) return TRUE;
|
||||
TranslateMessage(msg);
|
||||
DispatchMessage(msg);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#endif // 01.12.99 cg
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
MSG msg;
|
||||
WNDCLASS wc;
|
||||
RECT rectWindow;
|
||||
HSZ hszService, hszTopic; // variables for DDE server
|
||||
DWORD dwAffMask;
|
||||
|
||||
hApp = hInst;
|
||||
nArgc = __argc; // 08.11.99 cg, new, no. of command line arguments
|
||||
ppArgv = (LPCTSTR*) __argv; // 08.11.99 cg, new, command line arguments
|
||||
nArgc = __argc; // no. of command line arguments
|
||||
ppArgv = (LPCTSTR*) __argv; // command line arguments
|
||||
|
||||
wc.style = CS_BYTEALIGNCLIENT;
|
||||
wc.lpfnWndProc = (WNDPROC)MainWndProc;
|
||||
|
@ -1379,7 +1402,6 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
|
|||
}
|
||||
|
||||
// Create window
|
||||
|
||||
rectWindow.left = 0;
|
||||
rectWindow.top = 0;
|
||||
rectWindow.right = 256;
|
||||
|
@ -1402,11 +1424,9 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
|
|||
|
||||
ShowWindow(hWnd, nCmdShow);
|
||||
|
||||
// 01.12.99 cg, removed, useless and quit with resources open
|
||||
// if (FlushMessages(&msg)) return msg.wParam;
|
||||
|
||||
// initialization
|
||||
QueryPerformanceFrequency(&lFreq); // init high resolution counter
|
||||
QueryPerformanceCounter(&lAppStart);
|
||||
|
||||
GetCurrentDirectory(sizeof(szCurrentDirectory), szCurrentDirectory);
|
||||
|
||||
|
@ -1419,20 +1439,25 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
|
|||
if (hEventShutdn == NULL)
|
||||
{
|
||||
AbortMessage("Event creation failed.");
|
||||
DestroyWindow(hWnd); // 02.12.99 cg, bugfix, close DC
|
||||
DestroyWindow(hWnd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nState = 1; // thread starts in an invalid state
|
||||
nNextState = 1;
|
||||
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, NULL, 0, &lThreadId);
|
||||
nState = 0; // init state must be <> nNextState
|
||||
nNextState = 1; // go into invalid state
|
||||
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, NULL, CREATE_SUSPENDED, &lThreadId);
|
||||
if (hThread == NULL)
|
||||
{
|
||||
CloseHandle(hEventShutdn); // close event handle
|
||||
AbortMessage("Thread creation failed.");
|
||||
DestroyWindow(hWnd); // 01.12.99 cg, bugfix, close DC
|
||||
DestroyWindow(hWnd);
|
||||
return FALSE;
|
||||
}
|
||||
// on multiprocessor machines for QueryPerformanceCounter()
|
||||
dwAffMask = SetThreadAffinityMask(hThread,1);
|
||||
_ASSERT(dwAffMask != 0);
|
||||
ResumeThread(hThread); // start thread
|
||||
while (nState!=nNextState) Sleep(0); // wait for thread initialized
|
||||
|
||||
// initialize DDE server
|
||||
if (DdeInitialize(&idDdeInst,(PFNCALLBACK) &DdeCallback,
|
||||
|
@ -1440,42 +1465,36 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
|
|||
CBF_FAIL_EXECUTES | CBF_FAIL_ADVISES |
|
||||
CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS,0))
|
||||
{
|
||||
TerminateThread(hThread, 0); // 01.12.99 cg, bugfix, kill emulation thread
|
||||
CloseHandle(hEventShutdn); // 01.12.99 cg, bugfix, close event handle
|
||||
TerminateThread(hThread, 0); // kill emulation thread
|
||||
CloseHandle(hEventShutdn); // close event handle
|
||||
AbortMessage("Could not initialize server!");
|
||||
DestroyWindow(hWnd); // 01.12.99 cg, bugfix, close DC
|
||||
DestroyWindow(hWnd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// 08.11.99 cg, changed, replaced __argc and __argv variable
|
||||
_ASSERT(hWnd != NULL);
|
||||
_ASSERT(hWindowDC != NULL);
|
||||
|
||||
if (nArgc >= 2) // use decoded parameter line
|
||||
{
|
||||
CHAR szTemp[256] = "Loading ";
|
||||
strcat(szTemp, ppArgv[1]);
|
||||
SetWindowTitle(szTemp);
|
||||
// 01.12.99 cg, removed, useless and quit with resources open
|
||||
// if (FlushMessages(&msg)) return msg.wParam;
|
||||
if (OpenDocument(ppArgv[1]))
|
||||
goto start;
|
||||
}
|
||||
// 08.11.99 cg, end of replacement
|
||||
|
||||
// 11.12.99 cg, changed, call function
|
||||
ReadLastDocument(szBufferFilename, sizeof(szBufferFilename));
|
||||
if (szBufferFilename[0])
|
||||
{
|
||||
CHAR szTemp[256] = "Loading ";
|
||||
strcat(szTemp, szBufferFilename);
|
||||
SetWindowTitle(szTemp);
|
||||
// 01.12.99 cg, removed, useless and quit with resources open
|
||||
// if (FlushMessages(&msg)) return msg.wParam;
|
||||
if (OpenDocument(szBufferFilename))
|
||||
goto start;
|
||||
}
|
||||
|
||||
SetWindowTitle("New Document");
|
||||
// 01.12.99 cg, removed, useless and quit with resources open
|
||||
// if (FlushMessages(&msg)) return msg.wParam;
|
||||
if (NewDocument())
|
||||
{
|
||||
SetWindowTitle("Untitled");
|
||||
|
@ -1485,13 +1504,6 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
|
|||
ResetDocument();
|
||||
|
||||
start:
|
||||
InitializeCriticalSection(&csGDILock);
|
||||
InitializeCriticalSection(&csKeyLock);
|
||||
InitializeCriticalSection(&csIOLock);
|
||||
InitializeCriticalSection(&csT1Lock);
|
||||
InitializeCriticalSection(&csT2Lock);
|
||||
InitializeCriticalSection(&csRecvLock); // 24.10.99 cg, moved, init critical section for receive byte
|
||||
|
||||
// init clipboard format and name service
|
||||
uCF_HpObj = RegisterClipboardFormat(CF_HPOBJ);
|
||||
hszService = DdeCreateStringHandle(idDdeInst,szAppName,0);
|
||||
|
@ -1509,7 +1521,7 @@ start:
|
|||
}
|
||||
}
|
||||
|
||||
SwitchToState(2); // 01.12.99 cg, moved from OnDestroy(), exit emulation thread
|
||||
SwitchToState(2); // exit emulation thread
|
||||
|
||||
// clean up DDE server
|
||||
DdeNameService(idDdeInst, hszService, NULL, DNS_UNREGISTER);
|
||||
|
@ -1517,14 +1529,7 @@ start:
|
|||
DdeFreeStringHandle(idDdeInst, hszTopic);
|
||||
DdeUninitialize(idDdeInst);
|
||||
|
||||
DeleteCriticalSection(&csGDILock);
|
||||
DeleteCriticalSection(&csKeyLock);
|
||||
DeleteCriticalSection(&csIOLock);
|
||||
DeleteCriticalSection(&csT1Lock);
|
||||
DeleteCriticalSection(&csT2Lock);
|
||||
DeleteCriticalSection(&csRecvLock); // 24.10.99 cg, moved, end of critical section for receive byte
|
||||
|
||||
WriteSettings(); // 01.12.99 cg, moved from OnDestroy()
|
||||
WriteSettings(); // save emulation settings
|
||||
|
||||
CloseHandle(hEventShutdn); // close event handle
|
||||
_ASSERT(nState == 2); // emulation thread down?
|
||||
|
|
|
@ -112,13 +112,6 @@ SOURCE=.\Emu48.c
|
|||
# Begin Source File
|
||||
|
||||
SOURCE=.\Emu48.rc
|
||||
|
||||
!IF "$(CFG)" == "Emu48 - Win32 Release"
|
||||
|
||||
!ELSEIF "$(CFG)" == "Emu48 - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
|
@ -138,6 +131,10 @@ SOURCE=.\files.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\i28f160.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\keyboard.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -191,6 +188,10 @@ SOURCE=.\Emu48.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\i28f160.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\io.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
#include "types.h"
|
||||
|
||||
// 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 PORT1_PRESENT ((cCurrentRomType=='S')?P1C:P2C)
|
||||
#define PORT1_WRITE ((cCurrentRomType=='S')?P1W:P2W)
|
||||
#define PORT2_PRESENT ((cCurrentRomType=='S')?P2C:P1C)
|
||||
#define PORT2_WRITE ((cCurrentRomType=='S')?P2W:P1W)
|
||||
|
||||
#define BINARYHEADER48 "HPHP48-W"
|
||||
#define BINARYHEADER49 "HPHP49-W"
|
||||
|
@ -56,28 +56,29 @@ 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 CRITICAL_SECTION csRecvLock;
|
||||
extern INT nArgc;
|
||||
extern LPCTSTR *ppArgv;
|
||||
extern LARGE_INTEGER lFreq;
|
||||
extern LARGE_INTEGER lAppStart;
|
||||
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 bAutoSave;
|
||||
extern BOOL bAutoSaveOnExit;
|
||||
extern BOOL bAlwaysDisplayLog;
|
||||
// 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 HANDLE hThread;
|
||||
extern DWORD lThreadId;
|
||||
extern VOID SetWindowTitle(LPSTR szString);
|
||||
extern VOID CopyItemsToClipboard(HWND hWnd);
|
||||
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 ReadSettings(VOID);
|
||||
extern VOID WriteSettings(VOID);
|
||||
extern VOID ReadLastDocument(LPTSTR szFileName, DWORD nSize);
|
||||
extern VOID WriteLastDocument(LPCTSTR szFilename);
|
||||
|
||||
|
@ -110,7 +111,7 @@ extern VOID ResizeWindow(VOID);
|
|||
extern BOOL bInterrupt;
|
||||
extern UINT nState;
|
||||
extern UINT nNextState;
|
||||
extern BOOL bRealSpeed; // 11.12.99 cg, new, real speed flag
|
||||
extern BOOL bRealSpeed;
|
||||
extern BOOL bKeySlow;
|
||||
extern CHIPSET Chipset;
|
||||
extern char szSerialWire[16];
|
||||
|
@ -141,6 +142,7 @@ extern char szPort2Filename[260];
|
|||
extern LPBYTE pbyRom;
|
||||
extern DWORD dwRomSize;
|
||||
extern char cCurrentRomType;
|
||||
extern BOOL bRomWriteable;
|
||||
extern LPBYTE pbyPort2;
|
||||
extern BOOL bPort2Writeable;
|
||||
extern BOOL bPort2IsShared;
|
||||
|
@ -152,6 +154,7 @@ extern BOOL MapRom(LPCSTR szFilename);
|
|||
extern VOID UnmapRom(VOID);
|
||||
extern BOOL MapPort2(LPCSTR szFilename);
|
||||
extern VOID UnmapPort2(VOID);
|
||||
extern VOID UpdatePatches(BOOL bPatch);
|
||||
extern BOOL PatchRom(LPCSTR szFilename);
|
||||
extern VOID ResetDocument(VOID);
|
||||
extern BOOL NewDocument(VOID);
|
||||
|
@ -181,6 +184,7 @@ extern VOID SetT1(BYTE byValue);
|
|||
// MOps.c
|
||||
extern BOOL ioc_acc;
|
||||
extern BOOL ir_ctrl_acc;
|
||||
extern BOOL bFlashRomArray;
|
||||
extern BYTE disp;
|
||||
extern LPBYTE RMap[256];
|
||||
extern LPBYTE WMap[256];
|
||||
|
@ -190,7 +194,7 @@ 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 VOID CpuReset(VOID);
|
||||
extern BYTE GetLineCounter(VOID);
|
||||
extern VOID Npeek(BYTE *a, DWORD d, UINT s);
|
||||
extern VOID Nread(BYTE *a, DWORD d, UINT s);
|
||||
|
@ -231,7 +235,7 @@ 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 UpdateUSRQ(VOID);
|
||||
extern VOID CommTransmit(VOID);
|
||||
extern VOID CommReceive(VOID);
|
||||
|
||||
|
|
|
@ -32,9 +32,9 @@ BEGIN
|
|||
IDD_BREAKEDIT, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 5
|
||||
RIGHTMARGIN, 105
|
||||
RIGHTMARGIN, 106
|
||||
TOPMARGIN, 5
|
||||
BOTTOMMARGIN, 97
|
||||
BOTTOMMARGIN, 95
|
||||
END
|
||||
|
||||
IDD_ABOUT, DIALOG
|
||||
|
@ -50,7 +50,7 @@ BEGIN
|
|||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 160
|
||||
TOPMARGIN, 4
|
||||
BOTTOMMARGIN, 171
|
||||
BOTTOMMARGIN, 202
|
||||
END
|
||||
|
||||
IDD_CHOOSEKML, DIALOG
|
||||
|
@ -80,9 +80,9 @@ BEGIN
|
|||
IDD_DEBUG, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 5
|
||||
RIGHTMARGIN, 273
|
||||
TOPMARGIN, 5
|
||||
BOTTOMMARGIN, 212
|
||||
RIGHTMARGIN, 274
|
||||
TOPMARGIN, 2
|
||||
BOTTOMMARGIN, 252
|
||||
END
|
||||
|
||||
IDD_NEWVALUE, DIALOG
|
||||
|
@ -100,6 +100,22 @@ BEGIN
|
|||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 43
|
||||
END
|
||||
|
||||
IDD_ENTERBREAK, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 8
|
||||
RIGHTMARGIN, 149
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 69
|
||||
END
|
||||
|
||||
IDD_INSTRUCTIONS, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 179
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 162
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
@ -109,17 +125,17 @@ END
|
|||
// Dialog
|
||||
//
|
||||
|
||||
IDD_BREAKEDIT DIALOG DISCARDABLE 0, 0, 110, 102
|
||||
IDD_BREAKEDIT DIALOG DISCARDABLE 0, 0, 111, 100
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Edit breakpoints"
|
||||
FONT 8, "Courier New"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,77,83,28,14
|
||||
DEFPUSHBUTTON "OK",IDOK,78,81,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 |
|
||||
LISTBOX IDC_BREAKEDIT_WND,5,17,101,58,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
|
||||
PUSHBUTTON "&Add",IDC_BREAKEDIT_ADD,5,81,28,14
|
||||
PUSHBUTTON "&Delete",IDC_BREAKEDIT_DELETE,41,81,28,14
|
||||
END
|
||||
|
||||
IDD_ABOUT DIALOGEX 0, 0, 261, 160
|
||||
|
@ -130,21 +146,18 @@ BEGIN
|
|||
ICON IDI_EMU48,IDC_STATIC,7,6,20,20,SS_REALSIZEIMAGE,
|
||||
WS_EX_TRANSPARENT
|
||||
LTEXT "",IDC_VERSION,29,6,151,8,NOT WS_GROUP
|
||||
LTEXT "Copyright © 1999 Sébastien Carlier && Christoph Gießelink",
|
||||
LTEXT "Copyright © 2000 Sébastien Carlier && Christoph Gießelink",
|
||||
IDC_STATIC,29,18,181,8
|
||||
DEFPUSHBUTTON "OK",IDOK,215,12,39,14
|
||||
EDITTEXT IDC_LICENSE,7,33,247,112,ES_MULTILINE | ES_AUTOHSCROLL |
|
||||
ES_READONLY
|
||||
END
|
||||
|
||||
IDD_SETTINGS DIALOGEX 0, 0, 167, 178
|
||||
IDD_SETTINGS DIALOGEX 0, 0, 167, 209
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Settings"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x1
|
||||
BEGIN
|
||||
GROUPBOX "General",IDC_STATIC,7,4,153,63
|
||||
GROUPBOX "Memory Cards",IDC_STATIC,7,70,153,50
|
||||
GROUPBOX "Serial Ports",IDC_STATIC,7,124,153,27
|
||||
CONTROL "Authentic Calculator Speed",IDC_REALSPEED,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,13,13,104,10
|
||||
CONTROL "Automatically Save Files",IDC_AUTOSAVE,"Button",
|
||||
|
@ -154,22 +167,30 @@ BEGIN
|
|||
CONTROL "Always display KML Compilation Result",
|
||||
IDC_ALWAYSDISPLOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
13,52,136,10
|
||||
GROUPBOX "General",IDC_STATIC,7,4,153,63
|
||||
CONTROL "HP Mnemonics",IDC_DISASM_HP,"Button",BS_AUTORADIOBUTTON |
|
||||
WS_GROUP | WS_TABSTOP,13,81,65,11
|
||||
CONTROL "Class Mnemonics",IDC_DISASM_CLASS,"Button",
|
||||
BS_AUTORADIOBUTTON,84,81,70,11
|
||||
GROUPBOX "Disassembler",IDC_DISASM_MNEMONICS,7,70,153,28
|
||||
CONTROL "Port 1 is Plugged",IDC_PORT1EN,"Button",BS_AUTOCHECKBOX |
|
||||
WS_TABSTOP,13,79,67,10
|
||||
WS_TABSTOP,13,110,67,10
|
||||
CONTROL "Port 1 is Writeable",IDC_PORT1WR,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,84,79,69,10
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,84,110,69,10
|
||||
CONTROL "Port 2 is Shared",IDC_PORT2ISSHARED,"Button",
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,13,92,65,10
|
||||
LTEXT "Port 2 File :",IDC_STATIC,13,105,37,8
|
||||
EDITTEXT IDC_PORT2,51,103,104,12,ES_AUTOHSCROLL
|
||||
LTEXT "Wire:",IDC_STATIC,13,136,17,8
|
||||
COMBOBOX IDC_WIRE,31,134,48,42,CBS_DROPDOWNLIST | WS_VSCROLL |
|
||||
BS_AUTOCHECKBOX | WS_TABSTOP,13,123,65,10
|
||||
LTEXT "Port 2 File :",IDC_STATIC,13,136,37,8
|
||||
EDITTEXT IDC_PORT2,51,134,104,12,ES_AUTOHSCROLL
|
||||
GROUPBOX "Memory Cards",IDC_STATIC,7,101,153,50
|
||||
LTEXT "Wire:",IDC_STATIC,13,166,17,8
|
||||
COMBOBOX IDC_WIRE,31,164,48,42,CBS_DROPDOWNLIST | WS_VSCROLL |
|
||||
WS_TABSTOP,WS_EX_LEFTSCROLLBAR
|
||||
LTEXT "IR:",IDC_STATIC,89,136,9,8
|
||||
COMBOBOX IDC_IR,107,134,48,43,CBS_DROPDOWNLIST | WS_VSCROLL |
|
||||
LTEXT "IR:",IDC_STATIC,89,166,9,8
|
||||
COMBOBOX IDC_IR,107,164,48,43,CBS_DROPDOWNLIST | WS_VSCROLL |
|
||||
WS_TABSTOP
|
||||
DEFPUSHBUTTON "&Ok",IDOK,9,157,50,14
|
||||
PUSHBUTTON "&Cancel",IDCANCEL,107,157,50,14
|
||||
GROUPBOX "Serial Ports",IDC_STATIC,7,154,153,27
|
||||
DEFPUSHBUTTON "&Ok",IDOK,9,188,50,14
|
||||
PUSHBUTTON "&Cancel",IDCANCEL,107,188,50,14
|
||||
END
|
||||
|
||||
IDD_CHOOSEKML DIALOG DISCARDABLE 0, 0, 186, 66
|
||||
|
@ -215,90 +236,111 @@ BEGIN
|
|||
PUSHBUTTON "&Next Address",IDC_DISASM_NEXT,99,144,47,14
|
||||
PUSHBUTTON "&Copy Data",IDC_DISASM_COPY,150,144,47,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,201,144,47,14
|
||||
GROUPBOX "Module",IDC_DISASM_MODULE,7,5,166,26
|
||||
GROUPBOX "Module",IDC_DISASM_MODULE,7,5,241,26
|
||||
CONTROL "Map",IDC_DISASM_MAP,"Button",BS_AUTORADIOBUTTON |
|
||||
WS_GROUP | WS_TABSTOP,14,16,28,10
|
||||
CONTROL "ROM",IDC_DISASM_ROM,"Button",BS_AUTORADIOBUTTON,45,16,
|
||||
28,10
|
||||
CONTROL "RAM",IDC_DISASM_RAM,"Button",BS_AUTORADIOBUTTON,76,16,
|
||||
28,10
|
||||
WS_GROUP | WS_TABSTOP,14,16,37,10
|
||||
CONTROL "ROM",IDC_DISASM_ROM,"Button",BS_AUTORADIOBUTTON,61,16,
|
||||
37,10
|
||||
CONTROL "RAM",IDC_DISASM_RAM,"Button",BS_AUTORADIOBUTTON,108,16,
|
||||
37,10
|
||||
CONTROL "Port 1",IDC_DISASM_PORT1,"Button",BS_AUTORADIOBUTTON,
|
||||
107,16,28,10
|
||||
155,16,37,10
|
||||
CONTROL "Port 2",IDC_DISASM_PORT2,"Button",BS_AUTORADIOBUTTON,
|
||||
138,16,28,10
|
||||
GROUPBOX "Mnemonics",IDC_DISASM_MNEMONICS,180,5,68,26
|
||||
CONTROL "HP",IDC_DISASM_HP,"Button",BS_AUTORADIOBUTTON |
|
||||
WS_GROUP | WS_TABSTOP,187,16,24,10
|
||||
CONTROL "Class",IDC_DISASM_CLASS,"Button",BS_AUTORADIOBUTTON,215,
|
||||
16,31,10
|
||||
202,16,37,10
|
||||
LISTBOX IDC_DISASM_WIN,7,37,241,100,NOT LBS_NOTIFY |
|
||||
LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL |
|
||||
WS_TABSTOP,WS_EX_NOPARENTNOTIFY
|
||||
END
|
||||
|
||||
IDD_DEBUG DIALOGEX 0, 0, 278, 217
|
||||
IDD_DEBUG DIALOGEX 0, 0, 279, 254
|
||||
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 |
|
||||
LISTBOX IDC_DEBUG_CODE,11,12,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,
|
||||
GROUPBOX "Code",IDC_STATIC_CODE,5,2,177,138
|
||||
LTEXT "A= 0000000000000000",IDC_REG_A,192,12,77,8
|
||||
LTEXT "B= 0000000000000000",IDC_REG_B,192,19,77,8
|
||||
LTEXT "C= 0000000000000000",IDC_REG_C,192,26,77,8
|
||||
LTEXT "D= 0000000000000000",IDC_REG_D,192,33,77,8
|
||||
LTEXT "R0=0000000000000000",IDC_REG_R0,192,43,77,8
|
||||
LTEXT "R1=0000000000000000",IDC_REG_R1,192,50,77,8
|
||||
LTEXT "R2=0000000000000000",IDC_REG_R2,192,57,77,8
|
||||
LTEXT "R3=0000000000000000",IDC_REG_R3,192,64,77,8
|
||||
LTEXT "R4=0000000000000000",IDC_REG_R4,192,71,77,8
|
||||
LTEXT "D0=00000",IDC_REG_D0,192,82,33,8
|
||||
LTEXT "D1=00000",IDC_REG_D1,236,82,33,8
|
||||
LTEXT "P=0",IDC_REG_P,192,93,13,8
|
||||
LTEXT "PC=00000",IDC_REG_PC,236,93,33,8
|
||||
LTEXT "OUT=000",IDC_REG_OUT,192,104,29,8
|
||||
LTEXT "IN=0000",IDC_REG_IN,240,104,29,8
|
||||
LTEXT "ST=0000",IDC_REG_ST,192,115,29,8
|
||||
LTEXT "CY=0",IDC_REG_CY,224,115,17,8
|
||||
LTEXT "Mode=H",IDC_REG_MODE,244,115,25,8
|
||||
LTEXT "MP=0",IDC_REG_MP,192,125,17,8
|
||||
LTEXT "SR=0",IDC_REG_SR,212,125,17,8
|
||||
LTEXT "SB=0",IDC_REG_SB,232,125,17,8
|
||||
LTEXT "XM=0",IDC_REG_XM,252,125,17,8
|
||||
GROUPBOX "Registers",IDC_STATIC_REGISTERS,187,2,87,138
|
||||
CONTROL "",IDC_DEBUG_MEM,"Static",SS_WHITERECT | WS_GROUP,11,151,
|
||||
165,52,WS_EX_CLIENTEDGE
|
||||
LISTBOX IDC_DEBUG_MEM_ADDR,12,156,25,48,NOT LBS_NOTIFY |
|
||||
LISTBOX IDC_DEBUG_MEM_ADDR,12,153,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 |
|
||||
LISTBOX IDC_DEBUG_MEM_COL0,40,153,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER | WS_TABSTOP
|
||||
LISTBOX IDC_DEBUG_MEM_COL1,52,156,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LISTBOX IDC_DEBUG_MEM_COL1,52,153,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
|
||||
LISTBOX IDC_DEBUG_MEM_COL2,64,156,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LISTBOX IDC_DEBUG_MEM_COL2,64,153,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
|
||||
LISTBOX IDC_DEBUG_MEM_COL3,76,156,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LISTBOX IDC_DEBUG_MEM_COL3,76,153,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
|
||||
LISTBOX IDC_DEBUG_MEM_COL4,88,156,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LISTBOX IDC_DEBUG_MEM_COL4,88,153,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
|
||||
LISTBOX IDC_DEBUG_MEM_COL5,100,156,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LISTBOX IDC_DEBUG_MEM_COL5,100,153,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
|
||||
LISTBOX IDC_DEBUG_MEM_COL6,112,156,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LISTBOX IDC_DEBUG_MEM_COL6,112,153,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
|
||||
LISTBOX IDC_DEBUG_MEM_COL7,124,156,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LISTBOX IDC_DEBUG_MEM_COL7,124,153,11,48,LBS_NOINTEGRALHEIGHT |
|
||||
LBS_WANTKEYBOARDINPUT | NOT WS_BORDER
|
||||
LISTBOX IDC_DEBUG_MEM_TEXT,139,156,35,48,NOT LBS_NOTIFY |
|
||||
LISTBOX IDC_DEBUG_MEM_TEXT,139,153,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 |
|
||||
GROUPBOX "Memory",IDC_STATIC_MEMORY,5,141,177,68
|
||||
LISTBOX IDC_DEBUG_STACK,192,151,76,52,NOT LBS_NOTIFY |
|
||||
LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT |
|
||||
WS_VSCROLL | WS_TABSTOP
|
||||
GROUPBOX "Stack",IDC_STATIC_STACK,186,144,87,68
|
||||
GROUPBOX "Stack",IDC_STATIC_STACK,187,141,87,68
|
||||
LTEXT "Size Mask",IDC_STATIC,11,228,37,8
|
||||
LTEXT "Address",IDC_STATIC,11,236,29,8
|
||||
CTEXT "I/O",IDC_STATIC,55,220,21,8
|
||||
CTEXT "NCE2",IDC_STATIC,80,220,21,8
|
||||
CTEXT "CE1",IDC_STATIC,105,220,21,8
|
||||
CTEXT "CE2",IDC_STATIC,130,220,21,8
|
||||
CTEXT "NCE3",IDC_STATIC,155,220,21,8
|
||||
CTEXT "-----",IDC_MMU_IO_S,55,228,21,8
|
||||
CTEXT "-----",IDC_MMU_NCE2_S,80,228,21,8
|
||||
CTEXT "-----",IDC_MMU_CE1_S,105,228,21,8
|
||||
CTEXT "-----",IDC_MMU_CE2_S,130,228,21,8
|
||||
CTEXT "-----",IDC_MMU_NCE3_S,155,228,21,8
|
||||
CTEXT "-----",IDC_MMU_IO_A,55,236,21,8
|
||||
CTEXT "-----",IDC_MMU_CE1_A,105,236,21,8
|
||||
CTEXT "-----",IDC_MMU_CE2_A,130,236,21,8
|
||||
CTEXT "-----",IDC_MMU_NCE2_A,80,236,21,8
|
||||
CTEXT "-----",IDC_MMU_NCE3_A,155,236,21,8
|
||||
GROUPBOX "MMU",IDC_STATIC_MMU,5,210,177,39
|
||||
LTEXT "Interrupts =",IDC_STATIC,193,220,61,8
|
||||
LTEXT "Keyboard Scan =",IDC_STATIC,193,228,61,8
|
||||
LTEXT "Bank Switcher =",IDC_MISC_BS_TXT,193,236,61,8,
|
||||
WS_DISABLED
|
||||
LTEXT "",IDC_MISC_INT,256,220,13,8
|
||||
LTEXT "",IDC_MISC_KEY,256,228,13,8
|
||||
LTEXT "00",IDC_MISC_BS,256,236,13,8,WS_DISABLED
|
||||
GROUPBOX "Miscellaneous",IDC_STATIC_MISC,187,210,87,39
|
||||
END
|
||||
|
||||
IDD_NEWVALUE DIALOG DISCARDABLE 0, 0, 175, 50
|
||||
|
@ -323,6 +365,40 @@ BEGIN
|
|||
PUSHBUTTON "Cancel",IDCANCEL,92,29,50,14
|
||||
END
|
||||
|
||||
IDD_ENTERBREAK DIALOG DISCARDABLE 0, 0, 156, 76
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Enter breakpoint"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
LTEXT "Enter breakpoint (hexdezimal):",IDC_STATIC,8,9,96,8
|
||||
EDITTEXT IDC_ENTERADR,110,7,39,12,ES_AUTOHSCROLL
|
||||
CONTROL "&Code",IDC_BPCODE,"Button",BS_AUTORADIOBUTTON |
|
||||
WS_GROUP | WS_TABSTOP,17,24,33,10
|
||||
CONTROL "Memory &Access",IDC_BPACCESS,"Button",
|
||||
BS_AUTORADIOBUTTON,79,24,63,10
|
||||
CONTROL "Memory &Read",IDC_BPREAD,"Button",BS_AUTORADIOBUTTON,17,
|
||||
38,60,10
|
||||
CONTROL "Memory &Write",IDC_BPWRITE,"Button",BS_AUTORADIOBUTTON,
|
||||
79,38,59,10
|
||||
DEFPUSHBUTTON "OK",IDOK,14,55,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,92,55,50,14
|
||||
END
|
||||
|
||||
IDD_INSTRUCTIONS DIALOGEX 0, 0, 186, 169
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Last Instructions"
|
||||
FONT 8, "Courier New", 0, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "Instructions (disassembly maybe incorrect):",
|
||||
IDC_INSTR_TEXT,7,7,173,8
|
||||
LISTBOX IDC_INSTR_CODE,7,18,172,122,NOT LBS_NOTIFY |
|
||||
LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL |
|
||||
WS_TABSTOP,WS_EX_NOPARENTNOTIFY
|
||||
PUSHBUTTON "&Copy Data",IDC_INSTR_COPY,7,148,50,14
|
||||
PUSHBUTTON "C&lear Data",IDC_INSTR_CLEAR,68,148,50,14
|
||||
DEFPUSHBUTTON "Cancel",IDCANCEL,129,148,50,14
|
||||
END
|
||||
|
||||
|
||||
#ifndef _MAC
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -331,8 +407,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,1,5,0
|
||||
PRODUCTVERSION 1,1,5,0
|
||||
FILEVERSION 1,2,0,0
|
||||
PRODUCTVERSION 1,2,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x21L
|
||||
|
@ -347,15 +423,15 @@ BEGIN
|
|||
BEGIN
|
||||
BLOCK "00000000"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Sebastien Carlier\0"
|
||||
VALUE "FileDescription", "HP38/48/49 Emulator\0"
|
||||
VALUE "FileVersion", "1, 1, 5, 0\0"
|
||||
VALUE "CompanyName", "Sebastien Carlier & Christoph Gießelink\0"
|
||||
VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0"
|
||||
VALUE "FileVersion", "1, 2, 0, 0\0"
|
||||
VALUE "InternalName", "Emu48\0"
|
||||
VALUE "LegalCopyright", "Copyright © 1999\0"
|
||||
VALUE "LegalCopyright", "Copyright © 2000\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"
|
||||
VALUE "ProductVersion", "1, 2, 0, 0\0"
|
||||
VALUE "SpecialBuild", "Service Pack 20, Christoph Gießelink\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -445,6 +521,16 @@ BEGIN
|
|||
MENUITEM "&Clear all breakpoints", ID_BREAKPOINTS_CLEARALL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&NOP3 code breakpoints", ID_BREAKPOINTS_NOP3
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&RPL breakpoints", ID_BREAKPOINTS_RPL
|
||||
END
|
||||
POPUP "I&nterrupts"
|
||||
BEGIN
|
||||
MENUITEM "&Step Over Interrupts", ID_INTR_STEPOVERINT
|
||||
END
|
||||
POPUP "&Info"
|
||||
BEGIN
|
||||
MENUITEM "&Last Instructions...", ID_INFO_LASTINSTRUCTIONS
|
||||
END
|
||||
END
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "Opcodes.h"
|
||||
#include "io.h" // 24.10.99 cg, renamed from Serial.h
|
||||
#include "io.h"
|
||||
#include "debugger.h"
|
||||
|
||||
#define SAMPLE 16384 // speed adjust sample frequency
|
||||
|
@ -17,7 +17,7 @@
|
|||
BOOL bInterrupt = FALSE;
|
||||
UINT nState = 1;
|
||||
UINT nNextState = 0;
|
||||
BOOL bRealSpeed = FALSE; // 11.12.99 cg, moved from Emu48.c
|
||||
BOOL bRealSpeed = FALSE;
|
||||
BOOL bKeySlow = FALSE; // slow down for key emulation
|
||||
CHIPSET Chipset;
|
||||
|
||||
|
@ -28,7 +28,10 @@ DWORD dwSXCycles = 82; // SX cpu cycles in interval
|
|||
DWORD dwGXCycles = 123; // GX cpu cycles in interval
|
||||
|
||||
static BOOL bCommInit = FALSE; // COM port not open
|
||||
static BOOL bCpuSlow = FALSE; // 11.12.99 cg, renamed, enable/disable real speed
|
||||
static BOOL bCpuSlow = FALSE; // enable/disable real speed
|
||||
|
||||
static DWORD dwEDbgT2 = 0; // debugger timer2 emulation
|
||||
static DWORD dwEDbgCycles = 0; // debugger cycle counter
|
||||
|
||||
static DWORD dwOldCyc; // cpu cycles at last event
|
||||
static DWORD dwSpeedRef; // timer value at last event
|
||||
|
@ -36,6 +39,151 @@ static DWORD dwTickRef; // sample timer ticks
|
|||
|
||||
#include "Ops.h"
|
||||
|
||||
// save last instruction in circular instruction buffer
|
||||
static __inline VOID SaveInstrAddr(DWORD dwAddr)
|
||||
{
|
||||
if (pdwInstrArray) // circular buffer allocated
|
||||
{
|
||||
pdwInstrArray[wInstrWp] = dwAddr;
|
||||
wInstrWp = (wInstrWp + 1) % wInstrSize;
|
||||
if (wInstrWp == wInstrRp)
|
||||
wInstrRp = (wInstrRp + 1) % wInstrSize;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static __inline VOID Debugger(VOID) // debugger part
|
||||
{
|
||||
LARGE_INTEGER lDummyInt; // sample timer ticks
|
||||
BOOL bStopEmulation;
|
||||
BOOL bRplBreak = FALSE; // flag for RPL breakpoint
|
||||
|
||||
LPBYTE I = FASTPTR(Chipset.pc); // get opcode stream
|
||||
|
||||
SaveInstrAddr(Chipset.pc); // save pc in last instruction buffer
|
||||
|
||||
// check for code breakpoints
|
||||
bStopEmulation = CheckBreakpoint(Chipset.pc, 1, BP_EXEC);
|
||||
|
||||
// check for memory breakpoints, opcode #14x or #15x
|
||||
if (I[0] == 0x1 && (I[1] == 0x4 || I[1] == 0x5))
|
||||
{
|
||||
DWORD dwData = (I[2] & 0x1) ? Chipset.d1 : Chipset.d0;
|
||||
UINT nType = (I[2] & 0x2) ? BP_READ : BP_WRITE;
|
||||
|
||||
DWORD dwRange;
|
||||
if (I[1] == 0x4) // B,A
|
||||
{
|
||||
dwRange = (I[2] & 0x8) ? 2 : 5;
|
||||
}
|
||||
else // P,WP,XS,X,S,M,W or number of nibbles
|
||||
{
|
||||
if (I[2] & 0x8) // number of nibbles
|
||||
{
|
||||
dwRange = I[3]+1;
|
||||
}
|
||||
else // P,WP,XS,X,S,M,W
|
||||
{
|
||||
dwData += F_s[I[3]];
|
||||
dwRange = F_l[I[3]];
|
||||
}
|
||||
}
|
||||
#if defined DEBUG_DEBUGGER
|
||||
{
|
||||
char buffer[256];
|
||||
wsprintf(buffer,"Memory breakpoint %.5lx, %u\n",dwData,dwRange);
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
bStopEmulation |= CheckBreakpoint(dwData, dwRange, nType);
|
||||
}
|
||||
|
||||
// NOP3, opcode #420 (GOC)
|
||||
if (bDbgNOP3 && I[0] == 0x4 && I[1] == 0x2 && I[2] == 0x0)
|
||||
bStopEmulation = TRUE;
|
||||
|
||||
// RPL breakpoints, PC=(A), opcode #808C or PC=(C), opcode #808E
|
||||
if (bDbgRPL && I[0] == 0x8 && I[1] == 0x0 && I[2] == 0x8 && (I[3] == 0xC || I[3] == 0xE ))
|
||||
{
|
||||
BYTE byRplPtr[5];
|
||||
|
||||
// A=DAT0 A, D0=D0+ 5, PC=(A)
|
||||
// C=DAT0 A, D0=D0+ 5, PC=(C)
|
||||
Npeek(byRplPtr,Chipset.d0-5,5);
|
||||
if (memcmp(byRplPtr,(I[3] == 0xC) ? Chipset.A : Chipset.C,5) == 0)
|
||||
{
|
||||
bRplBreak = TRUE;
|
||||
bStopEmulation = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// step over interrupt execution
|
||||
if (bDbgSkipInt && !bStopEmulation && !Chipset.inte)
|
||||
return;
|
||||
|
||||
// check for step into
|
||||
bStopEmulation |= (nDbgState == DBG_STEPINTO);
|
||||
|
||||
// check for step over
|
||||
bStopEmulation |= (nDbgState == DBG_STEPOVER) && dwDbgRstkp == Chipset.rstkp;
|
||||
|
||||
// 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];
|
||||
}
|
||||
}
|
||||
|
||||
if (bStopEmulation) // stop condition
|
||||
{
|
||||
StopTimers(); // hold timer values when emulator is stopped
|
||||
if (Chipset.IORam[TIMER2_CTRL]&RUN) // check if timer running
|
||||
{
|
||||
if (dwEDbgT2 == Chipset.t2)
|
||||
{
|
||||
// cpu cycles for one timer2 tick elapsed
|
||||
if ((DWORD) (Chipset.cycles & 0xFFFFFFFF) - dwEDbgCycles
|
||||
>= (SAMPLE / 8192) * (DWORD) T2CYCLES)
|
||||
{
|
||||
--Chipset.t2;
|
||||
// adjust cycles reference
|
||||
dwEDbgCycles += (SAMPLE / 8192) * T2CYCLES;
|
||||
}
|
||||
}
|
||||
else // new timer2 value
|
||||
{
|
||||
// new cycle reference
|
||||
dwEDbgCycles = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
// check rising edge of Bit 8 of timer2
|
||||
if ((dwEDbgT2 & 0x100) == 0 && (Chipset.t2 & 0x100) != 0)
|
||||
Chipset.t1 = (Chipset.t1 - 1) & 0xF;
|
||||
}
|
||||
dwEDbgT2 = Chipset.t2; // timer2 check reference value
|
||||
|
||||
// OutputDebugString("Emulator stopped...\n");
|
||||
NotifyDebugger(bRplBreak);
|
||||
WaitForSingleObject(hEventDebug,INFINITE);
|
||||
// OutputDebugString("Emulator running...\n");
|
||||
|
||||
StartTimers(); // continue timers
|
||||
|
||||
Chipset.Shutdn = FALSE;
|
||||
Chipset.bShutdnWake = FALSE;
|
||||
|
||||
// init slow down part
|
||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
QueryPerformanceCounter(&lDummyInt);
|
||||
dwSpeedRef = lDummyInt.LowPart;
|
||||
}
|
||||
}
|
||||
|
||||
static __inline VOID CheckDisp(BOOL bSync)
|
||||
{
|
||||
if (disp == 0) return; // no display update need
|
||||
|
@ -83,11 +231,12 @@ static __inline VOID CheckSerial(VOID)
|
|||
|
||||
static __inline VOID AdjustSpeed(VOID) // adjust emulation speed
|
||||
{
|
||||
if (bCpuSlow || bKeySlow) // 11.12.99 cg, changed, emulation slow down
|
||||
if (bCpuSlow || bKeySlow) // emulation slow down
|
||||
{
|
||||
DWORD dwCycles,dwTicks;
|
||||
|
||||
// cycles elapsed for next check
|
||||
// 22.11.99 cg, changed, DWORD casting of Chipset.cycles
|
||||
if ((DWORD) (Chipset.cycles & 0xFFFFFFFF)-dwOldCyc >= (DWORD) T2CYCLES)
|
||||
if ((dwCycles = (DWORD) (Chipset.cycles & 0xFFFFFFFF)-dwOldCyc) >= (DWORD) T2CYCLES)
|
||||
{
|
||||
LARGE_INTEGER lAct;
|
||||
do
|
||||
|
@ -95,10 +244,22 @@ static __inline VOID AdjustSpeed(VOID) // adjust emulation speed
|
|||
BOOL bErr = QueryPerformanceCounter(&lAct);
|
||||
_ASSERT(bErr); // no high-resolution performance counter
|
||||
}
|
||||
while(lAct.LowPart-dwSpeedRef <= dwTickRef);
|
||||
while((dwTicks = lAct.LowPart-dwSpeedRef) <= dwTickRef);
|
||||
|
||||
dwOldCyc += T2CYCLES; // adjust cycles reference
|
||||
dwSpeedRef += dwTickRef; // adjust reference time
|
||||
// workaround for QueryPerformanceCounter() in Win2k,
|
||||
// if last command sequence took over 50ms -> synchronize
|
||||
if(dwTicks > 819 * dwTickRef) // time for last commands > 50ms (819 / 16384Hz)
|
||||
{
|
||||
// new synchronizing
|
||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
QueryPerformanceCounter(&lAct); // get timer ticks
|
||||
dwSpeedRef = lAct.LowPart; // save reference time
|
||||
}
|
||||
else
|
||||
{
|
||||
dwOldCyc += T2CYCLES; // adjust cycles reference
|
||||
dwSpeedRef += dwTickRef; // adjust reference time
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -109,7 +270,7 @@ VOID AdjKeySpeed(VOID) // slow down key repeat
|
|||
WORD i;
|
||||
BOOL bKey;
|
||||
|
||||
if (bCpuSlow) return; // 11.12.99 cg, changed, no need to slow down
|
||||
if (bCpuSlow) return; // 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)
|
||||
|
@ -119,7 +280,6 @@ VOID AdjKeySpeed(VOID) // slow down key repeat
|
|||
{
|
||||
LARGE_INTEGER lTime; // sample timer ticks
|
||||
// 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
|
||||
|
@ -134,17 +294,15 @@ VOID SetSpeed(BOOL bAdjust) // set emulation speed
|
|||
{
|
||||
LARGE_INTEGER lTime; // sample timer ticks
|
||||
// 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
|
||||
}
|
||||
bCpuSlow = bAdjust; // 11.12.99 cg, changed, save emulation speed
|
||||
bCpuSlow = bAdjust; // save emulation speed
|
||||
}
|
||||
|
||||
VOID UpdateKdnBit(VOID) // update KDN bit
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
@ -214,7 +372,8 @@ UINT SwitchToState(UINT nNewState)
|
|||
{
|
||||
case 0: // -> Run
|
||||
nNextState = 0;
|
||||
bInterrupt = FALSE;
|
||||
// don't enter opcode loop on interrupt request
|
||||
bInterrupt = Chipset.Shutdn || Chipset.SoftInt;
|
||||
SetEvent(hEventShutdn);
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
UpdateWindowStatus();
|
||||
|
@ -297,13 +456,26 @@ loop:
|
|||
if (bPort2Writeable) // is card writeable
|
||||
Chipset.cards_status |= PORT2_WRITE;
|
||||
}
|
||||
// card detection off and timer running
|
||||
if ((Chipset.IORam[CARDCTL] & ECDT) == 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0)
|
||||
{
|
||||
BOOL bNINT2 = Chipset.IORam[SRQ1] == 0 && (Chipset.IORam[SRQ2] & LSRQ) == 0;
|
||||
BOOL bNINT = (Chipset.IORam[CARDCTL] & SMP) == 0;
|
||||
|
||||
// state of CDT2
|
||||
bNINT2 = bNINT2 && (Chipset.cards_status & (P2W|P2C)) != P2C;
|
||||
// state of CDT1
|
||||
bNINT = bNINT && (Chipset.cards_status & (P1W|P1C)) != P1C;
|
||||
|
||||
IOBit(SRQ2,NINT2,bNINT2);
|
||||
IOBit(SRQ2,NINT,bNINT);
|
||||
}
|
||||
RomSwitch(Chipset.Bank_FF); // select HP49G ROM bank and update memory mapping
|
||||
UpdateDisplayPointers();
|
||||
UpdateMainDisplay();
|
||||
UpdateMenuDisplay();
|
||||
UpdateAnnunciators();
|
||||
// init speed reference
|
||||
// 22.11.99 cg, changed, DWORD casting
|
||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
QueryPerformanceCounter(&lDummyInt);
|
||||
dwSpeedRef = lDummyInt.LowPart;
|
||||
|
@ -313,65 +485,9 @@ loop:
|
|||
PCHANGED;
|
||||
while (!bInterrupt)
|
||||
{
|
||||
LPBYTE I = FASTPTR(Chipset.pc);
|
||||
if (bDbgEnable) Debugger(); // debugger active
|
||||
|
||||
if (bDbgEnable) // debugger active
|
||||
{
|
||||
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;
|
||||
Chipset.bShutdnWake = FALSE;
|
||||
|
||||
// init slow down part
|
||||
// 22.11.99 cg, changed, DWORD casting
|
||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
QueryPerformanceCounter(&lDummyInt);
|
||||
dwSpeedRef = lDummyInt.LowPart;
|
||||
}
|
||||
}
|
||||
|
||||
EvalOpcode(I);
|
||||
EvalOpcode(FASTPTR(Chipset.pc)); // execute opcode
|
||||
|
||||
CheckDisp(!Chipset.Shutdn); // check for display update
|
||||
CheckSerial(); // serial support
|
||||
|
@ -382,14 +498,16 @@ loop:
|
|||
// enter SHUTDN handler only in RUN mode
|
||||
if (Chipset.Shutdn && !(nDbgState == DBG_STEPINTO || nDbgState == DBG_STEPOVER))
|
||||
{
|
||||
WaitForSingleObject(hEventShutdn,INFINITE);
|
||||
if (!Chipset.SoftInt) // ignore SHUTDN on interrupt request
|
||||
WaitForSingleObject(hEventShutdn,INFINITE);
|
||||
else
|
||||
Chipset.bShutdnWake = TRUE; // waked by interrupt
|
||||
|
||||
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;
|
||||
|
@ -405,12 +523,11 @@ loop:
|
|||
Chipset.pc = 0xf;
|
||||
}
|
||||
}
|
||||
if (nNextState != 0)
|
||||
{
|
||||
StopTimers();
|
||||
Chipset.cards_status &= (Chipset.type=='S')?0x5:0xA;
|
||||
}
|
||||
}
|
||||
_ASSERT(nNextState != 0);
|
||||
|
||||
StopTimers();
|
||||
|
||||
while (nNextState == 3) // go into sleep state
|
||||
{
|
||||
nState = 3; // in sleep state
|
||||
|
|
|
@ -13,15 +13,18 @@
|
|||
//#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 \
|
||||
) \
|
||||
#define SFLAG53_56 ( (cCurrentRomType=='6') \
|
||||
? 0xE0E4F \
|
||||
: ( (cCurrentRomType=='A') \
|
||||
? 0xF0E4F \
|
||||
: ( (cCurrentRomType!='X') \
|
||||
? ( (cCurrentRomType=='S') \
|
||||
? 0x706D2 \
|
||||
: 0x80850 \
|
||||
) \
|
||||
: 0x80F0F \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
static __inline VOID Return(CHIPSET* w)
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h" // I/O register definitions
|
||||
#include "kml.h"
|
||||
#include "i28f160.h" // flash support
|
||||
|
||||
char szEmu48Directory[260];
|
||||
char szCurrentDirectory[260];
|
||||
|
@ -24,6 +26,7 @@ static HANDLE hRomFile = NULL;
|
|||
static HANDLE hRomMap = NULL;
|
||||
DWORD dwRomSize = 0;
|
||||
char cCurrentRomType = 0;
|
||||
BOOL bRomWriteable = FALSE; // flag if ROM writeable
|
||||
|
||||
static HANDLE hPort2File = NULL;
|
||||
static HANDLE hPort2Map = NULL;
|
||||
|
@ -33,7 +36,7 @@ BOOL bPort2IsShared = FALSE;
|
|||
DWORD dwPort2Size = 0; // size of mapped port2
|
||||
DWORD dwPort2Mask = 0;
|
||||
|
||||
// 01.12.99 cg, new, HP38G signature
|
||||
// document signatures
|
||||
static BYTE pbySignatureA[16] = "Emu38 Document\xFE";
|
||||
static BYTE pbySignatureE[16] = "Emu48 Document\xFE";
|
||||
static BYTE pbySignatureW[16] = "Win48 Document\xFE";
|
||||
|
@ -96,227 +99,13 @@ WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // separated from LoadObject()
|
|||
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# ROM
|
||||
//#
|
||||
//################
|
||||
|
||||
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;
|
||||
|
||||
if (pbyRom != NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
SetCurrentDirectory(szEmu48Directory);
|
||||
hRomFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
SetCurrentDirectory(szCurrentDirectory);
|
||||
if (hRomFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hRomFile = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
dwRomSize = GetFileSize(hRomFile, &dwFileSizeHigh);
|
||||
if (dwFileSizeHigh != 0)
|
||||
{ // file is too large.
|
||||
CloseHandle(hRomFile);
|
||||
hRomFile = NULL;
|
||||
dwRomSize = 0;
|
||||
return FALSE;
|
||||
}
|
||||
hRomMap = CreateFileMapping(hRomFile, NULL, PAGE_WRITECOPY, 0, dwRomSize, NULL);
|
||||
if (hRomMap == NULL)
|
||||
{
|
||||
CloseHandle(hRomFile);
|
||||
hRomFile = NULL;
|
||||
dwRomSize = 0;
|
||||
return FALSE;
|
||||
}
|
||||
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
AbortMessage("Sharing file mapping handle.");
|
||||
}
|
||||
pbyRom = MapViewOfFile(hRomMap, FILE_MAP_COPY, 0, 0, dwRomSize);
|
||||
if (pbyRom == NULL)
|
||||
{
|
||||
CloseHandle(hRomMap);
|
||||
CloseHandle(hRomFile);
|
||||
hRomMap = NULL;
|
||||
hRomFile = NULL;
|
||||
dwRomSize = 0;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID UnmapRom(VOID)
|
||||
{
|
||||
if (pbyRom==NULL) return;
|
||||
UnmapViewOfFile(pbyRom);
|
||||
CloseHandle(hRomMap);
|
||||
CloseHandle(hRomFile);
|
||||
pbyRom = NULL;
|
||||
hRomMap = NULL;
|
||||
hRomFile = NULL;
|
||||
dwRomSize = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Port2
|
||||
//#
|
||||
//################
|
||||
|
||||
static WORD CrcPort2(VOID) // calculate fingerprint of port2
|
||||
{
|
||||
DWORD dwCount;
|
||||
DWORD dwFileSize;
|
||||
WORD wCrc = 0;
|
||||
|
||||
// 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()
|
||||
|
||||
for (dwCount = 0;dwCount < dwFileSize; ++dwCount)
|
||||
wCrc = (wCrc >> 4) ^ (((wCrc ^ ((WORD) pbyPort2[dwCount])) & 0xf) * 0x1081);
|
||||
return wCrc;
|
||||
}
|
||||
|
||||
BOOL MapPort2(LPCSTR szFilename)
|
||||
{
|
||||
DWORD dwFileSizeLo;
|
||||
DWORD dwFileSizeHi;
|
||||
|
||||
if (pbyPort2 != NULL) return FALSE;
|
||||
bPort2Writeable = TRUE;
|
||||
dwPort2Size = 0; // reset size of port2
|
||||
|
||||
SetCurrentDirectory(szEmu48Directory);
|
||||
if (bPort2IsShared)
|
||||
{
|
||||
hPort2File = CreateFile(szFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
SetCurrentDirectory(szCurrentDirectory);
|
||||
if (hPort2File == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
bPort2Writeable = FALSE;
|
||||
SetCurrentDirectory(szEmu48Directory);
|
||||
hPort2File = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
SetCurrentDirectory(szCurrentDirectory);
|
||||
if (hPort2File == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hPort2File = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hPort2File = CreateFile(szFilename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
SetCurrentDirectory(szCurrentDirectory);
|
||||
if (hPort2File == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hPort2File = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
dwFileSizeLo = GetFileSize(hPort2File, &dwFileSizeHi);
|
||||
if (dwFileSizeHi != 0)
|
||||
{ // file is too large.
|
||||
CloseHandle(hPort2File);
|
||||
hPort2File = NULL;
|
||||
dwPort2Mask = 0;
|
||||
bPort2Writeable = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
if (dwFileSizeLo & 0x3FFFF)
|
||||
{ // file size is wrong
|
||||
CloseHandle(hPort2File);
|
||||
hPort2File = NULL;
|
||||
dwPort2Mask = 0;
|
||||
bPort2Writeable = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
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
|
||||
hPort2Map = CreateFileMapping(hPort2File, NULL, PAGE_READONLY, 0, dwFileSizeLo, NULL);
|
||||
if (hPort2Map == NULL)
|
||||
{
|
||||
CloseHandle(hPort2File);
|
||||
hPort2File = NULL;
|
||||
dwPort2Mask = 0;
|
||||
bPort2Writeable = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
if (bPort2Writeable)
|
||||
pbyPort2 = MapViewOfFile(hPort2Map, FILE_MAP_WRITE, 0, 0, dwFileSizeLo);
|
||||
else
|
||||
pbyPort2 = MapViewOfFile(hPort2Map, FILE_MAP_READ, 0, 0, dwFileSizeLo);
|
||||
if (pbyPort2 == NULL)
|
||||
{
|
||||
CloseHandle(hPort2Map);
|
||||
CloseHandle(hPort2File);
|
||||
hPort2Map = NULL;
|
||||
hPort2File = NULL;
|
||||
dwPort2Mask = 0;
|
||||
bPort2Writeable = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
dwPort2Size = dwFileSizeLo / 2048; // mapping size of port2
|
||||
if (dwPort2Size > 128) dwPort2Size = 128;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID UnmapPort2(VOID)
|
||||
{
|
||||
if (pbyPort2==NULL) return;
|
||||
UnmapViewOfFile(pbyPort2);
|
||||
CloseHandle(hPort2Map);
|
||||
CloseHandle(hPort2File);
|
||||
pbyPort2 = NULL;
|
||||
hPort2Map = NULL;
|
||||
hPort2File = NULL;
|
||||
dwPort2Size = 0; // reset size of port2
|
||||
dwPort2Mask = 0;
|
||||
bPort2Writeable = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Patch
|
||||
//#
|
||||
//################
|
||||
|
||||
static BYTE Asc2Nib(char c)
|
||||
static __inline BYTE Asc2Nib(char c)
|
||||
{
|
||||
if (c<'0') return 0;
|
||||
if (c<='9') return c-'0';
|
||||
|
@ -327,6 +116,76 @@ static BYTE Asc2Nib(char c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// functions to restore ROM patches
|
||||
typedef struct tnode
|
||||
{
|
||||
DWORD dwAddress; // patch address
|
||||
BYTE byROM; // original ROM value
|
||||
BYTE byPatch; // patched ROM value
|
||||
struct tnode *next; // next node
|
||||
} TREENODE;
|
||||
|
||||
static TREENODE *nodePatch = NULL;
|
||||
|
||||
static BOOL PatchNibble(DWORD dwAddress, BYTE byPatch)
|
||||
{
|
||||
TREENODE *p;
|
||||
|
||||
_ASSERT(pbyRom); // ROM defined
|
||||
if((p = (TREENODE *) LocalAlloc(LMEM_FIXED,sizeof(TREENODE))) == NULL)
|
||||
return TRUE;
|
||||
|
||||
p->dwAddress = dwAddress; // save current values
|
||||
p->byROM = pbyRom[dwAddress];
|
||||
p->byPatch = byPatch;
|
||||
p->next = nodePatch; // save node
|
||||
nodePatch = p;
|
||||
|
||||
pbyRom[dwAddress] = byPatch; // patch ROM
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static VOID RestorePatches(VOID)
|
||||
{
|
||||
TREENODE *p;
|
||||
|
||||
_ASSERT(pbyRom); // ROM defined
|
||||
while (nodePatch != NULL)
|
||||
{
|
||||
// restore original data
|
||||
pbyRom[nodePatch->dwAddress] = nodePatch->byROM;
|
||||
|
||||
p = nodePatch->next; // save pointer to next node
|
||||
LocalFree(nodePatch); // free node
|
||||
nodePatch = p; // new node
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID UpdatePatches(BOOL bPatch)
|
||||
{
|
||||
TREENODE *p = nodePatch;
|
||||
|
||||
_ASSERT(pbyRom); // ROM defined
|
||||
while (p != NULL)
|
||||
{
|
||||
if (bPatch)
|
||||
{
|
||||
// save original data and patch address
|
||||
p->byROM = pbyRom[p->dwAddress];
|
||||
pbyRom[p->dwAddress] = p->byPatch;
|
||||
}
|
||||
else
|
||||
{
|
||||
// restore original data
|
||||
pbyRom[p->dwAddress] = p->byROM;
|
||||
}
|
||||
|
||||
p = p->next; // next node
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL PatchRom(LPCSTR szFilename)
|
||||
{
|
||||
HANDLE hFile = NULL;
|
||||
|
@ -393,7 +252,8 @@ BOOL PatchRom(LPCSTR szFilename)
|
|||
while (lpBuf[nPos])
|
||||
{
|
||||
if (isxdigit(lpBuf[nPos]) == FALSE) break;
|
||||
pbyRom[dwAddress] = Asc2Nib(lpBuf[nPos]);
|
||||
// patch ROM and save original nibble
|
||||
PatchNibble(dwAddress, Asc2Nib(lpBuf[nPos]));
|
||||
dwAddress = (dwAddress+1)&(dwRomSize-1);
|
||||
nPos++;
|
||||
}
|
||||
|
@ -404,6 +264,266 @@ BOOL PatchRom(LPCSTR szFilename)
|
|||
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# ROM
|
||||
//#
|
||||
//################
|
||||
|
||||
static WORD CrcRom(VOID) // 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;
|
||||
|
||||
// open ROM for writing
|
||||
BOOL bWrite = (cCurrentRomType == 'X') ? bRomWriteable : FALSE;
|
||||
|
||||
if (pbyRom != NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
SetCurrentDirectory(szEmu48Directory);
|
||||
if (bWrite) // ROM writeable
|
||||
{
|
||||
hRomFile = CreateFile(szFilename,
|
||||
GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (hRomFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
bWrite = FALSE; // ROM not writeable
|
||||
hRomFile = CreateFile(szFilename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
else // writing ROM disabled
|
||||
{
|
||||
hRomFile = CreateFile(szFilename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
}
|
||||
SetCurrentDirectory(szCurrentDirectory);
|
||||
if (hRomFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hRomFile = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
dwRomSize = GetFileSize(hRomFile, &dwFileSizeHigh);
|
||||
if (dwFileSizeHigh != 0)
|
||||
{ // file is too large.
|
||||
CloseHandle(hRomFile);
|
||||
hRomFile = NULL;
|
||||
dwRomSize = 0;
|
||||
return FALSE;
|
||||
}
|
||||
hRomMap = CreateFileMapping(hRomFile, NULL, bWrite ? PAGE_READWRITE : PAGE_WRITECOPY, 0, dwRomSize, NULL);
|
||||
if (hRomMap == NULL)
|
||||
{
|
||||
CloseHandle(hRomFile);
|
||||
hRomFile = NULL;
|
||||
dwRomSize = 0;
|
||||
return FALSE;
|
||||
}
|
||||
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
AbortMessage("Sharing file mapping handle.");
|
||||
}
|
||||
pbyRom = MapViewOfFile(hRomMap, bWrite ? FILE_MAP_WRITE : FILE_MAP_COPY, 0, 0, dwRomSize);
|
||||
if (pbyRom == NULL)
|
||||
{
|
||||
CloseHandle(hRomMap);
|
||||
CloseHandle(hRomFile);
|
||||
hRomMap = NULL;
|
||||
hRomFile = NULL;
|
||||
dwRomSize = 0;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID UnmapRom(VOID)
|
||||
{
|
||||
if (pbyRom==NULL) return;
|
||||
RestorePatches(); // restore ROM Patches
|
||||
UnmapViewOfFile(pbyRom);
|
||||
CloseHandle(hRomMap);
|
||||
CloseHandle(hRomFile);
|
||||
pbyRom = NULL;
|
||||
hRomMap = NULL;
|
||||
hRomFile = NULL;
|
||||
dwRomSize = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Port2
|
||||
//#
|
||||
//################
|
||||
|
||||
static WORD CrcPort2(VOID) // calculate fingerprint of port2
|
||||
{
|
||||
DWORD dwCount;
|
||||
DWORD dwFileSize;
|
||||
WORD wCrc = 0;
|
||||
|
||||
// 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()
|
||||
|
||||
for (dwCount = 0;dwCount < dwFileSize; ++dwCount)
|
||||
wCrc = (wCrc >> 4) ^ (((wCrc ^ ((WORD) pbyPort2[dwCount])) & 0xf) * 0x1081);
|
||||
return wCrc;
|
||||
}
|
||||
|
||||
BOOL MapPort2(LPCSTR szFilename)
|
||||
{
|
||||
DWORD dwFileSizeLo;
|
||||
DWORD dwFileSizeHi;
|
||||
|
||||
if (pbyPort2 != NULL) return FALSE;
|
||||
bPort2Writeable = TRUE;
|
||||
dwPort2Size = 0; // reset size of port2
|
||||
|
||||
SetCurrentDirectory(szEmu48Directory);
|
||||
if (bPort2IsShared)
|
||||
{
|
||||
hPort2File = CreateFile(szFilename,
|
||||
GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
SetCurrentDirectory(szCurrentDirectory);
|
||||
if (hPort2File == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
bPort2Writeable = FALSE;
|
||||
SetCurrentDirectory(szEmu48Directory);
|
||||
hPort2File = CreateFile(szFilename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
SetCurrentDirectory(szCurrentDirectory);
|
||||
if (hPort2File == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hPort2File = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hPort2File = CreateFile(szFilename,
|
||||
GENERIC_READ|GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
SetCurrentDirectory(szCurrentDirectory);
|
||||
if (hPort2File == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
hPort2File = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
dwFileSizeLo = GetFileSize(hPort2File, &dwFileSizeHi);
|
||||
if (dwFileSizeHi != 0)
|
||||
{ // file is too large.
|
||||
CloseHandle(hPort2File);
|
||||
hPort2File = NULL;
|
||||
dwPort2Mask = 0;
|
||||
bPort2Writeable = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
if (dwFileSizeLo & 0x3FFFF)
|
||||
{ // file size is wrong
|
||||
CloseHandle(hPort2File);
|
||||
hPort2File = NULL;
|
||||
dwPort2Mask = 0;
|
||||
bPort2Writeable = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
dwPort2Mask = (dwFileSizeLo >> 18) - 1; // mask for valid address lines of the BS-FF
|
||||
hPort2Map = CreateFileMapping(hPort2File, NULL, bPort2Writeable ? PAGE_READWRITE : PAGE_READONLY,
|
||||
0, dwFileSizeLo, NULL);
|
||||
if (hPort2Map == NULL)
|
||||
{
|
||||
CloseHandle(hPort2File);
|
||||
hPort2File = NULL;
|
||||
dwPort2Mask = 0;
|
||||
bPort2Writeable = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
pbyPort2 = MapViewOfFile(hPort2Map, bPort2Writeable ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0, dwFileSizeLo);
|
||||
if (pbyPort2 == NULL)
|
||||
{
|
||||
CloseHandle(hPort2Map);
|
||||
CloseHandle(hPort2File);
|
||||
hPort2Map = NULL;
|
||||
hPort2File = NULL;
|
||||
dwPort2Mask = 0;
|
||||
bPort2Writeable = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
dwPort2Size = dwFileSizeLo / 2048; // mapping size of port2
|
||||
if (dwPort2Size > 128) dwPort2Size = 128;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID UnmapPort2(VOID)
|
||||
{
|
||||
if (pbyPort2==NULL) return;
|
||||
UnmapViewOfFile(pbyPort2);
|
||||
CloseHandle(hPort2Map);
|
||||
CloseHandle(hPort2File);
|
||||
pbyPort2 = NULL;
|
||||
hPort2Map = NULL;
|
||||
hPort2File = NULL;
|
||||
dwPort2Size = 0; // reset size of port2
|
||||
dwPort2Mask = 0;
|
||||
bPort2Writeable = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Documents
|
||||
|
@ -446,9 +566,9 @@ BOOL NewDocument(VOID)
|
|||
if (!InitKML(szCurrentKml,FALSE)) goto restore;
|
||||
Chipset.type = cCurrentRomType;
|
||||
|
||||
if (Chipset.type == 'A') // 01.12.99 cg, new, HP38G
|
||||
if (Chipset.type == '6' || Chipset.type == 'A') // HP38G
|
||||
{
|
||||
Chipset.Port0Size = 32;
|
||||
Chipset.Port0Size = (Chipset.type == 'A') ? 32 : 64;
|
||||
Chipset.Port1Size = 0;
|
||||
Chipset.Port2Size = 0;
|
||||
Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048);
|
||||
|
@ -471,7 +591,6 @@ BOOL NewDocument(VOID)
|
|||
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]);
|
||||
}
|
||||
if (Chipset.type == 'G') // HP48GX
|
||||
|
@ -487,7 +606,6 @@ BOOL NewDocument(VOID)
|
|||
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]);
|
||||
}
|
||||
if (Chipset.type == 'X') // HP49G
|
||||
|
@ -507,6 +625,8 @@ BOOL NewDocument(VOID)
|
|||
|
||||
bPort2Writeable = TRUE;
|
||||
Chipset.cards_status = 0xF;
|
||||
|
||||
FlashInit(); // init flash structure
|
||||
}
|
||||
RomSwitch(0); // boot ROM view of HP49G and map memory
|
||||
SaveBackup();
|
||||
|
@ -515,16 +635,14 @@ restore:
|
|||
RestoreBackup();
|
||||
ResetBackup();
|
||||
|
||||
// 01.12.99 cg, changed, added HP38G
|
||||
if(Chipset.type != 'A' && Chipset.type != 'X')
|
||||
// HP48SX/GX
|
||||
if(Chipset.type != '6' && 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)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
@ -562,7 +680,6 @@ 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);
|
||||
|
@ -620,7 +737,6 @@ BOOL OpenDocument(LPCSTR szFilename)
|
|||
Chipset.Port1 = NULL;
|
||||
Chipset.Port2 = NULL;
|
||||
|
||||
// 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)
|
||||
|
@ -634,6 +750,8 @@ BOOL OpenDocument(LPCSTR szFilename)
|
|||
goto restore;
|
||||
}
|
||||
|
||||
FlashInit(); // init flash structure
|
||||
|
||||
if (Chipset.Port0Size)
|
||||
{
|
||||
Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048);
|
||||
|
@ -662,13 +780,17 @@ BOOL OpenDocument(LPCSTR szFilename)
|
|||
|
||||
if (cCurrentRomType!='X') // HP38G, HP48SX/GX
|
||||
{
|
||||
if(cCurrentRomType!='A') // 01.12.99 cg, new, HP48SX/GX
|
||||
// HP48SX/GX
|
||||
if(cCurrentRomType!='6' && cCurrentRomType!='A')
|
||||
{
|
||||
// 08.11.99 cg, changed, replaced __argc and __argv variable
|
||||
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
||||
if (Chipset.wPort2Crc != CrcPort2())// port2 changed
|
||||
// port2 changed and card detection enabled
|
||||
if ( Chipset.wPort2Crc != CrcPort2()
|
||||
&& (Chipset.IORam[CARDCTL] & ECDT) != 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0
|
||||
)
|
||||
{
|
||||
Chipset.HST |= 8; // set Module Pulled
|
||||
Chipset.HST |= MP; // set Module Pulled
|
||||
IOBit(SRQ2,NINT,FALSE); // set NINT to low
|
||||
Chipset.SoftInt = TRUE; // set interrupt
|
||||
bInterrupt = TRUE;
|
||||
}
|
||||
|
@ -695,10 +817,8 @@ BOOL OpenDocument(LPCSTR szFilename)
|
|||
|
||||
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
|
||||
if (Chipset.wRomCrc != CrcRom()) // ROM changed
|
||||
CpuReset();
|
||||
// 20.11.99 cg, end of fingerprint check
|
||||
|
||||
lstrcpy(szCurrentFilename, szFilename);
|
||||
_ASSERT(hCurrentFile == NULL);
|
||||
|
@ -715,11 +835,10 @@ restore:
|
|||
RestoreBackup();
|
||||
ResetBackup();
|
||||
|
||||
// 01.12.99 cg, bugfix, add port2 only on HP48 calculators
|
||||
if(cCurrentRomType!='A' && cCurrentRomType!='X')
|
||||
// HP48SX/GX
|
||||
if(cCurrentRomType!='6' && 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;
|
||||
|
@ -741,8 +860,9 @@ BOOL SaveDocument(VOID)
|
|||
|
||||
SetFilePointer(hCurrentFile,0,0,FILE_BEGIN);
|
||||
|
||||
// 01.12.99 cg, changed, added HP38G signature
|
||||
pbySig = (Chipset.type=='A') ? pbySignatureA : ((Chipset.type!='X') ? pbySignatureE : pbySignatureV);
|
||||
// get document signature
|
||||
pbySig = (Chipset.type=='6' || Chipset.type=='A')
|
||||
? pbySignatureA : ((Chipset.type!='X') ? pbySignatureE : pbySignatureV);
|
||||
|
||||
if (!WriteFile(hCurrentFile, pbySig, 16, &lBytesWritten, NULL))
|
||||
{
|
||||
|
@ -750,7 +870,7 @@ BOOL SaveDocument(VOID)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
Chipset.wRomCrc = CrcRom(); // 20.11.99 cg, new, save fingerprint of ROM
|
||||
Chipset.wRomCrc = CrcRom(); // save fingerprint of ROM
|
||||
Chipset.wPort2Crc = CrcPort2(); // save fingerprint of port2
|
||||
|
||||
nLength = strlen(szCurrentKml);
|
||||
|
@ -801,11 +921,10 @@ BOOL SaveBackup(VOID)
|
|||
|
||||
if (pbyRom == NULL) return FALSE;
|
||||
|
||||
// 09.12.99 cg, changed, save window position
|
||||
// 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);
|
||||
|
@ -859,17 +978,15 @@ BOOL RestoreBackup(VOID)
|
|||
Chipset.Port2 = (LPBYTE)LocalAlloc(0,Chipset.Port2Size*2048);
|
||||
CopyMemory(Chipset.Port2, BackupChipset.Port2, Chipset.Port2Size*2048);
|
||||
}
|
||||
// 09.12.99 cg, bugfix, map port2
|
||||
// map port2
|
||||
else
|
||||
{
|
||||
if(cCurrentRomType!='A') // HP48SX/GX
|
||||
if(cCurrentRomType!='6' && 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);
|
||||
|
@ -920,14 +1037,12 @@ BOOL GetOpenFilename(VOID)
|
|||
"\0\0";
|
||||
if (cCurrentRomType!='X') // HP38G / HP48SX/GX
|
||||
{
|
||||
// 01.12.99 cg, new, HP38G support
|
||||
if (cCurrentRomType=='A') // HP38G
|
||||
if (cCurrentRomType=='6' || cCurrentRomType=='A') // HP38G
|
||||
{
|
||||
ofn.lpstrDefExt = "E38";
|
||||
ofn.nFilterIndex = 1;
|
||||
}
|
||||
else
|
||||
// 01.12.99 cg, end
|
||||
{
|
||||
ofn.lpstrDefExt = "E48";
|
||||
ofn.nFilterIndex = 2;
|
||||
|
@ -965,14 +1080,12 @@ BOOL GetSaveAsFilename(VOID)
|
|||
"\0\0";
|
||||
if (cCurrentRomType!='X') // HP38G / HP48SX/GX
|
||||
{
|
||||
// 01.12.99 cg, new, HP38G support
|
||||
if (cCurrentRomType=='A') // HP38G
|
||||
if (cCurrentRomType=='6' || cCurrentRomType=='A') // HP38G
|
||||
{
|
||||
ofn.lpstrDefExt = "E38";
|
||||
ofn.nFilterIndex = 1;
|
||||
}
|
||||
else
|
||||
// 01.12.99 cg, end
|
||||
{
|
||||
ofn.lpstrDefExt = "E48";
|
||||
ofn.nFilterIndex = 2;
|
||||
|
@ -1128,25 +1241,12 @@ BOOL SaveObject(LPCSTR szFilename) // separated stack reading part
|
|||
//#
|
||||
//################
|
||||
|
||||
static UINT DibNumColors (LPBITMAPINFOHEADER lpbi)
|
||||
static __inline UINT DibNumColors (LPBITMAPINFOHEADER lpbi)
|
||||
{
|
||||
UINT bits;
|
||||
|
||||
if (lpbi->biClrUsed != 0) return (UINT)lpbi->biClrUsed;
|
||||
bits = lpbi->biBitCount;
|
||||
|
||||
switch (bits)
|
||||
{
|
||||
case 1:
|
||||
return 2;
|
||||
case 4:
|
||||
return 16;
|
||||
case 8:
|
||||
return 256;
|
||||
default:
|
||||
/* A 24 bitcount DIB has no color table */
|
||||
return 0;
|
||||
}
|
||||
/* a 24 bitcount DIB has no color table */
|
||||
return (lpbi->biBitCount <= 8) ? (1 << lpbi->biBitCount) : 0;
|
||||
}
|
||||
|
||||
static HPALETTE CreateBIPalette(LPBITMAPINFOHEADER lpbi)
|
||||
|
@ -1292,6 +1392,7 @@ HBITMAP LoadBitmapFile(LPCSTR szFilename)
|
|||
pbyFile+pBmfh->bfOffBits,
|
||||
pBmi, DIB_RGB_COLORS);
|
||||
}
|
||||
_ASSERT(hBitmap != NULL);
|
||||
|
||||
quit:
|
||||
UnmapViewOfFile(pbyFile);
|
||||
|
|
696
sources/Emu48/I28F160.C
Normal file
696
sources/Emu48/I28F160.C
Normal file
|
@ -0,0 +1,696 @@
|
|||
/*
|
||||
* i28f160.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2000 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "i28f160.h"
|
||||
|
||||
#define _64KB (64*1024) // define 64KB
|
||||
|
||||
#define ARRAYSIZEOF(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
// Flash Command Set
|
||||
#define READ_ARRAY 0xFF
|
||||
#define READ_ID_CODES 0x90
|
||||
#define READ_QUERY 0x98
|
||||
#define READ_STATUS_REG 0x70
|
||||
#define CLEAR_STATUS_REG 0x50
|
||||
#define WRITE_BUFFER 0xE8
|
||||
#define WORD_BYTE_PROG1 0x40
|
||||
#define WORD_BYTE_PROG2 0x10
|
||||
#define BLOCK_ERASE 0x20
|
||||
#define BLOCK_ERASE_SUSPEND 0xB0
|
||||
#define BLOCK_ERASE_RESUME 0xD0
|
||||
#define STS_CONFIG 0xB8
|
||||
#define SET_CLR_BLOCK_LOCK 0x60
|
||||
#define FULL_CHIP_ERASE 0x30
|
||||
|
||||
#define CONFIRM 0xD0
|
||||
|
||||
// Status Register Definition
|
||||
#define WSMS 0x80 // WRITE STATE MACHINE STATUS
|
||||
#define ESS 0x40 // ERASE SUSPEND STATUS
|
||||
#define ECLBS 0x20 // ERASE AND CLEAR LOCK-BIT STATUS
|
||||
#define BWSLBS 0x10 // PROGRAM AND SET LOCK-BIT STATUS
|
||||
#define VPPS 0x08 // Vpp STATUS
|
||||
#define BWSS 0x04 // PROGRAM SUSPEND STATUS
|
||||
#define DPS 0x02 // DEVICE PROTECT STATUS
|
||||
|
||||
// Extended Status Register Definition
|
||||
#define WBS 0x80 // WRITE BUFFER STATUS
|
||||
|
||||
// write state defines
|
||||
#define WRS_DATA 0 // idle state
|
||||
#define WRS_WR_BUFFER_N 1 // write buffer no. of data
|
||||
#define WRS_WR_BUFFER_D 2 // write buffer data
|
||||
#define WRS_WR_BUFFER_C 3 // write buffer confirm
|
||||
#define WRS_WR_BYTE 4 // write byte/word
|
||||
#define WRS_BLOCK_ERASE 5 // block erase
|
||||
#define WRS_CHIP_ERASE 6 // full chip erase
|
||||
#define WRS_STS_PIN_CONFIG 7 // STS pin Configuration
|
||||
#define WRS_LOCK_BITS 8 // Set/Clear Block Lock-Bits
|
||||
|
||||
// read state defines
|
||||
#define RDS_DATA 0
|
||||
#define RDS_ID 1
|
||||
#define RDS_QUERY 2
|
||||
#define RDS_SR 3
|
||||
#define RDS_XSR 4
|
||||
|
||||
// global data
|
||||
WSMSET WSMset;
|
||||
BOOL bWP = FALSE; // WP# = low, locked blocks cannot be erased
|
||||
|
||||
// function prototypes
|
||||
// write function WSM state
|
||||
static VOID WrStateIdle(BYTE a, DWORD d);
|
||||
static VOID WrStateE8(DWORD d);
|
||||
static VOID WrStateE8N(BYTE a, DWORD d);
|
||||
static VOID WrStateE8D(BYTE a, DWORD d);
|
||||
static VOID WrStateE8C(BYTE a, DWORD d);
|
||||
static VOID WrState40(DWORD d);
|
||||
static VOID WrState40D(BYTE a, DWORD d);
|
||||
static VOID WrState20(DWORD d);
|
||||
static VOID WrState20C(BYTE a, DWORD d);
|
||||
static VOID WrState30(DWORD d);
|
||||
static VOID WrState30C(BYTE a, DWORD d);
|
||||
static VOID WrStateB8(DWORD d);
|
||||
static VOID WrStateB8D(BYTE a, DWORD d);
|
||||
static VOID WrState60(DWORD d);
|
||||
static VOID WrState60D(BYTE a, DWORD d);
|
||||
|
||||
static CONST VOID (*CONST fnWrState[])(BYTE a, DWORD d) =
|
||||
{
|
||||
WrStateIdle,
|
||||
WrStateE8N, WrStateE8D, WrStateE8C,
|
||||
WrState40D,
|
||||
WrState20C,
|
||||
WrState30C,
|
||||
WrStateB8D,
|
||||
WrState60D
|
||||
};
|
||||
|
||||
// read function WSM state
|
||||
static BYTE RdStateData(DWORD d);
|
||||
static BYTE RdStateId(DWORD d);
|
||||
static BYTE RdStateQuery(DWORD d);
|
||||
static BYTE RdStateSR(DWORD d);
|
||||
static BYTE RdStateXSR(DWORD d);
|
||||
|
||||
static CONST BYTE (*CONST fnRdState[])(DWORD d) =
|
||||
{
|
||||
RdStateData, RdStateId, RdStateQuery, RdStateSR, RdStateXSR
|
||||
};
|
||||
|
||||
|
||||
// read query table
|
||||
// device address A16-A1, A0 unused
|
||||
static CONST BYTE byQueryTab[] =
|
||||
{
|
||||
// access with "Read Identifier Codes" command
|
||||
// Identifier codes
|
||||
0xB0, // 00, Manufacturer Code
|
||||
0xD0, // 01, Device Code (16 Mbit)
|
||||
0x00, // 02, Block Lock Configuration
|
||||
|
||||
0x00, // 03, Reserved for vendor-specific information
|
||||
0x00, // 04, "
|
||||
0x00, // 05, "
|
||||
0x00, // 06, "
|
||||
0x00, // 07, "
|
||||
0x00, // 08, "
|
||||
0x00, // 09, "
|
||||
0x00, // 0A, "
|
||||
0x00, // 0B, "
|
||||
0x00, // 0C, "
|
||||
0x00, // 0D, "
|
||||
0x00, // 0E, "
|
||||
0x00, // 0F, "
|
||||
|
||||
// access with "Read Query" command
|
||||
// CFI query identification string
|
||||
0x51, // 10, Query-Unique ASCII string "Q"
|
||||
0x52, // 11, Query-Unique ASCII string "R"
|
||||
0x59, // 12, Query-Unique ASCII string "Y"
|
||||
0x01, // 13, Primary Vendor Command Set and Control Interface ID CODE
|
||||
0x00, // 14, "
|
||||
0x31, // 15, Address for Primary Algorithm Extended Query Table
|
||||
0x00, // 16, "
|
||||
0x00, // 17, Alternate Vendor Command Set and Control Interface ID Code
|
||||
0x00, // 18, "
|
||||
0x00, // 19, Address for Secondary Algorithm Extended Query Table
|
||||
0x00, // 1A, "
|
||||
|
||||
// System interface information
|
||||
0x27, // 1B, Vcc Logic Supply Minimum Program/Erase Voltage
|
||||
0x55, // 1C, Vcc Logic Supply Maximum Program/Erase Voltage
|
||||
0x27, // 1D, Vpp [Programming] Supply Minimum Program/Erase Voltage
|
||||
0x55, // 1E, Vpp [Programming] Supply Maximum Program/Erase Voltage
|
||||
0x03, // 1F, Typical Time-Out per Single Byte/Word Program
|
||||
0x06, // 20, Typical Time-Out for Max. Buffer Write
|
||||
0x0A, // 21, Typical Time-Out per Individual Block Erase
|
||||
0x0F, // 22, Typical Time-Out for Full Chip Erase
|
||||
0x04, // 23, Maximum Time-Out for Byte/Word Program
|
||||
0x04, // 24, Maximum Time-Out for Buffer Write
|
||||
0x04, // 25, Maximum Time-Out per Individual Block Erase
|
||||
0x04, // 26, Maximum Time-Out for Full Chip Erase
|
||||
0x15, // 27, Device Size
|
||||
0x02, // 28, Flash Device Interface Description
|
||||
0x00, // 29, "
|
||||
0x05, // 2A, Maximum Number of Bytes in Write Buffer
|
||||
0x00, // 2B, "
|
||||
0x01, // 2C, Number of Erase Block Regions within Device
|
||||
0x1F, // 2D, Erase Block Region Information
|
||||
0x00, // 2E, "
|
||||
0x00, // 2F, "
|
||||
0x01, // 30, "
|
||||
|
||||
// Intel-specific extended query table
|
||||
0x50, // 31, Primary Extended Query Table, Unique ASCII string "P"
|
||||
0x52, // 32, Primary Extended Query Table, Unique ASCII string "R"
|
||||
0x49, // 33, Primary Extended Query Table, Unique ASCII string "I"
|
||||
0x31, // 34, Major Version Number, ASCII
|
||||
0x30, // 35, Minor Version Number, ASCII
|
||||
0x0F, // 36, Optional Feature & Command Support
|
||||
0x00, // 37, "
|
||||
0x00, // 38, "
|
||||
0x00, // 39, "
|
||||
0x01, // 3A, Supported Functions after Suspend
|
||||
0x03, // 3B, Block Status Register Mask
|
||||
0x00, // 3C, "
|
||||
0x50, // 3D, Vcc Logic Supply Optimum Program/Erase voltage
|
||||
0x50 // 3E, Vpp [Programming] Supply Optimum Program/Erase voltage
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// write state functions
|
||||
//
|
||||
|
||||
static VOID WrStateIdle(BYTE a, DWORD d)
|
||||
{
|
||||
WSMset.bRomArray = FALSE; // register access
|
||||
|
||||
switch(a)
|
||||
{
|
||||
case READ_ARRAY: // read array mode, normal operation
|
||||
WSMset.bRomArray = TRUE; // data array access
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
WSMset.uRdState = RDS_DATA;
|
||||
break;
|
||||
case READ_ID_CODES: // read identifier codes register
|
||||
WSMset.uRdState = RDS_ID;
|
||||
break;
|
||||
case READ_QUERY: // read query register
|
||||
WSMset.uRdState = RDS_QUERY;
|
||||
break;
|
||||
case READ_STATUS_REG: // read status register
|
||||
WSMset.uRdState = RDS_SR;
|
||||
break;
|
||||
case CLEAR_STATUS_REG: // clear status register
|
||||
WSMset.byStatusReg = 0;
|
||||
break;
|
||||
case WRITE_BUFFER: // write to buffer
|
||||
WrStateE8(d);
|
||||
break;
|
||||
case WORD_BYTE_PROG1:
|
||||
case WORD_BYTE_PROG2: // byte/word program
|
||||
WrState40(d);
|
||||
break;
|
||||
case BLOCK_ERASE: // block erase
|
||||
WrState20(d);
|
||||
break;
|
||||
case BLOCK_ERASE_SUSPEND: // block erase, word/byte program suspend
|
||||
WSMset.byStatusReg |= WSMS; // operation suspended
|
||||
WSMset.byStatusReg &= ~ESS; // block erase completed (because no timing emulation)
|
||||
WSMset.byStatusReg &= ~BWSS; // program completed (because no timing emulation)
|
||||
WSMset.uRdState = RDS_SR;
|
||||
break;
|
||||
case BLOCK_ERASE_RESUME: // block erase, word/byte program resume
|
||||
WSMset.byStatusReg &= ~WSMS; // operation in progress
|
||||
WSMset.byStatusReg &= ~ESS; // block erase in progress
|
||||
WSMset.byStatusReg &= ~BWSS; // program in progress
|
||||
WSMset.byStatusReg |= WSMS; // operation completed (because no timing emulation)
|
||||
WSMset.uRdState = RDS_SR;
|
||||
break;
|
||||
case STS_CONFIG:
|
||||
WSMset.bRomArray = bFlashRomArray; // old access mode
|
||||
WrStateB8(d);
|
||||
break;
|
||||
case SET_CLR_BLOCK_LOCK: // set/clear block lock-bits
|
||||
WrState60(d);
|
||||
break;
|
||||
case FULL_CHIP_ERASE: // full chip erase
|
||||
WrState30(d);
|
||||
break;
|
||||
default: // wrong command
|
||||
WSMset.bRomArray = bFlashRomArray; // old access mode
|
||||
break;
|
||||
}
|
||||
|
||||
if(bFlashRomArray != WSMset.bRomArray) // new access mode
|
||||
{
|
||||
bFlashRomArray = WSMset.bRomArray; // change register access
|
||||
Map(0x00,0xFF); // update memory mapping
|
||||
UpdatePatches(bFlashRomArray); // patch/unpatch ROM again
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// write to buffer initial command
|
||||
static VOID WrStateE8(DWORD d)
|
||||
{
|
||||
// @todo add 2nd write buffer implementation
|
||||
// @todo add program timing implementation
|
||||
|
||||
WSMset.byExStatusReg = 0; // no write buffer
|
||||
if (WSMset.byWrite1No == 0) // buffer1 available
|
||||
{
|
||||
WSMset.byWrite1No = 1; // buffer1 in use
|
||||
WSMset.dwWrite1Addr = d; // byte block address of buffer1
|
||||
WSMset.byExStatusReg = WBS; // write buffer available
|
||||
// fill write buffer
|
||||
FillMemory(WSMset.pbyWrite1,ARRAYSIZEOF(WSMset.pbyWrite1),0xFF);
|
||||
WSMset.uWrState = WRS_WR_BUFFER_N; // set state machine
|
||||
WSMset.uRdState = RDS_XSR;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// write to buffer number of byte
|
||||
static VOID WrStateE8N(BYTE a, DWORD d)
|
||||
{
|
||||
_ASSERT(a <= 0x1F); // check buffer size
|
||||
a &= 0x1F; // maximum write buffer size
|
||||
WSMset.byWrite1No += a; // save no. of byte to program
|
||||
WSMset.byWrite1Size = a; // save size to check write buffer boundaries
|
||||
WSMset.dwWrite1Addr = d; // byte block address of buffer1
|
||||
WSMset.byStatusReg &= ~WSMS; // state machine busy
|
||||
WSMset.uWrState = WRS_WR_BUFFER_D;
|
||||
WSMset.uRdState = RDS_SR;
|
||||
return;
|
||||
}
|
||||
|
||||
// write to buffer data
|
||||
static VOID WrStateE8D(BYTE a, DWORD d)
|
||||
{
|
||||
// first data byte
|
||||
if (WSMset.byWrite1No == WSMset.byWrite1Size + 1)
|
||||
{
|
||||
// same block
|
||||
if ((WSMset.dwWrite1Addr & ~(_64KB-1)) == (d & ~(_64KB-1)))
|
||||
{
|
||||
WSMset.dwWrite1Addr = d; // byte block address of buffer1
|
||||
WSMset.pbyWrite1[0] = a; // save byte
|
||||
}
|
||||
else
|
||||
{
|
||||
WSMset.byWrite1No = 0; // free write buffer
|
||||
// improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
WSMset.byStatusReg |= WSMS; // data written
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// write address within buffer
|
||||
if (d >= WSMset.dwWrite1Addr && d <= WSMset.dwWrite1Addr + WSMset.byWrite1Size)
|
||||
{
|
||||
// save byte in buffer
|
||||
WSMset.pbyWrite1[d-WSMset.dwWrite1Addr] = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
WSMset.byWrite1No = 0; // free write buffer
|
||||
// improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
WSMset.byStatusReg |= WSMS; // data written
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (--WSMset.byWrite1No == 0) // last byte written
|
||||
WSMset.uWrState = WRS_WR_BUFFER_C; // goto confirm state
|
||||
return;
|
||||
}
|
||||
|
||||
// write to buffer confirm
|
||||
static VOID WrStateE8C(BYTE a, DWORD d)
|
||||
{
|
||||
if (CONFIRM == a) // write buffer confirm?
|
||||
{
|
||||
BYTE byPos;
|
||||
|
||||
d = WSMset.dwWrite1Addr << 1; // nibble start address
|
||||
|
||||
for (byPos = 0; byPos <= WSMset.byWrite1Size; ++byPos)
|
||||
{
|
||||
a = WSMset.pbyWrite1[byPos]; // get char from buffer
|
||||
|
||||
_ASSERT(d+1 < dwRomSize); // address valid?
|
||||
*(pbyRom+d) &= (a & 0x0f); // write LSB
|
||||
if (*(pbyRom+d) != (a & 0x0f)) // check writing
|
||||
WSMset.byStatusReg |= BWSLBS;
|
||||
++d; // next nibble
|
||||
*(pbyRom+d) &= (a >> 4); // write MSB
|
||||
if (*(pbyRom+d) != (a >> 4)) // check writing
|
||||
WSMset.byStatusReg |= BWSLBS;
|
||||
++d; // next nibble
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WSMset.byWrite1No = 0; // free write buffer
|
||||
// improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
}
|
||||
WSMset.byStatusReg |= WSMS; // data written
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
// byte/word program initial command
|
||||
static VOID WrState40(DWORD d)
|
||||
{
|
||||
WSMset.byStatusReg &= ~WSMS; // state machine busy
|
||||
WSMset.uWrState = WRS_WR_BYTE;
|
||||
WSMset.uRdState = RDS_SR;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// byte/word program data
|
||||
static VOID WrState40D(BYTE a, DWORD d)
|
||||
{
|
||||
d <<= 1; // nibble start address
|
||||
_ASSERT(d+1 < dwRomSize); // address valid?
|
||||
// no error set in BWSLBS, because i could alway program a "0"
|
||||
*(pbyRom+d++) &= (a & 0x0f); // write LSB
|
||||
*(pbyRom+d++) &= (a >> 4); // write MSB
|
||||
WSMset.byStatusReg |= WSMS; // data written
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
// block erase initial command
|
||||
static VOID WrState20(DWORD d)
|
||||
{
|
||||
WSMset.byStatusReg &= ~WSMS; // state machine busy
|
||||
WSMset.uWrState = WRS_BLOCK_ERASE;
|
||||
WSMset.uRdState = RDS_SR;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// block erase data & confirm
|
||||
static VOID WrState20C(BYTE a, DWORD d)
|
||||
{
|
||||
if (CONFIRM == a) // block erase confirm?
|
||||
{
|
||||
_ASSERT((d>>16) < ARRAYSIZEOF(WSMset.byLockCnfg));
|
||||
if (WSMset.byLockCnfg[d>>16] & 1) // lock bit of block is set
|
||||
{
|
||||
WSMset.byStatusReg |= ECLBS; // error in block erasure
|
||||
WSMset.byStatusReg |= DPS; // lock bit detected
|
||||
}
|
||||
else
|
||||
{
|
||||
LPBYTE pbyBlock;
|
||||
UINT i;
|
||||
|
||||
d &= ~(_64KB-1); // start of 64KB block
|
||||
_ASSERT(2*(d+_64KB) <= dwRomSize); // address valid?
|
||||
pbyBlock = pbyRom + (d << 1); // nibble start address
|
||||
for (i = 0; i < 2*_64KB; ++i) // write 128K nibble
|
||||
*pbyBlock++ = 0xf; // write nibble
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
}
|
||||
WSMset.byStatusReg |= WSMS; // block erased
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
// full chip erase initial command
|
||||
static VOID WrState30(DWORD d)
|
||||
{
|
||||
WSMset.byStatusReg &= ~WSMS; // state machine busy
|
||||
WSMset.uWrState = WRS_CHIP_ERASE;
|
||||
WSMset.uRdState = RDS_SR;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// full chip erase confirm
|
||||
static VOID WrState30C(BYTE a, DWORD d)
|
||||
{
|
||||
LPBYTE pbyBlock;
|
||||
UINT i,j;
|
||||
|
||||
if (CONFIRM == a) // chip erase confirm?
|
||||
{
|
||||
pbyBlock = pbyRom;
|
||||
for (i = 0; i < 32; ++i) // check all blocks
|
||||
{
|
||||
_ASSERT(2*((i+1)*_64KB) <= dwRomSize);
|
||||
_ASSERT(i < ARRAYSIZEOF(WSMset.byLockCnfg));
|
||||
|
||||
// lock bit of block is set & WP# = low, locked blocks cannot be erased
|
||||
if ((WSMset.byLockCnfg[i] & 1) != 0 && bWP == FALSE)
|
||||
{
|
||||
pbyBlock += 2*_64KB; // next block
|
||||
WSMset.byStatusReg |= ECLBS; // error in block erasure
|
||||
// WSMset.byStatusReg |= DPS; // lock bit detected
|
||||
}
|
||||
else
|
||||
{
|
||||
WSMset.byLockCnfg[i] = 0; // clear block lock bit
|
||||
|
||||
// write 128K nibble
|
||||
for (j = 0; j < 2*_64KB; ++j)
|
||||
*pbyBlock++ = 0xf; // write nibble
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
}
|
||||
WSMset.byStatusReg |= WSMS; // chip erased
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// STS pin Configuration initial command
|
||||
static VOID WrStateB8(DWORD d)
|
||||
{
|
||||
WSMset.uWrState = WRS_STS_PIN_CONFIG;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// STS pin Configuration data
|
||||
static VOID WrStateB8D(BYTE a, DWORD d)
|
||||
{
|
||||
// no emulation of STS pin Configuration
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(a);
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// Set/Clear block Lock-Bits initial command
|
||||
static VOID WrState60(DWORD d)
|
||||
{
|
||||
WSMset.byStatusReg &= ~WSMS; // state machine busy
|
||||
WSMset.uWrState = WRS_LOCK_BITS;
|
||||
WSMset.uRdState = RDS_SR;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// Set/Clear block Lock-Bits confirm
|
||||
static VOID WrState60D(BYTE a, DWORD d)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
switch(a)
|
||||
{
|
||||
case 0x01: // set block lock bit
|
||||
_ASSERT((d>>16) < ARRAYSIZEOF(WSMset.byLockCnfg));
|
||||
if (bWP) // WP# = high, can change block lock status
|
||||
WSMset.byLockCnfg[d>>16] = 1; // set block lock bit
|
||||
else
|
||||
WSMset.byStatusReg |= DPS; // device protect detect, WP# = low
|
||||
break;
|
||||
case CONFIRM: // clear block lock bits
|
||||
if (bWP) // WP# = high, can change block lock status
|
||||
{
|
||||
for (i = 0; i < 32; ++i) // clear all lock bits
|
||||
{
|
||||
_ASSERT(i < ARRAYSIZEOF(WSMset.byLockCnfg));
|
||||
WSMset.byLockCnfg[i] = 0; // clear block lock bit
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WSMset.byStatusReg |= DPS; // device protect detect, WP# = low
|
||||
}
|
||||
break;
|
||||
default: // improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
}
|
||||
WSMset.byStatusReg |= WSMS; // block lock-bit changed
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// read state functions
|
||||
//
|
||||
|
||||
// read array
|
||||
static BYTE RdStateData(DWORD d)
|
||||
{
|
||||
d <<= 1; // nibble address
|
||||
_ASSERT(d+1 < dwRomSize); // address valid?
|
||||
return *(pbyRom+d)|(*(pbyRom+d+1)<<4); // get byte
|
||||
}
|
||||
|
||||
// read identifier codes
|
||||
static BYTE RdStateId(DWORD d)
|
||||
{
|
||||
BYTE byData;
|
||||
|
||||
d >>= 1; // A0 is not connected, ignore it
|
||||
_ASSERT((d & 0xFF) < 0x10); // id with valid address?
|
||||
if ((d & 0xFF) != 0x02) // id code request
|
||||
{
|
||||
// get data from id/query table
|
||||
byData = (d < ARRAYSIZEOF(byQueryTab)) ? byQueryTab[d] : 0;
|
||||
}
|
||||
else // block lock table
|
||||
{
|
||||
UINT uIndex = d >> 15; // index into lock table
|
||||
_ASSERT(uIndex < ARRAYSIZEOF(WSMset.byLockCnfg));
|
||||
byData = WSMset.byLockCnfg[uIndex]; // get data from block lock table
|
||||
}
|
||||
return byData;
|
||||
}
|
||||
|
||||
// read query
|
||||
static BYTE RdStateQuery(DWORD d)
|
||||
{
|
||||
d >>= 1; // A0 is not connected, ignore it
|
||||
// query with valid address?
|
||||
_ASSERT(d >= 0x10 && d < ARRAYSIZEOF(byQueryTab));
|
||||
// get data from query table
|
||||
return (d < ARRAYSIZEOF(byQueryTab)) ? byQueryTab[d] : 0;
|
||||
}
|
||||
|
||||
// read status register
|
||||
static BYTE RdStateSR(DWORD d)
|
||||
{
|
||||
return WSMset.byStatusReg;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// read extended status register
|
||||
static BYTE RdStateXSR(DWORD d)
|
||||
{
|
||||
return WSMset.byExStatusReg;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
VOID FlashInit(VOID)
|
||||
{
|
||||
ZeroMemory(&WSMset,sizeof(WSMset));
|
||||
strcpy(WSMset.byType,"WSM"); // Write State Machine header
|
||||
WSMset.uSize = sizeof(WSMset); // size of this structure
|
||||
WSMset.byVersion = WSMVER; // version of flash implementation structure
|
||||
|
||||
// factory setting of locking bits
|
||||
WSMset.byLockCnfg[0] = 0x01; // first 64KB block is locked
|
||||
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
WSMset.uRdState = RDS_DATA;
|
||||
|
||||
// data mode of ROM
|
||||
WSMset.bRomArray = bFlashRomArray = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
VOID FlashRead(BYTE *a, DWORD d, UINT s)
|
||||
{
|
||||
BYTE v;
|
||||
|
||||
while (s) // each nibble
|
||||
{
|
||||
// output muliplexer
|
||||
_ASSERT(WSMset.uRdState < ARRAYSIZEOF(fnRdState));
|
||||
v = fnRdState[WSMset.uRdState](d>>1);
|
||||
|
||||
if ((d & 1) == 0) // even address
|
||||
{
|
||||
*a++ = v & 0xf; ++d; --s;
|
||||
}
|
||||
if (s && (d & 1)) // odd address
|
||||
{
|
||||
*a++ = v >> 4; ++d; --s;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID FlashWrite(BYTE *a, DWORD d, UINT s)
|
||||
{
|
||||
BYTE v;
|
||||
DWORD p;
|
||||
|
||||
while (s) // each nibble
|
||||
{
|
||||
p = d >> 1; // byte address
|
||||
if (s > 1 && (d & 1) == 0) // more than one byte on even address
|
||||
{
|
||||
v = *a++; // LSB
|
||||
v |= *a++ << 4; // MSB
|
||||
d += 2; s -= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get byte from output muliplexer
|
||||
_ASSERT(WSMset.uRdState < ARRAYSIZEOF(fnRdState));
|
||||
v = fnRdState[WSMset.uRdState](p);
|
||||
|
||||
if (d & 1) // odd address
|
||||
v = (v & 0x0f) | (*a << 4); // replace MSB
|
||||
else // even address
|
||||
v = (v & 0xf0) | *a; // replace LSB
|
||||
++a; ++d; --s;
|
||||
}
|
||||
|
||||
_ASSERT(WSMset.uWrState < ARRAYSIZEOF(fnWrState));
|
||||
fnWrState[WSMset.uWrState](v,p); // WSM
|
||||
}
|
||||
return;
|
||||
}
|
40
sources/Emu48/I28F160.H
Normal file
40
sources/Emu48/I28F160.H
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* i28f160.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2000 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
|
||||
#define WSMVER 0 // version of flash implementation structure
|
||||
|
||||
#define WSMSET WSMset_t
|
||||
typedef struct
|
||||
{
|
||||
BYTE byType[4]; // "WSM"
|
||||
UINT uSize; // size of this structure
|
||||
BYTE byVersion; // WSM version
|
||||
|
||||
BOOL bRomArray; // copy of bFlashRomArray
|
||||
BYTE byLockCnfg[32]; // block lock table
|
||||
UINT uWrState; // state of write function WSM
|
||||
UINT uRdState; // state of read function WSM
|
||||
BYTE byStatusReg; // status register
|
||||
BYTE byExStatusReg; // extended status register
|
||||
BYTE byWrite1No; // no. of written data in write buffer1
|
||||
BYTE byWrite1Size; // no. of valid data in write buffer1
|
||||
DWORD dwWrite1Addr; // destination address of buffer1
|
||||
BYTE pbyWrite1[32]; // write buffer1
|
||||
// BYTE byWrite2No; // no. of written data in write buffer2
|
||||
// BYTE byWrite2Size; // no. of valid data in write buffer2
|
||||
// DWORD dwWrite2Addr; // destination address of buffer2
|
||||
// BYTE pbyWrite2[32]; // write buffer2
|
||||
} WSMset_t;
|
||||
|
||||
// i28f160.h
|
||||
extern WSMSET WSMset;
|
||||
extern BOOL bWP;
|
||||
extern VOID FlashInit(VOID);
|
||||
extern VOID FlashRead(BYTE *a, DWORD d, UINT s);
|
||||
extern VOID FlashWrite(BYTE *a, DWORD d, UINT s);
|
|
@ -9,7 +9,10 @@
|
|||
|
||||
// I/O addresses without mapping offset
|
||||
#define CRC 0x04 // Crc (16 bit, LSB first)
|
||||
#define ANNCTRL 0x0b // Annunciator Control (2 nibble)
|
||||
#define BAUD 0x0d // Baudrate (Bit 2-0)
|
||||
#define CARDCTL 0x0e // card control
|
||||
#define CARDSTAT 0x0f // card status
|
||||
#define IOC 0x10 // IO CONTROL
|
||||
#define RCS 0x11 // RCS
|
||||
#define TCS 0x12 // TCS
|
||||
|
@ -21,11 +24,34 @@
|
|||
#define SRQ1 0x18 // SRQ1
|
||||
#define SRQ2 0x19 // SRQ2
|
||||
#define IR_CTRL 0x1a // IR CONTROL
|
||||
#define LCR 0x1c // Led Control Register
|
||||
#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)
|
||||
|
||||
// 0x0b Annunciator Control [AON XTRA LA6 LA5] [LA4 LA3 LA2 LA1]
|
||||
#define AON 0x80 // Annunciators on
|
||||
#define LXTRA 0x40 // does nothing
|
||||
#define LA6 0x20 // LA6 - Transmitting
|
||||
#define LA5 0x10 // LA5 - Busy
|
||||
#define LA4 0x08 // LA4 - Alert
|
||||
#define LA3 0x04 // LA3 - Alpha
|
||||
#define LA2 0x02 // LA2 - ALT Shift
|
||||
#define LA1 0x01 // LA1 - Shift
|
||||
|
||||
// 0x0e Card Control [ECDT RCDT SMP SWINT]
|
||||
#define ECDT 0x08 // Enable Card Detect
|
||||
#define RCDT 0x04 // Run Card Detect
|
||||
#define SMP 0x02 // Set module pulled
|
||||
#define SWINT 0x01 // Software Interrupt
|
||||
|
||||
// 0x0f Card Status [P2W P1W P2C P1C]
|
||||
#define P2W 0x08 // High when Port2 writeable
|
||||
#define P1W 0x04 // High when Port1 writeable
|
||||
#define P2C 0x02 // High when Card in Port2 inserted
|
||||
#define P1C 0x01 // High when Card in Port1 inserted
|
||||
|
||||
// 0x10 Serial I/O Control [SON ETBE ERBF ERBZ]
|
||||
#define SON 0x08 // Serial on
|
||||
#define ETBE 0x04 // Interrupt on transmit buffer empty
|
||||
|
@ -62,6 +88,12 @@
|
|||
#define EIRI 0x02 // Enable IR interrupt
|
||||
#define IRE 0x01 // IR event
|
||||
|
||||
// 0x1c Led Control Register [LED ELBE LBZ LBF]
|
||||
#define LED 0x08 // Turn on LED
|
||||
#define ELBE 0x04 // Enable Interrupt on Led Buffer empty
|
||||
#define LBZ 0x02 // Led Port Busy
|
||||
#define LBF 0x01 // Led Buffer Full
|
||||
|
||||
// 0x2e Timer1 Control [SRQ WKE INT XTRA]
|
||||
#define SRQ 0x08 // Service request
|
||||
#define WKE 0x04 // Wake up
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h" // I/O definitions
|
||||
|
||||
static WORD Keyboard_GetIR(VOID)
|
||||
{
|
||||
|
@ -38,16 +39,19 @@ VOID ScanKeyboard(BOOL bReset)
|
|||
WORD wOldIn = Chipset.in; // save old Chipset.in state
|
||||
|
||||
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;
|
||||
// update keyboard only if timer is running
|
||||
if (Chipset.IORam[TIMER2_CTRL]&RUN) // timer running
|
||||
Chipset.in = Keyboard_GetIR(); // update Chipset.in register
|
||||
else // timer stopped, no keyboard update
|
||||
Chipset.in &= 0x1FF; // IR[0:8], old keystate without ON key
|
||||
Chipset.in |= Chipset.IR15X; // add ON key
|
||||
|
||||
// interrrupt for any new pressed keys ?
|
||||
bKbdInt = ((Chipset.in & (Chipset.in ^ wOldIn)) != 0) || bReset;
|
||||
bKbdInt = (Chipset.in && (wOldIn & 0x1FF) == 0) || Chipset.IR15X || bReset;
|
||||
|
||||
// update keyboard interrupt pending flag
|
||||
// update keyboard interrupt pending flag when 1ms keyboard scan is disabled
|
||||
Chipset.intd = Chipset.intd || (bKbdInt && !Chipset.intk);
|
||||
|
||||
// keyboard interrupt enabled
|
||||
|
@ -87,7 +91,7 @@ VOID KeyboardEvent(BOOL bPress, UINT out, UINT in)
|
|||
}
|
||||
else
|
||||
{
|
||||
_ASSERT(out<9);
|
||||
_ASSERT(out < sizeof(Chipset.Keyboard_Row) / sizeof(Chipset.Keyboard_Row[0]));
|
||||
if (bPress) // key pressed
|
||||
Chipset.Keyboard_Row[out] |= in; // set key marker in keyboard row
|
||||
else
|
||||
|
|
|
@ -1626,7 +1626,12 @@ VOID RefreshButtons()
|
|||
{
|
||||
UINT x0 = pButton[i].nOx;
|
||||
UINT y0 = pButton[i].nOy;
|
||||
BitBlt(hWindowDC, x0, y0, pButton[i].nCx, pButton[i].nCy, hMainDC, x0, y0, SRCCOPY);
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
BitBlt(hWindowDC, x0, y0, pButton[i].nCx, pButton[i].nCy, hMainDC, x0, y0, SRCCOPY);
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
}
|
||||
DrawButton(i); // redraw pressed button
|
||||
}
|
||||
|
@ -1861,7 +1866,7 @@ BOOL InitKML(LPCSTR szFilename, BOOL bNoLog)
|
|||
DWORD lBytesRead;
|
||||
LPBYTE lpBuf;
|
||||
Block* pBlock;
|
||||
BOOL bOk = FALSE; // 08.12.99 cg, bugfix, variable not initialized at error condition
|
||||
BOOL bOk = FALSE;
|
||||
BYTE bySum = 0;
|
||||
|
||||
KillKML();
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "opcodes.h" // 25.10.99 cg, new, added for HST bits
|
||||
#include "io.h" // 24.10.99 cg, renamed from Serial.h
|
||||
#include "opcodes.h"
|
||||
#include "io.h"
|
||||
#include "i28f160.h" // flash support
|
||||
|
||||
// #define DEBUG_SERIAL // switch for SERIAL debug purpose
|
||||
// #define DEBUG_IO // switch for I/O debug purpose
|
||||
// #define DEBUG_FLASH // switch for FLASH MEMORY debug purpose
|
||||
|
||||
// defines for reading an open data bus
|
||||
#define READEVEN 0x0D
|
||||
|
@ -24,9 +26,14 @@
|
|||
#define P2MAPBASE ((BYTE)(Chipset.P2Base & ~Chipset.P2Size))
|
||||
#define BSMAPBASE ((BYTE)(Chipset.BSBase & ~Chipset.BSSize))
|
||||
|
||||
// values for mapping area
|
||||
enum MMUMAP { M_IO, M_ROM, M_RAM, M_P1, M_P2, M_BS };
|
||||
|
||||
BOOL ioc_acc = FALSE; // flag ioc changed
|
||||
BOOL ir_ctrl_acc = FALSE; // flag ir_ctl changed
|
||||
|
||||
BOOL bFlashRomArray = TRUE; // flag ROM mode
|
||||
|
||||
BYTE disp = 0; // flag for update display area
|
||||
|
||||
static LPBYTE pbyRomView[2] = {NULL,NULL}; // HP49G ROM views
|
||||
|
@ -57,8 +64,22 @@ static __inline BYTE UckBit(BYTE byBaudIndex)
|
|||
QueryPerformanceCounter(&lLC); // get counter value
|
||||
|
||||
// calculate UCK frequency
|
||||
return (((BYTE)((lLC.LowPart * dwBaudrates[byBaudIndex]) / lFreq.LowPart) & 0x1) << 3)
|
||||
& Chipset.IORam[IOC];
|
||||
return (((BYTE)(((lLC.QuadPart - lAppStart.QuadPart) * dwBaudrates[byBaudIndex])
|
||||
/ lFreq.QuadPart) & 0x1) << 3) & Chipset.IORam[IOC];
|
||||
}
|
||||
|
||||
// calculate nibble based linear flash address
|
||||
static __inline DWORD FlashROMAddr(DWORD d)
|
||||
{
|
||||
DWORD dwLinAddr;
|
||||
|
||||
// 6 bit of latch (was A6-A1 of address bus)
|
||||
dwLinAddr = (Chipset.Bank_FF >> 1) & 0x3f;
|
||||
// decode A21-A18
|
||||
dwLinAddr = ((d & 0x40000) ? (dwLinAddr & 0xf) : (dwLinAddr >> 4)) << 18;
|
||||
// decode A21-A18, A17-A0
|
||||
dwLinAddr |= d & 0x3FFFF;
|
||||
return dwLinAddr;
|
||||
}
|
||||
|
||||
// LCD line counter calculation
|
||||
|
@ -67,8 +88,31 @@ static BYTE F4096Hz(VOID) // get a 6 bit 4096Hz down counter value
|
|||
LARGE_INTEGER lLC;
|
||||
|
||||
QueryPerformanceCounter(&lLC); // get counter value
|
||||
|
||||
// calculate 4096 Hz frequency down counter value
|
||||
return -(BYTE)((lLC.LowPart * 4096) / lFreq.LowPart) & 0x3F;
|
||||
return -(BYTE)(((lLC.QuadPart - lAppStart.QuadPart) << 12) / lFreq.QuadPart) & 0x3F;
|
||||
}
|
||||
|
||||
// port configuration
|
||||
static enum MMUMAP MapData(DWORD d) // check MMU area
|
||||
{
|
||||
BYTE u = (BYTE) (d>>12);
|
||||
|
||||
if (Chipset.IOCfig && ((d&0xFFFC0)==Chipset.IOBase)) return M_IO;
|
||||
if (Chipset.P0Cfig && (((u^Chipset.P0Base) & ~Chipset.P0Size) == 0)) return M_RAM;
|
||||
if (cCurrentRomType=='S')
|
||||
{
|
||||
if (Chipset.P2Cfig && (((u^Chipset.P2Base) & ~Chipset.P2Size) == 0)) return M_P2;
|
||||
if (Chipset.P1Cfig && (((u^Chipset.P1Base) & ~Chipset.P1Size) == 0)) return M_P1;
|
||||
if (Chipset.BSCfig && (((u^Chipset.BSBase) & ~Chipset.BSSize) == 0)) return M_BS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Chipset.P1Cfig && (((u^Chipset.P1Base) & ~Chipset.P1Size) == 0)) return M_P1;
|
||||
if (Chipset.BSCfig && (((u^Chipset.BSBase) & ~Chipset.BSSize) == 0)) return M_BS;
|
||||
if (Chipset.P2Cfig && (((u^Chipset.P2Base) & ~Chipset.P2Size) == 0)) return M_P2;
|
||||
}
|
||||
return M_ROM;
|
||||
}
|
||||
|
||||
// port mapping
|
||||
|
@ -152,7 +196,7 @@ static VOID MapP1(BYTE a, BYTE b)
|
|||
m = (Chipset.Port1Size*2048)-1; // real size of module, address mask for mirroring
|
||||
p = (a<<12)&m; // offset to begin of P1 in nibbles
|
||||
|
||||
if (Chipset.cards_status & PORT1_WRITE) // 19.11.99 cg, changed, port1 write enabled
|
||||
if (Chipset.cards_status & PORT1_WRITE) // port1 write enabled
|
||||
{
|
||||
for (i=a; i<=b; i++) // scan each 2KB page
|
||||
{
|
||||
|
@ -274,24 +318,35 @@ static VOID MapROM(BYTE a, BYTE b)
|
|||
|
||||
if (cCurrentRomType == 'X') // HP49G
|
||||
{
|
||||
_ASSERT(pbyRomView[0]); // check ROM bank set
|
||||
_ASSERT(pbyRomView[1]);
|
||||
|
||||
m = (128*1024*2)-1; // mapped in 128KB pages
|
||||
p = (a<<12)&m; // offset to the begin of ROM in nibbles
|
||||
for (i=a; i<=b; i++) // scan each 2KB page
|
||||
if (bFlashRomArray) // view flash ROM data
|
||||
{
|
||||
RMap[i]=pbyRomView[(i & 0x40)!=0] + p;
|
||||
WMap[i]=NULL; // no writing
|
||||
p = (p+0x1000)&m;
|
||||
_ASSERT(pbyRomView[0]); // check ROM bank set
|
||||
_ASSERT(pbyRomView[1]);
|
||||
|
||||
m = (128*1024*2)-1; // mapped in 128KB pages
|
||||
p = (a<<12)&m; // offset to the begin of ROM in nibbles
|
||||
for (i=a; i<=b; i++) // scan each 2KB page
|
||||
{
|
||||
RMap[i]=pbyRomView[(i & 0x40)!=0] + p;
|
||||
WMap[i]=NULL; // no writing
|
||||
p = (p+0x1000)&m;
|
||||
}
|
||||
}
|
||||
else // view flash ROM register
|
||||
{
|
||||
for (i=a; i<=b; i++) // scan each 2KB page
|
||||
{
|
||||
RMap[i]=NULL; // view flash register
|
||||
WMap[i]=NULL; // no writing
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// HP48SX / HP48GX
|
||||
m = (dwRomSize-1)&0xFF000; // ROM address mask for mirroring
|
||||
// when G(X) ROM and DA19=0 (ROM disabled)
|
||||
if (cCurrentRomType != 'S' && (Chipset.IORam[0x29]&0x8) == 0)
|
||||
// HP38G / HP48SX / HP48GX
|
||||
m = dwRomSize - 1; // ROM address mask for mirroring
|
||||
// when 512KB ROM and DA19=0 (ROM disabled)
|
||||
if ((m & 0x80000) != 0 && (Chipset.IORam[0x29]&0x8) == 0)
|
||||
m >>= 1; // mirror ROM at #80000 (AR18=0)
|
||||
p = (a*0x1000)&m; // data offset in nibbles
|
||||
for (i=a;i<=b;i++) // scan each 2KB page
|
||||
|
@ -318,7 +373,14 @@ VOID Map(BYTE a, BYTE b) // maps 2KB pages with priority
|
|||
}
|
||||
else // HP48GX / HP49G
|
||||
{
|
||||
if (Chipset.P2Cfig) MapP2(a,b); // NCE3, port2
|
||||
if (Chipset.P2Cfig) // NCE3, port2
|
||||
{
|
||||
// LED bit set on a HP49
|
||||
if (cCurrentRomType=='X' && (Chipset.IORam[LCR]&LED))
|
||||
MapROM(a,b); // NCE3, ROM
|
||||
else
|
||||
MapP2(a,b); // NCE3, port2
|
||||
}
|
||||
if (Chipset.BSCfig) MapBS(a,b); // CE1, bank select (lower priority than CE2)
|
||||
if (Chipset.P1Cfig) MapP1(a,b); // CE2, port1 (higher priority than CE1)
|
||||
}
|
||||
|
@ -331,12 +393,11 @@ VOID RomSwitch(DWORD adr)
|
|||
if (cCurrentRomType=='X') // only HP49G
|
||||
{
|
||||
Chipset.Bank_FF = adr; // save address line
|
||||
// 13.12.99 cg, bugfix, A6 was always zero
|
||||
adr = (adr >> 1) & 0x3f; // 6 bit of latch (was A6-A1 of address bus)
|
||||
// lower 4 bit (16 banks) for 2nd ROM view
|
||||
pbyRomView[1] = pbyRom + ((adr & 0xf) * 128 * 1024 * 2);
|
||||
pbyRomView[1] = pbyRom + (((adr & 0xf) * 128 * 1024 * 2) & (dwRomSize - 1));
|
||||
// higher 2 bit (4 banks) for 1st ROM view
|
||||
pbyRomView[0] = pbyRom + ((adr >> 4) * 128 * 1024 * 2);
|
||||
pbyRomView[0] = pbyRom + (((adr >> 4) * 128 * 1024 * 2) & (dwRomSize - 1));
|
||||
}
|
||||
Map(0x00,0xFF); // update memory mapping
|
||||
return;
|
||||
|
@ -546,18 +607,16 @@ VOID C_Eq_Id()
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
VOID CpuReset(VOID) // 19.03.99 cg, new, register setting after Cpu Reset
|
||||
VOID CpuReset(VOID) // register setting after Cpu Reset
|
||||
{
|
||||
Chipset.pc = 0;
|
||||
// 23.10.99 cg, bugfix, additional settings
|
||||
Chipset.rstkp = 0;
|
||||
FillMemory(Chipset.rstk,sizeof(Chipset.rstk),0);
|
||||
Chipset.HST = 0;
|
||||
// 23.10.99 cg, end of additional settings
|
||||
Chipset.inte = TRUE;
|
||||
Chipset.Shutdn = FALSE;
|
||||
Chipset.SoftInt = TRUE;
|
||||
Chipset.FlashRomState = 0; // WSM state of flash memory
|
||||
Reset(); // reset MMU
|
||||
bInterrupt = TRUE;
|
||||
return;
|
||||
|
@ -565,27 +624,28 @@ VOID CpuReset(VOID) // 19.03.99 cg, new, register setting after Cpu Reset
|
|||
|
||||
BYTE GetLineCounter(VOID) // get line counter value
|
||||
{
|
||||
_ASSERT(byVblRef < 0x40);
|
||||
return (0x40 + F4096Hz() - byVblRef) & 0x3F;
|
||||
}
|
||||
|
||||
VOID Npeek(BYTE *a, DWORD d, UINT s)
|
||||
{
|
||||
enum MMUMAP eMap;
|
||||
DWORD u, v;
|
||||
UINT c;
|
||||
BYTE *p;
|
||||
|
||||
do
|
||||
{
|
||||
// 12.11.99 cg, new, added reading of I/O area
|
||||
// test Chipset.IOCfig for mapping
|
||||
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
|
||||
eMap = MapData(d); // get active memory controller
|
||||
if (M_IO == eMap) // I/O access
|
||||
{
|
||||
// update crc
|
||||
// update CRC
|
||||
Nunpack(Chipset.IORam+CRC, Chipset.crc, 4);
|
||||
// update CARDSTAT
|
||||
Chipset.IORam[CARDSTAT] = (Chipset.IORam[CARDCTL] & ECDT) ? Chipset.cards_status : 0;
|
||||
// update SRQ2
|
||||
UpdateKdnBit();
|
||||
IOBit(SRQ2,NINT2,Chipset.IORam[SRQ1] == 0 && (Chipset.IORam[SRQ2] & LSRQ) == 0);
|
||||
IOBit(SRQ2,NINT,(Chipset.HST & MP) == 0);
|
||||
ReadIO(a,SRQ2,1);
|
||||
// update timer1
|
||||
Chipset.IORam[TIMER1] = Chipset.t1;
|
||||
// update timer2
|
||||
|
@ -596,12 +656,34 @@ VOID Npeek(BYTE *a, DWORD d, UINT s)
|
|||
memcpy(a, Chipset.IORam+v, c);
|
||||
}
|
||||
else
|
||||
// 12.11.99 cg, end of new part
|
||||
{
|
||||
u = d>>12;
|
||||
v = d&0xFFF;
|
||||
c = MIN(s,0x1000-v);
|
||||
if ((p=RMap[u]) != NULL) memcpy(a, p+v, c);
|
||||
// Flash memory Read access
|
||||
if (cCurrentRomType == 'X' && (Chipset.IORam[LCR] & LED) && M_P2 == eMap)
|
||||
{
|
||||
FlashRead(a, FlashROMAddr(d), s);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((p=RMap[u]) != NULL) // module mapped
|
||||
{
|
||||
memcpy(a, p+v, c);
|
||||
}
|
||||
// simulate open data bus
|
||||
else // open data bus
|
||||
{
|
||||
for (u=0; u<c; ++u) // fill all nibbles
|
||||
{
|
||||
if (v+u & 1) // odd address
|
||||
a[u] = READODD;
|
||||
else // even address
|
||||
a[u] = READEVEN;
|
||||
}
|
||||
}
|
||||
// end of bugfix
|
||||
}
|
||||
}
|
||||
if (s-=c) {a+=c; d+=c;}
|
||||
} while (s);
|
||||
|
@ -610,20 +692,21 @@ VOID Npeek(BYTE *a, DWORD d, UINT s)
|
|||
|
||||
VOID Nread(BYTE *a, DWORD d, UINT s)
|
||||
{
|
||||
enum MMUMAP eMap;
|
||||
DWORD u, v;
|
||||
UINT c;
|
||||
BYTE *p;
|
||||
|
||||
do
|
||||
{
|
||||
// test Chipset.IOCfig for mapping
|
||||
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
|
||||
eMap = MapData(d); // get active memory controller
|
||||
if (M_IO == eMap) // I/O access
|
||||
{
|
||||
v = d&0x3F;
|
||||
c = MIN(s,0x40-v);
|
||||
ReadIO(a,v,c);
|
||||
|
||||
// 11.11.99 cg, bugfix, reading MSB of timer2 update the CRC register
|
||||
// reading MSB of timer2 update the CRC register
|
||||
if (v+c == 0x40) UpCRC(a[c-1]); // timer2 MSB touched, update the CRC register
|
||||
}
|
||||
else
|
||||
|
@ -631,41 +714,55 @@ VOID Nread(BYTE *a, DWORD d, UINT s)
|
|||
u = d>>12;
|
||||
v = d&0xFFF;
|
||||
c = MIN(s,0x1000-v);
|
||||
if ( (cCurrentRomType != 'S')
|
||||
&& (Chipset.BSCfig && (((u^Chipset.BSBase) & ~Chipset.BSSize) == 0))
|
||||
&& !(Chipset.P0Cfig && (((u^Chipset.P0Base) & ~Chipset.P0Size) == 0))
|
||||
&& !(Chipset.P1Cfig && (((u^Chipset.P1Base) & ~Chipset.P1Size) == 0))
|
||||
)
|
||||
// bank switcher access
|
||||
if (cCurrentRomType != 'S' && M_BS == eMap)
|
||||
{
|
||||
if (cCurrentRomType == 'G') // HP48GX
|
||||
{
|
||||
Chipset.Bank_FF = v+c; // save FF value
|
||||
Map(Chipset.P2Base,Chipset.P2End);
|
||||
}
|
||||
else // HP49G
|
||||
if (cCurrentRomType == 'X') // HP49G
|
||||
{
|
||||
if (0!=c) RomSwitch(d+c-1);
|
||||
RomSwitch(v+c);
|
||||
}
|
||||
}
|
||||
if ((p=RMap[u]) != NULL) // module mapped
|
||||
// Flash memory Read access
|
||||
if (cCurrentRomType == 'X' && (Chipset.IORam[LCR] & LED) && M_P2 == eMap)
|
||||
{
|
||||
memcpy(a, p+v, c);
|
||||
for (u=0; u<c; u++)
|
||||
UpCRC(a[u]);
|
||||
}
|
||||
// simulate open data bus
|
||||
else // open data bus
|
||||
{
|
||||
for (u=0; u<c; ++u) // fill all nibbles
|
||||
{
|
||||
if (v+u & 1) // odd address
|
||||
a[u] = READODD;
|
||||
else // even address
|
||||
a[u] = READEVEN;
|
||||
DWORD dwLinAddr = FlashROMAddr(d);
|
||||
|
||||
UpCRC(a[u]); // update CRC
|
||||
FlashRead(a, dwLinAddr, s);
|
||||
|
||||
#if defined DEBUG_FLASH
|
||||
{
|
||||
char buffer[256];
|
||||
wsprintf(buffer,"%.5lx: Flash Read : %.5x (%.6x),%u\n",Chipset.pc,d,dwLinAddr,s);
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((p=RMap[u]) != NULL) // module mapped
|
||||
{
|
||||
memcpy(a, p+v, c);
|
||||
}
|
||||
// simulate open data bus
|
||||
else // open data bus
|
||||
{
|
||||
for (u=0; u<c; ++u) // fill all nibbles
|
||||
{
|
||||
if (v+u & 1) // odd address
|
||||
a[u] = READODD;
|
||||
else // even address
|
||||
a[u] = READEVEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u=0; u<c; u++) // update CRC
|
||||
UpCRC(a[u]);
|
||||
}
|
||||
if (s-=c) {a+=c; d+=c;}
|
||||
} while (s);
|
||||
|
@ -674,6 +771,7 @@ VOID Nread(BYTE *a, DWORD d, UINT s)
|
|||
|
||||
VOID Nwrite(BYTE *a, DWORD d, UINT s)
|
||||
{
|
||||
enum MMUMAP eMap;
|
||||
DWORD u, v;
|
||||
UINT c;
|
||||
BYTE *p;
|
||||
|
@ -708,8 +806,8 @@ VOID Nwrite(BYTE *a, DWORD d, UINT s)
|
|||
}
|
||||
do
|
||||
{
|
||||
// test Chipset.IOCfig for mapping
|
||||
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
|
||||
eMap = MapData(d); // get active memory controller
|
||||
if (M_IO == eMap) // I/O access
|
||||
{
|
||||
v = d&0x3F;
|
||||
c = MIN(s,0x40-v);
|
||||
|
@ -720,36 +818,70 @@ VOID Nwrite(BYTE *a, DWORD d, UINT s)
|
|||
u = d>>12;
|
||||
v = d&0xFFF;
|
||||
c = MIN(s,0x1000-v);
|
||||
if ( (cCurrentRomType != 'S')
|
||||
&& (Chipset.BSCfig && (((u^Chipset.BSBase) & ~Chipset.BSSize) == 0))
|
||||
&& !(Chipset.P0Cfig && (((u^Chipset.P0Base) & ~Chipset.P0Size) == 0))
|
||||
&& !(Chipset.P1Cfig && (((u^Chipset.P1Base) & ~Chipset.P1Size) == 0))
|
||||
)
|
||||
// bank switcher access
|
||||
if (cCurrentRomType != 'S' && M_BS == eMap)
|
||||
{
|
||||
if (cCurrentRomType == 'G') // HP48GX
|
||||
{
|
||||
BOOL bMap = FALSE;
|
||||
BOOL bWrite = FALSE;
|
||||
|
||||
// write enabled
|
||||
if (Chipset.cards_status & PORT2_WRITE)
|
||||
{
|
||||
Chipset.Bank_FF = v+c-1;// save FF value
|
||||
bWrite = TRUE; // bank switched
|
||||
}
|
||||
else // write disabled, so latch last read cycle
|
||||
{
|
||||
if ((v & 1) != 0) // low address odd
|
||||
{
|
||||
Chipset.Bank_FF = v;// save FF value
|
||||
bMap = TRUE; // bank switched
|
||||
bWrite = TRUE; // bank switched
|
||||
}
|
||||
|
||||
if ((v+c & 1) != 0) // high address odd
|
||||
{
|
||||
Chipset.Bank_FF = v+c-1;// save FF value
|
||||
bMap = TRUE; // bank switched
|
||||
bWrite = TRUE; // bank switched
|
||||
}
|
||||
|
||||
if (bMap) Map(Chipset.P2Base,Chipset.P2End);
|
||||
}
|
||||
else // HP49G
|
||||
|
||||
if (bWrite) // write cycle?
|
||||
{
|
||||
if (0!=c) RomSwitch(d+c-1);
|
||||
// HP48GX
|
||||
if (cCurrentRomType == 'G') Map(Chipset.P2Base,Chipset.P2End);
|
||||
// HP49G
|
||||
if (cCurrentRomType == 'X') RomSwitch(Chipset.Bank_FF);
|
||||
}
|
||||
}
|
||||
if ((p=WMap[u]) != NULL) memcpy(p+v, a, c);
|
||||
// Flash memory Write access
|
||||
if (cCurrentRomType == 'X' && (Chipset.IORam[LCR] & LED) && M_P2 == eMap)
|
||||
{
|
||||
DWORD dwLinAddr = FlashROMAddr(d);
|
||||
|
||||
FlashWrite(a, dwLinAddr, s);
|
||||
|
||||
#if defined DEBUG_FLASH
|
||||
{
|
||||
char buffer[256];
|
||||
DWORD j;
|
||||
int i;
|
||||
|
||||
i = wsprintf(buffer,"%.5lx: Flash Write: %.5x (%.6x),%u = ",Chipset.pc,d,dwLinAddr,s);
|
||||
for (j = 0;j < s;++j,++i)
|
||||
{
|
||||
buffer[i] = a[j];
|
||||
if (buffer[i] > 9) buffer[i] += 0x27;
|
||||
buffer[i] += '0';
|
||||
}
|
||||
buffer[i++] = '\n';
|
||||
buffer[i] = 0;
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((p=WMap[u]) != NULL) memcpy(p+v, a, c);
|
||||
}
|
||||
}
|
||||
a+=c;
|
||||
d+=c;
|
||||
|
@ -805,6 +937,9 @@ VOID IOBit(DWORD d, BYTE b, BOOL s) // set/clear bit in I/O section
|
|||
|
||||
VOID ReadIO(BYTE *a, DWORD d, DWORD s)
|
||||
{
|
||||
BOOL bNINT;
|
||||
BOOL bNINT2;
|
||||
|
||||
BYTE c = 0xFF; // LINECOUNT not initialized
|
||||
BOOL rbr_acc = FALSE; // flag to receive data
|
||||
|
||||
|
@ -844,11 +979,27 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s)
|
|||
#endif
|
||||
*a |= UckBit(*a); // add UCK bit to BAUD rate register
|
||||
break;
|
||||
// case 0x0E: *a = Chipset.IORam[d]; break;
|
||||
case 0x0E:
|
||||
// SMP is !NINT and SWINT is always 0
|
||||
// clear SMP and SWINT bit
|
||||
Chipset.IORam[d] &= (ECDT | RCDT);
|
||||
// SMP is !NINT
|
||||
if ((Chipset.IORam[SRQ2] & NINT) == 0)
|
||||
Chipset.IORam[d] |= SMP;
|
||||
*a = Chipset.IORam[d];
|
||||
break;
|
||||
case 0x0F:
|
||||
// On a HP49G Chipset.cards_status bust always be 0xF
|
||||
_ASSERT(cCurrentRomType!='X' || Chipset.cards_status == 0xF);
|
||||
*a = Chipset.cards_status;
|
||||
// card detection disabled
|
||||
if ((Chipset.IORam[CARDCTL] & ECDT) == 0)
|
||||
{
|
||||
*a = 0; // no cards
|
||||
}
|
||||
else
|
||||
{
|
||||
// on a HP49G Chipset.cards_status bust always be 0xF
|
||||
_ASSERT(cCurrentRomType!='X' || Chipset.cards_status == 0xF);
|
||||
*a = Chipset.cards_status;
|
||||
}
|
||||
break;
|
||||
case 0x10: // IO CONTROL
|
||||
*a = Chipset.IORam[d]; // return IO CONTROL value
|
||||
|
@ -887,7 +1038,7 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s)
|
|||
case 0x15: // RBR MSB
|
||||
Chipset.IORam[RCS]&=~RBF;
|
||||
*a = Chipset.IORam[d]; // return RBR value
|
||||
UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ
|
||||
UpdateUSRQ(); // update USRQ
|
||||
rbr_acc = TRUE; // search for new RBR value
|
||||
#if defined DEBUG_SERIAL
|
||||
{
|
||||
|
@ -903,10 +1054,18 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s)
|
|||
break;
|
||||
case 0x19: // SREQ? MSB
|
||||
UpdateKdnBit(); // update KDN bit
|
||||
// 25.10.99 cg, bugfix, update NINT2 bit
|
||||
IOBit(SRQ2,NINT2,Chipset.IORam[SRQ1] == 0 && (Chipset.IORam[SRQ2] & LSRQ) == 0);
|
||||
// 25.10.99 cg, bugfix, update NINT bit
|
||||
IOBit(SRQ2,NINT,(Chipset.HST & MP) == 0);
|
||||
bNINT2 = Chipset.IORam[SRQ1] == 0 && (Chipset.IORam[SRQ2] & LSRQ) == 0;
|
||||
bNINT = (Chipset.IORam[SRQ2] & NINT) != 0;
|
||||
// card detection off and timer running
|
||||
if ((Chipset.IORam[CARDCTL] & ECDT) == 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0)
|
||||
{
|
||||
// state of CDT2
|
||||
bNINT2 = bNINT2 && (Chipset.cards_status & (P2W|P2C)) != P2C;
|
||||
// state of CDT1
|
||||
bNINT = bNINT && (Chipset.cards_status & (P1W|P1C)) != P1C;
|
||||
}
|
||||
IOBit(SRQ2,NINT2,bNINT2);
|
||||
IOBit(SRQ2,NINT,bNINT);
|
||||
// no break!
|
||||
case 0x18: // SREQ? LSB
|
||||
*a = Chipset.IORam[d]; // return SREQ value
|
||||
|
@ -1149,29 +1308,51 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
|
|||
#endif
|
||||
break;
|
||||
|
||||
// 0010E = NS:CARDCTRL
|
||||
// 0010E = NS:CARDCTL
|
||||
// 0010E @ [ECDT RCDT SMP SWINT] (read/write)
|
||||
// 0010E @ Enable Card Det., Run Card Det., Set Module Pulled, Software interrupt
|
||||
case 0x0E:
|
||||
Chipset.IORam[d]=c;
|
||||
#if 1
|
||||
if ( (RMap[4]!=(pbyRom+0x4000)) && (12 != c) )
|
||||
{
|
||||
c |= 0x10;
|
||||
}
|
||||
#endif
|
||||
if (c&1)
|
||||
{
|
||||
Chipset.SoftInt = TRUE;
|
||||
bInterrupt = TRUE;
|
||||
}
|
||||
if (c&2)
|
||||
{
|
||||
Chipset.HST |= 8; // MP
|
||||
// Chipset.SoftInt = TRUE;
|
||||
// bInterrupt = TRUE;
|
||||
}
|
||||
break;
|
||||
if (c & SWINT) // SWINT bit set
|
||||
{
|
||||
c &= (ECDT | RCDT | SMP); // clear SWINT bit
|
||||
Chipset.SoftInt = TRUE;
|
||||
bInterrupt = TRUE;
|
||||
}
|
||||
if ((c & SMP) == 0) // SMP bit cleared
|
||||
{
|
||||
BOOL bNINT = TRUE; // ack NINT interrupt -> NINT high
|
||||
// card detect disabled and CDT1 low -> retrigger
|
||||
if ((c & ECDT) == 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0)
|
||||
bNINT = (Chipset.cards_status & (P1W|P1C)) != P1C;
|
||||
IOBit(SRQ2,NINT,bNINT);
|
||||
}
|
||||
// falling edge of Enable Card Detect bit and timer running
|
||||
if ( ((c^Chipset.IORam[d]) & ECDT) != 0 && (c & ECDT) == 0
|
||||
&& (Chipset.IORam[TIMER2_CTRL] & RUN) != 0)
|
||||
{
|
||||
BOOL bNINT = (Chipset.IORam[SRQ2] & NINT) != 0;
|
||||
// card in slot1 isn't Read Only
|
||||
if ((Chipset.cards_status & (P1W|P1C)) != P1C)
|
||||
{
|
||||
// use random state of NINT line
|
||||
bNINT = bNINT && (ReadT2() & 0x1) != 0;
|
||||
}
|
||||
IOBit(SRQ2,NINT,bNINT);
|
||||
|
||||
Chipset.HST |= MP; // set Module Pulled
|
||||
|
||||
// Port1 and Port2 plugged and writeable or NINT2/NINT interrupt
|
||||
if ( Chipset.cards_status != (P2W|P1W|P2C|P1C)
|
||||
|| (Chipset.IORam[SRQ2] & NINT2) == 0
|
||||
|| (Chipset.IORam[SRQ2] & NINT ) == 0
|
||||
)
|
||||
{
|
||||
Chipset.SoftInt = TRUE; // set interrupt
|
||||
bInterrupt = TRUE;
|
||||
}
|
||||
}
|
||||
Chipset.IORam[d]=c;
|
||||
break;
|
||||
|
||||
// 0010F = NS:CARDSTATUS
|
||||
// 0010F @ [P2W P1W P2C P1C] (read-only) Port 2 writable .. Port 1 inserted
|
||||
|
@ -1182,7 +1363,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
|
|||
// 00110 @ Serial On, Interrupt On Recv.Buf.Empty, Full, Buzy
|
||||
case 0x10:
|
||||
Chipset.IORam[d]=c;
|
||||
UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ
|
||||
UpdateUSRQ(); // update USRQ
|
||||
ioc_acc = TRUE; // new IOC value
|
||||
#if defined DEBUG_SERIAL
|
||||
{
|
||||
|
@ -1244,7 +1425,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
|
|||
case 0x17:
|
||||
Chipset.IORam[d]=c;
|
||||
Chipset.IORam[TCS]|=TBF;
|
||||
UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ
|
||||
UpdateUSRQ(); // update USRQ
|
||||
tbr_acc = TRUE; // new TBR value
|
||||
#if defined DEBUG_SERIAL
|
||||
{
|
||||
|
@ -1282,7 +1463,22 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
|
|||
|
||||
// 0011C = NS:LCR
|
||||
// 0011C @ Led Control Register [LED ELBE LBZ LBF] (Setting LED is draining)
|
||||
case 0x1C: Chipset.IORam[d]=c; break;
|
||||
case 0x1C:
|
||||
// HP49G new mapping on LED bit change
|
||||
if (cCurrentRomType=='X' && ((c^Chipset.IORam[d])&LED))
|
||||
{
|
||||
Chipset.IORam[d]=c; // save new value for mapping
|
||||
Map(Chipset.P2Base,Chipset.P2End); // new ROM mapping
|
||||
#if defined DEBUG_FLASH
|
||||
{
|
||||
char buffer[256];
|
||||
wsprintf(buffer,"%.5lx: NCE3: R%cM\n",Chipset.pc,(c&LED) ? 'O' : 'A');
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Chipset.IORam[d]=c;
|
||||
break;
|
||||
|
||||
// 0011D = NS:LBR
|
||||
// 0011D @ Led Buffer Register [0 0 0 LBO] (bits 1-3 read zero)
|
||||
|
@ -1325,8 +1521,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
|
|||
// 00128 @ Normally has 55 -> Menu starts at display row 56
|
||||
case 0x28:
|
||||
case 0x29:
|
||||
// when G(X) and writing to register 0x29
|
||||
if (cCurrentRomType != 'S' && d == 0x29)
|
||||
if (d == 0x29)
|
||||
{
|
||||
if ((c^Chipset.IORam[d])&8) // DA19 changed
|
||||
{
|
||||
|
@ -1359,6 +1554,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
|
|||
StartTimers();
|
||||
else
|
||||
StopTimers();
|
||||
disp |= DISP_ANNUN; // update annunciators
|
||||
break;
|
||||
|
||||
// 00130 = NS:MENUADDR
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "Opcodes.h"
|
||||
#include "io.h" // I/O register definitions
|
||||
|
||||
#define w Chipset
|
||||
#define GOYES3 {if(w.carry) o_goyes3(I);else{w.pc+=2;return;}}
|
||||
|
@ -19,6 +20,10 @@
|
|||
|
||||
#include "Ops.h"
|
||||
|
||||
// Fields start and length
|
||||
UINT F_s[16] = {0/*P*/,0,2,0,15,3,0,0,0,0,0,0,0,0,0,0};
|
||||
UINT F_l[16] = {1,1/*P+1*/,1,3,1,12,2,16,0,0,0,0,0,0,0,5};
|
||||
|
||||
VOID o00(LPBYTE I) // RTNSXM
|
||||
{
|
||||
w.cycles+=9;
|
||||
|
@ -84,7 +89,7 @@ VOID o07(LPBYTE I) // C=RSTK
|
|||
|
||||
VOID o08(LPBYTE I) // CLRST
|
||||
{
|
||||
w.cycles+=5; // 22.10.99 cg, bugfix, fixed no. of cycles
|
||||
w.cycles+=5;
|
||||
w.pc+=2;
|
||||
memset(w.ST, 0, 3);
|
||||
return;
|
||||
|
@ -92,7 +97,7 @@ VOID o08(LPBYTE I) // CLRST
|
|||
|
||||
VOID o09(LPBYTE I) // C=ST
|
||||
{
|
||||
w.cycles+=5; // 22.10.99 cg, bugfix, fixed no. of cycles
|
||||
w.cycles+=5;
|
||||
w.pc+=2;
|
||||
memcpy(w.C, w.ST, 3);
|
||||
return;
|
||||
|
@ -100,7 +105,7 @@ VOID o09(LPBYTE I) // C=ST
|
|||
|
||||
VOID o0A(LPBYTE I) // ST=C
|
||||
{
|
||||
w.cycles+=5; // 22.10.99 cg, bugfix, fixed no. of cycles
|
||||
w.cycles+=5;
|
||||
w.pc+=2;
|
||||
memcpy(w.ST, w.C, 3);
|
||||
return;
|
||||
|
@ -108,7 +113,7 @@ VOID o0A(LPBYTE I) // ST=C
|
|||
|
||||
VOID o0B(LPBYTE I) // CSTEX
|
||||
{
|
||||
w.cycles+=5; // 22.10.99 cg, bugfix, fixed no. of cycles
|
||||
w.cycles+=5;
|
||||
w.pc+=2;
|
||||
Nxchg(w.C, w.ST, 3);
|
||||
return;
|
||||
|
@ -276,11 +281,29 @@ VOID o0F(LPBYTE I) // RTI
|
|||
INTERRUPT; // restart interrupt handler
|
||||
}
|
||||
|
||||
// low interrupt lines
|
||||
{
|
||||
BOOL bNINT2 = Chipset.IORam[SRQ1] == 0 && (Chipset.IORam[SRQ2] & LSRQ) == 0;
|
||||
BOOL bNINT = (Chipset.IORam[SRQ2] & NINT) != 0;
|
||||
|
||||
// card detection off and timer running
|
||||
if ((Chipset.IORam[CARDCTL] & ECDT) == 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0)
|
||||
{
|
||||
// state of CDT2
|
||||
bNINT2 = bNINT2 && (Chipset.cards_status & (P2W|P2C)) != P2C;
|
||||
// state of CDT1
|
||||
bNINT = bNINT && (Chipset.cards_status & (P1W|P1C)) != P1C;
|
||||
}
|
||||
|
||||
if (!bNINT2 || !bNINT) // NINT2 or NINT interrupt line low
|
||||
INTERRUPT; // restart interrupt handler
|
||||
}
|
||||
|
||||
// restart interrupt handler when timer interrupt
|
||||
if (w.IORam[0x2E]&0x02) // INT bit of timer1 is set
|
||||
if (w.IORam[TIMER1_CTRL]&INTR) // INT bit of timer1 is set
|
||||
ReadT1(); // check for int
|
||||
|
||||
if (w.IORam[0x2F]&0x02) // INT bit of timer2 is set
|
||||
if (w.IORam[TIMER2_CTRL]&INTR) // INT bit of timer2 is set
|
||||
ReadT2(); // check for int
|
||||
return;
|
||||
}
|
||||
|
@ -834,7 +857,7 @@ VOID o3X(LPBYTE I) // LCHEX
|
|||
{
|
||||
UINT n=I[1]+1;
|
||||
UINT d=16-w.P;
|
||||
w.cycles+=3+n; // 22.10.99 cg, bugfix, fixed no. of cycles
|
||||
w.cycles+=3+n;
|
||||
w.pc+=2;
|
||||
I+=2; // UNSAFE
|
||||
if (n<=d)
|
||||
|
@ -1010,7 +1033,6 @@ VOID o8080(LPBYTE I) // INTON
|
|||
w.cycles+=5;
|
||||
w.pc+=4;
|
||||
// cpu cycles at start of 1ms key handler
|
||||
// 22.11.99 cg, changed, DWORD casting
|
||||
w.dwKdnCycles = (DWORD) (w.cycles & 0xFFFFFFFF);
|
||||
|
||||
w.intk = TRUE;
|
||||
|
@ -1029,7 +1051,6 @@ VOID o80810(LPBYTE I) // RSI
|
|||
ScanKeyboard(TRUE); // one input bit high ?
|
||||
|
||||
// enable KDN update
|
||||
// 22.11.99 cg, changed, DWORD casting
|
||||
w.dwKdnCycles = (DWORD) (w.cycles & 0xFFFFFFFF) - (DWORD) T2CYCLES * 16;
|
||||
|
||||
if (w.in && w.inte == FALSE) // key interrupt pending
|
||||
|
@ -1083,7 +1104,7 @@ VOID o8085n(LPBYTE I) // ABIT=1 n
|
|||
|
||||
VOID o8086n(LPBYTE I) // ?ABIT=0 n
|
||||
{
|
||||
w.cycles+=9; // 22.10.99 cg, bugfix, fixed no. of cycles
|
||||
w.cycles+=9;
|
||||
w.pc+=5;
|
||||
Tbit0(w.A, I[4]);
|
||||
GOYES5;
|
||||
|
@ -1091,7 +1112,7 @@ VOID o8086n(LPBYTE I) // ?ABIT=0 n
|
|||
|
||||
VOID o8087n(LPBYTE I) // ?ABIT=1 n
|
||||
{
|
||||
w.cycles+=9; // 22.10.99 cg, bugfix, fixed no. of cycles
|
||||
w.cycles+=9;
|
||||
w.pc+=5;
|
||||
Tbit1(w.A, I[4]);
|
||||
GOYES5;
|
||||
|
@ -1115,7 +1136,7 @@ VOID o8089n(LPBYTE I) // CBIT=1 n
|
|||
|
||||
VOID o808An(LPBYTE I) // ?CBIT=0 n
|
||||
{
|
||||
w.cycles+=9; // 22.10.99 cg, bugfix, fixed no. of cycles
|
||||
w.cycles+=9;
|
||||
w.pc+=5;
|
||||
Tbit0(w.C, I[4]);
|
||||
GOYES5;
|
||||
|
@ -1123,7 +1144,7 @@ VOID o808An(LPBYTE I) // ?CBIT=0 n
|
|||
|
||||
VOID o808Bn(LPBYTE I) // ?CBIT=1 n
|
||||
{
|
||||
w.cycles+=9; // 22.10.99 cg, bugfix, fixed no. of cycles
|
||||
w.cycles+=9;
|
||||
w.pc+=5;
|
||||
Tbit1(w.C, I[4]);
|
||||
GOYES5;
|
||||
|
@ -1131,8 +1152,10 @@ VOID o808Bn(LPBYTE I) // ?CBIT=1 n
|
|||
|
||||
VOID o808C(LPBYTE I) // PC=(A)
|
||||
{
|
||||
BYTE p[5];
|
||||
w.cycles+=23;
|
||||
w.pc=Read5(Npack(w.A,5));
|
||||
Nread(p,Npack(w.A,5),5); // read (A) and update CRC
|
||||
w.pc=Npack(p,5);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1147,8 +1170,10 @@ VOID o808D(LPBYTE I) // BUSCD
|
|||
|
||||
VOID o808E(LPBYTE I) // PC=(C)
|
||||
{
|
||||
BYTE p[5];
|
||||
w.cycles+=23;
|
||||
w.pc=Read5(Npack(w.C,5));
|
||||
Nread(p,Npack(w.C,5),5); // read (C) and update CRC
|
||||
w.pc=Npack(p,5);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2085,7 +2110,7 @@ VOID o8Ed4(LPBYTE I) // GOSUBL #dddd
|
|||
DWORD d=Npack(I+2,4);
|
||||
rstkpush(w.pc+6);
|
||||
if (d&0x8000) w.pc-=0xfffa-d; else w.pc+=d+6;
|
||||
w.cycles+=14; // 22.10.99 cg, bugfix, fixed no. of cycles
|
||||
w.cycles+=14;
|
||||
w.pc&=0xFFFFF;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -7,17 +7,14 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// HST bits
|
||||
#define XM 1
|
||||
#define SB 2
|
||||
#define SR 4
|
||||
#define MP 8
|
||||
|
||||
#define PCHANGED ((void)(F_s[0]=Chipset.P,F_l[1]=Chipset.P+1))
|
||||
#define INTERRUPT ((void)(Chipset.SoftInt=TRUE,bInterrupt=TRUE))
|
||||
|
||||
#define T2CYCLES ((cCurrentRomType=='S')?dwSXCycles:dwGXCycles)
|
||||
|
||||
extern UINT F_s[16];
|
||||
extern UINT F_l[16];
|
||||
|
||||
extern VOID o00(LPBYTE I); // RTNSXM
|
||||
extern VOID o01(LPBYTE I); // RTN
|
||||
extern VOID o02(LPBYTE I); // RTNSC
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
*/
|
||||
// #pragma warning(disable:4244)
|
||||
|
||||
// Fields start and length
|
||||
static UINT F_s[16] = {0/*P*/,0,2,0,15,3,0,0,0,0,0,0,0,0,0,0};
|
||||
static UINT F_l[16] = {1,1/*P+1*/,1,3,1,12,2,16,0,0,0,0,0,0,0,5};
|
||||
|
||||
#define NFunpack(a, b, f) Nunpack((a)+F_s[f], b, F_l[f])
|
||||
#define NFread(a, b, f) Nread((a)+F_s[f], b, F_l[f])
|
||||
#define NFwrite(a, b, f) Nwrite((a)+F_s[f], b, F_l[f])
|
||||
|
@ -42,10 +38,24 @@ static UINT F_l[16] = {1,1/*P+1*/,1,3,1,12,2,16,0,0,0,0,0,0,0,5};
|
|||
|
||||
static __inline LPBYTE FASTPTR(DWORD d)
|
||||
{
|
||||
static BYTE pbyNULL[16];
|
||||
LPBYTE lpbyPage;
|
||||
|
||||
d &= 0xFFFFF; // handle address overflows
|
||||
|
||||
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
|
||||
return Chipset.IORam+d-Chipset.IOBase;
|
||||
|
||||
return RMap[d>>12]+(d&0xFFF);
|
||||
if((lpbyPage = RMap[d>>12]) != NULL) // page valid
|
||||
{
|
||||
lpbyPage += d & 0xFFF; // full address
|
||||
}
|
||||
else
|
||||
{
|
||||
lpbyPage = pbyNULL; // memory allocation
|
||||
Npeek(lpbyPage, d, 13); // fill with data (LA(8) = longest opcode)
|
||||
}
|
||||
return lpbyPage;
|
||||
}
|
||||
|
||||
static __inline void rstkpush(DWORD d)
|
||||
|
@ -90,19 +100,34 @@ static __inline void Nxchg(BYTE *a, BYTE *b, UINT s)
|
|||
static __inline void Ninc(BYTE *a, UINT s, UINT d)
|
||||
{
|
||||
UINT i;
|
||||
BYTE cBase = Chipset.mode_dec ? 10 : 16;
|
||||
|
||||
for (i=d; i<s+d; ++i)
|
||||
if (Chipset.mode_dec)
|
||||
{
|
||||
a[i&0xf]++;
|
||||
if (a[i&0xf] < cBase)
|
||||
BYTE c = 1;
|
||||
for (i=d; i<s+d; ++i)
|
||||
{
|
||||
Chipset.carry = FALSE;
|
||||
return;
|
||||
if (a[i&0xf] >= 10) a[i&0xf] &= 0x7;
|
||||
|
||||
a[i&0xf] += c;
|
||||
c = (a[i&0xf] >= 10);
|
||||
if (c) a[i&0xf] -= 10;
|
||||
}
|
||||
a[i&0xf] -= cBase;
|
||||
Chipset.carry = (c==1);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=d; i<s+d; ++i)
|
||||
{
|
||||
a[i&0xf]++;
|
||||
if (a[i&0xf] < 16)
|
||||
{
|
||||
Chipset.carry = FALSE;
|
||||
return;
|
||||
}
|
||||
a[i&0xf] -= 16;
|
||||
}
|
||||
Chipset.carry = TRUE;
|
||||
}
|
||||
Chipset.carry = TRUE;
|
||||
}
|
||||
|
||||
static __inline void Ninc16(BYTE *a, UINT s, UINT d)
|
||||
|
@ -143,7 +168,7 @@ static __inline void Ndec(BYTE *a, UINT s, UINT d)
|
|||
for (i=d; i<s+d; ++i)
|
||||
{
|
||||
a[i&0xf]--;
|
||||
if (a[i&0xf] < cBase)
|
||||
if ((a[i&0xf] & 0xF0) == 0) // check overflow
|
||||
{
|
||||
Chipset.carry = FALSE;
|
||||
return;
|
||||
|
@ -178,6 +203,10 @@ static __inline void Nadd(BYTE *a, BYTE *b, UINT s)
|
|||
|
||||
for (i=0; i<s; ++i)
|
||||
{
|
||||
// illegal number in dec mode
|
||||
if (Chipset.mode_dec && a[i] >= 10)
|
||||
a[i] &= 0x7;
|
||||
|
||||
a[i] += b[i] + c;
|
||||
if (a[i] >= cBase)
|
||||
{
|
||||
|
@ -199,7 +228,7 @@ static __inline void Nsub(BYTE *a, BYTE *b, UINT s)
|
|||
for (i=0; i<s; ++i)
|
||||
{
|
||||
a[i] -= b[i] + c;
|
||||
if (a[i] >= cBase)
|
||||
if ((a[i&0xf] & 0xF0) != 0) // check overflow
|
||||
{
|
||||
a[i] += cBase;
|
||||
c = 1;
|
||||
|
@ -219,7 +248,7 @@ static __inline void Nrsub(BYTE *a, BYTE *b, UINT s)
|
|||
for (i=0; i<s; ++i)
|
||||
{
|
||||
a[i] = b[i] - (a[i] + c);
|
||||
if (a[i] >= cBase)
|
||||
if ((a[i&0xf] & 0xF0) != 0) // check overflow
|
||||
{
|
||||
a[i] += cBase;
|
||||
c = 1;
|
||||
|
@ -244,7 +273,12 @@ static __inline void Nnot(BYTE *a, UINT s)
|
|||
{
|
||||
BYTE cBase = Chipset.mode_dec ? 9 : 15;
|
||||
|
||||
while (s--) a[s] = cBase - a[s];
|
||||
while (s--)
|
||||
{
|
||||
a[s] = cBase - a[s];
|
||||
if ((a[s] & 0xF0) != 0) // check overflow (dec mode only)
|
||||
a[s] &= 0x7;
|
||||
}
|
||||
Chipset.carry = FALSE;
|
||||
}
|
||||
|
||||
|
@ -257,8 +291,14 @@ static __inline void Nneg(BYTE *a, UINT s)
|
|||
if (Chipset.carry = (i!=s)) // value was non-zero
|
||||
{
|
||||
a[i] = cBase - a[i]; // first non-zero digit
|
||||
if ((a[i] & 0xF0) != 0) // check overflow (dec mode only)
|
||||
a[i] &= 0x7;
|
||||
for (--cBase, ++i; i<s; i++)
|
||||
{
|
||||
a[i] = cBase - a[i];
|
||||
if ((a[i] & 0xF0) != 0) // check overflow (dec mode only)
|
||||
a[i] &= 0x7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,18 +7,17 @@
|
|||
#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 IDD_ABOUT 105
|
||||
#define IDD_SETTINGS 106
|
||||
#define IDD_CHOOSEKML 107
|
||||
#define IDD_KMLLOG 108
|
||||
#define IDD_DISASM 109
|
||||
#define IDD_DEBUG 110
|
||||
#define IDD_NEWVALUE 111
|
||||
#define IDD_ENTERADR 112
|
||||
#define IDD_BREAKEDIT 113
|
||||
#define IDD_ENTERBREAK 114
|
||||
#define IDD_INSTRUCTIONS 115
|
||||
#define IDC_PORT1WR 1000
|
||||
#define IDC_AUTOSAVE 1001
|
||||
#define IDC_AUTOSAVEONEXIT 1002
|
||||
|
@ -31,75 +30,95 @@
|
|||
#define IDC_PORT2ISSHARED 1009
|
||||
#define IDC_PORT2 1010
|
||||
#define IDC_ALWAYSDISPLOG 1011
|
||||
#define IDC_NAME 1012
|
||||
#define IDC_REGTEXT 1013
|
||||
#define IDC_CODE 1014
|
||||
#define IDC_REGISTER 1015
|
||||
#define IDC_UPDATE 1016
|
||||
#define IDC_LICENSE 1017
|
||||
#define IDC_REALSPEED 1018
|
||||
#define IDC_PORT1EN 1019
|
||||
#define IDC_WIRE 1020
|
||||
#define IDC_IR 1021
|
||||
#define IDC_DISASM_WIN 1022
|
||||
#define IDC_DISASM_MAP 1023
|
||||
#define IDC_DISASM_ROM 1024
|
||||
#define IDC_DISASM_RAM 1025
|
||||
#define IDC_DISASM_PORT1 1026
|
||||
#define IDC_DISASM_PORT2 1027
|
||||
#define IDC_DISASM_MODULE 1028
|
||||
#define IDC_DISASM_HP 1029
|
||||
#define IDC_DISASM_CLASS 1030
|
||||
#define IDC_DISASM_MNEMONICS 1031
|
||||
#define IDC_ADDRESS 1032
|
||||
#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 IDC_UPDATE 1012
|
||||
#define IDC_LICENSE 1013
|
||||
#define IDC_REALSPEED 1014
|
||||
#define IDC_PORT1EN 1015
|
||||
#define IDC_WIRE 1016
|
||||
#define IDC_IR 1017
|
||||
#define IDC_DISASM_WIN 1018
|
||||
#define IDC_DISASM_MAP 1019
|
||||
#define IDC_DISASM_ROM 1020
|
||||
#define IDC_DISASM_RAM 1021
|
||||
#define IDC_DISASM_PORT1 1022
|
||||
#define IDC_DISASM_PORT2 1023
|
||||
#define IDC_DISASM_MODULE 1024
|
||||
#define IDC_DISASM_HP 1025
|
||||
#define IDC_DISASM_CLASS 1026
|
||||
#define IDC_DISASM_MNEMONICS 1027
|
||||
#define IDC_ADDRESS 1028
|
||||
#define IDC_DISASM_ADR 1029
|
||||
#define IDC_DISASM_NEXT 1030
|
||||
#define IDC_DISASM_COPY 1031
|
||||
#define IDC_DEBUG_CODE 1032
|
||||
#define IDC_STATIC_CODE 1033
|
||||
#define IDC_STATIC_REGISTERS 1034
|
||||
#define IDC_STATIC_MEMORY 1035
|
||||
#define IDC_STATIC_STACK 1036
|
||||
#define IDC_REG_A 1037
|
||||
#define IDC_REG_B 1038
|
||||
#define IDC_REG_C 1039
|
||||
#define IDC_REG_D 1040
|
||||
#define IDC_REG_R0 1041
|
||||
#define IDC_REG_R1 1042
|
||||
#define IDC_REG_R2 1043
|
||||
#define IDC_REG_R3 1044
|
||||
#define IDC_REG_R4 1045
|
||||
#define IDC_REG_D0 1046
|
||||
#define IDC_REG_D1 1047
|
||||
#define IDC_REG_P 1048
|
||||
#define IDC_REG_PC 1049
|
||||
#define IDC_REG_OUT 1050
|
||||
#define IDC_REG_IN 1051
|
||||
#define IDC_REG_ST 1052
|
||||
#define IDC_REG_CY 1053
|
||||
#define IDC_REG_MODE 1054
|
||||
#define IDC_REG_MP 1055
|
||||
#define IDC_REG_SR 1056
|
||||
#define IDC_REG_SB 1057
|
||||
#define IDC_REG_XM 1058
|
||||
#define IDC_MISC_INT 1059
|
||||
#define IDC_MISC_KEY 1060
|
||||
#define IDC_MISC_BS 1061
|
||||
#define IDC_NEWVALUE 1062
|
||||
#define IDC_ENTERADR 1063
|
||||
#define IDC_DEBUG_MEM 1064
|
||||
#define IDC_DEBUG_MEM_ADDR 1065
|
||||
#define IDC_DEBUG_MEM_COL0 1066
|
||||
#define IDC_DEBUG_MEM_COL1 1067
|
||||
#define IDC_DEBUG_MEM_COL2 1068
|
||||
#define IDC_DEBUG_MEM_COL3 1069
|
||||
#define IDC_DEBUG_MEM_COL4 1070
|
||||
#define IDC_DEBUG_MEM_COL5 1071
|
||||
#define IDC_DEBUG_MEM_COL6 1072
|
||||
#define IDC_DEBUG_MEM_COL7 1073
|
||||
#define IDC_DEBUG_MEM_TEXT 1074
|
||||
#define IDC_DEBUG_STACK 1075
|
||||
#define IDC_STATIC_BREAKPOINT 1076
|
||||
#define IDC_BREAKEDIT_ADD 1077
|
||||
#define IDC_BREAKEDIT_DELETE 1078
|
||||
#define IDC_BREAKEDIT_WND 1079
|
||||
#define IDC_STATIC_MMU 1080
|
||||
#define IDC_MMU_IO_A 1081
|
||||
#define IDC_MMU_NCE2_A 1082
|
||||
#define IDC_MMU_CE1_A 1083
|
||||
#define IDC_MMU_CE2_A 1084
|
||||
#define IDC_MMU_NCE3_A 1085
|
||||
#define IDC_MMU_IO_S 1086
|
||||
#define IDC_MMU_CE1_S 1087
|
||||
#define IDC_MMU_CE2_S 1088
|
||||
#define IDC_MMU_NCE2_S 1089
|
||||
#define IDC_MMU_NCE3_S 1090
|
||||
#define IDC_STATIC_MISC 1091
|
||||
#define IDC_MISC_BS_TXT 1092
|
||||
#define IDC_INSTR_TEXT 1093
|
||||
#define IDC_INSTR_CODE 1094
|
||||
#define IDC_INSTR_COPY 1095
|
||||
#define IDC_INSTR_CLEAR 1096
|
||||
#define IDC_BPCODE 1097
|
||||
#define IDC_BPACCESS 1098
|
||||
#define IDC_BPREAD 1099
|
||||
#define IDC_BPWRITE 1100
|
||||
#define ID_FILE_NEW 40001
|
||||
#define ID_FILE_OPEN 40002
|
||||
#define ID_FILE_SAVE 40003
|
||||
|
@ -120,31 +139,34 @@
|
|||
#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_DEBUG_RUN 40023
|
||||
#define ID_DEBUG_STEP 40024
|
||||
#define ID_DEBUG_STEPOVER 40025
|
||||
#define ID_DEBUG_BREAK 40026
|
||||
#define ID_DEBUG_STEPOUT 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
|
||||
#define ID_BREAKPOINTS_NOP3 40031
|
||||
#define ID_BREAKPOINTS_RPL 40032
|
||||
#define ID_DEBUG_CODE_GOADR 40033
|
||||
#define ID_DEBUG_CODE_GOPC 40034
|
||||
#define ID_DEBUG_CODE_SETPCTOSELECT 40035
|
||||
#define ID_DEBUG_MEM_GOADR 40036
|
||||
#define ID_DEBUG_MEM_GOPC 40037
|
||||
#define ID_DEBUG_MEM_GOD0 40038
|
||||
#define ID_DEBUG_MEM_GOD1 40039
|
||||
#define ID_DEBUG_MEM_GOSTACK 40040
|
||||
#define ID_INFO_LASTINSTRUCTIONS 40041
|
||||
#define ID_INTR_STEPOVERINT 40042
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 117
|
||||
#define _APS_NEXT_COMMAND_VALUE 40041
|
||||
#define _APS_NEXT_CONTROL_VALUE 1081
|
||||
#define _APS_NEXT_RESOURCE_VALUE 116
|
||||
#define _APS_NEXT_COMMAND_VALUE 40043
|
||||
#define _APS_NEXT_CONTROL_VALUE 1101
|
||||
#define _APS_NEXT_SYMED_VALUE 108
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h"
|
||||
|
||||
//| 38G | 48SX | 48GX | 49G | Name
|
||||
// #7056A #806E9 #806E9 =TEMPOB
|
||||
|
@ -24,6 +25,36 @@
|
|||
#define AVMEM ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x7066E:0x807ED):0x80E9B)
|
||||
#define INTRPPTR ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x705B0:0x8072F):0x8076B)
|
||||
|
||||
// check for Metakernel version
|
||||
#define METAKERNEL Metakernel()
|
||||
|
||||
// search for "MDGKER:MK2.30" or "MDGKER:PREVIE" in port1 of a HP48GX
|
||||
static BOOL Metakernel(VOID)
|
||||
{
|
||||
BOOL bMkDetect = FALSE;
|
||||
|
||||
// card in slot1 of a HP48GX enabled
|
||||
if (cCurrentRomType=='G' && Chipset.cards_status & PORT1_PRESENT)
|
||||
{
|
||||
// check for Metakernel string "MDGKER:"
|
||||
if (!strncmp(&Chipset.Port1[12],"\xD\x4\x4\x4\x7\x4\xB\x4\x5\x4\x2\x5\xA\x3",14))
|
||||
{
|
||||
bMkDetect = TRUE; // Metakernel detected
|
||||
// check for "MK"
|
||||
if (!strncmp(&Chipset.Port1[26],"\xD\x4\xB\x4",4))
|
||||
{
|
||||
// get version number
|
||||
WORD wVersion = ((Chipset.Port1[30] * 10) + Chipset.Port1[34]) * 10
|
||||
+ Chipset.Port1[36];
|
||||
|
||||
// version newer then V2.30, then compatible with HP OS
|
||||
bMkDetect = (wVersion <= 230);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bMkDetect;
|
||||
}
|
||||
|
||||
DWORD RPL_SkipOb(DWORD d)
|
||||
{
|
||||
BYTE X[8];
|
||||
|
@ -246,6 +277,7 @@ DWORD RPL_Pick(UINT l)
|
|||
|
||||
_ASSERT(l > 0); // first stack elememt is one
|
||||
if (l==0) return 0;
|
||||
if (METAKERNEL) ++l; // Metakernel support
|
||||
stkp = Read5(DSKTOP) + (l-1)*5;
|
||||
return Read5(stkp);
|
||||
}
|
||||
|
@ -256,6 +288,7 @@ VOID RPL_Replace(DWORD n)
|
|||
DWORD stkp;
|
||||
|
||||
stkp = Read5(DSKTOP);
|
||||
if (METAKERNEL) stkp+=5; // Metakernel support
|
||||
Write5(stkp,n);
|
||||
return;
|
||||
}
|
||||
|
@ -270,8 +303,17 @@ VOID RPL_Push(DWORD n)
|
|||
avmem--; // fetch memory
|
||||
Write5(AVMEM,avmem); // save new amount of free memory
|
||||
stkp = Read5(DSKTOP); // get pointer to stack level 1
|
||||
stkp-=5; // fetch new stack entry
|
||||
Write5(stkp,n); // save pointer to new object on stack level 1
|
||||
if (METAKERNEL) // Metakernel running ?
|
||||
{
|
||||
Write5(stkp-5,Read5(stkp)); // copy object pointer of stack level 1 to new stack level 1 entry
|
||||
Write5(stkp,n); // save pointer to new object on stack level 2
|
||||
stkp-=5; // fetch new stack entry
|
||||
}
|
||||
else
|
||||
{
|
||||
stkp-=5; // fetch new stack entry
|
||||
Write5(stkp,n); // save pointer to new object on stack level 1
|
||||
}
|
||||
Write5(DSKTOP,stkp); // save new pointer to stack level 1
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -8,34 +8,32 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h" // 24.10.99 cg, renamed from Serial.h
|
||||
#include "io.h"
|
||||
|
||||
#define INTERRUPT ((void)(Chipset.SoftInt=TRUE,bInterrupt=TRUE))
|
||||
|
||||
// 25.10.99 cg, new, state of USRQ
|
||||
// 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;
|
||||
static DWORD lSerialThreadId = 0;
|
||||
static BOOL bReading = TRUE;
|
||||
static WORD wPort = PORT_CLOSE;
|
||||
|
||||
static BOOL bReading;
|
||||
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)
|
||||
{
|
||||
DWORD dwEvent;
|
||||
SetCommMask(hComm,EV_RXCHAR); // event on RX
|
||||
|
||||
bReading = TRUE; // flag for SerialThread started
|
||||
while (bReading)
|
||||
{
|
||||
_ASSERT(hComm != NULL);
|
||||
|
@ -83,16 +81,16 @@ VOID CommOpen(LPSTR strWirePort,LPSTR strIrPort)
|
|||
|
||||
if(hComm != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// InitializeCriticalSection(&csRecv);
|
||||
|
||||
wPort = (Chipset.IORam[IR_CTRL] & EIRU) ? PORT_IR : PORT_WIRE;
|
||||
SetCommTimeouts(hComm,&CommTimeouts);
|
||||
CommSetBaud();
|
||||
|
||||
// set event RXD handler
|
||||
bReading = TRUE;
|
||||
bReading = FALSE;
|
||||
SetCommMask(hComm,EV_RXCHAR); // event on RX
|
||||
hCThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&SerialThread,NULL,0,&lSerialThreadId);
|
||||
_ASSERT(lSerialThreadId);
|
||||
while (!bReading) Sleep(0); // wait for SerialThread started
|
||||
}
|
||||
else
|
||||
hComm = NULL;
|
||||
|
@ -112,6 +110,7 @@ VOID CommClose(VOID)
|
|||
{
|
||||
if (hComm != NULL) // port open
|
||||
{
|
||||
Sleep(25); // workaround to fix problems with some Kermit server
|
||||
bReading = FALSE; // kill read thread
|
||||
SetCommMask(hComm,0L); // clear all events and force WaitCommEvent to return
|
||||
while (lSerialThreadId != 0) Sleep(0); // wait for termination
|
||||
|
@ -120,7 +119,6 @@ VOID CommClose(VOID)
|
|||
#if defined DEBUG_SERIAL
|
||||
OutputDebugString("COM port closed.\n");
|
||||
#endif
|
||||
// DeleteCriticalSection(&csRecv);
|
||||
wPort = PORT_CLOSE;
|
||||
}
|
||||
return;
|
||||
|
@ -165,7 +163,7 @@ VOID CommSetBaud(VOID)
|
|||
return;
|
||||
}
|
||||
|
||||
VOID UpdateUSRQ(VOID) // 25.10.99 cg, new, USRQ handling
|
||||
VOID UpdateUSRQ(VOID) // USRQ handling
|
||||
{
|
||||
IOBit(SRQ1,USRQ,NINT2USRQ); // update USRQ bit
|
||||
return;
|
||||
|
@ -173,7 +171,8 @@ VOID UpdateUSRQ(VOID) // 25.10.99 cg, new, USRQ handling
|
|||
|
||||
VOID CommTransmit(VOID)
|
||||
{
|
||||
DWORD dwWritten;
|
||||
OVERLAPPED os = { 0 };
|
||||
DWORD dwWritten;
|
||||
|
||||
BYTE tbr = (Chipset.IORam[TBR_MSB] << 4) | Chipset.IORam[TBR_LSB];
|
||||
|
||||
|
@ -188,7 +187,6 @@ VOID CommTransmit(VOID)
|
|||
}
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
@ -196,13 +194,17 @@ VOID CommTransmit(VOID)
|
|||
|
||||
CommReceive(); // receive byte available
|
||||
}
|
||||
// 23.10.99 cg, end of implementation
|
||||
|
||||
if (hComm != NULL) // com port open
|
||||
{
|
||||
os.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
WriteFile(hComm,(LPCVOID) &tbr,1,&dwWritten,&os);
|
||||
GetOverlappedResult(hComm,&os,&dwWritten,TRUE);
|
||||
CloseHandle(os.hEvent);
|
||||
}
|
||||
|
||||
Chipset.IORam[TCS] &= (~TBF); // clear transmit buffer
|
||||
UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ bit
|
||||
UpdateUSRQ(); // update USRQ bit
|
||||
if (Chipset.IORam[IOC] & ETBE) // interrupt on transmit buffer empty
|
||||
INTERRUPT;
|
||||
return;
|
||||
|
@ -210,6 +212,8 @@ VOID CommTransmit(VOID)
|
|||
|
||||
VOID CommReceive(VOID)
|
||||
{
|
||||
OVERLAPPED os = { 0 };
|
||||
|
||||
if (!(Chipset.IORam[IOC] & SON)) // UART off
|
||||
{
|
||||
dwBytesRead = 0L; // no bytes received
|
||||
|
@ -222,7 +226,7 @@ VOID CommReceive(VOID)
|
|||
if (Chipset.IORam[RCS] & RBF) // receive buffer full
|
||||
break;
|
||||
|
||||
// 23.10.99 cg, bugfix, reject reading if com port is closed and not whole operation
|
||||
// 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)
|
||||
|
@ -251,7 +255,7 @@ VOID CommReceive(VOID)
|
|||
--dwBytesRead;
|
||||
|
||||
Chipset.IORam[RCS] |= RBF; // receive buffer full
|
||||
UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ bit
|
||||
UpdateUSRQ(); // update USRQ bit
|
||||
if (Chipset.IORam[IOC] & ERBF) // interrupt on recv buffer full
|
||||
INTERRUPT;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "i28f160.h"
|
||||
|
||||
#define EMU48_INI "Emu48.ini"
|
||||
|
||||
|
@ -31,14 +32,19 @@ VOID ReadSettings(VOID)
|
|||
GetPrivateProfileString("Port2","Filename","SHARED.BIN",szPort2Filename,sizeof(szPort2Filename),EMU48_INI);
|
||||
// KML
|
||||
bAlwaysDisplayLog = GetPrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI);
|
||||
// Disassebler
|
||||
disassembler_mode = GetPrivateProfileInt("Disassembler","Mnemonics",disassembler_mode,EMU48_INI);
|
||||
// Emulator
|
||||
bRealSpeed = GetPrivateProfileInt("Emulator","RealSpeed",0,EMU48_INI);
|
||||
dwSXCycles = GetPrivateProfileInt("Emulator","SXCycles",82,EMU48_INI);
|
||||
dwGXCycles = GetPrivateProfileInt("Emulator","GXCycles",123,EMU48_INI);
|
||||
dwSXCycles = GetPrivateProfileInt("Emulator","SXCycles",dwSXCycles,EMU48_INI);
|
||||
dwGXCycles = GetPrivateProfileInt("Emulator","GXCycles",dwGXCycles,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);
|
||||
// ROM
|
||||
bRomWriteable = GetPrivateProfileInt("ROM","Writeable",TRUE,EMU48_INI);
|
||||
bWP = GetPrivateProfileInt("ROM","WP#",FALSE,EMU48_INI);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -53,6 +59,8 @@ VOID WriteSettings(VOID)
|
|||
WritePrivateProfileString("Port2","Filename",szPort2Filename,EMU48_INI);
|
||||
// KML
|
||||
WritePrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI);
|
||||
// Disassebler
|
||||
WritePrivateProfileInt("Disassembler","Mnemonics",disassembler_mode,EMU48_INI);
|
||||
// Emulator
|
||||
WritePrivateProfileInt("Emulator","RealSpeed",bRealSpeed,EMU48_INI);
|
||||
WritePrivateProfileInt("Emulator","SXCycles",dwSXCycles,EMU48_INI);
|
||||
|
@ -60,6 +68,8 @@ VOID WriteSettings(VOID)
|
|||
// Serial
|
||||
WritePrivateProfileString("Serial","Wire",szSerialWire,EMU48_INI);
|
||||
WritePrivateProfileString("Serial","Ir",szSerialIr,EMU48_INI);
|
||||
// ROM
|
||||
WritePrivateProfileInt("ROM","Writeable",bRomWriteable,EMU48_INI);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h" // 24.10.99 cg, new, I/O definitions
|
||||
#include "io.h" // I/O definitions
|
||||
|
||||
#define AUTO_OFF 10 // Time in minutes for 'auto off'
|
||||
|
||||
|
@ -30,13 +30,15 @@ static BOOL bOutRange = FALSE; // flag if timer value out of range
|
|||
static UINT uT1TimerId = 0;
|
||||
static UINT uT2TimerId = 0;
|
||||
|
||||
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 bNINT2T1 = FALSE; // state of NINT2 affected from timer1
|
||||
static BOOL bNINT2T2 = FALSE; // state of NINT2 affected from 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 BOOL bT2Val; // last access values valid
|
||||
|
||||
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);
|
||||
|
@ -46,22 +48,51 @@ static DWORD CalcT2(VOID) // calculate timer2 value
|
|||
DWORD dwT2 = Chipset.t2; // get value from chipset
|
||||
if (bStarted) // timer2 running
|
||||
{
|
||||
static DWORD dwT2Ref; // timer2 value at last timer2 access
|
||||
static DWORD dwT2Cyc; // cpu cycle counter at last timer2 access
|
||||
|
||||
LARGE_INTEGER lT2Act;
|
||||
DWORD dwT2Dif;
|
||||
|
||||
QueryPerformanceCounter(&lT2Act); // actual time
|
||||
// calculate ticks since reference point
|
||||
dwT2 -= (DWORD)
|
||||
(((lT2Act.QuadPart - lT2Ref.QuadPart) * T2_FREQ)
|
||||
/ lFreq.QuadPart);
|
||||
|
||||
// 2nd timer call in a time 32ms time frame
|
||||
dwT2Dif = dwT2Ref - dwT2;
|
||||
if (bT2Val && dwT2Dif > 0x01 && dwT2Dif <= 0x100)
|
||||
{
|
||||
#define CYC_PER_TICK (2 * 72)
|
||||
DWORD dwT2Ticks = ((DWORD) (Chipset.cycles & 0xFFFFFFFF) - dwT2Cyc) / CYC_PER_TICK;
|
||||
|
||||
if (dwT2Ticks >= dwT2Dif)
|
||||
{
|
||||
dwT2Cyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
dwT2 = dwT2Ref - dwT2Ticks;
|
||||
dwT2Cyc += dwT2Ticks * CYC_PER_TICK;
|
||||
}
|
||||
#undef CYC_PER_TICK
|
||||
}
|
||||
else
|
||||
{
|
||||
dwT2Cyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
}
|
||||
dwT2Ref = dwT2;
|
||||
bT2Val = TRUE; // access values valid
|
||||
}
|
||||
return dwT2;
|
||||
}
|
||||
|
||||
static VOID CheckT1(BYTE nT1)
|
||||
{
|
||||
// 24.10.99 cg, bugfix, implementation of TSRQ
|
||||
// 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
|
||||
{
|
||||
|
@ -94,10 +125,9 @@ static VOID CheckT1(BYTE nT1)
|
|||
|
||||
static VOID CheckT2(DWORD dwT2)
|
||||
{
|
||||
// 24.10.99 cg, bugfix, implementation of TSRQ
|
||||
// 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
|
||||
{
|
||||
|
@ -134,6 +164,7 @@ static VOID RescheduleT2(BOOL bRefPoint)
|
|||
_ASSERT(uT2TimerId == 0); // timer2 must stopped
|
||||
if (bRefPoint) // save reference time
|
||||
{
|
||||
bT2Val = FALSE; // init thread interrupt workaround
|
||||
QueryPerformanceCounter(&lT2Ref); // time of corresponding Chipset.t2 value
|
||||
uDelay = Chipset.t2; // timer value for delay
|
||||
}
|
||||
|
@ -273,10 +304,9 @@ VOID StartTimers(VOID)
|
|||
if (Chipset.IORam[TIMER2_CTRL]&RUN) // start timer1 and timer2 ?
|
||||
{
|
||||
bStarted = TRUE; // flag timer running
|
||||
// 24.10.99 cg, new, initialisation of NINT2 lines
|
||||
// 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)); // get timer resolution
|
||||
|
|
|
@ -7,15 +7,21 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define SWORD SHORT // 09.12.99 cg, new, signed 16 Bit variable
|
||||
#define QWORD ULONGLONG // 22.11.99 cg, new, unsigned 64 Bit variable
|
||||
// HST bits
|
||||
#define XM 1
|
||||
#define SB 2
|
||||
#define SR 4
|
||||
#define MP 8
|
||||
|
||||
#define SWORD SHORT // signed 16 Bit variable
|
||||
#define QWORD ULONGLONG // unsigned 64 Bit variable
|
||||
|
||||
#define CHIPSET Chipset_t
|
||||
typedef struct
|
||||
{
|
||||
SWORD nPosX; // 09.12.99 cg, bugfix, is a signed number
|
||||
SWORD nPosY; // 09.12.99 cg, bugfix, is a signed number
|
||||
BYTE type;
|
||||
SWORD nPosX; // position of window
|
||||
SWORD nPosY;
|
||||
BYTE type; // calculator type
|
||||
|
||||
DWORD Port0Size; // real size of module in KB
|
||||
DWORD Port1Size; // real size of module in KB
|
||||
|
@ -53,14 +59,17 @@ typedef struct
|
|||
|
||||
WORD crc;
|
||||
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
|
||||
WORD wRomCrc; // fingerprint of ROM
|
||||
#if defined _USRDLL // DLL version
|
||||
QWORD cycles; // oscillator cycles
|
||||
#else // EXE version
|
||||
DWORD cycles; // oscillator cycles
|
||||
DWORD cycles_reserved; // reserved for MSB of oscillator cycles
|
||||
#endif
|
||||
DWORD dwKdnCycles; // 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
|
||||
UINT FlashRomState; // WSM state of flash memory (unused)
|
||||
BYTE cards_status;
|
||||
BYTE IORam[64]; // I/O hardware register
|
||||
UINT IOBase; // address of I/O modules page
|
||||
|
@ -74,7 +83,7 @@ typedef struct
|
|||
BYTE t1;
|
||||
DWORD t2;
|
||||
|
||||
BOOL bShutdnWake; // 20.11.99 cg, moved, flag for wake up from SHUTDN mode
|
||||
BOOL bShutdnWake; // flag for wake up from SHUTDN mode
|
||||
|
||||
BYTE Keyboard_Row[9];
|
||||
WORD IR15X;
|
||||
|
|
Loading…
Reference in a new issue