2002-03-24: Updated to version 1.30

This commit is contained in:
Gwenhael Le Moine 2024-03-19 22:37:54 +01:00
parent 5f619b11ab
commit 5eac6ac58d
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
54 changed files with 2992 additions and 2127 deletions

View file

@ -1 +1,2 @@
;01477:6300; disable 10 min auto off (internal, undocumented)
017A6:81B1; =makebeep 017A6:81B1; =makebeep

Binary file not shown.

View file

@ -1,11 +1,11 @@
Debugger in Emu48/Tools/Debugger... Debugger in Emu48/Tools/Debugger...
----------------------------------- -----------------------------------
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. This is a short description of the internal assembly debugger of Emu48.
The debugger was designed to help customers 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 customers inspecting assembler code objects, a part that cannot be handled satisfactorily by the JAZZ package. Thanks to Mika Heiskanen and all the others supporting this great program.
After starting the debugger the emulation will stop at the current PC position. The emulation will continue after closing the debugger window. Please remember that the clock now shows the wrong time. After starting the debugger the emulation will stop at the current program counter position. The emulation will continue after closing the debugger window. Please remember that the clock now shows the wrong time.
1.) Menu Debug 1.) Menu Debug
@ -16,7 +16,7 @@ Continue calculator emulation under debugger control. The emulation will stop at
- Run to Cursor F6 - Run to Cursor F6
Execute program until address at cursor position is reached. Code and memory breakpoints are still active and may stop execution before. Execute program until address at cursor position is reached. Breakpoints are still active and may stop execution before.
- Step Into F7 - Step Into F7
@ -66,18 +66,18 @@ So be careful using the F9 key.
- Break F11 - Break F11
Stop the emulation at the current program counter position. Stops the emulation at the current program counter position.
2.) Menu Breakpoints 2.) Menu Breakpoints
- Set Breakpoint F2 - Set Breakpoint F2
Toggle a code breakpoint at the cursor position in the code window. 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 and memory breakpoints. When the breakpoint is checked it's enabled otherwise it's disabled. With "Add" you can add a new or enable an existing breakpoint, with "Delete" you can delete the selected ones. Addresses greater than #FFFFF are cut after the fifths nibble. When adding a new breakpoint, you must select if this is a "Code", "RPL", "Memory Access", "Memory Read" or "Memory Write" breakpoint. You get a sorted list of all current breakpoints. When the breakpoint is checked it's enabled otherwise it's disabled. With "Add" you can add a new or enable an existing breakpoint, with "Delete" you can delete the selected ones. Addresses greater than #FFFFF are cut after the fifths nibble. When adding a new breakpoint, you must select if this is a "Code", "RPL", "Memory Access", "Memory Read" or "Memory Write" breakpoint.
- "Code" stop before opcode execution on this address - "Code" stop before opcode execution on this address
- "RPL" stop on the first opcode of the selected RPL address - "RPL" stop on the first opcode of the selected RPL address
@ -85,11 +85,11 @@ You get a sorted list of the current code and memory breakpoints. When the break
- "Memory Read" stop before reading the selected address - "Memory Read" stop before reading the selected address
- "Memory Write" stop before writing to the selected address - "Memory Write" stop before writing to the selected address
With a left mouse button double click on a breakpoint you can toggle the check box inside. With a left mouse button double click on a breakpoint or using the space key on a selected breakpoint you can toggle the check box inside.
- Clear All Breakpoints - Clear All Breakpoints
Clear all breakpoints except the NOP3 ones. Clear all address specific breakpoints.
- NOP3 Code Breakpoints - NOP3 Code Breakpoints
@ -105,7 +105,7 @@ and
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 how to use a NOP3 Code breakpoint:
ASSEMBLE ASSEMBLE
NIBASC /HPHP48-E/ NIBASC /HPHP48-E/
@ -129,7 +129,7 @@ ENDCODE
- CODE Object Breakpoints - CODE Object Breakpoints
If this item is checked, the debugger stops program execution at the first instruction of every DOCODE object which isn't located in ROM. For inspecting DOCODE objects in ROM use the static CODE breakpoints instead please. If this item is checked, the debugger stops program execution at the first instruction of every DOCODE object which isn't located in ROM. For inspecting DOCODE objects in ROM use address CODE breakpoints instead please.
- RPL Breakpoints - RPL Breakpoints
@ -140,7 +140,7 @@ If this item is checked, the debugger stops program execution on every instructi
- Step Over 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 couldn't executed in single step any more. Code and memory breakpoints are still active. 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 couldn't executed in single step any more. Enabled 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" for stopping the debugger behind the RTI instruction, and uncheck this option again. You can also use this option if you want to quit the interrupt handler. Just check this option, press F7 for "Step Into" for stopping the debugger behind the RTI instruction, and uncheck this option again.
@ -151,10 +151,14 @@ You can also use this option if you want to quit the interrupt handler. Just che
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. In the "Last Instructions" dialog you can copy selected lines to the clipboard or clear this list. 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. In the "Last Instructions" dialog you can copy selected lines to the clipboard or clear this list.
- Write Only Registers...
Some of the display registers have a different meaning on reading and writing. This dialog shows the data written to the write only I/O registers.
5.) Code window 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 "->" or "-R" between the address and the disassembly.
You can use the UP, PAGE UP, DOWN and PAGE DOWN keys to scroll the window content. There is one strange behavior, when you move to higher addresses the debugger is able to disassemble the next line correctly, but when you move to cursor to lower addresses the debugger does not know if this address is at the begin or inside of an opcode. In result you get wrong disassembled lines. You can use the UP, PAGE UP, DOWN and PAGE DOWN keys to scroll the window content. There is one strange behavior, when you move to higher addresses the debugger is able to disassemble the next line correctly, but when you move to cursor to lower addresses the debugger does not know if this address is at the begin or inside of an opcode. In result you get wrong disassembled lines.
@ -170,7 +174,7 @@ Sets the cursor to the actual position of the PC.
- Set breakpoint F2 - Set breakpoint F2
Toggle a code breakpoint at the cursor position in the code window. Toggle a code breakpoint at the cursor position in the Code window.
- Set PC to selection - Set PC to selection
@ -186,9 +190,9 @@ With the left mouse button you change the content of the register. On bit regist
7.) Memory window 7.) Memory window
This windows shows the memory content. This windows shows the memory content in the selected context.
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 (only in Map mode) you can change the content of the two addresses. When the memory position is read only (ROM or write protected RAM) the content wouldn't change.
Context menu pressing the right mouse button: Context menu pressing the right mouse button:
@ -214,17 +218,60 @@ Sets the cursor to the return address placed in the top level of the stack.
- Find... F - Find... F
Calls the "Find" dialog box, allowing you to search for a data sequence in hexadecimal or ASCII mode. The search area is restricted to the mapped CPU address area, so it isn't possible to access hidden memory. When you close the "Find" dialog box, you will loose all saved strings in the data combo box. Calls the "Find" dialog box, allowing you to search for a data sequence in hexadecimal or ASCII mode. The search area is selected by the memory view Mapping mode described in the following section. When you close the "Find" dialog box, you will loose all saved strings in the data combo box.
- Mapping
Mapping is a Pop-up menu to select the memory view of the Memory window. Normally the CPU see only 512KB of the total memory, the rest is banked or covered by other modules. The following menu entries select the memory chip connected with the chosen Chip Select signal of the MMU. The connections are calculator model dependent.
- Mapping Map
This is the default mode. Here the Memory window shows what the CPU see. In this mode you can also change the memory content of writeable memory.
- Mapping NCE1/NCE2/CE1/CE2/NCE3
Here the Memory window shows the content of the selected Chip Select signal. The content is showed in a linear address model and it's content can't be changed in this mode.
Here's a comparison of the mapping of the emulated calculator models:
Abbreviations: ROM = Read Only Memory
RAM = Random Access Memory
Flash = electrical reprogramming ROM
Slt = Memory Card Slot
BS = Bank Switcher (no memory)
nc. = not connected
| HP38G | HP39/40G | HP48S/SX | HP48G/G+/GX | HP49G
-----------------------------------------------------------------------------
NCE1 | ROM 512KB | ROM 1024KB | ROM 256KB | ROM 512KB | Flash 2048KB
NCE2 | RAM 32KB | RAM 128KB | RAM 32KB | RAM 32/128KB | RAM 256KB
CE1 | nc. | BS | Slt1 32/128KB | BS | BS
CE2 | nc. | nc. | Slt2 32/128KB | Slt1 32/128KB | RAM 128KB
NCE3 | nc. | RAM 128KB | nc. | Slt2 32KB-4MB | RAM 128KB
8.) Stack window 8.) Stack window
The content of the hardware stack is viewed here. In "1:" is the current return address. A double click on an item shows the address content in the code window. The content of the hardware stack is viewed here. In "1:" is the current return address. A double click on an item shows the address content in the Code window.
Context menu pressing the right mouse button:
- Push
Push a new return address at topmost element on the stack.
- Pop
Pop the topmost element form the stack.
- Modify
Modifies the stack content of the current selection.
9.) MMU window 9.) MMU window
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. The configuration of the memory controllers is viewed here. The viewed addresses are the first address of each module area and may differ from the given address in the CONFIG command.
This example This example
@ -233,7 +280,7 @@ This example
LC(5) #98765 start address of module LC(5) #98765 start address of module
CONFIG CONFIG
will config a 128KB module at address #80000 and not at the given address. So the MMU viewer will show you address #80000. will config a 128KB module at address #80000 and not at the given address. So the MMU viewer will show you the address #80000.
10.) Miscellaneous window 10.) Miscellaneous window
@ -243,4 +290,4 @@ The Miscellaneous window show you the internal state of the interrupt flag, the
You can change the values by pressing the left mouse button over the old content. You can change the values by pressing the left mouse button over the old content.
05/15/01 (c) by Christoph Gießelink, cgiess@swol.de 02/21/02 (c) by Christoph Gießelink, cgiess@swol.de

BIN
EMU48.EXE

Binary file not shown.

102
EMU48.TXT
View file

@ -2,31 +2,10 @@
Emu48 - A freeware HP38/39/40/48/49 Emulator Emu48 - A freeware HP38/39/40/48/49 Emulator
for Windows 9x, ME, NT and 2000 for Windows 9x, ME, NT, 2000 and XP
****************
* INSTALLATION *
****************
Emu48 is distributed in 1 archive:
- Emu48-1_25.zip All files and sources
To install Emu48, just unzip Emu48-1_25.zip into an empty directory. When you
first run Emu48, it will detect the directory in which you installed it, and
will write its configuration to a file named Emu48.ini in your Windows
directory. If you move the Emu48 directory to another place you have to change
the directory path inside the Emu48.ini file manually or have to delete the
Emu48.ini file.
You can also update your current version with the Unofficial Service Packs:
- E48BP2x.ZIP New EXE-File
- E48SP2x.ZIP Sources of the Service Pack
Replace the original EXE file please.
******************** ********************
* OPERATING SYSTEM * * OPERATING SYSTEM *
******************** ********************
@ -35,6 +14,27 @@ This version of Emu48 should work with all Intel Win32 platforms. You may
recompile the sources to run Emu48 with Windows NT on a DEC Alpha. recompile the sources to run Emu48 with Windows NT on a DEC Alpha.
****************
* INSTALLATION *
****************
Emu48 is distributed in 1 archive:
- Emu48-1_30.zip All files and sources
To install Emu48, just unzip Emu48-1_30.zip into an empty directory. When you
first run Emu48, it will detect the directory in which you installed it, and
will write its configuration to a file named Emu48.ini in your Windows
directory. If you move the Emu48 directory to another place you have to change
the directory path inside the Emu48.ini file manually or have to delete the
Emu48.ini file.
You can also update your current version with the Unofficial Service Packs:
- E48BP3x.ZIP New EXE-File
- E48SP3x.ZIP Sources of the Service Pack
Replace the original EXE file please.
************************ ************************
* YOU NEED A ROM IMAGE * * YOU NEED A ROM IMAGE *
************************ ************************
@ -198,23 +198,18 @@ before doing this.
* SHARED RAM CARD * * SHARED RAM CARD *
******************* *******************
You can add a SHARED (I'll explain later) ram card of up to 4MB to a HP48. By You can add a SHARED (explained below) RAM card of up to 4MB to a HP48. By
default, no such card will be created when you start Emu48. The MkShared.exe default, no such card will be created when you start Emu48. The MkShared.exe
utility will allow you to create it. utility will allow you to create it.
The syntax is: To create a Port 2 RAM Card, call the program, select the RAM Card size, enter
MkShared <filename> <size_in_kilobytes> the card file name and press the 'Create' button. That's it. Please remember,
this program replace the destination file without any request!
For example, you can create a 2MB RAM card name SHARED.BIN (in Emu48's If you use RAM cards greater than 128 KB in a HP48SX, you can only see the first
directory) with the following command: 128 KB of the card. Please remember, the firmware of all HP48GX versions has a
bug when using a 4MB RAM card. You always get the message "Warning: Invalid Card
MkShared SHARED.BIN 2048 Data" at startup and Port 33 is unaccessible. This is not a bug of the emulator!
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.
Please remember, the firmware of all HP48GX versions has a bug when using a 4MB
RAM card. You always get the message "Warning: Invalid Card Data" at startup and
Port 33 is unaccessible. This is not a bug of the emulator!
When you have created this file, run Emu48, and use the Close menu item to close When you have created this file, run Emu48, and use the Close menu item to close
the calculator state. Now select File/Settings. In the "Port 2" text area, type the calculator state. Now select File/Settings. In the "Port 2" text area, type
@ -223,17 +218,18 @@ searched for in Emu48's directory).
You can also tick the check box "Port 2 Is Shared". When the box is cleared, You can also tick the check box "Port 2 Is Shared". When the box is cleared,
only the first instance of Emu48 will allow you to use the RAM card in Port 2. only the first instance of Emu48 will allow you to use the RAM card in Port 2.
When this box is ticked, the first instance of Emu48 will give you both read and When this box is checked, the first instance of Emu48 will give you both read
write access to this RAM card. If then you start Emu48 again, the RAM card in and write access to this RAM card. If you start Emu48 in another instance, the
Port 2 will be write-protected. Thus you can transfer files very easily between RAM card in Port 2 will be write-protected. Thus you can transfer files very
two calculators. This RAM card is used by both S/SX and G/GX types. easily between two calculators. This RAM card is used by both S/SX and G/GX
types.
*********************** ***********************
* FLASH ROM EMULATION * * FLASH ROM EMULATION *
*********************** ***********************
The HP49G save the operation system a reprogramable memory, a so called flash The HP49G save the operation system in a reprogramable memory, a so called flash
memory. The flash memory is divided into two parts, into the Operating System 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. 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.49G). As default Emu48 saves the Port 2 data in the ROM file (normally ROM.49G). As default
@ -259,11 +255,11 @@ versa.
********** **********
Emu48 includes a backup feature (in the Edit menu). It save the complete state Emu48 includes a backup feature (in the Edit menu). It save the complete state
of the calculator in the computer's memory. You might want to use it before of the calculator (excepting the ROM and Port 2 content) in the computer's
doing something risky, and if you don't want to save to the disk. It provides memory. You might want to use it before doing something risky, and if you don't
some kind of Undo feature. It is also used by Emu48 when you want to save or want to save to the disk. It provides some kind of Undo feature. It is also used
load a new document, to restore its old state if you cancel the operation or of by Emu48 when you want to save or load a new document, to restore its old state
something goes wrong. if you cancel the operation or of something goes wrong.
************ ************
@ -286,8 +282,8 @@ 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
HP. On HP48 S(X) calculators the address area #00052-#00070, on all other HP. On HP48 S(X) calculators the address area #00052-#00070, on all other
emulated calculators the address area #00058-#00076 in Port 0 are rewritten with emulated calculators the address area #00058-#00076 in System RAM are rewritten
the actual time information. with the actual time information.
************* *************
@ -297,7 +293,8 @@ the actual time information.
The section [Timers] in the Emu48.ini file isn't used any more. The variable The section [Timers] in the Emu48.ini file isn't used any more. The variable
values are replaced by useful constants. You may delete this section if you values are replaced by useful constants. You may delete this section if you
want. Starting an old version of Emu48 (V1.07 and earlier) will add this section want. Starting an old version of Emu48 (V1.07 and earlier) will add this section
again. again. If you move the Emu48 directory to another place, you have to adjust the
variable 'Emu48Directory' in the [Files] section.
************************ ************************
@ -378,7 +375,7 @@ Technical data:
Servername: Emu48 Servername: Emu48
Topicname: Stack Topicname: Stack
Item: Dummy (ignored, must be a nonzero string) Item: - (ignored, must be a nonzero string)
Clipboardformat: "CF_HPOBJ" (user defined) Clipboardformat: "CF_HPOBJ" (user defined)
The DDE commands CONNECT, POKE and REQUEST are supported. The DDE commands CONNECT, POKE and REQUEST are supported.
@ -405,9 +402,8 @@ to get more information please.
* SUPPORT * * SUPPORT *
*********** ***********
We cannot provide individual support for Emu48, but we will read all the mails We cannot provide any individual support for Emu48. All informations about Emu48
that you send. All informations about Emu48 will be on the Emu48 Official will be on the Emu48 Official Homepage on the Web:
Homepage on the Web:
http://www.epita.fr/~sebc/Emu48/index.html http://www.epita.fr/~sebc/Emu48/index.html
@ -425,7 +421,7 @@ Other graphics and scripts are available at Casey's Emu48 Graphics Page:
*************** ***************
Emu48 - An HP38/39/40/48/49 Emulator Emu48 - An HP38/39/40/48/49 Emulator
Copyright (C) 2001 Sebastien Carlier & Christoph Gießelink Copyright (C) 2002 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

Binary file not shown.

View file

@ -31,8 +31,14 @@ C$ $
KINVISLF ( translate, remove all CR's; we just need LF's ) KINVISLF ( translate, remove all CR's; we just need LF's )
DROP ( drop empty string ) DROP ( drop empty string )
palparse ( get object from string, returns true or false ) palparse ( get object from string, returns true or false )
?SEMI ( if true skip to end of secondary... ) NOTcase2DROP ( if conversation fail drop two objects and quit )
2DROP ( else drop two ) DUP ( duplicate object/composite )
CARCOMP ( return first object of the composite )
' xSILENT' ( put object xSILENT' on the stack )
EQ ( compare them )
NOT?SEMI ( if false skip to end of secondary... )
TWO ( get 2nd... )
NTHCOMPDROP ( ...object behind the xSILENT' )
; ;
ZERO ( ...check if it's not a string [actually, anything] ) ZERO ( ...check if it's not a string [actually, anything] )
:: ::

View file

@ -39,4 +39,4 @@ to thank Christoph Giesselink for optimizing my program, saving about
20 bytes, as well as for correcting a major bug. The attached HP49G 20 bytes, as well as for correcting a major bug. The attached HP49G
version of this program is unsupported, use it on your own risk. version of this program is unsupported, use it on your own risk.
Revision 1.4, see http://www.hpcalc.org for updates. Revision 1.6, see http://www.hpcalc.org for updates.

Binary file not shown.

50
Emu48asc/EMU49ASC.S Normal file
View file

@ -0,0 +1,50 @@
TITLE Emu49Asc ACSII<->Bin Converter
* Author: Christoph Giesselink
ASSEMBLE
NIBASC /HPHP49-B/
* Please don't blame me if this program destroy your memory content. The
* unsupported entry points are picked up from the beta ROM v1.19-6.
* These entry points may change in future and very important, they have
* changed in past! Use it on your own risk. Adjust the lines below to
* your used ROM version.
*=SetModes EQU #4649A (ROM 1.18, 1.19-4/5)
=SetModes EQU #4A3D4 (ROM 1.19-6)
*=RadixAngle$ EQU #463CF (ROM 1.18, 1.19-4/5)
=RadixAngle$ EQU #4A309 (ROM 1.19-6)
RPL
::
CK1NoBlame
CK&DISPATCH1
THREE ( String )
::
DUP ELEVEN 1_#1-SUB$ ( get first ten characters )
$ "%%HP:" ONE POS$ ( and look for the HP string)
DUP #0=?SKIP ( if found )
::
#5+ LAST$ ( remove it from original )
DUP ";" ONE POS$ ( search for end of modes )
2DUP #1+ LAST$ ( get the rest after modes )
UNROT 1_#1-SUB$ ( get the modes string )
SetModes ( set the current mode )
;
DROP ( drop position or flag )
KINVISLF DROP ( translate string )
palparse ( decode string )
NOTcase2DROP ( on fail -> DROP2 and exit )
DUP CARCOMP ' xSILENT' EQ ( heading xSILENT' object ? )
NOT?SEMI TWO NTHCOMPDROP ( yes, remove it )
;
ZERO ( Any Object )
::
EDITDECOMP$ ( make string )
KVISLF ( translate string )
$ "%%HP:" RadixAngle$ !append$ ( build file header with modes )
$ ";\0D\0A" !append$SWAP ( and CR+LF )
!append$ ( append program )
;
;

View file

@ -1,60 +0,0 @@
Here are the MASD sources for the HP49G v1.19-4/5 version of
EMU48ASC
!NO CODE
!RPL
::
CK1NoBlame
CK&DISPATCH1
BINT3
::
DUP
BINT11
1_#1-SUB$
"%%HP:"
BINT1
POS$
DUP
#0=?SKIP
::
#5+
LAST$
DUP
";"
BINT1
POS$
2DUP
#1+
LAST$
UNROT
1_#1-SUB$
PTR 4649A
;
DROP
KINVISLF
DROP
palparse
?SEMI
2DROP
;
BINT0
::
EDITDECOMP$
KVISLF
"%%HP:"
PTR 463CF
!append$
";\0D\0A"
!append$SWAP
!append$
;
;
@
Please don't blame me if this program destroy your memory content. The
unsupported entry points are picked up from the beta ROM v1.19-4. These
entry points may change in future and very important, they have changed
in past! Use it on your own risk.
Christoph

View file

@ -9,8 +9,8 @@ Global
End End
Background Background
Offset 0 0 Offset 4 4
Size 324 703 Size 322 701
End End
Lcd Lcd

Binary file not shown.

View file

@ -1,4 +1,4 @@
Known bugs and restrictions of Emu48 V1.25 Known bugs and restrictions of Emu48 V1.30
------------------------------------------ ------------------------------------------
- the following I/O bits aren't emulated (incomplete) - the following I/O bits aren't emulated (incomplete)
@ -9,7 +9,6 @@ Known bugs and restrictions of Emu48 V1.25
CMODE (0x10A) Mode register CMODE (0x10A) Mode register
IOC (0x110) [ERBZ] IOC (0x110) [ERBZ]
RCS (0x111) [RX RER RBZ] RCS (0x111) [RX RER RBZ]
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]
@ -20,14 +19,19 @@ Known bugs and restrictions of Emu48 V1.25
Windows 95a 1920, 3840, 7680 work, 15360 fail Windows 95a 1920, 3840, 7680 work, 15360 fail
Windows 98 all baudrates fail Windows 98 all baudrates fail
Windows NT4.0 SP3 all baudrates fail Windows NT4.0 SP3 all baudrates fail
- problems when receiving a break signal on the serial port
Windows 98, NT4.0 SP4 no retrigger on port open
Windows 98 timing problems setting the RER bit
Windows 2000 SP2 no known problems
- System-RPL commands VERYVERYSLOW, VERYSLOW and SLOW depends on PC - System-RPL commands VERYVERYSLOW, VERYSLOW and SLOW depends on PC
speed (are realized as simple down counter in ROM) speed (are realized as simple down counter in ROM)
- display updating differs from the real machine - display updating differs from the real machine
- screen VBL counter values may skip after large display operations - screen VBL counter values may skip after large display operations
like turning on or updating the whole display like turning on or updating the whole display
- executing an opcode over a MMU boundary will fail
- read on an unconfigured address (open data bus) will not show the - read on an unconfigured address (open data bus) will not show the
same value like a real calculator same value like a real calculator
- the G(X) hardware signals BEN and DA19 aren't fully supported, - the Yorke hardware signals BEN and DA19 aren't fully supported,
because the emulator don't use a multiplexed AR18 / NCE3 data line because the emulator don't use a multiplexed AR18 / NCE3 data line
-> 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
@ -41,20 +45,14 @@ Known bugs and restrictions of Emu48 V1.25
- 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
- memory window of debugger view some addresses in I/O register area
with invalid data
- the 'Offset' command in the 'Background' section of KML scripts
don't work, the offset is always zero
- Shell OS: clock isn't synchronized with real time - Shell OS: clock isn't synchronized with real time
- HP49G: the flash memory is emulated now with some restrictions - HP49G: the flash memory is emulated now with some restrictions
- first implementation, at the moment the flash memory is more a
simulation than an emulation
- no flash programming times, the flash state machine returns - no flash programming times, the flash state machine returns
immediately the ready signal immediately the ready signal
- only one write buffer, second not needed because of prior reason - only one write buffer, second not needed because of prior reason
- not fully tested, especially the status byte may sometimes - not fully tested, especially the status byte may return
return incorrect values (error bits) incorrect values (error bits)
- quitting the emulator while programming the flash isn't allowed, - quitting the emulator while programming the flash isn't allowed,
because the content of flash state machine isn't saved so far because the content of flash state machine isn't saved so far
05/15/01 (c) by Christoph Gießelink, cgiess@swol.de 03/19/02 (c) by Christoph Gießelink, cgiess@swol.de

View file

@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View file

@ -24,13 +24,13 @@
#include <assert.h> #include <assert.h>
#include "types.h" #include "types.h"
#define VERSION "2.0" #define VERSION "2.1"
#define FT_ERR 0 // illegal format #define FT_ERR 0 // illegal format
#define FT_NEW 1 // empty file #define FT_NEW 1 // empty file
#define FT_SXGX 2 // Emu48 HP48SX/GX state file #define FT_SXGX 2 // Emu48 HP48SX/GX state file
#define _KB(n) (n*1024*2) // KB in state file #define _KB(n) ((n)*1024*2) // KB in state file
#define HP48SIG "Emu48 Document\xFE" // HP48 state file signature #define HP48SIG "Emu48 Document\xFE" // HP48 state file signature
@ -63,7 +63,7 @@ UINT CheckType(char *lpszFileName)
BOOL SeekData(HANDLE hFile,UINT *nPortSize) BOOL SeekData(HANDLE hFile,UINT *nPortSize)
{ {
BYTE byBuffer[16]; BYTE byBuffer[16];
CHIPSET Chipset; CHIPSET *pChipset;
UINT i; UINT i;
DWORD lBytes; DWORD lBytes;
@ -85,14 +85,18 @@ BOOL SeekData(HANDLE hFile,UINT *nPortSize)
if (lBytes != sizeof(i)) return TRUE; if (lBytes != sizeof(i)) return TRUE;
// read CHIPSET structure // read CHIPSET structure
ReadFile(hFile,&Chipset,sizeof(Chipset),&lBytes,NULL); if ((pChipset = LocalAlloc(LMEM_FIXED,i)) == NULL)
if (lBytes != sizeof(Chipset)) return TRUE; return TRUE;
ReadFile(hFile,pChipset,i,&lBytes,NULL);
if (lBytes != i) { LocalFree(pChipset); return TRUE; }
// skip port0 // skip port0
SetFilePointer(hFile,_KB(Chipset.Port0Size),NULL,FILE_CURRENT); SetFilePointer(hFile,_KB(pChipset->Port0Size),NULL,FILE_CURRENT);
*nPortSize = _KB(Chipset.Port1Size); // expected filesize *nPortSize = _KB(pChipset->Port1Size); // expected filesize
LocalFree(pChipset);
return FALSE; return FALSE;
} }

View file

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

View file

@ -1,3 +1,333 @@
Service Pack 30 for Emu48 Version 1.0
DEBUGGER.C
- bugfix in function Debugger(), used wrong debugger window position
when task bar was on top or left side
- added implementation of "Write-Only Register" dialog box
DDESERV.C
- added io.h in header definition
- removed usage of Chipset.dispon variable
DISPLAY.C
- added sources of gray scale emulation (experimental)
- replaced the LCD1_ROW by the LCD_ROW definition and the use of the
LCD2_ROW and the LCD3_ROW definitions by a calculation base on
LCD_ROW
- changed macro LINES(), added brackets forcing operator priority
- changed BITMAPINFO color table variable type from DWORD to RGBQUAD
- changed LCD bitmap from 64 palette entries to the number of used
colors in the LCD area, so function UpdateContrast() do not change
the drawing patterns to a new palette entry, it change the palette
itself now
- bugfix in function UpdateContrast(), switch palette to LCD off
background color if display is off
- bugfix in function DestroyLcdBitmap(), contrast palette wasn't
restored to startup colors
- changed function WriteToMainDisplay(), used wrong sizeof argument
to get the 4 byte x-multiplier in the calculation of the memory
position in the LCD bitmap
- bugfix in function StartDisplay(), the VBL counter of a switched
on display starts at the LINECOUNT (0x128,0x129) register content
EMU48.C
- removed usage of Chipset.dispon variable
- bugfix in function SetCommList(), used wrong NO_SERIAL string
definition for UNICODE mode
- bugfix in function OnDestroy(), call function SwitchToState() only
if CPU emulation thread is running
- bugfix in function OnViewCopy(), clipboard contained wrong data
when left display margin was unequal to zero
EMU48.H
- changed prototype of function StartDisplay()
- extern declaration of global function
EMU48.RC
- fixed misspellings "hexdezimal" to "hexadecimal"
- added "Write-Only Register" dialog
- added Windows XP manifest resource
- changed version and copyright
EMU48.XML
- manifest file for Windows XP
ENGINE.C
- changed function WorkerThread(), added parameter to StartDisplay()
function call
FILES.C
- bugfix in function NewDocument(), OpenDocument() and
RestoreBackup(), used wrong window restore position when task bar
was on top or left side
- bugfix in function SaveBackup(), get workspace instead of screen
coordinates of main window
- changed function LoadObject(), changed text output of "load error"
message boxes
KML.C
- changed function InitAnnunciator() and DrawAnnunciator(),
determine the number of valid entries now from the annunciator
array size
MOPS.C
- removed usage of Chipset.dispon variable
- bugfix in function Npeek(), fixed most of the wrong read values in
the I/O register area
- changed function Nwrite(), added conditional gray scale compiling
and added parameter to StartDisplay() function call
- bugfix in function WriteIO(), after changing the DON bit in
BITOFFSET (0x100) the display contrast must be updated as well
RESOURCE.H
- added some definitions
SERIAL.C
- redesign of character transmit part, on some PC systems corrupted
characters were sent
TIMER.C
- workaround for Win2k in function CalcT2(), when detecting a
"negative" time use the CPU cycles for new timer2 value
Service Pack 29 for Emu48 Version 1.0
DEBUGGER.C
- bugfix in function UpdateMiscWnd(), readded trailing spaces in
"On" text
- changed function Debugger(), replaced bDbgEnable with nDbgState
access
DEBUGGER.H
- added new debugger state defines
DISPLAY.C
- added varaible and functions from MOPS.C
- new functions StartDisplay() and StopDisplay() to control display
EMU48.C
- added VOID as parameter in functions with no argument
- added Critical Section initialization for gray scale emulation
- changed function UpdateWindowStatus(), OnDropFiles(),
OnStackPaste() and OnObjectLoad(), replaced bDbgEnable with
nDbgState access
- changed function OnDropFiles(), OnFileClose(), OnStackPaste() and
OnObjectLoad(), added debugger control
EMU48.H
- added defines for conditional gray scale compiling
- removed declaration of bDbgEnable
- extern declaration of global variables and functions
EMU48.RC
- changed version and copyright
ENGINE.C
- removed global variable bDbgEnable, replaced by a state in the
nDbgState variable
- added new functions SuspendDebugger() and ResumeDebugger() for
debugger control
- changed functions Debugger(), WaitForSleepState(), SwitchToState()
and WorkerThread(), added debugger control instead of general
debugger switching off
- changed function CheckSerial(), removed interrupt handling and
made function public
- changed function SwitchToState() and WorkerThread(), replaced
bDbgEnable with nDbgState access
- changed function WorkerThread(), main loop don't check status of
serial port any more, serial port must be initialized before
entering the RUN state now, added start/stop VBL counter at
entering/leaving the RUN state
FILES.C
- changed function WriteStack(), minor optimization
MOPS.C
- removed variable ioc_acc
- moved variable byVblRef and the functions F4096Hz() and
GetLineCounter() to DISPLAY.C
- changed function CpuReset(), must close serial port here
- changed function WriteIO(), control of the BITOFFSET (0x100)
register calls now the functions StartDisplay() and StopDisplay()
to modify the VBL counter reference
- changed function WriteIO(), changing the IOC (0x110) register
must also update the serial port status, because this isn't
handled in the CPU main loop any more
TIMER.C
- changed function RescheduleT2(), calculate now ceil of time delay
to reduce checking of timer2 value without timer2 overflow
Service Pack 28 for Emu48 Version 1.0
DEBUGGER.C
- bugfix in table MemMap[], NCE3 reference in HP39/40 part was wrong
- bugfix in function SetMappingMenu(), used wrong variable type for
UNICODE mode
- changed function UpdateMiscWnd(), removed trailing spaces in text
- new functions OnStackPush(), OnStackPop() and OnStackModify() and
other changes for implementation of the stack context menu
- changed function OnFindOK(), minor optimizations
- changed function OnNewValue(), now returns exit condition
DISPLAY.C
- removed usage of Chipset.dispon variable
EMU48.C
- bugfix in function SetCommList(), detection of COM ports larger
than COM9 failed
- moved shutdown of CPU emulation thread from the WinMain() to the
OnDestroy() function to avoid trouble with closed window DC
EMU48.DSP
- added configuration "Release Unicode"
- added configuration "Debug Unicode"
EMU48.RC
- added "Stack" menu entries
- added accelerator key in "Find" dialog
- changed version and copyright
I28F160.C
- bugfix in table byQueryTab[], content of not specified offset 0x03
is 0x02; offset 0x1B and 0x1D contain 0x30 in the real chip
- changed function WrStateE8N(), WrStateE8D() and WrState60D(), use
device specific data from query table instead of program constants
- bugfix in function WrStateE8C(), don't set the BWSLBS bit in the
status register on trying to set a 0 bit
- changed function WrState40D(), removed useless increment
- bugfix in function WrState30C(), don't set the ECLBS bit in the
status register when trying to erase a lock bit with WP# = low
- changed function WrState20C() and WrState30C(), use device
dimensions from query table now and optimized data filling part
- bugfix in function WrState60D(), the BWSLBS or the ECLBS bit in
the status register is set when trying to modify lock bits with
WP# = low
- bugfix in function RdStateId() and RdStateQuery(), Flash commands
"Read Identifier Codes" and "Read Query" now behave on illegal
address access like the original calculator
RESOURCE.H
- added definitions
SERIAL.C
- bugfix in function SerialThread(), added implementation of the RER
bit in the RCS (0x111) register for receiver BREAK condition
- bugfix in function CommOpen(), opening COM ports larger than COM9
failed
- bugfix in function CommTxBRK(), added LPB (Loop Back) emulation
Service Pack 27 for Emu48 Version 1.0
DEBUGGER.C
- various changes in many functions for implementation of the module
memory view
- changed function CreateToolbar(), replaced InitCommonControlsEx()
with InitCommonControls() function call to be compatible with the
project version 0x0200
EMU48.C
- changed function Disasm(), can use value of external port2 size
directly now
EMU48.RC
- added "Mapping" menu entries
- changed version
FILES.C
- changed function MapPort2(), don't limit port2 to 128KB here
I28F160.C
- bugfix in function WrStateE8N(), a "Write to Buffer" command
failed when requesting for the buffer length
KML.C
- added VOID as parameter in function prototypes
- replaced structure names changed in KML.H into the new ones
KML.H
- changed structure names Token to KmlToken, Line to KmlLine, Block
to KmlBlock, Button to KmlButton and Annunciator to KmlAnnunciator
because the Line and Button definition clash with the MacOS API
MOPS.C
- changed function MapP2(), limit port2 mapping size to 128KB here
OPCODES.C
- changed function o138(), o139(), o13A(), o13B(), o13C(), o13D(),
o13E(), o13F(), o19d2(), o1Ad4(), o1Dd2() and o1Ed4(), added big
endian machine support (use define BIGENDIAN)
PCH.H
- added _WIN32_IE definition for project version
RESOURCE.H
- added definitions
Service Pack 26 for Emu48 Version 1.0
DEBUGGER.C
- bugfix in function ViewMemWnd(), wrong ASCII view of characters in
text area, strings are saved in LSB, MSB order
- changed function Debugger(), save and restore debugger window
position in session now
- bugfix in function Debugger(), missing initialization of menu
entry CODE Object Breakpoints
- bugfix in function OnFindOK(), search for ASCII character in
LSB, MSB order
DISPLAY.C
- bugfix in function ResizeWindow(), 'Offset' command in KML script
section 'Background' hasn't worked
EMU48.C
- added Critical Section initialization
- bugfix in function OnPaint(), 'Offset' command in KML script
section 'Background' hasn't worked
EMU48.H
- extern declaration of global variable and function
EMU48.RC
- changed version
FILES.C
- changed functions ResetDocument(), ResetBackup() and
InitializeOFN(), replaced function FillMemory() with ZeroMemory()
- changed function OpenDocument(), can handle various Chipset sizes
now
KML.C
- bugfix in function DrawButton() and ClipButton, 'Offset' command
in KML script section 'Background' hasn't worked
MOPS.C
- bugfix function WriteIO(), when writing to the IOC (0x110)
register a possible USRQ interrupt wasn't generated
- changed function WriteIO(), writing the RER bit of the RCS (0x111)
register and writing the TBF bit of the TBR (0x116,0x117) register
is thread save now
- bugfix function WriteIO(), added implementation of the BRK bit in
the TCS (0x112) register
- changed function WriteIO(), removed NINT2 line update at writing
TBR (0x116,0x117) register, is doing in function CommTransmit()
PCH.H
- added include ctype.h
SERIAL.C
- minimized size of PC receive buffer
- bugfix in function SerialThread(), CommOpen(), CommClose() and
CommTransmit(), added implementation of the RER bit (only for
framing errors) in the RCS (0x111) register and of the TBF and TBZ
bit in the TCS (0x112) register
- new function CommTxBRK(), handle BREAK condition on Tx line
Service Pack 25 for Emu48 Version 1.0 Service Pack 25 for Emu48 Version 1.0
DDESERV.C DDESERV.C

View file

@ -8,6 +8,7 @@
*/ */
#include "pch.h" #include "pch.h"
#include "Emu48.h" #include "Emu48.h"
#include "io.h"
HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv, HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv,
HSZ hsz1,HSZ hsz2,HDDEDATA hData, HSZ hsz1,HSZ hsz2,HDDEDATA hData,
@ -40,7 +41,7 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv,
if ((lpData = (LPBYTE) LocalAlloc(LMEM_FIXED,dwSize * 2)) == NULL) if ((lpData = (LPBYTE) LocalAlloc(LMEM_FIXED,dwSize * 2)) == NULL)
return (HDDEDATA) DDE_FNOTPROCESSED; return (HDDEDATA) DDE_FNOTPROCESSED;
if (!Chipset.dispon) // HP off if (!(Chipset.IORam[BITOFFSET]&DON)) // HP off
{ {
// turn on HP // turn on HP
KeyboardEvent(TRUE,0,0x8000); KeyboardEvent(TRUE,0,0x8000);

View file

@ -43,6 +43,28 @@ typedef struct CToolBarData
WORD aItems[1]; WORD aItems[1];
} CToolBarData; } CToolBarData;
typedef struct // type of breakpoint table
{
BOOL bEnable; // breakpoint enabled
UINT nType; // breakpoint type
DWORD dwAddr; // breakpoint address
} BP_T;
typedef struct // type of model memory mapping
{
CONST BYTE byType; // calculator type
CONST LPBYTE *ppbyNCE1; // NCE1 data
CONST DWORD *pdwNCE1Size; // NCE1 size
CONST LPBYTE *ppbyNCE2; // NCE2 data
CONST DWORD *pdwNCE2Size; // NCE2 size
CONST LPBYTE *ppbyCE1; // CE1 data
CONST DWORD *pdwCE1Size; // CE1 size
CONST LPBYTE *ppbyCE2; // CE2 data
CONST DWORD *pdwCE2Size; // CE2 size
CONST LPBYTE *ppbyNCE3; // NCE3 data
CONST DWORD *pdwNCE3Size; // NCE3 size
} MODEL_MAP_T;
static CONST int nCol[] = static CONST int nCol[] =
{ {
IDC_DEBUG_MEM_COL0, IDC_DEBUG_MEM_COL1, IDC_DEBUG_MEM_COL2, IDC_DEBUG_MEM_COL3, IDC_DEBUG_MEM_COL0, IDC_DEBUG_MEM_COL1, IDC_DEBUG_MEM_COL2, IDC_DEBUG_MEM_COL3,
@ -54,12 +76,70 @@ static CONST TCHAR cHex[] = { _T('0'),_T('1'),_T('2'),_T('3'),
_T('8'),_T('9'),_T('A'),_T('B'), _T('8'),_T('9'),_T('A'),_T('B'),
_T('C'),_T('D'),_T('E'),_T('F') }; _T('C'),_T('D'),_T('E'),_T('F') };
typedef struct // type of breakpoint table static CONST LPBYTE pbyNoMEM = NULL; // no memory module
static CONST MODEL_MAP_T MemMap[] =
{ {
BOOL bEnable; // breakpoint enabled {
UINT nType; // breakpoint type 0, // default
DWORD dwAddr; // breakpoint address &pbyNoMEM, NULL, // nc.
} BP_T; &pbyNoMEM, NULL, // nc.
&pbyNoMEM, NULL, // nc.
&pbyNoMEM, NULL, // nc.
&pbyNoMEM, NULL // nc.
},
{
'6', // HP38G (64K)
&pbyRom, &dwRomSize, // ROM
&Chipset.Port0, &Chipset.Port0Size, // RAM
&pbyNoMEM, NULL, // nc.
&pbyNoMEM, NULL, // nc.
&pbyNoMEM, NULL // nc.
},
{
'A', // HP38G
&pbyRom, &dwRomSize, // ROM
&Chipset.Port0, &Chipset.Port0Size, // RAM
&pbyNoMEM, NULL, // nc.
&pbyNoMEM, NULL, // nc.
&pbyNoMEM, NULL // nc.
},
{
'E', // HP39/40G
&pbyRom, &dwRomSize, // ROM
&Chipset.Port0, &Chipset.Port0Size, // RAM part 1
&pbyNoMEM, NULL, // BS
&pbyNoMEM, NULL, // nc.
&Chipset.Port2, &Chipset.Port2Size // RAM part 2
},
{
'G', // HP48GX
&pbyRom, &dwRomSize, // ROM
&Chipset.Port0, &Chipset.Port0Size, // RAM
&pbyNoMEM, NULL, // BS
&Chipset.Port1, &Chipset.Port1Size, // Card slot 1
&pbyPort2, &dwPort2Size // Card slot 2
},
{
'S', // HP48SX
&pbyRom, &dwRomSize, // ROM
&Chipset.Port0, &Chipset.Port0Size, // RAM
&Chipset.Port1, &Chipset.Port1Size, // Card slot 1
&pbyPort2, &dwPort2Size, // Card slot 2
&pbyNoMEM, NULL // nc.
},
{
'X', // HP49G
&pbyRom, &dwRomSize, // Flash
&Chipset.Port0, &Chipset.Port0Size, // RAM
&pbyNoMEM, NULL, // BS
&Chipset.Port1, &Chipset.Port1Size, // Port 1 part 1
&Chipset.Port2, &Chipset.Port2Size // Port 1 part 2
}
};
static INT nDbgPosX = 0; // position of debugger window
static INT nDbgPosY = 0;
static WORD wBreakpointCount = 0; // number of breakpoints static WORD wBreakpointCount = 0; // number of breakpoints
static BP_T sBreakpoint[MAXBREAKPOINTS]; // breakpoint table static BP_T sBreakpoint[MAXBREAKPOINTS]; // breakpoint table
@ -69,11 +149,17 @@ static BOOL bRplBreak; // RPL breakpoint
static DWORD dwAdrLine[MAXCODELINES]; // addresses of disassember lines in code window static DWORD dwAdrLine[MAXCODELINES]; // addresses of disassember lines in code window
static DWORD dwAdrMem = 0; // start address of memory window static DWORD dwAdrMem = 0; // start address of memory window
static UINT uIDMap = ID_DEBUG_MEM_MAP; // current memory view mode
static LPBYTE lbyMapData; // data
static DWORD dwMapDataSize; // data size
static LONG lCharWidth; // width of a character (is a fix font) static LONG lCharWidth; // width of a character (is a fix font)
static HMENU hMenuCode,hMenuMem; // handle of context menues static HMENU hMenuCode,hMenuMem,hMenuStack;// handle of context menues
static HWND hWndToolbar; // toolbar handle static HWND hWndToolbar; // toolbar handle
static MODEL_MAP_T CONST *pMapping; // model specific memory mapping
static CHIPSET OldChipset; // old chipset content static CHIPSET OldChipset; // old chipset content
static BOOL bRegUpdate[REG_SIZE]; // register update table static BOOL bRegUpdate[REG_SIZE]; // register update table
@ -81,10 +167,11 @@ static HBITMAP hBmpCheckBox; // checked and unchecked bitmap
// function prototypes // function prototypes
static BOOL OnMemFind(HWND hDlg); static BOOL OnMemFind(HWND hDlg);
static VOID OnNewValue(LPTSTR lpszValue); static INT OnNewValue(LPTSTR lpszValue);
static VOID OnEnterAddress(HWND hDlg, DWORD *dwValue); static VOID OnEnterAddress(HWND hDlg, DWORD *dwValue);
static BOOL OnEditBreakpoint(HWND hDlg); static BOOL OnEditBreakpoint(HWND hDlg);
static BOOL OnInfoIntr(HWND hDlg); static BOOL OnInfoIntr(HWND hDlg);
static BOOL OnInfoWoRegister(HWND hDlg);
//################ //################
//# //#
@ -105,6 +192,7 @@ static VOID DisableMenuKeys(HWND hDlg)
EnableMenuItem(hMenu,ID_DEBUG_STEPOVER,MF_GRAYED); EnableMenuItem(hMenu,ID_DEBUG_STEPOVER,MF_GRAYED);
EnableMenuItem(hMenu,ID_DEBUG_STEPOUT,MF_GRAYED); EnableMenuItem(hMenu,ID_DEBUG_STEPOUT,MF_GRAYED);
EnableMenuItem(hMenu,ID_INFO_LASTINSTRUCTIONS,MF_GRAYED); EnableMenuItem(hMenu,ID_INFO_LASTINSTRUCTIONS,MF_GRAYED);
EnableMenuItem(hMenu,ID_INFO_WRITEONLYREG,MF_GRAYED);
SendMessage(hWndToolbar,TB_ENABLEBUTTON,ID_DEBUG_RUN,MAKELONG((FALSE),0)); SendMessage(hWndToolbar,TB_ENABLEBUTTON,ID_DEBUG_RUN,MAKELONG((FALSE),0));
SendMessage(hWndToolbar,TB_ENABLEBUTTON,ID_DEBUG_BREAK,MAKELONG((TRUE),0)); SendMessage(hWndToolbar,TB_ENABLEBUTTON,ID_DEBUG_BREAK,MAKELONG((TRUE),0));
@ -115,6 +203,61 @@ static VOID DisableMenuKeys(HWND hDlg)
return; return;
} }
//
// set mapping menu
//
static VOID SetMappingMenu(HWND hDlg,UINT uID)
{
LPTSTR szCaption;
CheckMenuItem(hMenuMem,uIDMap,MF_UNCHECKED);
switch (uID)
{
case ID_DEBUG_MEM_MAP:
szCaption = _T("Memory");
lbyMapData = NULL; // data
dwMapDataSize = 512; // data size
break;
case ID_DEBUG_MEM_NCE1:
szCaption = _T("Memory (NCE1)");
lbyMapData = *pMapping->ppbyNCE1;
dwMapDataSize = *pMapping->pdwNCE1Size / 2048; // ROM size is always in nibbles
break;
case ID_DEBUG_MEM_NCE2:
szCaption = _T("Memory (NCE2)");
lbyMapData = *pMapping->ppbyNCE2;
dwMapDataSize = *pMapping->pdwNCE2Size;
break;
case ID_DEBUG_MEM_CE1:
szCaption = _T("Memory (CE1)");
lbyMapData = *pMapping->ppbyCE1;
dwMapDataSize = *pMapping->pdwCE1Size;
break;
case ID_DEBUG_MEM_CE2:
szCaption = _T("Memory (CE2)");
lbyMapData = *pMapping->ppbyCE2;
dwMapDataSize = *pMapping->pdwCE2Size;
break;
case ID_DEBUG_MEM_NCE3:
szCaption = _T("Memory (NCE3)");
lbyMapData = *pMapping->ppbyNCE3;
dwMapDataSize = *pMapping->pdwNCE3Size;
break;
default: _ASSERT(0);
}
dwMapDataSize *= 2048; // size in nibble
if (uIDMap != uID) dwAdrMem = 0; // view from address 0
uIDMap = uID;
CheckMenuItem(hMenuMem,uIDMap,MF_CHECKED);
SetDlgItemText(hDlg,IDC_STATIC_MEMORY,szCaption);
return;
};
// //
// set/reset breakpoint // set/reset breakpoint
// //
@ -155,6 +298,45 @@ static __inline VOID ToggleBreakpoint(DWORD dwAddr)
return; return;
} }
//
// init memory mapping table and mapping menu entry
//
static __inline VOID InitMemMap(HWND hDlg)
{
BOOL bActive;
INT i;
pMapping = MemMap; // init default mapping
// scan for all table entries
for (i = 0; i < ARRAYSIZEOF(MemMap); ++i)
{
if (MemMap[i].byType == cCurrentRomType)
{
pMapping = &MemMap[i]; // found entry
break;
}
}
_ASSERT(hMenuMem);
// enable menu mappings
EnableMenuItem(hMenuMem,ID_DEBUG_MEM_NCE1,(*pMapping->ppbyNCE1) ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(hMenuMem,ID_DEBUG_MEM_NCE2,(*pMapping->ppbyNCE2) ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(hMenuMem,ID_DEBUG_MEM_CE1, (*pMapping->ppbyCE1) ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(hMenuMem,ID_DEBUG_MEM_CE2, (*pMapping->ppbyCE2) ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(hMenuMem,ID_DEBUG_MEM_NCE3,(*pMapping->ppbyNCE3) ? MF_ENABLED : MF_GRAYED);
bActive = (ID_DEBUG_MEM_NCE1 == uIDMap && *pMapping->ppbyNCE1 != NULL)
|| (ID_DEBUG_MEM_NCE2 == uIDMap && *pMapping->ppbyNCE2 != NULL)
|| (ID_DEBUG_MEM_CE1 == uIDMap && *pMapping->ppbyCE1 != NULL)
|| (ID_DEBUG_MEM_CE2 == uIDMap && *pMapping->ppbyCE2 != NULL)
|| (ID_DEBUG_MEM_NCE3 == uIDMap && *pMapping->ppbyNCE3 != NULL);
SetMappingMenu(hDlg,bActive ? uIDMap : ID_DEBUG_MEM_MAP);
return;
}
// //
// init bank switcher area // init bank switcher area
// //
@ -243,7 +425,7 @@ static VOID ViewMemWnd(HWND hDlg, DWORD dwAddress)
INT i,j,k; INT i,j,k;
TCHAR szBuffer[16],szItem[4]; TCHAR szBuffer[16],szItem[4];
BYTE cChar = 0; BYTE cChar;
szItem[2] = 0; // end of string szItem[2] = 0; // end of string
dwAdrMem = dwAddress; // save start address of memory window dwAdrMem = dwAddress; // save start address of memory window
@ -258,17 +440,35 @@ static VOID ViewMemWnd(HWND hDlg, DWORD dwAddress)
{ {
BYTE byLineData[MAXMEMITEMS]; BYTE byLineData[MAXMEMITEMS];
// fetch data line if (ID_DEBUG_MEM_MAP == uIDMap) // mapped memory content
{
// fetch mapping data line
Npeek(byLineData, dwAddress, MAXMEMITEMS); Npeek(byLineData, dwAddress, MAXMEMITEMS);
wsprintf(szBuffer,_T("%05lX"),dwAddress); wsprintf(szBuffer,_T("%05lX"),dwAddress);
}
else // module memory content
{
INT i;
_ASSERT(lbyMapData); // valid module
// fetch modul data line
for (i = 0; i < MAXMEMITEMS; ++i)
{
byLineData[i] = lbyMapData[(dwAddress + i) & (dwMapDataSize - 1)];
}
wsprintf(szBuffer,_T("%06lX"),dwAddress);
}
SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_ADDR,LB_ADDSTRING,0,(LPARAM) szBuffer); SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_ADDR,LB_ADDSTRING,0,(LPARAM) szBuffer);
for (k = 0, j = 0; j < MAXMEMITEMS; ++j) for (k = 0, j = 0; j < MAXMEMITEMS; ++j)
{ {
// read from fetched data line // read from fetched data line
szItem[j&0x1] = cHex[byLineData[j]]; szItem[j&0x1] = cHex[byLineData[j]];
cChar = (cChar << 4) | byLineData[j]; // characters are saved in LBS, MSB order
cChar = (cChar >> 4) | (byLineData[j] << 4);
if ((j&0x1) != 0) if ((j&0x1) != 0)
{ {
@ -282,7 +482,8 @@ static VOID ViewMemWnd(HWND hDlg, DWORD dwAddress)
} }
szBuffer[j/2] = 0; // end of text string szBuffer[j/2] = 0; // end of text string
SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_TEXT,LB_ADDSTRING,0,(LPARAM) szBuffer); SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_TEXT,LB_ADDSTRING,0,(LPARAM) szBuffer);
dwAddress = (dwAddress + MAXMEMITEMS) & 0xFFFFF;
dwAddress = (dwAddress + MAXMEMITEMS) & (dwMapDataSize - 1);
} }
return; return;
#undef TEXTOFF #undef TEXTOFF
@ -563,6 +764,7 @@ VOID OnUpdate(HWND hDlg)
EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOVER,MF_ENABLED); EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOVER,MF_ENABLED);
EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOUT,MF_ENABLED); EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOUT,MF_ENABLED);
EnableMenuItem(GetMenu(hDlg),ID_INFO_LASTINSTRUCTIONS,MF_ENABLED); EnableMenuItem(GetMenu(hDlg),ID_INFO_LASTINSTRUCTIONS,MF_ENABLED);
EnableMenuItem(GetMenu(hDlg),ID_INFO_WRITEONLYREG,MF_ENABLED);
// enable toolbar buttons // enable toolbar buttons
SendMessage(hWndToolbar,TB_ENABLEBUTTON,ID_DEBUG_RUN,MAKELONG((TRUE),0)); SendMessage(hWndToolbar,TB_ENABLEBUTTON,ID_DEBUG_RUN,MAKELONG((TRUE),0));
@ -746,7 +948,7 @@ static BOOL OnCodeGoAdr(HWND hDlg)
if (dwAddress != -1) if (dwAddress != -1)
{ {
HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_CODE); HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_CODE);
ViewCodeWnd(hWnd,dwAddress); ViewCodeWnd(hWnd,dwAddress & 0xFFFFF);
SendMessage(hWnd,LB_SETCURSEL,0,0); SendMessage(hWnd,LB_SETCURSEL,0,0);
} }
return -1; // call windows default handler return -1; // call windows default handler
@ -758,7 +960,7 @@ static BOOL OnCodeGoAdr(HWND hDlg)
static BOOL OnCodeGoPC(HWND hDlg) static BOOL OnCodeGoPC(HWND hDlg)
{ {
UpdateCodeWnd(hDlg); UpdateCodeWnd(hDlg);
return TRUE; return 0;
} }
// //
@ -792,7 +994,7 @@ static BOOL OnMemGoAdr(HWND hDlg)
OnEnterAddress(hDlg, &dwAddress); OnEnterAddress(hDlg, &dwAddress);
if (dwAddress != -1) // not Cancel key if (dwAddress != -1) // not Cancel key
OnMemGoDx(hDlg,dwAddress); OnMemGoDx(hDlg,dwAddress & (dwMapDataSize - 1));
return -1; // call windows default handler return -1; // call windows default handler
} }
@ -804,7 +1006,7 @@ static BOOL OnClearAll(HWND hDlg)
wBreakpointCount = 0; wBreakpointCount = 0;
// redraw code window // redraw code window
InvalidateRect(GetDlgItem(hDlg,IDC_DEBUG_CODE),NULL,TRUE); InvalidateRect(GetDlgItem(hDlg,IDC_DEBUG_CODE),NULL,TRUE);
return TRUE; return 0;
} }
// //
@ -814,7 +1016,85 @@ static BOOL OnToggleMenuItem(HWND hDlg,UINT uIDCheckItem,BOOL *bCheck)
{ {
*bCheck = !*bCheck; // toggle flag *bCheck = !*bCheck; // toggle flag
CheckMenuItem(GetMenu(hDlg),uIDCheckItem,*bCheck ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(GetMenu(hDlg),uIDCheckItem,*bCheck ? MF_CHECKED : MF_UNCHECKED);
return 0;
}
//
// change memory window mapping style
//
static BOOL OnMemMapping(HWND hDlg,UINT uID)
{
if (uID == uIDMap) return -1; // same view, call windows default handler
SetMappingMenu(hDlg,uID); // update menu settings
UpdateMemoryWnd(hDlg); // update memory window
return 0;
}
//
// push value on hardware stack
//
static BOOL OnStackPush(HWND hDlg)
{
TCHAR szBuffer[] = _T("00000");
DWORD dwAddr;
HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_STACK);
if (nDbgState != DBG_STEPINTO) // not in single step mode
return TRUE; return TRUE;
if (IDOK != OnNewValue(szBuffer)) // canceled function
return TRUE;
_stscanf(szBuffer,_T("%5X"),&dwAddr);
rstkpush(dwAddr); // push data
UpdateStackWnd(hDlg); // update stack window
SendMessage(hWnd,LB_SETTOPINDEX,0,0); // top of listbox
SendMessage(hWnd,LB_SETCURSEL,0,0); // top selection
return 0;
}
//
// pop value from hardware stack
//
static BOOL OnStackPop(HWND hDlg)
{
HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_STACK);
if (nDbgState != DBG_STEPINTO) // not in single step mode
return TRUE;
rstkpop(); // pop data
UpdateStackWnd(hDlg); // update stack window
SendMessage(hWnd,LB_SETTOPINDEX,0,0); // top of listbox
SendMessage(hWnd,LB_SETCURSEL,0,0); // top selection
return 0;
}
// modify value on hardware stack
static BOOL OnStackModify(HWND hDlg)
{
TCHAR szBuffer[16];
HWND hWnd;
INT i;
if (nDbgState != DBG_STEPINTO) // not in single step mode
return TRUE;
hWnd = GetDlgItem(hDlg,IDC_DEBUG_STACK);
i = SendMessage(hWnd,LB_GETCURSEL,0,0);
if (LB_ERR == i) return TRUE; // no selection
SendMessage(hWnd,LB_GETTEXT,i,(LPARAM) szBuffer);
OnNewValue(&szBuffer[3]);
_stscanf(&szBuffer[3],_T("%5X"),&Chipset.rstk[(Chipset.rstkp-i-1)&7]);
UpdateStackWnd(hDlg); // update stack window
SendMessage(hWnd,LB_SETCURSEL,i,0); // restore cursor postion
return 0;
} }
// //
@ -970,7 +1250,9 @@ static BOOL OnDblClick(HWND hWnd, WORD wId)
if (nCol[i] == wId) // found ID if (nCol[i] == wId) // found ID
break; break;
if (i == MEMWNDMAX) return FALSE; // not IDC_DEBUG_MEM window, default handler // not IDC_DEBUG_MEM window or module mode -> default handler
if (i == MEMWNDMAX || ID_DEBUG_MEM_MAP != uIDMap)
return FALSE;
// calculate address of byte // calculate address of byte
dwAddress = i * 2; dwAddress = i * 2;
@ -1016,6 +1298,10 @@ static VOID OnContextMenu(HWND hDlg, LPARAM lParam, WPARAM wParam)
case IDC_DEBUG_MEM_COL7: // handle memory window case IDC_DEBUG_MEM_COL7: // handle memory window
TrackPopupMenu(hMenuMem,0,pt.x,pt.y,0,hDlg,NULL); TrackPopupMenu(hMenuMem,0,pt.x,pt.y,0,hDlg,NULL);
break; break;
case IDC_DEBUG_STACK: // handle code window
TrackPopupMenu(hMenuStack,0,pt.x,pt.y,0,hDlg,NULL);
break;
} }
return; return;
} }
@ -1079,13 +1365,13 @@ static __inline BOOL OnKeyUpDown(HWND hWnd, WPARAM wParam)
switch(LOWORD(wParam)) switch(LOWORD(wParam))
{ {
case VK_NEXT: case VK_NEXT:
dwAdrMem = (dwAdrMem + MAXMEMITEMS * MAXMEMLINES) & 0xFFFFF; dwAdrMem = (dwAdrMem + MAXMEMITEMS * MAXMEMLINES) & (dwMapDataSize - 1);
UpdateMemoryWnd(GetParent(hWnd)); UpdateMemoryWnd(GetParent(hWnd));
SendMessage(hWnd,LB_SETCURSEL,wY,0); SendMessage(hWnd,LB_SETCURSEL,wY,0);
return -2; return -2;
case VK_PRIOR: case VK_PRIOR:
dwAdrMem = (dwAdrMem - MAXMEMITEMS * MAXMEMLINES) & 0xFFFFF; dwAdrMem = (dwAdrMem - MAXMEMITEMS * MAXMEMLINES) & (dwMapDataSize - 1);
UpdateMemoryWnd(GetParent(hWnd)); UpdateMemoryWnd(GetParent(hWnd));
SendMessage(hWnd,LB_SETCURSEL,wY,0); SendMessage(hWnd,LB_SETCURSEL,wY,0);
return -2; return -2;
@ -1093,7 +1379,7 @@ static __inline BOOL OnKeyUpDown(HWND hWnd, WPARAM wParam)
case VK_DOWN: case VK_DOWN:
if (wY+1 >= MAXMEMLINES) if (wY+1 >= MAXMEMLINES)
{ {
dwAdrMem = (dwAdrMem + MAXMEMITEMS) & 0xFFFFF; dwAdrMem = (dwAdrMem + MAXMEMITEMS) & (dwMapDataSize - 1);
UpdateMemoryWnd(GetParent(hWnd)); UpdateMemoryWnd(GetParent(hWnd));
SendMessage(hWnd,LB_SETCURSEL,wY,0); SendMessage(hWnd,LB_SETCURSEL,wY,0);
return -2; return -2;
@ -1103,7 +1389,7 @@ static __inline BOOL OnKeyUpDown(HWND hWnd, WPARAM wParam)
case VK_UP: case VK_UP:
if (wY == 0) if (wY == 0)
{ {
dwAdrMem = (dwAdrMem - MAXMEMITEMS) & 0xFFFFF; dwAdrMem = (dwAdrMem - MAXMEMITEMS) & (dwMapDataSize - 1);
UpdateMemoryWnd(GetParent(hWnd)); UpdateMemoryWnd(GetParent(hWnd));
SendMessage(hWnd,LB_SETCURSEL,wY,0); SendMessage(hWnd,LB_SETCURSEL,wY,0);
return -2; return -2;
@ -1279,8 +1565,6 @@ VOID DisableDebugger(VOID)
// //
static __inline HWND CreateToolbar(HWND hWnd) static __inline HWND CreateToolbar(HWND hWnd)
{ {
INITCOMMONCONTROLSEX icex;
HRSRC hRes; HRSRC hRes;
HGLOBAL hGlobal; HGLOBAL hGlobal;
CToolBarData *pData; CToolBarData *pData;
@ -1289,10 +1573,7 @@ static __inline HWND CreateToolbar(HWND hWnd)
HWND hWndToolbar = NULL; // toolbar window HWND hWndToolbar = NULL; // toolbar window
// init common control DLL InitCommonControls(); // ensure that common control DLL is loaded
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_BAR_CLASSES;
InitCommonControlsEx(&icex);
if ((hRes = FindResource(hApp,MAKEINTRESOURCE(IDR_DEBUG_TOOLBAR),RT_TOOLBAR)) == NULL) if ((hRes = FindResource(hApp,MAKEINTRESOURCE(IDR_DEBUG_TOOLBAR),RT_TOOLBAR)) == NULL)
goto quit; goto quit;
@ -1343,8 +1624,9 @@ quit:
static BOOL CALLBACK Debugger(HWND hDlg, UINT message, DWORD wParam, LONG lParam) static BOOL CALLBACK Debugger(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
{ {
static HMENU hMenuMainCode,hMenuMainMem; static HMENU hMenuMainCode,hMenuMainMem,hMenuMainStack;
WINDOWPLACEMENT wndpl;
TEXTMETRIC tm; TEXTMETRIC tm;
HDC hDC; HDC hDC;
HFONT hFont; HFONT hFont;
@ -1353,12 +1635,13 @@ static BOOL CALLBACK Debugger(HWND hDlg, UINT message, DWORD wParam, LONG lParam
switch (message) switch (message)
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
_ASSERT(hWnd); SetWindowLocation(hDlg,nDbgPosX,nDbgPosY);
SetClassLong(hDlg,GCL_HICON,(LONG) LoadIcon(hApp,MAKEINTRESOURCE(IDI_EMU48))); SetClassLong(hDlg,GCL_HICON,(LONG) LoadIcon(hApp,MAKEINTRESOURCE(IDI_EMU48)));
hWndToolbar = CreateToolbar(hDlg); // add toolbar hWndToolbar = CreateToolbar(hDlg); // add toolbar
CheckMenuItem(GetMenu(hDlg),ID_BREAKPOINTS_NOP3,bDbgNOP3 ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(GetMenu(hDlg),ID_BREAKPOINTS_NOP3, bDbgNOP3 ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(GetMenu(hDlg),ID_BREAKPOINTS_DOCODE,bDbgCode ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(GetMenu(hDlg),ID_BREAKPOINTS_RPL, bDbgRPL ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(GetMenu(hDlg),ID_BREAKPOINTS_RPL, bDbgRPL ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(GetMenu(hDlg),ID_INTR_STEPOVERINT,bDbgSkipInt ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(GetMenu(hDlg),ID_INTR_STEPOVERINT, bDbgSkipInt ? MF_CHECKED : MF_UNCHECKED);
hDlgDebug = hDlg; // handle for debugger dialog hDlgDebug = hDlg; // handle for debugger dialog
hEventDebug = CreateEvent(NULL,FALSE,FALSE,NULL); hEventDebug = CreateEvent(NULL,FALSE,FALSE,NULL);
if (hEventDebug == NULL) if (hEventDebug == NULL)
@ -1374,6 +1657,10 @@ static BOOL CALLBACK Debugger(HWND hDlg, UINT message, DWORD wParam, LONG lParam
_ASSERT(hMenuMainMem); _ASSERT(hMenuMainMem);
hMenuMem = GetSubMenu(hMenuMainMem, 0); hMenuMem = GetSubMenu(hMenuMainMem, 0);
_ASSERT(hMenuMem); _ASSERT(hMenuMem);
hMenuMainStack = LoadMenu(hApp,MAKEINTRESOURCE(IDR_DEBUG_STACK));
_ASSERT(hMenuMainStack);
hMenuStack = GetSubMenu(hMenuMainStack, 0);
_ASSERT(hMenuStack);
// font settings // font settings
SendDlgItemMessage(hDlg,IDC_STATIC_CODE, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_STATIC_CODE, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
@ -1388,6 +1675,7 @@ static BOOL CALLBACK Debugger(HWND hDlg, UINT message, DWORD wParam, LONG lParam
wInstrSize = INSTRSIZE; // size of last instruction array wInstrSize = INSTRSIZE; // size of last instruction array
wInstrWp = wInstrRp = 0; // write/read pointer wInstrWp = wInstrRp = 0; // write/read pointer
InitMemMap(hDlg); // init memory mapping table
InitBsArea(hDlg); // init bank switcher list box InitBsArea(hDlg); // init bank switcher list box
disassembler_map = MEM_MAP; // disassemble with mapped modules disassembler_map = MEM_MAP; // disassemble with mapped modules
@ -1395,7 +1683,6 @@ static BOOL CALLBACK Debugger(HWND hDlg, UINT message, DWORD wParam, LONG lParam
dwDbgStopPC = -1; // no stop address for goto cursor dwDbgStopPC = -1; // no stop address for goto cursor
dwDbgRplPC = -1; // no stop address for RPL breakpoint dwDbgRplPC = -1; // no stop address for RPL breakpoint
bDbgEnable = TRUE; // debugger active
nDbgState = DBG_STEPINTO; // state "step into" nDbgState = DBG_STEPINTO; // state "step into"
if (Chipset.Shutdn) // cpu thread stopped if (Chipset.Shutdn) // cpu thread stopped
SetEvent(hEventShutdn); // goto debug session SetEvent(hEventShutdn); // goto debug session
@ -1406,8 +1693,7 @@ static BOOL CALLBACK Debugger(HWND hDlg, UINT message, DWORD wParam, LONG lParam
case WM_DESTROY: case WM_DESTROY:
// SetHP48Time(); // update time & date // SetHP48Time(); // update time & date
bDbgEnable = FALSE; // debugger inactive nDbgState = DBG_OFF; // debugger inactive
nDbgState = DBG_RUN; // state of debugger
bInterrupt = TRUE; // exit opcode loop bInterrupt = TRUE; // exit opcode loop
SetEvent(hEventDebug); SetEvent(hEventDebug);
if (pdwInstrArray) // free last instruction circular buffer if (pdwInstrArray) // free last instruction circular buffer
@ -1416,8 +1702,14 @@ static BOOL CALLBACK Debugger(HWND hDlg, UINT message, DWORD wParam, LONG lParam
pdwInstrArray = NULL; pdwInstrArray = NULL;
} }
CloseHandle(hEventDebug); CloseHandle(hEventDebug);
wndpl.length = sizeof(wndpl); // save debugger window position
GetWindowPlacement(hDlg, &wndpl);
nDbgPosX = wndpl.rcNormalPosition.left;
nDbgPosY = wndpl.rcNormalPosition.top;
DestroyMenu(hMenuMainCode); DestroyMenu(hMenuMainCode);
DestroyMenu(hMenuMainMem); DestroyMenu(hMenuMainMem);
DestroyMenu(hMenuMainStack);
DestroyMenu(hMenuStack);
_ASSERT(hWnd); _ASSERT(hWnd);
UpdateWindowStatus(); // enable application menu items UpdateWindowStatus(); // enable application menu items
hDlgDebug = NULL; // debugger windows closed hDlgDebug = NULL; // debugger windows closed
@ -1465,6 +1757,7 @@ static BOOL CALLBACK Debugger(HWND hDlg, UINT message, DWORD wParam, LONG lParam
case ID_BREAKPOINTS_DOCODE: return OnToggleMenuItem(hDlg,LOWORD(wParam),&bDbgCode); case ID_BREAKPOINTS_DOCODE: return OnToggleMenuItem(hDlg,LOWORD(wParam),&bDbgCode);
case ID_BREAKPOINTS_RPL: return OnToggleMenuItem(hDlg,LOWORD(wParam),&bDbgRPL); case ID_BREAKPOINTS_RPL: return OnToggleMenuItem(hDlg,LOWORD(wParam),&bDbgRPL);
case ID_INFO_LASTINSTRUCTIONS: return OnInfoIntr(hDlg); case ID_INFO_LASTINSTRUCTIONS: return OnInfoIntr(hDlg);
case ID_INFO_WRITEONLYREG: return OnInfoWoRegister(hDlg);
case ID_INTR_STEPOVERINT: return OnToggleMenuItem(hDlg,LOWORD(wParam),&bDbgSkipInt); case ID_INTR_STEPOVERINT: return OnToggleMenuItem(hDlg,LOWORD(wParam),&bDbgSkipInt);
case ID_DEBUG_MEM_GOADR: return OnMemGoAdr(hDlg); case ID_DEBUG_MEM_GOADR: return OnMemGoAdr(hDlg);
case ID_DEBUG_MEM_GOPC: return OnMemGoDx(hDlg,Chipset.pc); case ID_DEBUG_MEM_GOPC: return OnMemGoDx(hDlg,Chipset.pc);
@ -1472,6 +1765,15 @@ static BOOL CALLBACK Debugger(HWND hDlg, UINT message, DWORD wParam, LONG lParam
case ID_DEBUG_MEM_GOD1: return OnMemGoDx(hDlg,Chipset.d1); case ID_DEBUG_MEM_GOD1: return OnMemGoDx(hDlg,Chipset.d1);
case ID_DEBUG_MEM_GOSTACK: return OnMemGoDx(hDlg,Chipset.rstk[(Chipset.rstkp-1)&7]); case ID_DEBUG_MEM_GOSTACK: return OnMemGoDx(hDlg,Chipset.rstk[(Chipset.rstkp-1)&7]);
case ID_DEBUG_MEM_FIND: return OnMemFind(hDlg); case ID_DEBUG_MEM_FIND: return OnMemFind(hDlg);
case ID_DEBUG_MEM_MAP:
case ID_DEBUG_MEM_NCE1:
case ID_DEBUG_MEM_NCE2:
case ID_DEBUG_MEM_CE1:
case ID_DEBUG_MEM_CE2:
case ID_DEBUG_MEM_NCE3: return OnMemMapping(hDlg,LOWORD(wParam));
case ID_DEBUG_STACK_PUSH: return OnStackPush(hDlg);
case ID_DEBUG_STACK_POP: return OnStackPop(hDlg);
case ID_DEBUG_STACK_MODIFY: return OnStackModify(hDlg);
case ID_DEBUG_CANCEL: DestroyWindow(hDlg); return TRUE; case ID_DEBUG_CANCEL: DestroyWindow(hDlg); return TRUE;
} }
@ -1595,16 +1897,14 @@ static __inline BOOL OnFindOK(HWND hDlg,BOOL bASCII,DWORD *pdwAddrLast)
HWND hWnd = GetDlgItem(hDlg,IDC_FIND_DATA); HWND hWnd = GetDlgItem(hDlg,IDC_FIND_DATA);
i = GetWindowTextLength(hWnd); // text length i = GetWindowTextLength(hWnd) + 1; // text length incl. EOS
j = bASCII ? 2 : sizeof(*(LPTSTR)0); // buffer width
j = bASCII ? 2 : 1; // buffer width
if (j < sizeof(*(LPTSTR)0)) j = sizeof(*(LPTSTR)0);
// allocate search buffer // allocate search buffer
if ((lpbySearch = LocalAlloc(GMEM_FIXED,(i+1) * j)) != NULL) if ((lpbySearch = LocalAlloc(GMEM_FIXED,i * j)) != NULL)
{ {
// get search text and real length // get search text and real length
i = GetWindowText(hWnd,(LPTSTR) lpbySearch,(i+1)); i = GetWindowText(hWnd,(LPTSTR) lpbySearch,i);
// add string to combo box // add string to combo box
if (SendMessage(hWnd,CB_FINDSTRINGEXACT,0,(LPARAM) lpbySearch) == CB_ERR) if (SendMessage(hWnd,CB_FINDSTRINGEXACT,0,(LPARAM) lpbySearch) == CB_ERR)
@ -1630,9 +1930,9 @@ static __inline BOOL OnFindOK(HWND hDlg,BOOL bASCII,DWORD *pdwAddrLast)
// convert ASCII to number // convert ASCII to number
for (j = i - 1; j >= 0; --j) for (j = i - 1; j >= 0; --j)
{ {
// order MSB, LSB // order LSB, MSB
lpbySearch[j * 2 + 1] = lpbySearch[j] & 0xF; lpbySearch[j * 2 + 1] = lpbySearch[j] >> 4;
lpbySearch[j * 2] = lpbySearch[j] >> 4; lpbySearch[j * 2] = lpbySearch[j] & 0xF;
} }
i *= 2; // no. of nibbles i *= 2; // no. of nibbles
} }
@ -1663,19 +1963,26 @@ static __inline BOOL OnFindOK(HWND hDlg,BOOL bASCII,DWORD *pdwAddrLast)
if (*pdwAddrLast == dwAddr) if (*pdwAddrLast == dwAddr)
++dwAddr; ++dwAddr;
// scan 1M Nibble until match // scan mapping/module until match
for (; i && !bMatch && dwAddr <= dwAdrMem + 0x100000; ++dwAddr) for (; i && !bMatch && dwAddr <= dwAdrMem + dwMapDataSize; ++dwAddr)
{ {
BYTE byC; BYTE byC;
// i = no. of nibbles that have to match // i = no. of nibbles that have to match
for (bMatch = TRUE, j = 0;bMatch && j < i; ++j) for (bMatch = TRUE, j = 0;bMatch && j < i; ++j)
{
if (ID_DEBUG_MEM_MAP == uIDMap) // mapped memory content
{ {
Npeek(&byC,(dwAddr + j) & 0xFFFFF,1); Npeek(&byC,(dwAddr + j) & 0xFFFFF,1);
}
else // module memory content
{
byC = lbyMapData[(dwAddr + j) & (dwMapDataSize - 1)];
}
bMatch = (byC == lpbySearch[j]); bMatch = (byC == lpbySearch[j]);
} }
} }
dwAddr = (dwAddr - 1) & 0xFFFFF; // possible matching address dwAddr = (dwAddr - 1) & (dwMapDataSize - 1); // possible matching address
LocalFree(lpbySearch); LocalFree(lpbySearch);
// check match result // check match result
@ -1740,7 +2047,6 @@ static BOOL OnMemFind(HWND hDlg)
return -1; // call windows default handler return -1; // call windows default handler
} }
//################ //################
//# //#
//# New Value dialog box //# New Value dialog box
@ -1795,10 +2101,18 @@ static BOOL CALLBACK NewValue(HWND hDlg, UINT message, DWORD wParam, LONG lParam
UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(wParam);
} }
static VOID OnNewValue(LPTSTR lpszValue) static INT OnNewValue(LPTSTR lpszValue)
{ {
if (DialogBoxParam(hApp, MAKEINTRESOURCE(IDD_NEWVALUE), hDlgDebug, (DLGPROC)NewValue, (LPARAM)lpszValue) == -1) INT nResult;
if ((nResult = DialogBoxParam(hApp,
MAKEINTRESOURCE(IDD_NEWVALUE),
hDlgDebug,
(DLGPROC)NewValue,
(LPARAM)lpszValue)
) == -1)
AbortMessage(_T("Input Dialog Box Creation Error !")); AbortMessage(_T("Input Dialog Box Creation Error !"));
return nResult;
} }
@ -1840,7 +2154,7 @@ static BOOL CALLBACK EnterAddr(HWND hDlg, UINT message, DWORD wParam, LONG lPara
return FALSE; return FALSE;
} }
} }
if (*szBuffer) _stscanf(szBuffer,_T("%5X"),dwAddress); if (*szBuffer) _stscanf(szBuffer,_T("%6X"),dwAddress);
// no break // no break
case IDCANCEL: case IDCANCEL:
EndDialog(hDlg,wParam); EndDialog(hDlg,wParam);
@ -2269,7 +2583,6 @@ static BOOL CALLBACK InfoIntr(HWND hDlg, UINT message, DWORD wParam, LONG lParam
} }
} }
return FALSE; return FALSE;
UNREFERENCED_PARAMETER(wParam);
UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(lParam);
} }
@ -2277,7 +2590,44 @@ static BOOL OnInfoIntr(HWND hDlg)
{ {
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_INSTRUCTIONS), hDlg, (DLGPROC)InfoIntr) == -1) if (DialogBox(hApp, MAKEINTRESOURCE(IDD_INSTRUCTIONS), hDlg, (DLGPROC)InfoIntr) == -1)
AbortMessage(_T("Last Instructions Dialog Box Creation Error !")); AbortMessage(_T("Last Instructions Dialog Box Creation Error !"));
return 0;
}
//
// view write only I/O registers
//
static BOOL CALLBACK InfoWoRegister(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
{
TCHAR szBuffer[8];
switch (message)
{
case WM_INITDIALOG:
wsprintf(szBuffer,_T("%05X"),Chipset.start1);
SetDlgItemText(hDlg,IDC_ADDR20_24,szBuffer);
wsprintf(szBuffer,_T("%03X"),Chipset.loffset);
SetDlgItemText(hDlg,IDC_ADDR25_27,szBuffer);
wsprintf(szBuffer,_T("%02X"),Chipset.lcounter);
SetDlgItemText(hDlg,IDC_ADDR28_29,szBuffer);
wsprintf(szBuffer,_T("%05X"),Chipset.start2);
SetDlgItemText(hDlg,IDC_ADDR30_34,szBuffer);
return TRUE; return TRUE;
case WM_COMMAND:
if ((wParam==IDOK))
{
EndDialog(hDlg,wParam);
return TRUE;
}
}
return FALSE;
UNREFERENCED_PARAMETER(lParam);
}
static BOOL OnInfoWoRegister(HWND hDlg)
{
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_WRITEONLYREG), hDlg, (DLGPROC)InfoWoRegister) == -1)
AbortMessage(_T("Write-Only Register Dialog Box Creation Error !"));
return 0;
} }

View file

@ -15,10 +15,12 @@
#define BP_ACCESS (BP_READ|BP_WRITE) // read/write memory breakpoint #define BP_ACCESS (BP_READ|BP_WRITE) // read/write memory breakpoint
// debugger state definitions // debugger state definitions
#define DBG_RUN 0 #define DBG_SUSPEND -1
#define DBG_STEPINTO 1 #define DBG_OFF 0
#define DBG_STEPOVER 2 #define DBG_RUN 1
#define DBG_STEPOUT 3 #define DBG_STEPINTO 2
#define DBG_STEPOVER 3
#define DBG_STEPOUT 4
// debugger.c // debugger.c
extern BOOL CheckBreakpoint(DWORD dwAddr, DWORD wRange, UINT nType); extern BOOL CheckBreakpoint(DWORD dwAddr, DWORD wRange, UINT nType);

View file

@ -4,6 +4,7 @@
* This file is part of Emu48 * This file is part of Emu48
* *
* Copyright (C) 1995 Sebastien Carlier * Copyright (C) 1995 Sebastien Carlier
* Copyright (C) 2002 Christoph Gießelink
* *
*/ */
#include "pch.h" #include "pch.h"
@ -14,12 +15,27 @@
// #define DEBUG_DISPLAY // switch for DISPLAY debug purpose // #define DEBUG_DISPLAY // switch for DISPLAY debug purpose
#define LCD1_ROW 144 #if defined GRAYSCALE
#define LCD2_ROW 288 #define NOCOLORS 8
#define LCD3_ROW 576 #else
#define NOCOLORS 2
#endif
#define B 0x00000000 // black
#define W 0x00FFFFFF // white
#define I 0xFFFFFFFF // ignore
#define LCD_ROW (36*4) // max. pixel per line
// main display lines, handle zero lines exception // main display lines, handle zero lines exception
#define LINES(n) ((n == 0) ? 64 : (n+1)) #define LINES(n) (((n) == 0) ? 64 : ((n)+1))
#define GRAYMASK (((((NOCOLORS)-1)>>1)<<24) \
|((((NOCOLORS)-1)>>1)<<16) \
|((((NOCOLORS)-1)>>1)<<8) \
|((((NOCOLORS)-1)>>1)))
#define DIBPIXEL(d,p) *(((DWORD*)(d))++) = ((*((DWORD*)(d)) & GRAYMASK) << 1) | (p)
UINT nBackgroundX = 0; UINT nBackgroundX = 0;
UINT nBackgroundY = 0; UINT nBackgroundY = 0;
@ -31,40 +47,33 @@ UINT nLcdDoubled = 1;
LPBYTE pbyLcd; LPBYTE pbyLcd;
HDC hLcdDC = NULL; HDC hLcdDC = NULL;
HDC hMainDC = NULL; HDC hMainDC = NULL;
static HBITMAP hLcdBitmap; static HBITMAP hLcdBitmap;
static HBITMAP hMainBitmap; static HBITMAP hMainBitmap;
static HBITMAP hOldLcdBitmap; static HBITMAP hOldLcdBitmap;
static HBITMAP hOldMainBitmap; static HBITMAP hOldMainBitmap;
#define B 0x00000000 static DWORD Pattern[16];
#define W 0x00FFFFFF
#define I 0xFFFFFFFF static DWORD dwKMLColor[64] = // color table loaded by KML script
static struct
{ {
BITMAPINFOHEADER Lcd_bmih;
DWORD dwColor[64];
} bmiLcd =
{
{0x28,0/*x*/,0/*y*/,1,8,BI_RGB,0,0,0,64,0},
{
W,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B, W,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,
B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B, B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,
I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I, I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,
I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I
}
}; };
#undef B
#undef W
#undef I
static DWORD Pattern[16]; static struct
VOID UpdateContrast(BYTE byContrast)
{ {
DWORD c = byContrast; BITMAPINFOHEADER Lcd_bmih;
DWORD b = byContrast + 0x20; RGBQUAD bmiColors[NOCOLORS];
if (bmiLcd.dwColor[b] == 0xFFFFFFFF) b = 0; } bmiLcd =
{
{0x28,0/*x*/,0/*y*/,1,8,BI_RGB,0,0,0,NOCOLORS,0}
};
static __inline VOID BuildPattern(VOID)
{
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
if (nLcdDoubled == 1) if (nLcdDoubled == 1)
@ -75,38 +84,65 @@ VOID UpdateContrast(BYTE byContrast)
Pattern[i] = 0; Pattern[i] = 0;
for (j=8; j>0; j>>=1) for (j=8; j>0; j>>=1)
{ {
Pattern[i] = (Pattern[i] << 8) | ((i&j) ? c : b); Pattern[i] = (Pattern[i] << 8) | ((i&j) != 0);
} }
} }
return; return;
} }
c = (c<<8) | c;
b = (b<<8) | b;
if (nLcdDoubled == 2) if (nLcdDoubled == 2)
{ {
Pattern[0] = (b<<16)|b; Pattern[0] = 0x00000000;
Pattern[1] = (b<<16)|c; Pattern[1] = 0x00000101;
Pattern[2] = (c<<16)|b; Pattern[2] = 0x01010000;
Pattern[3] = (c<<16)|c; Pattern[3] = 0x01010101;
return; return;
} }
c = (c<<16) | c;
b = (b<<16) | b;
if (nLcdDoubled == 4) if (nLcdDoubled == 4)
{ {
Pattern[0] = b; Pattern[0] = 0x00000000;
Pattern[1] = c; Pattern[1] = 0x01010101;
} }
return; return;
} }
VOID UpdateContrast(BYTE byContrast)
{
#if defined GRAYSCALE
INT i;
RGBQUAD c = *(RGBQUAD*)&dwKMLColor[byContrast]; // pixel on color
RGBQUAD b = *(RGBQUAD*)&dwKMLColor[byContrast+32]; // pixel off color
if ((Chipset.IORam[BITOFFSET] & DON) == 0 || I == *(DWORD*)&b)
b = *(RGBQUAD*)&dwKMLColor[0];
// fill color palette of bitmap
for (i = 0; i < ARRAYSIZEOF(bmiLcd.bmiColors); ++i)
{
const INT nCAdj[] = { 0, 1, 1, 2, 1, 2, 2, 3 };
_ASSERT(i < ARRAYSIZEOF(bmiLcd.bmiColors));
_ASSERT(i < ARRAYSIZEOF(nCAdj));
bmiLcd.bmiColors[i] = b;
bmiLcd.bmiColors[i].rgbRed += (((INT) c.rgbRed - (INT) b.rgbRed) * nCAdj[i] / 3);
bmiLcd.bmiColors[i].rgbGreen += (((INT) c.rgbGreen - (INT) b.rgbGreen) * nCAdj[i] / 3);
bmiLcd.bmiColors[i].rgbBlue += (((INT) c.rgbBlue - (INT) b.rgbBlue) * nCAdj[i] / 3);
}
#else
bmiLcd.bmiColors[1] = *(RGBQUAD*)&dwKMLColor[byContrast]; // pixel on color
bmiLcd.bmiColors[0] = *(RGBQUAD*)&dwKMLColor[byContrast+32]; // pixel off color
if ((Chipset.IORam[BITOFFSET] & DON) == 0 || I == *(DWORD*)&bmiLcd.bmiColors[0])
bmiLcd.bmiColors[0] = *(RGBQUAD*)&dwKMLColor[0];
#endif
// update palette information
_ASSERT(hLcdDC);
SetDIBColorTable(hLcdDC,0,ARRAYSIZEOF(bmiLcd.bmiColors),bmiLcd.bmiColors);
return;
}
VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue) VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue)
{ {
bmiLcd.dwColor[nId&0x3F] = ((nRed&0xFF)<<16)|((nGreen&0xFF)<<8)|(nBlue&0xFF); dwKMLColor[nId&0x3F] = ((nRed&0xFF)<<16)|((nGreen&0xFF)<<8)|(nBlue&0xFF);
return; return;
} }
@ -114,8 +150,9 @@ VOID CreateLcdBitmap(VOID)
{ {
// create LCD bitmap // create LCD bitmap
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
bmiLcd.Lcd_bmih.biWidth = LCD1_ROW * nLcdDoubled; bmiLcd.Lcd_bmih.biWidth = LCD_ROW * nLcdDoubled;
bmiLcd.Lcd_bmih.biHeight = -64 * nLcdDoubled; bmiLcd.Lcd_bmih.biHeight = -64 * nLcdDoubled;
_ASSERT(hLcdDC == NULL);
hLcdDC = CreateCompatibleDC(hWindowDC); hLcdDC = CreateCompatibleDC(hWindowDC);
_ASSERT(hLcdDC != NULL); _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);
@ -124,14 +161,17 @@ VOID CreateLcdBitmap(VOID)
_ASSERT(hPalette != NULL); _ASSERT(hPalette != NULL);
SelectPalette(hLcdDC, hPalette, FALSE); // set palette for LCD DC SelectPalette(hLcdDC, hPalette, FALSE); // set palette for LCD DC
RealizePalette(hLcdDC); // realize palette RealizePalette(hLcdDC); // realize palette
BuildPattern(); // build Nibble -> DIB mask pattern
UpdateContrast(Chipset.contrast); UpdateContrast(Chipset.contrast);
return;
} }
VOID DestroyLcdBitmap(VOID) VOID DestroyLcdBitmap(VOID)
{ {
WORD i; // set contrast palette to startup colors
// clear background colors WORD i = 0; dwKMLColor[i++] = W;
for (i=32; i< 64; ++i) bmiLcd.dwColor[i] = 0xFFFFFFFF; while(i < 32) dwKMLColor[i++] = B;
while(i < 64) dwKMLColor[i++] = I;
if (hLcdDC != NULL) if (hLcdDC != NULL)
{ {
@ -191,6 +231,8 @@ VOID DestroyMainBitmap(VOID)
VOID UpdateDisplayPointers(VOID) VOID UpdateDisplayPointers(VOID)
{ {
GRAYON(EnterCriticalSection(&csLcdLock));
{
UINT nLines = LINES(Chipset.lcounter); UINT nLines = LINES(Chipset.lcounter);
#if defined DEBUG_DISPLAY #if defined DEBUG_DISPLAY
@ -216,6 +258,9 @@ VOID UpdateDisplayPointers(VOID)
Chipset.start12 = Chipset.start1; Chipset.start12 = Chipset.start1;
} }
Chipset.end2 = Chipset.start2 + (64 - nLines) * 34; Chipset.end2 = Chipset.start2 + (64 - nLines) * 34;
}
GRAYON(LeaveCriticalSection(&csLcdLock));
return;
} }
static BYTE Buf[36]; static BYTE Buf[36];
@ -235,10 +280,10 @@ VOID UpdateMainDisplay(VOID)
#endif #endif
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
if (!Chipset.dispon) if (!(Chipset.IORam[BITOFFSET]&DON))
{ {
nLines = 64; nLines = 64;
ZeroMemory(pbyLcd, LCD1_ROW * nLcdDoubled * nLines * nLcdDoubled); ZeroMemory(pbyLcd, LCD_ROW * nLcdDoubled * nLines * nLcdDoubled);
} }
else else
{ {
@ -250,15 +295,15 @@ VOID UpdateMainDisplay(VOID)
Npeek(Buf,d,36); Npeek(Buf,d,36);
for (x=0; x<36; x++) for (x=0; x<36; x++)
{ {
*(((DWORD*)p)++)=Pattern[Buf[x]&1]; DIBPIXEL(p,Pattern[Buf[x]&1]);
*(((DWORD*)p)++)=Pattern[(Buf[x]>>1) & 1]; DIBPIXEL(p,Pattern[(Buf[x]>>1) & 1]);
*(((DWORD*)p)++)=Pattern[(Buf[x]>>2) & 1]; DIBPIXEL(p,Pattern[(Buf[x]>>2) & 1]);
*(((DWORD*)p)++)=Pattern[(Buf[x]>>3) & 1]; DIBPIXEL(p,Pattern[(Buf[x]>>3) & 1]);
} }
CopyMemory(p, p-LCD3_ROW, LCD3_ROW); CopyMemory(p, p-LCD_ROW*4, LCD_ROW*4);
p+=LCD3_ROW; p+=LCD_ROW*4;
CopyMemory(p, p-LCD3_ROW*2, LCD3_ROW*2); CopyMemory(p, p-LCD_ROW*8, LCD_ROW*8);
p+=LCD3_ROW*2; p+=LCD_ROW*8;
d+=Chipset.width; d+=Chipset.width;
} }
} }
@ -269,11 +314,11 @@ VOID UpdateMainDisplay(VOID)
Npeek(Buf,d,36); Npeek(Buf,d,36);
for (x=0; x<36; x++) for (x=0; x<36; x++)
{ {
*(((DWORD*)p)++)=Pattern[Buf[x]&3]; DIBPIXEL(p,Pattern[Buf[x]&3]);
*(((DWORD*)p)++)=Pattern[Buf[x]>>2]; DIBPIXEL(p,Pattern[Buf[x]>>2]);
} }
CopyMemory(p, p-LCD2_ROW, LCD2_ROW); CopyMemory(p, p-LCD_ROW*2, LCD_ROW*2);
p+=LCD2_ROW; p+=LCD_ROW*2;
d+=Chipset.width; d+=Chipset.width;
} }
} }
@ -282,7 +327,10 @@ VOID UpdateMainDisplay(VOID)
for (y = 0; y < nLines; ++y) for (y = 0; y < nLines; ++y)
{ {
Npeek(Buf,d,36); Npeek(Buf,d,36);
for (x=0; x<36; x++) *(((DWORD*)p)++)=Pattern[Buf[x]]; for (x=0; x<36; x++) // every 4 pixel
{
DIBPIXEL(p,Pattern[Buf[x]]);
}
d+=Chipset.width; d+=Chipset.width;
} }
} }
@ -313,12 +361,12 @@ VOID UpdateMenuDisplay(VOID)
nLines = LINES(Chipset.lcounter); nLines = LINES(Chipset.lcounter);
if (!Chipset.dispon) return; if (!(Chipset.IORam[BITOFFSET]&DON)) return;
if (nLines == 64) return; // menu disabled if (nLines == 64) return; // menu disabled
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
// calculate bitmap offset // calculate bitmap offset
p = pbyLcd + (nLines*nLcdDoubled*LCD1_ROW*nLcdDoubled); p = pbyLcd + (nLines*nLcdDoubled*LCD_ROW*nLcdDoubled);
if (nLcdDoubled == 4) if (nLcdDoubled == 4)
{ {
for (y = nLines; y < 64; ++y) for (y = nLines; y < 64; ++y)
@ -326,15 +374,15 @@ VOID UpdateMenuDisplay(VOID)
Npeek(Buf,d,34); // 34 nibbles are viewed Npeek(Buf,d,34); // 34 nibbles are viewed
for (x = 0; x < 36; ++x) for (x = 0; x < 36; ++x)
{ {
*(((DWORD*)p)++)=Pattern[Buf[x]&1]; DIBPIXEL(p,Pattern[Buf[x]&1]);
*(((DWORD*)p)++)=Pattern[(Buf[x]>>1) & 1]; DIBPIXEL(p,Pattern[(Buf[x]>>1) & 1]);
*(((DWORD*)p)++)=Pattern[(Buf[x]>>2) & 1]; DIBPIXEL(p,Pattern[(Buf[x]>>2) & 1]);
*(((DWORD*)p)++)=Pattern[(Buf[x]>>3) & 1]; DIBPIXEL(p,Pattern[(Buf[x]>>3) & 1]);
} }
CopyMemory(p, p-LCD3_ROW, LCD3_ROW); CopyMemory(p, p-LCD_ROW*4, LCD_ROW*4);
p+=LCD3_ROW; p+=LCD_ROW*4;
CopyMemory(p, p-LCD3_ROW*2, LCD3_ROW*2); CopyMemory(p, p-LCD_ROW*8, LCD_ROW*8);
p+=LCD3_ROW*2; p+=LCD_ROW*8;
d+=34; d+=34;
} }
} }
@ -345,11 +393,11 @@ VOID UpdateMenuDisplay(VOID)
Npeek(Buf,d,34); // 34 nibbles are viewed Npeek(Buf,d,34); // 34 nibbles are viewed
for (x = 0; x < 36; ++x) for (x = 0; x < 36; ++x)
{ {
*(((DWORD*)p)++)=Pattern[Buf[x]&3]; DIBPIXEL(p,Pattern[Buf[x]&3]);
*(((DWORD*)p)++)=Pattern[Buf[x]>>2]; DIBPIXEL(p,Pattern[Buf[x]>>2]);
} }
CopyMemory(p, p-LCD2_ROW, LCD2_ROW); CopyMemory(p, p-LCD_ROW*2, LCD_ROW*2);
p+=LCD2_ROW; p+=LCD_ROW*2;
d+=34; d+=34;
} }
} }
@ -358,7 +406,10 @@ VOID UpdateMenuDisplay(VOID)
for (y = nLines; y < 64; ++y) for (y = nLines; y < 64; ++y)
{ {
Npeek(Buf,d,34); // 34 nibbles are viewed Npeek(Buf,d,34); // 34 nibbles are viewed
for (x = 0; x < 36; ++x) *(((DWORD*)p)++)=Pattern[Buf[x]]; for (x=0; x<36; x++) // every 4 pixel
{
DIBPIXEL(p,Pattern[Buf[x]]);
}
d+=34; d+=34;
} }
} }
@ -375,6 +426,7 @@ VOID UpdateMenuDisplay(VOID)
VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s) VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
{ {
#if !defined GRAYSCALE
INT x0, x; INT x0, x;
INT y0, y; INT y0, y;
DWORD *p; DWORD *p;
@ -403,8 +455,8 @@ VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
// calculate memory position in LCD bitmap // calculate memory position in LCD bitmap
p = (DWORD*) (pbyLcd + y0*LCD1_ROW*nLcdDoubled*nLcdDoubled p = (DWORD*) (pbyLcd + y0*LCD_ROW*nLcdDoubled*nLcdDoubled
+ x0*sizeof(bmiLcd.dwColor[0])*nLcdDoubled); + x0*sizeof(*p)*nLcdDoubled);
while (s--) // loop for nibbles to write while (s--) // loop for nibbles to write
{ {
@ -437,7 +489,7 @@ VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
x = 0; // first coloumn x = 0; // first coloumn
++y; // next row ++y; // next row
// recalculate bitmap memory position of new line // recalculate bitmap memory position of new line
p = (DWORD*) (pbyLcd+y*LCD1_ROW*nLcdDoubled*nLcdDoubled); p = (DWORD*) (pbyLcd+y*LCD_ROW*nLcdDoubled*nLcdDoubled);
} }
else else
p += nLcdDoubled; // next x position in bitmap p += nLcdDoubled; // next x position in bitmap
@ -477,11 +529,13 @@ VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
GdiFlush(); GdiFlush();
} }
LeaveCriticalSection(&csGDILock); LeaveCriticalSection(&csGDILock);
#endif
return; return;
} }
VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s) VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
{ {
#if !defined GRAYSCALE
UINT x0, x; UINT x0, x;
UINT y0, y; UINT y0, y;
DWORD *p; DWORD *p;
@ -504,7 +558,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
if (nLcdDoubled == 4) if (nLcdDoubled == 4)
{ {
p = (DWORD*)(pbyLcd + y0*LCD3_ROW*4 + x0*16); p = (DWORD*)(pbyLcd + y0*LCD_ROW*16 + x0*16);
while (s--) while (s--)
{ {
if (x<34) if (x<34)
@ -521,7 +575,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
x=0; x=0;
y++; y++;
if (y==64) break; if (y==64) break;
p=(DWORD*)(pbyLcd+y*LCD3_ROW*4); p=(DWORD*)(pbyLcd+y*LCD_ROW*16);
} else p+=4; } else p+=4;
} }
EnterCriticalSection(&csGDILock); // solving NT GDI problems EnterCriticalSection(&csGDILock); // solving NT GDI problems
@ -544,7 +598,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
} }
if (nLcdDoubled == 2) if (nLcdDoubled == 2)
{ {
p = (DWORD*)(pbyLcd + y0*LCD2_ROW*2 + x0*8); p = (DWORD*)(pbyLcd + y0*LCD_ROW*4 + x0*8);
while (s--) while (s--)
{ {
if (x<34) if (x<34)
@ -559,7 +613,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
x=0; x=0;
y++; y++;
if (y==64) break; if (y==64) break;
p=(DWORD*)(pbyLcd+y*LCD2_ROW*2); p=(DWORD*)(pbyLcd+y*LCD_ROW*4);
} else p+=2; } else p+=2;
} }
EnterCriticalSection(&csGDILock); // solving NT GDI problems EnterCriticalSection(&csGDILock); // solving NT GDI problems
@ -582,7 +636,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
} }
if (nLcdDoubled == 1) if (nLcdDoubled == 1)
{ {
p = (DWORD*)(pbyLcd + y0*LCD1_ROW + x0*4); p = (DWORD*)(pbyLcd + y0*LCD_ROW + x0*4);
while (s--) while (s--)
{ {
if (x<34) *p = Pattern[*a]; if (x<34) *p = Pattern[*a];
@ -593,7 +647,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
x=0; x=0;
y++; y++;
if (y==64) break; if (y==64) break;
p=(DWORD*)(pbyLcd+y*LCD1_ROW); p=(DWORD*)(pbyLcd+y*LCD_ROW);
} else p++; } else p++;
} }
EnterCriticalSection(&csGDILock); // solving NT GDI problems EnterCriticalSection(&csGDILock); // solving NT GDI problems
@ -612,6 +666,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
} }
LeaveCriticalSection(&csGDILock); LeaveCriticalSection(&csGDILock);
} }
#endif
return; return;
} }
@ -659,6 +714,131 @@ VOID ResizeWindow(VOID)
rectWindow.bottom - rectWindow.top, rectWindow.bottom - rectWindow.top,
SWP_NOMOVE | SWP_NOZORDER); SWP_NOMOVE | SWP_NOZORDER);
} }
_ASSERT(hWindowDC); // move destination window
SetWindowOrgEx(hWindowDC, nBackgroundX, nBackgroundY, NULL);
InvalidateRect(hWnd,NULL,TRUE); InvalidateRect(hWnd,NULL,TRUE);
return; return;
} }
#if defined GRAYSCALE
#define DISPLAY_FREQ 19 // display update 1/frequency (1/64) in ms
static LARGE_INTEGER lLcdRef; // reference time for VBL counter
static UINT uLcdTimerId = 0;
static VOID CALLBACK LcdProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
EnterCriticalSection(&csLcdLock);
{
UpdateMainDisplay(); // update display
UpdateMenuDisplay();
}
LeaveCriticalSection(&csLcdLock);
QueryPerformanceCounter(&lLcdRef); // actual time
return;
UNREFERENCED_PARAMETER(uEventId);
UNREFERENCED_PARAMETER(uMsg);
UNREFERENCED_PARAMETER(dwUser);
UNREFERENCED_PARAMETER(dw1);
UNREFERENCED_PARAMETER(dw2);
}
// LCD line counter calculation
BYTE GetLineCounter(VOID)
{
LARGE_INTEGER lLC;
BYTE byTime;
if (uLcdTimerId == 0) // display off
return ((Chipset.IORam[LINECOUNT+1] & (LC5|LC4)) << 4) | Chipset.IORam[LINECOUNT];
QueryPerformanceCounter(&lLC); // get elapsed time since display update
// elapsed ticks so far
byTime = (BYTE) (((lLC.QuadPart - lLcdRef.QuadPart) << 12) / lFreq.QuadPart);
if (byTime > 0x3F) byTime = 0x3F; // all counts made
return (0x7E - byTime) & 0x3F; // update display between VBL counter 0x3F-0x3E
}
VOID StartDisplay(BYTE byInitial)
{
if (uLcdTimerId) // LCD update timer running
return; // -> quit
if (Chipset.IORam[BITOFFSET]&DON) // display on?
{
QueryPerformanceCounter(&lLcdRef); // actual time of top line
// adjust startup counter to get the right VBL value
lLcdRef.QuadPart -= ((LONGLONG) ((0x7E - byInitial) & 0x3F) * lFreq.QuadPart) >> 12;
uLcdTimerId = timeSetEvent(DISPLAY_FREQ,0,(LPTIMECALLBACK)&LcdProc,0,TIME_PERIODIC);
_ASSERT(uLcdTimerId); // test if display update timer started
}
return;
}
VOID StopDisplay(VOID)
{
BYTE a[2];
ReadIO(a,LINECOUNT,2); // update VBL at display off time
if (uLcdTimerId == 0) // timer stopped
return; // -> quit
timeKillEvent(uLcdTimerId); // stop display update
uLcdTimerId = 0; // set flag display update stopped
EnterCriticalSection(&csLcdLock); // update to last condition
{
UpdateMainDisplay(); // update display
UpdateMenuDisplay();
}
LeaveCriticalSection(&csLcdLock);
return;
}
#else
static BYTE byVblRef = 0; // VBL stop reference
// LCD line counter calculation
static BYTE F4096Hz(VOID) // get a 6 bit 4096Hz down counter value
{
LARGE_INTEGER lLC;
QueryPerformanceCounter(&lLC); // get counter value
// calculate 4096 Hz frequency down counter value
return -(BYTE)(((lLC.QuadPart - lAppStart.QuadPart) << 12) / lFreq.QuadPart) & 0x3F;
}
BYTE GetLineCounter(VOID) // get line counter value
{
_ASSERT(byVblRef < 0x40);
return (0x40 + F4096Hz() - byVblRef) & 0x3F;
}
VOID StartDisplay(BYTE byInitial)
{
// get positive VBL difference between now and stop time
byVblRef = (0x40 + F4096Hz() - byInitial) & 0x3F;
return;
}
VOID StopDisplay(VOID)
{
BYTE a[2];
ReadIO(a,LINECOUNT,2); // update VBL at display off time
return;
}
#endif

View file

@ -13,7 +13,7 @@
#include "kml.h" #include "kml.h"
#include "debugger.h" #include "debugger.h"
#define VERSION "1.25" #define VERSION "1.30"
#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
@ -46,10 +46,12 @@ static const TCHAR szLicence[] =
CRITICAL_SECTION csGDILock; // critical section for hWindowDC CRITICAL_SECTION csGDILock; // critical section for hWindowDC
GRAYON(CRITICAL_SECTION csLcdLock); // critical section for display update
CRITICAL_SECTION csKeyLock; // critical section for key scan 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 csTxdLock; // critical section for transmit byte
CRITICAL_SECTION csRecvLock; // critical section for receive byte CRITICAL_SECTION csRecvLock; // critical section for receive byte
INT nArgc; // no. of command line arguments INT nArgc; // no. of command line arguments
LPCTSTR *ppArgv; // command line arguments LPCTSTR *ppArgv; // command line arguments
@ -97,7 +99,7 @@ VOID SetWindowTitle(LPTSTR szString)
return; return;
} }
VOID UpdateWindowStatus() VOID UpdateWindowStatus(VOID)
{ {
if (hWnd) // window open if (hWnd) // window open
{ {
@ -127,7 +129,7 @@ VOID UpdateWindowStatus()
EnableMenuItem(hMenu,ID_BACKUP_DELETE,uBackup); EnableMenuItem(hMenu,ID_BACKUP_DELETE,uBackup);
EnableMenuItem(hMenu,ID_VIEW_SCRIPT,uRun); EnableMenuItem(hMenu,ID_VIEW_SCRIPT,uRun);
EnableMenuItem(hMenu,ID_TOOL_DISASM,uRun); EnableMenuItem(hMenu,ID_TOOL_DISASM,uRun);
EnableMenuItem(hMenu,ID_TOOL_DEBUG,(bRun && !bDbgEnable) ? MF_ENABLED : MF_GRAYED); EnableMenuItem(hMenu,ID_TOOL_DEBUG,(bRun && nDbgState == DBG_OFF) ? MF_ENABLED : MF_GRAYED);
} }
return; return;
} }
@ -213,12 +215,12 @@ static VOID SetCommList(HWND hDlg,int nIDDlgItem,LPCTSTR szSetting)
TCHAR szBuffer[16]; TCHAR szBuffer[16];
WPARAM wSelect = 0; // set select to disabled WPARAM wSelect = 0; // set select to disabled
SendDlgItemMessage(hDlg,nIDDlgItem,CB_ADDSTRING,0,(LPARAM) NO_SERIAL); SendDlgItemMessage(hDlg,nIDDlgItem,CB_ADDSTRING,0,(LPARAM) _T(NO_SERIAL));
for (wCount = 1;wCount <= MAXPORTS;++wCount) for (wCount = 1;wCount <= MAXPORTS;++wCount)
{ {
wsprintf(szBuffer,_T("COM%u"),wCount); wsprintf(szBuffer,_T("\\\\.\\COM%u"),wCount);
if ((bAdd = (lstrcmp(szBuffer,szSetting) == 0))) if ((bAdd = (lstrcmp(&szBuffer[4],szSetting) == 0)))
wSelect = wIndex; wSelect = wIndex;
// test if COM port is valid // test if COM port is valid
@ -232,7 +234,7 @@ static VOID SetCommList(HWND hDlg,int nIDDlgItem,LPCTSTR szSetting)
if (bAdd) // add item to combobox if (bAdd) // add item to combobox
{ {
SendDlgItemMessage(hDlg,nIDDlgItem,CB_ADDSTRING,0,(LPARAM) szBuffer); SendDlgItemMessage(hDlg,nIDDlgItem,CB_ADDSTRING,0,(LPARAM) &szBuffer[4]);
++wIndex; ++wIndex;
} }
} }
@ -415,10 +417,12 @@ static UINT SaveChanges(BOOL bAuto)
static LRESULT OnCreate(HWND hWindow) static LRESULT OnCreate(HWND hWindow)
{ {
InitializeCriticalSection(&csGDILock); InitializeCriticalSection(&csGDILock);
GRAYON(InitializeCriticalSection(&csLcdLock));
InitializeCriticalSection(&csKeyLock); InitializeCriticalSection(&csKeyLock);
InitializeCriticalSection(&csIOLock); InitializeCriticalSection(&csIOLock);
InitializeCriticalSection(&csT1Lock); InitializeCriticalSection(&csT1Lock);
InitializeCriticalSection(&csT2Lock); InitializeCriticalSection(&csT2Lock);
InitializeCriticalSection(&csTxdLock);
InitializeCriticalSection(&csRecvLock); InitializeCriticalSection(&csRecvLock);
hWnd = hWindow; hWnd = hWindow;
@ -433,16 +437,19 @@ 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
ReleaseDC(hWnd, hWindowDC); if (hThread) SwitchToState(SM_RETURN); // exit emulation thread
SetWindowTitle(NULL); // free memory of title SetWindowTitle(NULL); // free memory of title
ReleaseDC(hWnd, hWindowDC);
hWindowDC = NULL; // hWindowDC isn't valid any more hWindowDC = NULL; // hWindowDC isn't valid any more
hWnd = NULL; hWnd = NULL;
DeleteCriticalSection(&csGDILock); DeleteCriticalSection(&csGDILock);
GRAYON(DeleteCriticalSection(&csLcdLock));
DeleteCriticalSection(&csKeyLock); DeleteCriticalSection(&csKeyLock);
DeleteCriticalSection(&csIOLock); DeleteCriticalSection(&csIOLock);
DeleteCriticalSection(&csT1Lock); DeleteCriticalSection(&csT1Lock);
DeleteCriticalSection(&csT2Lock); DeleteCriticalSection(&csT2Lock);
DeleteCriticalSection(&csTxdLock);
DeleteCriticalSection(&csRecvLock); DeleteCriticalSection(&csRecvLock);
#if defined _USRDLL // DLL version #if defined _USRDLL // DLL version
@ -465,6 +472,12 @@ static LRESULT OnPaint(HWND hWindow)
hPaintDC = BeginPaint(hWindow, &Paint); hPaintDC = BeginPaint(hWindow, &Paint);
if (hMainDC != NULL) if (hMainDC != NULL)
{ {
RECT rcMainPaint = Paint.rcPaint;
rcMainPaint.left += nBackgroundX; // coordinates in source bitmap
rcMainPaint.top += nBackgroundY;
rcMainPaint.right += nBackgroundX;
rcMainPaint.bottom += nBackgroundY;
EnterCriticalSection(&csGDILock); // solving NT GDI problems EnterCriticalSection(&csGDILock); // solving NT GDI problems
{ {
UINT nLines = (Chipset.lcounter == 0) ? 64 : (Chipset.lcounter + 1); UINT nLines = (Chipset.lcounter == 0) ? 64 : (Chipset.lcounter + 1);
@ -472,7 +485,7 @@ static LRESULT OnPaint(HWND hWindow)
// redraw background bitmap // redraw background bitmap
BitBlt(hPaintDC, Paint.rcPaint.left, Paint.rcPaint.top, BitBlt(hPaintDC, Paint.rcPaint.left, Paint.rcPaint.top,
Paint.rcPaint.right-Paint.rcPaint.left, Paint.rcPaint.bottom-Paint.rcPaint.top, Paint.rcPaint.right-Paint.rcPaint.left, Paint.rcPaint.bottom-Paint.rcPaint.top,
hMainDC, Paint.rcPaint.left, Paint.rcPaint.top, SRCCOPY); hMainDC, rcMainPaint.left, rcMainPaint.top, SRCCOPY);
// redraw main display area // redraw main display area
BitBlt(hWindowDC, nLcdX, nLcdY, BitBlt(hWindowDC, nLcdX, nLcdY,
131*nLcdDoubled, nLines*nLcdDoubled, 131*nLcdDoubled, nLines*nLcdDoubled,
@ -485,7 +498,7 @@ static LRESULT OnPaint(HWND hWindow)
} }
LeaveCriticalSection(&csGDILock); LeaveCriticalSection(&csGDILock);
UpdateAnnunciators(); UpdateAnnunciators();
RefreshButtons(&Paint.rcPaint); RefreshButtons(&rcMainPaint);
} }
EndPaint(hWindow, &Paint); EndPaint(hWindow, &Paint);
return 0; return 0;
@ -506,12 +519,17 @@ static LRESULT OnDropFiles(HANDLE hFilesInfo)
// get number of files dropped // get number of files dropped
wNumFiles = DragQueryFile (hFilesInfo,(UINT)-1,NULL,0); wNumFiles = DragQueryFile (hFilesInfo,(UINT)-1,NULL,0);
if (!Chipset.dispon && !bDbgEnable) // calculator off, turn on SuspendDebugger(); // suspend debugger
bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control
// calculator off, turn on
if (!(Chipset.IORam[BITOFFSET]&DON))
{ {
// turn on HP // turn on HP
KeyboardEvent(TRUE,0,0x8000); KeyboardEvent(TRUE,0,0x8000);
Sleep(200); Sleep(200);
KeyboardEvent(FALSE,0,0x8000); KeyboardEvent(FALSE,0,0x8000);
Sleep(200);
} }
_ASSERT(nState == SM_RUN); // emulator must be in RUN state _ASSERT(nState == SM_RUN); // emulator must be in RUN state
@ -519,7 +537,7 @@ static LRESULT OnDropFiles(HANDLE hFilesInfo)
{ {
DragFinish (hFilesInfo); DragFinish (hFilesInfo);
InfoMessage(_T("The emulator is busy.")); InfoMessage(_T("The emulator is busy."));
return 0; goto cancel;
} }
_ASSERT(nState == SM_SLEEP); _ASSERT(nState == SM_SLEEP);
@ -540,20 +558,24 @@ static LRESULT OnDropFiles(HANDLE hFilesInfo)
_ASSERT(nState == SM_RUN); _ASSERT(nState == SM_RUN);
if (bSuccess == FALSE) // data not copied if (bSuccess == FALSE) // data not copied
return 0; goto cancel;
KeyboardEvent(TRUE,0,0x8000); KeyboardEvent(TRUE,0,0x8000);
Sleep(200); Sleep(200);
KeyboardEvent(FALSE,0,0x8000); KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode // wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0); while(Chipset.Shutdn == FALSE) Sleep(0);
cancel:
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
ResumeDebugger();
return 0; return 0;
} }
// //
// ID_FILE_NEW // ID_FILE_NEW
// //
static LRESULT OnFileNew() static LRESULT OnFileNew(VOID)
{ {
SaveBackup(); SaveBackup();
if (pbyRom) if (pbyRom)
@ -572,7 +594,7 @@ cancel:
// //
// ID_FILE_OPEN // ID_FILE_OPEN
// //
static LRESULT OnFileOpen() static LRESULT OnFileOpen(VOID)
{ {
if (pbyRom) if (pbyRom)
{ {
@ -592,7 +614,7 @@ cancel:
// //
// ID_FILE_SAVE // ID_FILE_SAVE
// //
static LRESULT OnFileSave() static LRESULT OnFileSave(VOID)
{ {
if (pbyRom == NULL) return 0; if (pbyRom == NULL) return 0;
SwitchToState(SM_INVALID); SwitchToState(SM_INVALID);
@ -604,7 +626,7 @@ static LRESULT OnFileSave()
// //
// ID_FILE_SAVEAS // ID_FILE_SAVEAS
// //
static LRESULT OnFileSaveAs() static LRESULT OnFileSaveAs(VOID)
{ {
UINT uReply; UINT uReply;
@ -631,12 +653,13 @@ static LRESULT OnFileSaveAs()
// //
// ID_FILE_CLOSE // ID_FILE_CLOSE
// //
static LRESULT OnFileClose() static LRESULT OnFileClose(VOID)
{ {
if (pbyRom == NULL) return 0; if (pbyRom == NULL) return 0;
SwitchToState(SM_INVALID); SwitchToState(SM_INVALID);
if (SaveChanges(bAutoSave)!=IDCANCEL) if (SaveChanges(bAutoSave)!=IDCANCEL)
{ {
DisableDebugger();
KillKML(); KillKML();
ResetDocument(); ResetDocument();
SetWindowTitle(NULL); SetWindowTitle(NULL);
@ -653,7 +676,7 @@ static LRESULT OnFileClose()
// //
// WM_SYS_CLOSE // WM_SYS_CLOSE
// //
static LRESULT OnFileExit() static LRESULT OnFileExit(VOID)
{ {
SwitchToState(SM_INVALID); // hold emulation thread SwitchToState(SM_INVALID); // hold emulation thread
if (SaveChanges(bAutoSaveOnExit) == IDCANCEL) if (SaveChanges(bAutoSaveOnExit) == IDCANCEL)
@ -668,7 +691,7 @@ static LRESULT OnFileExit()
// //
// ID_STACK_COPY // ID_STACK_COPY
// //
static LRESULT OnStackCopy() // copy data from stack static LRESULT OnStackCopy(VOID) // copy data from stack
{ {
HANDLE hClipObj; HANDLE hClipObj;
LPBYTE lpData; LPBYTE lpData;
@ -733,18 +756,23 @@ error:
// //
// ID_STACK_PASTE // ID_STACK_PASTE
// //
static LRESULT OnStackPaste() // paste data to stack static LRESULT OnStackPaste(VOID) // paste data to stack
{ {
HANDLE hClipObj; HANDLE hClipObj;
LPBYTE lpClipdata,lpData; LPBYTE lpClipdata,lpData;
BOOL bSuccess = FALSE; BOOL bSuccess = FALSE;
if (!Chipset.dispon && !bDbgEnable) // calculator off, turn on SuspendDebugger(); // suspend debugger
bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control
// calculator off, turn on
if (!(Chipset.IORam[BITOFFSET]&DON))
{ {
KeyboardEvent(TRUE,0,0x8000); KeyboardEvent(TRUE,0,0x8000);
Sleep(200); Sleep(200);
KeyboardEvent(FALSE,0,0x8000); KeyboardEvent(FALSE,0,0x8000);
Sleep(200);
// wait for sleep mode // wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0); while(Chipset.Shutdn == FALSE) Sleep(0);
} }
@ -753,7 +781,7 @@ static LRESULT OnStackPaste() // paste data to stack
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{ {
InfoMessage(_T("The emulator is busy.")); InfoMessage(_T("The emulator is busy."));
return 0; goto cancel;
} }
_ASSERT(nState == SM_SLEEP); _ASSERT(nState == SM_SLEEP);
@ -790,20 +818,25 @@ static LRESULT OnStackPaste() // paste data to stack
_ASSERT(nState == SM_RUN); _ASSERT(nState == SM_RUN);
if (bSuccess == FALSE) // data not copied if (bSuccess == FALSE) // data not copied
return 0; goto cancel;
KeyboardEvent(TRUE,0,0x8000); KeyboardEvent(TRUE,0,0x8000);
Sleep(200); Sleep(200);
KeyboardEvent(FALSE,0,0x8000); KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode // wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0); while(Chipset.Shutdn == FALSE) Sleep(0);
cancel:
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
ResumeDebugger();
return 0; return 0;
} }
// //
// ID_VIEW_COPY // ID_VIEW_COPY
// //
static LRESULT OnViewCopy() static LRESULT OnViewCopy(VOID)
{ {
if (OpenClipboard(hWnd)) if (OpenClipboard(hWnd))
{ {
@ -827,7 +860,7 @@ static LRESULT OnViewCopy()
hBmp = CreateCompatibleBitmap(hLcdDC,131*nLcdDoubled,64*nLcdDoubled); hBmp = CreateCompatibleBitmap(hLcdDC,131*nLcdDoubled,64*nLcdDoubled);
hBmpDC = CreateCompatibleDC(hLcdDC); hBmpDC = CreateCompatibleDC(hLcdDC);
hBmp = SelectObject(hBmpDC,hBmp); hBmp = SelectObject(hBmpDC,hBmp);
BitBlt(hBmpDC, 0, 0, 131*nLcdDoubled, 64*nLcdDoubled, hLcdDC, 0, 0, SRCCOPY); BitBlt(hBmpDC,0,0,131*nLcdDoubled,64*nLcdDoubled,hLcdDC,Chipset.boffset*nLcdDoubled,0,SRCCOPY);
hBmp = SelectObject(hBmpDC,hBmp); hBmp = SelectObject(hBmpDC,hBmp);
// fill BITMAP structure for size information // fill BITMAP structure for size information
@ -897,11 +930,12 @@ static LRESULT OnViewCopy()
HBITMAP hOldBmp, hBmp; HBITMAP hOldBmp, hBmp;
HDC hBmpDC; HDC hBmpDC;
// don't work with background index <> 0
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
hBmp = CreateBitmap(131*nLcdDoubled,64*nLcdDoubled,1,1,NULL); hBmp = CreateBitmap(131*nLcdDoubled,64*nLcdDoubled,1,1,NULL);
hBmpDC = CreateCompatibleDC(NULL); hBmpDC = CreateCompatibleDC(NULL);
hOldBmp = (HBITMAP)SelectObject(hBmpDC,hBmp); hOldBmp = (HBITMAP)SelectObject(hBmpDC,hBmp);
BitBlt(hBmpDC, 0, 0, 131*nLcdDoubled, 64*nLcdDoubled, hLcdDC, 0, 0, SRCCOPY); BitBlt(hBmpDC,0,0,131*nLcdDoubled,64*nLcdDoubled,hLcdDC,Chipset.boffset*nLcdDoubled,0,SRCCOPY);
SetClipboardData(CF_BITMAP,hBmp); SetClipboardData(CF_BITMAP,hBmp);
SelectObject(hBmpDC,hOldBmp); SelectObject(hBmpDC,hOldBmp);
DeleteDC(hBmpDC); DeleteDC(hBmpDC);
@ -915,7 +949,7 @@ static LRESULT OnViewCopy()
// //
// ID_VIEW_RESET // ID_VIEW_RESET
// //
static LRESULT OnViewReset() static LRESULT OnViewReset(VOID)
{ {
if (nState != SM_RUN) return 0; if (nState != SM_RUN) return 0;
if (YesNoMessage(_T("Are you sure you want to press the Reset Button ?"))==IDYES) if (YesNoMessage(_T("Are you sure you want to press the Reset Button ?"))==IDYES)
@ -930,7 +964,7 @@ static LRESULT OnViewReset()
// //
// ID_VIEW_SETTINGS // ID_VIEW_SETTINGS
// //
static LRESULT OnViewSettings() static LRESULT OnViewSettings(VOID)
{ {
ReadSettings(); ReadSettings();
@ -947,7 +981,7 @@ static LRESULT OnViewSettings()
// //
// ID_VIEW_SCRIPT // ID_VIEW_SCRIPT
// //
static LRESULT OnViewScript() static LRESULT OnViewScript(VOID)
{ {
BYTE cType = cCurrentRomType; BYTE cType = cCurrentRomType;
if (nState != SM_RUN) if (nState != SM_RUN)
@ -979,7 +1013,7 @@ ok:
// //
// ID_BACKUP_SAVE // ID_BACKUP_SAVE
// //
static LRESULT OnBackupSave() static LRESULT OnBackupSave(VOID)
{ {
UINT nOldState; UINT nOldState;
if (pbyRom == NULL) return 0; if (pbyRom == NULL) return 0;
@ -992,7 +1026,7 @@ static LRESULT OnBackupSave()
// //
// ID_BACKUP_RESTORE // ID_BACKUP_RESTORE
// //
static LRESULT OnBackupRestore() static LRESULT OnBackupRestore(VOID)
{ {
SwitchToState(SM_INVALID); SwitchToState(SM_INVALID);
RestoreBackup(); RestoreBackup();
@ -1003,7 +1037,7 @@ static LRESULT OnBackupRestore()
// //
// ID_BACKUP_DELETE // ID_BACKUP_DELETE
// //
static LRESULT OnBackupDelete() static LRESULT OnBackupDelete(VOID)
{ {
ResetBackup(); ResetBackup();
return 0; return 0;
@ -1012,28 +1046,34 @@ static LRESULT OnBackupDelete()
// //
// ID_OBJECT_LOAD // ID_OBJECT_LOAD
// //
static LRESULT OnObjectLoad() static LRESULT OnObjectLoad(VOID)
{ {
static BOOL bWarning = TRUE; static BOOL bWarning = TRUE;
if (!Chipset.dispon && !bDbgEnable) // calculator off, turn on SuspendDebugger(); // suspend debugger
bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control
// calculator off, turn on
if (!(Chipset.IORam[BITOFFSET]&DON))
{ {
// turn on HP
KeyboardEvent(TRUE,0,0x8000); KeyboardEvent(TRUE,0,0x8000);
Sleep(200); Sleep(200);
KeyboardEvent(FALSE,0,0x8000); KeyboardEvent(FALSE,0,0x8000);
Sleep(200);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
} }
if (nState != SM_RUN) if (nState != SM_RUN)
{ {
InfoMessage(_T("The emulator must be running to load an object.")); InfoMessage(_T("The emulator must be running to load an object."));
return 0; goto cancel;
} }
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{ {
InfoMessage(_T("The emulator is busy.")); InfoMessage(_T("The emulator is busy."));
return 0; goto cancel;
} }
_ASSERT(nState == SM_SLEEP); _ASSERT(nState == SM_SLEEP);
@ -1054,20 +1094,20 @@ static LRESULT OnObjectLoad()
break; break;
case IDCANCEL: case IDCANCEL:
SwitchToState(SM_RUN); SwitchToState(SM_RUN);
return 0; goto cancel;
} }
} }
if (!GetLoadObjectFilename()) if (!GetLoadObjectFilename())
{ {
SwitchToState(SM_RUN); SwitchToState(SM_RUN);
return 0; goto cancel;
} }
if (!LoadObject(szBufferFilename)) if (!LoadObject(szBufferFilename))
{ {
SwitchToState(SM_RUN); SwitchToState(SM_RUN);
return 0; goto cancel;
} }
SwitchToState(SM_RUN); // run state SwitchToState(SM_RUN); // run state
@ -1077,13 +1117,17 @@ static LRESULT OnObjectLoad()
Sleep(200); Sleep(200);
KeyboardEvent(FALSE,0,0x8000); KeyboardEvent(FALSE,0,0x8000);
while(Chipset.Shutdn == FALSE) Sleep(0); while(Chipset.Shutdn == FALSE) Sleep(0);
cancel:
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
ResumeDebugger();
return 0; return 0;
} }
// //
// ID_OBJECT_SAVE // ID_OBJECT_SAVE
// //
static LRESULT OnObjectSave() static LRESULT OnObjectSave(VOID)
{ {
if (nState != SM_RUN) if (nState != SM_RUN)
{ {
@ -1165,9 +1209,10 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
return TRUE; return TRUE;
case IDC_DISASM_PORT2: case IDC_DISASM_PORT2:
disassembler_map = MEM_PORT2; disassembler_map = MEM_PORT2;
dwAddressMax = (cCurrentRomType=='E' || cCurrentRomType=='X') dwAddressMax = ((cCurrentRomType=='E' || cCurrentRomType=='X')
? (Chipset.Port2Size * 2048) ? Chipset.Port2Size
: ((dwPort2Mask != 0) ? ((dwPort2Mask + 1) << 18) : (dwPort2Size * 2048)); : dwPort2Size)
* 2048;
return TRUE; return TRUE;
case IDOK: case IDOK:
SendDlgItemMessage(hDlg,IDC_DISASM_ADR,EM_SETSEL,0,-1); SendDlgItemMessage(hDlg,IDC_DISASM_ADR,EM_SETSEL,0,-1);
@ -1209,7 +1254,6 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
// //
static BOOL CALLBACK About(HWND hDlg, UINT message, DWORD wParam, LONG lParam) static BOOL CALLBACK About(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
{ {
switch (message) switch (message)
{ {
case WM_INITDIALOG: case WM_INITDIALOG:
@ -1228,7 +1272,7 @@ static BOOL CALLBACK About(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
UNREFERENCED_PARAMETER(lParam); UNREFERENCED_PARAMETER(lParam);
} }
static LRESULT OnToolDisasm() // disasm dialogbox call static LRESULT OnToolDisasm(VOID) // disasm dialogbox call
{ {
if (pbyRom) SwitchToState(SM_SLEEP); if (pbyRom) SwitchToState(SM_SLEEP);
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_DISASM), hWnd, (DLGPROC)Disasm) == -1) if (DialogBox(hApp, MAKEINTRESOURCE(IDD_DISASM), hWnd, (DLGPROC)Disasm) == -1)
@ -1237,7 +1281,7 @@ static LRESULT OnToolDisasm() // disasm dialogbox call
return 0; return 0;
} }
static LRESULT OnAbout() static LRESULT OnAbout(VOID)
{ {
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)About) == -1) if (DialogBox(hApp, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)About) == -1)
AbortMessage(_T("About Dialog Box Creation Error !")); AbortMessage(_T("About Dialog Box Creation Error !"));
@ -1511,8 +1555,6 @@ start:
} }
} }
SwitchToState(SM_RETURN); // exit emulation thread
// clean up DDE server // clean up DDE server
DdeNameService(idDdeInst, hszService, NULL, DNS_UNREGISTER); DdeNameService(idDdeInst, hszService, NULL, DNS_UNREGISTER);
DdeFreeStringHandle(idDdeInst, hszService); DdeFreeStringHandle(idDdeInst, hszService);

View file

@ -19,6 +19,8 @@ CFG=Emu48 - Win32 Release
!MESSAGE !MESSAGE
!MESSAGE "Emu48 - Win32 Release" (based on "Win32 (x86) Application") !MESSAGE "Emu48 - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "Emu48 - Win32 Debug" (based on "Win32 (x86) Application") !MESSAGE "Emu48 - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE "Emu48 - Win32 Release Unicode" (based on "Win32 (x86) Application")
!MESSAGE "Emu48 - Win32 Debug Unicode" (based on "Win32 (x86) Application")
!MESSAGE !MESSAGE
# Begin Project # Begin Project
@ -80,12 +82,68 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386
!ELSEIF "$(CFG)" == "Emu48 - Win32 Release Unicode"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Emu48___"
# PROP BASE Intermediate_Dir "Emu48___"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\ReleaseUnicode"
# PROP Intermediate_Dir ".\ReleaseUnicode"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /Yu"pch.h" /FD /c
# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "_UNICODE" /D "UNICODE" /Yu"pch.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x40c /d "NDEBUG"
# ADD RSC /l 0x40c /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /machine:I386
!ELSEIF "$(CFG)" == "Emu48 - Win32 Debug Unicode"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Emu48__0"
# PROP BASE Intermediate_Dir "Emu48__0"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\DebugUnicode"
# PROP Intermediate_Dir ".\DebugUnicode"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /FR /Yu"pch.h" /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "_UNICODE" /D "UNICODE" /FR /Yu"pch.h" /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x40c /d "_DEBUG"
# ADD RSC /l 0x40c /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386
!ENDIF !ENDIF
# Begin Target # Begin Target
# Name "Emu48 - Win32 Release" # Name "Emu48 - Win32 Release"
# Name "Emu48 - Win32 Debug" # Name "Emu48 - Win32 Debug"
# Name "Emu48 - Win32 Release Unicode"
# Name "Emu48 - Win32 Debug Unicode"
# Begin Group "Source Files" # Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
@ -112,13 +170,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

View file

@ -6,6 +6,14 @@
* Copyright (C) 1995 Sebastien Carlier * Copyright (C) 1995 Sebastien Carlier
* *
*/ */
#if defined GRAYSCALE // grayscale defines
#define GRAYON(a) a
#define GRAYOFF(a)
#else
#define GRAYON(a)
#define GRAYOFF(a) a
#endif
#include "types.h" #include "types.h"
#define ARRAYSIZEOF(a) (sizeof(a) / sizeof(a[0])) #define ARRAYSIZEOF(a) (sizeof(a) / sizeof(a[0]))
@ -58,10 +66,12 @@ extern LPTSTR szAppName;
extern LPTSTR szTopic; extern LPTSTR szTopic;
extern LPTSTR szTitle; extern LPTSTR szTitle;
extern CRITICAL_SECTION csGDILock; extern CRITICAL_SECTION csGDILock;
extern CRITICAL_SECTION csLcdLock;
extern CRITICAL_SECTION csKeyLock; 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 csTxdLock;
extern CRITICAL_SECTION csRecvLock; extern CRITICAL_SECTION csRecvLock;
extern INT nArgc; extern INT nArgc;
extern LPCTSTR *ppArgv; extern LPCTSTR *ppArgv;
@ -114,6 +124,9 @@ extern VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s);
extern VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s); extern VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s);
extern VOID UpdateAnnunciators(VOID); extern VOID UpdateAnnunciators(VOID);
extern VOID ResizeWindow(VOID); extern VOID ResizeWindow(VOID);
extern BYTE GetLineCounter(VOID);
extern VOID StartDisplay(BYTE byInitial);
extern VOID StopDisplay(VOID);
// Engine.c // Engine.c
extern BOOL bInterrupt; extern BOOL bInterrupt;
@ -128,7 +141,7 @@ extern TCHAR szSerialIr[16];
extern DWORD dwSXCycles; extern DWORD dwSXCycles;
extern DWORD dwGXCycles; extern DWORD dwGXCycles;
extern HANDLE hEventDebug; extern HANDLE hEventDebug;
extern BOOL bDbgEnable; extern BOOL bDbgAutoStateCtrl;
extern INT nDbgState; extern INT nDbgState;
extern BOOL bDbgNOP3; extern BOOL bDbgNOP3;
extern BOOL bDbgCode; extern BOOL bDbgCode;
@ -142,6 +155,9 @@ extern DWORD *pdwInstrArray;
extern WORD wInstrSize; extern WORD wInstrSize;
extern WORD wInstrWp; extern WORD wInstrWp;
extern WORD wInstrRp; extern WORD wInstrRp;
extern VOID SuspendDebugger(VOID);
extern VOID ResumeDebugger(VOID);
extern VOID CheckSerial(VOID);
extern VOID AdjKeySpeed(VOID); extern VOID AdjKeySpeed(VOID);
extern VOID SetSpeed(BOOL bAdjust); extern VOID SetSpeed(BOOL bAdjust);
extern VOID UpdateKdnBit(VOID); extern VOID UpdateKdnBit(VOID);
@ -173,12 +189,13 @@ extern DWORD dwPort2Size;
extern DWORD dwPort2Mask; extern DWORD dwPort2Mask;
extern BOOL bBackup; extern BOOL bBackup;
extern WORD WriteStack(LPBYTE,DWORD); extern WORD WriteStack(LPBYTE,DWORD);
extern VOID SetWindowLocation(HWND hWnd,INT nPosX,INT nPosY);
extern VOID UpdatePatches(BOOL bPatch);
extern BOOL PatchRom(LPCTSTR szFilename);
extern BOOL MapRom(LPCTSTR szFilename); extern BOOL MapRom(LPCTSTR szFilename);
extern VOID UnmapRom(VOID); extern VOID UnmapRom(VOID);
extern BOOL MapPort2(LPCTSTR szFilename); extern BOOL MapPort2(LPCTSTR szFilename);
extern VOID UnmapPort2(VOID); extern VOID UnmapPort2(VOID);
extern VOID UpdatePatches(BOOL bPatch);
extern BOOL PatchRom(LPCTSTR szFilename);
extern VOID ResetDocument(VOID); extern VOID ResetDocument(VOID);
extern BOOL NewDocument(VOID); extern BOOL NewDocument(VOID);
extern BOOL OpenDocument(LPCTSTR szFilename); extern BOOL OpenDocument(LPCTSTR szFilename);
@ -205,7 +222,6 @@ extern BYTE ReadT1(VOID);
extern VOID SetT1(BYTE byValue); extern VOID SetT1(BYTE byValue);
// MOps.c // MOps.c
extern BOOL ioc_acc;
extern BOOL bFlashRomArray; extern BOOL bFlashRomArray;
extern BYTE disp; extern BYTE disp;
extern LPBYTE RMap[256]; extern LPBYTE RMap[256];
@ -218,7 +234,6 @@ extern VOID Reset(VOID);
extern VOID C_Eq_Id(VOID); extern VOID C_Eq_Id(VOID);
extern enum MMUMAP MapData(DWORD d); extern enum MMUMAP MapData(DWORD d);
extern VOID CpuReset(VOID); extern VOID CpuReset(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);
extern VOID Nwrite(BYTE *a, DWORD d, UINT s); extern VOID Nwrite(BYTE *a, DWORD d, UINT s);
@ -258,6 +273,7 @@ extern BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort);
extern VOID CommClose(VOID); extern VOID CommClose(VOID);
extern VOID CommSetBaud(VOID); extern VOID CommSetBaud(VOID);
extern BOOL UpdateUSRQ(VOID); extern BOOL UpdateUSRQ(VOID);
extern VOID CommTxBRK(VOID);
extern VOID CommTransmit(VOID); extern VOID CommTransmit(VOID);
extern VOID CommReceive(VOID); extern VOID CommReceive(VOID);

View file

@ -29,6 +29,14 @@ LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE GUIDELINES DESIGNINFO DISCARDABLE
BEGIN BEGIN
IDD_WRITEONLYREG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 173
TOPMARGIN, 7
BOTTOMMARGIN, 75
END
IDD_FIND, DIALOG IDD_FIND, DIALOG
BEGIN BEGIN
LEFTMARGIN, 6 LEFTMARGIN, 6
@ -133,7 +141,24 @@ END
// Dialog // Dialog
// //
IDD_FIND DIALOGEX 0, 0, 197, 47 IDD_WRITEONLYREG DIALOG DISCARDABLE 0, 0, 180, 82
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Write Only Registers"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "20-24 (Display Start Address)",IDC_STATIC,11,11,131,8
RTEXT "00000",IDC_ADDR20_24,144,11,25,8
LTEXT "25-27 (Display Line Offset)",IDC_STATIC,11,21,131,8
RTEXT "000",IDC_ADDR25_27,144,21,25,8
LTEXT "28-29 (Display Line Counter)",IDC_STATIC,11,31,131,8
RTEXT "00",IDC_ADDR28_29,144,31,25,8
LTEXT "30-34 (Display Secondary Start Address)",IDC_STATIC,11,
41,131,8
RTEXT "00000",IDC_ADDR30_34,144,41,25,8
DEFPUSHBUTTON "OK",IDOK,65,61,50,14
END
IDD_FIND DIALOG DISCARDABLE 0, 0, 197, 47
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Find" CAPTION "Find"
@ -144,7 +169,7 @@ BEGIN
WS_VSCROLL | WS_TABSTOP WS_VSCROLL | WS_TABSTOP
CONTROL "Find &ASCII",IDC_FIND_ASCII,"Button",BS_AUTOCHECKBOX | CONTROL "Find &ASCII",IDC_FIND_ASCII,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,46,30,49,10 WS_TABSTOP,46,30,49,10
DEFPUSHBUTTON "Find Next",IDOK,140,7,50,14 DEFPUSHBUTTON "&Find Next",IDOK,140,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,140,26,50,14 PUSHBUTTON "Cancel",IDCANCEL,140,26,50,14
END END
@ -163,7 +188,7 @@ BEGIN
PUSHBUTTON "&Delete",IDC_BREAKEDIT_DELETE,44,81,30,14 PUSHBUTTON "&Delete",IDC_BREAKEDIT_DELETE,44,81,30,14
END END
IDD_ABOUT DIALOGEX 0, 0, 261, 160 IDD_ABOUT DIALOG DISCARDABLE 0, 0, 261, 160
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Emu48" CAPTION "About Emu48"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
@ -171,14 +196,14 @@ 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 © 2001 Sébastien Carlier && Christoph Gießelink", LTEXT "Copyright © 2002 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, 209 IDD_SETTINGS DIALOG DISCARDABLE 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" FONT 8, "MS Sans Serif"
@ -233,7 +258,7 @@ BEGIN
PUSHBUTTON "V",IDC_UPDATE,115,17,10,14 PUSHBUTTON "V",IDC_UPDATE,115,17,10,14
END END
IDD_KMLLOG DIALOGEX 0, 0, 301, 167 IDD_KMLLOG DIALOG DISCARDABLE 0, 0, 301, 167
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "KML Script Compilation Result" CAPTION "KML Script Compilation Result"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
@ -251,7 +276,7 @@ BEGIN
WS_BORDER | WS_VSCROLL | NOT WS_TABSTOP,WS_EX_CLIENTEDGE WS_BORDER | WS_VSCROLL | NOT WS_TABSTOP,WS_EX_CLIENTEDGE
END END
IDD_DISASM DIALOGEX 0, 0, 255, 165 IDD_DISASM DIALOG DISCARDABLE 0, 0, 255, 165
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Disassembler" CAPTION "Disassembler"
FONT 8, "Courier New" FONT 8, "Courier New"
@ -277,7 +302,7 @@ BEGIN
WS_TABSTOP,WS_EX_NOPARENTNOTIFY WS_TABSTOP,WS_EX_NOPARENTNOTIFY
END END
IDD_DEBUG DIALOGEX 0, 0, 279, 269 IDD_DEBUG DIALOG DISCARDABLE 0, 0, 279, 269
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
@ -372,8 +397,8 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "New Value" CAPTION "New Value"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
BEGIN BEGIN
LTEXT "New value (hexdezimal):",IDC_STATIC,8,9,81,8 LTEXT "New value (hexadecimal):",IDC_STATIC,8,9,81,8
EDITTEXT IDC_NEWVALUE,91,7,77,12,ES_AUTOHSCROLL EDITTEXT IDC_NEWVALUE,93,7,75,12,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,21,29,50,14 DEFPUSHBUTTON "OK",IDOK,21,29,50,14
PUSHBUTTON "Cancel",IDCANCEL,103,29,50,14 PUSHBUTTON "Cancel",IDCANCEL,103,29,50,14
END END
@ -383,8 +408,8 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Enter Address" CAPTION "Enter Address"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
BEGIN BEGIN
LTEXT "Enter address (hexdezimal):",IDC_STATIC,8,9,90,8 LTEXT "Enter address (hexadecimal):",IDC_STATIC,8,9,93,8
EDITTEXT IDC_ENTERADR,106,7,43,12,ES_AUTOHSCROLL EDITTEXT IDC_ENTERADR,105,7,44,12,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,14,29,50,14 DEFPUSHBUTTON "OK",IDOK,14,29,50,14
PUSHBUTTON "Cancel",IDCANCEL,92,29,50,14 PUSHBUTTON "Cancel",IDCANCEL,92,29,50,14
END END
@ -394,8 +419,8 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Enter Breakpoint" CAPTION "Enter Breakpoint"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
BEGIN BEGIN
LTEXT "Enter breakpoint (hexdezimal):",IDC_STATIC,8,9,96,8 LTEXT "Enter breakpoint (hexadecimal):",IDC_STATIC,8,9,99,8
EDITTEXT IDC_ENTERADR,110,7,39,12,ES_AUTOHSCROLL EDITTEXT IDC_ENTERADR,112,7,37,12,ES_AUTOHSCROLL
CONTROL "&Code",IDC_BPCODE,"Button",BS_AUTORADIOBUTTON | CONTROL "&Code",IDC_BPCODE,"Button",BS_AUTORADIOBUTTON |
WS_GROUP | WS_TABSTOP,17,24,33,10 WS_GROUP | WS_TABSTOP,17,24,33,10
CONTROL "R&PL",IDC_BPRPL,"Button",BS_AUTORADIOBUTTON,17,50,30,10 CONTROL "R&PL",IDC_BPRPL,"Button",BS_AUTORADIOBUTTON,17,50,30,10
@ -409,7 +434,7 @@ BEGIN
PUSHBUTTON "Cancel",IDCANCEL,92,65,50,14 PUSHBUTTON "Cancel",IDCANCEL,92,65,50,14
END END
IDD_INSTRUCTIONS DIALOGEX 0, 0, 186, 169 IDD_INSTRUCTIONS DIALOG DISCARDABLE 0, 0, 186, 169
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Last Instructions" CAPTION "Last Instructions"
FONT 8, "Courier New" FONT 8, "Courier New"
@ -461,8 +486,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,2,5,0 FILEVERSION 1,3,0,0
PRODUCTVERSION 1,2,5,0 PRODUCTVERSION 1,3,0,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -479,12 +504,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Sebastien Carlier & Christoph Gießelink\0" VALUE "CompanyName", "Sebastien Carlier & Christoph Gießelink\0"
VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0" VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0"
VALUE "FileVersion", "1, 2, 5, 0\0" VALUE "FileVersion", "1, 3, 0, 0\0"
VALUE "InternalName", "Emu48\0" VALUE "InternalName", "Emu48\0"
VALUE "LegalCopyright", "Copyright © 2001\0" VALUE "LegalCopyright", "Copyright © 2002\0"
VALUE "OriginalFilename", "Emu48.exe\0" VALUE "OriginalFilename", "Emu48.exe\0"
VALUE "ProductName", "Emu48\0" VALUE "ProductName", "Emu48\0"
VALUE "ProductVersion", "1, 2, 5, 0\0" VALUE "ProductVersion", "1, 3, 0, 0\0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
@ -586,6 +611,7 @@ BEGIN
POPUP "&Info" POPUP "&Info"
BEGIN BEGIN
MENUITEM "&Last Instructions...", ID_INFO_LASTINSTRUCTIONS MENUITEM "&Last Instructions...", ID_INFO_LASTINSTRUCTIONS
MENUITEM "&Write Only Registers...", ID_INFO_WRITEONLYREG
END END
END END
@ -610,7 +636,31 @@ BEGIN
MENUITEM "Go to D&1", ID_DEBUG_MEM_GOD1 MENUITEM "Go to D&1", ID_DEBUG_MEM_GOD1
MENUITEM "Go to &Stack", ID_DEBUG_MEM_GOSTACK MENUITEM "Go to &Stack", ID_DEBUG_MEM_GOSTACK
MENUITEM SEPARATOR MENUITEM SEPARATOR
MENUITEM "Find...\tF", ID_DEBUG_MEM_FIND MENUITEM "&Find...\tF", ID_DEBUG_MEM_FIND
MENUITEM SEPARATOR
POPUP "&Mapping"
BEGIN
MENUITEM "Map", ID_DEBUG_MEM_MAP
MENUITEM SEPARATOR
MENUITEM "NCE1", ID_DEBUG_MEM_NCE1
, GRAYED
MENUITEM "NCE2", ID_DEBUG_MEM_NCE2
, GRAYED
MENUITEM "CE1", ID_DEBUG_MEM_CE1, GRAYED
MENUITEM "CE2", ID_DEBUG_MEM_CE2, GRAYED
MENUITEM "NCE3", ID_DEBUG_MEM_NCE3
, GRAYED
END
END
END
IDR_DEBUG_STACK MENU DISCARDABLE
BEGIN
POPUP ""
BEGIN
MENUITEM "&Push", ID_DEBUG_STACK_PUSH
MENUITEM "P&op", ID_DEBUG_STACK_POP
MENUITEM "&Modify", ID_DEBUG_STACK_MODIFY
END END
END END
@ -659,6 +709,14 @@ BEGIN
ID_BREAKPOINTS_CODEEDIT "Breakpoint List" ID_BREAKPOINTS_CODEEDIT "Breakpoint List"
END END
/////////////////////////////////////////////////////////////////////////////
//
// Manifest
//
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "Emu48.xml"
#endif // French (France) resources #endif // French (France) resources
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////

22
sources/Emu48/EMU48.XML Normal file
View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="Emu48"
type="win32"
/>
<description>Emu48</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>

View file

@ -32,8 +32,8 @@ DWORD dwGXCycles = 123; // GX cpu cycles in interval
// variables for debugger engine // variables for debugger engine
HANDLE hEventDebug; // event handle to stop cpu thread HANDLE hEventDebug; // event handle to stop cpu thread
BOOL bDbgEnable = FALSE; // debugger mode enable flag BOOL bDbgAutoStateCtrl = TRUE; // debugger suspend control by SwitchToState()
INT nDbgState = DBG_RUN; // state of debugger INT nDbgState = DBG_OFF; // state of debugger
BOOL bDbgNOP3 = FALSE; // halt on NOP3 (#420 opcode) BOOL bDbgNOP3 = FALSE; // halt on NOP3 (#420 opcode)
BOOL bDbgRPL = FALSE; // halt on RPL entry BOOL bDbgRPL = FALSE; // halt on RPL entry
@ -52,6 +52,9 @@ WORD wInstrSize; // size of last instruction array
WORD wInstrWp; // write pointer of instruction array WORD wInstrWp; // write pointer of instruction array
WORD wInstrRp; // read pointer of instruction array WORD wInstrRp; // read pointer of instruction array
static BOOL bDbgRplBreak = FALSE; // flag for RPL breakpoint
static INT nDbgOldState = DBG_OFF; // old state of debugger for suspend/resume
static BOOL bCpuSlow = FALSE; // enable/disable real speed static BOOL bCpuSlow = FALSE; // enable/disable real speed
static DWORD dwEDbgT2 = 0; // debugger timer2 emulation static DWORD dwEDbgT2 = 0; // debugger timer2 emulation
@ -80,12 +83,12 @@ static __inline VOID Debugger(VOID) // debugger part
{ {
LARGE_INTEGER lDummyInt; // sample timer ticks LARGE_INTEGER lDummyInt; // sample timer ticks
BOOL bStopEmulation; BOOL bStopEmulation;
BOOL bRplBreak = FALSE; // flag for RPL breakpoint
LPBYTE I = FASTPTR(Chipset.pc); // get opcode stream LPBYTE I = FASTPTR(Chipset.pc); // get opcode stream
SaveInstrAddr(Chipset.pc); // save pc in last instruction buffer SaveInstrAddr(Chipset.pc); // save pc in last instruction buffer
bDbgRplBreak = FALSE; // flag for RPL breakpoint
// check for code breakpoints // check for code breakpoints
bStopEmulation = CheckBreakpoint(Chipset.pc, 1, BP_EXEC); bStopEmulation = CheckBreakpoint(Chipset.pc, 1, BP_EXEC);
@ -121,7 +124,7 @@ static __inline VOID Debugger(VOID) // debugger part
if (dwDbgRplPC == Chipset.pc) if (dwDbgRplPC == Chipset.pc)
{ {
dwDbgRplPC = -1; dwDbgRplPC = -1;
bRplBreak = TRUE; bDbgRplBreak = TRUE;
bStopEmulation = TRUE; bStopEmulation = TRUE;
} }
@ -206,21 +209,48 @@ static __inline VOID Debugger(VOID) // debugger part
} }
dwEDbgT2 = Chipset.t2; // timer2 check reference value dwEDbgT2 = Chipset.t2; // timer2 check reference value
// OutputDebugString(_T("Emulator stopped...\n")); // redraw debugger window and stop
NotifyDebugger(bRplBreak); NotifyDebugger(bDbgRplBreak);
WaitForSingleObject(hEventDebug,INFINITE); WaitForSingleObject(hEventDebug,INFINITE);
// OutputDebugString(_T("Emulator running...\n"));
StartTimers(); // continue timers StartTimers(); // continue timers
if (nDbgState > DBG_OFF) // if debugger is active
{
Chipset.Shutdn = FALSE; Chipset.Shutdn = FALSE;
Chipset.bShutdnWake = FALSE; Chipset.bShutdnWake = FALSE;
}
// init slow down part // init slow down part
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
QueryPerformanceCounter(&lDummyInt); QueryPerformanceCounter(&lDummyInt);
dwSpeedRef = lDummyInt.LowPart; dwSpeedRef = lDummyInt.LowPart;
} }
return;
}
VOID SuspendDebugger(VOID)
{
// auto control enabled, emulation halted by debugger
if (bDbgAutoStateCtrl && nDbgState > DBG_OFF)
{
nDbgOldState = nDbgState; // save old state
nDbgState = DBG_SUSPEND; // suspend state
SetEvent(hEventDebug); // exit debugger
}
return;
}
VOID ResumeDebugger(VOID)
{
// auto control enabled, debugger is suspended
if (bDbgAutoStateCtrl && nDbgState == DBG_SUSPEND)
{
// active RPL breakpoint
if (bDbgRplBreak) dwDbgRplPC = Chipset.pc;
nDbgState = nDbgOldState; // set to old debugger state
}
return;
} }
static __inline VOID CheckDisp(BOOL bSync) static __inline VOID CheckDisp(BOOL bSync)
@ -239,35 +269,6 @@ static __inline VOID CheckDisp(BOOL bSync)
return; return;
} }
static __inline VOID CheckSerial(VOID)
{
if (ioc_acc) // IOC changed
{
ioc_acc = FALSE;
// COM port closed and serial on
if (bCommInit == FALSE && (Chipset.IORam[IOC] & SON) != 0)
{
bCommInit = CommOpen(szSerialWire,szSerialIr); // open COM ports
}
// COM port opened and serial off
if (bCommInit == TRUE && (Chipset.IORam[IOC] & SON) == 0)
{
CommClose(); // close COM port
bCommInit = FALSE;
}
// Interrupt on recv buffer full and receive buffer full
if ((Chipset.IORam[IOC] & ERBF) && (Chipset.IORam[RCS] & RBF))
{
Chipset.Shutdn = FALSE;
INTERRUPT;
}
}
return;
}
static __inline VOID AdjustSpeed(VOID) // adjust emulation speed static __inline VOID AdjustSpeed(VOID) // adjust emulation speed
{ {
if (bCpuSlow || bKeySlow) // emulation slow down if (bCpuSlow || bKeySlow) // emulation slow down
@ -304,6 +305,23 @@ static __inline VOID AdjustSpeed(VOID) // adjust emulation speed
return; return;
} }
VOID CheckSerial(VOID)
{
// COM port closed and serial on
if (bCommInit == FALSE && (Chipset.IORam[IOC] & SON) != 0)
{
bCommInit = CommOpen(szSerialWire,szSerialIr); // open COM ports
}
// COM port opened and serial off
if (bCommInit == TRUE && (Chipset.IORam[IOC] & SON) == 0)
{
CommClose(); // close COM port
bCommInit = FALSE;
}
return;
}
VOID AdjKeySpeed(VOID) // slow down key repeat VOID AdjKeySpeed(VOID) // slow down key repeat
{ {
WORD i; WORD i;
@ -338,19 +356,21 @@ VOID SetSpeed(BOOL bAdjust) // set emulation speed
dwSpeedRef = lTime.LowPart; // save reference time dwSpeedRef = lTime.LowPart; // save reference time
} }
bCpuSlow = bAdjust; // save emulation speed bCpuSlow = bAdjust; // save emulation speed
return;
} }
VOID UpdateKdnBit(VOID) // update KDN bit VOID UpdateKdnBit(VOID) // update KDN bit
{ {
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(SRQ2,KDN,Chipset.in != 0);
return;
} }
BOOL WaitForSleepState(VOID) // wait for cpu SHUTDN then sleep state BOOL WaitForSleepState(VOID) // wait for cpu SHUTDN then sleep state
{ {
DWORD dwRefTime; DWORD dwRefTime;
DisableDebugger(); // disable debugger SuspendDebugger(); // suspend debugger
dwRefTime = timeGetTime(); dwRefTime = timeGetTime();
// wait for the SHUTDN command with 1.5 sec timeout // wait for the SHUTDN command with 1.5 sec timeout
@ -359,6 +379,8 @@ BOOL WaitForSleepState(VOID) // wait for cpu SHUTDN then sleep state
if (Chipset.Shutdn) // not timeout, cpu is down if (Chipset.Shutdn) // not timeout, cpu is down
SwitchToState(SM_SLEEP); // go to sleep state SwitchToState(SM_SLEEP); // go to sleep state
else
ResumeDebugger(); // timeout, resume to debugger
return SM_SLEEP != nNextState; // state not changed, emulator was busy return SM_SLEEP != nNextState; // state not changed, emulator was busy
} }
@ -374,12 +396,12 @@ UINT SwitchToState(UINT nNewState)
switch (nNewState) switch (nNewState)
{ {
case SM_INVALID: // -> Invalid case SM_INVALID: // -> Invalid
DisableDebugger(); // disable debugger
nNextState = SM_INVALID; nNextState = SM_INVALID;
if (Chipset.Shutdn) if (Chipset.Shutdn)
SetEvent(hEventShutdn); SetEvent(hEventShutdn);
else else
bInterrupt = TRUE; bInterrupt = TRUE;
SuspendDebugger(); // suspend debugger
while (nState!=nNextState) Sleep(0); while (nState!=nNextState) Sleep(0);
UpdateWindowStatus(); UpdateWindowStatus();
break; break;
@ -399,7 +421,7 @@ UINT SwitchToState(UINT nNewState)
case SM_SLEEP: // -> Sleep case SM_SLEEP: // -> Sleep
nNextState = SM_SLEEP; nNextState = SM_SLEEP;
bInterrupt = TRUE; // exit main loop bInterrupt = TRUE; // exit main loop
SetEvent(hEventDebug); // exit debugger SuspendDebugger(); // suspend debugger
SetEvent(hEventShutdn); // exit shutdown SetEvent(hEventShutdn); // exit shutdown
while (nState!=nNextState) Sleep(0); while (nState!=nNextState) Sleep(0);
bInterrupt = FALSE; bInterrupt = FALSE;
@ -415,11 +437,13 @@ UINT SwitchToState(UINT nNewState)
nNextState = SM_RUN; nNextState = SM_RUN;
// don't enter opcode loop on interrupt request // don't enter opcode loop on interrupt request
bInterrupt = Chipset.Shutdn || Chipset.SoftInt; bInterrupt = Chipset.Shutdn || Chipset.SoftInt;
ResumeDebugger();
SetEvent(hEventShutdn); SetEvent(hEventShutdn);
while (nState!=nNextState) Sleep(0); while (nState!=nNextState) Sleep(0);
UpdateWindowStatus(); UpdateWindowStatus();
break; break;
case SM_RETURN: // -> Return case SM_RETURN: // -> Return
DisableDebugger(); // disable debugger
nNextState = SM_RETURN; nNextState = SM_RETURN;
SetEvent(hEventShutdn); SetEvent(hEventShutdn);
WaitForSingleObject(hThread,INFINITE); WaitForSingleObject(hThread,INFINITE);
@ -438,7 +462,8 @@ UINT SwitchToState(UINT nNewState)
case SM_RUN: // -> Run case SM_RUN: // -> Run
nNextState = SM_RUN; nNextState = SM_RUN;
// don't enter opcode loop on interrupt request // don't enter opcode loop on interrupt request
bInterrupt = !bDbgEnable && (Chipset.Shutdn || Chipset.SoftInt); bInterrupt = (nDbgState == DBG_OFF) && (Chipset.Shutdn || Chipset.SoftInt);
ResumeDebugger();
SetEvent(hEventShutdn); // leave sleep state SetEvent(hEventShutdn); // leave sleep state
break; break;
case SM_INVALID: // -> Invalid case SM_INVALID: // -> Invalid
@ -448,6 +473,7 @@ UINT SwitchToState(UINT nNewState)
UpdateWindowStatus(); UpdateWindowStatus();
break; break;
case SM_RETURN: // -> Return case SM_RETURN: // -> Return
DisableDebugger(); // disable debugger
nNextState = SM_INVALID; nNextState = SM_INVALID;
SetEvent(hEventShutdn); SetEvent(hEventShutdn);
while (nState!=nNextState) Sleep(0); while (nState!=nNextState) Sleep(0);
@ -482,7 +508,7 @@ loop:
nState = SM_RETURN; // in return state nState = SM_RETURN; // in return state
return 0; // kill thread return 0; // kill thread
} }
ioc_acc = TRUE; // test if UART on CheckSerial(); // test if UART on
} }
while (nNextState == SM_RUN) while (nNextState == SM_RUN)
{ {
@ -523,16 +549,27 @@ loop:
dwSpeedRef = lDummyInt.LowPart; dwSpeedRef = lDummyInt.LowPart;
SetHP48Time(); // update HP48 time & date SetHP48Time(); // update HP48 time & date
StartTimers(); StartTimers();
// start display counter/update engine
StartDisplay((BYTE)(((Chipset.IORam[LINECOUNT+1]<<4)|Chipset.IORam[LINECOUNT])&0x3F));
} }
PCHANGED; PCHANGED;
while (!bInterrupt) while (!bInterrupt)
{ {
if (bDbgEnable) Debugger(); // debugger active if (nDbgState > DBG_OFF) // debugger active
{
Debugger();
// if suspended skip next opcode execution
if (nDbgState == DBG_SUSPEND)
{
if (Chipset.Shutdn) break;
continue;
}
}
EvalOpcode(FASTPTR(Chipset.pc)); // execute opcode EvalOpcode(FASTPTR(Chipset.pc)); // execute opcode
CheckDisp(!Chipset.Shutdn); // check for display update GRAYOFF(CheckDisp(!Chipset.Shutdn)); // check for display update
CheckSerial(); // serial support
AdjustSpeed(); // adjust emulation speed AdjustSpeed(); // adjust emulation speed
} }
bInterrupt = FALSE; // be sure to reenter opcode loop bInterrupt = FALSE; // be sure to reenter opcode loop
@ -568,6 +605,7 @@ loop:
} }
_ASSERT(nNextState != SM_RUN); _ASSERT(nNextState != SM_RUN);
StopDisplay(); // stop display counter/update
StopTimers(); StopTimers();
while (nNextState == SM_SLEEP) // go into sleep state while (nNextState == SM_SLEEP) // go into sleep state

View file

@ -48,6 +48,7 @@ static BYTE pbySignatureV[16] = "Emu49 Document\xFE";
static HANDLE hCurrentFile = NULL; static HANDLE hCurrentFile = NULL;
static CHIPSET BackupChipset; static CHIPSET BackupChipset;
BOOL bBackup = FALSE; BOOL bBackup = FALSE;
//################ //################
@ -59,7 +60,7 @@ BOOL bBackup = FALSE;
WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // separated from LoadObject() WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // separated from LoadObject()
{ {
BOOL bBinary; BOOL bBinary;
DWORD dwLength, dwAddress, i; DWORD dwAddress, i;
bBinary = ((lpBuf[dwSize+0]=='H') bBinary = ((lpBuf[dwSize+0]=='H')
&& (lpBuf[dwSize+1]=='P') && (lpBuf[dwSize+1]=='P')
@ -69,7 +70,7 @@ WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // separated from LoadObject()
&& (lpBuf[dwSize+5]==((cCurrentRomType!='X') ? '8' : '9')) && (lpBuf[dwSize+5]==((cCurrentRomType!='X') ? '8' : '9'))
&& (lpBuf[dwSize+6]=='-')); && (lpBuf[dwSize+6]=='-'));
for (i=0; i<dwSize; i++) for (i = 0; i < dwSize; i++)
{ {
BYTE byTwoNibs = lpBuf[i+dwSize]; BYTE byTwoNibs = lpBuf[i+dwSize];
lpBuf[i*2 ] = (BYTE)(byTwoNibs&0xF); lpBuf[i*2 ] = (BYTE)(byTwoNibs&0xF);
@ -78,24 +79,24 @@ WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // separated from LoadObject()
if (bBinary == TRUE) if (bBinary == TRUE)
{ // load as binary { // load as binary
dwLength = RPL_ObjectSize(lpBuf+16); dwSize = RPL_ObjectSize(lpBuf+16);
dwAddress = RPL_CreateTemp(dwLength); dwAddress = RPL_CreateTemp(dwSize);
if (dwAddress == 0) return S_ERR_BINARY; if (dwAddress == 0) return S_ERR_BINARY;
Nwrite(lpBuf+16, dwAddress, dwLength); Nwrite(lpBuf+16,dwAddress,dwSize);
} }
else else
{ // load as string { // load as string
BYTE lpHead[5]; BYTE lpHead[5];
dwLength = dwSize*2; dwSize *= 2;
dwAddress = RPL_CreateTemp(dwLength+10); dwAddress = RPL_CreateTemp(dwSize+10);
if (dwAddress == 0) return S_ERR_ASCII; if (dwAddress == 0) return S_ERR_ASCII;
Nunpack(lpHead,0x02A2C,5); Nunpack(lpHead,0x02A2C,5); // String
Nwrite(lpHead,dwAddress,5); Nwrite(lpHead,dwAddress,5);
Nunpack(lpHead,dwLength+5,5); Nunpack(lpHead,dwSize+5,5); // length of String
Nwrite(lpHead,dwAddress+5,5); Nwrite(lpHead,dwAddress+5,5);
Nwrite(lpBuf, dwAddress+10, dwLength); Nwrite(lpBuf,dwAddress+10,dwSize); // data
} }
RPL_Push(dwAddress); RPL_Push(dwAddress);
return S_ERR_NO; return S_ERR_NO;
@ -103,6 +104,29 @@ WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // separated from LoadObject()
//################
//#
//# Window Position Tools
//#
//################
VOID SetWindowLocation(HWND hWnd,INT nPosX,INT nPosY)
{
WINDOWPLACEMENT wndpl;
RECT *pRc = &wndpl.rcNormalPosition;
wndpl.length = sizeof(wndpl);
GetWindowPlacement(hWnd,&wndpl);
pRc->right = pRc->right - pRc->left + nPosX;
pRc->bottom = pRc->bottom - pRc->top + nPosY;
pRc->left = nPosX;
pRc->top = nPosY;
SetWindowPlacement(hWnd,&wndpl);
return;
}
//################ //################
//# //#
//# Patch //# Patch
@ -487,7 +511,6 @@ BOOL MapPort2(LPCTSTR szFilename)
return FALSE; return FALSE;
} }
dwPort2Size = dwFileSizeLo / 2048; // mapping size of port2 dwPort2Size = dwFileSizeLo / 2048; // mapping size of port2
if (dwPort2Size > 128) dwPort2Size = 128;
return TRUE; return TRUE;
} }
@ -530,9 +553,9 @@ VOID ResetDocument(VOID)
if (Chipset.Port0) LocalFree(Chipset.Port0); if (Chipset.Port0) LocalFree(Chipset.Port0);
if (Chipset.Port1) LocalFree(Chipset.Port1); if (Chipset.Port1) LocalFree(Chipset.Port1);
if (Chipset.Port2) LocalFree(Chipset.Port2); else UnmapPort2(); if (Chipset.Port2) LocalFree(Chipset.Port2); else UnmapPort2();
FillMemory(&Chipset,sizeof(Chipset),0); ZeroMemory(&Chipset,sizeof(Chipset));
FillMemory(&RMap,sizeof(RMap),0); // delete MMU mappings ZeroMemory(&RMap,sizeof(RMap)); // delete MMU mappings
FillMemory(&WMap,sizeof(WMap),0); ZeroMemory(&WMap,sizeof(WMap));
UpdateWindowStatus(); UpdateWindowStatus();
return; return;
} }
@ -629,7 +652,7 @@ restore:
} }
if (pbyRom) if (pbyRom)
{ {
SetWindowPos(hWnd,NULL,Chipset.nPosX,Chipset.nPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); SetWindowLocation(hWnd,Chipset.nPosX,Chipset.nPosY);
Map(0x00,0xFF); Map(0x00,0xFF);
} }
return FALSE; return FALSE;
@ -638,8 +661,7 @@ restore:
BOOL OpenDocument(LPCTSTR szFilename) BOOL OpenDocument(LPCTSTR szFilename)
{ {
HANDLE hFile = INVALID_HANDLE_VALUE; HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD lBytesRead; DWORD lBytesRead,lSizeofChipset;
DWORD lSizeofChipset;
BYTE pbyFileSignature[16]; BYTE pbyFileSignature[16];
LPBYTE pbySig; LPBYTE pbySig;
UINT ctBytesCompared; UINT ctBytesCompared;
@ -725,21 +747,30 @@ BOOL OpenDocument(LPCTSTR szFilename)
goto restore; goto restore;
} }
// read chipset size inside file
ReadFile(hFile, &lSizeofChipset, sizeof(lSizeofChipset), &lBytesRead, NULL); ReadFile(hFile, &lSizeofChipset, sizeof(lSizeofChipset), &lBytesRead, NULL);
if (lBytesRead != sizeof(lSizeofChipset)) goto read_err; if (lBytesRead != sizeof(lSizeofChipset)) goto read_err;
if (lSizeofChipset!=sizeof(CHIPSET)) if (lSizeofChipset <= sizeof(Chipset)) // actual or older chipset version
{ {
AbortMessage(_T("This file is probably corrupted, and cannot be loaded.")); // read chipset content
goto restore; ZeroMemory(&Chipset,sizeof(Chipset)); // init chipset
}
ReadFile(hFile, &Chipset, lSizeofChipset, &lBytesRead, NULL); ReadFile(hFile, &Chipset, lSizeofChipset, &lBytesRead, NULL);
}
else // newer chipset version
{
// read my used chipset content
ReadFile(hFile, &Chipset, sizeof(Chipset), &lBytesRead, NULL);
// skip rest of chipset
SetFilePointer(hFile, lSizeofChipset-sizeof(Chipset), NULL, FILE_CURRENT);
lSizeofChipset = sizeof(Chipset);
}
if (lBytesRead != lSizeofChipset) goto read_err; if (lBytesRead != lSizeofChipset) goto read_err;
Chipset.Port0 = NULL; Chipset.Port0 = NULL;
Chipset.Port1 = NULL; Chipset.Port1 = NULL;
Chipset.Port2 = NULL; Chipset.Port2 = NULL;
SetWindowPos(hWnd,NULL,Chipset.nPosX,Chipset.nPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); SetWindowLocation(hWnd,Chipset.nPosX,Chipset.nPosY);
if (szCurrentKml == NULL) if (szCurrentKml == NULL)
{ {
@ -947,14 +978,16 @@ BOOL SaveDocumentAs(LPCTSTR szFilename)
BOOL SaveBackup(VOID) BOOL SaveBackup(VOID)
{ {
RECT Rect; WINDOWPLACEMENT wndpl;
if (pbyRom == NULL) return FALSE; if (pbyRom == NULL) return FALSE;
// save window position // save window position
GetWindowRect(hWnd, &Rect); // update saved window position _ASSERT(hWnd); // window open
Chipset.nPosX = (SWORD)Rect.left; wndpl.length = sizeof(wndpl); // update saved window position
Chipset.nPosY = (SWORD)Rect.top; GetWindowPlacement(hWnd, &wndpl);
Chipset.nPosX = (SWORD) wndpl.rcNormalPosition.left;
Chipset.nPosY = (SWORD) wndpl.rcNormalPosition.top;
lstrcpy(szBackupFilename, szCurrentFilename); lstrcpy(szBackupFilename, szCurrentFilename);
lstrcpy(szBackupKml, szCurrentKml); lstrcpy(szBackupKml, szCurrentKml);
@ -1017,7 +1050,7 @@ BOOL RestoreBackup(VOID)
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]); MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
} }
} }
SetWindowPos(hWnd,NULL,Chipset.nPosX,Chipset.nPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); SetWindowLocation(hWnd,Chipset.nPosX,Chipset.nPosY);
UpdateWindowStatus(); UpdateWindowStatus();
Map(0x00,0xFF); Map(0x00,0xFF);
return TRUE; return TRUE;
@ -1031,7 +1064,7 @@ BOOL ResetBackup(VOID)
if (BackupChipset.Port0) LocalFree(BackupChipset.Port0); if (BackupChipset.Port0) LocalFree(BackupChipset.Port0);
if (BackupChipset.Port1) LocalFree(BackupChipset.Port1); if (BackupChipset.Port1) LocalFree(BackupChipset.Port1);
if (BackupChipset.Port2) LocalFree(BackupChipset.Port2); if (BackupChipset.Port2) LocalFree(BackupChipset.Port2);
FillMemory(&BackupChipset,sizeof(BackupChipset),0); ZeroMemory(&BackupChipset,sizeof(BackupChipset));
bBackup = FALSE; bBackup = FALSE;
UpdateWindowStatus(); UpdateWindowStatus();
return TRUE; return TRUE;
@ -1047,7 +1080,7 @@ BOOL ResetBackup(VOID)
static VOID InitializeOFN(LPOPENFILENAME ofn) static VOID InitializeOFN(LPOPENFILENAME ofn)
{ {
FillMemory((LPVOID)ofn, sizeof(OPENFILENAME), 0); ZeroMemory((LPVOID)ofn, sizeof(OPENFILENAME));
ofn->lStructSize = sizeof(OPENFILENAME); ofn->lStructSize = sizeof(OPENFILENAME);
ofn->hwndOwner = hWnd; ofn->hwndOwner = hWnd;
ofn->Flags = OFN_EXPLORER|OFN_HIDEREADONLY; ofn->Flags = OFN_EXPLORER|OFN_HIDEREADONLY;
@ -1218,10 +1251,10 @@ BOOL LoadObject(LPCTSTR szFilename) // separated stack writing part
wError = WriteStack(lpBuf,dwFileSizeLow); wError = WriteStack(lpBuf,dwFileSizeLow);
if (wError == S_ERR_BINARY) if (wError == S_ERR_BINARY)
AbortMessage(_T("The HP48 has not enough free memory left to load this binary file.")); AbortMessage(_T("The calculator does not have enough\nfree memory to load this binary file."));
if (wError == S_ERR_ASCII) if (wError == S_ERR_ASCII)
AbortMessage(_T("The HP48 has not enough free memory left to load this text file.")); AbortMessage(_T("The calculator does not have enough\nfree memory to load this text file."));
LocalFree(lpBuf); LocalFree(lpBuf);
return (wError == S_ERR_NO); return (wError == S_ERR_NO);

View file

@ -10,8 +10,6 @@
#include "Emu48.h" #include "Emu48.h"
#include "i28f160.h" #include "i28f160.h"
#define _64KB (64*1024) // define 64KB
#define ARRAYSIZEOF(a) (sizeof(a) / sizeof(a[0])) #define ARRAYSIZEOF(a) (sizeof(a) / sizeof(a[0]))
// Flash Command Set // Flash Command Set
@ -56,11 +54,11 @@
#define WRS_LOCK_BITS 8 // Set/Clear Block Lock-Bits #define WRS_LOCK_BITS 8 // Set/Clear Block Lock-Bits
// read state defines // read state defines
#define RDS_DATA 0 #define RDS_DATA 0 // data read
#define RDS_ID 1 #define RDS_ID 1 // read identifier codes
#define RDS_QUERY 2 #define RDS_QUERY 2 // read query
#define RDS_SR 3 #define RDS_SR 3 // read status register
#define RDS_XSR 4 #define RDS_XSR 4 // read extended status register
// global data // global data
WSMSET WSMset; WSMSET WSMset;
@ -117,9 +115,9 @@ static CONST BYTE byQueryTab[] =
0xB0, // 00, Manufacturer Code 0xB0, // 00, Manufacturer Code
0xD0, // 01, Device Code (16 Mbit) 0xD0, // 01, Device Code (16 Mbit)
0x00, // 02, Block Lock Configuration 0x00, // 02, Block Lock Configuration
0x02, // 03, ??
0x00, // 03, Reserved for vendor-specific information 0x00, // 04, Reserved for vendor-specific information
0x00, // 04, "
0x00, // 05, " 0x00, // 05, "
0x00, // 06, " 0x00, // 06, "
0x00, // 07, " 0x00, // 07, "
@ -147,9 +145,9 @@ static CONST BYTE byQueryTab[] =
0x00, // 1A, " 0x00, // 1A, "
// System interface information // System interface information
0x27, // 1B, Vcc Logic Supply Minimum Program/Erase Voltage 0x30, // 1B, Vcc Logic Supply Minimum Program/Erase Voltage (0x27 intel doc, 0x30 real chip)
0x55, // 1C, Vcc Logic Supply Maximum Program/Erase Voltage 0x55, // 1C, Vcc Logic Supply Maximum Program/Erase Voltage
0x27, // 1D, Vpp [Programming] Supply Minimum Program/Erase Voltage 0x30, // 1D, Vpp [Programming] Supply Minimum Program/Erase Voltage (0x27 intel doc, 0x30 real chip)
0x55, // 1E, Vpp [Programming] Supply Maximum Program/Erase Voltage 0x55, // 1E, Vpp [Programming] Supply Maximum Program/Erase Voltage
0x03, // 1F, Typical Time-Out per Single Byte/Word Program 0x03, // 1F, Typical Time-Out per Single Byte/Word Program
0x06, // 20, Typical Time-Out for Max. Buffer Write 0x06, // 20, Typical Time-Out for Max. Buffer Write
@ -184,7 +182,8 @@ static CONST BYTE byQueryTab[] =
0x03, // 3B, Block Status Register Mask 0x03, // 3B, Block Status Register Mask
0x00, // 3C, " 0x00, // 3C, "
0x50, // 3D, Vcc Logic Supply Optimum Program/Erase voltage 0x50, // 3D, Vcc Logic Supply Optimum Program/Erase voltage
0x50 // 3E, Vpp [Programming] Supply Optimum Program/Erase voltage 0x50, // 3E, Vpp [Programming] Supply Optimum Program/Erase voltage
0x00 // 3F, ??
}; };
@ -285,8 +284,10 @@ static VOID WrStateE8(DWORD d)
// write to buffer number of byte // write to buffer number of byte
static VOID WrStateE8N(BYTE a, DWORD d) static VOID WrStateE8N(BYTE a, DWORD d)
{ {
_ASSERT(a <= 0x1F); // check buffer size if (WRITE_BUFFER == a) return; // got another "Write Command" instead of length
a &= 0x1F; // maximum write buffer size
_ASSERT(a < (1 << byQueryTab[0x2A])); // check buffer size
a &= (1 << byQueryTab[0x2A]) - 1; // maximum write buffer size
WSMset.byWrite1No += a; // save no. of byte to program WSMset.byWrite1No += a; // save no. of byte to program
WSMset.byWrite1Size = a; // save size to check write buffer boundaries WSMset.byWrite1Size = a; // save size to check write buffer boundaries
WSMset.dwWrite1Addr = d; // byte block address of buffer1 WSMset.dwWrite1Addr = d; // byte block address of buffer1
@ -302,8 +303,10 @@ static VOID WrStateE8D(BYTE a, DWORD d)
// first data byte // first data byte
if (WSMset.byWrite1No == WSMset.byWrite1Size + 1) if (WSMset.byWrite1No == WSMset.byWrite1Size + 1)
{ {
DWORD dwBlockMask = ~(((byQueryTab[0x30] << 8) | byQueryTab[0x2F]) * 256 - 1);
// same block // same block
if ((WSMset.dwWrite1Addr & ~(_64KB-1)) == (d & ~(_64KB-1))) if ((WSMset.dwWrite1Addr & dwBlockMask) == (d & dwBlockMask))
{ {
WSMset.dwWrite1Addr = d; // byte block address of buffer1 WSMset.dwWrite1Addr = d; // byte block address of buffer1
WSMset.pbyWrite1[0] = a; // save byte WSMset.pbyWrite1[0] = a; // save byte
@ -356,14 +359,9 @@ static VOID WrStateE8C(BYTE a, DWORD d)
a = WSMset.pbyWrite1[byPos]; // get char from buffer a = WSMset.pbyWrite1[byPos]; // get char from buffer
_ASSERT(d+1 < dwRomSize); // address valid? _ASSERT(d+1 < dwRomSize); // address valid?
*(pbyRom+d) &= (a & 0x0f); // write LSB // no error set in BWSLBS, because I could alway program a "0"
if (*(pbyRom+d) != (a & 0x0f)) // check writing *(pbyRom+d++) &= (a & 0x0F); // write LSB
WSMset.byStatusReg |= BWSLBS; *(pbyRom+d++) &= (a >> 4); // write MSB
++d; // next nibble
*(pbyRom+d) &= (a >> 4); // write MSB
if (*(pbyRom+d) != (a >> 4)) // check writing
WSMset.byStatusReg |= BWSLBS;
++d; // next nibble
} }
} }
else else
@ -392,9 +390,9 @@ static VOID WrState40D(BYTE a, DWORD d)
{ {
d <<= 1; // nibble start address d <<= 1; // nibble start address
_ASSERT(d+1 < dwRomSize); // address valid? _ASSERT(d+1 < dwRomSize); // address valid?
// no error set in BWSLBS, because i could alway program a "0" // no error set in BWSLBS, because I could alway program a "0"
*(pbyRom+d++) &= (a & 0x0f); // write LSB *(pbyRom+d++) &= (a & 0x0F); // write LSB
*(pbyRom+d++) &= (a >> 4); // write MSB *(pbyRom+d) &= (a >> 4); // write MSB
WSMset.byStatusReg |= WSMS; // data written WSMset.byStatusReg |= WSMS; // data written
WSMset.uWrState = WRS_DATA; WSMset.uWrState = WRS_DATA;
return; return;
@ -423,14 +421,13 @@ static VOID WrState20C(BYTE a, DWORD d)
} }
else else
{ {
LPBYTE pbyBlock; DWORD dwBlockSize = ((byQueryTab[0x30] << 8) | byQueryTab[0x2F]) * 256;
UINT i;
d &= ~(_64KB-1); // start of 64KB block d &= ~(dwBlockSize-1); // start of block
_ASSERT(2*(d+_64KB) <= dwRomSize); // address valid? dwBlockSize *= 2; // block size in nibbles
pbyBlock = pbyRom + (d << 1); // nibble start address _ASSERT(d+dwBlockSize <= dwRomSize); // address valid?
for (i = 0; i < 2*_64KB; ++i) // write 128K nibble // write 128K nibble
*pbyBlock++ = 0xf; // write nibble FillMemory(pbyRom + (d << 1),dwBlockSize,0x0F);
} }
} }
else else
@ -456,32 +453,32 @@ static VOID WrState30(DWORD d)
// full chip erase confirm // full chip erase confirm
static VOID WrState30C(BYTE a, DWORD d) static VOID WrState30C(BYTE a, DWORD d)
{ {
LPBYTE pbyBlock;
UINT i,j;
if (CONFIRM == a) // chip erase confirm? if (CONFIRM == a) // chip erase confirm?
{ {
pbyBlock = pbyRom; UINT i;
for (i = 0; i < 32; ++i) // check all blocks
WORD wNoOfBlocks = (byQueryTab[0x2E] << 8) | byQueryTab[0x2D];
DWORD dwBlockSize = ((byQueryTab[0x30] << 8) | byQueryTab[0x2F]) * 256;
LPBYTE pbyBlock = pbyRom;
dwBlockSize *= 2; // block size in nibbles
for (i = 0; i <= wNoOfBlocks; ++i) // check all blocks
{ {
_ASSERT(2*((i+1)*_64KB) <= dwRomSize); _ASSERT((i+1)*dwBlockSize <= dwRomSize);
_ASSERT(i < ARRAYSIZEOF(WSMset.byLockCnfg)); _ASSERT(i < ARRAYSIZEOF(WSMset.byLockCnfg));
// lock bit of block is set & WP# = low, locked blocks cannot be erased // lock bit of block is set & WP# = low, locked blocks cannot be erased
if ((WSMset.byLockCnfg[i] & 1) != 0 && bWP == FALSE) 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 WSMset.byLockCnfg[i] = 0; // clear block lock bit
// write 128K nibble // write 128K nibble
for (j = 0; j < 2*_64KB; ++j) FillMemory(pbyBlock,dwBlockSize,0x0F);
*pbyBlock++ = 0xf; // write nibble
} }
pbyBlock += dwBlockSize; // next block
} }
} }
else else
@ -535,12 +532,14 @@ static VOID WrState60D(BYTE a, DWORD d)
if (bWP) // WP# = high, can change block lock status if (bWP) // WP# = high, can change block lock status
WSMset.byLockCnfg[d>>16] = 1; // set block lock bit WSMset.byLockCnfg[d>>16] = 1; // set block lock bit
else else
WSMset.byStatusReg |= DPS; // device protect detect, WP# = low WSMset.byStatusReg |= (BWSLBS | DPS); // device protect detect, WP# = low
break; break;
case CONFIRM: // clear block lock bits case CONFIRM: // clear block lock bits
if (bWP) // WP# = high, can change block lock status if (bWP) // WP# = high, can change block lock status
{ {
for (i = 0; i < 32; ++i) // clear all lock bits WORD wNoOfBlocks = (byQueryTab[0x2E] << 8) | byQueryTab[0x2D];
for (i = 0; i <= wNoOfBlocks; ++i) // clear all lock bits
{ {
_ASSERT(i < ARRAYSIZEOF(WSMset.byLockCnfg)); _ASSERT(i < ARRAYSIZEOF(WSMset.byLockCnfg));
WSMset.byLockCnfg[i] = 0; // clear block lock bit WSMset.byLockCnfg[i] = 0; // clear block lock bit
@ -548,7 +547,7 @@ static VOID WrState60D(BYTE a, DWORD d)
} }
else else
{ {
WSMset.byStatusReg |= DPS; // device protect detect, WP# = low WSMset.byStatusReg |= (ECLBS | DPS); // device protect detect, WP# = low
} }
break; break;
default: // improper command sequence default: // improper command sequence
@ -578,11 +577,35 @@ static BYTE RdStateId(DWORD d)
BYTE byData; BYTE byData;
d >>= 1; // A0 is not connected, ignore it d >>= 1; // A0 is not connected, ignore it
_ASSERT((d & 0xFF) < 0x10); // id with valid address? if ((d & 0x03) != 0x02) // id code request
if ((d & 0xFF) != 0x02) // id code request
{ {
d &= 0x03; // data repetition
byData = byQueryTab[d]; // get data from first 4 bytes id/query table
}
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
d &= 0x1F; // data repetition
if (d >= 4) byData |= 0x02; // set bit 1 on wrong ID adresses
}
return byData;
}
// read query
static BYTE RdStateQuery(DWORD d)
{
BYTE byData;
d >>= 1; // A0 is not connected, ignore it
if ((d & 0x7F) != 0x02) // query request
{
d &= 0x7F; // data repetition
// get data from id/query table // get data from id/query table
byData = (d < ARRAYSIZEOF(byQueryTab)) ? byQueryTab[d] : 0; byData = (d >= 0x40 && d < 0x50) ? 0 : byQueryTab[d&0x3F];
} }
else // block lock table else // block lock table
{ {
@ -593,16 +616,6 @@ static BYTE RdStateId(DWORD d)
return byData; 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 // read status register
static BYTE RdStateSR(DWORD d) static BYTE RdStateSR(DWORD d)
{ {
@ -683,9 +696,9 @@ VOID FlashWrite(BYTE *a, DWORD d, UINT s)
v = fnRdState[WSMset.uRdState](p); v = fnRdState[WSMset.uRdState](p);
if (d & 1) // odd address if (d & 1) // odd address
v = (v & 0x0f) | (*a << 4); // replace MSB v = (v & 0x0F) | (*a << 4); // replace MSB
else // even address else // even address
v = (v & 0xf0) | *a; // replace LSB v = (v & 0xF0) | *a; // replace LSB
++a; ++d; --s; ++a; ++d; --s;
} }

View file

@ -91,7 +91,7 @@ VOID KeyboardEvent(BOOL bPress, UINT out, UINT in)
} }
else else
{ {
_ASSERT(out < sizeof(Chipset.Keyboard_Row) / sizeof(Chipset.Keyboard_Row[0])); _ASSERT(out < ARRAYSIZEOF(Chipset.Keyboard_Row));
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

View file

@ -11,37 +11,37 @@
#include "Emu48.h" #include "Emu48.h"
#include "kml.h" #include "kml.h"
static VOID FatalError(); static VOID FatalError(VOID);
static VOID InitLex(LPTSTR szScript); static VOID InitLex(LPTSTR szScript);
static VOID CleanLex(); static VOID CleanLex(VOID);
static VOID SkipWhite(UINT nMode); static VOID SkipWhite(UINT nMode);
static TokenId ParseToken(UINT nMode); static TokenId ParseToken(UINT nMode);
static DWORD ParseInteger(); static DWORD ParseInteger(VOID);
static LPTSTR ParseString(); static LPTSTR ParseString(VOID);
static TokenId Lex(UINT nMode); static TokenId Lex(UINT nMode);
static Line* ParseLine(TokenId eCommand); static KmlLine* ParseLine(TokenId eCommand);
static Line* IncludeLines(LPCTSTR szFilename); static KmlLine* IncludeLines(LPCTSTR szFilename);
static Line* ParseLines(); static KmlLine* ParseLines(VOID);
static Block* ParseBlock(TokenId eBlock); static KmlBlock* ParseBlock(TokenId eBlock);
static Block* IncludeBlocks(LPCTSTR szFilename); static KmlBlock* IncludeBlocks(LPCTSTR szFilename);
static Block* ParseBlocks(); static KmlBlock* ParseBlocks(VOID);
static VOID FreeLines(Line* pLine); static VOID FreeLines(KmlLine* pLine);
static VOID PressButton(UINT nId); static VOID PressButton(UINT nId);
static VOID ReleaseButton(UINT nId); static VOID ReleaseButton(UINT nId);
static VOID PressButtonById(UINT nId); static VOID PressButtonById(UINT nId);
static VOID ReleaseButtonById(UINT nId); static VOID ReleaseButtonById(UINT nId);
static LPTSTR GetStringParam(Block* pBlock, TokenId eBlock, TokenId eCommand, UINT nParam); static LPTSTR GetStringParam(KmlBlock* pBlock, TokenId eBlock, TokenId eCommand, UINT nParam);
static DWORD GetIntegerParam(Block* pBlock, TokenId eBlock, TokenId eCommand, UINT nParam); static DWORD GetIntegerParam(KmlBlock* pBlock, TokenId eBlock, TokenId eCommand, UINT nParam);
static Line* SkipLines(Line* pLine, TokenId eCommand); static KmlLine* SkipLines(KmlLine* pLine, TokenId eCommand);
static Line* If(Line* pLine, BOOL bCondition); static KmlLine* If(KmlLine* pLine, BOOL bCondition);
static Line* RunLine(Line* pLine); static KmlLine* RunLine(KmlLine* pLine);
static Block* LoadKMLGlobal(LPCTSTR szFilename); static KmlBlock* LoadKMLGlobal(LPCTSTR szFilename);
Block* pKml; KmlBlock* pKml;
static Block* pVKey[256]; static KmlBlock* pVKey[256];
static BYTE byVKeyMap[256]; static BYTE byVKeyMap[256];
static Button pButton[256]; static KmlButton pButton[256];
static Annunciator pAnnunciator[6]; static KmlAnnunciator pAnnunciator[6];
static UINT nButtons = 0; static UINT nButtons = 0;
static UINT nScancodes = 0; static UINT nScancodes = 0;
static UINT nAnnunciators = 0; static UINT nAnnunciators = 0;
@ -61,7 +61,7 @@ static LPTSTR szLexDelim[] =
_T(" \t\r") _T(" \t\r")
}; };
static Token pLexToken[] = static KmlToken pLexToken[] =
{ {
{TOK_ANNUNCIATOR,000001,11,_T("Annunciator")}, {TOK_ANNUNCIATOR,000001,11,_T("Annunciator")},
{TOK_BACKGROUND, 000000,10,_T("Background")}, {TOK_BACKGROUND, 000000,10,_T("Background")},
@ -279,7 +279,7 @@ static VOID CreateKmlList()
do do
{ {
KmlScript* pScript; KmlScript* pScript;
Block* pBlock; KmlBlock* pBlock;
LPTSTR szTitle; LPTSTR szTitle;
pBlock = LoadKMLGlobal(pFindFileData.cFileName); pBlock = LoadKMLGlobal(pFindFileData.cFileName);
@ -457,7 +457,7 @@ fail:
//# //#
//################ //################
static VOID FatalError() static VOID FatalError(VOID)
{ {
PrintfToLog(_T("Fatal Error at line %i"), nLexLine); PrintfToLog(_T("Fatal Error at line %i"), nLexLine);
szText[0] = 0; szText[0] = 0;
@ -471,7 +471,7 @@ static VOID InitLex(LPTSTR szScript)
return; return;
} }
static VOID CleanLex() static VOID CleanLex(VOID)
{ {
nLexLine = 0; nLexLine = 0;
nLexInteger = 0; nLexInteger = 0;
@ -574,7 +574,7 @@ static TokenId ParseToken(UINT nMode)
return TOK_NONE; return TOK_NONE;
} }
static DWORD ParseInteger() static DWORD ParseInteger(VOID)
{ {
DWORD nNum = 0; DWORD nNum = 0;
while (_istdigit(*szText)) while (_istdigit(*szText))
@ -585,7 +585,7 @@ static DWORD ParseInteger()
return nNum; return nNum;
} }
static LPTSTR ParseString() static LPTSTR ParseString(VOID)
{ {
LPTSTR szString; LPTSTR szString;
LPTSTR szBuffer; LPTSTR szBuffer;
@ -642,12 +642,12 @@ static TokenId Lex(UINT nMode)
return ParseToken(nMode); return ParseToken(nMode);
} }
static Line* ParseLine(TokenId eCommand) static KmlLine* ParseLine(TokenId eCommand)
{ {
UINT i, j; UINT i, j;
DWORD nParams; DWORD nParams;
TokenId eToken; TokenId eToken;
Line* pLine; KmlLine* pLine;
i = 0; i = 0;
while (pLexToken[i].nLen) while (pLexToken[i].nLen)
@ -658,7 +658,7 @@ static Line* ParseLine(TokenId eCommand)
if (pLexToken[i].nLen == 0) return NULL; if (pLexToken[i].nLen == 0) return NULL;
j = 0; j = 0;
pLine = LocalAlloc(LPTR,sizeof(Line)); pLine = LocalAlloc(LPTR,sizeof(KmlLine));
pLine->eCommand = eCommand; pLine->eCommand = eCommand;
nParams = pLexToken[i].nParams; nParams = pLexToken[i].nParams;
loop: loop:
@ -712,13 +712,13 @@ errline:
return NULL; return NULL;
} }
static Line* IncludeLines(LPCTSTR szFilename) static KmlLine* IncludeLines(LPCTSTR szFilename)
{ {
HANDLE hFile; HANDLE hFile;
LPTSTR lpbyBuf; LPTSTR lpbyBuf;
UINT uOldLine; UINT uOldLine;
LPTSTR szOldText; LPTSTR szOldText;
Line* pLine; KmlLine* pLine;
SetCurrentDirectory(szEmu48Directory); SetCurrentDirectory(szEmu48Directory);
hFile = CreateFile(szFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); hFile = CreateFile(szFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
@ -752,10 +752,10 @@ static Line* IncludeLines(LPCTSTR szFilename)
return pLine; return pLine;
} }
static Line* ParseLines() static KmlLine* ParseLines(VOID)
{ {
Line* pLine; KmlLine* pLine;
Line* pFirst = NULL; KmlLine* pFirst = NULL;
TokenId eToken; TokenId eToken;
UINT nLevel = 0; UINT nLevel = 0;
@ -824,15 +824,15 @@ abort:
return NULL; return NULL;
} }
static Block* ParseBlock(TokenId eType) static KmlBlock* ParseBlock(TokenId eType)
{ {
UINT u1; UINT u1;
Block* pBlock; KmlBlock* pBlock;
TokenId eToken; TokenId eToken;
nLinesIncludeLevel = 0; nLinesIncludeLevel = 0;
pBlock = LocalAlloc(LPTR,sizeof(Block)); pBlock = LocalAlloc(LPTR,sizeof(KmlBlock));
pBlock->eType = eType; pBlock->eType = eType;
u1 = 0; u1 = 0;
@ -880,13 +880,13 @@ static Block* ParseBlock(TokenId eType)
return pBlock; return pBlock;
} }
static Block* IncludeBlocks(LPCTSTR szFilename) static KmlBlock* IncludeBlocks(LPCTSTR szFilename)
{ {
HANDLE hFile; HANDLE hFile;
LPTSTR lpbyBuf; LPTSTR lpbyBuf;
UINT uOldLine; UINT uOldLine;
LPTSTR szOldText; LPTSTR szOldText;
Block* pFirst; KmlBlock* pFirst;
SetCurrentDirectory(szEmu48Directory); SetCurrentDirectory(szEmu48Directory);
hFile = CreateFile(szFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); hFile = CreateFile(szFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
@ -920,11 +920,11 @@ static Block* IncludeBlocks(LPCTSTR szFilename)
return pFirst; return pFirst;
} }
static Block* ParseBlocks() static KmlBlock* ParseBlocks(VOID)
{ {
TokenId eToken; TokenId eToken;
Block* pFirst = NULL; KmlBlock* pFirst = NULL;
Block* pBlock; KmlBlock* pBlock;
while ((eToken=Lex(LEX_BLOCK))!=TOK_NONE) while ((eToken=Lex(LEX_BLOCK))!=TOK_NONE)
{ {
@ -975,9 +975,9 @@ abort:
//# //#
//################ //################
static VOID InitGlobal(Block* pBlock) static VOID InitGlobal(KmlBlock* pBlock)
{ {
Line* pLine = pBlock->pFirstLine; KmlLine* pLine = pBlock->pFirstLine;
while (pLine) while (pLine)
{ {
switch (pLine->eCommand) switch (pLine->eCommand)
@ -1051,9 +1051,9 @@ static VOID InitGlobal(Block* pBlock)
return; return;
} }
static Line* InitBackground(Block* pBlock) static KmlLine* InitBackground(KmlBlock* pBlock)
{ {
Line* pLine = pBlock->pFirstLine; KmlLine* pLine = pBlock->pFirstLine;
while (pLine) while (pLine)
{ {
switch (pLine->eCommand) switch (pLine->eCommand)
@ -1076,9 +1076,9 @@ static Line* InitBackground(Block* pBlock)
return NULL; return NULL;
} }
static Line* InitLcd(Block* pBlock) static KmlLine* InitLcd(KmlBlock* pBlock)
{ {
Line* pLine = pBlock->pFirstLine; KmlLine* pLine = pBlock->pFirstLine;
while (pLine) while (pLine)
{ {
switch (pLine->eCommand) switch (pLine->eCommand)
@ -1105,11 +1105,11 @@ static Line* InitLcd(Block* pBlock)
return NULL; return NULL;
} }
static Line* InitAnnunciator(Block* pBlock) static KmlLine* InitAnnunciator(KmlBlock* pBlock)
{ {
Line* pLine = pBlock->pFirstLine; KmlLine* pLine = pBlock->pFirstLine;
UINT nId = pBlock->nId-1; UINT nId = pBlock->nId-1;
if (nId >= 6) if (nId >= ARRAYSIZEOF(pAnnunciator))
{ {
PrintfToLog(_T("Wrong Annunciator Id %i"), nId); PrintfToLog(_T("Wrong Annunciator Id %i"), nId);
return NULL; return NULL;
@ -1141,9 +1141,9 @@ static Line* InitAnnunciator(Block* pBlock)
return NULL; return NULL;
} }
static VOID InitButton(Block* pBlock) static VOID InitButton(KmlBlock* pBlock)
{ {
Line* pLine = pBlock->pFirstLine; KmlLine* pLine = pBlock->pFirstLine;
UINT nLevel = 0; UINT nLevel = 0;
if (nButtons>=256) if (nButtons>=256)
{ {
@ -1216,7 +1216,7 @@ static VOID InitButton(Block* pBlock)
//# //#
//################ //################
static Line* SkipLines(Line* pLine, TokenId eCommand) static KmlLine* SkipLines(KmlLine* pLine, TokenId eCommand)
{ {
UINT nLevel = 0; UINT nLevel = 0;
while (pLine) while (pLine)
@ -1238,7 +1238,7 @@ static Line* SkipLines(Line* pLine, TokenId eCommand)
return pLine; return pLine;
} }
static Line* If(Line* pLine, BOOL bCondition) static KmlLine* If(KmlLine* pLine, BOOL bCondition)
{ {
pLine = pLine->pNext; pLine = pLine->pNext;
if (bCondition) if (bCondition)
@ -1274,7 +1274,7 @@ static Line* If(Line* pLine, BOOL bCondition)
return pLine; return pLine;
} }
static Line* RunLine(Line* pLine) static KmlLine* RunLine(KmlLine* pLine)
{ {
switch (pLine->eCommand) switch (pLine->eCommand)
{ {
@ -1321,11 +1321,11 @@ static Line* RunLine(Line* pLine)
//# //#
//################ //################
static VOID FreeLines(Line* pLine) static VOID FreeLines(KmlLine* pLine)
{ {
while (pLine) while (pLine)
{ {
Line* pThisLine = pLine; KmlLine* pThisLine = pLine;
UINT i = 0; UINT i = 0;
DWORD nParams; DWORD nParams;
while (pLexToken[i].nLen) // search in all token definitions while (pLexToken[i].nLen) // search in all token definitions
@ -1351,11 +1351,11 @@ static VOID FreeLines(Line* pLine)
return; return;
} }
VOID FreeBlocks(Block* pBlock) VOID FreeBlocks(KmlBlock* pBlock)
{ {
while (pBlock) while (pBlock)
{ {
Block* pThisBlock = pBlock; KmlBlock* pThisBlock = pBlock;
pBlock = pBlock->pNext; pBlock = pBlock->pNext;
FreeLines(pThisBlock->pFirstLine); FreeLines(pThisBlock->pFirstLine);
LocalFree(pThisBlock); LocalFree(pThisBlock);
@ -1411,13 +1411,13 @@ VOID KillKML(VOID)
//# //#
//################ //################
static LPTSTR GetStringParam(Block* pBlock, TokenId eBlock, TokenId eCommand, UINT nParam) static LPTSTR GetStringParam(KmlBlock* pBlock, TokenId eBlock, TokenId eCommand, UINT nParam)
{ {
while (pBlock) while (pBlock)
{ {
if (pBlock->eType == eBlock) if (pBlock->eType == eBlock)
{ {
Line* pLine = pBlock->pFirstLine; KmlLine* pLine = pBlock->pFirstLine;
while (pLine) while (pLine)
{ {
if (pLine->eCommand == eCommand) if (pLine->eCommand == eCommand)
@ -1432,13 +1432,13 @@ static LPTSTR GetStringParam(Block* pBlock, TokenId eBlock, TokenId eCommand, UI
return NULL; return NULL;
} }
static DWORD GetIntegerParam(Block* pBlock, TokenId eBlock, TokenId eCommand, UINT nParam) static DWORD GetIntegerParam(KmlBlock* pBlock, TokenId eBlock, TokenId eCommand, UINT nParam)
{ {
while (pBlock) while (pBlock)
{ {
if (pBlock->eType == eBlock) if (pBlock->eType == eBlock)
{ {
Line* pLine = pBlock->pFirstLine; KmlLine* pLine = pBlock->pFirstLine;
while (pLine) while (pLine)
{ {
if (pLine->eCommand == eCommand) if (pLine->eCommand == eCommand)
@ -1583,10 +1583,10 @@ static VOID DrawButton(UINT nId)
else else
{ {
RECT Rect; RECT Rect;
Rect.left = x0; Rect.left = x0 - nBackgroundX;
Rect.right = x0 + pButton[nId].nCx; Rect.top = y0 - nBackgroundY;
Rect.top = y0; Rect.right = Rect.left + pButton[nId].nCx;
Rect.bottom = y0 + pButton[nId].nCy; Rect.bottom = Rect.top + pButton[nId].nCy;
InvalidateRect(hWnd, &Rect, FALSE); // call WM_PAINT for background and display redraw InvalidateRect(hWnd, &Rect, FALSE); // call WM_PAINT for background and display redraw
} }
break; break;
@ -1599,10 +1599,10 @@ static VOID DrawButton(UINT nId)
else else
{ {
RECT Rect; RECT Rect;
Rect.left = x0; Rect.left = x0 - nBackgroundX;
Rect.right = x0 + pButton[nId].nCx; Rect.top = y0 - nBackgroundY;
Rect.top = y0; Rect.right = Rect.left + pButton[nId].nCx;
Rect.bottom = y0 + pButton[nId].nCy; Rect.bottom = Rect.top + pButton[nId].nCy;
InvalidateRect(hWnd, &Rect, FALSE); // call WM_PAINT for background and display redraw InvalidateRect(hWnd, &Rect, FALSE); // call WM_PAINT for background and display redraw
} }
break; break;
@ -1648,7 +1648,7 @@ static VOID PressButton(UINT nId)
} }
else else
{ {
Line* pLine = pButton[nId].pOnDown; KmlLine* pLine = pButton[nId].pOnDown;
while ((pLine)&&(pLine->eCommand!=TOK_END)) while ((pLine)&&(pLine->eCommand!=TOK_END))
{ {
pLine = RunLine(pLine); pLine = RunLine(pLine);
@ -1667,7 +1667,7 @@ static VOID ReleaseButton(UINT nId)
} }
else else
{ {
Line* pLine = pButton[nId].pOnUp; KmlLine* pLine = pButton[nId].pOnUp;
while ((pLine)&&(pLine->eCommand!=TOK_END)) while ((pLine)&&(pLine->eCommand!=TOK_END))
{ {
pLine = RunLine(pLine); pLine = RunLine(pLine);
@ -1759,7 +1759,7 @@ VOID DrawAnnunciator(UINT nId, BOOL bOn)
UINT nSx,nSy; UINT nSx,nSy;
--nId; // zero based ID --nId; // zero based ID
if (nId>=6) return; if (nId >= ARRAYSIZEOF(pAnnunciator)) return;
if (bOn) if (bOn)
{ {
nSx = pAnnunciator[nId].nDx; // position of annunciator nSx = pAnnunciator[nId].nDx; // position of annunciator
@ -1794,6 +1794,9 @@ VOID DrawAnnunciator(UINT nId, BOOL bOn)
static BOOL ClipButton(UINT x, UINT y, UINT nId) static BOOL ClipButton(UINT x, UINT y, UINT nId)
{ {
x += nBackgroundX; // source display offset
y += nBackgroundY;
return (pButton[nId].nOx<=x) return (pButton[nId].nOx<=x)
&& (pButton[nId].nOy<=y) && (pButton[nId].nOy<=y)
&&(x<(pButton[nId].nOx+pButton[nId].nCx)) &&(x<(pButton[nId].nOx+pButton[nId].nCx))
@ -1897,7 +1900,7 @@ VOID RunKey(BYTE nId, BOOL bPressed)
{ {
if (pVKey[nId]) if (pVKey[nId])
{ {
Line* pLine = pVKey[nId]->pFirstLine; KmlLine* pLine = pVKey[nId]->pFirstLine;
byVKeyMap[nId] = bPressed; byVKeyMap[nId] = bPressed;
while (pLine) pLine = RunLine(pLine); while (pLine) pLine = RunLine(pLine);
} }
@ -1921,11 +1924,11 @@ VOID RunKey(BYTE nId, BOOL bPressed)
//# //#
//################ //################
static Block* LoadKMLGlobal(LPCTSTR szFilename) static KmlBlock* LoadKMLGlobal(LPCTSTR szFilename)
{ {
HANDLE hFile; HANDLE hFile;
LPTSTR lpBuf; LPTSTR lpBuf;
Block* pBlock; KmlBlock* pBlock;
DWORD eToken; DWORD eToken;
SetCurrentDirectory(szEmu48Directory); SetCurrentDirectory(szEmu48Directory);
@ -1954,7 +1957,7 @@ BOOL InitKML(LPCTSTR szFilename, BOOL bNoLog)
{ {
HANDLE hFile; HANDLE hFile;
LPTSTR lpBuf; LPTSTR lpBuf;
Block* pBlock; KmlBlock* pBlock;
BOOL bOk = FALSE; BOOL bOk = FALSE;
KillKML(); KillKML();

View file

@ -61,32 +61,32 @@ typedef enum eTokenId
#define TYPE_INTEGER 01 #define TYPE_INTEGER 01
#define TYPE_STRING 02 #define TYPE_STRING 02
typedef struct Token typedef struct KmlToken
{ {
TokenId eId; TokenId eId;
DWORD nParams; DWORD nParams;
DWORD nLen; DWORD nLen;
TCHAR szName[20]; TCHAR szName[20];
} Token; } KmlToken;
typedef struct Line typedef struct KmlLine
{ {
struct Line* pNext; struct KmlLine* pNext;
TokenId eCommand; TokenId eCommand;
DWORD nParam[6]; DWORD nParam[6];
} Line; } KmlLine;
typedef struct Block typedef struct KmlBlock
{ {
TokenId eType; TokenId eType;
DWORD nId; DWORD nId;
struct Line* pFirstLine; struct KmlLine* pFirstLine;
struct Block* pNext; struct KmlBlock* pNext;
} Block; } KmlBlock;
#define BUTTON_NOHOLD 0x0001 #define BUTTON_NOHOLD 0x0001
#define BUTTON_VIRTUAL 0x0002 #define BUTTON_VIRTUAL 0x0002
typedef struct Button typedef struct KmlButton
{ {
UINT nId; UINT nId;
BOOL bDown; BOOL bDown;
@ -96,20 +96,20 @@ typedef struct Button
UINT nDx, nDy; UINT nDx, nDy;
UINT nCx, nCy; UINT nCx, nCy;
UINT nOut, nIn; UINT nOut, nIn;
Line* pOnDown; KmlLine* pOnDown;
Line* pOnUp; KmlLine* pOnUp;
} Button; } KmlButton;
typedef struct Annunciator typedef struct KmlAnnunciator
{ {
UINT nOx, nOy; UINT nOx, nOy;
UINT nDx, nDy; UINT nDx, nDy;
UINT nCx, nCy; UINT nCx, nCy;
} Annunciator; } KmlAnnunciator;
extern Block* pKml; extern KmlBlock* pKml;
extern BOOL DisplayChooseKml(CHAR cType); extern BOOL DisplayChooseKml(CHAR cType);
extern VOID FreeBlocks(Block* pBlock); extern VOID FreeBlocks(KmlBlock* pBlock);
extern VOID DrawAnnunciator(UINT nId, BOOL bOn); extern VOID DrawAnnunciator(UINT nId, BOOL bOn);
extern VOID RefreshButtons(RECT *rc); extern VOID RefreshButtons(RECT *rc);
extern VOID MouseButtonDownAt(UINT nFlags, DWORD x, DWORD y); extern VOID MouseButtonDownAt(UINT nFlags, DWORD x, DWORD y);

View file

@ -27,16 +27,12 @@
#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))
BOOL ioc_acc = FALSE; // flag ioc changed
BOOL bFlashRomArray = TRUE; // flag ROM mode 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
static BYTE byVblRef = 0; // VBL stop reference
// CRC calculation // CRC calculation
static WORD crc_table[16] = static WORD crc_table[16] =
{ {
@ -133,17 +129,6 @@ static __inline VOID UpdateDisplay(DWORD d, UINT s)
return; return;
} }
// LCD line counter calculation
static BYTE F4096Hz(VOID) // get a 6 bit 4096Hz down counter value
{
LARGE_INTEGER lLC;
QueryPerformanceCounter(&lLC); // get counter value
// calculate 4096 Hz frequency down counter value
return -(BYTE)(((lLC.QuadPart - lAppStart.QuadPart) << 12) / lFreq.QuadPart) & 0x3F;
}
// port mapping // port mapping
LPBYTE RMap[256] = {NULL,}; LPBYTE RMap[256] = {NULL,};
@ -294,8 +279,11 @@ static VOID MapP2(BYTE a, BYTE b)
pbyTemp += (((Chipset.Bank_FF>>1)-1)&dwPort2Mask) << 18; pbyTemp += (((Chipset.Bank_FF>>1)-1)&dwPort2Mask) << 18;
} }
m = (dwPort2Size*2048)-1; // real size of module, address mask for mirroring // max. size per bank is 128KB
p = (a<<12)&m; // offset to begin of P2 in nibbles m = (dwPort2Size > 128) ? 128 : dwPort2Size;
m = (m * 2048) - 1; // real size of module, address mask for mirroring
p = (a << 12) & m; // offset to begin of P2 in nibbles
// SX: CE2.2 = CE2 // SX: CE2.2 = CE2
// GX: CE2.2 = BEN & /DA19 & /NCE3 // GX: CE2.2 = BEN & /DA19 & /NCE3
@ -673,23 +661,16 @@ VOID CpuReset(VOID) // register setting after Cpu Reset
Chipset.boffset = 0; // left margin Chipset.boffset = 0; // left margin
Chipset.lcounter = 0; // number of main display lines Chipset.lcounter = 0; // number of main display lines
Chipset.contrast = 0; // contrast dark Chipset.contrast = 0; // contrast dark
Chipset.dispon = 0; // display off
UpdateContrast(Chipset.contrast); // update contrast UpdateContrast(Chipset.contrast); // update contrast
// display update when changing to run state // display update when changing to run state
CommSetBaud(); // new baudrate CommSetBaud(); // new baudrate
ioc_acc = TRUE; // new IOC value, close serial port CheckSerial(); // close serial port
RomSwitch(Chipset.Bank_FF); // force new memory mapping RomSwitch(Chipset.Bank_FF); // force new memory mapping
return; return;
} }
BYTE GetLineCounter(VOID) // get line counter value
{
_ASSERT(byVblRef < 0x40);
return (0x40 + F4096Hz() - byVblRef) & 0x3F;
}
VOID Npeek(BYTE *a, DWORD d, UINT s) VOID Npeek(BYTE *a, DWORD d, UINT s)
{ {
enum MMUMAP eMap; enum MMUMAP eMap;
@ -702,22 +683,25 @@ VOID Npeek(BYTE *a, DWORD d, UINT s)
eMap = MapData(d); // get active memory controller eMap = MapData(d); // get active memory controller
if (M_IO == eMap) // I/O access if (M_IO == eMap) // I/O access
{ {
// update CRC
Nunpack(Chipset.IORam+CRC, Chipset.crc, 4);
// update CARDSTAT
Chipset.IORam[CARDSTAT] = (Chipset.IORam[CARDCTL] & ECDT) ? Chipset.cards_status : 0;
// update SRQ2
ReadIO(a,SRQ2,1);
// update timer1
Chipset.IORam[TIMER1] = Chipset.t1;
// update timer2
Nunpack(Chipset.IORam+TIMER2, ReadT2(), 8);
v = d&0x3F; v = d&0x3F;
c = MIN(s,0x40-v);
if (v >= RBR_LSB && v <= RBR_MSB)
{
// don't read RBR content with the function ReadIO()
c = MIN(s,RBR_MSB-v+1);
memcpy(a, Chipset.IORam+v, c); memcpy(a, Chipset.IORam+v, c);
} }
else else
{
// all others registers
if (v < RBR_LSB && (v+s) > RBR_LSB)
c = MIN(s,RBR_LSB-v);
else
c = MIN(s,0x40-v);
ReadIO(a,v,c);
}
}
else
{ {
u = d>>12; u = d>>12;
v = d&0xFFF; v = d&0xFFF;
@ -926,7 +910,7 @@ VOID Nwrite(BYTE *a, DWORD d, UINT s)
if ((p=WMap[u]) != NULL) memcpy(p+v, a, c); if ((p=WMap[u]) != NULL) memcpy(p+v, a, c);
} }
} }
UpdateDisplay(d, c); // update display GRAYOFF(UpdateDisplay(d, c)); // update display
a+=c; a+=c;
d+=c; d+=c;
} while (s-=c); } while (s-=c);
@ -999,7 +983,7 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s)
{ {
switch (d) switch (d)
{ {
case 0x00: *a = (Chipset.dispon<<3)|Chipset.boffset; break; case 0x00: *a = (Chipset.IORam[d]&DON)|Chipset.boffset; break;
case 0x01: *a = Chipset.contrast&0xF; break; case 0x01: *a = Chipset.contrast&0xF; break;
case 0x02: *a = Chipset.contrast>>4; break; case 0x02: *a = Chipset.contrast>>4; break;
case 0x03: *a = 0; case 0x03: *a = 0;
@ -1252,22 +1236,20 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
case 0x00: case 0x00:
if ((c^Chipset.IORam[d])&DON) // DON bit changed if ((c^Chipset.IORam[d])&DON) // DON bit changed
{ {
Chipset.dispon = c>>3;
disp |= (DISP_POINTER | DISP_MAIN | DISP_MENUE); disp |= (DISP_POINTER | DISP_MAIN | DISP_MENUE);
// adjust VBL counter start/stop values // adjust VBL counter start/stop values
if (Chipset.dispon) // display is on if ((c & DON) != 0) // set display on
{ {
// get positive VBL difference between now and stop time Chipset.IORam[d] |= DON; // for StartDisplay();
byVblRef = ( 0x40 UpdateContrast(Chipset.contrast);
+ F4096Hz() StartDisplay((BYTE) Chipset.lcounter); // start display update
- (((Chipset.IORam[0x29] << 4) | Chipset.IORam[0x28]) & 0x3F)
) & 0x3F;
} }
else // display is off else // display is off
{ {
BYTE a[2]; Chipset.IORam[d] &= ~DON;
ReadIO(a,0x28,2); // update VBL at display off time UpdateContrast(Chipset.contrast);
StopDisplay(); // stop display update
} }
} }
// OFF bits changed // OFF bits changed
@ -1420,8 +1402,8 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
Chipset.IORam[TBR_MSB] = 0; Chipset.IORam[TBR_MSB] = 0;
} }
Chipset.IORam[d]=c; Chipset.IORam[d]=c;
UpdateUSRQ(); // update USRQ CheckSerial(); // handle UART on/off
ioc_acc = TRUE; // new IOC value if (UpdateUSRQ()) INTERRUPT; // update USRQ bit
#if defined DEBUG_SERIAL #if defined DEBUG_SERIAL
{ {
TCHAR buffer[256]; TCHAR buffer[256];
@ -1436,7 +1418,12 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
case 0x11: case 0x11:
if (Chipset.IORam[IOC] & SON) if (Chipset.IORam[IOC] & SON)
{ {
EnterCriticalSection(&csIOLock);
{
// critical section because of RER access
Chipset.IORam[d]=(Chipset.IORam[d]&8)|(c&7); Chipset.IORam[d]=(Chipset.IORam[d]&8)|(c&7);
}
LeaveCriticalSection(&csIOLock);
#if defined DEBUG_SERIAL #if defined DEBUG_SERIAL
{ {
TCHAR buffer[256]; TCHAR buffer[256];
@ -1453,6 +1440,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
if (Chipset.IORam[IOC] & SON) if (Chipset.IORam[IOC] & SON)
{ {
Chipset.IORam[d]=c; Chipset.IORam[d]=c;
CommTxBRK(); // update BRK condition
#if defined DEBUG_SERIAL #if defined DEBUG_SERIAL
{ {
TCHAR buffer[256]; TCHAR buffer[256];
@ -1466,7 +1454,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
// 00113 = HP:CRER // 00113 = HP:CRER
// 00113 @ Serial Clear RER (writing anything clears RER bit) // 00113 @ Serial Clear RER (writing anything clears RER bit)
case 0x13: case 0x13:
Chipset.IORam[RCS]&=~RER; IOBit(RCS,RER,FALSE);
#if defined DEBUG_SERIAL #if defined DEBUG_SERIAL
{ {
TCHAR buffer[256]; TCHAR buffer[256];
@ -1478,7 +1466,6 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
// 00114 = HP:RBR // 00114 = HP:RBR
// 00114 @ Serial Receive Buffer Register (Reading clears RBF bit) // 00114 @ Serial Receive Buffer Register (Reading clears RBF bit)
// 00114 @ [RX RER RBZ RBF]
case 0x14: break; // read-only case 0x14: break; // read-only
case 0x15: break; // read-only case 0x15: break; // read-only
@ -1489,8 +1476,6 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
if (Chipset.IORam[IOC] & SON) if (Chipset.IORam[IOC] & SON)
{ {
Chipset.IORam[d]=c; Chipset.IORam[d]=c;
Chipset.IORam[TCS]|=TBF;
UpdateUSRQ(); // update USRQ
tbr_acc = TRUE; // new TBR value tbr_acc = TRUE; // new TBR value
#if defined DEBUG_SERIAL #if defined DEBUG_SERIAL
{ {
@ -1700,7 +1685,11 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
} }
} }
if (tbr_acc) CommTransmit(); // transmit char if (tbr_acc) // addr 0x116-0x117 changed
{
IOBit(TCS,TBF,TRUE); // set transmit buffer full bit
CommTransmit(); // transmit char
}
if (disp & DISP_POINTER) if (disp & DISP_POINTER)
{ {

View file

@ -16,6 +16,12 @@
#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;}}
#define GOYES5 {if(w.carry) o_goyes5(I);else{w.pc+=2;return;}} #define GOYES5 {if(w.carry) o_goyes5(I);else{w.pc+=2;return;}}
#if !defined BIGENDIAN
#define REG(t,r) (*((t*)&(r))) // low endian machine
#else
#define REG(t,r) (*((t*)((BYTE*)&(r)+sizeof(r)-sizeof(t)))) // big endian machine
#endif
#pragma intrinsic(memset,memcpy) #pragma intrinsic(memset,memcpy)
#include "Ops.h" #include "Ops.h"
@ -620,11 +626,11 @@ VOID o137(LPBYTE I) // CD1EX
return; return;
} }
VOID o138(LPBYTE I)// D0=AS VOID o138(LPBYTE I) // D0=AS
{ {
w.cycles+=7; w.cycles+=7;
w.pc+=3; w.pc+=3;
*((WORD*)&w.d0)=(WORD)Npack(w.A,4); REG(WORD,w.d0)=(WORD)Npack(w.A,4);
return; return;
} }
@ -632,14 +638,14 @@ VOID o139(LPBYTE I) // D1=AS
{ {
w.cycles+=7; w.cycles+=7;
w.pc+=3; w.pc+=3;
*((WORD*)&w.d1)=(WORD)Npack(w.A,4); REG(WORD,w.d1)=(WORD)Npack(w.A,4);
return; return;
} }
VOID o13A(LPBYTE I) // AD0XS VOID o13A(LPBYTE I) // AD0XS
{ {
DWORD d=w.d0; DWORD d=w.d0;
*((WORD*)&w.d0)=(WORD)Npack(w.A,4); REG(WORD,w.d0)=(WORD)Npack(w.A,4);
Nunpack(w.A,d,4); Nunpack(w.A,d,4);
w.cycles+=7; w.cycles+=7;
w.pc+=3; w.pc+=3;
@ -649,7 +655,7 @@ VOID o13A(LPBYTE I) // AD0XS
VOID o13B(LPBYTE I) // AD1XS VOID o13B(LPBYTE I) // AD1XS
{ {
DWORD d=w.d1; DWORD d=w.d1;
*((WORD*)&w.d1)=(WORD)Npack(w.A,4); REG(WORD,w.d1)=(WORD)Npack(w.A,4);
Nunpack(w.A,d,4); Nunpack(w.A,d,4);
w.cycles+=7; w.cycles+=7;
w.pc+=3; w.pc+=3;
@ -660,7 +666,7 @@ VOID o13C(LPBYTE I) // D0=CS
{ {
w.cycles+=7; w.cycles+=7;
w.pc+=3; w.pc+=3;
*((WORD*)&w.d0)=(WORD)Npack(w.C,4); REG(WORD,w.d0)=(WORD)Npack(w.C,4);
return; return;
} }
@ -668,24 +674,24 @@ VOID o13D(LPBYTE I) // D1=CS
{ {
w.cycles+=7; w.cycles+=7;
w.pc+=3; w.pc+=3;
*((WORD*)&w.d1)=(WORD)Npack(w.C,4); REG(WORD,w.d1)=(WORD)Npack(w.C,4);
return; return;
} }
VOID o13E(LPBYTE I) // AD0XS VOID o13E(LPBYTE I) // CD0XS
{ {
DWORD d=w.d0; DWORD d=w.d0;
*((WORD*)&w.d0)=(WORD)Npack(w.C,4); REG(WORD,w.d0)=(WORD)Npack(w.C,4);
Nunpack(w.C,d,4); Nunpack(w.C,d,4);
w.cycles+=7; w.cycles+=7;
w.pc+=3; w.pc+=3;
return; return;
} }
VOID o13F(LPBYTE I) // AD1XS VOID o13F(LPBYTE I) // CD1XS
{ {
DWORD d=w.d1; DWORD d=w.d1;
*((WORD*)&w.d1)=(WORD)Npack(w.C,4); REG(WORD,w.d1)=(WORD)Npack(w.C,4);
Nunpack(w.C,d,4); Nunpack(w.C,d,4);
w.cycles+=7; w.cycles+=7;
w.pc+=3; w.pc+=3;
@ -783,7 +789,7 @@ VOID o19d2(LPBYTE I) // D0=(2) #dd
{ {
w.cycles+=4; w.cycles+=4;
w.pc+=4; w.pc+=4;
*((BYTE*)&w.d0)=(BYTE)Npack(I+2,2); REG(BYTE,w.d0)=(BYTE)Npack(I+2,2);
return; return;
} }
@ -791,7 +797,7 @@ VOID o1Ad4(LPBYTE I) // D0=(4) #dddd
{ {
w.cycles+=6; w.cycles+=6;
w.pc+=6; w.pc+=6;
*((WORD*)&w.d0)=(WORD)Npack(I+2,4); REG(WORD,w.d0)=(WORD)Npack(I+2,4);
return; return;
} }
@ -824,7 +830,7 @@ VOID o1Dd2(LPBYTE I) // D1=(2) #dd
{ {
w.cycles+=4; w.cycles+=4;
w.pc+=4; w.pc+=4;
*((BYTE*)&w.d1)=(BYTE)Npack(I+2,2); REG(BYTE,w.d1)=(BYTE)Npack(I+2,2);
return; return;
} }
@ -832,7 +838,7 @@ VOID o1Ed4(LPBYTE I) // D1=(4) #dddd
{ {
w.cycles+=6; w.cycles+=6;
w.pc+=6; w.pc+=6;
*((WORD*)&w.d1)=(WORD)Npack(I+2,4); REG(WORD,w.d1)=(WORD)Npack(I+2,4);
return; return;
} }

View file

@ -90,8 +90,8 @@ extern VOID o13A(LPBYTE I); // AD0XS
extern VOID o13B(LPBYTE I); // AD1XS extern VOID o13B(LPBYTE I); // AD1XS
extern VOID o13C(LPBYTE I); // D0=CS extern VOID o13C(LPBYTE I); // D0=CS
extern VOID o13D(LPBYTE I); // D1=CS extern VOID o13D(LPBYTE I); // D1=CS
extern VOID o13E(LPBYTE I); // AD0XS extern VOID o13E(LPBYTE I); // CD0XS
extern VOID o13F(LPBYTE I); // AD1XS extern VOID o13F(LPBYTE I); // CD1XS
extern VOID o140(LPBYTE I); // DAT0=A A extern VOID o140(LPBYTE I); // DAT0=A A
extern VOID o141(LPBYTE I); // DAT0=A A extern VOID o141(LPBYTE I); // DAT0=A A
extern VOID o144(LPBYTE I); // DAT0=C A extern VOID o144(LPBYTE I); // DAT0=C A

View file

@ -2,11 +2,14 @@
// PCH.H // PCH.H
// //
#define _WIN32_IE 0x0200
#include <windows.h> #include <windows.h>
#include <tchar.h> #include <tchar.h>
#include <shellapi.h> #include <shellapi.h>
#include <commctrl.h> #include <commctrl.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <direct.h> #include <direct.h>
#include <crtdbg.h> #include <crtdbg.h>

View file

@ -8,19 +8,21 @@
#define IDR_DEBUG_TOOLBAR 103 #define IDR_DEBUG_TOOLBAR 103
#define IDR_DEBUG_CODE 104 #define IDR_DEBUG_CODE 104
#define IDR_DEBUG_MEM 105 #define IDR_DEBUG_MEM 105
#define IDD_ABOUT 106 #define IDR_DEBUG_STACK 106
#define IDD_SETTINGS 107 #define IDB_CHECKBOX 107
#define IDD_CHOOSEKML 108 #define IDD_ABOUT 108
#define IDD_KMLLOG 109 #define IDD_SETTINGS 109
#define IDD_DISASM 110 #define IDD_CHOOSEKML 110
#define IDD_DEBUG 111 #define IDD_KMLLOG 111
#define IDD_NEWVALUE 112 #define IDD_DISASM 112
#define IDD_ENTERADR 113 #define IDD_DEBUG 113
#define IDD_BREAKEDIT 114 #define IDD_NEWVALUE 114
#define IDD_ENTERBREAK 115 #define IDD_ENTERADR 115
#define IDD_INSTRUCTIONS 116 #define IDD_BREAKEDIT 116
#define IDD_FIND 117 #define IDD_ENTERBREAK 117
#define IDB_CHECKBOX 120 #define IDD_INSTRUCTIONS 118
#define IDD_WRITEONLYREG 119
#define IDD_FIND 120
#define IDC_PORT1WR 1000 #define IDC_PORT1WR 1000
#define IDC_AUTOSAVE 1001 #define IDC_AUTOSAVE 1001
#define IDC_AUTOSAVEONEXIT 1002 #define IDC_AUTOSAVEONEXIT 1002
@ -125,6 +127,10 @@
#define IDC_FIND_DATA 1101 #define IDC_FIND_DATA 1101
#define IDC_FIND_ASCII 1102 #define IDC_FIND_ASCII 1102
#define IDC_FIND_CASE 1103 #define IDC_FIND_CASE 1103
#define IDC_ADDR20_24 1104
#define IDC_ADDR25_27 1105
#define IDC_ADDR28_29 1106
#define IDC_ADDR30_34 1107
#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
@ -167,16 +173,35 @@
#define ID_DEBUG_MEM_GOD1 40042 #define ID_DEBUG_MEM_GOD1 40042
#define ID_DEBUG_MEM_GOSTACK 40043 #define ID_DEBUG_MEM_GOSTACK 40043
#define ID_DEBUG_MEM_FIND 40044 #define ID_DEBUG_MEM_FIND 40044
#define ID_INFO_LASTINSTRUCTIONS 40045 #define ID_DEBUG_MEM_MAP 40045
#define ID_INTR_STEPOVERINT 40046 #define ID_DEBUG_MEM_NCE1 40046
#define ID_DEBUG_MEM_NCE2 40047
#define ID_DEBUG_MEM_CE1 40048
#define ID_DEBUG_MEM_CE2 40049
#define ID_DEBUG_MEM_NCE3 40050
#define ID_DEBUG_STACK_PUSH 40051
#define ID_DEBUG_STACK_POP 40052
#define ID_DEBUG_STACK_MODIFY 40053
#define ID_INTR_STEPOVERINT 40054
#define ID_INFO_LASTINSTRUCTIONS 40055
#define ID_INFO_WRITEONLYREG 40056
// Resource definitions for Windows XP
//
#ifndef CREATEPROCESS_MANIFEST_RESOURCE_ID
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#endif
#ifndef RT_MANIFEST
#define RT_MANIFEST 24
#endif
// 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 121 #define _APS_NEXT_RESOURCE_VALUE 121
#define _APS_NEXT_COMMAND_VALUE 40047 #define _APS_NEXT_COMMAND_VALUE 40057
#define _APS_NEXT_CONTROL_VALUE 1104 #define _APS_NEXT_CONTROL_VALUE 1108
#define _APS_NEXT_SYMED_VALUE 108 #define _APS_NEXT_SYMED_VALUE 108
#endif #endif
#endif #endif

View file

@ -20,15 +20,43 @@
#define NINT2USRQ (NINT2ERBZ || NINT2ERBF || NINT2ETBE) #define NINT2USRQ (NINT2ERBZ || NINT2ERBF || NINT2ETBE)
static HANDLE hComm = NULL; static HANDLE hComm = NULL;
static HANDLE hCThread = NULL;
static DWORD lSerialThreadId; static HANDLE hCThreadTxd;
static HANDLE hCThreadEv;
static HANDLE hEventTxd;
static BOOL bWriting;
static BYTE tbr;
static BOOL bReading; static BOOL bReading;
static BYTE cBuffer[128]; static BYTE cBuffer[32];
static WORD nRp; static WORD nRp;
static DWORD dwBytesRead; static DWORD dwBytesRead;
static DWORD WINAPI SerialThread(LPVOID pParam) static DWORD WINAPI TransmitThread(LPVOID pParam)
{
OVERLAPPED osWr = { 0 };
osWr.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
while (bWriting)
{
WaitForSingleObject(hEventTxd,INFINITE);
if (bWriting)
{
DWORD dwWritten;
if (!WriteFile(hComm,(LPCVOID) &tbr,1,&dwWritten,&osWr))
if (GetLastError() == ERROR_IO_PENDING)
GetOverlappedResult(hComm,&osWr,&dwWritten,TRUE);
}
}
CloseHandle(osWr.hEvent); // close write event handle
return 0;
UNREFERENCED_PARAMETER(pParam);
}
static DWORD WINAPI EventThread(LPVOID pParam)
{ {
DWORD dwEvent; DWORD dwEvent;
@ -47,6 +75,19 @@ static DWORD WINAPI SerialThread(LPVOID pParam)
SetEvent(hEventShutdn); // wake up emulation thread SetEvent(hEventShutdn); // wake up emulation thread
} }
} }
if (dwEvent & EV_TXEMPTY) // signal transmit buffer empty
{
IOBit(TCS,TBZ,FALSE); // clear transmitter busy bit
CommTransmit(); // check for new char to transmit
}
if (dwEvent & EV_ERR) // signal error received
{
DWORD dwError;
ClearCommError(hComm,&dwError,NULL);
if (dwError & (CE_FRAME | CE_OVERRUN | CE_BREAK))
IOBit(RCS,RER,TRUE); // receiver error
}
} }
return 0; return 0;
UNREFERENCED_PARAMETER(pParam); UNREFERENCED_PARAMETER(pParam);
@ -60,11 +101,22 @@ BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort)
_ASSERT(Chipset.IORam[IOC] & SON); // UART on _ASSERT(Chipset.IORam[IOC] & SON); // UART on
if (hComm != NULL) // port already open if (hComm != NULL) // port already open
{
CloseHandle(hComm); CloseHandle(hComm);
hComm = NULL;
}
if (lstrcmp(strPort, _T(NO_SERIAL))) // port defined if (lstrcmp(strPort, _T(NO_SERIAL))) // port defined
{ {
hComm = CreateFile(strPort, TCHAR szDevice[16] = _T("\\\\.\\");
// check if device buffer is big enough
_ASSERT(lstrlen(szDevice) + lstrlen(strPort) < ARRAYSIZEOF(szDevice));
if (lstrlen(szDevice) + lstrlen(strPort) >= ARRAYSIZEOF(szDevice))
return hComm != NULL;
_tcscat(szDevice,strPort); // device name
hComm = CreateFile(szDevice,
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
0, 0,
NULL, NULL,
@ -74,17 +126,33 @@ BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort)
if(hComm != INVALID_HANDLE_VALUE) if(hComm != INVALID_HANDLE_VALUE)
{ {
DWORD dwThreadId;
nRp = 0; // reset receiver state nRp = 0; // reset receiver state
dwBytesRead = 0L; dwBytesRead = 0L;
SetCommTimeouts(hComm,&CommTimeouts); SetCommTimeouts(hComm,&CommTimeouts);
CommSetBaud(); CommSetBaud();
// set event RXD handler CommTxBRK(); // update BRK condition
// event to transmit character
hEventTxd = CreateEvent(NULL,FALSE,FALSE,NULL);
// create char transmit handler
bWriting = TRUE;
hCThreadTxd = CreateThread(NULL,0,&TransmitThread,NULL,CREATE_SUSPENDED,&dwThreadId);
_ASSERT(hCThreadTxd);
SetThreadPriority(hCThreadTxd,THREAD_PRIORITY_ABOVE_NORMAL);
ResumeThread(hCThreadTxd); // start thread
// create Comm event handler
bReading = FALSE; bReading = FALSE;
SetCommMask(hComm,EV_RXCHAR); // event on RX SetCommMask(hComm,EV_RXCHAR | EV_TXEMPTY | EV_ERR); // event on RX, TX, error
hCThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&SerialThread,NULL,0,&lSerialThreadId); hCThreadEv = CreateThread(NULL,0,&EventThread,NULL,CREATE_SUSPENDED,&dwThreadId);
_ASSERT(lSerialThreadId); _ASSERT(hCThreadEv);
SetThreadPriority(hCThreadEv,THREAD_PRIORITY_ABOVE_NORMAL);
ResumeThread(hCThreadEv); // start thread
while (!bReading) Sleep(0); // wait for SerialThread started while (!bReading) Sleep(0); // wait for SerialThread started
} }
else else
@ -106,10 +174,18 @@ VOID CommClose(VOID)
if (hComm != NULL) // port open if (hComm != NULL) // port open
{ {
Sleep(25); // workaround to fix problems with some Kermit server Sleep(25); // workaround to fix problems with some Kermit server
bReading = FALSE; // kill read thread
bReading = FALSE; // kill event thread
SetCommMask(hComm,0L); // clear all events and force WaitCommEvent to return SetCommMask(hComm,0L); // clear all events and force WaitCommEvent to return
WaitForSingleObject(hCThread,INFINITE); // wait for thread termination WaitForSingleObject(hCThreadEv,INFINITE);
CloseHandle(hCThread); // close thread handle CloseHandle(hCThreadEv);
bWriting = FALSE; // kill write thread
SetEvent(hEventTxd); // continue write thread
WaitForSingleObject(hCThreadTxd,INFINITE);
CloseHandle(hCThreadTxd);
CloseHandle(hEventTxd); // close Txd event
CloseHandle(hComm); // close port CloseHandle(hComm); // close port
hComm = NULL; hComm = NULL;
#if defined DEBUG_SERIAL #if defined DEBUG_SERIAL
@ -127,7 +203,7 @@ VOID CommSetBaud(VOID)
DCB dcb; DCB dcb;
FillMemory(&dcb,sizeof(dcb),0); ZeroMemory(&dcb,sizeof(dcb));
dcb.DCBlength = sizeof(dcb); dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = dwBaudrates[Chipset.IORam[BAUD] & 0x7]; dcb.BaudRate = dwBaudrates[Chipset.IORam[BAUD] & 0x7];
dcb.fBinary = TRUE; dcb.fBinary = TRUE;
@ -165,13 +241,57 @@ BOOL UpdateUSRQ(VOID) // USRQ handling
return bUSRQ; return bUSRQ;
} }
VOID CommTxBRK(VOID)
{
if (Chipset.IORam[TCS] & BRK) // BRK condition
{
if (hComm != NULL) // com port open
{
// abort data transfer
PurgeComm(hComm,PURGE_TXABORT | PURGE_TXCLEAR);
SetCommBreak(hComm); // set into BRK state
}
// TBF and TBZ bits of TCS are undefined
if (Chipset.IORam[TCS] & LPB) // is loopback bit set
{
dwBytesRead = nRp = 0; // clear receive buffer
cBuffer[dwBytesRead++] = 0; // save character in receive buffer
CommReceive(); // receive available byte
IOBit(RCS,RER,TRUE); // receiver error (no stop bit)
}
}
else
{
if (hComm != NULL) // com port open
{
ClearCommBreak(hComm); // clear BRK state
}
}
return;
}
VOID CommTransmit(VOID) VOID CommTransmit(VOID)
{ {
OVERLAPPED os = { 0 }; BOOL bTxChar = FALSE;
DWORD dwWritten;
BYTE tbr = (Chipset.IORam[TBR_MSB] << 4) | Chipset.IORam[TBR_LSB]; EnterCriticalSection(&csTxdLock);
if ( (Chipset.IORam[TCS] & TBZ) == 0 // transmitter not busy
&& (Chipset.IORam[TCS] & TBF) != 0) // transmit buffer full
{
tbr = (Chipset.IORam[TBR_MSB] << 4) | Chipset.IORam[TBR_LSB];
IOBit(TCS,TBF,FALSE); // clear transmit buffer full bit
IOBit(TCS,TBZ,TRUE); // set transmitter busy bit
bTxChar = TRUE;
}
LeaveCriticalSection(&csTxdLock);
if (bTxChar) // character to transmit
{
#if defined DEBUG_SERIAL #if defined DEBUG_SERIAL
{ {
TCHAR buffer[256]; TCHAR buffer[256];
@ -189,18 +309,18 @@ VOID CommTransmit(VOID)
cBuffer[nRp+dwBytesRead] = tbr; // save character in receive buffer cBuffer[nRp+dwBytesRead] = tbr; // save character in receive buffer
++dwBytesRead; ++dwBytesRead;
CommReceive(); // receive byte available CommReceive(); // receive available byte
} }
if (hComm != NULL) // com port open if (hComm != NULL) // com port open
{ {
os.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); SetEvent(hEventTxd); // write TBR byte
WriteFile(hComm,(LPCVOID) &tbr,1,&dwWritten,&os); }
GetOverlappedResult(hComm,&os,&dwWritten,TRUE); else
CloseHandle(os.hEvent); {
IOBit(TCS,TBZ,FALSE); // clear transmitter busy bit
}
} }
Chipset.IORam[TCS] &= (~TBF); // clear transmit buffer
if (UpdateUSRQ()) // update USRQ bit if (UpdateUSRQ()) // update USRQ bit
INTERRUPT; INTERRUPT;
return; return;
@ -251,7 +371,7 @@ VOID CommReceive(VOID)
--dwBytesRead; --dwBytesRead;
Chipset.IORam[RCS] |= RBF; // receive buffer full Chipset.IORam[RCS] |= RBF; // receive buffer full
if (UpdateUSRQ()) // update USRQ bit if(UpdateUSRQ()) // update USRQ bit
INTERRUPT; INTERRUPT;
} }
while(0); while(0);

View file

@ -56,34 +56,42 @@ static DWORD CalcT2(VOID) // calculate timer2 value
DWORD dwT2Dif; DWORD dwT2Dif;
QueryPerformanceCounter(&lT2Act); // actual time QueryPerformanceCounter(&lT2Act); // actual time
// calculate ticks since reference point // calculate realtime timer2 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; // timer2 ticks since last request
dwT2Dif = dwT2Ref - dwT2;
if (bT2Val && dwT2Dif > 0x01 && dwT2Dif <= 0x100) // checking if the MSB of dwT2Dif can be used as sign flag
_ASSERT((DWORD) tc.wPeriodMax < ((1<<(sizeof(dwT2Dif)*8-1))/8192)*1000);
// 2nd timer call in a 32ms time frame or elapsed time is negative (Win2k bug)
if (bT2Val && ((dwT2Dif > 0x01 && dwT2Dif <= 0x100) || (dwT2Dif & 0x80000000) != 0))
{ {
#define CYC_PER_TICK (2 * 72) #define CYC_PER_TICK (2 * 72)
DWORD dwT2Ticks = ((DWORD) (Chipset.cycles & 0xFFFFFFFF) - dwT2Cyc) / CYC_PER_TICK; DWORD dwT2Ticks = ((DWORD) (Chipset.cycles & 0xFFFFFFFF) - dwT2Cyc) / CYC_PER_TICK;
if (dwT2Ticks >= dwT2Dif) // estimated >= real elapsed timer2 ticks and positive time
if (dwT2Ticks >= dwT2Dif && (dwT2Dif & 0x80000000) == 0)
{ {
// reached actual time -> new synchronizing
dwT2Cyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); dwT2Cyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
} }
else else
{ {
dwT2 = dwT2Ref - dwT2Ticks; // real time too long or got negative time elapsed
dwT2Cyc += dwT2Ticks * CYC_PER_TICK; dwT2 = dwT2Ref - dwT2Ticks; // estimated timer2 value from CPU cycles
dwT2Cyc += dwT2Ticks * CYC_PER_TICK; // estimated CPU cycles for the timer2 ticks
} }
#undef CYC_PER_TICK #undef CYC_PER_TICK
} }
else else
{ {
// valid actual time -> new synchronizing
dwT2Cyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); dwT2Cyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
} }
dwT2Ref = dwT2; dwT2Ref = dwT2; // new reference time
bT2Val = TRUE; // access values valid bT2Val = TRUE; // access values valid
} }
return dwT2; return dwT2;
@ -174,7 +182,7 @@ static VOID RescheduleT2(BOOL bRefPoint)
uDelay = CalcT2(); // actual timer value for delay uDelay = CalcT2(); // actual timer value for delay
} }
uDelay &= 0x7FFFFFFF; // execute timer2 event when MSB change uDelay &= 0x7FFFFFFF; // execute timer2 event when MSB change
uDelay >>= 3; // timer delay in ms uDelay = (uDelay + 7) >> 3; // timer delay in ms
uDelay = MAX(tc.wPeriodMin,uDelay); // wait minimum delay of timer uDelay = MAX(tc.wPeriodMin,uDelay); // wait minimum delay of timer
if ((bOutRange = uDelay > tc.wPeriodMax)) // delay greater maximum delay if ((bOutRange = uDelay > tc.wPeriodMax)) // delay greater maximum delay
uDelay = tc.wPeriodMax; // wait maximum delay time uDelay = tc.wPeriodMax; // wait maximum delay time
@ -308,11 +316,11 @@ VOID StartTimers(VOID)
// 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;
// set timer resolution to 1 ms, if failed don't use "Accurate timer"
bAccurateTimer = (timeBeginPeriod(1) == TIMERR_NOERROR);
timeGetDevCaps(&tc,sizeof(tc)); // get timer resolution timeGetDevCaps(&tc,sizeof(tc)); // get timer resolution
CheckT1(Chipset.t1); // check for timer1 interrupts CheckT1(Chipset.t1); // check for timer1 interrupts
CheckT2(Chipset.t2); // check for timer2 interrupts CheckT2(Chipset.t2); // check for timer2 interrupts
// set timer resolution to 1 ms, if failed don't use "Accurate timer"
bAccurateTimer = (timeBeginPeriod(1) == TIMERR_NOERROR);
// set timer1 with given period // set timer1 with given period
uT1TimerId = timeSetEvent(T1_FREQ,0,(LPTIMECALLBACK)&TimeProc,1,TIME_PERIODIC); uT1TimerId = timeSetEvent(T1_FREQ,0,(LPTIMECALLBACK)&TimeProc,1,TIME_PERIODIC);
_ASSERT(uT1TimerId); // test if timer1 started _ASSERT(uT1TimerId); // test if timer1 started
@ -336,10 +344,9 @@ VOID StopTimers(VOID)
EnterCriticalSection(&csT2Lock); EnterCriticalSection(&csT2Lock);
{ {
Chipset.t2 = CalcT2(); // update chipset timer2 value Chipset.t2 = CalcT2(); // update chipset timer2 value
// AbortT2(); // removed, stop timer2 later
} }
LeaveCriticalSection(&csT2Lock); LeaveCriticalSection(&csT2Lock);
AbortT2(); // stop timer2 here AbortT2(); // stop timer2 outside critical section
} }
bStarted = FALSE; bStarted = FALSE;
if (bAccurateTimer) // "Accurate timer" running if (bAccurateTimer) // "Accurate timer" running

View file

@ -95,7 +95,7 @@ typedef struct
UINT lcounter; UINT lcounter;
UINT sync; // not used UINT sync; // not used
BYTE contrast; BYTE contrast;
BOOL dispon; BOOL dispon; // not used
DWORD start1; DWORD start1;
DWORD start12; DWORD start12;
DWORD end1; DWORD end1;

View file

@ -29,6 +29,14 @@ LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE GUIDELINES DESIGNINFO DISCARDABLE
BEGIN BEGIN
IDD_WRITEONLYREG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 173
TOPMARGIN, 7
BOTTOMMARGIN, 75
END
IDD_FIND, DIALOG IDD_FIND, DIALOG
BEGIN BEGIN
LEFTMARGIN, 6 LEFTMARGIN, 6
@ -133,7 +141,24 @@ END
// Dialog // Dialog
// //
IDD_FIND DIALOGEX 0, 0, 197, 47 IDD_WRITEONLYREG DIALOG DISCARDABLE 0, 0, 180, 82
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Write Only Registers"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "20-24 (Display Start Address)",IDC_STATIC,11,11,131,8
RTEXT "00000",IDC_ADDR20_24,144,11,25,8
LTEXT "25-27 (Display Line Offset)",IDC_STATIC,11,21,131,8
RTEXT "000",IDC_ADDR25_27,144,21,25,8
LTEXT "28-29 (Display Line Counter)",IDC_STATIC,11,31,131,8
RTEXT "00",IDC_ADDR28_29,144,31,25,8
LTEXT "30-34 (Display Secondary Start Address)",IDC_STATIC,11,
41,131,8
RTEXT "00000",IDC_ADDR30_34,144,41,25,8
DEFPUSHBUTTON "OK",IDOK,65,61,50,14
END
IDD_FIND DIALOG DISCARDABLE 0, 0, 197, 47
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOOLWINDOW EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Find" CAPTION "Find"
@ -144,7 +169,7 @@ BEGIN
WS_VSCROLL | WS_TABSTOP WS_VSCROLL | WS_TABSTOP
CONTROL "Find &ASCII",IDC_FIND_ASCII,"Button",BS_AUTOCHECKBOX | CONTROL "Find &ASCII",IDC_FIND_ASCII,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,46,30,49,10 WS_TABSTOP,46,30,49,10
DEFPUSHBUTTON "Find Next",IDOK,140,7,50,14 DEFPUSHBUTTON "&Find Next",IDOK,140,7,50,14
PUSHBUTTON "Cancel",IDCANCEL,140,26,50,14 PUSHBUTTON "Cancel",IDCANCEL,140,26,50,14
END END
@ -163,7 +188,7 @@ BEGIN
PUSHBUTTON "&Delete",IDC_BREAKEDIT_DELETE,44,81,30,14 PUSHBUTTON "&Delete",IDC_BREAKEDIT_DELETE,44,81,30,14
END END
IDD_ABOUT DIALOGEX 0, 0, 261, 160 IDD_ABOUT DIALOG DISCARDABLE 0, 0, 261, 160
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Emu48" CAPTION "About Emu48"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
@ -171,14 +196,14 @@ 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 © 2001 Sébastien Carlier && Christoph Gießelink", LTEXT "Copyright © 2002 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, 209 IDD_SETTINGS DIALOG DISCARDABLE 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" FONT 8, "MS Sans Serif"
@ -233,7 +258,7 @@ BEGIN
PUSHBUTTON "V",IDC_UPDATE,115,17,10,14 PUSHBUTTON "V",IDC_UPDATE,115,17,10,14
END END
IDD_KMLLOG DIALOGEX 0, 0, 301, 167 IDD_KMLLOG DIALOG DISCARDABLE 0, 0, 301, 167
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "KML Script Compilation Result" CAPTION "KML Script Compilation Result"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
@ -251,7 +276,7 @@ BEGIN
WS_BORDER | WS_VSCROLL | NOT WS_TABSTOP,WS_EX_CLIENTEDGE WS_BORDER | WS_VSCROLL | NOT WS_TABSTOP,WS_EX_CLIENTEDGE
END END
IDD_DISASM DIALOGEX 0, 0, 255, 165 IDD_DISASM DIALOG DISCARDABLE 0, 0, 255, 165
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Disassembler" CAPTION "Disassembler"
FONT 8, "Courier New" FONT 8, "Courier New"
@ -277,7 +302,7 @@ BEGIN
WS_TABSTOP,WS_EX_NOPARENTNOTIFY WS_TABSTOP,WS_EX_NOPARENTNOTIFY
END END
IDD_DEBUG DIALOGEX 0, 0, 279, 269 IDD_DEBUG DIALOG DISCARDABLE 0, 0, 279, 269
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
@ -372,8 +397,8 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "New Value" CAPTION "New Value"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
BEGIN BEGIN
LTEXT "New value (hexdezimal):",IDC_STATIC,8,9,81,8 LTEXT "New value (hexadecimal):",IDC_STATIC,8,9,81,8
EDITTEXT IDC_NEWVALUE,91,7,77,12,ES_AUTOHSCROLL EDITTEXT IDC_NEWVALUE,93,7,75,12,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,21,29,50,14 DEFPUSHBUTTON "OK",IDOK,21,29,50,14
PUSHBUTTON "Cancel",IDCANCEL,103,29,50,14 PUSHBUTTON "Cancel",IDCANCEL,103,29,50,14
END END
@ -383,8 +408,8 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Enter Address" CAPTION "Enter Address"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
BEGIN BEGIN
LTEXT "Enter address (hexdezimal):",IDC_STATIC,8,9,90,8 LTEXT "Enter address (hexadecimal):",IDC_STATIC,8,9,93,8
EDITTEXT IDC_ENTERADR,106,7,43,12,ES_AUTOHSCROLL EDITTEXT IDC_ENTERADR,105,7,44,12,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,14,29,50,14 DEFPUSHBUTTON "OK",IDOK,14,29,50,14
PUSHBUTTON "Cancel",IDCANCEL,92,29,50,14 PUSHBUTTON "Cancel",IDCANCEL,92,29,50,14
END END
@ -394,8 +419,8 @@ STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Enter Breakpoint" CAPTION "Enter Breakpoint"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
BEGIN BEGIN
LTEXT "Enter breakpoint (hexdezimal):",IDC_STATIC,8,9,96,8 LTEXT "Enter breakpoint (hexadecimal):",IDC_STATIC,8,9,99,8
EDITTEXT IDC_ENTERADR,110,7,39,12,ES_AUTOHSCROLL EDITTEXT IDC_ENTERADR,112,7,37,12,ES_AUTOHSCROLL
CONTROL "&Code",IDC_BPCODE,"Button",BS_AUTORADIOBUTTON | CONTROL "&Code",IDC_BPCODE,"Button",BS_AUTORADIOBUTTON |
WS_GROUP | WS_TABSTOP,17,24,33,10 WS_GROUP | WS_TABSTOP,17,24,33,10
CONTROL "R&PL",IDC_BPRPL,"Button",BS_AUTORADIOBUTTON,17,50,30,10 CONTROL "R&PL",IDC_BPRPL,"Button",BS_AUTORADIOBUTTON,17,50,30,10
@ -409,7 +434,7 @@ BEGIN
PUSHBUTTON "Cancel",IDCANCEL,92,65,50,14 PUSHBUTTON "Cancel",IDCANCEL,92,65,50,14
END END
IDD_INSTRUCTIONS DIALOGEX 0, 0, 186, 169 IDD_INSTRUCTIONS DIALOG DISCARDABLE 0, 0, 186, 169
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Last Instructions" CAPTION "Last Instructions"
FONT 8, "Courier New" FONT 8, "Courier New"
@ -438,7 +463,6 @@ IDR_DEBUG_TOOLBAR BITMAP MOVEABLE PURE "dbgtool.bmp"
// Toolbar // Toolbar
// //
#if 0 #if 0
// with VC++, this definition would be possible: // with VC++, this definition would be possible:
@ -460,7 +484,7 @@ END
#else #else
// winres does not recognize TOOLBAR, so this workaround is used: // windres does not recognize TOOLBAR, so this workaround is used:
IDR_DEBUG_TOOLBAR 241 DISCARDABLE IDR_DEBUG_TOOLBAR 241 DISCARDABLE
BEGIN BEGIN
@ -490,8 +514,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,2,5,0 FILEVERSION 1,3,0,0
PRODUCTVERSION 1,2,5,0 PRODUCTVERSION 1,3,0,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -508,12 +532,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Sebastien Carlier & Christoph Gießelink\0" VALUE "CompanyName", "Sebastien Carlier & Christoph Gießelink\0"
VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0" VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0"
VALUE "FileVersion", "1, 2, 5, 0\0" VALUE "FileVersion", "1, 3, 0, 0\0"
VALUE "InternalName", "Emu48\0" VALUE "InternalName", "Emu48\0"
VALUE "LegalCopyright", "Copyright © 2001\0" VALUE "LegalCopyright", "Copyright © 2002\0"
VALUE "OriginalFilename", "Emu48.exe\0" VALUE "OriginalFilename", "Emu48.exe\0"
VALUE "ProductName", "Emu48\0" VALUE "ProductName", "Emu48\0"
VALUE "ProductVersion", "1, 2, 5, 0\0" VALUE "ProductVersion", "1, 3, 0, 0\0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
@ -615,6 +639,7 @@ BEGIN
POPUP "&Info" POPUP "&Info"
BEGIN BEGIN
MENUITEM "&Last Instructions...", ID_INFO_LASTINSTRUCTIONS MENUITEM "&Last Instructions...", ID_INFO_LASTINSTRUCTIONS
MENUITEM "&Write Only Registers...", ID_INFO_WRITEONLYREG
END END
END END
@ -639,7 +664,31 @@ BEGIN
MENUITEM "Go to D&1", ID_DEBUG_MEM_GOD1 MENUITEM "Go to D&1", ID_DEBUG_MEM_GOD1
MENUITEM "Go to &Stack", ID_DEBUG_MEM_GOSTACK MENUITEM "Go to &Stack", ID_DEBUG_MEM_GOSTACK
MENUITEM SEPARATOR MENUITEM SEPARATOR
MENUITEM "Find...\tF", ID_DEBUG_MEM_FIND MENUITEM "&Find...\tF", ID_DEBUG_MEM_FIND
MENUITEM SEPARATOR
POPUP "&Mapping"
BEGIN
MENUITEM "Map", ID_DEBUG_MEM_MAP
MENUITEM SEPARATOR
MENUITEM "NCE1", ID_DEBUG_MEM_NCE1
, GRAYED
MENUITEM "NCE2", ID_DEBUG_MEM_NCE2
, GRAYED
MENUITEM "CE1", ID_DEBUG_MEM_CE1, GRAYED
MENUITEM "CE2", ID_DEBUG_MEM_CE2, GRAYED
MENUITEM "NCE3", ID_DEBUG_MEM_NCE3
, GRAYED
END
END
END
IDR_DEBUG_STACK MENU DISCARDABLE
BEGIN
POPUP ""
BEGIN
MENUITEM "&Push", ID_DEBUG_STACK_PUSH
MENUITEM "P&op", ID_DEBUG_STACK_POP
MENUITEM "&Modify", ID_DEBUG_STACK_MODIFY
END END
END END
@ -688,6 +737,14 @@ BEGIN
ID_BREAKPOINTS_CODEEDIT "Breakpoint List" ID_BREAKPOINTS_CODEEDIT "Breakpoint List"
END END
/////////////////////////////////////////////////////////////////////////////
//
// Manifest
//
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "Emu48.xml"
#endif // French (France) resources #endif // French (France) resources
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////

View file

@ -8,10 +8,8 @@ LD=gcc
CFLAGS= -Wall -Wno-missing-braces -Wno-format -Wno-uninitialized -O3 CFLAGS= -Wall -Wno-missing-braces -Wno-format -Wno-uninitialized -O3
# Things we need around to compile successfully # Things we need around to compile successfully
# I wonder why we need this _WIN32_IE definition, should take the
# default from the headers, but take a look and win32api 0.5's commctrl.h
DEFINES= -D_TCHAR=TCHAR -DIDC_STATIC=-1 -D_WIN32_IE=0x0300 DEFINES= -D_TCHAR=TCHAR -DIDC_STATIC=-1
LDFLAGS= -s -mwindows LDFLAGS= -s -mwindows

View file

@ -2,36 +2,27 @@
// PCH.H (MinGW version) // PCH.H (MinGW version)
// //
#define _WIN32_IE 0x0200
#include <windows.h> #include <windows.h>
#include <tchar.h> #include <tchar.h>
#include <shellapi.h> #include <shellapi.h>
#include <commctrl.h> #include <commctrl.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> // for functions missing in stdlib.h #include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <direct.h> #include <direct.h>
// #include <crtdbg.h> // missing file // #include <crtdbg.h> // missing file
#define _ASSERT(a) // normally defined in missing crtdbg.h #define _ASSERT(a) // normally defined in missing CRTDBG.H
#if defined POINTSTOPOINT // wrong implemented, so new correct definition #if defined POINTSTOPOINT // wrong implementation, so new correct definition
#undef POINTSTOPOINT #undef POINTSTOPOINT // fixed in w32api-1.2, but because of so many old versions...
#define POINTSTOPOINT(pt, pts) \ #define POINTSTOPOINT(pt, pts) \
{ (pt).x = (LONG)(SHORT)LOWORD(*(LONG*)&pts); \ { (pt).x = (LONG)(SHORT)LOWORD(*(LONG*)&pts); \
(pt).y = (LONG)(SHORT)HIWORD(*(LONG*)&pts); } (pt).y = (LONG)(SHORT)HIWORD(*(LONG*)&pts); }
#endif #endif
#if !defined TTN_GETDISPINFOA // missing #if !defined TTN_GETDISPINFO // missing in COMMCTRL.H
#define TTN_GETDISPINFOA (TTN_FIRST - 0) #define TTN_GETDISPINFO TTN_NEEDTEXT
#endif
#if !defined TTN_GETDISPINFOW // missing
#define TTN_GETDISPINFOW (TTN_FIRST - 10)
#endif
#if !defined TTN_GETDISPINFO // missing
#ifdef UNICODE
#define TTN_GETDISPINFO TTN_GETDISPINFOW
#else
#define TTN_GETDISPINFO TTN_GETDISPINFOA
#endif
#endif #endif

View file

@ -4,16 +4,18 @@
Emu48 is normally compiled with the Microsoft Visual C++ V6.0 compiler. An Emu48 is normally compiled with the Microsoft Visual C++ V6.0 compiler. An
alternative is the GCC compiler from the GNU project. A great distribution alternative is the GCC compiler from the GNU project. A great distribution
of the compiler and the necessary file is MinGW at www.mingw.org. of the compiler and the necessary files is MinGW at www.mingw.org.
Emu48 was tested with the following MinGW file versions: Emu48 was tested with the following MinGW file versions:
libbfd-2.10.91-20010121.zip MinGW-1.1.tar.gz
binutils-2.10.91-20010114.zip
ld-2.10.91-20010126.zip and
gcc-2.95.2-3.zip
w32api-0.5.1.tar.gz MinGW-1.1.tar.gz
mingw-runtime-0.5-20010221.tar.gz w32api-1.2.tar.gz
mingw-runtime-1.2.tar.gz
Because of some inconsistences in the current MinGW distribution you have to Because of some inconsistences in the current MinGW distribution you have to
add the files of this archive to the actual Emu48 source files. add the files of this archive to the actual Emu48 source files.
@ -22,4 +24,4 @@ Many thanks to Pedro A. Arranda Guti
compatible. compatible.
04/21/01 (c) by Christoph Gießelink, cgiess@swol.de 03/19/02 (c) by Christoph Gießelink, cgiess@swol.de

172
sources/MkShared/MKSHARED.C Normal file
View file

@ -0,0 +1,172 @@
/*
* MkShared, (c) 2002 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 <tchar.h>
#include <crtdbg.h>
#include "resource.h"
#define _KB(n) (2*(n)*1024)
#define ARRAYSIZEOF(a) (sizeof(a) / sizeof(a[0]))
#define DEFAULTFILE "SHARED.BIN"
static VOID SetInformation(HWND hWnd,LPCTSTR strSize,LPCTSTR strNoOfPorts,LPCTSTR strPorts)
{
SetDlgItemText(hWnd,IDC_FILE_SIZE,strSize);
SetDlgItemText(hWnd,IDC_NO_OF_PORTS,strNoOfPorts);
SetDlgItemText(hWnd,IDC_PORT_NO,strPorts);
return;
}
static VOID WriteCardFile(LPCTSTR strFilename,INT nBlocks)
{
HANDLE hFile = CreateFile(strFilename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD dwWritten;
LPBYTE pbyBuffer = LocalAlloc(LPTR,_KB(1));
while (nBlocks--) WriteFile(hFile, pbyBuffer, _KB(1), &dwWritten, NULL);
LocalFree(pbyBuffer);
CloseHandle(hFile);
return;
}
return;
}
static LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static _TCHAR szFilename[256];
static WORD wSize;
HCURSOR hCursor;
switch (iMsg)
{
case WM_COMMAND:
switch (wParam)
{
case IDC_CARD32:
wSize = 32;
SetInformation(hWnd,_T("64kb"),_T("1"),_T("2"));
return 0;
case IDC_CARD128:
wSize = 128;
SetInformation(hWnd,_T("256kb"),_T("1"),_T("2"));
return 0;
case IDC_CARD256:
wSize = 256;
SetInformation(hWnd,_T("512kb"),_T("2"),_T("2,3"));
return 0;
case IDC_CARD512:
wSize = 512;
SetInformation(hWnd,_T("1mb"),_T("4"),_T("2 through 5"));
return 0;
case IDC_CARD1024:
wSize = 1024;
SetInformation(hWnd,_T("2mb"),_T("8"),_T("2 through 9"));
return 0;
case IDC_CARD2048:
wSize = 2048;
SetInformation(hWnd,_T("4mb"),_T("16"),_T("2 through 17"));
return 0;
case IDC_CARD4096:
wSize = 4096;
SetInformation(hWnd,_T("8mb"),_T("32"),_T("2 through 33"));
return 0;
case IDOK:
GetDlgItemText(hWnd,IDC_FILENAME,szFilename,ARRAYSIZEOF(szFilename));
hCursor = SetCursor(LoadCursor(NULL,IDC_WAIT));
WriteCardFile(szFilename,wSize); // create file
SetCursor(hCursor); // restore cursor
return 0;
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,iMsg,wParam,lParam);
}
INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrev,LPSTR lpszCmdLine,INT nCmdShow)
{
HWND hWnd;
MSG msg;
WNDCLASS wc;
// RECT rc;
HFONT hFont;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = DLGWINDOWEXTRA;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDI_MKSHARED));
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
wc.lpszMenuName = NULL;
wc.lpszClassName = _T("CMkShared");
RegisterClass(&wc);
hWnd = CreateDialog(hInst,MAKEINTRESOURCE(IDD_MAIN),0,NULL);
_ASSERT(hWnd);
#if 0
// center window
GetWindowRect(hWnd, &rc);
SetWindowPos(hWnd, HWND_TOP,
((GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2),
((GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 2),
0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
#endif
// initialization
hFont = CreateFont(20,0,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET,OUT_DEVICE_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,DEFAULT_PITCH|TMPF_TRUETYPE|FF_ROMAN,"Times New Roman");
_ASSERT(hFont);
SendDlgItemMessage(hWnd,IDC_STATIC_TITLE,WM_SETFONT,(WPARAM)hFont,MAKELPARAM(TRUE,0));
SetDlgItemText(hWnd,IDC_FILENAME,_T(DEFAULTFILE));
// set to 32kb
SendDlgItemMessage(hWnd,IDC_CARD32,BM_SETCHECK,1,0);
PostMessage(hWnd,WM_COMMAND,IDC_CARD32,0);
while(GetMessage(&msg,NULL,0,0))
{
if(!IsDialogMessage(hWnd,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
DeleteObject(hFont);
return msg.wParam;
UNREFERENCED_PARAMETER(hPrev);
UNREFERENCED_PARAMETER(lpszCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
}

View file

@ -0,0 +1,114 @@
# Microsoft Developer Studio Project File - Name="MKSHARED" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 5.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=MKSHARED - 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 "MKSHARED.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 "MKSHARED.MAK" CFG="MKSHARED - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "MKSHARED - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "MKSHARED - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE
# Begin Project
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "MKSHARED - 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 Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
# 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 /nologo /subsystem:windows /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 comctl32.lib /nologo /subsystem:windows /machine:I386
!ELSEIF "$(CFG)" == "MKSHARED - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "MKSHARED___"
# PROP BASE Intermediate_Dir "MKSHARED___"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\Debug"
# PROP Intermediate_Dir ".\Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
# 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 /nologo /subsystem:windows /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 comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "MKSHARED - Win32 Release"
# Name "MKSHARED - Win32 Debug"
# Begin Group "Source"
# PROP Default_Filter "*.c"
# Begin Source File
SOURCE=.\MKSHARED.C
# End Source File
# End Group
# Begin Group "Header"
# PROP Default_Filter "*.h"
# End Group
# Begin Group "Resource"
# PROP Default_Filter "*.rc"
# Begin Source File
SOURCE=.\MKSHARED.RC
# End Source File
# End Group
# Begin Source File
SOURCE=.\MKSHARED.ICO
# End Source File
# End Target
# End Project

View file

@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 5.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "MKSHARED"=.\MKSHARED.DSP - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,180 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// German (Germany) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
#ifdef _WIN32
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_MAIN DIALOG DISCARDABLE 15, 32, 164, 167
STYLE WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Create Emu48 Ram Card"
CLASS "CMkShared"
FONT 8, "MS Sans Serif"
BEGIN
ICON IDI_MKSHARED,IDC_STATIC,6,6,20,20
CTEXT "Emu48\nRam Card Creator",IDC_STATIC_TITLE,34,6,94,26,
NOT WS_GROUP
ICON IDI_MKSHARED,IDC_STATIC,137,6,20,20
GROUPBOX "Size",IDC_STATIC,6,30,90,53
CONTROL "32kb",IDC_CARD32,"Button",BS_AUTORADIOBUTTON | BS_RIGHT |
WS_GROUP | WS_TABSTOP,14,40,34,10
CONTROL "128kb",IDC_CARD128,"Button",BS_AUTORADIOBUTTON |
BS_RIGHT,14,50,34,10
CONTROL "256kb",IDC_CARD256,"Button",BS_AUTORADIOBUTTON |
BS_RIGHT,14,60,34,10
CONTROL "512kb",IDC_CARD512,"Button",BS_AUTORADIOBUTTON |
BS_RIGHT,14,70,34,10
CONTROL "1mb",IDC_CARD1024,"Button",BS_AUTORADIOBUTTON |
BS_RIGHT,60,40,26,10
CONTROL "2mb",IDC_CARD2048,"Button",BS_AUTORADIOBUTTON |
BS_RIGHT,60,50,26,10
CONTROL "4mb",IDC_CARD4096,"Button",BS_AUTORADIOBUTTON |
BS_RIGHT,60,60,26,10
GROUPBOX "Filename:",IDC_STATIC,6,86,152,28
EDITTEXT IDC_FILENAME,13,96,138,12,ES_AUTOHSCROLL
DEFPUSHBUTTON "Create",IDOK,108,50,50,14
GROUPBOX "File Information:",IDC_STATIC,6,118,152,43
LTEXT "Actual File Size:",IDC_STATIC,13,129,57,8,NOT WS_GROUP
LTEXT "Static",IDC_FILE_SIZE,72,129,79,8,NOT WS_GROUP
LTEXT "Number of Ports:",IDC_STATIC,13,138,57,8,NOT WS_GROUP
LTEXT "Static",IDC_NO_OF_PORTS,72,138,79,8,NOT WS_GROUP
LTEXT "Ports:",IDC_STATIC,13,147,57,8,NOT WS_GROUP
LTEXT "Static",IDC_PORT_NO,72,147,79,8,NOT WS_GROUP
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_MAIN, DIALOG
BEGIN
LEFTMARGIN, 6
RIGHTMARGIN, 158
TOPMARGIN, 6
BOTTOMMARGIN, 161
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_MKSHARED ICON DISCARDABLE "MKSHARED.ICO"
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,1,0,0
PRODUCTVERSION 1,1,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "00000000"
BEGIN
VALUE "CompanyName", "Christoph Gießelink\0"
VALUE "FileDescription", "HP48 RAM Card Creator for Emu48\0"
VALUE "FileVersion", "1, 1, 0, 0\0"
VALUE "InternalName", "MkShared\0"
VALUE "LegalCopyright", "Copyright © 2002\0"
VALUE "OriginalFilename", "MkShared.exe\0"
VALUE "ProductName", "MkShared\0"
VALUE "ProductVersion", "1, 1, 0, 0\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 0
END
END
#endif // !_MAC
#endif // German (Germany) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View file

@ -1,65 +0,0 @@
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
HANDLE hFile;
DWORD dwWritten;
UINT nSize;
DWORD nBlocks;
LPBYTE pbyBuffer;
UINT main(int argc, char *argv[])
{
if (argc != 3)
{
printf("Usage:\n\t%s <filename> <size_in_kb>\n", argv[0]);
return 1;
}
nSize = atoi(argv[2]);
switch (nSize)
{
case 32:
nBlocks = 16;
break;
case 128:
nBlocks = 64;
break;
case 256:
nBlocks = 128;
break;
case 512:
nBlocks = 256;
break;
case 1024:
nBlocks = 512;
break;
case 2048:
nBlocks = 1024;
break;
case 4096:
nBlocks = 2048;
break;
default:
puts("Error: Valid sizes are 32, 128, 256, 512, 1024, 2048 and 4096.\n");
return 0;
}
hFile = CreateFile(argv[1],GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("Cannot open file %s.\n", argv[1]);
return 1;
}
pbyBuffer = LocalAlloc(LPTR,4096);
while (nBlocks--) WriteFile(hFile, pbyBuffer, 4096, &dwWritten, NULL);
LocalFree(pbyBuffer);
CloseHandle(hFile);
printf("Done.");
return 0;
}

View file

@ -1,186 +0,0 @@
# Microsoft Developer Studio Generated NMAKE File, Format Version 40001
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
!IF "$(CFG)" == ""
CFG=MkShared - Win32 Debug
!MESSAGE No configuration specified. Defaulting to MkShared - Win32 Debug.
!ENDIF
!IF "$(CFG)" != "MkShared - Win32 Release" && "$(CFG)" !=\
"MkShared - Win32 Debug"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE on this makefile
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "MkShared.mak" CFG="MkShared - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "MkShared - Win32 Release" (based on\
"Win32 (x86) Console Application")
!MESSAGE "MkShared - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
!ERROR An invalid configuration is specified.
!ENDIF
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
################################################################################
# Begin Project
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "MkShared - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
OUTDIR=.\Release
INTDIR=.\Release
ALL : "$(OUTDIR)\MkShared.exe"
CLEAN :
-@erase ".\Release\MkShared.exe"
-@erase ".\Release\Main.obj"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c
CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
/Fp"$(INTDIR)/MkShared.pch" /YX /Fo"$(INTDIR)/" /c
CPP_OBJS=.\Release/
CPP_SBRS=
# ADD BASE RSC /l 0x40c /d "NDEBUG"
# ADD RSC /l 0x40c /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
BSC32_FLAGS=/nologo /o"$(OUTDIR)/MkShared.bsc"
BSC32_SBRS=
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib /nologo /subsystem:console /machine:I386
LINK32_FLAGS=kernel32.lib /nologo /subsystem:console /incremental:no\
/pdb:"$(OUTDIR)/MkShared.pdb" /machine:I386 /out:"$(OUTDIR)/MkShared.exe"
LINK32_OBJS= \
"$(INTDIR)/Main.obj"
"$(OUTDIR)\MkShared.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "MkShared - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
OUTDIR=.\Debug
INTDIR=.\Debug
ALL : "$(OUTDIR)\MkShared.exe"
CLEAN :
-@erase ".\Debug\MkShared.exe"
-@erase ".\Debug\Main.obj"
-@erase ".\Debug\MkShared.ilk"
-@erase ".\Debug\MkShared.pdb"
-@erase ".\Debug\vc40.pdb"
-@erase ".\Debug\vc40.idb"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
/Fp"$(INTDIR)/MkShared.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c
CPP_OBJS=.\Debug/
CPP_SBRS=
# ADD BASE RSC /l 0x40c /d "_DEBUG"
# ADD RSC /l 0x40c /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
BSC32_FLAGS=/nologo /o"$(OUTDIR)/MkShared.bsc"
BSC32_SBRS=
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:I386
# ADD LINK32 kernel32.lib /nologo /subsystem:console /debug /machine:I386
LINK32_FLAGS=kernel32.lib /nologo /subsystem:console /incremental:yes\
/pdb:"$(OUTDIR)/MkShared.pdb" /debug /machine:I386\
/out:"$(OUTDIR)/MkShared.exe"
LINK32_OBJS= \
"$(INTDIR)/Main.obj"
"$(OUTDIR)\MkShared.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ENDIF
.c{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
.cpp{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
.cxx{$(CPP_OBJS)}.obj:
$(CPP) $(CPP_PROJ) $<
.c{$(CPP_SBRS)}.sbr:
$(CPP) $(CPP_PROJ) $<
.cpp{$(CPP_SBRS)}.sbr:
$(CPP) $(CPP_PROJ) $<
.cxx{$(CPP_SBRS)}.sbr:
$(CPP) $(CPP_PROJ) $<
################################################################################
# Begin Target
# Name "MkShared - Win32 Release"
# Name "MkShared - Win32 Debug"
!IF "$(CFG)" == "MkShared - Win32 Release"
!ELSEIF "$(CFG)" == "MkShared - Win32 Debug"
!ENDIF
################################################################################
# Begin Source File
SOURCE=.\Main.c
"$(INTDIR)\Main.obj" : $(SOURCE) "$(INTDIR)"
# End Source File
# End Target
# End Project
################################################################################

Binary file not shown.

View file

@ -0,0 +1,31 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by MKSHARED.RC
//
#define IDD_MAIN 100
#define IDI_MKSHARED 101
#define IDC_CARD32 1000
#define IDC_CARD128 1001
#define IDC_CARD256 1002
#define IDC_CARD512 1003
#define IDC_CARD1024 1004
#define IDC_CARD2048 1005
#define IDC_CARD4096 1006
#define IDC_STATIC_TITLE 1007
#define IDC_FILENAME 1008
#define IDC_FILE_SIZE 1009
#define IDC_NO_OF_PORTS 1010
#define IDC_PORT_NO 1011
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1012
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif