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
|
Lcd
|
||||||
Zoom 2
|
Zoom 2
|
||||||
Offset 20 52
|
Offset 20 52
|
||||||
Color 0 255 255 255
|
Color 0 255 255 255 # character color table
|
||||||
Color 1 255 255 255
|
Color 1 255 255 255
|
||||||
Color 2 255 255 255
|
Color 2 255 255 255
|
||||||
Color 3 255 255 255
|
Color 3 255 255 255
|
||||||
|
@ -42,22 +42,22 @@ Lcd
|
||||||
Color 5 255 255 255
|
Color 5 255 255 255
|
||||||
Color 6 255 255 255
|
Color 6 255 255 255
|
||||||
Color 7 255 255 255
|
Color 7 255 255 255
|
||||||
Color 8 240 240 240
|
Color 8 255 255 255
|
||||||
Color 9 225 225 225
|
Color 9 223 223 223
|
||||||
Color 10 210 210 210
|
Color 10 179 171 171
|
||||||
Color 11 195 195 195
|
Color 11 135 135 135
|
||||||
Color 12 180 180 180
|
Color 12 91 91 91
|
||||||
Color 13 165 165 165
|
Color 13 47 47 47
|
||||||
Color 14 150 150 150
|
Color 14 0 0 0
|
||||||
Color 15 135 135 135
|
Color 15 0 0 0
|
||||||
Color 16 120 120 120
|
Color 16 0 0 0
|
||||||
Color 17 105 105 105
|
Color 17 0 0 0
|
||||||
Color 18 90 90 90
|
Color 18 0 0 0
|
||||||
Color 19 75 75 75
|
Color 19 0 0 0
|
||||||
Color 20 60 60 60
|
Color 20 0 0 0
|
||||||
Color 21 45 45 45
|
Color 21 0 0 0
|
||||||
Color 22 30 30 30
|
Color 22 0 0 0
|
||||||
Color 23 15 15 15
|
Color 23 0 0 0
|
||||||
Color 24 0 0 0
|
Color 24 0 0 0
|
||||||
Color 25 0 0 0
|
Color 25 0 0 0
|
||||||
Color 26 0 0 0
|
Color 26 0 0 0
|
||||||
|
@ -66,6 +66,38 @@ Lcd
|
||||||
Color 29 0 0 0
|
Color 29 0 0 0
|
||||||
Color 30 0 0 0
|
Color 30 0 0 0
|
||||||
Color 31 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
|
End
|
||||||
|
|
||||||
Annunciator 1
|
Annunciator 1
|
||||||
|
|
64
CP_48S3.KML
64
CP_48S3.KML
|
@ -26,25 +26,25 @@ End
|
||||||
Lcd
|
Lcd
|
||||||
Zoom 2
|
Zoom 2
|
||||||
Offset 20 52
|
Offset 20 52
|
||||||
Color 0 255 255 255
|
Color 0 255 255 255 # character color table
|
||||||
Color 1 255 255 255
|
Color 1 255 255 255
|
||||||
Color 2 255 255 255
|
Color 2 255 255 255
|
||||||
Color 3 240 240 240
|
Color 3 240 240 240
|
||||||
Color 4 225 225 225
|
Color 4 216 216 216
|
||||||
Color 5 210 210 210
|
Color 5 192 192 192
|
||||||
Color 6 195 195 195
|
Color 6 168 168 168
|
||||||
Color 7 180 180 180
|
Color 7 144 144 144
|
||||||
Color 8 165 165 165
|
Color 8 120 120 120
|
||||||
Color 9 150 150 150
|
Color 9 96 96 96
|
||||||
Color 10 135 135 135
|
Color 10 72 72 72
|
||||||
Color 11 120 120 120
|
Color 11 48 48 48
|
||||||
Color 12 105 105 105
|
Color 12 24 24 24
|
||||||
Color 13 90 90 90
|
Color 13 0 0 0
|
||||||
Color 14 75 75 75
|
Color 14 0 0 0
|
||||||
Color 15 60 60 60
|
Color 15 0 0 0
|
||||||
Color 16 45 45 45
|
Color 16 0 0 0
|
||||||
Color 17 30 30 30
|
Color 17 0 0 0
|
||||||
Color 18 15 15 15
|
Color 18 0 0 0
|
||||||
Color 19 0 0 0
|
Color 19 0 0 0
|
||||||
Color 20 0 0 0
|
Color 20 0 0 0
|
||||||
Color 21 0 0 0
|
Color 21 0 0 0
|
||||||
|
@ -58,6 +58,38 @@ Lcd
|
||||||
Color 29 0 0 0
|
Color 29 0 0 0
|
||||||
Color 30 0 0 0
|
Color 30 0 0 0
|
||||||
Color 31 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
|
End
|
||||||
|
|
||||||
Annunciator 1
|
Annunciator 1
|
||||||
|
|
BIN
Convert.exe
BIN
Convert.exe
Binary file not shown.
78
DEBUGGER.TXT
78
DEBUGGER.TXT
|
@ -1,7 +1,7 @@
|
||||||
Debugger in Emu48/Tools/Debugger...
|
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.
|
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.
|
||||||
|
|
||||||
|
@ -32,19 +32,19 @@ The program counter will never reach the address behind the GOSUB instruction. T
|
||||||
|
|
||||||
- Step Out F9
|
- Step Out F9
|
||||||
|
|
||||||
Continue the program until a RTI, RTN, RTNC, RTNCC, RTNNC, RTNSC, RTNSXN, RTNYES instruction is found above the current stack level.
|
Continue the program until a RTI, RTN, RTNC, RTNCC, RTNNC, RTNSC, RTNSXN, RTNYES instruction is found above the current stack level.
|
||||||
|
|
||||||
At some code constructions (mostly used to save space on the hardware stack) like
|
At some code constructions (mostly used to save space on the hardware stack) like
|
||||||
|
|
||||||
C=RSTK
|
C=RSTK
|
||||||
PC=C
|
PC=C
|
||||||
|
|
||||||
and
|
and
|
||||||
|
|
||||||
C=RSTK
|
C=RSTK
|
||||||
RSTK=C
|
RSTK=C
|
||||||
RTN
|
RTN
|
||||||
|
|
||||||
the stop address will be wrong. The problem in both code fragments is the C=RSTK opcode. In the first example there is no RTN instruction to stop. In the second one the C=RSTK instruction purge the original return address and then the RSTK=C instruction is interpreted as a GOSUB instruction.
|
the stop address will be wrong. The problem in both code fragments is the C=RSTK opcode. In the first example there is no RTN instruction to stop. In the second one the C=RSTK instruction purge the original return address and then the RSTK=C instruction is interpreted as a GOSUB instruction.
|
||||||
|
|
||||||
In opposite the following code will work fine:
|
In opposite the following code will work fine:
|
||||||
|
@ -73,15 +73,20 @@ Toggle a code breakpoint at the cursor position in the code window.
|
||||||
|
|
||||||
- Edit breakpoints...
|
- 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 breakpoints
|
||||||
|
|
||||||
Clear all code breakpoints except the NOP3 ones.
|
Clear all breakpoints except the NOP3 ones.
|
||||||
|
|
||||||
- NOP3 code breakpoints
|
- 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:
|
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:
|
||||||
|
|
||||||
|
@ -90,7 +95,7 @@ NOP3 and NOP3, what's the difference? The Saturn CPU has no NOP command, so NOP3
|
||||||
and
|
and
|
||||||
|
|
||||||
Opcode 420 for GOC + (next line)
|
Opcode 420 for GOC + (next line)
|
||||||
|
|
||||||
In the assembler of the HPTOOLS 3.x package NOP3 is defined as opcode 820. The advantage of the opcode is that the execution time is always the same, independent from the carry flag. This code is used in the HP48 ROM as well. So I decided to use the GOC opcode for a code breakpoint condition.
|
In the assembler of the HPTOOLS 3.x package NOP3 is defined as opcode 820. The advantage of the opcode is that the execution time is always the same, independent from the carry flag. This code is used in the HP48 ROM as well. So I decided to use the GOC opcode for a code breakpoint condition.
|
||||||
|
|
||||||
A short example:
|
A short example:
|
||||||
|
@ -100,12 +105,12 @@ ASSEMBLE
|
||||||
|
|
||||||
BREAK MACRO
|
BREAK MACRO
|
||||||
CON(3) #024 NOP3
|
CON(3) #024 NOP3
|
||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
RPL
|
RPL
|
||||||
CODE
|
CODE
|
||||||
BREAK code breakpoint
|
BREAK code breakpoint
|
||||||
|
|
||||||
GOSBVL =SAVPTR save register
|
GOSBVL =SAVPTR save register
|
||||||
|
|
||||||
GOSUB + problem for step over
|
GOSUB + problem for step over
|
||||||
|
@ -115,8 +120,28 @@ CODE
|
||||||
GOVLNG =GETPTRLOOP
|
GOVLNG =GETPTRLOOP
|
||||||
ENDCODE
|
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.
|
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!
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
162
EMU48.TXT
162
EMU48.TXT
|
@ -10,16 +10,16 @@
|
||||||
****************
|
****************
|
||||||
|
|
||||||
Emu48 is distributed in 1 archive:
|
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
|
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
|
will write its configuration to a file named Emu48.ini in your Windows
|
||||||
directory.
|
directory.
|
||||||
|
|
||||||
You can also update your current version with the Unofficial Service Packs:
|
You can also update your current version with the Unofficial Service Packs:
|
||||||
- E48BP1x.ZIP New EXE-File
|
- E48BP2x.ZIP New EXE-File
|
||||||
- E48SP1x.ZIP Sources of the Service Pack
|
- E48SP2x.ZIP Sources of the Service Pack
|
||||||
|
|
||||||
Replace the original EXE file please.
|
Replace the original EXE file please.
|
||||||
|
|
||||||
|
@ -48,14 +48,14 @@ ROM, you have to convert it using the Convert utility.
|
||||||
|
|
||||||
To do that, start a Command Prompt while running Windows, and type:
|
To do that, start a Command Prompt while running Windows, and type:
|
||||||
Convert <rom-file> ROM.38G
|
Convert <rom-file> ROM.38G
|
||||||
|
|
||||||
Where <rom-file> is the path to your ROM image. This will create a file named
|
Where <rom-file> is the path to your ROM image. This will create a file named
|
||||||
ROM.38G. This tool will also check its validity.
|
ROM.38G. This tool will also check its validity.
|
||||||
|
|
||||||
- HP48:
|
- HP48:
|
||||||
If you have already used another HP48 emulator, you can convert the ROM using
|
If you have already used another HP48 emulator, you can convert the ROM using
|
||||||
the Convert utility.
|
the Convert utility.
|
||||||
|
|
||||||
To do that, start a Command Prompt while running Windows, and type:
|
To do that, start a Command Prompt while running Windows, and type:
|
||||||
Convert <rom-file> ROM.48G
|
Convert <rom-file> ROM.48G
|
||||||
or Convert <rom-file> ROM.48S
|
or Convert <rom-file> ROM.48S
|
||||||
|
@ -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
|
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.
|
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
|
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
|
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 G(X) ROM values between 9 and
|
display contrast values between 3 and 19 and the HP48 G(X) ROM values between 9
|
||||||
24.
|
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
|
The command line syntax is "Emu48 [E48file [Port2file]]". The first parameter
|
||||||
sets the filename for the emulation data, the second parameter the Port2 file.
|
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
|
You're not able to set a Port 2 file without setting the emulation data file.
|
||||||
arguments are optional.
|
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
|
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
|
use the serial port to transfer the data directly from your HP to the emulator.
|
||||||
emulator. The second way is to load data, saved on your PC, into the stack of
|
The second way is to load data, saved on your PC, into the stack of the
|
||||||
the emulator. You can do this by using the Edit/Load Object... command or with
|
emulator. You can do this by using the Edit/Load Object... command or with the
|
||||||
the file Drag and Drop feature. But there's one important restriction, the data
|
file Drag and Drop feature. But there's one important restriction, the data must
|
||||||
must a HP binary file (begin with HPHP48- or HPHP49-, this depends on your
|
a HP binary file (begin with HPHP48- or HPHP49-, this depends on your emulated
|
||||||
emulated calculator)! If not, the data is load as string. The Edit/Save
|
calculator)! If not, the data is load as string. The Edit/Save Object... command
|
||||||
Object... command will save the data in stack level 1 on the PC (always binary
|
will save the data in stack level 1 on the PC (always binary mode). Be sure,
|
||||||
mode). Be sure, when you use the second way for data transfer, that no program
|
when you use the second way for data transfer, that no program is running on the
|
||||||
is running on the emulator. The second way doesn't work on a HP38, because he
|
emulator. The second way doesn't work on a HP38, because he has no stack. So you
|
||||||
has no stack. So you can load aplets only from the serial port.
|
can load aplets only from the serial port.
|
||||||
|
|
||||||
|
|
||||||
*****************
|
*****************
|
||||||
* DRAG AND DROP *
|
* 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
|
command "Load object...") on the stack. Be sure that the emulator isn't busy
|
||||||
before doing this.
|
before doing this.
|
||||||
|
|
||||||
|
@ -187,12 +187,12 @@ utility will allow you to create it.
|
||||||
|
|
||||||
The syntax is:
|
The syntax is:
|
||||||
MkShared <filename> <size_in_kilobytes>
|
MkShared <filename> <size_in_kilobytes>
|
||||||
|
|
||||||
For example, you can create a 4MB RAM card name SHARED.BIN (in Emu48's
|
For example, you can create a 4MB RAM card name SHARED.BIN (in Emu48's
|
||||||
directory) with the following command:
|
directory) with the following command:
|
||||||
|
|
||||||
MkShared SHARED.BIN 4096
|
MkShared SHARED.BIN 4096
|
||||||
|
|
||||||
Valid sizes are 32, 128, 256, 512, 1024, 2048 and 4096 KB. If you use RAM cards
|
Valid sizes are 32, 128, 256, 512, 1024, 2048 and 4096 KB. If you use RAM cards
|
||||||
greater than 128 KB in a HP48SX, you can only see the first 128 KB of the card.
|
greater than 128 KB in a HP48SX, you can only see the first 128 KB of the card.
|
||||||
|
|
||||||
|
@ -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.
|
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 *
|
* COPY / PASTE STRING *
|
||||||
***********************
|
***********************
|
||||||
|
|
||||||
With the menu items "Copy String" and "Paste String" in the "Edit" menu you're
|
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.
|
versa.
|
||||||
|
|
||||||
|
|
||||||
|
@ -233,7 +249,7 @@ something goes wrong.
|
||||||
************
|
************
|
||||||
* KEYBOARD *
|
* KEYBOARD *
|
||||||
************
|
************
|
||||||
|
|
||||||
To enter a character to the emulator use the PC keyboard (key translation
|
To enter a character to the emulator use the PC keyboard (key translation
|
||||||
depends on the used KML script) or the mouse. If you press the left mouse
|
depends on the used KML script) or the mouse. If you press the left mouse
|
||||||
button, the emulator key is pressed as long as you press the mouse button or
|
button, the emulator key is pressed as long as you press the mouse button or
|
||||||
|
@ -249,9 +265,9 @@ button.
|
||||||
|
|
||||||
The emulator time is synchronized with the PC time at startup of the emulator.
|
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
|
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
|
HP. On HP48 S(X) calculators the address area #00052-#00070, on all other
|
||||||
the address area #00058-#00076 in Port0 are rewritten with the actual time
|
emulated calculators the address area #00058-#00076 in Port 0 are rewritten with
|
||||||
information.
|
the actual time information.
|
||||||
|
|
||||||
|
|
||||||
*************
|
*************
|
||||||
|
@ -268,28 +284,28 @@ again.
|
||||||
* REAL SPEED EMULATION *
|
* REAL SPEED EMULATION *
|
||||||
************************
|
************************
|
||||||
|
|
||||||
As you recognized the speed of the emulated HP48 is much faster than an original
|
As you recognized the speed of the emulated HP is much faster than an original
|
||||||
HP48. The reason is, the assembler commands are emulated faster than the
|
one. The reason is, the assembler commands are emulated faster than the original
|
||||||
original CPU can execute them. On one side this is a big advantage (faster
|
CPU can execute them. On one side this is a big advantage (faster execution of
|
||||||
execution of programs) on the other side this cause many trouble. In Emu48 only
|
programs) on the other side this cause many trouble. In Emu48 only the timers
|
||||||
the timers work with the original speed. In result all commands like User-RPL
|
work with the original speed. In result all commands like User-RPL WAIT wait
|
||||||
WAIT wait more or less the correct time. But many programs like shells or
|
more or less the correct time. But many programs like shells or editors use an
|
||||||
editors use an own key handler to realize an autorepeat implementation. Normally
|
own key handler to realize an autorepeat implementation. Normally these programs
|
||||||
these programs use the execution time of each assembler command for waiting. On
|
use the execution time of each assembler command for waiting. On Emu48 this time
|
||||||
Emu48 this time is much shorter, so the time between each key read is shorter as
|
is much shorter, so the time between each key read is shorter as well and you
|
||||||
well and you get a very fast key repetition. The editor ED from the JAZZ package
|
get a very fast key repetition. The editor ED from the JAZZ package hasn't this
|
||||||
hasn't this problem, because the key input is synchronized with one of the
|
problem, because the key input is synchronized with one of the timers. To solve
|
||||||
timers. To solve this problem Emu48 generally slow down emulation if a key is
|
this problem Emu48 generally slow down emulation if a key is pressed. To solve
|
||||||
pressed. To solve some other speed depending problems you are able to slow down
|
some other speed depending problems you are able to slow down the whole
|
||||||
the whole emulation speed. There are two variables 'SXCycles=82' and
|
emulation speed. There are two variables 'SXCycles=82' and 'GXCycles=123'
|
||||||
'GXCycles=123' defined in the Emu48.ini file, section [Emulator] which control
|
defined in the Emu48.ini file, section [Emulator] which control the "real" speed
|
||||||
the "real" speed and key repetition slow down for each calculator type. Each
|
and key repetition slow down for each calculator type. Each numeric value is
|
||||||
numeric value is representing the allowed CPU cycles in a 16384Hz time frame.
|
representing the allowed CPU cycles in a 16384Hz time frame. Because the used
|
||||||
Because the used cycle statements (from SASM.DOC) in Emu48 doesn't correspond to
|
cycle statements (from SASM.DOC) in Emu48 doesn't correspond to the real values
|
||||||
the real values of the CPU, the saved values are estimated by comparing the
|
of the CPU, the saved values are estimated by comparing the execution time of a
|
||||||
execution time of a program to the real calculator. Increasing the value fitting
|
program to the real calculator. Increasing the value fitting to your ROM will
|
||||||
to your ROM will make the "real speed" HP faster and vice versa. No warranty to
|
make the "real speed" HP faster and vice versa. No warranty to the functionality
|
||||||
the functionality of Emu48 when you go below the default values.
|
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
|
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
|
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
|
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
|
Now it's possible to make transfers between the real calculator and Emu48. If
|
||||||
problems with the connection please try the following. There's a simple way to
|
you have problems with the connection please try the following. There's a simple
|
||||||
check if your serial port is used by another program. First disable the serial
|
way to check if your serial port is used by another program. First disable the
|
||||||
settings in both combo boxes and very important close the settings dialog.
|
serial settings in both combo boxes and very important close the settings
|
||||||
Reopen the settings dialog and choose the COM port in the wire combo box to the
|
dialog. Reopen the settings dialog and choose the COM port in the wire combo box
|
||||||
port the HP48 is connected with. When you open this combo box you only see valid
|
to the port the HP is connected with. When you open this combo box you only see
|
||||||
(unused) serial ports. Don't use the IR combo box, it only works with 2400 Baud.
|
valid (unused) serial ports. Don't use the IR combo box, it only works with 2400
|
||||||
The next important thing are the serial settings of the HP48 and Emu48, they
|
Baud. The next important thing are the serial settings of the real calculator
|
||||||
must be equal. If this doesn't work then mostly there's a hardware or a resource
|
and Emu48, they must be equal. If this doesn't work then mostly there's a
|
||||||
problem of the serial port. Check this with connecting the HP48 with a transfer
|
hardware or a resource problem of the serial port. Check this with connecting
|
||||||
program you like on the same serial port.
|
the HP with a transfer program you like on the same serial port.
|
||||||
|
|
||||||
|
|
||||||
****************
|
****************
|
||||||
* DISASSEMBLER *
|
* DISASSEMBLER *
|
||||||
****************
|
****************
|
||||||
|
|
||||||
With the internal disassembler you're able to disassemble the HP48 address area.
|
With the internal disassembler you're able to disassemble the Saturn chip
|
||||||
With the default Map setting the disassembler always see the mapped memory
|
address area. With the default Map setting the disassembler always see the
|
||||||
address. If for example you configured the RAM at #00000 you will see the RAM
|
mapped memory address. If for example you configured the RAM at #00000 you will
|
||||||
and not the ROM at this address. With the other Module settings you specify a
|
see the RAM and not the ROM at this address. With the other module settings you
|
||||||
special module for disassembly. Each module will begin at address #00000 and
|
specify a special module for disassembly. Each module use a linear address mode,
|
||||||
will not overlapped by other modules. For Port2 I use a linear address mode,
|
beginning at address #00000 and will not overlapped by other modules. So, for
|
||||||
that means that the second port of a RAM card greater than 128KB is at address
|
example, you can access the second port of a HP48 RAM card greater than 128KB at
|
||||||
#40000 (128 * 1024 * 2) and so on. The "Copy Data" button copies the selected
|
address #40000 (128 * 1024 * 2). The "Copy Data" button copies the selected
|
||||||
disassembler lines to the PC clipboard.
|
disassembler lines to the PC clipboard.
|
||||||
|
|
||||||
|
|
||||||
|
@ -387,9 +403,9 @@ Other graphics and scripts are available at Casey's Emu48 Graphics Page:
|
||||||
***************
|
***************
|
||||||
* LEGAL STUFF *
|
* LEGAL STUFF *
|
||||||
***************
|
***************
|
||||||
|
|
||||||
Emu48 - An HP38/48/49 Emulator
|
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
|
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
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
|
43
PROBLEMS.TXT
43
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)
|
- the following I/O bits aren't emulated (incomplete)
|
||||||
DTEST (0x102) [VDIG LID TRIM]
|
DTEST (0x102) [VDIG LID TRIM]
|
||||||
DSPCTL (0x103) [LRT LRTD LRTC BIN]
|
DSPCTL (0x103) [LRT LRTD LRTC BIN]
|
||||||
LPE (0x109) [ELBI EVLBI GRST RST]
|
LPE (0x109) [ELBI EVLBI GRST RST]
|
||||||
IOC (0x110) [ERBZ]
|
IOC (0x110) [ERBZ]
|
||||||
RCS (0x111) [RX RER RBZ]
|
RCS (0x111) [RX RER RBZ]
|
||||||
TCS (0x112) [BRK TBZ TBF]
|
TCS (0x112) [BRK TBZ TBF]
|
||||||
SRQ1 (0x118) [ISQR VSRQ]
|
SRQ1 (0x118) [ISQR VSRQ]
|
||||||
SRQ2 (0x119) [LSRQ]
|
SRQ2 (0x119) [LSRQ]
|
||||||
IRC (0x11A) [IRI EIRU EIRI IRE]
|
IRC (0x11A) [IRI EIRU EIRI IRE]
|
||||||
LCR (0x11C) [LED ELBE LBZ LBF]
|
LCR (0x11C) [LED ELBE LBZ LBF]
|
||||||
LBR (0x11D) [LBO]
|
LBR (0x11D) [LBO]
|
||||||
- the baudrates 1920, 3840, 7680 and 15360 aren't emulated on most
|
- the baudrates 1920, 3840, 7680 and 15360 aren't emulated on most
|
||||||
operating systems
|
operating systems
|
||||||
Windows 95a 1920, 3840, 7680 work, 15360 fail
|
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,
|
-> all programs that run on a real calculator will run as well,
|
||||||
programs with incorrect DA19 / BEN handling may run on the
|
programs with incorrect DA19 / BEN handling may run on the
|
||||||
emulator but will crash on a real calculator
|
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
|
- no beeper support with OUT command -> all programs that aren't
|
||||||
use the "=makebeep" subroutine, like alarm wake up, have no sound
|
use the "=makebeep" subroutine, like alarm wake up, have no sound
|
||||||
- beeper emulation, ATTN key doesn't work,
|
- beeper emulation, ATTN key doesn't work,
|
||||||
Windows 9x: plays only default sound event or standard system beep
|
Windows 9x: plays only default sound event or standard system beep
|
||||||
- no infrared printer support
|
- 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
|
- memory window of debugger view some addresses in I/O register area
|
||||||
with invalid data
|
with invalid data
|
||||||
- Shell OS: clock isn't synchronized with real time
|
- Shell OS: clock isn't synchronized with real time
|
||||||
- HP49G: flash ROM is treated as ROM (no writing to flash memory)
|
- HP49G: the flash memory is emulated now with some restrictions
|
||||||
-> writing to port 2:FLASH will crash the emulation!
|
- 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 <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <malloc.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;
|
LPBYTE pRom;
|
||||||
DWORD dwSizeLo, dwSizeHi;
|
|
||||||
BYTE szVersion[16];
|
|
||||||
BOOL bUnpack = FALSE;
|
|
||||||
BOOL bSwap = FALSE;
|
|
||||||
BOOL bText = FALSE;
|
|
||||||
DWORD dwWritten;
|
|
||||||
WORD wCRC;
|
WORD wCRC;
|
||||||
BOOL bIsGx;
|
WORD wType;
|
||||||
|
|
||||||
static WORD crc_table[16] =
|
static WORD crc_table[16] =
|
||||||
{
|
{
|
||||||
|
@ -36,7 +31,7 @@ BOOL CheckCRC()
|
||||||
UINT i;
|
UINT i;
|
||||||
DWORD dwBase = 0x00000;
|
DWORD dwBase = 0x00000;
|
||||||
UINT nPass = 0;
|
UINT nPass = 0;
|
||||||
UINT nPasses = bIsGx?2:1;
|
UINT nPasses = (wType != HP48S)?2:1;
|
||||||
|
|
||||||
again:
|
again:
|
||||||
|
|
||||||
|
@ -94,32 +89,58 @@ static DWORD Asc2Nib5(LPSTR lpBuf)
|
||||||
|((DWORD)Asc2Nib(lpBuf[4])));
|
|((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[])
|
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))
|
if ((argc!=2)&&(argc!=3))
|
||||||
{
|
{
|
||||||
printf("Usage:\n\t%s <old-rom-dump> [<new-rom-dump>]\n", argv[0]);
|
printf("Usage:\n\t%s <old-rom-dump> [<new-rom-dump>]\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
pRom = LocalAlloc(LMEM_FIXED,512*1024*2);
|
||||||
pRom = LocalAlloc(0,1048576);
|
|
||||||
if (pRom == NULL)
|
if (pRom == NULL)
|
||||||
{
|
{
|
||||||
printf("Memory Allocation Failed !");
|
printf("Memory Allocation Failed !");
|
||||||
return 1;
|
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)
|
if (hFile == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
|
LocalFree(pRom);
|
||||||
printf("Cannot open file %s.\n", argv[1]);
|
printf("Cannot open file %s.\n", argv[1]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
dwSizeLo = GetFileSize(hFile, &dwSizeHi);
|
dwSizeLo = GetFileSize(hFile, NULL);
|
||||||
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||||
if (hMap == NULL)
|
if (hMap == NULL)
|
||||||
{
|
{
|
||||||
|
LocalFree(pRom);
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
puts("CreateFileMapping failed.");
|
puts("CreateFileMapping failed.");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -127,42 +148,65 @@ UINT main(int argc, char *argv[])
|
||||||
pIn = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
pIn = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
||||||
if (pIn == NULL)
|
if (pIn == NULL)
|
||||||
{
|
{
|
||||||
|
LocalFree(pRom);
|
||||||
CloseHandle(hMap);
|
CloseHandle(hMap);
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
puts("MapViewOfFile failed.\n");
|
puts("MapViewOfFile failed.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pIn[0])
|
for (i = 0; i < 2 && !bFormatDetected; ++i)
|
||||||
{
|
{
|
||||||
case '0':
|
switch (pIn[0+dwAddrOffset])
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
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;
|
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 (bUnpack) printf("Unpacking nibbles.\n");
|
||||||
if (bSwap) printf("Swapping nibbles.\n");
|
if (bSwap) printf("Swapping nibbles.\n");
|
||||||
if (bText) printf("Reading text file.\n");
|
if (bText) printf("Reading text file.\n");
|
||||||
|
if (bDA19) printf("Swapping banks.\n");
|
||||||
|
|
||||||
if (bText)
|
if (bText)
|
||||||
{
|
{
|
||||||
|
@ -200,8 +244,9 @@ UINT main(int argc, char *argv[])
|
||||||
DWORD i;
|
DWORD i;
|
||||||
for (i=0; i<dwSizeLo; i++)
|
for (i=0; i<dwSizeLo; i++)
|
||||||
{
|
{
|
||||||
pRom[(i<<1) ] = pIn[i]>>4;
|
BYTE byC = pIn[(i+dwAddrOffset)&(dwSizeLo-1)];
|
||||||
pRom[(i<<1)+1] = pIn[i]&0xF;
|
pRom[(i<<1) ] = byC>>4;
|
||||||
|
pRom[(i<<1)+1] = byC&0xF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -209,8 +254,9 @@ UINT main(int argc, char *argv[])
|
||||||
DWORD i;
|
DWORD i;
|
||||||
for (i=0; i<dwSizeLo; i++)
|
for (i=0; i<dwSizeLo; i++)
|
||||||
{
|
{
|
||||||
pRom[(i<<1) ] = pIn[i]&0xF;
|
BYTE byC = pIn[(i+dwAddrOffset)&(dwSizeLo-1)];
|
||||||
pRom[(i<<1)+1] = pIn[i]>>4;
|
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)
|
for (i=0; i<dwSizeLo; i+=2)
|
||||||
{
|
{
|
||||||
BYTE a, b;
|
BYTE a, b;
|
||||||
a = pIn[i];
|
a = pIn[(i+dwAddrOffset)&(dwSizeLo-1)];
|
||||||
b = pIn[i+1];
|
b = pIn[(i+1+dwAddrOffset)&(dwSizeLo-1)];
|
||||||
pRom[i] = a;
|
pRom[i] = b;
|
||||||
pRom[i+1] = b;
|
pRom[i+1] = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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(hMap);
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
|
|
||||||
if (bText||bUnpack||bSwap)
|
if (bText||bUnpack||bSwap||bDA19)
|
||||||
{
|
{
|
||||||
printf("File converted.");
|
printf("File converted.\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bIsGx = (pRom[0x29] == 0x00);
|
do
|
||||||
|
|
||||||
printf("ROM Model Detected : HP48%c\n", bIsGx?'G':'S');
|
|
||||||
|
|
||||||
if (bIsGx)
|
|
||||||
{
|
{
|
||||||
UINT i;
|
// HP38G
|
||||||
for (i=0; i<6; i++)
|
wType = HP38G;
|
||||||
{
|
dwAddress = 0x7FFAF;
|
||||||
szVersion[i] = pRom[0x7FFBF + (i<<1) + 1] << 4;
|
uLen = 10;
|
||||||
szVersion[i] |= pRom[0x7FFBF + (i<<1) ];
|
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;
|
szVersion[i] = pRom[dwAddress + (i<<1) + 1] << 4;
|
||||||
for (i=0; i<6; i++)
|
szVersion[i] |= pRom[dwAddress + (i<<1)];
|
||||||
{
|
|
||||||
szVersion[i] = pRom[0x7FFF0 + (i<<1) + 1] << 4;
|
|
||||||
szVersion[i] |= pRom[0x7FFF0 + (i<<1) ];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
szVersion[6] = 0;
|
szVersion[i] = 0;
|
||||||
|
|
||||||
printf("ROM Version : %s\n", szVersion);
|
printf("ROM Version : %s\n", szVersion);
|
||||||
|
|
||||||
FillMemory(pRom+0x100, 0x40, 0);
|
ZeroMemory(pRom+0x100, 0x40); // clear IO register area
|
||||||
|
|
||||||
if (CheckCRC())
|
if (CheckCRC())
|
||||||
{
|
{
|
||||||
|
@ -283,14 +348,14 @@ UINT main(int argc, char *argv[])
|
||||||
|
|
||||||
if (argc == 3)
|
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)
|
if (hFile == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
LocalFree(pRom);
|
LocalFree(pRom);
|
||||||
printf("Cannot open file %s.\n", argv[2]);
|
printf("Cannot open file %s.\n", argv[2]);
|
||||||
return 1;
|
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);
|
CloseHandle(hOut);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,16 +10,16 @@
|
||||||
****************
|
****************
|
||||||
|
|
||||||
Emu48 is distributed in 1 archive:
|
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
|
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
|
will write its configuration to a file named Emu48.ini in your Windows
|
||||||
directory.
|
directory.
|
||||||
|
|
||||||
You can also update your current version with the Unofficial Service Packs:
|
You can also update your current version with the Unofficial Service Packs:
|
||||||
- E48BP1x.ZIP New EXE-File
|
- E48BP2x.ZIP New EXE-File
|
||||||
- E48SP1x.ZIP Sources of the Service Pack
|
- E48SP2x.ZIP Sources of the Service Pack
|
||||||
|
|
||||||
Replace the original EXE file please.
|
Replace the original EXE file please.
|
||||||
|
|
||||||
|
@ -48,14 +48,14 @@ ROM, you have to convert it using the Convert utility.
|
||||||
|
|
||||||
To do that, start a Command Prompt while running Windows, and type:
|
To do that, start a Command Prompt while running Windows, and type:
|
||||||
Convert <rom-file> ROM.38G
|
Convert <rom-file> ROM.38G
|
||||||
|
|
||||||
Where <rom-file> is the path to your ROM image. This will create a file named
|
Where <rom-file> is the path to your ROM image. This will create a file named
|
||||||
ROM.38G. This tool will also check its validity.
|
ROM.38G. This tool will also check its validity.
|
||||||
|
|
||||||
- HP48:
|
- HP48:
|
||||||
If you have already used another HP48 emulator, you can convert the ROM using
|
If you have already used another HP48 emulator, you can convert the ROM using
|
||||||
the Convert utility.
|
the Convert utility.
|
||||||
|
|
||||||
To do that, start a Command Prompt while running Windows, and type:
|
To do that, start a Command Prompt while running Windows, and type:
|
||||||
Convert <rom-file> ROM.48G
|
Convert <rom-file> ROM.48G
|
||||||
or Convert <rom-file> ROM.48S
|
or Convert <rom-file> ROM.48S
|
||||||
|
@ -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
|
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.
|
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
|
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
|
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 G(X) ROM values between 9 and
|
display contrast values between 3 and 19 and the HP48 G(X) ROM values between 9
|
||||||
24.
|
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
|
The command line syntax is "Emu48 [E48file [Port2file]]". The first parameter
|
||||||
sets the filename for the emulation data, the second parameter the Port2 file.
|
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
|
You're not able to set a Port 2 file without setting the emulation data file.
|
||||||
arguments are optional.
|
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
|
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
|
use the serial port to transfer the data directly from your HP to the emulator.
|
||||||
emulator. The second way is to load data, saved on your PC, into the stack of
|
The second way is to load data, saved on your PC, into the stack of the
|
||||||
the emulator. You can do this by using the Edit/Load Object... command or with
|
emulator. You can do this by using the Edit/Load Object... command or with the
|
||||||
the file Drag and Drop feature. But there's one important restriction, the data
|
file Drag and Drop feature. But there's one important restriction, the data must
|
||||||
must a HP binary file (begin with HPHP48- or HPHP49-, this depends on your
|
a HP binary file (begin with HPHP48- or HPHP49-, this depends on your emulated
|
||||||
emulated calculator)! If not, the data is load as string. The Edit/Save
|
calculator)! If not, the data is load as string. The Edit/Save Object... command
|
||||||
Object... command will save the data in stack level 1 on the PC (always binary
|
will save the data in stack level 1 on the PC (always binary mode). Be sure,
|
||||||
mode). Be sure, when you use the second way for data transfer, that no program
|
when you use the second way for data transfer, that no program is running on the
|
||||||
is running on the emulator. The second way doesn't work on a HP38, because he
|
emulator. The second way doesn't work on a HP38, because he has no stack. So you
|
||||||
has no stack. So you can load aplets only from the serial port.
|
can load aplets only from the serial port.
|
||||||
|
|
||||||
|
|
||||||
*****************
|
*****************
|
||||||
* DRAG AND DROP *
|
* 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
|
command "Load object...") on the stack. Be sure that the emulator isn't busy
|
||||||
before doing this.
|
before doing this.
|
||||||
|
|
||||||
|
@ -187,12 +187,12 @@ utility will allow you to create it.
|
||||||
|
|
||||||
The syntax is:
|
The syntax is:
|
||||||
MkShared <filename> <size_in_kilobytes>
|
MkShared <filename> <size_in_kilobytes>
|
||||||
|
|
||||||
For example, you can create a 4MB RAM card name SHARED.BIN (in Emu48's
|
For example, you can create a 4MB RAM card name SHARED.BIN (in Emu48's
|
||||||
directory) with the following command:
|
directory) with the following command:
|
||||||
|
|
||||||
MkShared SHARED.BIN 4096
|
MkShared SHARED.BIN 4096
|
||||||
|
|
||||||
Valid sizes are 32, 128, 256, 512, 1024, 2048 and 4096 KB. If you use RAM cards
|
Valid sizes are 32, 128, 256, 512, 1024, 2048 and 4096 KB. If you use RAM cards
|
||||||
greater than 128 KB in a HP48SX, you can only see the first 128 KB of the card.
|
greater than 128 KB in a HP48SX, you can only see the first 128 KB of the card.
|
||||||
|
|
||||||
|
@ -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.
|
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 *
|
* COPY / PASTE STRING *
|
||||||
***********************
|
***********************
|
||||||
|
|
||||||
With the menu items "Copy String" and "Paste String" in the "Edit" menu you're
|
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.
|
versa.
|
||||||
|
|
||||||
|
|
||||||
|
@ -233,7 +249,7 @@ something goes wrong.
|
||||||
************
|
************
|
||||||
* KEYBOARD *
|
* KEYBOARD *
|
||||||
************
|
************
|
||||||
|
|
||||||
To enter a character to the emulator use the PC keyboard (key translation
|
To enter a character to the emulator use the PC keyboard (key translation
|
||||||
depends on the used KML script) or the mouse. If you press the left mouse
|
depends on the used KML script) or the mouse. If you press the left mouse
|
||||||
button, the emulator key is pressed as long as you press the mouse button or
|
button, the emulator key is pressed as long as you press the mouse button or
|
||||||
|
@ -249,9 +265,9 @@ button.
|
||||||
|
|
||||||
The emulator time is synchronized with the PC time at startup of the emulator.
|
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
|
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
|
HP. On HP48 S(X) calculators the address area #00052-#00070, on all other
|
||||||
the address area #00058-#00076 in Port0 are rewritten with the actual time
|
emulated calculators the address area #00058-#00076 in Port 0 are rewritten with
|
||||||
information.
|
the actual time information.
|
||||||
|
|
||||||
|
|
||||||
*************
|
*************
|
||||||
|
@ -268,28 +284,28 @@ again.
|
||||||
* REAL SPEED EMULATION *
|
* REAL SPEED EMULATION *
|
||||||
************************
|
************************
|
||||||
|
|
||||||
As you recognized the speed of the emulated HP48 is much faster than an original
|
As you recognized the speed of the emulated HP is much faster than an original
|
||||||
HP48. The reason is, the assembler commands are emulated faster than the
|
one. The reason is, the assembler commands are emulated faster than the original
|
||||||
original CPU can execute them. On one side this is a big advantage (faster
|
CPU can execute them. On one side this is a big advantage (faster execution of
|
||||||
execution of programs) on the other side this cause many trouble. In Emu48 only
|
programs) on the other side this cause many trouble. In Emu48 only the timers
|
||||||
the timers work with the original speed. In result all commands like User-RPL
|
work with the original speed. In result all commands like User-RPL WAIT wait
|
||||||
WAIT wait more or less the correct time. But many programs like shells or
|
more or less the correct time. But many programs like shells or editors use an
|
||||||
editors use an own key handler to realize an autorepeat implementation. Normally
|
own key handler to realize an autorepeat implementation. Normally these programs
|
||||||
these programs use the execution time of each assembler command for waiting. On
|
use the execution time of each assembler command for waiting. On Emu48 this time
|
||||||
Emu48 this time is much shorter, so the time between each key read is shorter as
|
is much shorter, so the time between each key read is shorter as well and you
|
||||||
well and you get a very fast key repetition. The editor ED from the JAZZ package
|
get a very fast key repetition. The editor ED from the JAZZ package hasn't this
|
||||||
hasn't this problem, because the key input is synchronized with one of the
|
problem, because the key input is synchronized with one of the timers. To solve
|
||||||
timers. To solve this problem Emu48 generally slow down emulation if a key is
|
this problem Emu48 generally slow down emulation if a key is pressed. To solve
|
||||||
pressed. To solve some other speed depending problems you are able to slow down
|
some other speed depending problems you are able to slow down the whole
|
||||||
the whole emulation speed. There are two variables 'SXCycles=82' and
|
emulation speed. There are two variables 'SXCycles=82' and 'GXCycles=123'
|
||||||
'GXCycles=123' defined in the Emu48.ini file, section [Emulator] which control
|
defined in the Emu48.ini file, section [Emulator] which control the "real" speed
|
||||||
the "real" speed and key repetition slow down for each calculator type. Each
|
and key repetition slow down for each calculator type. Each numeric value is
|
||||||
numeric value is representing the allowed CPU cycles in a 16384Hz time frame.
|
representing the allowed CPU cycles in a 16384Hz time frame. Because the used
|
||||||
Because the used cycle statements (from SASM.DOC) in Emu48 doesn't correspond to
|
cycle statements (from SASM.DOC) in Emu48 doesn't correspond to the real values
|
||||||
the real values of the CPU, the saved values are estimated by comparing the
|
of the CPU, the saved values are estimated by comparing the execution time of a
|
||||||
execution time of a program to the real calculator. Increasing the value fitting
|
program to the real calculator. Increasing the value fitting to your ROM will
|
||||||
to your ROM will make the "real speed" HP faster and vice versa. No warranty to
|
make the "real speed" HP faster and vice versa. No warranty to the functionality
|
||||||
the functionality of Emu48 when you go below the default values.
|
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
|
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
|
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
|
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
|
Now it's possible to make transfers between the real calculator and Emu48. If
|
||||||
problems with the connection please try the following. There's a simple way to
|
you have problems with the connection please try the following. There's a simple
|
||||||
check if your serial port is used by another program. First disable the serial
|
way to check if your serial port is used by another program. First disable the
|
||||||
settings in both combo boxes and very important close the settings dialog.
|
serial settings in both combo boxes and very important close the settings
|
||||||
Reopen the settings dialog and choose the COM port in the wire combo box to the
|
dialog. Reopen the settings dialog and choose the COM port in the wire combo box
|
||||||
port the HP48 is connected with. When you open this combo box you only see valid
|
to the port the HP is connected with. When you open this combo box you only see
|
||||||
(unused) serial ports. Don't use the IR combo box, it only works with 2400 Baud.
|
valid (unused) serial ports. Don't use the IR combo box, it only works with 2400
|
||||||
The next important thing are the serial settings of the HP48 and Emu48, they
|
Baud. The next important thing are the serial settings of the real calculator
|
||||||
must be equal. If this doesn't work then mostly there's a hardware or a resource
|
and Emu48, they must be equal. If this doesn't work then mostly there's a
|
||||||
problem of the serial port. Check this with connecting the HP48 with a transfer
|
hardware or a resource problem of the serial port. Check this with connecting
|
||||||
program you like on the same serial port.
|
the HP with a transfer program you like on the same serial port.
|
||||||
|
|
||||||
|
|
||||||
****************
|
****************
|
||||||
* DISASSEMBLER *
|
* DISASSEMBLER *
|
||||||
****************
|
****************
|
||||||
|
|
||||||
With the internal disassembler you're able to disassemble the HP48 address area.
|
With the internal disassembler you're able to disassemble the Saturn chip
|
||||||
With the default Map setting the disassembler always see the mapped memory
|
address area. With the default Map setting the disassembler always see the
|
||||||
address. If for example you configured the RAM at #00000 you will see the RAM
|
mapped memory address. If for example you configured the RAM at #00000 you will
|
||||||
and not the ROM at this address. With the other Module settings you specify a
|
see the RAM and not the ROM at this address. With the other module settings you
|
||||||
special module for disassembly. Each module will begin at address #00000 and
|
specify a special module for disassembly. Each module use a linear address mode,
|
||||||
will not overlapped by other modules. For Port2 I use a linear address mode,
|
beginning at address #00000 and will not overlapped by other modules. So, for
|
||||||
that means that the second port of a RAM card greater than 128KB is at address
|
example, you can access the second port of a HP48 RAM card greater than 128KB at
|
||||||
#40000 (128 * 1024 * 2) and so on. The "Copy Data" button copies the selected
|
address #40000 (128 * 1024 * 2). The "Copy Data" button copies the selected
|
||||||
disassembler lines to the PC clipboard.
|
disassembler lines to the PC clipboard.
|
||||||
|
|
||||||
|
|
||||||
|
@ -387,9 +403,9 @@ Other graphics and scripts are available at Casey's Emu48 Graphics Page:
|
||||||
***************
|
***************
|
||||||
* LEGAL STUFF *
|
* LEGAL STUFF *
|
||||||
***************
|
***************
|
||||||
|
|
||||||
Emu48 - An HP38/48/49 Emulator
|
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
|
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
|
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
|
Service Pack 15 for Emu48 Version 1.0
|
||||||
|
|
||||||
DEBUGGER.C
|
DEBUGGER.C
|
||||||
|
@ -24,7 +374,7 @@ EMU48.C
|
||||||
- replaced __argc and __argv variables by process variables
|
- replaced __argc and __argv variables by process variables
|
||||||
- replaced INI file handling part
|
- replaced INI file handling part
|
||||||
- changed address in GPL license string
|
- changed address in GPL license string
|
||||||
- added HP38 stuff to function UpdateWindowStatus() and
|
- added HP38 stuff to function UpdateWindowStatus() and
|
||||||
SettingsProc()
|
SettingsProc()
|
||||||
- changed function SettingsProc(), replaced Port1_Writeable variable
|
- changed function SettingsProc(), replaced Port1_Writeable variable
|
||||||
- bugfix in function OnViewReset(), some registers wasn't reset,
|
- bugfix in function OnViewReset(), some registers wasn't reset,
|
||||||
|
@ -112,7 +462,7 @@ OPCODES.C
|
||||||
- bugfix in function o08(), o09(), o0A(), o0B(), o3X(), o8086n(),
|
- bugfix in function o08(), o09(), o0A(), o0B(), o3X(), o8086n(),
|
||||||
o8087n(), o808An(), o808Bn() and o8Ed4(), changed number of cpu
|
o8087n(), o808An(), o808Bn() and o8Ed4(), changed number of cpu
|
||||||
cycles
|
cycles
|
||||||
|
|
||||||
RESOURCE.H
|
RESOURCE.H
|
||||||
- added several definitions
|
- added several definitions
|
||||||
|
|
||||||
|
@ -200,7 +550,7 @@ EXTERNAL.C
|
||||||
- some minor changes for the HP49 beeper emulation
|
- some minor changes for the HP49 beeper emulation
|
||||||
|
|
||||||
FILES.C
|
FILES.C
|
||||||
- added new document type for HP49G
|
- added new document type for HP49
|
||||||
- change in function WriteStack(), accept HP49 binary files now
|
- change in function WriteStack(), accept HP49 binary files now
|
||||||
- the port2 open/close handling is now controlled by the document
|
- the port2 open/close handling is now controlled by the document
|
||||||
- several changes in port2 handling, the HP49 use an internal 128KB
|
- several changes in port2 handling, the HP49 use an internal 128KB
|
||||||
|
@ -400,7 +750,7 @@ EMU48.C
|
||||||
- bugfix in functions OnFileExit() and OnSysClose(), stop emulation
|
- bugfix in functions OnFileExit() and OnSysClose(), stop emulation
|
||||||
thread before saving emulation data
|
thread before saving emulation data
|
||||||
- changed function Disasm(), changed list box from single to multi
|
- changed function Disasm(), changed list box from single to multi
|
||||||
selectable items, added button to copy selected items to
|
selectable items, added button to copy selected items to
|
||||||
clipboard
|
clipboard
|
||||||
- moved function DragAcceptFiles() to WM_CREATE handler
|
- moved function DragAcceptFiles() to WM_CREATE handler
|
||||||
- added function DragAcceptFiles() to WM_DESTROY handler
|
- added function DragAcceptFiles() to WM_DESTROY handler
|
||||||
|
@ -533,14 +883,14 @@ MOPS.C
|
||||||
- bugfix in function ReadIO(), the TIMER1CTRL and TIMER2CTRL
|
- bugfix in function ReadIO(), the TIMER1CTRL and TIMER2CTRL
|
||||||
register (0x12E,0x12F) must be updated before reading
|
register (0x12E,0x12F) must be updated before reading
|
||||||
- bugfix in function WriteIO(), don't clear the XTRA bit in the
|
- bugfix in function WriteIO(), don't clear the XTRA bit in the
|
||||||
TIMER1CTRL register (0x12E) while setting
|
TIMER1CTRL register (0x12E) while setting
|
||||||
- bugfix in function WriteIO(), after setting new TIMER1CTRL and
|
- bugfix in function WriteIO(), after setting new TIMER1CTRL and
|
||||||
TIMER2CTRL register (0x12E,0x12F) values the control bit
|
TIMER2CTRL register (0x12E,0x12F) values the control bit
|
||||||
condition must be checked
|
condition must be checked
|
||||||
- bugfix in function WriteIO(), handle start/stop of the LINECOUNT
|
- bugfix in function WriteIO(), handle start/stop of the LINECOUNT
|
||||||
register when the DON bit in the DISPIO (0x100) register has
|
register when the DON bit in the DISPIO (0x100) register has
|
||||||
changed
|
changed
|
||||||
- bugfix in function WriteIO(), force new ROM mapping if DA19 in
|
- bugfix in function WriteIO(), force new ROM mapping if DA19 in
|
||||||
the MSB LINECOUNT (0x129) register has changed on a G(X) ROM
|
the MSB LINECOUNT (0x129) register has changed on a G(X) ROM
|
||||||
|
|
||||||
OPCODES.H
|
OPCODES.H
|
||||||
|
@ -876,7 +1226,7 @@ MOPS.C
|
||||||
OPCODES.H
|
OPCODES.H
|
||||||
- bugfix in INTON and INTOFF command, they aren't able to generate a
|
- bugfix in INTON and INTOFF command, they aren't able to generate a
|
||||||
keyboard interrupt
|
keyboard interrupt
|
||||||
- bugfix in RSI command, call interrupt routine or set interrupt
|
- bugfix in RSI command, call interrupt routine or set interrupt
|
||||||
pending flag if a bit of the IN register is high
|
pending flag if a bit of the IN register is high
|
||||||
- RTI command changed, doesn't handle ON key here
|
- RTI command changed, doesn't handle ON key here
|
||||||
- added InfoMessage for BUSCB command
|
- added InfoMessage for BUSCB command
|
||||||
|
@ -1011,7 +1361,7 @@ FILES.C
|
||||||
NT (NT GDI is 32 bit coded, Windows 95 mostly 16 bit -> the
|
NT (NT GDI is 32 bit coded, Windows 95 mostly 16 bit -> the
|
||||||
failed conversion doesn't matter with Windows 95)
|
failed conversion doesn't matter with Windows 95)
|
||||||
- bugfix in close file handling of function OpenDocument()
|
- bugfix in close file handling of function OpenDocument()
|
||||||
- InitKML() need chipset for contrast setting in RestoreBackup()
|
- InitKML() need chipset for contrast setting in RestoreBackup()
|
||||||
|
|
||||||
KML.C
|
KML.C
|
||||||
- added global variables
|
- added global variables
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,12 +7,13 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// #define BP_EXEC 1 // code breakpoint
|
// breakpoint type definitions
|
||||||
// #define BP_READ 2 // read memory breakpoint
|
#define BP_EXEC 1 // code breakpoint
|
||||||
// #define BP_WRITE 4 // write memory breakpoint
|
#define BP_READ 2 // read memory breakpoint
|
||||||
// #define BP_RANGE 8 // check address range
|
#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_RUN 0
|
||||||
#define DBG_STEPINTO 1
|
#define DBG_STEPINTO 1
|
||||||
#define DBG_STEPOVER 2
|
#define DBG_STEPOVER 2
|
||||||
|
@ -22,10 +23,16 @@
|
||||||
extern HWND hDlgDebug;
|
extern HWND hDlgDebug;
|
||||||
extern HANDLE hEventDebug;
|
extern HANDLE hEventDebug;
|
||||||
extern BOOL bDbgEnable;
|
extern BOOL bDbgEnable;
|
||||||
extern INT nDbgState; // 13.11.99 cg, state of debugger
|
extern INT nDbgState;
|
||||||
extern BOOL bDbgNOP3;
|
extern BOOL bDbgNOP3;
|
||||||
|
extern BOOL bDbgRPL;
|
||||||
|
extern BOOL bDbgSkipInt;
|
||||||
extern DWORD dwDbgRstkp;
|
extern DWORD dwDbgRstkp;
|
||||||
extern DWORD dwDbgRstk; // 13.11.99 cg, possible return address
|
extern DWORD dwDbgRstk;
|
||||||
extern BOOL CheckBreakpoint(DWORD dwAddr);
|
extern DWORD *pdwInstrArray;
|
||||||
extern VOID NotifyDebugger(VOID); // 10.11.99 cg, notify debugger emulation stopped
|
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);
|
extern LRESULT OnToolDebug(VOID);
|
||||||
|
|
|
@ -503,13 +503,14 @@ static char *disasm_1 (DWORD *addr, char *out)
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
fn = read_nibble (addr);
|
fn = read_nibble (addr);
|
||||||
fn = (fn & 7);
|
c = (fn < 8); // flag for operand register
|
||||||
if (fn > 4)
|
fn = (fn & 7); // get register number
|
||||||
fn -= 4;
|
if (fn > 4) // illegal opcode
|
||||||
|
break; // no output
|
||||||
switch (disassembler_mode)
|
switch (disassembler_mode)
|
||||||
{
|
{
|
||||||
case HP_MNEMONICS:
|
case HP_MNEMONICS:
|
||||||
c = (char) ((fn < 8) ? 'A' : 'C');
|
c = (char) (c ? 'A' : 'C');
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
wsprintf (buf, "R%d=%c", fn, c);
|
wsprintf (buf, "R%d=%c", fn, c);
|
||||||
else
|
else
|
||||||
|
@ -519,7 +520,7 @@ static char *disasm_1 (DWORD *addr, char *out)
|
||||||
case CLASS_MNEMONICS:
|
case CLASS_MNEMONICS:
|
||||||
p = append_str (out, "move.w");
|
p = append_str (out, "move.w");
|
||||||
p = append_tab (out);
|
p = append_tab (out);
|
||||||
c = (char) ((fn < 8) ? 'a' : 'c');
|
c = (char) (c ? 'a' : 'c');
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
wsprintf (buf, "%c, r%d", c, fn);
|
wsprintf (buf, "%c, r%d", c, fn);
|
||||||
else
|
else
|
||||||
|
@ -534,20 +535,21 @@ static char *disasm_1 (DWORD *addr, char *out)
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
fn = read_nibble (addr);
|
fn = read_nibble (addr);
|
||||||
fn = (fn & 7);
|
c = (fn < 8); // flag for operand register
|
||||||
if (fn > 4)
|
fn = (fn & 7); // get register number
|
||||||
fn -= 4;
|
if (fn > 4) // illegal opcode
|
||||||
|
break; // no output
|
||||||
switch (disassembler_mode)
|
switch (disassembler_mode)
|
||||||
{
|
{
|
||||||
case HP_MNEMONICS:
|
case HP_MNEMONICS:
|
||||||
c = (char) ((fn < 8) ? 'A' : 'C');
|
c = (char) (c ? 'A' : 'C');
|
||||||
wsprintf (buf, "%cR%dEX", c, fn);
|
wsprintf (buf, "%cR%dEX", c, fn);
|
||||||
p = append_str (out, buf);
|
p = append_str (out, buf);
|
||||||
break;
|
break;
|
||||||
case CLASS_MNEMONICS:
|
case CLASS_MNEMONICS:
|
||||||
p = append_str (out, "exg.w");
|
p = append_str (out, "exg.w");
|
||||||
p = append_tab (out);
|
p = append_tab (out);
|
||||||
c = (char) ((fn < 8) ? 'a' : 'c');
|
c = (char) (c ? 'a' : 'c');
|
||||||
wsprintf (buf, "%c, r%d", c, fn);
|
wsprintf (buf, "%c, r%d", c, fn);
|
||||||
p = append_str (p, buf);
|
p = append_str (p, buf);
|
||||||
break;
|
break;
|
||||||
|
@ -1020,6 +1022,8 @@ static char *disasm_8 (DWORD *addr, char *out, BOOL view)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 9:
|
case 9:
|
||||||
|
fn = read_nibble (addr); // get field selector
|
||||||
|
n = read_nibble (addr); // get register selector
|
||||||
switch (disassembler_mode)
|
switch (disassembler_mode)
|
||||||
{
|
{
|
||||||
case HP_MNEMONICS:
|
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]);
|
op_str_81[(n & 3) + 4 * disassembler_mode]);
|
||||||
p = append_str (out, buf);
|
p = append_str (out, buf);
|
||||||
p = append_tab (out);
|
p = append_tab (out);
|
||||||
p = append_field (p, read_nibble (addr));
|
p = append_field (p, fn);
|
||||||
break;
|
break;
|
||||||
case CLASS_MNEMONICS:
|
case CLASS_MNEMONICS:
|
||||||
p = append_str (out, "lsr");
|
p = append_str (out, "lsr");
|
||||||
p = append_field (p, read_nibble (addr));
|
p = append_field (p, fn);
|
||||||
p = append_tab (out);
|
p = append_tab (out);
|
||||||
p = append_str (p, "#1, ");
|
p = append_str (p, "#1, ");
|
||||||
p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]);
|
p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "Emu48.h"
|
#include "Emu48.h"
|
||||||
|
#include "io.h"
|
||||||
#include "kml.h"
|
#include "kml.h"
|
||||||
|
|
||||||
#define LCD1_ROW 144
|
#define LCD1_ROW 144
|
||||||
|
@ -109,8 +110,13 @@ VOID CreateLcdBitmap()
|
||||||
bmiLcd.Lcd_bmih.biWidth = LCD1_ROW * nLcdDoubled;
|
bmiLcd.Lcd_bmih.biWidth = LCD1_ROW * nLcdDoubled;
|
||||||
bmiLcd.Lcd_bmih.biHeight = -64 * nLcdDoubled;
|
bmiLcd.Lcd_bmih.biHeight = -64 * nLcdDoubled;
|
||||||
hLcdDC = CreateCompatibleDC(hWindowDC);
|
hLcdDC = CreateCompatibleDC(hWindowDC);
|
||||||
|
_ASSERT(hLcdDC != NULL);
|
||||||
hLcdBitmap = CreateDIBSection(hLcdDC, (BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS, (LPVOID*)&pbyLcd, NULL, 0);
|
hLcdBitmap = CreateDIBSection(hLcdDC, (BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS, (LPVOID*)&pbyLcd, NULL, 0);
|
||||||
|
_ASSERT(hLcdBitmap != NULL);
|
||||||
hOldLcdBitmap = SelectObject(hLcdDC, hLcdBitmap);
|
hOldLcdBitmap = SelectObject(hLcdDC, hLcdBitmap);
|
||||||
|
_ASSERT(hPalette != NULL);
|
||||||
|
SelectPalette(hLcdDC, hPalette, FALSE); // set palette for LCD DC
|
||||||
|
RealizePalette(hLcdDC); // realize palette
|
||||||
UpdateContrast(Chipset.contrast);
|
UpdateContrast(Chipset.contrast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +141,12 @@ VOID DestroyLcdBitmap()
|
||||||
|
|
||||||
BOOL CreateMainBitmap(LPSTR szFilename)
|
BOOL CreateMainBitmap(LPSTR szFilename)
|
||||||
{
|
{
|
||||||
|
HPALETTE hAssertPalette;
|
||||||
|
|
||||||
|
_ASSERT(hWindowDC != NULL);
|
||||||
hMainDC = CreateCompatibleDC(hWindowDC);
|
hMainDC = CreateCompatibleDC(hWindowDC);
|
||||||
|
_ASSERT(hMainDC != NULL);
|
||||||
|
if (hMainDC == NULL) return FALSE; // quit if failed
|
||||||
hMainBitmap = LoadBitmapFile(szFilename);
|
hMainBitmap = LoadBitmapFile(szFilename);
|
||||||
if (hMainBitmap == NULL)
|
if (hMainBitmap == NULL)
|
||||||
{
|
{
|
||||||
|
@ -143,7 +154,10 @@ BOOL CreateMainBitmap(LPSTR szFilename)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
hOldMainBitmap = SelectObject(hMainDC, hMainBitmap);
|
hOldMainBitmap = SelectObject(hMainDC, hMainBitmap);
|
||||||
SelectPalette(hMainDC, hPalette, FALSE);
|
_ASSERT(hPalette != NULL);
|
||||||
|
hAssertPalette = SelectPalette(hMainDC, hPalette, FALSE);
|
||||||
|
_ASSERT(hAssertPalette != NULL);
|
||||||
|
RealizePalette(hMainDC);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,14 +570,17 @@ VOID UpdateAnnunciators()
|
||||||
{
|
{
|
||||||
BYTE c;
|
BYTE c;
|
||||||
|
|
||||||
c = (BYTE)(Chipset.IORam[0xB] | (Chipset.IORam[0xC]<<4));
|
c = (BYTE)(Chipset.IORam[ANNCTRL] | (Chipset.IORam[ANNCTRL+1]<<4));
|
||||||
if (!(c&0x80)) c=0;
|
// switch annunciators off if timer stopped
|
||||||
DrawAnnunciator(1,c&0x01);
|
if ((c & AON) == 0 || (Chipset.IORam[TIMER2_CTRL] & RUN) == 0)
|
||||||
DrawAnnunciator(2,c&0x02);
|
c=0;
|
||||||
DrawAnnunciator(3,c&0x04);
|
|
||||||
DrawAnnunciator(4,c&0x08);
|
DrawAnnunciator(1,c&LA1);
|
||||||
DrawAnnunciator(5,c&0x10);
|
DrawAnnunciator(2,c&LA2);
|
||||||
DrawAnnunciator(6,c&0x20);
|
DrawAnnunciator(3,c&LA3);
|
||||||
|
DrawAnnunciator(4,c&LA4);
|
||||||
|
DrawAnnunciator(5,c&LA5);
|
||||||
|
DrawAnnunciator(6,c&LA6);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,11 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "Emu48.h"
|
#include "Emu48.h"
|
||||||
|
#include "io.h"
|
||||||
#include "kml.h"
|
#include "kml.h"
|
||||||
#include "debugger.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 CF_HPOBJ "CF_HPOBJ" // clipboard format for DDE
|
||||||
|
|
||||||
#define MAXPORTS 16 // number of COM ports
|
#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 szTopic = "Stack"; // topic for DDE server
|
||||||
LPSTR szTitle = NULL;
|
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"
|
"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"
|
"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"
|
"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 csIOLock; // critical section for I/O access
|
||||||
CRITICAL_SECTION csT1Lock; // critical section for timer1 access
|
CRITICAL_SECTION csT1Lock; // critical section for timer1 access
|
||||||
CRITICAL_SECTION csT2Lock; // critical section for timer2 access
|
CRITICAL_SECTION csT2Lock; // critical section for timer2 access
|
||||||
CRITICAL_SECTION csRecvLock; // 24.10.99 cg, moved, critical section for receive byte
|
CRITICAL_SECTION csRecvLock; // critical section for receive byte
|
||||||
INT nArgc; // 08.11.99 cg, new, no. of command line arguments
|
INT nArgc; // no. of command line arguments
|
||||||
LPCTSTR *ppArgv; // 08.11.99 cg, new, command line arguments
|
LPCTSTR *ppArgv; // command line arguments
|
||||||
LARGE_INTEGER lFreq; // counter frequency
|
LARGE_INTEGER lFreq; // high performance counter frequency
|
||||||
|
LARGE_INTEGER lAppStart; // high performance counter value at Appl. start
|
||||||
DWORD idDdeInst; // DDE server id
|
DWORD idDdeInst; // DDE server id
|
||||||
UINT uCF_HpObj; // DDE clipboard format
|
UINT uCF_HpObj; // DDE clipboard format
|
||||||
HANDLE hThread;
|
HANDLE hThread;
|
||||||
|
@ -110,10 +112,9 @@ VOID UpdateWindowStatus()
|
||||||
|
|
||||||
if ((nState == 0)||(nState == 3))
|
if ((nState == 0)||(nState == 3))
|
||||||
{
|
{
|
||||||
// 02.12.99 cg, new, disable stack loading items on HP38G
|
// disable stack loading items on HP38G
|
||||||
UINT uStackEnable = (cCurrentRomType!='A') ? MF_ENABLED : MF_GRAYED;
|
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_SAVE,(szCurrentFilename[0]) ? MF_ENABLED : MF_GRAYED);
|
||||||
EnableMenuItem(hMenu,ID_FILE_SAVEAS,MF_ENABLED);
|
EnableMenuItem(hMenu,ID_FILE_SAVEAS,MF_ENABLED);
|
||||||
EnableMenuItem(hMenu,ID_FILE_CLOSE,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_BACKUP_SAVE,MF_ENABLED);
|
||||||
EnableMenuItem(hMenu,ID_VIEW_COPY,MF_ENABLED);
|
EnableMenuItem(hMenu,ID_VIEW_COPY,MF_ENABLED);
|
||||||
EnableMenuItem(hMenu,ID_VIEW_RESET,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_LOAD,uStackEnable);
|
||||||
EnableMenuItem(hMenu,ID_OBJECT_SAVE,uStackEnable);
|
EnableMenuItem(hMenu,ID_OBJECT_SAVE,uStackEnable);
|
||||||
EnableMenuItem(hMenu,ID_STACK_COPY,uStackEnable);
|
EnableMenuItem(hMenu,ID_STACK_COPY,uStackEnable);
|
||||||
EnableMenuItem(hMenu,ID_STACK_PASTE,uStackEnable);
|
EnableMenuItem(hMenu,ID_STACK_PASTE,uStackEnable);
|
||||||
// 02.12.99 cg, end of added part
|
|
||||||
EnableMenuItem(hMenu,ID_TOOL_DISASM,MF_ENABLED);
|
EnableMenuItem(hMenu,ID_TOOL_DISASM,MF_ENABLED);
|
||||||
}
|
}
|
||||||
else
|
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
|
//# 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_AUTOSAVEONEXIT,bAutoSaveOnExit);
|
||||||
CheckDlgButton(hDlg,IDC_ALWAYSDISPLOG,bAlwaysDisplayLog);
|
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
|
// set combobox parameter
|
||||||
SetCommList(hDlg,IDC_WIRE,szSerialWire);
|
SetCommList(hDlg,IDC_WIRE,szSerialWire);
|
||||||
SetCommList(hDlg,IDC_IR,szSerialIr);
|
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);
|
EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 01.12.99 cg, HP48SX/GX
|
// HP48SX/GX
|
||||||
if (cCurrentRomType!='A' && cCurrentRomType!='X')
|
if (cCurrentRomType!='6' && cCurrentRomType!='A' && cCurrentRomType!='X')
|
||||||
{
|
{
|
||||||
// init port1 enable checkbox
|
// init port1 enable checkbox
|
||||||
CheckDlgButton(hDlg,IDC_PORT1EN,(Chipset.cards_status & PORT1_PRESENT) != 0);
|
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);
|
CheckDlgButton(hDlg,IDC_PORT1WR,(Chipset.cards_status & PORT1_WRITE) != 0);
|
||||||
// init port2 shared checkbox and set port2 filename
|
// init port2 shared checkbox and set port2 filename
|
||||||
CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared);
|
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);
|
CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared);
|
||||||
SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename);
|
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);
|
SendDlgItemMessage(hDlg,IDC_IR,CB_RESETCONTENT,0,0);
|
||||||
EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE);
|
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')
|
if (Chipset.Port1Size && cCurrentRomType!='X')
|
||||||
{
|
{
|
||||||
UINT nOldState = SwitchToState(3);
|
UINT nOldState = SwitchToState(3);
|
||||||
// port1 disabled ?;
|
// save old card status
|
||||||
|
BYTE bCardsStatus = Chipset.cards_status;
|
||||||
|
|
||||||
|
// port1 disabled?
|
||||||
Chipset.cards_status &= ~(PORT1_PRESENT | PORT1_WRITE);
|
Chipset.cards_status &= ~(PORT1_PRESENT | PORT1_WRITE);
|
||||||
if (IsDlgButtonChecked(hDlg, IDC_PORT1EN))
|
if (IsDlgButtonChecked(hDlg, IDC_PORT1EN))
|
||||||
{
|
{
|
||||||
Chipset.cards_status |= PORT1_PRESENT;
|
Chipset.cards_status |= PORT1_PRESENT;
|
||||||
// 19.11.99 cg, changed, use dialog variable now
|
|
||||||
if (IsDlgButtonChecked(hDlg, IDC_PORT1WR))
|
if (IsDlgButtonChecked(hDlg, IDC_PORT1WR))
|
||||||
Chipset.cards_status |= PORT1_WRITE;
|
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;
|
bInterrupt = TRUE;
|
||||||
}
|
}
|
||||||
Map(0x00,0xFF);
|
Map(0x00,0xFF);
|
||||||
|
@ -293,9 +366,12 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP
|
||||||
bPort2IsShared = IsDlgButtonChecked(hDlg,IDC_PORT2ISSHARED);
|
bPort2IsShared = IsDlgButtonChecked(hDlg,IDC_PORT2ISSHARED);
|
||||||
GetDlgItemText(hDlg,IDC_PORT2,szPort2Filename,sizeof(szPort2Filename));
|
GetDlgItemText(hDlg,IDC_PORT2,szPort2Filename,sizeof(szPort2Filename));
|
||||||
}
|
}
|
||||||
|
// set disassebler mode
|
||||||
|
disassembler_mode = IsDlgButtonChecked(hDlg,IDC_DISASM_HP) ? HP_MNEMONICS : CLASS_MNEMONICS;
|
||||||
// set combobox parameter
|
// set combobox parameter
|
||||||
GetDlgItemText(hDlg,IDC_WIRE,szSerialWire,sizeof(szSerialWire));
|
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);
|
EndDialog(hDlg, wParam);
|
||||||
}
|
}
|
||||||
if (wParam == IDCANCEL)
|
if (wParam == IDCANCEL)
|
||||||
|
@ -340,7 +416,7 @@ static UINT SaveChanges(BOOL bAuto)
|
||||||
uReply = GetSaveAsFilename();
|
uReply = GetSaveAsFilename();
|
||||||
if (uReply != IDOK) return uReply;
|
if (uReply != IDOK) return uReply;
|
||||||
if (!SaveDocumentAs(szBufferFilename)) return IDCANCEL;
|
if (!SaveDocumentAs(szBufferFilename)) return IDCANCEL;
|
||||||
WriteLastDocument(szCurrentFilename); // 11.12.99 cg, changed, call function
|
WriteLastDocument(szCurrentFilename);
|
||||||
return IDYES;
|
return IDYES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,6 +437,13 @@ static UINT SaveChanges(BOOL bAuto)
|
||||||
//
|
//
|
||||||
static LRESULT OnCreate(HWND hWindow)
|
static LRESULT OnCreate(HWND hWindow)
|
||||||
{
|
{
|
||||||
|
InitializeCriticalSection(&csGDILock);
|
||||||
|
InitializeCriticalSection(&csKeyLock);
|
||||||
|
InitializeCriticalSection(&csIOLock);
|
||||||
|
InitializeCriticalSection(&csT1Lock);
|
||||||
|
InitializeCriticalSection(&csT2Lock);
|
||||||
|
InitializeCriticalSection(&csRecvLock);
|
||||||
|
|
||||||
hWnd = hWindow;
|
hWnd = hWindow;
|
||||||
hWindowDC = GetDC(hWnd);
|
hWindowDC = GetDC(hWnd);
|
||||||
DragAcceptFiles(hWnd,TRUE); // support dropped files
|
DragAcceptFiles(hWnd,TRUE); // support dropped files
|
||||||
|
@ -373,12 +456,18 @@ static LRESULT OnCreate(HWND hWindow)
|
||||||
static LRESULT OnDestroy(HWND hWindow)
|
static LRESULT OnDestroy(HWND hWindow)
|
||||||
{
|
{
|
||||||
DragAcceptFiles(hWnd,FALSE); // no WM_DROPFILES message any more
|
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);
|
ReleaseDC(hWnd, hWindowDC);
|
||||||
SetWindowTitle(NULL); // free memory of title
|
SetWindowTitle(NULL); // free memory of title
|
||||||
hWindowDC = NULL; // hWindowDC isn't valid any more
|
hWindowDC = NULL; // hWindowDC isn't valid any more
|
||||||
hWnd = NULL;
|
hWnd = NULL;
|
||||||
|
|
||||||
|
DeleteCriticalSection(&csGDILock);
|
||||||
|
DeleteCriticalSection(&csKeyLock);
|
||||||
|
DeleteCriticalSection(&csIOLock);
|
||||||
|
DeleteCriticalSection(&csT1Lock);
|
||||||
|
DeleteCriticalSection(&csT2Lock);
|
||||||
|
DeleteCriticalSection(&csRecvLock);
|
||||||
|
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
return 0;
|
return 0;
|
||||||
UNREFERENCED_PARAMETER(hWindow);
|
UNREFERENCED_PARAMETER(hWindow);
|
||||||
|
@ -395,7 +484,12 @@ static LRESULT OnPaint(HWND hWindow)
|
||||||
hPaintDC = BeginPaint(hWindow, &Paint);
|
hPaintDC = BeginPaint(hWindow, &Paint);
|
||||||
if (hMainDC != NULL)
|
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))
|
if ((nState==0)||(nState==3))
|
||||||
{
|
{
|
||||||
UpdateMainDisplay();
|
UpdateMainDisplay();
|
||||||
|
@ -417,7 +511,8 @@ static LRESULT OnDropFiles(HANDLE hFilesInfo)
|
||||||
WORD wNumFiles,wIndex;
|
WORD wNumFiles,wIndex;
|
||||||
BOOL bSuccess;
|
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
|
// get number of files dropped
|
||||||
wNumFiles = DragQueryFile (hFilesInfo,(UINT)-1,NULL,0);
|
wNumFiles = DragQueryFile (hFilesInfo,(UINT)-1,NULL,0);
|
||||||
|
@ -438,7 +533,6 @@ static LRESULT OnDropFiles(HANDLE hFilesInfo)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (nState!=nNextState) Sleep(0);
|
|
||||||
_ASSERT(nState==3);
|
_ASSERT(nState==3);
|
||||||
|
|
||||||
// get each name and load it into the emulator
|
// get each name and load it into the emulator
|
||||||
|
@ -547,7 +641,7 @@ static LRESULT OnFileSaveAs()
|
||||||
SwitchToState(0);
|
SwitchToState(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
WriteLastDocument(szCurrentFilename); // 11.12.99 cg, changed, call function
|
WriteLastDocument(szCurrentFilename);
|
||||||
|
|
||||||
SwitchToState(0);
|
SwitchToState(0);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -606,7 +700,6 @@ static LRESULT OnStackCopy() // copy data from stack
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (nState!=nNextState) Sleep(0);
|
|
||||||
_ASSERT(nState==3);
|
_ASSERT(nState==3);
|
||||||
|
|
||||||
if ((dwAddress = RPL_Pick(1)) == 0) // pick address of level1 object
|
if ((dwAddress = RPL_Pick(1)) == 0) // pick address of level1 object
|
||||||
|
@ -682,7 +775,6 @@ static LRESULT OnStackPaste() // paste data to stack
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (nState!=nNextState) Sleep(0);
|
|
||||||
_ASSERT(nState==3);
|
_ASSERT(nState==3);
|
||||||
|
|
||||||
if (OpenClipboard(hWnd))
|
if (OpenClipboard(hWnd))
|
||||||
|
@ -848,7 +940,7 @@ static LRESULT OnViewReset()
|
||||||
if (YesNoMessage("Are you sure you want to press the Reset Button ?")==IDYES)
|
if (YesNoMessage("Are you sure you want to press the Reset Button ?")==IDYES)
|
||||||
{
|
{
|
||||||
SwitchToState(3);
|
SwitchToState(3);
|
||||||
CpuReset(); // 19.03.99 cg, changed, register setting after Cpu Reset
|
CpuReset(); // register setting after Cpu Reset
|
||||||
SwitchToState(0);
|
SwitchToState(0);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -963,7 +1055,6 @@ static LRESULT OnObjectLoad()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (nState!=nNextState) Sleep(0);
|
|
||||||
_ASSERT(nState==3);
|
_ASSERT(nState==3);
|
||||||
|
|
||||||
if (bWarning)
|
if (bWarning)
|
||||||
|
@ -971,7 +1062,7 @@ static LRESULT OnObjectLoad()
|
||||||
UINT uReply = YesNoCancelMessage(
|
UINT uReply = YesNoCancelMessage(
|
||||||
"Warning: Trying to load an object while the emulator is busy \n"
|
"Warning: Trying to load an object while the emulator is busy \n"
|
||||||
"will certainly result in a memory lost. Before loading an object \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 ?");
|
"Do you want to see this warning next time you try to load an object ?");
|
||||||
switch (uReply)
|
switch (uReply)
|
||||||
{
|
{
|
||||||
|
@ -1020,9 +1111,11 @@ static LRESULT OnObjectSave()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
|
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
|
||||||
|
{
|
||||||
|
InfoMessage("The emulator is busy.");
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
while (nState!=nNextState) Sleep(0);
|
|
||||||
_ASSERT(nState==3);
|
_ASSERT(nState==3);
|
||||||
|
|
||||||
if (!GetSaveObjectFilename())
|
if (!GetSaveObjectFilename())
|
||||||
|
@ -1046,9 +1139,8 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
|
||||||
static DWORD dwAddress, dwAddressMax;
|
static DWORD dwAddress, dwAddressMax;
|
||||||
|
|
||||||
LONG i;
|
LONG i;
|
||||||
LPINT lpnCount;
|
|
||||||
char *cpStop,szAddress[256] = "0";
|
char *cpStop,szAddress[256] = "0";
|
||||||
|
|
||||||
switch (message)
|
switch (message)
|
||||||
{
|
{
|
||||||
case WM_INITDIALOG:
|
case WM_INITDIALOG:
|
||||||
|
@ -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_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_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_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_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_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_ADR,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
||||||
SendDlgItemMessage(hDlg,IDC_DISASM_NEXT,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
SendDlgItemMessage(hDlg,IDC_DISASM_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));
|
SendDlgItemMessage(hDlg,IDCANCEL,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
|
||||||
SetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress);
|
SetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress);
|
||||||
disassembler_map = MEM_MAP; // disassemble with mapped modules
|
disassembler_map = MEM_MAP; // disassemble with mapped modules
|
||||||
disassembler_mode = HP_MNEMONICS; // use HP mnemonics for disassembling
|
|
||||||
dwAddress = strtoul(szAddress,&cpStop,16);
|
dwAddress = strtoul(szAddress,&cpStop,16);
|
||||||
dwAddressMax = 0x100000; // greatest address (mapped mode)
|
dwAddressMax = 0x100000; // greatest address (mapped mode)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1101,12 +1188,6 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
|
||||||
? (Chipset.Port2Size * 2048)
|
? (Chipset.Port2Size * 2048)
|
||||||
: ((dwPort2Mask != 0) ? ((dwPort2Mask + 1) << 18) : (dwPort2Size * 2048));
|
: ((dwPort2Mask != 0) ? ((dwPort2Mask + 1) << 18) : (dwPort2Size * 2048));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case IDC_DISASM_HP:
|
|
||||||
disassembler_mode = HP_MNEMONICS;
|
|
||||||
return TRUE;
|
|
||||||
case IDC_DISASM_CLASS:
|
|
||||||
disassembler_mode = CLASS_MNEMONICS;
|
|
||||||
return TRUE;
|
|
||||||
case IDOK:
|
case IDOK:
|
||||||
SendDlgItemMessage(hDlg,IDC_DISASM_ADR,EM_SETSEL,0,-1);
|
SendDlgItemMessage(hDlg,IDC_DISASM_ADR,EM_SETSEL,0,-1);
|
||||||
GetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress,sizeof(szAddress));
|
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:
|
case IDC_DISASM_NEXT:
|
||||||
if (dwAddress >= dwAddressMax)
|
if (dwAddress >= dwAddressMax)
|
||||||
return FALSE;
|
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);
|
dwAddress = disassemble(dwAddress,&szAddress[i],VIEW_LONG);
|
||||||
i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_ADDSTRING,0,(LPARAM) szAddress);
|
i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_ADDSTRING,0,(LPARAM) szAddress);
|
||||||
SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_SELITEMRANGE,FALSE,MAKELPARAM(0,i));
|
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);
|
SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_SETTOPINDEX,i,0);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case IDC_DISASM_COPY:
|
case IDC_DISASM_COPY:
|
||||||
// get number of selections
|
// copy selected items to clipboard
|
||||||
if ((i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETSELCOUNT,0,0)) == 0)
|
CopyItemsToClipboard(GetDlgItem(hDlg,IDC_DISASM_WIN));
|
||||||
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
|
|
||||||
}
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case IDCANCEL:
|
case IDCANCEL:
|
||||||
EndDialog(hDlg, wParam);
|
EndDialog(hDlg, wParam);
|
||||||
|
@ -1335,29 +1370,17 @@ LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||||
return DefWindowProc(hWindow, uMsg, wParam, lParam);
|
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)
|
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
|
||||||
{
|
{
|
||||||
MSG msg;
|
MSG msg;
|
||||||
WNDCLASS wc;
|
WNDCLASS wc;
|
||||||
RECT rectWindow;
|
RECT rectWindow;
|
||||||
HSZ hszService, hszTopic; // variables for DDE server
|
HSZ hszService, hszTopic; // variables for DDE server
|
||||||
|
DWORD dwAffMask;
|
||||||
|
|
||||||
hApp = hInst;
|
hApp = hInst;
|
||||||
nArgc = __argc; // 08.11.99 cg, new, no. of command line arguments
|
nArgc = __argc; // no. of command line arguments
|
||||||
ppArgv = (LPCTSTR*) __argv; // 08.11.99 cg, new, command line arguments
|
ppArgv = (LPCTSTR*) __argv; // command line arguments
|
||||||
|
|
||||||
wc.style = CS_BYTEALIGNCLIENT;
|
wc.style = CS_BYTEALIGNCLIENT;
|
||||||
wc.lpfnWndProc = (WNDPROC)MainWndProc;
|
wc.lpfnWndProc = (WNDPROC)MainWndProc;
|
||||||
|
@ -1379,7 +1402,6 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create window
|
// Create window
|
||||||
|
|
||||||
rectWindow.left = 0;
|
rectWindow.left = 0;
|
||||||
rectWindow.top = 0;
|
rectWindow.top = 0;
|
||||||
rectWindow.right = 256;
|
rectWindow.right = 256;
|
||||||
|
@ -1402,11 +1424,9 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
|
||||||
|
|
||||||
ShowWindow(hWnd, nCmdShow);
|
ShowWindow(hWnd, nCmdShow);
|
||||||
|
|
||||||
// 01.12.99 cg, removed, useless and quit with resources open
|
|
||||||
// if (FlushMessages(&msg)) return msg.wParam;
|
|
||||||
|
|
||||||
// initialization
|
// initialization
|
||||||
QueryPerformanceFrequency(&lFreq); // init high resolution counter
|
QueryPerformanceFrequency(&lFreq); // init high resolution counter
|
||||||
|
QueryPerformanceCounter(&lAppStart);
|
||||||
|
|
||||||
GetCurrentDirectory(sizeof(szCurrentDirectory), szCurrentDirectory);
|
GetCurrentDirectory(sizeof(szCurrentDirectory), szCurrentDirectory);
|
||||||
|
|
||||||
|
@ -1419,20 +1439,25 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
|
||||||
if (hEventShutdn == NULL)
|
if (hEventShutdn == NULL)
|
||||||
{
|
{
|
||||||
AbortMessage("Event creation failed.");
|
AbortMessage("Event creation failed.");
|
||||||
DestroyWindow(hWnd); // 02.12.99 cg, bugfix, close DC
|
DestroyWindow(hWnd);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nState = 1; // thread starts in an invalid state
|
nState = 0; // init state must be <> nNextState
|
||||||
nNextState = 1;
|
nNextState = 1; // go into invalid state
|
||||||
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, NULL, 0, &lThreadId);
|
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, NULL, CREATE_SUSPENDED, &lThreadId);
|
||||||
if (hThread == NULL)
|
if (hThread == NULL)
|
||||||
{
|
{
|
||||||
CloseHandle(hEventShutdn); // close event handle
|
CloseHandle(hEventShutdn); // close event handle
|
||||||
AbortMessage("Thread creation failed.");
|
AbortMessage("Thread creation failed.");
|
||||||
DestroyWindow(hWnd); // 01.12.99 cg, bugfix, close DC
|
DestroyWindow(hWnd);
|
||||||
return FALSE;
|
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
|
// initialize DDE server
|
||||||
if (DdeInitialize(&idDdeInst,(PFNCALLBACK) &DdeCallback,
|
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_FAIL_EXECUTES | CBF_FAIL_ADVISES |
|
||||||
CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS,0))
|
CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS,0))
|
||||||
{
|
{
|
||||||
TerminateThread(hThread, 0); // 01.12.99 cg, bugfix, kill emulation thread
|
TerminateThread(hThread, 0); // kill emulation thread
|
||||||
CloseHandle(hEventShutdn); // 01.12.99 cg, bugfix, close event handle
|
CloseHandle(hEventShutdn); // close event handle
|
||||||
AbortMessage("Could not initialize server!");
|
AbortMessage("Could not initialize server!");
|
||||||
DestroyWindow(hWnd); // 01.12.99 cg, bugfix, close DC
|
DestroyWindow(hWnd);
|
||||||
return FALSE;
|
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
|
if (nArgc >= 2) // use decoded parameter line
|
||||||
{
|
{
|
||||||
CHAR szTemp[256] = "Loading ";
|
CHAR szTemp[256] = "Loading ";
|
||||||
strcat(szTemp, ppArgv[1]);
|
strcat(szTemp, ppArgv[1]);
|
||||||
SetWindowTitle(szTemp);
|
SetWindowTitle(szTemp);
|
||||||
// 01.12.99 cg, removed, useless and quit with resources open
|
|
||||||
// if (FlushMessages(&msg)) return msg.wParam;
|
|
||||||
if (OpenDocument(ppArgv[1]))
|
if (OpenDocument(ppArgv[1]))
|
||||||
goto start;
|
goto start;
|
||||||
}
|
}
|
||||||
// 08.11.99 cg, end of replacement
|
|
||||||
|
|
||||||
// 11.12.99 cg, changed, call function
|
|
||||||
ReadLastDocument(szBufferFilename, sizeof(szBufferFilename));
|
ReadLastDocument(szBufferFilename, sizeof(szBufferFilename));
|
||||||
if (szBufferFilename[0])
|
if (szBufferFilename[0])
|
||||||
{
|
{
|
||||||
CHAR szTemp[256] = "Loading ";
|
CHAR szTemp[256] = "Loading ";
|
||||||
strcat(szTemp, szBufferFilename);
|
strcat(szTemp, szBufferFilename);
|
||||||
SetWindowTitle(szTemp);
|
SetWindowTitle(szTemp);
|
||||||
// 01.12.99 cg, removed, useless and quit with resources open
|
|
||||||
// if (FlushMessages(&msg)) return msg.wParam;
|
|
||||||
if (OpenDocument(szBufferFilename))
|
if (OpenDocument(szBufferFilename))
|
||||||
goto start;
|
goto start;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetWindowTitle("New Document");
|
SetWindowTitle("New Document");
|
||||||
// 01.12.99 cg, removed, useless and quit with resources open
|
|
||||||
// if (FlushMessages(&msg)) return msg.wParam;
|
|
||||||
if (NewDocument())
|
if (NewDocument())
|
||||||
{
|
{
|
||||||
SetWindowTitle("Untitled");
|
SetWindowTitle("Untitled");
|
||||||
|
@ -1485,13 +1504,6 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
|
||||||
ResetDocument();
|
ResetDocument();
|
||||||
|
|
||||||
start:
|
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
|
// init clipboard format and name service
|
||||||
uCF_HpObj = RegisterClipboardFormat(CF_HPOBJ);
|
uCF_HpObj = RegisterClipboardFormat(CF_HPOBJ);
|
||||||
hszService = DdeCreateStringHandle(idDdeInst,szAppName,0);
|
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
|
// clean up DDE server
|
||||||
DdeNameService(idDdeInst, hszService, NULL, DNS_UNREGISTER);
|
DdeNameService(idDdeInst, hszService, NULL, DNS_UNREGISTER);
|
||||||
|
@ -1517,14 +1529,7 @@ start:
|
||||||
DdeFreeStringHandle(idDdeInst, hszTopic);
|
DdeFreeStringHandle(idDdeInst, hszTopic);
|
||||||
DdeUninitialize(idDdeInst);
|
DdeUninitialize(idDdeInst);
|
||||||
|
|
||||||
DeleteCriticalSection(&csGDILock);
|
WriteSettings(); // save emulation settings
|
||||||
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()
|
|
||||||
|
|
||||||
CloseHandle(hEventShutdn); // close event handle
|
CloseHandle(hEventShutdn); // close event handle
|
||||||
_ASSERT(nState == 2); // emulation thread down?
|
_ASSERT(nState == 2); // emulation thread down?
|
||||||
|
|
|
@ -112,13 +112,6 @@ SOURCE=.\Emu48.c
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\Emu48.rc
|
SOURCE=.\Emu48.rc
|
||||||
|
|
||||||
!IF "$(CFG)" == "Emu48 - Win32 Release"
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "Emu48 - Win32 Debug"
|
|
||||||
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
@ -138,6 +131,10 @@ SOURCE=.\files.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\i28f160.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\keyboard.c
|
SOURCE=.\keyboard.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
@ -191,6 +188,10 @@ SOURCE=.\Emu48.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\i28f160.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\io.h
|
SOURCE=.\io.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
// cards status
|
// cards status
|
||||||
#define PORT1_PRESENT ((cCurrentRomType=='S')?0x1:0x2)
|
#define PORT1_PRESENT ((cCurrentRomType=='S')?P1C:P2C)
|
||||||
#define PORT1_WRITE ((cCurrentRomType=='S')?0x4:0x8)
|
#define PORT1_WRITE ((cCurrentRomType=='S')?P1W:P2W)
|
||||||
#define PORT2_PRESENT ((cCurrentRomType=='S')?0x2:0x1)
|
#define PORT2_PRESENT ((cCurrentRomType=='S')?P2C:P1C)
|
||||||
#define PORT2_WRITE ((cCurrentRomType=='S')?0x8:0x4)
|
#define PORT2_WRITE ((cCurrentRomType=='S')?P2W:P1W)
|
||||||
|
|
||||||
#define BINARYHEADER48 "HPHP48-W"
|
#define BINARYHEADER48 "HPHP48-W"
|
||||||
#define BINARYHEADER49 "HPHP49-W"
|
#define BINARYHEADER49 "HPHP49-W"
|
||||||
|
@ -56,28 +56,29 @@ extern CRITICAL_SECTION csKeyLock;
|
||||||
extern CRITICAL_SECTION csIOLock;
|
extern CRITICAL_SECTION csIOLock;
|
||||||
extern CRITICAL_SECTION csT1Lock;
|
extern CRITICAL_SECTION csT1Lock;
|
||||||
extern CRITICAL_SECTION csT2Lock;
|
extern CRITICAL_SECTION csT2Lock;
|
||||||
extern CRITICAL_SECTION csRecvLock; // 24.10.99 cg, critical section for receive byte
|
extern CRITICAL_SECTION csRecvLock;
|
||||||
extern INT nArgc; // 08.11.99 cg, no. of command line arguments
|
extern INT nArgc;
|
||||||
extern LPCTSTR *ppArgv; // 08.11.99 cg, command line arguments
|
extern LPCTSTR *ppArgv;
|
||||||
extern LARGE_INTEGER lFreq;
|
extern LARGE_INTEGER lFreq;
|
||||||
|
extern LARGE_INTEGER lAppStart;
|
||||||
extern DWORD idDdeInst;
|
extern DWORD idDdeInst;
|
||||||
extern UINT uCF_HpObj;
|
extern UINT uCF_HpObj;
|
||||||
extern HINSTANCE hApp;
|
extern HINSTANCE hApp;
|
||||||
extern HWND hWnd;
|
extern HWND hWnd;
|
||||||
extern HDC hWindowDC;
|
extern HDC hWindowDC;
|
||||||
extern BOOL bPort2IsShared;
|
extern BOOL bPort2IsShared;
|
||||||
extern BOOL bAutoSave; // 11.12.99 cg, add declaration
|
extern BOOL bAutoSave;
|
||||||
extern BOOL bAutoSaveOnExit; // 11.12.99 cg, add declaration
|
extern BOOL bAutoSaveOnExit;
|
||||||
extern BOOL bAlwaysDisplayLog;
|
extern BOOL bAlwaysDisplayLog;
|
||||||
// extern UINT uTimer1Period; // 11.12.99 cg, removed old definition
|
extern HANDLE hThread;
|
||||||
extern HANDLE hThread; // 11.12.99 cg, add declaration
|
extern DWORD lThreadId;
|
||||||
extern DWORD lThreadId; // 11.12.99 cg, add declaration
|
|
||||||
extern VOID SetWindowTitle(LPSTR szString);
|
extern VOID SetWindowTitle(LPSTR szString);
|
||||||
|
extern VOID CopyItemsToClipboard(HWND hWnd);
|
||||||
extern VOID UpdateWindowStatus(VOID);
|
extern VOID UpdateWindowStatus(VOID);
|
||||||
|
|
||||||
// Settings.c
|
// Settings.c
|
||||||
extern VOID ReadSettings(VOID); // 11.12.99 cg, moved from Emu48.c
|
extern VOID ReadSettings(VOID);
|
||||||
extern VOID WriteSettings(VOID); // 11.12.99 cg, moved from Emu48.c
|
extern VOID WriteSettings(VOID);
|
||||||
extern VOID ReadLastDocument(LPTSTR szFileName, DWORD nSize);
|
extern VOID ReadLastDocument(LPTSTR szFileName, DWORD nSize);
|
||||||
extern VOID WriteLastDocument(LPCTSTR szFilename);
|
extern VOID WriteLastDocument(LPCTSTR szFilename);
|
||||||
|
|
||||||
|
@ -110,7 +111,7 @@ extern VOID ResizeWindow(VOID);
|
||||||
extern BOOL bInterrupt;
|
extern BOOL bInterrupt;
|
||||||
extern UINT nState;
|
extern UINT nState;
|
||||||
extern UINT nNextState;
|
extern UINT nNextState;
|
||||||
extern BOOL bRealSpeed; // 11.12.99 cg, new, real speed flag
|
extern BOOL bRealSpeed;
|
||||||
extern BOOL bKeySlow;
|
extern BOOL bKeySlow;
|
||||||
extern CHIPSET Chipset;
|
extern CHIPSET Chipset;
|
||||||
extern char szSerialWire[16];
|
extern char szSerialWire[16];
|
||||||
|
@ -141,6 +142,7 @@ extern char szPort2Filename[260];
|
||||||
extern LPBYTE pbyRom;
|
extern LPBYTE pbyRom;
|
||||||
extern DWORD dwRomSize;
|
extern DWORD dwRomSize;
|
||||||
extern char cCurrentRomType;
|
extern char cCurrentRomType;
|
||||||
|
extern BOOL bRomWriteable;
|
||||||
extern LPBYTE pbyPort2;
|
extern LPBYTE pbyPort2;
|
||||||
extern BOOL bPort2Writeable;
|
extern BOOL bPort2Writeable;
|
||||||
extern BOOL bPort2IsShared;
|
extern BOOL bPort2IsShared;
|
||||||
|
@ -152,6 +154,7 @@ extern BOOL MapRom(LPCSTR szFilename);
|
||||||
extern VOID UnmapRom(VOID);
|
extern VOID UnmapRom(VOID);
|
||||||
extern BOOL MapPort2(LPCSTR szFilename);
|
extern BOOL MapPort2(LPCSTR szFilename);
|
||||||
extern VOID UnmapPort2(VOID);
|
extern VOID UnmapPort2(VOID);
|
||||||
|
extern VOID UpdatePatches(BOOL bPatch);
|
||||||
extern BOOL PatchRom(LPCSTR szFilename);
|
extern BOOL PatchRom(LPCSTR szFilename);
|
||||||
extern VOID ResetDocument(VOID);
|
extern VOID ResetDocument(VOID);
|
||||||
extern BOOL NewDocument(VOID);
|
extern BOOL NewDocument(VOID);
|
||||||
|
@ -181,6 +184,7 @@ extern VOID SetT1(BYTE byValue);
|
||||||
// MOps.c
|
// MOps.c
|
||||||
extern BOOL ioc_acc;
|
extern BOOL ioc_acc;
|
||||||
extern BOOL ir_ctrl_acc;
|
extern BOOL ir_ctrl_acc;
|
||||||
|
extern BOOL bFlashRomArray;
|
||||||
extern BYTE disp;
|
extern BYTE disp;
|
||||||
extern LPBYTE RMap[256];
|
extern LPBYTE RMap[256];
|
||||||
extern LPBYTE WMap[256];
|
extern LPBYTE WMap[256];
|
||||||
|
@ -190,7 +194,7 @@ extern VOID Config(VOID);
|
||||||
extern VOID Uncnfg(VOID);
|
extern VOID Uncnfg(VOID);
|
||||||
extern VOID Reset(VOID);
|
extern VOID Reset(VOID);
|
||||||
extern VOID C_Eq_Id(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 BYTE GetLineCounter(VOID);
|
||||||
extern VOID Npeek(BYTE *a, DWORD d, UINT s);
|
extern VOID Npeek(BYTE *a, DWORD d, UINT s);
|
||||||
extern VOID Nread(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 CommOpen(LPSTR strWirePort,LPSTR strIrPort);
|
||||||
extern VOID CommClose(VOID);
|
extern VOID CommClose(VOID);
|
||||||
extern VOID CommSetBaud(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 CommTransmit(VOID);
|
||||||
extern VOID CommReceive(VOID);
|
extern VOID CommReceive(VOID);
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,9 @@ BEGIN
|
||||||
IDD_BREAKEDIT, DIALOG
|
IDD_BREAKEDIT, DIALOG
|
||||||
BEGIN
|
BEGIN
|
||||||
LEFTMARGIN, 5
|
LEFTMARGIN, 5
|
||||||
RIGHTMARGIN, 105
|
RIGHTMARGIN, 106
|
||||||
TOPMARGIN, 5
|
TOPMARGIN, 5
|
||||||
BOTTOMMARGIN, 97
|
BOTTOMMARGIN, 95
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_ABOUT, DIALOG
|
IDD_ABOUT, DIALOG
|
||||||
|
@ -50,7 +50,7 @@ BEGIN
|
||||||
LEFTMARGIN, 7
|
LEFTMARGIN, 7
|
||||||
RIGHTMARGIN, 160
|
RIGHTMARGIN, 160
|
||||||
TOPMARGIN, 4
|
TOPMARGIN, 4
|
||||||
BOTTOMMARGIN, 171
|
BOTTOMMARGIN, 202
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_CHOOSEKML, DIALOG
|
IDD_CHOOSEKML, DIALOG
|
||||||
|
@ -80,9 +80,9 @@ BEGIN
|
||||||
IDD_DEBUG, DIALOG
|
IDD_DEBUG, DIALOG
|
||||||
BEGIN
|
BEGIN
|
||||||
LEFTMARGIN, 5
|
LEFTMARGIN, 5
|
||||||
RIGHTMARGIN, 273
|
RIGHTMARGIN, 274
|
||||||
TOPMARGIN, 5
|
TOPMARGIN, 2
|
||||||
BOTTOMMARGIN, 212
|
BOTTOMMARGIN, 252
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_NEWVALUE, DIALOG
|
IDD_NEWVALUE, DIALOG
|
||||||
|
@ -100,6 +100,22 @@ BEGIN
|
||||||
TOPMARGIN, 7
|
TOPMARGIN, 7
|
||||||
BOTTOMMARGIN, 43
|
BOTTOMMARGIN, 43
|
||||||
END
|
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
|
END
|
||||||
#endif // APSTUDIO_INVOKED
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
@ -109,17 +125,17 @@ END
|
||||||
// Dialog
|
// 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
|
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
CAPTION "Edit breakpoints"
|
CAPTION "Edit breakpoints"
|
||||||
FONT 8, "Courier New"
|
FONT 8, "Courier New"
|
||||||
BEGIN
|
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
|
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
|
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
||||||
PUSHBUTTON "&Add",IDC_BREAKEDIT_ADD,5,83,28,14
|
PUSHBUTTON "&Add",IDC_BREAKEDIT_ADD,5,81,28,14
|
||||||
PUSHBUTTON "&Delete",IDC_BREAKEDIT_DELETE,41,83,28,14
|
PUSHBUTTON "&Delete",IDC_BREAKEDIT_DELETE,41,81,28,14
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_ABOUT DIALOGEX 0, 0, 261, 160
|
IDD_ABOUT DIALOGEX 0, 0, 261, 160
|
||||||
|
@ -130,21 +146,18 @@ BEGIN
|
||||||
ICON IDI_EMU48,IDC_STATIC,7,6,20,20,SS_REALSIZEIMAGE,
|
ICON IDI_EMU48,IDC_STATIC,7,6,20,20,SS_REALSIZEIMAGE,
|
||||||
WS_EX_TRANSPARENT
|
WS_EX_TRANSPARENT
|
||||||
LTEXT "",IDC_VERSION,29,6,151,8,NOT WS_GROUP
|
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
|
IDC_STATIC,29,18,181,8
|
||||||
DEFPUSHBUTTON "OK",IDOK,215,12,39,14
|
DEFPUSHBUTTON "OK",IDOK,215,12,39,14
|
||||||
EDITTEXT IDC_LICENSE,7,33,247,112,ES_MULTILINE | ES_AUTOHSCROLL |
|
EDITTEXT IDC_LICENSE,7,33,247,112,ES_MULTILINE | ES_AUTOHSCROLL |
|
||||||
ES_READONLY
|
ES_READONLY
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_SETTINGS DIALOGEX 0, 0, 167, 178
|
IDD_SETTINGS DIALOGEX 0, 0, 167, 209
|
||||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
CAPTION "Settings"
|
CAPTION "Settings"
|
||||||
FONT 8, "MS Sans Serif", 0, 0, 0x1
|
FONT 8, "MS Sans Serif", 0, 0, 0x1
|
||||||
BEGIN
|
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",
|
CONTROL "Authentic Calculator Speed",IDC_REALSPEED,"Button",
|
||||||
BS_AUTOCHECKBOX | WS_TABSTOP,13,13,104,10
|
BS_AUTOCHECKBOX | WS_TABSTOP,13,13,104,10
|
||||||
CONTROL "Automatically Save Files",IDC_AUTOSAVE,"Button",
|
CONTROL "Automatically Save Files",IDC_AUTOSAVE,"Button",
|
||||||
|
@ -154,22 +167,30 @@ BEGIN
|
||||||
CONTROL "Always display KML Compilation Result",
|
CONTROL "Always display KML Compilation Result",
|
||||||
IDC_ALWAYSDISPLOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
|
IDC_ALWAYSDISPLOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||||
13,52,136,10
|
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 |
|
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",
|
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",
|
CONTROL "Port 2 is Shared",IDC_PORT2ISSHARED,"Button",
|
||||||
BS_AUTOCHECKBOX | WS_TABSTOP,13,92,65,10
|
BS_AUTOCHECKBOX | WS_TABSTOP,13,123,65,10
|
||||||
LTEXT "Port 2 File :",IDC_STATIC,13,105,37,8
|
LTEXT "Port 2 File :",IDC_STATIC,13,136,37,8
|
||||||
EDITTEXT IDC_PORT2,51,103,104,12,ES_AUTOHSCROLL
|
EDITTEXT IDC_PORT2,51,134,104,12,ES_AUTOHSCROLL
|
||||||
LTEXT "Wire:",IDC_STATIC,13,136,17,8
|
GROUPBOX "Memory Cards",IDC_STATIC,7,101,153,50
|
||||||
COMBOBOX IDC_WIRE,31,134,48,42,CBS_DROPDOWNLIST | WS_VSCROLL |
|
LTEXT "Wire:",IDC_STATIC,13,166,17,8
|
||||||
|
COMBOBOX IDC_WIRE,31,164,48,42,CBS_DROPDOWNLIST | WS_VSCROLL |
|
||||||
WS_TABSTOP,WS_EX_LEFTSCROLLBAR
|
WS_TABSTOP,WS_EX_LEFTSCROLLBAR
|
||||||
LTEXT "IR:",IDC_STATIC,89,136,9,8
|
LTEXT "IR:",IDC_STATIC,89,166,9,8
|
||||||
COMBOBOX IDC_IR,107,134,48,43,CBS_DROPDOWNLIST | WS_VSCROLL |
|
COMBOBOX IDC_IR,107,164,48,43,CBS_DROPDOWNLIST | WS_VSCROLL |
|
||||||
WS_TABSTOP
|
WS_TABSTOP
|
||||||
DEFPUSHBUTTON "&Ok",IDOK,9,157,50,14
|
GROUPBOX "Serial Ports",IDC_STATIC,7,154,153,27
|
||||||
PUSHBUTTON "&Cancel",IDCANCEL,107,157,50,14
|
DEFPUSHBUTTON "&Ok",IDOK,9,188,50,14
|
||||||
|
PUSHBUTTON "&Cancel",IDCANCEL,107,188,50,14
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_CHOOSEKML DIALOG DISCARDABLE 0, 0, 186, 66
|
IDD_CHOOSEKML DIALOG DISCARDABLE 0, 0, 186, 66
|
||||||
|
@ -215,90 +236,111 @@ BEGIN
|
||||||
PUSHBUTTON "&Next Address",IDC_DISASM_NEXT,99,144,47,14
|
PUSHBUTTON "&Next Address",IDC_DISASM_NEXT,99,144,47,14
|
||||||
PUSHBUTTON "&Copy Data",IDC_DISASM_COPY,150,144,47,14
|
PUSHBUTTON "&Copy Data",IDC_DISASM_COPY,150,144,47,14
|
||||||
PUSHBUTTON "Cancel",IDCANCEL,201,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 |
|
CONTROL "Map",IDC_DISASM_MAP,"Button",BS_AUTORADIOBUTTON |
|
||||||
WS_GROUP | WS_TABSTOP,14,16,28,10
|
WS_GROUP | WS_TABSTOP,14,16,37,10
|
||||||
CONTROL "ROM",IDC_DISASM_ROM,"Button",BS_AUTORADIOBUTTON,45,16,
|
CONTROL "ROM",IDC_DISASM_ROM,"Button",BS_AUTORADIOBUTTON,61,16,
|
||||||
28,10
|
37,10
|
||||||
CONTROL "RAM",IDC_DISASM_RAM,"Button",BS_AUTORADIOBUTTON,76,16,
|
CONTROL "RAM",IDC_DISASM_RAM,"Button",BS_AUTORADIOBUTTON,108,16,
|
||||||
28,10
|
37,10
|
||||||
CONTROL "Port 1",IDC_DISASM_PORT1,"Button",BS_AUTORADIOBUTTON,
|
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,
|
CONTROL "Port 2",IDC_DISASM_PORT2,"Button",BS_AUTORADIOBUTTON,
|
||||||
138,16,28,10
|
202,16,37,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
|
|
||||||
LISTBOX IDC_DISASM_WIN,7,37,241,100,NOT LBS_NOTIFY |
|
LISTBOX IDC_DISASM_WIN,7,37,241,100,NOT LBS_NOTIFY |
|
||||||
LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL |
|
LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL |
|
||||||
WS_TABSTOP,WS_EX_NOPARENTNOTIFY
|
WS_TABSTOP,WS_EX_NOPARENTNOTIFY
|
||||||
END
|
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
|
STYLE WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||||
CAPTION "Debugger"
|
CAPTION "Debugger"
|
||||||
MENU IDR_DEBUG
|
MENU IDR_DEBUG
|
||||||
FONT 8, "Courier New", 0, 0, 0x1
|
FONT 8, "Courier New", 0, 0, 0x1
|
||||||
BEGIN
|
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_OWNERDRAWFIXED | LBS_HASSTRINGS |
|
||||||
LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT |
|
LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT |
|
||||||
WS_TABSTOP
|
WS_TABSTOP
|
||||||
GROUPBOX "Code",IDC_STATIC_CODE,5,5,177,138
|
GROUPBOX "Code",IDC_STATIC_CODE,5,2,177,138
|
||||||
LTEXT "A= 0000000000000000",IDC_REG_A,192,15,77,8
|
LTEXT "A= 0000000000000000",IDC_REG_A,192,12,77,8
|
||||||
LTEXT "B= 0000000000000000",IDC_REG_B,192,22,77,8
|
LTEXT "B= 0000000000000000",IDC_REG_B,192,19,77,8
|
||||||
LTEXT "C= 0000000000000000",IDC_REG_C,192,29,77,8
|
LTEXT "C= 0000000000000000",IDC_REG_C,192,26,77,8
|
||||||
LTEXT "D= 0000000000000000",IDC_REG_D,192,36,77,8
|
LTEXT "D= 0000000000000000",IDC_REG_D,192,33,77,8
|
||||||
LTEXT "R0=0000000000000000",IDC_REG_R0,192,46,77,8
|
LTEXT "R0=0000000000000000",IDC_REG_R0,192,43,77,8
|
||||||
LTEXT "R1=0000000000000000",IDC_REG_R1,192,53,77,8
|
LTEXT "R1=0000000000000000",IDC_REG_R1,192,50,77,8
|
||||||
LTEXT "R2=0000000000000000",IDC_REG_R2,192,60,77,8
|
LTEXT "R2=0000000000000000",IDC_REG_R2,192,57,77,8
|
||||||
LTEXT "R3=0000000000000000",IDC_REG_R3,192,67,77,8
|
LTEXT "R3=0000000000000000",IDC_REG_R3,192,64,77,8
|
||||||
LTEXT "R4=0000000000000000",IDC_REG_R4,192,74,77,8
|
LTEXT "R4=0000000000000000",IDC_REG_R4,192,71,77,8
|
||||||
LTEXT "D0=00000",IDC_REG_D0,192,85,33,8
|
LTEXT "D0=00000",IDC_REG_D0,192,82,33,8
|
||||||
LTEXT "D1=00000",IDC_REG_D1,236,85,33,8
|
LTEXT "D1=00000",IDC_REG_D1,236,82,33,8
|
||||||
LTEXT "P=0",IDC_REG_P,192,96,13,8
|
LTEXT "P=0",IDC_REG_P,192,93,13,8
|
||||||
LTEXT "PC=00000",IDC_REG_PC,236,96,33,8
|
LTEXT "PC=00000",IDC_REG_PC,236,93,33,8
|
||||||
LTEXT "OUT=000",IDC_REG_OUT,192,107,29,8
|
LTEXT "OUT=000",IDC_REG_OUT,192,104,29,8
|
||||||
LTEXT "IN=0000",IDC_REG_IN,240,107,29,8
|
LTEXT "IN=0000",IDC_REG_IN,240,104,29,8
|
||||||
LTEXT "ST=0000",IDC_REG_ST,192,118,29,8
|
LTEXT "ST=0000",IDC_REG_ST,192,115,29,8
|
||||||
LTEXT "CY=0",IDC_REG_CY,224,118,17,8
|
LTEXT "CY=0",IDC_REG_CY,224,115,17,8
|
||||||
LTEXT "Mode=H",IDC_REG_MODE,244,118,25,8
|
LTEXT "Mode=H",IDC_REG_MODE,244,115,25,8
|
||||||
LTEXT "MP=0",IDC_REG_MP,192,128,17,8
|
LTEXT "MP=0",IDC_REG_MP,192,125,17,8
|
||||||
LTEXT "SR=0",IDC_REG_SR,212,128,17,8
|
LTEXT "SR=0",IDC_REG_SR,212,125,17,8
|
||||||
LTEXT "SB=0",IDC_REG_SB,232,128,17,8
|
LTEXT "SB=0",IDC_REG_SB,232,125,17,8
|
||||||
LTEXT "XM=0",IDC_REG_XM,252,128,17,8
|
LTEXT "XM=0",IDC_REG_XM,252,125,17,8
|
||||||
GROUPBOX "Registers",IDC_STATIC_REGISTERS,186,5,87,138
|
GROUPBOX "Registers",IDC_STATIC_REGISTERS,187,2,87,138
|
||||||
CONTROL "",IDC_DEBUG_MEM,"Static",SS_WHITERECT | WS_GROUP,11,154,
|
CONTROL "",IDC_DEBUG_MEM,"Static",SS_WHITERECT | WS_GROUP,11,151,
|
||||||
165,52,WS_EX_CLIENTEDGE
|
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
|
LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_DISABLED | NOT
|
||||||
WS_BORDER
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_DISABLED | NOT
|
||||||
WS_BORDER
|
WS_BORDER
|
||||||
GROUPBOX "Memory",IDC_STATIC_MEMORY,5,144,177,68
|
GROUPBOX "Memory",IDC_STATIC_MEMORY,5,141,177,68
|
||||||
LISTBOX IDC_DEBUG_STACK,192,154,75,52,NOT LBS_NOTIFY |
|
LISTBOX IDC_DEBUG_STACK,192,151,76,52,NOT LBS_NOTIFY |
|
||||||
LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT |
|
LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT |
|
||||||
WS_VSCROLL | WS_TABSTOP
|
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
|
END
|
||||||
|
|
||||||
IDD_NEWVALUE DIALOG DISCARDABLE 0, 0, 175, 50
|
IDD_NEWVALUE DIALOG DISCARDABLE 0, 0, 175, 50
|
||||||
|
@ -323,6 +365,40 @@ BEGIN
|
||||||
PUSHBUTTON "Cancel",IDCANCEL,92,29,50,14
|
PUSHBUTTON "Cancel",IDCANCEL,92,29,50,14
|
||||||
END
|
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
|
#ifndef _MAC
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -331,8 +407,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,1,5,0
|
FILEVERSION 1,2,0,0
|
||||||
PRODUCTVERSION 1,1,5,0
|
PRODUCTVERSION 1,2,0,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x21L
|
FILEFLAGS 0x21L
|
||||||
|
@ -347,15 +423,15 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
BLOCK "00000000"
|
BLOCK "00000000"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Sebastien Carlier\0"
|
VALUE "CompanyName", "Sebastien Carlier & Christoph Gießelink\0"
|
||||||
VALUE "FileDescription", "HP38/48/49 Emulator\0"
|
VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0"
|
||||||
VALUE "FileVersion", "1, 1, 5, 0\0"
|
VALUE "FileVersion", "1, 2, 0, 0\0"
|
||||||
VALUE "InternalName", "Emu48\0"
|
VALUE "InternalName", "Emu48\0"
|
||||||
VALUE "LegalCopyright", "Copyright © 1999\0"
|
VALUE "LegalCopyright", "Copyright © 2000\0"
|
||||||
VALUE "OriginalFilename", "Emu48.exe\0"
|
VALUE "OriginalFilename", "Emu48.exe\0"
|
||||||
VALUE "ProductName", "Emu48\0"
|
VALUE "ProductName", "Emu48\0"
|
||||||
VALUE "ProductVersion", "1, 1, 5, 0\0"
|
VALUE "ProductVersion", "1, 2, 0, 0\0"
|
||||||
VALUE "SpecialBuild", "Service Pack 15, Christoph Gießelink\0"
|
VALUE "SpecialBuild", "Service Pack 20, Christoph Gießelink\0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
@ -445,6 +521,16 @@ BEGIN
|
||||||
MENUITEM "&Clear all breakpoints", ID_BREAKPOINTS_CLEARALL
|
MENUITEM "&Clear all breakpoints", ID_BREAKPOINTS_CLEARALL
|
||||||
MENUITEM SEPARATOR
|
MENUITEM SEPARATOR
|
||||||
MENUITEM "&NOP3 code breakpoints", ID_BREAKPOINTS_NOP3
|
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
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Emu48.h"
|
#include "Emu48.h"
|
||||||
#include "Opcodes.h"
|
#include "Opcodes.h"
|
||||||
#include "io.h" // 24.10.99 cg, renamed from Serial.h
|
#include "io.h"
|
||||||
#include "debugger.h"
|
#include "debugger.h"
|
||||||
|
|
||||||
#define SAMPLE 16384 // speed adjust sample frequency
|
#define SAMPLE 16384 // speed adjust sample frequency
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
BOOL bInterrupt = FALSE;
|
BOOL bInterrupt = FALSE;
|
||||||
UINT nState = 1;
|
UINT nState = 1;
|
||||||
UINT nNextState = 0;
|
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
|
BOOL bKeySlow = FALSE; // slow down for key emulation
|
||||||
CHIPSET Chipset;
|
CHIPSET Chipset;
|
||||||
|
|
||||||
|
@ -28,7 +28,10 @@ DWORD dwSXCycles = 82; // SX cpu cycles in interval
|
||||||
DWORD dwGXCycles = 123; // GX cpu cycles in interval
|
DWORD dwGXCycles = 123; // GX cpu cycles in interval
|
||||||
|
|
||||||
static BOOL bCommInit = FALSE; // COM port not open
|
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 dwOldCyc; // cpu cycles at last event
|
||||||
static DWORD dwSpeedRef; // timer value at last event
|
static DWORD dwSpeedRef; // timer value at last event
|
||||||
|
@ -36,6 +39,151 @@ static DWORD dwTickRef; // sample timer ticks
|
||||||
|
|
||||||
#include "Ops.h"
|
#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)
|
static __inline VOID CheckDisp(BOOL bSync)
|
||||||
{
|
{
|
||||||
if (disp == 0) return; // no display update need
|
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
|
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
|
// cycles elapsed for next check
|
||||||
// 22.11.99 cg, changed, DWORD casting of Chipset.cycles
|
if ((dwCycles = (DWORD) (Chipset.cycles & 0xFFFFFFFF)-dwOldCyc) >= (DWORD) T2CYCLES)
|
||||||
if ((DWORD) (Chipset.cycles & 0xFFFFFFFF)-dwOldCyc >= (DWORD) T2CYCLES)
|
|
||||||
{
|
{
|
||||||
LARGE_INTEGER lAct;
|
LARGE_INTEGER lAct;
|
||||||
do
|
do
|
||||||
|
@ -95,10 +244,22 @@ static __inline VOID AdjustSpeed(VOID) // adjust emulation speed
|
||||||
BOOL bErr = QueryPerformanceCounter(&lAct);
|
BOOL bErr = QueryPerformanceCounter(&lAct);
|
||||||
_ASSERT(bErr); // no high-resolution performance counter
|
_ASSERT(bErr); // no high-resolution performance counter
|
||||||
}
|
}
|
||||||
while(lAct.LowPart-dwSpeedRef <= dwTickRef);
|
while((dwTicks = lAct.LowPart-dwSpeedRef) <= dwTickRef);
|
||||||
|
|
||||||
dwOldCyc += T2CYCLES; // adjust cycles reference
|
// workaround for QueryPerformanceCounter() in Win2k,
|
||||||
dwSpeedRef += dwTickRef; // adjust reference time
|
// 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;
|
return;
|
||||||
|
@ -109,7 +270,7 @@ VOID AdjKeySpeed(VOID) // slow down key repeat
|
||||||
WORD i;
|
WORD i;
|
||||||
BOOL bKey;
|
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
|
bKey = FALSE; // search for a pressed key
|
||||||
for (i = 0;i < sizeof(Chipset.Keyboard_Row) / sizeof(Chipset.Keyboard_Row[0]) && !bKey;++i)
|
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
|
LARGE_INTEGER lTime; // sample timer ticks
|
||||||
// save reference cycles
|
// save reference cycles
|
||||||
// 22.11.99 cg, changed, DWORD casting
|
|
||||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||||
QueryPerformanceCounter(&lTime); // get timer ticks
|
QueryPerformanceCounter(&lTime); // get timer ticks
|
||||||
dwSpeedRef = lTime.LowPart; // save reference time
|
dwSpeedRef = lTime.LowPart; // save reference time
|
||||||
|
@ -134,17 +294,15 @@ VOID SetSpeed(BOOL bAdjust) // set emulation speed
|
||||||
{
|
{
|
||||||
LARGE_INTEGER lTime; // sample timer ticks
|
LARGE_INTEGER lTime; // sample timer ticks
|
||||||
// save reference cycles
|
// save reference cycles
|
||||||
// 22.11.99 cg, changed, DWORD casting
|
|
||||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||||
QueryPerformanceCounter(&lTime); // get timer ticks
|
QueryPerformanceCounter(&lTime); // get timer ticks
|
||||||
dwSpeedRef = lTime.LowPart; // save reference time
|
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
|
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)
|
if (Chipset.intk && (DWORD) (Chipset.cycles & 0xFFFFFFFFF) - Chipset.dwKdnCycles > (DWORD) T2CYCLES * 16)
|
||||||
IOBit(0x19,8,Chipset.in != 0);
|
IOBit(0x19,8,Chipset.in != 0);
|
||||||
}
|
}
|
||||||
|
@ -214,7 +372,8 @@ UINT SwitchToState(UINT nNewState)
|
||||||
{
|
{
|
||||||
case 0: // -> Run
|
case 0: // -> Run
|
||||||
nNextState = 0;
|
nNextState = 0;
|
||||||
bInterrupt = FALSE;
|
// don't enter opcode loop on interrupt request
|
||||||
|
bInterrupt = Chipset.Shutdn || Chipset.SoftInt;
|
||||||
SetEvent(hEventShutdn);
|
SetEvent(hEventShutdn);
|
||||||
while (nState!=nNextState) Sleep(0);
|
while (nState!=nNextState) Sleep(0);
|
||||||
UpdateWindowStatus();
|
UpdateWindowStatus();
|
||||||
|
@ -297,13 +456,26 @@ loop:
|
||||||
if (bPort2Writeable) // is card writeable
|
if (bPort2Writeable) // is card writeable
|
||||||
Chipset.cards_status |= PORT2_WRITE;
|
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
|
RomSwitch(Chipset.Bank_FF); // select HP49G ROM bank and update memory mapping
|
||||||
UpdateDisplayPointers();
|
UpdateDisplayPointers();
|
||||||
UpdateMainDisplay();
|
UpdateMainDisplay();
|
||||||
UpdateMenuDisplay();
|
UpdateMenuDisplay();
|
||||||
UpdateAnnunciators();
|
UpdateAnnunciators();
|
||||||
// init speed reference
|
// init speed reference
|
||||||
// 22.11.99 cg, changed, DWORD casting
|
|
||||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||||
QueryPerformanceCounter(&lDummyInt);
|
QueryPerformanceCounter(&lDummyInt);
|
||||||
dwSpeedRef = lDummyInt.LowPart;
|
dwSpeedRef = lDummyInt.LowPart;
|
||||||
|
@ -313,65 +485,9 @@ loop:
|
||||||
PCHANGED;
|
PCHANGED;
|
||||||
while (!bInterrupt)
|
while (!bInterrupt)
|
||||||
{
|
{
|
||||||
LPBYTE I = FASTPTR(Chipset.pc);
|
if (bDbgEnable) Debugger(); // debugger active
|
||||||
|
|
||||||
if (bDbgEnable) // debugger active
|
EvalOpcode(FASTPTR(Chipset.pc)); // execute opcode
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
CheckDisp(!Chipset.Shutdn); // check for display update
|
CheckDisp(!Chipset.Shutdn); // check for display update
|
||||||
CheckSerial(); // serial support
|
CheckSerial(); // serial support
|
||||||
|
@ -382,14 +498,16 @@ loop:
|
||||||
// enter SHUTDN handler only in RUN mode
|
// enter SHUTDN handler only in RUN mode
|
||||||
if (Chipset.Shutdn && !(nDbgState == DBG_STEPINTO || nDbgState == DBG_STEPOVER))
|
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
|
if (Chipset.bShutdnWake) // waked up by timer, keyboard or serial
|
||||||
{
|
{
|
||||||
Chipset.bShutdnWake = FALSE;
|
Chipset.bShutdnWake = FALSE;
|
||||||
Chipset.Shutdn = FALSE;
|
Chipset.Shutdn = FALSE;
|
||||||
// init speed reference
|
// init speed reference
|
||||||
// 22.11.99 cg, changed, DWORD casting
|
|
||||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||||
QueryPerformanceCounter(&lDummyInt);
|
QueryPerformanceCounter(&lDummyInt);
|
||||||
dwSpeedRef = lDummyInt.LowPart;
|
dwSpeedRef = lDummyInt.LowPart;
|
||||||
|
@ -405,12 +523,11 @@ loop:
|
||||||
Chipset.pc = 0xf;
|
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
|
while (nNextState == 3) // go into sleep state
|
||||||
{
|
{
|
||||||
nState = 3; // in sleep state
|
nState = 3; // in sleep state
|
||||||
|
|
|
@ -13,15 +13,18 @@
|
||||||
//#F0E4F #706D2 #80850 #80F0F =SFLAG53_56
|
//#F0E4F #706D2 #80850 #80F0F =SFLAG53_56
|
||||||
|
|
||||||
// memory address for flags -53 to -56
|
// memory address for flags -53 to -56
|
||||||
#define SFLAG53_56 ( (cCurrentRomType=='A') \
|
#define SFLAG53_56 ( (cCurrentRomType=='6') \
|
||||||
? 0xF0E4F \
|
? 0xE0E4F \
|
||||||
: ( (cCurrentRomType!='X') \
|
: ( (cCurrentRomType=='A') \
|
||||||
? ( (cCurrentRomType=='S') \
|
? 0xF0E4F \
|
||||||
? 0x706D2 \
|
: ( (cCurrentRomType!='X') \
|
||||||
: 0x80850 \
|
? ( (cCurrentRomType=='S') \
|
||||||
) \
|
? 0x706D2 \
|
||||||
: 0x80F0F \
|
: 0x80850 \
|
||||||
) \
|
) \
|
||||||
|
: 0x80F0F \
|
||||||
|
) \
|
||||||
|
) \
|
||||||
)
|
)
|
||||||
|
|
||||||
static __inline VOID Return(CHIPSET* w)
|
static __inline VOID Return(CHIPSET* w)
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
*/
|
*/
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Emu48.h"
|
#include "Emu48.h"
|
||||||
|
#include "io.h" // I/O register definitions
|
||||||
#include "kml.h"
|
#include "kml.h"
|
||||||
|
#include "i28f160.h" // flash support
|
||||||
|
|
||||||
char szEmu48Directory[260];
|
char szEmu48Directory[260];
|
||||||
char szCurrentDirectory[260];
|
char szCurrentDirectory[260];
|
||||||
|
@ -24,6 +26,7 @@ static HANDLE hRomFile = NULL;
|
||||||
static HANDLE hRomMap = NULL;
|
static HANDLE hRomMap = NULL;
|
||||||
DWORD dwRomSize = 0;
|
DWORD dwRomSize = 0;
|
||||||
char cCurrentRomType = 0;
|
char cCurrentRomType = 0;
|
||||||
|
BOOL bRomWriteable = FALSE; // flag if ROM writeable
|
||||||
|
|
||||||
static HANDLE hPort2File = NULL;
|
static HANDLE hPort2File = NULL;
|
||||||
static HANDLE hPort2Map = NULL;
|
static HANDLE hPort2Map = NULL;
|
||||||
|
@ -33,7 +36,7 @@ BOOL bPort2IsShared = FALSE;
|
||||||
DWORD dwPort2Size = 0; // size of mapped port2
|
DWORD dwPort2Size = 0; // size of mapped port2
|
||||||
DWORD dwPort2Mask = 0;
|
DWORD dwPort2Mask = 0;
|
||||||
|
|
||||||
// 01.12.99 cg, new, HP38G signature
|
// document signatures
|
||||||
static BYTE pbySignatureA[16] = "Emu38 Document\xFE";
|
static BYTE pbySignatureA[16] = "Emu38 Document\xFE";
|
||||||
static BYTE pbySignatureE[16] = "Emu48 Document\xFE";
|
static BYTE pbySignatureE[16] = "Emu48 Document\xFE";
|
||||||
static BYTE pbySignatureW[16] = "Win48 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
|
//# Patch
|
||||||
//#
|
//#
|
||||||
//################
|
//################
|
||||||
|
|
||||||
static BYTE Asc2Nib(char c)
|
static __inline BYTE Asc2Nib(char c)
|
||||||
{
|
{
|
||||||
if (c<'0') return 0;
|
if (c<'0') return 0;
|
||||||
if (c<='9') return c-'0';
|
if (c<='9') return c-'0';
|
||||||
|
@ -327,6 +116,76 @@ static BYTE Asc2Nib(char c)
|
||||||
return 0;
|
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)
|
BOOL PatchRom(LPCSTR szFilename)
|
||||||
{
|
{
|
||||||
HANDLE hFile = NULL;
|
HANDLE hFile = NULL;
|
||||||
|
@ -393,7 +252,8 @@ BOOL PatchRom(LPCSTR szFilename)
|
||||||
while (lpBuf[nPos])
|
while (lpBuf[nPos])
|
||||||
{
|
{
|
||||||
if (isxdigit(lpBuf[nPos]) == FALSE) break;
|
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);
|
dwAddress = (dwAddress+1)&(dwRomSize-1);
|
||||||
nPos++;
|
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
|
//# Documents
|
||||||
|
@ -446,9 +566,9 @@ BOOL NewDocument(VOID)
|
||||||
if (!InitKML(szCurrentKml,FALSE)) goto restore;
|
if (!InitKML(szCurrentKml,FALSE)) goto restore;
|
||||||
Chipset.type = cCurrentRomType;
|
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.Port1Size = 0;
|
||||||
Chipset.Port2Size = 0;
|
Chipset.Port2Size = 0;
|
||||||
Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048);
|
Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048);
|
||||||
|
@ -471,7 +591,6 @@ BOOL NewDocument(VOID)
|
||||||
Chipset.cards_status = 0x5;
|
Chipset.cards_status = 0x5;
|
||||||
|
|
||||||
// use 2nd command line argument if defined
|
// use 2nd command line argument if defined
|
||||||
// 08.11.99 cg, changed, replaced __argc and __argv variable
|
|
||||||
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
||||||
}
|
}
|
||||||
if (Chipset.type == 'G') // HP48GX
|
if (Chipset.type == 'G') // HP48GX
|
||||||
|
@ -487,7 +606,6 @@ BOOL NewDocument(VOID)
|
||||||
Chipset.cards_status = 0xA;
|
Chipset.cards_status = 0xA;
|
||||||
|
|
||||||
// use 2nd command line argument if defined
|
// use 2nd command line argument if defined
|
||||||
// 08.11.99 cg, changed, replaced __argc and __argv variable
|
|
||||||
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
||||||
}
|
}
|
||||||
if (Chipset.type == 'X') // HP49G
|
if (Chipset.type == 'X') // HP49G
|
||||||
|
@ -507,6 +625,8 @@ BOOL NewDocument(VOID)
|
||||||
|
|
||||||
bPort2Writeable = TRUE;
|
bPort2Writeable = TRUE;
|
||||||
Chipset.cards_status = 0xF;
|
Chipset.cards_status = 0xF;
|
||||||
|
|
||||||
|
FlashInit(); // init flash structure
|
||||||
}
|
}
|
||||||
RomSwitch(0); // boot ROM view of HP49G and map memory
|
RomSwitch(0); // boot ROM view of HP49G and map memory
|
||||||
SaveBackup();
|
SaveBackup();
|
||||||
|
@ -515,16 +635,14 @@ restore:
|
||||||
RestoreBackup();
|
RestoreBackup();
|
||||||
ResetBackup();
|
ResetBackup();
|
||||||
|
|
||||||
// 01.12.99 cg, changed, added HP38G
|
// HP48SX/GX
|
||||||
if(Chipset.type != 'A' && Chipset.type != 'X')
|
if(Chipset.type != '6' && Chipset.type != 'A' && Chipset.type != 'X')
|
||||||
{
|
{
|
||||||
// use 2nd command line argument if defined
|
// use 2nd command line argument if defined
|
||||||
// 08.11.99 cg, changed, replaced __argc and __argv variable
|
|
||||||
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
||||||
}
|
}
|
||||||
if (pbyRom)
|
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);
|
SetWindowPos(hWnd,NULL,Chipset.nPosX,Chipset.nPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
|
||||||
Map(0x00,0xFF);
|
Map(0x00,0xFF);
|
||||||
}
|
}
|
||||||
|
@ -562,7 +680,6 @@ BOOL OpenDocument(LPCSTR szFilename)
|
||||||
switch (pbyFileSignature[0])
|
switch (pbyFileSignature[0])
|
||||||
{
|
{
|
||||||
case 'E':
|
case 'E':
|
||||||
// 01.12.99 cg, changed, added HP38 signature
|
|
||||||
pbySig = (pbyFileSignature[3] == '3')
|
pbySig = (pbyFileSignature[3] == '3')
|
||||||
? pbySignatureA
|
? pbySignatureA
|
||||||
: ((pbyFileSignature[4] == '8') ? pbySignatureE : pbySignatureV);
|
: ((pbyFileSignature[4] == '8') ? pbySignatureE : pbySignatureV);
|
||||||
|
@ -620,7 +737,6 @@ BOOL OpenDocument(LPCSTR szFilename)
|
||||||
Chipset.Port1 = NULL;
|
Chipset.Port1 = NULL;
|
||||||
Chipset.Port2 = 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);
|
SetWindowPos(hWnd,NULL,Chipset.nPosX,Chipset.nPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
|
||||||
|
|
||||||
if (szCurrentKml == NULL)
|
if (szCurrentKml == NULL)
|
||||||
|
@ -634,6 +750,8 @@ BOOL OpenDocument(LPCSTR szFilename)
|
||||||
goto restore;
|
goto restore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlashInit(); // init flash structure
|
||||||
|
|
||||||
if (Chipset.Port0Size)
|
if (Chipset.Port0Size)
|
||||||
{
|
{
|
||||||
Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048);
|
Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048);
|
||||||
|
@ -662,13 +780,17 @@ BOOL OpenDocument(LPCSTR szFilename)
|
||||||
|
|
||||||
if (cCurrentRomType!='X') // HP38G, HP48SX/GX
|
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]);
|
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
|
Chipset.SoftInt = TRUE; // set interrupt
|
||||||
bInterrupt = TRUE;
|
bInterrupt = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -695,10 +817,8 @@ BOOL OpenDocument(LPCSTR szFilename)
|
||||||
|
|
||||||
RomSwitch(Chipset.Bank_FF); // reload ROM view of HP49G and map memory
|
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();
|
CpuReset();
|
||||||
// 20.11.99 cg, end of fingerprint check
|
|
||||||
|
|
||||||
lstrcpy(szCurrentFilename, szFilename);
|
lstrcpy(szCurrentFilename, szFilename);
|
||||||
_ASSERT(hCurrentFile == NULL);
|
_ASSERT(hCurrentFile == NULL);
|
||||||
|
@ -715,11 +835,10 @@ restore:
|
||||||
RestoreBackup();
|
RestoreBackup();
|
||||||
ResetBackup();
|
ResetBackup();
|
||||||
|
|
||||||
// 01.12.99 cg, bugfix, add port2 only on HP48 calculators
|
// HP48SX/GX
|
||||||
if(cCurrentRomType!='A' && cCurrentRomType!='X')
|
if(cCurrentRomType!='6' && cCurrentRomType!='A' && cCurrentRomType!='X')
|
||||||
{
|
{
|
||||||
// use 2nd command line argument if defined
|
// use 2nd command line argument if defined
|
||||||
// 08.11.99 cg, changed, replaced __argc and __argv variable
|
|
||||||
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -741,8 +860,9 @@ BOOL SaveDocument(VOID)
|
||||||
|
|
||||||
SetFilePointer(hCurrentFile,0,0,FILE_BEGIN);
|
SetFilePointer(hCurrentFile,0,0,FILE_BEGIN);
|
||||||
|
|
||||||
// 01.12.99 cg, changed, added HP38G signature
|
// get document signature
|
||||||
pbySig = (Chipset.type=='A') ? pbySignatureA : ((Chipset.type!='X') ? pbySignatureE : pbySignatureV);
|
pbySig = (Chipset.type=='6' || Chipset.type=='A')
|
||||||
|
? pbySignatureA : ((Chipset.type!='X') ? pbySignatureE : pbySignatureV);
|
||||||
|
|
||||||
if (!WriteFile(hCurrentFile, pbySig, 16, &lBytesWritten, NULL))
|
if (!WriteFile(hCurrentFile, pbySig, 16, &lBytesWritten, NULL))
|
||||||
{
|
{
|
||||||
|
@ -750,7 +870,7 @@ BOOL SaveDocument(VOID)
|
||||||
return FALSE;
|
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
|
Chipset.wPort2Crc = CrcPort2(); // save fingerprint of port2
|
||||||
|
|
||||||
nLength = strlen(szCurrentKml);
|
nLength = strlen(szCurrentKml);
|
||||||
|
@ -801,11 +921,10 @@ BOOL SaveBackup(VOID)
|
||||||
|
|
||||||
if (pbyRom == NULL) return FALSE;
|
if (pbyRom == NULL) return FALSE;
|
||||||
|
|
||||||
// 09.12.99 cg, changed, save window position
|
// save window position
|
||||||
GetWindowRect(hWnd, &Rect); // update saved window position
|
GetWindowRect(hWnd, &Rect); // update saved window position
|
||||||
Chipset.nPosX = (SWORD)Rect.left;
|
Chipset.nPosX = (SWORD)Rect.left;
|
||||||
Chipset.nPosY = (SWORD)Rect.top;
|
Chipset.nPosY = (SWORD)Rect.top;
|
||||||
// 09.12.99 cg, end of part
|
|
||||||
|
|
||||||
lstrcpy(szBackupFilename, szCurrentFilename);
|
lstrcpy(szBackupFilename, szCurrentFilename);
|
||||||
lstrcpy(szBackupKml, szCurrentKml);
|
lstrcpy(szBackupKml, szCurrentKml);
|
||||||
|
@ -859,17 +978,15 @@ BOOL RestoreBackup(VOID)
|
||||||
Chipset.Port2 = (LPBYTE)LocalAlloc(0,Chipset.Port2Size*2048);
|
Chipset.Port2 = (LPBYTE)LocalAlloc(0,Chipset.Port2Size*2048);
|
||||||
CopyMemory(Chipset.Port2, BackupChipset.Port2, Chipset.Port2Size*2048);
|
CopyMemory(Chipset.Port2, BackupChipset.Port2, Chipset.Port2Size*2048);
|
||||||
}
|
}
|
||||||
// 09.12.99 cg, bugfix, map port2
|
// map port2
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(cCurrentRomType!='A') // HP48SX/GX
|
if(cCurrentRomType!='6' && cCurrentRomType!='A') // HP48SX/GX
|
||||||
{
|
{
|
||||||
// use 2nd command line argument if defined
|
// use 2nd command line argument if defined
|
||||||
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
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);
|
SetWindowPos(hWnd,NULL,Chipset.nPosX,Chipset.nPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
|
||||||
UpdateWindowStatus();
|
UpdateWindowStatus();
|
||||||
Map(0x00,0xFF);
|
Map(0x00,0xFF);
|
||||||
|
@ -920,14 +1037,12 @@ BOOL GetOpenFilename(VOID)
|
||||||
"\0\0";
|
"\0\0";
|
||||||
if (cCurrentRomType!='X') // HP38G / HP48SX/GX
|
if (cCurrentRomType!='X') // HP38G / HP48SX/GX
|
||||||
{
|
{
|
||||||
// 01.12.99 cg, new, HP38G support
|
if (cCurrentRomType=='6' || cCurrentRomType=='A') // HP38G
|
||||||
if (cCurrentRomType=='A') // HP38G
|
|
||||||
{
|
{
|
||||||
ofn.lpstrDefExt = "E38";
|
ofn.lpstrDefExt = "E38";
|
||||||
ofn.nFilterIndex = 1;
|
ofn.nFilterIndex = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// 01.12.99 cg, end
|
|
||||||
{
|
{
|
||||||
ofn.lpstrDefExt = "E48";
|
ofn.lpstrDefExt = "E48";
|
||||||
ofn.nFilterIndex = 2;
|
ofn.nFilterIndex = 2;
|
||||||
|
@ -965,14 +1080,12 @@ BOOL GetSaveAsFilename(VOID)
|
||||||
"\0\0";
|
"\0\0";
|
||||||
if (cCurrentRomType!='X') // HP38G / HP48SX/GX
|
if (cCurrentRomType!='X') // HP38G / HP48SX/GX
|
||||||
{
|
{
|
||||||
// 01.12.99 cg, new, HP38G support
|
if (cCurrentRomType=='6' || cCurrentRomType=='A') // HP38G
|
||||||
if (cCurrentRomType=='A') // HP38G
|
|
||||||
{
|
{
|
||||||
ofn.lpstrDefExt = "E38";
|
ofn.lpstrDefExt = "E38";
|
||||||
ofn.nFilterIndex = 1;
|
ofn.nFilterIndex = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// 01.12.99 cg, end
|
|
||||||
{
|
{
|
||||||
ofn.lpstrDefExt = "E48";
|
ofn.lpstrDefExt = "E48";
|
||||||
ofn.nFilterIndex = 2;
|
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;
|
if (lpbi->biClrUsed != 0) return (UINT)lpbi->biClrUsed;
|
||||||
bits = lpbi->biBitCount;
|
|
||||||
|
|
||||||
switch (bits)
|
/* a 24 bitcount DIB has no color table */
|
||||||
{
|
return (lpbi->biBitCount <= 8) ? (1 << lpbi->biBitCount) : 0;
|
||||||
case 1:
|
|
||||||
return 2;
|
|
||||||
case 4:
|
|
||||||
return 16;
|
|
||||||
case 8:
|
|
||||||
return 256;
|
|
||||||
default:
|
|
||||||
/* A 24 bitcount DIB has no color table */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HPALETTE CreateBIPalette(LPBITMAPINFOHEADER lpbi)
|
static HPALETTE CreateBIPalette(LPBITMAPINFOHEADER lpbi)
|
||||||
|
@ -1292,7 +1392,8 @@ HBITMAP LoadBitmapFile(LPCSTR szFilename)
|
||||||
pbyFile+pBmfh->bfOffBits,
|
pbyFile+pBmfh->bfOffBits,
|
||||||
pBmi, DIB_RGB_COLORS);
|
pBmi, DIB_RGB_COLORS);
|
||||||
}
|
}
|
||||||
|
_ASSERT(hBitmap != NULL);
|
||||||
|
|
||||||
quit:
|
quit:
|
||||||
UnmapViewOfFile(pbyFile);
|
UnmapViewOfFile(pbyFile);
|
||||||
CloseHandle(hMap);
|
CloseHandle(hMap);
|
||||||
|
|
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
|
// I/O addresses without mapping offset
|
||||||
#define CRC 0x04 // Crc (16 bit, LSB first)
|
#define CRC 0x04 // Crc (16 bit, LSB first)
|
||||||
|
#define ANNCTRL 0x0b // Annunciator Control (2 nibble)
|
||||||
#define BAUD 0x0d // Baudrate (Bit 2-0)
|
#define BAUD 0x0d // Baudrate (Bit 2-0)
|
||||||
|
#define CARDCTL 0x0e // card control
|
||||||
|
#define CARDSTAT 0x0f // card status
|
||||||
#define IOC 0x10 // IO CONTROL
|
#define IOC 0x10 // IO CONTROL
|
||||||
#define RCS 0x11 // RCS
|
#define RCS 0x11 // RCS
|
||||||
#define TCS 0x12 // TCS
|
#define TCS 0x12 // TCS
|
||||||
|
@ -21,11 +24,34 @@
|
||||||
#define SRQ1 0x18 // SRQ1
|
#define SRQ1 0x18 // SRQ1
|
||||||
#define SRQ2 0x19 // SRQ2
|
#define SRQ2 0x19 // SRQ2
|
||||||
#define IR_CTRL 0x1a // IR CONTROL
|
#define IR_CTRL 0x1a // IR CONTROL
|
||||||
|
#define LCR 0x1c // Led Control Register
|
||||||
#define TIMER1_CTRL 0x2e // Timer1 Control
|
#define TIMER1_CTRL 0x2e // Timer1 Control
|
||||||
#define TIMER2_CTRL 0x2f // Timer2 Control
|
#define TIMER2_CTRL 0x2f // Timer2 Control
|
||||||
#define TIMER1 0x37 // Timer1 (4 bit)
|
#define TIMER1 0x37 // Timer1 (4 bit)
|
||||||
#define TIMER2 0x38 // Timer2 (32 bit, LSB first)
|
#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]
|
// 0x10 Serial I/O Control [SON ETBE ERBF ERBZ]
|
||||||
#define SON 0x08 // Serial on
|
#define SON 0x08 // Serial on
|
||||||
#define ETBE 0x04 // Interrupt on transmit buffer empty
|
#define ETBE 0x04 // Interrupt on transmit buffer empty
|
||||||
|
@ -62,6 +88,12 @@
|
||||||
#define EIRI 0x02 // Enable IR interrupt
|
#define EIRI 0x02 // Enable IR interrupt
|
||||||
#define IRE 0x01 // IR event
|
#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]
|
// 0x2e Timer1 Control [SRQ WKE INT XTRA]
|
||||||
#define SRQ 0x08 // Service request
|
#define SRQ 0x08 // Service request
|
||||||
#define WKE 0x04 // Wake up
|
#define WKE 0x04 // Wake up
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Emu48.h"
|
#include "Emu48.h"
|
||||||
|
#include "io.h" // I/O definitions
|
||||||
|
|
||||||
static WORD Keyboard_GetIR(VOID)
|
static WORD Keyboard_GetIR(VOID)
|
||||||
{
|
{
|
||||||
|
@ -38,16 +39,19 @@ VOID ScanKeyboard(BOOL bReset)
|
||||||
WORD wOldIn = Chipset.in; // save old Chipset.in state
|
WORD wOldIn = Chipset.in; // save old Chipset.in state
|
||||||
|
|
||||||
UpdateKdnBit(); // update KDN bit
|
UpdateKdnBit(); // update KDN bit
|
||||||
// 22.11.99 cg, changed, DWORD casting
|
|
||||||
Chipset.dwKdnCycles = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
Chipset.dwKdnCycles = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||||
|
|
||||||
// update Chipset.in register
|
// update keyboard only if timer is running
|
||||||
Chipset.in = Keyboard_GetIR() | Chipset.IR15X;
|
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 ?
|
// 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);
|
Chipset.intd = Chipset.intd || (bKbdInt && !Chipset.intk);
|
||||||
|
|
||||||
// keyboard interrupt enabled
|
// keyboard interrupt enabled
|
||||||
|
@ -87,7 +91,7 @@ VOID KeyboardEvent(BOOL bPress, UINT out, UINT in)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_ASSERT(out<9);
|
_ASSERT(out < sizeof(Chipset.Keyboard_Row) / sizeof(Chipset.Keyboard_Row[0]));
|
||||||
if (bPress) // key pressed
|
if (bPress) // key pressed
|
||||||
Chipset.Keyboard_Row[out] |= in; // set key marker in keyboard row
|
Chipset.Keyboard_Row[out] |= in; // set key marker in keyboard row
|
||||||
else
|
else
|
||||||
|
|
|
@ -1626,7 +1626,12 @@ VOID RefreshButtons()
|
||||||
{
|
{
|
||||||
UINT x0 = pButton[i].nOx;
|
UINT x0 = pButton[i].nOx;
|
||||||
UINT y0 = pButton[i].nOy;
|
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
|
DrawButton(i); // redraw pressed button
|
||||||
}
|
}
|
||||||
|
@ -1861,7 +1866,7 @@ BOOL InitKML(LPCSTR szFilename, BOOL bNoLog)
|
||||||
DWORD lBytesRead;
|
DWORD lBytesRead;
|
||||||
LPBYTE lpBuf;
|
LPBYTE lpBuf;
|
||||||
Block* pBlock;
|
Block* pBlock;
|
||||||
BOOL bOk = FALSE; // 08.12.99 cg, bugfix, variable not initialized at error condition
|
BOOL bOk = FALSE;
|
||||||
BYTE bySum = 0;
|
BYTE bySum = 0;
|
||||||
|
|
||||||
KillKML();
|
KillKML();
|
||||||
|
|
|
@ -8,11 +8,13 @@
|
||||||
*/
|
*/
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Emu48.h"
|
#include "Emu48.h"
|
||||||
#include "opcodes.h" // 25.10.99 cg, new, added for HST bits
|
#include "opcodes.h"
|
||||||
#include "io.h" // 24.10.99 cg, renamed from Serial.h
|
#include "io.h"
|
||||||
|
#include "i28f160.h" // flash support
|
||||||
|
|
||||||
// #define DEBUG_SERIAL // switch for SERIAL debug purpose
|
// #define DEBUG_SERIAL // switch for SERIAL debug purpose
|
||||||
// #define DEBUG_IO // switch for I/O 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
|
// defines for reading an open data bus
|
||||||
#define READEVEN 0x0D
|
#define READEVEN 0x0D
|
||||||
|
@ -24,9 +26,14 @@
|
||||||
#define P2MAPBASE ((BYTE)(Chipset.P2Base & ~Chipset.P2Size))
|
#define P2MAPBASE ((BYTE)(Chipset.P2Base & ~Chipset.P2Size))
|
||||||
#define BSMAPBASE ((BYTE)(Chipset.BSBase & ~Chipset.BSSize))
|
#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 ioc_acc = FALSE; // flag ioc changed
|
||||||
BOOL ir_ctrl_acc = FALSE; // flag ir_ctl changed
|
BOOL ir_ctrl_acc = FALSE; // flag ir_ctl changed
|
||||||
|
|
||||||
|
BOOL bFlashRomArray = TRUE; // flag ROM mode
|
||||||
|
|
||||||
BYTE disp = 0; // flag for update display area
|
BYTE disp = 0; // flag for update display area
|
||||||
|
|
||||||
static LPBYTE pbyRomView[2] = {NULL,NULL}; // HP49G ROM views
|
static LPBYTE pbyRomView[2] = {NULL,NULL}; // HP49G ROM views
|
||||||
|
@ -57,8 +64,22 @@ static __inline BYTE UckBit(BYTE byBaudIndex)
|
||||||
QueryPerformanceCounter(&lLC); // get counter value
|
QueryPerformanceCounter(&lLC); // get counter value
|
||||||
|
|
||||||
// calculate UCK frequency
|
// calculate UCK frequency
|
||||||
return (((BYTE)((lLC.LowPart * dwBaudrates[byBaudIndex]) / lFreq.LowPart) & 0x1) << 3)
|
return (((BYTE)(((lLC.QuadPart - lAppStart.QuadPart) * dwBaudrates[byBaudIndex])
|
||||||
& Chipset.IORam[IOC];
|
/ 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
|
// LCD line counter calculation
|
||||||
|
@ -67,8 +88,31 @@ static BYTE F4096Hz(VOID) // get a 6 bit 4096Hz down counter value
|
||||||
LARGE_INTEGER lLC;
|
LARGE_INTEGER lLC;
|
||||||
|
|
||||||
QueryPerformanceCounter(&lLC); // get counter value
|
QueryPerformanceCounter(&lLC); // get counter value
|
||||||
|
|
||||||
// calculate 4096 Hz frequency down 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
|
// 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
|
m = (Chipset.Port1Size*2048)-1; // real size of module, address mask for mirroring
|
||||||
p = (a<<12)&m; // offset to begin of P1 in nibbles
|
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
|
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
|
if (cCurrentRomType == 'X') // HP49G
|
||||||
{
|
{
|
||||||
_ASSERT(pbyRomView[0]); // check ROM bank set
|
if (bFlashRomArray) // view flash ROM data
|
||||||
_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;
|
_ASSERT(pbyRomView[0]); // check ROM bank set
|
||||||
WMap[i]=NULL; // no writing
|
_ASSERT(pbyRomView[1]);
|
||||||
p = (p+0x1000)&m;
|
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HP48SX / HP48GX
|
// HP38G / HP48SX / HP48GX
|
||||||
m = (dwRomSize-1)&0xFF000; // ROM address mask for mirroring
|
m = dwRomSize - 1; // ROM address mask for mirroring
|
||||||
// when G(X) ROM and DA19=0 (ROM disabled)
|
// when 512KB ROM and DA19=0 (ROM disabled)
|
||||||
if (cCurrentRomType != 'S' && (Chipset.IORam[0x29]&0x8) == 0)
|
if ((m & 0x80000) != 0 && (Chipset.IORam[0x29]&0x8) == 0)
|
||||||
m >>= 1; // mirror ROM at #80000 (AR18=0)
|
m >>= 1; // mirror ROM at #80000 (AR18=0)
|
||||||
p = (a*0x1000)&m; // data offset in nibbles
|
p = (a*0x1000)&m; // data offset in nibbles
|
||||||
for (i=a;i<=b;i++) // scan each 2KB page
|
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
|
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.BSCfig) MapBS(a,b); // CE1, bank select (lower priority than CE2)
|
||||||
if (Chipset.P1Cfig) MapP1(a,b); // CE2, port1 (higher priority than CE1)
|
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
|
if (cCurrentRomType=='X') // only HP49G
|
||||||
{
|
{
|
||||||
Chipset.Bank_FF = adr; // save address line
|
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)
|
adr = (adr >> 1) & 0x3f; // 6 bit of latch (was A6-A1 of address bus)
|
||||||
// lower 4 bit (16 banks) for 2nd ROM view
|
// 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
|
// 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
|
Map(0x00,0xFF); // update memory mapping
|
||||||
return;
|
return;
|
||||||
|
@ -546,18 +607,16 @@ VOID C_Eq_Id()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID CpuReset(VOID) // register setting after Cpu Reset
|
||||||
VOID CpuReset(VOID) // 19.03.99 cg, new, register setting after Cpu Reset
|
|
||||||
{
|
{
|
||||||
Chipset.pc = 0;
|
Chipset.pc = 0;
|
||||||
// 23.10.99 cg, bugfix, additional settings
|
|
||||||
Chipset.rstkp = 0;
|
Chipset.rstkp = 0;
|
||||||
FillMemory(Chipset.rstk,sizeof(Chipset.rstk),0);
|
FillMemory(Chipset.rstk,sizeof(Chipset.rstk),0);
|
||||||
Chipset.HST = 0;
|
Chipset.HST = 0;
|
||||||
// 23.10.99 cg, end of additional settings
|
|
||||||
Chipset.inte = TRUE;
|
Chipset.inte = TRUE;
|
||||||
Chipset.Shutdn = FALSE;
|
Chipset.Shutdn = FALSE;
|
||||||
Chipset.SoftInt = TRUE;
|
Chipset.SoftInt = TRUE;
|
||||||
|
Chipset.FlashRomState = 0; // WSM state of flash memory
|
||||||
Reset(); // reset MMU
|
Reset(); // reset MMU
|
||||||
bInterrupt = TRUE;
|
bInterrupt = TRUE;
|
||||||
return;
|
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
|
BYTE GetLineCounter(VOID) // get line counter value
|
||||||
{
|
{
|
||||||
|
_ASSERT(byVblRef < 0x40);
|
||||||
return (0x40 + F4096Hz() - byVblRef) & 0x3F;
|
return (0x40 + F4096Hz() - byVblRef) & 0x3F;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID Npeek(BYTE *a, DWORD d, UINT s)
|
VOID Npeek(BYTE *a, DWORD d, UINT s)
|
||||||
{
|
{
|
||||||
|
enum MMUMAP eMap;
|
||||||
DWORD u, v;
|
DWORD u, v;
|
||||||
UINT c;
|
UINT c;
|
||||||
BYTE *p;
|
BYTE *p;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// 12.11.99 cg, new, added reading of I/O area
|
eMap = MapData(d); // get active memory controller
|
||||||
// test Chipset.IOCfig for mapping
|
if (M_IO == eMap) // I/O access
|
||||||
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
|
|
||||||
{
|
{
|
||||||
// update crc
|
// update CRC
|
||||||
Nunpack(Chipset.IORam+CRC, Chipset.crc, 4);
|
Nunpack(Chipset.IORam+CRC, Chipset.crc, 4);
|
||||||
|
// update CARDSTAT
|
||||||
|
Chipset.IORam[CARDSTAT] = (Chipset.IORam[CARDCTL] & ECDT) ? Chipset.cards_status : 0;
|
||||||
// update SRQ2
|
// update SRQ2
|
||||||
UpdateKdnBit();
|
ReadIO(a,SRQ2,1);
|
||||||
IOBit(SRQ2,NINT2,Chipset.IORam[SRQ1] == 0 && (Chipset.IORam[SRQ2] & LSRQ) == 0);
|
|
||||||
IOBit(SRQ2,NINT,(Chipset.HST & MP) == 0);
|
|
||||||
// update timer1
|
// update timer1
|
||||||
Chipset.IORam[TIMER1] = Chipset.t1;
|
Chipset.IORam[TIMER1] = Chipset.t1;
|
||||||
// update timer2
|
// update timer2
|
||||||
|
@ -596,12 +656,34 @@ VOID Npeek(BYTE *a, DWORD d, UINT s)
|
||||||
memcpy(a, Chipset.IORam+v, c);
|
memcpy(a, Chipset.IORam+v, c);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// 12.11.99 cg, end of new part
|
|
||||||
{
|
{
|
||||||
u = d>>12;
|
u = d>>12;
|
||||||
v = d&0xFFF;
|
v = d&0xFFF;
|
||||||
c = MIN(s,0x1000-v);
|
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;}
|
if (s-=c) {a+=c; d+=c;}
|
||||||
} while (s);
|
} while (s);
|
||||||
|
@ -610,20 +692,21 @@ VOID Npeek(BYTE *a, DWORD d, UINT s)
|
||||||
|
|
||||||
VOID Nread(BYTE *a, DWORD d, UINT s)
|
VOID Nread(BYTE *a, DWORD d, UINT s)
|
||||||
{
|
{
|
||||||
|
enum MMUMAP eMap;
|
||||||
DWORD u, v;
|
DWORD u, v;
|
||||||
UINT c;
|
UINT c;
|
||||||
BYTE *p;
|
BYTE *p;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// test Chipset.IOCfig for mapping
|
eMap = MapData(d); // get active memory controller
|
||||||
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
|
if (M_IO == eMap) // I/O access
|
||||||
{
|
{
|
||||||
v = d&0x3F;
|
v = d&0x3F;
|
||||||
c = MIN(s,0x40-v);
|
c = MIN(s,0x40-v);
|
||||||
ReadIO(a,v,c);
|
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
|
if (v+c == 0x40) UpCRC(a[c-1]); // timer2 MSB touched, update the CRC register
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -631,41 +714,55 @@ VOID Nread(BYTE *a, DWORD d, UINT s)
|
||||||
u = d>>12;
|
u = d>>12;
|
||||||
v = d&0xFFF;
|
v = d&0xFFF;
|
||||||
c = MIN(s,0x1000-v);
|
c = MIN(s,0x1000-v);
|
||||||
if ( (cCurrentRomType != 'S')
|
// bank switcher access
|
||||||
&& (Chipset.BSCfig && (((u^Chipset.BSBase) & ~Chipset.BSSize) == 0))
|
if (cCurrentRomType != 'S' && M_BS == eMap)
|
||||||
&& !(Chipset.P0Cfig && (((u^Chipset.P0Base) & ~Chipset.P0Size) == 0))
|
|
||||||
&& !(Chipset.P1Cfig && (((u^Chipset.P1Base) & ~Chipset.P1Size) == 0))
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (cCurrentRomType == 'G') // HP48GX
|
if (cCurrentRomType == 'G') // HP48GX
|
||||||
{
|
{
|
||||||
Chipset.Bank_FF = v+c; // save FF value
|
Chipset.Bank_FF = v+c; // save FF value
|
||||||
Map(Chipset.P2Base,Chipset.P2End);
|
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);
|
DWORD dwLinAddr = FlashROMAddr(d);
|
||||||
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;
|
|
||||||
|
|
||||||
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;}
|
if (s-=c) {a+=c; d+=c;}
|
||||||
} while (s);
|
} while (s);
|
||||||
|
@ -674,6 +771,7 @@ VOID Nread(BYTE *a, DWORD d, UINT s)
|
||||||
|
|
||||||
VOID Nwrite(BYTE *a, DWORD d, UINT s)
|
VOID Nwrite(BYTE *a, DWORD d, UINT s)
|
||||||
{
|
{
|
||||||
|
enum MMUMAP eMap;
|
||||||
DWORD u, v;
|
DWORD u, v;
|
||||||
UINT c;
|
UINT c;
|
||||||
BYTE *p;
|
BYTE *p;
|
||||||
|
@ -708,8 +806,8 @@ VOID Nwrite(BYTE *a, DWORD d, UINT s)
|
||||||
}
|
}
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// test Chipset.IOCfig for mapping
|
eMap = MapData(d); // get active memory controller
|
||||||
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
|
if (M_IO == eMap) // I/O access
|
||||||
{
|
{
|
||||||
v = d&0x3F;
|
v = d&0x3F;
|
||||||
c = MIN(s,0x40-v);
|
c = MIN(s,0x40-v);
|
||||||
|
@ -720,36 +818,70 @@ VOID Nwrite(BYTE *a, DWORD d, UINT s)
|
||||||
u = d>>12;
|
u = d>>12;
|
||||||
v = d&0xFFF;
|
v = d&0xFFF;
|
||||||
c = MIN(s,0x1000-v);
|
c = MIN(s,0x1000-v);
|
||||||
if ( (cCurrentRomType != 'S')
|
// bank switcher access
|
||||||
&& (Chipset.BSCfig && (((u^Chipset.BSBase) & ~Chipset.BSSize) == 0))
|
if (cCurrentRomType != 'S' && M_BS == eMap)
|
||||||
&& !(Chipset.P0Cfig && (((u^Chipset.P0Base) & ~Chipset.P0Size) == 0))
|
|
||||||
&& !(Chipset.P1Cfig && (((u^Chipset.P1Base) & ~Chipset.P1Size) == 0))
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (cCurrentRomType == 'G') // HP48GX
|
BOOL bWrite = FALSE;
|
||||||
{
|
|
||||||
BOOL bMap = 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
|
if ((v & 1) != 0) // low address odd
|
||||||
{
|
{
|
||||||
Chipset.Bank_FF = v;// save FF value
|
Chipset.Bank_FF = v;// save FF value
|
||||||
bMap = TRUE; // bank switched
|
bWrite = TRUE; // bank switched
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((v+c & 1) != 0) // high address odd
|
if ((v+c & 1) != 0) // high address odd
|
||||||
{
|
{
|
||||||
Chipset.Bank_FF = v+c-1;// save FF value
|
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;
|
a+=c;
|
||||||
d+=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)
|
VOID ReadIO(BYTE *a, DWORD d, DWORD s)
|
||||||
{
|
{
|
||||||
|
BOOL bNINT;
|
||||||
|
BOOL bNINT2;
|
||||||
|
|
||||||
BYTE c = 0xFF; // LINECOUNT not initialized
|
BYTE c = 0xFF; // LINECOUNT not initialized
|
||||||
BOOL rbr_acc = FALSE; // flag to receive data
|
BOOL rbr_acc = FALSE; // flag to receive data
|
||||||
|
|
||||||
|
@ -844,11 +979,27 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s)
|
||||||
#endif
|
#endif
|
||||||
*a |= UckBit(*a); // add UCK bit to BAUD rate register
|
*a |= UckBit(*a); // add UCK bit to BAUD rate register
|
||||||
break;
|
break;
|
||||||
// case 0x0E: *a = Chipset.IORam[d]; break;
|
case 0x0E:
|
||||||
case 0x0F:
|
// SMP is !NINT and SWINT is always 0
|
||||||
// On a HP49G Chipset.cards_status bust always be 0xF
|
// clear SMP and SWINT bit
|
||||||
_ASSERT(cCurrentRomType!='X' || Chipset.cards_status == 0xF);
|
Chipset.IORam[d] &= (ECDT | RCDT);
|
||||||
*a = Chipset.cards_status;
|
// SMP is !NINT
|
||||||
|
if ((Chipset.IORam[SRQ2] & NINT) == 0)
|
||||||
|
Chipset.IORam[d] |= SMP;
|
||||||
|
*a = Chipset.IORam[d];
|
||||||
|
break;
|
||||||
|
case 0x0F:
|
||||||
|
// 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;
|
break;
|
||||||
case 0x10: // IO CONTROL
|
case 0x10: // IO CONTROL
|
||||||
*a = Chipset.IORam[d]; // return IO CONTROL value
|
*a = Chipset.IORam[d]; // return IO CONTROL value
|
||||||
|
@ -887,7 +1038,7 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s)
|
||||||
case 0x15: // RBR MSB
|
case 0x15: // RBR MSB
|
||||||
Chipset.IORam[RCS]&=~RBF;
|
Chipset.IORam[RCS]&=~RBF;
|
||||||
*a = Chipset.IORam[d]; // return RBR value
|
*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
|
rbr_acc = TRUE; // search for new RBR value
|
||||||
#if defined DEBUG_SERIAL
|
#if defined DEBUG_SERIAL
|
||||||
{
|
{
|
||||||
|
@ -903,10 +1054,18 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s)
|
||||||
break;
|
break;
|
||||||
case 0x19: // SREQ? MSB
|
case 0x19: // SREQ? MSB
|
||||||
UpdateKdnBit(); // update KDN bit
|
UpdateKdnBit(); // update KDN bit
|
||||||
// 25.10.99 cg, bugfix, update NINT2 bit
|
bNINT2 = Chipset.IORam[SRQ1] == 0 && (Chipset.IORam[SRQ2] & LSRQ) == 0;
|
||||||
IOBit(SRQ2,NINT2,Chipset.IORam[SRQ1] == 0 && (Chipset.IORam[SRQ2] & LSRQ) == 0);
|
bNINT = (Chipset.IORam[SRQ2] & NINT) != 0;
|
||||||
// 25.10.99 cg, bugfix, update NINT bit
|
// card detection off and timer running
|
||||||
IOBit(SRQ2,NINT,(Chipset.HST & MP) == 0);
|
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!
|
// no break!
|
||||||
case 0x18: // SREQ? LSB
|
case 0x18: // SREQ? LSB
|
||||||
*a = Chipset.IORam[d]; // return SREQ value
|
*a = Chipset.IORam[d]; // return SREQ value
|
||||||
|
@ -1149,29 +1308,51 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 0010E = NS:CARDCTRL
|
// 0010E = NS:CARDCTL
|
||||||
// 0010E @ [ECDT RCDT SMP SWINT] (read/write)
|
// 0010E @ [ECDT RCDT SMP SWINT] (read/write)
|
||||||
// 0010E @ Enable Card Det., Run Card Det., Set Module Pulled, Software interrupt
|
// 0010E @ Enable Card Det., Run Card Det., Set Module Pulled, Software interrupt
|
||||||
case 0x0E:
|
case 0x0E:
|
||||||
Chipset.IORam[d]=c;
|
if (c & SWINT) // SWINT bit set
|
||||||
#if 1
|
{
|
||||||
if ( (RMap[4]!=(pbyRom+0x4000)) && (12 != c) )
|
c &= (ECDT | RCDT | SMP); // clear SWINT bit
|
||||||
{
|
Chipset.SoftInt = TRUE;
|
||||||
c |= 0x10;
|
bInterrupt = TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
if ((c & SMP) == 0) // SMP bit cleared
|
||||||
if (c&1)
|
{
|
||||||
{
|
BOOL bNINT = TRUE; // ack NINT interrupt -> NINT high
|
||||||
Chipset.SoftInt = TRUE;
|
// card detect disabled and CDT1 low -> retrigger
|
||||||
bInterrupt = TRUE;
|
if ((c & ECDT) == 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0)
|
||||||
}
|
bNINT = (Chipset.cards_status & (P1W|P1C)) != P1C;
|
||||||
if (c&2)
|
IOBit(SRQ2,NINT,bNINT);
|
||||||
{
|
}
|
||||||
Chipset.HST |= 8; // MP
|
// falling edge of Enable Card Detect bit and timer running
|
||||||
// Chipset.SoftInt = TRUE;
|
if ( ((c^Chipset.IORam[d]) & ECDT) != 0 && (c & ECDT) == 0
|
||||||
// bInterrupt = TRUE;
|
&& (Chipset.IORam[TIMER2_CTRL] & RUN) != 0)
|
||||||
}
|
{
|
||||||
break;
|
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 = NS:CARDSTATUS
|
||||||
// 0010F @ [P2W P1W P2C P1C] (read-only) Port 2 writable .. Port 1 inserted
|
// 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
|
// 00110 @ Serial On, Interrupt On Recv.Buf.Empty, Full, Buzy
|
||||||
case 0x10:
|
case 0x10:
|
||||||
Chipset.IORam[d]=c;
|
Chipset.IORam[d]=c;
|
||||||
UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ
|
UpdateUSRQ(); // update USRQ
|
||||||
ioc_acc = TRUE; // new IOC value
|
ioc_acc = TRUE; // new IOC value
|
||||||
#if defined DEBUG_SERIAL
|
#if defined DEBUG_SERIAL
|
||||||
{
|
{
|
||||||
|
@ -1244,7 +1425,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
|
||||||
case 0x17:
|
case 0x17:
|
||||||
Chipset.IORam[d]=c;
|
Chipset.IORam[d]=c;
|
||||||
Chipset.IORam[TCS]|=TBF;
|
Chipset.IORam[TCS]|=TBF;
|
||||||
UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ
|
UpdateUSRQ(); // update USRQ
|
||||||
tbr_acc = TRUE; // new TBR value
|
tbr_acc = TRUE; // new TBR value
|
||||||
#if defined DEBUG_SERIAL
|
#if defined DEBUG_SERIAL
|
||||||
{
|
{
|
||||||
|
@ -1282,7 +1463,22 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
|
||||||
|
|
||||||
// 0011C = NS:LCR
|
// 0011C = NS:LCR
|
||||||
// 0011C @ Led Control Register [LED ELBE LBZ LBF] (Setting LED is draining)
|
// 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 = NS:LBR
|
||||||
// 0011D @ Led Buffer Register [0 0 0 LBO] (bits 1-3 read zero)
|
// 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
|
// 00128 @ Normally has 55 -> Menu starts at display row 56
|
||||||
case 0x28:
|
case 0x28:
|
||||||
case 0x29:
|
case 0x29:
|
||||||
// when G(X) and writing to register 0x29
|
if (d == 0x29)
|
||||||
if (cCurrentRomType != 'S' && d == 0x29)
|
|
||||||
{
|
{
|
||||||
if ((c^Chipset.IORam[d])&8) // DA19 changed
|
if ((c^Chipset.IORam[d])&8) // DA19 changed
|
||||||
{
|
{
|
||||||
|
@ -1359,6 +1554,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
|
||||||
StartTimers();
|
StartTimers();
|
||||||
else
|
else
|
||||||
StopTimers();
|
StopTimers();
|
||||||
|
disp |= DISP_ANNUN; // update annunciators
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// 00130 = NS:MENUADDR
|
// 00130 = NS:MENUADDR
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Emu48.h"
|
#include "Emu48.h"
|
||||||
#include "Opcodes.h"
|
#include "Opcodes.h"
|
||||||
|
#include "io.h" // I/O register definitions
|
||||||
|
|
||||||
#define w Chipset
|
#define w Chipset
|
||||||
#define GOYES3 {if(w.carry) o_goyes3(I);else{w.pc+=2;return;}}
|
#define GOYES3 {if(w.carry) o_goyes3(I);else{w.pc+=2;return;}}
|
||||||
|
@ -19,6 +20,10 @@
|
||||||
|
|
||||||
#include "Ops.h"
|
#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
|
VOID o00(LPBYTE I) // RTNSXM
|
||||||
{
|
{
|
||||||
w.cycles+=9;
|
w.cycles+=9;
|
||||||
|
@ -84,7 +89,7 @@ VOID o07(LPBYTE I) // C=RSTK
|
||||||
|
|
||||||
VOID o08(LPBYTE I) // CLRST
|
VOID o08(LPBYTE I) // CLRST
|
||||||
{
|
{
|
||||||
w.cycles+=5; // 22.10.99 cg, bugfix, fixed no. of cycles
|
w.cycles+=5;
|
||||||
w.pc+=2;
|
w.pc+=2;
|
||||||
memset(w.ST, 0, 3);
|
memset(w.ST, 0, 3);
|
||||||
return;
|
return;
|
||||||
|
@ -92,7 +97,7 @@ VOID o08(LPBYTE I) // CLRST
|
||||||
|
|
||||||
VOID o09(LPBYTE I) // C=ST
|
VOID o09(LPBYTE I) // C=ST
|
||||||
{
|
{
|
||||||
w.cycles+=5; // 22.10.99 cg, bugfix, fixed no. of cycles
|
w.cycles+=5;
|
||||||
w.pc+=2;
|
w.pc+=2;
|
||||||
memcpy(w.C, w.ST, 3);
|
memcpy(w.C, w.ST, 3);
|
||||||
return;
|
return;
|
||||||
|
@ -100,7 +105,7 @@ VOID o09(LPBYTE I) // C=ST
|
||||||
|
|
||||||
VOID o0A(LPBYTE I) // ST=C
|
VOID o0A(LPBYTE I) // ST=C
|
||||||
{
|
{
|
||||||
w.cycles+=5; // 22.10.99 cg, bugfix, fixed no. of cycles
|
w.cycles+=5;
|
||||||
w.pc+=2;
|
w.pc+=2;
|
||||||
memcpy(w.ST, w.C, 3);
|
memcpy(w.ST, w.C, 3);
|
||||||
return;
|
return;
|
||||||
|
@ -108,7 +113,7 @@ VOID o0A(LPBYTE I) // ST=C
|
||||||
|
|
||||||
VOID o0B(LPBYTE I) // CSTEX
|
VOID o0B(LPBYTE I) // CSTEX
|
||||||
{
|
{
|
||||||
w.cycles+=5; // 22.10.99 cg, bugfix, fixed no. of cycles
|
w.cycles+=5;
|
||||||
w.pc+=2;
|
w.pc+=2;
|
||||||
Nxchg(w.C, w.ST, 3);
|
Nxchg(w.C, w.ST, 3);
|
||||||
return;
|
return;
|
||||||
|
@ -276,11 +281,29 @@ VOID o0F(LPBYTE I) // RTI
|
||||||
INTERRUPT; // restart interrupt handler
|
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
|
// 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
|
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
|
ReadT2(); // check for int
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -834,7 +857,7 @@ VOID o3X(LPBYTE I) // LCHEX
|
||||||
{
|
{
|
||||||
UINT n=I[1]+1;
|
UINT n=I[1]+1;
|
||||||
UINT d=16-w.P;
|
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;
|
w.pc+=2;
|
||||||
I+=2; // UNSAFE
|
I+=2; // UNSAFE
|
||||||
if (n<=d)
|
if (n<=d)
|
||||||
|
@ -1010,7 +1033,6 @@ VOID o8080(LPBYTE I) // INTON
|
||||||
w.cycles+=5;
|
w.cycles+=5;
|
||||||
w.pc+=4;
|
w.pc+=4;
|
||||||
// cpu cycles at start of 1ms key handler
|
// cpu cycles at start of 1ms key handler
|
||||||
// 22.11.99 cg, changed, DWORD casting
|
|
||||||
w.dwKdnCycles = (DWORD) (w.cycles & 0xFFFFFFFF);
|
w.dwKdnCycles = (DWORD) (w.cycles & 0xFFFFFFFF);
|
||||||
|
|
||||||
w.intk = TRUE;
|
w.intk = TRUE;
|
||||||
|
@ -1029,7 +1051,6 @@ VOID o80810(LPBYTE I) // RSI
|
||||||
ScanKeyboard(TRUE); // one input bit high ?
|
ScanKeyboard(TRUE); // one input bit high ?
|
||||||
|
|
||||||
// enable KDN update
|
// enable KDN update
|
||||||
// 22.11.99 cg, changed, DWORD casting
|
|
||||||
w.dwKdnCycles = (DWORD) (w.cycles & 0xFFFFFFFF) - (DWORD) T2CYCLES * 16;
|
w.dwKdnCycles = (DWORD) (w.cycles & 0xFFFFFFFF) - (DWORD) T2CYCLES * 16;
|
||||||
|
|
||||||
if (w.in && w.inte == FALSE) // key interrupt pending
|
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
|
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;
|
w.pc+=5;
|
||||||
Tbit0(w.A, I[4]);
|
Tbit0(w.A, I[4]);
|
||||||
GOYES5;
|
GOYES5;
|
||||||
|
@ -1091,7 +1112,7 @@ VOID o8086n(LPBYTE I) // ?ABIT=0 n
|
||||||
|
|
||||||
VOID o8087n(LPBYTE I) // ?ABIT=1 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;
|
w.pc+=5;
|
||||||
Tbit1(w.A, I[4]);
|
Tbit1(w.A, I[4]);
|
||||||
GOYES5;
|
GOYES5;
|
||||||
|
@ -1115,7 +1136,7 @@ VOID o8089n(LPBYTE I) // CBIT=1 n
|
||||||
|
|
||||||
VOID o808An(LPBYTE I) // ?CBIT=0 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;
|
w.pc+=5;
|
||||||
Tbit0(w.C, I[4]);
|
Tbit0(w.C, I[4]);
|
||||||
GOYES5;
|
GOYES5;
|
||||||
|
@ -1123,7 +1144,7 @@ VOID o808An(LPBYTE I) // ?CBIT=0 n
|
||||||
|
|
||||||
VOID o808Bn(LPBYTE I) // ?CBIT=1 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;
|
w.pc+=5;
|
||||||
Tbit1(w.C, I[4]);
|
Tbit1(w.C, I[4]);
|
||||||
GOYES5;
|
GOYES5;
|
||||||
|
@ -1131,8 +1152,10 @@ VOID o808Bn(LPBYTE I) // ?CBIT=1 n
|
||||||
|
|
||||||
VOID o808C(LPBYTE I) // PC=(A)
|
VOID o808C(LPBYTE I) // PC=(A)
|
||||||
{
|
{
|
||||||
|
BYTE p[5];
|
||||||
w.cycles+=23;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1147,8 +1170,10 @@ VOID o808D(LPBYTE I) // BUSCD
|
||||||
|
|
||||||
VOID o808E(LPBYTE I) // PC=(C)
|
VOID o808E(LPBYTE I) // PC=(C)
|
||||||
{
|
{
|
||||||
|
BYTE p[5];
|
||||||
w.cycles+=23;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2085,7 +2110,7 @@ VOID o8Ed4(LPBYTE I) // GOSUBL #dddd
|
||||||
DWORD d=Npack(I+2,4);
|
DWORD d=Npack(I+2,4);
|
||||||
rstkpush(w.pc+6);
|
rstkpush(w.pc+6);
|
||||||
if (d&0x8000) w.pc-=0xfffa-d; else w.pc+=d+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;
|
w.pc&=0xFFFFF;
|
||||||
return;
|
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 PCHANGED ((void)(F_s[0]=Chipset.P,F_l[1]=Chipset.P+1))
|
||||||
#define INTERRUPT ((void)(Chipset.SoftInt=TRUE,bInterrupt=TRUE))
|
#define INTERRUPT ((void)(Chipset.SoftInt=TRUE,bInterrupt=TRUE))
|
||||||
|
|
||||||
#define T2CYCLES ((cCurrentRomType=='S')?dwSXCycles:dwGXCycles)
|
#define T2CYCLES ((cCurrentRomType=='S')?dwSXCycles:dwGXCycles)
|
||||||
|
|
||||||
|
extern UINT F_s[16];
|
||||||
|
extern UINT F_l[16];
|
||||||
|
|
||||||
extern VOID o00(LPBYTE I); // RTNSXM
|
extern VOID o00(LPBYTE I); // RTNSXM
|
||||||
extern VOID o01(LPBYTE I); // RTN
|
extern VOID o01(LPBYTE I); // RTN
|
||||||
extern VOID o02(LPBYTE I); // RTNSC
|
extern VOID o02(LPBYTE I); // RTNSC
|
||||||
|
|
|
@ -8,10 +8,6 @@
|
||||||
*/
|
*/
|
||||||
// #pragma warning(disable:4244)
|
// #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 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 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])
|
#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 __inline LPBYTE FASTPTR(DWORD d)
|
||||||
{
|
{
|
||||||
|
static BYTE pbyNULL[16];
|
||||||
|
LPBYTE lpbyPage;
|
||||||
|
|
||||||
|
d &= 0xFFFFF; // handle address overflows
|
||||||
|
|
||||||
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
|
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
|
||||||
return Chipset.IORam+d-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)
|
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)
|
static __inline void Ninc(BYTE *a, UINT s, UINT d)
|
||||||
{
|
{
|
||||||
UINT i;
|
UINT i;
|
||||||
BYTE cBase = Chipset.mode_dec ? 10 : 16;
|
|
||||||
|
|
||||||
for (i=d; i<s+d; ++i)
|
if (Chipset.mode_dec)
|
||||||
{
|
{
|
||||||
a[i&0xf]++;
|
BYTE c = 1;
|
||||||
if (a[i&0xf] < cBase)
|
for (i=d; i<s+d; ++i)
|
||||||
{
|
{
|
||||||
Chipset.carry = FALSE;
|
if (a[i&0xf] >= 10) a[i&0xf] &= 0x7;
|
||||||
return;
|
|
||||||
|
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)
|
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)
|
for (i=d; i<s+d; ++i)
|
||||||
{
|
{
|
||||||
a[i&0xf]--;
|
a[i&0xf]--;
|
||||||
if (a[i&0xf] < cBase)
|
if ((a[i&0xf] & 0xF0) == 0) // check overflow
|
||||||
{
|
{
|
||||||
Chipset.carry = FALSE;
|
Chipset.carry = FALSE;
|
||||||
return;
|
return;
|
||||||
|
@ -178,6 +203,10 @@ static __inline void Nadd(BYTE *a, BYTE *b, UINT s)
|
||||||
|
|
||||||
for (i=0; i<s; ++i)
|
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;
|
a[i] += b[i] + c;
|
||||||
if (a[i] >= cBase)
|
if (a[i] >= cBase)
|
||||||
{
|
{
|
||||||
|
@ -195,11 +224,11 @@ static __inline void Nsub(BYTE *a, BYTE *b, UINT s)
|
||||||
UINT i;
|
UINT i;
|
||||||
BYTE c = 0;
|
BYTE c = 0;
|
||||||
BYTE cBase = Chipset.mode_dec ? 10 : 16;
|
BYTE cBase = Chipset.mode_dec ? 10 : 16;
|
||||||
|
|
||||||
for (i=0; i<s; ++i)
|
for (i=0; i<s; ++i)
|
||||||
{
|
{
|
||||||
a[i] -= b[i] + c;
|
a[i] -= b[i] + c;
|
||||||
if (a[i] >= cBase)
|
if ((a[i&0xf] & 0xF0) != 0) // check overflow
|
||||||
{
|
{
|
||||||
a[i] += cBase;
|
a[i] += cBase;
|
||||||
c = 1;
|
c = 1;
|
||||||
|
@ -219,7 +248,7 @@ static __inline void Nrsub(BYTE *a, BYTE *b, UINT s)
|
||||||
for (i=0; i<s; ++i)
|
for (i=0; i<s; ++i)
|
||||||
{
|
{
|
||||||
a[i] = b[i] - (a[i] + c);
|
a[i] = b[i] - (a[i] + c);
|
||||||
if (a[i] >= cBase)
|
if ((a[i&0xf] & 0xF0) != 0) // check overflow
|
||||||
{
|
{
|
||||||
a[i] += cBase;
|
a[i] += cBase;
|
||||||
c = 1;
|
c = 1;
|
||||||
|
@ -244,7 +273,12 @@ static __inline void Nnot(BYTE *a, UINT s)
|
||||||
{
|
{
|
||||||
BYTE cBase = Chipset.mode_dec ? 9 : 15;
|
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;
|
Chipset.carry = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,8 +291,14 @@ static __inline void Nneg(BYTE *a, UINT s)
|
||||||
if (Chipset.carry = (i!=s)) // value was non-zero
|
if (Chipset.carry = (i!=s)) // value was non-zero
|
||||||
{
|
{
|
||||||
a[i] = cBase - a[i]; // first non-zero digit
|
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++)
|
for (--cBase, ++i; i<s; i++)
|
||||||
|
{
|
||||||
a[i] = cBase - a[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 102
|
||||||
#define IDR_DEBUG_CODE 103
|
#define IDR_DEBUG_CODE 103
|
||||||
#define IDR_DEBUG_MEM 104
|
#define IDR_DEBUG_MEM 104
|
||||||
#define IDB_EMPTY 105
|
#define IDD_ABOUT 105
|
||||||
#define IDD_ABOUT 106
|
#define IDD_SETTINGS 106
|
||||||
#define IDD_ABOUTS 107
|
#define IDD_CHOOSEKML 107
|
||||||
#define IDD_SETTINGS 108
|
#define IDD_KMLLOG 108
|
||||||
#define IDD_CHOOSEKML 109
|
#define IDD_DISASM 109
|
||||||
#define IDD_KMLLOG 110
|
#define IDD_DEBUG 110
|
||||||
#define IDD_REGISTER 111
|
#define IDD_NEWVALUE 111
|
||||||
#define IDD_DISASM 112
|
#define IDD_ENTERADR 112
|
||||||
#define IDD_DEBUG 113
|
#define IDD_BREAKEDIT 113
|
||||||
#define IDD_NEWVALUE 114
|
#define IDD_ENTERBREAK 114
|
||||||
#define IDD_ENTERADR 115
|
#define IDD_INSTRUCTIONS 115
|
||||||
#define IDD_BREAKEDIT 116
|
|
||||||
#define IDC_PORT1WR 1000
|
#define IDC_PORT1WR 1000
|
||||||
#define IDC_AUTOSAVE 1001
|
#define IDC_AUTOSAVE 1001
|
||||||
#define IDC_AUTOSAVEONEXIT 1002
|
#define IDC_AUTOSAVEONEXIT 1002
|
||||||
|
@ -31,75 +30,95 @@
|
||||||
#define IDC_PORT2ISSHARED 1009
|
#define IDC_PORT2ISSHARED 1009
|
||||||
#define IDC_PORT2 1010
|
#define IDC_PORT2 1010
|
||||||
#define IDC_ALWAYSDISPLOG 1011
|
#define IDC_ALWAYSDISPLOG 1011
|
||||||
#define IDC_NAME 1012
|
#define IDC_UPDATE 1012
|
||||||
#define IDC_REGTEXT 1013
|
#define IDC_LICENSE 1013
|
||||||
#define IDC_CODE 1014
|
#define IDC_REALSPEED 1014
|
||||||
#define IDC_REGISTER 1015
|
#define IDC_PORT1EN 1015
|
||||||
#define IDC_UPDATE 1016
|
#define IDC_WIRE 1016
|
||||||
#define IDC_LICENSE 1017
|
#define IDC_IR 1017
|
||||||
#define IDC_REALSPEED 1018
|
#define IDC_DISASM_WIN 1018
|
||||||
#define IDC_PORT1EN 1019
|
#define IDC_DISASM_MAP 1019
|
||||||
#define IDC_WIRE 1020
|
#define IDC_DISASM_ROM 1020
|
||||||
#define IDC_IR 1021
|
#define IDC_DISASM_RAM 1021
|
||||||
#define IDC_DISASM_WIN 1022
|
#define IDC_DISASM_PORT1 1022
|
||||||
#define IDC_DISASM_MAP 1023
|
#define IDC_DISASM_PORT2 1023
|
||||||
#define IDC_DISASM_ROM 1024
|
#define IDC_DISASM_MODULE 1024
|
||||||
#define IDC_DISASM_RAM 1025
|
#define IDC_DISASM_HP 1025
|
||||||
#define IDC_DISASM_PORT1 1026
|
#define IDC_DISASM_CLASS 1026
|
||||||
#define IDC_DISASM_PORT2 1027
|
#define IDC_DISASM_MNEMONICS 1027
|
||||||
#define IDC_DISASM_MODULE 1028
|
#define IDC_ADDRESS 1028
|
||||||
#define IDC_DISASM_HP 1029
|
#define IDC_DISASM_ADR 1029
|
||||||
#define IDC_DISASM_CLASS 1030
|
#define IDC_DISASM_NEXT 1030
|
||||||
#define IDC_DISASM_MNEMONICS 1031
|
#define IDC_DISASM_COPY 1031
|
||||||
#define IDC_ADDRESS 1032
|
#define IDC_DEBUG_CODE 1032
|
||||||
#define IDC_DISASM_ADR 1033
|
#define IDC_STATIC_CODE 1033
|
||||||
#define IDC_DISASM_NEXT 1034
|
#define IDC_STATIC_REGISTERS 1034
|
||||||
#define IDC_DISASM_COPY 1035
|
#define IDC_STATIC_MEMORY 1035
|
||||||
#define IDC_DEBUG_CODE 1036
|
#define IDC_STATIC_STACK 1036
|
||||||
#define IDC_STATIC_CODE 1037
|
#define IDC_REG_A 1037
|
||||||
#define IDC_STATIC_REGISTERS 1038
|
#define IDC_REG_B 1038
|
||||||
#define IDC_STATIC_MEMORY 1039
|
#define IDC_REG_C 1039
|
||||||
#define IDC_STATIC_STACK 1040
|
#define IDC_REG_D 1040
|
||||||
#define IDC_REG_A 1041
|
#define IDC_REG_R0 1041
|
||||||
#define IDC_REG_B 1042
|
#define IDC_REG_R1 1042
|
||||||
#define IDC_REG_C 1043
|
#define IDC_REG_R2 1043
|
||||||
#define IDC_REG_D 1044
|
#define IDC_REG_R3 1044
|
||||||
#define IDC_REG_R0 1045
|
#define IDC_REG_R4 1045
|
||||||
#define IDC_REG_R1 1046
|
#define IDC_REG_D0 1046
|
||||||
#define IDC_REG_R2 1047
|
#define IDC_REG_D1 1047
|
||||||
#define IDC_REG_R3 1048
|
#define IDC_REG_P 1048
|
||||||
#define IDC_REG_R4 1049
|
#define IDC_REG_PC 1049
|
||||||
#define IDC_REG_D0 1050
|
#define IDC_REG_OUT 1050
|
||||||
#define IDC_REG_D1 1051
|
#define IDC_REG_IN 1051
|
||||||
#define IDC_REG_P 1052
|
#define IDC_REG_ST 1052
|
||||||
#define IDC_REG_PC 1053
|
#define IDC_REG_CY 1053
|
||||||
#define IDC_REG_OUT 1054
|
#define IDC_REG_MODE 1054
|
||||||
#define IDC_REG_IN 1055
|
#define IDC_REG_MP 1055
|
||||||
#define IDC_REG_ST 1056
|
#define IDC_REG_SR 1056
|
||||||
#define IDC_REG_CY 1057
|
#define IDC_REG_SB 1057
|
||||||
#define IDC_REG_MODE 1058
|
#define IDC_REG_XM 1058
|
||||||
#define IDC_REG_MP 1059
|
#define IDC_MISC_INT 1059
|
||||||
#define IDC_REG_SR 1060
|
#define IDC_MISC_KEY 1060
|
||||||
#define IDC_REG_SB 1061
|
#define IDC_MISC_BS 1061
|
||||||
#define IDC_REG_XM 1062
|
#define IDC_NEWVALUE 1062
|
||||||
#define IDC_NEWVALUE 1063
|
#define IDC_ENTERADR 1063
|
||||||
#define IDC_ENTERADR 1064
|
#define IDC_DEBUG_MEM 1064
|
||||||
#define IDC_DEBUG_MEM 1065
|
#define IDC_DEBUG_MEM_ADDR 1065
|
||||||
#define IDC_DEBUG_MEM_ADDR 1066
|
#define IDC_DEBUG_MEM_COL0 1066
|
||||||
#define IDC_DEBUG_MEM_COL0 1067
|
#define IDC_DEBUG_MEM_COL1 1067
|
||||||
#define IDC_DEBUG_MEM_COL1 1068
|
#define IDC_DEBUG_MEM_COL2 1068
|
||||||
#define IDC_DEBUG_MEM_COL2 1069
|
#define IDC_DEBUG_MEM_COL3 1069
|
||||||
#define IDC_DEBUG_MEM_COL3 1070
|
#define IDC_DEBUG_MEM_COL4 1070
|
||||||
#define IDC_DEBUG_MEM_COL4 1071
|
#define IDC_DEBUG_MEM_COL5 1071
|
||||||
#define IDC_DEBUG_MEM_COL5 1072
|
#define IDC_DEBUG_MEM_COL6 1072
|
||||||
#define IDC_DEBUG_MEM_COL6 1073
|
#define IDC_DEBUG_MEM_COL7 1073
|
||||||
#define IDC_DEBUG_MEM_COL7 1074
|
#define IDC_DEBUG_MEM_TEXT 1074
|
||||||
#define IDC_DEBUG_MEM_TEXT 1075
|
#define IDC_DEBUG_STACK 1075
|
||||||
#define IDC_DEBUG_STACK 1076
|
#define IDC_STATIC_BREAKPOINT 1076
|
||||||
#define IDC_STATIC_BREAKPOINT 1077
|
#define IDC_BREAKEDIT_ADD 1077
|
||||||
#define IDC_BREAKEDIT_ADD 1078
|
#define IDC_BREAKEDIT_DELETE 1078
|
||||||
#define IDC_BREAKEDIT_DELETE 1079
|
#define IDC_BREAKEDIT_WND 1079
|
||||||
#define IDC_BREAKEDIT_WND 1080
|
#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_NEW 40001
|
||||||
#define ID_FILE_OPEN 40002
|
#define ID_FILE_OPEN 40002
|
||||||
#define ID_FILE_SAVE 40003
|
#define ID_FILE_SAVE 40003
|
||||||
|
@ -120,31 +139,34 @@
|
||||||
#define ID_STACK_PASTE 40020
|
#define ID_STACK_PASTE 40020
|
||||||
#define ID_TOOL_DISASM 40021
|
#define ID_TOOL_DISASM 40021
|
||||||
#define ID_TOOL_DEBUG 40022
|
#define ID_TOOL_DEBUG 40022
|
||||||
#define ID_DEBUG_RUN 40024
|
#define ID_DEBUG_RUN 40023
|
||||||
#define ID_DEBUG_STEP 40025
|
#define ID_DEBUG_STEP 40024
|
||||||
#define ID_DEBUG_STEPOVER 40026
|
#define ID_DEBUG_STEPOVER 40025
|
||||||
#define ID_DEBUG_BREAK 40027
|
#define ID_DEBUG_BREAK 40026
|
||||||
|
#define ID_DEBUG_STEPOUT 40027
|
||||||
#define ID_BREAKPOINTS_SETBREAK 40028
|
#define ID_BREAKPOINTS_SETBREAK 40028
|
||||||
#define ID_BREAKPOINTS_CODEEDIT 40029
|
#define ID_BREAKPOINTS_CODEEDIT 40029
|
||||||
#define ID_BREAKPOINTS_CLEARALL 40030
|
#define ID_BREAKPOINTS_CLEARALL 40030
|
||||||
#define ID_DEBUG_CODE_GOADR 40031
|
#define ID_BREAKPOINTS_NOP3 40031
|
||||||
#define ID_DEBUG_CODE_GOPC 40032
|
#define ID_BREAKPOINTS_RPL 40032
|
||||||
#define ID_DEBUG_CODE_SETPCTOSELECT 40033
|
#define ID_DEBUG_CODE_GOADR 40033
|
||||||
#define ID_DEBUG_MEM_GOADR 40034
|
#define ID_DEBUG_CODE_GOPC 40034
|
||||||
#define ID_DEBUG_MEM_GOPC 40035
|
#define ID_DEBUG_CODE_SETPCTOSELECT 40035
|
||||||
#define ID_DEBUG_MEM_GOD0 40036
|
#define ID_DEBUG_MEM_GOADR 40036
|
||||||
#define ID_DEBUG_MEM_GOD1 40037
|
#define ID_DEBUG_MEM_GOPC 40037
|
||||||
#define ID_DEBUG_MEM_GOSTACK 40038
|
#define ID_DEBUG_MEM_GOD0 40038
|
||||||
#define ID_BREAKPOINTS_NOP3 40039
|
#define ID_DEBUG_MEM_GOD1 40039
|
||||||
#define ID_DEBUG_STEPOUT 40040
|
#define ID_DEBUG_MEM_GOSTACK 40040
|
||||||
|
#define ID_INFO_LASTINSTRUCTIONS 40041
|
||||||
|
#define ID_INTR_STEPOVERINT 40042
|
||||||
|
|
||||||
// Next default values for new objects
|
// Next default values for new objects
|
||||||
//
|
//
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 117
|
#define _APS_NEXT_RESOURCE_VALUE 116
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40041
|
#define _APS_NEXT_COMMAND_VALUE 40043
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1081
|
#define _APS_NEXT_CONTROL_VALUE 1101
|
||||||
#define _APS_NEXT_SYMED_VALUE 108
|
#define _APS_NEXT_SYMED_VALUE 108
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Emu48.h"
|
#include "Emu48.h"
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
//| 38G | 48SX | 48GX | 49G | Name
|
//| 38G | 48SX | 48GX | 49G | Name
|
||||||
// #7056A #806E9 #806E9 =TEMPOB
|
// #7056A #806E9 #806E9 =TEMPOB
|
||||||
|
@ -24,6 +25,36 @@
|
||||||
#define AVMEM ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x7066E:0x807ED):0x80E9B)
|
#define AVMEM ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x7066E:0x807ED):0x80E9B)
|
||||||
#define INTRPPTR ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x705B0:0x8072F):0x8076B)
|
#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)
|
DWORD RPL_SkipOb(DWORD d)
|
||||||
{
|
{
|
||||||
BYTE X[8];
|
BYTE X[8];
|
||||||
|
@ -246,6 +277,7 @@ DWORD RPL_Pick(UINT l)
|
||||||
|
|
||||||
_ASSERT(l > 0); // first stack elememt is one
|
_ASSERT(l > 0); // first stack elememt is one
|
||||||
if (l==0) return 0;
|
if (l==0) return 0;
|
||||||
|
if (METAKERNEL) ++l; // Metakernel support
|
||||||
stkp = Read5(DSKTOP) + (l-1)*5;
|
stkp = Read5(DSKTOP) + (l-1)*5;
|
||||||
return Read5(stkp);
|
return Read5(stkp);
|
||||||
}
|
}
|
||||||
|
@ -256,6 +288,7 @@ VOID RPL_Replace(DWORD n)
|
||||||
DWORD stkp;
|
DWORD stkp;
|
||||||
|
|
||||||
stkp = Read5(DSKTOP);
|
stkp = Read5(DSKTOP);
|
||||||
|
if (METAKERNEL) stkp+=5; // Metakernel support
|
||||||
Write5(stkp,n);
|
Write5(stkp,n);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -264,14 +297,23 @@ VOID RPL_Replace(DWORD n)
|
||||||
VOID RPL_Push(DWORD n)
|
VOID RPL_Push(DWORD n)
|
||||||
{
|
{
|
||||||
DWORD stkp, avmem;
|
DWORD stkp, avmem;
|
||||||
|
|
||||||
avmem = Read5(AVMEM); // amount of free memory
|
avmem = Read5(AVMEM); // amount of free memory
|
||||||
if (avmem==0) return; // no memory free
|
if (avmem==0) return; // no memory free
|
||||||
avmem--; // fetch memory
|
avmem--; // fetch memory
|
||||||
Write5(AVMEM,avmem); // save new amount of free memory
|
Write5(AVMEM,avmem); // save new amount of free memory
|
||||||
stkp = Read5(DSKTOP); // get pointer to stack level 1
|
stkp = Read5(DSKTOP); // get pointer to stack level 1
|
||||||
stkp-=5; // fetch new stack entry
|
if (METAKERNEL) // Metakernel running ?
|
||||||
Write5(stkp,n); // save pointer to new object on stack level 1
|
{
|
||||||
|
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
|
Write5(DSKTOP,stkp); // save new pointer to stack level 1
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,34 +8,32 @@
|
||||||
*/
|
*/
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Emu48.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))
|
#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 NINT2ERBZ ((Chipset.IORam[IOC] & ERBZ) != 0 && (Chipset.IORam[RCS] & RBZ) != 0)
|
||||||
#define NINT2ERBF ((Chipset.IORam[IOC] & ERBF) != 0 && (Chipset.IORam[RCS] & RBF) != 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 NINT2ETBE ((Chipset.IORam[IOC] & ETBE) != 0 && (Chipset.IORam[TCS] & TBF) == 0)
|
||||||
|
|
||||||
#define NINT2USRQ (NINT2ERBZ || NINT2ERBF || NINT2ETBE)
|
#define NINT2USRQ (NINT2ERBZ || NINT2ERBF || NINT2ETBE)
|
||||||
|
|
||||||
static OVERLAPPED os = { 0 };
|
|
||||||
static HANDLE hComm = NULL;
|
static HANDLE hComm = NULL;
|
||||||
static HANDLE hCThread = NULL;
|
static HANDLE hCThread = NULL;
|
||||||
static DWORD lSerialThreadId = 0;
|
static DWORD lSerialThreadId = 0;
|
||||||
static BOOL bReading = TRUE;
|
|
||||||
static WORD wPort = PORT_CLOSE;
|
static WORD wPort = PORT_CLOSE;
|
||||||
|
|
||||||
|
static BOOL bReading;
|
||||||
static BYTE cBuffer[128];
|
static BYTE cBuffer[128];
|
||||||
static WORD nRp;
|
static WORD nRp;
|
||||||
static DWORD dwBytesRead = 0L;
|
static DWORD dwBytesRead = 0L;
|
||||||
|
|
||||||
// static CRITICAL_SECTION csRecv; // 24.10.99 cg, moved to main function
|
|
||||||
|
|
||||||
static DWORD WINAPI SerialThread(LPVOID pParam)
|
static DWORD WINAPI SerialThread(LPVOID pParam)
|
||||||
{
|
{
|
||||||
DWORD dwEvent;
|
DWORD dwEvent;
|
||||||
SetCommMask(hComm,EV_RXCHAR); // event on RX
|
|
||||||
|
bReading = TRUE; // flag for SerialThread started
|
||||||
while (bReading)
|
while (bReading)
|
||||||
{
|
{
|
||||||
_ASSERT(hComm != NULL);
|
_ASSERT(hComm != NULL);
|
||||||
|
@ -83,16 +81,16 @@ VOID CommOpen(LPSTR strWirePort,LPSTR strIrPort)
|
||||||
|
|
||||||
if(hComm != INVALID_HANDLE_VALUE)
|
if(hComm != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
// InitializeCriticalSection(&csRecv);
|
|
||||||
|
|
||||||
wPort = (Chipset.IORam[IR_CTRL] & EIRU) ? PORT_IR : PORT_WIRE;
|
wPort = (Chipset.IORam[IR_CTRL] & EIRU) ? PORT_IR : PORT_WIRE;
|
||||||
SetCommTimeouts(hComm,&CommTimeouts);
|
SetCommTimeouts(hComm,&CommTimeouts);
|
||||||
CommSetBaud();
|
CommSetBaud();
|
||||||
|
|
||||||
// set event RXD handler
|
// 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);
|
hCThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&SerialThread,NULL,0,&lSerialThreadId);
|
||||||
_ASSERT(lSerialThreadId);
|
_ASSERT(lSerialThreadId);
|
||||||
|
while (!bReading) Sleep(0); // wait for SerialThread started
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
hComm = NULL;
|
hComm = NULL;
|
||||||
|
@ -112,6 +110,7 @@ VOID CommClose(VOID)
|
||||||
{
|
{
|
||||||
if (hComm != NULL) // port open
|
if (hComm != NULL) // port open
|
||||||
{
|
{
|
||||||
|
Sleep(25); // workaround to fix problems with some Kermit server
|
||||||
bReading = FALSE; // kill read thread
|
bReading = FALSE; // kill read thread
|
||||||
SetCommMask(hComm,0L); // clear all events and force WaitCommEvent to return
|
SetCommMask(hComm,0L); // clear all events and force WaitCommEvent to return
|
||||||
while (lSerialThreadId != 0) Sleep(0); // wait for termination
|
while (lSerialThreadId != 0) Sleep(0); // wait for termination
|
||||||
|
@ -120,7 +119,6 @@ VOID CommClose(VOID)
|
||||||
#if defined DEBUG_SERIAL
|
#if defined DEBUG_SERIAL
|
||||||
OutputDebugString("COM port closed.\n");
|
OutputDebugString("COM port closed.\n");
|
||||||
#endif
|
#endif
|
||||||
// DeleteCriticalSection(&csRecv);
|
|
||||||
wPort = PORT_CLOSE;
|
wPort = PORT_CLOSE;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -165,7 +163,7 @@ VOID CommSetBaud(VOID)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID UpdateUSRQ(VOID) // 25.10.99 cg, new, USRQ handling
|
VOID UpdateUSRQ(VOID) // USRQ handling
|
||||||
{
|
{
|
||||||
IOBit(SRQ1,USRQ,NINT2USRQ); // update USRQ bit
|
IOBit(SRQ1,USRQ,NINT2USRQ); // update USRQ bit
|
||||||
return;
|
return;
|
||||||
|
@ -173,7 +171,8 @@ VOID UpdateUSRQ(VOID) // 25.10.99 cg, new, USRQ handling
|
||||||
|
|
||||||
VOID CommTransmit(VOID)
|
VOID CommTransmit(VOID)
|
||||||
{
|
{
|
||||||
DWORD dwWritten;
|
OVERLAPPED os = { 0 };
|
||||||
|
DWORD dwWritten;
|
||||||
|
|
||||||
BYTE tbr = (Chipset.IORam[TBR_MSB] << 4) | Chipset.IORam[TBR_LSB];
|
BYTE tbr = (Chipset.IORam[TBR_MSB] << 4) | Chipset.IORam[TBR_LSB];
|
||||||
|
|
||||||
|
@ -188,7 +187,6 @@ VOID CommTransmit(VOID)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 23.10.99 cg, bugfix, add serial loopback support
|
|
||||||
if (Chipset.IORam[TCS] & LPB) // is loopback bit set
|
if (Chipset.IORam[TCS] & LPB) // is loopback bit set
|
||||||
{
|
{
|
||||||
cBuffer[nRp+dwBytesRead] = tbr; // save character in receive buffer
|
cBuffer[nRp+dwBytesRead] = tbr; // save character in receive buffer
|
||||||
|
@ -196,13 +194,17 @@ VOID CommTransmit(VOID)
|
||||||
|
|
||||||
CommReceive(); // receive byte available
|
CommReceive(); // receive byte available
|
||||||
}
|
}
|
||||||
// 23.10.99 cg, end of implementation
|
|
||||||
|
|
||||||
if (hComm != NULL) // com port open
|
if (hComm != NULL) // com port open
|
||||||
|
{
|
||||||
|
os.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||||
WriteFile(hComm,(LPCVOID) &tbr,1,&dwWritten,&os);
|
WriteFile(hComm,(LPCVOID) &tbr,1,&dwWritten,&os);
|
||||||
|
GetOverlappedResult(hComm,&os,&dwWritten,TRUE);
|
||||||
|
CloseHandle(os.hEvent);
|
||||||
|
}
|
||||||
|
|
||||||
Chipset.IORam[TCS] &= (~TBF); // clear transmit buffer
|
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
|
if (Chipset.IORam[IOC] & ETBE) // interrupt on transmit buffer empty
|
||||||
INTERRUPT;
|
INTERRUPT;
|
||||||
return;
|
return;
|
||||||
|
@ -210,6 +212,8 @@ VOID CommTransmit(VOID)
|
||||||
|
|
||||||
VOID CommReceive(VOID)
|
VOID CommReceive(VOID)
|
||||||
{
|
{
|
||||||
|
OVERLAPPED os = { 0 };
|
||||||
|
|
||||||
if (!(Chipset.IORam[IOC] & SON)) // UART off
|
if (!(Chipset.IORam[IOC] & SON)) // UART off
|
||||||
{
|
{
|
||||||
dwBytesRead = 0L; // no bytes received
|
dwBytesRead = 0L; // no bytes received
|
||||||
|
@ -222,7 +226,7 @@ VOID CommReceive(VOID)
|
||||||
if (Chipset.IORam[RCS] & RBF) // receive buffer full
|
if (Chipset.IORam[RCS] & RBF) // receive buffer full
|
||||||
break;
|
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 (hComm && dwBytesRead == 0L) // com port open and buffer empty
|
||||||
{
|
{
|
||||||
if(ReadFile(hComm,&cBuffer,sizeof(cBuffer),&dwBytesRead,&os) == FALSE)
|
if(ReadFile(hComm,&cBuffer,sizeof(cBuffer),&dwBytesRead,&os) == FALSE)
|
||||||
|
@ -251,7 +255,7 @@ VOID CommReceive(VOID)
|
||||||
--dwBytesRead;
|
--dwBytesRead;
|
||||||
|
|
||||||
Chipset.IORam[RCS] |= RBF; // receive buffer full
|
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
|
if (Chipset.IORam[IOC] & ERBF) // interrupt on recv buffer full
|
||||||
INTERRUPT;
|
INTERRUPT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
*/
|
*/
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Emu48.h"
|
#include "Emu48.h"
|
||||||
|
#include "i28f160.h"
|
||||||
|
|
||||||
#define EMU48_INI "Emu48.ini"
|
#define EMU48_INI "Emu48.ini"
|
||||||
|
|
||||||
|
@ -31,14 +32,19 @@ VOID ReadSettings(VOID)
|
||||||
GetPrivateProfileString("Port2","Filename","SHARED.BIN",szPort2Filename,sizeof(szPort2Filename),EMU48_INI);
|
GetPrivateProfileString("Port2","Filename","SHARED.BIN",szPort2Filename,sizeof(szPort2Filename),EMU48_INI);
|
||||||
// KML
|
// KML
|
||||||
bAlwaysDisplayLog = GetPrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI);
|
bAlwaysDisplayLog = GetPrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI);
|
||||||
|
// Disassebler
|
||||||
|
disassembler_mode = GetPrivateProfileInt("Disassembler","Mnemonics",disassembler_mode,EMU48_INI);
|
||||||
// Emulator
|
// Emulator
|
||||||
bRealSpeed = GetPrivateProfileInt("Emulator","RealSpeed",0,EMU48_INI);
|
bRealSpeed = GetPrivateProfileInt("Emulator","RealSpeed",0,EMU48_INI);
|
||||||
dwSXCycles = GetPrivateProfileInt("Emulator","SXCycles",82,EMU48_INI);
|
dwSXCycles = GetPrivateProfileInt("Emulator","SXCycles",dwSXCycles,EMU48_INI);
|
||||||
dwGXCycles = GetPrivateProfileInt("Emulator","GXCycles",123,EMU48_INI);
|
dwGXCycles = GetPrivateProfileInt("Emulator","GXCycles",dwGXCycles,EMU48_INI);
|
||||||
SetSpeed(bRealSpeed); // set speed
|
SetSpeed(bRealSpeed); // set speed
|
||||||
// Serial
|
// Serial
|
||||||
GetPrivateProfileString("Serial","Wire",NO_SERIAL,szSerialWire,sizeof(szSerialWire),EMU48_INI);
|
GetPrivateProfileString("Serial","Wire",NO_SERIAL,szSerialWire,sizeof(szSerialWire),EMU48_INI);
|
||||||
GetPrivateProfileString("Serial","Ir",NO_SERIAL,szSerialIr,sizeof(szSerialIr),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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +59,8 @@ VOID WriteSettings(VOID)
|
||||||
WritePrivateProfileString("Port2","Filename",szPort2Filename,EMU48_INI);
|
WritePrivateProfileString("Port2","Filename",szPort2Filename,EMU48_INI);
|
||||||
// KML
|
// KML
|
||||||
WritePrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI);
|
WritePrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI);
|
||||||
|
// Disassebler
|
||||||
|
WritePrivateProfileInt("Disassembler","Mnemonics",disassembler_mode,EMU48_INI);
|
||||||
// Emulator
|
// Emulator
|
||||||
WritePrivateProfileInt("Emulator","RealSpeed",bRealSpeed,EMU48_INI);
|
WritePrivateProfileInt("Emulator","RealSpeed",bRealSpeed,EMU48_INI);
|
||||||
WritePrivateProfileInt("Emulator","SXCycles",dwSXCycles,EMU48_INI);
|
WritePrivateProfileInt("Emulator","SXCycles",dwSXCycles,EMU48_INI);
|
||||||
|
@ -60,6 +68,8 @@ VOID WriteSettings(VOID)
|
||||||
// Serial
|
// Serial
|
||||||
WritePrivateProfileString("Serial","Wire",szSerialWire,EMU48_INI);
|
WritePrivateProfileString("Serial","Wire",szSerialWire,EMU48_INI);
|
||||||
WritePrivateProfileString("Serial","Ir",szSerialIr,EMU48_INI);
|
WritePrivateProfileString("Serial","Ir",szSerialIr,EMU48_INI);
|
||||||
|
// ROM
|
||||||
|
WritePrivateProfileInt("ROM","Writeable",bRomWriteable,EMU48_INI);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*/
|
*/
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Emu48.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'
|
#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 uT1TimerId = 0;
|
||||||
static UINT uT2TimerId = 0;
|
static UINT uT2TimerId = 0;
|
||||||
|
|
||||||
static BOOL bNINT2T1 = FALSE; // 24.10.99 cg, new, state of NINT2 affected form Timer1
|
static BOOL bNINT2T1 = FALSE; // state of NINT2 affected from timer1
|
||||||
static BOOL bNINT2T2 = FALSE; // 24.10.99 cg, new, state of NINT2 affected form Timer2
|
static BOOL bNINT2T2 = FALSE; // state of NINT2 affected from timer2
|
||||||
|
|
||||||
static BOOL bAccurateTimer; // flag if accurate timer is used
|
static BOOL bAccurateTimer; // flag if accurate timer is used
|
||||||
static LARGE_INTEGER lT2Ref; // counter value at timer2 start
|
static LARGE_INTEGER lT2Ref; // counter value at timer2 start
|
||||||
static TIMECAPS tc; // timer information
|
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 __inline MAX(int a, int b) {return (a>b)?a:b;}
|
||||||
|
|
||||||
static void CALLBACK TimeProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2);
|
static void 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
|
DWORD dwT2 = Chipset.t2; // get value from chipset
|
||||||
if (bStarted) // timer2 running
|
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;
|
LARGE_INTEGER lT2Act;
|
||||||
|
DWORD dwT2Dif;
|
||||||
|
|
||||||
QueryPerformanceCounter(&lT2Act); // actual time
|
QueryPerformanceCounter(&lT2Act); // actual time
|
||||||
// calculate ticks since reference point
|
// calculate ticks since reference point
|
||||||
dwT2 -= (DWORD)
|
dwT2 -= (DWORD)
|
||||||
(((lT2Act.QuadPart - lT2Ref.QuadPart) * T2_FREQ)
|
(((lT2Act.QuadPart - lT2Ref.QuadPart) * T2_FREQ)
|
||||||
/ lFreq.QuadPart);
|
/ 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;
|
return dwT2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID CheckT1(BYTE nT1)
|
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;
|
bNINT2T1 = (Chipset.IORam[TIMER1_CTRL]&INTR) != 0 && (nT1&8) != 0;
|
||||||
IOBit(SRQ1,TSRQ,bNINT2T1 || bNINT2T2);
|
IOBit(SRQ1,TSRQ,bNINT2T1 || bNINT2T2);
|
||||||
// 24.10.99 cg, end of implementation
|
|
||||||
|
|
||||||
if ((nT1&8) == 0) // timer1 MSB not set
|
if ((nT1&8) == 0) // timer1 MSB not set
|
||||||
{
|
{
|
||||||
|
@ -94,10 +125,9 @@ static VOID CheckT1(BYTE nT1)
|
||||||
|
|
||||||
static VOID CheckT2(DWORD dwT2)
|
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;
|
bNINT2T2 = (Chipset.IORam[TIMER2_CTRL]&INTR) != 0 && (dwT2&0x80000000) != 0;
|
||||||
IOBit(SRQ1,TSRQ,bNINT2T1 || bNINT2T2);
|
IOBit(SRQ1,TSRQ,bNINT2T1 || bNINT2T2);
|
||||||
// 24.10.99 cg, end of implementation
|
|
||||||
|
|
||||||
if ((dwT2&0x80000000) == 0) // timer2 MSB not set
|
if ((dwT2&0x80000000) == 0) // timer2 MSB not set
|
||||||
{
|
{
|
||||||
|
@ -134,6 +164,7 @@ static VOID RescheduleT2(BOOL bRefPoint)
|
||||||
_ASSERT(uT2TimerId == 0); // timer2 must stopped
|
_ASSERT(uT2TimerId == 0); // timer2 must stopped
|
||||||
if (bRefPoint) // save reference time
|
if (bRefPoint) // save reference time
|
||||||
{
|
{
|
||||||
|
bT2Val = FALSE; // init thread interrupt workaround
|
||||||
QueryPerformanceCounter(&lT2Ref); // time of corresponding Chipset.t2 value
|
QueryPerformanceCounter(&lT2Ref); // time of corresponding Chipset.t2 value
|
||||||
uDelay = Chipset.t2; // timer value for delay
|
uDelay = Chipset.t2; // timer value for delay
|
||||||
}
|
}
|
||||||
|
@ -273,10 +304,9 @@ VOID StartTimers(VOID)
|
||||||
if (Chipset.IORam[TIMER2_CTRL]&RUN) // start timer1 and timer2 ?
|
if (Chipset.IORam[TIMER2_CTRL]&RUN) // start timer1 and timer2 ?
|
||||||
{
|
{
|
||||||
bStarted = TRUE; // flag timer running
|
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;
|
bNINT2T1 = (Chipset.IORam[TIMER1_CTRL]&INTR) != 0 && (Chipset.t1 & 8) != 0;
|
||||||
bNINT2T2 = (Chipset.IORam[TIMER2_CTRL]&INTR) != 0 && (Chipset.t2 & 0x80000000) != 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"
|
// set timer resolution to 1 ms, if failed don't use "Accurate timer"
|
||||||
bAccurateTimer = (timeBeginPeriod(1) == TIMERR_NOERROR);
|
bAccurateTimer = (timeBeginPeriod(1) == TIMERR_NOERROR);
|
||||||
timeGetDevCaps(&tc,sizeof(tc)); // get timer resolution
|
timeGetDevCaps(&tc,sizeof(tc)); // get timer resolution
|
||||||
|
|
|
@ -7,15 +7,21 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define SWORD SHORT // 09.12.99 cg, new, signed 16 Bit variable
|
// HST bits
|
||||||
#define QWORD ULONGLONG // 22.11.99 cg, new, unsigned 64 Bit variable
|
#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
|
#define CHIPSET Chipset_t
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SWORD nPosX; // 09.12.99 cg, bugfix, is a signed number
|
SWORD nPosX; // position of window
|
||||||
SWORD nPosY; // 09.12.99 cg, bugfix, is a signed number
|
SWORD nPosY;
|
||||||
BYTE type;
|
BYTE type; // calculator type
|
||||||
|
|
||||||
DWORD Port0Size; // real size of module in KB
|
DWORD Port0Size; // real size of module in KB
|
||||||
DWORD Port1Size; // real size of module in KB
|
DWORD Port1Size; // real size of module in KB
|
||||||
|
@ -53,14 +59,17 @@ typedef struct
|
||||||
|
|
||||||
WORD crc;
|
WORD crc;
|
||||||
WORD wPort2Crc; // fingerprint of port2
|
WORD wPort2Crc; // fingerprint of port2
|
||||||
WORD wRomCrc; // 20.11.99 cg, new, fingerprint of ROM
|
WORD wRomCrc; // fingerprint of ROM
|
||||||
// QWORD cycles; // 22.11.99 cg, changed, oscillator cycles
|
#if defined _USRDLL // DLL version
|
||||||
DWORD cycles; // 22.11.99 cg, moved, oscillator cycles
|
QWORD cycles; // oscillator cycles
|
||||||
DWORD cycles_reserved; // 22.11.99 cg, reserved for MSB of oscillator cycles
|
#else // EXE version
|
||||||
DWORD dwKdnCycles; // 22.11.99 cg, moved, cpu cycles at start of 1ms key handler
|
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 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 cards_status;
|
||||||
BYTE IORam[64]; // I/O hardware register
|
BYTE IORam[64]; // I/O hardware register
|
||||||
UINT IOBase; // address of I/O modules page
|
UINT IOBase; // address of I/O modules page
|
||||||
|
@ -74,7 +83,7 @@ typedef struct
|
||||||
BYTE t1;
|
BYTE t1;
|
||||||
DWORD t2;
|
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];
|
BYTE Keyboard_Row[9];
|
||||||
WORD IR15X;
|
WORD IR15X;
|
||||||
|
|
Loading…
Reference in a new issue