2017-08-18: Updated to version 57
Signed-off-by: Gwenhael Le Moine <gwenhael.le.moine@gmail.com>
This commit is contained in:
parent
5b61a0678e
commit
d048b845e4
41 changed files with 2197 additions and 6426 deletions
373
DEBUGGER.TXT
373
DEBUGGER.TXT
|
@ -1,373 +0,0 @@
|
|||
Debugger in Emu48/Tools/Debugger...
|
||||
-----------------------------------
|
||||
|
||||
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.
|
||||
|
||||
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.) System Menu / Debugger Settings
|
||||
|
||||
This is the configuration dialog for the debugger.
|
||||
|
||||
In the "Disassembler" section you can switch between HP and Class Mnemonics for the disassembler. This switch is exactly the same like in the main Settings dialog.
|
||||
|
||||
In the "Symbolic" section you can setup the debugger for symbolic debugging. Therefore the debugger needs a reference file. The reference file must contain a table for converting an absolute address into a symbolic name. I decided to use the HP-TOOLS object files (file extension *.o) with the supported entries. These object files are usually provided by HP for the HP48 and HP49 series and are necessary for linking object files. In the case of older calculators you have to make them by your own. Using the object file for the linker as reference has two disadvantages. First such an object file has an assembler specific output format, in our case the debugger only understands the output format of HP SASM v3.x. Second, in some cases an entries has two or more different names and I cannot control which name is returned.
|
||||
|
||||
Example from ENTRIES.A (HP48 Supported ROM Entry Points)
|
||||
|
||||
=UNROT EQU #60FAC *
|
||||
=3UNROLL EQU #60FAC *
|
||||
=XYZ>ZXY EQU #60FAC *
|
||||
|
||||
My implementation returns the last name inside the linker object file to the chosen address.
|
||||
|
||||
If you don't have the linker object file, the HP28S entry point list for example is only distributed as assembler source file SUPROM28.A, you can simply generate it with
|
||||
|
||||
sasm -N SUPROM28.A
|
||||
|
||||
- Enable
|
||||
|
||||
With an unchecked Enable check box you can disable the symbolic debugging without removing the reference file.
|
||||
|
||||
- Model
|
||||
|
||||
Each calculator model needs his own symbol reference file. The given models exactly corresponds to the one used in the KML script. When you opening the settings dialog automatically the actual model is chosen in the combo box. You can switch to all other possible calculator models to enter the corresponding reference files. When you exit the dialog with the Ok button all filenames are saved.
|
||||
|
||||
- Edit field
|
||||
|
||||
The edit field must contain the filename to the model specific symbol reference file which is chosen by the combo box.
|
||||
|
||||
|
||||
2.) Menu Debug
|
||||
|
||||
- Run F5
|
||||
|
||||
Continue calculator emulation under debugger control. The emulation will stop at a breakpoint. Please remember that the emulation speed is slower than without debugger control.
|
||||
|
||||
- Run to Cursor F6
|
||||
|
||||
Execute program until address at cursor position is reached. Breakpoints are still active and may stop execution before.
|
||||
|
||||
- Step Into F7
|
||||
|
||||
Execute one code instruction.
|
||||
|
||||
- Step Over F8
|
||||
|
||||
Execute a GOSUB, GOSUBL or GOSBVL as one instruction. Normally the instruction cursor will set to the position behind the GOSUB instruction.
|
||||
|
||||
But this makes trouble in the following code part:
|
||||
|
||||
GOSUB +
|
||||
NIBASC /Hello world/
|
||||
+ C=RSTK
|
||||
|
||||
The program counter will never reach the address behind the GOSUB instruction. The debugger solve this problem by breaking the emulation when the stack has the same level before the GOSUB instruction. In this example the single step execution will continue after the C=RSTK instruction.
|
||||
|
||||
- Step Out F9
|
||||
|
||||
Continue the program until a RTI, RTN, RTNC, RTNCC, RTNNC, RTNSC, RTNSXN, RTNYES instruction is found above the current stack level.
|
||||
|
||||
At some code constructions (mostly used to save space on the hardware stack) like
|
||||
|
||||
C=RSTK
|
||||
PC=C
|
||||
|
||||
and
|
||||
|
||||
C=RSTK
|
||||
RSTK=C
|
||||
RTN
|
||||
|
||||
the stop address will be wrong. The problem in both code fragments is the C=RSTK opcode. In the first example there is no RTN instruction to stop. In the second one the C=RSTK instruction purge the original return address and then the RSTK=C instruction is interpreted as a GOSUB instruction.
|
||||
|
||||
In opposite the following code will work fine:
|
||||
|
||||
RSTK=C
|
||||
..
|
||||
code <- F9 was pressed here
|
||||
..
|
||||
GOSUB -
|
||||
C=RSTK
|
||||
RTN <- emulation will stop after this instruction
|
||||
- RTN
|
||||
|
||||
So be careful using the F9 key.
|
||||
|
||||
- Break F11
|
||||
|
||||
Stops the emulation at the current program counter position.
|
||||
|
||||
|
||||
3.) Menu Breakpoints
|
||||
|
||||
- Set Breakpoint F2
|
||||
|
||||
Toggle a code breakpoint at the cursor position in the Code window.
|
||||
|
||||
- Edit Breakpoints...
|
||||
|
||||
You get a sorted list of 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
|
||||
- "RPL" stop on the first opcode of the selected RPL address
|
||||
- "Memory Access" stop before reading or writing to the selected address
|
||||
- "Memory Read" stop before reading the selected address
|
||||
- "Memory Write" stop before writing to the selected address
|
||||
|
||||
With a left mouse button double click on a breakpoint you can toggle the check box inside. When you use the space key instead, on all selected breakpoints the check box is toggled.
|
||||
|
||||
- Clear All Breakpoints
|
||||
|
||||
Clear all address specific breakpoints.
|
||||
|
||||
- NOP3 Code Breakpoints
|
||||
|
||||
What are NOP3 code breakpoints? As you know user programs are loaded somewhere in memory and can be moved after a garbage collection. So it's very difficult to break a user program at a hard set breakpoint with F2. To solve this problem the debugger will stop emulation at a NOP3 opcode. So you can easily add a NOP3 command into your sources to force a break condition. To enable this you have to check this item.
|
||||
|
||||
NOP3 and NOP3, what's the difference? The Saturn CPU has no NOP command, so NOP3 is an opcode that is three nibbles long and doesn't change a register. In the HP SASM.DOC document two different opcodes are defined for NOP3:
|
||||
|
||||
Opcode 820 for HST=0 0
|
||||
|
||||
and
|
||||
|
||||
Opcode 420 for GOC + (next line)
|
||||
|
||||
In the assembler of the HPTOOLS 3.x package NOP3 is defined as opcode 820. The advantage of the opcode is that the execution time is always the same, independent from the carry flag. This code is used in the HP48 ROM as well. So I decided to use the GOC opcode for a code breakpoint condition.
|
||||
|
||||
A short example how to use a NOP3 Code breakpoint:
|
||||
|
||||
ASSEMBLE
|
||||
NIBASC /HPHP48-E/
|
||||
|
||||
BREAK MACRO
|
||||
CON(3) #024 NOP3
|
||||
ENDM
|
||||
|
||||
RPL
|
||||
CODE
|
||||
BREAK code breakpoint
|
||||
|
||||
GOSBVL =SAVPTR save register
|
||||
|
||||
GOSUB + problem for step over
|
||||
NIBASC /Hello world/
|
||||
+ C=RSTK
|
||||
|
||||
GOVLNG =GETPTRLOOP
|
||||
ENDCODE
|
||||
|
||||
- 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 address CODE breakpoints instead please.
|
||||
|
||||
- RPL Breakpoints
|
||||
|
||||
If this item is checked, the debugger stops program execution on every instruction called after a PC=(A) or PC=(C) opcode. This is normally the begin of a new RPL command. RPL breakpoints use a "-R" marker instead of the assembler "->" PC position marker.
|
||||
|
||||
|
||||
4.) Menu Interrupts
|
||||
|
||||
- Step Over Interrupts
|
||||
|
||||
If this item is checked, interrupt handler code will be skipped. This option is useful when you don't want to debug the interrupt handler. But be careful, when you disable the interrupts all code until interrupt enable belong to the interrupt handler code and 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.
|
||||
|
||||
|
||||
5.) Menu Info
|
||||
|
||||
- Last Instructions...
|
||||
|
||||
This is a short viewer for the last 255 executed CPU addresses. The disassembled opcode maybe wrong, because only the CPU address of each command was saved and memory mapping may have changed meanwhile. In the "Last Instructions" dialog you can copy selected lines to the clipboard or clear this list.
|
||||
|
||||
- Profiler...
|
||||
|
||||
This opens a small toolbox window which shows the number of CPU cycles and the corresponding execution time of the instruction sequence between the last two breakpoints. The CPU cycles are only approximate values, the real cycles are depending mostly on the used ROM to Saturn CPU core interface.
|
||||
|
||||
- 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.
|
||||
|
||||
|
||||
6.) Code window
|
||||
|
||||
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.
|
||||
|
||||
Context menu pressing the right mouse button:
|
||||
|
||||
- Go to address... G
|
||||
|
||||
Moves the cursor to the specified code address. Therefore you can enter a hexadecimal number or the symbolic reference name.
|
||||
|
||||
- Go to PC
|
||||
|
||||
Sets the cursor to the actual position of the PC.
|
||||
|
||||
- Set breakpoint F2
|
||||
|
||||
Toggle a code breakpoint at the cursor position in the Code window.
|
||||
|
||||
- Set PC to selection
|
||||
|
||||
Set the PC to the cursor position. Be careful with this command, you change the execution order of the commands!
|
||||
|
||||
- Find
|
||||
|
||||
Search in the mapped CPU address area for an address which contain a PCO (Primitive Code Object) header. The disassembled code of this address is shown in the Code window.
|
||||
|
||||
- Previous PCO
|
||||
|
||||
Search for a PCO before the address shown in the first line of the Code window.
|
||||
|
||||
- Next PCO
|
||||
|
||||
Search for a PCO behind the address shown in the first line of the Code window.
|
||||
|
||||
|
||||
7.) Register window
|
||||
|
||||
Here you can see the actual contents of the CPU registers. The values are only updated at a program execution stop. All changed CPU registers are highlighted.
|
||||
|
||||
With the left mouse button you change the content of the register. On bit registers, like CY and Mode, the state change immediately without any request.
|
||||
|
||||
|
||||
8.) Memory window
|
||||
|
||||
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, the + and - keys change the memory position by one nibble under the cursor. 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:
|
||||
|
||||
- Go to address... G
|
||||
|
||||
Moves the cursor to the specified memory address. Therefore you can enter a hexadecimal number or the symbolic reference name.
|
||||
|
||||
- Go to PC
|
||||
|
||||
Sets the cursor to the actual position of the PC.
|
||||
|
||||
- Go to D0
|
||||
|
||||
Sets the cursor to the actual position of the D0 register.
|
||||
|
||||
- Go to D1
|
||||
|
||||
Sets the cursor to the actual position of the D1 register.
|
||||
|
||||
- Go to Stack
|
||||
|
||||
Sets the cursor to the return address placed in the top level of the stack.
|
||||
|
||||
- Follow
|
||||
|
||||
Follow is a Pop-up menu to change the address behavior of the memory window. Normally the address of the memory window is static and only change by entering a new address. With Follow the memory window view follow the content of a selected address or register. In follow mode the memory window is only updated after an emulation step.
|
||||
|
||||
- Follow none
|
||||
|
||||
This is the default mode. The address of the memory window is static.
|
||||
|
||||
- Follow Address Content
|
||||
|
||||
This is a special mode of indirect addressing. You can specify an address which content will we interpreted as memory pointer. The memory window follow this memory pointer.
|
||||
|
||||
- Follow Register PC/D0/D1
|
||||
|
||||
The Memory window follow the content of the selected register.
|
||||
|
||||
- Find... F
|
||||
|
||||
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. If the data sequence is found the Memory window and an opened "RPL Object Viewer" window will be updated.
|
||||
|
||||
With the button "Previous" you can search for the previous and with the button "Next" you can search for the next occurrence of the data sequence.
|
||||
|
||||
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
|
||||
|
||||
- Load Memory Data...
|
||||
|
||||
The "Load Memory Data" dialog box allows loading memory dump files to the specified address inside the Saturn address area. The specified address must point to RAM, writing into ROM areas isn't possible. The memory dump file must be in packed data format, meaning each byte in file contain two Saturn data nibbles with the low nibble containing the even and the high nibble the following odd address. The disadvantage of packed files is that you cannot load memory files with an odd number of data nibbles, but the advantage is that you can directly load an assembler output to memory.
|
||||
|
||||
- Save Memory Data...
|
||||
|
||||
The "Save Memory Data" dialog box allows saving the data of the specified Saturn address area into a memory dump file. The memory dump file contain the data in packed data format, meaning each byte in file contain two Saturn data nibbles with the low nibble containing the even and the high nibble the following odd address.
|
||||
|
||||
- RPL Object Viewer...
|
||||
|
||||
This opens a small toolbox window showing the decompiled RPL object in the selected memory map mode at the memory address marked by the cursor. If the toolbox window is already open the content will be updated. There's a problem if you want to select an address inside the marked two addresses. The easiest way to switch the address is the use of the + and - keys changing the memory position by one nibble under the cursor.
|
||||
|
||||
|
||||
9.) 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.
|
||||
|
||||
Context menu pressing the right mouse button:
|
||||
|
||||
- Push
|
||||
|
||||
Push a new element before the current selection onto the stack.
|
||||
|
||||
- Pop
|
||||
|
||||
Pop the selected element from the stack.
|
||||
|
||||
- Modify
|
||||
|
||||
Modifies the stack content of the current selection.
|
||||
|
||||
|
||||
10.) MMU window
|
||||
|
||||
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
|
||||
|
||||
LC(5) #C0000 128KB size
|
||||
CONFIG
|
||||
LC(5) #98765 start address of module
|
||||
CONFIG
|
||||
|
||||
will config a 128KB module at address #80000 and not at the given address. So the MMU viewer will show you the address #80000.
|
||||
|
||||
|
||||
11.) Miscellaneous window
|
||||
|
||||
The Miscellaneous window show you the internal state of the interrupt flag, the 1ms keyboard handler and the contents of the Bank Switcher latch. The Bank Switcher item is only enabled on calculators with a latch inside. You see the loaded value of the address lines A6-A0. You have to ignore the last bit (A0), because it isn't wired to the six bit latch.
|
||||
|
||||
You can change the values by pressing the left mouse button over the old content.
|
||||
|
||||
|
||||
01/09/13 (c) by Christoph Gießelink
|
482
EMU48.TXT
482
EMU48.TXT
|
@ -1,482 +0,0 @@
|
|||
|
||||
|
||||
|
||||
Emu48 - A freeware HP38/39/40/48/49 Emulator
|
||||
for Windows 9x, ME, NT, 2000, XP, Vista and 7
|
||||
|
||||
|
||||
|
||||
********************
|
||||
* OPERATING SYSTEM *
|
||||
********************
|
||||
|
||||
This version of Emu48 should work with all Intel x86 and x64 platforms.
|
||||
|
||||
|
||||
****************
|
||||
* INSTALLATION *
|
||||
****************
|
||||
|
||||
Emu48 is distributed in 1 archive:
|
||||
- Emu48v15xSetup.zip All files and sources
|
||||
|
||||
To install Emu48, just start the executable file inside the Emu48v15xSetup.zip
|
||||
archive. The installer will guide you through the installation. When you first
|
||||
run Emu48, it will detect the directory in which you installed it, and will
|
||||
write its configuration to the registry HKCU\Software\Emu48. If you move the
|
||||
Emu48 directory to another place you have to change the directory path inside
|
||||
the "Choose Your KML Script" dialog.
|
||||
|
||||
You can also update your current version with the Service Packs:
|
||||
- E48BP5x.ZIP New EXE-File
|
||||
- E48SP5x.ZIP Sources of the Service Pack
|
||||
|
||||
Replace the original EXE file please.
|
||||
|
||||
|
||||
************************
|
||||
* YOU NEED A ROM IMAGE *
|
||||
************************
|
||||
|
||||
Emu48 needs an image of a calculator ROM to be able to run. Since fall 2000 the
|
||||
emulator ROM's for the HP38, 39, 40, 48 and 49 are freely available on different
|
||||
internet sites. Because there's no license for the distribution of the ROM
|
||||
images, they aren't included in the Emu48 package. You can still use the classic
|
||||
way extracting them from your own calculator. But in mostly all cases you have
|
||||
to convert the ROM files into the Emu48 ROM format.
|
||||
|
||||
- HP38:
|
||||
To upload the ROM of your HP38G, you will need a special aplet called "ROM
|
||||
UPLOAD", available at http://www.hpcalc.org/details.php?id=633. 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.
|
||||
|
||||
- HP39/40:
|
||||
To upload the ROM of your HP39G/HP40G, you will need a special aplet called "ROM
|
||||
UPLOAD", available at http://hp.giesselink.com/emu48.htm. Once you've uploaded
|
||||
the ROM, you have to convert it using the Rom2emu utility.
|
||||
|
||||
To do that, start a Command Prompt while running Windows, and type:
|
||||
Rom2emu <rom-file> ROM.39G
|
||||
|
||||
There's also a HP39G/HP40G beta ROM for emulators inside an old Emu48 package
|
||||
available at http://www.hpcalc.org/details.php?id=4272.
|
||||
|
||||
- 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. 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.hpcalc.org/details.php?id=3686
|
||||
ROMDump Wizard http://hp.giesselink.com/emu48.htm
|
||||
|
||||
- HP49G:
|
||||
There's no ROM download program available so far. But you can create a ROM image
|
||||
with the UPD49ROM tool available at http://hp.giesselink.com/emu48.htm and a ROM
|
||||
update file for the HP49G calculator available at
|
||||
http://www.hpcalc.org/hp49/pc/rom/. I suggested to use version 1.19-6
|
||||
(http://www.hpcalc.org/details.php?id=3240).
|
||||
|
||||
To create a HP49G ROM image file, start a Command Prompt while running Windows,
|
||||
and type:
|
||||
UPD49ROM -f hp49119-6.flash ROM.49G
|
||||
|
||||
This will create a HP49G ROM image file with an empty User Port 2.
|
||||
|
||||
|
||||
****************
|
||||
* HOW TO START *
|
||||
****************
|
||||
|
||||
When Emu48 is installed and you have put the ROM image(s), which must be in the
|
||||
Emu48 ROM format, into 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 or use the
|
||||
("...") button to start the directory browser.
|
||||
|
||||
Choose a KML script in the list box for your calculator ROM you put into Emu48's
|
||||
directory.
|
||||
|
||||
Several HP48 scripts are included in the Emu48 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 Rechlin's great HP archive
|
||||
http://www.hpcalc.org/
|
||||
|
||||
And if you are interested in writing new scripts, get the KML 2.0 documentation
|
||||
from Christoph's page at http://hp.giesselink.com/emu48.htm
|
||||
|
||||
Once you have selected a script, press OK to start the emulator. In most cases,
|
||||
when Emu48 crash after pressing the OK button, you forgot to convert the ROM
|
||||
image into the emulator format. While it's running, you can use the View/Change
|
||||
KML Script... command to change the visual aspect of Emu48.
|
||||
|
||||
|
||||
***************
|
||||
* KML SCRIPTS *
|
||||
***************
|
||||
|
||||
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.
|
||||
|
||||
Maybe you have to adjust the "Rom" filename in the "Global" section. This mostly
|
||||
happen with the HP49G ROM name. Some KML files use the name ROM.E49, that's the
|
||||
name of the emulator ROM file published by HP. But Emu48 state files for the
|
||||
HP49G have the same file extension, so the use of ROM.49G is preferred now.
|
||||
|
||||
|
||||
****************
|
||||
* 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 (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
|
||||
utility will allow you to create it.
|
||||
|
||||
To create a Port 2 RAM Card, call the program, select the RAM Card size, enter
|
||||
the card file name and press the 'Create' button. That's it. Please remember,
|
||||
this program replace the destination file without any request!
|
||||
|
||||
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 call 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) or press the "..." button
|
||||
for the file browser. If this field is disabled you have chosen the Port 2 file
|
||||
over the 2nd command line argument, so change the name there please.
|
||||
|
||||
The "Port 2 is Writeable" check box represents the actual read/write state of
|
||||
the Port 2 file. Changing the state will also change the state for the
|
||||
calculator by modifying the Read-Only attribute of the file.
|
||||
|
||||
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 checked, the first instance of Emu48 will give you both read
|
||||
and write access to this RAM card. If you start Emu48 in another instance, 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.
|
||||
|
||||
Please remember, all port configuration changes mostly behave like on the
|
||||
original calculator. This means when you do this changes with the emulated
|
||||
calculator on, it's the same like when you do this with a real calculator on. In
|
||||
many times, this depends on the current state of the calculator, this will work
|
||||
without any problems by doing an automatically calculator warmstart. But for the
|
||||
most secure way, switch off the emulated calculator first, please!
|
||||
|
||||
|
||||
***********************
|
||||
* FLASH ROM EMULATION *
|
||||
***********************
|
||||
|
||||
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
|
||||
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
|
||||
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 Stack" and "Paste Stack" in the "Edit" menu you're
|
||||
able to copy real and complex numbers and 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 (excepting the ROM and Port 2 content) 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 System RAM are rewritten
|
||||
with the actual time information.
|
||||
|
||||
|
||||
********************************
|
||||
* Registry HKCU\Software\Emu48 *
|
||||
********************************
|
||||
|
||||
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. If you move the Emu48 directory to another place, you have to adjust the
|
||||
variable 'Emu48Directory' in the [Files] section.
|
||||
|
||||
|
||||
************************
|
||||
* 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.
|
||||
|
||||
|
||||
*******************************
|
||||
* INFRARED PRINTER SIMULATION *
|
||||
*******************************
|
||||
|
||||
The emulator has the ability to print decoded data to a HP82240A/B printer
|
||||
simulation. The data transfer to the printer simulator is done over UDP. You can
|
||||
the define the IPv4 address and the port the printer simulator is listening.
|
||||
|
||||
|
||||
****************
|
||||
* 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.
|
||||
|
||||
|
||||
************
|
||||
* DEBUGGER *
|
||||
************
|
||||
|
||||
Emu48 has an integrated Saturn assembler debugger inside. For further
|
||||
information read the separated "Debugger.txt" documentation please.
|
||||
|
||||
|
||||
**************
|
||||
* 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. In difference
|
||||
you can choose the stack level for the transfer in the DDE item field. Take care
|
||||
to transmit data only after the acknowledge of the last DDE transaction.
|
||||
|
||||
Technical data:
|
||||
|
||||
Servername: Emu48
|
||||
Topicname: Stack
|
||||
Item: 1 (stack level)
|
||||
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://hp.giesselink.com/index.htm to get more
|
||||
information please.
|
||||
|
||||
|
||||
***********
|
||||
* SUPPORT *
|
||||
***********
|
||||
|
||||
We cannot provide any individual support for Emu48. Information about Emu48 will
|
||||
be on the Emu48 Homepage or on the Emu48 FAQ at
|
||||
|
||||
http://hp.giesselink.com/index.htm
|
||||
|
||||
It's also a good idea to look at the Usenet forum comp.sys.hp48. Emu48 topics
|
||||
have discussed there in different threads for years now.
|
||||
|
||||
|
||||
***************
|
||||
* LEGAL STUFF *
|
||||
***************
|
||||
|
||||
Emu48 - An HP38/39/40/48/49 Emulator
|
||||
Copyright (C) 2013 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 *
|
||||
***************
|
||||
|
||||
Sebastien Carlier
|
||||
Christoph Giesselink
|
||||
|
||||
E-Mail:
|
||||
c dot giesselink at gmx dot de
|
||||
|
||||
Homepage:
|
||||
http://hp.giesselink.com/
|
|
@ -1,29 +0,0 @@
|
|||
Emu48 1.56+ (based on Emu48 1.58)
|
||||
|
||||
Emu48+ is a modified version of Emu48 to add support for the ARM-based
|
||||
calculators. It does not emulate the ARM CPU, but it enhances the
|
||||
Saturn emulation to more closely match the emulation provided by the
|
||||
Saturn emulator on the ARM-based calculators.
|
||||
|
||||
Emu48+ adds support for many of the Saturn+ instructions, including
|
||||
some of the BUSCC instructions, and it also adds support for the 80-line
|
||||
display used on the 49g+ and 50g.
|
||||
|
||||
At present, the additional calculators supported in Emu48+ are the
|
||||
49g+, 48gII (hardware revision 1), 50g, and 39g+.
|
||||
|
||||
To create KML scripts for the additional calculator models, use the
|
||||
following model codes:
|
||||
|
||||
39g+: Model "P"
|
||||
|
||||
49g+: Model "Q"
|
||||
|
||||
48gII: Model "2"
|
||||
|
||||
50g: Model "Q"
|
||||
Class 50
|
||||
|
||||
Most of the code that was changed in Emu48+ over Emu48 was provided by
|
||||
Cyrille de Brebisson of Hewlett-Packard.
|
||||
|
BIN
Emu48.dll
BIN
Emu48.dll
Binary file not shown.
BIN
Emu48.exe
BIN
Emu48.exe
Binary file not shown.
651
Emu48.htm
Normal file
651
Emu48.htm
Normal file
|
@ -0,0 +1,651 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Emu48 Manual</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta name="author" content="Christoph Giesselink">
|
||||
<meta name="description" content="Emulator Manual Emu48">
|
||||
<style type="text/css">
|
||||
<!--
|
||||
body { background-color:white;
|
||||
font-family:'Times New Roman',Times,Arial,serif;
|
||||
/* font-size:76%; */
|
||||
}
|
||||
p { font-size:1.0em; }
|
||||
h1 { color:red; font-size:1.5em; }
|
||||
h2 { color:red; font-size:1.5em; }
|
||||
h3 { color:red; font-size:1.1em; }
|
||||
#headline { margin-left: 20%; text-align:center; font-size:1.5em; }
|
||||
#navi { float: left; width: 15%; }
|
||||
#main { margin-left: 20%; }
|
||||
.nav1 { font-weight:bold; font-size:0.8em; }
|
||||
.nav2 { font-weight:normal; font-size:0.8em; }
|
||||
-->
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="headline">
|
||||
<p>Emu48 - A freeware HP38G/39G/40G/48SX/48GX/49G Emulator<br>
|
||||
for Windows 9x, ME, NT, 2000, XP, Vista, 7, 8 and 10</p>
|
||||
</div>
|
||||
<div id="navi">
|
||||
<p><a class="nav1" href="#s1">1. General</a></p>
|
||||
<p><a class="nav1" href="#s2">2. Acknowledgements</a></p>
|
||||
<p><a class="nav1" href="#s3">3. ROM Images</a></p>
|
||||
<p><a class="nav1" href="#s4">4. Installation</a></p>
|
||||
<p><a class="nav1" href="#s5">5. How to Start</a></p>
|
||||
<p><a class="nav1" href="#s6">6. Command Line</a></p>
|
||||
<p><a class="nav1" href="#s7">7. Virtual Keyboard</a></p>
|
||||
<p><a class="nav1" href="#s8">8. File Menu</a><br>
|
||||
<span class="nav2">
|
||||
<a href="#ss8.1">8.1 New...</a><br>
|
||||
<a href="#ss8.2">8.2 Open...</a><br>
|
||||
<a href="#ss8.3">8.3 Save</a><br>
|
||||
<a href="#ss8.4">8.4 Save As...</a><br>
|
||||
<a href="#ss8.5">8.5 Close</a><br>
|
||||
<a href="#ss8.6">8.6 Settings</a><br>
|
||||
<a href="#ss8.6.1">8.6.1 Settings General</a><br>
|
||||
<a href="#ss8.6.2">8.6.2 Settings Memory</a><br>
|
||||
<a href="#ss8.6.3">8.6.3 Settings Peripheral</a><br>
|
||||
<a href="#ss8.7">8.7 Exit</a>
|
||||
</span></p>
|
||||
<p><a class="nav1" href="#s9">9. Edit Menu</a><br>
|
||||
<span class="nav2">
|
||||
<a href="#ss9.1">9.1 Load Object...</a><br>
|
||||
<a href="#ss9.2">9.2 Save Object...</a><br>
|
||||
<a href="#ss9.3">9.3 Copy Screen</a><br>
|
||||
<a href="#ss9.4">9.4 Copy Stack</a><br>
|
||||
<a href="#ss9.5">9.5 Paste Stack</a><br>
|
||||
<a href="#ss9.6">9.6 Reset Calculator</a><br>
|
||||
<a href="#ss9.7">9.7 Backup</a><br>
|
||||
<a href="#ss9.7.1">9.7.1 Backup Save</a><br>
|
||||
<a href="#ss9.7.2">9.7.2 Backup Restore</a><br>
|
||||
<a href="#ss9.7.3">9.7.3 Backup Delete</a>
|
||||
</span></p>
|
||||
<p><a class="nav1" href="#s10">10. View Menu</a><br>
|
||||
<a class="nav2" href="#ss10.1">10.1 Change KML Script...</a></p>
|
||||
<p><a class="nav1" href="#s11">11. Tools Menu</a><br>
|
||||
<span class="nav2">
|
||||
<a href="#ss11.1">11.1 Disassembler...</a><br>
|
||||
<a href="#ss11.2">11.2 Debugger...</a><br>
|
||||
<a href="#ss11.3">11.3 Macro</a><br>
|
||||
<a href="#ss11.3.1">11.3.1 Macro Record...</a><br>
|
||||
<a href="#ss11.3.2">11.3.2 Macro Play...</a><br>
|
||||
<a href="#ss11.3.3">11.3.3 Macro Stop</a><br>
|
||||
<a href="#ss11.3.4">11.3.4 Macro Settings...</a>
|
||||
</span></p>
|
||||
<p><a class="nav1" href="#s12">12. Help Menu</a><br>
|
||||
<span class="nav2">
|
||||
<a href="#ss12.1">12.1 Help Topics</a><br>
|
||||
<a href="#ss12.2">12.2 About Emu48...</a>
|
||||
</span></p>
|
||||
<p><a class="nav1" href="#s13">13. DDE Server</a></p>
|
||||
<p><a class="nav1" href="#s14">14. Emu48+ Changes</a></p>
|
||||
<p><a class="nav1" href="#s15">15. License</a></p>
|
||||
</div>
|
||||
<div id="main">
|
||||
<h1><a name=s1>1. General</a></h1>
|
||||
<p>Emu48 is an emulator for the Hewlett Packard HP38G, HP39G,
|
||||
HP40G, HP48SX, HP48GX and HP49G calculator hardware. These calculators
|
||||
are based on the 1LT8 Clarke (HP48SX) and on the Yorke chip.</p>
|
||||
<h1><a name=s2>2. Acknowledgements</a></h1>
|
||||
<p>First of all a big thank to Sébastien Carlier for publishing
|
||||
Emu48 v1.0 under the GPL. Without this decision newer versions of the
|
||||
emulator wouldn't have been possible or ports to other similar
|
||||
calculators wouldn't have been made. Also a big thank to Jean-Yves
|
||||
Avenard for his technical assistance in the beginning. And finally I
|
||||
want to thank all the unnamed authors for publishing material about
|
||||
these calculators.</p>
|
||||
<h1><a name=s3>3. ROM Images</a></h1>
|
||||
<p>Emu48 needs an image of a calculator ROM to be able to run. ROM
|
||||
images are valid in a packed (even address lower nibble, odd address
|
||||
higher nibble) or unpacked (one nibble per byte with even address first)
|
||||
form.</p>
|
||||
<p>Since fall 2000 the emulator ROM's for the HP38, 39, 40, 48 and 49
|
||||
are freely available on different Internet sites. Because there's no
|
||||
license for the distribution of the ROM images, they aren't included
|
||||
in the Emu48 package. You can still use the classic way extracting
|
||||
them from your own calculator. But in mostly all cases you have to
|
||||
convert the ROM files into the Emu48 ROM format.</p>
|
||||
<ul>
|
||||
<li>HP38
|
||||
<p>To upload the ROM of your HP38G, you will need a special aplet
|
||||
called <a href="http://www.hpcalc.org/details.php?id=633">"ROM UPLOAD"</a>.
|
||||
Once you've uploaded the ROM, you have to convert it using the
|
||||
Convert utility.</p>
|
||||
<p>To do that, start a Command Prompt while running Windows, and
|
||||
type:</p>
|
||||
<blockquote>Convert <rom-file> ROM.38G</blockquote>
|
||||
<p>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.
|
||||
</p></li>
|
||||
<li>HP39/40
|
||||
<p>To upload the ROM of your HP39G/HP40G, you will need a special aplet
|
||||
called <a href="http://hp.giesselink.com/emu48.htm">"ROM UPLOAD"</a>.
|
||||
Once you've uploaded the ROM, you have to convert it using the Rom2emu utility.
|
||||
</p>
|
||||
<p>To do that, start a Command Prompt while running Windows, and
|
||||
type:</p>
|
||||
<blockquote>Rom2emu <rom-file> ROM.39G</blockquote>
|
||||
<p>There's also a HP39G/HP40G beta ROM for emulators inside an old
|
||||
<a href="http://www.hpcalc.org/details.php?id=4272">Emu48 package</a>.
|
||||
</p></li>
|
||||
<li>HP48
|
||||
<p>If you have already used another HP48 emulator, you can convert
|
||||
the ROM using the Convert utility.
|
||||
</p>
|
||||
<p>To do that, start a Command Prompt while running Windows, and
|
||||
type:</p>
|
||||
<blockquote>Convert <rom-file> ROM.48G</blockquote>
|
||||
<p>or</p>
|
||||
<blockquote>Convert <rom-file> ROM.48S</blockquote>
|
||||
<p>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.</p>
|
||||
<p>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. After the download you may have to convert your dump with
|
||||
the CONVERT utility into the Emu48 format.</p>
|
||||
<p>You can find the latest version of the ROM dump programs on:</p>
|
||||
<blockquote>
|
||||
ROMUPL.BIN <a href="http://www.hpcalc.org/details.php?id=3686">
|
||||
http://www.hpcalc.org/details.php?id=3686</a><br>
|
||||
ROMDump Wizard
|
||||
<a href="http://hp.giesselink.com/emu48.htm">
|
||||
http://hp.giesselink.com/emu48.htm</a>
|
||||
</blockquote></li>
|
||||
<li>HP49G
|
||||
<p>There's no ROM download program available so far. But you can
|
||||
create a ROM image with the
|
||||
<a href="http://hp.giesselink.com/emu48.htm">UPD49ROM tool</a>
|
||||
and a <a href="http://www.hpcalc.org/hp49/pc/rom/">
|
||||
ROM update file</a> for the HP49G calculator. I suggested to use
|
||||
<a href="http://www.hpcalc.org/details.php?id=3240">version 1.19-6</a>
|
||||
</p>
|
||||
<p>To create a HP49G ROM image file, start a Command Prompt while
|
||||
running Windows, and type:</p>
|
||||
<blockquote>UPD49ROM -f hp49119-6.flash ROM.49G</blockquote>
|
||||
<p>This will create a HP49G ROM image file with an empty User
|
||||
Port 2.</p></li>
|
||||
</ul>
|
||||
<h1><a name=s4>4. Installation</a></h1>
|
||||
<p>To install Emu48 you may use the installer package which contain,
|
||||
among the binaries, some HP48 KML scripts or just unzip the emulator
|
||||
and the required emulator skins from archives into an empty directory.
|
||||
Finally you have to copy your ROM images into this directory and
|
||||
adjust the ROM image name to the name used in the corresponding KML
|
||||
script. When you first run Emu48, it will detect the directory in
|
||||
which you installed it, and will write the configuration to the
|
||||
registry at <i>HKCU\Software\Emu48</i>.</p>
|
||||
<h1><a name=s5>5. How to Start</a></h1>
|
||||
<p>When Emu48 is installed and you have put valid KML scripts and the
|
||||
corresponding ROM image(s) into your Emu48 installation directory, you
|
||||
can start Emu48. You'll see a "Choose Your KML Script"
|
||||
box.</p>
|
||||
<p>KML scripts in fact define the visual aspect of Emu48, the behavior of
|
||||
the buttons, of the keyboard, ... It's a GREAT way to customize your copy
|
||||
of Emu48.</p>
|
||||
<p>Check that the path in the "Emu48 Directory" text area is
|
||||
correct. Modify it if the directory in which you installed Emu48 is not
|
||||
the directory displayed. Click the refresh button ("V") after
|
||||
modifying it to update the list box or use the ("...") button to
|
||||
start the directory browser.</p>
|
||||
<p>Choose a KML script in the list box for your calculator ROM you put
|
||||
into Emu48's directory.</p>
|
||||
<p>Several HP48 scripts are included in the Emu48 archive:</p>
|
||||
<ul>
|
||||
<li>Emu48's Default Faceplate for HP48G/GX</li>
|
||||
<li>Emu48's Default Faceplate for HP48S/SX
|
||||
<p>These two are simple scripts, good for 800x600 display
|
||||
resolution.</p></li>
|
||||
<li>Casey's Gx with Toolbar and Touch Screen</li>
|
||||
<li>Casey's Sx with Toolbar and Touch Screen
|
||||
<p>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!</p></li>
|
||||
<li>Floating buttons
|
||||
<p>This one looks really great.</p></li>
|
||||
<li>Small but realistic HP48 Gx
|
||||
<p>This one has been designed for small resolutions such as
|
||||
640x480.
|
||||
</p></li>
|
||||
</ul>
|
||||
<p>If you want other great scripts, visit Rechlin's great HP archive
|
||||
<a href="http://www.hpcalc.org/"></a></p>
|
||||
<p>And if you are interested in writing new scripts, get the KML 2.0
|
||||
documentation from <a href="http://hp.giesselink.com/emu48.htm">the
|
||||
authors Emu48 page</a>.</p>
|
||||
<p>Once you have selected a script, press OK to start the emulator. In
|
||||
most cases, when Emu48 crash after pressing the OK button, you are using
|
||||
an invalid ROM image. While it's running, you can use the View/Change KML
|
||||
Script... command to change the visual aspect of Emu48.</p>
|
||||
<h1><a name=s6>6. Command Line</a></h1>
|
||||
<p>The command line syntax is "<i>Emu48 [E48file [Port2file]]</i>".
|
||||
The first parameter sets the filename for the emulation data
|
||||
independent from the "LastDocument" setting, the second
|
||||
parameter the Port2 file. You're not able to set a Port 2 file without
|
||||
setting the emulation data file. The arguments are optional.</p>
|
||||
<h1><a name=s7>7. Virtual Keyboard</a></h1>
|
||||
<p>There are two ways to use the virtual keyboard on the emulated
|
||||
calculator:</p>
|
||||
<ol>
|
||||
<li><a href="#mouse">by Mouse</a></li>
|
||||
<li><a href="#keyboard">by PC keyboard</a></li>
|
||||
</ol>
|
||||
<p><a name=mouse></a>
|
||||
The easiest way to use the emulated calculator is using the mouse. The KML
|
||||
script define buttons with an area where mouse input is active. The mouse
|
||||
cursor change from an arrow to a hand cursor in these areas. The state of
|
||||
the virtual key follow the state of your left mouse button. When the mouse
|
||||
cursor leaves the virtual key area the virtual button automatically
|
||||
release. In some cases you need to press more than one key on the
|
||||
emulator. For these cases press the virtual key with the right mouse
|
||||
button. When you release the mouse button or leave the area of the virtual
|
||||
key, the key is still hold. To release all hold virtual buttons, just use
|
||||
the left mouse button again. A single release of a hold virtual key isn't
|
||||
possible.</p>
|
||||
<p><a name=keyboard></a>
|
||||
Another convenient way is using the PC keyboard. The KML script language
|
||||
support a large variety of commands to implement this feature. So keyboard
|
||||
usage depends on your used KML script and not on the emulator. Because of
|
||||
this it's impossible to say what's happen when you press a key on the PC
|
||||
keyboard. For further details read the KML 2.0 documentation mentioned
|
||||
before please.</p>
|
||||
<h1><a name=s8>8. File Menu</a></h1>
|
||||
<h2><a name=ss8.1>8.1 New...</a></h2>
|
||||
<p>Creates a new emulation session. You're asked for a new KML script
|
||||
where you can select the calculator type and skin to emulate.</p>
|
||||
<h2><a name=ss8.2>8.2 Open...</a></h2>
|
||||
<p>Opens an existing emulation session. The emulation continues at the
|
||||
same position where the loaded session was aborted. Loading emulation
|
||||
sessions made with a different ROM revision may <u>destroy</u> the memory
|
||||
content or may cause other unpredictable results.</p>
|
||||
<h2><a name=ss8.3>8.3 Save</a></h2>
|
||||
<p>Saves the current running session with the actual name.</p>
|
||||
<h2><a name=ss8.4>8.4 Save As...</a></h2>
|
||||
<p>Saves the current running session with a new name. You're also get in
|
||||
this dialog when you Exit a new session without a state file name.</p>
|
||||
<h2><a name=ss8.5>8.5 Close</a></h2>
|
||||
<p>Closes the current session without closing the emulator.</p>
|
||||
<h2><a name=ss8.6>8.6 Settings</a></h2>
|
||||
<p>This calls the Settings dialog. This dialog has three tabs:
|
||||
General, Memory and Peripheral.</p>
|
||||
<h3><a name=ss8.6.1>8.6.1 Settings General</a></h3>
|
||||
<h4>8.6.1.1 Section General</h4>
|
||||
<ul>
|
||||
<li><i>Authentic Calculator Speed</i>
|
||||
<p>When this option is checked, the emulation speed will be similar
|
||||
to the real calculator depending on the RATE control register
|
||||
content.</p></li>
|
||||
<li><i>Enable Virtual LCD Delay</i>
|
||||
<p>Try this option for a better 4 color gray scale display simulation
|
||||
output.</p></li>
|
||||
<li><i>Always On Top</i>
|
||||
<p>When this option is checked, the emulator window will always be the
|
||||
topmost one.</p></li>
|
||||
<li><i>Activation Follows Mouse</i>
|
||||
<p>This option enables a X-Mouse style windows activation. When the
|
||||
mouse is moved over the emulator window, the emulator is getting the
|
||||
focus and popping up into foreground.</p></li>
|
||||
<li><i>Single Instance</i>
|
||||
<p>When this option is checked, the program is only allowed to run in
|
||||
a single instance. If another running instance is detected, the detected
|
||||
instance is set into foreground as active window and get a request to
|
||||
change his state file to the given one by the current instance. Finally
|
||||
the current instance is terminated.</p></li>
|
||||
<li><i>Automatically Save Files</i>
|
||||
<p>When this option is checked, the current state file will automatically
|
||||
saved when you change to another state file, but not when you close the
|
||||
emulator program.</p></li>
|
||||
<li><i>Automatically Save Files On Exit</i>
|
||||
<p>When this option is checked, the current state file will be saved
|
||||
automatically at the end when the emulator program is closed.</p></li>
|
||||
<li><i>Show Load Object Warning</i>
|
||||
<p>When this option is checked, you'll get a warning message box when you
|
||||
try to load an object with the <i>Load Object...</i> menu command. If
|
||||
this option is unchecked, the warning will be skipped.</p></li>
|
||||
<li><i>Always Show KML Compilation Result</i>
|
||||
<p>When this option is checked, you see the results of the KML
|
||||
(Keyboard Macro Language) interpreter at every KML script load.</p></li>
|
||||
</ul>
|
||||
<h4>8.6.1.2 Section Style</h4>
|
||||
<ul>
|
||||
<li><i>Show Title</i>
|
||||
<p>When this option is checked, the window title bar is visible.</p></li>
|
||||
<li><i>Show Menu</i>
|
||||
<p>When this option is checked, the menu bar is enabled. If unchecked,
|
||||
the menu is accessible as context menu in the client area outside the
|
||||
calculator button definitions.</p></li>
|
||||
</ul>
|
||||
<h4>8.6.1.3 Section Disassembler</h4>
|
||||
<p>Choosing the assembler syntax:</p>
|
||||
<ul>
|
||||
<li><i>HP Mnemonics</i>
|
||||
<p>This is the standard syntax used by HP.</p></li>
|
||||
<li><i>Class Mnemonics</i>
|
||||
<p>Class (Clarke assembler) was written by Lutz Vieweg in 1991, at a time
|
||||
when HP had not published their own development tools. The syntax is very
|
||||
similar to the AG and STAR mnemonics used at this time. Especially
|
||||
published assembler programs written for the HP28S use the similar AG
|
||||
syntax.</p></li>
|
||||
</ul>
|
||||
<h3><a name=ss8.6.2>8.6.2 Settings Memory</a></h3>
|
||||
<h4>8.6.2.1 Section Memory Cards</h4>
|
||||
<ul>
|
||||
<li><i>Port 1 is Plugged</i>
|
||||
<p>When this option is checked, a 128 KB RAM card is emulated in card
|
||||
Port 1. The RAM card content is saved in the current emulator state
|
||||
file.</p></li>
|
||||
<li><i>Port 1 is Writeable</i>
|
||||
<p>When this option is checked, the RAM card in card Port 1 is
|
||||
writable else the card is Read-Only by simulating the card write
|
||||
protect switch.</p></li>
|
||||
<li><i>Port 2 is Shared</i>
|
||||
<p>When this option is unchecked, only the first instance of Emu48
|
||||
will allow you to use the RAM card in Port 2. When this option is
|
||||
checked, the first instance of Emu48 will give you both read and
|
||||
write access to this RAM card. If you start Emu48 in another
|
||||
instance, 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.</p></li>
|
||||
<li><i>Port 2 is Writeable</i>
|
||||
<p>This option represents the actual read/write state of the Port 2
|
||||
file. Changing the option will also change the state for the
|
||||
calculator by modifying the Read-Only attribute of the file.</p></li>
|
||||
<li><i>Port 2 File</i>
|
||||
<p>You can add a 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 one. To create a Port 2 RAM Card, call the
|
||||
program, select the RAM Card size, enter the card file name and press
|
||||
the 'Create' button. That's it. Please remember, this program replace
|
||||
the destination file without any request!</p>
|
||||
<p>If you already have a Port 2 card file in unpacked format, you
|
||||
have to copy the file into the emulator directory. If you choose a
|
||||
different directory you have to use a full path file name.</p>
|
||||
<p>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 4 MB RAM card. You always
|
||||
get the message "Warning: Invalid Card Data" at startup
|
||||
and Port 33 is inaccessible. This is not a bug of the emulator!</p>
|
||||
<p>When you have created or copied the file, enter the card file
|
||||
name into the Port 2 File edit box.</p>
|
||||
<p>Please remember, all port configuration changes mostly behave
|
||||
like on the original calculator. This means when you do this changes
|
||||
with the emulated calculator on, it's the same like when you do this
|
||||
with a real calculator on. In many times, this depends on the current
|
||||
state of the calculator, this will work without any problems by doing
|
||||
an automatically calculator warmstart. But for the most secure way,
|
||||
switch off the emulated calculator first, please!</p></li>
|
||||
</ul>
|
||||
<h3><a name=ss8.6.3>8.6.3 Settings Peripheral</a></h3>
|
||||
<h4>8.6.3.1 Section Sound</h4>
|
||||
<p>A new implementation of the sound engine made ROM patches for sound
|
||||
output obsolete. The new sound engine emulates the behavior of the beeper
|
||||
output ports and only work in connection with a sound card. Using the
|
||||
internal PC speaker isn't possible any more. The old beeper method with a
|
||||
ROM patch is still working but deprecated, it's strongly recommended to
|
||||
remove all beep patches from your current KML scripts to enable the new
|
||||
sound engine. The support of the old sound implementation by a ROM patch
|
||||
maybe removed in later versions of the emulator and remaining beep
|
||||
patches will corrupt the ROM with an illegal opcode then.
|
||||
</p>
|
||||
<p>
|
||||
For the sound generation the calculator must know his own CPU strobe
|
||||
frequency. On the real calculator the speed depends on various settings
|
||||
like component tolerances, actual temperature, humidity and other
|
||||
variables. The resulting speed is measured by the calculator firmware
|
||||
at a cold- or at a warmstart and stored in the =CSPEED variable. The
|
||||
content of this calculator variable has direct influence on the
|
||||
resulting frequency and duration. On the emulator the HP48SX CPU
|
||||
strobe frequency is set by the registry key
|
||||
<i>HKCU\Software\Emu48\Emulator\SXCycles</i>, for all other
|
||||
calculators at <i>HKCU\Software\Emu48\Emulator\GXCycles</i>.
|
||||
For some reasons the CPU cycles are only estimated and so the
|
||||
strobe frequency value in the registry is not the exact CPU strobe
|
||||
frequency of the calculator in Hz divided by 16384 like in the
|
||||
other emulators. Because older versions of the emulator were not
|
||||
able to measure the CPU strobe frequency properly or the strobe
|
||||
frequency registry content has been changed since the last
|
||||
measurement, the =CSPEED variable of this session file may contain
|
||||
a wrong frequency value. You easily may discover this by measuring
|
||||
the real duration of a 10s beep. Is the difference to 10s less
|
||||
than 1s everything is ok, if not, you should perform a
|
||||
<u style="color:red">warmstart</u> of the calculator in this
|
||||
session file. Alternatively you may execute a
|
||||
<a href=#ss9.6>Reset Calculator</a>. This recalls the measuring
|
||||
routine and save the result in the speed variable. Both restart
|
||||
variants purge the stack content!
|
||||
</p>
|
||||
<ul>
|
||||
<li><i>Volume</i>
|
||||
<p>The output volume can be selected with the Volume slider relative to
|
||||
the Master Volume control.
|
||||
</p></li>
|
||||
<li><i>Device</i>
|
||||
<p>By default the sound device is set to "Standard Audio", but
|
||||
you can also manually choose the output device. The device name is
|
||||
somehow cut since Window Vista, but the method of reading the device
|
||||
name is used for backwards compatibility to older versions of the
|
||||
Operating System. When you change the Standard Audio device in the
|
||||
Operating System settings dialog, the internal device numbering may
|
||||
change, and so the manually selected audio device.</p></li>
|
||||
</ul>
|
||||
<h4>8.6.3.2 Section Infrared Printer</h4>
|
||||
<p>The emulator has the ability to print data to a HP82240A/B printer
|
||||
simulation. The data transfer to the printer simulator is done over UDP.
|
||||
In this section you can the define the IPv4 address and the port the
|
||||
printer simulator is listening. A suitable HP82240B printer simulation can
|
||||
be found <a href="http://hp.giesselink.com/hp82240b.htm">here</a>.</p>
|
||||
<h4>8.6.3.3 Section Serial Ports</h4>
|
||||
<ul>
|
||||
<li><i>Wire</i>
|
||||
<p>In the Wire combo box you can select the COM port device connected
|
||||
to the wire port of the calculator.</p></li>
|
||||
<li><i>Ir</i>
|
||||
<p>In the Ir combo box you can select the COM port device connected
|
||||
to the IR port of the calculator. Please remember that the IR port
|
||||
only work with 2400 baud.</p></li>
|
||||
</ul>
|
||||
<h2><a name=ss8.7>8.7 Exit</a></h2>
|
||||
<p>Quit emulation. The default actions at finishing are defined in the
|
||||
<a href=#ss8.6>Settings</a> dialog. If the current session is
|
||||
"Untitled" you are asked for a session file name using the
|
||||
<a href="#ss8.4">Save As...</a> dialog. If you quit the emulator
|
||||
without a given filename, you're asked for choosing a KML script at
|
||||
next startup.</p>
|
||||
<h1><a name=s9>9. Edit Menu</a></h1>
|
||||
<h2><a name=ss9.1>9.1 Load Object...</a></h2>
|
||||
<p>This is only valid for the HP48SX, HP48GX and the HP49G emulation.
|
||||
You can load HP48 and HP49G binary objects to stack level 1. Therefore
|
||||
the object must begin with "HPHP48-x" for a HP48 or with
|
||||
"HPHP49-x" for a HP49G binary object where x can be any
|
||||
alphanumeric character. If the binary header isn't present, the object
|
||||
is loaded as string. Dropping HP objects over the emulator window will
|
||||
also load objects. Be sure that the emulator isn't busy before doing
|
||||
this.</p>
|
||||
<h2><a name=ss9.2>9.2 Save Object...</a></h2>
|
||||
<p>This is only valid for the HP48SX, HP48GX and the HP49G emulation.
|
||||
Save the current object in stack level 1 as binary object to disk.</p>
|
||||
<h2><a name=ss9.3>9.3 Copy Screen</a></h2>
|
||||
<p>Copy the screen content as bitmap to the clipboard.</p>
|
||||
<h2><a name=ss9.4>9.4 Copy Stack</a></h2>
|
||||
<p>This is only valid for the HP48SX, HP48GX and the HP49G emulation.</p>
|
||||
<p>Copy a "Real Number", "Complex Number" or
|
||||
"String" object in stack level 1 to the clipboard. On all
|
||||
other objects, the command will be ignored. This prevents sending
|
||||
binary objects to the clipboard.</p>
|
||||
<p>The decimal point (radix mark) of "Real Numbers" in the
|
||||
clipboard is equal to the calculator setting. This point maybe
|
||||
important when you try to paste the numbers into a program using the
|
||||
locale settings of the host operating system.</p>
|
||||
<h2><a name=ss9.5>9.5 Paste Stack</a></h2>
|
||||
<p>This is only valid for the HP48SX, HP48GX and the HP49G emulation.</p>
|
||||
<p>Paste the text field content of the clipboard to stack level 1 of
|
||||
the emulated calculator. If the clipboard content is representing a
|
||||
real number, the number will be saved as "Real Number"
|
||||
object. Is the content a complex number object, the number will be
|
||||
saved as "Complex Number" object, in all other cases as
|
||||
"String" object.</p>
|
||||
<p>To import "Real or Complex Numbers" from the clipboard,
|
||||
the decimal point (radix mark) of the clipboard and calculator
|
||||
<u>must</u> be equal. A real or complex number is only detected in the
|
||||
case of valid real number characters in the clipboard. Especially
|
||||
heading and tailing white spaces aren't valid number characters
|
||||
also.</p>
|
||||
<p>Complex numbers must be in the form <i>(a,b)</i> when using the
|
||||
point radix mark or in the form <i>(a;b)</i> when using the comma
|
||||
radix mark. The Cartesian or algebraic form <i>a+bi</i> is not
|
||||
supported.</p>
|
||||
<h2><a name=ss9.6>9.6 Reset Calculator</a></h2>
|
||||
<p>This emulates the Reset pin of the internal CPU.</p>
|
||||
<h2><a name=ss9.7>9.7 Backup</a></h2>
|
||||
<h3><a name=ss9.7.1>9.7.1 Backup Save</a></h3>
|
||||
<p>This saves the current emulator status into a backup slot. If the
|
||||
backup slot already contain data, it will be overwritten.</p>
|
||||
<h3><a name=ss9.7.2>9.7.2 Backup Restore</a></h3>
|
||||
<p>This restores a previous saved emulator status without request. If you
|
||||
changed the calculator model meanwhile, the emulator will switch back to
|
||||
the old model.</p>
|
||||
<h3><a name=ss9.7.3>9.7.3 Backup Delete</a></h3>
|
||||
<p>This deletes the data in the backup slot.</p>
|
||||
<h1><a name=s10>10. View Menu</a></h1>
|
||||
<h2><a name=ss10.1>10.1 Change KML Script...</a></h2>
|
||||
<p>This allows you to change the skin of the current emulated calculator.
|
||||
In opposite to the New... command you see only scripts emulating the same
|
||||
calculator model.</p>
|
||||
<h1><a name=s11>11. Tools Menu</a></h1>
|
||||
<h2><a name=ss11.1>11.1 Disassembler...</a></h2>
|
||||
<p>This is a simple disassembler.</p>
|
||||
<p>Enter the address to disassemble in hexadecimal into the "Address
|
||||
(HEX)" field and press <Return>. With the "Next Address"
|
||||
button the next opcode is disassembled. With the "Copy Data" button
|
||||
you can copy all selected lines inside the list box to the clipboard.</p>
|
||||
<h2><a name=ss11.2>11.2 Debugger...</a></h2>
|
||||
<p>The assembler code debugger of the emulator. For more details refer to the
|
||||
extra documentation of the debugger please.</p>
|
||||
<h2><a name=ss11.3>11.3 Macro</a></h2>
|
||||
<p>The keyboard macro recorder unit.</p>
|
||||
<h3><a name=ss11.3.1>11.3.1 Macro Record...</a></h3>
|
||||
<p>Prompts a dialog to enter the macro file for the data to record. After
|
||||
accepting the confirm message, every key event is recorded into the macro
|
||||
file with it's time information.</p>
|
||||
<h3><a name=ss11.3.2>11.3.2 Macro Play...</a></h3>
|
||||
<p>Prompts a dialog box to ask for the keyboard macro file to play. The
|
||||
replay starts immediately after selecting the file.</p>
|
||||
<h3><a name=ss11.3.3>11.3.3 Macro Stop</a></h3>
|
||||
<p>Stops recording or replaying a keyboard macro file.</p>
|
||||
<h3><a name=ss11.3.4>11.3.4 Macro Settings...</a></h3>
|
||||
<p>Settings for the Macro Replay mode</p>
|
||||
<ul>
|
||||
<li><i>Real</i>
|
||||
<p>Replay macro with the original recording speed.</p></li>
|
||||
<li><i>Manual</i>
|
||||
<p>Replay macro with the speed set by the speed slider.</p></li>
|
||||
</ul>
|
||||
<h1><a name=s12>12. Help Menu</a></h1>
|
||||
<h2><a name=ss12.1>12.1 Help Topics</a></h2>
|
||||
<p>Call this document.</p>
|
||||
<h2><a name=ss12.2>12.2 About Emu48...</a></h2>
|
||||
<p>The version, copyright and license message...</p>
|
||||
<h1><a name=s13>13. DDE Server</a></h1>
|
||||
<p>Emu48 has an integrated DDE server to transmit data from and to the HP
|
||||
stack. Because only the HP48 and HP49 have a stack, all DDE transfers
|
||||
are ignored on the other calculators. You have the same restrictions like
|
||||
with the commands "Load object..." and "Save
|
||||
Object...", that a running program may corrupt memory. In difference
|
||||
you can choose the stack level for the transfer in the DDE item field.
|
||||
Take care to transmit data only after the acknowledge of the last DDE
|
||||
transaction.</p>
|
||||
<p>Technical data:</p>
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="651" summary="DDE settings">
|
||||
<tr>
|
||||
<td width="111">Servicename:</td>
|
||||
<td width="536">Emu48</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="111">Topicname:</td>
|
||||
<td width="536">Stack</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="111">Item:</td>
|
||||
<td width="536">1 (stack level)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="111">Clipboardformat:</td>
|
||||
<td width="536">"CF_HPOBJ" (user defined)</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>The DDE commands CONNECT, POKE and REQUEST are supported.</p>
|
||||
<p>The structure of the clipboard format "CF_HPOBJ":</p>
|
||||
<table border="1" cellpadding="0" cellspacing="0" width="100%" summary="CF_HPOBJ format">
|
||||
<tr>
|
||||
<td width="34%">4 Byte (length of object, LSB first)</td>
|
||||
<td width="66%" align="center">HP object (normal HP object)</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h1><a name=s14>14. Emu48+ Changes</a></h1>
|
||||
<p>Emu48+ is a modified version of Emu48 to add support for the ARM-based
|
||||
calculators. It does not emulate the ARM CPU, but it enhances the
|
||||
Saturn emulation to more closely match the emulation provided by the
|
||||
Saturn emulator on the ARM-based calculators.</p>
|
||||
<p>Emu48+ adds support for many of the Saturn+ instructions, including
|
||||
some of the BUSCC instructions, and it also adds support for the 80-line
|
||||
display used on the 49g+ and 50g.</p>
|
||||
<p>At present, the additional calculators supported in Emu48+ are the
|
||||
49g+, 48gII (hardware revision 1), 50g, and 39g+/39gs/40gs.</p>
|
||||
<p>To create KML scripts for the additional calculator models, use the
|
||||
following model codes:</p>
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="651" summary="DDE settings">
|
||||
<tr>
|
||||
<td width="111">39g+/39gs:</td>
|
||||
<td width="536">Model "P"<br>
|
||||
Class 39</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="111">40gs:</td>
|
||||
<td width="536">Model "P"<br>
|
||||
Class 40</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="111">48gII:</td>
|
||||
<td width="536">Model "2"</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="111">49g+:</td>
|
||||
<td width="536">Model "Q"</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="111">50g:</td>
|
||||
<td width="536">Model "Q"<br>
|
||||
Class 50</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Most of the code that was changed in Emu48+ over Emu48 was provided by
|
||||
Cyrille de Brebisson of Hewlett-Packard.</p>
|
||||
<h1><a name=s15>15. License</a></h1>
|
||||
<p>Emu48 - A HP38G/39G/40G/48SX/48GX/49G Emulator<br>
|
||||
Copyright (C) 2017 Christoph Gießelink</p>
|
||||
<p>Emu48+ - A 39g+/39gs/40gs/48gII/49g+/50g Emulator<br>
|
||||
Copyright (C) 2017 Cyrille de Brebisson<br>
|
||||
Additional changes by Bill Graves and Eric Rechlin</p>
|
||||
<p>This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.</p>
|
||||
<p>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.</p>
|
||||
<p>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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
10
PROBLEMS.TXT
10
PROBLEMS.TXT
|
@ -1,4 +1,10 @@
|
|||
Known bugs and restrictions of Emu48 V1.58
|
||||
Additional known bugs and restrictions of Emu48 V1.57+
|
||||
------------------------------------------------------
|
||||
|
||||
- some display issues, such as when scrolling up, that were fixed in
|
||||
regular Emu48 haven't yet been merged into Emu48+
|
||||
|
||||
Known bugs and restrictions of Emu48 V1.59
|
||||
------------------------------------------
|
||||
|
||||
- the following I/O bits aren't emulated (incomplete)
|
||||
|
@ -47,4 +53,4 @@ Known bugs and restrictions of Emu48 V1.58
|
|||
- quitting the emulator while programming the flash isn't allowed,
|
||||
because the content of flash state machine isn't saved so far
|
||||
|
||||
08/16/16 (c) by Christoph Gießelink, c dot giesselink at gmx dot de
|
||||
08/15/17 (c) by Christoph Gießelink, c dot giesselink at gmx dot de
|
||||
|
|
4652
source/CHANGES.TXT
4652
source/CHANGES.TXT
File diff suppressed because it is too large
Load diff
|
@ -156,6 +156,50 @@ static VOID DisableMenuKeys(HWND hDlg)
|
|||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// read edit control and decode content as hex number or if enabled as symbol name
|
||||
//
|
||||
static BOOL GetAddr(HWND hDlg,INT nID,DWORD *pdwAddr,DWORD dwMaxAddr,BOOL bSymbEnable)
|
||||
{
|
||||
TCHAR szBuffer[48];
|
||||
INT i;
|
||||
BOOL bSucc = TRUE;
|
||||
|
||||
HWND hWnd = GetDlgItem(hDlg,nID);
|
||||
|
||||
GetWindowText(hWnd,szBuffer,ARRAYSIZEOF(szBuffer));
|
||||
|
||||
if (*szBuffer != 0)
|
||||
{
|
||||
// if address is not a symbol name decode number
|
||||
if ( !bSymbEnable || szBuffer[0] != _T('=')
|
||||
|| RplGetAddr(&szBuffer[1],pdwAddr))
|
||||
{
|
||||
// test if valid hex address
|
||||
for (i = 0; bSucc && i < (LONG) lstrlen(szBuffer); ++i)
|
||||
{
|
||||
bSucc = (_istxdigit(szBuffer[i]) != 0);
|
||||
}
|
||||
|
||||
if (bSucc) // valid characters
|
||||
{
|
||||
// convert string to number
|
||||
*pdwAddr = _tcstoul(szBuffer,NULL,16);
|
||||
}
|
||||
}
|
||||
|
||||
// inside address range?
|
||||
bSucc = bSucc && (*pdwAddr <= dwMaxAddr);
|
||||
|
||||
if (!bSucc) // invalid address
|
||||
{
|
||||
SendMessage(hWnd,EM_SETSEL,0,-1);
|
||||
SetFocus(hWnd); // focus to edit control
|
||||
}
|
||||
}
|
||||
return bSucc;
|
||||
}
|
||||
|
||||
//
|
||||
// set mapping menu
|
||||
//
|
||||
|
@ -212,50 +256,6 @@ static VOID SetMappingMenu(HWND hDlg,UINT uID)
|
|||
return;
|
||||
};
|
||||
|
||||
//
|
||||
// read edit control and decode content as hex number or if enabled as symbol name
|
||||
//
|
||||
static BOOL GetAddr(HWND hDlg,INT nID,DWORD *pdwAddr,DWORD dwMaxAddr,BOOL bSymbEnable)
|
||||
{
|
||||
TCHAR szBuffer[48];
|
||||
INT i;
|
||||
BOOL bSucc = TRUE;
|
||||
|
||||
HWND hWnd = GetDlgItem(hDlg,nID);
|
||||
|
||||
GetWindowText(hWnd,szBuffer,ARRAYSIZEOF(szBuffer));
|
||||
|
||||
if (*szBuffer != 0)
|
||||
{
|
||||
// if address is not a symbol name decode number
|
||||
if ( !bSymbEnable || szBuffer[0] != _T('=')
|
||||
|| RplGetAddr(&szBuffer[1],pdwAddr))
|
||||
{
|
||||
// test if valid hex address
|
||||
for (i = 0; bSucc && i < (LONG) lstrlen(szBuffer); ++i)
|
||||
{
|
||||
bSucc = (_istxdigit(szBuffer[i]) != 0);
|
||||
}
|
||||
|
||||
if (bSucc) // valid characters
|
||||
{
|
||||
// convert string to number
|
||||
*pdwAddr = _tcstoul(szBuffer,NULL,16);
|
||||
}
|
||||
}
|
||||
|
||||
// inside address range?
|
||||
bSucc = bSucc && (*pdwAddr <= dwMaxAddr);
|
||||
|
||||
if (!bSucc) // invalid address
|
||||
{
|
||||
SendMessage(hWnd,EM_SETSEL,0,-1);
|
||||
SetFocus(hWnd); // focus to edit control
|
||||
}
|
||||
}
|
||||
return bSucc;
|
||||
}
|
||||
|
||||
//
|
||||
// get address of cursor in memory window
|
||||
//
|
||||
|
@ -1423,7 +1423,6 @@ static BOOL OnDblClick(HWND hWnd, WORD wId)
|
|||
ViewMemWnd(hDlg,dwAdrMem); // update memory window
|
||||
SendMessage(hWnd,LB_SETCURSEL,i,0);
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1874,7 +1873,6 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM
|
|||
// add Settings item to sysmenu
|
||||
_ASSERT((IDM_DEBUG_SETTINGS & 0xFFF0) == IDM_DEBUG_SETTINGS);
|
||||
_ASSERT(IDM_DEBUG_SETTINGS < 0xF000);
|
||||
|
||||
if ((hSysMenu = GetSystemMenu(hDlg,FALSE)) != NULL)
|
||||
{
|
||||
VERIFY(AppendMenu(hSysMenu,MF_SEPARATOR,0,NULL));
|
||||
|
@ -2122,7 +2120,7 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM
|
|||
|
||||
case WM_NOTIFY:
|
||||
// tooltip for toolbar
|
||||
if(((LPNMHDR) lParam)->code == TTN_GETDISPINFO)
|
||||
if (((LPNMHDR) lParam)->code == TTN_GETDISPINFO)
|
||||
{
|
||||
((LPTOOLTIPTEXT) lParam)->hinst = hApp;
|
||||
((LPTOOLTIPTEXT) lParam)->lpszText = MAKEINTRESOURCE(((LPTOOLTIPTEXT) lParam)->hdr.idFrom);
|
||||
|
@ -2984,7 +2982,7 @@ static BOOL ToggleBreakpointItem(HWND hWnd, INT nItem)
|
|||
static VOID DrawBreakpoint(HWND hWnd, INT i)
|
||||
{
|
||||
TCHAR *szText,szBuffer[32];
|
||||
LPARAM nItem;
|
||||
INT nItem;
|
||||
|
||||
switch(sBreakpoint[i].nType)
|
||||
{
|
||||
|
@ -3150,7 +3148,7 @@ static INT_PTR CALLBACK EditBreakpoint(HWND hDlg, UINT message, WPARAM wParam, L
|
|||
}
|
||||
|
||||
case WM_VKEYTOITEM:
|
||||
if(LOWORD(wParam) == VK_SPACE)
|
||||
if (LOWORD(wParam) == VK_SPACE)
|
||||
{
|
||||
hWnd = GetDlgItem(hDlg,IDC_BREAKEDIT_WND);
|
||||
for (nItem = 0; nItem < wBreakpointCount; ++nItem)
|
||||
|
|
|
@ -85,7 +85,7 @@ static CONST MODEL_MAP_T MemMap[] =
|
|||
&Port2, &Chipset.Port2Size // Port 1 part 2
|
||||
},
|
||||
{ // CdB for HP: add Q type
|
||||
'Q', // HP49G+
|
||||
'Q', // HP49g+
|
||||
&pbyRom, &dwRomSize, // Flash
|
||||
&Port0, &Chipset.Port0Size, // RAM
|
||||
&pbyNoMEM, NULL, // BS
|
||||
|
@ -93,7 +93,7 @@ static CONST MODEL_MAP_T MemMap[] =
|
|||
&Port2, &Chipset.Port2Size // Port 1 part 2
|
||||
},
|
||||
{ // CdB for HP: add 2 type
|
||||
'2', // HP48Gii
|
||||
'2', // HP48gII
|
||||
&pbyRom, &dwRomSize, // ROM
|
||||
&Port0, &Chipset.Port0Size, // RAM
|
||||
&pbyNoMEM, NULL, // BS
|
||||
|
@ -101,7 +101,7 @@ static CONST MODEL_MAP_T MemMap[] =
|
|||
&pbyNoMEM, NULL, // Port 1 part 2
|
||||
},
|
||||
{ // CdB for HP: add P type
|
||||
'P', // HP39G+
|
||||
'P', // HP39g+/gs
|
||||
&pbyRom, &dwRomSize, // ROM
|
||||
&Port0, &Chipset.Port0Size, // RAM
|
||||
&pbyNoMEM, NULL, // BS
|
||||
|
|
294
source/DISPLAY.C
294
source/DISPLAY.C
|
@ -15,8 +15,10 @@
|
|||
|
||||
// #define DEBUG_DISPLAY // switch for DISPLAY debug purpose
|
||||
|
||||
#define NOCOLORSGRAY 8
|
||||
#define NOCOLORSBW 2
|
||||
#define NOCOLORSGRAY 8 // no. of colors in gray scale mode
|
||||
#define NOCOLORSBW 2 // no. of colors in black and white mode
|
||||
|
||||
#define DISPLAY_FREQ 19 // display update 1/frequency (1/64) in ms (gray scale mode)
|
||||
|
||||
#define B 0x00000000 // black
|
||||
#define W 0x00FFFFFF // white
|
||||
|
@ -29,29 +31,50 @@
|
|||
|((((c)-1)>>1)<<8) \
|
||||
|((((c)-1)>>1)))
|
||||
|
||||
#define DIBPIXEL(d,p) *((DWORD*)(d)) = ((*((DWORD*)(d)) & dwGrayMask) << 1) | (p); *((LPBYTE*) &(d)) += 4
|
||||
#define DIBPIXEL4(d,p) *((DWORD*)(d)) = ((*((DWORD*)(d)) & dwGrayMask) << 1) | (p); \
|
||||
*((LPBYTE*) &(d)) += 4
|
||||
|
||||
BOOL bGrayscale = FALSE; // Default is to not emulate grayscale
|
||||
BOOL bGrayscale = FALSE;
|
||||
UINT nBackgroundX = 0;
|
||||
UINT nBackgroundY = 0;
|
||||
UINT nBackgroundW = 0;
|
||||
UINT nBackgroundH = 0;
|
||||
UINT nLcdX = 0;
|
||||
UINT nLcdY = 0;
|
||||
UINT nLcdZoom = 1;
|
||||
UINT nLcdZoom = 1; // memory DC zoom
|
||||
UINT nGdiXZoom = 1; // GDI x zoom
|
||||
UINT nGdiYZoom = 1; // GDI y zoom
|
||||
HDC hLcdDC = NULL;
|
||||
HDC hMainDC = NULL;
|
||||
HDC hAnnunDC = NULL; // annunciator DC
|
||||
|
||||
BYTE (*GetLineCounter)(VOID) = NULL;
|
||||
VOID (*StartDisplay)(BYTE byInitial) = NULL;
|
||||
VOID (*StopDisplay)(VOID) = NULL;
|
||||
|
||||
static BYTE GetLineCounterGray(VOID);
|
||||
static BYTE GetLineCounterBW(VOID);
|
||||
static VOID StartDisplayGray(BYTE byInitial);
|
||||
static VOID StartDisplayBW(BYTE byInitial);
|
||||
static VOID StopDisplayGray(VOID);
|
||||
static VOID StopDisplayBW(VOID);
|
||||
|
||||
static LPBYTE pbyLcd;
|
||||
|
||||
static HBITMAP hLcdBitmap;
|
||||
static HBITMAP hMainBitmap;
|
||||
static HBITMAP hAnnunBitmap;
|
||||
|
||||
static DWORD Pattern[16];
|
||||
static BYTE Buf[36];
|
||||
|
||||
static DWORD dwGrayMask;
|
||||
|
||||
static LARGE_INTEGER lLcdRef; // reference time for VBL counter
|
||||
static UINT uLcdTimerId = 0;
|
||||
|
||||
static BYTE byVblRef = 0; // VBL stop reference
|
||||
|
||||
static DWORD dwKMLColor[64] = // color table loaded by KML script
|
||||
{
|
||||
W,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,
|
||||
|
@ -116,9 +139,6 @@ VOID UpdateContrast(BYTE byContrast)
|
|||
// update palette information
|
||||
_ASSERT(hLcdDC);
|
||||
SetDIBColorTable(hLcdDC,0,ARRAYSIZEOF(bmiLcd.bmiColors),bmiLcd.bmiColors);
|
||||
|
||||
// recalculate update mask for online gray <-> bw switching
|
||||
dwGrayMask = bGrayscale ? GRAYMASK(NOCOLORSGRAY) : GRAYMASK(NOCOLORSBW);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -128,22 +148,42 @@ VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue)
|
|||
return;
|
||||
}
|
||||
|
||||
VOID SetLcdMode(BOOL bMode)
|
||||
{
|
||||
if ((bGrayscale = bMode))
|
||||
{
|
||||
// set pixel update mask
|
||||
dwGrayMask = GRAYMASK(NOCOLORSGRAY);
|
||||
GetLineCounter = GetLineCounterGray;
|
||||
StartDisplay = StartDisplayGray;
|
||||
StopDisplay = StopDisplayGray;
|
||||
}
|
||||
else
|
||||
{
|
||||
// set pixel update mask
|
||||
dwGrayMask = GRAYMASK(NOCOLORSBW);
|
||||
GetLineCounter = GetLineCounterBW;
|
||||
StartDisplay = StartDisplayBW;
|
||||
StopDisplay = StopDisplayBW;
|
||||
}
|
||||
UpdateContrast(Chipset.contrast);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID CreateLcdBitmap(VOID)
|
||||
{
|
||||
// create LCD bitmap
|
||||
bmiLcd.Lcd_bmih.biWidth = LCD_ROW;
|
||||
bmiLcd.Lcd_bmih.biHeight = -SCREENHEIGHT; // CdB for HP: add 64/80 ligne display for apples
|
||||
bmiLcd.Lcd_bmih.biHeight = -SCREENHEIGHT; // CdB for HP: add 64/80 line display for apples
|
||||
_ASSERT(hLcdDC == NULL);
|
||||
hLcdDC = CreateCompatibleDC(hWindowDC);
|
||||
_ASSERT(hLcdDC != NULL);
|
||||
hLcdBitmap = CreateDIBSection(hWindowDC,(BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS,(VOID **)&pbyLcd,NULL,0);
|
||||
VERIFY(hLcdDC = CreateCompatibleDC(hWindowDC));
|
||||
VERIFY(hLcdBitmap = CreateDIBSection(hWindowDC,(BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS,(VOID **)&pbyLcd,NULL,0));
|
||||
hLcdBitmap = (HBITMAP) SelectObject(hLcdDC,hLcdBitmap);
|
||||
_ASSERT(hPalette != NULL);
|
||||
SelectPalette(hLcdDC,hPalette,FALSE); // set palette for LCD DC
|
||||
RealizePalette(hLcdDC); // realize palette
|
||||
BuildPattern(); // build Nibble -> DIB mask pattern
|
||||
dwGrayMask = bGrayscale ? GRAYMASK(NOCOLORSGRAY) : GRAYMASK(NOCOLORSBW);
|
||||
UpdateContrast(Chipset.contrast);
|
||||
SetLcdMode(bGrayscale); // init display update function pointer
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -151,8 +191,12 @@ VOID DestroyLcdBitmap(VOID)
|
|||
{
|
||||
// set contrast palette to startup colors
|
||||
WORD i = 0; dwKMLColor[i++] = W;
|
||||
while(i < 32) dwKMLColor[i++] = B;
|
||||
while(i < 64) dwKMLColor[i++] = I;
|
||||
while (i < 32) dwKMLColor[i++] = B;
|
||||
while (i < 64) dwKMLColor[i++] = I;
|
||||
|
||||
GetLineCounter = NULL;
|
||||
StartDisplay = NULL;
|
||||
StopDisplay = NULL;
|
||||
|
||||
if (hLcdDC != NULL)
|
||||
{
|
||||
|
@ -167,11 +211,8 @@ VOID DestroyLcdBitmap(VOID)
|
|||
|
||||
BOOL CreateMainBitmap(LPCTSTR szFilename)
|
||||
{
|
||||
HPALETTE hAssertPalette;
|
||||
|
||||
_ASSERT(hWindowDC != NULL);
|
||||
hMainDC = CreateCompatibleDC(hWindowDC);
|
||||
_ASSERT(hMainDC != NULL);
|
||||
VERIFY(hMainDC = CreateCompatibleDC(hWindowDC));
|
||||
if (hMainDC == NULL) return FALSE; // quit if failed
|
||||
hMainBitmap = LoadBitmapFile(szFilename);
|
||||
if (hMainBitmap == NULL)
|
||||
|
@ -182,8 +223,7 @@ BOOL CreateMainBitmap(LPCTSTR szFilename)
|
|||
}
|
||||
hMainBitmap = (HBITMAP) SelectObject(hMainDC,hMainBitmap);
|
||||
_ASSERT(hPalette != NULL);
|
||||
hAssertPalette = SelectPalette(hMainDC,hPalette,FALSE);
|
||||
_ASSERT(hAssertPalette != NULL);
|
||||
VERIFY(SelectPalette(hMainDC,hPalette,FALSE));
|
||||
RealizePalette(hMainDC);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -201,6 +241,40 @@ VOID DestroyMainBitmap(VOID)
|
|||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// load annunciator bitmap
|
||||
//
|
||||
BOOL CreateAnnunBitmap(LPCTSTR szFilename)
|
||||
{
|
||||
_ASSERT(hWindowDC != NULL);
|
||||
VERIFY(hAnnunDC = CreateCompatibleDC(hWindowDC));
|
||||
if (hAnnunDC == NULL) return FALSE; // quit if failed
|
||||
hAnnunBitmap = LoadBitmapFile(szFilename);
|
||||
if (hAnnunBitmap == NULL)
|
||||
{
|
||||
DeleteDC(hAnnunDC);
|
||||
hAnnunDC = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
hAnnunBitmap = (HBITMAP) SelectObject(hAnnunDC,hAnnunBitmap);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// destroy annunciator bitmap
|
||||
//
|
||||
VOID DestroyAnnunBitmap(VOID)
|
||||
{
|
||||
if (hAnnunDC != NULL)
|
||||
{
|
||||
VERIFY(DeleteObject(SelectObject(hAnnunDC,hAnnunBitmap)));
|
||||
DeleteDC(hAnnunDC);
|
||||
hAnnunDC = NULL;
|
||||
hAnnunBitmap = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//****************
|
||||
//*
|
||||
//* LCD functions
|
||||
|
@ -242,8 +316,8 @@ VOID UpdateDisplayPointers(VOID)
|
|||
VOID UpdateMainDisplay(VOID)
|
||||
{
|
||||
UINT x, y;
|
||||
BYTE *p = pbyLcd+(Chipset.d0size*LCD_ROW); // CdB for HP: add 64/80 line display for apples
|
||||
DWORD d = Chipset.start1;
|
||||
BYTE *p = pbyLcd+(Chipset.d0size*LCD_ROW); // CdB for HP: add 64/80 ligne display for apples
|
||||
|
||||
#if defined DEBUG_DISPLAY
|
||||
{
|
||||
|
@ -264,7 +338,7 @@ VOID UpdateMainDisplay(VOID)
|
|||
Npeek(Buf,d,36);
|
||||
for (x=0; x<36; ++x) // every 4 pixel
|
||||
{
|
||||
DIBPIXEL(p,Pattern[Buf[x]]);
|
||||
DIBPIXEL4(p,Pattern[Buf[x]]);
|
||||
// check for display buffer overflow
|
||||
_ASSERT(p <= pbyLcd + LCD_ROW * SCREENHEIGHT);
|
||||
}
|
||||
|
@ -273,14 +347,9 @@ VOID UpdateMainDisplay(VOID)
|
|||
}
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
// CdB for HP: add 64/80 ligne display for apples
|
||||
StretchBlt(hWindowDC,
|
||||
nLcdX, nLcdY+Chipset.d0size*nLcdZoom,
|
||||
131*nLcdZoom, MAINSCREENHEIGHT*nLcdZoom,
|
||||
hLcdDC,
|
||||
Chipset.boffset, Chipset.d0size,
|
||||
131, MAINSCREENHEIGHT,
|
||||
SRCCOPY);
|
||||
// CdB for HP: add 64/80 line display for apples
|
||||
StretchBlt(hWindowDC, nLcdX, nLcdY+Chipset.d0size*nLcdZoom, 131*nLcdZoom, MAINSCREENHEIGHT*nLcdZoom,
|
||||
hLcdDC, Chipset.boffset, Chipset.d0size, 131, MAINSCREENHEIGHT, SRCCOPY);
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
|
@ -305,13 +374,13 @@ VOID UpdateMenuDisplay(VOID)
|
|||
if (MENUHEIGHT==0) return; // menu disabled
|
||||
|
||||
// calculate bitmap offset
|
||||
p = pbyLcd + ((Chipset.d0size+MAINSCREENHEIGHT)*LCD_ROW); // CdB for HP: add 64/80 ligne display for apples
|
||||
p = pbyLcd + ((Chipset.d0size+MAINSCREENHEIGHT)*LCD_ROW); // CdB for HP: add 64/80 line display for apples
|
||||
for (y = 0; y < MENUHEIGHT; ++y)
|
||||
{
|
||||
Npeek(Buf,d,34); // 34 nibbles are viewed
|
||||
for (x=0; x<34; ++x) // every 4 pixel
|
||||
{
|
||||
DIBPIXEL(p,Pattern[Buf[x]]);
|
||||
DIBPIXEL4(p,Pattern[Buf[x]]);
|
||||
// check for display buffer overflow
|
||||
_ASSERT(p <= pbyLcd + LCD_ROW * SCREENHEIGHT);
|
||||
}
|
||||
|
@ -321,7 +390,7 @@ VOID UpdateMenuDisplay(VOID)
|
|||
}
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
// CdB for HP: add 64/80 ligne display for apples
|
||||
// CdB for HP: add 64/80 line display for apples
|
||||
StretchBlt(hWindowDC,
|
||||
nLcdX, nLcdY+(MAINSCREENHEIGHT+Chipset.d0size)*nLcdZoom,
|
||||
131*nLcdZoom, MENUHEIGHT*nLcdZoom,
|
||||
|
@ -359,19 +428,15 @@ VOID RefreshDisp0()
|
|||
memcpy(Buf,d,34); // 34 nibbles are viewed
|
||||
for (x=0; x<36; ++x) // every 4 pixel
|
||||
{
|
||||
DIBPIXEL(p,Pattern[Buf[x]]);
|
||||
DIBPIXEL4(p,Pattern[Buf[x]]);
|
||||
}
|
||||
d+=34;
|
||||
}
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
StretchBlt(hWindowDC,
|
||||
nLcdX, nLcdY,
|
||||
131*nLcdZoom, Chipset.d0size*nLcdZoom,
|
||||
hLcdDC,
|
||||
Chipset.d0offset, 0,
|
||||
131, Chipset.d0size,
|
||||
SRCCOPY);
|
||||
StretchBlt(hWindowDC, nLcdX, nLcdY,
|
||||
131*nLcdZoom*nGdiXZoom, Chipset.d0size*nLcdZoom*nGdiYZoom,
|
||||
hLcdDC, Chipset.d0offset, 0, 131, Chipset.d0size, SRCCOPY);
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
|
@ -386,10 +451,7 @@ VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
|
|||
|
||||
INT lWidth = abs(Chipset.width); // display width
|
||||
|
||||
if (bGrayscale)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (bGrayscale) return; // no direct writing in grayscale mode
|
||||
|
||||
#if defined DEBUG_DISPLAY
|
||||
{
|
||||
|
@ -399,7 +461,9 @@ VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!(Chipset.IORam[BITOFFSET]&DON)) return; // display off
|
||||
if (!(Chipset.IORam[BITOFFSET]&DON)) // display off
|
||||
return; // no drawing
|
||||
|
||||
if (MAINSCREENHEIGHT == 0) return; // menu disabled
|
||||
|
||||
d -= Chipset.start1; // nibble offset to DISPADDR (start of display)
|
||||
|
@ -417,27 +481,25 @@ VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
|
|||
{
|
||||
*p = Pattern[*a];
|
||||
}
|
||||
a++; // next value to write
|
||||
x++; // next x position
|
||||
++a; // next value to write
|
||||
++x; // next x position
|
||||
if (((INT) x==lWidth)&&s) // end of display line
|
||||
{
|
||||
x = 0; // first coloumn
|
||||
y++; // next row
|
||||
++y; // next row
|
||||
if (y == (INT) MAINSCREENHEIGHT+Chipset.d0size) break;
|
||||
// recalculate bitmap memory position of new line
|
||||
p = (DWORD*) (pbyLcd+y*LCD_ROW); // CdB for HP: add 64/80 ligne display for apples
|
||||
} else p++;
|
||||
p = (DWORD*) (pbyLcd+y*LCD_ROW); // CdB for HP: add 64/80 line display for apples
|
||||
}
|
||||
else
|
||||
p++;
|
||||
}
|
||||
if (y==y0) y++;
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
StretchBlt(hWindowDC,
|
||||
nLcdX, nLcdY+y0*nLcdZoom,
|
||||
StretchBlt(hWindowDC, nLcdX, nLcdY+y0*nLcdZoom,
|
||||
131*nLcdZoom, (y-y0)*nLcdZoom,
|
||||
hLcdDC,
|
||||
Chipset.boffset, y0,
|
||||
131, y-y0,
|
||||
SRCCOPY); // CdB for HP: add 64/80 ligne display for apples
|
||||
hLcdDC, Chipset.boffset, y0, 131, y-y0, SRCCOPY); // CdB for HP: add 64/80 line display for apples
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
|
@ -450,10 +512,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
|
|||
UINT y0, y;
|
||||
DWORD *p;
|
||||
|
||||
if (bGrayscale)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (bGrayscale) return; // no direct writing in grayscale mode
|
||||
|
||||
#if defined DEBUG_DISPLAY
|
||||
{
|
||||
|
@ -463,12 +522,12 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!(Chipset.IORam[BITOFFSET]&DON)) return; // display off
|
||||
if (!(Chipset.IORam[BITOFFSET]&DON)) return;
|
||||
if (MENUHEIGHT == 0) return; // menu disabled
|
||||
|
||||
d -= Chipset.start2; // nibble offset to DISPADDR (start of display)
|
||||
d -= Chipset.start2;
|
||||
y0 = y = (d / 34) + MAINSCREENHEIGHT+Chipset.d0size; // bitmap row
|
||||
x0 = x = d % 34; // bitmap coloumn
|
||||
x0 = x = d % 34;
|
||||
p = (DWORD*)(pbyLcd + y0*LCD_ROW + x0*sizeof(*p));
|
||||
|
||||
// outside menu display area
|
||||
|
@ -495,13 +554,9 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
|
|||
if (y==y0) y++;
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
StretchBlt(hWindowDC,
|
||||
nLcdX, nLcdY+y0*nLcdZoom,
|
||||
StretchBlt(hWindowDC, nLcdX, nLcdY+y0*nLcdZoom,
|
||||
131*nLcdZoom, (y-y0)*nLcdZoom,
|
||||
hLcdDC,
|
||||
0, y0,
|
||||
131, y-y0,
|
||||
SRCCOPY); // CdB for HP: add 64/80 ligne display for apples
|
||||
hLcdDC, 0, y0, 131, y-y0, SRCCOPY); // CdB for HP: add 64/80 line display for apples
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
|
@ -557,33 +612,25 @@ VOID ResizeWindow(VOID)
|
|||
SWP_NOMOVE | SWP_NOZORDER);
|
||||
}
|
||||
|
||||
_ASSERT(hWindowDC); // move destination window
|
||||
SetWindowOrgEx(hWindowDC, nBackgroundX, nBackgroundY, NULL);
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
_ASSERT(hWindowDC); // move origin of destination window
|
||||
VERIFY(SetWindowOrgEx(hWindowDC, nBackgroundX, nBackgroundY, NULL));
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
InvalidateRect(hWnd,NULL,TRUE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//################
|
||||
//#
|
||||
//# functions for gray scale implementation
|
||||
//#
|
||||
//################
|
||||
|
||||
#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 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;
|
||||
}
|
||||
|
||||
// main display update routine
|
||||
static VOID CALLBACK LcdProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
|
||||
{
|
||||
EnterCriticalSection(&csLcdLock);
|
||||
|
@ -605,17 +652,11 @@ static VOID CALLBACK LcdProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1,
|
|||
}
|
||||
|
||||
// LCD line counter calculation
|
||||
BYTE GetLineCounter(VOID)
|
||||
static BYTE GetLineCounterGray(VOID)
|
||||
{
|
||||
LARGE_INTEGER lLC;
|
||||
BYTE byTime;
|
||||
|
||||
if (!bGrayscale)
|
||||
{
|
||||
_ASSERT(byVblRef < 0x40);
|
||||
return (0x40 + F4096Hz() - byVblRef) & 0x3F;
|
||||
}
|
||||
|
||||
if (uLcdTimerId == 0) // display off
|
||||
return ((Chipset.IORam[LINECOUNT+1] & (LC5|LC4)) << 4) | Chipset.IORam[LINECOUNT];
|
||||
|
||||
|
@ -629,15 +670,8 @@ BYTE GetLineCounter(VOID)
|
|||
return 0x3F - byTime; // update display between VBL counter 0x3F-0x3E
|
||||
}
|
||||
|
||||
VOID StartDisplay(BYTE byInitial)
|
||||
static VOID StartDisplayGray(BYTE byInitial)
|
||||
{
|
||||
if (!bGrayscale)
|
||||
{
|
||||
// get positive VBL difference between now and stop time
|
||||
byVblRef = (0x40 + F4096Hz() - byInitial) & 0x3F;
|
||||
return;
|
||||
}
|
||||
|
||||
if (uLcdTimerId) // LCD update timer running
|
||||
return; // -> quit
|
||||
|
||||
|
@ -649,20 +683,16 @@ VOID StartDisplay(BYTE byInitial)
|
|||
_ASSERT(byInitial <= 0x3F); // line counter value 0 - 63
|
||||
lLcdRef.QuadPart -= ((LONGLONG) (0x3F - byInitial) * lFreq.QuadPart) >> 12;
|
||||
|
||||
uLcdTimerId = timeSetEvent(DISPLAY_FREQ,0,(LPTIMECALLBACK)&LcdProc,0,TIME_PERIODIC);
|
||||
_ASSERT(uLcdTimerId); // test if display update timer started
|
||||
VERIFY(uLcdTimerId = timeSetEvent(DISPLAY_FREQ,0,(LPTIMECALLBACK)&LcdProc,0,TIME_PERIODIC));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID StopDisplay(VOID)
|
||||
static VOID StopDisplayGray(VOID)
|
||||
{
|
||||
BYTE a[2];
|
||||
ReadIO(a,LINECOUNT,2,TRUE); // update VBL at display off time
|
||||
|
||||
if (!bGrayscale)
|
||||
return;
|
||||
|
||||
if (uLcdTimerId == 0) // timer stopped
|
||||
return; // -> quit
|
||||
|
||||
|
@ -678,3 +708,39 @@ VOID StopDisplay(VOID)
|
|||
LeaveCriticalSection(&csLcdLock);
|
||||
return;
|
||||
}
|
||||
//################
|
||||
//#
|
||||
//# functions for black and white implementation
|
||||
//#
|
||||
//################
|
||||
|
||||
// LCD line counter calculation in BW mode
|
||||
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;
|
||||
}
|
||||
|
||||
static BYTE GetLineCounterBW(VOID) // get line counter value
|
||||
{
|
||||
_ASSERT(byVblRef < 0x40);
|
||||
return (0x40 + F4096Hz() - byVblRef) & 0x3F;
|
||||
}
|
||||
|
||||
static VOID StartDisplayBW(BYTE byInitial)
|
||||
{
|
||||
// get positive VBL difference between now and stop time
|
||||
byVblRef = (0x40 + F4096Hz() - byInitial) & 0x3F;
|
||||
return;
|
||||
}
|
||||
|
||||
static VOID StopDisplayBW(VOID)
|
||||
{
|
||||
BYTE a[2];
|
||||
ReadIO(a,LINECOUNT,2,TRUE); // update VBL at display off time
|
||||
return;
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
#include "kml.h"
|
||||
#include "debugger.h"
|
||||
|
||||
#define VERSION "1.56+"
|
||||
#define VERSION "1.57+"
|
||||
|
||||
#ifdef _DEBUG
|
||||
LPCTSTR szNoTitle = _T("Emu48 ")_T(VERSION)_T(" Debug");
|
||||
|
@ -318,35 +318,6 @@ static BOOL IsFileWriteable(LPCTSTR szFilename)
|
|||
return bWriteable;
|
||||
}
|
||||
|
||||
// set listfield for sound device combo box
|
||||
static VOID SetSoundDeviceList(HWND hWnd,UINT uDeviceID)
|
||||
{
|
||||
WAVEOUTCAPS woc;
|
||||
UINT uSelectDevice,uDevID,uDevNo;
|
||||
|
||||
SendMessage(hWnd,CB_RESETCONTENT,0,0);
|
||||
|
||||
// preset selector
|
||||
uSelectDevice = (UINT) SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM) _T("Standard Audio"));
|
||||
SendMessage(hWnd,CB_SETITEMDATA,uSelectDevice,WAVE_MAPPER);
|
||||
|
||||
uDevNo = waveOutGetNumDevs();
|
||||
for (uDevID = 0; uDevID < uDevNo; ++uDevID)
|
||||
{
|
||||
if ( waveOutGetDevCaps(uDevID,&woc,sizeof(woc)) == MMSYSERR_NOERROR
|
||||
&& (woc.dwFormats & WAVE_FORMAT_4M08) != 0)
|
||||
{
|
||||
// copy product name to combo box
|
||||
LONG i = (LONG) SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM) woc.szPname);
|
||||
SendMessage(hWnd,CB_SETITEMDATA,i,uDevID);
|
||||
|
||||
if (uDevID == uDeviceID) uSelectDevice = i;
|
||||
}
|
||||
}
|
||||
SendMessage(hWnd,CB_SETCURSEL,uSelectDevice,0L);
|
||||
return;
|
||||
}
|
||||
|
||||
// set listfield for serial combo boxes
|
||||
static VOID SetCommList(HWND hDlg,LPCTSTR szWireSetting,LPCTSTR szIrSetting)
|
||||
{
|
||||
|
@ -394,7 +365,7 @@ static VOID SetCommList(HWND hDlg,LPCTSTR szWireSetting,LPCTSTR szIrSetting)
|
|||
|
||||
// test if COM port is valid
|
||||
hComm = CreateFile(szBuffer,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
|
||||
if(hComm != INVALID_HANDLE_VALUE)
|
||||
if (hComm != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
VERIFY(CloseHandle(hComm));
|
||||
bAddWire = bAddIr = TRUE;
|
||||
|
@ -472,8 +443,7 @@ static INT_PTR CALLBACK SettingsGeneralProc(HWND hDlg, UINT uMsg, WPARAM wParam,
|
|||
if (bGrayscale != (BOOL) IsDlgButtonChecked(hDlg,IDC_GRAYSCALE))
|
||||
{
|
||||
UINT nOldState = SwitchToState(SM_INVALID);
|
||||
bGrayscale = !bGrayscale; // set new grayscale mode
|
||||
UpdateContrast(Chipset.contrast); // update LCD color table for new mode
|
||||
SetLcdMode(!bGrayscale); // set new display mode
|
||||
SwitchToState(nOldState);
|
||||
}
|
||||
|
||||
|
@ -534,7 +504,7 @@ static INT_PTR CALLBACK SettingsMemoryProc(HWND hDlg, UINT uMsg, WPARAM wParam,
|
|||
EnableWindow(GetDlgItem(hDlg,IDC_PORT1WR),FALSE);
|
||||
}
|
||||
}
|
||||
else // HP38G/HP39G/HP40G/HP49G/HP39G+/HP48Gii/HP49G+ // CdB for HP: add apples
|
||||
else // HP38G/HP39G/HP40G/HP49G
|
||||
{
|
||||
EnableWindow(GetDlgItem(hDlg,IDC_PORT1EN),FALSE);
|
||||
EnableWindow(GetDlgItem(hDlg,IDC_PORT1WR),FALSE);
|
||||
|
@ -716,7 +686,7 @@ static INT_PTR CALLBACK SettingsPeripheralProc(HWND hDlg, UINT uMsg, WPARAM wPar
|
|||
EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE);
|
||||
}
|
||||
|
||||
if (cCurrentRomType=='X' || cCurrentRomType=='2' || cCurrentRomType=='Q') // HP49G/HP48GII/HP49G+ // CdB for HP: add Apples
|
||||
if (cCurrentRomType=='X') // HP49G
|
||||
{
|
||||
SendDlgItemMessage(hDlg,IDC_IR,CB_RESETCONTENT,0,0);
|
||||
EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE);
|
||||
|
@ -751,8 +721,7 @@ static INT_PTR CALLBACK SettingsPeripheralProc(HWND hDlg, UINT uMsg, WPARAM wPar
|
|||
ResetUdp(); // invalidate saved UDP address
|
||||
// set combobox parameter
|
||||
GetDlgItemText(hDlg,IDC_WIRE,szSerialWire,ARRAYSIZEOF(szSerialWire));
|
||||
// HP49G, 48GII, 49G+ Ir port is not connected
|
||||
if (cCurrentRomType!='X' && cCurrentRomType!='2' && cCurrentRomType!='Q') // HP49G/HP48GII/HP49G+ // CdB for HP: add Apples
|
||||
if (cCurrentRomType!='X') // HP49G Ir port is not connected
|
||||
GetDlgItemText(hDlg,IDC_IR,szSerialIr,ARRAYSIZEOF(szSerialIr));
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -912,20 +881,25 @@ static LRESULT OnPaint(HWND hWindow)
|
|||
BitBlt(hPaintDC, Paint.rcPaint.left, Paint.rcPaint.top,
|
||||
Paint.rcPaint.right-Paint.rcPaint.left, Paint.rcPaint.bottom-Paint.rcPaint.top,
|
||||
hMainDC, rcMainPaint.left, rcMainPaint.top, SRCCOPY);
|
||||
|
||||
// CdB for HP: add apples display stuff
|
||||
SetWindowOrgEx(hPaintDC, nBackgroundX, nBackgroundY, NULL);
|
||||
|
||||
// redraw header display area
|
||||
StretchBlt(hPaintDC, nLcdX, nLcdY,
|
||||
131*nLcdZoom, Chipset.d0size*nLcdZoom,
|
||||
131*nLcdZoom*nGdiXZoom, Chipset.d0size*nLcdZoom*nGdiYZoom,
|
||||
hLcdDC, Chipset.d0offset, 0, 131, Chipset.d0size, SRCCOPY);
|
||||
|
||||
// redraw main display area
|
||||
StretchBlt(hPaintDC, nLcdX, nLcdY+Chipset.d0size*nLcdZoom,
|
||||
131*nLcdZoom, nLines*nLcdZoom,
|
||||
hLcdDC, Chipset.boffset, Chipset.d0size, 131, MAINSCREENHEIGHT, SRCCOPY);
|
||||
StretchBlt(hPaintDC, nLcdX, nLcdY+Chipset.d0size*nLcdZoom*nGdiYZoom,
|
||||
131*nLcdZoom*nGdiXZoom, nLines*nLcdZoom*nGdiYZoom,
|
||||
hLcdDC, Chipset.boffset, Chipset.d0size,
|
||||
131, MAINSCREENHEIGHT, SRCCOPY);
|
||||
// redraw menu display area
|
||||
StretchBlt(hPaintDC, nLcdX, nLcdY+(MAINSCREENHEIGHT+Chipset.d0size)*nLcdZoom,
|
||||
131*nLcdZoom, MENUHEIGHT*nLcdZoom,
|
||||
hLcdDC, 0, (MAINSCREENHEIGHT+Chipset.d0size), 131, MENUHEIGHT, SRCCOPY);
|
||||
StretchBlt(hPaintDC, nLcdX, nLcdY+(MAINSCREENHEIGHT+Chipset.d0size)*nLcdZoom*nGdiYZoom,
|
||||
131*nLcdZoom*nGdiXZoom, MENUHEIGHT*nLcdZoom*nGdiYZoom,
|
||||
hLcdDC, 0, (MAINSCREENHEIGHT+Chipset.d0size),
|
||||
131, MENUHEIGHT, SRCCOPY);
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
|
@ -981,7 +955,7 @@ static LRESULT OnDropFiles(HDROP hFilesInfo)
|
|||
{
|
||||
TCHAR szFileName[MAX_PATH];
|
||||
WORD wNumFiles,wIndex;
|
||||
BOOL bSuccess;
|
||||
BOOL bSuccess = FALSE;
|
||||
|
||||
// get number of files dropped
|
||||
wNumFiles = DragQueryFile (hFilesInfo,(UINT)-1,NULL,0);
|
||||
|
@ -1030,7 +1004,7 @@ static LRESULT OnDropFiles(HDROP hFilesInfo)
|
|||
Sleep(dwWakeupDelay);
|
||||
KeyboardEvent(FALSE,0,0x8000);
|
||||
// wait for sleep mode
|
||||
while(Chipset.Shutdn == FALSE) Sleep(0);
|
||||
while (Chipset.Shutdn == FALSE) Sleep(0);
|
||||
|
||||
cancel:
|
||||
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
|
||||
|
@ -1491,7 +1465,7 @@ static LRESULT OnObjectLoad(VOID)
|
|||
KeyboardEvent(FALSE,0,0x8000);
|
||||
|
||||
// wait for sleep mode
|
||||
while(Chipset.Shutdn == FALSE) Sleep(0);
|
||||
while (Chipset.Shutdn == FALSE) Sleep(0);
|
||||
}
|
||||
|
||||
if (nState != SM_RUN)
|
||||
|
@ -1546,7 +1520,7 @@ static LRESULT OnObjectLoad(VOID)
|
|||
KeyboardEvent(TRUE,0,0x8000);
|
||||
Sleep(dwWakeupDelay);
|
||||
KeyboardEvent(FALSE,0,0x8000);
|
||||
while(Chipset.Shutdn == FALSE) Sleep(0);
|
||||
while (Chipset.Shutdn == FALSE) Sleep(0);
|
||||
|
||||
cancel:
|
||||
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
|
||||
|
@ -1737,15 +1711,21 @@ static LRESULT OnToolDisasm(VOID) // disasm dialogbox call
|
|||
{
|
||||
if (pbyRom) SwitchToState(SM_SLEEP);
|
||||
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_DISASM), hWnd, (DLGPROC)Disasm) == -1)
|
||||
AbortMessage(_T("Disassembler Dialog Box Creation Error !"));
|
||||
AbortMessage(_T("Disassembler Dialog Box Creation Error!"));
|
||||
if (pbyRom) SwitchToState(SM_RUN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LRESULT OnTopics(VOID)
|
||||
{
|
||||
ShellExecute(hWnd,_T("open"),_T("Emu48.htm"),NULL,szEmuDirectory,SW_SHOWNORMAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LRESULT OnAbout(VOID)
|
||||
{
|
||||
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)About) == -1)
|
||||
AbortMessage(_T("About Dialog Box Creation Error !"));
|
||||
AbortMessage(_T("About Dialog Box Creation Error!"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1979,6 +1959,7 @@ LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
case ID_TOOL_MACRO_PLAY: return OnToolMacroPlay();
|
||||
case ID_TOOL_MACRO_STOP: return OnToolMacroStop();
|
||||
case ID_TOOL_MACRO_SETTINGS: return OnToolMacroSettings();
|
||||
case ID_HELP_TOPICS: return OnTopics();
|
||||
case ID_ABOUT: return OnAbout();
|
||||
}
|
||||
// check if command ID belongs to MRU file area
|
||||
|
@ -2004,8 +1985,8 @@ LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||
case WM_LBUTTONUP: return OnLButtonUp((UINT) wParam, LOWORD(lParam), HIWORD(lParam));
|
||||
case WM_MOUSEMOVE: return OnMouseMove((UINT) wParam, LOWORD(lParam), HIWORD(lParam));
|
||||
case WM_NCMOUSEMOVE: return OnNcMouseMove((UINT) wParam, LOWORD(lParam), HIWORD(lParam));
|
||||
case WM_KEYUP: return OnKeyUp((int)wParam, lParam);
|
||||
case WM_KEYDOWN: return OnKeyDown((int)wParam, lParam);
|
||||
case WM_KEYUP: return OnKeyUp((int) wParam, lParam);
|
||||
case WM_KEYDOWN: return OnKeyDown((int) wParam, lParam);
|
||||
#if !defined _USRDLL // not in DLL version
|
||||
case WM_COPYDATA: return OnCopyData((PCOPYDATASTRUCT) lParam);
|
||||
#endif
|
||||
|
@ -2125,10 +2106,10 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
|
|||
rectWindow.top = 0;
|
||||
rectWindow.right = 256;
|
||||
rectWindow.bottom = 0;
|
||||
AdjustWindowRect(&rectWindow, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, TRUE);
|
||||
AdjustWindowRect(&rectWindow, STYLE_TITLE, TRUE);
|
||||
|
||||
hWnd = CreateWindow(MAKEINTATOM(classAtom),_T("Emu48"),
|
||||
WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED,
|
||||
STYLE_TITLE,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
rectWindow.right - rectWindow.left,
|
||||
rectWindow.bottom - rectWindow.top,
|
||||
|
@ -2242,7 +2223,7 @@ start:
|
|||
|
||||
while (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if( !TranslateAccelerator(hWnd, hAccel, &msg)
|
||||
if ( !TranslateAccelerator(hWnd, hAccel, &msg)
|
||||
&& (hDlgDebug == NULL || !IsDialogMessage(hDlgDebug, &msg))
|
||||
&& (hDlgFind == NULL || !IsDialogMessage(hDlgFind, &msg))
|
||||
&& (hDlgProfile == NULL || !IsDialogMessage(hDlgProfile, &msg))
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||
|
||||
CFG=Emu48 - Win32 DebugRegDebug4x
|
||||
CFG=Emu48 - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
|
@ -13,7 +13,7 @@ CFG=Emu48 - Win32 DebugRegDebug4x
|
|||
!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 "Emu48.mak" CFG="Emu48 - Win32 DebugRegDebug4x"
|
||||
!MESSAGE NMAKE /f "Emu48.mak" CFG="Emu48 - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
|
@ -50,8 +50,8 @@ RSC=rc.exe
|
|||
# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "REGISTRY" /Yu"pch.h" /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x40c /d "NDEBUG"
|
||||
# ADD RSC /l 0x40c /d "NDEBUG"
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
|
@ -76,8 +76,8 @@ LINK32=link.exe
|
|||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "REGISTRY" /FR /Yu"pch.h" /FD /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x40c /d "_DEBUG"
|
||||
# ADD RSC /l 0x40c /d "_DEBUG"
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
|
@ -100,11 +100,11 @@ LINK32=link.exe
|
|||
# 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 "REGISTRY" /D "_UNICODE" /D "UNICODE" /Yu"pch.h" /FD /c
|
||||
# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "REGISTRY" /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"
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
|
@ -127,11 +127,12 @@ LINK32=link.exe
|
|||
# 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 "REGISTRY" /D "_UNICODE" /D "UNICODE" /FR /Yu"pch.h" /FD /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "REGISTRY" /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"
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
# SUBTRACT RSC /x
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
|
@ -143,14 +144,14 @@ LINK32=link.exe
|
|||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "DebugRegDebug4x"
|
||||
# PROP BASE Intermediate_Dir "DebugRegDebug4x"
|
||||
# PROP BASE Output_Dir "Emu48___Win32_DebugRegDebug4x"
|
||||
# PROP BASE Intermediate_Dir "Emu48___Win32_DebugRegDebug4x"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugRegDebug4x"
|
||||
# PROP Intermediate_Dir "DebugRegDebug4x"
|
||||
# PROP Output_Dir ".\DebugRegDebug4x"
|
||||
# PROP Intermediate_Dir ".\DebugRegDebug4x"
|
||||
# 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
|
||||
|
@ -170,14 +171,14 @@ LINK32=link.exe
|
|||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "ReleaseRegDebug4x"
|
||||
# PROP BASE Intermediate_Dir "ReleaseRegDebug4x"
|
||||
# PROP BASE Output_Dir "Emu48___Win32_ReleaseRegDebug4x"
|
||||
# PROP BASE Intermediate_Dir "Emu48___Win32_ReleaseRegDebug4x"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "ReleaseRegDebug4x"
|
||||
# PROP Intermediate_Dir "ReleaseRegDebug4x"
|
||||
# PROP Output_Dir ".\ReleaseRegDebug4x"
|
||||
# PROP Intermediate_Dir ".\ReleaseRegDebug4x"
|
||||
# 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
|
||||
|
@ -280,6 +281,10 @@ SOURCE=.\kml.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lowbat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mops.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -313,6 +318,10 @@ SOURCE=.\settings.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sndenum.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -381,6 +390,10 @@ SOURCE=.\pch.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\snddef.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\types.h
|
||||
# End Source File
|
||||
# End Group
|
||||
|
@ -400,5 +413,9 @@ SOURCE=.\DBGTOOL.BMP
|
|||
SOURCE=.\Emu48.ico
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\EMU48.XML
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -3,7 +3,7 @@ Microsoft Developer Studio Workspace File, Format Version 6.00
|
|||
|
||||
###############################################################################
|
||||
|
||||
Project: "Emu48"=".\Emu48.dsp" - Package Owner=<4>
|
||||
Project: "Emu48"=.\Emu48.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
|
@ -61,7 +61,7 @@
|
|||
|
||||
// window styles
|
||||
#define STYLE_TITLE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED)
|
||||
#define STYLE_NOTITLE (WS_POPUP|WS_CLIPSIBLINGS)
|
||||
#define STYLE_NOTITLE (WS_POPUP|WS_SYSMENU|WS_MINIMIZEBOX|WS_CLIPSIBLINGS)
|
||||
|
||||
// WM_COPYDATA identifier
|
||||
#define CDID_FILENAME 1 // send file name
|
||||
|
@ -154,6 +154,7 @@ extern VOID WriteSettingsInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, INT nValue)
|
|||
extern VOID DelSettingsKey(LPCTSTR lpszSection, LPCTSTR lpszEntry);
|
||||
|
||||
// Display.c
|
||||
extern BOOL bGrayscale;
|
||||
extern UINT nBackgroundX;
|
||||
extern UINT nBackgroundY;
|
||||
extern UINT nBackgroundW;
|
||||
|
@ -161,14 +162,23 @@ extern UINT nBackgroundH;
|
|||
extern UINT nLcdX;
|
||||
extern UINT nLcdY;
|
||||
extern UINT nLcdZoom;
|
||||
extern UINT nGdiXZoom;
|
||||
extern UINT nGdiYZoom;
|
||||
extern HDC hLcdDC;
|
||||
extern HDC hMainDC;
|
||||
extern HDC hAnnunDC;
|
||||
extern BYTE (*GetLineCounter)(VOID);
|
||||
extern VOID (*StartDisplay)(BYTE byInitial);
|
||||
extern VOID (*StopDisplay)(VOID);
|
||||
extern VOID UpdateContrast(BYTE byContrast);
|
||||
extern VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue);
|
||||
extern VOID SetLcdMode(BOOL bMode);
|
||||
extern VOID CreateLcdBitmap(VOID);
|
||||
extern VOID DestroyLcdBitmap(VOID);
|
||||
extern BOOL CreateMainBitmap(LPCTSTR szFilename);
|
||||
extern VOID DestroyMainBitmap(VOID);
|
||||
extern BOOL CreateAnnunBitmap(LPCTSTR szFilename);
|
||||
extern VOID DestroyAnnunBitmap(VOID);
|
||||
extern VOID UpdateDisplayPointers(VOID);
|
||||
extern VOID UpdateMainDisplay(VOID);
|
||||
extern VOID UpdateMenuDisplay(VOID);
|
||||
|
@ -177,9 +187,6 @@ extern VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s);
|
|||
extern VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s);
|
||||
extern VOID UpdateAnnunciators(VOID);
|
||||
extern VOID ResizeWindow(VOID);
|
||||
extern BYTE GetLineCounter(VOID);
|
||||
extern VOID StartDisplay(BYTE byInitial);
|
||||
extern VOID StopDisplay(VOID);
|
||||
|
||||
// Engine.c
|
||||
extern BOOL bInterrupt;
|
||||
|
@ -191,7 +198,6 @@ extern BOOL bKeySlow;
|
|||
extern BOOL bSoundSlow;
|
||||
extern UINT nOpcSlow;
|
||||
extern BOOL bCommInit;
|
||||
extern BOOL bGrayscale;
|
||||
extern CHIPSET Chipset;
|
||||
extern TCHAR szSerialWire[16];
|
||||
extern TCHAR szSerialIr[16];
|
||||
|
@ -283,6 +289,8 @@ extern BOOL GetSaveObjectFilename(LPCTSTR lpstrFilter,LPCTSTR lpstrDefExt);
|
|||
extern WORD WriteStack(UINT nStkLevel,LPBYTE lpBuf,DWORD dwSize);
|
||||
extern BOOL LoadObject(LPCTSTR szFilename);
|
||||
extern BOOL SaveObject(LPCTSTR szFilename);
|
||||
extern BOOL LoadIconFromFile(LPCTSTR szFilename);
|
||||
extern VOID LoadIconDefault(VOID);
|
||||
extern HBITMAP LoadBitmapFile(LPCTSTR szFilename);
|
||||
extern HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol);
|
||||
|
||||
|
@ -320,6 +328,12 @@ extern VOID IOBit(DWORD d, BYTE b, BOOL s);
|
|||
extern VOID ReadIO(BYTE *a, DWORD b, DWORD s, BOOL bUpdate);
|
||||
extern VOID WriteIO(BYTE *a, DWORD b, DWORD s);
|
||||
|
||||
// Lowbat.c
|
||||
extern BOOL bLowBatDisable;
|
||||
extern VOID StartBatMeasure(VOID);
|
||||
extern VOID StopBatMeasure(VOID);
|
||||
extern VOID GetBatteryState(BOOL *pbLBI, BOOL *pbVLBI);
|
||||
|
||||
// Keyboard.c
|
||||
extern DWORD dwKeyMinDelay;
|
||||
extern VOID ScanKeyboard(BOOL bActive, BOOL bReset);
|
||||
|
@ -364,6 +378,9 @@ extern VOID RPL_Push(UINT l,DWORD n);
|
|||
extern VOID External(CHIPSET* w);
|
||||
extern VOID RCKBp(CHIPSET* w);
|
||||
|
||||
// SndEnum.c
|
||||
extern VOID SetSoundDeviceList(HWND hWnd,UINT uDeviceID);
|
||||
|
||||
// Sound.c
|
||||
extern DWORD dwWaveVol;
|
||||
extern DWORD dwWaveTime;
|
||||
|
|
|
@ -106,7 +106,6 @@ BEGIN
|
|||
VERTGUIDE, 14
|
||||
VERTGUIDE, 147
|
||||
VERTGUIDE, 154
|
||||
VERTGUIDE, 161
|
||||
VERTGUIDE, 237
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 127
|
||||
|
@ -115,7 +114,7 @@ BEGIN
|
|||
IDD_CHOOSEKML, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 188
|
||||
RIGHTMARGIN, 208
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 59
|
||||
END
|
||||
|
@ -296,7 +295,7 @@ FONT 8, "MS Sans Serif"
|
|||
BEGIN
|
||||
ICON IDI_EMU48,IDC_STATIC,7,6,20,20,SS_REALSIZEIMAGE
|
||||
LTEXT "",IDC_VERSION,29,6,151,8,NOT WS_GROUP
|
||||
LTEXT "Copyright © 2015 Christoph Gießelink && Sébastien Carlier",
|
||||
LTEXT "Copyright © 2017 Christoph Gießelink && Sébastien Carlier",
|
||||
IDC_STATIC,29,18,181,8
|
||||
DEFPUSHBUTTON "OK",IDOK,215,12,39,14
|
||||
EDITTEXT IDC_LICENSE,7,33,247,112,ES_MULTILINE | ES_AUTOHSCROLL |
|
||||
|
@ -384,18 +383,18 @@ BEGIN
|
|||
GROUPBOX "Serial Ports",IDC_STATIC,161,64,83,50
|
||||
END
|
||||
|
||||
IDD_CHOOSEKML DIALOG DISCARDABLE 0, 0, 195, 66
|
||||
IDD_CHOOSEKML DIALOG DISCARDABLE 0, 0, 215, 66
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Choose Your KML Script"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,138,7,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,138,27,50,14
|
||||
COMBOBOX IDC_KMLSCRIPT,7,47,181,120,CBS_DROPDOWNLIST |
|
||||
DEFPUSHBUTTON "OK",IDOK,158,7,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,158,27,50,14
|
||||
COMBOBOX IDC_KMLSCRIPT,7,47,201,120,CBS_DROPDOWNLIST |
|
||||
CBS_OEMCONVERT | CBS_SORT | WS_VSCROLL | WS_TABSTOP
|
||||
EDITTEXT IDC_EMUDIR,7,17,106,14,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "...",IDC_EMUDIRSEL,113,17,10,14
|
||||
PUSHBUTTON "V",IDC_UPDATE,123,17,10,14
|
||||
EDITTEXT IDC_EMUDIR,7,17,126,14,ES_AUTOHSCROLL
|
||||
PUSHBUTTON "...",IDC_EMUDIRSEL,133,17,10,14
|
||||
PUSHBUTTON "V",IDC_UPDATE,143,17,10,14
|
||||
LTEXT "Emu48 Directory :",IDC_STATIC,7,7,115,8
|
||||
LTEXT "Current KML Script :",IDC_STATIC,7,37,115,8
|
||||
END
|
||||
|
@ -411,9 +410,9 @@ BEGIN
|
|||
IDC_ALWAYSDISPLOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
7,146,139,14
|
||||
GROUPBOX "",IDC_STATIC,7,7,287,36
|
||||
CTEXT "Title of the Script",IDC_TITLE,71,14,158,8
|
||||
CTEXT "by",IDC_STATIC,71,22,158,8
|
||||
CTEXT "The Author",IDC_AUTHOR,71,30,158,8,NOT WS_GROUP
|
||||
CTEXT "Title of the Script",IDC_TITLE,7,14,287,8
|
||||
CTEXT "by",IDC_STATIC,7,22,287,8
|
||||
CTEXT "The Author",IDC_AUTHOR,7,30,287,8,NOT WS_GROUP
|
||||
EDITTEXT IDC_KMLLOG,7,48,287,92,ES_MULTILINE | ES_AUTOHSCROLL |
|
||||
ES_OEMCONVERT | ES_READONLY | WS_VSCROLL | NOT
|
||||
WS_TABSTOP
|
||||
|
@ -692,8 +691,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,5,6,0
|
||||
PRODUCTVERSION 1,5,6,0
|
||||
FILEVERSION 1,5,7,0
|
||||
PRODUCTVERSION 1,5,7,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -709,13 +708,13 @@ BEGIN
|
|||
BLOCK "04090000"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Christoph Gießelink & Sebastien Carlier\0"
|
||||
VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0"
|
||||
VALUE "FileVersion", "1, 5, 6, 0\0"
|
||||
VALUE "FileDescription", "HP38/39/40/48/49/50 Emulator\0"
|
||||
VALUE "FileVersion", "1, 5, 7, 0\0"
|
||||
VALUE "InternalName", "Emu48\0"
|
||||
VALUE "LegalCopyright", "Copyright © 2015\0"
|
||||
VALUE "LegalCopyright", "Copyright © 2017\0"
|
||||
VALUE "OriginalFilename", "Emu48.exe\0"
|
||||
VALUE "ProductName", "Emu48\0"
|
||||
VALUE "ProductVersion", "1, 5, 6, 0\0"
|
||||
VALUE "ProductVersion", "1, 5, 7, 0\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -797,6 +796,8 @@ BEGIN
|
|||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
MENUITEM "&Help Topics", ID_HELP_TOPICS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&About Emu48...", ID_ABOUT
|
||||
END
|
||||
END
|
||||
|
@ -862,6 +863,8 @@ BEGIN
|
|||
END
|
||||
POPUP "&Help"
|
||||
BEGIN
|
||||
MENUITEM "&Help Topics", ID_HELP_TOPICS
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "&About Emu48...", ID_ABOUT
|
||||
END
|
||||
END
|
||||
|
|
|
@ -120,6 +120,10 @@ SOURCE=.\display.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\disrpl.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Emu48.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -164,6 +168,10 @@ SOURCE=.\kml.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lowbat.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mops.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -197,6 +205,10 @@ SOURCE=.\settings.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sndenum.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sound.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -229,6 +241,10 @@ SOURCE=.\debugger.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\disrpl.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Emu48.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -261,6 +277,10 @@ SOURCE=.\pch.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\snddef.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\types.h
|
||||
# End Source File
|
||||
# End Group
|
||||
|
@ -269,6 +289,14 @@ SOURCE=.\types.h
|
|||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CHECKBOX.BMP
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\DBGTOOL.BMP
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Emu48.ico
|
||||
# End Source File
|
||||
# End Group
|
||||
|
|
|
@ -31,8 +31,8 @@ TCHAR szSerialIr[16]; // devicename for IR port
|
|||
|
||||
DWORD dwSXCycles = 82; // SX cpu cycles in interval
|
||||
DWORD dwGXCycles = 123; // GX cpu cycles in interval
|
||||
DWORD dwGPCycles = 123*3; // G+ cpu cycles in interval // CdB for HP: add apples display management
|
||||
DWORD dwG2Cycles = 123*2; // Gii cpu cycles in interval // CdB for HP: add apples display management
|
||||
DWORD dwGPCycles = 123*3; // g+ cpu cycles in interval // CdB for HP: add apples display management
|
||||
DWORD dwG2Cycles = 123*2; // gII cpu cycles in interval // CdB for HP: add apples display management
|
||||
|
||||
// variables for debugger engine
|
||||
HANDLE hEventDebug; // event handle to stop cpu thread
|
||||
|
@ -571,9 +571,10 @@ loop:
|
|||
QueryPerformanceCounter(&lDummyInt);
|
||||
dwSpeedRef = lDummyInt.LowPart;
|
||||
SetHP48Time(); // update HP48 time & date
|
||||
StartTimers();
|
||||
// start display counter/update engine
|
||||
StartDisplay((BYTE)(((Chipset.IORam[LINECOUNT+1]<<4)|Chipset.IORam[LINECOUNT])&0x3F));
|
||||
StartBatMeasure(); // start battery measurement
|
||||
StartTimers();
|
||||
}
|
||||
PCHANGED;
|
||||
while (!bInterrupt)
|
||||
|
@ -631,6 +632,7 @@ loop:
|
|||
_ASSERT(nNextState != SM_RUN);
|
||||
|
||||
StopDisplay(); // stop display counter/update
|
||||
StopBatMeasure(); // stop battery measurement
|
||||
StopTimers();
|
||||
|
||||
while (nNextState == SM_SLEEP) // go into sleep state
|
||||
|
|
|
@ -4,14 +4,13 @@
|
|||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1995 Sebastien Carlier
|
||||
* Copyright (C) 2005 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "ops.h"
|
||||
|
||||
#define SAMPLES_PER_SEC 44100 // sound sampling rate
|
||||
|
||||
//| 38G | 39G | 40G | 48SX | 48GX | 49G | Name
|
||||
//#F0E4F #80F0F #80F0F #706D2 #80850 #80F0F =SFLAG53_56
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ static TREENODE *nodePatch = NULL;
|
|||
|
||||
static BOOL PatchNibble(DWORD dwAddress, BYTE byPatch)
|
||||
{
|
||||
TREENODE *p;
|
||||
PTREENODE p;
|
||||
|
||||
_ASSERT(pbyRom); // ROM defined
|
||||
if ((p = (PTREENODE) malloc(sizeof(TREENODE))) == NULL)
|
||||
|
@ -830,7 +830,7 @@ BOOL NewDocument(VOID)
|
|||
// use 2nd command line argument if defined
|
||||
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
||||
}
|
||||
if (Chipset.type == 'X' || Chipset.type == '2' || Chipset.type == 'Q') // HP49G/HP48Gii/HP49G+ // CdB for HP: add apples
|
||||
if (Chipset.type == 'X' || Chipset.type == '2' || Chipset.type == 'Q') // HP49G/HP48gII/HP49g+/50g // CdB for HP: add apples
|
||||
{
|
||||
Chipset.Port0Size = 256;
|
||||
Chipset.Port1Size = 128;
|
||||
|
@ -841,11 +841,11 @@ BOOL NewDocument(VOID)
|
|||
|
||||
FlashInit(); // init flash structure
|
||||
}
|
||||
if (Chipset.type == 'Q') // HP49G+ // CdB for HP: add apples
|
||||
|
||||
if (Chipset.type == 'Q') // HP49g+/50g // CdB for HP: add apples
|
||||
{
|
||||
Chipset.d0size = 16;
|
||||
}
|
||||
|
||||
Chipset.IORam[LPE] = RST; // set ReSeT bit at power on reset
|
||||
|
||||
// allocate port memory
|
||||
|
@ -861,7 +861,7 @@ BOOL NewDocument(VOID)
|
|||
}
|
||||
if (Chipset.Port2Size)
|
||||
{
|
||||
Port2 = (LPBYTE) calloc(Chipset.Port2Size*2048,sizeof(*Port2));
|
||||
Port2 = (LPBYTE) calloc(Chipset.Port2Size*2048,sizeof(*Port1));
|
||||
_ASSERT(Port2 != NULL);
|
||||
}
|
||||
LoadBreakpointList(NULL); // clear debugger breakpoint list
|
||||
|
@ -873,14 +873,13 @@ restore:
|
|||
ResetBackup();
|
||||
|
||||
// HP48SX/GX
|
||||
if(Chipset.type == 'S' || Chipset.type == 'G')
|
||||
if (Chipset.type == 'S' || Chipset.type == 'G')
|
||||
{
|
||||
// use 2nd command line argument if defined
|
||||
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
||||
}
|
||||
if (pbyRom)
|
||||
{
|
||||
SetWindowLocation(hWnd,Chipset.nPosX,Chipset.nPosY);
|
||||
Map(0x00,0xFF);
|
||||
}
|
||||
return FALSE;
|
||||
|
@ -1060,7 +1059,7 @@ BOOL OpenDocument(LPCTSTR szFilename)
|
|||
}
|
||||
|
||||
// HP48SX/GX
|
||||
if(cCurrentRomType=='S' || cCurrentRomType=='G')
|
||||
if (cCurrentRomType=='S' || cCurrentRomType=='G')
|
||||
{
|
||||
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
||||
// port2 changed and card detection enabled
|
||||
|
@ -1128,7 +1127,7 @@ restore:
|
|||
ResetBackup();
|
||||
|
||||
// HP48SX/GX
|
||||
if(cCurrentRomType=='S' || cCurrentRomType=='G')
|
||||
if (cCurrentRomType=='S' || cCurrentRomType=='G')
|
||||
{
|
||||
// use 2nd command line argument if defined
|
||||
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
|
||||
|
@ -1400,12 +1399,12 @@ BOOL GetSaveAsFilename(VOID)
|
|||
ofn.lpstrDefExt = _T("e38");
|
||||
ofn.nFilterIndex = 1;
|
||||
}
|
||||
if (cCurrentRomType=='E' || cCurrentRomType=='P') // HP39/40G/hp439G+ // CdB for HP: add apples
|
||||
if (cCurrentRomType=='E' || cCurrentRomType=='P') // HP39/40 // CdB for HP: add apples
|
||||
{
|
||||
ofn.lpstrDefExt = _T("e39");
|
||||
ofn.nFilterIndex = 2;
|
||||
}
|
||||
if (cCurrentRomType=='X' || cCurrentRomType=='2' || cCurrentRomType=='Q') // HP49G/HP48Gii/HP49G+ // CdB for HP: add apples
|
||||
if (cCurrentRomType=='X' || cCurrentRomType=='2' || cCurrentRomType=='Q') // HP49G/HP48gII/HP49g+/HP50g // CdB for HP: add apples
|
||||
{
|
||||
ofn.lpstrDefExt = _T("e49");
|
||||
ofn.nFilterIndex = 4;
|
||||
|
@ -1446,7 +1445,7 @@ BOOL GetSaveObjectFilename(LPCTSTR lpstrFilter,LPCTSTR lpstrDefExt)
|
|||
|
||||
InitializeOFN(&ofn);
|
||||
ofn.lpstrFilter = lpstrFilter;
|
||||
ofn.lpstrDefExt = lpstrDefExt;
|
||||
ofn.lpstrDefExt = NULL;
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.lpstrFile = szBuffer;
|
||||
ofn.lpstrFile[0] = 0;
|
||||
|
@ -1455,6 +1454,19 @@ BOOL GetSaveObjectFilename(LPCTSTR lpstrFilter,LPCTSTR lpstrDefExt)
|
|||
if (GetSaveFileName(&ofn) == FALSE) return FALSE;
|
||||
_ASSERT(ARRAYSIZEOF(szBufferFilename) == ofn.nMaxFile);
|
||||
lstrcpy(szBufferFilename, ofn.lpstrFile);
|
||||
if (ofn.nFileExtension == 0) // given filename has no extension
|
||||
{
|
||||
// actual name length
|
||||
UINT nLength = lstrlen(szBufferFilename);
|
||||
|
||||
// destination buffer has room for the default extension
|
||||
if (nLength + 1 + lstrlen(lpstrDefExt) < ARRAYSIZEOF(szBufferFilename))
|
||||
{
|
||||
// add default extension
|
||||
szBufferFilename[nLength++] = _T('.');
|
||||
lstrcpy(&szBufferFilename[nLength], lpstrDefExt);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1595,6 +1607,39 @@ BOOL SaveObject(LPCTSTR szFilename) // separated stack reading part
|
|||
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Load Icon
|
||||
//#
|
||||
//################
|
||||
|
||||
BOOL LoadIconFromFile(LPCTSTR szFilename)
|
||||
{
|
||||
HANDLE hIcon;
|
||||
|
||||
SetCurrentDirectory(szEmuDirectory);
|
||||
// not necessary to destroy because icon is shared
|
||||
hIcon = LoadImage(NULL, szFilename, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE|LR_LOADFROMFILE|LR_SHARED);
|
||||
SetCurrentDirectory(szCurrentDirectory);
|
||||
|
||||
if (hIcon)
|
||||
{
|
||||
SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIcon);
|
||||
SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
|
||||
}
|
||||
return hIcon != NULL;
|
||||
}
|
||||
|
||||
VOID LoadIconDefault(VOID)
|
||||
{
|
||||
// use window class icon
|
||||
SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) NULL);
|
||||
SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Load Bitmap
|
||||
|
@ -2325,7 +2370,7 @@ HBITMAP LoadBitmapFile(LPCTSTR szFilename)
|
|||
if ( Bmp.dwFileSize >= 6
|
||||
&& (memcmp(Bmp.pbyFile,"GIF87a",6) == 0 || memcmp(Bmp.pbyFile,"GIF89a",6) == 0))
|
||||
{
|
||||
hBitmap = DecodeGif(&Bmp,NULL);
|
||||
hBitmap = DecodeGif(&Bmp,&dwTColor);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
172
source/KML.C
172
source/KML.C
|
@ -76,15 +76,18 @@ static CONST KmlToken pLexToken[] =
|
|||
{TOK_VIRTUAL, 000000, 7,_T("Virtual")},
|
||||
{TOK_INCLUDE, 000002, 7,_T("Include")},
|
||||
{TOK_NOTFLAG, 000001, 7,_T("NotFlag")},
|
||||
{TOK_MENUBAR, 000001, 7,_T("Menubar")}, // for PPC compatibility reasons
|
||||
{TOK_GLOBAL, 000000, 6,_T("Global")},
|
||||
{TOK_AUTHOR, 000002, 6,_T("Author")},
|
||||
{TOK_BITMAP, 000002, 6,_T("Bitmap")},
|
||||
{TOK_OFFSET, 000011, 6,_T("Offset")},
|
||||
{TOK_ZOOMXY, 000011, 6,_T("Zoomxy")},
|
||||
{TOK_BUTTON, 000001, 6,_T("Button")},
|
||||
{TOK_IFFLAG, 000001, 6,_T("IfFlag")},
|
||||
{TOK_ONDOWN, 000000, 6,_T("OnDown")},
|
||||
{TOK_NOHOLD, 000000, 6,_T("NoHold")},
|
||||
{TOK_LOCALE, 000001, 6,_T("Locale")},
|
||||
{TOK_TOPBAR, 000001, 6,_T("Topbar")}, // for PPC compatibility reasons
|
||||
{TOK_TITLE, 000002, 5,_T("Title")},
|
||||
{TOK_OUTIN, 000011, 5,_T("OutIn")},
|
||||
{TOK_PATCH, 000002, 5,_T("Patch")},
|
||||
|
@ -95,14 +98,17 @@ static CONST KmlToken pLexToken[] =
|
|||
{TOK_CLASS, 000001, 5,_T("Class")},
|
||||
{TOK_PRESS, 000001, 5,_T("Press")},
|
||||
{TOK_IFMEM, 000111, 5,_T("IfMem")},
|
||||
{TOK_SCALE, 000011, 5,_T("Scale")},
|
||||
{TOK_TYPE, 000001, 4,_T("Type")},
|
||||
{TOK_SIZE, 000011, 4,_T("Size")},
|
||||
{TOK_ZOOM, 000001, 4,_T("Zoom")},
|
||||
{TOK_DOWN, 000011, 4,_T("Down")},
|
||||
{TOK_ELSE, 000000, 4,_T("Else")},
|
||||
{TOK_ONUP, 000000, 4,_T("OnUp")},
|
||||
{TOK_ICON, 000002, 4,_T("Icon")},
|
||||
{TOK_MAP, 000011, 3,_T("Map")},
|
||||
{TOK_ROM, 000002, 3,_T("Rom")},
|
||||
{TOK_VGA, 000001, 3,_T("Vga")}, // for PPC compatibility reasons
|
||||
{TOK_LCD, 000000, 3,_T("Lcd")},
|
||||
{TOK_END, 000000, 3,_T("End")},
|
||||
{TOK_NONE, 000000, 0,_T("")}
|
||||
|
@ -134,6 +140,9 @@ static UINT uButtonClicked = 0;
|
|||
static BOOL bKeyPressed = FALSE; // no key pressed
|
||||
static UINT uLastKeyPressed = 0; // var for last pressed key
|
||||
|
||||
static INT nScaleMul = 0; // no scaling
|
||||
static INT nScaleDiv = 0;
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Compilation Result
|
||||
|
@ -1239,6 +1248,14 @@ static VOID InitGlobal(KmlBlock* pBlock)
|
|||
nCurrentClass = (UINT) pLine->nParam[0];
|
||||
PrintfToLog(_T("Calculator Class : %u"), nCurrentClass);
|
||||
break;
|
||||
case TOK_ICON:
|
||||
if (!LoadIconFromFile((LPTSTR) pLine->nParam[0]))
|
||||
{
|
||||
PrintfToLog(_T("Cannot load Icon %s."), (LPTSTR)pLine->nParam[0]);
|
||||
break;
|
||||
}
|
||||
PrintfToLog(_T("Icon %s loaded."), (LPTSTR)pLine->nParam[0]);
|
||||
break;
|
||||
case TOK_DEBUG:
|
||||
bDebug = (BOOL) pLine->nParam[0]&1;
|
||||
PrintfToLog(_T("Debug %s"), bDebug?_T("On"):_T("Off"));
|
||||
|
@ -1287,6 +1304,10 @@ static VOID InitGlobal(KmlBlock* pBlock)
|
|||
dwTColorTol = (DWORD) pLine->nParam[0];
|
||||
dwTColor = RGB((BYTE) pLine->nParam[1],(BYTE) pLine->nParam[2],(BYTE) pLine->nParam[3]);
|
||||
break;
|
||||
case TOK_SCALE:
|
||||
nScaleMul = (INT) pLine->nParam[0];
|
||||
nScaleDiv = (INT) pLine->nParam[1];
|
||||
break;
|
||||
default:
|
||||
PrintfToLog(_T("Command %s Ignored in Block %s"), GetStringOf(pLine->eCommand), GetStringOf(pBlock->eType));
|
||||
}
|
||||
|
@ -1332,13 +1353,45 @@ static KmlLine* InitLcd(KmlBlock* pBlock)
|
|||
nLcdY = (UINT) pLine->nParam[1];
|
||||
break;
|
||||
case TOK_ZOOM:
|
||||
if ((nLcdZoom = (UINT) pLine->nParam[0]) == 0)
|
||||
nLcdZoom = 1;
|
||||
if ((nGdiXZoom = (UINT) pLine->nParam[0]) == 0)
|
||||
nGdiXZoom = 1; // default zoom
|
||||
|
||||
// search for memory DC zoom (1-4)
|
||||
for (nLcdZoom = 4; (nGdiXZoom % nLcdZoom) != 0; --nLcdZoom) { };
|
||||
_ASSERT(nLcdZoom > 0); // because (nGdiXZoom % 1) == 0
|
||||
nGdiXZoom /= nLcdZoom; // remainder is GDI zoom
|
||||
nGdiYZoom = nGdiXZoom;
|
||||
break;
|
||||
case TOK_ZOOMXY:
|
||||
if ((nGdiXZoom = (UINT) pLine->nParam[0]) == 0)
|
||||
nGdiXZoom = 1; // default zoom
|
||||
if ((nGdiYZoom = (UINT) pLine->nParam[1]) == 0)
|
||||
nGdiYZoom = 1; // default zoom
|
||||
|
||||
// search for memory DC zoom (1-4)
|
||||
for (nLcdZoom = 4; ((nGdiXZoom % nLcdZoom) | (nGdiYZoom % nLcdZoom)) != 0 ; --nLcdZoom) { };
|
||||
_ASSERT(nLcdZoom > 0); // because (nGdiYZoom % 1) == 0 && (nGdiYZoom % 1) == 0
|
||||
nGdiXZoom /= nLcdZoom; // remainder is GDI zoom
|
||||
nGdiYZoom /= nLcdZoom;
|
||||
break;
|
||||
case TOK_COLOR:
|
||||
SetLcdColor((UINT) pLine->nParam[0],(UINT) pLine->nParam[1],
|
||||
(UINT) pLine->nParam[2],(UINT) pLine->nParam[3]);
|
||||
break;
|
||||
case TOK_BITMAP:
|
||||
if (hAnnunDC != NULL)
|
||||
{
|
||||
PrintfToLog(_T("Bitmap %s ignored."), (LPCTSTR)pLine->nParam[0]);
|
||||
AddToLog(_T("Please put only one Bitmap command in the Lcd block."));
|
||||
break;
|
||||
}
|
||||
if (!CreateAnnunBitmap((LPCTSTR)pLine->nParam[0]))
|
||||
{
|
||||
PrintfToLog(_T("Cannot load Annunciator Bitmap %s."), (LPCTSTR)pLine->nParam[0]);
|
||||
break;
|
||||
}
|
||||
PrintfToLog(_T("Annunciator Bitmap %s loaded."), (LPCTSTR)pLine->nParam[0]);
|
||||
break;
|
||||
case TOK_END:
|
||||
return pLine;
|
||||
default:
|
||||
|
@ -1628,6 +1681,7 @@ VOID KillKML(VOID)
|
|||
}
|
||||
UnmapRom();
|
||||
DestroyLcdBitmap();
|
||||
DestroyAnnunBitmap();
|
||||
DestroyMainBitmap();
|
||||
if (hPalette)
|
||||
{
|
||||
|
@ -1649,6 +1703,7 @@ VOID KillKML(VOID)
|
|||
}
|
||||
hRgn = NULL;
|
||||
}
|
||||
LoadIconDefault();
|
||||
bClicking = FALSE;
|
||||
uButtonClicked = 0;
|
||||
FreeBlocks(pKml);
|
||||
|
@ -1670,8 +1725,12 @@ VOID KillKML(VOID)
|
|||
nBackgroundW = 256;
|
||||
nBackgroundH = 0;
|
||||
nLcdZoom = 1;
|
||||
nGdiXZoom = 1;
|
||||
nGdiYZoom = 1;
|
||||
dwTColor = (DWORD) -1;
|
||||
dwTColorTol = 0;
|
||||
nScaleMul = 0;
|
||||
nScaleDiv = 0;
|
||||
cCurrentRomType = 0;
|
||||
nCurrentClass = 0;
|
||||
ResizeWindow();
|
||||
|
@ -2065,17 +2124,22 @@ VOID RefreshButtons(RECT *rc)
|
|||
|
||||
VOID DrawAnnunciator(UINT nId, BOOL bOn)
|
||||
{
|
||||
HDC hDC;
|
||||
UINT nSx,nSy;
|
||||
|
||||
--nId; // zero based ID
|
||||
if (nId >= ARRAYSIZEOF(pAnnunciator)) return;
|
||||
if (bOn)
|
||||
{
|
||||
hDC = hAnnunDC != NULL ? hAnnunDC : hMainDC;
|
||||
|
||||
nSx = pAnnunciator[nId].nDx; // position of annunciator
|
||||
nSy = pAnnunciator[nId].nDy;
|
||||
}
|
||||
else
|
||||
{
|
||||
hDC = hMainDC;
|
||||
|
||||
nSx = pAnnunciator[nId].nOx; // position of background
|
||||
nSy = pAnnunciator[nId].nOy;
|
||||
}
|
||||
|
@ -2084,7 +2148,7 @@ VOID DrawAnnunciator(UINT nId, BOOL bOn)
|
|||
BitBlt(hWindowDC,
|
||||
pAnnunciator[nId].nOx, pAnnunciator[nId].nOy,
|
||||
pAnnunciator[nId].nCx, pAnnunciator[nId].nCy,
|
||||
hMainDC,
|
||||
hDC,
|
||||
nSx, nSy,
|
||||
SRCCOPY);
|
||||
GdiFlush();
|
||||
|
@ -2280,6 +2344,105 @@ VOID PlayKey(UINT nOut, UINT nIn, BOOL bPressed)
|
|||
//#
|
||||
//################
|
||||
|
||||
static VOID ResizeMainBitmap(INT nMul, INT nDiv)
|
||||
{
|
||||
if (nMul * nDiv > 0) // resize main picture
|
||||
{
|
||||
BITMAP Bitmap;
|
||||
int nMode;
|
||||
INT nWidth,nHeight;
|
||||
UINT i;
|
||||
|
||||
// update graphic
|
||||
nBackgroundX = MulDiv(nBackgroundX,nMul,nDiv);
|
||||
nBackgroundY = MulDiv(nBackgroundY,nMul,nDiv);
|
||||
nBackgroundW = MulDiv(nBackgroundW,nMul,nDiv);
|
||||
nBackgroundH = MulDiv(nBackgroundH,nMul,nDiv);
|
||||
nLcdX = MulDiv(nLcdX,nMul,nDiv);
|
||||
nLcdY = MulDiv(nLcdY,nMul,nDiv);
|
||||
nGdiXZoom = MulDiv(nGdiXZoom * nLcdZoom,nMul,nDiv);
|
||||
nGdiYZoom = MulDiv(nGdiYZoom * nLcdZoom,nMul,nDiv);
|
||||
|
||||
// search for memory DC zoom (1-4)
|
||||
for (nLcdZoom = 4; ((nGdiXZoom % nLcdZoom) | (nGdiYZoom % nLcdZoom)) != 0 ; --nLcdZoom) { };
|
||||
_ASSERT(nLcdZoom > 0); // because (nGdiYZoom % 1) == 0 && (nGdiYZoom % 1) == 0
|
||||
nGdiXZoom /= nLcdZoom; // remainder is GDI zoom
|
||||
nGdiYZoom /= nLcdZoom;
|
||||
|
||||
// update script coordinates (buttons)
|
||||
for (i = 0; i < nButtons; ++i)
|
||||
{
|
||||
pButton[i].nOx = (UINT) (pButton[i].nOx * nMul / nDiv);
|
||||
pButton[i].nOy = (UINT) (pButton[i].nOy * nMul / nDiv);
|
||||
pButton[i].nDx = (UINT) (pButton[i].nDx * nMul / nDiv);
|
||||
pButton[i].nDy = (UINT) (pButton[i].nDy * nMul / nDiv);
|
||||
pButton[i].nCx = (UINT) (pButton[i].nCx * nMul / nDiv);
|
||||
pButton[i].nCy = (UINT) (pButton[i].nCy * nMul / nDiv);
|
||||
}
|
||||
|
||||
// update script coordinates (annunciators)
|
||||
for (i = 0; i < ARRAYSIZEOF(pAnnunciator); ++i)
|
||||
{
|
||||
// translate offset
|
||||
pAnnunciator[i].nOx = (UINT) (pAnnunciator[i].nOx * nMul / nDiv);
|
||||
pAnnunciator[i].nOy = (UINT) (pAnnunciator[i].nOy * nMul / nDiv);
|
||||
|
||||
if (hAnnunDC == NULL) // no external annunciator bitmap
|
||||
{
|
||||
// translate down (with rounding)
|
||||
pAnnunciator[i].nDx = (UINT) MulDiv(pAnnunciator[i].nDx,nMul,nDiv);
|
||||
pAnnunciator[i].nDy = (UINT) MulDiv(pAnnunciator[i].nDy,nMul,nDiv);
|
||||
// translate size (with rounding)
|
||||
pAnnunciator[i].nCx = (UINT) MulDiv(pAnnunciator[i].nCx,nMul,nDiv);
|
||||
pAnnunciator[i].nCy = (UINT) MulDiv(pAnnunciator[i].nCy,nMul,nDiv);
|
||||
}
|
||||
}
|
||||
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
// get bitmap size
|
||||
GetObject(GetCurrentObject(hMainDC,OBJ_BITMAP),sizeof(Bitmap),&Bitmap);
|
||||
|
||||
// resulting bitmap size
|
||||
nWidth = MulDiv(Bitmap.bmWidth,nMul,nDiv);
|
||||
nHeight = MulDiv(Bitmap.bmHeight,nMul,nDiv);
|
||||
|
||||
VERIFY(nMode = SetStretchBltMode(hMainDC,HALFTONE));
|
||||
|
||||
if (nMul <= nDiv) // shrinking bitmap
|
||||
{
|
||||
VERIFY(StretchBlt(
|
||||
hMainDC,0,0,nWidth,nHeight,
|
||||
hMainDC,0,0,Bitmap.bmWidth,Bitmap.bmHeight,
|
||||
SRCCOPY));
|
||||
}
|
||||
else // expanding bitmap
|
||||
{
|
||||
// bitmap with new size
|
||||
HDC hMemDC = CreateCompatibleDC(hMainDC);
|
||||
HBITMAP hMainBitMap = CreateCompatibleBitmap(hMainDC,nWidth,nHeight);
|
||||
HBITMAP hMemBitMap = (HBITMAP) SelectObject(hMemDC,SelectObject(hMainDC,hMainBitMap));
|
||||
|
||||
VERIFY(StretchBlt(
|
||||
hMainDC,0,0,nWidth,nHeight,
|
||||
hMemDC,0,0,Bitmap.bmWidth,Bitmap.bmHeight,
|
||||
SRCCOPY));
|
||||
|
||||
// delete original bitmap
|
||||
VERIFY(DeleteObject(SelectObject(hMemDC,hMemBitMap)));
|
||||
DeleteDC(hMemDC);
|
||||
}
|
||||
|
||||
VERIFY(SetStretchBltMode(hMainDC,nMode));
|
||||
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
ResizeWindow();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static KmlBlock* LoadKMLGlobal(LPCTSTR szFilename)
|
||||
{
|
||||
HANDLE hFile;
|
||||
|
@ -2418,6 +2581,7 @@ BOOL InitKML(LPCTSTR szFilename, BOOL bNoLog)
|
|||
goto quit;
|
||||
}
|
||||
|
||||
ResizeMainBitmap(nScaleMul,nScaleDiv); // resize main picture
|
||||
CreateLcdBitmap();
|
||||
|
||||
PrintfToLog(_T("%i Buttons Defined"), nButtons);
|
||||
|
@ -2430,7 +2594,7 @@ BOOL InitKML(LPCTSTR szFilename, BOOL bNoLog)
|
|||
quit:
|
||||
if (bOk)
|
||||
{
|
||||
// HP38G/HP39G(+)/HP40G have no object loading, ignore // CdB for HP: add apples
|
||||
// HP38G/HP39G(+|s)/HP40G(s) have no object loading, ignore // CdB for HP: add apples
|
||||
DragAcceptFiles(hWnd,cCurrentRomType != '6' && cCurrentRomType != 'A' && cCurrentRomType != 'E' && cCurrentRomType != 'P');
|
||||
|
||||
if (!bNoLog)
|
||||
|
|
62
source/KML.H
62
source/KML.H
|
@ -32,35 +32,39 @@ typedef enum eTokenId
|
|||
TOK_GLOBAL, //16
|
||||
TOK_AUTHOR, //17
|
||||
TOK_BITMAP, //18
|
||||
TOK_OFFSET, //19
|
||||
TOK_BUTTON, //20
|
||||
TOK_IFFLAG, //21
|
||||
TOK_ONDOWN, //22
|
||||
TOK_NOHOLD, //23
|
||||
TOK_LOCALE, //24
|
||||
TOK_TOPBAR, //25
|
||||
TOK_TITLE, //26
|
||||
TOK_OUTIN, //27
|
||||
TOK_PATCH, //28
|
||||
TOK_PRINT, //29
|
||||
TOK_DEBUG, //30
|
||||
TOK_COLOR, //31
|
||||
TOK_MODEL, //32
|
||||
TOK_CLASS, //33
|
||||
TOK_PRESS, //34
|
||||
TOK_IFMEM, //35
|
||||
TOK_TYPE, //36
|
||||
TOK_SIZE, //37
|
||||
TOK_DOWN, //38
|
||||
TOK_ZOOM, //39
|
||||
TOK_ELSE, //40
|
||||
TOK_ONUP, //41
|
||||
TOK_EOL, //42
|
||||
TOK_MAP, //43
|
||||
TOK_ROM, //44
|
||||
TOK_VGA, //45
|
||||
TOK_LCD, //46
|
||||
TOK_END //47
|
||||
TOK_ZOOMXY, //19
|
||||
TOK_OFFSET, //20
|
||||
TOK_BUTTON, //21
|
||||
TOK_IFFLAG, //22
|
||||
TOK_ONDOWN, //23
|
||||
TOK_NOHOLD, //24
|
||||
TOK_LOCALE, //25
|
||||
TOK_TOPBAR, //26
|
||||
TOK_MENUBAR, //27
|
||||
TOK_TITLE, //28
|
||||
TOK_OUTIN, //29
|
||||
TOK_PATCH, //30
|
||||
TOK_PRINT, //31
|
||||
TOK_DEBUG, //32
|
||||
TOK_COLOR, //33
|
||||
TOK_MODEL, //34
|
||||
TOK_CLASS, //35
|
||||
TOK_PRESS, //36
|
||||
TOK_IFMEM, //37
|
||||
TOK_SCALE, //38
|
||||
TOK_TYPE, //39
|
||||
TOK_SIZE, //40
|
||||
TOK_DOWN, //41
|
||||
TOK_ZOOM, //42
|
||||
TOK_ELSE, //43
|
||||
TOK_ONUP, //44
|
||||
TOK_ICON, //45
|
||||
TOK_EOL, //46
|
||||
TOK_MAP, //47
|
||||
TOK_ROM, //48
|
||||
TOK_VGA, //49
|
||||
TOK_LCD, //50
|
||||
TOK_END //51
|
||||
} TokenId;
|
||||
|
||||
#define TYPE_NONE 00
|
||||
|
|
122
source/LOWBAT.C
Normal file
122
source/LOWBAT.C
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* lowbat.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2006 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h" // I/O definitions
|
||||
|
||||
// #define BAT_SIMULATION // switch low bat simulation
|
||||
|
||||
#define BAT_FREQ (60*1000) // bat update time in ms (real machine = 60us, HP28C = 60s)
|
||||
|
||||
BOOL bLowBatDisable = FALSE;
|
||||
|
||||
static HANDLE hCThreadBat = NULL;
|
||||
static HANDLE hEventBat;
|
||||
|
||||
static DWORD WINAPI LowBatThread(LPVOID pParam)
|
||||
{
|
||||
BOOL bLBI,bVLBI;
|
||||
|
||||
do
|
||||
{
|
||||
GetBatteryState(&bLBI,&bVLBI); // get battery state
|
||||
|
||||
// very low bat detection
|
||||
bVLBI = bVLBI && (Chipset.IORam[LPE] & EVLBI) != 0;
|
||||
|
||||
IOBit(LPD,VLBI,bVLBI); // set VLBI
|
||||
IOBit(SRQ1,VSRQ,bVLBI); // and service bit
|
||||
|
||||
if (bVLBI) // VLBI detected
|
||||
{
|
||||
Chipset.SoftInt = TRUE;
|
||||
bInterrupt = TRUE;
|
||||
|
||||
if (Chipset.Shutdn) // CPU shut down
|
||||
{
|
||||
Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode
|
||||
SetEvent(hEventShutdn); // wake up emulation thread
|
||||
}
|
||||
}
|
||||
}
|
||||
while (WaitForSingleObject(hEventBat,BAT_FREQ) == WAIT_TIMEOUT);
|
||||
|
||||
return 0;
|
||||
UNREFERENCED_PARAMETER(pParam);
|
||||
}
|
||||
|
||||
VOID StartBatMeasure(VOID)
|
||||
{
|
||||
DWORD dwThreadId;
|
||||
|
||||
if (hCThreadBat) // Bat measuring thread running
|
||||
return; // -> quit
|
||||
|
||||
// event to cancel Bat refresh loop
|
||||
hEventBat = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||
|
||||
VERIFY(hCThreadBat = CreateThread(NULL,0,&LowBatThread,NULL,0,&dwThreadId));
|
||||
return;
|
||||
}
|
||||
|
||||
VOID StopBatMeasure(VOID)
|
||||
{
|
||||
if (hCThreadBat == NULL) // thread stopped
|
||||
return; // -> quit
|
||||
|
||||
SetEvent(hEventBat); // leave Bat update thread
|
||||
WaitForSingleObject(hCThreadBat,INFINITE);
|
||||
CloseHandle(hCThreadBat);
|
||||
hCThreadBat = NULL; // set flag Bat update stopped
|
||||
CloseHandle(hEventBat); // close Bat event
|
||||
return;
|
||||
}
|
||||
|
||||
VOID GetBatteryState(BOOL *pbLBI, BOOL *pbVLBI)
|
||||
{
|
||||
#if defined BAT_SIMULATION
|
||||
switch (GetPrivateProfileInt(_T("LowBat"),_T("Level"),2,_T(".\\Lowbat.ini")))
|
||||
{
|
||||
case 0: // empty
|
||||
*pbLBI = TRUE;
|
||||
*pbVLBI = TRUE;
|
||||
break;
|
||||
case 1: // low
|
||||
*pbLBI = TRUE;
|
||||
*pbVLBI = FALSE;
|
||||
break;
|
||||
default: // full
|
||||
*pbLBI = FALSE;
|
||||
*pbVLBI = FALSE;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
SYSTEM_POWER_STATUS sSps;
|
||||
|
||||
*pbLBI = FALSE; // no battery warning
|
||||
*pbVLBI = FALSE;
|
||||
|
||||
VERIFY(GetSystemPowerStatus(&sSps));
|
||||
|
||||
// low bat emulation enabled and battery powered
|
||||
if (!bLowBatDisable && sSps.ACLineStatus == AC_LINE_OFFLINE)
|
||||
{
|
||||
// on critical battery state make sure that lowbat flag is also set
|
||||
if ((sSps.BatteryFlag & BATTERY_FLAG_CRITICAL) != 0)
|
||||
sSps.BatteryFlag |= BATTERY_FLAG_LOW;
|
||||
|
||||
// low bat detection
|
||||
*pbLBI = ((sSps.BatteryFlag & BATTERY_FLAG_LOW) != 0);
|
||||
|
||||
// very low bat detection
|
||||
*pbVLBI = ((sSps.BatteryFlag & BATTERY_FLAG_CRITICAL) != 0);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
|
@ -326,7 +326,7 @@ static VOID MapROM(BYTE a, BYTE b)
|
|||
UINT i;
|
||||
DWORD p, m;
|
||||
|
||||
// HP39(+)/40G, HP49G(+) HP48Gii // CdB for HP: add apples memory
|
||||
// HP39(+)/40G, HP49G/g+ HP48gII // CdB for HP: add apples memory
|
||||
if (cCurrentRomType == 'E' || cCurrentRomType == 'X' || cCurrentRomType == 'P' || cCurrentRomType == '2' || cCurrentRomType == 'Q')
|
||||
{
|
||||
if (bFlashRomArray) // view flash ROM data
|
||||
|
@ -397,7 +397,7 @@ VOID Map(BYTE a, BYTE b) // maps 2KB pages with priority
|
|||
}
|
||||
if (Chipset.P0Cfig) MapP0(a,b); // RAM, highest priority (execpt HDW)
|
||||
// CdB for HP: add apples header
|
||||
// @todo cg, bug if display header area is mapped to addr 0
|
||||
// @todo cg, bug if display header area is mapped to addr 0
|
||||
if (Chipset.d0address!=0)
|
||||
{
|
||||
RMap[Chipset.d0address]=&(Chipset.d0memory[0]); RMap[Chipset.d0address+1]=&(Chipset.d0memory[2048*2]);
|
||||
|
@ -760,8 +760,9 @@ VOID Npeek(BYTE *a, DWORD d, UINT s)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (s-=c) {a+=c; d=(d+c)&0xFFFFF;}
|
||||
} while (s);
|
||||
a+=c;
|
||||
d=(d+c)&0xFFFFF;
|
||||
} while (s-=c);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -850,8 +851,9 @@ VOID Nread(BYTE *a, DWORD d, UINT s)
|
|||
for (u=0; u<c; u++) // update CRC
|
||||
UpCRC(a[u]);
|
||||
}
|
||||
if (s-=c) {a+=c; d=(d+c)&0xFFFFF;}
|
||||
} while (s);
|
||||
a+=c;
|
||||
d=(d+c)&0xFFFFF;
|
||||
} while (s-=c);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -941,8 +943,7 @@ VOID Nwrite(BYTE *a, DWORD d, UINT s)
|
|||
if ((p=WMap[u]) != NULL) memcpy(p+v, a, c);
|
||||
}
|
||||
}
|
||||
if (!bGrayscale)
|
||||
UpdateDisplay(d, c); // update display
|
||||
if (!bGrayscale) UpdateDisplay(d, c); // update display
|
||||
a+=c;
|
||||
d=(d+c)&0xFFFFF;
|
||||
} while (s-=c);
|
||||
|
@ -1020,8 +1021,8 @@ static DWORD ReadT2Acc(VOID)
|
|||
|
||||
VOID ReadIO(BYTE *a, DWORD d, DWORD s, BOOL bUpdate)
|
||||
{
|
||||
BOOL bNINT;
|
||||
BOOL bNINT2;
|
||||
BOOL bNINT,bNINT2;
|
||||
BOOL bLBI,bVLBI;
|
||||
|
||||
BYTE c = 0xFF; // LINECOUNT not initialized
|
||||
BOOL rbr_acc = FALSE; // flag to receive data
|
||||
|
@ -1046,7 +1047,22 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s, BOOL bUpdate)
|
|||
case 0x05: *a = (Chipset.crc>> 4)&0xF; break;
|
||||
case 0x06: *a = (Chipset.crc>> 8)&0xF; break;
|
||||
case 0x07: *a = (Chipset.crc>>12)&0xF; break;
|
||||
case 0x08: *a = 0; break;
|
||||
case 0x08: // LPD
|
||||
// LB2 and LB1 not emulated, must be 0
|
||||
_ASSERT((Chipset.IORam[LPD] & (LB2 | LB1)) == 0);
|
||||
|
||||
GetBatteryState(&bLBI,&bVLBI); // get battery state
|
||||
|
||||
// check if battery states enabled
|
||||
bLBI = bLBI && ((Chipset.IORam[LPE] & ELBI) != 0);
|
||||
bVLBI = bVLBI && ((Chipset.IORam[LPE] & EVLBI) != 0);
|
||||
|
||||
// set IO bits
|
||||
IOBit(LPD,LB0,bLBI);
|
||||
IOBit(LPD,VLBI,bVLBI);
|
||||
IOBit(SRQ1,VSRQ,bVLBI);
|
||||
*a = Chipset.IORam[d];
|
||||
break;
|
||||
case 0x09: // LPE
|
||||
*a = Chipset.IORam[d];
|
||||
if (bUpdate)
|
||||
|
@ -1073,6 +1089,7 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s, BOOL bUpdate)
|
|||
{
|
||||
*a = Chipset.IORam[d] & 0x7;
|
||||
#if defined DEBUG_SERIAL // return BAUD value
|
||||
if (bUpdate)
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("%.5lx: BAUD Read: %x\n"),Chipset.pc,*a);
|
||||
|
@ -1099,14 +1116,15 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s, BOOL bUpdate)
|
|||
}
|
||||
else
|
||||
{
|
||||
// on a HP39/40G and HP49G Chipset.cards_status bust always be 0xF
|
||||
// _ASSERT((cCurrentRomType!='E' && cCurrentRomType!='X' && cCurrentRomType!='2' && cCurrentRomType!='P' && cCurrentRomType!='Q') || Chipset.cards_status == 0xF); // CdB for HP: add apples
|
||||
// on a HP30/40G and HP49G Chipset.cards_status bust always be 0xF
|
||||
_ASSERT((cCurrentRomType!='E' && cCurrentRomType!='X' && cCurrentRomType!='2' && cCurrentRomType!='P' && cCurrentRomType!='Q') || Chipset.cards_status == 0xF); // CdB for HP: add apples
|
||||
*a = Chipset.cards_status;
|
||||
}
|
||||
break;
|
||||
case 0x10: // IO CONTROL
|
||||
*a = Chipset.IORam[d]; // return IO CONTROL value
|
||||
#if defined DEBUG_SERIAL
|
||||
if (bUpdate)
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("%.5lx: IOC Read: %x\n"),Chipset.pc,*a);
|
||||
|
@ -1117,6 +1135,7 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s, BOOL bUpdate)
|
|||
case 0x11: // RCS
|
||||
*a = Chipset.IORam[d] | RX; // return RCS value
|
||||
#if defined DEBUG_SERIAL
|
||||
if (bUpdate)
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("%.5lx: RCS Read: %x\n"),Chipset.pc,*a);
|
||||
|
@ -1127,6 +1146,7 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s, BOOL bUpdate)
|
|||
case 0x12: // TCS
|
||||
*a = Chipset.IORam[d]; // return TCS value
|
||||
#if defined DEBUG_SERIAL
|
||||
if (bUpdate)
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("%.5lx: TCS Read: %x\n"),Chipset.pc,*a);
|
||||
|
@ -1179,6 +1199,7 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s, BOOL bUpdate)
|
|||
case 0x18: // SREQ? LSB
|
||||
*a = Chipset.IORam[d]; // return SREQ value
|
||||
#if defined DEBUG_SERIAL
|
||||
if (bUpdate)
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("%.5lx: SEQ %s Read: %x\n"),Chipset.pc,(d==0x18) ? "LSB" : "MSB",*a);
|
||||
|
@ -1421,8 +1442,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s)
|
|||
}
|
||||
else // Clarke / Yorke chip
|
||||
{
|
||||
// bit 3 is read-only
|
||||
Chipset.IORam[d] = (Chipset.IORam[d]&8)|(c&7);
|
||||
Chipset.IORam[d]=(Chipset.IORam[d]&8)|(c&7); // bit 3 is read-only
|
||||
}
|
||||
CommSetBaud(); // set baudrate
|
||||
#if defined DEBUG_SERIAL
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "Opcodes.h"
|
||||
#include "apple.h"
|
||||
#include "io.h" // I/O register definitions
|
||||
#include "i28f160.h"
|
||||
|
||||
#define w Chipset
|
||||
#define GOYES3 {if(w.carry) o_goyes3(I);else{w.pc+=2;return;}}
|
||||
|
@ -2445,7 +2444,7 @@ VOID o_goyes5(LPBYTE I)
|
|||
}
|
||||
|
||||
//////// EXTENSIONS ////////
|
||||
VOID o81B1(LPBYTE I)
|
||||
VOID o81B1(LPBYTE I) // beep patch
|
||||
{
|
||||
if (cCurrentRomType=='Q' || cCurrentRomType=='2' || cCurrentRomType=='P')
|
||||
{
|
||||
|
|
|
@ -180,6 +180,7 @@
|
|||
#define ID_OBJECT_LOAD 40009
|
||||
#define ID_OBJECT_SAVE 40010
|
||||
#define ID_ABOUT 40011
|
||||
#define ID_HELP_TOPICS 40012
|
||||
#define ID_FILE_CLOSE 40013
|
||||
#define ID_BACKUP_SAVE 40014
|
||||
#define ID_BACKUP_RESTORE 40015
|
||||
|
@ -247,6 +248,6 @@
|
|||
#define _APS_NEXT_RESOURCE_VALUE 130
|
||||
#define _APS_NEXT_COMMAND_VALUE 40072
|
||||
#define _APS_NEXT_CONTROL_VALUE 1136
|
||||
#define _APS_NEXT_SYMED_VALUE 108
|
||||
#define _APS_NEXT_SYMED_VALUE 109
|
||||
#endif
|
||||
#endif
|
||||
|
|
10
source/RPL.C
10
source/RPL.C
|
@ -68,7 +68,7 @@
|
|||
#define DOROMP 0x02E92 // XLIB Name
|
||||
#define SEMI 0x0312B // ;
|
||||
|
||||
#define GARBAGECOL 0x0613E // =GARBAGECOL entry for HP48S/G/GII and HP49G(+)
|
||||
#define GARBAGECOL 0x0613E // =GARBAGECOL entry for HP48S/G and HP49G
|
||||
|
||||
// check for Metakernel version
|
||||
#define METAKERNEL Metakernel()
|
||||
|
@ -105,7 +105,7 @@ static DWORD RPL_GarbageCol(VOID) // RPL variables must be in system RAM
|
|||
CHIPSET OrgChipset;
|
||||
DWORD dwAVMEM;
|
||||
|
||||
// only for HP48SX, HP48GX, HP49G, HP48GII and HP49G+
|
||||
// only for HP48SX, HP48GX, HP49G, HP48gII and HP49g+
|
||||
_ASSERT( cCurrentRomType == 'S' || cCurrentRomType == 'G' || cCurrentRomType == 'X'
|
||||
|| cCurrentRomType == '2' || cCurrentRomType == 'Q');
|
||||
|
||||
|
@ -226,7 +226,7 @@ DWORD RPL_SkipOb(DWORD d)
|
|||
break;
|
||||
case DOLNGREAL: // Precision Real (HP49G)
|
||||
l = 5;
|
||||
if (cCurrentRomType=='X' && cCurrentRomType!='2' && cCurrentRomType!='Q') // CdB for HP: add apples
|
||||
if (cCurrentRomType=='X')
|
||||
{
|
||||
l += Read5(d+l);
|
||||
l += Read5(d+l);
|
||||
|
@ -234,7 +234,7 @@ DWORD RPL_SkipOb(DWORD d)
|
|||
break;
|
||||
case DOLNGCMP: // Precision Complex (HP49G)
|
||||
l = 5;
|
||||
if (cCurrentRomType=='X' && cCurrentRomType!='2' && cCurrentRomType!='Q') // CdB for HP: add apples
|
||||
if (cCurrentRomType=='X')
|
||||
{
|
||||
l += Read5(d+l);
|
||||
l += Read5(d+l);
|
||||
|
@ -401,7 +401,7 @@ DWORD RPL_CreateTemp(DWORD l,BOOL bGarbageCol)
|
|||
Nwrite(p,a+l,b-a);
|
||||
free(p);
|
||||
Write5(a+l-5,l); // set object length field
|
||||
return a+1; // return base address of new object
|
||||
return (a+1); // return base address of new object
|
||||
}
|
||||
|
||||
UINT RPL_Depth(VOID)
|
||||
|
|
|
@ -120,7 +120,7 @@ BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort)
|
|||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
|
||||
if(hComm != INVALID_HANDLE_VALUE)
|
||||
if (hComm != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD dwThreadId;
|
||||
|
||||
|
@ -353,13 +353,13 @@ VOID CommReceive(VOID)
|
|||
// reject reading if com port is closed and not whole operation
|
||||
if (hComm && dwBytesRead == 0L) // com port open and buffer empty
|
||||
{
|
||||
if(ReadFile(hComm,&cBuffer,sizeof(cBuffer),&dwBytesRead,&os) == FALSE)
|
||||
if (ReadFile(hComm,&cBuffer,sizeof(cBuffer),&dwBytesRead,&os) == FALSE)
|
||||
dwBytesRead = 0L;
|
||||
else // bytes received
|
||||
nRp = 0; // reset read pointer
|
||||
}
|
||||
|
||||
if(dwBytesRead == 0L) // receive buffer empty
|
||||
if (dwBytesRead == 0L) // receive buffer empty
|
||||
break;
|
||||
|
||||
#if defined DEBUG_SERIAL
|
||||
|
@ -379,10 +379,10 @@ VOID CommReceive(VOID)
|
|||
--dwBytesRead;
|
||||
|
||||
Chipset.IORam[RCS] |= RBF; // receive buffer full
|
||||
if(UpdateUSRQ()) // update USRQ bit
|
||||
if (UpdateUSRQ()) // update USRQ bit
|
||||
INTERRUPT;
|
||||
}
|
||||
while(0);
|
||||
while (FALSE);
|
||||
LeaveCriticalSection(&csRecvLock);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -199,6 +199,8 @@ VOID ReadSettings(VOID)
|
|||
uWaveDevId = ReadInt(_T("Emulator"),_T("WaveDeviceId"),uWaveDevId);
|
||||
dwWaveVol = ReadInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol);
|
||||
dwWaveTime = ReadInt(_T("Emulator"),_T("WaveTime"),dwWaveTime);
|
||||
// LowBat
|
||||
bLowBatDisable = ReadInt(_T("LowBat"),_T("Disable"),bLowBatDisable);
|
||||
// Macro
|
||||
bMacroRealSpeed = ReadInt(_T("Macro"),_T("RealSpeed"),bMacroRealSpeed);
|
||||
nMacroTimeout = ReadInt(_T("Macro"),_T("ReplayTimeout"),nMacroTimeout);
|
||||
|
@ -252,6 +254,8 @@ VOID WriteSettings(VOID)
|
|||
WriteInt(_T("Emulator"),_T("WaveDeviceId"),uWaveDevId);
|
||||
WriteInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol);
|
||||
WriteInt(_T("Emulator"),_T("WaveTime"),dwWaveTime);
|
||||
// LowBat
|
||||
WriteInt(_T("LowBat"),_T("Disable"),bLowBatDisable);
|
||||
// Macro
|
||||
WriteInt(_T("Macro"),_T("RealSpeed"),bMacroRealSpeed);
|
||||
WriteInt(_T("Macro"),_T("ReplayTimeout"),nMacroTimeout);
|
||||
|
|
102
source/SNDDEF.H
Normal file
102
source/SNDDEF.H
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* snddef.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2015 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
|
||||
#include <initguid.h>
|
||||
|
||||
#if _MSC_VER >= 1600 // valid for VS2010 and later
|
||||
|
||||
#include <DSound.h>
|
||||
#include <Dsconf.h>
|
||||
|
||||
#else // create the necessary definitions manually
|
||||
|
||||
//
|
||||
// IKsPropertySet
|
||||
//
|
||||
|
||||
#ifndef _IKsPropertySet_
|
||||
#define _IKsPropertySet_
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct IKsPropertySet;
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef struct IKsPropertySet *LPKSPROPERTYSET;
|
||||
|
||||
DEFINE_GUID(IID_IKsPropertySet, 0x31efac30, 0x515c, 0x11d0, 0xa9, 0xaa, 0x00, 0xaa, 0x00, 0x61, 0xbe, 0x93);
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IKsPropertySet
|
||||
|
||||
DECLARE_INTERFACE_(IKsPropertySet, IUnknown)
|
||||
{
|
||||
// IUnknown methods
|
||||
STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID*) PURE;
|
||||
STDMETHOD_(ULONG,AddRef) (THIS) PURE;
|
||||
STDMETHOD_(ULONG,Release) (THIS) PURE;
|
||||
|
||||
// IKsPropertySet methods
|
||||
STDMETHOD(Get) (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength,
|
||||
LPVOID pPropertyData, ULONG ulDataLength, PULONG pulBytesReturned) PURE;
|
||||
STDMETHOD(Set) (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength,
|
||||
LPVOID pPropertyData, ULONG ulDataLength) PURE;
|
||||
STDMETHOD(QuerySupport) (THIS_ REFGUID rguidPropSet, ULONG ulId, PULONG pulTypeSupport) PURE;
|
||||
};
|
||||
|
||||
#endif // _IKsPropertySet_
|
||||
|
||||
// DirectSound Configuration Component GUID {11AB3EC0-25EC-11d1-A4D8-00C04FC28ACA}
|
||||
DEFINE_GUID(CLSID_DirectSoundPrivate, 0x11ab3ec0, 0x25ec, 0x11d1, 0xa4, 0xd8, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
|
||||
|
||||
// DirectSound Device Properties {84624F82-25EC-11d1-A4D8-00C04FC28ACA}
|
||||
DEFINE_GUID(DSPROPSETID_DirectSoundDevice, 0x84624f82, 0x25ec, 0x11d1, 0xa4, 0xd8, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A = 1,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1 = 2,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1 = 3,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W = 4,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A = 5,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W = 6,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A = 7,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W = 8,
|
||||
} DSPROPERTY_DIRECTSOUNDDEVICE;
|
||||
|
||||
#ifdef UNICODE
|
||||
#define DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W
|
||||
#else // UNICODE
|
||||
#define DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A
|
||||
#endif // UNICODE
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DIRECTSOUNDDEVICE_TYPE_EMULATED,
|
||||
DIRECTSOUNDDEVICE_TYPE_VXD,
|
||||
DIRECTSOUNDDEVICE_TYPE_WDM
|
||||
} DIRECTSOUNDDEVICE_TYPE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DIRECTSOUNDDEVICE_DATAFLOW_RENDER,
|
||||
DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE
|
||||
} DIRECTSOUNDDEVICE_DATAFLOW;
|
||||
|
||||
typedef struct _DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA
|
||||
{
|
||||
DIRECTSOUNDDEVICE_TYPE Type; // Device type
|
||||
DIRECTSOUNDDEVICE_DATAFLOW DataFlow; // Device dataflow
|
||||
GUID DeviceId; // DirectSound device id
|
||||
LPTSTR Description; // Device description
|
||||
LPTSTR Module; // Device driver module
|
||||
LPTSTR Interface; // Device interface
|
||||
ULONG WaveDeviceId; // Wave device id
|
||||
} DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA, *PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA;
|
||||
|
||||
#endif
|
256
source/SNDENUM.C
Normal file
256
source/SNDENUM.C
Normal file
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* SndEnum.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2015 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "snddef.h"
|
||||
|
||||
typedef HRESULT (WINAPI *LPFNDLLGETCLASSOBJECT)(REFCLSID,REFIID,LPVOID *);
|
||||
static LPFNDLLGETCLASSOBJECT pfnDllGetClassObject = NULL;
|
||||
|
||||
//
|
||||
// create a IKsPropertySet interface
|
||||
//
|
||||
static __inline HRESULT DirectSoundPrivateCreate(LPKSPROPERTYSET *ppKsPropertySet)
|
||||
{
|
||||
LPCLASSFACTORY pClassFactory = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
// create a class factory object
|
||||
#if defined __cplusplus
|
||||
hr = pfnDllGetClassObject(CLSID_DirectSoundPrivate,IID_IClassFactory,(LPVOID *) &pClassFactory);
|
||||
#else
|
||||
hr = pfnDllGetClassObject(&CLSID_DirectSoundPrivate,&IID_IClassFactory,(LPVOID *) &pClassFactory);
|
||||
#endif
|
||||
|
||||
// create the DirectSoundPrivate object and query for an IKsPropertySet interface
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
#if defined __cplusplus
|
||||
hr = pClassFactory->CreateInstance(NULL,IID_IKsPropertySet,(LPVOID *) ppKsPropertySet);
|
||||
#else
|
||||
hr = pClassFactory->lpVtbl->CreateInstance(pClassFactory,NULL,&IID_IKsPropertySet,(LPVOID *) ppKsPropertySet);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pClassFactory) // release the class factory object
|
||||
{
|
||||
#if defined __cplusplus
|
||||
pClassFactory->Release();
|
||||
#else
|
||||
pClassFactory->lpVtbl->Release(pClassFactory);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (FAILED(hr) && *ppKsPropertySet) // handle failure
|
||||
{
|
||||
#if defined __cplusplus
|
||||
(*ppKsPropertySet)->Release();
|
||||
#else
|
||||
(*ppKsPropertySet)->lpVtbl->Release(*ppKsPropertySet);
|
||||
#endif
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
//
|
||||
// get the device information about a DirectSound GUID.
|
||||
//
|
||||
static BOOL GetInfoFromDSoundGUID(CONST GUID *lpGUID, UINT *puWaveDeviceID)
|
||||
{
|
||||
LPKSPROPERTYSET pKsPropertySet = NULL;
|
||||
HRESULT hr;
|
||||
BOOL bSuccess = FALSE;
|
||||
|
||||
hr = DirectSoundPrivateCreate(&pKsPropertySet);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ULONG ulBytesReturned = 0;
|
||||
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA sDirectSoundDeviceDescription;
|
||||
|
||||
ZeroMemory(&sDirectSoundDeviceDescription,sizeof(sDirectSoundDeviceDescription));
|
||||
sDirectSoundDeviceDescription.DeviceId = *lpGUID;
|
||||
|
||||
// get the size of the direct sound device description
|
||||
#if defined __cplusplus
|
||||
hr = pKsPropertySet->Get(
|
||||
DSPROPSETID_DirectSoundDevice,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
||||
NULL,
|
||||
0,
|
||||
&sDirectSoundDeviceDescription,
|
||||
sizeof(sDirectSoundDeviceDescription),
|
||||
&ulBytesReturned
|
||||
);
|
||||
#else
|
||||
hr = pKsPropertySet->lpVtbl->Get(pKsPropertySet,
|
||||
&DSPROPSETID_DirectSoundDevice,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
||||
NULL,
|
||||
0,
|
||||
&sDirectSoundDeviceDescription,
|
||||
sizeof(sDirectSoundDeviceDescription),
|
||||
&ulBytesReturned
|
||||
);
|
||||
#endif
|
||||
|
||||
if (SUCCEEDED(hr) && ulBytesReturned)
|
||||
{
|
||||
PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA psDirectSoundDeviceDescription = NULL;
|
||||
|
||||
// fetch the direct sound device description
|
||||
psDirectSoundDeviceDescription = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA) malloc(ulBytesReturned);
|
||||
if (psDirectSoundDeviceDescription != NULL)
|
||||
{
|
||||
// init structure with data from length request
|
||||
*psDirectSoundDeviceDescription = sDirectSoundDeviceDescription;
|
||||
|
||||
#if defined __cplusplus
|
||||
hr = pKsPropertySet->Get(
|
||||
DSPROPSETID_DirectSoundDevice,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
||||
NULL,
|
||||
0,
|
||||
psDirectSoundDeviceDescription,
|
||||
ulBytesReturned,
|
||||
&ulBytesReturned
|
||||
);
|
||||
#else
|
||||
hr = pKsPropertySet->lpVtbl->Get(pKsPropertySet,
|
||||
&DSPROPSETID_DirectSoundDevice,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
||||
NULL,
|
||||
0,
|
||||
psDirectSoundDeviceDescription,
|
||||
ulBytesReturned,
|
||||
&ulBytesReturned
|
||||
);
|
||||
#endif
|
||||
|
||||
if ((bSuccess = SUCCEEDED(hr)))
|
||||
{
|
||||
// the requested device ID
|
||||
*puWaveDeviceID = psDirectSoundDeviceDescription->WaveDeviceId;
|
||||
}
|
||||
free(psDirectSoundDeviceDescription);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined __cplusplus
|
||||
pKsPropertySet->Release();
|
||||
#else
|
||||
pKsPropertySet->lpVtbl->Release(pKsPropertySet);
|
||||
#endif
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
//
|
||||
// callback function for DirectSoundEnumerate()
|
||||
//
|
||||
static BOOL CALLBACK DSEnumProc(LPGUID lpGUID,LPCTSTR lpszDesc,LPCTSTR lpszDrvName,LPVOID lpContext)
|
||||
{
|
||||
HWND hWnd = (HWND) lpContext; // window handle of the combo box
|
||||
|
||||
if (lpGUID != NULL) // NULL only for "Primary Sound Driver"
|
||||
{
|
||||
UINT uDevID;
|
||||
|
||||
if (GetInfoFromDSoundGUID(lpGUID,&uDevID))
|
||||
{
|
||||
WAVEOUTCAPS woc;
|
||||
|
||||
// has device the necessary capabilities?
|
||||
if ( waveOutGetDevCaps(uDevID,&woc,sizeof(woc)) == MMSYSERR_NOERROR
|
||||
&& (woc.dwFormats & WAVE_FORMAT_4M08) != 0)
|
||||
{
|
||||
// copy product name and wave device ID to combo box
|
||||
LONG i = (LONG) SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM) lpszDesc);
|
||||
SendMessage(hWnd,CB_SETITEMDATA,i,uDevID);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
UNREFERENCED_PARAMETER(lpszDrvName);
|
||||
}
|
||||
|
||||
// set listfield for sound device combo box
|
||||
VOID SetSoundDeviceList(HWND hWnd,UINT uDeviceID)
|
||||
{
|
||||
typedef BOOL (CALLBACK *LPDSENUMCALLBACK)(LPGUID, LPCTSTR, LPCTSTR, LPVOID);
|
||||
typedef HRESULT (WINAPI *LPFN_SDE)(LPDSENUMCALLBACK lpDSEnumCallback,LPVOID lpContext);
|
||||
LPFN_SDE pfnDirectSoundEnumerate = NULL;
|
||||
|
||||
UINT uSelectDevice,uDevID,uDevNo;
|
||||
|
||||
HMODULE hDSound = LoadLibrary(_T("dsound.dll"));
|
||||
|
||||
if (hDSound != NULL) // direct sound dll found
|
||||
{
|
||||
#if defined _UNICODE
|
||||
pfnDirectSoundEnumerate = (LPFN_SDE) GetProcAddress(hDSound,"DirectSoundEnumerateW");
|
||||
#else
|
||||
pfnDirectSoundEnumerate = (LPFN_SDE) GetProcAddress(hDSound,"DirectSoundEnumerateA");
|
||||
#endif
|
||||
pfnDllGetClassObject = (LPFNDLLGETCLASSOBJECT) GetProcAddress(hDSound,"DllGetClassObject");
|
||||
}
|
||||
|
||||
SendMessage(hWnd,CB_RESETCONTENT,0,0);
|
||||
|
||||
// preset selector
|
||||
uSelectDevice = (UINT) SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM) _T("Standard Audio"));
|
||||
SendMessage(hWnd,CB_SETITEMDATA,uSelectDevice,WAVE_MAPPER);
|
||||
|
||||
// check for direct sound interface functions
|
||||
if (pfnDirectSoundEnumerate != NULL && pfnDllGetClassObject != NULL)
|
||||
{
|
||||
// copy product name and wave device ID to combo box
|
||||
if (SUCCEEDED(pfnDirectSoundEnumerate((LPDSENUMCALLBACK) DSEnumProc,hWnd)))
|
||||
{
|
||||
UINT i;
|
||||
|
||||
uDevNo = (UINT) SendMessage(hWnd,CB_GETCOUNT,0,0);
|
||||
for (i = 0; i < uDevNo; ++i)
|
||||
{
|
||||
// translate device ID to combo box position
|
||||
uDevID = (UINT) SendMessage(hWnd,CB_GETITEMDATA,i,0);
|
||||
|
||||
if (uDevID == uDeviceID) uSelectDevice = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // direct sound not available, detect over wave capabilities
|
||||
{
|
||||
WAVEOUTCAPS woc;
|
||||
|
||||
uDevNo = waveOutGetNumDevs();
|
||||
for (uDevID = 0; uDevID < uDevNo; ++uDevID)
|
||||
{
|
||||
if ( waveOutGetDevCaps(uDevID,&woc,sizeof(woc)) == MMSYSERR_NOERROR
|
||||
&& (woc.dwFormats & WAVE_FORMAT_4M08) != 0)
|
||||
{
|
||||
// copy product name and wave device ID to combo box
|
||||
LONG i = (LONG) SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM) woc.szPname);
|
||||
SendMessage(hWnd,CB_SETITEMDATA,i,uDevID);
|
||||
|
||||
if (uDevID == uDeviceID) uSelectDevice = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// activate last selected combo box item
|
||||
SendMessage(hWnd,CB_SETCURSEL,uSelectDevice,0L);
|
||||
|
||||
if (hDSound != NULL) // direct sound dll loaded
|
||||
{
|
||||
pfnDllGetClassObject = NULL;
|
||||
VERIFY(FreeLibrary(hDSound));
|
||||
}
|
||||
return;
|
||||
}
|
|
@ -7,7 +7,6 @@
|
|||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "resource.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h"
|
||||
|
||||
|
@ -296,7 +295,7 @@ static __inline INT SetBcd(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,
|
|||
byNum[j] = byNum[j + i];
|
||||
}
|
||||
|
||||
if(byNum[1] == 0) // number is 0
|
||||
if (byNum[1] == 0) // number is 0
|
||||
{
|
||||
ZeroMemory(pbyNum,nMantLen + nExpLen + 1);
|
||||
return nMantLen + nExpLen + 1;
|
||||
|
@ -326,7 +325,7 @@ static __inline INT SetBcd(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,
|
|||
while (*cp >= _T('0') && *cp <= _T('9'))
|
||||
lExp = lExp * 10 + *cp++ - _T('0');
|
||||
|
||||
if(i) lExp = -lExp;
|
||||
if (i) lExp = -lExp;
|
||||
}
|
||||
|
||||
if (*cp != 0) return 0;
|
||||
|
@ -805,7 +804,7 @@ LRESULT OnStackPaste(VOID) // paste data to stack
|
|||
}
|
||||
}
|
||||
}
|
||||
while(FALSE);
|
||||
while (FALSE);
|
||||
|
||||
GlobalUnlock(hClipObj);
|
||||
}
|
||||
|
@ -825,7 +824,7 @@ LRESULT OnStackPaste(VOID) // paste data to stack
|
|||
KeyboardEvent(FALSE,0,0x8000);
|
||||
|
||||
// wait for sleep mode
|
||||
while(Chipset.Shutdn == FALSE) Sleep(0);
|
||||
while (Chipset.Shutdn == FALSE) Sleep(0);
|
||||
|
||||
cancel:
|
||||
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define SWORD SHORT // signed 16 Bit variable
|
||||
#define QWORD ULONGLONG // unsigned 64 Bit variable
|
||||
|
||||
#define CHIPSET Chipset_t
|
||||
typedef struct
|
||||
{
|
||||
SWORD nPosX; // position of window
|
||||
|
@ -106,7 +107,7 @@ typedef struct
|
|||
DWORD d0offset; // offset inside the header display for the content
|
||||
DWORD d0address; // address in saturn addr area for d0memory (2 pages)
|
||||
// BOOL d0Cfig; // modul configured
|
||||
} CHIPSET;
|
||||
} Chipset_t;
|
||||
|
||||
// additional Saturnator registers and Apple hardware
|
||||
typedef struct
|
||||
|
|
340
source/gpl.txt
340
source/gpl.txt
|
@ -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) <year> <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) year 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.
|
Loading…
Reference in a new issue