diff --git a/BEEP.EXT b/BEEP.EXT index 006f2ff..7a499cb 100644 --- a/BEEP.EXT +++ b/BEEP.EXT @@ -1 +1 @@ -017A6:81B1 +017A6:81B1; =makebeep diff --git a/COPYING.TXT b/COPYING.TXT index a43ea21..60549be 100644 --- a/COPYING.TXT +++ b/COPYING.TXT @@ -2,7 +2,7 @@ Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS - Appendix: How to Apply These Terms to Your New Programs + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -305,7 +305,8 @@ the "copyright" line and a pointer to where the full notice is found. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Also add information on how to contact you by electronic and paper mail. diff --git a/DEBUGGER.TXT b/DEBUGGER.TXT new file mode 100644 index 0000000..b554875 --- /dev/null +++ b/DEBUGGER.TXT @@ -0,0 +1,189 @@ +Debugger in Emu48/Tools/Debugger... +----------------------------------- + +This is a short description of the internal debugger of Emu48. The debugger is not perfect and/or complete. I provide it as it is. Please don't send me any suggestions or changes at the moment. If you have a better idea make it for yourself. Of course you're free to publish them or send me your changes. + +The debugger was designed to help costumers inspecting assembler code objects, a part that cannot be handled satisfactorily by the JAZZ package. Thanks to Mika Heiskanen and all the others supporting this great program. + +After starting the debugger the emulation will stop at the current PC position. The emulation will continue after closing the debugger window. Please remember that the clock now shows the wrong time. + + +1.) Menu Debug + +- Run F5 + +Continue calculator emulation under debugger control. The emulation will stop at a breakpoint. Please remember that the emulation speed is slower than without debugger control. + +- Step Into F7 + +Execute one code instruction. + +- Step Over F8 + +Execute a GOSUB, GOSUBL or GOSBVL as one instruction. Normally the instruction cursor will set to the position behind the GOSUB instruction. + +But this makes trouble in the following code part: + + GOSUB + + NIBASC /Hello world/ ++ C=RSTK + +The program counter will never reach the address behind the GOSUB instruction. The debugger solve this problem by breaking the emulation when the stack has the same level before the GOSUB instruction. In this example the single step execution will continue after the C=RSTK instruction. + +- Step Out F9 + +Continue the program until a RTI, RTN, RTNC, RTNCC, RTNNC, RTNSC, RTNSXN, RTNYES instruction is found above the current stack level. + +At some code constructions (mostly used to save space on the hardware stack) like + + C=RSTK + PC=C + +and + + C=RSTK + RSTK=C + RTN + +the stop address will be wrong. The problem in both code fragments is the C=RSTK opcode. In the first example there is no RTN instruction to stop. In the second one the C=RSTK instruction purge the original return address and then the RSTK=C instruction is interpreted as a GOSUB instruction. + +In opposite the following code will work fine: + + RSTK=C + .. + code <- F9 was pressed here + .. + GOSUB - + C=RSTK + RTN <- emulation will stop after this instruction +- RTN + +So be careful using the F9 key. + +- Break F11 + +Stop the emulation started with F5. + + +2.) Menu Breakpoints + +- Set breakpoint F2 + +Toggle a code breakpoint at the cursor position in the code window. + +- Edit breakpoints... + +You get a sorted list of the current code breakpoints. With "Add" you can add a new, with "Delete" you can delete an existing breakpoint. Addresses greater than #FFFFF are cutted after the fifths nibble. + +- Clear all breakpoints + +Clear all code breakpoints except the NOP3 ones. + +- NOP3 code breakpoints + +What are NOP3 code breakpoints? As you now user programs are loaded somewhere in memory and can be moved after a garbage collection. So it's very difficult to break a user program at a hard set breakpoint with F2. To solve this problem the debugger will stop emulation at a NOP3 opcode. So you can easily add a NOP3 command into your sources to force a break condition. To enable this you have to check this item. + +NOP3 and NOP3, what's the difference? The Saturn CPU has no NOP command, so NOP3 is an opcode that is three nibbles long and doesn't change a register. In the HP SASM.DOC document two different opcodes are defined for NOP3: + + Opcode 820 for HST=0 0 + +and + + Opcode 420 for GOC + (next line) + +In the assembler of the HPTOOLS 3.x package NOP3 is defined as opcode 820. The advantage of the opcode is that the execution time is always the same, independent from the carry flag. This code is used in the HP48 ROM as well. So I decided to use the GOC opcode for a code breakpoint condition. + +A short example: + +ASSEMBLE + NIBASC /HPHP48-E/ + +BREAK MACRO + CON(3) #024 NOP3 + ENDM + +RPL +CODE + BREAK code breakpoint + + GOSBVL =SAVPTR save register + + GOSUB + problem for step over + NIBASC /Hello world/ ++ C=RSTK + + GOVLNG =GETPTRLOOP +ENDCODE + + +3.) Code window + +This windows shows you the disassembled code. The line with the current PC is marked with a "->" between the address and the disassembly. + +You can use the UP, PAGE UP, DOWN and PAGE DOWN keys to scroll the window content. There is one strange behavior, when you move to higher addresses the debugger is able to disassemble the next line correctly, but when you move to cursor to lower addresses the debugger does not know if this address is at the begin or inside of an opcode. In result you get wrong disassembled lines. + +Context menu pressing the right mouse button: + +- Go to address... G + +Moves the cursor to the specified code address. + +- Go to PC + +Sets the cursor to the actual position of the PC. + +- Set breakpoint F2 + +Toggle a code breakpoint at the cursor position in the code window. + +- Set PC to selection + +Set the PC to the cursor position. Be careful with this command, you change the execution order of the commands! + + +4.) Register window + +Here you can see the actual contents of the CPU registers. The values are only updated after a single step execution. + +With the left mouse button you change the content of the register. On bit registers like CY and Mode the state changes immediately without any request. + + +5.) Memory window + +This windows shows you the memory content. + +You can use the arrow, PAGE UP and PAGE DOWN keys to move the cursor to a memory position. With a double click on the left mouse button you change the content of the two addresses. When the memory position is read only (ROM) the content wouldn't change. + +Context menu pressing the right mouse button: + +- Go to address... G + +Moves the cursor to the specified memory address. + +- Go to PC + +Sets the cursor to the actual position of the PC. + +- Go to D0 + +Sets the cursor to the actual position of the D0 register. + +- Go to D1 + +Sets the cursor to the actual position of the D0 register. + +- Go to Stack + +Sets the cursor to the return address placed in the top level of the stack. + + +6.) Stack window + +The content of the hardware stack is viewed here. + + +7.) Problems + +The timers aren't updated in the single step mode at the moment. Please skip these parts with setting a code breakpoint behind the critical section and continue emulation with F5. + +12/14/99 (c) by Christoph Gießelink, cgiess@swol.de diff --git a/DEFAULTG.KML b/DEFAULTG.KML index 4031e83..0c8f2d2 100644 --- a/DEFAULTG.KML +++ b/DEFAULTG.KML @@ -16,7 +16,7 @@ End Lcd Zoom 2 Offset 20 20 - Color 0 255 255 255 + Color 0 255 255 255 # character color table Color 1 255 255 255 Color 2 255 255 255 Color 3 255 255 255 @@ -24,22 +24,22 @@ Lcd Color 5 255 255 255 Color 6 255 255 255 Color 7 255 255 255 - Color 8 240 240 240 - Color 9 225 225 225 - Color 10 210 210 210 - Color 11 195 195 195 - Color 12 180 180 180 - Color 13 165 165 165 - Color 14 150 150 150 - Color 15 135 135 135 - Color 16 120 120 120 - Color 17 105 105 105 - Color 18 90 90 90 - Color 19 75 75 75 - Color 20 60 60 60 - Color 21 45 45 45 - Color 22 30 30 30 - Color 23 15 15 15 + Color 8 255 255 255 + Color 9 223 223 223 + Color 10 179 171 171 + Color 11 135 135 135 + Color 12 91 91 91 + Color 13 47 47 47 + Color 14 0 0 0 + Color 15 0 0 0 + Color 16 0 0 0 + Color 17 0 0 0 + Color 18 0 0 0 + Color 19 0 0 0 + Color 20 0 0 0 + Color 21 0 0 0 + Color 22 0 0 0 + Color 23 0 0 0 Color 24 0 0 0 Color 25 0 0 0 Color 26 0 0 0 @@ -48,6 +48,38 @@ Lcd Color 29 0 0 0 Color 30 0 0 0 Color 31 0 0 0 + Color 32 255 255 255 # background color table + Color 33 255 255 255 + Color 34 255 255 255 + Color 35 255 255 255 + Color 36 255 255 255 + Color 37 255 255 255 + Color 38 255 255 255 + Color 39 255 255 255 + Color 40 255 255 255 + Color 41 255 255 255 + Color 42 255 255 255 + Color 43 255 255 255 + Color 44 255 255 255 + Color 45 255 255 255 + Color 46 255 255 255 + Color 47 232 232 232 + Color 48 209 209 209 + Color 49 186 186 186 + Color 50 163 163 163 + Color 51 140 140 140 + Color 52 117 117 117 + Color 53 94 94 94 + Color 54 71 71 71 + Color 55 48 48 48 + Color 56 25 25 25 + Color 57 2 2 2 + Color 58 0 0 0 + Color 59 0 0 0 + Color 60 0 0 0 + Color 61 0 0 0 + Color 62 0 0 0 + Color 63 0 0 0 End Annunciator 1 diff --git a/DEFAULTS.KML b/DEFAULTS.KML index 3b2c525..ce46368 100644 --- a/DEFAULTS.KML +++ b/DEFAULTS.KML @@ -16,25 +16,25 @@ End Lcd Zoom 2 Offset 20 20 - Color 0 255 255 255 + Color 0 255 255 255 # character color table Color 1 255 255 255 Color 2 255 255 255 Color 3 240 240 240 - Color 4 225 225 225 - Color 5 210 210 210 - Color 6 195 195 195 - Color 7 180 180 180 - Color 8 165 165 165 - Color 9 150 150 150 - Color 10 135 135 135 - Color 11 120 120 120 - Color 12 105 105 105 - Color 13 90 90 90 - Color 14 75 75 75 - Color 15 60 60 60 - Color 16 45 45 45 - Color 17 30 30 30 - Color 18 15 15 15 + Color 4 216 216 216 + Color 5 192 192 192 + Color 6 168 168 168 + Color 7 144 144 144 + Color 8 120 120 120 + Color 9 96 96 96 + Color 10 72 72 72 + Color 11 48 48 48 + Color 12 24 24 24 + Color 13 0 0 0 + Color 14 0 0 0 + Color 15 0 0 0 + Color 16 0 0 0 + Color 17 0 0 0 + Color 18 0 0 0 Color 19 0 0 0 Color 20 0 0 0 Color 21 0 0 0 @@ -48,6 +48,38 @@ Lcd Color 29 0 0 0 Color 30 0 0 0 Color 31 0 0 0 + Color 32 255 255 255 # background color table + Color 33 255 255 255 + Color 34 255 255 255 + Color 35 255 255 255 + Color 36 255 255 255 + Color 37 255 255 255 + Color 38 255 255 255 + Color 39 255 255 255 + Color 40 255 255 255 + Color 41 255 255 255 + Color 42 255 255 255 + Color 43 255 255 255 + Color 44 255 255 255 + Color 45 255 255 255 + Color 46 230 230 230 + Color 47 205 205 205 + Color 48 180 180 180 + Color 49 155 155 155 + Color 50 130 130 130 + Color 51 105 105 105 + Color 52 80 80 80 + Color 53 55 55 55 + Color 54 30 30 30 + Color 55 5 5 5 + Color 56 0 0 0 + Color 57 0 0 0 + Color 58 0 0 0 + Color 59 0 0 0 + Color 60 0 0 0 + Color 61 0 0 0 + Color 62 0 0 0 + Color 63 0 0 0 End Annunciator 1 diff --git a/EMU48.EXE b/EMU48.EXE index 97698a8..5e3fdd4 100644 Binary files a/EMU48.EXE and b/EMU48.EXE differ diff --git a/EMU48.TXT b/EMU48.TXT index 104c4bb..6268a89 100644 --- a/EMU48.TXT +++ b/EMU48.TXT @@ -1,7 +1,7 @@ - Emu48 - A freeware HP48 Emulator for Windows 95, 98 and NT + Emu48 - A freeware HP38/48/49 Emulator for Windows 9x, NT and 2000 @@ -9,219 +9,405 @@ * INSTALLATION * **************** -Emu48 is now distributed in a single archive, named Emu48-1.xx.zip. This version -integrates the changed made by Christoph Giesselink in his service pack 10. +Emu48 is distributed in 1 archive: +- Emu48-1_15.zip All files and sources -To install Emu48, just unzip Emu48-1.xx.zip into an empty directory. -When you first run Emu48, it will detect the directory in which you -installed it, and will write its configuration to a file named Emu48.ini in -your Windows directory. +To install Emu48, just unzip Emu48-1_15.zip into an empty directory. When you +first run Emu48, it will detect the directory in which you installed it, and +will write its configuration to a file named Emu48.ini in your Windows +directory. -Note: - As of version 1.0, Emu48 will only run with Windows 95, 98 and NT. - Since the source code is provided, you can add features or port it to new - plateforms, but you are required to send me your changes. +You can also update your current version with the Unofficial Service Packs: +- E48BP1x.ZIP New EXE-File +- E48SP1x.ZIP Sources of the Service Pack +Replace the original EXE file please. + + + ******************** + * OPERATING SYSTEM * + ******************** + +This version of Emu48 should work with all Intel Win32 platforms. You may +recompile the sources to run Emu48 with Windows NT on a DEC Alpha. ************************ * YOU NEED A ROM IMAGE * ************************ -Emu48 needs an image of the ROM of YOUR calculator to be able to run. -Since the ROM is copyrighted by HP, I won't give you mine, and you should not -give yours or make it freely available. -To use the ROM software of a calculator, you must be the owner of this -calculator. +Emu48 needs an image of the ROM of YOUR calculator to be able to run. Since the +ROM is copyrighted by HP, I won't give you mine, and you should not give yours +or make it freely available. To use the ROM software of a calculator, you must +be the owner of this calculator. -- If you have already used another HP48 emulator, you can convert the ROM with - you were using with the Convert utility. - To do that, start a Command Promt while running Windows, and type : - Convert ROM.48G -or Convert ROM.48S - Where is the path to your old ROM image. This will create a file - named ROM.48G or ROM.48S, depending on the version you own. - This tool should be able to read any style of ROM image, and will also check - its validity. Note than if you run it with only one parameter, no file will - be written, but it will still check the validity of the ROM. +- HP38: +To upload the ROM of your HP38G, you will need a special aplet called "ROM +UPLOAD", available at http://www.epita.fr/~avenar_j/hp. Once you've uploaded the +ROM, you have to convert it using the Convert utility. + +To do that, start a Command Prompt while running Windows, and type: + Convert ROM.38G + +Where is the path to your ROM image. This will create a file named +ROM.38G. This tool will also check its validity. + +- HP48: +If you have already used another HP48 emulator, you can convert the ROM using +the Convert utility. -- If you have never used an HP48 emulator, and don't have a ROM dump, you can - either use the old ROMDump utility and then Convert your dump, or you can - use my ROMDump Wizard, which will almost automatically get the ROM from your - HP48. However, this Wizard was written without a documentation on the - transfer protocol used by the HP48 (Kermit), so I cannot guarantee that it - will work. It worked on my computer, maybe it will work on yours. Try it ! +To do that, start a Command Prompt while running Windows, and type: + Convert ROM.48G +or Convert ROM.48S - WARNING: If you use ROMDump or the ROMDump Wizard, DO NOT INTERRUPT THE - PROCESS ! Your HP48 would lock, and the only way to reset it is - through the Reset hole. +Where 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. - IMPORTANT: To save a lot of space, two DLLs needed by the Romdump Wizard - have not been included in the Romdump Wizard's distribution. - They are called MSVCRT40.DLL and MFC40.DLL, and are available - on the Web at the Emu48 Official Homepage : - http://www.geocities.com/CapeCanaveral/5948/index.html - These two files are freely distributable, and would be included - in this archive if they weren't so large (about 1.4Mb for both) - Note that they are NOT needed by Emu48 : only the Romdump Wizard - requires them. +If you have never used an HP48 emulator, and don't have a ROM dump, you can +either use Jean-Yves Avenard's ROMUPL.BIN or the ROMDump Wizard V1.x, which will +almost automatically get the ROM from your HP48. Don't use the ROMDump Wizard +versions V0.x any more please! After the download you may have to convert your +dump with the CONVERT utility into the Emu48 format. -* Once you have your ROM dump(s), SAVE THEM TO A FLOPPY DISK ! - It will save you a lot of troubles if you were to lose them. +You can find the latest version of the ROM dump programs on: +ROMUPL.BIN http://www.epita.fr/~avenar_j/hp/calcen.html +ROMDump Wizard http://privat.swol.de/ChristophGiesselink/index.htm +Once you have your ROM dump(s), SAVE THEM TO A FLOPPY DISK! It will save you a +lot of trouble if you were lose them. + +- HP49: +There's no ROM download program available so far. But you can find a HP49G ROM +for emulators in the YorkeM emulator package or in the HP49G SDK on +http://www.hpcalc.org in the HP49 section. **************** * HOW TO START * **************** -When Emu48 is installed and you have put the ROM image(s) in its directory, you -can start Emu48. You'll see a "Choose Your KML Script" box. +When Emu48 is installed and you have put the ROM image(s) in the Emu48 +directory, you can start Emu48. You'll see a "Choose Your KML Script" box. -KML Scripts in fact define the visual aspect of Emu48, the behaviour of the -buttons, of the keyboard... It is a GREAT way to customize your copy of Emu48. +KML Scripts in fact define the visual aspect of Emu48, the behavior of the +buttons, of the keyboard, ... It's a GREAT way to customize your copy of Emu48. Check that the path in the "Emu48 Directory" text area is correct. Modify it if -the directory in which you installed Emu48 is not the directory displayed. -Click the refresh button ("V") after modifying it to update the list box. +the directory in which you installed Emu48 is not the directory displayed. Click +the refresh button ("V") after modifying it to update the list box. Choose a KML script in the list box. If you have put a G/GX ROM dump in Emu48's directory, choose a script for G/GX. If you have put a S/SX ROM dump in Emu48's directory, choose a script for S/SX. -Several scripts are included in the archive : + +Several scripts are included in the common archive: * Emu48's Default Faceplate for HP48G/GX * Emu48's Default Faceplate for HP48S/SX - These two are simple scripts, and they use the bitmap from Win48 2.05. + These two are simple scripts, good for 800x600 display resolution. * Casey's Gx with Toolbar and Touch Screen * Casey's Sx with Toolbar and Touch Screen These script uses many advanced features, and is a good demonstration of - the power of Emu48's scripting language, KML. Try it, it is really great ! + the power of Emu48's scripting language KML. Try it, it is really great! * Floating buttons This one looks really great. * Small but realistic HP48 Gx This one has been designed for small resolutions such as 640x480. - Note: some things in this script have to be be fixed. + Note: some things in this script have to be fixed. - If you want other great scripts, visit Casey's Emu48 homepage : + If you want other great scripts, visit Casey's Emu48 homepage: http://www.gulftel.com/~pattersc/emu48/ - And if you are interested in writting new scripts, you'll want the KML 2.0 - documentation, available on Casey's page and on my page : - http://www.geocities.com/CapeCanaveral/5948/kmlind.htm +And if you are interested in writing new scripts, get the KML 2.0 documentation +from Christoph's page at http://privat.swol.de/ChristophGiesselink/emu48.htm -Once you have selected a script, press Ok to start the emulator. While it is -running, you can use the View/Change Kml Script to change the visual aspect -of Emu48. +Once you have selected a script, press OK to start the emulator. While it's +running, you can use the View/Change KML Script... command to change the visual +aspect of Emu48. + *************** + * KML SCRIPTS * + *************** + +In some cases you have to fix Color 0 in your KML script file, because the +colors red and blue has been swapped in the "Lcd" section (bugfix in a previous +version). Don't use TRUELCD.KMI for emulating display contrast in your scripts. +It's not fully correct. The hardware contrast values are in the area from 0 to +31. But the HP48 ROMs bounds them to useful values. The S(X) ROM use only +display contrast values between 3 and 19 and the G(X) ROM values between 9 and +24. + + + **************** + * COMMAND LINE * + **************** + +The command line syntax is "Emu48 [E48file [Port2file]]". The first parameter +sets the filename for the emulation data, the second parameter the Port2 file. +You're not able to set a Port2 file without setting the emulation data file. The +arguments are optional. + + + ******************* + * LOAD/SAVE FILES * + ******************* + +There are two ways to transfer files from or to the emulator. The one way is to +use the serial port to transfer the data directly from your HP48 to the +emulator. The second way is to load data, saved on your PC, into the stack of +the emulator. You can do this by using the Edit/Load Object... command or with +the file Drag and Drop feature. But there's one important restriction, the data +must a HP binary file (begin with HPHP48- or HPHP49-, this depends on your +emulated calculator)! If not, the data is load as string. The Edit/Save +Object... command will save the data in stack level 1 on the PC (always binary +mode). Be sure, when you use the second way for data transfer, that no program +is running on the emulator. The second way doesn't work on a HP38, because he +has no stack. So you can load aplets only from the serial port. + + + ***************** + * DRAG AND DROP * + ***************** + +Dropping HP48 objects over the emulator window will load program files (like the +command "Load object...") on the stack. Be sure that the emulator isn't busy +before doing this. + ******************* * SHARED RAM CARD * ******************* -You can add a SHARED (I'll explain later) ram card of up to 4Mb. By default, no such -card will be created when you start Emu48. The MkShared.exe utility, included in the -registered version, will allow you to create it. -The syntax is : +You can add a SHARED (I'll explain later) ram card of up to 4MB to a HP48. By +default, no such card will be created when you start Emu48. The MkShared.exe +utility will allow you to create it. + +The syntax is: MkShared -For example, you can create a 4Mb RAM card name SHARED.BIN (in Emu48's directory) with -the following command : + +For example, you can create a 4MB RAM card name SHARED.BIN (in Emu48's +directory) with the following command: + MkShared SHARED.BIN 4096 -Valid sizes are 128, 256, 512, 1024, 2048 and 4096 kb. + +Valid sizes are 32, 128, 256, 512, 1024, 2048 and 4096 KB. If you use RAM cards +greater than 128 KB in a HP48SX, you can only see the first 128 KB of the card. -When you have created this file, run Emu48, and use the Close menu item to close the -calculator state. Now select View/Settings. In the "Port 2" text area, type the name -of the file you created (if you don't include a path, it will be searched for in Emu48's -directory). +When you have created this file, run Emu48, and use the Close menu item to close +the calculator state. Now select File/Settings. In the "Port 2" text area, type +the name of the file you created (if you don't include a path, it will be +searched for in Emu48's directory). -You can also tick the check box "Port 2 Is Shared". -When the box is cleared, only the first instance of Emu48 will allow you to use the RAM -card in Port 2. -When this box is ticked, the first instance of Emu48 will give you both read and write -access to this RAM card. If then you start Emu48 again, the RAM card in Port 2 will be -write-protected. You can thus transfer files very easily between two calculators. This -RAM card is used by both S/SX and G/GX types. - -Note that you have to close Emu48 and restart it if you modify these settings. +You can also tick the check box "Port 2 Is Shared". When the box is cleared, +only the first instance of Emu48 will allow you to use the RAM card in Port 2. +When this box is ticked, the first instance of Emu48 will give you both read and +write access to this RAM card. If then you start Emu48 again, the RAM card in +Port 2 will be write-protected. Thus you can transfer files very easily between +two calculators. This RAM card is used by both S/SX and G/GX types. + *********************** + * COPY / PASTE STRING * + *********************** - ******************** - * SPECIAL FEATURES * - ******************** +With the menu items "Copy String" and "Paste String" in the "Edit" menu you're +able to copy HP48 string objects from the stack to the PC clipboard and vice +versa. -Emu48 includes a backup feature (in the View menu). It save the complete state of the -calculator in the computer's memory. You might want to use it before doing something -risky, and if you don't want to save to the disk. It provides some kind of Undo feature. -It is also used by Emu48 when you want to save or load a new document, to restore its -old state if you cancel the operation or of something goes wrong. + ********** + * BACKUP * + ********** + +Emu48 includes a backup feature (in the Edit menu). It save the complete state +of the calculator in the computer's memory. You might want to use it before +doing something risky, and if you don't want to save to the disk. It provides +some kind of Undo feature. It is also used by Emu48 when you want to save or +load a new document, to restore its old state if you cancel the operation or of +something goes wrong. + + + ************ + * KEYBOARD * + ************ + +To enter a character to the emulator use the PC keyboard (key translation +depends on the used KML script) or the mouse. If you press the left mouse +button, the emulator key is pressed as long as you press the mouse button or +leaving the area of the emulator button. Sometimes you need to press more then +one key (contrast setting, warmstart, ...). To do this, press the right mouse +button. All "locked" buttons are released after enter a key with the left mouse +button. + + + ********* + * CLOCK * + ********* + +The emulator time is synchronized with the PC time at startup of the emulator. +This may cause problems with other non original operating systems running on the +HP48. On S(X) calculators the address area #00052-#00070, on G(X) calculators +the address area #00058-#00076 in Port0 are rewritten with the actual time +information. + + + ************* + * EMU48.INI * + ************* + +The section [Timers] in the Emu48.ini file isn't used any more. The variable +values are replaced by useful constants. You may delete this section if you +want. Starting an old version of Emu48 (V1.07 and earlier) will add this section +again. + + + ************************ + * REAL SPEED EMULATION * + ************************ + +As you recognized the speed of the emulated HP48 is much faster than an original +HP48. The reason is, the assembler commands are emulated faster than the +original CPU can execute them. On one side this is a big advantage (faster +execution of programs) on the other side this cause many trouble. In Emu48 only +the timers work with the original speed. In result all commands like User-RPL +WAIT wait more or less the correct time. But many programs like shells or +editors use an own key handler to realize an autorepeat implementation. Normally +these programs use the execution time of each assembler command for waiting. On +Emu48 this time is much shorter, so the time between each key read is shorter as +well and you get a very fast key repetition. The editor ED from the JAZZ package +hasn't this problem, because the key input is synchronized with one of the +timers. To solve this problem Emu48 generally slow down emulation if a key is +pressed. To solve some other speed depending problems you are able to slow down +the whole emulation speed. There are two variables 'SXCycles=82' and +'GXCycles=123' defined in the Emu48.ini file, section [Emulator] which control +the "real" speed and key repetition slow down for each calculator type. Each +numeric value is representing the allowed CPU cycles in a 16384Hz time frame. +Because the used cycle statements (from SASM.DOC) in Emu48 doesn't correspond to +the real values of the CPU, the saved values are estimated by comparing the +execution time of a program to the real calculator. Increasing the value fitting +to your ROM will make the "real speed" HP faster and vice versa. No warranty to +the functionality of Emu48 when you go below the default values. + + + ************************* + * SERIAL PORT EMULATION * + ************************* + +The serial ports are emulated as well now. You may choose the same serial port +for wire and IR. Remember that the IR port only work with 2400 Baud. If you want +to change the serial port settings, but they are disabled, close the serial port +with the command CLOSEIO or power cycle the HP48 first. + +Now it's possible to make transfers between the HP48 and Emu48. If you have +problems with the connection please try the following. There's a simple way to +check if your serial port is used by another program. First disable the serial +settings in both combo boxes and very important close the settings dialog. +Reopen the settings dialog and choose the COM port in the wire combo box to the +port the HP48 is connected with. When you open this combo box you only see valid +(unused) serial ports. Don't use the IR combo box, it only works with 2400 Baud. +The next important thing are the serial settings of the HP48 and Emu48, they +must be equal. If this doesn't work then mostly there's a hardware or a resource +problem of the serial port. Check this with connecting the HP48 with a transfer +program you like on the same serial port. + + + **************** + * DISASSEMBLER * + **************** + +With the internal disassembler you're able to disassemble the HP48 address area. +With the default Map setting the disassembler always see the mapped memory +address. If for example you configured the RAM at #00000 you will see the RAM +and not the ROM at this address. With the other Module settings you specify a +special module for disassembly. Each module will begin at address #00000 and +will not overlapped by other modules. For Port2 I use a linear address mode, +that means that the second port of a RAM card greater than 128KB is at address +#40000 (128 * 1024 * 2) and so on. The "Copy Data" button copies the selected +disassembler lines to the PC clipboard. + + + ************** + * DDE SERVER * + ************** + +I implemented a DDE server in Emu48 to transmit data from and to the HP stack +with DDE. You have the same restrictions like with the commands "Load object..." +and "Save Object...", that a running program may corrupt memory. Take care to +transmit data only after the acknowledge of the last DDE transaction. + +Technical data: + +Servername: Emu48 +Topicname: Stack +Item: Dummy (ignored, must be a nonzero string) +Clipboardformat: "CF_HPOBJ" (user defined) + +The DDE commands CONNECT, POKE and REQUEST are supported. + +The structure of the clipboard format "CF_HPOBJ": + ++--------+------------------------------------+ +| 4 Byte | HP object | ++--------+------------------------------------+ + \ \ + \ +--- normal HP object + +----------- length of object (LSB first) ******************** * TROUBLE SHOOTING * ******************** -Q: The emulator display the keyboard, but the screen stays blank or is filled - with garbage. -A: Your ROM image is probably wrong. Check it with the Convert utility, and if - it says that the CRC is wrong, you should try to download your ROM again. - -Q: What does this message mean : - "This file is missing or already loaded in another instance of Emu48." -A: Maybe you deleted or moved the files that the emulator tries to load when - starting (the last files you saved). - The other possibility is that you are running several instances of Emu48, - but you are trying to load the same file in both instances, which causes - a sharing violation. - +Visit the Emu48 FAQ site at http://privat.swol.de/ChristophGiesselink/index.htm +to get more information please. *********** * SUPPORT * *********** -I cannot provide individual support for Emu48, but I will read all the mails -that you send. -All informations about Emu48 will be on the Emu48 Official Homepage on the Web : +We cannot provide individual support for Emu48, but we will read all the mails +that you send. All informations about Emu48 will be on the Emu48 Official +Homepage on the Web: - http://www.epita.fr/~sebc/Emu48 + http://www.epita.fr/~sebc/Emu48/index.html -Service packs are maintained by Christoph Gießelink : +or on the Emu48 FAQ at - http://privat.swol.de/ChristophGiesselink/ + http://privat.swol.de/ChristophGiesselink/index.htm + +Other graphics and scripts are available at Casey's Emu48 Graphics Page: -Other graphics and scripts are available at Casey's Emu48 Graphics Page : http://www.gulftel.com/~pattersc/emu48/ - *************** * LEGAL STUFF * *************** + +Emu48 - An HP38/48/49 Emulator +Copyright (C) 1999 Sebastien Carlier & Christoph Gießelink - Emu48 - An HP48 Emulator - Copyright (C) 1997 Sebastien Carlier +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA - - ************** - * The Author * - ************** + *************** + * The Authors * + *************** Paper Mail: Sebastien Carlier @@ -233,4 +419,15 @@ E-Mail: sebc@epita.fr Homepage: - http://www.epita.fr/~sebc + http://www.epita.fr/~sebc/Emu48/index.html + + +Paper Mail: + Christoph Giesselink + GERMANY + +E-Mail: + cgiess@swol.de + +Homepage: + http://privat.swol.de/ChristophGiesselink/index.htm diff --git a/EMU48SP.TXT b/EMU48SP.TXT deleted file mode 100644 index 33c9168..0000000 --- a/EMU48SP.TXT +++ /dev/null @@ -1,137 +0,0 @@ - - - Emu48 - A freeware HP48 Emulator for Windows 95 and NT - - ---- Changes and Additions of Emu48 V1.0 --- - -Thank Sebastien Carlier for his emulator and that he made the sources public. Special thanks to Jean-Yves Avenard, Cyrille de Brebisson and Will Laughin for there suggestions, additions and fixes. - -My first contact with this emulator (Shareware Win48) was in early 1997. At this time I worked with Windows NT 4.0. The emulator was unusable for me at this time. As well I had some problems with the latest version of Emu48 (Version 1.0). This was the beginning of the "Unofficial Service Packs". - - - ******************** - * OPERATING SYSTEM * - ******************** - -This version of Emu48 should work with all Intel Win32 platforms. Several problems with Windows NT 4.0, Win95b and Win98 are fixed now. You may recompile the sources to run Emu48 on a DEC Alpha. - - - **************** - * COMMAND LINE * - **************** - -The command line syntax is "Emu48 [E48file [Port2file]]". The first parameter sets the filename for the Emulation Data, the second parameter the Port2 file. You're not able to set a Port2 file without setting the Emulation Data file. The arguments are optional. - - - *********** - * DISPLAY * - *********** - -The display emulation is now closer to the original. But there are several problems left, especially with the gray scale emulation. - - - ******************** - * KEYBOARD CHANGES * - ******************** - -I changed the behavior for pressing more than one key. All keys will release, when you go outside the button area now. To hold down a key, you have to press the right mouse button. The key autorepeat emulation is working now. - - - ********* - * CLOCK * - ********* - -The emulator time is synchronized with the PC time at startup of the emulator. This may cause problems with other non original operating systems running on the HP48. On S(X) calculators the address area #00052-#00070, on G(X) calculators the address area #00058-#00076 in Port0 are rewritten with the actual time information. - - - *************** - * KML SCRIPTS * - *************** - -Your LCD contrast setting will be saved now. In some cases you have to fix Color 0 in your KML script file, because the colors red and blue has been swapped in the "Lcd" section. Don't use TRUELCD.KMI for emulating display contrast in your scripts. It's not fully correct. The hardware contrast values are in the area from 0 to 31. But the HP48 roms bounds them to useful values. The S(X) ROM use only display contrast values between 3 and 19 and the G(X) ROM values between 9 and 24. - -You're able to define a different background color for each contrast value for a more realistic display emulation now. The background color entry for the corresponding color is calculated by adding 32 to the color value. That means the color definitions from 32 to 63 are background colors. If the background color for the contrast isn't defined, Color 0 is used. - -You can use 4 as new value for "Zoom" in the "Lcd" section of the KML script for a very big display view now. - - - *********************** - * COPY / PASTE STRING * - *********************** - -With the menu items "Copy String" and "Paste String" in the "Edit" menu you're able to copy HP48 string objects from the stack to the PC Clipboard and vice versa. - - - ***************** - * DRAG AND DROP * - ***************** - -Dropping HP48 objects over the emulator window will load program files (like the command "Load object...") on the stack. Be sure that the emulator isn't busy before doing this. - - - ************* - * EMU48.INI * - ************* - -The section [Timers] in the Emu48.ini file isn't used any more. The variable values are replaced by useful constants. You may delete this section if you want. Starting an old version of Emu48 (V1.07 and earlier) will add this section again. - - - ************************ - * REAL SPEED EMULATION * - ************************ - -As you recognized the speed of the emulated HP48 is much faster than an original HP48. The reason is, the assembler commands are emulated faster than the original CPU can execute them. On one side this is a big advantage (faster execution of programs) on the other side this cause many trouble. In Emu48 only the timers work with the original speed. In result all commands like User-RPL WAIT wait more or less the correct time. But many programs like shells or editors use an own key handler to realize an autorepeat implementation. Normally these programs use the execution time of each assembler command for waiting. On Emu48 this time is much shorter, so the time between each key read is shorter as well and you get a very fast key repetition. The editor ED from the JAZZ package hasn't this problem, because the key input is synchronized with one of the timers. To solve this problem Emu48 generally slow down emulation if a key is pressed. To solve some other speed depending problems you are able to slow down the whole emulation speed. There are two variables 'SXCycles=82' and 'GXCycles=123' defined in the Emu48.ini file, section [Emulator] which control the "real" speed and key repetition slow down for each calculator type. Each numeric value is representing the allowed CPU cycles in a 16384Hz time frame. Because the used cycle statements (from SASM.DOC) in Emu48 doesn't correspond to the real values of the CPU, the saved values are estimated by comparing the execution time of a program to the real calculator. Increasing the value fitting to your ROM will make the "real speed" HP faster and vice versa. No warranty to the functionality of Emu48 when you go below the default values. - - - ************************* - * SERIAL PORT EMULATION * - ************************* - -The serial ports are emulated as well now. You may choose the same serial port for wire and IR. Remember that the IR port only work with 2400 Baud. There's a problem known with the command RECX from the Library 1275: "XYMODEM v3.2 for S/G". On fast PC's this command doesn't work. Slow down emulation to run it. If you want to change the serial port settings, but they are disabled, close the serial port with the command CLOSEIO or power cycle the HP48 first. - -Now it's possible to make transfers between the HP48 and Emu48. If you have problems with the connection please try the following. There's a simple way to check if your serial port is used by another program. First disable the serial settings in both combo boxes and very important close the settings dialog. Reopen the settings dialog and choose the COM port in the wire combo box to the port the HP48 is connected with. When you open this combo box you only see valid (unused) serial ports. Don't use the IR combo box, it only works with 2400 Baud. The next important thing are the serial settings of the HP48 and Emu48, they must be equal. If this doesn't work then mostly there's a hardware problem, check this with connecting the HP48 with a transfer program you like on the same serial port. - - - **************** - * DISASSEMBLER * - **************** - -With the internal disassembler you're able to disassemble the HP48 address area. With the default Map setting the disassembler always see the mapped memory address. If for example you configured the RAM at #00000 you will see the RAM and not the ROM at this address. With the other Module settings you specify a special module for disassembly. Each module will begin at address #00000 and will not overlapped by other modules. For Port2 I use a linear address mode, that means that the second port of a RAM card greater than 128K is at address #40000 (128 * 1024 * 2) and so on. The "Copy Data" button copies the selected disassembler lines to the PC Clipboard. - - - ************** - * DDE SERVER * - ************** - -I implemented a DDE server in Emu48 to transmit data from and to the HP stack with DDE. You have the same restrictions like with the commands "Load object..." and "Save Object...", that a running program may corrupt memory. Take care to transmit data only after the acknowledge of the last DDE transaction. - -Technical data: - -Servername: Emu48 -Topicname: Stack -Item: Dummy (ignored, must be a nonzero string) -Clipboardformat: "CF_HPOBJ" (user defined) - -The DDE commands CONNECT, POKE and REQUEST are supported. - -The structure of the clipboard format "CF_HPOBJ": - -+--------+------------------------------------+ -| 4 Byte | HP object | -+--------+------------------------------------+ - \ \ - \ +--- normal HP object - +----------- length of object (LSB first) - - - ******** - * TIPS * - ******** - -I hope some of your Emu48 problems has been solved as well. If you use a patched ROM version (i.e. to solve the auto off problem), try an unpatched one. - - -Christoph Gießelink, cgiess@swol.de - -http://privat.swol.de/ChristophGiesselink diff --git a/JC.BMP b/JC.BMP deleted file mode 100644 index 92d366c..0000000 Binary files a/JC.BMP and /dev/null differ diff --git a/JC.KML b/JC.KML deleted file mode 100644 index 0eadb32..0000000 --- a/JC.KML +++ /dev/null @@ -1,364 +0,0 @@ -Global - Title "Small but realistic HP48 Gx" - Author "Jeffery L. McMahan and Sebastien Carlier" - Print "Original picture by Jeffery L. McMahan" - Print "Modified for VGA by Sebastien Carlier" - Model "G" - Rom "ROM.48G" - Patch "BEEP.EXT" - Bitmap "jc.bmp" - Debug 1 -End - -Background - Offset 0 0 - Size 165 353 -End - -Lcd - Zoom 1 - Offset 17 43 - Include "TrueLCD.kmi" -End - -Annunciator 1 - Size 8 6 - Offset 40 45 - Down 0 400 -End - -Annunciator 2 - Size 8 6 - Offset 60 45 - Down 9 400 -End - -Annunciator 3 - Size 8 6 - Offset 80 45 - Down 17 400 -End - -Annunciator 4 - Size 10 6 - Offset 100 45 - Down 25 400 -End - -Annunciator 5 - Size 5 6 - Offset 120 45 - Down 35 400 -End - -Annunciator 6 - Size 7 6 - Offset 140 45 - Down 43 400 -End - -Button 11 - Type 3 - Size 16 10 - Offset 17 139 - OutIn 1 16 -End -Button 12 - Type 3 - Size 16 10 - Offset 40 139 - OutIn 8 16 -End -Button 13 - Type 3 - Size 16 10 - Offset 63 139 - OutIn 8 8 -End -Button 14 - Type 3 - Size 16 10 - Offset 86 139 - OutIn 8 4 -End -Button 15 - Type 3 - Size 16 10 - Offset 109 139 - OutIn 8 2 -End -Button 16 - Type 3 - Size 16 10 - Offset 132 139 - OutIn 8 1 -End - -Button 21 - Type 3 - Size 16 12 - Offset 17 162 - OutIn 2 16 -End -Button 22 - Type 3 - Size 16 12 - Offset 40 162 - OutIn 7 16 -End -Button 23 - Type 3 - Size 16 12 - Offset 63 162 - OutIn 7 8 -End -Button 24 - Type 3 - Size 16 12 - Offset 86 162 - OutIn 7 4 -End -Button 25 - Type 3 - Size 16 12 - Offset 109 162 - OutIn 7 2 -End -Button 26 - Type 3 - Size 16 12 - Offset 132 162 - OutIn 7 1 -End - -Button 31 - Type 3 - Size 16 12 - Offset 17 184 - OutIn 0 16 -End -Button 32 - Type 3 - Size 16 12 - Offset 40 184 - OutIn 6 16 -End -Button 33 - Type 3 - Size 16 12 - Offset 63 184 - OutIn 6 8 -End -Button 34 - Type 3 - Size 16 12 - Offset 86 184 - OutIn 6 4 -End -Button 35 - Type 3 - Size 16 12 - Offset 109 184 - OutIn 6 2 -End -Button 36 - Type 3 - Size 16 12 - Offset 132 184 - OutIn 6 1 -End - -Button 41 - Type 3 - Size 16 12 - Offset 17 207 - OutIn 3 16 -End -Button 42 - Type 3 - Size 16 12 - Offset 40 207 - OutIn 5 16 -End -Button 43 - Type 3 - Size 16 12 - Offset 63 207 - OutIn 5 8 -End -Button 44 - Type 3 - Size 16 12 - Offset 86 207 - OutIn 5 4 -End -Button 45 - Type 3 - Size 16 12 - Offset 109 207 - OutIn 5 2 -End -Button 46 - Type 3 - Size 16 12 - Offset 132 207 - OutIn 5 1 -End - -Button 51 - Type 1 - Size 39 12 - Offset 17 229 - OutIn 4 16 -End -Button 52 - Type 3 - Size 16 10 - Offset 70 229 - OutIn 4 8 -End -Button 53 - Type 3 - Size 16 10 - Offset 95 229 - OutIn 4 4 -End -Button 54 - Type 3 - Size 16 10 - Offset 121 229 - OutIn 4 2 -End -Button 55 - Type 3 - Size 16 10 - Offset 147 229 - OutIn 4 1 -End - -Button 61 - Type 3 - Size 16 10 - Offset 19 252 - OutIn 3 32 -End -Button 62 - Type 3 - Size 21 12 - Offset 43 252 - OutIn 3 8 -End -Button 63 - Type 3 - Size 21 12 - Offset 79 252 - OutIn 3 4 -End -Button 64 - Type 3 - Size 21 12 - Offset 110 252 - OutIn 3 2 -End -Button 65 - Type 3 - Size 21 12 - Offset 141 252 - OutIn 3 1 -End - -Button 71 - Type 3 - Size 16 10 - Offset 19 274 - OutIn 2 32 -End -Button 72 - Type 3 - Size 21 12 - Offset 48 274 - OutIn 2 8 -End -Button 73 - Type 3 - Size 21 12 - Offset 79 274 - OutIn 2 4 -End -Button 74 - Type 3 - Size 21 12 - Offset 110 274 - OutIn 2 2 -End -Button 75 - Type 3 - Size 21 12 - Offset 141 274 - OutIn 2 1 -End - -Button 81 - Type 3 - Size 16 10 - Offset 19 297 - OutIn 1 32 -End -Button 82 - Type 3 - Size 21 12 - Offset 48 297 - OutIn 1 8 -End -Button 83 - Type 3 - Size 21 12 - Offset 79 297 - OutIn 1 4 -End -Button 84 - Type 3 - Size 21 12 - Offset 110 297 - OutIn 1 2 -End -Button 85 - Type 3 - Size 21 12 - Offset 141 297 - OutIn 1 1 -End - -Button 91 - Type 3 - Size 16 10 - Offset 19 319 - OutIn 0 32768 -End -Button 92 - Type 3 - Size 21 12 - Offset 48 319 - OutIn 0 8 -End -Button 93 - Type 3 - Size 21 12 - Offset 79 319 - OutIn 0 4 -End -Button 94 - Type 3 - Size 21 12 - Offset 110 319 - OutIn 0 2 -End -Button 95 - Type 3 - Size 21 12 - Offset 141 319 - OutIn 0 1 -End - -Include "Keyboard.kmi" - diff --git a/JEMAC.BMP b/JEMAC.BMP new file mode 100644 index 0000000..51868f2 Binary files /dev/null and b/JEMAC.BMP differ diff --git a/JEMAC.KML b/JEMAC.KML index 7dc72cc..e803c1f 100644 --- a/JEMAC.KML +++ b/JEMAC.KML @@ -16,38 +16,70 @@ End Lcd Zoom 2 Offset 34 86 - Color 0 123 132 99 + Color 0 123 132 99 # character color table Color 1 123 132 99 Color 2 123 132 99 Color 3 123 132 99 Color 4 123 132 99 Color 5 123 132 99 Color 6 123 132 99 - Color 7 123 132 99 - Color 8 123 132 99 + Color 7 121 132 99 + Color 8 121 132 99 Color 9 116 124 96 - Color 10 109 116 93 - Color 11 102 108 90 - Color 12 95 100 87 - Color 13 88 92 84 - Color 14 81 84 78 - Color 15 74 76 75 - Color 16 67 68 72 - Color 17 60 60 69 - Color 18 53 52 66 - Color 19 46 44 63 - Color 20 39 36 60 - Color 21 32 28 57 - Color 22 25 20 54 - Color 23 18 12 51 - Color 24 11 4 48 - Color 25 4 0 45 - Color 26 0 0 42 - Color 27 0 0 39 - Color 28 0 0 36 - Color 29 0 0 33 - Color 30 0 0 30 - Color 31 0 0 27 + Color 10 101 107 88 + Color 11 86 90 80 + Color 12 71 73 72 + Color 13 56 56 64 + Color 14 41 39 56 + Color 15 26 22 48 + Color 16 11 5 40 + Color 17 11 5 40 + Color 18 11 5 40 + Color 19 11 5 40 + Color 20 11 5 40 + Color 21 11 5 40 + Color 22 11 5 40 + Color 23 11 5 40 + Color 24 11 5 40 # last GX + Color 25 11 5 40 + Color 26 11 5 40 + Color 27 11 5 40 + Color 28 11 5 40 + Color 29 11 5 40 + Color 30 11 5 40 + Color 31 11 5 40 + Color 32 123 132 99 # background color table + Color 33 123 132 99 + Color 34 123 132 99 + Color 35 123 132 99 + Color 36 123 132 99 + Color 37 121 132 99 + Color 38 121 132 99 + Color 39 123 132 99 + Color 40 123 132 99 + Color 41 123 132 99 + Color 42 123 132 99 + Color 43 123 132 99 + Color 44 123 132 99 + Color 45 123 132 99 + Color 46 123 132 99 + Color 47 123 132 99 + Color 48 123 132 99 + Color 49 111 119 95 + Color 50 99 106 91 + Color 51 87 93 87 + Color 52 75 80 83 + Color 53 63 67 79 + Color 54 51 54 75 + Color 55 39 41 72 + Color 56 27 28 67 + Color 57 15 15 62 + Color 58 3 2 57 + Color 59 0 0 52 + Color 60 0 0 47 + Color 61 0 0 42 + Color 62 0 0 37 + Color 63 0 0 32 End Annunciator 1 @@ -438,6 +470,10 @@ Scancode 40 Map 40 35 End +Scancode 48 + Map 48 92 +End + Scancode 49 IfFlag 0 Map 49 71 diff --git a/PROBLEMS.TXT b/PROBLEMS.TXT index 377e034..50930f1 100644 --- a/PROBLEMS.TXT +++ b/PROBLEMS.TXT @@ -1,12 +1,18 @@ -Known bugs and restrictions of Emu48 V1.10 +Known bugs and restrictions of Emu48 V1.15 ------------------------------------------ -- input cursor blink frequency on stack view is wrong when a key is - hold down -- the POWERCTRL register (0x109) isn't emulated -- bit 3 [UCK] of the BAUD register (0x10D) isn't emulated -- the bits of the SRQ registers (0x118,0x119), except the KDN bit, - aren't emulated +- the following I/O bits aren't emulated (incomplete) + DTEST (0x102) [VDIG LID TRIM] + DSPCTL (0x103) [LRT LRTD LRTC BIN] + LPE (0x109) [ELBI EVLBI GRST RST] + IOC (0x110) [ERBZ] + RCS (0x111) [RX RER RBZ] + TCS (0x112) [BRK TBZ TBF] + SRQ1 (0x118) [ISQR VSRQ] + SRQ2 (0x119) [LSRQ] + IRC (0x11A) [IRI EIRU EIRI IRE] + LCR (0x11C) [LED ELBE LBZ LBF] + LBR (0x11D) [LBO] - the baudrates 1920, 3840, 7680 and 15360 aren't emulated on most operating systems Windows 95a 1920, 3840, 7680 work, 15360 fail @@ -14,9 +20,6 @@ Known bugs and restrictions of Emu48 V1.10 Windows NT4.0 SP3 all baudrates fail - System-RPL commands VERYVERYSLOW, VERYSLOW and SLOW depends on PC speed (are realized as simple down counter in ROM) -- in all original KML scripts Color 7 is missing in the LCD section -- because of correcting the RGB order in SetLcdColor() the LCD - background color may be wrong in some KML scripts - display updating differs from the real machine - screen VBL counter values may skip after large display operations like turning on or updating the whole display @@ -26,12 +29,16 @@ Known bugs and restrictions of Emu48 V1.10 because the emulator don't use a multiplexed AR18 / NCE3 data line -> all programs that run on a real calculator will run as well, programs with incorrect DA19 / BEN handling may run on the - emulator and will crash on a real calculator + emulator but will crash on a real calculator - no beeper support with OUT command -> all programs that aren't use the "=makebeep" subroutine, like alarm wake up, have no sound - beeper emulation, ATTN key doesn't work, Windows 9x: plays only default sound event or standard system beep - no infrared printer support +- memory window of debugger view some addresses in I/O register area + with invalid data - Shell OS: clock isn't synchronized with real time +- HP49G: flash ROM is treated as ROM (no writing to flash memory) + -> writing to port 2:FLASH will crash the emulation! -03/11/99 (c) by Christoph Gießelink, cgiess@swol.de +12/14/99 (c) by Christoph Gießelink, cgiess@swol.de diff --git a/REALGX.BMP b/REALGX.BMP new file mode 100644 index 0000000..89bcde4 Binary files /dev/null and b/REALGX.BMP differ diff --git a/REALGX.KML b/REALGX.KML new file mode 100644 index 0000000..6561656 --- /dev/null +++ b/REALGX.KML @@ -0,0 +1,722 @@ +Global + Print "==========================================================" + Print "" + Print "This graphic is by Casey Patterson." + Print "pattersc@gulftel.com" + Print "" + Print "Come to my page to get more graphics for your Win48!!!" + Print "" + Print "http://www.gulftel.com/~pattersc/win48/" + Print "" + Print "==========================================================" + Title "Casey's Real Gx" + Author "Casey Patterson" + Model "G" + Rom "ROM.48G" + Patch "BEEP.EXT" + Bitmap "realgx.bmp" + Debug 0 +End + +Background + Offset 0 0 + Size 183 400 +End + +Lcd + Zoom 1 + Offset 27 53 + Color 0 123 132 99 + Color 1 123 132 99 + Color 2 123 132 99 + Color 3 123 132 99 + Color 4 123 132 99 + Color 5 123 132 99 + Color 6 123 132 99 + Color 7 123 132 99 + Color 8 123 132 99 + Color 9 116 124 96 + Color 10 109 116 93 + Color 11 102 108 90 + Color 12 95 100 87 + Color 13 88 92 84 + Color 14 81 84 78 + Color 15 74 76 75 + Color 16 67 68 72 + Color 17 60 60 69 + Color 18 53 52 66 + Color 19 46 44 63 + Color 20 39 36 60 + Color 21 32 28 57 + Color 22 25 20 54 + Color 23 18 12 51 + Color 24 11 4 48 + Color 25 4 0 45 + Color 26 0 0 42 + Color 27 0 0 39 + Color 28 0 0 36 + Color 29 0 0 33 + Color 30 0 0 30 + Color 31 0 0 27 +End + +Annunciator 1 + Size 8 6 + Offset 40 45 + Down 0 400 +End + +Annunciator 2 + Size 8 6 + Offset 60 45 + Down 9 400 +End + +Annunciator 3 + Size 8 6 + Offset 80 45 + Down 17 400 +End + +Annunciator 4 + Size 10 6 + Offset 100 45 + Down 25 400 +End + +Annunciator 5 + Size 5 6 + Offset 120 45 + Down 35 400 +End + +Annunciator 6 + Size 7 6 + Offset 140 45 + Down 43 400 +End + +Button 11 + Type 1 + Size 19 13 + Offset 18 156 + OutIn 1 16 +End +Button 12 + Type 1 + Size 19 13 + Offset 44 156 + OutIn 8 16 +End +Button 13 + Type 1 + Size 19 13 + Offset 70 156 + OutIn 8 8 +End +Button 14 + Type 1 + Size 19 13 + Offset 95 156 + OutIn 8 4 +End +Button 15 + Type 1 + Size 19 13 + Offset 121 156 + OutIn 8 2 +End +Button 16 + Type 1 + Size 19 13 + Offset 147 156 + OutIn 8 1 +End + +Button 21 + Type 1 + Size 19 15 + Offset 18 182 + OutIn 2 16 +End +Button 22 + Type 1 + Size 19 15 + Offset 44 182 + OutIn 7 16 +End +Button 23 + Type 1 + Size 19 15 + Offset 70 182 + OutIn 7 8 +End +Button 24 + Type 1 + Size 19 15 + Offset 95 182 + OutIn 7 4 +End +Button 25 + Type 1 + Size 19 15 + Offset 121 182 + OutIn 7 2 +End +Button 26 + Type 1 + Size 19 15 + Offset 147 182 + OutIn 7 1 +End + +Button 31 + Type 1 + Size 19 15 + Offset 18 208 + OutIn 0 16 +End +Button 32 + Type 1 + Size 19 15 + Offset 44 208 + OutIn 6 16 +End +Button 33 + Type 1 + Size 19 15 + Offset 70 208 + OutIn 6 8 +End +Button 34 + Type 1 + Size 19 15 + Offset 95 208 + OutIn 6 4 +End +Button 35 + Type 1 + Size 19 15 + Offset 121 208 + OutIn 6 2 +End +Button 36 + Type 1 + Size 19 15 + Offset 147 208 + OutIn 6 1 +End + +Button 41 + Type 1 + Size 19 15 + Offset 18 233 + OutIn 3 16 +End +Button 42 + Type 1 + Size 19 15 + Offset 44 233 + OutIn 5 16 +End +Button 43 + Type 1 + Size 19 15 + Offset 70 233 + OutIn 5 8 +End +Button 44 + Type 1 + Size 19 15 + Offset 95 233 + OutIn 5 4 +End +Button 45 + Type 1 + Size 19 15 + Offset 121 233 + OutIn 5 2 +End +Button 46 + Type 1 + Size 19 15 + Offset 147 233 + OutIn 5 1 +End + +Button 51 + Type 1 + Size 45 15 + Offset 18 259 + OutIn 4 16 +End +Button 52 + Type 1 + Size 19 15 + Offset 70 259 + OutIn 4 8 +End +Button 53 + Type 1 + Size 19 15 + Offset 95 259 + OutIn 4 4 +End +Button 54 + Type 1 + Size 19 15 + Offset 121 259 + OutIn 4 2 +End +Button 55 + Type 1 + Size 19 15 + Offset 147 259 + OutIn 4 1 +End + +Button 61 + Type 1 + Size 18 15 + Offset 19 284 + OutIn 3 32 +End +Button 62 + Type 1 + Size 24 15 + Offset 48 284 + OutIn 3 8 +End +Button 63 + Type 1 + Size 24 15 + Offset 79 284 + OutIn 3 4 +End +Button 64 + Type 1 + Size 24 15 + Offset 110 284 + OutIn 3 2 +End +Button 65 + Type 1 + Size 24 15 + Offset 141 284 + OutIn 3 1 +End + +Button 71 + Type 1 + Size 18 15 + Offset 19 310 + OutIn 2 32 +End +Button 72 + Type 1 + Size 24 15 + Offset 48 310 + OutIn 2 8 +End +Button 73 + Type 1 + Size 24 15 + Offset 79 310 + OutIn 2 4 +End +Button 74 + Type 1 + Size 24 15 + Offset 110 310 + OutIn 2 2 +End +Button 75 + Type 1 + Size 24 15 + Offset 141 310 + OutIn 2 1 +End + +Button 81 + Type 1 + Size 18 15 + Offset 19 335 + OutIn 1 32 +End +Button 82 + Type 1 + Size 24 15 + Offset 48 335 + OutIn 1 8 +End +Button 83 + Type 1 + Size 24 15 + Offset 79 335 + OutIn 1 4 +End +Button 84 + Type 1 + Size 24 15 + Offset 110 335 + OutIn 1 2 +End +Button 85 + Type 1 + Size 24 15 + Offset 141 335 + OutIn 1 1 +End + +Button 91 + Type 1 + Size 18 15 + Offset 19 361 + OutIn 0 32768 +End +Button 92 + Type 1 + Size 24 15 + Offset 48 361 + OutIn 0 8 +End +Button 93 + Type 1 + Size 24 15 + Offset 79 361 + OutIn 0 4 +End +Button 94 + Type 1 + Size 24 15 + Offset 110 361 + OutIn 0 2 +End +Button 95 + Type 1 + Size 24 15 + Offset 141 361 + OutIn 0 1 +End + + +Scancode 8 + Map 8 55 +End + +Scancode 13 + Map 13 51 +End + +Scancode 16 + IfPressed 16 + SetFlag 0 + Else + ResetFlag 0 + End +End + +Scancode 17 + IfPressed 17 + SetFlag 1 + Else + ResetFlag 1 + End +End + +Scancode 27 + Map 27 91 +End + +Scancode 37 + Map 37 34 +End + +Scancode 38 + Map 38 25 +End + +Scancode 39 + Map 39 36 +End + +Scancode 40 + Map 40 35 +End + +Scancode 49 + IfFlag 0 + Map 49 71 + Map 49 54 + Else + Map 49 82 + End +End + +Scancode 50 + Map 50 83 +End + +Scancode 51 + IfFlag 0 + Map 51 81 + Map 51 65 + Else + Map 51 84 + End +End + +Scancode 52 + Map 52 72 +End + +Scancode 53 + Map 53 73 +End + +Scancode 54 + Map 54 74 +End + +Scancode 55 + Map 55 62 +End + +Scancode 56 + IfFlag 0 + Map 56 75 + Else + Map 56 63 + End +End + +Scancode 57 + IfFlag 0 + Map 57 71 + Map 57 65 + Else + Map 57 64 + End +End + +Scancode 65 + Map 65 11 +End + +Scancode 66 + Map 66 12 +End + +Scancode 67 + Map 67 13 +End + +Scancode 68 + Map 68 14 +End + +Scancode 69 + Map 69 15 +End + +Scancode 70 + Map 70 16 +End + +Scancode 71 + Map 71 21 +End + +Scancode 72 + Map 72 22 +End + +Scancode 73 + Map 73 23 +End + +Scancode 74 + Map 74 24 +End + +Scancode 75 + Map 75 25 +End + +Scancode 76 + Map 76 26 +End + +Scancode 77 + Map 77 31 +End + +Scancode 78 + IfFlag 1 + MenuItem 1 + Else + Map 78 32 + End +End + +Scancode 79 + Map 79 33 +End + +Scancode 80 + Map 80 34 +End + +Scancode 81 + Map 81 35 +End + +Scancode 82 + Map 82 36 +End + +Scancode 83 + Map 83 41 +End + +Scancode 84 + Map 84 42 +End + +Scancode 85 + Map 85 43 +End + +Scancode 86 + Map 86 44 +End + +Scancode 87 + Map 87 45 +End + +Scancode 88 + Map 88 46 +End + +Scancode 89 + Map 89 52 +End + +Scancode 90 + Map 90 53 +End + +Scancode 96 + Map 96 92 +End + +Scancode 97 + Map 97 82 +End + +Scancode 98 + Map 98 83 +End + +Scancode 99 + Map 99 84 +End + +Scancode 100 + Map 100 72 +End + +Scancode 101 + Map 101 73 +End + +Scancode 102 + Map 102 74 +End + +Scancode 103 + Map 103 62 +End + +Scancode 104 + Map 104 63 +End + +Scancode 105 + Map 105 64 +End + +Scancode 106 + Map 106 75 +End + +Scancode 107 + Map 107 95 +End + +Scancode 109 + Map 109 85 +End + +Scancode 110 + Map 110 93 +End + +Scancode 111 + Map 111 65 +End + +Scancode 186 + IfFlag 0 + Map 186 81 + Map 186 95 + End +End + +Scancode 188 + Map 188 71 + Map 188 93 +End + +Scancode 190 + Map 190 93 +End + +Scancode 191 + IfFlag 0 + Map 191 71 + Map 191 55 + Else + Map 191 65 + End +End + +Scancode 219 + IfFlag 0 + Map 219 71 + Map 219 95 + Else + Map 219 71 + Map 219 75 + End +End + +Scancode 220 + Map 220 54 +End + +Scancode 222 + IfFlag 0 + Map 222 81 + Map 222 85 + Else + Map 222 31 + End +End + + + + + + diff --git a/REALSX.BMP b/REALSX.BMP new file mode 100644 index 0000000..683854b Binary files /dev/null and b/REALSX.BMP differ diff --git a/REALSX.KML b/REALSX.KML new file mode 100644 index 0000000..d8a8a13 --- /dev/null +++ b/REALSX.KML @@ -0,0 +1,722 @@ +Global + Print "==========================================================" + Print "" + Print "This graphic is by Casey Patterson." + Print "pattersc@gulftel.com" + Print "" + Print "Come to my page to get more graphics for your Win48!!!" + Print "" + Print "http://www.gulftel.com/~pattersc/win48/" + Print "" + Print "==========================================================" + Title "Casey's Real Sx" + Author "Casey Patterson" + Model "S" + Rom "ROM.48S" + Patch "BEEP.EXT" + Bitmap "realsx.bmp" + Debug 0 +End + +Background + Offset 0 0 + Size 183 400 +End + +Lcd + Zoom 1 + Offset 26 53 + Color 0 161 173 130 + Color 1 0 0 0 + Color 2 0 0 0 + Color 3 0 0 0 + Color 4 0 0 0 + Color 5 0 0 0 + Color 6 0 0 0 + Color 7 0 0 0 + Color 8 0 0 0 + Color 9 0 0 0 + Color 10 0 0 0 + Color 11 0 0 0 + Color 12 0 0 0 + Color 13 0 0 0 + Color 14 0 0 0 + Color 15 0 0 0 + Color 16 0 0 0 + Color 17 0 0 0 + Color 18 0 0 0 + Color 19 0 0 0 + Color 20 0 0 0 + Color 21 0 0 0 + Color 22 0 0 0 + Color 23 0 0 0 + Color 24 0 0 0 + Color 25 0 0 0 + Color 26 0 0 0 + Color 27 0 0 0 + Color 28 0 0 0 + Color 29 0 0 0 + Color 30 0 0 0 + Color 31 0 0 0 +End + +Annunciator 1 + Size 8 6 + Offset 40 45 + Down 0 400 +End + +Annunciator 2 + Size 8 6 + Offset 60 45 + Down 9 400 +End + +Annunciator 3 + Size 8 6 + Offset 80 45 + Down 17 400 +End + +Annunciator 4 + Size 10 6 + Offset 100 45 + Down 25 400 +End + +Annunciator 5 + Size 5 6 + Offset 120 45 + Down 35 400 +End + +Annunciator 6 + Size 7 6 + Offset 140 45 + Down 43 400 +End + +Button 11 + Type 1 + Size 19 13 + Offset 18 156 + OutIn 1 16 +End +Button 12 + Type 1 + Size 19 13 + Offset 44 156 + OutIn 8 16 +End +Button 13 + Type 1 + Size 19 13 + Offset 70 156 + OutIn 8 8 +End +Button 14 + Type 1 + Size 19 13 + Offset 95 156 + OutIn 8 4 +End +Button 15 + Type 1 + Size 19 13 + Offset 121 156 + OutIn 8 2 +End +Button 16 + Type 1 + Size 19 13 + Offset 147 156 + OutIn 8 1 +End + +Button 21 + Type 1 + Size 19 15 + Offset 18 182 + OutIn 2 16 +End +Button 22 + Type 1 + Size 19 15 + Offset 44 182 + OutIn 7 16 +End +Button 23 + Type 1 + Size 19 15 + Offset 70 182 + OutIn 7 8 +End +Button 24 + Type 1 + Size 19 15 + Offset 95 182 + OutIn 7 4 +End +Button 25 + Type 1 + Size 19 15 + Offset 121 182 + OutIn 7 2 +End +Button 26 + Type 1 + Size 19 15 + Offset 147 182 + OutIn 7 1 +End + +Button 31 + Type 1 + Size 19 15 + Offset 18 208 + OutIn 0 16 +End +Button 32 + Type 1 + Size 19 15 + Offset 44 208 + OutIn 6 16 +End +Button 33 + Type 1 + Size 19 15 + Offset 70 208 + OutIn 6 8 +End +Button 34 + Type 1 + Size 19 15 + Offset 95 208 + OutIn 6 4 +End +Button 35 + Type 1 + Size 19 15 + Offset 121 208 + OutIn 6 2 +End +Button 36 + Type 1 + Size 19 15 + Offset 147 208 + OutIn 6 1 +End + +Button 41 + Type 1 + Size 19 15 + Offset 18 233 + OutIn 3 16 +End +Button 42 + Type 1 + Size 19 15 + Offset 44 233 + OutIn 5 16 +End +Button 43 + Type 1 + Size 19 15 + Offset 70 233 + OutIn 5 8 +End +Button 44 + Type 1 + Size 19 15 + Offset 95 233 + OutIn 5 4 +End +Button 45 + Type 1 + Size 19 15 + Offset 121 233 + OutIn 5 2 +End +Button 46 + Type 1 + Size 19 15 + Offset 147 233 + OutIn 5 1 +End + +Button 51 + Type 1 + Size 45 15 + Offset 18 259 + OutIn 4 16 +End +Button 52 + Type 1 + Size 19 15 + Offset 70 259 + OutIn 4 8 +End +Button 53 + Type 1 + Size 19 15 + Offset 95 259 + OutIn 4 4 +End +Button 54 + Type 1 + Size 19 15 + Offset 121 259 + OutIn 4 2 +End +Button 55 + Type 1 + Size 19 15 + Offset 147 259 + OutIn 4 1 +End + +Button 61 + Type 1 + Size 18 15 + Offset 19 284 + OutIn 3 32 +End +Button 62 + Type 1 + Size 24 15 + Offset 48 284 + OutIn 3 8 +End +Button 63 + Type 1 + Size 24 15 + Offset 79 284 + OutIn 3 4 +End +Button 64 + Type 1 + Size 24 15 + Offset 110 284 + OutIn 3 2 +End +Button 65 + Type 1 + Size 24 15 + Offset 141 284 + OutIn 3 1 +End + +Button 71 + Type 1 + Size 18 15 + Offset 19 310 + OutIn 2 32 +End +Button 72 + Type 1 + Size 24 15 + Offset 48 310 + OutIn 2 8 +End +Button 73 + Type 1 + Size 24 15 + Offset 79 310 + OutIn 2 4 +End +Button 74 + Type 1 + Size 24 15 + Offset 110 310 + OutIn 2 2 +End +Button 75 + Type 1 + Size 24 15 + Offset 141 310 + OutIn 2 1 +End + +Button 81 + Type 1 + Size 18 15 + Offset 19 335 + OutIn 1 32 +End +Button 82 + Type 1 + Size 24 15 + Offset 48 335 + OutIn 1 8 +End +Button 83 + Type 1 + Size 24 15 + Offset 79 335 + OutIn 1 4 +End +Button 84 + Type 1 + Size 24 15 + Offset 110 335 + OutIn 1 2 +End +Button 85 + Type 1 + Size 24 15 + Offset 141 335 + OutIn 1 1 +End + +Button 91 + Type 1 + Size 18 15 + Offset 19 361 + OutIn 0 32768 +End +Button 92 + Type 1 + Size 24 15 + Offset 48 361 + OutIn 0 8 +End +Button 93 + Type 1 + Size 24 15 + Offset 79 361 + OutIn 0 4 +End +Button 94 + Type 1 + Size 24 15 + Offset 110 361 + OutIn 0 2 +End +Button 95 + Type 1 + Size 24 15 + Offset 141 361 + OutIn 0 1 +End + + +Scancode 8 + Map 8 55 +End + +Scancode 13 + Map 13 51 +End + +Scancode 16 + IfPressed 16 + SetFlag 0 + Else + ResetFlag 0 + End +End + +Scancode 17 + IfPressed 17 + SetFlag 1 + Else + ResetFlag 1 + End +End + +Scancode 27 + Map 27 91 +End + +Scancode 37 + Map 37 34 +End + +Scancode 38 + Map 38 25 +End + +Scancode 39 + Map 39 36 +End + +Scancode 40 + Map 40 35 +End + +Scancode 49 + IfFlag 0 + Map 49 71 + Map 49 54 + Else + Map 49 82 + End +End + +Scancode 50 + Map 50 83 +End + +Scancode 51 + IfFlag 0 + Map 51 81 + Map 51 65 + Else + Map 51 84 + End +End + +Scancode 52 + Map 52 72 +End + +Scancode 53 + Map 53 73 +End + +Scancode 54 + Map 54 74 +End + +Scancode 55 + Map 55 62 +End + +Scancode 56 + IfFlag 0 + Map 56 75 + Else + Map 56 63 + End +End + +Scancode 57 + IfFlag 0 + Map 57 71 + Map 57 65 + Else + Map 57 64 + End +End + +Scancode 65 + Map 65 11 +End + +Scancode 66 + Map 66 12 +End + +Scancode 67 + Map 67 13 +End + +Scancode 68 + Map 68 14 +End + +Scancode 69 + Map 69 15 +End + +Scancode 70 + Map 70 16 +End + +Scancode 71 + Map 71 21 +End + +Scancode 72 + Map 72 22 +End + +Scancode 73 + Map 73 23 +End + +Scancode 74 + Map 74 24 +End + +Scancode 75 + Map 75 25 +End + +Scancode 76 + Map 76 26 +End + +Scancode 77 + Map 77 31 +End + +Scancode 78 + IfFlag 1 + MenuItem 1 + Else + Map 78 32 + End +End + +Scancode 79 + Map 79 33 +End + +Scancode 80 + Map 80 34 +End + +Scancode 81 + Map 81 35 +End + +Scancode 82 + Map 82 36 +End + +Scancode 83 + Map 83 41 +End + +Scancode 84 + Map 84 42 +End + +Scancode 85 + Map 85 43 +End + +Scancode 86 + Map 86 44 +End + +Scancode 87 + Map 87 45 +End + +Scancode 88 + Map 88 46 +End + +Scancode 89 + Map 89 52 +End + +Scancode 90 + Map 90 53 +End + +Scancode 96 + Map 96 92 +End + +Scancode 97 + Map 97 82 +End + +Scancode 98 + Map 98 83 +End + +Scancode 99 + Map 99 84 +End + +Scancode 100 + Map 100 72 +End + +Scancode 101 + Map 101 73 +End + +Scancode 102 + Map 102 74 +End + +Scancode 103 + Map 103 62 +End + +Scancode 104 + Map 104 63 +End + +Scancode 105 + Map 105 64 +End + +Scancode 106 + Map 106 75 +End + +Scancode 107 + Map 107 95 +End + +Scancode 109 + Map 109 85 +End + +Scancode 110 + Map 110 93 +End + +Scancode 111 + Map 111 65 +End + +Scancode 186 + IfFlag 0 + Map 186 81 + Map 186 95 + End +End + +Scancode 188 + Map 188 71 + Map 188 93 +End + +Scancode 190 + Map 190 93 +End + +Scancode 191 + IfFlag 0 + Map 191 71 + Map 191 55 + Else + Map 191 65 + End +End + +Scancode 219 + IfFlag 0 + Map 219 71 + Map 219 95 + Else + Map 219 71 + Map 219 75 + End +End + +Scancode 220 + Map 220 54 +End + +Scancode 222 + IfFlag 0 + Map 222 81 + Map 222 85 + Else + Map 222 31 + End +End + + + + + + diff --git a/ROMDUMP.EXE b/ROMDUMP.EXE index 147ded2..01d7946 100644 Binary files a/ROMDUMP.EXE and b/ROMDUMP.EXE differ diff --git a/ROMDUMP.TXT b/ROMDUMP.TXT index 5eeb9c1..1534115 100644 --- a/ROMDUMP.TXT +++ b/ROMDUMP.TXT @@ -1,27 +1,28 @@ -######################################## -# # -# ROMDump Wizard # -# # -######################################## + *********************** + * ROMDump Wizard V1.1 * + *********************** -This program is a rewritten version of the ROMDump Wizard from -Sebastien Carlier. It based on API calls and doesn't need the -MFC DLL's any more. It has been written to allow you to quickly -dump the rom from your HP48. The process is entirely automated, -and should work most of the time. However, I cannot guarantee -that it will work on your computer. It works perfectly on my -computer. +The ROMDump Wizard has been written to allow you to quickly dump the ROM from +your HP48. The process is entirely automated and can be interrupted at any time. +This program is a rewritten version of the ROMDump Wizard from Sebastien +Carlier. The download engine has changed and is now based on Jean-Yves Avenard's +great ROMUPL program. My ROM copy times: -SX: 00:16:10 (OS: NT4.0 SP3) -SX: 00:15:38 (OS: Win95 4.00.950a) -GX: 00:30:47 (OS: Win95 4.00.950a) +SX: 00:06:08 (OS: NT4.0 SP3) +GX: 00:11:19 (OS: NT4.0 SP3) -After download you will find the rom file ROM.48S or ROM.48G in -the directory of the ROMDUMP.EXE utility. Be sure that there is -no older file with the used names in this directory before using! +In Step 2 you are asked for the "ROM format". Choose "x48/raw" for all-purpose +use and "Emu48" if you want to use the ROM dump for the Emu48 emulator (Win32 +version). You can also use the CONVERT utility to convert "x48/raw" ROM dumps +into the Emu48 format. After downloading you will find the ROM file in the +directory of the ROMDUMP.EXE utility. -If you have any problems, please don't ask me. I'm busy enough -with my work. +In the "x48/raw" mode the file has the name 48SX_?.ROM or 48GX_?.ROM. The ? in +the name is a placeholder for the character of the ROM version you have. In the +"Emu48" mode the file has the name ROM.48S or ROM.48G; this depends on the +calculator you have. Be sure that there is no older file with the used names in +this directory before using! --- Christoph Gießelink + +07/01/99 (c) by Christoph Gießelink, cgiess@swol.de diff --git a/sources/COPYING.TXT b/sources/COPYING.TXT index a43ea21..60549be 100644 --- a/sources/COPYING.TXT +++ b/sources/COPYING.TXT @@ -2,7 +2,7 @@ Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS - Appendix: How to Apply These Terms to Your New Programs + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -305,7 +305,8 @@ the "copyright" line and a pointer to where the full notice is found. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Also add information on how to contact you by electronic and paper mail. diff --git a/sources/EMU48.TXT b/sources/EMU48.TXT index 95eb475..6268a89 100644 --- a/sources/EMU48.TXT +++ b/sources/EMU48.TXT @@ -1,7 +1,7 @@ - Emu48 - A freeware HP48 Emulator for Windows 95 and NT + Emu48 - A freeware HP38/48/49 Emulator for Windows 9x, NT and 2000 @@ -9,219 +9,405 @@ * INSTALLATION * **************** -Emu48 is distributed in 3 separate archives : -- Emu48-1.x-bin.zip All the executables files (REQUIRED) -- Emu48-1.x-src.zip The sources of Emu48 and some useful tools (OPTIONAL) -- Emu48-com.zip Files common to all 1.x versions (REQUIRES) +Emu48 is distributed in 1 archive: +- Emu48-1_15.zip All files and sources -To install Emu48, just unzip Emu48-1.x-bin.zip and Emu48-com.zip into an empty -directory. When you first run Emu48, it will detect the directory in which you -installed it, and will write its configuration to a file named Emu48.ini in -your Windows directory. +To install Emu48, just unzip Emu48-1_15.zip into an empty directory. When you +first run Emu48, it will detect the directory in which you installed it, and +will write its configuration to a file named Emu48.ini in your Windows +directory. -Note: - As of version 1.0, Emu48 will only run with Windows 95 and NT. - I am working on a port to Unix (XWindow). When this is finished, - I may port it to Windows 3.1 and OS/2. - Since the source code is provided, you can add features or port it to new - plateforms, but you are required to send me your changes. +You can also update your current version with the Unofficial Service Packs: +- E48BP1x.ZIP New EXE-File +- E48SP1x.ZIP Sources of the Service Pack +Replace the original EXE file please. + + + ******************** + * OPERATING SYSTEM * + ******************** + +This version of Emu48 should work with all Intel Win32 platforms. You may +recompile the sources to run Emu48 with Windows NT on a DEC Alpha. ************************ * YOU NEED A ROM IMAGE * ************************ -Emu48 needs an image of the ROM of YOUR calculator to be able to run. -Since the ROM is copyrighted by HP, I won't give you mine, and you should not -give yours or make it freely available. -To use the ROM software of a calculator, you must be the owner of this -calculator. +Emu48 needs an image of the ROM of YOUR calculator to be able to run. Since the +ROM is copyrighted by HP, I won't give you mine, and you should not give yours +or make it freely available. To use the ROM software of a calculator, you must +be the owner of this calculator. -- If you have already used another HP48 emulator, you can convert the ROM with - you were using with the Conver utility. - To do that, start a Command Promt while running Windows, and type : - Convert ROM.48G -or Convert ROM.48S - Where is the path to your old ROM image. This will create a file - named ROM.48G or ROM.48S, depending on the version you own. - This tool should be able to read any style of ROM image, and will also check - its validity. Note than if you run it with only one parameter, no file will - be written, but it will still check the validity of the ROM. +- HP38: +To upload the ROM of your HP38G, you will need a special aplet called "ROM +UPLOAD", available at http://www.epita.fr/~avenar_j/hp. Once you've uploaded the +ROM, you have to convert it using the Convert utility. + +To do that, start a Command Prompt while running Windows, and type: + Convert ROM.38G + +Where is the path to your ROM image. This will create a file named +ROM.38G. This tool will also check its validity. + +- HP48: +If you have already used another HP48 emulator, you can convert the ROM using +the Convert utility. -- If you have never used an HP48 emulator, and don't have a ROM dump, you can - either use the old ROMDump utility and then Convert your dump, or you can - use my ROMDump Wizard, which will almost automatically get the ROM from your - HP48. However, this Wizard was written without a documentation on the - transfer protocol used by the HP48 (Kermit), so I cannot guarantee that it - will work. It worked on my computer, maybe it will work on yours. Try it ! +To do that, start a Command Prompt while running Windows, and type: + Convert ROM.48G +or Convert ROM.48S - WARNING: If you use ROMDump or the ROMDump Wizard, DO NOT INTERRUPT THE - PROCESS ! Your HP48 would lock, and the only way to reset it is - through the Reset hole. +Where 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. - IMPORTANT: To save a lot of space, two DLLs needed by the Romdump Wizard - have not been included in the Romdump Wizard's distribution. - They are called MSVCRT40.DLL and MFC40.DLL, and are available - on the Web at the Emu48 Official Homepage : - http://www.geocities.com/CapeCanaveral/5948/index.html - These two files are freely distributable, and would be included - in this archive if they weren't so large (about 1.4Mb for both) - Note that they are NOT needed by Emu48 : only the Romdump Wizard - requires them. +If you have never used an HP48 emulator, and don't have a ROM dump, you can +either use Jean-Yves Avenard's ROMUPL.BIN or the ROMDump Wizard V1.x, which will +almost automatically get the ROM from your HP48. Don't use the ROMDump Wizard +versions V0.x any more please! After the download you may have to convert your +dump with the CONVERT utility into the Emu48 format. -* Once you have your ROM dump(s), SAVE THEM TO A FLOPPY DISK ! - It will save you a lot of troubles if you were to lose them. +You can find the latest version of the ROM dump programs on: +ROMUPL.BIN http://www.epita.fr/~avenar_j/hp/calcen.html +ROMDump Wizard http://privat.swol.de/ChristophGiesselink/index.htm +Once you have your ROM dump(s), SAVE THEM TO A FLOPPY DISK! It will save you a +lot of trouble if you were lose them. + +- HP49: +There's no ROM download program available so far. But you can find a HP49G ROM +for emulators in the YorkeM emulator package or in the HP49G SDK on +http://www.hpcalc.org in the HP49 section. **************** * HOW TO START * **************** -When Emu48 is installed and you have put the ROM image(s) in its directory, you -can start Emu48. You'll see a "Choose Your KML Script" box. +When Emu48 is installed and you have put the ROM image(s) in the Emu48 +directory, you can start Emu48. You'll see a "Choose Your KML Script" box. -KML Scripts in fact define the visual aspect of Emu48, the behaviour of the -buttons, of the keyboard... It is a GREAT way to customize your copy of Emu48. +KML Scripts in fact define the visual aspect of Emu48, the behavior of the +buttons, of the keyboard, ... It's a GREAT way to customize your copy of Emu48. Check that the path in the "Emu48 Directory" text area is correct. Modify it if -the directory in which you installed Emu48 is not the directory displayed. -Click the refresh button ("V") after modifying it to update the list box. +the directory in which you installed Emu48 is not the directory displayed. Click +the refresh button ("V") after modifying it to update the list box. Choose a KML script in the list box. If you have put a G/GX ROM dump in Emu48's directory, choose a script for G/GX. If you have put a S/SX ROM dump in Emu48's directory, choose a script for S/SX. -Several scripts are included in the common archive : + +Several scripts are included in the common archive: * Emu48's Default Faceplate for HP48G/GX * Emu48's Default Faceplate for HP48S/SX - These two are simple scripts, and they use the bitmap from Win48 2.05. + These two are simple scripts, good for 800x600 display resolution. * Casey's Gx with Toolbar and Touch Screen * Casey's Sx with Toolbar and Touch Screen These script uses many advanced features, and is a good demonstration of - the power of Emu48's scripting language, KML. Try it, it is really great ! + the power of Emu48's scripting language KML. Try it, it is really great! * Floating buttons This one looks really great. * Small but realistic HP48 Gx This one has been designed for small resolutions such as 640x480. - Note: some things in this script have to be be fixed. + Note: some things in this script have to be fixed. - If you want other great scripts, visit Casey's Emu48 homepage : + If you want other great scripts, visit Casey's Emu48 homepage: http://www.gulftel.com/~pattersc/emu48/ - And if you are interested in writting new scripts, you'll want the KML 2.0 - documentation, available on Casey's page and on my page : - http://www.geocities.com/CapeCanaveral/5948/kmlind.htm +And if you are interested in writing new scripts, get the KML 2.0 documentation +from Christoph's page at http://privat.swol.de/ChristophGiesselink/emu48.htm -Once you have selected a script, press Ok to start the emulator. While it is -running, you can use the View/Change Kml Script to change the visual aspect -of Emu48. +Once you have selected a script, press OK to start the emulator. While it's +running, you can use the View/Change KML Script... command to change the visual +aspect of Emu48. + *************** + * KML SCRIPTS * + *************** + +In some cases you have to fix Color 0 in your KML script file, because the +colors red and blue has been swapped in the "Lcd" section (bugfix in a previous +version). Don't use TRUELCD.KMI for emulating display contrast in your scripts. +It's not fully correct. The hardware contrast values are in the area from 0 to +31. But the HP48 ROMs bounds them to useful values. The S(X) ROM use only +display contrast values between 3 and 19 and the G(X) ROM values between 9 and +24. + + + **************** + * COMMAND LINE * + **************** + +The command line syntax is "Emu48 [E48file [Port2file]]". The first parameter +sets the filename for the emulation data, the second parameter the Port2 file. +You're not able to set a Port2 file without setting the emulation data file. The +arguments are optional. + + + ******************* + * LOAD/SAVE FILES * + ******************* + +There are two ways to transfer files from or to the emulator. The one way is to +use the serial port to transfer the data directly from your HP48 to the +emulator. The second way is to load data, saved on your PC, into the stack of +the emulator. You can do this by using the Edit/Load Object... command or with +the file Drag and Drop feature. But there's one important restriction, the data +must a HP binary file (begin with HPHP48- or HPHP49-, this depends on your +emulated calculator)! If not, the data is load as string. The Edit/Save +Object... command will save the data in stack level 1 on the PC (always binary +mode). Be sure, when you use the second way for data transfer, that no program +is running on the emulator. The second way doesn't work on a HP38, because he +has no stack. So you can load aplets only from the serial port. + + + ***************** + * DRAG AND DROP * + ***************** + +Dropping HP48 objects over the emulator window will load program files (like the +command "Load object...") on the stack. Be sure that the emulator isn't busy +before doing this. + ******************* * SHARED RAM CARD * ******************* -You can add a SHARED (I'll explain later) ram card of up to 4Mb. By default, no such -card will be created when you start Emu48. The MkShared.exe utility, included in the -registered version, will allow you to create it. -The syntax is : +You can add a SHARED (I'll explain later) ram card of up to 4MB to a HP48. By +default, no such card will be created when you start Emu48. The MkShared.exe +utility will allow you to create it. + +The syntax is: MkShared -For example, you can create a 4Mb RAM card name SHARED.BIN (in Emu48's directory) with -the following command : + +For example, you can create a 4MB RAM card name SHARED.BIN (in Emu48's +directory) with the following command: + MkShared SHARED.BIN 4096 -Valid sizes are 128, 256, 512, 1024, 2048 and 4096 kb. + +Valid sizes are 32, 128, 256, 512, 1024, 2048 and 4096 KB. If you use RAM cards +greater than 128 KB in a HP48SX, you can only see the first 128 KB of the card. -When you have created this file, run Emu48, and use the Close menu item to close the -calculator state. Now select View/Settings. In the "Port 2" text area, type the name -of the file you created (if you don't include a path, it will be searched for in Emu48's -directory). +When you have created this file, run Emu48, and use the Close menu item to close +the calculator state. Now select File/Settings. In the "Port 2" text area, type +the name of the file you created (if you don't include a path, it will be +searched for in Emu48's directory). -You can also tick the check box "Port 2 Is Shared". -When the box is cleared, only the first instance of Emu48 will allow you to use the RAM -card in Port 2. -When this box is ticked, the first instance of Emu48 will give you both read and write -access to this RAM card. If then you start Emu48 again, the RAM card in Port 2 will be -write-protected. You can thus transfer files very easily between two calculators. This -RAM card is used by both S/SX and G/GX types. - -Note that you have to close Emu48 and restart it if you modify these settings. +You can also tick the check box "Port 2 Is Shared". When the box is cleared, +only the first instance of Emu48 will allow you to use the RAM card in Port 2. +When this box is ticked, the first instance of Emu48 will give you both read and +write access to this RAM card. If then you start Emu48 again, the RAM card in +Port 2 will be write-protected. Thus you can transfer files very easily between +two calculators. This RAM card is used by both S/SX and G/GX types. + *********************** + * COPY / PASTE STRING * + *********************** - ******************** - * SPECIAL FEATURES * - ******************** +With the menu items "Copy String" and "Paste String" in the "Edit" menu you're +able to copy HP48 string objects from the stack to the PC clipboard and vice +versa. -Emu48 includes a backup feature (in the View menu). It save the complete state of the -calculator in the computer's memory. You might want to use it before doing something -risky, and if you don't want to save to the disk. It provides some kind of Undo feature. -It is also used by Emu48 when you want to save or load a new document, to restore its -old state if you cancel the operation or of something goes wrong. + ********** + * BACKUP * + ********** + +Emu48 includes a backup feature (in the Edit menu). It save the complete state +of the calculator in the computer's memory. You might want to use it before +doing something risky, and if you don't want to save to the disk. It provides +some kind of Undo feature. It is also used by Emu48 when you want to save or +load a new document, to restore its old state if you cancel the operation or of +something goes wrong. + + + ************ + * KEYBOARD * + ************ + +To enter a character to the emulator use the PC keyboard (key translation +depends on the used KML script) or the mouse. If you press the left mouse +button, the emulator key is pressed as long as you press the mouse button or +leaving the area of the emulator button. Sometimes you need to press more then +one key (contrast setting, warmstart, ...). To do this, press the right mouse +button. All "locked" buttons are released after enter a key with the left mouse +button. + + + ********* + * CLOCK * + ********* + +The emulator time is synchronized with the PC time at startup of the emulator. +This may cause problems with other non original operating systems running on the +HP48. On S(X) calculators the address area #00052-#00070, on G(X) calculators +the address area #00058-#00076 in Port0 are rewritten with the actual time +information. + + + ************* + * EMU48.INI * + ************* + +The section [Timers] in the Emu48.ini file isn't used any more. The variable +values are replaced by useful constants. You may delete this section if you +want. Starting an old version of Emu48 (V1.07 and earlier) will add this section +again. + + + ************************ + * REAL SPEED EMULATION * + ************************ + +As you recognized the speed of the emulated HP48 is much faster than an original +HP48. The reason is, the assembler commands are emulated faster than the +original CPU can execute them. On one side this is a big advantage (faster +execution of programs) on the other side this cause many trouble. In Emu48 only +the timers work with the original speed. In result all commands like User-RPL +WAIT wait more or less the correct time. But many programs like shells or +editors use an own key handler to realize an autorepeat implementation. Normally +these programs use the execution time of each assembler command for waiting. On +Emu48 this time is much shorter, so the time between each key read is shorter as +well and you get a very fast key repetition. The editor ED from the JAZZ package +hasn't this problem, because the key input is synchronized with one of the +timers. To solve this problem Emu48 generally slow down emulation if a key is +pressed. To solve some other speed depending problems you are able to slow down +the whole emulation speed. There are two variables 'SXCycles=82' and +'GXCycles=123' defined in the Emu48.ini file, section [Emulator] which control +the "real" speed and key repetition slow down for each calculator type. Each +numeric value is representing the allowed CPU cycles in a 16384Hz time frame. +Because the used cycle statements (from SASM.DOC) in Emu48 doesn't correspond to +the real values of the CPU, the saved values are estimated by comparing the +execution time of a program to the real calculator. Increasing the value fitting +to your ROM will make the "real speed" HP faster and vice versa. No warranty to +the functionality of Emu48 when you go below the default values. + + + ************************* + * SERIAL PORT EMULATION * + ************************* + +The serial ports are emulated as well now. You may choose the same serial port +for wire and IR. Remember that the IR port only work with 2400 Baud. If you want +to change the serial port settings, but they are disabled, close the serial port +with the command CLOSEIO or power cycle the HP48 first. + +Now it's possible to make transfers between the HP48 and Emu48. If you have +problems with the connection please try the following. There's a simple way to +check if your serial port is used by another program. First disable the serial +settings in both combo boxes and very important close the settings dialog. +Reopen the settings dialog and choose the COM port in the wire combo box to the +port the HP48 is connected with. When you open this combo box you only see valid +(unused) serial ports. Don't use the IR combo box, it only works with 2400 Baud. +The next important thing are the serial settings of the HP48 and Emu48, they +must be equal. If this doesn't work then mostly there's a hardware or a resource +problem of the serial port. Check this with connecting the HP48 with a transfer +program you like on the same serial port. + + + **************** + * DISASSEMBLER * + **************** + +With the internal disassembler you're able to disassemble the HP48 address area. +With the default Map setting the disassembler always see the mapped memory +address. If for example you configured the RAM at #00000 you will see the RAM +and not the ROM at this address. With the other Module settings you specify a +special module for disassembly. Each module will begin at address #00000 and +will not overlapped by other modules. For Port2 I use a linear address mode, +that means that the second port of a RAM card greater than 128KB is at address +#40000 (128 * 1024 * 2) and so on. The "Copy Data" button copies the selected +disassembler lines to the PC clipboard. + + + ************** + * DDE SERVER * + ************** + +I implemented a DDE server in Emu48 to transmit data from and to the HP stack +with DDE. You have the same restrictions like with the commands "Load object..." +and "Save Object...", that a running program may corrupt memory. Take care to +transmit data only after the acknowledge of the last DDE transaction. + +Technical data: + +Servername: Emu48 +Topicname: Stack +Item: Dummy (ignored, must be a nonzero string) +Clipboardformat: "CF_HPOBJ" (user defined) + +The DDE commands CONNECT, POKE and REQUEST are supported. + +The structure of the clipboard format "CF_HPOBJ": + ++--------+------------------------------------+ +| 4 Byte | HP object | ++--------+------------------------------------+ + \ \ + \ +--- normal HP object + +----------- length of object (LSB first) ******************** * TROUBLE SHOOTING * ******************** -Q: The emulator display the keyboard, but the screen stays blank or is filled - with garbage. -A: Your ROM image is probably wrong. Check it with the Convert utility, and if - it says that the CRC is wrong, you should try to download your ROM again. - -Q: What does this message mean : - "This file is missing or already loaded in another instance of Emu48." -A: Maybe you deleted or moved the files that the emulator tries to load when - starting (the last files you saved). - The other possibility is that you are running several instances of Emu48, - but you are trying to load the same file in both instances, which causes - a sharing violation. - +Visit the Emu48 FAQ site at http://privat.swol.de/ChristophGiesselink/index.htm +to get more information please. *********** * SUPPORT * *********** -I cannot provide individual support for Emu48, but I will read all the mails -that you send. -All informations about Emu48 will be on the Emu48 Official Homepage on the Web : +We cannot provide individual support for Emu48, but we will read all the mails +that you send. All informations about Emu48 will be on the Emu48 Official +Homepage on the Web: - http://www.geocities.com/CapeCanaveral/5948/index.html + http://www.epita.fr/~sebc/Emu48/index.html + +or on the Emu48 FAQ at + + http://privat.swol.de/ChristophGiesselink/index.htm + +Other graphics and scripts are available at Casey's Emu48 Graphics Page: -Other graphics and scripts are available at Casey's Emu48 Graphics Page : http://www.gulftel.com/~pattersc/emu48/ - *************** * LEGAL STUFF * *************** + +Emu48 - An HP38/48/49 Emulator +Copyright (C) 1999 Sebastien Carlier & Christoph Gießelink - Emu48 - An HP48 Emulator - Copyright (C) 1997 Sebastien Carlier +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA - - ************** - * The Author * - ************** + *************** + * The Authors * + *************** Paper Mail: Sebastien Carlier @@ -231,7 +417,17 @@ Paper Mail: E-Mail: sebc@epita.fr - sebc@anet.fr Homepage: - http://www.geocities.com/CapeCanaveral/5948/index.html + http://www.epita.fr/~sebc/Emu48/index.html + + +Paper Mail: + Christoph Giesselink + GERMANY + +E-Mail: + cgiess@swol.de + +Homepage: + http://privat.swol.de/ChristophGiesselink/index.htm diff --git a/sources/Emu48/CHANGES.TXT b/sources/Emu48/CHANGES.TXT index 567e6de..f32f064 100644 --- a/sources/Emu48/CHANGES.TXT +++ b/sources/Emu48/CHANGES.TXT @@ -1,3 +1,393 @@ +Service Pack 15 for Emu48 Version 1.0 + +DEBUGGER.C +- added emulation run flag +- added notify function for emulation stopped +- added color highlighting on changed registers +- added implementation of "Step Out" (exit function) +- bugfix in function ViewMemWnd(), use the Npeek() function for + reading memory data, so fixed some problems with reading invalid + data from the I/O register area +- changed function OnClearAll(), changed argument to dialog handle +- bugfix in function OnDblClick(), fixed swapped nibbles after enter + new data +- changed function OnKeyCodeWnd(), changed first argument to dialog + handle +- bugfix in function Debugger(), removed context menu resource leaks + and a call of GetDlgItem() with invalid arguments + +DEBUGGER.H +- extern declaration of global functions +- moved WM_UPDATE definition to DEBUGGER.C + +EMU48.C +- replaced __argc and __argv variables by process variables +- replaced INI file handling part +- changed address in GPL license string +- added HP38 stuff to function UpdateWindowStatus() and + SettingsProc() +- changed function SettingsProc(), replaced Port1_Writeable variable +- bugfix in function OnViewReset(), some registers wasn't reset, + call reset function now +- bugfix in function OnDestroy(), moved functions SwitchToState() + and WriteSettings() to main program, because emulation thread may + not run and settings aren't read so far when main window close +- removed function FlushMessages() and all references, because it's + useless and references made trouble at a WM_QUIT message +- removed several other resource leaks on error conditions +- made function MainWndProc() public + +EMU48.DSP +- renamed serial.h into io.h in header definition +- added settings.c sources + +EMU48.H +- extern declaration of global variable and functions + +EMU48.RC +- changed language definition of dialog IDD_BREAKEDIT +- added Menuitem Debug "Step Out" in debugger menu +- changed version and copyright + +ENGINE.C +- renamed header Serial.h into io.h +- renamed wShutdnWake to bShutdnWake in Chipset structure +- moved bRealSpeed variable and make it public +- solved bRealSpeed name conflict +- added DWORD casting from Chipset.cycles variable +- added part for debugger function "Step Out" +- changed notify function for update debugger window + +EXTERNAL.C +- some minor changes for the HP38 beeper emulation + +FILES.C +- added new document type for HP38G +- replaced __argc and __argv variables by process variables +- added function CrcRom() to get a fingerprint of the ROM +- changed function NewDocument(), deleted Port1_Writeable variable, + isn't used any more +- bugfix in function OpenDocument(), in restore situation add port2 + only at HP48 emulation +- changed function OpenDocument(), check fingerprint of ROM +- changed function SaveDocument(), update fingerprint of ROM +- changed function SaveBackup(), save window position as well +- bugfix in function RestoreBackup(), lost port2 of a HP48 + +KEYBOARD.C +- renamed wShutdnWake to bShutdnWake in Chipset structure +- added DWORD casting from Chipset.cycles variable + +KLM.C +- bugfix in function InitKML(), on a KML script syntax error only + continue with the Cancel button + +IO.H +- old SERIAL.H, added I/O definitions + +MOPS.C +- renamed header Serial.h into io.h +- renamed funtion CRC() to UpCRC() +- changed function UckBit(), removed unused variable +- changed function MapP1(), use cards_status instead of + Port1_Writeable variable +- bugfix in function RomSwitch(), lached address line A6 was always + zero -> no access to upper half of flash memory +- added function CpuReset() to set cpu registers after reset +- changed function Npeek(), return data from I/O register area as + well now (for debugger support) +- bugfix in function Nread(), reading from the timer2 MSB register + (0x13F) updates the CRC register (0x104-0x107) +- bugfix in function ReadIO(), update the USRQ bit in the SRQ1 + register (0x118) after reading the RBR register (0x114,0x115) +- bugfix in function ReadIO(), update the NINT2 and NINT bits in the + SRQ2 register (0x119) +- bugfix in function WriteIO(), update the USRQ bit in the SRQ1 + register (0x118) after writing the IOC register (0x110) or the + TBR register (0x116,0x117) + +OPCODES.C +- added DWORD casting from w.cycles variable +- checked all undocumented cpu cycles and removed remarks +- bugfix in function o08(), o09(), o0A(), o0B(), o3X(), o8086n(), + o8087n(), o808An(), o808Bn() and o8Ed4(), changed number of cpu + cycles + +RESOURCE.H +- added several definitions + +SERIAL.C +- renamed header Serial.h into io.h +- renamed wShutdnWake to bShutdnWake in Chipset structure +- moved initialize/remove of Critical Section handler from the + function CommOpen() and CommClose() to main program +- added function UpdateUSRQ(), implements USRQ bit handling +- bugfix in function CommTransmit(), added LPB bit emulation in the + TCS register (0x112) and USRQ bit emulation in the SRQ1 register + (0x118) +- bugfix in function CommReceive(), only reject reading if com port + is closed and not whole operation and added USRQ bit emulation in + the SRQ1 register (0x118) + +SERIAL.H +- renamed to IO.H + +SETTINGS.C +- new modul to handle the INI file + +TIMER.C +- removed timer I/O definitions, replaced by include file IO.H +- replaced INT define with INTR (conflict with C variable type INT) +- renamed wShutdnWake variable to bShutdnWake +- bugfix in function CheckT1() and CheckT2(), added TSRQ bit + emulation in the SRQ1 register (0x118) + +TYPES.H +- changed variable type of wPosX and wPosY, position data is signed +- use position of wShutdnWake for wRomCrc +- use position of dwKdnCycles for cycles variable +- use position of Port1_Writeable for MSB of cycles variable +- use position of Port2_Writeable for dwKdnCycles variable +- use old position of the cycles variable for bShutdnWake + + +Service Pack 14 for Emu48 Version 1.0 + +COLOR.H +- new header with color definitions + +DDESERV.C +- added different files headers for HP48/49 + +DEBUGGER.C +- new modul for debugger routines + +DEBUGGER.H +- header file for debugger part + +DISASM.C +- changed function append_r_addr() and append_pc_comment(), relative + jumps now can viewed with the target address instead of a relative + offset and target address in remark; implemented a local variable +- bugfix in function rn_port2(), calculated port2 mask was wrong +- added HP49 stuff to function rn_port2() + +EMU48.DSP +- added debugger.c sources + +EMU48.C +- added debugger menu entry +- added HP49 stuff to the disassembler +- added HP49 stuff to function SettingsProc() +- changed function OnViewSettings(), removed port2 open/close + handling, now done in the document handler +- deleted unused function OnSysClose() +- bugfix in function Disasm(), in entry IDC_DISASM_PORT2 the highest + useable address was always wrong + +EMU48.RC +- added Menuitem Tools "Debugger..." +- changed version and copyright + +EMU48.H +- extern declaration of global variable and functions + +ENGINE.C +- moved inline function FASTPTR() to OPS.H +- added debug part in main emulation loop + +EXTERNAL.C +- some minor changes for the HP49 beeper emulation + +FILES.C +- added new document type for HP49G +- change in function WriteStack(), accept HP49 binary files now +- the port2 open/close handling is now controlled by the document +- several changes in port2 handling, the HP49 use an internal 128KB + RAM card instead of the external RAM card of the HP48 +- changed function UnmapPort2(), added return value for unmap + success +- changed function PatchRom(), longer addresses than 5 nibbles can + be used now +- changed function OpenDocument(), restore HP49 ROM bank selection + after document load +- changed function InitKML(), removed initialization of MMU + +KEYBOARD.C +- changed function ScanKeyboard(), added a flag for wake up from + SHUTDN mode + +KML.C +- bugfix in function PressButton(), if button already pressed, do + nothing -> fixed a draw problem with KML button type 3 +- bugfix in function RefreshButtons(), KML type 3 buttons, must + complete redraw before refresh them + +MOPS.C +- added HP49 MMU parts +- bugfix in function ReadIO(), update the UCK bit in the BAU + register (0x10D) + +OPS.H +- moved inline function FASTPTR() from ENGINE.C to header file + +RESOURCE.H +- added several definitions + +RPL.C +- added HP49 memory pointers +- added HP49 flash pointer object (=DOFASHP) +- added HP49 precision integer object (=DOINT) +- added HP49 precision real object (=DOLNGREAL) +- added HP49 precision complex object (=DOLNGCMP) +- added HP49 symbolic matrix object (=DOMATRIX) +- added HP49 aplet object (=DOAPLET) +- added HP49 mini font object (=DOMINIFONT) + +SERIAL.C +- changed function SerialThread(), added a flag for wake up from + SHUTDN mode + +TIMER.C +- changed functions CheckT1() and CheckT2(), added a flag for wake + up from SHUTDN mode + +TYPES.H +- use position of the wUnused1 variable for SHUTDN wake up flag + + +Service Pack 13 for Emu48 Version 1.0 + +DISASM.C +- bugfix in function disasm_8(), the HS=0 n opcode was showed wrong + +EMU48.DSP +- added fetch.c and opcodes.c sources + +EMU48.C +- bugfix in function Disasm() and About(), handled messages must + return TRUE + +EMU48.H +- added function prototypes + +ENGINE.C +- moved several definitions to OPCODE.H +- made function AdjKeySpeed() public +- replaced opcode handling include files by a function call, decoder + now works with tables instead of case switching +- deleted unused code parts in modul + +FETCH.C +- new modul with opcode dispatcher + +FETCH.H +- file deleted, replaced by FETCH.C + +FILES.C +- bugfix in function PatchRom(), no correct handling of remarks, + interpreter failed on lower case hex digits in arguments + +OPCODES.C +- new modul with opcode implementation + +OPCODES.H +- file content changed, replaced by OPCODES.C + + +Service Pack 12 for Emu48 Version 1.0 + +DISPLAY.C +- minor change in function UpdateMainDisplay() +- deleted remarked global variables and unused code parts in + function WriteToMainDisplay() + +EMU48.C +- added auto event object for controlling the CPU thread + +EMU48.H +- removed extern declaration of variable +- extern declaration of global variable and functions + +ENGINE.C +- new function CheckDisp(), synchronize display update now with the + line update counter +- replaced all ResumeThread() with SetEvent() calls +- replaced all SuspendThread() with WaitForSingleObject() calls + +KEYBOARD.C +- replaced all ResumeThread() with SetEvent() calls +- deleted unused code parts in function ScanKeyboard() + +MOPS.C +- flag for updating display area is now global +- new function GetLineCounter() for getting the actual display + refresh line +- changed function WriteIO(), display isn't updated here any more +- use serial definitions from "serial.h" now +- deleted remarked functions Nread2(), Nwrite2(), Nread5() and + Nwrite5() + +SERIAL.C +- replaced all ResumeThread() with SetEvent() calls + +TIMER.C +- bugfix in function SetT1(), loading same timer value doesn't + restart timer period +- replaced all ResumeThread() with SetEvent() calls + + +Service Pack 11 for Emu48 Version 1.0 + +EMU48.C +- removed cards status definitions +- bugfix in function OnFileExit(), continuing the emulation failed + after pressing the "Cancel" button in save dialogbox +- removed function OnSysClose(), no difference to function + OnFileExit() +- changed message implementation WM_SYSCOMMAND/SC_CLOSE to function + OnFileExit() + +EMU48.DSP +- added preprocessor definition "STRICT" to project + +EMU48.H +- moved cards status definitions from EMU48.C to header file +- extern declaration of global function + +EMU48.RC +- changed version and copyright + +ENGINE.C +- bugfix in function WorkerThread(), after changing the port2 card + status the memory mapping must be updated +- update HP48 time now in function WorkerThread() and not in + function StartTimers() + +FILES.C +- changed function MapPort2(), dwPort2Mask now shows the valid + address lines of the bank switcher FF + +MOPS.C +- bugfix in function MapP1() and MapP2(), clear mapping area if port + is configured but not plugged +- bugfix in function MapP2(), odd bank switch values loaded the + wrong page of port2 and bank switcher must be disabled on S(X) + versions +- changed function Nread(), simulate an open data bus now (fix + value for even and odd address) +- bugfix in function Nread(), don't change bank switcher value if + RAM or CE2 is on the same address, because these modules have + higher access priority +- bugfix in function Nwrite(), bank switching now works with the + 'datx=r fsd' command + +TIMER.C +- renamed function SetAccesstime() to SetHP48Time() and made + function public +- removed update of HP48 time in function StartTimers() + + Service Pack 10 for Emu48 Version 1.0 DISPLAY.C @@ -15,7 +405,7 @@ EMU48.C - moved function DragAcceptFiles() to WM_CREATE handler - added function DragAcceptFiles() to WM_DESTROY handler - allow second command line parameter as port2 filename -- added Critical Section initialisation +- added Critical Section initialization EMU48.H - removed extern declaration of global function @@ -134,7 +524,7 @@ MOPS.C - bugfix in function Nread(), bank switching now works with every 'r=datx fsd' command in the complete mapped bank switch control area, an unconfigured bank switch area is now disabled and the - GX bank switch information (content of FlipFlop) is saved now + GX bank switch information (content of Flipflop) is saved now - bugfix in function Nwrite(), at some conditions no update of the display area and IO area couldn't be unconfigured - removed functions Nread2(), Nwrite2(), Nread5() and Nwrite5() @@ -291,7 +681,7 @@ DISPLAY.C EMU48.C - added global variable -- added semaphor handling for key scan +- added semaphore handling for key scan - added disassembler dialog box and menu entry - bugfix in function OnViewCopy(), the clipboard wasn't closed when EmptyClipboard() failed @@ -476,8 +866,8 @@ EMU48.RC KEYBOARD.C - bugfixes in 1 ms keyboard interrupt handler, keyboard interrupts are generated at one of the following conditions: pressing the ON - key (non maskeable), pressing a key detected by the 1 ms keyboard - scan when enabled (maskeable), detect a key after an OUT command + key (non maskable), pressing a key detected by the 1 ms keyboard + scan when enabled (maskable), detect a key after an OUT command or after the RSI command when a bit in the IN register is set MOPS.C @@ -593,7 +983,7 @@ DISPLAY.C EMU48.C - version changed - added global variable -- added semaphor handling to avoid GDI trouble with NT that prevent +- added semaphore handling to avoid GDI trouble with NT that prevent graphic update sometimes - added message for right mouse key - bugfix of a parameter of GetPrivateProfileString() diff --git a/sources/Emu48/COLOR.H b/sources/Emu48/COLOR.H new file mode 100644 index 0000000..02f0d4c --- /dev/null +++ b/sources/Emu48/COLOR.H @@ -0,0 +1,27 @@ +/* + * color.h + * + * This file is part of Emu48 + * + * Copyright (C) 1999 Christoph Gießelink + * + */ + +#define COLOR_BLACK 0x00000000 +#define COLOR_MAROON 0x00000080 +#define COLOR_GREEN 0x00008000 +#define COLOR_OLIVE 0x00008080 +#define COLOR_NAVY 0x00800000 +#define COLOR_PURPLE 0x00800080 +#define COLOR_TEAL 0x00808000 +#define COLOR_GRAY 0x00808080 +#define COLOR_SILVER 0x00C0C0C0 +#define COLOR_RED 0x000000FF +#define COLOR_LIME 0x0000FF00 +#define COLOR_YELLOW 0x0000FFFF +#define COLOR_BLUE 0x00FF0000 +#define COLOR_FUCHSIA 0x00FF00FF +#define COLOR_AQUA 0x00FFFF00 +#define COLOR_LTGRAY 0x00C0C0C0 +#define COLOR_DKGRAY 0x00808080 +#define COLOR_WHITE 0x00FFFFFF diff --git a/sources/Emu48/DDESERV.C b/sources/Emu48/DDESERV.C index 6d9b138..9684598 100644 --- a/sources/Emu48/DDESERV.C +++ b/sources/Emu48/DDESERV.C @@ -15,7 +15,7 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv, { BYTE szBuffer[32]; HDDEDATA hReturn; - LPBYTE lpData; + LPBYTE lpData,lpHeader; DWORD dwAddress,dwSize,dwLoop,dwIndex; BOOL bSuccess; @@ -40,16 +40,15 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv, if ((lpData = (LPBYTE) LocalAlloc(LMEM_FIXED,dwSize * 2)) == NULL) return (HDDEDATA) DDE_FNOTPROCESSED; - if (!Chipset.dispon) // 25.08.98 cg, moved, HP off + if (!Chipset.dispon) // HP off { // turn on HP KeyboardEvent(TRUE,0,0x8000); Sleep(200); KeyboardEvent(FALSE,0,0x8000); - // while(Chipset.Shutdn == FALSE) Sleep(0); // 25.08.98 cg, removed } - if (WaitForSleepState()) // 16.06.98 cg, wait for cpu SHUTDN then sleep state + if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state { LocalFree(lpData); // free memory return (HDDEDATA) DDE_FNOTPROCESSED; @@ -86,7 +85,7 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv, if (iFmt != uCF_HpObj || nState != 0) return NULL; - if (WaitForSleepState()) // 16.06.98 cg, wait for cpu SHUTDN then sleep state + if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state return NULL; while (nState!=nNextState) Sleep(0); @@ -100,8 +99,10 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv, } dwLoop = dwSize = (RPL_SkipOb(dwAddress) - dwAddress + 1) / 2; + lpHeader = (Chipset.type != 'X') ? BINARYHEADER48 : BINARYHEADER49; + // length of binary header - dwIndex = sizeof(BINARYHEADER) - 1; + dwIndex = strlen(lpHeader); // size of objectsize + header + object dwSize += dwIndex + sizeof(DWORD); @@ -117,7 +118,7 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv, *(DWORD *)lpData = dwLoop + dwIndex; // copy header - memcpy(lpData + sizeof(DWORD),BINARYHEADER,dwIndex); + memcpy(lpData + sizeof(DWORD),lpHeader,dwIndex); // copy data for (dwIndex += sizeof(DWORD);dwLoop--;++dwIndex,dwAddress += 2) diff --git a/sources/Emu48/DEBUGGER.C b/sources/Emu48/DEBUGGER.C new file mode 100644 index 0000000..c33a16d --- /dev/null +++ b/sources/Emu48/DEBUGGER.C @@ -0,0 +1,1475 @@ +/* + * debugger.c + * + * This file is part of Emu48 + * + * Copyright (C) 1999 Christoph Gießelink + * + */ +#include "pch.h" +#include "resource.h" +#include "Emu48.h" +#include "Opcodes.h" +#include "ops.h" +#include "color.h" +#include "debugger.h" + +#define MAXCODELINES 15 // number of lines in code window +#define MAXMEMLINES 6 // number of lines in memory window +#define MAXMEMITEMS 16 // number of address items in a memory window line +#define MAXBREAKPOINTS 256 // max. number of breakpoints + +#define WM_UPDATE (WM_USER+0x1000) // update debugger dialog box + +#define MEMWNDMAX (sizeof(nCol) / sizeof(nCol[0])) + +static CONST int nCol[] = +{ + IDC_DEBUG_MEM_COL0, IDC_DEBUG_MEM_COL1, IDC_DEBUG_MEM_COL2, IDC_DEBUG_MEM_COL3, + IDC_DEBUG_MEM_COL4, IDC_DEBUG_MEM_COL5, IDC_DEBUG_MEM_COL6, IDC_DEBUG_MEM_COL7 +}; + +static CONST char cHex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + +static WORD wBreakpointCount = 0; // number of breakpoints +static DWORD dwBreakpoint[MAXBREAKPOINTS]; // breakpoint table + +static DWORD dwAdrLine[MAXCODELINES]; // addresses of disassember lines in code window +static DWORD dwAdrMem = 0; // start address of memory window + +static LONG lCharWidth; // width of a character (is a fix font) + +static HMENU hMenuCode,hMenuMem; // handle of context menues + +static CHIPSET OldChipset; // 10.11.99 cg, new, old chipset content + +HWND hDlgDebug = NULL; // handle for debugger dialog + +HANDLE hEventDebug; // event handle to stop cpu thread + +BOOL bDbgEnable = FALSE; // debugger mode enable flag +INT nDbgState = DBG_RUN; // 13.11.99 cg, new, state of debugger + +//BOOL bDbgSingle = FALSE; // 13.11.99 cg, removed +//BOOL bDbgOver = FALSE; // 13.11.99 cg, removed + +BOOL bDbgNOP3 = FALSE; // halt on NOP3 (#420 opcode) + +DWORD dwDbgRstkp; // stack recursion level of step over end +DWORD dwDbgRstk; // 13.11.99 cg, new, possible return address + +// function prototypes +static VOID OnNewValue(LPSTR lpszValue); +static VOID OnEnterAddress(HWND hDlg, DWORD *dwValue); +static BOOL OnEditBreakpoint(HWND hDlg); + + +//################ +//# +//# Low level subroutines +//# +//################ + +// +// set/reset breakpoint +// +static __inline VOID ToggleBreakpoint(DWORD dwAddr) +{ + INT i; + + for (i = 0; i < wBreakpointCount; ++i) // scan all breakpoints + { + if (dwBreakpoint[i] == dwAddr) // breakpoint found + { + // purge breakpoint + for (++i; i < wBreakpointCount; ++i) + dwBreakpoint[i-1] = dwBreakpoint[i]; + --wBreakpointCount; + return; + } + } + + // breakpoint not found + if (wBreakpointCount >= MAXBREAKPOINTS) // breakpoint buffer full + { + AbortMessage("Reached maximum number of breakpoints !"); + return; + } + + dwBreakpoint[wBreakpointCount] = dwAddr; + ++wBreakpointCount; + return; +} + +// +// convert nibble register to string +// +static LPSTR RegToStr(BYTE *pReg, WORD wNib) +{ + static char szBuffer[32]; + + WORD i; + + for (i = 0;i < wNib;++i) + szBuffer[i] = cHex[pReg[wNib-i-1]]; + szBuffer[i] = 0; + + return szBuffer; +} + +// +// convert string to nibble register +// +static VOID StrToReg(BYTE *pReg, WORD wNib, LPSTR lpszValue) +{ + int i,nValuelen; + + nValuelen = strlen(lpszValue); + for (i = wNib - 1;i >= 0;--i) + { + if (i >= nValuelen) // no character in string + { + pReg[i] = 0; // fill with zero + } + else + { + pReg[i] = *lpszValue - '0'; // convert to number + if (pReg[i] > 9) pReg[i] -= 7; + ++lpszValue; + } + } + return; +} + +// +// write code window +// +static VOID ViewCodeWnd(HWND hWnd, DWORD dwAddress) +{ + INT i,j; + char szAddress[64]; + + SendMessage(hWnd,WM_SETREDRAW,FALSE,0); + SendMessage(hWnd,LB_RESETCONTENT,0,0); + for (i = 0; i < MAXCODELINES; ++i) + { + dwAdrLine[i] = dwAddress; + j = wsprintf(szAddress,(dwAddress == Chipset.pc) ?"%05lX-> " : "%05lX ",dwAddress); + dwAddress = disassemble(dwAddress,&szAddress[j],VIEW_SHORT); + SendMessage(hWnd,LB_ADDSTRING,0,(LPARAM) szAddress); + } + SendMessage(hWnd,WM_SETREDRAW,TRUE,0); + return; +} + +// +// write memory window +// +static VOID ViewMemWnd(HWND hDlg, DWORD dwAddress) +{ + #define TEXTOFF 32 + + INT i,j,k; + char szBuffer[16],szItem[4]; + BYTE cChar = 0; + + szItem[2] = 0; // end of string + dwAdrMem = dwAddress; // save start address of memory window + + // purge all list boxes + SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_ADDR,LB_RESETCONTENT,0,0); + SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_TEXT,LB_RESETCONTENT,0,0); + for (j = 0; j < MEMWNDMAX; ++j) + SendDlgItemMessage(hDlg,nCol[j],LB_RESETCONTENT,0,0); + + for (i = 0; i < MAXMEMLINES; ++i) + { + BYTE byLineData[MAXMEMITEMS]; + + // 12.11.99 cg, changed, fetch data line + Npeek(byLineData, dwAddress, MAXMEMITEMS); + + wsprintf(szBuffer,"%05lX",dwAddress); + SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_ADDR,LB_ADDSTRING,0,(LPARAM) szBuffer); + + for (k = 0, j = 0; j < MAXMEMITEMS; ++j) + { + // 12.11.99 cg, changed, read from fetched data line + szItem[j&0x1] = cHex[byLineData[j]]; + cChar = (cChar << 4) | byLineData[j]; + + if ((j&0x1) != 0) + { + // byte field + _ASSERT(j/2 < MEMWNDMAX); + SendDlgItemMessage(hDlg,nCol[j/2],LB_ADDSTRING,0,(LPARAM) szItem); + + // text field + szBuffer[j/2] = (isprint(cChar) != 0) ? cChar : '.'; + } + } + szBuffer[j/2] = 0; // end of text string + SendDlgItemMessage(hDlg,IDC_DEBUG_MEM_TEXT,LB_ADDSTRING,0,(LPARAM) szBuffer); + dwAddress = (dwAddress + MAXMEMITEMS) & 0xFFFFF; + } + return; + #undef TEXTOFF +} + +// +// write stack window +// +static VOID ViewStackWnd(HWND hDlg) +{ + INT i; + char szBuffer[64]; + + HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_STACK); + + SendMessage(hWnd,WM_SETREDRAW,FALSE,0); + SendMessage(hWnd,LB_RESETCONTENT,0,0); + for (i = 1; i <= sizeof(Chipset.rstk) / sizeof(Chipset.rstk[0]); ++i) + { + wsprintf(szBuffer,"%d: %05X", i, Chipset.rstk[(Chipset.rstkp-i)&7]); + SendMessage(hWnd,LB_ADDSTRING,0,(LPARAM) szBuffer); + } + SendMessage(hWnd,WM_SETREDRAW,TRUE,0); + return; +} + +//################ +//# +//# High level Window draw routines +//# +//################ + +// +// update code window with scrolling +// +static VOID UpdateCodeWnd(HWND hDlg) +{ + INT i; + DWORD dwAddress; + char szAddress[256]; + + HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_CODE); + + // seach for actual address in code area + for (i = 0; i < MAXCODELINES; ++i) + { + // get address + SendMessage(hWnd,LB_GETTEXT,i,(LONG) szAddress); + sscanf(szAddress,"%X",&dwAddress); + + if (dwAddress == Chipset.pc) // found new pc address line + break; + } + + // redraw code window + dwAddress = dwAdrLine[0]; // redraw list box with modified pc + if (i == MAXCODELINES) // address not found + { + dwAddress = Chipset.pc; // begin with actual pc + i = 0; // set cursor on top + } + if (i > 10) // cursor near bottom line + { + dwAddress = dwAdrLine[i-10]; // move that pc is in line 11 + i = 10; // set cursor to actual pc + } + ViewCodeWnd(hWnd,dwAddress); // init code area + SendMessage(hWnd,LB_SETCURSEL,i,0); // set + return; +} + +// +// update register window +// +static VOID UpdateRegisterWnd(HWND hDlg) +{ + char szBuffer[64]; + + wsprintf(szBuffer,"A= %s",RegToStr(Chipset.A,16)); + SetDlgItemText(hDlg,IDC_REG_A,szBuffer); + wsprintf(szBuffer,"B= %s",RegToStr(Chipset.B,16)); + SetDlgItemText(hDlg,IDC_REG_B,szBuffer); + wsprintf(szBuffer,"C= %s",RegToStr(Chipset.C,16)); + SetDlgItemText(hDlg,IDC_REG_C,szBuffer); + wsprintf(szBuffer,"D= %s",RegToStr(Chipset.D,16)); + SetDlgItemText(hDlg,IDC_REG_D,szBuffer); + wsprintf(szBuffer,"R0=%s",RegToStr(Chipset.R0,16)); + SetDlgItemText(hDlg,IDC_REG_R0,szBuffer); + wsprintf(szBuffer,"R1=%s",RegToStr(Chipset.R1,16)); + SetDlgItemText(hDlg,IDC_REG_R1,szBuffer); + wsprintf(szBuffer,"R2=%s",RegToStr(Chipset.R2,16)); + SetDlgItemText(hDlg,IDC_REG_R2,szBuffer); + wsprintf(szBuffer,"R3=%s",RegToStr(Chipset.R3,16)); + SetDlgItemText(hDlg,IDC_REG_R3,szBuffer); + wsprintf(szBuffer,"R4=%s",RegToStr(Chipset.R4,16)); + SetDlgItemText(hDlg,IDC_REG_R4,szBuffer); + wsprintf(szBuffer,"D0=%05X",Chipset.d0); + SetDlgItemText(hDlg,IDC_REG_D0,szBuffer); + wsprintf(szBuffer,"D1=%05X",Chipset.d1); + SetDlgItemText(hDlg,IDC_REG_D1,szBuffer); + wsprintf(szBuffer,"P=%X",Chipset.P); + SetDlgItemText(hDlg,IDC_REG_P,szBuffer); + wsprintf(szBuffer,"PC=%05X",Chipset.pc); + SetDlgItemText(hDlg,IDC_REG_PC,szBuffer); + wsprintf(szBuffer,"OUT=%03X",Chipset.out); + SetDlgItemText(hDlg,IDC_REG_OUT,szBuffer); + wsprintf(szBuffer,"IN=%04X",Chipset.in); + SetDlgItemText(hDlg,IDC_REG_IN,szBuffer); + wsprintf(szBuffer,"ST=%s",RegToStr(Chipset.ST,4)); + SetDlgItemText(hDlg,IDC_REG_ST,szBuffer); + wsprintf(szBuffer,"CY=%d",Chipset.carry); + SetDlgItemText(hDlg,IDC_REG_CY,szBuffer); + wsprintf(szBuffer,"Mode=%c",Chipset.mode_dec ? 'D' : 'H'); + SetDlgItemText(hDlg,IDC_REG_MODE,szBuffer); + wsprintf(szBuffer,"MP=%d",(Chipset.HST & MP) != 0); + SetDlgItemText(hDlg,IDC_REG_MP,szBuffer); + wsprintf(szBuffer,"SR=%d",(Chipset.HST & SR) != 0); + SetDlgItemText(hDlg,IDC_REG_SR,szBuffer); + wsprintf(szBuffer,"SB=%d",(Chipset.HST & SB) != 0); + SetDlgItemText(hDlg,IDC_REG_SB,szBuffer); + wsprintf(szBuffer,"XM=%d",(Chipset.HST & XM) != 0); + SetDlgItemText(hDlg,IDC_REG_XM,szBuffer); + return; +} + +// +// update memory window +// +static VOID UpdateMemoryWnd(HWND hDlg) +{ + ViewMemWnd(hDlg,dwAdrMem); + return; +} + +// +// update complete debugger dialog +// +VOID OnUpdate(HWND hDlg) +{ + nDbgState = DBG_STEPINTO; // 13.11.99 cg, changed, state "step into" + + // enable debug buttons + EnableMenuItem(GetMenu(hDlg),ID_DEBUG_RUN,MF_ENABLED); + EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEP,MF_ENABLED); + EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOVER,MF_ENABLED); + // 12.11.99 cg, new + EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOUT,MF_ENABLED); + + // update windows + UpdateCodeWnd(hDlg); // update code window + UpdateRegisterWnd(hDlg); // update registers window + UpdateMemoryWnd(hDlg); // update memory window + ViewStackWnd(hDlg); // update stack window + ShowWindow(hDlg,SW_RESTORE); // 15.11.99 cg, moved, pop up if minimized + SetFocus(hDlg); // set focus to debugger + return; +} + + +//################ +//# +//# Virtual key handler +//# +//################ + +// +// toggle breakpoint key handler (F2) +// +static BOOL OnKeyF2(HWND hDlg) +{ + HWND hWnd; + RECT rc; + LONG i; + + hWnd = GetDlgItem(hDlg,IDC_DEBUG_CODE); + i = SendMessage(hWnd,LB_GETCURSEL,0,0); // get selected item + ToggleBreakpoint(dwAdrLine[i]); // toggle breakpoint at address + // update region of toggled item + SendMessage(hWnd,LB_GETITEMRECT,i,(LPARAM)&rc); + InvalidateRect(hWnd,&rc,TRUE); + return -1; // call windows default handler +} + +// +// run key handler (F5) +// +static BOOL OnKeyF5(HWND hDlg) +{ + HWND hWnd; + INT i,nPos; + char szBuf[64]; + + if (nDbgState != DBG_RUN) // 13.11.99 cg, changed, emulation stopped + { + hWnd = GetDlgItem(hDlg,IDC_DEBUG_CODE); + nPos = SendMessage(hWnd,LB_GETCURSEL,0,0); + + // clear "->" in code window + for (i = 0; i < MAXCODELINES; ++i) + { + SendMessage(hWnd,LB_GETTEXT,i,(LPARAM) szBuf); + if (szBuf[5] == '-') // PC in window + { + szBuf[5] = szBuf[6] = ' '; + SendMessage(hWnd,LB_DELETESTRING,i,0); + SendMessage(hWnd,LB_INSERTSTRING,i,(LPARAM)(LPSTR)szBuf); + break; + } + } + SendMessage(hWnd,LB_SETCURSEL,nPos,0); + + // disable menu keys + EnableMenuItem(GetMenu(hDlg),ID_DEBUG_RUN,MF_GRAYED); + EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEP,MF_GRAYED); + EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOVER,MF_GRAYED); + // 12.11.99 cg, new + EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOUT,MF_GRAYED); + + nDbgState = DBG_RUN; // 13.11.99 cg, changed, state "run" + OldChipset = Chipset; // 10.11.99 cg, new, save chipset values + SetEvent(hEventDebug); // run emulation + } + return -1; // call windows default handler + UNREFERENCED_PARAMETER(hDlg); +} + +// +// step into key handler (F7) +// +static BOOL OnKeyF7(HWND hDlg) +{ + if (nDbgState != DBG_RUN) // 13.11.99 cg, changed, emulation stopped + { + nDbgState = DBG_STEPINTO; // 13.11.99 cg, changed, state "step into" + OldChipset = Chipset; // 10.11.99 cg, new, save chipset values + SetEvent(hEventDebug); // run emulation + } + return -1; // call windows default handler + UNREFERENCED_PARAMETER(hDlg); +} + +// +// step over key handler (F8) +// +static BOOL OnKeyF8(HWND hDlg) +{ + if (nDbgState != DBG_RUN) // 13.11.99 cg, changed, emulation stopped + { + LPBYTE I = FASTPTR(Chipset.pc); + + dwDbgRstkp = Chipset.rstkp; // save stack level + + nDbgState = DBG_STEPINTO; // 13.11.99 cg, changed, state "step into" + if (I[0] == 0x7) // GOSUB 7aaa + { + nDbgState = DBG_STEPOVER; // 13.11.99 cg, changed, state "step over" + } + if (I[0] == 0x8) // GOSUBL or GOSBVL + { + if (I[1] == 0xE) // GOSUBL 8Eaaaa + { + nDbgState = DBG_STEPOVER; // 13.11.99 cg, changed, state "step over" + } + if (I[1] == 0xF) // GOSBVL 8Eaaaaa + { + nDbgState = DBG_STEPOVER; // 13.11.99 cg, changed, state "step over" + } + } + OldChipset = Chipset; // 10.11.99 cg, new, save chipset values + SetEvent(hEventDebug); // run emulation + } + return -1; // call windows default handler + UNREFERENCED_PARAMETER(hDlg); +} + +// +// step out key handler (F9) +// +// 13.11.99 cg, new +static BOOL OnKeyF9(HWND hDlg) +{ + if (nDbgState != DBG_RUN) // emulation stopped + { + // disable menu keys + EnableMenuItem(GetMenu(hDlg),ID_DEBUG_RUN,MF_GRAYED); + EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEP,MF_GRAYED); + EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOVER,MF_GRAYED); + EnableMenuItem(GetMenu(hDlg),ID_DEBUG_STEPOUT,MF_GRAYED); + + dwDbgRstkp = (Chipset.rstkp-1)&7; // save stack data + dwDbgRstk = Chipset.rstk[dwDbgRstkp]; + nDbgState = DBG_STEPOUT; // 13.11.99 cg, changed, state "step out" + OldChipset = Chipset; // save chipset values + SetEvent(hEventDebug); // run emulation + } + return -1; // call windows default handler + UNREFERENCED_PARAMETER(hDlg); +} + +// +// break key handler (F11) +// +static BOOL OnKeyF11(HWND hDlg) +{ + nDbgState = DBG_STEPINTO; // 13.11.99 cg, changed, state "step into" + return -1; // call windows default handler + UNREFERENCED_PARAMETER(hDlg); +} + +// +// view of given address in disassembler window +// +static BOOL OnCodeGoAdr(HWND hDlg) +{ + DWORD dwAddress = -1; // no address given + + OnEnterAddress(hDlg, &dwAddress); + if (dwAddress != -1) + { + HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_CODE); + ViewCodeWnd(hWnd,dwAddress); + SendMessage(hWnd,LB_SETCURSEL,0,0); + } + return -1; // call windows default handler +} + +// +// view pc in disassembler window +// +static BOOL OnCodeGoPC(HWND hDlg) +{ + UpdateCodeWnd(hDlg); + return TRUE; +} + +// +// set pc to selction +// +static BOOL OnCodeSetPcToSelection(HWND hDlg) +{ + Chipset.pc = dwAdrLine[SendDlgItemMessage(hDlg,IDC_DEBUG_CODE,LB_GETCURSEL,0,0)]; + return OnCodeGoPC(hDlg); +} + +// +// view from address in memory window +// +static BOOL OnMemGoDx(HWND hDlg, DWORD dwAddress) +{ + HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_MEM_COL0); + + ViewMemWnd(hDlg, dwAddress); + SendMessage(hWnd,LB_SETCURSEL,0,0); + SetFocus(hWnd); + return -1; // call windows default handler +} + +// +// view of given address in memory window +// +static BOOL OnMemGoAdr(HWND hDlg) +{ + DWORD dwAddress = -1; // no address given + + OnEnterAddress(hDlg, &dwAddress); + if (dwAddress != -1) // not Cancel key + OnMemGoDx(hDlg,dwAddress); + return -1; // call windows default handler +} + +// +// clear all breakpoints +// +static BOOL OnClearAll(HWND hDlg) // 13.12.99 cg, changed argument +{ + wBreakpointCount = 0; + // 13.12.99 cg, changed, redraw code window + InvalidateRect(GetDlgItem(hDlg,IDC_DEBUG_CODE),NULL,TRUE); + return TRUE; +} + +// +// toggle NOP3 breakpoint +// +static BOOL OnNOP3Break(HWND hDlg) +{ + bDbgNOP3 = !bDbgNOP3; // toggle NOP3 debug flag + CheckMenuItem(GetMenu(hDlg),ID_BREAKPOINTS_NOP3,bDbgNOP3 ? MF_CHECKED : MF_UNCHECKED); + return TRUE; +} + +// +// new register setting +// +static BOOL OnLButtonUp(HWND hDlg, LPARAM lParam) +{ + char szBuffer[64]; + POINT pt; + HWND hWnd; + INT nId; + + #define BUFLEN (sizeof(szBuffer) / sizeof(szBuffer[0])) + + POINTSTOPOINT(pt,MAKEPOINTS(lParam)); + hWnd = ChildWindowFromPoint(hDlg,pt); // handle of selected window + nId = GetDlgCtrlID(hWnd); // control ID of window + + SendMessage(hWnd,WM_GETTEXT,BUFLEN,(LPARAM)szBuffer); + switch (nId) + { + case IDC_REG_A: // A + OnNewValue(&szBuffer[3]); + StrToReg(Chipset.A,16,&szBuffer[3]); + break; + case IDC_REG_B: // B + OnNewValue(&szBuffer[3]); + StrToReg(Chipset.B,16,&szBuffer[3]); + break; + case IDC_REG_C: // C + OnNewValue(&szBuffer[3]); + StrToReg(Chipset.C,16,&szBuffer[3]); + break; + case IDC_REG_D: // D + OnNewValue(&szBuffer[3]); + StrToReg(Chipset.D,16,&szBuffer[3]); + break; + case IDC_REG_R0: // R0 + OnNewValue(&szBuffer[3]); + StrToReg(Chipset.R0,16,&szBuffer[3]); + break; + case IDC_REG_R1: // R1 + OnNewValue(&szBuffer[3]); + StrToReg(Chipset.R1,16,&szBuffer[3]); + break; + case IDC_REG_R2: // R2 + OnNewValue(&szBuffer[3]); + StrToReg(Chipset.R2,16,&szBuffer[3]); + break; + case IDC_REG_R3: // R3 + OnNewValue(&szBuffer[3]); + StrToReg(Chipset.R3,16,&szBuffer[3]); + break; + case IDC_REG_R4: // R4 + OnNewValue(&szBuffer[3]); + StrToReg(Chipset.R4,16,&szBuffer[3]); + break; + case IDC_REG_D0: // D0 + OnNewValue(&szBuffer[3]); + sscanf(&szBuffer[3],"%5X",&Chipset.d0); + break; + case IDC_REG_D1: // D1 + OnNewValue(&szBuffer[3]); + sscanf(&szBuffer[3],"%5X",&Chipset.d1); + break; + case IDC_REG_P: // P + OnNewValue(&szBuffer[2]); + Chipset.P = szBuffer[2] - '0'; + if (Chipset.P > 9) Chipset.P -= 7; + break; + case IDC_REG_PC: // PC + OnNewValue(&szBuffer[3]); + sscanf(&szBuffer[3],"%5X",&Chipset.pc); + break; + case IDC_REG_OUT: // OUT + OnNewValue(&szBuffer[4]); + sscanf(&szBuffer[4],"%3X",&Chipset.out); + break; + case IDC_REG_IN: // IN + OnNewValue(&szBuffer[3]); + sscanf(&szBuffer[3],"%4X",&Chipset.in); + break; + case IDC_REG_ST: // ST + OnNewValue(&szBuffer[3]); + StrToReg(Chipset.ST,4,&szBuffer[3]); + break; + case IDC_REG_CY: // CY +// if (YesNoMessage("Change Carry flag ?") == IDYES) + Chipset.carry = !Chipset.carry; + break; + case IDC_REG_MODE: // MODE + Chipset.mode_dec = !Chipset.mode_dec; + break; + case IDC_REG_MP: // MP + Chipset.HST ^= MP; + break; + case IDC_REG_SR: // SR + Chipset.HST ^= SR; + break; + case IDC_REG_SB: // SB + Chipset.HST ^= SB; + break; + case IDC_REG_XM: // XM + Chipset.HST ^= XM; + break; + } + UpdateRegisterWnd(hDlg); // update register + return TRUE; + #undef BUFLEN +} + +// +// double click in list box area +// +static BOOL OnDblClick(HWND hWnd, WORD wId) +{ + char szBuffer[4]; + BYTE byData; + INT i; + DWORD dwAddress; + + for (i = 0; i < MEMWNDMAX; ++i) // scan all Id's + if (nCol[i] == wId) // found ID + break; + + if (i == MEMWNDMAX) return FALSE; // not IDC_DEBUG_MEM window, default handler + + // calculate address of byte + dwAddress = i * 2; + i = SendMessage(hWnd,LB_GETCARETINDEX,0,0); + dwAddress += MAXMEMITEMS * i + dwAdrMem; + + // enter new value + SendMessage(hWnd,LB_GETTEXT,i,(LPARAM) szBuffer); + OnNewValue(szBuffer); + sscanf(szBuffer,"%2X", &byData); + byData = (byData >> 4) | (byData << 4); // 12.11.99 cg, bugfix, change nibbles for writing + + Write2(dwAddress, byData); // write data + UpdateMemoryWnd(GetParent(hWnd)); // update memory window + SendMessage(hWnd,LB_SETCURSEL,i,0); + return FALSE; +} + +// +// request for context menu +// +static VOID OnContextMenu(HWND hDlg, LPARAM lParam, WPARAM wParam) +{ + POINT pt; + INT nId; + + POINTSTOPOINT(pt,MAKEPOINTS(lParam)); // mouse position + nId = GetDlgCtrlID((HWND) wParam); // control ID of window + + switch(nId) + { + case IDC_DEBUG_CODE: // handle code window + TrackPopupMenu(hMenuCode,0,pt.x,pt.y,0,hDlg,NULL); + break; + + case IDC_DEBUG_MEM_COL0: + case IDC_DEBUG_MEM_COL1: + case IDC_DEBUG_MEM_COL2: + case IDC_DEBUG_MEM_COL3: + case IDC_DEBUG_MEM_COL4: + case IDC_DEBUG_MEM_COL5: + case IDC_DEBUG_MEM_COL6: + case IDC_DEBUG_MEM_COL7: // handle memory window + TrackPopupMenu(hMenuMem,0,pt.x,pt.y,0,hDlg,NULL); + break; + } + return; +} + +//################ +//# +//# Dialog handler +//# +//################ + +// +// handle right/left keys in memory window +// +static __inline BOOL OnKeyRightLeft(HWND hWnd, WPARAM wParam) +{ + HWND hWndNew; + WORD wX, wY; + INT nId; + + nId = GetDlgCtrlID(hWnd); // control ID of window + + for (wX = 0; wX < MEMWNDMAX; ++wX) // scan all Id's + if (nCol[wX] == nId) // found ID + break; + + if (wX == MEMWNDMAX) return -1; // not IDC_DEBUG_MEM window, default handler + + // delete old focus + wY = HIWORD(wParam); + SendMessage(hWnd,LB_SETCURSEL,-1,0); + + // new position + wX = (LOWORD(wParam) == VK_RIGHT) ? (wX + 1) : (wX + MEMWNDMAX - 1); + wX %= MEMWNDMAX; + + // set new focus + hWndNew = GetDlgItem(GetParent(hWnd),nCol[wX]); + SendMessage(hWndNew,LB_SETCURSEL,wY,0); + SetFocus(hWndNew); + + return -2; +} + +// +// handle (page) up/down keys in memory window +// +static __inline BOOL OnKeyUpDown(HWND hWnd, WPARAM wParam) +{ + INT wX, wY; + INT nId; + + nId = GetDlgCtrlID(hWnd); // control ID of window + + for (wX = 0; wX < MEMWNDMAX; ++wX) // scan all Id's + if (nCol[wX] == nId) // found ID + break; + + if (wX == MEMWNDMAX) return -1; // not IDC_DEBUG_MEM window, default handler + + wY = HIWORD(wParam); // get old focus + + switch(LOWORD(wParam)) + { + case VK_NEXT: + dwAdrMem = (dwAdrMem + MAXMEMITEMS * MAXMEMLINES) & 0xFFFFF; + UpdateMemoryWnd(GetParent(hWnd)); + SendMessage(hWnd,LB_SETCURSEL,wY,0); + return -2; + + case VK_PRIOR: + dwAdrMem = (dwAdrMem - MAXMEMITEMS * MAXMEMLINES) & 0xFFFFF; + UpdateMemoryWnd(GetParent(hWnd)); + SendMessage(hWnd,LB_SETCURSEL,wY,0); + return -2; + + case VK_DOWN: + if (wY+1 >= MAXMEMLINES) + { + dwAdrMem = (dwAdrMem + MAXMEMITEMS) & 0xFFFFF; + UpdateMemoryWnd(GetParent(hWnd)); + SendMessage(hWnd,LB_SETCURSEL,wY,0); + return -2; + } + break; + + case VK_UP: + if (wY == 0) + { + dwAdrMem = (dwAdrMem - MAXMEMITEMS) & 0xFFFFF; + UpdateMemoryWnd(GetParent(hWnd)); + SendMessage(hWnd,LB_SETCURSEL,wY,0); + return -2; + } + break; + } + return -1; +} + +// +// handle keys in code window +// +// 13.12.99 cg, changed first argument +static __inline BOOL OnKeyCodeWnd(HWND hDlg, WPARAM wParam) +{ + // 13.12.99 cg, new, get handle of code window (was argument) + HWND hWnd = GetDlgItem(hDlg,IDC_DEBUG_CODE); + WORD wKey = LOWORD(wParam); + WORD wItem = HIWORD(wParam); + + // down key on last line + if ((wKey == VK_DOWN || wKey == VK_NEXT) && wItem == MAXCODELINES - 1) + { + ViewCodeWnd(hWnd,dwAdrLine[1]); + SendMessage(hWnd,LB_SETCURSEL,wItem,0); + } + // up key on first line + if ((wKey == VK_UP || wKey == VK_PRIOR) && wItem == 0) + { + if (dwAdrLine[0] > 0) ViewCodeWnd(hWnd,dwAdrLine[0]-1); + } + + if (wKey == 'G') return OnCodeGoAdr(GetParent(hWnd)); // goto new address + + return -1; +} + +// +// handle drawing in code window +// +static __inline BOOL OnDrawCodeWnd(LPDRAWITEMSTRUCT lpdis) +{ + char szBuf[64]; + COLORREF crBkColor; + COLORREF crTextColor; + BOOL bBrk,bPC; + + if (lpdis->itemID == -1) // no item in list box + return TRUE; + + // get item text + SendMessage(lpdis->hwndItem,LB_GETTEXT,lpdis->itemID,(LONG)(LPSTR)szBuf); + + bBrk = CheckBreakpoint(dwAdrLine[lpdis->itemID]); // check breakpoint + bPC = szBuf[5] == '-'; // check if line of program counter + + crTextColor = COLOR_WHITE; // standard text color + + if (lpdis->itemState & ODS_SELECTED) // cursor line + { + if (bPC) // PC line + { + crBkColor = bBrk ? COLOR_DKGRAY : COLOR_TEAL; + } + else // normal line + { + crBkColor = bBrk ? COLOR_PURPLE : COLOR_NAVY; + } + } + else // not cursor line + { + if (bPC) // PC line + { + crBkColor = bBrk ? COLOR_OLIVE : COLOR_GREEN; + } + else // normal line + { + if (bBrk) + { + crBkColor = COLOR_MAROON; + } + else + { + crBkColor = COLOR_WHITE; + crTextColor = COLOR_BLACK; + } + } + } + + // write Text + crBkColor = SetBkColor(lpdis->hDC,crBkColor); + crTextColor = SetTextColor(lpdis->hDC,crTextColor); + + ExtTextOut(lpdis->hDC,(int)(lpdis->rcItem.left)+2,(int)(lpdis->rcItem.top), + ETO_OPAQUE,(LPRECT)&lpdis->rcItem,szBuf,strlen(szBuf),NULL); + + SetBkColor(lpdis->hDC,crBkColor); + SetTextColor(lpdis->hDC,crTextColor); + + if (lpdis->itemState & ODS_FOCUS) // redraw focus + DrawFocusRect(lpdis->hDC,&lpdis->rcItem); + + return TRUE; // focus handled here +} + +// +// detect changed register +// +// 10.11.99 cg, new +static __inline BOOL OnCtlColorStatic(HWND hWnd) +{ + switch(GetDlgCtrlID(hWnd)) + { + case IDC_REG_A: // A + return memcmp(Chipset.A, OldChipset.A, sizeof(Chipset.A)); + case IDC_REG_B: // B + return memcmp(Chipset.B, OldChipset.B, sizeof(Chipset.B)); + case IDC_REG_C: // C + return memcmp(Chipset.C, OldChipset.C, sizeof(Chipset.C)); + case IDC_REG_D: // D + return memcmp(Chipset.D, OldChipset.D, sizeof(Chipset.D)); + case IDC_REG_R0: // R0 + return memcmp(Chipset.R0, OldChipset.R0, sizeof(Chipset.R0)); + case IDC_REG_R1: // R1 + return memcmp(Chipset.R1, OldChipset.R1, sizeof(Chipset.R1)); + case IDC_REG_R2: // R2 + return memcmp(Chipset.R2, OldChipset.R2, sizeof(Chipset.R2)); + case IDC_REG_R3: // R3 + return memcmp(Chipset.R3, OldChipset.R3, sizeof(Chipset.R3)); + case IDC_REG_R4: // R4 + return memcmp(Chipset.R4, OldChipset.R4, sizeof(Chipset.R4)); + case IDC_REG_D0: // D0 + return Chipset.d0 != OldChipset.d0; + case IDC_REG_D1: // D1 + return Chipset.d1 != OldChipset.d1; + case IDC_REG_P: // P + return Chipset.P != OldChipset.P; + case IDC_REG_PC: // PC + return Chipset.pc != OldChipset.pc; + case IDC_REG_OUT: // OUT + return Chipset.out != OldChipset.out; + case IDC_REG_IN: // IN + return Chipset.in != OldChipset.in; + case IDC_REG_ST: // ST + return memcmp(Chipset.ST, OldChipset.ST, sizeof(Chipset.ST)); + case IDC_REG_CY: // CY + return Chipset.carry != OldChipset.carry; + case IDC_REG_MODE: // MODE + return Chipset.mode_dec != OldChipset.mode_dec; + case IDC_REG_MP: // MP + return (Chipset.HST ^ OldChipset.HST) & MP; + case IDC_REG_SR: // SR + return (Chipset.HST ^ OldChipset.HST) & SR; + case IDC_REG_SB: // SB + return (Chipset.HST ^ OldChipset.HST) & SB; + case IDC_REG_XM: // XM + return (Chipset.HST ^ OldChipset.HST) & XM; + } + return FALSE; // not changed +} + + +//################ +//# +//# Public functions +//# +//################ + +// +// check for code breakpoints +// +BOOL CheckBreakpoint(DWORD dwAddr) +{ + INT i; + + for (i = 0; i < wBreakpointCount; ++i) // scan all breakpoints + { + if (dwBreakpoint[i] == dwAddr) // breakpoint found + return TRUE; + } + return FALSE; +} + +// +// notify debugger that emulation stopped +// +VOID NotifyDebugger(VOID) // 10.11.99 cg, new, update registers +{ + _ASSERT(hDlgDebug); // debug dialog box open + PostMessage(hDlgDebug,WM_UPDATE,0,0); + return; +} + +//################ +//# +//# Debugger Message loop +//# +//################ + +// +// ID_TOOL_DEBUG +// +static BOOL CALLBACK Debugger(HWND hDlg, UINT message, DWORD wParam, LONG lParam) +{ + static HMENU hMenuMainCode,hMenuMainMem; + + LPDRAWITEMSTRUCT lpdis; + LPMEASUREITEMSTRUCT lpmis; + TEXTMETRIC tm; + HDC hDC; + HFONT hFont; + INT i; + + switch (message) + { + case WM_INITDIALOG: + _ASSERT(hWnd); + EnableMenuItem(GetMenu(hWnd),ID_TOOL_DEBUG,MF_GRAYED); + CheckMenuItem(GetMenu(hDlg),ID_BREAKPOINTS_NOP3,bDbgNOP3 ? MF_CHECKED : MF_UNCHECKED); + hDlgDebug = hDlg; // handle for debugger dialog + // 13.12.99 cg, changed, save handle of base menus + hMenuMainCode = LoadMenu(hApp,MAKEINTRESOURCE(IDR_DEBUG_CODE)); + _ASSERT(hMenuMainCode); + hMenuCode = GetSubMenu(hMenuMainCode, 0); + _ASSERT(hMenuCode); + hMenuMainMem = LoadMenu(hApp,MAKEINTRESOURCE(IDR_DEBUG_MEM)); + _ASSERT(hMenuMainMem); + hMenuMem = GetSubMenu(hMenuMainMem, 0); + _ASSERT(hMenuMem); + // 13.12.99 cg, end of changed part + hEventDebug = CreateEvent(NULL,FALSE,FALSE,NULL); + if (hEventDebug == NULL) + { + AbortMessage("Event creation failed !"); + return TRUE; + } + + // font settings + SendDlgItemMessage(hDlg,IDC_STATIC_CODE, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDC_STATIC_REGISTERS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDC_STATIC_MEMORY, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDC_STATIC_STACK, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + + bDbgEnable = TRUE; // debugger active + nDbgState = DBG_STEPINTO; // 13.11.99 cg, changed, state "step into" + if (Chipset.Shutdn) // cpu thread stopped + SetEvent(hEventShutdn); // goto debug session + + OldChipset = Chipset; // 10.11.99 cg, new, save chipset values + return TRUE; + + case WM_DESTROY: + // SetHP48Time(); // update HP48 time & date + hDlgDebug = NULL; // debugger windows closed + bDbgEnable = FALSE; // debugger inactive + nDbgState = DBG_RUN; // 13.11.99 cg, changed, state of debugger + bInterrupt = TRUE; // exit opcode loop + SetEvent(hEventDebug); + CloseHandle(hEventDebug); + DestroyMenu(hMenuMainCode); // 13.12.99 cg, bugfix, used wrong handle + DestroyMenu(hMenuMainMem); // 13.12.99 cg, bugfix, used wrong handle + _ASSERT(hWnd); + EnableMenuItem(GetMenu(hWnd),ID_TOOL_DEBUG,MF_ENABLED); + break; + + case WM_CLOSE: + DestroyWindow(hDlg); + break; + + case WM_UPDATE: + OnUpdate(hDlg); + return TRUE; + + case WM_COMMAND: + switch (HIWORD(wParam)) + { + case LBN_DBLCLK: + return OnDblClick((HWND) lParam, LOWORD(wParam)); + + case LBN_SETFOCUS: + i = SendMessage((HWND) lParam,LB_GETCARETINDEX,0,0); + SendMessage((HWND) lParam,LB_SETCURSEL,i,0); + return TRUE; + + case LBN_KILLFOCUS: + SendMessage((HWND) lParam,LB_SETCURSEL,-1,0); + return TRUE; + } + + switch (LOWORD(wParam)) + { + case ID_BREAKPOINTS_SETBREAK: return OnKeyF2(hDlg); + case ID_DEBUG_RUN: return OnKeyF5(hDlg); + case ID_DEBUG_STEP: return OnKeyF7(hDlg); + case ID_DEBUG_STEPOVER: return OnKeyF8(hDlg); + case ID_DEBUG_STEPOUT: return OnKeyF9(hDlg); + case ID_DEBUG_BREAK: return OnKeyF11(hDlg); + case ID_DEBUG_CODE_GOADR: return OnCodeGoAdr(hDlg); + case ID_DEBUG_CODE_GOPC: return OnCodeGoPC(hDlg); + case ID_DEBUG_CODE_SETPCTOSELECT: return OnCodeSetPcToSelection(hDlg); + case ID_BREAKPOINTS_CODEEDIT: return OnEditBreakpoint(hDlg); + // 13.12.99 cg, changed argument to dialog handle + case ID_BREAKPOINTS_CLEARALL: return OnClearAll(hDlg); + case ID_BREAKPOINTS_NOP3: return OnNOP3Break(hDlg); + case ID_DEBUG_MEM_GOADR: return OnMemGoAdr(hDlg); + case ID_DEBUG_MEM_GOPC: return OnMemGoDx(hDlg, Chipset.pc); + case ID_DEBUG_MEM_GOD0: return OnMemGoDx(hDlg, Chipset.d0); + case ID_DEBUG_MEM_GOD1: return OnMemGoDx(hDlg, Chipset.d1); + case ID_DEBUG_MEM_GOSTACK: return OnMemGoDx(hDlg, Chipset.rstk[(Chipset.rstkp-1)&7]); + } + break; + + case WM_VKEYTOITEM: + switch (LOWORD(wParam)) // always valid + { + case VK_F2: return OnKeyF2(hDlg); // toggle breakpoint + case VK_F5: return OnKeyF5(hDlg); // key run + case VK_F7: return OnKeyF7(hDlg); // key step into + case VK_F8: return OnKeyF8(hDlg); // key step over + case VK_F9: return OnKeyF9(hDlg); // key step out + case VK_F11: return OnKeyF11(hDlg); // key break + } + + switch(GetDlgCtrlID((HWND) lParam)) // calling window + { + // handle code window + case IDC_DEBUG_CODE: + // 13.12.99 cg, changed first argument to dialog handle + return OnKeyCodeWnd(hDlg, wParam); + + // handle memory window + case IDC_DEBUG_MEM_COL0: + case IDC_DEBUG_MEM_COL1: + case IDC_DEBUG_MEM_COL2: + case IDC_DEBUG_MEM_COL3: + case IDC_DEBUG_MEM_COL4: + case IDC_DEBUG_MEM_COL5: + case IDC_DEBUG_MEM_COL6: + case IDC_DEBUG_MEM_COL7: + switch (LOWORD(wParam)) + { + case 'G': return OnMemGoAdr(GetParent((HWND) lParam)); + case VK_RIGHT: + case VK_LEFT: return OnKeyRightLeft((HWND) lParam, wParam); + case VK_NEXT: + case VK_PRIOR: + case VK_DOWN: + case VK_UP: return OnKeyUpDown((HWND) lParam, wParam); + } + break; + } + return -1; // default action + + case WM_LBUTTONUP: + return OnLButtonUp(hDlg, lParam); + + case WM_CONTEXTMENU: + OnContextMenu(hDlg, lParam, wParam); + break; + + case WM_CTLCOLORSTATIC: // 10.11.99 cg, new, register color highlighting + // highlight text? + if (OnCtlColorStatic((HWND) lParam)) + { + SetTextColor((HDC) wParam, COLOR_RED); + SetBkColor((HDC) wParam, GetSysColor(COLOR_INACTIVECAPTIONTEXT)); + return (BOOL) GetStockObject(NULL_BRUSH); // transparent brush + } + break; + + case WM_DRAWITEM: + lpdis = (LPDRAWITEMSTRUCT)lParam; // get pointer to the DRAWITEMSTRUCT + if (wParam == IDC_DEBUG_CODE) return OnDrawCodeWnd(lpdis); + break; + + case WM_MEASUREITEM: + lpmis = (LPMEASUREITEMSTRUCT)lParam; // get pointer to the MEASUREITEMSTRUCT + + hDC = GetDC(hDlg); + + // GetTextMetrics from "Courier New 8" font + hFont = CreateFont(-MulDiv(8,GetDeviceCaps(hDC, LOGPIXELSY),72),0,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_DONTCARE,"Courier New"); + + hFont = SelectObject(hDC,hFont); + GetTextMetrics(hDC,&tm); + hFont = SelectObject(hDC,hFont); + DeleteObject(hFont); + + lpmis->itemHeight = tm.tmHeight; + lCharWidth = tm.tmAveCharWidth; + + ReleaseDC(hDlg,hDC); + return TRUE; + } + return FALSE; +} + +LRESULT OnToolDebug() // 06.08.99 cg, new, debugger dialogbox call +{ + if ((hDlgDebug = CreateDialog(hApp,MAKEINTRESOURCE(IDD_DEBUG),GetParent(hWnd), + (DLGPROC)Debugger)) == NULL) + AbortMessage("Debugger Dialog Box Creation Error !"); + + SetClassLong(hDlgDebug,GCL_HICON,(LONG) LoadIcon(hApp,MAKEINTRESOURCE(IDI_EMU48))); + return 0; +} + + +//################ +//# +//# New Value dialog box +//# +//################ + +// +// enter new value dialog +// +static BOOL CALLBACK NewValue(HWND hDlg, UINT message, DWORD wParam, LONG lParam) +{ + static LPSTR lpszBuffer; // handle of buffer + static int nBufferlen; // length of buffer + + LONG i; + + switch (message) + { + case WM_INITDIALOG: + lpszBuffer = (LPSTR) lParam; + nBufferlen = strlen(lpszBuffer)+1; // length with zero string terminator + SetDlgItemText(hDlg,IDC_NEWVALUE,lpszBuffer); + return TRUE; + case WM_COMMAND: + switch(wParam) + { + case IDOK: + GetDlgItemText(hDlg,IDC_NEWVALUE,lpszBuffer,nBufferlen); + // test if valid hex address + for (i = 0; i < (LONG) strlen(lpszBuffer); ++i) + { + if (isxdigit(lpszBuffer[i]) == FALSE) + { + SendDlgItemMessage(hDlg,IDC_NEWVALUE,EM_SETSEL,0,-1); + return FALSE; + } + } + // no break + case IDCANCEL: + EndDialog(hDlg, wParam); + return TRUE; + } + } + return FALSE; + UNREFERENCED_PARAMETER(wParam); +} + +static VOID OnNewValue(LPSTR lpszValue) +{ + if (DialogBoxParam(hApp, MAKEINTRESOURCE(IDD_NEWVALUE), hDlgDebug, (DLGPROC)NewValue, (LPARAM)lpszValue) == -1) + AbortMessage("Input Dialog Box Creation Error !"); +} + + +//################ +//# +//# Goto Address dialog box +//# +//################ + +// +// enter goto address dialog +// +static BOOL CALLBACK EnterAddr(HWND hDlg, UINT message, DWORD wParam, LONG lParam) +{ + static DWORD *dwAddress; + + char szBuffer[8]; + LONG i; + + switch (message) + { + case WM_INITDIALOG: + dwAddress = (DWORD *) lParam; + SetDlgItemText(hDlg,IDC_ENTERADR,""); + return TRUE; + case WM_COMMAND: + switch(wParam) + { + case IDOK: + GetDlgItemText(hDlg,IDC_ENTERADR,szBuffer,8); + // test if valid hex address + for (i = 0; i < (LONG) strlen(szBuffer); ++i) + { + if (isxdigit(szBuffer[i]) == FALSE) + { + SendDlgItemMessage(hDlg,IDC_ENTERADR,EM_SETSEL,0,-1); + return FALSE; + } + } + if (*szBuffer) sscanf(szBuffer,"%5X",dwAddress); + // no break + case IDCANCEL: + EndDialog(hDlg, wParam); + return TRUE; + } + } + return FALSE; + UNREFERENCED_PARAMETER(wParam); +} + +static VOID OnEnterAddress(HWND hDlg, DWORD *dwValue) +{ + if (DialogBoxParam(hApp, MAKEINTRESOURCE(IDD_ENTERADR), hDlg, (DLGPROC)EnterAddr, (LPARAM)dwValue) == -1) + AbortMessage("Address Dialog Box Creation Error !"); +} + + +//################ +//# +//# Edit breakpoint dialog box +//# +//################ + +// +// enter edit breakpoint dialog +// +static BOOL CALLBACK EditBreakpoint(HWND hDlg, UINT message, DWORD wParam, LONG lParam) +{ + char szBuffer[32]; + DWORD dwAddress; + INT i; + + HWND hWnd = GetDlgItem(hDlg,IDC_BREAKEDIT_WND); + + switch (message) + { + case WM_INITDIALOG: + // font settings + SendDlgItemMessage(hDlg,IDC_STATIC_BREAKPOINT,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDC_BREAKEDIT_ADD, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDC_BREAKEDIT_DELETE, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDOK, WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + + SendMessage(hWnd,WM_SETREDRAW,FALSE,0); + SendMessage(hWnd,LB_RESETCONTENT,0,0); + for (i = 0; i < wBreakpointCount; ++i) + { + wsprintf(szBuffer,"%05X (Code)",dwBreakpoint[i]); + SendMessage(hWnd,LB_ADDSTRING,0,(LPARAM) szBuffer); + } + SendMessage(hWnd,WM_SETREDRAW,TRUE,0); + return TRUE; + case WM_COMMAND: + switch(wParam) + { + case IDC_BREAKEDIT_ADD: + dwAddress = -1; // no address given + OnEnterAddress(hDlg, &dwAddress); + if (dwAddress != -1) + { + for (i = 0; i < wBreakpointCount; ++i) + { + if (dwBreakpoint[i] == dwAddress) + return FALSE; + } + + wsprintf(szBuffer,"%05X (Code)",dwAddress); + SendMessage(hWnd,LB_ADDSTRING,0,(LPARAM) szBuffer); + + dwBreakpoint[wBreakpointCount] = dwAddress; + ++wBreakpointCount; + } + return TRUE; + case IDC_BREAKEDIT_DELETE: + if ((i = SendMessage(hWnd,LB_GETCURSEL,0,0)) == LB_ERR) + return FALSE; + + SendMessage(hWnd,LB_GETTEXT,i,(LPARAM) szBuffer); + SendMessage(hWnd,LB_DELETESTRING,i,0); + + sscanf(szBuffer,"%X",&dwAddress); + for (i = 0; i < wBreakpointCount; ++i) + { + if (dwBreakpoint[i] == dwAddress) + { + // move rest to top + for (++i; i < wBreakpointCount; ++i) + dwBreakpoint[i-1] = dwBreakpoint[i]; + + --wBreakpointCount; + break; + } + } + return TRUE; + case IDOK: + case IDCANCEL: + EndDialog(hDlg, wParam); + return TRUE; + } + } + return FALSE; + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); +} + +static BOOL OnEditBreakpoint(HWND hDlg) +{ + if (DialogBox(hApp, MAKEINTRESOURCE(IDD_BREAKEDIT), hDlg, (DLGPROC)EditBreakpoint) == -1) + AbortMessage("Edit Breakpoint Dialog Box Creation Error !"); + + UpdateCodeWnd(hDlg); // update code window + return -1; +} diff --git a/sources/Emu48/DEBUGGER.H b/sources/Emu48/DEBUGGER.H new file mode 100644 index 0000000..b20648f --- /dev/null +++ b/sources/Emu48/DEBUGGER.H @@ -0,0 +1,31 @@ +/* + * debugger.h + * + * This file is part of Emu48 + * + * Copyright (C) 1999 Christoph Gießelink + * + */ + +// #define BP_EXEC 1 // code breakpoint +// #define BP_READ 2 // read memory breakpoint +// #define BP_WRITE 4 // write memory breakpoint +// #define BP_RANGE 8 // check address range + +// 13.11.99 cg, new, debugger state definitions +#define DBG_RUN 0 +#define DBG_STEPINTO 1 +#define DBG_STEPOVER 2 +#define DBG_STEPOUT 3 + +// debugger.c +extern HWND hDlgDebug; +extern HANDLE hEventDebug; +extern BOOL bDbgEnable; +extern INT nDbgState; // 13.11.99 cg, state of debugger +extern BOOL bDbgNOP3; +extern DWORD dwDbgRstkp; +extern DWORD dwDbgRstk; // 13.11.99 cg, possible return address +extern BOOL CheckBreakpoint(DWORD dwAddr); +extern VOID NotifyDebugger(VOID); // 10.11.99 cg, notify debugger emulation stopped +extern LRESULT OnToolDebug(VOID); diff --git a/sources/Emu48/DISASM.C b/sources/Emu48/DISASM.C index 1cada8e..a1e9d72 100644 --- a/sources/Emu48/DISASM.C +++ b/sources/Emu48/DISASM.C @@ -215,8 +215,6 @@ static char *hst_bits[8] = // static functions -// 10.11.98 cg, added new mapping functions - static BYTE rn_map (DWORD *p) { DWORD d = *p; @@ -259,12 +257,24 @@ static BYTE rn_port1 (DWORD *p) static BYTE rn_port2 (DWORD *p) { + BYTE *pbyVal; DWORD d = *p; - *p = ++(*p) & (((dwPort2Mask + 1) << 17) - 1); + if (cCurrentRomType=='X') // HP49G + { + *p = ++(*p) & (Chipset.Port2Size * 2048 - 1); - _ASSERT(d < ((dwPort2Mask + 1) << 17)); - return *(pbyPort2 + d); + _ASSERT(d < Chipset.Port2Size * 2048); + pbyVal = Chipset.Port2; + } + else // HP48SX/GX + { + *p = ++(*p) & (((dwPort2Mask + 1) << 18) - 1); + + _ASSERT(d < ((dwPort2Mask + 1) << 18)); + pbyVal = pbyPort2; + } + return *(pbyVal + d); } static BYTE read_nibble (DWORD *p) @@ -324,13 +334,11 @@ static char *append_imm_nibble (char *buf, DWORD *addr, int n) if (n > 1) *buf++ = '$'; } - // 01.12.98 cg, bugfix, add hex header for hex numbers else // HP Mnemonics { if (n > 1) // hex mode *buf++ = '#'; // insert hex header } - // 01.12.98 cg, end of bugfix if (n > 1) { for (i = 0; i < n; i++) @@ -408,31 +416,40 @@ static char *append_r_addr (char *buf, DWORD * pc, long disp, int n, int offset) return buf; } -static char *append_pc_comment (char *buf, DWORD pc) +static char *append_pc_comment (char *buf, DWORD pc, BOOL view) { char *p = buf; - while (strlen (buf) < 4 * TAB_SKIP) - p = append_tab (buf); - - switch (disassembler_mode) + if (view == VIEW_LONG) // output of address in remarks { - case HP_MNEMONICS: - p = append_str (p, "# Address: "); - p = append_addr (p, pc); + while (strlen (buf) < 4 * TAB_SKIP) + p = append_tab (buf); + + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (p, "# Address: "); + p = append_addr (p, pc); + break; + case CLASS_MNEMONICS: + p = append_str (p, "; address: "); + p = append_addr (p, pc); + break; + default: + p = append_str (p, "Unknown disassembler mode"); break; - case CLASS_MNEMONICS: - p = append_str (p, "; address: "); - p = append_addr (p, pc); - break; - default: - p = append_str (p, "Unknown disassembler mode"); - break; + } + } + else // output of address in brackets + { + while (*p) ++p; + p = append_str (p, " ["); + p = append_addr (p, pc); + p = append_str (p, "]"); } return p; } - static char *append_hst_bits (char *buf, int n) { int i; @@ -444,8 +461,6 @@ static char *append_hst_bits (char *buf, int n) for (i = 0; i < 4; i++) if (n & (1 << i)) { - if (p != buf) - p = append_str (p, "="); p = append_str (p, hst_bits[i + 4 * disassembler_mode]); } break; @@ -739,7 +754,7 @@ static char *disasm_1 (DWORD *addr, char *out) return p; } -static char *disasm_8 (DWORD *addr, char *out) +static char *disasm_8 (DWORD *addr, char *out, BOOL view) { BYTE n; BYTE fn; @@ -864,7 +879,7 @@ static char *disasm_8 (DWORD *addr, char *out) { p = append_str (p, ", GOYES "); p = append_r_addr (p, &pc, disp, 2, 5); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); } else p = append_str (p, ", RTNYES"); @@ -880,7 +895,7 @@ static char *disasm_8 (DWORD *addr, char *out) { p = append_str (p, ", "); p = append_r_addr (p, &pc, disp, 2, 5); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); } break; default: @@ -1130,8 +1145,19 @@ static char *disasm_8 (DWORD *addr, char *out) } else { - p = append_hst_bits (out, n); - p = append_str (p, "=0"); + // when not only one bit is set the HS=0 opcode is used + if (n != 1 && n != 2 && n != 4 && n != 8) + { + p = append_str (out, "HS=0"); + p = append_tab (out); + wsprintf (buf, "%d", n); + p = append_str (p, buf); + } + else + { + p = append_hst_bits (out, n); + p = append_str (p, "=0"); + } } break; case CLASS_MNEMONICS: @@ -1162,7 +1188,7 @@ static char *disasm_8 (DWORD *addr, char *out) { p = append_str (p, "GOYES "); p = append_r_addr (p, &pc, disp, 2, 3); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); } else p = append_str (p, "RTNYES"); @@ -1177,7 +1203,7 @@ static char *disasm_8 (DWORD *addr, char *out) { p = append_str (p, ", "); p = append_r_addr (p, &pc, disp, 2, 3); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); } p = append_hst_bits (out, n); break; @@ -1226,7 +1252,7 @@ static char *disasm_8 (DWORD *addr, char *out) { p = append_str (p, ", GOYES "); p = append_r_addr (p, &pc, disp, 2, 3); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); } else p = append_str (p, ", RTNYES"); @@ -1241,7 +1267,7 @@ static char *disasm_8 (DWORD *addr, char *out) { p = append_str (p, ", "); p = append_r_addr (p, &pc, disp, 2, 3); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); } break; default: @@ -1267,7 +1293,7 @@ static char *disasm_8 (DWORD *addr, char *out) { p = append_str (p, ", GOYES "); p = append_r_addr (p, &pc, disp, 2, 3); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); } else p = append_str (p, ", RTNYES"); @@ -1282,7 +1308,7 @@ static char *disasm_8 (DWORD *addr, char *out) { p = append_str (p, ", "); p = append_r_addr (p, &pc, disp, 2, 3); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); } break; default: @@ -1303,13 +1329,13 @@ static char *disasm_8 (DWORD *addr, char *out) p = append_str (out, (fn == 0xc) ? "GOLONG" : "GOSUBL"); p = append_tab (out); p = append_r_addr (p, &pc, disp, 4, (fn == 0xc) ? 2 : 6); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); break; case CLASS_MNEMONICS: p = append_str (out, (fn == 0xc) ? "bra.4" : "bsr.4"); p = append_tab (out); p = append_r_addr (p, &pc, disp, 4, (fn == 0xc) ? 2 : 6); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); break; default: p = append_str (out, "Unknown disassembler mode"); @@ -1347,7 +1373,7 @@ static char *disasm_8 (DWORD *addr, char *out) // public functions -DWORD disassemble (DWORD addr, LPSTR out) +DWORD disassemble (DWORD addr, LPSTR out, BOOL view) { BYTE n; BYTE fn; @@ -1396,12 +1422,10 @@ DWORD disassemble (DWORD addr, LPSTR out) switch (disassembler_mode) { case HP_MNEMONICS: - // 21.01.99 cg, changed output format p = append_str (out, "P="); p = append_tab (out); wsprintf (buf, "%d", n); p = append_str (p, buf); - // 21.01.99 cg, end of changed output format break; case CLASS_MNEMONICS: wsprintf (buf, "move.1 #%d, p", n); @@ -1462,7 +1486,7 @@ DWORD disassemble (DWORD addr, LPSTR out) { p = append_tab (out); p = append_r_addr (p, &pc, disp, 2, 1); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); } break; @@ -1478,7 +1502,7 @@ DWORD disassemble (DWORD addr, LPSTR out) { p = append_tab (out); p = append_r_addr (p, &pc, disp, 2, 1); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); } break; @@ -1507,7 +1531,7 @@ DWORD disassemble (DWORD addr, LPSTR out) p = append_str (out, "GOTO"); p = append_tab (out); p = append_r_addr (p, &pc, disp, 3, 1); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); break; case CLASS_MNEMONICS: @@ -1524,7 +1548,7 @@ DWORD disassemble (DWORD addr, LPSTR out) p = append_str (out, "bra.3"); p = append_tab (out); p = append_r_addr (p, &pc, disp, 3, 1); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); break; default: @@ -1542,14 +1566,14 @@ DWORD disassemble (DWORD addr, LPSTR out) p = append_str (out, "GOSUB"); p = append_tab (out); p = append_r_addr (p, &pc, disp, 3, 4); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); break; case CLASS_MNEMONICS: p = append_str (out, "bsr.3"); p = append_tab (out); p = append_r_addr (p, &pc, disp, 3, 4); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); break; default: @@ -1563,7 +1587,7 @@ DWORD disassemble (DWORD addr, LPSTR out) --addr; if (fn != 0xa && fn != 0xb) { - p = disasm_8 (&addr, out); + p = disasm_8 (&addr, out, view); break; } /* Fall through */ @@ -1602,7 +1626,7 @@ DWORD disassemble (DWORD addr, LPSTR out) if (disp != 0) { p = append_r_addr (p, &pc, disp, 2, 3); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); } break; @@ -1619,7 +1643,7 @@ DWORD disassemble (DWORD addr, LPSTR out) { p = append_str (p, ", "); p = append_r_addr (p, &pc, disp, 2, 3); - p = append_pc_comment (out, pc); + p = append_pc_comment (out, pc, view); } break; diff --git a/sources/Emu48/DISPLAY.C b/sources/Emu48/DISPLAY.C index 3b887b7..9dae547 100644 --- a/sources/Emu48/DISPLAY.C +++ b/sources/Emu48/DISPLAY.C @@ -13,7 +13,7 @@ #define LCD1_ROW 144 #define LCD2_ROW 288 -#define LCD3_ROW 576 // 24.08.98 cg, new, X4 display +#define LCD3_ROW 576 UINT nBackgroundX = 0; UINT nBackgroundY = 0; @@ -21,10 +21,10 @@ UINT nBackgroundW = 0; UINT nBackgroundH = 0; UINT nLcdX = 0; UINT nLcdY = 0; -UINT nLcdDoubled = 1; // 24.08.98 cg, changed to integer var +UINT nLcdDoubled = 1; LPBYTE pbyLcd; -HDC hLcdDC = NULL; // 22.01.98 cg, new, for security only -HDC hMainDC = NULL; // 22.01.98 cg, new, for security only +HDC hLcdDC = NULL; +HDC hMainDC = NULL; static HBITMAP hLcdBitmap; static HBITMAP hMainBitmap; static HBITMAP hOldLcdBitmap; @@ -51,12 +51,9 @@ static struct #undef W #undef I -static DWORD Pattern[16]; // 29.01.99 cg, new, use only one pattern -// static DWORD Pattern4[16]; -// static DWORD Pattern2[4]; -// static DWORD Pattern1[2]; // 24.08.98 cg, new, pattern for X4 +static DWORD Pattern[16]; -VOID UpdateContrast(BYTE byContrast) // 23.02.99 cg, changed, new implementation +VOID UpdateContrast(BYTE byContrast) { DWORD c = byContrast; DWORD b = byContrast + 0x20; @@ -101,8 +98,6 @@ VOID UpdateContrast(BYTE byContrast) // 23.02.99 cg, changed, new implementatio VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue) { - // 25.01.08 cg, bugfix, wrong bit position of red and blue - // 23.02.99 cg, changed, allow 64 colors now bmiLcd.dwColor[nId&0x3F] = ((nRed&0xFF)<<16)|((nGreen&0xFF)<<8)|(nBlue&0xFF); return; } @@ -110,21 +105,19 @@ VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue) VOID CreateLcdBitmap() { // create LCD bitmap - // 24.08.98 cg, changed implementation _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); bmiLcd.Lcd_bmih.biWidth = LCD1_ROW * nLcdDoubled; bmiLcd.Lcd_bmih.biHeight = -64 * nLcdDoubled; - // 24.08.98 cg, end of changed implementation hLcdDC = CreateCompatibleDC(hWindowDC); hLcdBitmap = CreateDIBSection(hLcdDC, (BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS, (LPVOID*)&pbyLcd, NULL, 0); hOldLcdBitmap = SelectObject(hLcdDC, hLcdBitmap); - UpdateContrast(Chipset.contrast); // 23.01.98 cg, bugfix, use saved contrast + UpdateContrast(Chipset.contrast); } VOID DestroyLcdBitmap() { WORD i; - // 23.02.99 cg, new, clear background colors + // clear background colors for (i=32; i< 64; ++i) bmiLcd.dwColor[i] = 0xFFFFFFFF; if (hLcdDC != NULL) @@ -177,14 +170,14 @@ VOID DestroyMainBitmap() VOID UpdateDisplayPointers() { - // 09.09.98 cg, bugfix, calculate display width + // calculate display width Chipset.width = (34 + Chipset.loffset + (Chipset.boffset / 4) * 2) & 0xFFFFFFFE; Chipset.end1 = Chipset.start1 + (Chipset.lcounter + 1) * Chipset.width; if (Chipset.end1 < Chipset.start1) { - // 09.09.98 cg, bugfix, calculate first address of main display + // calculate first address of main display Chipset.start12 = Chipset.end1 - Chipset.width; - // 09.09.98 cg, bugfix, calculate last address of main display + // calculate last address of main display Chipset.end1 = Chipset.start1 - Chipset.width; } else @@ -197,7 +190,7 @@ VOID UpdateDisplayPointers() static BYTE Buf[36]; static BOOL bScreenIsClean = FALSE; -VOID UpdateMainDisplay() // 29.04.98 cg, bugfix, update display even if it's off +VOID UpdateMainDisplay() { UINT x, y; INT nLines; @@ -210,16 +203,13 @@ VOID UpdateMainDisplay() // 29.04.98 cg, bugfix, update display even if it's if (!bScreenIsClean) { bScreenIsClean = TRUE; - // 24.08.98 cg, changed parameter - // 05.01.99 cg, bugfix, with Zoom > 1 only a part of the display was cleared - FillMemory(pbyLcd, LCD1_ROW * nLcdDoubled * nLines * nLcdDoubled, 0); + ZeroMemory(pbyLcd, LCD1_ROW * nLcdDoubled * nLines * nLcdDoubled); } } else { nLines = Chipset.lcounter + 1; bScreenIsClean = FALSE; - // 24.08.98 cg, new, new part for X4 _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); if (nLcdDoubled == 4) { @@ -240,8 +230,7 @@ VOID UpdateMainDisplay() // 29.04.98 cg, bugfix, update display even if it's d+=Chipset.width; } } - // 24.08.98 cg, end of new part - if (nLcdDoubled == 2) // 24.08.98 cg, new var type + if (nLcdDoubled == 2) { for (y=0; y<=Chipset.lcounter; y++) { @@ -256,7 +245,7 @@ VOID UpdateMainDisplay() // 29.04.98 cg, bugfix, update display even if it's d+=Chipset.width; } } - if (nLcdDoubled == 1) // 24.08.98 cg, new var type + if (nLcdDoubled == 1) { for (y=0; y<=Chipset.lcounter; y++) { @@ -266,13 +255,12 @@ VOID UpdateMainDisplay() // 29.04.98 cg, bugfix, update display even if it's } } } - EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems + EnterCriticalSection(&csGDILock); // solving NT GDI problems { - // 24.08.98 cg, use of new var type BitBlt(hWindowDC, nLcdX, nLcdY, 131*nLcdDoubled, nLines*nLcdDoubled, hLcdDC, Chipset.boffset*nLcdDoubled, 0, SRCCOPY); - GdiFlush(); // 22.01.98 cg + GdiFlush(); } - LeaveCriticalSection(&csGDILock); // 22.01.98 cg + LeaveCriticalSection(&csGDILock); return; } @@ -284,15 +272,14 @@ VOID UpdateMenuDisplay() if (!Chipset.dispon) return; if (Chipset.lcounter==0x3F) return; // menu disabled - // 24.08.98 cg, new, new part for X4 _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); - // 18.01.99 cg, calculate offset once + // calculate offset once p = pbyLcd + ((Chipset.lcounter+1)*nLcdDoubled*LCD1_ROW*nLcdDoubled); if (nLcdDoubled == 4) { for (y=Chipset.lcounter+1; y<64; y++) { - Npeek(Buf,d,34); // 01.02.99 cg, only 34 nibbles are viewed + Npeek(Buf,d,34); // 34 nibbles are viewed for (x=0; x<36; x++) { *(((DWORD*)p)++)=Pattern[Buf[x]&1]; @@ -307,12 +294,11 @@ VOID UpdateMenuDisplay() d+=34; } } - // 24.08.98 cg, end of new part - if (nLcdDoubled == 2) // 24.08.98 cg, new var type + if (nLcdDoubled == 2) { for (y=Chipset.lcounter+1; y<64; y++) { - Npeek(Buf,d,34); // 01.02.99 cg, only 34 nibbles are viewed + Npeek(Buf,d,34); // 34 nibbles are viewed for (x=0; x<36; x++) { *(((DWORD*)p)++)=Pattern[Buf[x]&3]; @@ -323,31 +309,28 @@ VOID UpdateMenuDisplay() d+=34; } } - if (nLcdDoubled == 1) // 24.08.98 cg, new var type + if (nLcdDoubled == 1) { for (y=Chipset.lcounter+1; y<64; y++) { - Npeek(Buf,d,34); // 01.02.99 cg, only 34 nibbles are viewed + Npeek(Buf,d,34); // 34 nibbles are viewed for (x=0; x<36; x++) *(((DWORD*)p)++)=Pattern[Buf[x]]; d+=34; } } - EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems + EnterCriticalSection(&csGDILock); // solving NT GDI problems { - // 18.01.99 cg, use common output BitBlt(hWindowDC, nLcdX, nLcdY+(Chipset.lcounter+1)*nLcdDoubled, 131*nLcdDoubled, (63-Chipset.lcounter)*nLcdDoubled, hLcdDC, 0, (Chipset.lcounter+1)*nLcdDoubled, SRCCOPY); - GdiFlush(); // 22.01.98 cg + GdiFlush(); } - LeaveCriticalSection(&csGDILock); // 22.01.98 cg + LeaveCriticalSection(&csGDILock); return; } VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s) { - // 09.09.98 cg, new bugfixed implementation - // 09.03.99 cg, removed calculated corresponding source memory address INT x0, x; INT y0, y; DWORD *p; @@ -441,141 +424,6 @@ VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s) GdiFlush(); } LeaveCriticalSection(&csGDILock); - -#if 0 - // 09.09.98 cg, removed - UINT x0, x; - UINT y0, y; - DWORD *p; - - if (Chipset.width<0) return; - d -= Chipset.start1; - y0 = y = d / Chipset.width; - x0 = x = d % Chipset.width; - // 05.03.98 cg, bugfix, cut right border later - // if ((x0*4+Chipset.boffset)>=131) return; - // 24.08.98 cg, new, new part for X4 - _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); - if (nLcdDoubled == 4) - { - p = (DWORD*)(pbyLcd + y0*LCD3_ROW*4 + x0*16); - while (s--) - { - if (x<36) - { - p[432] = p[288] = p[144] = p[0] = Pattern1[(*a)&1]; - p[433] = p[289] = p[145] = p[1] = Pattern1[((*a)>>1) &1]; - p[434] = p[290] = p[146] = p[2] = Pattern1[((*a)>>2) &1]; - p[435] = p[291] = p[147] = p[3] = Pattern1[((*a)>>3) &1]; - } - a++; - x++; - if ((x==(UINT)Chipset.width)&&s) - { - x=0; - y++; - if (y==(Chipset.lcounter+1)) break; - p=(DWORD*)(pbyLcd+y*LCD3_ROW*4); - } else p+=4; - } - EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems - { - if (y0!=y) - { - y+=3; - y0<<=2; y<<=2; - BitBlt(hWindowDC, nLcdX, nLcdY+y0, 524, y-y0, hLcdDC, Chipset.boffset*4, y0, SRCCOPY); - } - else - { - if (x0>0) --x0; // 09.03.98 cg, bugfix, draw left nibble - x0<<=4; x<<=4; - if (x0>524) x0=524; // 05.03.98 cg, bugfix, cut right border - if (x >524) x =524; - y0<<=2; // y<<=1; // 09.03.98 cg, removed - BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, 4, hLcdDC, x0+Chipset.boffset*4, y0, SRCCOPY); - } - GdiFlush(); // 22.01.98 cg - } - LeaveCriticalSection(&csGDILock); // 22.01.98 cg - } - // 24.08.98 cg, end of new part - if (nLcdDoubled == 2) // 24.08.98 cg, new var type - { - p = (DWORD*)(pbyLcd + y0*LCD2_ROW*2 + x0*8); - while (s--) - { - if (x<36) - { - p[72] = p[0] = Pattern2[(*a)&3]; - p[73] = p[1] = Pattern2[(*a)>>2]; - } - a++; - x++; - if ((x==(UINT)Chipset.width)&&s) - { - x=0; - y++; - if (y==(Chipset.lcounter+1)) break; - p=(DWORD*)(pbyLcd+y*LCD2_ROW*2); - } else p+=2; - } - EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems - { - if (y0!=y) - { - y++; - y0<<=1; y<<=1; - BitBlt(hWindowDC, nLcdX, nLcdY+y0, 262, y-y0, hLcdDC, Chipset.boffset*2, y0, SRCCOPY); - } - else - { - if (x0>0) --x0; // 09.03.98 cg, bugfix, draw left nibble - x0<<=3; x<<=3; - if (x0>262) x0=262; // 05.03.98 cg, bugfix, cut right border - if (x >262) x =262; - y0<<=1; // y<<=1; // 09.03.98 cg, removed - BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, 2, hLcdDC, x0+Chipset.boffset*2, y0, SRCCOPY); - } - GdiFlush(); // 22.01.98 cg - } - LeaveCriticalSection(&csGDILock); // 22.01.98 cg - } - if (nLcdDoubled == 1) // 24.08.98 cg, new var type - { - p = (DWORD*)(pbyLcd + y0*LCD1_ROW + x0*4); - while (s--) - { - if (x<36) *p = Pattern4[*a]; - a++; - x++; - if ((x==(UINT)Chipset.width)&&s) - { - x=0; - y++; - if (y==(Chipset.lcounter+1)) break; - p=(DWORD*)(pbyLcd+y*LCD1_ROW); - } else p++; - } - EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems - { - if (y0!=y) - { - BitBlt(hWindowDC, nLcdX, nLcdY+y0, 131, y-y0+1, hLcdDC, Chipset.boffset, y0, SRCCOPY); - } - else - { - if (x0>0) --x0; // 09.03.98 cg, bugfix, draw left nibble - x0<<=2; x<<=2; - if (x0>131) x0=131; // 05.03.98 cg, bugfix, cut right border - if (x >131) x=131; - BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, 1, hLcdDC, x0+Chipset.boffset, y0, SRCCOPY); - } - GdiFlush(); // 22.01.98 cg - } - LeaveCriticalSection(&csGDILock); // 22.01.98 cg - } -#endif return; } @@ -585,13 +433,11 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s) UINT y0, y; DWORD *p; - // if (Chipset.width<0) return; // 09.09.98 cg, bugfix, allow menu update if (Chipset.lcounter==0x3F) return; // menu disabled d -= Chipset.start2; y0 = y = (d / 34) + (Chipset.lcounter+1); x0 = x = d % 34; - if (x0 > 32) return; // 01.02.99 cg, changed, position out of viewed area - // 24.08.98 cg, new, new part for X4 + if (x0 > 32) return; // position out of viewed area _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); if (nLcdDoubled == 4) { @@ -615,7 +461,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s) p=(DWORD*)(pbyLcd+y*LCD3_ROW*4); } else p+=4; } - EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems + EnterCriticalSection(&csGDILock); // solving NT GDI problems { if (y0!=y) { @@ -629,12 +475,11 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s) if (x>524) x=524; BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, y-y0+4, hLcdDC, x0, y0, SRCCOPY); } - GdiFlush(); // 22.01.98 cg + GdiFlush(); } - LeaveCriticalSection(&csGDILock); // 22.01.98 cg + LeaveCriticalSection(&csGDILock); } - // 24.08.98 cg, new, new part for X4 - if (nLcdDoubled == 2) // 24.08.98 cg, new var type + if (nLcdDoubled == 2) { p = (DWORD*)(pbyLcd + y0*LCD2_ROW*2 + x0*8); while (s--) @@ -654,7 +499,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s) p=(DWORD*)(pbyLcd+y*LCD2_ROW*2); } else p+=2; } - EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems + EnterCriticalSection(&csGDILock); // solving NT GDI problems { if (y0!=y) { @@ -668,11 +513,11 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s) if (x>262) x=262; BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, y-y0+2, hLcdDC, x0, y0, SRCCOPY); } - GdiFlush(); // 22.01.98 cg + GdiFlush(); } - LeaveCriticalSection(&csGDILock); // 22.01.98 cg + LeaveCriticalSection(&csGDILock); } - if (nLcdDoubled == 1) // 24.08.98 cg, new var type + if (nLcdDoubled == 1) { p = (DWORD*)(pbyLcd + y0*LCD1_ROW + x0*4); while (s--) @@ -688,7 +533,7 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s) p=(DWORD*)(pbyLcd+y*LCD1_ROW); } else p++; } - EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems + EnterCriticalSection(&csGDILock); // solving NT GDI problems { if (y0!=y) { @@ -700,9 +545,9 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s) if (x>131) x=131; BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, y-y0+1, hLcdDC, x0, y0, SRCCOPY); } - GdiFlush(); // 22.01.98 cg + GdiFlush(); } - LeaveCriticalSection(&csGDILock); // 22.01.98 cg + LeaveCriticalSection(&csGDILock); } return; } @@ -727,7 +572,7 @@ VOID ResizeWindow() RECT rectWindow; RECT rectClient; - if (hWnd == NULL) return; // 30.01.98 cg, bugfix, return if window closed + if (hWnd == NULL) return; // return if window closed rectWindow.left = 0; rectWindow.top = 0; diff --git a/sources/Emu48/EMU48.C b/sources/Emu48/EMU48.C index 7de057f..c6f05fb 100644 --- a/sources/Emu48/EMU48.C +++ b/sources/Emu48/EMU48.C @@ -10,31 +10,25 @@ #include "resource.h" #include "Emu48.h" #include "kml.h" +#include "debugger.h" -#define VERSION "1.10" // 05.02.99 cg, version changed -#define EMU48_INI "Emu48.ini" -#define CF_HPOBJ "CF_HPOBJ" // 13.05.98 cg, clipboard format for DDE +#define VERSION "1.15" // 23.10.99 cg, changed version +#define CF_HPOBJ "CF_HPOBJ" // clipboard format for DDE -#define MAXPORTS 16 // 20.05.98 cg, number of COM ports +#define MAXPORTS 16 // number of COM ports -// 30.05.98 cg, new, cards status -#define PORT1_PRESENT ((cCurrentRomType=='S')?0x1:0x2) -#define PORT1_WRITE ((cCurrentRomType=='S')?0x4:0x8) -#define PORT2_PRESENT ((cCurrentRomType=='S')?0x2:0x1) -#define PORT2_WRITE ((cCurrentRomType=='S')?0x8:0x4) - -// #define MONOCHROME // 27.01.99 cg, CF_BITMAP clipboard format +// #define MONOCHROME // CF_BITMAP clipboard format #ifdef _DEBUG LPSTR szNoTitle = "Emu48 "VERSION" Debug"; #else -LPSTR szNoTitle = "Emu48 "VERSION; // 20.01.98 cg, changed +LPSTR szNoTitle = "Emu48 "VERSION; #endif -LPSTR szAppName = "Emu48"; // 13.05.98 cg, new, application name for DDE server -LPSTR szTopic = "Stack"; // 13.05.98 cg, new, topic for DDE server +LPSTR szAppName = "Emu48"; // application name for DDE server +LPSTR szTopic = "Stack"; // topic for DDE server LPSTR szTitle = NULL; -static const char szLicence[] = +static const char szLicence[] = // 30.11.99 cg, changed, update of address "This program is free software; you can redistribute it and/or modify\r\n" "it under the terms of the GNU General Public License as published by\r\n" "the Free Software Foundation; either version 2 of the License, or\r\n" @@ -46,31 +40,34 @@ static const char szLicence[] = "See the GNU General Public License for more details.\r\n" "\r\n" "You should have received a copy of the GNU General Public License\r\n" - "along with this program; if not, write to the Free Software\r\n" - "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA."; + "along with this program; if not, write to the Free Software Foundation,\r\n" + "Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"; -CRITICAL_SECTION csGDILock; // 22.01.98 cg, critical section for hWindowDC -CRITICAL_SECTION csKeyLock; // 02.09.98 cg, critical section for key scan -CRITICAL_SECTION csIOLock; // 24.02.99 cg, new, critical section for I/O access -CRITICAL_SECTION csT1Lock; // 21.04.98 cg, new, critical section for timer1 access -CRITICAL_SECTION csT2Lock; // 21.04.98 cg, new, critical section for timer2 access -LARGE_INTEGER lFreq; // 24.08.98 cg, new, counter frequency -DWORD idDdeInst; // 13.05.98 cg, DDE server id -UINT uCF_HpObj; // 13.05.98 cg, DDE clipboard format -HINSTANCE hApp = NULL; -HWND hWnd = NULL; -HDC hWindowDC = NULL; -HPALETTE hPalette = NULL; -HPALETTE hOldPalette = NULL; // 11.09.98 cg, new, old palette of hWindowDC +CRITICAL_SECTION csGDILock; // critical section for hWindowDC +CRITICAL_SECTION csKeyLock; // critical section for key scan +CRITICAL_SECTION csIOLock; // critical section for I/O access +CRITICAL_SECTION csT1Lock; // critical section for timer1 access +CRITICAL_SECTION csT2Lock; // critical section for timer2 access +CRITICAL_SECTION csRecvLock; // 24.10.99 cg, moved, critical section for receive byte +INT nArgc; // 08.11.99 cg, new, no. of command line arguments +LPCTSTR *ppArgv; // 08.11.99 cg, new, command line arguments +LARGE_INTEGER lFreq; // counter frequency +DWORD idDdeInst; // DDE server id +UINT uCF_HpObj; // DDE clipboard format HANDLE hThread; DWORD lThreadId; +HANDLE hEventShutdn; // event handle to stop cpu thread + +HINSTANCE hApp = NULL; +HWND hWnd = NULL; +HDC hWindowDC = NULL; +HPALETTE hPalette = NULL; +HPALETTE hOldPalette = NULL; // old palette of hWindowDC BOOL bAutoSave = FALSE; BOOL bAutoSaveOnExit = TRUE; BOOL bAlwaysDisplayLog = TRUE; -static BOOL bRealSpeed = FALSE; - //################ //# //# Window Status @@ -91,6 +88,7 @@ VOID SetWindowTitle(LPSTR szString) { szTitle = NULL; } + _ASSERT(hWnd != NULL); if (szTitle) { SetWindowText(hWnd, szTitle); @@ -106,28 +104,29 @@ VOID UpdateWindowStatus() { HMENU hMenu; - if (hWnd == NULL) return; // 30.01.98 cg, bugfix, return if window closed + if (hWnd == NULL) return; // return if window closed hMenu = GetMenu(hWnd); if ((nState == 0)||(nState == 3)) { - if (szCurrentFilename[0]) - EnableMenuItem(hMenu,ID_FILE_SAVE,MF_ENABLED); - else - EnableMenuItem(hMenu,ID_FILE_SAVE,MF_GRAYED); + // 02.12.99 cg, new, disable stack loading items on HP38G + UINT uStackEnable = (cCurrentRomType!='A') ? MF_ENABLED : MF_GRAYED; + + // 02.12.99 cg, changed implementation + EnableMenuItem(hMenu,ID_FILE_SAVE,(szCurrentFilename[0]) ? MF_ENABLED : MF_GRAYED); EnableMenuItem(hMenu,ID_FILE_SAVEAS,MF_ENABLED); EnableMenuItem(hMenu,ID_FILE_CLOSE,MF_ENABLED); EnableMenuItem(hMenu,ID_BACKUP_SAVE,MF_GRAYED); EnableMenuItem(hMenu,ID_BACKUP_SAVE,MF_ENABLED); EnableMenuItem(hMenu,ID_VIEW_COPY,MF_ENABLED); EnableMenuItem(hMenu,ID_VIEW_RESET,MF_ENABLED); - EnableMenuItem(hMenu,ID_OBJECT_LOAD,MF_ENABLED); - EnableMenuItem(hMenu,ID_OBJECT_SAVE,MF_ENABLED); - // 17.06.98 cg, new, enable menu entries - EnableMenuItem(hMenu,ID_STACK_COPY,MF_ENABLED); - EnableMenuItem(hMenu,ID_STACK_PASTE,MF_ENABLED); - // 10.11.98 cg, new, enable menu entries + // 02.12.99 cg, new, added HP38G part + EnableMenuItem(hMenu,ID_OBJECT_LOAD,uStackEnable); + EnableMenuItem(hMenu,ID_OBJECT_SAVE,uStackEnable); + EnableMenuItem(hMenu,ID_STACK_COPY,uStackEnable); + EnableMenuItem(hMenu,ID_STACK_PASTE,uStackEnable); + // 02.12.99 cg, end of added part EnableMenuItem(hMenu,ID_TOOL_DISASM,MF_ENABLED); } else @@ -140,10 +139,8 @@ VOID UpdateWindowStatus() EnableMenuItem(hMenu,ID_VIEW_RESET,MF_GRAYED); EnableMenuItem(hMenu,ID_OBJECT_LOAD,MF_GRAYED); EnableMenuItem(hMenu,ID_OBJECT_SAVE,MF_GRAYED); - // 17.06.98 cg, new, disable menu entries EnableMenuItem(hMenu,ID_STACK_COPY,MF_GRAYED); EnableMenuItem(hMenu,ID_STACK_PASTE,MF_GRAYED); - // 10.11.98 cg, new, enable menu entries EnableMenuItem(hMenu,ID_TOOL_DISASM,MF_GRAYED); } if (bBackup) @@ -167,14 +164,7 @@ VOID UpdateWindowStatus() //# //################ -static BOOL WritePrivateProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue, LPCTSTR lpszFilename) -{ - char s[16]; - wsprintf(s,"%i",nValue); - return WritePrivateProfileString(lpszSection, lpszEntry, s, lpszFilename); -} - -// 20.05.98 cg, new, set listfield for serial combobox +// set listfield for serial combobox static VOID SetCommList(HWND hDlg,int nIDDlgItem,char *szSetting) { HANDLE hComm; @@ -209,115 +199,78 @@ static VOID SetCommList(HWND hDlg,int nIDDlgItem,char *szSetting) SendDlgItemMessage(hDlg,nIDDlgItem,CB_SETCURSEL,wSelect,0L); } -static VOID ReadSettings() -{ - // Files - // 01.02.98 cg, calculate size of buffer - GetPrivateProfileString("Files","Emu48Directory",szCurrentDirectory,szEmu48Directory, - sizeof(szEmu48Directory),EMU48_INI); - bAutoSave = GetPrivateProfileInt("Files","AutoSave",bAutoSave,EMU48_INI); - bAutoSaveOnExit = GetPrivateProfileInt("Files","AutoSaveOnExit",bAutoSaveOnExit,EMU48_INI); - // Port2 - bPort2IsShared = GetPrivateProfileInt("Port2","IsShared",0,EMU48_INI); - // 01.02.98 cg, calculate size of buffer - GetPrivateProfileString("Port2","Filename","SHARED.BIN",szPort2Filename,sizeof(szPort2Filename),EMU48_INI); - // Timers - // 13.06.98 cg, changed default value from unset to set - // 10.11.98 cg, removed, not adjustable any more - // bAccurateTimer = GetPrivateProfileInt("Timers","AccurateTimer",1,EMU48_INI); - // uT1Period = GetPrivateProfileInt("Timers","T1Period",62,EMU48_INI); - // KML - bAlwaysDisplayLog = GetPrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI); - // 23.04.98 cg, new, Emulator - bRealSpeed = GetPrivateProfileInt("Emulator","RealSpeed",0,EMU48_INI); - dwSXCycles = GetPrivateProfileInt("Emulator","SXCycles",82,EMU48_INI); - dwGXCycles = GetPrivateProfileInt("Emulator","GXCycles",123,EMU48_INI); - SetSpeed(bRealSpeed); // 23.04.98 cg, set speed - // 20.05.98 cg, new, Serial - GetPrivateProfileString("Serial","Wire",NO_SERIAL,szSerialWire,sizeof(szSerialWire),EMU48_INI); - GetPrivateProfileString("Serial","Ir",NO_SERIAL,szSerialIr,sizeof(szSerialIr),EMU48_INI); - return; -} - -static VOID WriteSettings() -{ - // Files - WritePrivateProfileString("Files","Emu48Directory",szEmu48Directory,EMU48_INI); - WritePrivateProfileInt("Files","AutoSave",bAutoSave,EMU48_INI); - WritePrivateProfileInt("Files","AutoSaveOnExit",bAutoSaveOnExit,EMU48_INI); - // Port2 - WritePrivateProfileInt("Port2","IsShared",bPort2IsShared,EMU48_INI); - WritePrivateProfileString("Port2","Filename",szPort2Filename,EMU48_INI); - // Timers - // 10.11.98 cg, removed, not adjustable any more - // WritePrivateProfileInt("Timers","AccurateTimer",bAccurateTimer,EMU48_INI); - // WritePrivateProfileInt("Timers","T1Period",uT1Period,EMU48_INI); - // KML - WritePrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI); - // 23.04.98 cg, new, Emulator - WritePrivateProfileInt("Emulator","RealSpeed",bRealSpeed,EMU48_INI); - WritePrivateProfileInt("Emulator","SXCycles",dwSXCycles,EMU48_INI); - WritePrivateProfileInt("Emulator","GXCycles",dwGXCycles,EMU48_INI); - // 20.05.98 cg, new, Serial - WritePrivateProfileString("Serial","Wire",szSerialWire,EMU48_INI); - WritePrivateProfileString("Serial","Ir",szSerialIr,EMU48_INI); - return; -} - static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lParam) { switch (message) { case WM_INITDIALOG: - // 30.05.98 cg, new, init port1 enable checkbox - CheckDlgButton(hDlg,IDC_PORT1EN,(Chipset.cards_status & PORT1_PRESENT) != 0); - CheckDlgButton(hDlg,IDC_PORT1WR,Chipset.Port1_Writeable); - // 23.04.98 cg, new, init speed checkbox + // init speed checkbox CheckDlgButton(hDlg,IDC_REALSPEED,bRealSpeed); CheckDlgButton(hDlg,IDC_AUTOSAVE,bAutoSave); CheckDlgButton(hDlg,IDC_AUTOSAVEONEXIT,bAutoSaveOnExit); CheckDlgButton(hDlg,IDC_ALWAYSDISPLOG,bAlwaysDisplayLog); - CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared); - SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename); - // 10.11.98 cg, removed, not adjustable any more - // SetDlgItemInt(hDlg,IDC_T1PERIOD,uT1Period,FALSE); - // 20.05.98 cg, new, set combobox parameter + + // set combobox parameter SetCommList(hDlg,IDC_WIRE,szSerialWire); SetCommList(hDlg,IDC_IR,szSerialIr); - // 10.11.98 cg, removed, not adjustable any more - // CheckDlgButton(hDlg,IDC_USEMMTIMER,bAccurateTimer); - if (nState == 1) - { - // 30.05.98 cg, new, disable port1 enable box - EnableWindow(GetDlgItem(hDlg,IDC_PORT1EN),FALSE); - EnableWindow(GetDlgItem(hDlg,IDC_PORT1WR),FALSE); - } - else - { - EnableWindow(GetDlgItem(hDlg,IDC_PORT2ISSHARED),FALSE); - EnableWindow(GetDlgItem(hDlg,IDC_PORT2),FALSE); - } - if (CommConnect() != PORT_CLOSE) // 20.05.98 cg, new, disable when port open + if (CommConnect() != PORT_CLOSE) // disable when port open { EnableWindow(GetDlgItem(hDlg,IDC_WIRE),FALSE); EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE); } + + // 01.12.99 cg, HP48SX/GX + if (cCurrentRomType!='A' && cCurrentRomType!='X') + { + // init port1 enable checkbox + CheckDlgButton(hDlg,IDC_PORT1EN,(Chipset.cards_status & PORT1_PRESENT) != 0); + // 19.11.99 cg, changed, use cards_status variable now + CheckDlgButton(hDlg,IDC_PORT1WR,(Chipset.cards_status & PORT1_WRITE) != 0); + // init port2 shared checkbox and set port2 filename + CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared); + SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename); + if (nState == 1) // Invalid State + { + EnableWindow(GetDlgItem(hDlg,IDC_PORT1EN),FALSE); + EnableWindow(GetDlgItem(hDlg,IDC_PORT1WR),FALSE); + } + } + else // HP38G/HP49G + { + EnableWindow(GetDlgItem(hDlg,IDC_PORT1EN),FALSE); + EnableWindow(GetDlgItem(hDlg,IDC_PORT1WR),FALSE); + if (nState == 1) // Invalid State + { + // init port2 shared checkbox and set port2 filename + CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared); + SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename); + } + if (cCurrentRomType=='X') // 01.12.99 cg, HP48SX/GX + { + SendDlgItemMessage(hDlg,IDC_IR,CB_RESETCONTENT,0,0); + EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE); + } + } + if (nState != 1) // not in Invalid State + { + // hide port2 settings + EnableWindow(GetDlgItem(hDlg,IDC_PORT2ISSHARED),FALSE); + EnableWindow(GetDlgItem(hDlg,IDC_PORT2),FALSE); + } return TRUE; case WM_COMMAND: if (wParam == IDOK) { - // BOOL bTranslated; - // UINT uNewT1Period; - if (Chipset.Port1Size) + if (Chipset.Port1Size && cCurrentRomType!='X') { UINT nOldState = SwitchToState(3); - Chipset.Port1_Writeable = IsDlgButtonChecked(hDlg, IDC_PORT1WR); - // 30.05.98 cg, changed, added code for port1 disable - Chipset.cards_status = 0; + // port1 disabled ?; + Chipset.cards_status &= ~(PORT1_PRESENT | PORT1_WRITE); if (IsDlgButtonChecked(hDlg, IDC_PORT1EN)) { Chipset.cards_status |= PORT1_PRESENT; - if (Chipset.Port1_Writeable) + // 19.11.99 cg, changed, use dialog variable now + if (IsDlgButtonChecked(hDlg, IDC_PORT1WR)) Chipset.cards_status |= PORT1_WRITE; } if (Chipset.inte) @@ -329,27 +282,18 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP Map(0x00,0xFF); SwitchToState(nOldState); } - // 23.04.98 cg, new, get speed checkbox value + // get speed checkbox value bRealSpeed = IsDlgButtonChecked(hDlg,IDC_REALSPEED); bAutoSave = IsDlgButtonChecked(hDlg, IDC_AUTOSAVE); bAutoSaveOnExit = IsDlgButtonChecked(hDlg, IDC_AUTOSAVEONEXIT); bAlwaysDisplayLog = IsDlgButtonChecked(hDlg, IDC_ALWAYSDISPLOG); - SetSpeed(bRealSpeed); // 23.04.98 cg, set speed + SetSpeed(bRealSpeed); // set speed if (nState == 1) { bPort2IsShared = IsDlgButtonChecked(hDlg,IDC_PORT2ISSHARED); - // 01.02.98 cg, calculate size of buffer GetDlgItemText(hDlg,IDC_PORT2,szPort2Filename,sizeof(szPort2Filename)); } - // 10.11.98 cg, removed, not adjustable any more - // bAccurateTimer = IsDlgButtonChecked(hDlg,IDC_USEMMTIMER); - // uNewT1Period = GetDlgItemInt(hDlg, IDC_T1PERIOD, &bTranslated, FALSE); - // if (bTranslated) - // uT1Period = uNewT1Period; - // else - // uT1Period = 62; - // 20.05.98 cg, new, set combobox parameter - // 26.08.98 cg, changed implementation + // set combobox parameter GetDlgItemText(hDlg,IDC_WIRE,szSerialWire,sizeof(szSerialWire)); GetDlgItemText(hDlg,IDC_IR ,szSerialIr ,sizeof(szSerialIr)); EndDialog(hDlg, wParam); @@ -358,16 +302,10 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP { EndDialog(hDlg, wParam); } - // 10.11.98 cg, removed, not adjustable any more - // if (wParam == IDC_T1DEFAULT) - // { - // SetDlgItemInt(hDlg,IDC_T1PERIOD,62,FALSE); - // } break; } return FALSE; UNREFERENCED_PARAMETER(lParam); - UNREFERENCED_PARAMETER(hDlg); } @@ -402,7 +340,7 @@ static UINT SaveChanges(BOOL bAuto) uReply = GetSaveAsFilename(); if (uReply != IDOK) return uReply; if (!SaveDocumentAs(szBufferFilename)) return IDCANCEL; - WritePrivateProfileString("Files","LastDocument",szCurrentFilename,EMU48_INI); + WriteLastDocument(szCurrentFilename); // 11.12.99 cg, changed, call function return IDYES; } @@ -425,7 +363,7 @@ static LRESULT OnCreate(HWND hWindow) { hWnd = hWindow; hWindowDC = GetDC(hWnd); - DragAcceptFiles(hWnd,TRUE); // 05.02.99 cg & Will Laughlin, moved, support dropped files + DragAcceptFiles(hWnd,TRUE); // support dropped files return 0; } @@ -434,12 +372,12 @@ static LRESULT OnCreate(HWND hWindow) // static LRESULT OnDestroy(HWND hWindow) { - DragAcceptFiles(hWnd,FALSE); // 05.02.99 cg & Will Laughlin, no WM_DROPFILES message any more - SwitchToState(2); - WriteSettings(); + DragAcceptFiles(hWnd,FALSE); // no WM_DROPFILES message any more + // SwitchToState(2); // 01.12.99 cg, removed, doing in main program now + // WriteSettings(); // 01.12.99 cg, removed, doing in main program now ReleaseDC(hWnd, hWindowDC); - SetWindowTitle(NULL); // 27.01.98 cg, bugfix, free memory of title - hWindowDC = NULL; // 11.09.98 cg, hWindowDC isn't valid any more + SetWindowTitle(NULL); // free memory of title + hWindowDC = NULL; // hWindowDC isn't valid any more hWnd = NULL; PostQuitMessage(0); return 0; @@ -455,14 +393,14 @@ static LRESULT OnPaint(HWND hWindow) HDC hPaintDC; hPaintDC = BeginPaint(hWindow, &Paint); - if (hMainDC != NULL) // 30.01.98 cg, bugfix, EndPaint() was not called + if (hMainDC != NULL) { BitBlt(hPaintDC, 0, 0, nBackgroundW, nBackgroundH, hMainDC, nBackgroundX, nBackgroundY, SRCCOPY); if ((nState==0)||(nState==3)) { UpdateMainDisplay(); UpdateMenuDisplay(); - UpdateAnnunciators(); // 21.07.98 cg, bugfix, redraw annunciators + UpdateAnnunciators(); RefreshButtons(); } } @@ -473,13 +411,14 @@ static LRESULT OnPaint(HWND hWindow) // // WM_DROPFILES // -// 01.11.98 cg & Will Laughlin, new, support dropped files static LRESULT OnDropFiles(HANDLE hFilesInfo) { char szFileName[MAX_PATH]; WORD wNumFiles,wIndex; BOOL bSuccess; + if (cCurrentRomType=='A') return 0; // 06.12.99 cg, new, HP38 has no stack, ignore + // get number of files dropped wNumFiles = DragQueryFile (hFilesInfo,(UINT)-1,NULL,0); @@ -608,7 +547,7 @@ static LRESULT OnFileSaveAs() SwitchToState(0); return 0; } - WritePrivateProfileString("Files","LastDocument",szCurrentFilename,EMU48_INI); + WriteLastDocument(szCurrentFilename); // 11.12.99 cg, changed, call function SwitchToState(0); return 0; @@ -636,26 +575,15 @@ static LRESULT OnFileClose() // // ID_FILE_EXIT -// -static LRESULT OnFileExit() -{ - SwitchToState(2); // 21.02.99 cg, bugfix, hold emulation thread first - if (SaveChanges(bAutoSaveOnExit) == IDCANCEL) - { - return 0; - } - DestroyWindow(hWnd); - return 0; -} - // // WM_SYS_CLOSE // -static LRESULT OnSysClose() +static LRESULT OnFileExit() { - SwitchToState(2); // 21.02.99 cg, bugfix, hold emulation thread first + SwitchToState(1); // hold emulation thread if (SaveChanges(bAutoSaveOnExit) == IDCANCEL) { + SwitchToState(0); // on cancel restart emulation thread return 0; } DestroyWindow(hWnd); @@ -665,7 +593,7 @@ static LRESULT OnSysClose() // // ID_STACK_COPY // -static LRESULT OnStackCopy() // 17.06.98 cg, new, copy data from stack +static LRESULT OnStackCopy() // copy data from stack { HANDLE hClipObj; LPBYTE lpData; @@ -731,14 +659,13 @@ error: // // ID_STACK_PASTE // -static LRESULT OnStackPaste() // 17.06.98 cg, new, paste data to stack +static LRESULT OnStackPaste() // paste data to stack { HANDLE hClipObj; LPBYTE lpClipdata,lpData; BOOL bSuccess = FALSE; - // 10.11.98 cg, bugfix, moved from bottom of function if (!Chipset.dispon) // calculator off, turn on { KeyboardEvent(TRUE,0,0x8000); @@ -805,13 +732,12 @@ static LRESULT OnStackPaste() // 17.06.98 cg, new, paste data to stack // static LRESULT OnViewCopy() { - // 22.09.98 cg, bugfix, always close clipboard if (OpenClipboard(hWnd)) { if (EmptyClipboard()) { #if !defined MONOCHROME - // 27.01.99 cg, changed implementation for DIB bitmap + // DIB bitmap #define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4) #define PALVERSION 0x300 @@ -894,18 +820,15 @@ static LRESULT OnViewCopy() DeleteObject(hBmp); #undef WIDTHBYTES #undef PALVERSION - // 27.01.99 cg, end of changed implementation #else HBITMAP hOldBmp, hBmp; HDC hBmpDC; - // 24.08.98 cg, changed implementation _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); hBmp = CreateBitmap(131*nLcdDoubled,64*nLcdDoubled,1,1,NULL); hBmpDC = CreateCompatibleDC(NULL); hOldBmp = (HBITMAP)SelectObject(hBmpDC,hBmp); BitBlt(hBmpDC, 0, 0, 131*nLcdDoubled, 64*nLcdDoubled, hLcdDC, 0, 0, SRCCOPY); - // 24.08.98 cg, end of changed implementation SetClipboardData(CF_BITMAP,hBmp); SelectObject(hBmpDC,hOldBmp); DeleteDC(hBmpDC); @@ -913,7 +836,6 @@ static LRESULT OnViewCopy() } CloseClipboard(); } - // 22.09.98 cg, end of bugfix return 0; } @@ -926,12 +848,7 @@ static LRESULT OnViewReset() if (YesNoMessage("Are you sure you want to press the Reset Button ?")==IDYES) { SwitchToState(3); - Chipset.pc = 0; - Chipset.inte = TRUE; - Chipset.Shutdn = FALSE; - Chipset.SoftInt = TRUE; - Reset(); // 21.01.98 cg, bugfix, must unconfig MMU too - bInterrupt = TRUE; + CpuReset(); // 19.03.99 cg, changed, register setting after Cpu Reset SwitchToState(0); } return 0; @@ -943,10 +860,13 @@ static LRESULT OnViewReset() static LRESULT OnViewSettings() { ReadSettings(); - if (nState == 1) UnmapPort2(); + + // in nState = 1 port2 file must be closed from document + _ASSERT(nState != 1 || pbyPort2 == NULL); + if (DialogBox(hApp, MAKEINTRESOURCE(IDD_SETTINGS), hWnd, (DLGPROC)SettingsProc) == -1) AbortMessage("Settings Dialog Creation Error !"); - if (nState == 1) MapPort2(szPort2Filename); + WriteSettings(); return 0; } @@ -1023,7 +943,7 @@ static LRESULT OnObjectLoad() { static BOOL bWarning = TRUE; - if (!Chipset.dispon) // 10.11.98 cg, new, calculator off, turn on + if (!Chipset.dispon) // calculator off, turn on { // turn on HP KeyboardEvent(TRUE,0,0x8000); @@ -1037,7 +957,7 @@ static LRESULT OnObjectLoad() return 0; } - if (WaitForSleepState()) // 10.11.98 cg, changed, wait for cpu SHUTDN then sleep state + if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state { InfoMessage("The emulator is busy."); return 0; @@ -1084,7 +1004,6 @@ static LRESULT OnObjectLoad() KeyboardEvent(TRUE,0,0x8000); Sleep(200); KeyboardEvent(FALSE,0,0x8000); - // 10.11.98 cg, changed, wait for sleep mode while(Chipset.Shutdn == FALSE) Sleep(0); return 0; } @@ -1094,14 +1013,13 @@ static LRESULT OnObjectLoad() // static LRESULT OnObjectSave() { - if (nState!=0) { InfoMessage("The emulator must be running to save an object."); return 0; } - if (WaitForSleepState()) // 10.11.98 cg, wait for cpu SHUTDN then sleep state + if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state return 0; while (nState!=nNextState) Sleep(0); @@ -1121,9 +1039,8 @@ static LRESULT OnObjectSave() } // -// ID_DISASM +// ID_TOOL_DISASM // -// 15.07.98 cg, new, dialogbox for disassembly static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam) { static DWORD dwAddress, dwAddressMax; @@ -1135,7 +1052,7 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam) switch (message) { case WM_INITDIALOG: - // 10.11.98 cg, new, set fonts & cursor + // set fonts & cursor SendDlgItemMessage(hDlg,IDC_DISASM_MODULE,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_DISASM_MAP,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_DISASM_ROM,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); @@ -1147,50 +1064,49 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam) SendDlgItemMessage(hDlg,IDC_DISASM_CLASS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_DISASM_MAP,BM_SETCHECK,1,0); SendDlgItemMessage(hDlg,IDC_DISASM_HP,BM_SETCHECK,1,0); - // 10.11.98 cg, end of new part SendDlgItemMessage(hDlg,IDC_ADDRESS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_DISASM_ADR,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDC_DISASM_NEXT,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); - // 12.02.98 cg, new, set font of new button SendDlgItemMessage(hDlg,IDC_DISASM_COPY,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SendDlgItemMessage(hDlg,IDCANCEL,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); SetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress); - disassembler_map = MEM_MAP; // 10.11.98 cg, new disassemble with mapped modules - disassembler_mode = HP_MNEMONICS; // 10.11.98 cg, new use HP mnemonics for disassembling + disassembler_map = MEM_MAP; // disassemble with mapped modules + disassembler_mode = HP_MNEMONICS; // use HP mnemonics for disassembling dwAddress = strtoul(szAddress,&cpStop,16); - dwAddressMax = 0x100000; // 10.11.98 cg, new, greatest address (mapped mode) + dwAddressMax = 0x100000; // greatest address (mapped mode) return TRUE; case WM_COMMAND: switch(wParam) { - // 10.11.98 cg, new, decode radio buttons + // decode radio buttons case IDC_DISASM_MAP: disassembler_map = MEM_MAP; dwAddressMax = 0x100000; - break; + return TRUE; case IDC_DISASM_ROM: disassembler_map = MEM_ROM; dwAddressMax = dwRomSize; - break; + return TRUE; case IDC_DISASM_RAM: disassembler_map = MEM_RAM; dwAddressMax = Chipset.Port0Size * 2048; - break; + return TRUE; case IDC_DISASM_PORT1: disassembler_map = MEM_PORT1; dwAddressMax = ((Chipset.cards_status & PORT1_PRESENT) != 0) ? (Chipset.Port1Size * 2048) : 0; - break; + return TRUE; case IDC_DISASM_PORT2: disassembler_map = MEM_PORT2; - dwAddressMax = (dwPort2Mask != 0) ? ((dwPort2Mask + 1) << 17) : 0; - break; + dwAddressMax = (cCurrentRomType=='X') + ? (Chipset.Port2Size * 2048) + : ((dwPort2Mask != 0) ? ((dwPort2Mask + 1) << 18) : (dwPort2Size * 2048)); + return TRUE; case IDC_DISASM_HP: disassembler_mode = HP_MNEMONICS; - break; + return TRUE; case IDC_DISASM_CLASS: disassembler_mode = CLASS_MNEMONICS; - break; - // 10.11.98 cg, end of new part + return TRUE; case IDOK: SendDlgItemMessage(hDlg,IDC_DISASM_ADR,EM_SETSEL,0,-1); GetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress,sizeof(szAddress)); @@ -1203,17 +1119,15 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam) dwAddress = strtoul(szAddress,&cpStop,16); // no break case IDC_DISASM_NEXT: - if (dwAddress >= dwAddressMax) // 10.11.98 cg, bugfix, moved check from IDOK + if (dwAddress >= dwAddressMax) return FALSE; - i = wsprintf(szAddress,"%05lX ",dwAddress); - dwAddress = disassemble(dwAddress,&szAddress[i]); - // 12.02.99 cg, changed, implementation for multi selectable items + i = wsprintf(szAddress,(dwAddress <= 99999) ? "%05lX " : "%06lX ",dwAddress); + dwAddress = disassemble(dwAddress,&szAddress[i],VIEW_LONG); i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_ADDSTRING,0,(LPARAM) szAddress); SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_SELITEMRANGE,FALSE,MAKELPARAM(0,i)); SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_SETSEL,TRUE,i); SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_SETTOPINDEX,i,0); - break; - // 12.02.99 cg, new, copy selected items to clipoard + return TRUE; case IDC_DISASM_COPY: // get number of selections if ((i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETSELCOUNT,0,0)) == 0) @@ -1263,17 +1177,15 @@ static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam) } LocalFree(lpnCount); // free item table } - break; - // 12.02.99 cg, end of new part + return TRUE; case IDCANCEL: EndDialog(hDlg, wParam); - break; + return TRUE; } break; } return FALSE; UNREFERENCED_PARAMETER(lParam); - UNREFERENCED_PARAMETER(hDlg); } // @@ -1292,16 +1204,15 @@ static BOOL CALLBACK About(HWND hDlg, UINT message, DWORD wParam, LONG lParam) if ((wParam==IDOK)||(wParam==IDCANCEL)) { EndDialog(hDlg, wParam); - break; + return TRUE; } break; } return FALSE; UNREFERENCED_PARAMETER(lParam); - UNREFERENCED_PARAMETER(hDlg); } -static LRESULT OnToolDisasm() // 15.07.98 cg, new, disasm dialogbox call +static LRESULT OnToolDisasm() // disasm dialogbox call { if (pbyRom) SwitchToState(3); if (DialogBox(hApp, MAKEINTRESOURCE(IDD_DISASM), hWnd, (DLGPROC)Disasm) == -1) @@ -1312,10 +1223,8 @@ static LRESULT OnToolDisasm() // 15.07.98 cg, new, disasm dialogbox call static LRESULT OnAbout() { - // if (pbyRom) SwitchToState(3); // 25.01.99 cg, removed, don't stop emulation if (DialogBox(hApp, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)About) == -1) AbortMessage("About Dialog Box Creation Error !"); - // if (pbyRom) SwitchToState(0); // 25.01.99 cg, removed return 0; } @@ -1339,7 +1248,7 @@ static LRESULT OnMouseMove(UINT nFlags, WORD x, WORD y) static LRESULT OnKeyDown(int nVirtKey, DWORD lKeyData) { - // 03.09.98 cg, bugfix, call RunKey() only once (suppress autorepeat feature) + // call RunKey() only once (suppress autorepeat feature) if (nState==0 && (lKeyData & 0x40000000)==0) RunKey((BYTE)nVirtKey, TRUE); return 0; @@ -1352,14 +1261,13 @@ static LRESULT OnKeyUp(int nVirtKey, DWORD lKeyData) UNREFERENCED_PARAMETER(lKeyData); } -static LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam) +LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: return OnCreate(hWindow); case WM_DESTROY: return OnDestroy(hWindow); case WM_PAINT: return OnPaint(hWindow); - // 01.11.98 cg & Will Laughlin, new, support dropped files case WM_DROPFILES: return OnDropFiles((HANDLE)wParam); case WM_ACTIVATE: if (LOWORD(wParam)==WA_INACTIVE) break; @@ -1395,8 +1303,8 @@ static LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPAR case ID_FILE_SAVEAS: return OnFileSaveAs(); case ID_FILE_CLOSE: return OnFileClose(); case ID_FILE_EXIT: return OnFileExit(); - case ID_STACK_COPY: return OnStackCopy(); // 17.06.98 cg, new, copy data from stack - case ID_STACK_PASTE: return OnStackPaste(); // 17.06.98 cg, new, paste data to stack + case ID_STACK_COPY: return OnStackCopy(); + case ID_STACK_PASTE: return OnStackPaste(); case ID_VIEW_COPY: return OnViewCopy(); case ID_VIEW_RESET: return OnViewReset(); case ID_VIEW_SETTINGS: return OnViewSettings(); @@ -1406,17 +1314,18 @@ static LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPAR case ID_BACKUP_DELETE: return OnBackupDelete(); case ID_OBJECT_LOAD: return OnObjectLoad(); case ID_OBJECT_SAVE: return OnObjectSave(); - case ID_TOOL_DISASM: return OnToolDisasm(); // 15.07.98 cg, new, disassembler dialog box + case ID_TOOL_DISASM: return OnToolDisasm(); + case ID_TOOL_DEBUG: return OnToolDebug(); case ID_ABOUT: return OnAbout(); } break; case WM_SYSCOMMAND: switch (LOWORD(wParam)) { - case SC_CLOSE: return OnSysClose(); + case SC_CLOSE: return OnFileExit(); } break; - case WM_RBUTTONDOWN: // 01.10.97 cg, for holding key pressed + case WM_RBUTTONDOWN: case WM_LBUTTONDOWN: return OnLButtonDown(wParam, LOWORD(lParam), HIWORD(lParam)); case WM_LBUTTONUP: return OnLButtonUp(wParam, LOWORD(lParam), HIWORD(lParam)); case WM_MOUSEMOVE: return OnMouseMove(wParam, LOWORD(lParam), HIWORD(lParam)); @@ -1426,6 +1335,7 @@ static LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPAR return DefWindowProc(hWindow, uMsg, wParam, lParam); } +#if 0 // 01.12.99 cg, removed static BOOL FlushMessages(LPMSG msg) { while (PeekMessage(msg, NULL, 0, 0, PM_REMOVE)) @@ -1436,16 +1346,18 @@ static BOOL FlushMessages(LPMSG msg) } return FALSE; } +#endif // 01.12.99 cg -// 01.11.98 cg, bugfix, changed varible type of first two arguments -int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { MSG msg; WNDCLASS wc; RECT rectWindow; - HSZ hszService, hszTopic; // 13.05.98 cg, new, varibles for DDE server + HSZ hszService, hszTopic; // variables for DDE server hApp = hInst; + nArgc = __argc; // 08.11.99 cg, new, no. of command line arguments + ppArgv = (LPCTSTR*) __argv; // 08.11.99 cg, new, command line arguments wc.style = CS_BYTEALIGNCLIENT; wc.lpfnWndProc = (WNDPROC)MainWndProc; @@ -1489,67 +1401,81 @@ int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC } ShowWindow(hWnd, nCmdShow); - - if (FlushMessages(&msg)) return msg.wParam; + + // 01.12.99 cg, removed, useless and quit with resources open + // if (FlushMessages(&msg)) return msg.wParam; // initialization - QueryPerformanceFrequency(&lFreq); // 24.08.98 cg, init high resolution counter + QueryPerformanceFrequency(&lFreq); // init high resolution counter - // 01.02.98 cg, calculate size of buffer GetCurrentDirectory(sizeof(szCurrentDirectory), szCurrentDirectory); ReadSettings(); - // szNoTitle = "Emu48 "VERSION; // 20.01.98 cg, removed - UpdateWindowStatus(); - + + // create auto event handle + hEventShutdn = CreateEvent(NULL,FALSE,FALSE,NULL); + if (hEventShutdn == NULL) + { + AbortMessage("Event creation failed."); + DestroyWindow(hWnd); // 02.12.99 cg, bugfix, close DC + return FALSE; + } + nState = 1; // thread starts in an invalid state nNextState = 1; hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, NULL, 0, &lThreadId); if (hThread == NULL) { + CloseHandle(hEventShutdn); // close event handle AbortMessage("Thread creation failed."); + DestroyWindow(hWnd); // 01.12.99 cg, bugfix, close DC return FALSE; } - - // 20.02.99 cg, changed, use 2nd command line argument if defined - MapPort2((__argc < 3) ? szPort2Filename : __argv[2]); - // 13.05.98 cg, new, initialize DDE server + // initialize DDE server if (DdeInitialize(&idDdeInst,(PFNCALLBACK) &DdeCallback, APPCLASS_STANDARD | CBF_FAIL_EXECUTES | CBF_FAIL_ADVISES | CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS,0)) { + TerminateThread(hThread, 0); // 01.12.99 cg, bugfix, kill emulation thread + CloseHandle(hEventShutdn); // 01.12.99 cg, bugfix, close event handle AbortMessage("Could not initialize server!"); + DestroyWindow(hWnd); // 01.12.99 cg, bugfix, close DC return FALSE; } - if (__argc >= 2) // 20.02.99 cg, changed, use decoded parameter line + // 08.11.99 cg, changed, replaced __argc and __argv variable + if (nArgc >= 2) // use decoded parameter line { CHAR szTemp[256] = "Loading "; - strcat(szTemp, __argv[1]); // 20.02.99 cg, changed, use decoded parameter line + strcat(szTemp, ppArgv[1]); SetWindowTitle(szTemp); - if (FlushMessages(&msg)) return msg.wParam; - if (OpenDocument(__argv[1])) // 20.02.99 cg, changed, use decoded parameter line + // 01.12.99 cg, removed, useless and quit with resources open + // if (FlushMessages(&msg)) return msg.wParam; + if (OpenDocument(ppArgv[1])) goto start; } + // 08.11.99 cg, end of replacement - // 09.12.97 cg, bugfix, function parameter - GetPrivateProfileString("Files","LastDocument","",szBufferFilename,sizeof(szBufferFilename),EMU48_INI); + // 11.12.99 cg, changed, call function + ReadLastDocument(szBufferFilename, sizeof(szBufferFilename)); if (szBufferFilename[0]) { CHAR szTemp[256] = "Loading "; strcat(szTemp, szBufferFilename); SetWindowTitle(szTemp); - if (FlushMessages(&msg)) return msg.wParam; + // 01.12.99 cg, removed, useless and quit with resources open + // if (FlushMessages(&msg)) return msg.wParam; if (OpenDocument(szBufferFilename)) goto start; } - + SetWindowTitle("New Document"); - if (FlushMessages(&msg)) return msg.wParam; + // 01.12.99 cg, removed, useless and quit with resources open + // if (FlushMessages(&msg)) return msg.wParam; if (NewDocument()) { SetWindowTitle("Untitled"); @@ -1557,53 +1483,57 @@ int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC } ResetDocument(); - // SetWindowTitle(NULL); // 27.01.98 cg, removed, see WM_DESTROY start: - InitializeCriticalSection(&csGDILock); // 03.01.99 cg, bugfix, initialize critical section - InitializeCriticalSection(&csKeyLock); // 03.01.99 cg, bugfix, initialize critical section - InitializeCriticalSection(&csIOLock); // 24.02.99 cg, new, initialize critical section - InitializeCriticalSection(&csT1Lock); // 03.01.99 cg, bugfix, initialize critical section - InitializeCriticalSection(&csT2Lock); // 03.01.99 cg, bugfix, initialize critical section + InitializeCriticalSection(&csGDILock); + InitializeCriticalSection(&csKeyLock); + InitializeCriticalSection(&csIOLock); + InitializeCriticalSection(&csT1Lock); + InitializeCriticalSection(&csT2Lock); + InitializeCriticalSection(&csRecvLock); // 24.10.99 cg, moved, init critical section for receive byte - // 13.05.98 cg, new, init clipboard format and name service + // init clipboard format and name service uCF_HpObj = RegisterClipboardFormat(CF_HPOBJ); hszService = DdeCreateStringHandle(idDdeInst,szAppName,0); hszTopic = DdeCreateStringHandle(idDdeInst,szTopic,0); DdeNameService(idDdeInst,hszService,NULL,DNS_REGISTER); - // 13.05.98 cg, new, end of init if (pbyRom) SwitchToState(0); while (GetMessage(&msg, NULL, 0, 0)) { - TranslateMessage(&msg); - DispatchMessage(&msg); + if(hDlgDebug == NULL || !IsDialogMessage(hDlgDebug, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } - // 13.05.98 cg, new, clean up DDE server + SwitchToState(2); // 01.12.99 cg, moved from OnDestroy(), exit emulation thread + + // clean up DDE server DdeNameService(idDdeInst, hszService, NULL, DNS_UNREGISTER); DdeFreeStringHandle(idDdeInst, hszService); DdeFreeStringHandle(idDdeInst, hszTopic); DdeUninitialize(idDdeInst); - // 13.05.98 cg, new, end of clean up - DeleteCriticalSection(&csGDILock); // 03.01.99 cg, bugfix, release critical section - DeleteCriticalSection(&csKeyLock); // 03.01.99 cg, bugfix, release critical section - DeleteCriticalSection(&csIOLock); // 24.02.99 cg, new, release critical section - DeleteCriticalSection(&csT1Lock); // 03.01.99 cg, bugfix, release critical section - DeleteCriticalSection(&csT2Lock); // 03.01.99 cg, bugfix, release critical section + DeleteCriticalSection(&csGDILock); + DeleteCriticalSection(&csKeyLock); + DeleteCriticalSection(&csIOLock); + DeleteCriticalSection(&csT1Lock); + DeleteCriticalSection(&csT2Lock); + DeleteCriticalSection(&csRecvLock); // 24.10.99 cg, moved, end of critical section for receive byte + + WriteSettings(); // 01.12.99 cg, moved from OnDestroy() - // SwitchToState(2); // 27.01.98 cg, removed, done in WM_DESTROY - _ASSERT(nState == 2); // 30.01.98 cg, set by WM_DESTROY + CloseHandle(hEventShutdn); // close event handle + _ASSERT(nState == 2); // emulation thread down? ResetDocument(); ResetBackup(); - cCurrentRomType = 0; - // KillKML(); // 27.01.98 cg, removed, done in ResetDocument() or OnFileClose() - _ASSERT(pKml == NULL); // 27.01.98 cg, KML script not closed - UnmapPort2(); - _ASSERT(szTitle == NULL); // 11.09.98 cg, freed allocated memory - _ASSERT(hPalette == NULL); // 11.09.98 cg, freed resource memory + _ASSERT(pbyPort2 == NULL); // port2 file unmapped + _ASSERT(pKml == NULL); // KML script not closed + _ASSERT(szTitle == NULL); // freed allocated memory + _ASSERT(hPalette == NULL); // freed resource memory return msg.wParam; UNREFERENCED_PARAMETER(lpCmdLine); diff --git a/sources/Emu48/EMU48.DSP b/sources/Emu48/EMU48.DSP index 0f2cfc4..906bd19 100644 --- a/sources/Emu48/EMU48.DSP +++ b/sources/Emu48/EMU48.DSP @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"pch.h" /FD /c +# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /Yu"pch.h" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x40c /d "NDEBUG" @@ -68,7 +68,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"pch.h" /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /FR /Yu"pch.h" /FD /c # ADD BASE MTL /nologo /D "_DEBUG" /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x40c /d "_DEBUG" @@ -95,6 +95,10 @@ SOURCE=.\ddeserv.c # End Source File # Begin Source File +SOURCE=.\debugger.c +# End Source File +# Begin Source File + SOURCE=.\disasm.c # End Source File # Begin Source File @@ -126,6 +130,10 @@ SOURCE=.\external.c # End Source File # Begin Source File +SOURCE=.\fetch.c +# End Source File +# Begin Source File + SOURCE=.\files.c # End Source File # Begin Source File @@ -142,6 +150,10 @@ SOURCE=.\mops.c # End Source File # Begin Source File +SOURCE=.\opcodes.c +# End Source File +# Begin Source File + SOURCE=.\pch.c # ADD CPP /Yc"pch.h" # End Source File @@ -155,6 +167,10 @@ SOURCE=.\serial.c # End Source File # Begin Source File +SOURCE=.\settings.c +# End Source File +# Begin Source File + SOURCE=.\timer.c # End Source File # End Group @@ -163,15 +179,31 @@ SOURCE=.\timer.c # PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" # Begin Source File +SOURCE=.\color.h +# End Source File +# Begin Source File + +SOURCE=.\debugger.h +# End Source File +# Begin Source File + SOURCE=.\Emu48.h # End Source File # Begin Source File +SOURCE=.\io.h +# End Source File +# Begin Source File + SOURCE=.\kml.h # End Source File # Begin Source File -SOURCE=.\Ops.h +SOURCE=.\opcodes.h +# End Source File +# Begin Source File + +SOURCE=.\ops.h # End Source File # Begin Source File diff --git a/sources/Emu48/EMU48.H b/sources/Emu48/EMU48.H index 4b7d684..b63e135 100644 --- a/sources/Emu48/EMU48.H +++ b/sources/Emu48/EMU48.H @@ -8,61 +8,90 @@ */ #include "types.h" -#define BINARYHEADER "HPHP48-W" // 11.05.98 cg, new +// cards status +#define PORT1_PRESENT ((cCurrentRomType=='S')?0x1:0x2) +#define PORT1_WRITE ((cCurrentRomType=='S')?0x4:0x8) +#define PORT2_PRESENT ((cCurrentRomType=='S')?0x2:0x1) +#define PORT2_WRITE ((cCurrentRomType=='S')?0x8:0x4) -#define S_ERR_NO 0 // 11.05,98 cg, new, stack errorcodes +#define BINARYHEADER48 "HPHP48-W" +#define BINARYHEADER49 "HPHP49-W" + +#define S_ERR_NO 0 // stack errorcodes #define S_ERR_BINARY 1 #define S_ERR_ASCII 2 -#define NO_SERIAL "disabled" // 22.05.98 cg, new, serial port not open +#define NO_SERIAL "disabled" // port not open -#define PORT_CLOSE 0 // 20.05.98 cg, new, COM port status +#define PORT_CLOSE 0 // COM port status #define PORT_WIRE 1 #define PORT_IR 2 -#define HP_MNEMONICS FALSE // 10.11.98 cg, new, disassembler mnenomics mode +#define HP_MNEMONICS FALSE // disassembler mnenomics mode #define CLASS_MNEMONICS TRUE -#define MEM_MAP 0 // 10.11.98 cg, new, memory module definition +#define MEM_MAP 0 // memory module definition #define MEM_ROM 1 #define MEM_RAM 2 #define MEM_PORT1 3 #define MEM_PORT2 4 +#define VIEW_SHORT FALSE // view of disassembler output +#define VIEW_LONG TRUE + +#define DISP_POINTER 0x01 // defines for display area +#define DISP_MAIN 0x02 +#define DISP_MENUE 0x04 +#define DISP_ANNUN 0x08 + // Emu48.c extern HPALETTE hPalette; -extern HPALETTE hOldPalette; // 11.09.98 cg, old palette of hWindowDC -extern LPSTR szAppName; // 13.05.98 cg, application name for DDE server -extern LPSTR szTopic; // 13.05.98 cg, topic for DDE server +extern HPALETTE hOldPalette; +extern HANDLE hEventShutdn; +extern LPSTR szAppName; +extern LPSTR szTopic; extern LPSTR szTitle; -extern CRITICAL_SECTION csGDILock; // 22.01.98 cg, critical section for hWindowDC -extern CRITICAL_SECTION csKeyLock; // 02.09.98 cg, critical section for key scan -extern CRITICAL_SECTION csIOLock; // 24.02.99 cg, critical section for I/O access -extern CRITICAL_SECTION csT1Lock; // 21.04.98 cg, critical section for timer1 access -extern CRITICAL_SECTION csT2Lock; // 21.04.98 cg, critical section for timer2 access -extern LARGE_INTEGER lFreq; // 24.08.98 cg, counter frequency -extern DWORD idDdeInst; // 13.05.98 cg, DDE server id -extern UINT uCF_HpObj; // 13.05.98 cg, DDE clipboard format -extern HINSTANCE hApp; // 01.11.98 cg, wrong variable type +extern CRITICAL_SECTION csGDILock; +extern CRITICAL_SECTION csKeyLock; +extern CRITICAL_SECTION csIOLock; +extern CRITICAL_SECTION csT1Lock; +extern CRITICAL_SECTION csT2Lock; +extern CRITICAL_SECTION csRecvLock; // 24.10.99 cg, critical section for receive byte +extern INT nArgc; // 08.11.99 cg, no. of command line arguments +extern LPCTSTR *ppArgv; // 08.11.99 cg, command line arguments +extern LARGE_INTEGER lFreq; +extern DWORD idDdeInst; +extern UINT uCF_HpObj; +extern HINSTANCE hApp; extern HWND hWnd; extern HDC hWindowDC; extern BOOL bPort2IsShared; +extern BOOL bAutoSave; // 11.12.99 cg, add declaration +extern BOOL bAutoSaveOnExit; // 11.12.99 cg, add declaration extern BOOL bAlwaysDisplayLog; -extern UINT uTimer1Period; +// extern UINT uTimer1Period; // 11.12.99 cg, removed old definition +extern HANDLE hThread; // 11.12.99 cg, add declaration +extern DWORD lThreadId; // 11.12.99 cg, add declaration extern VOID SetWindowTitle(LPSTR szString); extern VOID UpdateWindowStatus(VOID); +// Settings.c +extern VOID ReadSettings(VOID); // 11.12.99 cg, moved from Emu48.c +extern VOID WriteSettings(VOID); // 11.12.99 cg, moved from Emu48.c +extern VOID ReadLastDocument(LPTSTR szFileName, DWORD nSize); +extern VOID WriteLastDocument(LPCTSTR szFilename); + // Display.c -extern UINT nBackgroundX; -extern UINT nBackgroundY; -extern UINT nBackgroundW; -extern UINT nBackgroundH; -extern UINT nLcdX; -extern UINT nLcdY; -extern UINT nLcdDoubled; // 24.08.98 cg, changed to integer var -extern LPBYTE pbyLcd; -extern HDC hLcdDC; -extern HDC hMainDC; +extern UINT nBackgroundX; +extern UINT nBackgroundY; +extern UINT nBackgroundW; +extern UINT nBackgroundH; +extern UINT nLcdX; +extern UINT nLcdY; +extern UINT nLcdDoubled; +extern LPBYTE pbyLcd; +extern HDC hLcdDC; +extern HDC hMainDC; extern VOID UpdateContrast(BYTE byContrast); extern VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue); extern VOID CreateLcdBitmap(VOID); @@ -81,21 +110,25 @@ extern VOID ResizeWindow(VOID); extern BOOL bInterrupt; extern UINT nState; extern UINT nNextState; -extern BOOL bKeySlow; // 18.11.98 cg, slow down for key emulation -extern HANDLE hThread; +extern BOOL bRealSpeed; // 11.12.99 cg, new, real speed flag +extern BOOL bKeySlow; extern CHIPSET Chipset; -extern char szSerialWire[16]; // 20.05.98 cg, devicename for wire port -extern char szSerialIr[16]; // 20.05.98 cg, devicename for IR port -extern DWORD dwSXCycles; // 23.04.98 cg, SX cpu cycles in 1/16384 Hz -extern DWORD dwGXCycles; // 23.04.98 cg, GX cpu cycles in 1/16384 Hz -extern VOID SetSpeed(BOOL bAdjust); // 23.04.98 cg, set emulation speed -extern VOID UpdateKdnBit(VOID); // 25.02.99 cg, update KDN bit -extern BOOL WaitForSleepState(VOID); // 16.06.98 cg, wait for cpu SHUTDN then sleep state +extern char szSerialWire[16]; +extern char szSerialIr[16]; +extern DWORD dwSXCycles; +extern DWORD dwGXCycles; +extern VOID AdjKeySpeed(VOID); +extern VOID SetSpeed(BOOL bAdjust); +extern VOID UpdateKdnBit(VOID); +extern BOOL WaitForSleepState(VOID); extern UINT SwitchToState(UINT nNewState); extern UINT WorkerThread(LPVOID pParam); extern DWORD Npack(BYTE *a, UINT s); extern VOID Nunpack(BYTE *a, DWORD b, UINT s); +// Fetch.c +extern VOID EvalOpcode(LPBYTE I); + // Files.c extern char szEmu48Directory[260]; extern char szCurrentDirectory[260]; @@ -111,11 +144,10 @@ extern char cCurrentRomType; extern LPBYTE pbyPort2; extern BOOL bPort2Writeable; extern BOOL bPort2IsShared; -extern DWORD dwPort2Size; // 26.06.98 cg, size of mapped port2 +extern DWORD dwPort2Size; extern DWORD dwPort2Mask; -// extern UINT nPort2Bank; // 15.12.98 cg, removed, not used any more extern BOOL bBackup; -extern WORD WriteStack(LPBYTE,DWORD); // 11.05.98 cg, write object to stack +extern WORD WriteStack(LPBYTE,DWORD); extern BOOL MapRom(LPCSTR szFilename); extern VOID UnmapRom(VOID); extern BOOL MapPort2(LPCSTR szFilename); @@ -138,8 +170,7 @@ extern BOOL SaveObject(LPCSTR szFilename); extern HBITMAP LoadBitmapFile(LPCSTR szFilename); // Timer.c -// extern BOOL bAccurateTimer; // 10.11.98 cg, removed, not adjustable any more -// extern UINT uT1Period; // 10.11.98 cg, removed, not adjustable any more +extern VOID SetHP48Time(VOID); extern VOID StartTimers(VOID); extern VOID StopTimers(VOID); extern DWORD ReadT2(VOID); @@ -148,32 +179,32 @@ extern BYTE ReadT1(VOID); extern VOID SetT1(BYTE byValue); // MOps.c -extern BOOL ioc_acc; // 17.05.98 cg, flag ioc changed -extern BOOL ir_ctrl_acc; // 17.05.98 cg, flag ir_ctl changed -extern LPBYTE RMap[256]; -extern LPBYTE WMap[256]; -extern VOID Map(BYTE a, BYTE b); -extern VOID Config(VOID); -extern VOID Uncnfg(VOID); -extern VOID Reset(VOID); -extern VOID C_Eq_Id(VOID); -extern VOID Npeek(BYTE *a, DWORD d, UINT s); -extern VOID Nread(BYTE *a, DWORD d, UINT s); -extern VOID Nwrite(BYTE *a, DWORD d, UINT s); -// extern VOID Nread2(BYTE *a, DWORD d); // 15.12.98 cg, removed, repaced by Nread() -// extern VOID Nwrite2(BYTE *a, DWORD d);// 15.12.98 cg, removed, repaced by Nwrite() -// extern VOID Nread5(BYTE *a, DWORD d); // 15.12.98 cg, removed, repaced by Nread() -// extern VOID Nwrite5(BYTE *a, DWORD d);// 15.12.98 cg, removed, repaced by Nwite() -extern BYTE Read2(DWORD d); -extern DWORD Read5(DWORD d); -extern VOID Write5(DWORD d, DWORD n); -extern VOID IOBit(DWORD d, BYTE b, BOOL s);// 24.02.99 cg, set/clear bit in I/O section -extern VOID ReadIO(BYTE *a, DWORD b, DWORD s); -extern VOID WriteIO(BYTE *a, DWORD b, DWORD s); +extern BOOL ioc_acc; +extern BOOL ir_ctrl_acc; +extern BYTE disp; +extern LPBYTE RMap[256]; +extern LPBYTE WMap[256]; +extern VOID Map(BYTE a, BYTE b); +extern VOID RomSwitch(DWORD adr); +extern VOID Config(VOID); +extern VOID Uncnfg(VOID); +extern VOID Reset(VOID); +extern VOID C_Eq_Id(VOID); +extern VOID CpuReset(VOID); // 19.03.99 cg, register setting after Cpu Reset +extern BYTE GetLineCounter(VOID); +extern VOID Npeek(BYTE *a, DWORD d, UINT s); +extern VOID Nread(BYTE *a, DWORD d, UINT s); +extern VOID Nwrite(BYTE *a, DWORD d, UINT s); +extern BYTE Read2(DWORD d); +extern DWORD Read5(DWORD d); +extern VOID Write5(DWORD d, DWORD n); +extern VOID Write2(DWORD d, BYTE n); +extern VOID IOBit(DWORD d, BYTE b, BOOL s); +extern VOID ReadIO(BYTE *a, DWORD b, DWORD s); +extern VOID WriteIO(BYTE *a, DWORD b, DWORD s); // Keyboard.c -// extern WORD Keyboard_GetIR(VOID); // 13.02.99 cg, is static now -extern VOID ScanKeyboard(BOOL bReset); // 02.09.98 cg, add flag for key state reset +extern VOID ScanKeyboard(BOOL bReset); extern VOID KeyboardEvent(BOOL bPress, UINT out, UINT in); // RPL.c @@ -193,13 +224,14 @@ extern HDDEDATA CALLBACK DdeCallback(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, DWOR // Disasm.c extern BOOL disassembler_mode; extern WORD disassembler_map; -extern DWORD disassemble (DWORD addr, LPSTR out); +extern DWORD disassemble (DWORD addr, LPSTR out, BOOL view); // Serial.c extern WORD CommConnect(VOID); extern VOID CommOpen(LPSTR strWirePort,LPSTR strIrPort); extern VOID CommClose(VOID); extern VOID CommSetBaud(VOID); +extern VOID UpdateUSRQ(VOID); // 25.10.99 cg, USRQ handling extern VOID CommTransmit(VOID); extern VOID CommReceive(VOID); @@ -213,7 +245,7 @@ static __inline int YesNoCancelMessage(LPCSTR szMessage) {return MessageBox(hWnd static __inline LPSTR DuplicateString(LPCSTR szString) { UINT uLength = strlen(szString) + 1; - LPSTR szDup = LocalAlloc(LMEM_FIXED,uLength); // 27.01.98 cg, adjust memsize + LPSTR szDup = LocalAlloc(LMEM_FIXED,uLength); CopyMemory(szDup,szString,uLength); return szDup; } diff --git a/sources/Emu48/EMU48.RC b/sources/Emu48/EMU48.RC index 3d3635c..9f7774f 100644 --- a/sources/Emu48/EMU48.RC +++ b/sources/Emu48/EMU48.RC @@ -21,133 +21,86 @@ LANGUAGE LANG_FRENCH, SUBLANG_FRENCH #pragma code_page(1252) #endif //_WIN32 -#ifndef _MAC ///////////////////////////////////////////////////////////////////////////// // -// Version +// DESIGNINFO // -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,1,0,0 - PRODUCTVERSION 1,1,0,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x21L -#else - FILEFLAGS 0x20L -#endif - FILEOS 0x40004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "00000000" - BEGIN - VALUE "CompanyName", "Sebastien Carlier\0" - VALUE "FileDescription", "HP48 Emulator\0" - VALUE "FileVersion", "1, 1, 0, 0\0" - VALUE "InternalName", "Emu48\0" - VALUE "LegalCopyright", "Copyright © 1999\0" - VALUE "OriginalFilename", "Emu48.exe\0" - VALUE "ProductName", "Emu48\0" - VALUE "ProductVersion", "1, 1, 0, 0\0" - VALUE "SpecialBuild", "Service Pack 10, Christoph Gießelink\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 0 - END -END - -#endif // !_MAC - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_EMU48 ICON DISCARDABLE "Emu48.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_MENU MENU DISCARDABLE -BEGIN - POPUP "&File" - BEGIN - MENUITEM "&New...", ID_FILE_NEW - MENUITEM "&Open...", ID_FILE_OPEN - MENUITEM "&Save", ID_FILE_SAVE, GRAYED - MENUITEM "Save &As...", ID_FILE_SAVEAS, GRAYED - MENUITEM "&Close", ID_FILE_CLOSE, GRAYED - MENUITEM SEPARATOR - MENUITEM "S&ettings...", ID_VIEW_SETTINGS - MENUITEM SEPARATOR - MENUITEM "E&xit", ID_FILE_EXIT - END - POPUP "&Edit" - BEGIN - MENUITEM "&Load Object...", ID_OBJECT_LOAD - MENUITEM "&Save Object...", ID_OBJECT_SAVE - MENUITEM SEPARATOR - MENUITEM "&Copy String", ID_STACK_COPY - MENUITEM "C&opy Screen", ID_VIEW_COPY - MENUITEM "&Paste String", ID_STACK_PASTE - MENUITEM SEPARATOR - MENUITEM "&Reset Calculator", ID_VIEW_RESET, GRAYED - POPUP "&Backup" - BEGIN - MENUITEM "&Save", ID_BACKUP_SAVE, GRAYED - MENUITEM "&Restore", ID_BACKUP_RESTORE - , GRAYED - MENUITEM "&Delete", ID_BACKUP_DELETE, GRAYED - END - END - POPUP "&View" - BEGIN - MENUITEM "Change &KML Script...", ID_VIEW_SCRIPT - END - POPUP "&Tools" - BEGIN - MENUITEM "&Disassembler...", ID_TOOL_DISASM - END - POPUP "&Help" - BEGIN - MENUITEM "&About Emu48...", ID_ABOUT - END -END - - #ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE +GUIDELINES DESIGNINFO DISCARDABLE BEGIN - "resource.h\0" -END + IDD_BREAKEDIT, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 105 + TOPMARGIN, 5 + BOTTOMMARGIN, 97 + END -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 254 + TOPMARGIN, 6 + BOTTOMMARGIN, 145 + END -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END + IDD_SETTINGS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 160 + TOPMARGIN, 4 + BOTTOMMARGIN, 171 + END + IDD_CHOOSEKML, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 59 + END + + IDD_KMLLOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 294 + TOPMARGIN, 7 + BOTTOMMARGIN, 160 + END + + IDD_DISASM, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + TOPMARGIN, 5 + BOTTOMMARGIN, 158 + END + + IDD_DEBUG, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 273 + TOPMARGIN, 5 + BOTTOMMARGIN, 212 + END + + IDD_NEWVALUE, DIALOG + BEGIN + LEFTMARGIN, 8 + RIGHTMARGIN, 168 + TOPMARGIN, 7 + BOTTOMMARGIN, 43 + END + + IDD_ENTERADR, DIALOG + BEGIN + LEFTMARGIN, 8 + RIGHTMARGIN, 149 + TOPMARGIN, 7 + BOTTOMMARGIN, 43 + END +END #endif // APSTUDIO_INVOKED @@ -156,6 +109,19 @@ END // Dialog // +IDD_BREAKEDIT DIALOG DISCARDABLE 0, 0, 110, 102 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit breakpoints" +FONT 8, "Courier New" +BEGIN + DEFPUSHBUTTON "OK",IDOK,77,83,28,14 + LTEXT "Current breakpoints:",IDC_STATIC_BREAKPOINT,5,5,82,8 + LISTBOX IDC_BREAKEDIT_WND,5,17,100,60,NOT LBS_NOTIFY | LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "&Add",IDC_BREAKEDIT_ADD,5,83,28,14 + PUSHBUTTON "&Delete",IDC_BREAKEDIT_DELETE,41,83,28,14 +END + IDD_ABOUT DIALOGEX 0, 0, 261, 160 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "About Emu48" @@ -270,39 +236,265 @@ BEGIN WS_TABSTOP,WS_EX_NOPARENTNOTIFY END +IDD_DEBUG DIALOGEX 0, 0, 278, 217 +STYLE WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Debugger" +MENU IDR_DEBUG +FONT 8, "Courier New", 0, 0, 0x1 +BEGIN + LISTBOX IDC_DEBUG_CODE,11,15,165,122,NOT LBS_NOTIFY | + LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | + LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT | + WS_TABSTOP + GROUPBOX "Code",IDC_STATIC_CODE,5,5,177,138 + LTEXT "A= 0000000000000000",IDC_REG_A,192,15,77,8 + LTEXT "B= 0000000000000000",IDC_REG_B,192,22,77,8 + LTEXT "C= 0000000000000000",IDC_REG_C,192,29,77,8 + LTEXT "D= 0000000000000000",IDC_REG_D,192,36,77,8 + LTEXT "R0=0000000000000000",IDC_REG_R0,192,46,77,8 + LTEXT "R1=0000000000000000",IDC_REG_R1,192,53,77,8 + LTEXT "R2=0000000000000000",IDC_REG_R2,192,60,77,8 + LTEXT "R3=0000000000000000",IDC_REG_R3,192,67,77,8 + LTEXT "R4=0000000000000000",IDC_REG_R4,192,74,77,8 + LTEXT "D0=00000",IDC_REG_D0,192,85,33,8 + LTEXT "D1=00000",IDC_REG_D1,236,85,33,8 + LTEXT "P=0",IDC_REG_P,192,96,13,8 + LTEXT "PC=00000",IDC_REG_PC,236,96,33,8 + LTEXT "OUT=000",IDC_REG_OUT,192,107,29,8 + LTEXT "IN=0000",IDC_REG_IN,240,107,29,8 + LTEXT "ST=0000",IDC_REG_ST,192,118,29,8 + LTEXT "CY=0",IDC_REG_CY,224,118,17,8 + LTEXT "Mode=H",IDC_REG_MODE,244,118,25,8 + LTEXT "MP=0",IDC_REG_MP,192,128,17,8 + LTEXT "SR=0",IDC_REG_SR,212,128,17,8 + LTEXT "SB=0",IDC_REG_SB,232,128,17,8 + LTEXT "XM=0",IDC_REG_XM,252,128,17,8 + GROUPBOX "Registers",IDC_STATIC_REGISTERS,186,5,87,138 + CONTROL "",IDC_DEBUG_MEM,"Static",SS_WHITERECT | WS_GROUP,11,154, + 165,52,WS_EX_CLIENTEDGE + LISTBOX IDC_DEBUG_MEM_ADDR,12,156,25,48,NOT LBS_NOTIFY | + LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_DISABLED | NOT + WS_BORDER + LISTBOX IDC_DEBUG_MEM_COL0,40,156,11,48,LBS_NOINTEGRALHEIGHT | + LBS_WANTKEYBOARDINPUT | NOT WS_BORDER | WS_TABSTOP + LISTBOX IDC_DEBUG_MEM_COL1,52,156,11,48,LBS_NOINTEGRALHEIGHT | + LBS_WANTKEYBOARDINPUT | NOT WS_BORDER + LISTBOX IDC_DEBUG_MEM_COL2,64,156,11,48,LBS_NOINTEGRALHEIGHT | + LBS_WANTKEYBOARDINPUT | NOT WS_BORDER + LISTBOX IDC_DEBUG_MEM_COL3,76,156,11,48,LBS_NOINTEGRALHEIGHT | + LBS_WANTKEYBOARDINPUT | NOT WS_BORDER + LISTBOX IDC_DEBUG_MEM_COL4,88,156,11,48,LBS_NOINTEGRALHEIGHT | + LBS_WANTKEYBOARDINPUT | NOT WS_BORDER + LISTBOX IDC_DEBUG_MEM_COL5,100,156,11,48,LBS_NOINTEGRALHEIGHT | + LBS_WANTKEYBOARDINPUT | NOT WS_BORDER + LISTBOX IDC_DEBUG_MEM_COL6,112,156,11,48,LBS_NOINTEGRALHEIGHT | + LBS_WANTKEYBOARDINPUT | NOT WS_BORDER + LISTBOX IDC_DEBUG_MEM_COL7,124,156,11,48,LBS_NOINTEGRALHEIGHT | + LBS_WANTKEYBOARDINPUT | NOT WS_BORDER + LISTBOX IDC_DEBUG_MEM_TEXT,139,156,35,48,NOT LBS_NOTIFY | + LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_DISABLED | NOT + WS_BORDER + GROUPBOX "Memory",IDC_STATIC_MEMORY,5,144,177,68 + LISTBOX IDC_DEBUG_STACK,192,154,75,52,NOT LBS_NOTIFY | + LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT | + WS_VSCROLL | WS_TABSTOP + GROUPBOX "Stack",IDC_STATIC_STACK,186,144,87,68 +END + +IDD_NEWVALUE DIALOG DISCARDABLE 0, 0, 175, 50 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "New Value" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "New value (hexdezimal):",IDC_STATIC,8,9,81,8 + EDITTEXT IDC_NEWVALUE,91,7,77,12,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,21,29,50,14 + PUSHBUTTON "Cancel",IDCANCEL,103,29,50,14 +END + +IDD_ENTERADR DIALOG DISCARDABLE 0, 0, 156, 50 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Enter address" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Enter address (hexdezimal):",IDC_STATIC,8,9,90,8 + EDITTEXT IDC_ENTERADR,106,7,43,12,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,14,29,50,14 + PUSHBUTTON "Cancel",IDCANCEL,92,29,50,14 +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,1,5,0 + PRODUCTVERSION 1,1,5,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x21L +#else + FILEFLAGS 0x20L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "00000000" + BEGIN + VALUE "CompanyName", "Sebastien Carlier\0" + VALUE "FileDescription", "HP38/48/49 Emulator\0" + VALUE "FileVersion", "1, 1, 5, 0\0" + VALUE "InternalName", "Emu48\0" + VALUE "LegalCopyright", "Copyright © 1999\0" + VALUE "OriginalFilename", "Emu48.exe\0" + VALUE "ProductName", "Emu48\0" + VALUE "ProductVersion", "1, 1, 5, 0\0" + VALUE "SpecialBuild", "Service Pack 15, Christoph Gießelink\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 0 + END +END + +#endif // !_MAC + ///////////////////////////////////////////////////////////////////////////// // -// DESIGNINFO +// Icon // -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_EMU48 ICON DISCARDABLE "Emu48.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE BEGIN - IDD_CHOOSEKML, DIALOG + POPUP "&File" BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 179 - TOPMARGIN, 7 - BOTTOMMARGIN, 59 + MENUITEM "&New...", ID_FILE_NEW + MENUITEM "&Open...", ID_FILE_OPEN + MENUITEM "&Save", ID_FILE_SAVE, GRAYED + MENUITEM "Save &As...", ID_FILE_SAVEAS, GRAYED + MENUITEM "&Close", ID_FILE_CLOSE, GRAYED + MENUITEM SEPARATOR + MENUITEM "S&ettings...", ID_VIEW_SETTINGS + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_FILE_EXIT END - - IDD_KMLLOG, DIALOG + POPUP "&Edit" BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 294 - TOPMARGIN, 7 - BOTTOMMARGIN, 160 + MENUITEM "&Load Object...", ID_OBJECT_LOAD + MENUITEM "&Save Object...", ID_OBJECT_SAVE + MENUITEM SEPARATOR + MENUITEM "&Copy String", ID_STACK_COPY + MENUITEM "C&opy Screen", ID_VIEW_COPY + MENUITEM "&Paste String", ID_STACK_PASTE + MENUITEM SEPARATOR + MENUITEM "&Reset Calculator", ID_VIEW_RESET, GRAYED + POPUP "&Backup" + BEGIN + MENUITEM "&Save", ID_BACKUP_SAVE, GRAYED + MENUITEM "&Restore", ID_BACKUP_RESTORE + , GRAYED + MENUITEM "&Delete", ID_BACKUP_DELETE, GRAYED + END END - - IDD_DISASM, DIALOG + POPUP "&View" BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 248 - TOPMARGIN, 5 - BOTTOMMARGIN, 158 + MENUITEM "Change &KML Script...", ID_VIEW_SCRIPT + END + POPUP "&Tools" + BEGIN + MENUITEM "D&isassembler...", ID_TOOL_DISASM + MENUITEM "&Debugger...", ID_TOOL_DEBUG + END + POPUP "&Help" + BEGIN + MENUITEM "&About Emu48...", ID_ABOUT END END + +IDR_DEBUG MENU DISCARDABLE +BEGIN + POPUP "&Debug" + BEGIN + MENUITEM "&Run\tF5", ID_DEBUG_RUN + MENUITEM "&Step Into\tF7", ID_DEBUG_STEP + MENUITEM "Step &Over\tF8", ID_DEBUG_STEPOVER + MENUITEM "Step O&ut\tF9", ID_DEBUG_STEPOUT + MENUITEM "&Break\tF11", ID_DEBUG_BREAK + END + POPUP "&Breakpoints" + BEGIN + MENUITEM "Set &breakpoint\tF2", ID_BREAKPOINTS_SETBREAK + MENUITEM "&Edit breakpoints...", ID_BREAKPOINTS_CODEEDIT + MENUITEM "&Clear all breakpoints", ID_BREAKPOINTS_CLEARALL + MENUITEM SEPARATOR + MENUITEM "&NOP3 code breakpoints", ID_BREAKPOINTS_NOP3 + END +END + +IDR_DEBUG_CODE MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "&Go to address...\tG", ID_DEBUG_CODE_GOADR + MENUITEM "Go to &PC", ID_DEBUG_CODE_GOPC + MENUITEM "Set &breakpoint\tF2", ID_BREAKPOINTS_SETBREAK + MENUITEM "&Set PC to selection", ID_DEBUG_CODE_SETPCTOSELECT + END +END + +IDR_DEBUG_MEM MENU DISCARDABLE +BEGIN + POPUP "" + BEGIN + MENUITEM "&Go to address...\tG", ID_DEBUG_MEM_GOADR + MENUITEM "Go to &PC", ID_DEBUG_MEM_GOPC + MENUITEM "Go to D&0", ID_DEBUG_MEM_GOD0 + MENUITEM "Go to D&1", ID_DEBUG_MEM_GOD1 + MENUITEM "Go to &Stack", ID_DEBUG_MEM_GOSTACK + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + #endif // APSTUDIO_INVOKED #endif // French (France) resources diff --git a/sources/Emu48/ENGINE.C b/sources/Emu48/ENGINE.C index b11bb4d..00c9bfe 100644 --- a/sources/Emu48/ENGINE.C +++ b/sources/Emu48/ENGINE.C @@ -8,81 +8,72 @@ */ #include "pch.h" #include "Emu48.h" -#include "Serial.h" +#include "Opcodes.h" +#include "io.h" // 24.10.99 cg, renamed from Serial.h +#include "debugger.h" -// HST bits -#define XM 1 -#define SB 2 -#define SR 4 -#define MP 8 - -#pragma intrinsic(memset,memcpy) - -#define w Chipset -#define PCHANGED ((void)(F_s[0]=w.P,F_l[1]=w.P+1)) -#define GOYES3 {if(w.carry)goto o_goyes3;else{w.pc+=2;continue;}} -#define GOYES5 {if(w.carry)goto o_goyes5;else{w.pc+=2;continue;}} -#define INTERRUPT ((void)(w.SoftInt=TRUE,bInterrupt=TRUE)) - -#define SAMPLE 16384 // 23.04.98 cg, new, speed adjust sample frequency - -// 23.04.98 cg, new, cpu cycles for interval -#define T2CYCLES ((cCurrentRomType=='S')?dwSXCycles:dwGXCycles) - -//#define FASTPTR(d) (RMap[d>>12]+(d&0xFFF)) -static __inline LPBYTE FASTPTR(DWORD d) -{ - // 17.12.98 cg, bugfix, code is running in IO area as well - if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase)) - return Chipset.IORam+d-Chipset.IOBase; - - return RMap[d>>12]+(d&0xFFF); -} - -#include "Ops.h" +#define SAMPLE 16384 // speed adjust sample frequency BOOL bInterrupt = FALSE; UINT nState = 1; UINT nNextState = 0; -BOOL bKeySlow = FALSE; // 18.11.98 cg, new, slow down for key emulation +BOOL bRealSpeed = FALSE; // 11.12.99 cg, moved from Emu48.c +BOOL bKeySlow = FALSE; // slow down for key emulation CHIPSET Chipset; -char szSerialWire[16]; // 20.05.98 cg, new, devicename for wire port -char szSerialIr[16]; // 20.05.98 cg, new, devicename for IR port +char szSerialWire[16]; // evicename for wire port +char szSerialIr[16]; // devicename for IR port -DWORD dwSXCycles = 82; // 23.04.98 cg, new, SX cpu cycles in interval -DWORD dwGXCycles = 123; // 23.04.98 cg, new, GX cpu cycles in interval +DWORD dwSXCycles = 82; // SX cpu cycles in interval +DWORD dwGXCycles = 123; // GX cpu cycles in interval -static BOOL bCommInit = FALSE; // 17.05.98 cg, new, COM port not open -static BOOL bRealSpeed = FALSE; // 23.04.98 cg, new, enable/disable real speed +static BOOL bCommInit = FALSE; // COM port not open +static BOOL bCpuSlow = FALSE; // 11.12.99 cg, renamed, enable/disable real speed -static DWORD dwOldCyc; // 23.04.98 cg, new, cpu cycles at last event -static DWORD dwSpeedRef; // 23.04.98 cg, new, timer value at last event -static DWORD dwTickRef; // 23.04.98 cg, new, sample timer ticks +static DWORD dwOldCyc; // cpu cycles at last event +static DWORD dwSpeedRef; // timer value at last event +static DWORD dwTickRef; // sample timer ticks -static __inline VOID CheckSerial(VOID) // 17.05.98 cg, new function - // 25.02.99 cg, changed, inline coded now +#include "Ops.h" + +static __inline VOID CheckDisp(BOOL bSync) +{ + if (disp == 0) return; // no display update need + + // update display when drawing top line or display is off + if (bSync && GetLineCounter() != 0x3F && (Chipset.IORam[0x00]&8)) + return; + + _ASSERT((disp & DISP_POINTER) == 0); // display pointer already updated + if (disp & DISP_MAIN) UpdateMainDisplay(); + if (disp & DISP_MENUE) UpdateMenuDisplay(); + _ASSERT((disp & DISP_ANNUN) == 0); // annunciators already updated + disp = 0; // display updated + return; +} + +static __inline VOID CheckSerial(VOID) { if (ioc_acc) // IOC changed { ioc_acc = FALSE; // COM port closed and serial on - if (bCommInit == FALSE && (Chipset.IORam[IO_CTRL] & SON) != 0) + if (bCommInit == FALSE && (Chipset.IORam[IOC] & SON) != 0) { CommOpen(szSerialWire,szSerialIr); // open COM ports bCommInit = CommConnect() != PORT_CLOSE; } // COM port opend and serial off - if (bCommInit == TRUE && (Chipset.IORam[IO_CTRL] & SON) == 0) + if (bCommInit == TRUE && (Chipset.IORam[IOC] & SON) == 0) { CommClose(); // close COM port bCommInit = FALSE; } // Interrupt on recv buffer full and receive buffer full - if ((Chipset.IORam[IO_CTRL] & ERBF) && (Chipset.IORam[RCS] & RBF)) + if ((Chipset.IORam[IOC] & ERBF) && (Chipset.IORam[RCS] & RBF)) { Chipset.Shutdn = FALSE; INTERRUPT; @@ -90,13 +81,13 @@ static __inline VOID CheckSerial(VOID) // 17.05.98 cg, new function } } -static __inline VOID AdjustSpeed(VOID) // 23.04.98 cg, new, adjust emulation speed - // 25.02.99 cg, changed, inline coded now +static __inline VOID AdjustSpeed(VOID) // adjust emulation speed { - if (bRealSpeed || bKeySlow) // 18.11.98 cg, changed, slow down + if (bCpuSlow || bKeySlow) // 11.12.99 cg, changed, emulation slow down { // cycles elapsed for next check - if (Chipset.cycles-dwOldCyc >= (DWORD) T2CYCLES) + // 22.11.99 cg, changed, DWORD casting of Chipset.cycles + if ((DWORD) (Chipset.cycles & 0xFFFFFFFF)-dwOldCyc >= (DWORD) T2CYCLES) { LARGE_INTEGER lAct; do @@ -113,14 +104,12 @@ static __inline VOID AdjustSpeed(VOID) // 23.04.98 cg, new, adjust emulation sp return; } -static VOID AdjKeySpeed(VOID) // 05.07.98 cg, new, slow down key repeat - // 18.11.98 cg, bugfix, slow down whole emulation, - // when key pressed +VOID AdjKeySpeed(VOID) // slow down key repeat { WORD i; BOOL bKey; - if (bRealSpeed) return; // no need to slow down + if (bCpuSlow) return; // 11.12.99 cg, changed, no need to slow down bKey = FALSE; // search for a pressed key for (i = 0;i < sizeof(Chipset.Keyboard_Row) / sizeof(Chipset.Keyboard_Row[0]) && !bKey;++i) @@ -129,7 +118,9 @@ static VOID AdjKeySpeed(VOID) // 05.07.98 cg, new, slow down key repeat if (!bKeySlow && bKey) // key pressed, init variables { LARGE_INTEGER lTime; // sample timer ticks - dwOldCyc = Chipset.cycles; // save reference cycles + // save reference cycles + // 22.11.99 cg, changed, DWORD casting + dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); QueryPerformanceCounter(&lTime); // get timer ticks dwSpeedRef = lTime.LowPart; // save reference time } @@ -137,25 +128,28 @@ static VOID AdjKeySpeed(VOID) // 05.07.98 cg, new, slow down key repeat return; } -VOID SetSpeed(BOOL bAdjust) // 23.04.98 cg, new, set emulation speed +VOID SetSpeed(BOOL bAdjust) // set emulation speed { - if (bAdjust) // 15.05.98 cg, changed, switch to real speed + if (bAdjust) // switch to real speed { LARGE_INTEGER lTime; // sample timer ticks - dwOldCyc = Chipset.cycles; // save reference cycles + // save reference cycles + // 22.11.99 cg, changed, DWORD casting + dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); QueryPerformanceCounter(&lTime); // get timer ticks dwSpeedRef = lTime.LowPart; // save reference time } - bRealSpeed = bAdjust; // 15.05.98 cg, bugfix, save emulation speed + bCpuSlow = bAdjust; // 11.12.99 cg, changed, save emulation speed } -VOID UpdateKdnBit(VOID) // 25.02.99 cg, new, update KDN bit +VOID UpdateKdnBit(VOID) // update KDN bit { - if (Chipset.intk && Chipset.cycles - Chipset.dwKdnCycles > (DWORD) T2CYCLES * 16) + // 22.11.99 cg, changed, DWORD casting of Chipset.cycles + if (Chipset.intk && (DWORD) (Chipset.cycles & 0xFFFFFFFFF) - Chipset.dwKdnCycles > (DWORD) T2CYCLES * 16) IOBit(0x19,8,Chipset.in != 0); } -BOOL WaitForSleepState(VOID) // 16.06.98 cg, new, wait for cpu SHUTDN then sleep state +BOOL WaitForSleepState(VOID) // wait for cpu SHUTDN then sleep state { DWORD dwRefTime = timeGetTime(); @@ -177,12 +171,17 @@ UINT SwitchToState(UINT nNewState) switch (nState) { case 0: // Run + if (hDlgDebug) // debugger running + { + DestroyWindow(hDlgDebug); // then close debugger to renter emulation + hDlgDebug = NULL; + } switch (nNewState) { case 1: // -> Invalid nNextState = 1; if (Chipset.Shutdn) - ResumeThread(hThread); + SetEvent(hEventShutdn); else bInterrupt = TRUE; while (nState!=nNextState) Sleep(0); @@ -191,19 +190,19 @@ UINT SwitchToState(UINT nNewState) case 2: // -> Return nNextState = 1; if (Chipset.Shutdn) - ResumeThread(hThread); + SetEvent(hEventShutdn); else bInterrupt = TRUE; while (nState!=nNextState) Sleep(0); nNextState = 2; - ResumeThread(hThread); + SetEvent(hEventShutdn); while (nState!=nNextState) Sleep(0); UpdateWindowStatus(); break; case 3: // -> Sleep nNextState = 3; if (Chipset.Shutdn) - ResumeThread(hThread); + SetEvent(hEventShutdn); else bInterrupt = TRUE; while (nState!=nNextState) Sleep(0); @@ -216,24 +215,18 @@ UINT SwitchToState(UINT nNewState) case 0: // -> Run nNextState = 0; bInterrupt = FALSE; - // 16.05.98 cg, bugfix, wait until thread is down, then resume - while (ResumeThread(hThread)==0) Sleep(0); -// ResumeThread(hThread); + SetEvent(hEventShutdn); while (nState!=nNextState) Sleep(0); UpdateWindowStatus(); break; case 2: // -> Return nNextState = 2; - // 16.05.98 cg, bugfix, wait until thread is down, then resume - while (ResumeThread(hThread)==0) Sleep(0); -// ResumeThread(hThread); + SetEvent(hEventShutdn); while (nState!=nNextState) Sleep(0); break; case 3: // -> Sleep nNextState = 3; - // 16.05.98 cg, bugfix, wait until thread is down, then resume - while (ResumeThread(hThread)==0) Sleep(0); -// ResumeThread(hThread); + SetEvent(hEventShutdn); while (nState!=nNextState) Sleep(0); UpdateWindowStatus(); break; @@ -245,29 +238,20 @@ UINT SwitchToState(UINT nNewState) case 0: // -> Run nNextState = 0; if (Chipset.Shutdn) bInterrupt=TRUE; - // 16.05.98 cg, bugfix, wait until thread is down, then resume - while (ResumeThread(hThread)==0) Sleep(0); -// ResumeThread(hThread); - //while (nState!=nNextState) Sleep(0); + SetEvent(hEventShutdn); break; case 1: // -> Invalid nNextState = 1; - // 16.05.98 cg, bugfix, wait until thread is down, then resume - while (ResumeThread(hThread)==0) Sleep(0); -// ResumeThread(hThread); + SetEvent(hEventShutdn); while (nState!=nNextState) Sleep(0); UpdateWindowStatus(); break; case 2: // -> Return nNextState = 1; - // 16.05.98 cg, bugfix, wait until thread is down, then resume - while (ResumeThread(hThread)==0) Sleep(0); -// ResumeThread(hThread); + SetEvent(hEventShutdn); while (nState!=nNextState) Sleep(0); nNextState = 2; - // 16.05.98 cg, bugfix, wait until thread is down, then resume - while (ResumeThread(hThread)==0) Sleep(0); -// ResumeThread(hThread); + SetEvent(hEventShutdn); while (nState!=nNextState) Sleep(0); UpdateWindowStatus(); break; @@ -279,82 +263,140 @@ UINT SwitchToState(UINT nNewState) UINT WorkerThread(LPVOID pParam) { - LARGE_INTEGER lDummyInt; // 23.04.98 cg, new, sample timer ticks - QueryPerformanceFrequency(&lDummyInt); // 23.04.98 cg, new, init timer ticks - lDummyInt.QuadPart /= SAMPLE; // 23.04.98 cg, new, calculate sample ticks - dwTickRef = lDummyInt.LowPart; // 23.04.98 cg, new, sample timer ticks - _ASSERT(dwTickRef); // 23.04.98 cg, new, tick resolution error + LARGE_INTEGER lDummyInt; // sample timer ticks + QueryPerformanceFrequency(&lDummyInt); // init timer ticks + lDummyInt.QuadPart /= SAMPLE; // calculate sample ticks + dwTickRef = lDummyInt.LowPart; // sample timer ticks + _ASSERT(dwTickRef); // tick resolution error loop: while (nNextState == 1) // go into invalid state { - CommClose(); // 17.05.98 cg, new, close COM port - bCommInit = FALSE; // 17.05.98 cg, new, COM port not open + CommClose(); // close COM port + bCommInit = FALSE; // COM port not open nState = 1; // in invalid state - SuspendThread(hThread); // sleep thread + WaitForSingleObject(hEventShutdn,INFINITE); if (nNextState == 2) // go into return state { nState = 2; // in return state return 0; // kill thread } - ioc_acc = TRUE; // 17.05.98 cg, new, test if UART on + ioc_acc = TRUE; // test if UART on } while (nNextState == 0) { if (nState!=0) { nState = 0; - if (Chipset.type == 'S') + // clear port2 status bits + Chipset.cards_status &= ~(PORT2_PRESENT | PORT2_WRITE); + if (pbyPort2 || Chipset.Port2) // card plugged in port2 { - Chipset.cards_status &= 0x5; - if (pbyPort2) Chipset.cards_status |= 0x2; - if (bPort2Writeable) Chipset.cards_status |= 0x8; - } - else - { - Chipset.cards_status &= 0xA; - if (pbyPort2) Chipset.cards_status |= 0x1; - if (bPort2Writeable) Chipset.cards_status |= 0x4; + Chipset.cards_status |= PORT2_PRESENT; + + if (bPort2Writeable) // is card writeable + Chipset.cards_status |= PORT2_WRITE; } + RomSwitch(Chipset.Bank_FF); // select HP49G ROM bank and update memory mapping UpdateDisplayPointers(); UpdateMainDisplay(); UpdateMenuDisplay(); UpdateAnnunciators(); - // 23.04.98 cg, new, init speed reference - dwOldCyc = Chipset.cycles; + // init speed reference + // 22.11.99 cg, changed, DWORD casting + dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); QueryPerformanceCounter(&lDummyInt); dwSpeedRef = lDummyInt.LowPart; - // 23.04.98 cg, end of init + SetHP48Time(); // update HP48 time & date StartTimers(); } PCHANGED; while (!bInterrupt) { - do - { - LPBYTE I = FASTPTR(w.pc); - #include "Fetch.h" - #include "Opcodes.h" - } - while(0); // 23.04.98 cg, workaround for continue + LPBYTE I = FASTPTR(Chipset.pc); - CheckSerial(); // 17.05.98 cg, serial support - AdjustSpeed(); // 23.04.98 cg, adjust emulation speed + if (bDbgEnable) // debugger active + { + BOOL bStopEmulation; + + // 13.11.99 cg, changed, check for step into + bStopEmulation = (nDbgState == DBG_STEPINTO); + + // check for step over + bStopEmulation |= (nDbgState == DBG_STEPOVER) && dwDbgRstkp == Chipset.rstkp; + + // 13.11.99 cg, new, check for step out, something was popped from hardware stack + if (nDbgState == DBG_STEPOUT && dwDbgRstkp == Chipset.rstkp) + { + _ASSERT(bStopEmulation == FALSE); + if ((bStopEmulation = (Chipset.pc == dwDbgRstk)) == FALSE) + { + // it was C=RSTK, check for next object popped from hardware stack + dwDbgRstkp = (Chipset.rstkp-1)&7; + dwDbgRstk = Chipset.rstk[dwDbgRstkp]; + } + } + // 13.11.99 cg, end of step out implementation + + // check for breakpoints + bStopEmulation |= CheckBreakpoint(Chipset.pc); + + // NOP3, opcode #420 (GOC) + if (bDbgNOP3 && I[0] == 0x4 && I[1] == 0x2 && I[2] == 0x0) + bStopEmulation = TRUE; + + if (bStopEmulation) // stop condition + { + StopTimers(); // hold timer values when emulator is stopped + + OutputDebugString("Emulator stopped...\n"); + NotifyDebugger(); // 10.11.99 cg, changed, update registers + WaitForSingleObject(hEventDebug,INFINITE); + OutputDebugString("Emulator running...\n"); + + + // @todo add timer emulation + + + StartTimers(); // continue timers + + Chipset.Shutdn = FALSE; + Chipset.bShutdnWake = FALSE; + + // init slow down part + // 22.11.99 cg, changed, DWORD casting + dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); + QueryPerformanceCounter(&lDummyInt); + dwSpeedRef = lDummyInt.LowPart; + } + } + + EvalOpcode(I); + + CheckDisp(!Chipset.Shutdn); // check for display update + CheckSerial(); // serial support + AdjustSpeed(); // adjust emulation speed } - if (Chipset.Shutdn) + bInterrupt = FALSE; // be sure to reenter opcode loop + + // enter SHUTDN handler only in RUN mode + if (Chipset.Shutdn && !(nDbgState == DBG_STEPINTO || nDbgState == DBG_STEPOVER)) { - bInterrupt = FALSE; - SuspendThread(hThread); - Chipset.Shutdn = FALSE; - // 23.04.98 cg, new, init speed reference - dwOldCyc = Chipset.cycles; - QueryPerformanceCounter(&lDummyInt); - dwSpeedRef = lDummyInt.LowPart; - // 23.04.98 cg, end of init + WaitForSingleObject(hEventShutdn,INFINITE); + + if (Chipset.bShutdnWake) // waked up by timer, keyboard or serial + { + Chipset.bShutdnWake = FALSE; + Chipset.Shutdn = FALSE; + // init speed reference + // 22.11.99 cg, changed, DWORD casting + dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); + QueryPerformanceCounter(&lDummyInt); + dwSpeedRef = lDummyInt.LowPart; + } } if (Chipset.SoftInt) { - bInterrupt = FALSE; Chipset.SoftInt = FALSE; if (Chipset.inte) { @@ -372,7 +414,7 @@ loop: while (nNextState == 3) // go into sleep state { nState = 3; // in sleep state - SuspendThread(hThread); // sleep thread + WaitForSingleObject(hEventShutdn,INFINITE); } goto loop; UNREFERENCED_PARAMETER(pParam); diff --git a/sources/Emu48/EXTERNAL.C b/sources/Emu48/EXTERNAL.C index 8f36a7b..9468714 100644 --- a/sources/Emu48/EXTERNAL.C +++ b/sources/Emu48/EXTERNAL.C @@ -9,8 +9,20 @@ #include "pch.h" #include "Emu48.h" -// 02.02.98 cg, new, memory address for flags -53 to -56 -#define SFLAG53_56 ((cCurrentRomType=='S')?0x706D2:0x80850) +//| 38G | 48SX | 48GX | 49G | Name +//#F0E4F #706D2 #80850 #80F0F =SFLAG53_56 + +// memory address for flags -53 to -56 +#define SFLAG53_56 ( (cCurrentRomType=='A') \ + ? 0xF0E4F \ + : ( (cCurrentRomType!='X') \ + ? ( (cCurrentRomType=='S') \ + ? 0x706D2 \ + : 0x80850 \ + ) \ + : 0x80F0F \ + ) \ + ) static __inline VOID Return(CHIPSET* w) { @@ -20,45 +32,34 @@ static __inline VOID Return(CHIPSET* w) return; } -VOID External(CHIPSET* w) +VOID External(CHIPSET* w) // Beep patch { - if (w->pc==0x017A6) // Beep + BYTE fbeep; + DWORD freq,dur; + + freq = Npack(w->D,5); // frequency in Hz + dur = Npack(w->C,5); // duration in ms + Nread(&fbeep,SFLAG53_56,1); // fetch system flags -53 to -56 + + w->carry = TRUE; // setting of no beep + if (!(fbeep & 0x8) && freq) // bit -56 clear and frequency > 0 Hz { - // begin with patch - // 02.02.98 cg, changed for better emulation - BYTE fbeep; - DWORD freq,dur; + if (freq < 37) freq = 37; // low limit of freqency (NT) + if (freq > 4400) freq = 4400; // high limit of HP (SX) - freq = Npack(w->D,5); // frequency in Hz - dur = Npack(w->C,5); // duration in ms - Nread(&fbeep,SFLAG53_56,1); // fetch system flags -53 to -56 + if (dur > 1048575) // high limit of HP (SX) + dur = 1048575; - w->carry = TRUE; // 22.07.98 cg, setting of no beep - if (!(fbeep & 0x8) && freq) // bit -56 clear and frequency > 0 Hz - { - if (freq < 37) freq = 37; // low limit of freqency (NT) - if (freq > 4400) freq = 4400; // 22.07.98 cg, high limit of HP (SX) + Beep(freq,dur); // NT: ok, Windows 95: default sound or standard system beep - if (dur > 1048575) // 22.07.98 cg, high limit of HP (SX) - dur = 1048575; + // estimate cpu cycles for beeping time (2MHz / 4MHz) + w->cycles += dur * ((cCurrentRomType=='S') ? 2000 : 4000); - Beep(freq,dur); // NT: ok, Windows 95: default sound or standard system beep - - // 22.07.98 cg, estimate cpu cycles for beeping time (2MHz / 4MHz) - w->cycles += dur * ((cCurrentRomType=='S') ? 2000 : 4000); - - // original routine return with... - w->P = 0; // 22.07.98 cg, P=0 - w->intk = TRUE; // 22.07.98 cg, INTON - w->carry = FALSE; // 22.07.98 cg, RTNCC - } - // MessageBeep(0xFFFFFFFF); // original, replaced - // continue with original part - - //Beep(600,50); - Return(w); - return; + // original routine return with... + w->P = 0; // P=0 + w->intk = TRUE; // INTON + w->carry = FALSE; // RTNCC } - w->pc +=4; + Return(w); return; } diff --git a/sources/Emu48/Emu48.mak b/sources/Emu48/Emu48.mak deleted file mode 100644 index 40c2721..0000000 --- a/sources/Emu48/Emu48.mak +++ /dev/null @@ -1,442 +0,0 @@ -# Microsoft Developer Studio Generated NMAKE File, Format Version 40001 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Application" 0x0101 - -!IF "$(CFG)" == "" -CFG=Emu48 - Win32 Debug -!MESSAGE No configuration specified. Defaulting to Emu48 - Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "Emu48 - Win32 Release" && "$(CFG)" != "Emu48 - Win32 Debug" -!MESSAGE Invalid configuration "$(CFG)" specified. -!MESSAGE You can specify a configuration when running NMAKE on this makefile -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "Emu48.mak" CFG="Emu48 - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Emu48 - Win32 Release" (based on "Win32 (x86) Application") -!MESSAGE "Emu48 - Win32 Debug" (based on "Win32 (x86) Application") -!MESSAGE -!ERROR An invalid configuration is specified. -!ENDIF - -!IF "$(OS)" == "Windows_NT" -NULL= -!ELSE -NULL=nul -!ENDIF -################################################################################ -# Begin Project -RSC=rc.exe -CPP=cl.exe -MTL=mktyplib.exe - -!IF "$(CFG)" == "Emu48 - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -OUTDIR=.\Release -INTDIR=.\Release - -ALL : "$(OUTDIR)\Emu48.exe" - -CLEAN : - -@erase ".\Release\Emu48.exe" - -@erase ".\Release\timer.obj" - -@erase ".\Release\Emu48.pch" - -@erase ".\Release\rpl.obj" - -@erase ".\Release\pch.obj" - -@erase ".\Release\mops.obj" - -@erase ".\Release\kml.obj" - -@erase ".\Release\keyboard.obj" - -@erase ".\Release\files.obj" - -@erase ".\Release\external.obj" - -@erase ".\Release\engine.obj" - -@erase ".\Release\Emu48.obj" - -@erase ".\Release\display.obj" - -@erase ".\Release\Emu48.res" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"pch.h" /c -CPP_PROJ=/nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ - /Fp"$(INTDIR)/Emu48.pch" /Yu"pch.h" /Fo"$(INTDIR)/" /c -CPP_OBJS=.\Release/ -CPP_SBRS= -# ADD BASE MTL /nologo /D "NDEBUG" /win32 -# ADD MTL /nologo /D "NDEBUG" /win32 -MTL_PROJ=/nologo /D "NDEBUG" /win32 -# ADD BASE RSC /l 0x40c /d "NDEBUG" -# ADD RSC /l 0x40c /d "NDEBUG" -RSC_PROJ=/l 0x40c /fo"$(INTDIR)/Emu48.res" /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/Emu48.bsc" -BSC32_SBRS= -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib /nologo /subsystem:windows /machine:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib /nologo\ - /subsystem:windows /incremental:no /pdb:"$(OUTDIR)/Emu48.pdb" /machine:I386\ - /out:"$(OUTDIR)/Emu48.exe" -LINK32_OBJS= \ - "$(INTDIR)/timer.obj" \ - "$(INTDIR)/rpl.obj" \ - "$(INTDIR)/pch.obj" \ - "$(INTDIR)/mops.obj" \ - "$(INTDIR)/kml.obj" \ - "$(INTDIR)/keyboard.obj" \ - "$(INTDIR)/files.obj" \ - "$(INTDIR)/external.obj" \ - "$(INTDIR)/engine.obj" \ - "$(INTDIR)/Emu48.obj" \ - "$(INTDIR)/display.obj" \ - "$(INTDIR)/Emu48.res" - -"$(OUTDIR)\Emu48.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "Emu48 - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -OUTDIR=.\Debug -INTDIR=.\Debug - -ALL : "$(OUTDIR)\Emu48.exe" - -CLEAN : - -@erase ".\Debug\Emu48.exe" - -@erase ".\Debug\timer.obj" - -@erase ".\Debug\Emu48.pch" - -@erase ".\Debug\rpl.obj" - -@erase ".\Debug\pch.obj" - -@erase ".\Debug\mops.obj" - -@erase ".\Debug\kml.obj" - -@erase ".\Debug\keyboard.obj" - -@erase ".\Debug\files.obj" - -@erase ".\Debug\external.obj" - -@erase ".\Debug\engine.obj" - -@erase ".\Debug\Emu48.obj" - -@erase ".\Debug\display.obj" - -@erase ".\Debug\Emu48.res" - -@erase ".\Debug\Emu48.ilk" - -@erase ".\Debug\Emu48.pdb" - -@erase ".\Debug\vc40.pdb" - -@erase ".\Debug\vc40.idb" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /Zp8 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"pch.h" /c -CPP_PROJ=/nologo /Zp8 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D\ - "_WINDOWS" /Fp"$(INTDIR)/Emu48.pch" /Yu"pch.h" /Fo"$(INTDIR)/" /Fd"$(INTDIR)/"\ - /c -CPP_OBJS=.\Debug/ -CPP_SBRS= -# ADD BASE MTL /nologo /D "_DEBUG" /win32 -# ADD MTL /nologo /D "_DEBUG" /win32 -MTL_PROJ=/nologo /D "_DEBUG" /win32 -# ADD BASE RSC /l 0x40c /d "_DEBUG" -# ADD RSC /l 0x40c /d "_DEBUG" -RSC_PROJ=/l 0x40c /fo"$(INTDIR)/Emu48.res" /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/Emu48.bsc" -BSC32_SBRS= -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib /nologo /subsystem:windows /debug /machine:I386 -LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib /nologo\ - /subsystem:windows /incremental:yes /pdb:"$(OUTDIR)/Emu48.pdb" /debug\ - /machine:I386 /out:"$(OUTDIR)/Emu48.exe" -LINK32_OBJS= \ - "$(INTDIR)/timer.obj" \ - "$(INTDIR)/rpl.obj" \ - "$(INTDIR)/pch.obj" \ - "$(INTDIR)/mops.obj" \ - "$(INTDIR)/kml.obj" \ - "$(INTDIR)/keyboard.obj" \ - "$(INTDIR)/files.obj" \ - "$(INTDIR)/external.obj" \ - "$(INTDIR)/engine.obj" \ - "$(INTDIR)/Emu48.obj" \ - "$(INTDIR)/display.obj" \ - "$(INTDIR)/Emu48.res" - -"$(OUTDIR)\Emu48.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ENDIF - -.c{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_OBJS)}.obj: - $(CPP) $(CPP_PROJ) $< - -.c{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cpp{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -.cxx{$(CPP_SBRS)}.sbr: - $(CPP) $(CPP_PROJ) $< - -################################################################################ -# Begin Target - -# Name "Emu48 - Win32 Release" -# Name "Emu48 - Win32 Debug" - -!IF "$(CFG)" == "Emu48 - Win32 Release" - -!ELSEIF "$(CFG)" == "Emu48 - Win32 Debug" - -!ENDIF - -################################################################################ -# Begin Source File - -SOURCE=.\timer.c -DEP_CPP_TIMER=\ - ".\pch.h"\ - ".\Emu48.h"\ - ".\types.h"\ - - -"$(INTDIR)\timer.obj" : $(SOURCE) $(DEP_CPP_TIMER) "$(INTDIR)"\ - "$(INTDIR)\Emu48.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\rpl.c -DEP_CPP_RPL_C=\ - ".\pch.h"\ - ".\Emu48.h"\ - ".\types.h"\ - - -"$(INTDIR)\rpl.obj" : $(SOURCE) $(DEP_CPP_RPL_C) "$(INTDIR)"\ - "$(INTDIR)\Emu48.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\pch.c -DEP_CPP_PCH_C=\ - ".\pch.h"\ - - -!IF "$(CFG)" == "Emu48 - Win32 Release" - -# ADD CPP /Yc"pch.h" - -BuildCmds= \ - $(CPP) /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ - /Fp"$(INTDIR)/Emu48.pch" /Yc"pch.h" /Fo"$(INTDIR)/" /c $(SOURCE) \ - - -"$(INTDIR)\pch.obj" : $(SOURCE) $(DEP_CPP_PCH_C) "$(INTDIR)" - $(BuildCmds) - -"$(INTDIR)\Emu48.pch" : $(SOURCE) $(DEP_CPP_PCH_C) "$(INTDIR)" - $(BuildCmds) - -!ELSEIF "$(CFG)" == "Emu48 - Win32 Debug" - -# ADD CPP /Yc"pch.h" - -BuildCmds= \ - $(CPP) /nologo /Zp8 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D\ - "_WINDOWS" /Fp"$(INTDIR)/Emu48.pch" /Yc"pch.h" /Fo"$(INTDIR)/" /Fd"$(INTDIR)/"\ - /c $(SOURCE) \ - - -"$(INTDIR)\pch.obj" : $(SOURCE) $(DEP_CPP_PCH_C) "$(INTDIR)" - $(BuildCmds) - -"$(INTDIR)\Emu48.pch" : $(SOURCE) $(DEP_CPP_PCH_C) "$(INTDIR)" - $(BuildCmds) - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\mops.c -DEP_CPP_MOPS_=\ - ".\pch.h"\ - ".\Emu48.h"\ - ".\types.h"\ - - -"$(INTDIR)\mops.obj" : $(SOURCE) $(DEP_CPP_MOPS_) "$(INTDIR)"\ - "$(INTDIR)\Emu48.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\kml.c -DEP_CPP_KML_C=\ - ".\pch.h"\ - ".\Emu48.h"\ - ".\kml.h"\ - ".\types.h"\ - - -"$(INTDIR)\kml.obj" : $(SOURCE) $(DEP_CPP_KML_C) "$(INTDIR)"\ - "$(INTDIR)\Emu48.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\keyboard.c -DEP_CPP_KEYBO=\ - ".\pch.h"\ - ".\Emu48.h"\ - ".\types.h"\ - - -"$(INTDIR)\keyboard.obj" : $(SOURCE) $(DEP_CPP_KEYBO) "$(INTDIR)"\ - "$(INTDIR)\Emu48.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\files.c -DEP_CPP_FILES=\ - ".\pch.h"\ - ".\Emu48.h"\ - ".\kml.h"\ - ".\types.h"\ - - -"$(INTDIR)\files.obj" : $(SOURCE) $(DEP_CPP_FILES) "$(INTDIR)"\ - "$(INTDIR)\Emu48.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\external.c -DEP_CPP_EXTER=\ - ".\pch.h"\ - ".\Emu48.h"\ - ".\types.h"\ - - -"$(INTDIR)\external.obj" : $(SOURCE) $(DEP_CPP_EXTER) "$(INTDIR)"\ - "$(INTDIR)\Emu48.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\engine.c -DEP_CPP_ENGIN=\ - ".\pch.h"\ - ".\Emu48.h"\ - ".\Ops.h"\ - ".\types.h"\ - - -"$(INTDIR)\engine.obj" : $(SOURCE) $(DEP_CPP_ENGIN) "$(INTDIR)"\ - "$(INTDIR)\Emu48.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\Emu48.c -DEP_CPP_EMU48=\ - ".\pch.h"\ - ".\Emu48.h"\ - ".\kml.h"\ - ".\types.h"\ - - -"$(INTDIR)\Emu48.obj" : $(SOURCE) $(DEP_CPP_EMU48) "$(INTDIR)"\ - "$(INTDIR)\Emu48.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\display.c -DEP_CPP_DISPL=\ - ".\pch.h"\ - ".\Emu48.h"\ - ".\kml.h"\ - ".\types.h"\ - - -"$(INTDIR)\display.obj" : $(SOURCE) $(DEP_CPP_DISPL) "$(INTDIR)"\ - "$(INTDIR)\Emu48.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\Emu48.rc -DEP_RSC_EMU48_=\ - ".\Emu48.ico"\ - - -"$(INTDIR)\Emu48.res" : $(SOURCE) $(DEP_RSC_EMU48_) "$(INTDIR)" - $(RSC) $(RSC_PROJ) $(SOURCE) - - -# End Source File -# End Target -# End Project -################################################################################ diff --git a/sources/Emu48/Emu48.mdp b/sources/Emu48/Emu48.mdp deleted file mode 100644 index cf45f75..0000000 Binary files a/sources/Emu48/Emu48.mdp and /dev/null differ diff --git a/sources/Emu48/FETCH.C b/sources/Emu48/FETCH.C new file mode 100644 index 0000000..550d10f --- /dev/null +++ b/sources/Emu48/FETCH.C @@ -0,0 +1,777 @@ +/* + * fetch.c + * + * This file is part of Emu48 + * + * Copyright (C) 1999 Christoph Gießelink + * + */ +#include "pch.h" +#include "Opcodes.h" + +#define F 0xFF // F = function + +typedef struct +{ + const VOID *pLnk; + const DWORD dwTyp; +} JMPTAB; + +// jump tables +static const JMPTAB oF_[] = +{ + oF0, F, + oF1, F, + oF2, F, + oF3, F, + oF4, F, + oF5, F, + oF6, F, + oF7, F, + oF8, F, + oF9, F, + oFA, F, + oFB, F, + oFC, F, + oFD, F, + oFE, F, + oFF, F +}; + +static const JMPTAB oE_[] = +{ + oE0, F, + oE1, F, + oE2, F, + oE3, F, + oE4, F, + oE5, F, + oE6, F, + oE7, F, + oE8, F, + oE9, F, + oEA, F, + oEB, F, + oEC, F, + oED, F, + oEE, F, + oEF, F +}; + +static const JMPTAB oD_[] = +{ + oD0, F, + oD1, F, + oD2, F, + oD3, F, + oD4, F, + oD5, F, + oD6, F, + oD7, F, + oD8, F, + oD9, F, + oDA, F, + oDB, F, + oDC, F, + oDD, F, + oDE, F, + oDF, F +}; + +static const JMPTAB oC_[] = +{ + oC0, F, + oC1, F, + oC2, F, + oC3, F, + oC4, F, + oC5, F, + oC6, F, + oC7, F, + oC8, F, + oC9, F, + oCA, F, + oCB, F, + oCC, F, + oCD, F, + oCE, F, + oCF, F +}; + +static const JMPTAB oBb_[] = +{ + oBb0, F, + oBb1, F, + oBb2, F, + oBb3, F, + oBb4, F, + oBb5, F, + oBb6, F, + oBb7, F, + oBb8, F, + oBb9, F, + oBbA, F, + oBbB, F, + oBbC, F, + oBbD, F, + oBbE, F, + oBbF, F +}; + +static const JMPTAB oBa_[] = +{ + oBa0, F, + oBa1, F, + oBa2, F, + oBa3, F, + oBa4, F, + oBa5, F, + oBa6, F, + oBa7, F, + oBa8, F, + oBa9, F, + oBaA, F, + oBaB, F, + oBaC, F, + oBaD, F, + oBaE, F, + oBaF, F +}; + +static const JMPTAB oB_[] = +{ + oBa_, 2, + oBa_, 2, + oBa_, 2, + oBa_, 2, + oBa_, 2, + oBa_, 2, + oBa_, 2, + oBa_, 2, + oBb_, 2, + oBb_, 2, + oBb_, 2, + oBb_, 2, + oBb_, 2, + oBb_, 2, + oBb_, 2, + oBb_, 2 +}; + +static const JMPTAB oAb_[] = +{ + oAb0, F, + oAb1, F, + oAb2, F, + oAb3, F, + oAb4, F, + oAb5, F, + oAb6, F, + oAb7, F, + oAb8, F, + oAb9, F, + oAbA, F, + oAbB, F, + oAbC, F, + oAbD, F, + oAbE, F, + oAbF, F +}; + +static const JMPTAB oAa_[] = +{ + oAa0, F, + oAa1, F, + oAa2, F, + oAa3, F, + oAa4, F, + oAa5, F, + oAa6, F, + oAa7, F, + oAa8, F, + oAa9, F, + oAaA, F, + oAaB, F, + oAaC, F, + oAaD, F, + oAaE, F, + oAaF, F +}; + +static const JMPTAB oA_[] = +{ + oAa_, 2, + oAa_, 2, + oAa_, 2, + oAa_, 2, + oAa_, 2, + oAa_, 2, + oAa_, 2, + oAa_, 2, + oAb_, 2, + oAb_, 2, + oAb_, 2, + oAb_, 2, + oAb_, 2, + oAb_, 2, + oAb_, 2, + oAb_, 2 +}; + +static const JMPTAB o9b_[] = +{ + o9b0, F, + o9b1, F, + o9b2, F, + o9b3, F, + o9b4, F, + o9b5, F, + o9b6, F, + o9b7, F, + o9b8, F, + o9b9, F, + o9bA, F, + o9bB, F, + o9bC, F, + o9bD, F, + o9bE, F, + o9bF, F +}; + +static const JMPTAB o9a_[] = +{ + o9a0, F, + o9a1, F, + o9a2, F, + o9a3, F, + o9a4, F, + o9a5, F, + o9a6, F, + o9a7, F, + o9a8, F, + o9a9, F, + o9aA, F, + o9aB, F, + o9aC, F, + o9aD, F, + o9aE, F, + o9aF, F +}; + +static const JMPTAB o9_[] = +{ + o9a_, 2, + o9a_, 2, + o9a_, 2, + o9a_, 2, + o9a_, 2, + o9a_, 2, + o9a_, 2, + o9a_, 2, + o9b_, 2, + o9b_, 2, + o9b_, 2, + o9b_, 2, + o9b_, 2, + o9b_, 2, + o9b_, 2, + o9b_, 2 +}; + +static const JMPTAB o8B_[] = +{ + o8B0, F, + o8B1, F, + o8B2, F, + o8B3, F, + o8B4, F, + o8B5, F, + o8B6, F, + o8B7, F, + o8B8, F, + o8B9, F, + o8BA, F, + o8BB, F, + o8BC, F, + o8BD, F, + o8BE, F, + o8BF, F +}; + +static const JMPTAB o8A_[] = +{ + o8A0, F, + o8A1, F, + o8A2, F, + o8A3, F, + o8A4, F, + o8A5, F, + o8A6, F, + o8A7, F, + o8A8, F, + o8A9, F, + o8AA, F, + o8AB, F, + o8AC, F, + o8AD, F, + o8AE, F, + o8AF, F +}; + +static const JMPTAB o81B_[] = +{ + o_invalid4, F, + o81B1, F, + o81B2, F, + o81B3, F, + o81B4, F, + o81B5, F, + o81B6, F, + o81B7, F, + o_invalid4, F, + o_invalid4, F, + o_invalid4, F, + o_invalid4, F, + o_invalid4, F, + o_invalid4, F, + o_invalid4, F, + o_invalid4, F +}; + +static const JMPTAB o81Af2_[] = +{ + o81Af20, F, + o81Af21, F, + o81Af22, F, + o81Af23, F, + o81Af24, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o81Af28, F, + o81Af29, F, + o81Af2A, F, + o81Af2B, F, + o81Af2C, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F +}; + +static const JMPTAB o81Af1_[] = +{ + o81Af10, F, + o81Af11, F, + o81Af12, F, + o81Af13, F, + o81Af14, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o81Af18, F, + o81Af19, F, + o81Af1A, F, + o81Af1B, F, + o81Af1C, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F +}; + +static const JMPTAB o81Af0_[] = +{ + o81Af00, F, + o81Af01, F, + o81Af02, F, + o81Af03, F, + o81Af04, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o81Af08, F, + o81Af09, F, + o81Af0A, F, + o81Af0B, F, + o81Af0C, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F +}; + +static const JMPTAB o81A_[] = +{ + o81Af0_, 5, + o81Af1_, 5, + o81Af2_, 5, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F +}; + +static const JMPTAB o819_[] = +{ + o819f0, F, + o819f1, F, + o819f2, F, + o819f3, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F +}; + +static const JMPTAB o818_[] = +{ + o818f0x, F, + o818f1x, F, + o818f2x, F, + o818f3x, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o818f8x, F, + o818f9x, F, + o818fAx, F, + o818fBx, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F, + o_invalid6, F +}; + +static const JMPTAB o81_[] = +{ + o810, F, + o811, F, + o812, F, + o813, F, + o814, F, + o815, F, + o816, F, + o817, F, + o818_, 4, + o819_, 4, + o81A_, 4, + o81B_, 3, + o81C, F, + o81D, F, + o81E, F, + o81F, F +}; + +static const JMPTAB o8081_[] = +{ + o80810, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F, + o_invalid5, F +}; + +static const JMPTAB o808_[] = +{ + o8080, F, + o8081_, 4, + o8082X, F, + o8083, F, + o8084n, F, + o8085n, F, + o8086n, F, + o8087n, F, + o8088n, F, + o8089n, F, + o808An, F, + o808Bn, F, + o808C, F, + o808D, F, + o808E, F, + o808F, F +}; + +static const JMPTAB o80_[] = +{ + o800, F, + o801, F, + o802, F, + o803, F, + o804, F, + o805, F, + o806, F, + o807, F, + o808_, 3, + o809, F, + o80A, F, + o80B, F, + o80Cn, F, + o80Dn, F, + o80E, F, + o80Fn, F +}; + +static const JMPTAB o8_[] = +{ + o80_, 2, + o81_, 2, + o82n, F, + o83n, F, + o84n, F, + o85n, F, + o86n, F, + o87n, F, + o88n, F, + o89n, F, + o8A_, 2, + o8B_, 2, + o8Cd4, F, + o8Dd5, F, + o8Ed4, F, + o8Fd5, F +}; + +static const JMPTAB o15_[] = +{ + o150a, F, + o151a, F, + o152a, F, + o153a, F, + o154a, F, + o155a, F, + o156a, F, + o157a, F, + o158x, F, + o159x, F, + o15Ax, F, + o15Bx, F, + o15Cx, F, + o15Dx, F, + o15Ex, F, + o15Fx, F +}; + +static const JMPTAB o14_[] = +{ + o140, F, + o141, F, + o142, F, + o143, F, + o144, F, + o145, F, + o146, F, + o147, F, + o148, F, + o149, F, + o14A, F, + o14B, F, + o14C, F, + o14D, F, + o14E, F, + o14F, F +}; + +static const JMPTAB o13_[] = +{ + o130, F, + o131, F, + o132, F, + o133, F, + o134, F, + o135, F, + o136, F, + o137, F, + o138, F, + o139, F, + o13A, F, + o13B, F, + o13C, F, + o13D, F, + o13E, F, + o13F, F +}; + +static const JMPTAB o12_[] = +{ + o120, F, + o121, F, + o122, F, + o123, F, + o124, F, + o_invalid3, F, + o_invalid3, F, + o_invalid3, F, + o128, F, + o129, F, + o12A, F, + o12B, F, + o12C, F, + o_invalid3, F, + o_invalid3, F, + o_invalid3, F +}; + +static const JMPTAB o11_[] = +{ + o110, F, + o111, F, + o112, F, + o113, F, + o114, F, + o_invalid3, F, + o_invalid3, F, + o_invalid3, F, + o118, F, + o119, F, + o11A, F, + o11B, F, + o11C, F, + o_invalid3, F, + o_invalid3, F, + o_invalid3, F +}; + +static const JMPTAB o10_[] = +{ + o100, F, + o101, F, + o102, F, + o103, F, + o104, F, + o_invalid3, F, + o_invalid3, F, + o_invalid3, F, + o108, F, + o109, F, + o10A, F, + o10B, F, + o10C, F, + o_invalid3, F, + o_invalid3, F, + o_invalid3, F +}; + +static const JMPTAB o1_[] = +{ + o10_, 2, + o11_, 2, + o12_, 2, + o13_, 2, + o14_, 2, + o15_, 2, + o16x, F, + o17x, F, + o18x, F, + o19d2, F, + o1Ad4, F, + o1Bd5, F, + o1Cx, F, + o1Dd2, F, + o1Ed4, F, + o1Fd5, F +}; + +static const JMPTAB o0E_[] = +{ + o0Ef0, F, + o0Ef1, F, + o0Ef2, F, + o0Ef3, F, + o0Ef4, F, + o0Ef5, F, + o0Ef6, F, + o0Ef7, F, + o0Ef8, F, + o0Ef9, F, + o0EfA, F, + o0EfB, F, + o0EfC, F, + o0EfD, F, + o0EfE, F, + o0EfF, F +}; + +static const JMPTAB o0_[] = +{ + o00, F, + o01, F, + o02, F, + o03, F, + o04, F, + o05, F, + o06, F, + o07, F, + o08, F, + o09, F, + o0A, F, + o0B, F, + o0C, F, + o0D, F, + o0E_, 3, + o0F, F +}; + +static const JMPTAB o_[] = +{ + o0_, 1, + o1_, 1, + o2n, F, + o3X, F, + o4d2, F, + o5d2, F, + o6d3, F, + o7d3, F, + o8_, 1, + o9_, 1, + oA_, 1, + oB_, 1, + oC_, 1, + oD_, 1, + oE_, 1, + oF_, 1 +}; + +// opcode dispatcher +VOID EvalOpcode(LPBYTE I) +{ + DWORD dwTemp,dwIndex = 0; + JMPTAB const *pJmpTab = o_; + + do + { + dwTemp = I[dwIndex]; // table entry + dwIndex = pJmpTab[dwTemp].dwTyp; // next pointer type + pJmpTab = pJmpTab[dwTemp].pLnk; // next pointer to table/function + } + while (dwIndex != F); // reference to table? -> again + + ((VOID (*)(LPBYTE)) pJmpTab)(I); // call function + return; +} diff --git a/sources/Emu48/FETCH.H b/sources/Emu48/FETCH.H deleted file mode 100644 index 68e74fb..0000000 --- a/sources/Emu48/FETCH.H +++ /dev/null @@ -1,675 +0,0 @@ -/* - * fetch.h - * - * This file is part of Emu48 - * - * Copyright (C) 1995 Sebastien Carlier - * - */ - -switch(I[0]) -{ -case 0x0: goto o0_; -case 0x1: goto o1_; -case 0x2: goto o2n; -case 0x3: goto o3X; -case 0x4: goto o4d2; -case 0x5: goto o5d2; -case 0x6: goto o6d3; -case 0x7: goto o7d3; -case 0x8: goto o8_; -case 0x9: goto o9_; -case 0xA: goto oA_; -case 0xB: goto oB_; -case 0xC: goto oC_; -case 0xD: goto oD_; -case 0xE: goto oE_; -case 0xF: goto oF_; -default : goto o_invalid; -} - -o0_: -switch(I[1]) -{ -case 0x0: goto o00; -case 0x1: goto o01; -case 0x2: goto o02; -case 0x3: goto o03; -case 0x4: goto o04; -case 0x5: goto o05; -case 0x6: goto o06; -case 0x7: goto o07; -case 0x8: goto o08; -case 0x9: goto o09; -case 0xA: goto o0A; -case 0xB: goto o0B; -case 0xC: goto o0C; -case 0xD: goto o0D; -case 0xE: goto o0E_; -case 0xF: goto o0F; -default : goto o_invalid; -} - -o0E_: -switch(I[3]) -{ -case 0x0: goto o0Ef0; -case 0x1: goto o0Ef1; -case 0x2: goto o0Ef2; -case 0x3: goto o0Ef3; -case 0x4: goto o0Ef4; -case 0x5: goto o0Ef5; -case 0x6: goto o0Ef6; -case 0x7: goto o0Ef7; -case 0x8: goto o0Ef8; -case 0x9: goto o0Ef9; -case 0xA: goto o0EfA; -case 0xB: goto o0EfB; -case 0xC: goto o0EfC; -case 0xD: goto o0EfD; -case 0xE: goto o0EfE; -case 0xF: goto o0EfF; -default : goto o_invalid; -} - -o1_: -switch(I[1]) -{ -case 0x0: goto o10_; -case 0x1: goto o11_; -case 0x2: goto o12_; -case 0x3: goto o13_; -case 0x4: goto o14_; -case 0x5: goto o15_; -case 0x6: goto o16x; -case 0x7: goto o17x; -case 0x8: goto o18x; -case 0x9: goto o19d2; -case 0xA: goto o1Ad4; -case 0xB: goto o1Bd5; -case 0xC: goto o1Cx; -case 0xD: goto o1Dd2; -case 0xE: goto o1Ed4; -case 0xF: goto o1Fd5; -default : goto o_invalid; -} - -o10_: -switch(I[2]) -{ -case 0x0: goto o100; -case 0x1: goto o101; -case 0x2: goto o102; -case 0x3: goto o103; -case 0x4: goto o104; -case 0x8: goto o108; -case 0x9: goto o109; -case 0xA: goto o10A; -case 0xB: goto o10B; -case 0xC: goto o10C; -default : goto o_invalid3; -} - -o11_: -switch(I[2]) -{ -case 0x0: goto o110; -case 0x1: goto o111; -case 0x2: goto o112; -case 0x3: goto o113; -case 0x4: goto o114; -case 0x8: goto o118; -case 0x9: goto o119; -case 0xA: goto o11A; -case 0xB: goto o11B; -case 0xC: goto o11C; -default : goto o_invalid3; -} - -o12_: -switch(I[2]) -{ -case 0x0: goto o120; -case 0x1: goto o121; -case 0x2: goto o122; -case 0x3: goto o123; -case 0x4: goto o124; -case 0x8: goto o128; -case 0x9: goto o129; -case 0xA: goto o12A; -case 0xB: goto o12B; -case 0xC: goto o12C; -default : goto o_invalid3; -} - -o13_: -switch(I[2]) -{ -case 0x0: goto o130; -case 0x1: goto o131; -case 0x2: goto o132; -case 0x3: goto o133; -case 0x4: goto o134; -case 0x5: goto o135; -case 0x6: goto o136; -case 0x7: goto o137; -case 0x8: goto o138; -case 0x9: goto o139; -case 0xA: goto o13A; -case 0xB: goto o13B; -case 0xC: goto o13C; -case 0xD: goto o13D; -case 0xE: goto o13E; -case 0xF: goto o13F; -default : goto o_invalid; -} - -o14_: -switch(I[2]) -{ -case 0x0: goto o140; -case 0x1: goto o141; -case 0x2: goto o142; -case 0x3: goto o143; -case 0x4: goto o144; -case 0x5: goto o145; -case 0x6: goto o146; -case 0x7: goto o147; -case 0x8: goto o148; -case 0x9: goto o149; -case 0xA: goto o14A; -case 0xB: goto o14B; -case 0xC: goto o14C; -case 0xD: goto o14D; -case 0xE: goto o14E; -case 0xF: goto o14F; -default : goto o_invalid; -} - -o15_: -switch(I[2]) { -case 0x0: goto o150a; -case 0x1: goto o151a; -case 0x2: goto o152a; -case 0x3: goto o153a; -case 0x4: goto o154a; -case 0x5: goto o155a; -case 0x6: goto o156a; -case 0x7: goto o157a; -case 0x8: goto o158x; -case 0x9: goto o159x; -case 0xA: goto o15Ax; -case 0xB: goto o15Bx; -case 0xC: goto o15Cx; -case 0xD: goto o15Dx; -case 0xE: goto o15Ex; -case 0xF: goto o15Fx; -default : goto o_invalid; -} - -o8_: -switch(I[1]) -{ -case 0x0: goto o80_; -case 0x1: goto o81_; -case 0x2: goto o82n; -case 0x3: goto o83n; -case 0x4: goto o84n; -case 0x5: goto o85n; -case 0x6: goto o86n; -case 0x7: goto o87n; -case 0x8: goto o88n; -case 0x9: goto o89n; -case 0xA: goto o8A_; -case 0xB: goto o8B_; -case 0xC: goto o8Cd4; -case 0xD: goto o8Dd5; -case 0xE: goto o8Ed4; -case 0xF: goto o8Fd5; -default : goto o_invalid; -} - -o80_: -switch(I[2]) -{ -case 0x0: goto o800; -case 0x1: goto o801; -case 0x2: goto o802; -case 0x3: goto o803; -case 0x4: goto o804; -case 0x5: goto o805; -case 0x6: goto o806; -case 0x7: goto o807; -case 0x8: goto o808_; -case 0x9: goto o809; -case 0xA: goto o80A; -case 0xB: goto o80B; -case 0xC: goto o80Cn; -case 0xD: goto o80Dn; -case 0xE: goto o80E; -case 0xF: goto o80Fn; -default : goto o_invalid; -} - -o808_: -switch(I[3]) -{ -case 0x0: goto o8080; -case 0x1: if (I[4]) goto o_invalid5; goto o80810; -case 0x2: goto o8082X; -case 0x3: goto o8083; -case 0x4: goto o8084n; -case 0x5: goto o8085n; -case 0x6: goto o8086n; -case 0x7: goto o8087n; -case 0x8: goto o8088n; -case 0x9: goto o8089n; -case 0xA: goto o808An; -case 0xB: goto o808Bn; -case 0xC: goto o808C; -case 0xD: goto o808D; -case 0xE: goto o808E; -case 0xF: goto o808F; -default : goto o_invalid; -} - -o81_: -switch(I[2]) -{ -case 0x0: goto o810; -case 0x1: goto o811; -case 0x2: goto o812; -case 0x3: goto o813; -case 0x4: goto o814; -case 0x5: goto o815; -case 0x6: goto o816; -case 0x7: goto o817; -case 0x8: goto o818_; -case 0x9: goto o819_; -case 0xA: goto o81A_; -case 0xB: goto o81B_; -case 0xC: goto o81C; -case 0xD: goto o81D; -case 0xE: goto o81E; -case 0xF: goto o81F; -default : goto o_invalid; -} - -o818_: -switch(I[4]) -{ -case 0x0: goto o818f0x; -case 0x1: goto o818f1x; -case 0x2: goto o818f2x; -case 0x3: goto o818f3x; -case 0x8: goto o818f8x; -case 0x9: goto o818f9x; -case 0xA: goto o818fAx; -case 0xB: goto o818fBx; -default : goto o_invalid6; -} - -o819_: -switch(I[4]) -{ -case 0x0: goto o819f0; -case 0x1: goto o819f1; -case 0x2: goto o819f2; -case 0x3: goto o819f3; -default : goto o_invalid5; -} - -o81A_: -switch(I[4]) -{ -case 0x0: goto o81Af0_; -case 0x1: goto o81Af1_; -case 0x2: goto o81Af2_; -default : goto o_invalid6; -} - -o81Af0_: -switch(I[5]) -{ -case 0x0: goto o81Af00; -case 0x1: goto o81Af01; -case 0x2: goto o81Af02; -case 0x3: goto o81Af03; -case 0x4: goto o81Af04; -case 0x8: goto o81Af08; -case 0x9: goto o81Af09; -case 0xA: goto o81Af0A; -case 0xB: goto o81Af0B; -case 0xC: goto o81Af0C; -default : goto o_invalid6; -} - -o81Af1_: -switch(I[5]) -{ -case 0x0: goto o81Af10; -case 0x1: goto o81Af11; -case 0x2: goto o81Af12; -case 0x3: goto o81Af13; -case 0x4: goto o81Af14; -case 0x8: goto o81Af18; -case 0x9: goto o81Af19; -case 0xA: goto o81Af1A; -case 0xB: goto o81Af1B; -case 0xC: goto o81Af1C; -default : goto o_invalid6; -} - -o81Af2_: -switch(I[5]) -{ -case 0x0: goto o81Af20; -case 0x1: goto o81Af21; -case 0x2: goto o81Af22; -case 0x3: goto o81Af23; -case 0x4: goto o81Af24; -case 0x8: goto o81Af28; -case 0x9: goto o81Af29; -case 0xA: goto o81Af2A; -case 0xB: goto o81Af2B; -case 0xC: goto o81Af2C; -default : goto o_invalid6; -} - -o81B_: -switch(I[3]) -{ -//////// EXTENSIONS //////// -// case 0x0: goto o81B0; // 05.01.99 cg, removed, unused extension -case 0x1: goto o81B1; -//////////////////////////// -case 0x2: goto o81B2; -case 0x3: goto o81B3; -case 0x4: goto o81B4; -case 0x5: goto o81B5; -case 0x6: goto o81B6; -case 0x7: goto o81B7; -default : goto o_invalid4; -} - -o8A_: -switch(I[2]) -{ -case 0x0: goto o8A0; -case 0x1: goto o8A1; -case 0x2: goto o8A2; -case 0x3: goto o8A3; -case 0x4: goto o8A4; -case 0x5: goto o8A5; -case 0x6: goto o8A6; -case 0x7: goto o8A7; -case 0x8: goto o8A8; -case 0x9: goto o8A9; -case 0xA: goto o8AA; -case 0xB: goto o8AB; -case 0xC: goto o8AC; -case 0xD: goto o8AD; -case 0xE: goto o8AE; -case 0xF: goto o8AF; -default : goto o_invalid; -} - -o8B_: -switch(I[2]) -{ -case 0x0: goto o8B0; -case 0x1: goto o8B1; -case 0x2: goto o8B2; -case 0x3: goto o8B3; -case 0x4: goto o8B4; -case 0x5: goto o8B5; -case 0x6: goto o8B6; -case 0x7: goto o8B7; -case 0x8: goto o8B8; -case 0x9: goto o8B9; -case 0xA: goto o8BA; -case 0xB: goto o8BB; -case 0xC: goto o8BC; -case 0xD: goto o8BD; -case 0xE: goto o8BE; -case 0xF: goto o8BF; -default : goto o_invalid; -} - -o9_: -if (I[1]<8) -goto o9a_; -else -goto o9b_; - -o9a_: -switch(I[2]) -{ -case 0x0: goto o9a0; -case 0x1: goto o9a1; -case 0x2: goto o9a2; -case 0x3: goto o9a3; -case 0x4: goto o9a4; -case 0x5: goto o9a5; -case 0x6: goto o9a6; -case 0x7: goto o9a7; -case 0x8: goto o9a8; -case 0x9: goto o9a9; -case 0xA: goto o9aA; -case 0xB: goto o9aB; -case 0xC: goto o9aC; -case 0xD: goto o9aD; -case 0xE: goto o9aE; -case 0xF: goto o9aF; -default : goto o_invalid; -} - -o9b_: -switch(I[2]) -{ -case 0x0: goto o9b0; -case 0x1: goto o9b1; -case 0x2: goto o9b2; -case 0x3: goto o9b3; -case 0x4: goto o9b4; -case 0x5: goto o9b5; -case 0x6: goto o9b6; -case 0x7: goto o9b7; -case 0x8: goto o9b8; -case 0x9: goto o9b9; -case 0xA: goto o9bA; -case 0xB: goto o9bB; -case 0xC: goto o9bC; -case 0xD: goto o9bD; -case 0xE: goto o9bE; -case 0xF: goto o9bF; -default : goto o_invalid; -} - -oA_: -if (I[1]<8) -goto oAa_; -else -goto oAb_; - -oAa_: -switch(I[2]) -{ -case 0x0: goto oAa0; -case 0x1: goto oAa1; -case 0x2: goto oAa2; -case 0x3: goto oAa3; -case 0x4: goto oAa4; -case 0x5: goto oAa5; -case 0x6: goto oAa6; -case 0x7: goto oAa7; -case 0x8: goto oAa8; -case 0x9: goto oAa9; -case 0xA: goto oAaA; -case 0xB: goto oAaB; -case 0xC: goto oAaC; -case 0xD: goto oAaD; -case 0xE: goto oAaE; -case 0xF: goto oAaF; -default : goto o_invalid; -} - -oAb_: -switch(I[2]) -{ -case 0x0: goto oAb0; -case 0x1: goto oAb1; -case 0x2: goto oAb2; -case 0x3: goto oAb3; -case 0x4: goto oAb4; -case 0x5: goto oAb5; -case 0x6: goto oAb6; -case 0x7: goto oAb7; -case 0x8: goto oAb8; -case 0x9: goto oAb9; -case 0xA: goto oAbA; -case 0xB: goto oAbB; -case 0xC: goto oAbC; -case 0xD: goto oAbD; -case 0xE: goto oAbE; -case 0xF: goto oAbF; -default : goto o_invalid; -} - -oB_: -if (I[1]<8) -goto oBa_; -else -goto oBb_; - -oBa_: -switch(I[2]) -{ -case 0x0: goto oBa0; -case 0x1: goto oBa1; -case 0x2: goto oBa2; -case 0x3: goto oBa3; -case 0x4: goto oBa4; -case 0x5: goto oBa5; -case 0x6: goto oBa6; -case 0x7: goto oBa7; -case 0x8: goto oBa8; -case 0x9: goto oBa9; -case 0xA: goto oBaA; -case 0xB: goto oBaB; -case 0xC: goto oBaC; -case 0xD: goto oBaD; -case 0xE: goto oBaE; -case 0xF: goto oBaF; -default : goto o_invalid; -} - -oBb_: -switch(I[2]) -{ -case 0x0: goto oBb0; -case 0x1: goto oBb1; -case 0x2: goto oBb2; -case 0x3: goto oBb3; -case 0x4: goto oBb4; -case 0x5: goto oBb5; -case 0x6: goto oBb6; -case 0x7: goto oBb7; -case 0x8: goto oBb8; -case 0x9: goto oBb9; -case 0xA: goto oBbA; -case 0xB: goto oBbB; -case 0xC: goto oBbC; -case 0xD: goto oBbD; -case 0xE: goto oBbE; -case 0xF: goto oBbF; -default : goto o_invalid; -} - -oC_: -switch(I[1]) -{ -case 0x0: goto oC0; -case 0x1: goto oC1; -case 0x2: goto oC2; -case 0x3: goto oC3; -case 0x4: goto oC4; -case 0x5: goto oC5; -case 0x6: goto oC6; -case 0x7: goto oC7; -case 0x8: goto oC8; -case 0x9: goto oC9; -case 0xA: goto oCA; -case 0xB: goto oCB; -case 0xC: goto oCC; -case 0xD: goto oCD; -case 0xE: goto oCE; -case 0xF: goto oCF; -default : goto o_invalid; -} - -oD_: -switch(I[1]) -{ -case 0x0: goto oD0; -case 0x1: goto oD1; -case 0x2: goto oD2; -case 0x3: goto oD3; -case 0x4: goto oD4; -case 0x5: goto oD5; -case 0x6: goto oD6; -case 0x7: goto oD7; -case 0x8: goto oD8; -case 0x9: goto oD9; -case 0xA: goto oDA; -case 0xB: goto oDB; -case 0xC: goto oDC; -case 0xD: goto oDD; -case 0xE: goto oDE; -case 0xF: goto oDF; -default : goto o_invalid; -} - -oE_: -switch(I[1]) -{ -case 0x0: goto oE0; -case 0x1: goto oE1; -case 0x2: goto oE2; -case 0x3: goto oE3; -case 0x4: goto oE4; -case 0x5: goto oE5; -case 0x6: goto oE6; -case 0x7: goto oE7; -case 0x8: goto oE8; -case 0x9: goto oE9; -case 0xA: goto oEA; -case 0xB: goto oEB; -case 0xC: goto oEC; -case 0xD: goto oED; -case 0xE: goto oEE; -case 0xF: goto oEF; -default : goto o_invalid; -} - -oF_: -switch(I[1]) -{ -case 0x0: goto oF0; -case 0x1: goto oF1; -case 0x2: goto oF2; -case 0x3: goto oF3; -case 0x4: goto oF4; -case 0x5: goto oF5; -case 0x6: goto oF6; -case 0x7: goto oF7; -case 0x8: goto oF8; -case 0x9: goto oF9; -case 0xA: goto oFA; -case 0xB: goto oFB; -case 0xC: goto oFC; -case 0xD: goto oFD; -case 0xE: goto oFE; -case 0xF: goto oFF; -default : goto o_invalid; -} diff --git a/sources/Emu48/FILES.C b/sources/Emu48/FILES.C index 3b15ab4..8c2883d 100644 --- a/sources/Emu48/FILES.C +++ b/sources/Emu48/FILES.C @@ -30,13 +30,15 @@ static HANDLE hPort2Map = NULL; LPBYTE pbyPort2 = NULL; BOOL bPort2Writeable = FALSE; BOOL bPort2IsShared = FALSE; -DWORD dwPort2Size = 0; // 26.06.98 cg, new, size of mapped port2 +DWORD dwPort2Size = 0; // size of mapped port2 DWORD dwPort2Mask = 0; -// UINT nPort2Bank = 0; // 15.12.98 cg, removed, not used any more +// 01.12.99 cg, new, HP38G signature +static BYTE pbySignatureA[16] = "Emu38 Document\xFE"; static BYTE pbySignatureE[16] = "Emu48 Document\xFE"; static BYTE pbySignatureW[16] = "Win48 Document\xFE"; -static HANDLE hCurrentFile = NULL; +static BYTE pbySignatureV[16] = "Emu49 Document\xFE"; +static HANDLE hCurrentFile = NULL; static CHIPSET BackupChipset; BOOL bBackup = FALSE; @@ -47,7 +49,7 @@ BOOL bBackup = FALSE; //# //################ -WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // 11.05.98 cg, new, separated from LoadObject() +WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // separated from LoadObject() { BOOL bBinary; DWORD dwLength, dwAddress, i; @@ -57,7 +59,7 @@ WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // 11.05.98 cg, new, separated from L && (lpBuf[dwSize+2]=='H') && (lpBuf[dwSize+3]=='P') && (lpBuf[dwSize+4]=='4') - && (lpBuf[dwSize+5]=='8') + && (lpBuf[dwSize+5]==((cCurrentRomType!='X') ? '8' : '9')) && (lpBuf[dwSize+6]=='-')); for (i=0; i> 17) - 1; // 26.06,98 cg, optimized, calculate bank switching mask + dwPort2Mask = (dwFileSizeLo >> 18) - 1; // mask for valid address lines of the BS-FF if (bPort2Writeable) hPort2Map = CreateFileMapping(hPort2File, NULL, PAGE_READWRITE, 0, dwFileSizeLo, NULL); else @@ -272,12 +288,12 @@ BOOL MapPort2(LPCSTR szFilename) bPort2Writeable = FALSE; return FALSE; } - dwPort2Size = dwFileSizeLo / 2048; // 26.06.98 cg, new, mapping size of port2 + dwPort2Size = dwFileSizeLo / 2048; // mapping size of port2 if (dwPort2Size > 128) dwPort2Size = 128; return TRUE; } -VOID UnmapPort2() +VOID UnmapPort2(VOID) { if (pbyPort2==NULL) return; UnmapViewOfFile(pbyPort2); @@ -286,7 +302,7 @@ VOID UnmapPort2() pbyPort2 = NULL; hPort2Map = NULL; hPort2File = NULL; - dwPort2Size = 0; // 26.06.98 cg, new, reset size of port2 + dwPort2Size = 0; // reset size of port2 dwPort2Mask = 0; bPort2Writeable = FALSE; return; @@ -311,23 +327,13 @@ static BYTE Asc2Nib(char c) return 0; } -static DWORD Asc2Nib5(LPSTR lpBuf) -{ - return ( - ((DWORD)Asc2Nib(lpBuf[0])<<16) - |((DWORD)Asc2Nib(lpBuf[1])<<12) - |((DWORD)Asc2Nib(lpBuf[2])<<8) - |((DWORD)Asc2Nib(lpBuf[3])<<4) - |((DWORD)Asc2Nib(lpBuf[4]))); -} - BOOL PatchRom(LPCSTR szFilename) { HANDLE hFile = NULL; DWORD dwFileSizeLow = 0; DWORD dwFileSizeHigh = 0; DWORD lBytesRead = 0; - LPBYTE lpBuf = NULL; + LPBYTE lpStop,lpBuf = NULL; DWORD dwAddress = 0; UINT nPos = 0; @@ -359,19 +365,6 @@ BOOL PatchRom(LPCSTR szFilename) nPos = 0; while (lpBuf[nPos]) { - if (lpBuf[nPos]==';') // comment ? - { - do - { - if (lpBuf[nPos]=='\n') break; - nPos++; - } while (lpBuf[nPos]); - if (lpBuf[nPos]==0) - { - LocalFree(lpBuf); - return TRUE; - } - } do // remove blank space { if ( (lpBuf[nPos]!=' ') @@ -380,28 +373,28 @@ BOOL PatchRom(LPCSTR szFilename) &&(lpBuf[nPos]!='\t')) break; nPos++; } while (lpBuf[nPos]); - if (lpBuf[nPos] == 0) break; - if (lpBuf[nPos+5]!=':') + if (lpBuf[nPos]==';') // comment ? { - nPos++; - continue; + do + { + nPos++; + if (lpBuf[nPos]=='\n') + { + nPos++; + break; + } + } while (lpBuf[nPos]); } - dwAddress = Asc2Nib5(lpBuf+nPos); - nPos+=6; + if (lpBuf[nPos] == 0) break; + dwAddress = strtoul(&lpBuf[nPos],&lpStop,16); + nPos += lpStop-&lpBuf[nPos]+1; + if (*lpStop != ':' || *lpStop == 0) + continue; while (lpBuf[nPos]) { - if (lpBuf[nPos]<'0') break; - if (lpBuf[nPos]>'9') - { - if (lpBuf[nPos]<'A') break; - if (lpBuf[nPos]>'F') break; - pbyRom[dwAddress] = lpBuf[nPos]-'A'+10; - } - else - { - pbyRom[dwAddress] = lpBuf[nPos]-'0'; - } - dwAddress = (dwAddress+1)&0xFFFFF; + if (isxdigit(lpBuf[nPos]) == FALSE) break; + pbyRom[dwAddress] = Asc2Nib(lpBuf[nPos]); + dwAddress = (dwAddress+1)&(dwRomSize-1); nPos++; } } @@ -417,7 +410,7 @@ BOOL PatchRom(LPCSTR szFilename) //# //################ -VOID ResetDocument() +VOID ResetDocument(VOID) { if (szCurrentKml[0]) { @@ -432,24 +425,43 @@ VOID ResetDocument() szCurrentFilename[0]=0; if (Chipset.Port0) LocalFree(Chipset.Port0); if (Chipset.Port1) LocalFree(Chipset.Port1); + if (cCurrentRomType == 'X') + { + if (Chipset.Port2) LocalFree(Chipset.Port2); + } + else + { + UnmapPort2(); + } FillMemory(&Chipset,sizeof(Chipset),0); UpdateWindowStatus(); return; } -BOOL NewDocument() +BOOL NewDocument(VOID) { - SaveBackup(); ResetDocument(); if (!DisplayChooseKml(0)) goto restore; if (!InitKML(szCurrentKml,FALSE)) goto restore; Chipset.type = cCurrentRomType; - if (Chipset.type == 'S') + + if (Chipset.type == 'A') // 01.12.99 cg, new, HP38G + { + Chipset.Port0Size = 32; + Chipset.Port1Size = 0; + Chipset.Port2Size = 0; + Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048); + _ASSERT(Chipset.Port0 != NULL); + FillMemory(Chipset.Port0, Chipset.Port0Size*2048, 0); + Chipset.Port1 = NULL; + Chipset.Port2 = NULL; + Chipset.cards_status = 0x0; + } + if (Chipset.type == 'S') // HP48SX { Chipset.Port0Size = 32; Chipset.Port1Size = 128; - Chipset.Port1_Writeable = TRUE; Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048); _ASSERT(Chipset.Port0 != NULL); FillMemory(Chipset.Port0, Chipset.Port0Size*2048, 0); @@ -457,12 +469,15 @@ BOOL NewDocument() _ASSERT(Chipset.Port1 != NULL); FillMemory(Chipset.Port1, Chipset.Port1Size*2048, 0); Chipset.cards_status = 0x5; + + // use 2nd command line argument if defined + // 08.11.99 cg, changed, replaced __argc and __argv variable + MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]); } - else + if (Chipset.type == 'G') // HP48GX { Chipset.Port0Size = 128; Chipset.Port1Size = 128; - Chipset.Port1_Writeable = TRUE; Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048); _ASSERT(Chipset.Port0 != NULL); FillMemory(Chipset.Port0, Chipset.Port0Size*2048, 0); @@ -470,15 +485,47 @@ BOOL NewDocument() _ASSERT(Chipset.Port1 != NULL); FillMemory(Chipset.Port1, Chipset.Port1Size*2048, 0); Chipset.cards_status = 0xA; + + // use 2nd command line argument if defined + // 08.11.99 cg, changed, replaced __argc and __argv variable + MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]); } - Map(0x00,0xFF); + if (Chipset.type == 'X') // HP49G + { + Chipset.Port0Size = 256; + Chipset.Port1Size = 128; + Chipset.Port2Size = 128; + Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048); + _ASSERT(Chipset.Port0 != NULL); + FillMemory(Chipset.Port0, Chipset.Port0Size*2048, 0); + Chipset.Port1 = (LPBYTE)LocalAlloc(0,Chipset.Port1Size*2048); + _ASSERT(Chipset.Port1 != NULL); + FillMemory(Chipset.Port1, Chipset.Port1Size*2048, 0); + Chipset.Port2 = (LPBYTE)LocalAlloc(0,Chipset.Port2Size*2048); + _ASSERT(Chipset.Port2 != NULL); + FillMemory(Chipset.Port2, Chipset.Port2Size*2048, 0); + + bPort2Writeable = TRUE; + Chipset.cards_status = 0xF; + } + RomSwitch(0); // boot ROM view of HP49G and map memory + SaveBackup(); return TRUE; restore: RestoreBackup(); ResetBackup(); + + // 01.12.99 cg, changed, added HP38G + if(Chipset.type != 'A' && Chipset.type != 'X') + { + // use 2nd command line argument if defined + // 08.11.99 cg, changed, replaced __argc and __argv variable + MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]); + } if (pbyRom) { - SetWindowPos(hWnd,NULL,(int)Chipset.wPosX,(int)Chipset.wPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); + // 09.12.99 cg, changed, removed typecast of the position data + SetWindowPos(hWnd,NULL,Chipset.nPosX,Chipset.nPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); Map(0x00,0xFF); } return FALSE; @@ -490,6 +537,7 @@ BOOL OpenDocument(LPCSTR szFilename) DWORD lBytesRead; DWORD lSizeofChipset; BYTE pbyFileSignature[16]; + LPBYTE pbySig; UINT ctBytesCompared; UINT nLength; @@ -514,9 +562,13 @@ BOOL OpenDocument(LPCSTR szFilename) switch (pbyFileSignature[0]) { case 'E': + // 01.12.99 cg, changed, added HP38 signature + pbySig = (pbyFileSignature[3] == '3') + ? pbySignatureA + : ((pbyFileSignature[4] == '8') ? pbySignatureE : pbySignatureV); for (ctBytesCompared=0; ctBytesCompared<14; ctBytesCompared++) { - if (pbyFileSignature[ctBytesCompared]!=pbySignatureE[ctBytesCompared]) + if (pbyFileSignature[ctBytesCompared]!=pbySig[ctBytesCompared]) { AbortMessage("This file is not a valid Emu48 document."); goto restore; @@ -540,7 +592,7 @@ BOOL OpenDocument(LPCSTR szFilename) switch (pbyFileSignature[14]) { - case 0xFE: // Win48 2.1 / Emu48 0.99.x format + case 0xFE: // Win48 2.1 / Emu4x 0.99.x format ReadFile(hFile, &nLength, sizeof(nLength), &lBytesRead, NULL); ReadFile(hFile, szCurrentKml, nLength, &lBytesRead, NULL); if (nLength != lBytesRead) goto read_err; @@ -566,25 +618,20 @@ BOOL OpenDocument(LPCSTR szFilename) if (lBytesRead != lSizeofChipset) goto read_err; Chipset.Port0 = NULL; Chipset.Port1 = NULL; + Chipset.Port2 = NULL; - // 26.01.98 cg, bugfix, WORD to int conversation failed with negative numbers - SetWindowPos(hWnd,NULL,(short)Chipset.wPosX,(short)Chipset.wPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); + // 09.12.99 cg, changed, removed typecast of the position data + SetWindowPos(hWnd,NULL,Chipset.nPosX,Chipset.nPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); if (szCurrentKml == NULL) { if (!DisplayChooseKml(Chipset.type)) - { - // CloseHandle(hFile); // 29.01.98 cg, bugfix, will be close at end of function goto restore; - } } while (!InitKML(szCurrentKml,FALSE)) { if (!DisplayChooseKml(Chipset.type)) - { - // CloseHandle(hFile); // 29.01.98 cg, bugfix, will be close at end of function goto restore; - } } if (Chipset.Port0Size) @@ -613,16 +660,49 @@ BOOL OpenDocument(LPCSTR szFilename) if (lBytesRead != Chipset.Port1Size*2048) goto read_err; } - if (Chipset.wPort2Crc != CrcPort2()) // 21.02.99 cg, new, port2 changed + if (cCurrentRomType!='X') // HP38G, HP48SX/GX { - Chipset.HST |= 8; // 21.02.99 cg, new, set Module Pulled - Chipset.SoftInt = TRUE; // 21.02.99 cg, new, set interrupt - bInterrupt = TRUE; // 21.02.99 cg, new + if(cCurrentRomType!='A') // 01.12.99 cg, new, HP48SX/GX + { + // 08.11.99 cg, changed, replaced __argc and __argv variable + MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]); + if (Chipset.wPort2Crc != CrcPort2())// port2 changed + { + Chipset.HST |= 8; // set Module Pulled + Chipset.SoftInt = TRUE; // set interrupt + bInterrupt = TRUE; + } + } + } + else // HP49G + { + if (Chipset.Port2Size) + { + Chipset.Port2 = (LPBYTE)LocalAlloc(0,Chipset.Port2Size*2048); + if (Chipset.Port2 == NULL) + { + AbortMessage("Memory Allocation Failure."); + goto restore; + } + + ReadFile(hFile, Chipset.Port2, Chipset.Port2Size*2048, &lBytesRead, NULL); + if (lBytesRead != Chipset.Port2Size*2048) goto read_err; + + bPort2Writeable = TRUE; + Chipset.cards_status = 0xF; + } } + RomSwitch(Chipset.Bank_FF); // reload ROM view of HP49G and map memory + + // 20.11.99 cg, new, check fingerprint of ROM + if (Chipset.wRomCrc != CrcRom()) // ROM changed + CpuReset(); + // 20.11.99 cg, end of fingerprint check + lstrcpy(szCurrentFilename, szFilename); + _ASSERT(hCurrentFile == NULL); hCurrentFile = hFile; - Map(0x00,0xFF); SetWindowTitle(szCurrentFilename); UpdateWindowStatus(); return TRUE; @@ -630,34 +710,48 @@ BOOL OpenDocument(LPCSTR szFilename) read_err: AbortMessage("This file must be truncated, and cannot be loaded."); restore: - if (INVALID_HANDLE_VALUE != hFile) // 29.01.98 cg, bugfix, close if valid handle + if (INVALID_HANDLE_VALUE != hFile) // close if valid handle CloseHandle(hFile); RestoreBackup(); ResetBackup(); + + // 01.12.99 cg, bugfix, add port2 only on HP48 calculators + if(cCurrentRomType!='A' && cCurrentRomType!='X') + { + // use 2nd command line argument if defined + // 08.11.99 cg, changed, replaced __argc and __argv variable + MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]); + } return FALSE; } -BOOL SaveDocument() +BOOL SaveDocument(VOID) { DWORD lBytesWritten; DWORD lSizeofChipset; + LPBYTE pbySig; UINT nLength; RECT Rect; if (hCurrentFile == NULL) return FALSE; - GetWindowRect(hWnd, &Rect); - Chipset.wPosX = (WORD)Rect.left; - Chipset.wPosY = (WORD)Rect.top; + GetWindowRect(hWnd, &Rect); // update saved window position + Chipset.nPosX = (SWORD)Rect.left; + Chipset.nPosY = (SWORD)Rect.top; SetFilePointer(hCurrentFile,0,0,FILE_BEGIN); - if (!WriteFile(hCurrentFile, pbySignatureE, 16, &lBytesWritten, NULL)) + + // 01.12.99 cg, changed, added HP38G signature + pbySig = (Chipset.type=='A') ? pbySignatureA : ((Chipset.type!='X') ? pbySignatureE : pbySignatureV); + + if (!WriteFile(hCurrentFile, pbySig, 16, &lBytesWritten, NULL)) { AbortMessage("Could not write into file !"); return FALSE; } - Chipset.wPort2Crc = CrcPort2(); // 21.02.99 cg, new, save fingerprint of port2 + Chipset.wRomCrc = CrcRom(); // 20.11.99 cg, new, save fingerprint of ROM + Chipset.wPort2Crc = CrcPort2(); // save fingerprint of port2 nLength = strlen(szCurrentKml); WriteFile(hCurrentFile, &nLength, sizeof(nLength), &lBytesWritten, NULL); @@ -667,34 +761,25 @@ BOOL SaveDocument() WriteFile(hCurrentFile, &Chipset, lSizeofChipset, &lBytesWritten, NULL); if (Chipset.Port0Size) WriteFile(hCurrentFile, Chipset.Port0, Chipset.Port0Size*2048, &lBytesWritten, NULL); if (Chipset.Port1Size) WriteFile(hCurrentFile, Chipset.Port1, Chipset.Port1Size*2048, &lBytesWritten, NULL); - + if (cCurrentRomType=='X' && Chipset.Port2Size) WriteFile(hCurrentFile, Chipset.Port2, Chipset.Port2Size*2048, &lBytesWritten, NULL); return TRUE; } BOOL SaveDocumentAs(LPCTSTR szFilename) { - HANDLE hFile = INVALID_HANDLE_VALUE; + HANDLE hFile; if (hCurrentFile) // already file in use { - if (lstrcmpi(szFilename, szCurrentFilename)==0) - { - hFile = hCurrentFile; // same file, do not open a new one - } - } - if (hFile == INVALID_HANDLE_VALUE) // not same file, open a new one - { - hFile = CreateFile(szFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); + CloseHandle(hCurrentFile); // close it, even it's same, so data always will be saved + hCurrentFile = NULL; } + hFile = CreateFile(szFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) // error, couldn't create a new file { AbortMessage("This file must be currently used by another instance of Emu48."); return FALSE; } - if (hCurrentFile) // 02.10.98 cg, previous file in use - { - CloseHandle(hCurrentFile); // 02.10.98 cg, bugfix, close it - } lstrcpy(szCurrentFilename, szFilename); // save new file name hCurrentFile = hFile; // and the corresponding handle SetWindowTitle(szCurrentFilename); // update window title line @@ -710,28 +795,44 @@ BOOL SaveDocumentAs(LPCTSTR szFilename) //# //################ -BOOL SaveBackup() +BOOL SaveBackup(VOID) { + RECT Rect; + if (pbyRom == NULL) return FALSE; + + // 09.12.99 cg, changed, save window position + GetWindowRect(hWnd, &Rect); // update saved window position + Chipset.nPosX = (SWORD)Rect.left; + Chipset.nPosY = (SWORD)Rect.top; + // 09.12.99 cg, end of part + lstrcpy(szBackupFilename, szCurrentFilename); lstrcpy(szBackupKml, szCurrentKml); if (BackupChipset.Port0) LocalFree(BackupChipset.Port0); if (BackupChipset.Port1) LocalFree(BackupChipset.Port1); + if (BackupChipset.Port2) LocalFree(BackupChipset.Port2); CopyMemory(&BackupChipset, &Chipset, sizeof(Chipset)); BackupChipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048); CopyMemory(BackupChipset.Port0, Chipset.Port0, Chipset.Port0Size*2048); BackupChipset.Port1 = (LPBYTE)LocalAlloc(0,Chipset.Port1Size*2048); CopyMemory(BackupChipset.Port1, Chipset.Port1, Chipset.Port1Size*2048); + BackupChipset.Port2 = NULL; + if (cCurrentRomType=='X') // HP49G + { + BackupChipset.Port2 = (LPBYTE)LocalAlloc(0,Chipset.Port2Size*2048); + CopyMemory(BackupChipset.Port2, Chipset.Port2, Chipset.Port2Size*2048); + } bBackup = TRUE; UpdateWindowStatus(); return TRUE; } -BOOL RestoreBackup() +BOOL RestoreBackup(VOID) { if (!bBackup) return FALSE; ResetDocument(); - // 02.02.98 cg, moved, need chipset for contrast setting in InitKML() + // need chipset for contrast setting in InitKML() CopyMemory(&Chipset, &BackupChipset, sizeof(Chipset)); if (!InitKML(szBackupKml,TRUE)) { @@ -749,25 +850,40 @@ BOOL RestoreBackup() szCurrentFilename[0] = 0; } } - // 02.02.98 cg, removed, done before - // CopyMemory(&Chipset, &BackupChipset, sizeof(Chipset)); Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048); CopyMemory(Chipset.Port0, BackupChipset.Port0, Chipset.Port0Size*2048); Chipset.Port1 = (LPBYTE)LocalAlloc(0,Chipset.Port1Size*2048); CopyMemory(Chipset.Port1, BackupChipset.Port1, Chipset.Port1Size*2048); - SetWindowPos(hWnd,NULL,(int)Chipset.wPosX,(int)Chipset.wPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); + if (cCurrentRomType=='X') // HP49G + { + Chipset.Port2 = (LPBYTE)LocalAlloc(0,Chipset.Port2Size*2048); + CopyMemory(Chipset.Port2, BackupChipset.Port2, Chipset.Port2Size*2048); + } + // 09.12.99 cg, bugfix, map port2 + else + { + if(cCurrentRomType!='A') // HP48SX/GX + { + // use 2nd command line argument if defined + MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]); + } + } + // 09.12.99 cg, end of bugfix + // 09.12.99 cg, changed, removed typecast of the position data + SetWindowPos(hWnd,NULL,Chipset.nPosX,Chipset.nPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); UpdateWindowStatus(); Map(0x00,0xFF); return TRUE; } -BOOL ResetBackup() +BOOL ResetBackup(VOID) { if (!bBackup) return FALSE; szBackupFilename[0] = 0; szBackupKml[0] = 0; if (BackupChipset.Port0) LocalFree(BackupChipset.Port0); if (BackupChipset.Port1) LocalFree(BackupChipset.Port1); + if (BackupChipset.Port2) LocalFree(BackupChipset.Port2); FillMemory(&BackupChipset,sizeof(BackupChipset),0); bBackup = FALSE; UpdateWindowStatus(); @@ -791,17 +907,37 @@ static VOID InitializeOFN(LPOPENFILENAME ofn) return; } -BOOL GetOpenFilename() +BOOL GetOpenFilename(VOID) { OPENFILENAME ofn; InitializeOFN(&ofn); ofn.lpstrFilter = + "Emu38 Document (*.E38)\0*.E38\0" "Emu48 Document (*.E48)\0*.E48\0" + "Emu49 Document (*.E49)\0*.E49\0" "Win48 Document (*.W48)\0*.W48\0" "\0\0"; - ofn.lpstrDefExt = "E48"; - ofn.nFilterIndex = 1; + if (cCurrentRomType!='X') // HP38G / HP48SX/GX + { + // 01.12.99 cg, new, HP38G support + if (cCurrentRomType=='A') // HP38G + { + ofn.lpstrDefExt = "E38"; + ofn.nFilterIndex = 1; + } + else + // 01.12.99 cg, end + { + ofn.lpstrDefExt = "E48"; + ofn.nFilterIndex = 2; + } + } + else // HP49G + { + ofn.lpstrDefExt = "E49"; + ofn.nFilterIndex = 3; + } ofn.lpstrFile = LocalAlloc(0,512); ofn.lpstrFile[0] = 0; ofn.nMaxFile = 512; @@ -816,17 +952,37 @@ BOOL GetOpenFilename() return TRUE; } -BOOL GetSaveAsFilename() +BOOL GetSaveAsFilename(VOID) { OPENFILENAME ofn; InitializeOFN(&ofn); ofn.lpstrFilter = + "Emu38 Document (*.E38)\0*.E38\0" "Emu48 Document (*.E48)\0*.E48\0" + "Emu49 Document (*.E49)\0*.E49\0" "Win48 Document (*.W48)\0*.W48\0" "\0\0"; - ofn.lpstrDefExt = "E48"; - ofn.nFilterIndex = 1; + if (cCurrentRomType!='X') // HP38G / HP48SX/GX + { + // 01.12.99 cg, new, HP38G support + if (cCurrentRomType=='A') // HP38G + { + ofn.lpstrDefExt = "E38"; + ofn.nFilterIndex = 1; + } + else + // 01.12.99 cg, end + { + ofn.lpstrDefExt = "E48"; + ofn.nFilterIndex = 2; + } + } + else // HP49G + { + ofn.lpstrDefExt = "E49"; + ofn.nFilterIndex = 3; + } ofn.lpstrFile = LocalAlloc(0,512); ofn.lpstrFile[0] = 0; ofn.nMaxFile = 512; @@ -841,7 +997,7 @@ BOOL GetSaveAsFilename() return TRUE; } -BOOL GetLoadObjectFilename() +BOOL GetLoadObjectFilename(VOID) { OPENFILENAME ofn; @@ -862,7 +1018,7 @@ BOOL GetLoadObjectFilename() return TRUE; } -BOOL GetSaveObjectFilename() +BOOL GetSaveObjectFilename(VOID) { OPENFILENAME ofn; @@ -891,7 +1047,7 @@ BOOL GetSaveObjectFilename() //# //################ -BOOL LoadObject(LPCSTR szFilename) // 11.05.98 cg, changed, separated stack writing part +BOOL LoadObject(LPCSTR szFilename) // separated stack writing part { HANDLE hFile; DWORD dwFileSizeLow; @@ -928,9 +1084,10 @@ BOOL LoadObject(LPCSTR szFilename) // 11.05.98 cg, changed, separated stack wr return (wError == S_ERR_NO); } -BOOL SaveObject(LPCSTR szFilename) // 11.05.98 cg, changed, separated stack reading part +BOOL SaveObject(LPCSTR szFilename) // separated stack reading part { HANDLE hFile; + LPBYTE pbyHeader; DWORD lBytesWritten; DWORD dwAddress; DWORD dwLength; @@ -950,7 +1107,9 @@ BOOL SaveObject(LPCSTR szFilename) // 11.05.98 cg, changed, separated stack re return FALSE; } - WriteFile(hFile, BINARYHEADER, 8, &lBytesWritten, NULL); + pbyHeader = (Chipset.type != 'X') ? BINARYHEADER48 : BINARYHEADER49; + WriteFile(hFile, pbyHeader, 8, &lBytesWritten, NULL); + while (dwLength--) { BYTE byByte = Read2(dwAddress); @@ -1078,18 +1237,18 @@ HBITMAP LoadBitmapFile(LPCSTR szFilename) LPBITMAPFILEHEADER pBmfh; LPBITMAPINFO pBmi; - if (hRomFile == NULL) return NULL; // 17.10.97 cg, bugfix, line moved and error case is NULL + if (hRomFile == NULL) return NULL; SetCurrentDirectory(szEmu48Directory); hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); SetCurrentDirectory(szCurrentDirectory); - // 19.01.98 cg, bugfix, opend with GENERIC_READ -> PAGE_READONLY + // opened with GENERIC_READ -> PAGE_READONLY hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (hMap == NULL) { CloseHandle(hFile); return NULL; } - // 19.01.98 cg, bugfix, opend with GENERIC_READ -> PAGE_READONLY -> FILE_MAP_READ + // opened with GENERIC_READ -> PAGE_READONLY -> FILE_MAP_READ pbyFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); if (pbyFile == NULL) { @@ -1103,9 +1262,9 @@ HBITMAP LoadBitmapFile(LPCSTR szFilename) if (pBmfh->bfType != 0x4D42) goto quit; // "BM" pBmi = (LPBITMAPINFO)(pbyFile+sizeof(BITMAPFILEHEADER)); - _ASSERT(hPalette == NULL); // 11.09.98 cg, resource free + _ASSERT(hPalette == NULL); // resource free hPalette = CreateBIPalette(&pBmi->bmiHeader); - // 11.09.98 cg, save old palette + // save old palette hOldPalette = SelectPalette(hWindowDC, hPalette, FALSE); RealizePalette(hWindowDC); diff --git a/sources/Emu48/IO.H b/sources/Emu48/IO.H new file mode 100644 index 0000000..3a667a1 --- /dev/null +++ b/sources/Emu48/IO.H @@ -0,0 +1,75 @@ +/* + * io.h + * + * This file is part of Emu48 + * + * Copyright (C) 1999 Christoph Gießelink + * + */ + +// I/O addresses without mapping offset +#define CRC 0x04 // Crc (16 bit, LSB first) +#define BAUD 0x0d // Baudrate (Bit 2-0) +#define IOC 0x10 // IO CONTROL +#define RCS 0x11 // RCS +#define TCS 0x12 // TCS +#define CRER 0x13 // CRER +#define RBR_LSB 0x14 // RBR low nibble +#define RBR_MSB 0x15 // RBR high nibble +#define TBR_LSB 0x16 // TBR low nibble +#define TBR_MSB 0x17 // TBR high nibble +#define SRQ1 0x18 // SRQ1 +#define SRQ2 0x19 // SRQ2 +#define IR_CTRL 0x1a // IR CONTROL +#define TIMER1_CTRL 0x2e // Timer1 Control +#define TIMER2_CTRL 0x2f // Timer2 Control +#define TIMER1 0x37 // Timer1 (4 bit) +#define TIMER2 0x38 // Timer2 (32 bit, LSB first) + +// 0x10 Serial I/O Control [SON ETBE ERBF ERBZ] +#define SON 0x08 // Serial on +#define ETBE 0x04 // Interrupt on transmit buffer empty +#define ERBF 0x02 // Interrupt on receive buffer full +#define ERBZ 0x01 // Interrupt on receiver busy + +// 0x11 Serial Receive Control/Status [RX RER RBZ RBF] +#define RX 0x08 // Rx pin state (read-only) +#define RER 0x04 // Receiver error +#define RBZ 0x02 // Receiver busy +#define RBF 0x01 // Receive buffer full + +// 0x12 Serial Transmit Control/Status [BRK LPB TBZ TBF] +#define BRK 0x08 // Break +#define LPB 0x04 // Loopback +#define TBZ 0x02 // Transmitter busy +#define TBF 0x01 // Transmit buffer full + +// 0x18 Service Request Register 1 [ISRQ TSRQ USRQ VSRQ] +#define ISRQ 0x08 // IR receiver pulls NINT2 +#define TSRQ 0x04 // Timer pulls NINT2 +#define USRQ 0x02 // UART pulls NINT2 +#define VSRQ 0x01 // VLBI pulls NINT2 + +// 0x19 Service Request Register 2 [KDN NINT2 NINT LSRQ] +#define KDN 0x08 // Bit set when ON Key or Key Interrupt +#define NINT2 0x04 // State of NINT2 +#define NINT 0x02 // State of NINT +#define LSRQ 0x01 // LED driver pulls NINT2 + +// 0x1a IR Control Register [IRI EIRU EIRI IRE] +#define IRI 0x08 // IR input (read-only) +#define EIRU 0x04 // Enable IR UART mode +#define EIRI 0x02 // Enable IR interrupt +#define IRE 0x01 // IR event + +// 0x2e Timer1 Control [SRQ WKE INT XTRA] +#define SRQ 0x08 // Service request +#define WKE 0x04 // Wake up +#define INTR 0x02 // Interrupt +#define XTRA 0x01 // Extra function + +// 0x2f Timer2 Control [SRQ WKE INT RUN] +#define SRQ 0x08 // Service request +#define WKE 0x04 // Wake up +#define INTR 0x02 // Interrupt +#define RUN 0x01 // Timer run diff --git a/sources/Emu48/KEYBOARD.C b/sources/Emu48/KEYBOARD.C index 5191007..27fe5cd 100644 --- a/sources/Emu48/KEYBOARD.C +++ b/sources/Emu48/KEYBOARD.C @@ -9,7 +9,7 @@ #include "pch.h" #include "Emu48.h" -static WORD Keyboard_GetIR(VOID) // 13.02.99 cg, make function static +static WORD Keyboard_GetIR(VOID) { WORD r = 0; @@ -26,9 +26,8 @@ static WORD Keyboard_GetIR(VOID) // 13.02.99 cg, make function static return r; } -VOID ScanKeyboard(BOOL bReset) // 02.09.98 cg, changed, add flag for key state reset +VOID ScanKeyboard(BOOL bReset) { - // 02.09.98 cg, new, changed implementation // bReset = TRUE -> Reset Chipset.in interrupt state register // FALSE -> generate interrupt only for new pressed keys @@ -38,9 +37,9 @@ VOID ScanKeyboard(BOOL bReset) // 02.09.98 cg, changed, add flag for key stat WORD wOldIn = Chipset.in; // save old Chipset.in state - // 26.02.99 cg, bugfix, update KDN bit - UpdateKdnBit(); - Chipset.dwKdnCycles = Chipset.cycles; + UpdateKdnBit(); // update KDN bit + // 22.11.99 cg, changed, DWORD casting + Chipset.dwKdnCycles = (DWORD) (Chipset.cycles & 0xFFFFFFFF); // update Chipset.in register Chipset.in = Keyboard_GetIR() | Chipset.IR15X; @@ -48,10 +47,10 @@ VOID ScanKeyboard(BOOL bReset) // 02.09.98 cg, changed, add flag for key stat // interrrupt for any new pressed keys ? bKbdInt = ((Chipset.in & (Chipset.in ^ wOldIn)) != 0) || bReset; - // 01.03.99 cg, bugfix, update keyboard interrupt pending flag + // update keyboard interrupt pending flag Chipset.intd = Chipset.intd || (bKbdInt && !Chipset.intk); - // 28.02.99 cg, changed, keyboard interrupt enabled + // keyboard interrupt enabled bKbdInt = bKbdInt && (Chipset.intk || Chipset.IR15X != 0) && Chipset.inte; if (Chipset.in != 0) // any key pressed @@ -63,76 +62,18 @@ VOID ScanKeyboard(BOOL bReset) // 02.09.98 cg, changed, add flag for key stat } if (Chipset.Shutdn) // cpu sleeping - ResumeThread(hThread); // wake up + { + Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode + SetEvent(hEventShutdn); // wake up emulation thread + } } else { - Chipset.intd = FALSE; // 01.03.99 cg, bugfix, no keyboard interrupt pending + Chipset.intd = FALSE; // no keyboard interrupt pending } } LeaveCriticalSection(&csKeyLock); -#if 0 - // 02.09.98 cg, removed - // 11.06.98 cg, new, changed implementation - // keyboard interrupt enabled - BOOL bKbdInt = (Chipset.intk || Chipset.IR15X != 0) && Chipset.inte && Chipset.in == 0; - - // update Chipset.in register - Chipset.in = Keyboard_GetIR() | Chipset.IR15X; - - if (Chipset.in != 0) // call interrupt ? - { - if (bKbdInt) // interrupt enabled - { - Chipset.SoftInt = TRUE; // interrupt request - bInterrupt = TRUE; // exit emulation loop - } - - if (Chipset.Shutdn) // cpu sleeping - ResumeThread(hThread); // wake up - } -#endif - -#if 0 - // 11.06.98 cg, removed - WORD IR = Keyboard_GetIR(); - - Chipset.in = IR | Chipset.IR15X; - - if (Chipset.IR15X) - { - if (Chipset.inte) - { -// PatBlt(hWindowDC,0,0,8,8,DSTINVERT); - Chipset.SoftInt = TRUE; - bInterrupt = TRUE; - } - if (Chipset.Shutdn) - { -// PatBlt(hWindowDC,8,0,8,8,DSTINVERT); - Chipset.Shutdn = FALSE; // Prevent another ResumeThread - ResumeThread(hThread); - } - } - - if (IR != 0) - { - if ((Chipset.inte) && (Chipset.intk)) - { -// PatBlt(hWindowDC,0,8,8,8,DSTINVERT); - Chipset.SoftInt = TRUE; - bInterrupt = TRUE; - } - if (Chipset.Shutdn) - { -// PatBlt(hWindowDC,8,8,8,8,DSTINVERT); - Chipset.Shutdn = FALSE; // Prevent another ResumeThread - ResumeThread(hThread); - } - } -#endif - return; } @@ -148,17 +89,12 @@ VOID KeyboardEvent(BOOL bPress, UINT out, UINT in) { _ASSERT(out<9); if (bPress) // key pressed - { - // 11.06.98 cg, removed, do interrupt handling in ScanKeyboard() - // if (((Chipset.Keyboard_Row[out]&in) == 0) && (Chipset.inte==FALSE) && (Chipset.intk)) - // Chipset.intd = TRUE; Chipset.Keyboard_Row[out] |= in; // set key marker in keyboard row - } else Chipset.Keyboard_Row[out] &= (~in); // clear key marker in keyboard row } - ScanKeyboard(FALSE); // 02.09.98 cg, changed, update Chipset.in register - bKeySlow = FALSE; // 18.11.98 cg, new, break key slow down - Sleep(50); // 28.09.98 cg, hold key state for a definite time + ScanKeyboard(FALSE); // update Chipset.in register + bKeySlow = FALSE; // break key slow down + Sleep(50); // hold key state for a definite time return; } diff --git a/sources/Emu48/KML.C b/sources/Emu48/KML.C index ba32c63..580b1da 100644 --- a/sources/Emu48/KML.C +++ b/sources/Emu48/KML.C @@ -116,8 +116,8 @@ static TokenId eIsBlock[] = static BOOL bClicking = FALSE; static UINT uButtonClicked = 0; -static BOOL bPressed = FALSE; // 01.10.97 cg, no key pressed -static UINT uLastPressedKey = 0; // 01.10.97 cg, var for last pressed key +static BOOL bPressed = FALSE; // no key pressed +static UINT uLastPressedKey = 0; // var for last pressed key //################ //# @@ -339,7 +339,6 @@ static BOOL CALLBACK ChooseKMLProc(HWND hDlg, UINT message, DWORD wParam, LONG l if (wParam == IDC_UPDATE) { DestroyKmlList(); - // 01.02.98 cg, calculate size of buffer GetDlgItemText(hDlg,IDC_EMU48DIR,szEmu48Directory,sizeof(szEmu48Directory)); CreateKmlList(); hList = GetDlgItem(hDlg,IDC_KMLSCRIPT); @@ -356,7 +355,6 @@ static BOOL CALLBACK ChooseKMLProc(HWND hDlg, UINT message, DWORD wParam, LONG l } if (wParam == IDOK) { - // 01.02.98 cg, calculate size of buffer GetDlgItemText(hDlg,IDC_EMU48DIR,szEmu48Directory,sizeof(szEmu48Directory)); hList = GetDlgItem(hDlg,IDC_KMLSCRIPT); nIndex = SendMessage(hList, CB_GETCURSEL, 0, 0); @@ -623,7 +621,7 @@ loop: if (eToken != TOK_EOL) { PrintfToLog("%i: Too many parameters (%i expected).", nLexLine, j); - goto errline; // 09.03.99 cg, bugfix, free memory of arguments + goto errline; // free memory of arguments } return pLine; } @@ -632,7 +630,7 @@ loop: if (eToken != TOK_INTEGER) { PrintfToLog("%i: Parameter %i of %s must be an integer.", nLexLine, j+1, pLexToken[i].szName); - goto errline; // 09.03.99 cg, bugfix, free memory of arguments + goto errline; // free memory of arguments } pLine->nParam[j++] = nLexInteger; nParams >>= 3; @@ -643,7 +641,7 @@ loop: if (eToken != TOK_STRING) { PrintfToLog("%i: Parameter %i of %s must be a string.", nLexLine, j+1, pLexToken[i].szName); - goto errline; // 09.03.99 cg, bugfix, free memory of arguments + goto errline; // free memory of arguments } pLine->nParam[j++] = (DWORD)szLexString; nParams >>= 3; @@ -651,7 +649,6 @@ loop: } AddToLog("Oops..."); errline: - // 09.03.99 cg, bugfix, free memory of all string arguments // if last argument was string, free it if (eToken == TOK_STRING) LocalFree(szLexString); @@ -662,9 +659,8 @@ errline: { LocalFree((LPVOID)pLine->nParam[i]); } - nParams >>= 3; // next argument type + nParams >>= 3; // next argument type } - // 09.03.99 cg, end of bugfix LocalFree(pLine); return NULL; } @@ -738,15 +734,15 @@ static Line* ParseLines() if (IsBlock(eToken)) nLevel++; if (eToken == TOK_INCLUDE) { - LPSTR szFilename; // 11.09.98 cg + LPSTR szFilename; eToken = Lex(LEX_PARAM); // get include parameter in 'szLexString' if (eToken != TOK_STRING) // not a string (token don't begin with ") { AddToLog("Include: string expected as parameter."); - FatalError(); // 09.03.99 cg, moved from abort part + FatalError(); goto abort; } - szFilename = szLexString; // 11.09.98 cg, save pointer to allocated memory + szFilename = szLexString; // save pointer to allocated memory if (pFirst) { pLine->pNext = IncludeLines(szLexString); @@ -755,8 +751,8 @@ static Line* ParseLines() { pLine = pFirst = IncludeLines(szLexString); } - LocalFree(szFilename); // 11.09.98 cg, bugfix, free memory - if (pLine == NULL) // 09.03.99 cg, bugfix, parsing error + LocalFree(szFilename); // free memory + if (pLine == NULL) // parsing error goto abort; while (pLine->pNext) pLine=pLine->pNext; continue; @@ -781,7 +777,7 @@ static Line* ParseLines() { pLine = pFirst = ParseLine(eToken); } - if (pLine == NULL) // 09.03.99 cg, bugfix, parsing error + if (pLine == NULL) // parsing error goto abort; } if (nLinesIncludeLevel) @@ -793,7 +789,6 @@ static Line* ParseLines() abort: if (pFirst) { - // pLine->pNext = NULL; // 09.03.99 cg, bugfix, pLine == NULL ! FreeLines(pFirst); } return NULL; @@ -846,7 +841,7 @@ static Block* ParseBlock(TokenId eType) pBlock->pFirstLine = ParseLines(); - if (pBlock->pFirstLine == NULL) // 09.03.99 cg, bugfix, break on ParseLines error + if (pBlock->pFirstLine == NULL) // break on ParseLines error { LocalFree(pBlock); pBlock = NULL; @@ -922,21 +917,21 @@ static Block* ParseBlocks() { if (eToken == TOK_INCLUDE) { - LPSTR szFilename; // 11.09.98 cg + LPSTR szFilename; eToken = Lex(LEX_PARAM); // get include parameter in 'szLexString' if (eToken != TOK_STRING) // not a string (token don't begin with ") { AddToLog("Include: string expected as parameter."); - FatalError(); // 09.03.99 cg, moved from abort part + FatalError(); goto abort; } - szFilename = szLexString; // 11.09.98 cg, save pointer to allocated memory + szFilename = szLexString; // save pointer to allocated memory if (pFirst) pBlock = pBlock->pNext = IncludeBlocks(szLexString); else pBlock = pFirst = IncludeBlocks(szLexString); - LocalFree(szFilename); // 11.09.98 cg, bugfix, free memory - if (pBlock == NULL) // 09.03.99 cg, bugfix, parsing error + LocalFree(szFilename); // free memory + if (pBlock == NULL) // parsing error goto abort; while (pBlock->pNext) pBlock=pBlock->pNext; continue; @@ -948,7 +943,7 @@ static Block* ParseBlocks() if (pBlock == NULL) { AddToLog("Invalid block."); - FatalError(); // 09.03.99 cg, moved from abort part + FatalError(); goto abort; } } @@ -1076,7 +1071,7 @@ static Line* InitLcd(Block* pBlock) nLcdY = pLine->nParam[1]; break; case TOK_ZOOM: - nLcdDoubled = pLine->nParam[0]; // 24.08.98 cg, changed var type + nLcdDoubled = pLine->nParam[0]; if (nLcdDoubled != 1 && nLcdDoubled != 2 && nLcdDoubled != 4) nLcdDoubled = 1; break; @@ -1327,10 +1322,9 @@ static VOID FreeLines(Line* pLine) { if ((nParams&7) == TYPE_STRING) // string type { - // 09.03.99 cg, bugfix, free string without incr. parameter buffer LocalFree((LPVOID)pLine->nParam[i]); } - i++; // 09.03.99 cg, bugfix, incr. parameter buffer index + i++; // incr. parameter buffer index nParams >>= 3; // next argument type } pLine = pLine->pNext; // get next line @@ -1368,7 +1362,7 @@ VOID KillKML() // 11.09.98, bugfix, unlock hPalette if (hWindowDC) SelectPalette(hWindowDC, hOldPalette, FALSE); err = DeleteObject(hPalette); - _ASSERT(err != FALSE); // 11.09.98 cg, freed resource memory + _ASSERT(err != FALSE); // freed resource memory hPalette = NULL; } bClicking = FALSE; @@ -1453,7 +1447,7 @@ static VOID DrawButton(UINT nId) UINT x0 = pButton[nId].nOx; UINT y0 = pButton[nId].nOy; - EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems + EnterCriticalSection(&csGDILock); // solving NT GDI problems { switch (pButton[nId].nType) { @@ -1533,14 +1527,16 @@ static VOID DrawButton(UINT nId) else BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, x0, y0, SRCCOPY); } - GdiFlush(); // 22.01.98 cg + GdiFlush(); } - LeaveCriticalSection(&csGDILock); // 22.01.98 cg + LeaveCriticalSection(&csGDILock); return; } static VOID PressButton(UINT nId) { + if (pButton[nId].bDown) return; // key already pressed -> exit + pButton[nId].bDown = TRUE; DrawButton(nId); if (pButton[nId].nIn) @@ -1605,7 +1601,7 @@ static VOID ReleaseButtonById(UINT nId) return; } -static VOID ReleaseAllButtons(VOID) // 01.10.97 cg, new, release all buttons +static VOID ReleaseAllButtons(VOID) // release all buttons { UINT i; for (i=0; i=6) return; - EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems + EnterCriticalSection(&csGDILock); // solving NT GDI problems { if (bOn) { @@ -1660,9 +1665,9 @@ VOID DrawAnnunciator(UINT nId, BOOL bOn) pAnnunciator[nId].nOx, pAnnunciator[nId].nOy, SRCCOPY); } - GdiFlush(); // 22.01.98 cg + GdiFlush(); } - LeaveCriticalSection(&csGDILock); // 22.01.98 cg + LeaveCriticalSection(&csGDILock); return; } @@ -1691,7 +1696,7 @@ VOID MouseButtonDownAt(UINT nFlags, DWORD x, DWORD y) { if (pButton[i].dwFlags&BUTTON_NOHOLD) { - if (nFlags&MK_LBUTTON) // 01.10.97 cg, use only with left mouse button + if (nFlags&MK_LBUTTON) // use only with left mouse button { bClicking = TRUE; uButtonClicked = i; @@ -1702,13 +1707,13 @@ VOID MouseButtonDownAt(UINT nFlags, DWORD x, DWORD y) } if (pButton[i].dwFlags&BUTTON_VIRTUAL) { - if (!(nFlags&MK_LBUTTON)) // 01.10.97 cg, use only with left mouse button + if (!(nFlags&MK_LBUTTON)) // use only with left mouse button return; bClicking = TRUE; uButtonClicked = i; } - bPressed = TRUE; // 01.10.97 cg, key pressed - uLastPressedKey = i; // 01.10.97 cg, save pressed key + bPressed = TRUE; // key pressed + uLastPressedKey = i; // save pressed key PressButton(i); return; } @@ -1718,14 +1723,11 @@ VOID MouseButtonDownAt(UINT nFlags, DWORD x, DWORD y) VOID MouseButtonUpAt(UINT nFlags, DWORD x, DWORD y) { UINT i; -// begin with patch - if (bPressed) // 01.10.97 cg, emulator key pressed + if (bPressed) // emulator key pressed { - ReleaseAllButtons(); // 01.10.97 cg, release all buttons + ReleaseAllButtons(); // release all buttons return; } -// continue with original part to look for nohold buttons - for (i=0; i quit - if ((bPressed) && !(ClipButton(x,y,uLastPressedKey))) // 01.10.97 cg, not on last pressed key - ReleaseAllButtons(); // 01.10.97 cg, release all buttons + if ((bPressed) && !(ClipButton(x,y,uLastPressedKey))) // not on last pressed key + ReleaseAllButtons(); // release all buttons if (!bClicking) return; // normal emulation key -> quit -// continue with original part if (pButton[uButtonClicked].dwFlags&BUTTON_NOHOLD) { @@ -1861,7 +1861,7 @@ BOOL InitKML(LPCSTR szFilename, BOOL bNoLog) DWORD lBytesRead; LPBYTE lpBuf; Block* pBlock; - BOOL bOk; + BOOL bOk = FALSE; // 08.12.99 cg, bugfix, variable not initialized at error condition BYTE bySum = 0; KillKML(); @@ -1943,7 +1943,6 @@ BOOL InitKML(LPCSTR szFilename, BOOL bNoLog) goto quit; } CreateLcdBitmap(); - Map(0x00,0xFF); PrintfToLog("%i Buttons Defined", nButtons); PrintfToLog("%i Scancodes Defined", nScancodes); diff --git a/sources/Emu48/MOPS.C b/sources/Emu48/MOPS.C index 312c874..0054321 100644 --- a/sources/Emu48/MOPS.C +++ b/sources/Emu48/MOPS.C @@ -8,20 +8,30 @@ */ #include "pch.h" #include "Emu48.h" +#include "opcodes.h" // 25.10.99 cg, new, added for HST bits +#include "io.h" // 24.10.99 cg, renamed from Serial.h -// #define DEBUG_SERIAL // 17.05.98 cg, new, switch for SERIAL debug purpose -// #define DEBUG_IO // 21.01.99 cg, new, switch for IO debug purpose +// #define DEBUG_SERIAL // switch for SERIAL debug purpose +// #define DEBUG_IO // switch for I/O debug purpose -// 30.06.98 cg, new, on mapping boundary adjusted base addresses +// defines for reading an open data bus +#define READEVEN 0x0D +#define READODD 0x0E + +// on mapping boundary adjusted base addresses #define P0MAPBASE ((BYTE)(Chipset.P0Base & ~Chipset.P0Size)) #define P1MAPBASE ((BYTE)(Chipset.P1Base & ~Chipset.P1Size)) #define P2MAPBASE ((BYTE)(Chipset.P2Base & ~Chipset.P2Size)) #define BSMAPBASE ((BYTE)(Chipset.BSBase & ~Chipset.BSSize)) -BOOL ioc_acc = FALSE; // 17.05.98 cg, new, flag ioc changed -BOOL ir_ctrl_acc = FALSE; // 17.05.98 cg, new, flag ir_ctl changed +BOOL ioc_acc = FALSE; // flag ioc changed +BOOL ir_ctrl_acc = FALSE; // flag ir_ctl changed -static BYTE byVblRef = 0; // 14.01.99 cg, new, VBL stop reference +BYTE disp = 0; // flag for update display area + +static LPBYTE pbyRomView[2] = {NULL,NULL}; // HP49G ROM views + +static BYTE byVblRef = 0; // VBL stop reference // CRC calculation static WORD crc_table[16] = @@ -29,14 +39,30 @@ static WORD crc_table[16] = 0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387, 0x8408, 0x9489, 0xA50A, 0xB58B, 0xC60C, 0xD68D, 0xE70E, 0xF78F }; -static __inline VOID CRC(BYTE nib) +static __inline VOID UpCRC(BYTE nib) { Chipset.crc = (WORD)((Chipset.crc>>4)^crc_table[(Chipset.crc^nib)&0xf]); } -// LCD line counter calculation +// generate UCK signal +static __inline BYTE UckBit(BYTE byBaudIndex) +{ + // table content = baudrate * 16 + const DWORD dwBaudrates[] = { 19200, 30720, 38400, 61440, 76800, 122880, 153600, 245760 }; -static BYTE F4096Hz(VOID) // 14.01.99 cg, new, get a 6 bit 4096Hz down counter value + LARGE_INTEGER lLC; + + _ASSERT(byBaudIndex < sizeof(dwBaudrates) / sizeof(dwBaudrates[0])); + + QueryPerformanceCounter(&lLC); // get counter value + + // calculate UCK frequency + return (((BYTE)((lLC.LowPart * dwBaudrates[byBaudIndex]) / lFreq.LowPart) & 0x1) << 3) + & Chipset.IORam[IOC]; +} + +// LCD line counter calculation +static BYTE F4096Hz(VOID) // get a 6 bit 4096Hz down counter value { LARGE_INTEGER lLC; @@ -65,13 +91,13 @@ static VOID MapP0(BYTE a, BYTE b) UINT i; DWORD p, m; - a = (BYTE)MAX(a,P0MAPBASE); // 30.06.98 cg, bugfix, adjust base to mapping boundary + a = (BYTE)MAX(a,P0MAPBASE); // adjust base to mapping boundary b = (BYTE)MIN(b,Chipset.P0End); m = (Chipset.Port0Size*2048)-1; - p = (a<<12)&m; // 29.06.98 cg, bugfix, offset to begin of P0 in nibbles + p = (a<<12)&m; // offset to begin of P0 in nibbles for (i=a; i<=b; i++) { - // 21.01.99 cg, bugfix, mapping area may have holes + // mapping area may have holes if (((i ^ Chipset.P0Base) & ~Chipset.P0Size) == 0) { RMap[i]=Chipset.Port0 + p; @@ -85,21 +111,17 @@ static VOID MapP0(BYTE a, BYTE b) static VOID MapBS(BYTE a, BYTE b) { UINT i; - // DWORD p, m; // 15.12.98 cg, removed - a = (BYTE)MAX(a,BSMAPBASE); // 30.06.98 cg, bugfix, adjust base to mapping boundary + a = (BYTE)MAX(a,BSMAPBASE); // adjust base to mapping boundary b = (BYTE)MIN(b,Chipset.BSEnd); - // m = (dwRomSize-1)&0xFF000; // 15.12.98 cg, removed - // p = (a*0x1000)&m; // 15.12.98 cg, removed for (i=a;i<=b;i++) { - // 21.01.99 cg, bugfix, mapping area may have holes + // mapping area may have holes if (((i ^ Chipset.BSBase) & ~Chipset.BSSize) == 0) { - RMap[i] = NULL; // 15.12.98 cg, bugfix, no read cycle, open data bus - WMap[i] = NULL; + RMap[i]=NULL; // bugfix, no read cycle, open data bus + WMap[i]=NULL; } - // p = (p+0x1000)&m; // 15.12.98 cg, removed } return; } @@ -109,17 +131,32 @@ static VOID MapP1(BYTE a, BYTE b) UINT i; DWORD p, m; - if (Chipset.Port1 == NULL) return; // memory for port1 allocated - // 30.06.98 cg, bugfix, adjust base to mapping boundary + // clear mapping area if port1 is configured but not plugged a = (BYTE)MAX(a,P1MAPBASE); // lowest address for use is P1Base b = (BYTE)MIN(b,Chipset.P1End); // highest address for use is P1End - m = (Chipset.Port1Size*2048)-1; // real size of module, address mask for mirroring - p = (a<<12)&m; // 29.06.98 cg, bugfix, offset to begin of P1 in nibbles - if (Chipset.Port1_Writeable) // port1 write enabled + + // port1 not plugged + if (Chipset.Port1 == NULL || !(Chipset.cards_status & PORT1_PRESENT)) { for (i=a; i<=b; i++) // scan each 2KB page { - // 21.01.99 cg, bugfix, mapping area may have holes + if (((i ^ Chipset.P1Base) & ~Chipset.P1Size) == 0) + { + RMap[i]=NULL; + WMap[i]=NULL; + } + } + return; + } + + m = (Chipset.Port1Size*2048)-1; // real size of module, address mask for mirroring + p = (a<<12)&m; // offset to begin of P1 in nibbles + + if (Chipset.cards_status & PORT1_WRITE) // 19.11.99 cg, changed, port1 write enabled + { + for (i=a; i<=b; i++) // scan each 2KB page + { + // mapping area may have holes if (((i ^ Chipset.P1Base) & ~Chipset.P1Size) == 0) { RMap[i]=Chipset.Port1 + p; // save page address for read @@ -132,7 +169,7 @@ static VOID MapP1(BYTE a, BYTE b) { for (i=a; i<=b; i++) // scan each 2KB page { - // 21.01.99 cg, bugfix, mapping area may have holes + // mapping area may have holes if (((i ^ Chipset.P1Base) & ~Chipset.P1Size) == 0) { RMap[i]=Chipset.Port1 + p; // save page address for read @@ -150,32 +187,62 @@ static VOID MapP2(BYTE a, BYTE b) DWORD p, m; LPBYTE pbyTemp; - if (pbyPort2 == NULL) return; // no port2 defined - // 15.12.98 cg, changed, Chipset.Port2_Bank now is the saved port2 FF content - pbyTemp = pbyPort2 + ((((Chipset.Port2_Bank-1)&dwPort2Mask)>>1) << 18); - a = (BYTE)MAX(a,P2MAPBASE); // 30.06.98 cg, bugfix, adjust base to mapping boundary + // clear mapping area if port2 is configured but not plugged + a = (BYTE)MAX(a,P2MAPBASE); // adjust base to mapping boundary b = (BYTE)MIN(b,Chipset.P2End); - m = (dwPort2Size*2048)-1; // 26.06.98 cg, bugfix, real size of module, address mask for mirroring - p = (a<<12)&m; // 29.06.98 cg, bugfix, offset to begin of P2 in nibbles - // 15.12.98 cg, bugfix, only fill mapping table when CE2.2 is set + + if (cCurrentRomType == 'X') // HP49G + { + m = (Chipset.Port2Size*2048)-1; + p = (a<<12)&m; // offset to begin of P0 in nibbles + for (i=a; i<=b; i++) + { + // mapping area may have holes + if (((i ^ Chipset.P2Base) & ~Chipset.P2Size) == 0) + { + RMap[i]=Chipset.Port2 + p; + WMap[i]=Chipset.Port2 + p; + } + p = (p+0x1000)&m; + } + return; + } + + // HP48SX / HP48GX + // only fill mapping table when CE2.2 is set for (i=a; i<=b; i++) // fill mapping area with not configured { - // 21.01.99 cg, bugfix, mapping area may have holes + // mapping area may have holes if (((i ^ Chipset.P2Base) & ~Chipset.P2Size) == 0) { - RMap[i] = NULL; - WMap[i] = NULL; + RMap[i]=NULL; + WMap[i]=NULL; } } + + // port2 not plugged + if (pbyPort2 == NULL || !(Chipset.cards_status & PORT2_PRESENT)) + return; + + pbyTemp = pbyPort2; + if (cCurrentRomType != 'S') // bank switching only with GX + { + // Chipset.Port2_Bank is the saved port2 FF content + pbyTemp += (((Chipset.Bank_FF>>1)-1)&dwPort2Mask) << 18; + } + + m = (dwPort2Size*2048)-1; // real size of module, address mask for mirroring + p = (a<<12)&m; // offset to begin of P2 in nibbles + // SX: CE2.2 = CE2 // GX: CE2.2 = BEN & /DA19 & /NCE3 - if (cCurrentRomType == 'S' || ((Chipset.IORam[0x29]&0x8) == 0 && (Chipset.Port2_Bank&0x40))) + if (cCurrentRomType == 'S' || ((Chipset.IORam[0x29]&0x8) == 0 && (Chipset.Bank_FF&0x40))) { if (bPort2Writeable) { for (i=a; i<=b; i++) { - // 21.01.99 cg, bugfix, mapping area may have holes + // mapping area may have holes if (((i ^ Chipset.P2Base) & ~Chipset.P2Size) == 0) { RMap[i]=pbyTemp + p; @@ -188,7 +255,7 @@ static VOID MapP2(BYTE a, BYTE b) { for (i=a; i<=b; i++) { - // 21.01.99 cg, bugfix, mapping area may have holes + // mapping area may have holes if (((i ^ Chipset.P2Base) & ~Chipset.P2Size) == 0) { RMap[i]=pbyTemp + p; @@ -197,7 +264,6 @@ static VOID MapP2(BYTE a, BYTE b) } } } - // 15.12.98 cg, end of bugfix return; } @@ -206,12 +272,28 @@ static VOID MapROM(BYTE a, BYTE b) UINT i; DWORD p, m; + if (cCurrentRomType == 'X') // HP49G + { + _ASSERT(pbyRomView[0]); // check ROM bank set + _ASSERT(pbyRomView[1]); + + m = (128*1024*2)-1; // mapped in 128KB pages + p = (a<<12)&m; // offset to the begin of ROM in nibbles + for (i=a; i<=b; i++) // scan each 2KB page + { + RMap[i]=pbyRomView[(i & 0x40)!=0] + p; + WMap[i]=NULL; // no writing + p = (p+0x1000)&m; + } + return; + } + + // HP48SX / HP48GX m = (dwRomSize-1)&0xFF000; // ROM address mask for mirroring - // 15.12.98 cg, bugfix, when G(X) ROM and DA19=0 (ROM disabled) + // when G(X) ROM and DA19=0 (ROM disabled) if (cCurrentRomType != 'S' && (Chipset.IORam[0x29]&0x8) == 0) m >>= 1; // mirror ROM at #80000 (AR18=0) - // 15.12.98 cg, end of bugfix - p = (a*0x1000)&m; // 27.06.98 cg, bugfix, data offset in nibbles + p = (a*0x1000)&m; // data offset in nibbles for (i=a;i<=b;i++) // scan each 2KB page { RMap[i]=pbyRom + p; // save page address for read @@ -223,25 +305,43 @@ static VOID MapROM(BYTE a, BYTE b) VOID Map(BYTE a, BYTE b) // maps 2KB pages with priority { - // 25.06.98 cg, size optimized implementation + // On HP49G Chipset.cards_status must be 0xF + _ASSERT(cCurrentRomType!='X' || !Chipset.P1Cfig || Chipset.cards_status == 0xF); + // priority order is HDW, RAM, CE2, CE1, NCE3, ROM MapROM(a,b); // ROM, lowest priority, always mapped - if (cCurrentRomType=='S') + if (cCurrentRomType=='S') // HP48SX { if (Chipset.BSCfig) MapBS(a,b); // NCE3, not used in S(X) - if (Chipset.P1Cfig) MapP1(a,b); // 25.06.98 cg, bugfix, CE1, port1 (lower priority than CE2) - if (Chipset.P2Cfig) MapP2(a,b); // 25.06.98 cg, bugfix, CE2, port2 (higher priority than CE1) + if (Chipset.P1Cfig) MapP1(a,b); // CE1, port1 (lower priority than CE2) + if (Chipset.P2Cfig) MapP2(a,b); // CE2, port2 (higher priority than CE1) } - else + else // HP48GX / HP49G { if (Chipset.P2Cfig) MapP2(a,b); // NCE3, port2 - if (Chipset.BSCfig) MapBS(a,b); // 25.06.98 cg, bugfix, CE1, bank select (lower priority than CE2) - if (Chipset.P1Cfig) MapP1(a,b); // 25.06.98 cg, bugfix, CE2, port1 (higher priority than CE1) + if (Chipset.BSCfig) MapBS(a,b); // CE1, bank select (lower priority than CE2) + if (Chipset.P1Cfig) MapP1(a,b); // CE2, port1 (higher priority than CE1) } if (Chipset.P0Cfig) MapP0(a,b); // RAM, highest priority (execpt HDW) return; } +VOID RomSwitch(DWORD adr) +{ + if (cCurrentRomType=='X') // only HP49G + { + Chipset.Bank_FF = adr; // save address line + // 13.12.99 cg, bugfix, A6 was always zero + adr = (adr >> 1) & 0x3f; // 6 bit of latch (was A6-A1 of address bus) + // lower 4 bit (16 banks) for 2nd ROM view + pbyRomView[1] = pbyRom + ((adr & 0xf) * 128 * 1024 * 2); + // higher 2 bit (4 banks) for 1st ROM view + pbyRomView[0] = pbyRom + ((adr >> 4) * 128 * 1024 * 2); + } + Map(0x00,0xFF); // update memory mapping + return; +} + //////////////////////////////////////////////////////////////////////////////// // // Bus Commands @@ -254,7 +354,6 @@ VOID Config() // configure modules in fixed order BYTE b = (BYTE)(d>>12); // number of 2KB pages or page address BYTE s = (BYTE)(b^0xFF); // size in pages-1, offset to last page - // 25.06.98 cg, size optimized implementation // config order is HDW, RAM, CE1, CE2, NCE3 if (!Chipset.IOCfig) // address of HDW, first module, ROM always configured { @@ -273,12 +372,12 @@ VOID Config() // configure modules in fixed order { Chipset.P0Cfig = TRUE; Chipset.P0Base = b; // save first page address - b &= ~Chipset.P0Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary + b &= ~Chipset.P0Size; // adjust base to mapping boundary Chipset.P0End = b+Chipset.P0Size; // save last page address - Map(b,Chipset.P0End); // 30.06.98 cg, bugfix, refresh mapping + Map(b,Chipset.P0End); // refresh mapping return; } - if (cCurrentRomType=='S') + if (cCurrentRomType=='S') // HP48SX { if (!Chipset.P1Cfg2) // CE1 size, port1 { @@ -290,9 +389,9 @@ VOID Config() // configure modules in fixed order { Chipset.P1Cfig = TRUE; Chipset.P1Base = b; - b &= ~Chipset.P1Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary + b &= ~Chipset.P1Size; // adjust base to mapping boundary Chipset.P1End = b+Chipset.P1Size; - Map(b,Chipset.P1End); // 30.06.98 cg, bugfix, refresh mapping + Map(b,Chipset.P1End); // refresh mapping return; } if (!Chipset.P2Cfg2) // CE2 size, port2 @@ -305,9 +404,9 @@ VOID Config() // configure modules in fixed order { Chipset.P2Cfig = TRUE; Chipset.P2Base = b; - b &= ~Chipset.P2Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary + b &= ~Chipset.P2Size; // adjust base to mapping boundary Chipset.P2End = b+Chipset.P2Size; - Map(b,Chipset.P2End); // 30.06.98 cg, bugfix, refresh mapping + Map(b,Chipset.P2End); // refresh mapping return; } if (!Chipset.BSCfg2) // NCE3 size, not used in S(X) @@ -320,13 +419,13 @@ VOID Config() // configure modules in fixed order { Chipset.BSCfig = TRUE; Chipset.BSBase = b; - b &= ~Chipset.BSSize; // 30.06.98 cg, bugfix, adjust base to mapping boundary + b &= ~Chipset.BSSize; // adjust base to mapping boundary Chipset.BSEnd = b+Chipset.BSSize; - Map(b,Chipset.BSEnd); // 30.06.98 cg, bugfix, refresh mapping + Map(b,Chipset.BSEnd); // refresh mapping return; } } - else + else // HP48GX / HP49G { if (!Chipset.BSCfg2) // CE1 size, bank select { @@ -338,9 +437,9 @@ VOID Config() // configure modules in fixed order { Chipset.BSCfig = TRUE; Chipset.BSBase = b; - b &= ~Chipset.BSSize; // 30.06.98 cg, bugfix, adjust base to mapping boundary + b &= ~Chipset.BSSize; // adjust base to mapping boundary Chipset.BSEnd = b+Chipset.BSSize; - Map(b,Chipset.BSEnd); // 30.06.98 cg, bugfix, refresh mapping + Map(b,Chipset.BSEnd); // refresh mapping return; } if (!Chipset.P1Cfg2) // CE2 size, port1 @@ -353,9 +452,9 @@ VOID Config() // configure modules in fixed order { Chipset.P1Cfig = TRUE; Chipset.P1Base = b; - b &= ~Chipset.P1Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary + b &= ~Chipset.P1Size; // adjust base to mapping boundary Chipset.P1End = b+Chipset.P1Size; - Map(b,Chipset.P1End); // 30.06.98 cg, bugfix, refresh mapping + Map(b,Chipset.P1End); // refresh mapping return; } if (!Chipset.P2Cfg2) // NCE3 size, port2 @@ -368,9 +467,9 @@ VOID Config() // configure modules in fixed order { Chipset.P2Cfig = TRUE; Chipset.P2Base = b; - b &= ~Chipset.P2Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary + b &= ~Chipset.P2Size; // adjust base to mapping boundary Chipset.P2End = b+Chipset.P2Size; - Map(b,Chipset.P2End); // 30.06.98 cg, bugfix, refresh mapping + Map(b,Chipset.P2End); // refresh mapping return; } } @@ -382,40 +481,26 @@ VOID Uncnfg() DWORD d=Npack(Chipset.C,5); // decode address BYTE b=(BYTE)(d>>12); // page address - // 25.06.98 cg, size optimized implementation // unconfig order is HDW, RAM, CE2, CE1, NCE3 - // 03.12.98 cg, bugfix, adjust base to mapping boundary if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase)) - // 03.12.98 cg, bugfix, Chipset.IOBase must be saved for C=ID command {Chipset.IOCfig=FALSE;Map(b,b);return;} - // 30.08.98 cg, bugfix, adjust base to mapping boundary if ((Chipset.P0Cfig)&&((b&~Chipset.P0Size)==P0MAPBASE)) {Chipset.P0Cfig=FALSE;Chipset.P0Cfg2=FALSE;Map(P0MAPBASE,Chipset.P0End);return;} - if (cCurrentRomType=='S') + if (cCurrentRomType=='S') // HP48SX { - // 25.06.98 cg, bugfix, CE2, port2 (higher priority than CE1) - // 30.08.98 cg, bugfix, adjust base to mapping boundary if ((Chipset.P2Cfig)&&((b&~Chipset.P2Size)==P2MAPBASE)) {Chipset.P2Cfig=FALSE;Chipset.P2Cfg2=FALSE;Map(P2MAPBASE,Chipset.P2End);return;} - // 25.06.98 cg, bugfix, CE1, port1 (lower priority than CE2) - // 30.08.98 cg, bugfix, adjust base to mapping boundary if ((Chipset.P1Cfig)&&((b&~Chipset.P1Size)==P1MAPBASE)) {Chipset.P1Cfig=FALSE;Chipset.P1Cfg2=FALSE;Map(P1MAPBASE,Chipset.P1End);return;} - // 30.08.98 cg, bugfix, adjust base to mapping boundary if ((Chipset.BSCfig)&&((b&~Chipset.BSSize)==BSMAPBASE)) {Chipset.BSCfig=FALSE;Chipset.BSCfg2=FALSE;Map(BSMAPBASE,Chipset.BSEnd);return;} } - else + else // HP48GX / HP49G { - // 25.06.98 cg, bugfix, CE2, port1 (higher priority than CE1) - // 30.08.98 cg, bugfix, adjust base to mapping boundary if ((Chipset.P1Cfig)&&((b&~Chipset.P1Size)==P1MAPBASE)) {Chipset.P1Cfig=FALSE;Chipset.P1Cfg2=FALSE;Map(P1MAPBASE,Chipset.P1End);return;} - // 25.06.98 cg, bugfix, CE1, bank select (lower priority than CE2) - // 30.08.98 cg, bugfix, adjust base to mapping boundary if ((Chipset.BSCfig)&&((b&~Chipset.BSSize)==BSMAPBASE)) {Chipset.BSCfig=FALSE;Chipset.BSCfg2=FALSE;Map(BSMAPBASE,Chipset.BSEnd);return;} - // 30.08.98 cg, bugfix, adjust base to mapping boundary if ((Chipset.P2Cfig)&&((b&~Chipset.P2Size)==P2MAPBASE)) {Chipset.P2Cfig=FALSE;Chipset.P2Cfg2=FALSE;Map(P2MAPBASE,Chipset.P2End);return;} } @@ -435,13 +520,11 @@ VOID Reset() VOID C_Eq_Id() { - // 25.06.98 cg, size optimized implementation // config order is HDW, RAM, CE1, CE2, NCE3 - // 03.12.98 cg, bugfix, don't shift Chipset.IOBase for ID if (!Chipset.IOCfig) {Nunpack(Chipset.C,(Chipset.IOBase) ^0x00019,5);return;} if (!Chipset.P0Cfg2) {Nunpack(Chipset.C,(Chipset.P0Size*0x1000)^0xFF003,5);return;} if (!Chipset.P0Cfig) {Nunpack(Chipset.C,(Chipset.P0Base*0x1000)^0x000F4,5);return;} - if (cCurrentRomType=='S') + if (cCurrentRomType=='S') // HP48SX { if (!Chipset.P1Cfg2) {Nunpack(Chipset.C,(Chipset.P1Size*0x1000)^0xFF005,5);return;} if (!Chipset.P1Cfig) {Nunpack(Chipset.C,(Chipset.P1Base*0x1000)^0x000F6,5);return;} @@ -450,7 +533,7 @@ VOID C_Eq_Id() if (!Chipset.BSCfg2) {Nunpack(Chipset.C,(Chipset.BSSize*0x1000)^0xFF001,5);return;} if (!Chipset.BSCfig) {Nunpack(Chipset.C,(Chipset.BSBase*0x1000)^0x000F2,5);return;} } - else + else // HP48GX / HP49G { if (!Chipset.BSCfg2) {Nunpack(Chipset.C,(Chipset.BSSize*0x1000)^0xFF005,5);return;} if (!Chipset.BSCfig) {Nunpack(Chipset.C,(Chipset.BSBase*0x1000)^0x000F6,5);return;} @@ -463,6 +546,28 @@ VOID C_Eq_Id() return; } + +VOID CpuReset(VOID) // 19.03.99 cg, new, register setting after Cpu Reset +{ + Chipset.pc = 0; + // 23.10.99 cg, bugfix, additional settings + Chipset.rstkp = 0; + FillMemory(Chipset.rstk,sizeof(Chipset.rstk),0); + Chipset.HST = 0; + // 23.10.99 cg, end of additional settings + Chipset.inte = TRUE; + Chipset.Shutdn = FALSE; + Chipset.SoftInt = TRUE; + Reset(); // reset MMU + bInterrupt = TRUE; + return; +} + +BYTE GetLineCounter(VOID) // get line counter value +{ + return (0x40 + F4096Hz() - byVblRef) & 0x3F; +} + VOID Npeek(BYTE *a, DWORD d, UINT s) { DWORD u, v; @@ -471,10 +576,33 @@ VOID Npeek(BYTE *a, DWORD d, UINT s) do { - u = d>>12; - v = d&0xFFF; - c = MIN(s,0x1000-v); - if ((p=RMap[u]) != NULL) memcpy(a, p+v, c); + // 12.11.99 cg, new, added reading of I/O area + // test Chipset.IOCfig for mapping + if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase)) + { + // update crc + Nunpack(Chipset.IORam+CRC, Chipset.crc, 4); + // update SRQ2 + UpdateKdnBit(); + IOBit(SRQ2,NINT2,Chipset.IORam[SRQ1] == 0 && (Chipset.IORam[SRQ2] & LSRQ) == 0); + IOBit(SRQ2,NINT,(Chipset.HST & MP) == 0); + // update timer1 + Chipset.IORam[TIMER1] = Chipset.t1; + // update timer2 + Nunpack(Chipset.IORam+TIMER2, ReadT2(), 8); + + v = d&0x3F; + c = MIN(s,0x40-v); + memcpy(a, Chipset.IORam+v, c); + } + else + // 12.11.99 cg, end of new part + { + u = d>>12; + v = d&0xFFF; + c = MIN(s,0x1000-v); + if ((p=RMap[u]) != NULL) memcpy(a, p+v, c); + } if (s-=c) {a+=c; d+=c;} } while (s); return; @@ -488,30 +616,55 @@ VOID Nread(BYTE *a, DWORD d, UINT s) do { - // 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping + // test Chipset.IOCfig for mapping if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase)) { v = d&0x3F; c = MIN(s,0x40-v); ReadIO(a,v,c); + + // 11.11.99 cg, bugfix, reading MSB of timer2 update the CRC register + if (v+c == 0x40) UpCRC(a[c-1]); // timer2 MSB touched, update the CRC register } else { u = d>>12; v = d&0xFFF; c = MIN(s,0x1000-v); - // 15.12.98 cg, bugfix, bank switching - if ((Chipset.BSCfig)&&((u&~Chipset.BSSize)==BSMAPBASE)) + if ( (cCurrentRomType != 'S') + && (Chipset.BSCfig && (((u^Chipset.BSBase) & ~Chipset.BSSize) == 0)) + && !(Chipset.P0Cfig && (((u^Chipset.P0Base) & ~Chipset.P0Size) == 0)) + && !(Chipset.P1Cfig && (((u^Chipset.P1Base) & ~Chipset.P1Size) == 0)) + ) { - Chipset.Port2_Bank = v+c; // save FF value - Map(Chipset.P2Base,Chipset.P2End); + if (cCurrentRomType == 'G') // HP48GX + { + Chipset.Bank_FF = v+c; // save FF value + Map(Chipset.P2Base,Chipset.P2End); + } + else // HP49G + { + if (0!=c) RomSwitch(d+c-1); + } } - // 15.12.98 cg, end of bugfix - if ((p=RMap[u]) != NULL) + if ((p=RMap[u]) != NULL) // module mapped { memcpy(a, p+v, c); for (u=0; uChipset.start12)) { p = a; // copy source ptr @@ -554,10 +706,9 @@ VOID Nwrite(BYTE *a, DWORD d, UINT s) } WriteToMenuDisplay(p,u,c); } - // 09.01.99 cg, end of bugfix do { - // 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping + // test Chipset.IOCfig for mapping if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase)) { v = d&0x3F; @@ -569,6 +720,35 @@ VOID Nwrite(BYTE *a, DWORD d, UINT s) u = d>>12; v = d&0xFFF; c = MIN(s,0x1000-v); + if ( (cCurrentRomType != 'S') + && (Chipset.BSCfig && (((u^Chipset.BSBase) & ~Chipset.BSSize) == 0)) + && !(Chipset.P0Cfig && (((u^Chipset.P0Base) & ~Chipset.P0Size) == 0)) + && !(Chipset.P1Cfig && (((u^Chipset.P1Base) & ~Chipset.P1Size) == 0)) + ) + { + if (cCurrentRomType == 'G') // HP48GX + { + BOOL bMap = FALSE; + + if ((v & 1) != 0) // low address odd + { + Chipset.Bank_FF = v;// save FF value + bMap = TRUE; // bank switched + } + + if ((v+c & 1) != 0) // high address odd + { + Chipset.Bank_FF = v+c-1;// save FF value + bMap = TRUE; // bank switched + } + + if (bMap) Map(Chipset.P2Base,Chipset.P2End); + } + else // HP49G + { + if (0!=c) RomSwitch(d+c-1); + } + } if ((p=WMap[u]) != NULL) memcpy(p+v, a, c); } a+=c; @@ -577,128 +757,6 @@ VOID Nwrite(BYTE *a, DWORD d, UINT s) return; } -#if 0 -// 15.12.98, removed, replaced by function Nread() -VOID Nread2(BYTE *a, DWORD d) -{ - DWORD u, v; - BYTE *p; - - // 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping - if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase)) - { - u = d&0x3F; - if (u>0x3E) {Nread(a,d,2);return;} - ReadIO(a,u,2); - return; - } - u = d>>12; - v = d&0xFFF; - if (u==Chipset.BSBase) // bank switching - { - nPort2Bank = (v&dwPort2Mask)>>1; - Map(Chipset.P2Base,Chipset.P2End); - a[0] = 3; - a[1] = 3; - return; - } - if (v>0xFFE) {Nread(a,d,2);return;} - if ((p=RMap[u]) != NULL) - { - *((WORD*)a) = *((WORD*)(p+v)); - CRC(a[0]); - CRC(a[1]); - } - return; -} -#endif - -#if 0 -// 15.12.98, removed, replaced by function Nread() -VOID Nwrite2(BYTE *a, DWORD d) -{ - DWORD u, v; - BYTE *p; - - // 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping - if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase)) - { - Nwrite(a,d,2); - return; - } - u = d>>12; - v = d&0xFFF; - if (v>0xFFE) {Nwrite(a,d,2);return;} - if ((d=Chipset.start12)) - WriteToMainDisplay(a,d,2); - if ((d=Chipset.start2)) - WriteToMenuDisplay(a,d,2); - if ((p=WMap[u]) != NULL) - { - *((WORD*)(p+v)) = *((WORD*)a); - } - return; -} -#endif - -#if 0 -// 15.12.98, removed, replaced by function Nread() -VOID Nread5(BYTE *a, DWORD d) -{ - DWORD u, v; - BYTE *p; - - // 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping - if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase)) - { - u = d&0x3F; - if (u>0x3A) {Nread(a,d,5);return;} - ReadIO(a,u,5); - return; - } - v = d&0xFFF; - if (v>0xFFA) {Nread(a,d,5);return;} - u = d>>12; - if ((p=RMap[u]) != NULL) - { - *((DWORD*)a) = *((DWORD*)(p+v)); - a[4] = p[v+4]; - CRC(a[0]); - CRC(a[1]); - CRC(a[2]); - CRC(a[3]); - CRC(a[4]); - } - return; -} -#endif - -#if 0 -// 15.12.98, removed, replaced by function Nread() -VOID Nwrite5(BYTE *a, DWORD d) -{ - DWORD u, v; - BYTE *p; - - // 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping - if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase)) - { - Nwrite(a,d,5); - return; - } - v = d&0xFFF; - if (v>0xFFA) {Nwrite(a,d,5);return;} - if ((d=Chipset.start12)) WriteToMainDisplay(a,d,5); - if ((d=Chipset.start2)) WriteToMenuDisplay(a,d,5); - u = d>>12; - if ((p=WMap[u]) != NULL) - { - *((DWORD*)(p+v)) = *((DWORD*)a); - p[v+4] = a[4]; - } -} -#endif - DWORD Read5(DWORD d) { BYTE p[8]; @@ -724,7 +782,16 @@ VOID Write5(DWORD d, DWORD n) return; } -VOID IOBit(DWORD d, BYTE b, BOOL s) // 24.02.99 cg, new, set/clear bit in I/O section +VOID Write2(DWORD d, BYTE n) +{ + BYTE p[2]; + + Nunpack(p,n,2); + Nwrite(p,d,2); + return; +} + +VOID IOBit(DWORD d, BYTE b, BOOL s) // set/clear bit in I/O section { EnterCriticalSection(&csIOLock); { @@ -736,13 +803,12 @@ VOID IOBit(DWORD d, BYTE b, BOOL s) // 24.02.99 cg, new, set/clear bit in I/O LeaveCriticalSection(&csIOLock); } -VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name +VOID ReadIO(BYTE *a, DWORD d, DWORD s) { - // DWORD d = b; // 24.08.98 cg, removed - BYTE c = 0xFF; // 26.08.98 cg, new, LINECOUNT not initialized - BOOL rbr_acc = FALSE; // 17.05.98 cg, new, flag to receive data + BYTE c = 0xFF; // LINECOUNT not initialized + BOOL rbr_acc = FALSE; // flag to receive data - #if defined DEBUG_IO // 21.01.99 cg, new + #if defined DEBUG_IO { char buffer[256]; wsprintf(buffer,"%.5lx: IO read : %02x,%u\n",Chipset.pc,d,s); @@ -768,19 +834,24 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name // case 0x0B: *a = Chipset.IORam[d]; break; // case 0x0C: *a = Chipset.IORam[d]; break; case 0x0D: // BAUD - *a = Chipset.IORam[d]; - #if defined DEBUG_SERIAL // 17.05.98 cg, return BAUD value + *a = Chipset.IORam[d] & 0x7; + #if defined DEBUG_SERIAL // return BAUD value { char buffer[256]; wsprintf(buffer,"%.5lx: BAUD Read: %x\n",Chipset.pc,*a); OutputDebugString(buffer); } #endif + *a |= UckBit(*a); // add UCK bit to BAUD rate register break; // case 0x0E: *a = Chipset.IORam[d]; break; - case 0x0F: *a = Chipset.cards_status; break; + case 0x0F: + // On a HP49G Chipset.cards_status bust always be 0xF + _ASSERT(cCurrentRomType!='X' || Chipset.cards_status == 0xF); + *a = Chipset.cards_status; + break; case 0x10: // IO CONTROL - *a = Chipset.IORam[d]; // 17.05.98 cg, return IO CONTROL value + *a = Chipset.IORam[d]; // return IO CONTROL value #if defined DEBUG_SERIAL { char buffer[256]; @@ -790,7 +861,7 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name #endif break; case 0x11: // RCS - *a = Chipset.IORam[d]; // 17.05.98 cg, return RCS value + *a = Chipset.IORam[d]; // return RCS value #if defined DEBUG_SERIAL { char buffer[256]; @@ -800,7 +871,7 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name #endif break; case 0x12: // TCS - *a = Chipset.IORam[d]; // 17.05.98 cg, new, return TCS value + *a = Chipset.IORam[d]; // return TCS value #if defined DEBUG_SERIAL { char buffer[256]; @@ -814,9 +885,10 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name break; case 0x14: // RBR LSB case 0x15: // RBR MSB - Chipset.IORam[0x11]&=0xE; - *a = Chipset.IORam[d]; // 17.05.95, new, return RBR value - rbr_acc = TRUE; // 17.05.95, new, search for new RBR value + Chipset.IORam[RCS]&=~RBF; + *a = Chipset.IORam[d]; // return RBR value + UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ + rbr_acc = TRUE; // search for new RBR value #if defined DEBUG_SERIAL { char buffer[256]; @@ -830,10 +902,14 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name *a = 0; break; case 0x19: // SREQ? MSB - UpdateKdnBit(); // 25.02.99 cg, bugfix, update KDN bit + UpdateKdnBit(); // update KDN bit + // 25.10.99 cg, bugfix, update NINT2 bit + IOBit(SRQ2,NINT2,Chipset.IORam[SRQ1] == 0 && (Chipset.IORam[SRQ2] & LSRQ) == 0); + // 25.10.99 cg, bugfix, update NINT bit + IOBit(SRQ2,NINT,(Chipset.HST & MP) == 0); // no break! case 0x18: // SREQ? LSB - *a = Chipset.IORam[d]; // 17.05.95, new, return SREQ value + *a = Chipset.IORam[d]; // return SREQ value #if defined DEBUG_SERIAL { char buffer[256]; @@ -843,7 +919,7 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name #endif break; case 0x1A: // IR CONTROL - *a = Chipset.IORam[d]; // 17.05.98 cg, new, return IR CONTROL value + *a = Chipset.IORam[d]; // return IR CONTROL value #if defined DEBUG_SERIAL { char buffer[256]; @@ -853,8 +929,8 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name #endif break; case 0x1B: *a = 0; break; - case 0x1C: *a = 0; break; - case 0x1D: *a = 0; break; + case 0x1C: *a = 0; break; // LED CONTROL + case 0x1D: *a = 0; break; // LED BUFFER // case 0x1E: *a = Chipset.IORam[0x1E]; break; // case 0x1F: *a = Chipset.IORam[0x1F]; break; case 0x20: *a = 3; break; @@ -865,15 +941,13 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name case 0x25: *a = 3; break; case 0x26: *a = 3; break; case 0x27: *a = 3; break; - // 14.01.99 cg, bugfixed LINECOUNT implementation case 0x28: // LINECOUNT LSB case 0x29: // LINECOUNT MSB + DA19 M32 if (Chipset.IORam[0x00]&8) // display on { if (c == 0xFF) // no actual line information { - // get LCD update line - c = (0x40 + F4096Hz() - byVblRef) & 0x3F; + c = GetLineCounter(); // get LCD update line // save line information in IO registers Chipset.IORam[0x28] = c & 0xF; Chipset.IORam[0x29] = (Chipset.IORam[0x29] & 0xC) | (c >> 4); @@ -893,8 +967,6 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name // case 0x2B: *a = 0; break; // case 0x2C: *a = 0; break; // case 0x2D: *a = 0; break; - // 14.01.99 cg, end of bugfixed implementation - // 21.12.98 cg, bugfix, update timer control register before case 0x2E: ReadT1(); // dummy read for update timer1 control register *a = Chipset.IORam[d]; @@ -903,7 +975,6 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name ReadT2(); // dummy read for update timer2 control register *a = Chipset.IORam[d]; break; - // 21.12.98 cg, end of bugfix case 0x30: *a = 3; break; case 0x31: *a = 3; break; case 0x32: *a = 3; break; @@ -924,23 +995,21 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name } d++; a++; } while (--s); - if (rbr_acc) CommReceive(); // 17.05.98 cg, new, look for new character + if (rbr_acc) CommReceive(); // look for new character return; } -VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name +VOID WriteIO(BYTE *a, DWORD d, DWORD s) { - // DWORD d=b; // 07.09.98 cg, removed - DWORD b; // 07.09.98 cg, new + DWORD b; BYTE c; - BYTE disp=0; - BOOL tbr_acc = FALSE; // 17.05.98 cg, new, flag to transmit data - BOOL bDISPADDR = FALSE; // 07.09.98 cg, new, flag addr 0x120-0x124 changed - BOOL bLINEOFFS = FALSE; // 07.09.98 cg, new, flag addr 0x125-0x127 changed - BOOL bLINECOUNT = FALSE; // 07.09.98 cg, new, flag addr 0x128-0x129 changed - BOOL bMENUADDR = FALSE; // 07.09.98 cg, new, flag addr 0x130-0x134 changed + BOOL tbr_acc = FALSE; // flag to transmit data + BOOL bDISPADDR = FALSE; // flag addr 0x120-0x124 changed + BOOL bLINEOFFS = FALSE; // flag addr 0x125-0x127 changed + BOOL bLINECOUNT = FALSE; // flag addr 0x128-0x129 changed + BOOL bMENUADDR = FALSE; // flag addr 0x130-0x134 changed - #if defined DEBUG_IO // 21.01.99 cg, new + #if defined DEBUG_IO { char buffer[256]; DWORD j; @@ -979,9 +1048,9 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name if ((c^Chipset.IORam[d])&8) // DON bit changed { Chipset.dispon = c>>3; - disp|=7; + disp |= (DISP_POINTER | DISP_MAIN | DISP_MENUE); - // 14.01.99 cg, bugfix, adjust VBL counter start/stop values + // adjust VBL counter start/stop values if (Chipset.dispon) // display is on { // get positive VBL difference between now and stop time @@ -995,12 +1064,11 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name BYTE a[2]; ReadIO(a,0x28,2); // update VBL at display off time } - // 14.01.99 cg, end of VBL adjust } if ((c^Chipset.IORam[d])&7) // OFF bits changed { Chipset.boffset = c&7; - disp|=3; + disp |= (DISP_POINTER | DISP_MAIN); } Chipset.IORam[d] = c; break; @@ -1014,7 +1082,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name Chipset.IORam[d]=c; Chipset.contrast = (Chipset.contrast&0x10)|c; UpdateContrast(Chipset.contrast); - disp|=7; + disp |= (DISP_POINTER | DISP_MAIN | DISP_MENUE); } break; @@ -1027,7 +1095,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name Chipset.IORam[d]=c; Chipset.contrast = (Chipset.contrast&0x0f)|((c&1)<<4); UpdateContrast(Chipset.contrast); - disp|=7; + disp |= (DISP_POINTER | DISP_MAIN | DISP_MENUE); } break; @@ -1062,7 +1130,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name if (c!=Chipset.IORam[d]) { Chipset.IORam[d] = c; - disp|=8; + disp |= DISP_ANNUN; } break; @@ -1071,7 +1139,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name // 0010D @ 3 bits = {1200 1920 2400 3840 4800 7680 9600 15360} case 0x0D: Chipset.IORam[d]=(Chipset.IORam[d]&8)|(c&7); // bit 3 is read-only - CommSetBaud(); // 17.05.98 cg, new, set baudrate + CommSetBaud(); // set baudrate #if defined DEBUG_SERIAL { char buffer[256]; @@ -1114,7 +1182,8 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name // 00110 @ Serial On, Interrupt On Recv.Buf.Empty, Full, Buzy case 0x10: Chipset.IORam[d]=c; - ioc_acc = TRUE; // 17.05.98 cg, new, new IOC + UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ + ioc_acc = TRUE; // new IOC value #if defined DEBUG_SERIAL { char buffer[256]; @@ -1153,7 +1222,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name // 00113 = HP:CRER // 00113 @ Serial Clear RER (writing anything clears RER bit) case 0x13: - Chipset.IORam[0x11]&=0xB; + Chipset.IORam[RCS]&=~RER; #if defined DEBUG_SERIAL { char buffer[256]; @@ -1174,8 +1243,9 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name case 0x16: case 0x17: Chipset.IORam[d]=c; - Chipset.IORam[0x12]|=1; - tbr_acc = TRUE; // 17.05.98 cg, new, new TBR value + Chipset.IORam[TCS]|=TBF; + UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ + tbr_acc = TRUE; // new TBR value #if defined DEBUG_SERIAL { char buffer[256]; @@ -1196,7 +1266,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name // 0011A @ IR Input, Enable IR UART mode, Enable IR Interrupt, IR Event case 0x1A: Chipset.IORam[d]=(Chipset.IORam[d]&8)|(c&7); - ir_ctrl_acc = TRUE; // 17.05.98 cg, new, new IR_CTRL + ir_ctrl_acc = TRUE; // new IR_CTRL value #if defined DEBUG_SERIAL { char buffer[256]; @@ -1229,7 +1299,6 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name // 00120 = NS:DISPADDR // 00120 @ Display Start Address (write only) // 00120 @ bit 0 is ignored (display must start on byte boundary) - // 07.09.98 cg, bugfix, new implementation case 0x20: case 0x21: case 0x22: @@ -1238,29 +1307,25 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name Chipset.IORam[d]=c; bDISPADDR = TRUE; // addr 0x120-0x124 changed break; - // 07.09.98 cg, end of new implementation // 00125 = NS:LINEOFFS // 00125 @ Display Line offset (write only) (no of bytes skipped after each line) // 00125 @ MSG sign extended - // 07.09.98 cg, bugfix, new implementation case 0x25: case 0x26: case 0x27: Chipset.IORam[d]=c; bLINEOFFS = TRUE; // addr 0x125-0x127 changed break; - // 07.09.98 cg, end of new implementation // 00128 = NS:LINECOUNT // 00128 @ Display Line Counter and miscellaneous (28-29) // 00128 @ [LC3 LC2 LC1 LC0] [DA19 M32 LC5 LC4] // 00128 @ Line counter 6 bits -> max = 2^6-1 = 63 = disp height // 00128 @ Normally has 55 -> Menu starts at display row 56 - // 07.09.98 cg, bugfix, new implementation case 0x28: case 0x29: - // 15.12.98 cg, bugfix, when G(X) and writing to register 0x29 + // when G(X) and writing to register 0x29 if (cCurrentRomType != 'S' && d == 0x29) { if ((c^Chipset.IORam[d])&8) // DA19 changed @@ -1269,11 +1334,9 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name Map(0x00,0xFF); // new ROM mapping } } - // 15.12.98 cg, end of bugfix Chipset.IORam[d]=c; bLINECOUNT = TRUE; // addr 0x128-0x129 changed break; - // 07.09.98 cg, end of new implementation case 0x2A: break; case 0x2B: break; @@ -1283,15 +1346,15 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name // 0012E = NS:TIMER1CTRL // 0012E @ TIMER1 Control [SRQ WKE INT XTRA] case 0x2E: - Chipset.IORam[d]=c; // 05.01.99 cg, bugfix, don't clear XTRA bit - ReadT1(); // 05.01.99 cg, bugfix, dummy read for checking control bits + Chipset.IORam[d]=c; // don't clear XTRA bit + ReadT1(); // dummy read for checking control bits break; // 0012F = NS:TIMER2CTRL // 0012F @ TIMER2 Control [SRQ WKE INT RUN] case 0x2F: Chipset.IORam[d]=c; - ReadT2(); // 05.01.99 cg, bugfix, dummy read for checking control bits + ReadT2(); // dummy read for checking control bits if (c&1) StartTimers(); else @@ -1301,7 +1364,6 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name // 00130 = NS:MENUADDR // 00130 @ Display Secondary Start Address (write only) (30-34) // 00130 @ Menu Display Address, no line offsets - // 07.09.98 cg, bugfix, new implementation case 0x30: case 0x31: case 0x32: @@ -1310,7 +1372,6 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name Chipset.IORam[d]=c; bMENUADDR = TRUE; // addr 0x130-0x134 changed break; - // 07.09.98 cg, end of new implementation case 0x35: break; case 0x36: break; @@ -1318,7 +1379,7 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name // 00137 = HP:TIMER1 // 00137 @ Decremented 16 times/s case 0x37: - SetT1(c); // 11.06.98 cg, bugfix, set new value + SetT1(c); // set new value break; // 00138 = HP:TIMER2 @@ -1330,48 +1391,55 @@ VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name a++; d++; } while (--s); - if (bDISPADDR) // 07.09.98 cg, new, addr 0x120-0x124 changed + if (bDISPADDR) // 0x120-0x124 changed { b = Npack(Chipset.IORam+0x20,5)&0xFFFFE; if (b != Chipset.start1) { Chipset.start1 = b; - disp|=3; + disp |= (DISP_POINTER | DISP_MAIN); } } - if (bLINEOFFS) // 07.09.98 cg, new, addr 0x125-0x127 changed + if (bLINEOFFS) // addr 0x125-0x127 changed { signed short lo = (signed short)Npack(Chipset.IORam+0x25,3); if (lo&0x800) lo-=0x1000; if (lo != Chipset.loffset) { Chipset.loffset = lo; - disp|=3; + disp |= (DISP_POINTER | DISP_MAIN); } } - if (bLINECOUNT) // 07.09.98 cg, new, addr 0x128-0x129 changed + if (bLINECOUNT) // addr 0x128-0x129 changed { b = Npack(Chipset.IORam+0x28,2)&0x3F; if (Chipset.lcounter != b) { Chipset.lcounter = b; - disp|=7; + disp |= (DISP_POINTER | DISP_MAIN | DISP_MENUE); } } - if (bMENUADDR) // 07.09.98 cg, new, addr 0x130-0x134 changed + if (bMENUADDR) // addr 0x130-0x134 changed { b = Npack(Chipset.IORam+0x30,5)&0xFFFFE; if (b != Chipset.start2) { Chipset.start2 = b; - disp|=5; + disp |= (DISP_POINTER | DISP_MENUE); } } - if (tbr_acc) CommTransmit(); // 17.05.98 cg, new, transmit char - if (disp&1) UpdateDisplayPointers(); - if (disp&2) UpdateMainDisplay(); - if (disp&4) UpdateMenuDisplay(); - if (disp&8) UpdateAnnunciators(); + if (tbr_acc) CommTransmit(); // transmit char + + if (disp & DISP_POINTER) + { + disp &= ~DISP_POINTER; // display pointer updated + UpdateDisplayPointers(); + } + if (disp & DISP_ANNUN) + { + disp &= ~DISP_ANNUN; // annunciators updated + UpdateAnnunciators(); + } return; } diff --git a/sources/Emu48/OPCODES.C b/sources/Emu48/OPCODES.C new file mode 100644 index 0000000..f0ad488 --- /dev/null +++ b/sources/Emu48/OPCODES.C @@ -0,0 +1,2415 @@ +/* + * opcodes.c + * + * This file is part of Emu48 + * + * Copyright (C) 1995 Sebastien Carlier + * Copyright (C) 1999 Christoph Gießelink + * + */ +#include "pch.h" +#include "Emu48.h" +#include "Opcodes.h" + +#define w Chipset +#define GOYES3 {if(w.carry) o_goyes3(I);else{w.pc+=2;return;}} +#define GOYES5 {if(w.carry) o_goyes5(I);else{w.pc+=2;return;}} + +#pragma intrinsic(memset,memcpy) + +#include "Ops.h" + +VOID o00(LPBYTE I) // RTNSXM +{ + w.cycles+=9; + w.pc = rstkpop(); + w.HST |= XM; + return; +} + +VOID o01(LPBYTE I) // RTN +{ + w.cycles+=9; + w.pc = rstkpop(); + return; +} + +VOID o02(LPBYTE I) // RTNSC +{ + w.cycles+=9; + w.pc = rstkpop(); + w.carry = TRUE; + return; +} + +VOID o03(LPBYTE I) // RTNCC +{ + w.cycles+=9; + w.pc = rstkpop(); + w.carry = FALSE; + return; +} + +VOID o04(LPBYTE I) // SETHEX +{ + w.cycles+=3; + w.pc+=2; + w.mode_dec = FALSE; + return; +} + +VOID o05(LPBYTE I) // SETDEC +{ + w.cycles+=3; + w.pc+=2; + w.mode_dec = TRUE; + return; +} + +VOID o06(LPBYTE I) // RSTK=C +{ + w.cycles+=8; + w.pc+=2; + rstkpush(Npack(w.C,5)); + return; +} + +VOID o07(LPBYTE I) // C=RSTK +{ + w.cycles+=8; + w.pc+=2; + Nunpack(w.C,rstkpop(),5); + return; +} + +VOID o08(LPBYTE I) // CLRST +{ + w.cycles+=5; // 22.10.99 cg, bugfix, fixed no. of cycles + w.pc+=2; + memset(w.ST, 0, 3); + return; +} + +VOID o09(LPBYTE I) // C=ST +{ + w.cycles+=5; // 22.10.99 cg, bugfix, fixed no. of cycles + w.pc+=2; + memcpy(w.C, w.ST, 3); + return; +} + +VOID o0A(LPBYTE I) // ST=C +{ + w.cycles+=5; // 22.10.99 cg, bugfix, fixed no. of cycles + w.pc+=2; + memcpy(w.ST, w.C, 3); + return; +} + +VOID o0B(LPBYTE I) // CSTEX +{ + w.cycles+=5; // 22.10.99 cg, bugfix, fixed no. of cycles + w.pc+=2; + Nxchg(w.C, w.ST, 3); + return; +} + +VOID o0C(LPBYTE I) // P=P+1 +{ + w.cycles+=3; + w.pc+=2; + if (w.P<15) + { + w.P++; + w.carry=FALSE; + } + else + { + w.P=0; + w.carry=TRUE; + } + PCHANGED; + return; +} + +VOID o0D(LPBYTE I) // P=P-1 +{ + w.cycles+=3; + w.pc+=2; + if (w.P) + { + w.P--; + w.carry=FALSE; + } + else + { + w.P=0xF; + w.carry=TRUE; + } + PCHANGED; + return; +} + +VOID o0Ef0(LPBYTE I) // A=A&B f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFand(w.A,w.B,I[2]); + return; +} +VOID o0Ef1(LPBYTE I) // B=B&C f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFand(w.B,w.C,I[2]); + return; +} +VOID o0Ef2(LPBYTE I) // C=C&A f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFand(w.C,w.A,I[2]); + return; +} +VOID o0Ef3(LPBYTE I) // D=D&C f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFand(w.D,w.C,I[2]); + return; +} +VOID o0Ef4(LPBYTE I) // B=B&A f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFand(w.B,w.A,I[2]); + return; +} +VOID o0Ef5(LPBYTE I) // C=C&B f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFand(w.C,w.B,I[2]); + return; +} +VOID o0Ef6(LPBYTE I) // A=A&C f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFand(w.A,w.C,I[2]); + return; +} +VOID o0Ef7(LPBYTE I) // C=C&D f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFand(w.C,w.D,I[2]); + return; +} + +VOID o0Ef8(LPBYTE I) // A=A!B f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFor(w.A,w.B,I[2]); + return; +} +VOID o0Ef9(LPBYTE I) // B=B!C f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFor(w.B,w.C,I[2]); + return; +} +VOID o0EfA(LPBYTE I) // C=C!A f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFor(w.C,w.A,I[2]); + return; +} +VOID o0EfB(LPBYTE I) // D=D!C f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFor(w.D,w.C,I[2]); + return; +} +VOID o0EfC(LPBYTE I) // B=B!A f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFor(w.B,w.A,I[2]); + return; +} +VOID o0EfD(LPBYTE I) // C=C!B f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFor(w.C,w.B,I[2]); + return; +} +VOID o0EfE(LPBYTE I) // A=A!C f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFor(w.A,w.C,I[2]); + return; +} +VOID o0EfF(LPBYTE I) // C=C!D f +{ + w.cycles+=4+F_l[I[2]]; + w.pc+=4; + NFor(w.C,w.D,I[2]); + return; +} + +VOID o0F(LPBYTE I) // RTI +{ + w.cycles+=9; + w.pc = rstkpop(); + w.inte = TRUE; // enable interrupt + + if ((w.intd && w.intk) || w.IR15X) // keyboard interrupt pending + { + w.intd = FALSE; // no keyboard interrupt pending any more + INTERRUPT; // restart interrupt handler + } + + // restart interrupt handler when timer interrupt + if (w.IORam[0x2E]&0x02) // INT bit of timer1 is set + ReadT1(); // check for int + + if (w.IORam[0x2F]&0x02) // INT bit of timer2 is set + ReadT2(); // check for int + return; +} + +VOID o100(LPBYTE I) // R0=A W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.R0, w.A, 16); + return; +} + +VOID o101(LPBYTE I) // R1=A W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.R1, w.A, 16); + return; +} + +VOID o102(LPBYTE I) // R2=A W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.R2, w.A, 16); + return; +} + +VOID o103(LPBYTE I) // R3=A W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.R3, w.A, 16); + return; +} + +VOID o104(LPBYTE I) // R4=A W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.R4, w.A, 16); + return; +} + +VOID o108(LPBYTE I) // R0=C W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.R0, w.C, 16); + return; +} + +VOID o109(LPBYTE I) // R1=C W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.R1, w.C, 16); + return; +} + +VOID o10A(LPBYTE I) // R2=C W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.R2, w.C, 16); + return; +} + +VOID o10B(LPBYTE I) // R3=C W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.R3, w.C, 16); + return; +} + +VOID o10C(LPBYTE I) // R4=C W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.R4, w.C, 16); + return; +} + +VOID o110(LPBYTE I) // A=R0 W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.A, w.R0, 16); + return; +} + +VOID o111(LPBYTE I) // A=R1 W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.A, w.R1, 16); + return; +} + +VOID o112(LPBYTE I) // A=R2 W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.A, w.R2, 16); + return; +} + +VOID o113(LPBYTE I) // A=R3 W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.A, w.R3, 16); + return; +} + +VOID o114(LPBYTE I) // A=R4 W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.A, w.R4, 16); + return; +} + +VOID o118(LPBYTE I) // C=R0 W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.C, w.R0, 16); + return; +} + +VOID o119(LPBYTE I) // C=R1 W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.C, w.R1, 16); + return; +} + +VOID o11A(LPBYTE I) // C=R2 W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.C, w.R2, 16); + return; +} + +VOID o11B(LPBYTE I) // C=R3 W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.C, w.R3, 16); + return; +} + +VOID o11C(LPBYTE I) // C=R4 W +{ + w.cycles+=19; + w.pc+=3; + memcpy(w.C, w.R4, 16); + return; +} + +VOID o120(LPBYTE I) // AR0EX W +{ + w.cycles+=19; + w.pc+=3; + Nxchg(w.A, w.R0, 16); + return; +} + +VOID o121(LPBYTE I) // AR1EX W +{ + w.cycles+=19; + w.pc+=3; + Nxchg(w.A, w.R1, 16); + return; +} + +VOID o122(LPBYTE I) // AR2EX W +{ + w.cycles+=19; + w.pc+=3; + Nxchg(w.A, w.R2, 16); + return; +} + +VOID o123(LPBYTE I) // AR3EX W +{ + w.cycles+=19; + w.pc+=3; + Nxchg(w.A, w.R3, 16); + return; +} + +VOID o124(LPBYTE I) // AR4EX W +{ + w.cycles+=19; + w.pc+=3; + Nxchg(w.A, w.R4, 16); + return; +} + +VOID o128(LPBYTE I) // CR0EX W +{ + w.cycles+=19; + w.pc+=3; + Nxchg(w.C, w.R0, 16); + return; +} + +VOID o129(LPBYTE I) // CR1EX W +{ + w.cycles+=19; + w.pc+=3; + Nxchg(w.C, w.R1, 16); + return; +} + +VOID o12A(LPBYTE I) // CR2EX W +{ + w.cycles+=19; + w.pc+=3; + Nxchg(w.C, w.R2, 16); + return; +} + +VOID o12B(LPBYTE I) // CR3EX W +{ + w.cycles+=19; + w.pc+=3; + Nxchg(w.C, w.R3, 16); + return; +} + +VOID o12C(LPBYTE I) // CR4EX W +{ + w.cycles+=19; + w.pc+=3; + Nxchg(w.C, w.R4, 16); + return; +} + +VOID o130(LPBYTE I) // D0=A +{ + w.cycles+=8; + w.pc+=3; + w.d0=Npack(w.A,5); + return; +} + +VOID o131(LPBYTE I) // D1=A +{ + w.cycles+=8; + w.pc+=3; + w.d1=Npack(w.A,5); + return; +} + +VOID o132(LPBYTE I) // AD0EX +{ + DWORD d = w.d0; + w.d0=Npack(w.A,5); + Nunpack(w.A,d,5); + w.cycles+=8; + w.pc+=3; + return; +} + +VOID o133(LPBYTE I) // AD1EX +{ + DWORD d=w.d1; + w.d1=Npack(w.A,5); + Nunpack(w.A,d,5); + w.cycles+=8; + w.pc+=3; + return; +} + +VOID o134(LPBYTE I) // D0=C +{ + w.cycles+=8; + w.pc+=3; + w.d0=Npack(w.C,5); + return; +} + +VOID o135(LPBYTE I) // D1=C +{ + w.cycles+=8; + w.pc+=3; + w.d1=Npack(w.C,5); + return; +} + +VOID o136(LPBYTE I) // CD0EX +{ + DWORD d=w.d0; + w.d0=Npack(w.C,5); + Nunpack(w.C,d,5); + w.cycles+=8; + w.pc+=3; + return; +} + +VOID o137(LPBYTE I) // CD1EX +{ + DWORD d=w.d1; + w.d1=Npack(w.C,5); + Nunpack(w.C,d,5); + w.cycles+=8; + w.pc+=3; + return; +} + +VOID o138(LPBYTE I)// D0=AS +{ + w.cycles+=7; + w.pc+=3; + *((WORD*)&w.d0)=(WORD)Npack(w.A,4); + return; +} + +VOID o139(LPBYTE I) // D1=AS +{ + w.cycles+=7; + w.pc+=3; + *((WORD*)&w.d1)=(WORD)Npack(w.A,4); + return; +} + +VOID o13A(LPBYTE I) // AD0XS +{ + DWORD d=w.d0; + *((WORD*)&w.d0)=(WORD)Npack(w.A,4); + Nunpack(w.A,d,4); + w.cycles+=7; + w.pc+=3; + return; +} + +VOID o13B(LPBYTE I) // AD1XS +{ + DWORD d=w.d1; + *((WORD*)&w.d1)=(WORD)Npack(w.A,4); + Nunpack(w.A,d,4); + w.cycles+=7; + w.pc+=3; + return; +} + +VOID o13C(LPBYTE I) // D0=CS +{ + w.cycles+=7; + w.pc+=3; + *((WORD*)&w.d0)=(WORD)Npack(w.C,4); + return; +} + +VOID o13D(LPBYTE I) // D1=CS +{ + w.cycles+=7; + w.pc+=3; + *((WORD*)&w.d1)=(WORD)Npack(w.C,4); + return; +} + +VOID o13E(LPBYTE I) // AD0XS +{ + DWORD d=w.d0; + *((WORD*)&w.d0)=(WORD)Npack(w.C,4); + Nunpack(w.C,d,4); + w.cycles+=7; + w.pc+=3; + return; +} + +VOID o13F(LPBYTE I) // AD1XS +{ + DWORD d=w.d1; + *((WORD*)&w.d1)=(WORD)Npack(w.C,4); + Nunpack(w.C,d,4); + w.cycles+=7; + w.pc+=3; + return; +} + +VOID o140(LPBYTE I) { w.cycles+=17; w.pc+=3; Nwrite(w.A, w.d0, 5); return; } // DAT0=A A +VOID o141(LPBYTE I) { w.cycles+=17; w.pc+=3; Nwrite(w.A, w.d1, 5); return; } // DAT1=A A +VOID o144(LPBYTE I) { w.cycles+=17; w.pc+=3; Nwrite(w.C, w.d0, 5); return; } // DAT0=C A +VOID o145(LPBYTE I) { w.cycles+=17; w.pc+=3; Nwrite(w.C, w.d1, 5); return; } // DAT1=C A +VOID o148(LPBYTE I) { w.cycles+=14; w.pc+=3; Nwrite(w.A, w.d0, 2); return; } // DAT0=A B +VOID o149(LPBYTE I) { w.cycles+=14; w.pc+=3; Nwrite(w.A, w.d1, 2); return; } // DAT1=A B +VOID o14C(LPBYTE I) { w.cycles+=14; w.pc+=3; Nwrite(w.C, w.d0, 2); return; } // DAT0=C B +VOID o14D(LPBYTE I) { w.cycles+=14; w.pc+=3; Nwrite(w.C, w.d1, 2); return; } // DAT1=C B + +VOID o142(LPBYTE I) { w.cycles+=18; w.pc+=3; Nread(w.A, w.d0, 5); return; } // A=DAT0 A +VOID o143(LPBYTE I) { w.cycles+=18; w.pc+=3; Nread(w.A, w.d1, 5); return; } // A=DAT1 A +VOID o146(LPBYTE I) { w.cycles+=18; w.pc+=3; Nread(w.C, w.d0, 5); return; } // C=DAT0 A +VOID o147(LPBYTE I) { w.cycles+=18; w.pc+=3; Nread(w.C, w.d1, 5); return; } // C=DAT1 A +VOID o14A(LPBYTE I) { w.cycles+=15; w.pc+=3; Nread(w.A, w.d0, 2); return; } // A=DAT0 B +VOID o14B(LPBYTE I) { w.cycles+=15; w.pc+=3; Nread(w.A, w.d1, 2); return; } // A=DAT1 B +VOID o14E(LPBYTE I) { w.cycles+=15; w.pc+=3; Nread(w.C, w.d0, 2); return; } // C=DAT0 B +VOID o14F(LPBYTE I) { w.cycles+=15; w.pc+=3; Nread(w.C, w.d1, 2); return; } // C=DAT0 B + +VOID o150a(LPBYTE I) { w.cycles+=16+F_l[I[3]]; w.pc+=4; NFwrite(w.A, w.d0, I[3]); return; } // DAT0=A a +VOID o151a(LPBYTE I) { w.cycles+=16+F_l[I[3]]; w.pc+=4; NFwrite(w.A, w.d1, I[3]); return; } // DAT1=A a +VOID o154a(LPBYTE I) { w.cycles+=16+F_l[I[3]]; w.pc+=4; NFwrite(w.C, w.d0, I[3]); return; } // DAT0=C a +VOID o155a(LPBYTE I) { w.cycles+=16+F_l[I[3]]; w.pc+=4; NFwrite(w.C, w.d1, I[3]); return; } // DAT1=C a +VOID o152a(LPBYTE I) { w.cycles+=17+F_l[I[3]]; w.pc+=4; NFread(w.A, w.d0, I[3]); return; } // A=DAT0 a +VOID o153a(LPBYTE I) { w.cycles+=17+F_l[I[3]]; w.pc+=4; NFread(w.A, w.d1, I[3]); return; } // A=DAT1 a +VOID o156a(LPBYTE I) { w.cycles+=17+F_l[I[3]]; w.pc+=4; NFread(w.C, w.d0, I[3]); return; } // C=DAT0 a +VOID o157a(LPBYTE I) { w.cycles+=17+F_l[I[3]]; w.pc+=4; NFread(w.C, w.d1, I[3]); return; } // C=DAT1 a + +VOID o158x(LPBYTE I) { w.cycles+=15+I[3]+1; w.pc+=4; Nwrite(w.A, w.d0, I[3]+1); return; } // DAT0=A x +VOID o159x(LPBYTE I) { w.cycles+=15+I[3]+1; w.pc+=4; Nwrite(w.A, w.d1, I[3]+1); return; } // DAT1=A x +VOID o15Cx(LPBYTE I) { w.cycles+=15+I[3]+1; w.pc+=4; Nwrite(w.C, w.d0, I[3]+1); return; } // DAT0=C x +VOID o15Dx(LPBYTE I) { w.cycles+=15+I[3]+1; w.pc+=4; Nwrite(w.C, w.d1, I[3]+1); return; } // DAT1=C x +VOID o15Ax(LPBYTE I) { w.cycles+=16+I[3]+1; w.pc+=4; Nread(w.A, w.d0, I[3]+1); return; } // A=DAT0 x +VOID o15Bx(LPBYTE I) { w.cycles+=16+I[3]+1; w.pc+=4; Nread(w.A, w.d1, I[3]+1); return; } // A=DAT1 x +VOID o15Ex(LPBYTE I) { w.cycles+=16+I[3]+1; w.pc+=4; Nread(w.C, w.d0, I[3]+1); return; } // C=DAT0 x +VOID o15Fx(LPBYTE I) { w.cycles+=16+I[3]+1; w.pc+=4; Nread(w.C, w.d1, I[3]+1); return; } // C=DAT1 x + +VOID o16x(LPBYTE I) // D0=D0+ (n+1) +{ + w.cycles+=7; + w.pc+=3; + w.d0+=I[2]+1; + if (w.d0>0xfffff) + { + w.d0&=0xfffff; + w.carry=TRUE; + } + else + { + w.carry=FALSE; + } + return; +} + +VOID o17x(LPBYTE I) // D1=D1+ (n+1) +{ + w.cycles+=7; + w.pc+=3; + w.d1+=I[2]+1; + if (w.d1>0xfffff) + { + w.d1&=0xfffff; + w.carry=TRUE; + } + else + { + w.carry=FALSE; + } + return; +} + +VOID o18x(LPBYTE I) // D0=D0- (n+1) +{ + w.cycles+=7; + w.pc+=3; + w.d0-=I[2]+1; + if (w.d0>0xfffff) + { + w.d0&=0xfffff; + w.carry=TRUE; + } + else + { + w.carry=FALSE; + } + return; +} + +VOID o19d2(LPBYTE I) // D0=(2) #dd +{ + w.cycles+=4; + w.pc+=4; + *((BYTE*)&w.d0)=(BYTE)Npack(I+2,2); + return; +} + +VOID o1Ad4(LPBYTE I) // D0=(4) #dddd +{ + w.cycles+=6; + w.pc+=6; + *((WORD*)&w.d0)=(WORD)Npack(I+2,4); + return; +} + +VOID o1Bd5(LPBYTE I) // D0=(5) #ddddd +{ + w.cycles+=7; + w.pc+=7; + w.d0=Npack(I+2,5); + return; +} + +VOID o1Cx(LPBYTE I) // D1=D1- (n+1) +{ + w.cycles+=7; + w.pc+=3; + w.d1-=I[2]+1; + if (w.d1>0xfffff) + { + w.d1&=0xfffff; + w.carry=TRUE; + } + else + { + w.carry=FALSE; + } + return; +} + +VOID o1Dd2(LPBYTE I) // D1=(2) #dd +{ + w.cycles+=4; + w.pc+=4; + *((BYTE*)&w.d1)=(BYTE)Npack(I+2,2); + return; +} + +VOID o1Ed4(LPBYTE I) // D1=(4) #dddd +{ + w.cycles+=6; + w.pc+=6; + *((WORD*)&w.d1)=(WORD)Npack(I+2,4); + return; +} + +VOID o1Fd5(LPBYTE I) // D1=(5) #ddddd +{ + w.cycles+=7; + w.pc+=7; + w.d1=Npack(I+2,5); + return; +} + +VOID o2n(LPBYTE I) // P= n +{ + w.cycles+=2; + w.pc+=2; + w.P=I[1]; + PCHANGED; + return; +} + +VOID o3X(LPBYTE I) // LCHEX +{ + UINT n=I[1]+1; + UINT d=16-w.P; + w.cycles+=3+n; // 22.10.99 cg, bugfix, fixed no. of cycles + w.pc+=2; + I+=2; // UNSAFE + if (n<=d) + { + memcpy(w.C+w.P,I,n); //Nread(C+P,w.pc,n); + } + else + { + memcpy(w.C+w.P,I,d); //Nread(C+P,w.pc,d); + memcpy(w.C,I+d,n-d); //Nread(C,w.pc+d,n-d); + } + w.pc+=n; + return; +} + +VOID o4d2(LPBYTE I) // GOC #dd +{ + if (!w.carry) + { + w.cycles+=3; + w.pc+=3; + } + else + { + signed char jmp=I[1]+(I[2]<<4); + if (jmp) + w.pc+=jmp+1; + else + w.pc=rstkpop(); + w.cycles+=10; + w.pc&=0xFFFFF; + } + return; +} + +VOID o5d2(LPBYTE I) // GONC +{ + if (w.carry) + { + w.cycles+=3; + w.pc+=3; + } + else + { + signed char jmp=I[1]+(I[2]<<4); + if (jmp) + w.pc+=jmp+1; + else + w.pc=rstkpop(); + w.cycles+=10; + w.pc&=0xFFFFF; + } + return; +} + +VOID o6d3(LPBYTE I) // GOTO +{ + DWORD d=Npack(I+1,3); + if (d&0x800) + w.pc-=0xFFF-d; + else + w.pc+=d+1; + w.cycles+=11; + w.pc&=0xFFFFF; + return; +} + +VOID o7d3(LPBYTE I) // GOSUB +{ + DWORD d=Npack(I+1,3); + rstkpush(w.pc+4); + if (d&0x800) w.pc-=0xFFC-d; else w.pc+=d+4; + w.cycles+=12; + w.pc&=0xFFFFF; + return; +} + +VOID o800(LPBYTE I) // OUT=CS +{ + w.cycles+=4; + w.pc+=3; + w.out = (w.out&0xff0) | w.C[0]; + ScanKeyboard(FALSE); + return; +} + +VOID o801(LPBYTE I) // OUT=C +{ + w.cycles+=6; + w.pc+=3; + w.out = (WORD)Npack(w.C, 3); + ScanKeyboard(FALSE); + return; +} + +VOID o802(LPBYTE I) // A=IN +{ + w.cycles+=7; + if ((w.pc&1)==0) w.pc+=3; // emulate saturn bug + AdjKeySpeed(); // slow down key repeat + IOBit(0x19,8,w.in != 0); // update KDN bit in the SRQ register + Nunpack(w.A, w.in, 4); + return; +} + +VOID o803(LPBYTE I) // C=IN +{ + w.cycles+=7; + if ((w.pc&1)==0) w.pc+=3; // emulate saturn bug + AdjKeySpeed(); // slow down key repeat + IOBit(0x19,8,w.in != 0); // update KDN bit in the SRQ register + Nunpack(w.C, w.in, 4); + return; +} + +VOID o804(LPBYTE I) // UNCNFG +{ + w.cycles+=12; + w.pc+=3; + Uncnfg(); + return; +} + +VOID o805(LPBYTE I) // CONFIG +{ + w.cycles+=11; + w.pc+=3; + Config(); + return; +} + +VOID o806(LPBYTE I) // C=ID +{ + w.cycles+=11; + w.pc+=3; + C_Eq_Id(); + return; +} + +VOID o807(LPBYTE I) // SHUTDN +{ + BOOL bShutdn = TRUE; // shut down + + w.cycles+=5; + w.pc+=3; + // only shut down when no timer wake up + if (w.IORam[0x2E]&0x04) // WKE bit of timer1 is set + { + if (ReadT1()&0x08) // and MSB of timer1 is set + { + w.IORam[0x2E] &= ~0x04; // clear WKE + bShutdn = FALSE; // don't shut down + } + } + if (w.IORam[0x2F]&0x04) // WKE bit of timer2 is set + { + if (ReadT2()&0x80000000) // and MSB of timer2 is set + { + w.IORam[0x2F] &= ~0x04; // clear WKE + bShutdn = FALSE; // don't shut down + } + } + if (w.in==0 && bShutdn) // changed, shut down only when enabled + { + w.Shutdn = TRUE; // set mode before exit emulation loop + bInterrupt = TRUE; + } + return; +} + +VOID o8080(LPBYTE I) // INTON +{ + w.cycles+=5; + w.pc+=4; + // cpu cycles at start of 1ms key handler + // 22.11.99 cg, changed, DWORD casting + w.dwKdnCycles = (DWORD) (w.cycles & 0xFFFFFFFF); + + w.intk = TRUE; + if (w.intd || w.IR15X) // keyboard interrupt pending + { + w.intd = FALSE; // no keyboard interrupt pending any more + INTERRUPT; // restart interrupt handler + } + return; +} + +VOID o80810(LPBYTE I) // RSI +{ + w.cycles+=6; + w.pc+=5; + ScanKeyboard(TRUE); // one input bit high ? + + // enable KDN update + // 22.11.99 cg, changed, DWORD casting + w.dwKdnCycles = (DWORD) (w.cycles & 0xFFFFFFFF) - (DWORD) T2CYCLES * 16; + + if (w.in && w.inte == FALSE) // key interrupt pending + w.intd = TRUE; // keyboard interrupt pending + return; +} + +VOID o8082X(LPBYTE I) // LA +{ + UINT n=I[4]+1; + UINT d=16-w.P; + w.cycles+=6+n; + w.pc+=5+n; + I+=5; // UNSAFE + if (n<=d) + { + memcpy(w.A+w.P,I,n); + } + else + { + memcpy(w.A+w.P,I,d); + memcpy(w.A,I+d,n-d); + } + return; +} + +VOID o8083(LPBYTE I) // BUSCB +{ + w.cycles+=7; + w.pc+=4; + // emulated as NOP + // InfoMessage("BUSCB instruction executed."); + return; +} + +VOID o8084n(LPBYTE I) // ABIT=0 n +{ + w.cycles+=6; + w.pc+=5; + Nbit0(w.A, I[4]); + return; +} + +VOID o8085n(LPBYTE I) // ABIT=1 n +{ + w.cycles+=6; + w.pc+=5; + Nbit1(w.A, I[4]); + return; +} + +VOID o8086n(LPBYTE I) // ?ABIT=0 n +{ + w.cycles+=9; // 22.10.99 cg, bugfix, fixed no. of cycles + w.pc+=5; + Tbit0(w.A, I[4]); + GOYES5; +} + +VOID o8087n(LPBYTE I) // ?ABIT=1 n +{ + w.cycles+=9; // 22.10.99 cg, bugfix, fixed no. of cycles + w.pc+=5; + Tbit1(w.A, I[4]); + GOYES5; +} + +VOID o8088n(LPBYTE I) // CBIT=0 n +{ + w.cycles+=6; + w.pc+=5; + Nbit0(w.C, I[4]); + return; +} + +VOID o8089n(LPBYTE I) // CBIT=1 n +{ + w.cycles+=6; + w.pc+=5; + Nbit1(w.C, I[4]); + return; +} + +VOID o808An(LPBYTE I) // ?CBIT=0 n +{ + w.cycles+=9; // 22.10.99 cg, bugfix, fixed no. of cycles + w.pc+=5; + Tbit0(w.C, I[4]); + GOYES5; +} + +VOID o808Bn(LPBYTE I) // ?CBIT=1 n +{ + w.cycles+=9; // 22.10.99 cg, bugfix, fixed no. of cycles + w.pc+=5; + Tbit1(w.C, I[4]); + GOYES5; +} + +VOID o808C(LPBYTE I) // PC=(A) +{ + w.cycles+=23; + w.pc=Read5(Npack(w.A,5)); + return; +} + +VOID o808D(LPBYTE I) // BUSCD +{ + w.cycles+=7; + w.pc+=4; + // emulated as NOP + // InfoMessage("BUSCD instruction executed."); + return; +} + +VOID o808E(LPBYTE I) // PC=(C) +{ + w.cycles+=23; + w.pc=Read5(Npack(w.C,5)); + return; +} + +VOID o808F(LPBYTE I) // INTOFF +{ + w.cycles+=5; + w.pc+=4; + UpdateKdnBit(); // update KDN bit + w.intk = FALSE; + return; +} + +VOID o809(LPBYTE I) // C+P+1 - HEX MODE +{ + w.cycles+=8; + w.pc+=3; + w.C[0]+=w.P; Nincx(w.C,5); + return; +} + +VOID o80A(LPBYTE I) // RESET +{ + w.cycles+=6; + w.pc+=3; + Reset(); + return; +} + +VOID o80B(LPBYTE I) // BUSCC +{ + w.cycles+=6; + w.pc+=3; + // emulated as NOP + // InfoMessage("BUSCC instruction executed."); + return; +} + +VOID o80Cn(LPBYTE I) // C=P n +{ + w.cycles+=6; + w.pc+=4; + w.C[I[3]] = w.P; + return; +} + +VOID o80Dn(LPBYTE I) // P=C n +{ + w.cycles+=6; + w.pc+=4; + w.P = w.C[I[3]]; + PCHANGED; + return; +} + +VOID o80E(LPBYTE I) // SREQ? +{ + w.cycles+=7; + w.pc+=3; + w.C[0]=0; + InfoMessage("SREQ? instruction executed."); + return; +} + +VOID o80Fn(LPBYTE I) // CPEX n +{ + BYTE n = w.P; + w.P = w.C[I[3]]; + w.C[I[3]] = n; + PCHANGED; + w.cycles+=6; + w.pc+=4; + return; +} + +VOID o810(LPBYTE I) // ASLC +{ + w.cycles+=21; + w.pc+=3; + Nslc(w.A, 16); + return; +} + +VOID o811(LPBYTE I) // BSLC +{ + w.cycles+=21; + w.pc+=3; + Nslc(w.B, 16); + return; +} + +VOID o812(LPBYTE I) // CSLC +{ + w.cycles+=21; + w.pc+=3; + Nslc(w.C, 16); + return; +} + +VOID o813(LPBYTE I) // DSLC +{ + w.cycles+=21; + w.pc+=3; + Nslc(w.D, 16); + return; +} + +VOID o814(LPBYTE I) // ASRC +{ + w.cycles+=21; + w.pc+=3; + Nsrc(w.A, 16); + return; +} + +VOID o815(LPBYTE I) // BSRC +{ + w.cycles+=21; + w.pc+=3; + Nsrc(w.B, 16); + return; +} + +VOID o816(LPBYTE I) // CSRC +{ + w.cycles+=21; + w.pc+=3; + Nsrc(w.C, 16); + return; +} + +VOID o817(LPBYTE I) // DSRC +{ + w.cycles+=21; + w.pc+=3; + Nsrc(w.D, 16); + return; +} + +VOID o818f0x(LPBYTE I) // A=A+x+1 f +{ + // register length with saturn bug emulation + UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; + + w.cycles+=5+F_l[I[3]]; + w.pc+=6; + w.A[F_s[I[3]]]+=I[5]; // add constant value-1 + Ninc16(w.A,nF_l,F_s[I[3]]); // add one and adjust in HEX mode + return; +} + +VOID o818f1x(LPBYTE I) // B=B+x+1 f +{ + // register length with saturn bug emulation + UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; + + w.cycles+=5+F_l[I[3]]; + w.pc+=6; + w.B[F_s[I[3]]]+=I[5]; // add constant value-1 + Ninc16(w.B,nF_l,F_s[I[3]]); // add one and adjust in HEX mode + return; +} + +VOID o818f2x(LPBYTE I) // C=C+x+1 f +{ + // register length with saturn bug emulation + UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; + + w.cycles+=5+F_l[I[3]]; + w.pc+=6; + w.C[F_s[I[3]]]+=I[5]; // add constant value-1 + Ninc16(w.C,nF_l,F_s[I[3]]); // add one and adjust in HEX mode + return; +} + +VOID o818f3x(LPBYTE I) // D=D+x+1 f +{ + // register length with saturn bug emulation + UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; + + w.cycles+=5+F_l[I[3]]; + w.pc+=6; + w.D[F_s[I[3]]]+=I[5]; // add constant value-1 + Ninc16(w.D,nF_l,F_s[I[3]]); // add one and adjust in HEX mode + return; +} + +VOID o818f8x(LPBYTE I) // A=A-x-1 f +{ + // register length with saturn bug emulation + UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; + + w.cycles+=5+F_l[I[3]]; + w.pc+=6; + w.A[F_s[I[3]]]-=I[5]; // sub constant value+1 + Ndec16(w.A,nF_l,F_s[I[3]]); // dec one and adjust in HEX mode + return; +} + +VOID o818f9x(LPBYTE I) // B=B-x-1 f +{ + // register length with saturn bug emulation + UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; + + w.cycles+=5+F_l[I[3]]; + w.pc+=6; + w.B[F_s[I[3]]]-=I[5]; // sub constant value+1 + Ndec16(w.B,nF_l,F_s[I[3]]); // dec one and adjust in HEX mode + return; +} + +VOID o818fAx(LPBYTE I) // C=C-x-1 f +{ + // register length with saturn bug emulation + UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; + + w.cycles+=5+F_l[I[3]]; + w.pc+=6; + w.C[F_s[I[3]]]-=I[5]; // sub constant value+1 + Ndec16(w.C,nF_l,F_s[I[3]]); // dec one and adjust in HEX mode + return; +} + +VOID o818fBx(LPBYTE I) // D=D-x-1 f +{ + // register length with saturn bug emulation + UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; + + w.cycles+=5+F_l[I[3]]; + w.pc+=6; + w.D[F_s[I[3]]]-=I[5]; // sub constant value+1 + Ndec16(w.D,nF_l,F_s[I[3]]); // dec one and adjust in HEX mode + return; +} + +VOID o819f0(LPBYTE I) // ASRB +{ + w.cycles+=20; + w.pc+=5; + NFsrb(w.A, I[3]); + return; +} + +VOID o819f1(LPBYTE I) // BSRB +{ + w.cycles+=20; + w.pc+=5; + NFsrb(w.B, I[3]); + return; +} + +VOID o819f2(LPBYTE I) // CSRB +{ + w.cycles+=20; + w.pc+=5; + NFsrb(w.C, I[3]); + return; +} + +VOID o819f3(LPBYTE I) // DSRB +{ + w.cycles+=20; + w.pc+=5; + NFsrb(w.D, I[3]); + return; +} + +VOID o81Af00(LPBYTE I) // R0=A f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.R0, w.A, I[3]); + return; +} + +VOID o81Af01(LPBYTE I) // R1=A f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.R1, w.A, I[3]); + return; +} + +VOID o81Af02(LPBYTE I) // R2=A f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.R2, w.A, I[3]); + return; +} + +VOID o81Af03(LPBYTE I) // R3=A f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.R3, w.A, I[3]); + return; +} + +VOID o81Af04(LPBYTE I) // R4=A f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.R4, w.A, I[3]); + return; +} + +VOID o81Af08(LPBYTE I) // R0=C f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.R0, w.C, I[3]); + return; +} + +VOID o81Af09(LPBYTE I) // R1=C f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.R1, w.C, I[3]); + return; +} + +VOID o81Af0A(LPBYTE I) // R2=C f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.R2, w.C, I[3]); + return; +} + +VOID o81Af0B(LPBYTE I) // R3=C f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.R3, w.C, I[3]); + return; +} + +VOID o81Af0C(LPBYTE I) // R4=C f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.R4, w.C, I[3]); + return; +} + +VOID o81Af10(LPBYTE I) // A=R0 f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.A, w.R0, I[3]); + return; +} + +VOID o81Af11(LPBYTE I) // A=R1 f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.A, w.R1, I[3]); + return; +} + +VOID o81Af12(LPBYTE I) // A=R2 f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.A, w.R2, I[3]); + return; +} + +VOID o81Af13(LPBYTE I) // A=R3 f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.A, w.R3, I[3]); + return; +} + +VOID o81Af14(LPBYTE I) // A=R4 f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.A, w.R4, I[3]); + return; +} + +VOID o81Af18(LPBYTE I) // C=R0 f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.C, w.R0, I[3]); + return; +} + +VOID o81Af19(LPBYTE I) // C=R1 f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.C, w.R1, I[3]); + return; +} + +VOID o81Af1A(LPBYTE I) // C=R2 f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.C, w.R2, I[3]); + return; +} + +VOID o81Af1B(LPBYTE I) // C=R3 f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.C, w.R3, I[3]); + return; +} + +VOID o81Af1C(LPBYTE I) // C=R4 f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFcopy(w.C, w.R4, I[3]); + return; +} + +VOID o81Af20(LPBYTE I) // AR0EX f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFxchg(w.A, w.R0, I[3]); + return; +} + +VOID o81Af21(LPBYTE I) // AR1EX f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFxchg(w.A, w.R1, I[3]); + return; +} + +VOID o81Af22(LPBYTE I) // AR2EX f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFxchg(w.A, w.R2, I[3]); + return; +} + +VOID o81Af23(LPBYTE I) // AR3EX f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFxchg(w.A, w.R3, I[3]); + return; +} + +VOID o81Af24(LPBYTE I) // AR4EX f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFxchg(w.A, w.R4, I[3]); + return; +} + +VOID o81Af28(LPBYTE I) // CR0EX f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFxchg(w.C, w.R0, I[3]); + return; +} + +VOID o81Af29(LPBYTE I) // CR1EX f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFxchg(w.C, w.R1, I[3]); + return; +} + +VOID o81Af2A(LPBYTE I) // CR2EX f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFxchg(w.C, w.R2, I[3]); + return; +} + +VOID o81Af2B(LPBYTE I) // CR3EX f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFxchg(w.C, w.R3, I[3]); + return; +} + +VOID o81Af2C(LPBYTE I) // CR4EX f +{ + w.cycles+=6+F_l[I[3]]; + w.pc+=6; + NFxchg(w.C, w.R4, I[3]); + return; +} + +VOID o81B2(LPBYTE I) // PC=A +{ + w.cycles+=16; + w.pc = Npack(w.A,5); + return; +} + +VOID o81B3(LPBYTE I) // PC=C +{ + w.cycles+=16; + w.pc = Npack(w.C,5); + return; +} + +VOID o81B4(LPBYTE I) // A=PC +{ + w.cycles+=9; + w.pc+=4; + Nunpack(w.A,w.pc,5); + return; +} + +VOID o81B5(LPBYTE I) // C=PC +{ + w.cycles+=9; + w.pc+=4; + Nunpack(w.C,w.pc,5); + return; +} + +VOID o81B6(LPBYTE I) // APCEX +{ + DWORD d=w.pc+4; + w.cycles+=16; + w.pc=Npack(w.A,5); + Nunpack(w.A,d,5); + return; +} + +VOID o81B7(LPBYTE I) // CPCEX +{ + DWORD d=w.pc+4; + w.cycles+=16; + w.pc=Npack(w.C,5); + Nunpack(w.C,d,5); + return; +} + +VOID o81C(LPBYTE I) // ASRB +{ + w.cycles+=20; + w.pc+=3; + Nsrb(w.A, 16); + return; +} + +VOID o81D(LPBYTE I) // BSRB +{ + w.cycles+=20; + w.pc+=3; + Nsrb(w.B, 16); + return; +} + +VOID o81E(LPBYTE I) // CSRB +{ + w.cycles+=20; + w.pc+=3; + Nsrb(w.C, 16); + return; +} + +VOID o81F(LPBYTE I) // DSRB +{ + w.cycles+=20; + w.pc+=3; + Nsrb(w.D, 16); + return; +} + +VOID o82n(LPBYTE I) // HST=0 m +{ + w.cycles+=3; + w.pc+=3; + w.HST&=~I[2]; + return; +} + +VOID o83n(LPBYTE I) // ?HST=0 m +{ + w.cycles+=6; + w.pc+=3; + if ((w.HST&I[2])==0) + w.carry=TRUE; + else + w.carry=FALSE; + GOYES3; +} + +VOID o84n(LPBYTE I) // ST=0 n +{ + w.cycles+=4; + w.pc+=3; + Nbit0(w.ST, I[2]); + return; +} + +VOID o85n(LPBYTE I) // ST=1 n +{ + w.cycles+=4; + w.pc+=3; + Nbit1(w.ST, I[2]); + return; +} + +VOID o86n(LPBYTE I) // ?ST=0 n +{ + w.cycles+=7; + w.pc+=3; + Tbit0(w.ST, I[2]); + GOYES3; +} + +VOID o87n(LPBYTE I) // ?ST=1 n +{ + w.cycles+=7; + w.pc+=3; + Tbit1(w.ST, I[2]); + GOYES3; +} + +VOID o88n(LPBYTE I) // ?P# n +{ + w.cycles+=6; + w.pc+=3; + if (w.P!=I[2]) + w.carry=TRUE; + else + w.carry=FALSE; + GOYES3; +} + +VOID o89n(LPBYTE I) // ?P= n +{ + w.cycles+=6; + w.pc+=3; + if (w.P==I[2]) + w.carry=TRUE; + else + w.carry=FALSE; + GOYES3; +} + +VOID o8A0(LPBYTE I) // ?A=B A +{ + w.cycles+=11; + w.pc+=3; + Te(w.A, w.B, 5); + GOYES3; +} + +VOID o8A1(LPBYTE I) // ?B=C A +{ + w.cycles+=11; + w.pc+=3; + Te(w.B, w.C, 5); + GOYES3; +} + +VOID o8A2(LPBYTE I) // ?C=A A +{ + w.cycles+=11; + w.pc+=3; + Te(w.C, w.A, 5); + GOYES3; +} + +VOID o8A3(LPBYTE I) // ?D=C A +{ + w.cycles+=11; + w.pc+=3; + Te(w.D, w.C, 5); + GOYES3; +} + +VOID o8A4(LPBYTE I) // ?A#B A +{ + w.cycles+=11; + w.pc+=3; + Tne(w.A, w.B, 5); + GOYES3; +} + +VOID o8A5(LPBYTE I) // ?B#C A +{ + w.cycles+=11; + w.pc+=3; + Tne(w.B, w.C, 5); + GOYES3; +} + +VOID o8A6(LPBYTE I) // ?C#A A +{ + w.cycles+=11; + w.pc+=3; + Tne(w.C, w.A, 5); + GOYES3; +} + +VOID o8A7(LPBYTE I) // ?D#C A +{ + w.cycles+=11; + w.pc+=3; + Tne(w.D, w.C, 5); + GOYES3; +} + +VOID o8A8(LPBYTE I) // ?A=0 A +{ + w.cycles+=11; + w.pc+=3; + Tz(w.A, 5); + GOYES3; +} + +VOID o8A9(LPBYTE I) // ?B=0 A +{ + w.cycles+=11; + w.pc+=3; + Tz(w.B, 5); + GOYES3; +} + +VOID o8AA(LPBYTE I) // ?C=0 A +{ + w.cycles+=11; + w.pc+=3; + Tz(w.C, 5); + GOYES3; +} + +VOID o8AB(LPBYTE I) // ?D=0 A +{ + w.cycles+=11; + w.pc+=3; + Tz(w.D, 5); + GOYES3; +} + +VOID o8AC(LPBYTE I) // ?A#0 A +{ + w.cycles+=11; + w.pc+=3; + Tnz(w.A, 5); + GOYES3; +} + +VOID o8AD(LPBYTE I) // ?B#0 A +{ + w.cycles+=11; + w.pc+=3; + Tnz(w.B, 5); + GOYES3; +} + +VOID o8AE(LPBYTE I) // ?C#0 A +{ + w.cycles+=11; + w.pc+=3; + Tnz(w.C, 5); + GOYES3; +} + +VOID o8AF(LPBYTE I) // ?D#0 A +{ + w.cycles+=11; + w.pc+=3; + Tnz(w.D, 5); + GOYES3; +} + +VOID o8B0(LPBYTE I) // ?A>B A +{ + w.cycles+=11; + w.pc+=3; + Ta(w.A, w.B, 5); + GOYES3; +} + +VOID o8B1(LPBYTE I) // ?B>C A +{ + w.cycles+=11; + w.pc+=3; + Ta(w.B, w.C, 5); + GOYES3; +} + +VOID o8B2(LPBYTE I) // ?C>A A +{ + w.cycles+=11; + w.pc+=3; + Ta(w.C, w.A, 5); + GOYES3; +} + +VOID o8B3(LPBYTE I) // ?D>C A +{ + w.cycles+=11; + w.pc+=3; + Ta(w.D, w.C, 5); + GOYES3; +} + +VOID o8B4(LPBYTE I) // ?A=B A +{ + w.cycles+=11; + w.pc+=3; + Tae(w.A, w.B, 5); + GOYES3; +} + +VOID o8B9(LPBYTE I) // ?B>=C A +{ + w.cycles+=11; + w.pc+=3; + Tae(w.B, w.C, 5); + GOYES3; +} + +VOID o8BA(LPBYTE I) // ?C>=A A +{ + w.cycles+=11; + w.pc+=3; + Tae(w.C, w.A, 5); + GOYES3; +} + +VOID o8BB(LPBYTE I) // ?D>=C A +{ + w.cycles+=11; + w.pc+=3; + Tae(w.D, w.C, 5); + GOYES3; +} + +VOID o8BC(LPBYTE I) // ?A<=B A +{ + w.cycles+=11; + w.pc+=3; + Tbe(w.A, w.B, 5); + GOYES3; +} + +VOID o8BD(LPBYTE I) // ?B<=C A +{ + w.cycles+=11; + w.pc+=3; + Tbe(w.B, w.C, 5); + GOYES3; +} + +VOID o8BE(LPBYTE I) // ?C<=A A +{ + w.cycles+=11; + w.pc+=3; + Tbe(w.C, w.A, 5); + GOYES3; +} + +VOID o8BF(LPBYTE I) // ?D<=C A +{ + w.cycles+=11; + w.pc+=3; + Tbe(w.D, w.C, 5); + GOYES3; +} + +VOID o8Cd4(LPBYTE I) // GOLONG #dddd +{ + DWORD d=Npack(I+2, 4); + if (d&0x8000) w.pc-=0xfffe-d; else w.pc+=d+2; + w.cycles+=14; + w.pc&=0xFFFFF; + return; +} + +VOID o8Dd5(LPBYTE I) // GOVLNG #ddddd +{ + w.cycles+=14; + w.pc = Npack(I+2, 5); + return; +} + +VOID o8Ed4(LPBYTE I) // GOSUBL #dddd +{ + DWORD d=Npack(I+2,4); + rstkpush(w.pc+6); + if (d&0x8000) w.pc-=0xfffa-d; else w.pc+=d+6; + w.cycles+=14; // 22.10.99 cg, bugfix, fixed no. of cycles + w.pc&=0xFFFFF; + return; +} + +VOID o8Fd5(LPBYTE I) // GOSBVL #ddddd +{ + w.cycles+=15; + rstkpush(w.pc+7); + w.pc=Npack(I+2, 5); + return; +} + + // ?r=s f +VOID o9a0(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.A, w.B, I[1]); GOYES3; } +VOID o9a1(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.B, w.C, I[1]); GOYES3; } +VOID o9a2(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.C, w.A, I[1]); GOYES3; } +VOID o9a3(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.D, w.C, I[1]); GOYES3; } + + // ?r#s f +VOID o9a4(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFne(w.A, w.B, I[1]); GOYES3; } +VOID o9a5(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFne(w.B, w.C, I[1]); GOYES3; } +VOID o9a6(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFne(w.C, w.A, I[1]); GOYES3; } +VOID o9a7(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFne(w.D, w.C, I[1]); GOYES3; } + + // ?r=0 f +VOID o9a8(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFz(w.A, I[1]); GOYES3; } +VOID o9a9(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFz(w.B, I[1]); GOYES3; } +VOID o9aA(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFz(w.C, I[1]); GOYES3; } +VOID o9aB(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFz(w.D, I[1]); GOYES3; } + + // ?r#0 f +VOID o9aC(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFnz(w.A, I[1]); GOYES3; } +VOID o9aD(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFnz(w.B, I[1]); GOYES3; } +VOID o9aE(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFnz(w.C, I[1]); GOYES3; } +VOID o9aF(LPBYTE I) { w.cycles+=6+F_l[I[1]]; w.pc+=3; TFnz(w.D, I[1]); GOYES3; } + + // ?s>r f +VOID o9b0(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFa(w.A, w.B, I[1]&7); GOYES3; } +VOID o9b1(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFa(w.B, w.C, I[1]&7); GOYES3; } +VOID o9b2(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFa(w.C, w.A, I[1]&7); GOYES3; } +VOID o9b3(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFa(w.D, w.C, I[1]&7); GOYES3; } + + // ?r=s f +VOID o9b8(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFae(w.A, w.B, I[1]&7); GOYES3; } +VOID o9b9(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFae(w.B, w.C, I[1]&7); GOYES3; } +VOID o9bA(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFae(w.C, w.A, I[1]&7); GOYES3; } +VOID o9bB(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFae(w.D, w.C, I[1]&7); GOYES3; } + + // ?r<=s f +VOID o9bC(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFbe(w.A, w.B, I[1]&7); GOYES3; } +VOID o9bD(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFbe(w.B, w.C, I[1]&7); GOYES3; } +VOID o9bE(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFbe(w.C, w.A, I[1]&7); GOYES3; } +VOID o9bF(LPBYTE I) { w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFbe(w.D, w.C, I[1]&7); GOYES3; } + + // r=r+s f +VOID oAa0(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.A, w.B, I[1]); return; } +VOID oAa1(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.B, w.C, I[1]); return; } +VOID oAa2(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.C, w.A, I[1]); return; } +VOID oAa3(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.D, w.C, I[1]); return; } + + // r=r+r f +VOID oAa4(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.A, w.A, I[1]); return; } +VOID oAa5(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.B, w.B, I[1]); return; } +VOID oAa6(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.C, w.C, I[1]); return; } +VOID oAa7(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.D, w.D, I[1]); return; } + + // s=s+r f +VOID oAa8(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.B, w.A, I[1]); return; } +VOID oAa9(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.C, w.B, I[1]); return; } +VOID oAaA(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.A, w.C, I[1]); return; } +VOID oAaB(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.C, w.D, I[1]); return; } + + // r=r-1 f +VOID oAaC(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFdec(w.A, I[1]); return; } +VOID oAaD(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFdec(w.B, I[1]); return; } +VOID oAaE(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFdec(w.C, I[1]); return; } +VOID oAaF(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFdec(w.D, I[1]); return; } + + // r=0 f +VOID oAb0(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFzero(w.A, I[1]&7); return; } +VOID oAb1(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFzero(w.B, I[1]&7); return; } +VOID oAb2(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFzero(w.C, I[1]&7); return; } +VOID oAb3(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFzero(w.D, I[1]&7); return; } + + // r=s f +VOID oAb4(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.A, w.B, I[1]&7); return; } +VOID oAb5(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.B, w.C, I[1]&7); return; } +VOID oAb6(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.C, w.A, I[1]&7); return; } +VOID oAb7(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.D, w.C, I[1]&7); return; } + + // s=r f +VOID oAb8(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.B, w.A, I[1]&7); return; } +VOID oAb9(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.C, w.B, I[1]&7); return; } +VOID oAbA(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.A, w.C, I[1]&7); return; } +VOID oAbB(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.C, w.D, I[1]&7); return; } + + // rsEX f +VOID oAbC(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFxchg(w.A, w.B, I[1]&7); return; } +VOID oAbD(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFxchg(w.B, w.C, I[1]&7); return; } +VOID oAbE(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFxchg(w.C, w.A, I[1]&7); return; } +VOID oAbF(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFxchg(w.D, w.C, I[1]&7); return; } + + // r=r-s f +VOID oBa0(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.A, w.B, I[1]); return; } +VOID oBa1(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.B, w.C, I[1]); return; } +VOID oBa2(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.C, w.A, I[1]); return; } +VOID oBa3(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.D, w.C, I[1]); return; } + + // r=r+1 f +VOID oBa4(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFinc(w.A, I[1]); return; } +VOID oBa5(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFinc(w.B, I[1]); return; } +VOID oBa6(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFinc(w.C, I[1]); return; } +VOID oBa7(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFinc(w.D, I[1]); return; } + + // s=s-r f +VOID oBa8(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.B, w.A, I[1]); return; } +VOID oBa9(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.C, w.B, I[1]); return; } +VOID oBaA(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.A, w.C, I[1]); return; } +VOID oBaB(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.C, w.D, I[1]); return; } + + // r=s-r f +VOID oBaC(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFrsub(w.A, w.B, I[1]); return; } +VOID oBaD(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFrsub(w.B, w.C, I[1]); return; } +VOID oBaE(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFrsub(w.C, w.A, I[1]); return; } +VOID oBaF(LPBYTE I) { w.cycles+=3+F_l[I[1]]; w.pc+=3; NFrsub(w.D, w.C, I[1]); return; } + + // rSL f +VOID oBb0(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsl(w.A, I[1]&7); return; } +VOID oBb1(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsl(w.B, I[1]&7); return; } +VOID oBb2(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsl(w.C, I[1]&7); return; } +VOID oBb3(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsl(w.D, I[1]&7); return; } + + // rSR f +VOID oBb4(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsr(w.A, I[1]&7); return; } +VOID oBb5(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsr(w.B, I[1]&7); return; } +VOID oBb6(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsr(w.C, I[1]&7); return; } +VOID oBb7(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsr(w.D, I[1]&7); return; } + + // r=-r f +VOID oBb8(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFneg(w.A, I[1]&7); return; } +VOID oBb9(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFneg(w.B, I[1]&7); return; } +VOID oBbA(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFneg(w.C, I[1]&7); return; } +VOID oBbB(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFneg(w.D, I[1]&7); return; } + + // r=-r-1 f +VOID oBbC(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFnot(w.A, I[1]&7); return; } +VOID oBbD(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFnot(w.B, I[1]&7); return; } +VOID oBbE(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFnot(w.C, I[1]&7); return; } +VOID oBbF(LPBYTE I) { w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFnot(w.D, I[1]&7); return; } + + // r=r+s A +VOID oC0(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.A, w.B, 5); return; } +VOID oC1(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.B, w.C, 5); return; } +VOID oC2(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.C, w.A, 5); return; } +VOID oC3(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.D, w.C, 5); return; } + + // r=r+r A +VOID oC4(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.A, w.A, 5); return; } +VOID oC5(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.B, w.B, 5); return; } +VOID oC6(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.C, w.C, 5); return; } +VOID oC7(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.D, w.D, 5); return; } + + // s=s+r A +VOID oC8(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.B, w.A, 5); return; } +VOID oC9(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.C, w.B, 5); return; } +VOID oCA(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.A, w.C, 5); return; } +VOID oCB(LPBYTE I) { w.cycles+=7; w.pc+=2; Nadd(w.C, w.D, 5); return; } + + // r=r-1 A +VOID oCC(LPBYTE I) { w.cycles+=7; w.pc+=2; Ndec(w.A, 5, 0); return; } +VOID oCD(LPBYTE I) { w.cycles+=7; w.pc+=2; Ndec(w.B, 5, 0); return; } +VOID oCE(LPBYTE I) { w.cycles+=7; w.pc+=2; Ndec(w.C, 5, 0); return; } +VOID oCF(LPBYTE I) { w.cycles+=7; w.pc+=2; Ndec(w.D, 5, 0); return; } + + // r=0 A +VOID oD0(LPBYTE I) { w.cycles+=7; w.pc+=2; memset(w.A, 0, 5); return; } +VOID oD1(LPBYTE I) { w.cycles+=7; w.pc+=2; memset(w.B, 0, 5); return; } +VOID oD2(LPBYTE I) { w.cycles+=7; w.pc+=2; memset(w.C, 0, 5); return; } +VOID oD3(LPBYTE I) { w.cycles+=7; w.pc+=2; memset(w.D, 0, 5); return; } + + // r=s A +VOID oD4(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.A, w.B, 5); return; } +VOID oD5(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.B, w.C, 5); return; } +VOID oD6(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.C, w.A, 5); return; } +VOID oD7(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.D, w.C, 5); return; } + + // s=r A +VOID oD8(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.B, w.A, 5); return; } +VOID oD9(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.C, w.B, 5); return; } +VOID oDA(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.A, w.C, 5); return; } +VOID oDB(LPBYTE I) { w.cycles+=7; w.pc+=2; memcpy(w.C, w.D, 5); return; } + + // rsEX +VOID oDC(LPBYTE I) { w.cycles+=7; w.pc+=2; Nxchg(w.A, w.B, 5); return; } +VOID oDD(LPBYTE I) { w.cycles+=7; w.pc+=2; Nxchg(w.B, w.C, 5); return; } +VOID oDE(LPBYTE I) { w.cycles+=7; w.pc+=2; Nxchg(w.C, w.A, 5); return; } +VOID oDF(LPBYTE I) { w.cycles+=7; w.pc+=2; Nxchg(w.D, w.C, 5); return; } + + // r=r-s A +VOID oE0(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.A, w.B, 5); return; } +VOID oE1(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.B, w.C, 5); return; } +VOID oE2(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.C, w.A, 5); return; } +VOID oE3(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.D, w.C, 5); return; } + + // r=r+1 A +VOID oE4(LPBYTE I) { w.cycles+=7; w.pc+=2; Ninc(w.A, 5, 0); return; } +VOID oE5(LPBYTE I) { w.cycles+=7; w.pc+=2; Ninc(w.B, 5, 0); return; } +VOID oE6(LPBYTE I) { w.cycles+=7; w.pc+=2; Ninc(w.C, 5, 0); return; } +VOID oE7(LPBYTE I) { w.cycles+=7; w.pc+=2; Ninc(w.D, 5, 0); return; } + + // s=s-r A +VOID oE8(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.B, w.A, 5); return; } +VOID oE9(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.C, w.B, 5); return; } +VOID oEA(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.A, w.C, 5); return; } +VOID oEB(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsub(w.C, w.D, 5); return; } + + // r=s-r A +VOID oEC(LPBYTE I) { w.cycles+=7; w.pc+=2; Nrsub(w.A, w.B, 5); return; } +VOID oED(LPBYTE I) { w.cycles+=7; w.pc+=2; Nrsub(w.B, w.C, 5); return; } +VOID oEE(LPBYTE I) { w.cycles+=7; w.pc+=2; Nrsub(w.C, w.A, 5); return; } +VOID oEF(LPBYTE I) { w.cycles+=7; w.pc+=2; Nrsub(w.D, w.C, 5); return; } + + // rSL A +VOID oF0(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsl(w.A, 5); return; } +VOID oF1(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsl(w.B, 5); return; } +VOID oF2(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsl(w.C, 5); return; } +VOID oF3(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsl(w.D, 5); return; } + + // rSR A +VOID oF4(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsr(w.A, 5); return; } +VOID oF5(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsr(w.B, 5); return; } +VOID oF6(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsr(w.C, 5); return; } +VOID oF7(LPBYTE I) { w.cycles+=7; w.pc+=2; Nsr(w.D, 5); return; } + + // r=-r A +VOID oF8(LPBYTE I) { w.cycles+=7; w.pc+=2; Nneg(w.A, 5); return; } +VOID oF9(LPBYTE I) { w.cycles+=7; w.pc+=2; Nneg(w.B, 5); return; } +VOID oFA(LPBYTE I) { w.cycles+=7; w.pc+=2; Nneg(w.C, 5); return; } +VOID oFB(LPBYTE I) { w.cycles+=7; w.pc+=2; Nneg(w.D, 5); return; } + + // r=-r-1 A +VOID oFC(LPBYTE I) { w.cycles+=7; w.pc+=2; Nnot(w.A, 5); return; } +VOID oFD(LPBYTE I) { w.cycles+=7; w.pc+=2; Nnot(w.B, 5); return; } +VOID oFE(LPBYTE I) { w.cycles+=7; w.pc+=2; Nnot(w.C, 5); return; } +VOID oFF(LPBYTE I) { w.cycles+=7; w.pc+=2; Nnot(w.D, 5); return; } + +// invalid, unknown length (LPBYTE I) reset +VOID o_invalid(LPBYTE I) +{ + _ASSERT(FALSE); // invalid, unknow length + w.pc=0; + return; +} + +// length is guessed, just skip +VOID o_invalid3(LPBYTE I) +{ + _ASSERT(FALSE); // invalid, length guessed, skip 3 nibbles + w.pc+=3; + return; +} + +VOID o_invalid4(LPBYTE I) +{ + _ASSERT(FALSE); // invalid, length guessed, skip 4 nibbles + w.pc+=4; + return; +} + +VOID o_invalid5(LPBYTE I) +{ + _ASSERT(FALSE); // invalid, length guessed, skip 5 nibbles + w.pc+=5; + return; +} + +VOID o_invalid6(LPBYTE I) +{ + _ASSERT(FALSE); // invalid, length guessed, skip 6 nibbles + w.pc+=6; + return; +} + +VOID o_goyes3(LPBYTE I) +{ + signed char jmp = I[3]+(I[4]<<4); + w.cycles+=7; + if (jmp) + w.pc=(w.pc+jmp)&0xFFFFF; + else + w.pc=rstkpop(); + return; +} + +VOID o_goyes5(LPBYTE I) +{ + signed char jmp = I[5]+(I[6]<<4); + w.cycles+=7; + if (jmp) + w.pc=(w.pc+jmp)&0xFFFFF; + else + w.pc=rstkpop(); + return; +} + +//////// EXTENSIONS //////// +#if 0 // unused extension +VOID o81B0(LPBYTE I) + // ?Win48 + w.HST |= SB; + w.pc+=4; + return; +#endif + +VOID o81B1(LPBYTE I) +{ + External(&w); + PCHANGED; // update field select table + return; +} +//////////////////////////// diff --git a/sources/Emu48/OPCODES.H b/sources/Emu48/OPCODES.H index 5081465..56a3965 100644 --- a/sources/Emu48/OPCODES.H +++ b/sources/Emu48/OPCODES.H @@ -3,2403 +3,449 @@ * * This file is part of Emu48 * - * Copyright (C) 1995 Sebastien Carlier + * Copyright (C) 1999 Christoph Gießelink * */ -// 05.03.98 cg, added cycles for each command (S(X) values) - -o00: // RTNSXM -{ - w.cycles+=9; - w.pc = rstkpop(); - w.HST |= XM; - continue; -} - -o01: // RTN -{ - w.cycles+=9; - w.pc = rstkpop(); - continue; -} - -o02: // RTNSC -{ - w.cycles+=9; - w.pc = rstkpop(); - w.carry = TRUE; - continue; -} - -o03: // RTNCC -{ - w.cycles+=9; - w.pc = rstkpop(); - w.carry = FALSE; - continue; -} - -o04: // SETHEX -{ - w.cycles+=3; - w.pc+=2; - w.mode_dec = FALSE; - continue; -} - -o05: // SETDEC -{ - w.cycles+=3; - w.pc+=2; - w.mode_dec = TRUE; - continue; -} - -o06: // RSTK=C -{ - w.cycles+=8; - w.pc+=2; - rstkpush(Npack(w.C,5)); - continue; -} - -o07: // C=RSTK -{ - w.cycles+=8; - w.pc+=2; - Nunpack(w.C,rstkpop(),5); - continue; -} - -o08: // CLRST -{ - w.cycles+=6; - w.pc+=2; - memset(w.ST, 0, 3); - continue; -} - -o09: // C=ST -{ - w.cycles+=6; - w.pc+=2; - memcpy(w.C, w.ST, 3); - continue; -} - -o0A: // ST=C -{ - w.cycles+=6; - w.pc+=2; - memcpy(w.ST, w.C, 3); - continue; -} - -o0B: // CSTEX -{ - w.cycles+=6; - w.pc+=2; - Nxchg(w.C, w.ST, 3); - continue; -} - -o0C: // P=P+1 -{ - w.cycles+=3; - w.pc+=2; - if (w.P<15) - { - w.P++; - w.carry=FALSE; - } - else - { - w.P=0; - w.carry=TRUE; - } - PCHANGED; - continue; -} - -o0D: // P=P-1 -{ - w.cycles+=3; - w.pc+=2; - if (w.P) - { - w.P--; - w.carry=FALSE; - } - else - { - w.P=0xF; - w.carry=TRUE; - } - PCHANGED; - continue; -} - -o0Ef0: // A=A&B f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFand(w.A,w.B,I[2]); - continue; -} -o0Ef1: // B=B&C f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFand(w.B,w.C,I[2]); - continue; -} -o0Ef2: // C=C&A f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFand(w.C,w.A,I[2]); - continue; -} -o0Ef3: // D=D&C f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFand(w.D,w.C,I[2]); - continue; -} -o0Ef4: // B=B&A f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFand(w.B,w.A,I[2]); - continue; -} -o0Ef5: // C=C&B f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFand(w.C,w.B,I[2]); - continue; -} -o0Ef6: // A=A&C f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFand(w.A,w.C,I[2]); - continue; -} -o0Ef7: // C=C&D f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFand(w.C,w.D,I[2]); - continue; -} - -o0Ef8: // A=A!B f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFor(w.A,w.B,I[2]); - continue; -} -o0Ef9: // B=B!C f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFor(w.B,w.C,I[2]); - continue; -} -o0EfA: // C=C!A f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFor(w.C,w.A,I[2]); - continue; -} -o0EfB: // D=D!C f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFor(w.D,w.C,I[2]); - continue; -} -o0EfC: // B=B!A f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFor(w.B,w.A,I[2]); - continue; -} -o0EfD: // C=C!B f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFor(w.C,w.B,I[2]); - continue; -} -o0EfE: // A=A!C f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFor(w.A,w.C,I[2]); - continue; -} -o0EfF: // C=C!D f -{ - w.cycles+=4+F_l[I[2]]; - w.pc+=4; - NFor(w.C,w.D,I[2]); - continue; -} - -o0F: // RTI -{ - w.cycles+=9; - w.pc = rstkpop(); - w.inte = TRUE; // enable interrupt - - if ((w.intd && w.intk) || w.IR15X) // 28.03.99 cg, bugfix, keyboard interrupt pending - { - w.intd = FALSE; // no keyboard interrupt pending any more - INTERRUPT; // restart interrupt handler - } - - // 30.11.98 cg, bugfix, restart interrupt handler when timer interrupt - if (w.IORam[0x2E]&0x02) // INT bit of timer1 is set - ReadT1(); // check for int - - if (w.IORam[0x2F]&0x02) // INT bit of timer2 is set - ReadT2(); // check for int - // 30.11.98 cg, end of bugfix - continue; -} - -o100: // R0=A W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.R0, w.A, 16); - continue; -} - -o101: // R1=A W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.R1, w.A, 16); - continue; -} - -o102: // R2=A W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.R2, w.A, 16); - continue; -} - -o103: // R3=A W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.R3, w.A, 16); - continue; -} - -o104: // R4=A W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.R4, w.A, 16); - continue; -} - -o108: // R0=C W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.R0, w.C, 16); - continue; -} - -o109: // R1=C W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.R1, w.C, 16); - continue; -} - -o10A: // R2=C W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.R2, w.C, 16); - continue; -} - -o10B: // R3=C W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.R3, w.C, 16); - continue; -} - -o10C: // R4=C W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.R4, w.C, 16); - continue; -} - -o110: // A=R0 W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.A, w.R0, 16); - continue; -} - -o111: // A=R1 W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.A, w.R1, 16); - continue; -} - -o112: // A=R2 W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.A, w.R2, 16); - continue; -} - -o113: // A=R3 W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.A, w.R3, 16); - continue; -} - -o114: // A=R4 W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.A, w.R4, 16); - continue; -} - -o118: // C=R0 W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.C, w.R0, 16); - continue; -} - -o119: // C=R1 W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.C, w.R1, 16); - continue; -} - -o11A: // C=R2 W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.C, w.R2, 16); - continue; -} - -o11B: // C=R3 W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.C, w.R3, 16); - continue; -} - -o11C: // C=R4 W -{ - w.cycles+=19; - w.pc+=3; - memcpy(w.C, w.R4, 16); - continue; -} - -o120: // AR0EX W -{ - w.cycles+=19; - w.pc+=3; - Nxchg(w.A, w.R0, 16); - continue; -} - -o121: // AR1EX W -{ - w.cycles+=19; - w.pc+=3; - Nxchg(w.A, w.R1, 16); - continue; -} - -o122: // AR2EX W -{ - w.cycles+=19; - w.pc+=3; - Nxchg(w.A, w.R2, 16); - continue; -} - -o123: // AR3EX W -{ - w.cycles+=19; - w.pc+=3; - Nxchg(w.A, w.R3, 16); - continue; -} - -o124: // AR4EX W -{ - w.cycles+=19; - w.pc+=3; - Nxchg(w.A, w.R4, 16); - continue; -} - -o128: // CR0EX W -{ - w.cycles+=19; - w.pc+=3; - Nxchg(w.C, w.R0, 16); - continue; -} - -o129: // CR1EX W -{ - w.cycles+=19; - w.pc+=3; - Nxchg(w.C, w.R1, 16); - continue; -} - -o12A: // CR2EX W -{ - w.cycles+=19; - w.pc+=3; - Nxchg(w.C, w.R2, 16); - continue; -} - -o12B: // CR3EX W -{ - w.cycles+=19; - w.pc+=3; - Nxchg(w.C, w.R3, 16); - continue; -} - -o12C: // CR4EX W -{ - w.cycles+=19; - w.pc+=3; - Nxchg(w.C, w.R4, 16); - continue; -} - -o130: // D0=A -{ - w.cycles+=8; - w.pc+=3; - w.d0=Npack(w.A,5); - continue; -} - -o131: // D1=A -{ - w.cycles+=8; - w.pc+=3; - w.d1=Npack(w.A,5); - continue; -} - -o132: // AD0EX -{ - DWORD d = w.d0; - w.d0=Npack(w.A,5); - Nunpack(w.A,d,5); - w.cycles+=8; - w.pc+=3; - continue; -} - -o133: // AD1EX -{ - DWORD d=w.d1; - w.d1=Npack(w.A,5); - Nunpack(w.A,d,5); - w.cycles+=8; - w.pc+=3; - continue; -} - -o134: // D0=C -{ - w.cycles+=8; - w.pc+=3; - w.d0=Npack(w.C,5); - continue; -} - -o135: // D1=C -{ - w.cycles+=8; - w.pc+=3; - w.d1=Npack(w.C,5); - continue; -} - -o136: // CD0EX -{ - DWORD d=w.d0; - w.d0=Npack(w.C,5); - Nunpack(w.C,d,5); - w.cycles+=8; - w.pc+=3; - continue; -} - -o137: // CD1EX -{ - DWORD d=w.d1; - w.d1=Npack(w.C,5); - Nunpack(w.C,d,5); - w.cycles+=8; - w.pc+=3; - continue; -} - -o138:// D0=AS -{ - w.cycles+=7; - w.pc+=3; - *((WORD*)&w.d0)=(WORD)Npack(w.A,4); - continue; -} - -o139: // D1=AS -{ - w.cycles+=7; - w.pc+=3; - *((WORD*)&w.d1)=(WORD)Npack(w.A,4); - continue; -} - -o13A: // AD0XS -{ - DWORD d=w.d0; - *((WORD*)&w.d0)=(WORD)Npack(w.A,4); - Nunpack(w.A,d,4); - w.cycles+=7; - w.pc+=3; - continue; -} - -o13B: // AD1XS -{ - DWORD d=w.d1; - *((WORD*)&w.d1)=(WORD)Npack(w.A,4); - Nunpack(w.A,d,4); - w.cycles+=7; - w.pc+=3; - continue; -} - -o13C: // D0=CS -{ - w.cycles+=7; - w.pc+=3; - *((WORD*)&w.d0)=(WORD)Npack(w.C,4); - continue; -} - -o13D: // D1=CS -{ - w.cycles+=7; - w.pc+=3; - *((WORD*)&w.d1)=(WORD)Npack(w.C,4); - continue; -} - -o13E: // AD0XS -{ - DWORD d=w.d0; - *((WORD*)&w.d0)=(WORD)Npack(w.C,4); - Nunpack(w.C,d,4); - w.cycles+=7; - w.pc+=3; - continue; -} - -o13F: // AD1XS -{ - DWORD d=w.d1; - *((WORD*)&w.d1)=(WORD)Npack(w.C,4); - Nunpack(w.C,d,4); - w.cycles+=7; - w.pc+=3; - continue; -} - -o140: w.cycles+=17; w.pc+=3; Nwrite(w.A, w.d0, 5); continue; // DAT0=A A // 15.12.98 cg, replaced Nwrite() -o141: w.cycles+=17; w.pc+=3; Nwrite(w.A, w.d1, 5); continue; // DAT1=A A // 15.12.98 cg, replaced Nwrite() -o144: w.cycles+=17; w.pc+=3; Nwrite(w.C, w.d0, 5); continue; // DAT0=C A // 15.12.98 cg, replaced Nwrite() -o145: w.cycles+=17; w.pc+=3; Nwrite(w.C, w.d1, 5); continue; // DAT1=C A // 15.12.98 cg, replaced Nwrite() -o148: w.cycles+=14; w.pc+=3; Nwrite(w.A, w.d0, 2); continue; // DAT0=A B // 15.12.98 cg, replaced Nwrite() -o149: w.cycles+=14; w.pc+=3; Nwrite(w.A, w.d1, 2); continue; // DAT1=A B // 15.12.98 cg, replaced Nwrite() -o14C: w.cycles+=14; w.pc+=3; Nwrite(w.C, w.d0, 2); continue; // DAT0=C B // 15.12.98 cg, replaced Nwrite() -o14D: w.cycles+=14; w.pc+=3; Nwrite(w.C, w.d1, 2); continue; // DAT1=C B // 15.12.98 cg, replaced Nwrite() - -o142: w.cycles+=18; w.pc+=3; Nread(w.A, w.d0, 5); continue; // A=DAT0 A // 15.12.98 cg, replaced Nread() -o143: w.cycles+=18; w.pc+=3; Nread(w.A, w.d1, 5); continue; // A=DAT1 A // 15.12.98 cg, replaced Nread() -o146: w.cycles+=18; w.pc+=3; Nread(w.C, w.d0, 5); continue; // C=DAT0 A // 15.12.98 cg, replaced Nread() -o147: w.cycles+=18; w.pc+=3; Nread(w.C, w.d1, 5); continue; // C=DAT1 A // 15.12.98 cg, replaced Nread() -o14A: w.cycles+=15; w.pc+=3; Nread(w.A, w.d0, 2); continue; // A=DAT0 B // 15.12.98 cg, replaced Nread() -o14B: w.cycles+=15; w.pc+=3; Nread(w.A, w.d1, 2); continue; // A=DAT1 B // 15.12.98 cg, replaced Nread() -o14E: w.cycles+=15; w.pc+=3; Nread(w.C, w.d0, 2); continue; // C=DAT0 B // 15.12.98 cg, replaced Nread() -o14F: w.cycles+=15; w.pc+=3; Nread(w.C, w.d1, 2); continue; // C=DAT0 B // 15.12.98 cg, replaced Nread() - -o150a: w.cycles+=16+F_l[I[3]]; w.pc+=4; NFwrite(w.A, w.d0, I[3]); continue;// DAT0=A a -o151a: w.cycles+=16+F_l[I[3]]; w.pc+=4; NFwrite(w.A, w.d1, I[3]); continue;// DAT1=A a -o154a: w.cycles+=16+F_l[I[3]]; w.pc+=4; NFwrite(w.C, w.d0, I[3]); continue;// DAT0=C a -o155a: w.cycles+=16+F_l[I[3]]; w.pc+=4; NFwrite(w.C, w.d1, I[3]); continue;// DAT1=C a -o152a: w.cycles+=17+F_l[I[3]]; w.pc+=4; NFread(w.A, w.d0, I[3]); continue;// A=DAT0 a -o153a: w.cycles+=17+F_l[I[3]]; w.pc+=4; NFread(w.A, w.d1, I[3]); continue;// A=DAT1 a -o156a: w.cycles+=17+F_l[I[3]]; w.pc+=4; NFread(w.C, w.d0, I[3]); continue;// C=DAT0 a -o157a: w.cycles+=17+F_l[I[3]]; w.pc+=4; NFread(w.C, w.d1, I[3]); continue;// C=DAT1 a - -o158x: w.cycles+=15+I[3]+1; w.pc+=4; Nwrite(w.A, w.d0, I[3]+1); continue;// DAT0=A x -o159x: w.cycles+=15+I[3]+1; w.pc+=4; Nwrite(w.A, w.d1, I[3]+1); continue;// DAT1=A x -o15Cx: w.cycles+=15+I[3]+1; w.pc+=4; Nwrite(w.C, w.d0, I[3]+1); continue;// DAT0=C x -o15Dx: w.cycles+=15+I[3]+1; w.pc+=4; Nwrite(w.C, w.d1, I[3]+1); continue;// DAT1=C x -o15Ax: w.cycles+=16+I[3]+1; w.pc+=4; Nread(w.A, w.d0, I[3]+1); continue;// A=DAT0 x -o15Bx: w.cycles+=16+I[3]+1; w.pc+=4; Nread(w.A, w.d1, I[3]+1); continue;// A=DAT1 x -o15Ex: w.cycles+=16+I[3]+1; w.pc+=4; Nread(w.C, w.d0, I[3]+1); continue;// C=DAT0 x -o15Fx: w.cycles+=16+I[3]+1; w.pc+=4; Nread(w.C, w.d1, I[3]+1); continue; // C=DAT1 x - -o16x: // D0=D0+ (n+1) -{ - w.cycles+=7; - w.pc+=3; - w.d0+=I[2]+1; - if (w.d0>0xfffff) - { - w.d0&=0xfffff; - w.carry=TRUE; - } - else - { - w.carry=FALSE; - } - continue; -} - -o17x: // D1=D1+ (n+1) -{ - w.cycles+=7; - w.pc+=3; - w.d1+=I[2]+1; - if (w.d1>0xfffff) - { - w.d1&=0xfffff; - w.carry=TRUE; - } - else - { - w.carry=FALSE; - } - continue; -} - -o18x: // D0=D0- (n+1) -{ - w.cycles+=7; - w.pc+=3; - w.d0-=I[2]+1; - if (w.d0>0xfffff) - { - w.d0&=0xfffff; - w.carry=TRUE; - } - else - { - w.carry=FALSE; - } - continue; -} - -o19d2: // D0=(2) #dd -{ - w.cycles+=4; - w.pc+=4; - *((BYTE*)&w.d0)=(BYTE)Npack(I+2,2); - continue; -} - -o1Ad4: // D0=(4) #dddd -{ - w.cycles+=6; - w.pc+=6; - *((WORD*)&w.d0)=(WORD)Npack(I+2,4); - continue; -} - -o1Bd5: // D0=(5) #ddddd -{ - w.cycles+=7; - w.pc+=7; - w.d0=Npack(I+2,5); - continue; -} - -o1Cx: // D1=D1- (n+1) -{ - w.cycles+=7; - w.pc+=3; - w.d1-=I[2]+1; - if (w.d1>0xfffff) - { - w.d1&=0xfffff; - w.carry=TRUE; - } - else - { - w.carry=FALSE; - } - continue; -} - -o1Dd2: // D1=(2) #dd -{ - w.cycles+=4; - w.pc+=4; - *((BYTE*)&w.d1)=(BYTE)Npack(I+2,2); - continue; -} - -o1Ed4: // D1=(4) #dddd -{ - w.cycles+=6; - w.pc+=6; - *((WORD*)&w.d1)=(WORD)Npack(I+2,4); - continue; -} - -o1Fd5: // D1=(5) #ddddd -{ - w.cycles+=7; - w.pc+=7; - w.d1=Npack(I+2,5); - continue; -} - -o2n: // P= n -{ - w.cycles+=2; - w.pc+=2; - w.P=I[1]; - PCHANGED; - continue; -} - -o3X: // LCHEX -{ - UINT n=I[1]+1; - UINT d=16-w.P; - w.cycles+=4+n; - w.pc+=2; - I+=2; // UNSAFE - if (n<=d) - { - memcpy(w.C+w.P,I,n); //Nread(C+P,w.pc,n); - } - else - { - memcpy(w.C+w.P,I,d); //Nread(C+P,w.pc,d); - memcpy(w.C,I+d,n-d); //Nread(C,w.pc+d,n-d); - } - w.pc+=n; - continue; -} - -o4d2: // GOC #dd -{ - if (!w.carry) - { - w.cycles+=3; - w.pc+=3; - } - else - { - signed char jmp=I[1]+(I[2]<<4); - if (jmp) - w.pc+=jmp+1; - else - w.pc=rstkpop(); - w.cycles+=10; - w.pc&=0xFFFFF; - } - continue; -} - -o5d2: // GONC -{ - if (w.carry) - { - w.cycles+=3; - w.pc+=3; - } - else - { - signed char jmp=I[1]+(I[2]<<4); - if (jmp) - w.pc+=jmp+1; - else - w.pc=rstkpop(); - w.cycles+=10; - w.pc&=0xFFFFF; - } - continue; -} - -o6d3: // GOTO -{ - DWORD d=Npack(I+1,3); - if (d&0x800) - w.pc-=0xFFF-d; - else - w.pc+=d+1; - w.cycles+=11; - w.pc&=0xFFFFF; - continue; -} - -o7d3: // GOSUB -{ - DWORD d=Npack(I+1,3); - rstkpush(w.pc+4); - if (d&0x800) w.pc-=0xFFC-d; else w.pc+=d+4; - w.cycles+=12; - w.pc&=0xFFFFF; - continue; -} - -o800: // OUT=CS -{ - w.cycles+=4; - w.pc+=3; - w.out = (w.out&0xff0) | w.C[0]; - ScanKeyboard(FALSE); // 02.09.98 cg, changed, add parameter - continue; -} - -o801: // OUT=C -{ - w.cycles+=6; - w.pc+=3; - w.out = (WORD)Npack(w.C, 3); - ScanKeyboard(FALSE); // 02.09.98 cg, changed, add parameter - continue; -} - -o802: // A=IN -{ - w.cycles+=7; - if ((w.pc&1)==0) w.pc+=3; // 02.03.98 cg, bugfix, emulate saturn bug - AdjKeySpeed(); // 06.07.98 cg, new, slow down key repeat - IOBit(0x19,8,w.in != 0); // 24.02.99 cg, bugfix, update KDN bit in the SRQ register - Nunpack(w.A, w.in, 4); - continue; -} - -o803: // C=IN -{ - w.cycles+=7; - if ((w.pc&1)==0) w.pc+=3; // 02.03.98 cg, bugfix, emulate saturn bug - AdjKeySpeed(); // 06.07.98 cg, new, slow down key repeat - IOBit(0x19,8,w.in != 0); // 24.02.99 cg, bugfix, update KDN bit in the SRQ register - Nunpack(w.C, w.in, 4); - continue; -} - -o804: // UNCNFG -{ - w.cycles+=12; - w.pc+=3; - Uncnfg(); - continue; -} - -o805: // CONFIG -{ - w.cycles+=11; - w.pc+=3; - Config(); - continue; -} - -o806: // C=ID -{ - w.cycles+=11; - w.pc+=3; - C_Eq_Id(); - continue; -} - -o807: // SHUTDN -{ - BOOL bShutdn = TRUE; // 25.11.98 cg, new, shut down - - w.cycles+=5; - w.pc+=3; - // 25.11.98 cg, bugfix, only shut down when no timer wake up - if (w.IORam[0x2E]&0x04) // WKE bit of timer1 is set - { - if (ReadT1()&0x08) // and MSB of timer1 is set - { - w.IORam[0x2E] &= ~0x04; // clear WKE - bShutdn = FALSE; // don't shut down - } - } - if (w.IORam[0x2F]&0x04) // WKE bit of timer2 is set - { - if (ReadT2()&0x80000000) // and MSB of timer2 is set - { - w.IORam[0x2F] &= ~0x04; // clear WKE - bShutdn = FALSE; // don't shut down - } - } - // 25.11.98 cg, end of bugfix - if (w.in==0 && bShutdn) // 25.11.98 cg, changed, shut down only when enabled - { - w.Shutdn = TRUE; // 30.05.98 cg, set mode before exit emulation loop - bInterrupt = TRUE; - } - continue; -} - -o8080: // INTON -{ - w.cycles+=5; - w.pc+=4; - w.dwKdnCycles = w.cycles; // 25.02.99 cg, new, cpu cycles at start of 1ms key handler - w.intk = TRUE; - if (w.intd || w.IR15X) // 28.03.99 cg, bugfix, keyboard interrupt pending - { - w.intd = FALSE; // no keyboard interrupt pending any more - INTERRUPT; // restart interrupt handler - } - // ScanKeyboard(); // 30.05.98 cg, don't generate a keyboard interrupt here - continue; -} - -o80810: // RSI -{ - w.cycles+=6; - w.pc+=5; - // w.intk = TRUE; // 04.06.98 cg, removed, no INTON operation - ScanKeyboard(TRUE); // 02.09.98 cg, changed, one input bit high ? - - // 25.02.99 cg, enable KDN update - w.dwKdnCycles = w.cycles - (DWORD) T2CYCLES * 16; - - if (w.in && w.inte == FALSE) // 28.02.99 cg, bugfix, key interrupt pending - w.intd = TRUE; // 02.09.98 cg, keyboard interrupt pending - continue; -} - -o8082X: // LA -{ - UINT n=I[4]+1; - UINT d=16-w.P; - w.cycles+=6+n; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=5+n; - I+=5; // UNSAFE - if (n<=d) - { - memcpy(w.A+w.P,I,n); - } - else - { - memcpy(w.A+w.P,I,d); - memcpy(w.A,I+d,n-d); - } - continue; -} - -o8083: // BUSCB -{ - w.cycles+=7; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=4; - // 25.11.98 cg, removed, emulated as NOP - // InfoMessage("BUSCB instruction executed."); - continue; -} - -o8084n: // ABIT=0 n -{ - w.cycles+=6; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=5; - Nbit0(w.A, I[4]); - continue; -} - -o8085n: // ABIT=1 n -{ - w.cycles+=6; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=5; - Nbit1(w.A, I[4]); - continue; -} - -o8086n: // ?ABIT=0 n -{ - w.cycles+=7; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=5; - Tbit0(w.A, I[4]); - GOYES5; -} - -o8087n: // ?ABIT=1 n -{ - w.cycles+=7; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=5; - Tbit1(w.A, I[4]); - GOYES5; -} - -o8088n: // CBIT=0 n -{ - w.cycles+=6; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=5; - Nbit0(w.C, I[4]); - continue; -} - -o8089n: // CBIT=1 n -{ - w.cycles+=6; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=5; - Nbit1(w.C, I[4]); - continue; -} - -o808An: // ?CBIT=0 n -{ - w.cycles+=7; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=5; - Tbit0(w.C, I[4]); - GOYES5; -} - -o808Bn: // ?CBIT=1 n -{ - w.cycles+=7; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=5; - Tbit1(w.C, I[4]); - GOYES5; -} - -o808C: // PC=(A) -{ - w.cycles+=23; - w.pc=Read5(Npack(w.A,5)); - continue; -} - -o808D: // BUSCD -{ - w.cycles+=7; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=4; - // 25.11.98 cg, removed, emulated as NOP - // InfoMessage("BUSCD instruction executed."); - continue; -} - -o808E: // PC=(C) -{ - w.cycles+=23; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc=Read5(Npack(w.C,5)); - continue; -} - -o808F: // INTOFF -{ - w.cycles+=5; - w.pc+=4; - UpdateKdnBit(); // 25.02.99 cg, bugfix, update KDN bit - w.intk = FALSE; - // ScanKeyboard(); // 30.05.98 cg, don't generate a keyboard interrupt here - continue; -} - -o809: // C+P+1 - HEX MODE -{ - w.cycles+=8; - w.pc+=3; - w.C[0]+=w.P; Nincx(w.C,5); - continue; -} - -o80A: // RESET -{ - w.cycles+=6; - w.pc+=3; - Reset(); - continue; -} - -o80B: // BUSCC -{ - w.cycles+=6; - w.pc+=3; - // 25.11.98 cg, removed, emulated as NOP - // InfoMessage("BUSCC instruction executed."); - continue; -} - -o80Cn: // C=P n -{ - w.cycles+=6; - w.pc+=4; - w.C[I[3]] = w.P; - continue; -} - -o80Dn: // P=C n -{ - w.cycles+=6; - w.pc+=4; - w.P = w.C[I[3]]; - PCHANGED; - continue; -} - -o80E: // SREQ? -{ - w.cycles+=7; - w.pc+=3; - w.C[0]=0; - InfoMessage("SREQ? instruction executed."); - continue; -} - -o80Fn: // CPEX n -{ - BYTE n = w.P; - w.P = w.C[I[3]]; - w.C[I[3]] = n; - PCHANGED; - w.cycles+=6; - w.pc+=4; - continue; -} - -o810: // ASLC -{ - w.cycles+=21; - w.pc+=3; - Nslc(w.A, 16); - continue; -} - -o811: // BSLC -{ - w.cycles+=21; - w.pc+=3; - Nslc(w.B, 16); - continue; -} - -o812: // CSLC -{ - w.cycles+=21; - w.pc+=3; - Nslc(w.C, 16); - continue; -} - -o813: // DSLC -{ - w.cycles+=21; - w.pc+=3; - Nslc(w.D, 16); - continue; -} - -o814: // ASRC -{ - w.cycles+=21; - w.pc+=3; - Nsrc(w.A, 16); - continue; -} - -o815: // BSRC -{ - w.cycles+=21; - w.pc+=3; - Nsrc(w.B, 16); - continue; -} - -o816: // CSRC -{ - w.cycles+=21; - w.pc+=3; - Nsrc(w.C, 16); - continue; -} - -o817: // DSRC -{ - w.cycles+=21; - w.pc+=3; - Nsrc(w.D, 16); - continue; -} - -o818f0x: // A=A+x+1 f -{ - // 15.02.99 cg, changed, register length with saturn bug emulation - UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; - - w.cycles+=5+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - w.A[F_s[I[3]]]+=I[5]; // add constant value-1 - Ninc16(w.A,nF_l,F_s[I[3]]); // 15.02.99 cg, bugfix, add one and adjust in HEX mode - continue; -} - -o818f1x: // B=B+x+1 f -{ - // 15.02.99 cg, changed, register length with saturn bug emulation - UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; - - w.cycles+=5+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - w.B[F_s[I[3]]]+=I[5]; // add constant value-1 - Ninc16(w.B,nF_l,F_s[I[3]]); // 15.02.99 cg, bugfix, add one and adjust in HEX mode - continue; -} - -o818f2x: // C=C+x+1 f -{ - // 15.02.99 cg, changed, register length with saturn bug emulation - UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; - - w.cycles+=5+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - w.C[F_s[I[3]]]+=I[5]; // add constant value-1 - Ninc16(w.C,nF_l,F_s[I[3]]); // 15.02.99 cg, bugfix, add one and adjust in HEX mode - continue; -} - -o818f3x: // D=D+x+1 f -{ - // 15.02.99 cg, changed, register length with saturn bug emulation - UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; - - w.cycles+=5+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - w.D[F_s[I[3]]]+=I[5]; // add constant value-1 - Ninc16(w.D,nF_l,F_s[I[3]]); // 15.02.99 cg, bugfix, add one and adjust in HEX mode - // 24.03.98 cg, end of saturn bug emulation - continue; -} - -o818f8x: // A=A-x-1 f -{ - // 15.02.99 cg, changed, register length with saturn bug emulation - UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; - - w.cycles+=5+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - w.A[F_s[I[3]]]-=I[5]; // sub constant value+1 - Ndec16(w.A,nF_l,F_s[I[3]]); // 15.02.99 cg, bugfix, dec one and adjust in HEX mode - continue; -} - -o818f9x: // B=B-x-1 f -{ - // 15.02.99 cg, changed, register length with saturn bug emulation - UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; - - w.cycles+=5+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - w.B[F_s[I[3]]]-=I[5]; // sub constant value+1 - Ndec16(w.B,nF_l,F_s[I[3]]); // 15.02.99 cg, bugfix, dec one and adjust in HEX mode - continue; -} - -o818fAx: // C=C-x-1 f -{ - // 15.02.99 cg, changed, register length with saturn bug emulation - UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; - - w.cycles+=5+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - w.C[F_s[I[3]]]-=I[5]; // sub constant value+1 - Ndec16(w.C,nF_l,F_s[I[3]]); // 15.02.99 cg, bugfix, dec one and adjust in HEX mode - continue; -} - -o818fBx: // D=D-x-1 f -{ - // 15.02.99 cg, changed, register length with saturn bug emulation - UINT nF_l = (F_l[I[3]] == 1) ? 0x11 : F_l[I[3]]; - - w.cycles+=5+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - w.D[F_s[I[3]]]-=I[5]; // sub constant value+1 - Ndec16(w.D,nF_l,F_s[I[3]]); // 15.02.99 cg, bugfix, dec one and adjust in HEX mode - continue; -} - -o819f0: // ASRB -{ - w.cycles+=20; - w.pc+=5; - NFsrb(w.A, I[3]); - continue; -} - -o819f1: // BSRB -{ - w.cycles+=20; - w.pc+=5; - NFsrb(w.B, I[3]); - continue; -} - -o819f2: // CSRB -{ - w.cycles+=20; - w.pc+=5; - NFsrb(w.C, I[3]); - continue; -} - -o819f3: // DSRB -{ - w.cycles+=20; - w.pc+=5; - NFsrb(w.D, I[3]); - continue; -} - -o81Af00: // R0=A f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.R0, w.A, I[3]); - continue; -} - -o81Af01: // R1=A f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.R1, w.A, I[3]); - continue; -} - -o81Af02: // R2=A f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.R2, w.A, I[3]); - continue; -} - -o81Af03: // R3=A f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.R3, w.A, I[3]); - continue; -} - -o81Af04: // R4=A f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.R4, w.A, I[3]); - continue; -} - -o81Af08: // R0=C f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.R0, w.C, I[3]); - continue; -} - -o81Af09: // R1=C f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.R1, w.C, I[3]); - continue; -} - -o81Af0A: // R2=C f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.R2, w.C, I[3]); - continue; -} - -o81Af0B: // R3=C f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.R3, w.C, I[3]); - continue; -} - -o81Af0C: // R4=C f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.R4, w.C, I[3]); - continue; -} - -o81Af10: // A=R0 f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.A, w.R0, I[3]); - continue; -} - -o81Af11: // A=R1 f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.A, w.R1, I[3]); - continue; -} - -o81Af12: // A=R2 f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.A, w.R2, I[3]); - continue; -} - -o81Af13: // A=R3 f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.A, w.R3, I[3]); - continue; -} - -o81Af14: // A=R4 f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.A, w.R4, I[3]); - continue; -} - -o81Af18: // C=R0 f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.C, w.R0, I[3]); - continue; -} - -o81Af19: // C=R1 f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.C, w.R1, I[3]); - continue; -} - -o81Af1A: // C=R2 f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.C, w.R2, I[3]); - continue; -} - -o81Af1B: // C=R3 f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.C, w.R3, I[3]); - continue; -} - -o81Af1C: // C=R4 f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFcopy(w.C, w.R4, I[3]); - continue; -} - -o81Af20: // AR0EX f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFxchg(w.A, w.R0, I[3]); - continue; -} - -o81Af21: // AR1EX f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFxchg(w.A, w.R1, I[3]); - continue; -} - -o81Af22: // AR2EX f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFxchg(w.A, w.R2, I[3]); - continue; -} - -o81Af23: // AR3EX f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFxchg(w.A, w.R3, I[3]); - continue; -} - -o81Af24: // AR4EX f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFxchg(w.A, w.R4, I[3]); - continue; -} - -o81Af28: // CR0EX f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFxchg(w.C, w.R0, I[3]); - continue; -} - -o81Af29: // CR1EX f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFxchg(w.C, w.R1, I[3]); - continue; -} - -o81Af2A: // CR2EX f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFxchg(w.C, w.R2, I[3]); - continue; -} - -o81Af2B: // CR3EX f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFxchg(w.C, w.R3, I[3]); - continue; -} - -o81Af2C: // CR4EX f -{ - w.cycles+=6+F_l[I[3]]; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=6; - NFxchg(w.C, w.R4, I[3]); - continue; -} - -o81B2: // PC=A -{ - w.cycles+=16; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc = Npack(w.A,5); - continue; -} - -o81B3: // PC=C -{ - w.cycles+=16; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc = Npack(w.C,5); - continue; -} - -o81B4: // A=PC -{ - w.cycles+=9; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=4; - Nunpack(w.A,w.pc,5); - continue; -} - -o81B5: // C=PC -{ - w.cycles+=9; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=4; - Nunpack(w.C,w.pc,5); - continue; -} - -o81B6: // APCEX -{ - DWORD d=w.pc+4; - w.cycles+=16; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc=Npack(w.A,5); - Nunpack(w.A,d,5); - continue; -} - -o81B7: // CPCEX -{ - DWORD d=w.pc+4; - w.cycles+=16; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc=Npack(w.C,5); - Nunpack(w.C,d,5); - continue; -} - -o81C: // ASRB -{ - w.cycles+=20; - w.pc+=3; - Nsrb(w.A, 16); - continue; -} - -o81D: // BSRB -{ - w.cycles+=20; - w.pc+=3; - Nsrb(w.B, 16); - continue; -} - -o81E: // CSRB -{ - w.cycles+=20; - w.pc+=3; - Nsrb(w.C, 16); - continue; -} - -o81F: // DSRB -{ - w.cycles+=20; - w.pc+=3; - Nsrb(w.D, 16); - continue; -} - -o82n: // HST=0 m -{ - w.cycles+=3; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=3; - w.HST&=~I[2]; - continue; -} - -o83n: // ?HST=0 m -{ - w.cycles+=6; // cg, cycles undocumented, fetched from JAZZ V6.5 - w.pc+=3; - if ((w.HST&I[2])==0) - w.carry=TRUE; - else - w.carry=FALSE; - GOYES3; -} - -o84n: // ST=0 n -{ - w.cycles+=4; - w.pc+=3; - Nbit0(w.ST, I[2]); - continue; -} - -o85n: // ST=1 n -{ - w.cycles+=4; - w.pc+=3; - Nbit1(w.ST, I[2]); - continue; -} - -o86n: // ?ST=0 n -{ - w.cycles+=7; - w.pc+=3; - Tbit0(w.ST, I[2]); - GOYES3; -} - -o87n: // ?ST=1 n -{ - w.cycles+=7; - w.pc+=3; - Tbit1(w.ST, I[2]); - GOYES3; -} - -o88n: // ?P# n -{ - w.cycles+=6; - w.pc+=3; - if (w.P!=I[2]) - w.carry=TRUE; - else - w.carry=FALSE; - GOYES3; -} - -o89n: // ?P= n -{ - w.cycles+=6; - w.pc+=3; - if (w.P==I[2]) - w.carry=TRUE; - else - w.carry=FALSE; - GOYES3; -} - -o8A0: // ?A=B A -{ - w.cycles+=11; - w.pc+=3; - Te(w.A, w.B, 5); - GOYES3; -} - -o8A1: // ?B=C A -{ - w.cycles+=11; - w.pc+=3; - Te(w.B, w.C, 5); - GOYES3; -} - -o8A2: // ?C=A A -{ - w.cycles+=11; - w.pc+=3; - Te(w.C, w.A, 5); - GOYES3; -} - -o8A3: // ?D=C A -{ - w.cycles+=11; - w.pc+=3; - Te(w.D, w.C, 5); - GOYES3; -} - -o8A4: // ?A#B A -{ - w.cycles+=11; - w.pc+=3; - Tne(w.A, w.B, 5); - GOYES3; -} - -o8A5: // ?B#C A -{ - w.cycles+=11; - w.pc+=3; - Tne(w.B, w.C, 5); - GOYES3; -} - -o8A6: // ?C#A A -{ - w.cycles+=11; - w.pc+=3; - Tne(w.C, w.A, 5); - GOYES3; -} - -o8A7: // ?D#C A -{ - w.cycles+=11; - w.pc+=3; - Tne(w.D, w.C, 5); - GOYES3; -} - -o8A8: // ?A=0 A -{ - w.cycles+=11; - w.pc+=3; - Tz(w.A, 5); - GOYES3; -} - -o8A9: // ?B=0 A -{ - w.cycles+=11; - w.pc+=3; - Tz(w.B, 5); - GOYES3; -} - -o8AA: // ?C=0 A -{ - w.cycles+=11; - w.pc+=3; - Tz(w.C, 5); - GOYES3; -} - -o8AB: // ?D=0 A -{ - w.cycles+=11; - w.pc+=3; - Tz(w.D, 5); - GOYES3; -} - -o8AC: // ?A#0 A -{ - w.cycles+=11; - w.pc+=3; - Tnz(w.A, 5); - GOYES3; -} - -o8AD: // ?B#0 A -{ - w.cycles+=11; - w.pc+=3; - Tnz(w.B, 5); - GOYES3; -} - -o8AE: // ?C#0 A -{ - w.cycles+=11; - w.pc+=3; - Tnz(w.C, 5); - GOYES3; -} - -o8AF: // ?D#0 A -{ - w.cycles+=11; - w.pc+=3; - Tnz(w.D, 5); - GOYES3; -} - -o8B0: // ?A>B A -{ - w.cycles+=11; - w.pc+=3; - Ta(w.A, w.B, 5); - GOYES3; -} - -o8B1: // ?B>C A -{ - w.cycles+=11; - w.pc+=3; - Ta(w.B, w.C, 5); - GOYES3; -} - -o8B2: // ?C>A A -{ - w.cycles+=11; - w.pc+=3; - Ta(w.C, w.A, 5); - GOYES3; -} - -o8B3: // ?D>C A -{ - w.cycles+=11; - w.pc+=3; - Ta(w.D, w.C, 5); - GOYES3; -} - -o8B4: // ?A=B A -{ - w.cycles+=11; - w.pc+=3; - Tae(w.A, w.B, 5); - GOYES3; -} - -o8B9: // ?B>=C A -{ - w.cycles+=11; - w.pc+=3; - Tae(w.B, w.C, 5); - GOYES3; -} - -o8BA: // ?C>=A A -{ - w.cycles+=11; - w.pc+=3; - Tae(w.C, w.A, 5); - GOYES3; -} - -o8BB: // ?D>=C A -{ - w.cycles+=11; - w.pc+=3; - Tae(w.D, w.C, 5); - GOYES3; -} - -o8BC: // ?A<=B A -{ - w.cycles+=11; - w.pc+=3; - Tbe(w.A, w.B, 5); - GOYES3; -} - -o8BD: // ?B<=C A -{ - w.cycles+=11; - w.pc+=3; - Tbe(w.B, w.C, 5); - GOYES3; -} - -o8BE: // ?C<=A A -{ - w.cycles+=11; - w.pc+=3; - Tbe(w.C, w.A, 5); - GOYES3; -} - -o8BF: // ?D<=C A -{ - w.cycles+=11; - w.pc+=3; - Tbe(w.D, w.C, 5); - GOYES3; -} - -o8Cd4: // GOLONG #dddd -{ - DWORD d=Npack(I+2, 4); - if (d&0x8000) w.pc-=0xfffe-d; else w.pc+=d+2; - w.cycles+=14; - w.pc&=0xFFFFF; - continue; -} - -o8Dd5: // GOVLNG #ddddd -{ - w.cycles+=14; - w.pc = Npack(I+2, 5); - continue; -} - -o8Ed4: // GOSUBL #dddd -{ - DWORD d=Npack(I+2,4); - rstkpush(w.pc+6); - if (d&0x8000) w.pc-=0xfffa-d; else w.pc+=d+6; - w.cycles+=15; - w.pc&=0xFFFFF; - continue; -} - -o8Fd5: // GOSBVL #ddddd -{ - w.cycles+=15; - rstkpush(w.pc+7); - w.pc=Npack(I+2, 5); - continue; -} - - // ?r=s f -o9a0: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.A, w.B, I[1]); GOYES3; -o9a1: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.B, w.C, I[1]); GOYES3; -o9a2: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.C, w.A, I[1]); GOYES3; -o9a3: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFe(w.D, w.C, I[1]); GOYES3; - - // ?r#s f -o9a4: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFne(w.A, w.B, I[1]); GOYES3; -o9a5: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFne(w.B, w.C, I[1]); GOYES3; -o9a6: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFne(w.C, w.A, I[1]); GOYES3; -o9a7: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFne(w.D, w.C, I[1]); GOYES3; - - // ?r=0 f -o9a8: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFz(w.A, I[1]); GOYES3; -o9a9: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFz(w.B, I[1]); GOYES3; -o9aA: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFz(w.C, I[1]); GOYES3; -o9aB: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFz(w.D, I[1]); GOYES3; - - // ?r#0 f -o9aC: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFnz(w.A, I[1]); GOYES3; -o9aD: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFnz(w.B, I[1]); GOYES3; -o9aE: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFnz(w.C, I[1]); GOYES3; -o9aF: w.cycles+=6+F_l[I[1]]; w.pc+=3; TFnz(w.D, I[1]); GOYES3; - - // ?s>r f -o9b0: w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFa(w.A, w.B, I[1]&7); GOYES3; -o9b1: w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFa(w.B, w.C, I[1]&7); GOYES3; -o9b2: w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFa(w.C, w.A, I[1]&7); GOYES3; -o9b3: w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFa(w.D, w.C, I[1]&7); GOYES3; - - // ?r=s f -o9b8: w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFae(w.A, w.B, I[1]&7); GOYES3; -o9b9: w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFae(w.B, w.C, I[1]&7); GOYES3; -o9bA: w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFae(w.C, w.A, I[1]&7); GOYES3; -o9bB: w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFae(w.D, w.C, I[1]&7); GOYES3; - - // ?r<=s f -o9bC: w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFbe(w.A, w.B, I[1]&7); GOYES3; -o9bD: w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFbe(w.B, w.C, I[1]&7); GOYES3; -o9bE: w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFbe(w.C, w.A, I[1]&7); GOYES3; -o9bF: w.cycles+=6+F_l[I[1]&7]; w.pc+=3; TFbe(w.D, w.C, I[1]&7); GOYES3; - - // r=r+s f -oAa0: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.A, w.B, I[1]); continue; -oAa1: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.B, w.C, I[1]); continue; -oAa2: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.C, w.A, I[1]); continue; -oAa3: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.D, w.C, I[1]); continue; - - // r=r+r f -oAa4: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.A, w.A, I[1]); continue; // 25.03.98 cg, replaced NFdbl() -oAa5: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.B, w.B, I[1]); continue; // 25.03.98 cg, replaced NFdbl() -oAa6: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.C, w.C, I[1]); continue; // 25.03.98 cg, replaced NFdbl() -oAa7: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.D, w.D, I[1]); continue; // 25.03.98 cg, replaced NFdbl() - - // s=s+r f -oAa8: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.B, w.A, I[1]); continue; -oAa9: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.C, w.B, I[1]); continue; -oAaA: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.A, w.C, I[1]); continue; -oAaB: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFadd(w.C, w.D, I[1]); continue; - - // r=r-1 f -oAaC: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFdec(w.A, I[1]); continue; -oAaD: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFdec(w.B, I[1]); continue; -oAaE: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFdec(w.C, I[1]); continue; -oAaF: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFdec(w.D, I[1]); continue; - - // r=0 f -oAb0: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFzero(w.A, I[1]&7); continue; -oAb1: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFzero(w.B, I[1]&7); continue; -oAb2: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFzero(w.C, I[1]&7); continue; -oAb3: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFzero(w.D, I[1]&7); continue; - - // r=s f -oAb4: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.A, w.B, I[1]&7); continue; -oAb5: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.B, w.C, I[1]&7); continue; -oAb6: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.C, w.A, I[1]&7); continue; -oAb7: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.D, w.C, I[1]&7); continue; - - // s=r f -oAb8: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.B, w.A, I[1]&7); continue; -oAb9: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.C, w.B, I[1]&7); continue; -oAbA: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.A, w.C, I[1]&7); continue; -oAbB: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFcopy(w.C, w.D, I[1]&7); continue; - - // rsEX f -oAbC: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFxchg(w.A, w.B, I[1]&7); continue; -oAbD: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFxchg(w.B, w.C, I[1]&7); continue; -oAbE: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFxchg(w.C, w.A, I[1]&7); continue; -oAbF: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFxchg(w.D, w.C, I[1]&7); continue; - - // r=r-s f -oBa0: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.A, w.B, I[1]); continue; -oBa1: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.B, w.C, I[1]); continue; -oBa2: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.C, w.A, I[1]); continue; -oBa3: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.D, w.C, I[1]); continue; - - // r=r+1 f -oBa4: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFinc(w.A, I[1]); continue; -oBa5: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFinc(w.B, I[1]); continue; -oBa6: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFinc(w.C, I[1]); continue; -oBa7: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFinc(w.D, I[1]); continue; - - // s=s-r f -oBa8: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.B, w.A, I[1]); continue; -oBa9: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.C, w.B, I[1]); continue; -oBaA: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.A, w.C, I[1]); continue; -oBaB: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFsub(w.C, w.D, I[1]); continue; - - // r=s-r f -oBaC: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFrsub(w.A, w.B, I[1]); continue; -oBaD: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFrsub(w.B, w.C, I[1]); continue; -oBaE: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFrsub(w.C, w.A, I[1]); continue; -oBaF: w.cycles+=3+F_l[I[1]]; w.pc+=3; NFrsub(w.D, w.C, I[1]); continue; - - // rSL f -oBb0: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsl(w.A, I[1]&7); continue; -oBb1: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsl(w.B, I[1]&7); continue; -oBb2: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsl(w.C, I[1]&7); continue; -oBb3: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsl(w.D, I[1]&7); continue; - - // rSR f -oBb4: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsr(w.A, I[1]&7); continue; -oBb5: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsr(w.B, I[1]&7); continue; -oBb6: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsr(w.C, I[1]&7); continue; -oBb7: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFsr(w.D, I[1]&7); continue; - - // r=-r f -oBb8: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFneg(w.A, I[1]&7); continue; -oBb9: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFneg(w.B, I[1]&7); continue; -oBbA: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFneg(w.C, I[1]&7); continue; -oBbB: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFneg(w.D, I[1]&7); continue; - - // r=-r-1 f -oBbC: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFnot(w.A, I[1]&7); continue; -oBbD: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFnot(w.B, I[1]&7); continue; -oBbE: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFnot(w.C, I[1]&7); continue; -oBbF: w.cycles+=3+F_l[I[1]&7]; w.pc+=3; NFnot(w.D, I[1]&7); continue; - - // r=r+s A -oC0: w.cycles+=7; w.pc+=2; Nadd(w.A, w.B, 5); continue; -oC1: w.cycles+=7; w.pc+=2; Nadd(w.B, w.C, 5); continue; -oC2: w.cycles+=7; w.pc+=2; Nadd(w.C, w.A, 5); continue; -oC3: w.cycles+=7; w.pc+=2; Nadd(w.D, w.C, 5); continue; - - // r=r+r A -oC4: w.cycles+=7; w.pc+=2; Nadd(w.A, w.A, 5); continue; // 25.03.98 cg, replaced Ndbl() -oC5: w.cycles+=7; w.pc+=2; Nadd(w.B, w.B, 5); continue; // 25.03.98 cg, replaced Ndbl() -oC6: w.cycles+=7; w.pc+=2; Nadd(w.C, w.C, 5); continue; // 25.03.98 cg, replaced Ndbl() -oC7: w.cycles+=7; w.pc+=2; Nadd(w.D, w.D, 5); continue; // 25.03.98 cg, replaced Ndbl() - - // s=s+r A -oC8: w.cycles+=7; w.pc+=2; Nadd(w.B, w.A, 5); continue; -oC9: w.cycles+=7; w.pc+=2; Nadd(w.C, w.B, 5); continue; -oCA: w.cycles+=7; w.pc+=2; Nadd(w.A, w.C, 5); continue; -oCB: w.cycles+=7; w.pc+=2; Nadd(w.C, w.D, 5); continue; - - // r=r-1 A -oCC: w.cycles+=7; w.pc+=2; Ndec(w.A, 5, 0); continue; // 24.03.98 cg, changed -oCD: w.cycles+=7; w.pc+=2; Ndec(w.B, 5, 0); continue; // 24.03.98 cg, changed -oCE: w.cycles+=7; w.pc+=2; Ndec(w.C, 5, 0); continue; // 24.03.98 cg, changed -oCF: w.cycles+=7; w.pc+=2; Ndec(w.D, 5, 0); continue; // 24.03.98 cg, changed - - // r=0 A -oD0: w.cycles+=7; w.pc+=2; memset(w.A, 0, 5); continue; -oD1: w.cycles+=7; w.pc+=2; memset(w.B, 0, 5); continue; -oD2: w.cycles+=7; w.pc+=2; memset(w.C, 0, 5); continue; -oD3: w.cycles+=7; w.pc+=2; memset(w.D, 0, 5); continue; - - // r=s A -oD4: w.cycles+=7; w.pc+=2; memcpy(w.A, w.B, 5); continue; -oD5: w.cycles+=7; w.pc+=2; memcpy(w.B, w.C, 5); continue; -oD6: w.cycles+=7; w.pc+=2; memcpy(w.C, w.A, 5); continue; -oD7: w.cycles+=7; w.pc+=2; memcpy(w.D, w.C, 5); continue; - - // s=r A -oD8: w.cycles+=7; w.pc+=2; memcpy(w.B, w.A, 5); continue; -oD9: w.cycles+=7; w.pc+=2; memcpy(w.C, w.B, 5); continue; -oDA: w.cycles+=7; w.pc+=2; memcpy(w.A, w.C, 5); continue; -oDB: w.cycles+=7; w.pc+=2; memcpy(w.C, w.D, 5); continue; - - // rsEX -oDC: w.cycles+=7; w.pc+=2; Nxchg(w.A, w.B, 5); continue; -oDD: w.cycles+=7; w.pc+=2; Nxchg(w.B, w.C, 5); continue; -oDE: w.cycles+=7; w.pc+=2; Nxchg(w.C, w.A, 5); continue; -oDF: w.cycles+=7; w.pc+=2; Nxchg(w.D, w.C, 5); continue; - - // r=r-s A -oE0: w.cycles+=7; w.pc+=2; Nsub(w.A, w.B, 5); continue; -oE1: w.cycles+=7; w.pc+=2; Nsub(w.B, w.C, 5); continue; -oE2: w.cycles+=7; w.pc+=2; Nsub(w.C, w.A, 5); continue; -oE3: w.cycles+=7; w.pc+=2; Nsub(w.D, w.C, 5); continue; - - // r=r+1 A -oE4: w.cycles+=7; w.pc+=2; Ninc(w.A, 5, 0); continue; // 24.03.98 cg, changed -oE5: w.cycles+=7; w.pc+=2; Ninc(w.B, 5, 0); continue; // 24.03.98 cg, changed -oE6: w.cycles+=7; w.pc+=2; Ninc(w.C, 5, 0); continue; // 24.03.98 cg, changed -oE7: w.cycles+=7; w.pc+=2; Ninc(w.D, 5, 0); continue; // 24.03.98 cg, changed - - // s=s-r A -oE8: w.cycles+=7; w.pc+=2; Nsub(w.B, w.A, 5); continue; -oE9: w.cycles+=7; w.pc+=2; Nsub(w.C, w.B, 5); continue; -oEA: w.cycles+=7; w.pc+=2; Nsub(w.A, w.C, 5); continue; -oEB: w.cycles+=7; w.pc+=2; Nsub(w.C, w.D, 5); continue; - - // r=s-r A -oEC: w.cycles+=7; w.pc+=2; Nrsub(w.A, w.B, 5); continue; -oED: w.cycles+=7; w.pc+=2; Nrsub(w.B, w.C, 5); continue; -oEE: w.cycles+=7; w.pc+=2; Nrsub(w.C, w.A, 5); continue; -oEF: w.cycles+=7; w.pc+=2; Nrsub(w.D, w.C, 5); continue; - - // rSL A -oF0: w.cycles+=7; w.pc+=2; Nsl(w.A, 5); continue; -oF1: w.cycles+=7; w.pc+=2; Nsl(w.B, 5); continue; -oF2: w.cycles+=7; w.pc+=2; Nsl(w.C, 5); continue; -oF3: w.cycles+=7; w.pc+=2; Nsl(w.D, 5); continue; - - // rSR A -oF4: w.cycles+=7; w.pc+=2; Nsr(w.A, 5); continue; -oF5: w.cycles+=7; w.pc+=2; Nsr(w.B, 5); continue; -oF6: w.cycles+=7; w.pc+=2; Nsr(w.C, 5); continue; -oF7: w.cycles+=7; w.pc+=2; Nsr(w.D, 5); continue; - - // r=-r A -oF8: w.cycles+=7; w.pc+=2; Nneg(w.A, 5); continue; -oF9: w.cycles+=7; w.pc+=2; Nneg(w.B, 5); continue; -oFA: w.cycles+=7; w.pc+=2; Nneg(w.C, 5); continue; -oFB: w.cycles+=7; w.pc+=2; Nneg(w.D, 5); continue; - - // r=-r-1 A -oFC: w.cycles+=7; w.pc+=2; Nnot(w.A, 5); continue; -oFD: w.cycles+=7; w.pc+=2; Nnot(w.B, 5); continue; -oFE: w.cycles+=7; w.pc+=2; Nnot(w.C, 5); continue; -oFF: w.cycles+=7; w.pc+=2; Nnot(w.D, 5); continue; - -// invalid, unknown length : reset -o_invalid: -{ - _ASSERT(FALSE); // invalid, unknow length - w.pc=0; - continue; -} - -// length is guessed, just skip -o_invalid3: -{ - _ASSERT(FALSE); // invalid, length guessed, skip 3 nibbles - w.pc+=3; - continue; -} - -o_invalid4: -{ - _ASSERT(FALSE); // invalid, length guessed, skip 4 nibbles - w.pc+=4; - continue; -} - -o_invalid5: -{ - _ASSERT(FALSE); // invalid, length guessed, skip 5 nibbles - w.pc+=5; - continue; -} - -o_invalid6: -{ - _ASSERT(FALSE); // invalid, length guessed, skip 6 nibbles - w.pc+=6; - continue; -} - -o_goyes3: -{ - signed char jmp = I[3]+(I[4]<<4); - w.cycles+=7; - if (jmp) - w.pc=(w.pc+jmp)&0xFFFFF; - else - w.pc=rstkpop(); - continue; -} - -o_goyes5: -{ - signed char jmp = I[5]+(I[6]<<4); - w.cycles+=7; - if (jmp) - w.pc=(w.pc+jmp)&0xFFFFF; - else - w.pc=rstkpop(); - continue; -} - -//////// EXTENSIONS //////// -#if 0 // 05.01.99 cg, removed, unused extension -o81B0: - // ?Win48 - w.HST |= SB; - w.pc+=4; - continue; -#endif - -o81B1: - External(&w); - PCHANGED; // 22.07.98 cg, new, update field select table - continue; -//////////////////////////// +// HST bits +#define XM 1 +#define SB 2 +#define SR 4 +#define MP 8 + +#define PCHANGED ((void)(F_s[0]=Chipset.P,F_l[1]=Chipset.P+1)) +#define INTERRUPT ((void)(Chipset.SoftInt=TRUE,bInterrupt=TRUE)) + +#define T2CYCLES ((cCurrentRomType=='S')?dwSXCycles:dwGXCycles) + +extern VOID o00(LPBYTE I); // RTNSXM +extern VOID o01(LPBYTE I); // RTN +extern VOID o02(LPBYTE I); // RTNSC +extern VOID o03(LPBYTE I); // RTNCC +extern VOID o04(LPBYTE I); // SETHEX +extern VOID o05(LPBYTE I); // SETDEC +extern VOID o06(LPBYTE I); // RSTK=C +extern VOID o07(LPBYTE I); // C=RSTK +extern VOID o08(LPBYTE I); // CLRST +extern VOID o09(LPBYTE I); // C=ST +extern VOID o0A(LPBYTE I); // ST=C +extern VOID o0B(LPBYTE I); // CSTEX +extern VOID o0C(LPBYTE I); // P=P+1 +extern VOID o0D(LPBYTE I); // P=P-1 +extern VOID o0Ef0(LPBYTE I); // A=A&B f +extern VOID o0Ef1(LPBYTE I); // B=B&C f +extern VOID o0Ef2(LPBYTE I); // C=C&A f +extern VOID o0Ef3(LPBYTE I); // D=D&C f +extern VOID o0Ef4(LPBYTE I); // B=B&A f +extern VOID o0Ef5(LPBYTE I); // C=C&B f +extern VOID o0Ef6(LPBYTE I); // A=A&C f +extern VOID o0Ef7(LPBYTE I); // C=C&D f +extern VOID o0Ef8(LPBYTE I); // A=A!B f +extern VOID o0Ef9(LPBYTE I); // B=B!C f +extern VOID o0EfA(LPBYTE I); // C=C!A f +extern VOID o0EfB(LPBYTE I); // D=D!C f +extern VOID o0EfC(LPBYTE I); // B=B!A f +extern VOID o0EfD(LPBYTE I); // C=C!B f +extern VOID o0EfE(LPBYTE I); // A=A!C f +extern VOID o0EfF(LPBYTE I); // C=C!D f +extern VOID o0F(LPBYTE I); // RTI +extern VOID o100(LPBYTE I); // R0=A W +extern VOID o101(LPBYTE I); // R1=A W +extern VOID o102(LPBYTE I); // R2=A W +extern VOID o103(LPBYTE I); // R3=A W +extern VOID o104(LPBYTE I); // R4=A W +extern VOID o108(LPBYTE I); // R0=C W +extern VOID o109(LPBYTE I); // R1=C W +extern VOID o10A(LPBYTE I); // R2=C W +extern VOID o10B(LPBYTE I); // R3=C W +extern VOID o10C(LPBYTE I); // R4=C W +extern VOID o110(LPBYTE I); // A=R0 W +extern VOID o111(LPBYTE I); // A=R1 W +extern VOID o112(LPBYTE I); // A=R2 W +extern VOID o113(LPBYTE I); // A=R3 W +extern VOID o114(LPBYTE I); // A=R4 W +extern VOID o118(LPBYTE I); // C=R0 W +extern VOID o119(LPBYTE I); // C=R1 W +extern VOID o11A(LPBYTE I); // C=R2 W +extern VOID o11B(LPBYTE I); // C=R3 W +extern VOID o11C(LPBYTE I); // C=R4 W +extern VOID o120(LPBYTE I); // AR0EX W +extern VOID o121(LPBYTE I); // AR1EX W +extern VOID o122(LPBYTE I); // AR2EX W +extern VOID o123(LPBYTE I); // AR3EX W +extern VOID o124(LPBYTE I); // AR4EX W +extern VOID o128(LPBYTE I); // CR0EX W +extern VOID o129(LPBYTE I); // CR1EX W +extern VOID o12A(LPBYTE I); // CR2EX W +extern VOID o12B(LPBYTE I); // CR3EX W +extern VOID o12C(LPBYTE I); // CR4EX W +extern VOID o130(LPBYTE I); // D0=A +extern VOID o131(LPBYTE I); // D1=A +extern VOID o132(LPBYTE I); // AD0EX +extern VOID o133(LPBYTE I); // AD1EX +extern VOID o134(LPBYTE I); // D0=C +extern VOID o135(LPBYTE I); // D1=C +extern VOID o136(LPBYTE I); // CD0EX +extern VOID o137(LPBYTE I); // CD1EX +extern VOID o138(LPBYTE I); // D0=AS +extern VOID o139(LPBYTE I); // D1=AS +extern VOID o13A(LPBYTE I); // AD0XS +extern VOID o13B(LPBYTE I); // AD1XS +extern VOID o13C(LPBYTE I); // D0=CS +extern VOID o13D(LPBYTE I); // D1=CS +extern VOID o13E(LPBYTE I); // AD0XS +extern VOID o13F(LPBYTE I); // AD1XS +extern VOID o140(LPBYTE I); // DAT0=A A +extern VOID o141(LPBYTE I); // DAT0=A A +extern VOID o144(LPBYTE I); // DAT0=C A +extern VOID o145(LPBYTE I); // DAT1=C A +extern VOID o148(LPBYTE I); // DAT0=A B +extern VOID o149(LPBYTE I); // DAT1=A B +extern VOID o14C(LPBYTE I); // DAT0=C B +extern VOID o14D(LPBYTE I); // DAT1=C B +extern VOID o142(LPBYTE I); // A=DAT0 A +extern VOID o143(LPBYTE I); // A=DAT1 A +extern VOID o146(LPBYTE I); // C=DAT0 A +extern VOID o147(LPBYTE I); // C=DAT1 A +extern VOID o14A(LPBYTE I); // A=DAT0 B +extern VOID o14B(LPBYTE I); // A=DAT1 B +extern VOID o14E(LPBYTE I); // C=DAT0 B +extern VOID o14F(LPBYTE I); // C=DAT0 B +extern VOID o150a(LPBYTE I); // DAT0=A a +extern VOID o151a(LPBYTE I); // DAT1=A a +extern VOID o154a(LPBYTE I); // DAT0=C a +extern VOID o155a(LPBYTE I); // DAT1=C a +extern VOID o152a(LPBYTE I); // A=DAT0 a +extern VOID o153a(LPBYTE I); // A=DAT1 a +extern VOID o156a(LPBYTE I); // C=DAT0 a +extern VOID o157a(LPBYTE I); // C=DAT1 a +extern VOID o158x(LPBYTE I); // DAT0=A x +extern VOID o159x(LPBYTE I); // DAT1=A x +extern VOID o15Cx(LPBYTE I); // DAT0=C x +extern VOID o15Dx(LPBYTE I); // DAT1=C x +extern VOID o15Ax(LPBYTE I); // A=DAT0 x +extern VOID o15Bx(LPBYTE I); // A=DAT1 x +extern VOID o15Ex(LPBYTE I); // C=DAT0 x +extern VOID o15Fx(LPBYTE I); // C=DAT1 x +extern VOID o16x(LPBYTE I); // D0=D0+ (n+1) +extern VOID o17x(LPBYTE I); // D1=D1+ (n+1) +extern VOID o18x(LPBYTE I); // D0=D0- (n+1) +extern VOID o19d2(LPBYTE I); // D0=(2) #dd +extern VOID o1Ad4(LPBYTE I); // D0=(4) #dddd +extern VOID o1Bd5(LPBYTE I); // D0=(5) #ddddd +extern VOID o1Cx(LPBYTE I); // D1=D1- (n+1) +extern VOID o1Dd2(LPBYTE I); // D1=(2) #dd +extern VOID o1Ed4(LPBYTE I); // D1=(4) #dddd +extern VOID o1Fd5(LPBYTE I); // D1=(5) #ddddd +extern VOID o2n(LPBYTE I); // P= n +extern VOID o3X(LPBYTE I); // LCHEX +extern VOID o4d2(LPBYTE I); // GOC #dd +extern VOID o5d2(LPBYTE I); // GONC +extern VOID o6d3(LPBYTE I); // GOTO +extern VOID o7d3(LPBYTE I); // GOSUB +extern VOID o800(LPBYTE I); // OUT=CS +extern VOID o801(LPBYTE I); // OUT=C +extern VOID o802(LPBYTE I); // A=IN +extern VOID o803(LPBYTE I); // C=IN +extern VOID o804(LPBYTE I); // UNCNFG +extern VOID o805(LPBYTE I); // CONFIG +extern VOID o806(LPBYTE I); // C=ID +extern VOID o807(LPBYTE I); // SHUTDN +extern VOID o8080(LPBYTE I); // INTON +extern VOID o80810(LPBYTE I); // RSI +extern VOID o8082X(LPBYTE I); // LA +extern VOID o8083(LPBYTE I); // BUSCB +extern VOID o8084n(LPBYTE I); // ABIT=0 n +extern VOID o8085n(LPBYTE I); // ABIT=1 n +extern VOID o8086n(LPBYTE I); // ?ABIT=0 n +extern VOID o8087n(LPBYTE I); // ?ABIT=1 n +extern VOID o8088n(LPBYTE I); // CBIT=0 n +extern VOID o8089n(LPBYTE I); // CBIT=1 n +extern VOID o808An(LPBYTE I); // ?CBIT=0 n +extern VOID o808Bn(LPBYTE I); // ?CBIT=1 n +extern VOID o808C(LPBYTE I); // PC=(A) +extern VOID o808D(LPBYTE I); // BUSCD +extern VOID o808E(LPBYTE I); // PC=(C) +extern VOID o808F(LPBYTE I); // INTOFF +extern VOID o809(LPBYTE I); // C+P+1 - HEX MODE +extern VOID o80A(LPBYTE I); // RESET +extern VOID o80B(LPBYTE I); // BUSCC +extern VOID o80Cn(LPBYTE I); // C=P n +extern VOID o80Dn(LPBYTE I); // P=C n +extern VOID o80E(LPBYTE I); // SREQ? +extern VOID o80Fn(LPBYTE I); // CPEX n +extern VOID o810(LPBYTE I); // ASLC +extern VOID o811(LPBYTE I); // BSLC +extern VOID o812(LPBYTE I); // CSLC +extern VOID o813(LPBYTE I); // DSLC +extern VOID o814(LPBYTE I); // ASRC +extern VOID o815(LPBYTE I); // BSRC +extern VOID o816(LPBYTE I); // CSRC +extern VOID o817(LPBYTE I); // DSRC +extern VOID o818f0x(LPBYTE I); // A=A+x+1 f +extern VOID o818f1x(LPBYTE I); // B=B+x+1 f +extern VOID o818f2x(LPBYTE I); // C=C+x+1 f +extern VOID o818f3x(LPBYTE I); // D=D+x+1 f +extern VOID o818f8x(LPBYTE I); // A=A-x-1 f +extern VOID o818f9x(LPBYTE I); // B=B-x-1 f +extern VOID o818fAx(LPBYTE I); // C=C-x-1 f +extern VOID o818fBx(LPBYTE I); // D=D-x-1 f +extern VOID o819f0(LPBYTE I); // ASRB +extern VOID o819f1(LPBYTE I); // BSRB +extern VOID o819f2(LPBYTE I); // CSRB +extern VOID o819f3(LPBYTE I); // DSRB +extern VOID o81Af00(LPBYTE I); // R0=A f +extern VOID o81Af01(LPBYTE I); // R1=A f +extern VOID o81Af02(LPBYTE I); // R2=A f +extern VOID o81Af03(LPBYTE I); // R3=A f +extern VOID o81Af04(LPBYTE I); // R4=A f +extern VOID o81Af08(LPBYTE I); // R0=C f +extern VOID o81Af09(LPBYTE I); // R1=C f +extern VOID o81Af0A(LPBYTE I); // R2=C f +extern VOID o81Af0B(LPBYTE I); // R3=C f +extern VOID o81Af0C(LPBYTE I); // R4=C f +extern VOID o81Af10(LPBYTE I); // A=R0 f +extern VOID o81Af11(LPBYTE I); // A=R1 f +extern VOID o81Af12(LPBYTE I); // A=R2 f +extern VOID o81Af13(LPBYTE I); // A=R3 f +extern VOID o81Af14(LPBYTE I); // A=R4 f +extern VOID o81Af18(LPBYTE I); // C=R0 f +extern VOID o81Af19(LPBYTE I); // C=R1 f +extern VOID o81Af1A(LPBYTE I); // C=R2 f +extern VOID o81Af1B(LPBYTE I); // C=R3 f +extern VOID o81Af1C(LPBYTE I); // C=R4 f +extern VOID o81Af20(LPBYTE I); // AR0EX f +extern VOID o81Af21(LPBYTE I); // AR1EX f +extern VOID o81Af22(LPBYTE I); // AR2EX f +extern VOID o81Af23(LPBYTE I); // AR3EX f +extern VOID o81Af24(LPBYTE I); // AR4EX f +extern VOID o81Af28(LPBYTE I); // CR0EX f +extern VOID o81Af29(LPBYTE I); // CR1EX f +extern VOID o81Af2A(LPBYTE I); // CR2EX f +extern VOID o81Af2B(LPBYTE I); // CR3EX f +extern VOID o81Af2C(LPBYTE I); // CR4EX f +extern VOID o81B2(LPBYTE I); // PC=A +extern VOID o81B3(LPBYTE I); // PC=C +extern VOID o81B4(LPBYTE I); // A=PC +extern VOID o81B5(LPBYTE I); // C=PC +extern VOID o81B6(LPBYTE I); // APCEX +extern VOID o81B7(LPBYTE I); // CPCEX +extern VOID o81C(LPBYTE I); // ASRB +extern VOID o81D(LPBYTE I); // BSRB +extern VOID o81E(LPBYTE I); // CSRB +extern VOID o81F(LPBYTE I); // DSRB +extern VOID o82n(LPBYTE I); // HST=0 m +extern VOID o83n(LPBYTE I); // ?HST=0 m +extern VOID o84n(LPBYTE I); // ST=0 n +extern VOID o85n(LPBYTE I); // ST=1 n +extern VOID o86n(LPBYTE I); // ?ST=0 n +extern VOID o87n(LPBYTE I); // ?ST=1 n +extern VOID o88n(LPBYTE I); // ?P# n +extern VOID o89n(LPBYTE I); // ?P= n +extern VOID o8A0(LPBYTE I); // ?A=B A +extern VOID o8A1(LPBYTE I); // ?B=C A +extern VOID o8A2(LPBYTE I); // ?C=A A +extern VOID o8A3(LPBYTE I); // ?D=C A +extern VOID o8A4(LPBYTE I); // ?A#B A +extern VOID o8A5(LPBYTE I); // ?B#C A +extern VOID o8A6(LPBYTE I); // ?C#A A +extern VOID o8A7(LPBYTE I); // ?D#C A +extern VOID o8A8(LPBYTE I); // ?A=0 A +extern VOID o8A9(LPBYTE I); // ?B=0 A +extern VOID o8AA(LPBYTE I); // ?C=0 A +extern VOID o8AB(LPBYTE I); // ?D=0 A +extern VOID o8AC(LPBYTE I); // ?A#0 A +extern VOID o8AD(LPBYTE I); // ?B#0 A +extern VOID o8AE(LPBYTE I); // ?C#0 A +extern VOID o8AF(LPBYTE I); // ?D#0 A +extern VOID o8B0(LPBYTE I); // ?A>B A +extern VOID o8B1(LPBYTE I); // ?B>C A +extern VOID o8B2(LPBYTE I); // ?C>A A +extern VOID o8B3(LPBYTE I); // ?D>C A +extern VOID o8B4(LPBYTE I); // ?A=B A +extern VOID o8B9(LPBYTE I); // ?B>=C A +extern VOID o8BA(LPBYTE I); // ?C>=A A +extern VOID o8BB(LPBYTE I); // ?D>=C A +extern VOID o8BC(LPBYTE I); // ?A<=B A +extern VOID o8BD(LPBYTE I); // ?B<=C A +extern VOID o8BE(LPBYTE I); // ?C<=A A +extern VOID o8BF(LPBYTE I); // ?D<=C A +extern VOID o8Cd4(LPBYTE I); // GOLONG #dddd +extern VOID o8Dd5(LPBYTE I); // GOVLNG #ddddd +extern VOID o8Ed4(LPBYTE I); // GOSUBL #dddd +extern VOID o8Fd5(LPBYTE I); // GOSBVL #ddddd +extern VOID o9a0(LPBYTE I); // ?A=B f +extern VOID o9a1(LPBYTE I); // ?B=C f +extern VOID o9a2(LPBYTE I); // ?C=A f +extern VOID o9a3(LPBYTE I); // ?D=C f +extern VOID o9a4(LPBYTE I); // ?A#B f +extern VOID o9a5(LPBYTE I); // ?B#C f +extern VOID o9a6(LPBYTE I); // ?C#A f +extern VOID o9a7(LPBYTE I); // ?D#C f +extern VOID o9a8(LPBYTE I); // ?A=0 f +extern VOID o9a9(LPBYTE I); // ?B=0 f +extern VOID o9aA(LPBYTE I); // ?C=0 f +extern VOID o9aB(LPBYTE I); // ?D=0 f +extern VOID o9aC(LPBYTE I); // ?A#0 f +extern VOID o9aD(LPBYTE I); // ?B#0 f +extern VOID o9aE(LPBYTE I); // ?C#0 f +extern VOID o9aF(LPBYTE I); // ?D#0 f +extern VOID o9b0(LPBYTE I); // ?A>B f +extern VOID o9b1(LPBYTE I); // ?B>C f +extern VOID o9b2(LPBYTE I); // ?C>A f +extern VOID o9b3(LPBYTE I); // ?D>C f +extern VOID o9b4(LPBYTE I); // ?A=B f +extern VOID o9b9(LPBYTE I); // ?B>=C f +extern VOID o9bA(LPBYTE I); // ?C>=A f +extern VOID o9bB(LPBYTE I); // ?D>=C f +extern VOID o9bC(LPBYTE I); // ?A<=B f +extern VOID o9bD(LPBYTE I); // ?B<=C f +extern VOID o9bE(LPBYTE I); // ?C<=A f +extern VOID o9bF(LPBYTE I); // ?D<=C f +extern VOID oAa0(LPBYTE I); // A=A+B f +extern VOID oAa1(LPBYTE I); // B=B+C f +extern VOID oAa2(LPBYTE I); // C=C+A f +extern VOID oAa3(LPBYTE I); // D=D+C f +extern VOID oAa4(LPBYTE I); // A=A+A f +extern VOID oAa5(LPBYTE I); // B=B+B f +extern VOID oAa6(LPBYTE I); // C=C+C f +extern VOID oAa7(LPBYTE I); // D=D+D f +extern VOID oAa8(LPBYTE I); // B=B+A f +extern VOID oAa9(LPBYTE I); // C=C+B f +extern VOID oAaA(LPBYTE I); // A=A+C f +extern VOID oAaB(LPBYTE I); // C=C+D f +extern VOID oAaC(LPBYTE I); // A=A-1 f +extern VOID oAaD(LPBYTE I); // B=B-1 f +extern VOID oAaE(LPBYTE I); // C=C-1 f +extern VOID oAaF(LPBYTE I); // D=D-1 f +extern VOID oAb0(LPBYTE I); // A=0 f +extern VOID oAb1(LPBYTE I); // B=0 f +extern VOID oAb2(LPBYTE I); // C=0 f +extern VOID oAb3(LPBYTE I); // D=0 f +extern VOID oAb4(LPBYTE I); // A=B f +extern VOID oAb5(LPBYTE I); // B=C f +extern VOID oAb6(LPBYTE I); // C=A f +extern VOID oAb7(LPBYTE I); // D=C f +extern VOID oAb8(LPBYTE I); // B=A f +extern VOID oAb9(LPBYTE I); // C=B f +extern VOID oAbA(LPBYTE I); // A=C f +extern VOID oAbB(LPBYTE I); // C=D f +extern VOID oAbC(LPBYTE I); // ABEX f +extern VOID oAbD(LPBYTE I); // BCEX f +extern VOID oAbE(LPBYTE I); // CAEX f +extern VOID oAbF(LPBYTE I); // DCEX f +extern VOID oBa0(LPBYTE I); // A=A-B f +extern VOID oBa1(LPBYTE I); // B=B-C f +extern VOID oBa2(LPBYTE I); // C=C-A f +extern VOID oBa3(LPBYTE I); // D=D-C f +extern VOID oBa4(LPBYTE I); // A=A+1 f +extern VOID oBa5(LPBYTE I); // B=B+1 f +extern VOID oBa6(LPBYTE I); // C=C+1 f +extern VOID oBa7(LPBYTE I); // D=D+1 f +extern VOID oBa8(LPBYTE I); // B=B-A f +extern VOID oBa9(LPBYTE I); // C=C-B f +extern VOID oBaA(LPBYTE I); // A=A-C f +extern VOID oBaB(LPBYTE I); // C=C-D f +extern VOID oBaC(LPBYTE I); // A=B-A f +extern VOID oBaD(LPBYTE I); // B=C-B f +extern VOID oBaE(LPBYTE I); // C=A-C f +extern VOID oBaF(LPBYTE I); // D=C-D f +extern VOID oBb0(LPBYTE I); // ASL f +extern VOID oBb1(LPBYTE I); // BSL f +extern VOID oBb2(LPBYTE I); // CSL f +extern VOID oBb3(LPBYTE I); // DSL f +extern VOID oBb4(LPBYTE I); // ASR f +extern VOID oBb5(LPBYTE I); // BSR f +extern VOID oBb6(LPBYTE I); // CSR f +extern VOID oBb7(LPBYTE I); // DSR f +extern VOID oBb8(LPBYTE I); // A=-A f +extern VOID oBb9(LPBYTE I); // B=-B f +extern VOID oBbA(LPBYTE I); // C=-C f +extern VOID oBbB(LPBYTE I); // D=-D f +extern VOID oBbC(LPBYTE I); // A=-A-1 f +extern VOID oBbD(LPBYTE I); // B=-B-1 f +extern VOID oBbE(LPBYTE I); // C=-C-1 f +extern VOID oBbF(LPBYTE I); // D=-D-1 f +extern VOID oC0(LPBYTE I); // A=A+B A +extern VOID oC1(LPBYTE I); // B=B+C A +extern VOID oC2(LPBYTE I); // C=C+A A +extern VOID oC3(LPBYTE I); // D=D+C A +extern VOID oC4(LPBYTE I); // A=A+A A +extern VOID oC5(LPBYTE I); // B=B+B A +extern VOID oC6(LPBYTE I); // C=C+C A +extern VOID oC7(LPBYTE I); // D=D+D A +extern VOID oC8(LPBYTE I); // B=B+A A +extern VOID oC9(LPBYTE I); // C=C+B A +extern VOID oCA(LPBYTE I); // A=A+C A +extern VOID oCB(LPBYTE I); // C=C+D A +extern VOID oCC(LPBYTE I); // A=A-1 A +extern VOID oCD(LPBYTE I); // B=B-1 A +extern VOID oCE(LPBYTE I); // C=C-1 A +extern VOID oCF(LPBYTE I); // D=D-1 A +extern VOID oD0(LPBYTE I); // A=0 A +extern VOID oD1(LPBYTE I); // B=0 A +extern VOID oD2(LPBYTE I); // C=0 A +extern VOID oD3(LPBYTE I); // D=0 A +extern VOID oD4(LPBYTE I); // A=B A +extern VOID oD5(LPBYTE I); // B=C A +extern VOID oD6(LPBYTE I); // C=A A +extern VOID oD7(LPBYTE I); // D=C A +extern VOID oD8(LPBYTE I); // B=A A +extern VOID oD9(LPBYTE I); // C=B A +extern VOID oDA(LPBYTE I); // A=C A +extern VOID oDB(LPBYTE I); // C=D A +extern VOID oDC(LPBYTE I); // ABEX +extern VOID oDD(LPBYTE I); // BCEX +extern VOID oDE(LPBYTE I); // CAEX +extern VOID oDF(LPBYTE I); // DCEX +extern VOID oE0(LPBYTE I); // A=A-B A +extern VOID oE1(LPBYTE I); // B=B-C A +extern VOID oE2(LPBYTE I); // C=C-A A +extern VOID oE3(LPBYTE I); // D=D-C A +extern VOID oE4(LPBYTE I); // A=A+1 A +extern VOID oE5(LPBYTE I); // B=B+1 A +extern VOID oE6(LPBYTE I); // C=C+1 A +extern VOID oE7(LPBYTE I); // D=D+1 A +extern VOID oE8(LPBYTE I); // B=B-A A +extern VOID oE9(LPBYTE I); // C=C-B A +extern VOID oEA(LPBYTE I); // A=A-C A +extern VOID oEB(LPBYTE I); // C=C-D A +extern VOID oEC(LPBYTE I); // A=B-A A +extern VOID oED(LPBYTE I); // B=C-B A +extern VOID oEE(LPBYTE I); // C=A-C A +extern VOID oEF(LPBYTE I); // D=C-D A +extern VOID oF0(LPBYTE I); // ASL A +extern VOID oF1(LPBYTE I); // BSL A +extern VOID oF2(LPBYTE I); // CSL A +extern VOID oF3(LPBYTE I); // DSL A +extern VOID oF4(LPBYTE I); // ASR A +extern VOID oF5(LPBYTE I); // BSR A +extern VOID oF6(LPBYTE I); // CSR A +extern VOID oF7(LPBYTE I); // DSR A +extern VOID oF8(LPBYTE I); // A=-A A +extern VOID oF9(LPBYTE I); // B=-B A +extern VOID oFA(LPBYTE I); // C=-C A +extern VOID oFB(LPBYTE I); // D=-D A +extern VOID oFC(LPBYTE I); // A=-A-1 A +extern VOID oFD(LPBYTE I); // B=-B-1 A +extern VOID oFE(LPBYTE I); // C=-C-1 A +extern VOID oFF(LPBYTE I); // D=-D-1 A + +extern VOID o_invalid(LPBYTE I); +extern VOID o_invalid3(LPBYTE I); +extern VOID o_invalid4(LPBYTE I); +extern VOID o_invalid5(LPBYTE I); +extern VOID o_invalid6(LPBYTE I); + +extern VOID o_goyes3(LPBYTE I); +extern VOID o_goyes5(LPBYTE I); + +extern VOID o81B1(LPBYTE I); diff --git a/sources/Emu48/OPS.H b/sources/Emu48/OPS.H index ec5a0ee..d4bd351 100644 --- a/sources/Emu48/OPS.H +++ b/sources/Emu48/OPS.H @@ -24,8 +24,8 @@ static UINT F_l[16] = {1,1/*P+1*/,1,3,1,12,2,16,0,0,0,0,0,0,0,5}; #define NFor(a, b, f) Nor((a)+F_s[f], (b)+F_s[f], F_l[f]) #define NFzero(a,f) memset((a)+F_s[f], 0, F_l[f]) #define NFpack(a, f) Npack((a)+F_s[f], F_l[f]) -#define NFinc(a, f) Ninc(a, F_l[f], F_s[f]) // 24.03.98 cg, changed -#define NFdec(a, f) Ndec(a, F_l[f], F_s[f]) // 24.03.98 cg, changed +#define NFinc(a, f) Ninc(a, F_l[f], F_s[f]) +#define NFdec(a, f) Ndec(a, F_l[f], F_s[f]) #define NFnot(a, f) Nnot((a)+F_s[f], F_l[f]) #define NFneg(a, f) Nneg((a)+F_s[f], F_l[f]) #define NFsl(a, f) Nsl((a)+F_s[f], F_l[f]) @@ -40,9 +40,16 @@ static UINT F_l[16] = {1,1/*P+1*/,1,3,1,12,2,16,0,0,0,0,0,0,0,5}; #define TFbe(a, b, f) Tbe((a)+F_s[f], (b)+F_s[f], F_l[f]) #define TFnz(a, f) Tnz((a)+F_s[f], F_l[f]) +static __inline LPBYTE FASTPTR(DWORD d) +{ + if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase)) + return Chipset.IORam+d-Chipset.IOBase; + + return RMap[d>>12]+(d&0xFFF); +} + static __inline void rstkpush(DWORD d) { - Chipset.rstk[Chipset.rstkp] = d; Chipset.rstkp=(Chipset.rstkp+1)&7; } @@ -80,7 +87,6 @@ static __inline void Nxchg(BYTE *a, BYTE *b, UINT s) memcpy(a, X, s); } -// 24.03.98 cg, changed, new implementation static __inline void Ninc(BYTE *a, UINT s, UINT d) { UINT i; @@ -98,9 +104,7 @@ static __inline void Ninc(BYTE *a, UINT s, UINT d) } Chipset.carry = TRUE; } -// 24.03.98 cg, end of new implementation -// 15.02.99 cg, new function static __inline void Ninc16(BYTE *a, UINT s, UINT d) { UINT i; @@ -117,7 +121,6 @@ static __inline void Ninc16(BYTE *a, UINT s, UINT d) } Chipset.carry = TRUE; } -// 15.02.98 cg, end of new function static __inline void Nincx(BYTE *a, UINT s) { @@ -132,7 +135,6 @@ static __inline void Nincx(BYTE *a, UINT s) Chipset.carry=TRUE; } -// 24.03.98 cg, changed, new implementation static __inline void Ndec(BYTE *a, UINT s, UINT d) { UINT i; @@ -150,9 +152,7 @@ static __inline void Ndec(BYTE *a, UINT s, UINT d) } Chipset.carry = TRUE; } -// 24.03.98 cg, end of new implementation -// 15.02.99 cg, new function static __inline void Ndec16(BYTE *a, UINT s, UINT d) { UINT i; @@ -169,9 +169,7 @@ static __inline void Ndec16(BYTE *a, UINT s, UINT d) } Chipset.carry = TRUE; } -// 15.02.98 cg, end of new function -// 25.03.98 cg, optimized, new implementation static __inline void Nadd(BYTE *a, BYTE *b, UINT s) { UINT i; @@ -191,9 +189,7 @@ static __inline void Nadd(BYTE *a, BYTE *b, UINT s) } Chipset.carry = (c==1); } -// 25.03.98 cg, end of new implementation -// 25.03.98 cg, optimized, new implementation static __inline void Nsub(BYTE *a, BYTE *b, UINT s) { UINT i; @@ -213,9 +209,7 @@ static __inline void Nsub(BYTE *a, BYTE *b, UINT s) } Chipset.carry = (c==1); } -// 25.03.98 cg, end of new implementation -// 25.03.98 cg, optimized, new implementation static __inline void Nrsub(BYTE *a, BYTE *b, UINT s) { UINT i; @@ -235,7 +229,6 @@ static __inline void Nrsub(BYTE *a, BYTE *b, UINT s) } Chipset.carry = (c==1); } -// 25.03.98 cg, end of new implementation static __inline void Nand(BYTE *a, BYTE *b, UINT s) { @@ -247,7 +240,6 @@ static __inline void Nor(BYTE *a, BYTE *b, UINT s) while (s--) a[s]|=b[s]; } -// 25.03.98 cg, optimized, new implementation static __inline void Nnot(BYTE *a, UINT s) { BYTE cBase = Chipset.mode_dec ? 9 : 15; @@ -255,9 +247,7 @@ static __inline void Nnot(BYTE *a, UINT s) while (s--) a[s] = cBase - a[s]; Chipset.carry = FALSE; } -// 25.03.98 cg, end of new implementation -// 25.03.98 cg, optimized, new implementation static __inline void Nneg(BYTE *a, UINT s) { UINT i; @@ -271,7 +261,6 @@ static __inline void Nneg(BYTE *a, UINT s) a[i] = cBase - a[i]; } } -// 25.03.98 cg, end of new implementation static __inline void Nsl(BYTE *a, UINT s) { diff --git a/sources/Emu48/RESOURCE.H b/sources/Emu48/RESOURCE.H index e5f7d4a..b2978fe 100644 --- a/sources/Emu48/RESOURCE.H +++ b/sources/Emu48/RESOURCE.H @@ -4,14 +4,21 @@ // #define IDI_EMU48 100 #define IDR_MENU 101 -#define IDB_EMPTY 102 -#define IDD_ABOUT 103 -#define IDD_ABOUTS 104 -#define IDD_SETTINGS 105 -#define IDD_CHOOSEKML 106 -#define IDD_KMLLOG 107 -#define IDD_REGISTER 108 -#define IDD_DISASM 109 +#define IDR_DEBUG 102 +#define IDR_DEBUG_CODE 103 +#define IDR_DEBUG_MEM 104 +#define IDB_EMPTY 105 +#define IDD_ABOUT 106 +#define IDD_ABOUTS 107 +#define IDD_SETTINGS 108 +#define IDD_CHOOSEKML 109 +#define IDD_KMLLOG 110 +#define IDD_REGISTER 111 +#define IDD_DISASM 112 +#define IDD_DEBUG 113 +#define IDD_NEWVALUE 114 +#define IDD_ENTERADR 115 +#define IDD_BREAKEDIT 116 #define IDC_PORT1WR 1000 #define IDC_AUTOSAVE 1001 #define IDC_AUTOSAVEONEXIT 1002 @@ -48,6 +55,51 @@ #define IDC_DISASM_ADR 1033 #define IDC_DISASM_NEXT 1034 #define IDC_DISASM_COPY 1035 +#define IDC_DEBUG_CODE 1036 +#define IDC_STATIC_CODE 1037 +#define IDC_STATIC_REGISTERS 1038 +#define IDC_STATIC_MEMORY 1039 +#define IDC_STATIC_STACK 1040 +#define IDC_REG_A 1041 +#define IDC_REG_B 1042 +#define IDC_REG_C 1043 +#define IDC_REG_D 1044 +#define IDC_REG_R0 1045 +#define IDC_REG_R1 1046 +#define IDC_REG_R2 1047 +#define IDC_REG_R3 1048 +#define IDC_REG_R4 1049 +#define IDC_REG_D0 1050 +#define IDC_REG_D1 1051 +#define IDC_REG_P 1052 +#define IDC_REG_PC 1053 +#define IDC_REG_OUT 1054 +#define IDC_REG_IN 1055 +#define IDC_REG_ST 1056 +#define IDC_REG_CY 1057 +#define IDC_REG_MODE 1058 +#define IDC_REG_MP 1059 +#define IDC_REG_SR 1060 +#define IDC_REG_SB 1061 +#define IDC_REG_XM 1062 +#define IDC_NEWVALUE 1063 +#define IDC_ENTERADR 1064 +#define IDC_DEBUG_MEM 1065 +#define IDC_DEBUG_MEM_ADDR 1066 +#define IDC_DEBUG_MEM_COL0 1067 +#define IDC_DEBUG_MEM_COL1 1068 +#define IDC_DEBUG_MEM_COL2 1069 +#define IDC_DEBUG_MEM_COL3 1070 +#define IDC_DEBUG_MEM_COL4 1071 +#define IDC_DEBUG_MEM_COL5 1072 +#define IDC_DEBUG_MEM_COL6 1073 +#define IDC_DEBUG_MEM_COL7 1074 +#define IDC_DEBUG_MEM_TEXT 1075 +#define IDC_DEBUG_STACK 1076 +#define IDC_STATIC_BREAKPOINT 1077 +#define IDC_BREAKEDIT_ADD 1078 +#define IDC_BREAKEDIT_DELETE 1079 +#define IDC_BREAKEDIT_WND 1080 #define ID_FILE_NEW 40001 #define ID_FILE_OPEN 40002 #define ID_FILE_SAVE 40003 @@ -67,14 +119,32 @@ #define ID_STACK_COPY 40019 #define ID_STACK_PASTE 40020 #define ID_TOOL_DISASM 40021 +#define ID_TOOL_DEBUG 40022 +#define ID_DEBUG_RUN 40024 +#define ID_DEBUG_STEP 40025 +#define ID_DEBUG_STEPOVER 40026 +#define ID_DEBUG_BREAK 40027 +#define ID_BREAKPOINTS_SETBREAK 40028 +#define ID_BREAKPOINTS_CODEEDIT 40029 +#define ID_BREAKPOINTS_CLEARALL 40030 +#define ID_DEBUG_CODE_GOADR 40031 +#define ID_DEBUG_CODE_GOPC 40032 +#define ID_DEBUG_CODE_SETPCTOSELECT 40033 +#define ID_DEBUG_MEM_GOADR 40034 +#define ID_DEBUG_MEM_GOPC 40035 +#define ID_DEBUG_MEM_GOD0 40036 +#define ID_DEBUG_MEM_GOD1 40037 +#define ID_DEBUG_MEM_GOSTACK 40038 +#define ID_BREAKPOINTS_NOP3 40039 +#define ID_DEBUG_STEPOUT 40040 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 110 -#define _APS_NEXT_COMMAND_VALUE 40022 -#define _APS_NEXT_CONTROL_VALUE 1036 +#define _APS_NEXT_RESOURCE_VALUE 117 +#define _APS_NEXT_COMMAND_VALUE 40041 +#define _APS_NEXT_CONTROL_VALUE 1081 #define _APS_NEXT_SYMED_VALUE 108 #endif #endif diff --git a/sources/Emu48/RPL.C b/sources/Emu48/RPL.C index 0f42608..80404e3 100644 --- a/sources/Emu48/RPL.C +++ b/sources/Emu48/RPL.C @@ -9,20 +9,20 @@ #include "pch.h" #include "Emu48.h" -//| SX | GX | Name -//#7056A #806E9 =TEMPOB -//#7056F #806EE =TEMPTOP -//#70574 #806F3 =RSKTOP (B) -//#70579 #806F8 =DSKTOP (D1) -//#7066E #807ED =AVMEM (D) -//#705B0 #8072F =INTRPPTR (D0) +//| 38G | 48SX | 48GX | 49G | Name +// #7056A #806E9 #806E9 =TEMPOB +// #7056F #806EE #806EE =TEMPTOP +//#F0692 #70574 #806F3 #806F3 =RSKTOP (B) +//#F0697 #70579 #806F8 #806F8 =DSKTOP (D1) +//#F0DEA #7066E #807ED #80E9B =AVMEM (D) +//#F0705 #705B0 #8072F #8076B =INTRPPTR (D0) #define TEMPOB ((cCurrentRomType=='S')?0x7056A:0x806E9) #define TEMPTOP ((cCurrentRomType=='S')?0x7056F:0x806EE) #define RSKTOP ((cCurrentRomType=='S')?0x70574:0x806F3) #define DSKTOP ((cCurrentRomType=='S')?0x70579:0x806F8) -#define AVMEM ((cCurrentRomType=='S')?0x7066E:0x807ED) -#define INTRPPTR ((cCurrentRomType=='S')?0x705B0:0x8072F) +#define AVMEM ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x7066E:0x807ED):0x80E9B) +#define INTRPPTR ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x705B0:0x8072F):0x8076B) DWORD RPL_SkipOb(DWORD d) { @@ -33,14 +33,21 @@ DWORD RPL_SkipOb(DWORD d) n = Npack(X, 5); // read prolog switch (n) { - case 0x02911: l= 10; break; // System Binary - case 0x02933: l= 21; break; // Real - case 0x02955: l= 26; break; // Long Real - case 0x02977: l= 37; break; // Complex - case 0x0299D: l= 47; break; // Long Complex - case 0x029BF: l= 7; break; // Character - case 0x02BAA: l= 15; break; // Extended Pointer - case 0x02E92: l= 11; break; // XLIB Name + case 0x026AC: l = (cCurrentRomType!='X') ? 5 : 12; break; // Flash PTR (HP49G) + case 0x02911: l = 10; break; // System Binary + case 0x02933: l = 21; break; // Real + case 0x02955: l = 26; break; // Long Real + case 0x02977: l = 37; break; // Complex + case 0x0299D: l = 47; break; // Long Complex + case 0x029BF: l = 7; break; // Character + case 0x02BAA: l = 15; break; // Extended Pointer + case 0x02E92: l = 11; break; // XLIB Name + case 0x02686: // Symbolic matrix (HP49G) + if (cCurrentRomType!='X') + { + l = 5; + break; + } case 0x02A74: // List case 0x02AB8: // Algebraic case 0x02ADA: // Unit @@ -71,6 +78,14 @@ DWORD RPL_SkipOb(DWORD d) n = Npack(X,2)*2 + 4; return RPL_SkipOb(d+n); } + case 0x02614: // Precision Integer (HP49G) + case 0x026D5: // Aplet (HP49G) + case 0x026FE: // Mini Font (HP49G) + if (cCurrentRomType!='X') + { + l = 5; + break; + } case 0x029E8: // Array case 0x02A0A: // Linked Array case 0x02A2C: // String @@ -79,12 +94,30 @@ DWORD RPL_SkipOb(DWORD d) case 0x02B40: // Library case 0x02B62: // Backup case 0x02B88: // Library Data - case 0x02BCC: // Reserved 1 + case 0x02BCC: // Reserved 1, Font (HP49G) case 0x02BEE: // Reserved 2 case 0x02C10: // Reserved 3 case 0x02DCC: // Code l = 5+Read5(d+5); break; + case 0x0263A: // Precision Real (HP49G) + l = 5; + if (cCurrentRomType=='X') + { + l += Read5(d+l); + l += Read5(d+l); + } + break; + case 0x02660: // Precision Complex (HP49G) + l = 5; + if (cCurrentRomType=='X') + { + l += Read5(d+l); + l += Read5(d+l); + l += Read5(d+l); + l += Read5(d+l); + } + break; default: return d+5; } return d+l; @@ -97,14 +130,21 @@ DWORD RPL_ObjectSize(BYTE *o) n = Npack(o, 5); // read prolog switch (n) { - case 0x02911: l= 10; break; // System Binary - case 0x02933: l= 21; break; // Real - case 0x02955: l= 26; break; // Long Real - case 0x02977: l= 37; break; // Complex - case 0x0299D: l= 47; break; // Long Complex - case 0x029BF: l= 7; break; // Character - case 0x02BAA: l= 15; break; // Extended Pointer - case 0x02E92: l= 11; break; // XLIB Name + case 0x026AC: l = (cCurrentRomType!='X') ? 5 : 12; break; // Flash PTR (HP49G) + case 0x02911: l = 10; break; // System Binary + case 0x02933: l = 21; break; // Real + case 0x02955: l = 26; break; // Long Real + case 0x02977: l = 37; break; // Complex + case 0x0299D: l = 47; break; // Long Complex + case 0x029BF: l = 7; break; // Character + case 0x02BAA: l = 15; break; // Extended Pointer + case 0x02E92: l = 11; break; // XLIB Name + case 0x02686: // Symbolic matrix (HP49G) + if (cCurrentRomType!='X') + { + l = 5; + break; + } case 0x02A74: // List case 0x02AB8: // Algebraic case 0x02ADA: // Unit @@ -113,7 +153,7 @@ DWORD RPL_ObjectSize(BYTE *o) do { l+=n; o+=n; n=RPL_ObjectSize(o); } while (n); l += 5; break; - case 0x0312B: l= 0; break; // SEMI + case 0x0312B: l = 0; break; // SEMI case 0x02E48: // Global Name case 0x02E6D: // Local Name case 0x02AFC: // Tagged @@ -134,6 +174,14 @@ DWORD RPL_ObjectSize(BYTE *o) l += RPL_ObjectSize(o+l); } break; + case 0x02614: // Precision Integer (HP49G) + case 0x026D5: // Aplet (HP49G) + case 0x026FE: // Mini Font (HP49G) + if (cCurrentRomType!='X') + { + l = 5; + break; + } case 0x029E8: // Array case 0x02A0A: // Linked Array case 0x02A2C: // String @@ -142,12 +190,30 @@ DWORD RPL_ObjectSize(BYTE *o) case 0x02B40: // Library case 0x02B62: // Backup case 0x02B88: // Library Data - case 0x02BCC: // Reserved 1 + case 0x02BCC: // Reserved 1, Font (HP49G) case 0x02BEE: // Reserved 2 case 0x02C10: // Reserved 3 case 0x02DCC: // Code l = 5 + Npack(o+5,5); break; + case 0x0263A: // Precision Real (HP49G) + l = 5; + if (cCurrentRomType=='X') + { + l += Npack(o+l,5); + l += Npack(o+l,5); + } + break; + case 0x02660: // Precision Complex (HP49G) + l = 5; + if (cCurrentRomType=='X') + { + l += Npack(o+l,5); + l += Npack(o+l,5); + l += Npack(o+l,5); + l += Npack(o+l,5); + } + break; default: l=5; } return l; @@ -178,13 +244,13 @@ DWORD RPL_Pick(UINT l) { DWORD stkp; - _ASSERT(l > 0); // 12.11.98 cg, new, first stack elememt is one + _ASSERT(l > 0); // first stack elememt is one if (l==0) return 0; stkp = Read5(DSKTOP) + (l-1)*5; return Read5(stkp); } -#if 0 // 12.11.98 cg, function not needed yet +#if 0 // function not needed yet VOID RPL_Replace(DWORD n) { DWORD stkp; diff --git a/sources/Emu48/SERIAL.C b/sources/Emu48/SERIAL.C index 2155cf7..fab7f93 100644 --- a/sources/Emu48/SERIAL.C +++ b/sources/Emu48/SERIAL.C @@ -8,10 +8,17 @@ */ #include "pch.h" #include "Emu48.h" -#include "Serial.h" +#include "io.h" // 24.10.99 cg, renamed from Serial.h #define INTERRUPT ((void)(Chipset.SoftInt=TRUE,bInterrupt=TRUE)) +// 25.10.99 cg, new, state of USRQ +#define NINT2ERBZ ((Chipset.IORam[IOC] & ERBZ) != 0 && (Chipset.IORam[RCS] & RBZ) != 0) +#define NINT2ERBF ((Chipset.IORam[IOC] & ERBF) != 0 && (Chipset.IORam[RCS] & RBF) != 0) +#define NINT2ETBE ((Chipset.IORam[IOC] & ETBE) != 0 && (Chipset.IORam[TCS] & TBF) == 0) + +#define NINT2USRQ (NINT2ERBZ || NINT2ERBF || NINT2ETBE) + static OVERLAPPED os = { 0 }; static HANDLE hComm = NULL; static HANDLE hCThread = NULL; @@ -19,7 +26,11 @@ static DWORD lSerialThreadId = 0; static BOOL bReading = TRUE; static WORD wPort = PORT_CLOSE; -static CRITICAL_SECTION csRecv; // 01.06.98 cg, new, critical section for receive byte +static BYTE cBuffer[128]; +static WORD nRp; +static DWORD dwBytesRead = 0L; + +// static CRITICAL_SECTION csRecv; // 24.10.99 cg, moved to main function static DWORD WINAPI SerialThread(LPVOID pParam) { @@ -34,7 +45,10 @@ static DWORD WINAPI SerialThread(LPVOID pParam) CommReceive(); // get data // interrupt request and emulation thread down if (Chipset.SoftInt && Chipset.Shutdn) - ResumeThread(hThread); // wake up emulation thread + { + Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode + SetEvent(hEventShutdn); // wake up emulation thread + } } } lSerialThreadId = 0; // signal serial thread is down @@ -42,7 +56,6 @@ static DWORD WINAPI SerialThread(LPVOID pParam) UNREFERENCED_PARAMETER(pParam); } - WORD CommConnect(VOID) { return wPort; @@ -54,10 +67,11 @@ VOID CommOpen(LPSTR strWirePort,LPSTR strIrPort) LPSTR strPort = (Chipset.IORam[IR_CTRL] & EIRU) ? strIrPort : strWirePort; + _ASSERT(Chipset.IORam[IOC] & SON); // UART on if (hComm != NULL) // port already open CloseHandle(hComm); - if (strcmp(strPort,NO_SERIAL)) // port defined + if (strcmp(strPort, NO_SERIAL)) // port defined { hComm = CreateFile(strPort, GENERIC_READ | GENERIC_WRITE, @@ -69,8 +83,7 @@ VOID CommOpen(LPSTR strWirePort,LPSTR strIrPort) if(hComm != INVALID_HANDLE_VALUE) { - // 01.06.98 cg, bugfix, initialize critical section - InitializeCriticalSection(&csRecv); + // InitializeCriticalSection(&csRecv); wPort = (Chipset.IORam[IR_CTRL] & EIRU) ? PORT_IR : PORT_WIRE; SetCommTimeouts(hComm,&CommTimeouts); @@ -92,6 +105,7 @@ VOID CommOpen(LPSTR strWirePort,LPSTR strIrPort) OutputDebugString(buffer); } #endif + return; } VOID CommClose(VOID) @@ -106,9 +120,10 @@ VOID CommClose(VOID) #if defined DEBUG_SERIAL OutputDebugString("COM port closed.\n"); #endif - DeleteCriticalSection(&csRecv); // 01.06.98 cg, bugfix, release critical section + // DeleteCriticalSection(&csRecv); wPort = PORT_CLOSE; } + return; } VOID CommSetBaud(VOID) @@ -147,6 +162,13 @@ VOID CommSetBaud(VOID) SetCommState(hComm,&dcb); } + return; +} + +VOID UpdateUSRQ(VOID) // 25.10.99 cg, new, USRQ handling +{ + IOBit(SRQ1,USRQ,NINT2USRQ); // update USRQ bit + return; } VOID CommTransmit(VOID) @@ -166,36 +188,42 @@ VOID CommTransmit(VOID) } #endif - if (hComm != NULL) // wire com port open + // 23.10.99 cg, bugfix, add serial loopback support + if (Chipset.IORam[TCS] & LPB) // is loopback bit set + { + cBuffer[nRp+dwBytesRead] = tbr; // save character in receive buffer + ++dwBytesRead; + + CommReceive(); // receive byte available + } + // 23.10.99 cg, end of implementation + + if (hComm != NULL) // com port open WriteFile(hComm,(LPCVOID) &tbr,1,&dwWritten,&os); Chipset.IORam[TCS] &= (~TBF); // clear transmit buffer - if (Chipset.IORam[IO_CTRL] & ETBE) // interrupt on transmit buffer empty + UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ bit + if (Chipset.IORam[IOC] & ETBE) // interrupt on transmit buffer empty INTERRUPT; + return; } VOID CommReceive(VOID) { - static BYTE cBuffer[128]; - static WORD nRp; - static DWORD dwBytesRead = 0L; - - if (hComm == NULL) // not open - return; - - if (!(Chipset.IORam[IO_CTRL] & SON)) // UART off + if (!(Chipset.IORam[IOC] & SON)) // UART off { dwBytesRead = 0L; // no bytes received return; } - EnterCriticalSection(&csRecv); // 01.06.98 cg, bugfix, synchronize + EnterCriticalSection(&csRecvLock); do { if (Chipset.IORam[RCS] & RBF) // receive buffer full break; - if (dwBytesRead == 0L) // buffer empty + // 23.10.99 cg, bugfix, reject reading if com port is closed and not whole operation + if (hComm && dwBytesRead == 0L) // com port open and buffer empty { if(ReadFile(hComm,&cBuffer,sizeof(cBuffer),&dwBytesRead,&os) == FALSE) dwBytesRead = 0L; @@ -223,9 +251,11 @@ VOID CommReceive(VOID) --dwBytesRead; Chipset.IORam[RCS] |= RBF; // receive buffer full - if (Chipset.IORam[IO_CTRL] & ERBF) // interrupt on recv buffer full + UpdateUSRQ(); // 25.10.99 cg, bugfix, update USRQ bit + if (Chipset.IORam[IOC] & ERBF) // interrupt on recv buffer full INTERRUPT; } while(0); - LeaveCriticalSection(&csRecv); // 01.06.98 cg + LeaveCriticalSection(&csRecvLock); + return; } diff --git a/sources/Emu48/SERIAL.H b/sources/Emu48/SERIAL.H deleted file mode 100644 index 5fd63e2..0000000 --- a/sources/Emu48/SERIAL.H +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Serial.h - * - * This file is part of Emu48 - * - * Copyright (C) 1998 Christoph Gießelink - * - */ - -// UART addresses without mapping offset -#define BAUD 0x0d // Baudrate (Bit 2-0) -#define IO_CTRL 0x10 // IO CONTROL -#define RCS 0x11 // RCS -#define TCS 0x12 // TCS -#define CRER 0x13 // CRER -#define RBR_LSB 0x14 // RBR low nibble -#define RBR_MSB 0x15 // RBR high nibble -#define TBR_LSB 0x16 // TBR low nibble -#define TBR_MSB 0x17 // TBR high nibble -#define IR_CTRL 0x1a // IR CONTROL - -// 0x10 Serial I/O Control [SON ETBE ERBF ERBZ] -#define SON 0x08 // Serial on -#define ETBE 0x04 // Interrupt on transmit buffer empty -#define ERBF 0x02 // Interrupt on receive buffer full -#define ERBZ 0x01 // Interrupt on receiver busy - -// 0x11 Serial Receive Control/Status [RX RER RBZ RBF] -#define RX 0x08 // ??? Rx pin high (read-only) -#define RER 0x04 // Receiver error -#define RBZ 0x02 // Receiver busy -#define RBF 0x01 // Receive buffer full - -// 0x12 Serial Transmit Control/Status [BRK LPB TBZ TBF] -#define BRK 0x08 -#define LPB 0x04 -#define TBZ 0x02 // Transmitter busy -#define TBF 0x01 // Transmit buffer full - -// 0x1a IR Control Register [IRI EIRU EIRI IRE] -#define IRI 0x08 // IR input (read-only) -#define EIRU 0x04 // Enable IR UART mode -#define EIRI 0x02 // Enable IR interrupt -#define IRE 0x01 // IR event diff --git a/sources/Emu48/SETTINGS.C b/sources/Emu48/SETTINGS.C new file mode 100644 index 0000000..0c909fa --- /dev/null +++ b/sources/Emu48/SETTINGS.C @@ -0,0 +1,76 @@ +/* + * settings.c + * + * This file is part of Emu48 + * + * Copyright (C) 1995 Sebastien Carlier + * Copyright (C) 1999 Christoph Gießelink + * + */ +#include "pch.h" +#include "Emu48.h" + +#define EMU48_INI "Emu48.ini" + +static BOOL WritePrivateProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue, LPCTSTR lpszFilename) +{ + char s[16]; + wsprintf(s,"%i",nValue); + return WritePrivateProfileString(lpszSection, lpszEntry, s, lpszFilename); +} + +VOID ReadSettings(VOID) +{ + // Files + GetPrivateProfileString("Files","Emu48Directory",szCurrentDirectory,szEmu48Directory, + sizeof(szEmu48Directory),EMU48_INI); + bAutoSave = GetPrivateProfileInt("Files","AutoSave",bAutoSave,EMU48_INI); + bAutoSaveOnExit = GetPrivateProfileInt("Files","AutoSaveOnExit",bAutoSaveOnExit,EMU48_INI); + // Port2 + bPort2IsShared = GetPrivateProfileInt("Port2","IsShared",0,EMU48_INI); + GetPrivateProfileString("Port2","Filename","SHARED.BIN",szPort2Filename,sizeof(szPort2Filename),EMU48_INI); + // KML + bAlwaysDisplayLog = GetPrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI); + // Emulator + bRealSpeed = GetPrivateProfileInt("Emulator","RealSpeed",0,EMU48_INI); + dwSXCycles = GetPrivateProfileInt("Emulator","SXCycles",82,EMU48_INI); + dwGXCycles = GetPrivateProfileInt("Emulator","GXCycles",123,EMU48_INI); + SetSpeed(bRealSpeed); // set speed + // Serial + GetPrivateProfileString("Serial","Wire",NO_SERIAL,szSerialWire,sizeof(szSerialWire),EMU48_INI); + GetPrivateProfileString("Serial","Ir",NO_SERIAL,szSerialIr,sizeof(szSerialIr),EMU48_INI); + return; +} + +VOID WriteSettings(VOID) +{ + // Files + WritePrivateProfileString("Files","Emu48Directory",szEmu48Directory,EMU48_INI); + WritePrivateProfileInt("Files","AutoSave",bAutoSave,EMU48_INI); + WritePrivateProfileInt("Files","AutoSaveOnExit",bAutoSaveOnExit,EMU48_INI); + // Port2 + WritePrivateProfileInt("Port2","IsShared",bPort2IsShared,EMU48_INI); + WritePrivateProfileString("Port2","Filename",szPort2Filename,EMU48_INI); + // KML + WritePrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI); + // Emulator + WritePrivateProfileInt("Emulator","RealSpeed",bRealSpeed,EMU48_INI); + WritePrivateProfileInt("Emulator","SXCycles",dwSXCycles,EMU48_INI); + WritePrivateProfileInt("Emulator","GXCycles",dwGXCycles,EMU48_INI); + // Serial + WritePrivateProfileString("Serial","Wire",szSerialWire,EMU48_INI); + WritePrivateProfileString("Serial","Ir",szSerialIr,EMU48_INI); + return; +} + +VOID ReadLastDocument(LPTSTR szFilename, DWORD nSize) +{ + GetPrivateProfileString("Files","LastDocument","",szFilename,nSize,EMU48_INI); + return; +} + +VOID WriteLastDocument(LPCTSTR szFilename) +{ + WritePrivateProfileString("Files","LastDocument",szFilename,EMU48_INI); + return; +} diff --git a/sources/Emu48/TIMER.C b/sources/Emu48/TIMER.C index 540983c..2f73b5a 100644 --- a/sources/Emu48/TIMER.C +++ b/sources/Emu48/TIMER.C @@ -8,63 +8,198 @@ */ #include "pch.h" #include "Emu48.h" +#include "io.h" // 24.10.99 cg, new, I/O definitions -#define AUTO_OFF 10 // 25.02.98 cg, new, Time in minutes for 'auto off' +#define AUTO_OFF 10 // Time in minutes for 'auto off' -// 25.02.98 cg, new, Ticks for 01.01.1970 00:00:00 +// Ticks for 01.01.1970 00:00:00 #define UNIX_0_TIME 0x0001cf2e8f800000 -// 25.02.98 cg, new, Ticks for 'auto off' +// Ticks for 'auto off' #define OFF_TIME ((LONGLONG) (AUTO_OFF * 60) << 13) -// 30.09.98 cg, new, memory address for clock and auto off -// S(X) = 0x70052-0x70070, G(X) = 0x80058-0x80076 +// memory address for clock and auto off +// S(X) = 0x70052-0x70070, G(X) = 0x80058-0x80076, 49G = 0x80058-0x80076 #define RPLTIME ((cCurrentRomType=='S')?0x52:0x58) -#define T1_FREQ 62 // 10.11.98 cg, new, Timer1 1/frequency in ms -#define T2_FREQ 8192 // 06.04.98 cg, new, Timer2 frequency - -// 27.02.98 cg, new, Timer definitions - -// Timer addresses without mapping offset -#define TIMER1_CTRL 0x2e // Timer1 Control -#define TIMER2_CTRL 0x2f // Timer2 Control -#define TIMER1 0x37 // Timer1 (4 bit) -#define TIMER2 0x3f // Timer2 (32 bit, LSB first) - -// 0x2e Timer1 Control [SRQ WKE INT XTRA] -#define SRQ 0x08 // Service request -#define WKE 0x04 // Wake up -#define INT 0x02 // Interrupt -#define XTRA 0x01 // Extra function - -// 0x2f Timer2 Control [SRQ WKE INT RUN] -#define SRQ 0x08 // Service request -#define WKE 0x04 // Wake up -#define INT 0x02 // Interrupt -#define RUN 0x01 // Timer run - -// BOOL bAccurateTimer = TRUE; // 10.11.98 cg, removed, not adjustable any more -// UINT uT1Period = 62; // 10.11.98 cg, removed, not adjustable any more +#define T1_FREQ 62 // Timer1 1/frequency in ms +#define T2_FREQ 8192 // Timer2 frequency static BOOL bStarted = FALSE; -static BOOL bOutRange = FALSE; // 21.04.98 cg, new, flag if timer value out of range +static BOOL bOutRange = FALSE; // flag if timer value out of range static UINT uT1TimerId = 0; static UINT uT2TimerId = 0; -// static DWORD dwT1Ticks = 0; // 19.02.98 cg, removed, not used -// static DWORD dwT2Init = 0; // 06.04.98 cg, removed, not used any more -// static DWORD dwT2Step = 0; // 06.04.98 cg, removed, not used any more -// static DWORD dwT2Ticks = 0; // 06.04.98 cg, removed, not used any more -static BOOL bAccurateTimer; // 10.11.98 cg, new, flag if accurate timer is used -static LARGE_INTEGER lT2Ref; // 06.04.98 cg, new, counter value at timer2 start -static TIMECAPS tc; // 21.04.98 cg, new, timer information +static BOOL bNINT2T1 = FALSE; // 24.10.99 cg, new, state of NINT2 affected form Timer1 +static BOOL bNINT2T2 = FALSE; // 24.10.99 cg, new, state of NINT2 affected form Timer2 + +static BOOL bAccurateTimer; // flag if accurate timer is used +static LARGE_INTEGER lT2Ref; // counter value at timer2 start +static TIMECAPS tc; // timer information static __inline MAX(int a, int b) {return (a>b)?a:b;} static void CALLBACK TimeProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2); -static VOID SetAccesstime(VOID) // 06.10.97 cg, new, set date and time +static DWORD CalcT2(VOID) // calculate timer2 value +{ + DWORD dwT2 = Chipset.t2; // get value from chipset + if (bStarted) // timer2 running + { + LARGE_INTEGER lT2Act; + QueryPerformanceCounter(&lT2Act); // actual time + // calculate ticks since reference point + dwT2 -= (DWORD) + (((lT2Act.QuadPart - lT2Ref.QuadPart) * T2_FREQ) + / lFreq.QuadPart); + } + return dwT2; +} + +static VOID CheckT1(BYTE nT1) +{ + // 24.10.99 cg, bugfix, implementation of TSRQ + bNINT2T1 = (Chipset.IORam[TIMER1_CTRL]&INTR) != 0 && (nT1&8) != 0; + IOBit(SRQ1,TSRQ,bNINT2T1 || bNINT2T2); + // 24.10.99 cg, end of implementation + + if ((nT1&8) == 0) // timer1 MSB not set + { + Chipset.IORam[TIMER1_CTRL] &= ~SRQ; // clear SRQ bit + return; + } + + _ASSERT((nT1&8) != 0); // timer1 MSB set + + // timer MSB is one and either INT or WAKE is set + if ( (Chipset.IORam[TIMER1_CTRL]&WKE) + || (Chipset.IORam[TIMER1_CTRL]&INTR)) + Chipset.IORam[TIMER1_CTRL] |= SRQ; // set SRQ + // cpu not sleeping and T1 -> Interrupt + if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER1_CTRL]&WKE)) + && (Chipset.IORam[TIMER1_CTRL]&INTR)) + { + Chipset.SoftInt = TRUE; + bInterrupt = TRUE; + } + // cpu sleeping and T1 -> Wake Up + if (Chipset.Shutdn && (Chipset.IORam[TIMER1_CTRL]&WKE)) + { + Chipset.IORam[TIMER1_CTRL] &= ~WKE; // clear WKE bit + Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode + SetEvent(hEventShutdn); // wake up emulation thread + } + return; +} + +static VOID CheckT2(DWORD dwT2) +{ + // 24.10.99 cg, bugfix, implementation of TSRQ + bNINT2T2 = (Chipset.IORam[TIMER2_CTRL]&INTR) != 0 && (dwT2&0x80000000) != 0; + IOBit(SRQ1,TSRQ,bNINT2T1 || bNINT2T2); + // 24.10.99 cg, end of implementation + + if ((dwT2&0x80000000) == 0) // timer2 MSB not set + { + Chipset.IORam[TIMER2_CTRL] &= ~SRQ; // clear SRQ bit + return; + } + + _ASSERT((dwT2&0x80000000) != 0); // timer2 MSB set + + // timer MSB is one and either INT or WAKE is set + if ( (Chipset.IORam[TIMER2_CTRL]&WKE) + || (Chipset.IORam[TIMER2_CTRL]&INTR)) + Chipset.IORam[TIMER2_CTRL] |= SRQ; // set SRQ + // cpu not sleeping and T2 -> Interrupt + if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER2_CTRL]&WKE)) + && (Chipset.IORam[TIMER2_CTRL]&INTR)) + { + Chipset.SoftInt = TRUE; + bInterrupt = TRUE; + } + // cpu sleeping and T2 -> Wake Up + if (Chipset.Shutdn && (Chipset.IORam[TIMER2_CTRL]&WKE)) + { + Chipset.IORam[TIMER2_CTRL] &= ~WKE; // clear WKE bit + Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode + SetEvent(hEventShutdn); // wake up emulation thread + } + return; +} + +static VOID RescheduleT2(BOOL bRefPoint) +{ + UINT uDelay; + _ASSERT(uT2TimerId == 0); // timer2 must stopped + if (bRefPoint) // save reference time + { + QueryPerformanceCounter(&lT2Ref); // time of corresponding Chipset.t2 value + uDelay = Chipset.t2; // timer value for delay + } + else // called without new refpoint, restart t2 with actual value + { + uDelay = CalcT2(); // actual timer value for delay + } + uDelay &= 0x7FFFFFFF; // execute timer2 event when MSB change + uDelay >>= 3; // timer delay in ms + uDelay = MAX(tc.wPeriodMin,uDelay); // wait minimum delay of timer + if (bOutRange = uDelay > tc.wPeriodMax) // delay greater maximum delay + uDelay = tc.wPeriodMax; // wait maximum delay time + // start timer2; schedule event, when Chipset.t2 will be zero (Chipset.t2 / 8 = time in ms) + uT2TimerId = timeSetEvent(uDelay,0,(LPTIMECALLBACK)&TimeProc,2,TIME_ONESHOT); + _ASSERT(uT2TimerId); // test if timer2 started + return; +} + +static VOID AbortT2(VOID) +{ + _ASSERT(uT2TimerId); + timeKillEvent(uT2TimerId); // kill event + uT2TimerId = 0; // then reset var + return; +} + +static void CALLBACK TimeProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) +{ + _ASSERT(uEventId); // illegal EventId + if (!bStarted) // timer stopped + return; // -> quit + if (uEventId == uT1TimerId) // called from timer1 event (default period 16 Hz) + { + EnterCriticalSection(&csT1Lock); + { + Chipset.t1 = (Chipset.t1-1)&0xF;// decrement timer value + CheckT1(Chipset.t1); // test timer1 control bits + } + LeaveCriticalSection(&csT1Lock); + return; + } + if (uEventId == uT2TimerId) // called from timer2 event, Chipset.t2 should be zero + { + EnterCriticalSection(&csT2Lock); + { + uT2TimerId = 0; // single shot timer timer2 stopped + if (!bOutRange) // timer event elapsed + { + // timer2 overrun, test timer2 control bits else restart timer2 + Chipset.t2 = CalcT2(); // calculate new timer2 value + CheckT2(Chipset.t2); // test timer2 control bits + } + RescheduleT2(!bOutRange); // restart timer2 + } + LeaveCriticalSection(&csT2Lock); + return; + } + return; + UNREFERENCED_PARAMETER(uMsg); + UNREFERENCED_PARAMETER(dwUser); + UNREFERENCED_PARAMETER(dw1); + UNREFERENCED_PARAMETER(dw2); +} + + +VOID SetHP48Time(VOID) // set date and time { SYSTEMTIME ts; LONGLONG ticks, time; @@ -104,188 +239,33 @@ static VOID SetAccesstime(VOID) // 06.10.97 cg, new, set date and time time = ticks; // save for calc. timeout time += OFF_TIME; // add 10 min for auto off - dw = RPLTIME; // 30.09.98, bugfix, HP addresses for clock in port0 + dw = RPLTIME; // HP addresses for clock in port0 crc = 0x0; // reset crc value for (i = 0; i < 13; ++i, ++dw) // write date and time { *p = (BYTE) ticks & 0xf; crc = (crc >> 4) ^ (((crc ^ ((WORD) *p)) & 0xf) * 0x1081); - Chipset.Port0[dw] = *p; // 30.09.98, bugfix, always store in port0 + Chipset.Port0[dw] = *p; // always store in port0 ticks >>= 4; } Nunpack(p,crc,4); // write crc - memcpy(Chipset.Port0+dw,p,4); // 30.09.98, bugfix, always store in port0 + memcpy(Chipset.Port0+dw,p,4); // always store in port0 dw += 4; // HP addresses for timeout for (i = 0; i < 13; ++i, ++dw) // write time for auto off { - // 30.09.98, bugfix, always store in port0 + // always store in port0 Chipset.Port0[dw] = (BYTE) time & 0xf; time >>= 4; } - Chipset.Port0[dw] = 0xf; // 30.09.98, bugfix, always store in port0 + Chipset.Port0[dw] = 0xf; // always store in port0 return; } -static DWORD CalcT2(VOID) // 21.04.98 cg, new, calculate timer2 value -{ - DWORD dwT2 = Chipset.t2; // get value from chipset - if (bStarted) // timer2 running - { - LARGE_INTEGER lT2Act; - QueryPerformanceCounter(&lT2Act); // actual time - // calculate ticks since reference point - dwT2 -= (DWORD) - (((lT2Act.QuadPart - lT2Ref.QuadPart) * T2_FREQ) - / lFreq.QuadPart); - } - return dwT2; -} - -static VOID CheckT1(BYTE nT1) // 25.11.98 cg, bugfix, changed implementation -{ - if ((nT1&8) == 0) // timer1 MSB not set - { - Chipset.IORam[TIMER1_CTRL] &= ~SRQ; // clear SRQ bit - return; - } - - _ASSERT((nT1&8) != 0); // timer1 MSB set - - // timer MSB is one and either INT or WAKE is set - if ( (Chipset.IORam[TIMER1_CTRL]&WKE) - || (Chipset.IORam[TIMER1_CTRL]&INT)) - Chipset.IORam[TIMER1_CTRL] |= SRQ; // set SRQ - // cpu not sleeping and T1 -> Interrupt - if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER1_CTRL]&WKE)) - && (Chipset.IORam[TIMER1_CTRL]&INT)) - { - Chipset.SoftInt = TRUE; - bInterrupt = TRUE; - } - // cpu sleeping and T1 -> Wake Up - if (Chipset.Shutdn && (Chipset.IORam[TIMER1_CTRL]&WKE)) - { - Chipset.IORam[TIMER1_CTRL] &= ~WKE; // clear WKE bit - ResumeThread(hThread); // wake up emulation thread - } - return; -} - -static VOID CheckT2(DWORD dwT2) // 25.11.98 cg, bugfix, changed implementation -{ - if ((dwT2&0x80000000) == 0) // timer2 MSB not set - { - Chipset.IORam[TIMER2_CTRL] &= ~SRQ; // clear SRQ bit - return; - } - - _ASSERT((dwT2&0x80000000) != 0); // timer2 MSB set - - // timer MSB is one and either INT or WAKE is set - if ( (Chipset.IORam[TIMER2_CTRL]&WKE) - || (Chipset.IORam[TIMER2_CTRL]&INT)) - Chipset.IORam[TIMER2_CTRL] |= SRQ; // set SRQ - // cpu not sleeping and T2 -> Interrupt - if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER2_CTRL]&WKE)) - && (Chipset.IORam[TIMER2_CTRL]&INT)) - { - Chipset.SoftInt = TRUE; - bInterrupt = TRUE; - } - // cpu sleeping and T2 -> Wake Up - if (Chipset.Shutdn && (Chipset.IORam[TIMER2_CTRL]&WKE)) - { - Chipset.IORam[TIMER2_CTRL] &= ~WKE; // clear WKE bit - ResumeThread(hThread); // wake up emulation thread - } - return; -} - -static VOID RescheduleT2(BOOL bRefPoint) // 21.04.98 cg, add function parameter -{ - UINT uDelay; - _ASSERT(uT2TimerId == 0); // timer2 must stopped - // 29.09.98 cg, bugfix, changed implementation - if (bRefPoint) // save reference time - { - QueryPerformanceCounter(&lT2Ref); // time of corresponding Chipset.t2 value - uDelay = Chipset.t2; // timer value for delay - } - else // called without new refpoint, restart t2 with actual value - { - uDelay = CalcT2(); // actual timer value for delay - } - uDelay &= 0x7FFFFFFF; // 24.11.98 cg, bugfix, execute timer2 event when MSB change - uDelay >>= 3; // timer delay in ms - uDelay = MAX(tc.wPeriodMin,uDelay); // wait minimum delay of timer - if (bOutRange = uDelay > tc.wPeriodMax) // delay greater maximum delay - uDelay = tc.wPeriodMax; // wait maximum delay time - // 29.09.98 cg, end of changed implementation - // dwT2Init = timeGetTime(); // 06.04.98 cg, not used any more - // dwT2Ticks = dwT2Init; // 06.04.98 cg, not used any more - // start timer2; schedule event, when Chipset.t2 will be zero (Chipset.t2 / 8 = time in ms) - uT2TimerId = timeSetEvent(uDelay,0,(LPTIMECALLBACK)&TimeProc,2,TIME_ONESHOT); - _ASSERT(uT2TimerId); // 21.04.98 cg, new, test if timer2 started - return; -} - -static VOID AbortT2(VOID) -{ - _ASSERT(uT2TimerId); - timeKillEvent(uT2TimerId); // 09.10.97 cg, bugfix, first kill event - uT2TimerId = 0; // 09.10.97 cg, bugfix, then reset var - return; -} - -static void CALLBACK TimeProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) -{ - _ASSERT(uEventId); // 16.03.98 cg, new, illegal EventId - if (!bStarted) // timer stopped - return; // -> quit - // called from timer1 event (default period 16 Hz) - // if ((uT1TimerId!=0) && (uEventId == uT1TimerId)) - if (uEventId == uT1TimerId) // 16.03.98 cg, removed useless part - { - EnterCriticalSection(&csT1Lock); // 21.04.98 cg, bugfix, synchronize - { - Chipset.t1 = (Chipset.t1-1)&0xF;// decrement timer value - CheckT1(Chipset.t1); // test timer1 control bits - } - LeaveCriticalSection(&csT1Lock); // 21.04.98 cg - return; - } - // called from timer2 event, Chipset.t2 should be zero - // if ((uT2TimerId!=0) && (uEventId == uT2TimerId)) - if (uEventId == uT2TimerId) // 16.03.98 cg, removed useless part - { - EnterCriticalSection(&csT2Lock); // 21.04.98 cg, bugfix, synchronize - { - uT2TimerId = 0; // 30.11.98 cg, bugfix, single shot timer timer2 stopped - if (!bOutRange) // 21.04.98 cg, timer event elapsed - { - // timer2 overrun, test timer2 control bits else restart timer2 - // 16.11.98 cg, bugfix, don't wait for timer2 overrun any more - Chipset.t2 = CalcT2(); // calculate new timer2 value - CheckT2(Chipset.t2); // test timer2 control bits - } - RescheduleT2(!bOutRange); // restart timer2 - } - LeaveCriticalSection(&csT2Lock); // 21.04.98 cg - return; - } - return; - UNREFERENCED_PARAMETER(uMsg); - UNREFERENCED_PARAMETER(dwUser); // 19.02.98 cg, added unreferenced parameter declarations - UNREFERENCED_PARAMETER(dw1); - UNREFERENCED_PARAMETER(dw2); -} - - VOID StartTimers(VOID) { if (bStarted) // timer running @@ -293,18 +273,16 @@ VOID StartTimers(VOID) if (Chipset.IORam[TIMER2_CTRL]&RUN) // start timer1 and timer2 ? { bStarted = TRUE; // flag timer running - SetAccesstime(); // 06.10.97 cg, set date and time - // 10.11.98 cg, changed, use always accurate timer - // if (bAccurateTimer) // box "Accurate timer" checked - // { - // 21.04.98 cg, optimized, set timer resolution to 1 ms, if failed don't use "Accurate timer" + // 24.10.99 cg, new, initialisation of NINT2 lines + bNINT2T1 = (Chipset.IORam[TIMER1_CTRL]&INTR) != 0 && (Chipset.t1 & 8) != 0; + bNINT2T2 = (Chipset.IORam[TIMER2_CTRL]&INTR) != 0 && (Chipset.t2 & 0x80000000) != 0; + // 24.10.99 cg, end of initialisation + // set timer resolution to 1 ms, if failed don't use "Accurate timer" bAccurateTimer = (timeBeginPeriod(1) == TIMERR_NOERROR); - // } - timeGetDevCaps(&tc,sizeof(tc)); // 21.04.98 cg, get timer resolution + timeGetDevCaps(&tc,sizeof(tc)); // get timer resolution // set timer1 with given period - // 10.11.98 cg, changed, use fix event time uT1TimerId = timeSetEvent(T1_FREQ,0,(LPTIMECALLBACK)&TimeProc,1,TIME_PERIODIC); - _ASSERT(uT1TimerId); // 16.03.98 cg, new, test if timer1 started + _ASSERT(uT1TimerId); // test if timer1 started RescheduleT2(TRUE); // start timer2 } return; @@ -314,23 +292,21 @@ VOID StopTimers(VOID) { if (!bStarted) // timer stopped return; // -> quit - // Chipset.t2 = ReadT2(); // 21.04.98 cg, removed, read timer2 value later if (uT1TimerId != 0) // timer1 running { - // 02.12.98 cg, bugfix, Critical Section handler may cause a dead lock + // Critical Section handler may cause a dead lock timeKillEvent(uT1TimerId); // stop timer1 uT1TimerId = 0; // set flag timer1 stopped - // 02.12.98 cg, end of bugfix } if (uT2TimerId != 0) // timer2 running { - EnterCriticalSection(&csT2Lock); // 21.04.98 cg, bugfix, synchronize + EnterCriticalSection(&csT2Lock); { - Chipset.t2 = CalcT2(); // 21.04.98 cg, update chipset timer2 value - // AbortT2(); // 02.12.98 cg, removed, stop timer2 later + Chipset.t2 = CalcT2(); // update chipset timer2 value + // AbortT2(); // removed, stop timer2 later } - LeaveCriticalSection(&csT2Lock); // 21.04.98 cg - AbortT2(); // 02.12.98 cg, bugfix, stop timer2 here + LeaveCriticalSection(&csT2Lock); + AbortT2(); // stop timer2 here } bStarted = FALSE; if (bAccurateTimer) // "Accurate timer" running @@ -342,13 +318,12 @@ VOID StopTimers(VOID) DWORD ReadT2(VOID) { - // 21.04.98 cg, changed implementation DWORD dwT2; EnterCriticalSection(&csT2Lock); { - // 16.12.98 cg, bugfix, calculate timer2 value or if stopped last timer value + // calculate timer2 value or if stopped last timer value dwT2 = bStarted ? CalcT2() : Chipset.t2; - CheckT2(dwT2); // 25.11.98 cg, new, update timer2 control bits + CheckT2(dwT2); // update timer2 control bits } LeaveCriticalSection(&csT2Lock); return dwT2; @@ -357,15 +332,12 @@ DWORD ReadT2(VOID) VOID SetT2(DWORD dwValue) { // calling AbortT2() inside Critical Section handler may cause a dead lock - if (uT2TimerId != 0) // 02.12.98 cg, bugfix, timer2 running - AbortT2(); // 02.12.98 cg, bugfix, stop timer2 - // 21.04.98 cg, changed implementation + if (uT2TimerId != 0) // timer2 running + AbortT2(); // stop timer2 EnterCriticalSection(&csT2Lock); { - // if (uT2TimerId != 0) // 02.12.98 cg, removed, done before - // AbortT2(); // 02.12.98 cg, removed, done before Chipset.t2 = dwValue; // set new value - CheckT2(Chipset.t2); // 25.11.98 cg, readded, test timer2 control bits + CheckT2(Chipset.t2); // test timer2 control bits if (bStarted) // timer running RescheduleT2(TRUE); // restart timer2 } @@ -376,28 +348,32 @@ VOID SetT2(DWORD dwValue) BYTE ReadT1(VOID) { BYTE nT1; - EnterCriticalSection(&csT1Lock); // 21.04.98 cg, bugfix, synchronize + EnterCriticalSection(&csT1Lock); { nT1 = Chipset.t1; // read timer1 value - CheckT1(nT1); // 25.11.98 cg, new, update timer1 control bits + CheckT1(nT1); // update timer1 control bits } - LeaveCriticalSection(&csT1Lock); // 21.04.98 cg + LeaveCriticalSection(&csT1Lock); return nT1; } VOID SetT1(BYTE byValue) { - timeKillEvent(uT1TimerId); // 11.06.98 cg, bugfix, stop timer1 - uT1TimerId = 0; // 11.06.98 cg, new, set flag timer1 stopped - EnterCriticalSection(&csT1Lock); // 21.04.98 cg, bugfix, synchronize + _ASSERT(byValue < 0x10); // timer1 is only a 4bit counter + + if (Chipset.t1 == byValue) // same value doesn't restart timer period + return; + + timeKillEvent(uT1TimerId); // stop timer1 + uT1TimerId = 0; // set flag timer1 stopped + EnterCriticalSection(&csT1Lock); { - Chipset.t1 = byValue&0xF; // set new timer1 value - CheckT1(Chipset.t1); // 25.11.98 cg, readded, test timer1 control bits + Chipset.t1 = byValue; // set new timer1 value + CheckT1(Chipset.t1); // test timer1 control bits } - LeaveCriticalSection(&csT1Lock); // 21.04.98 cg - // 11.06.98 cg, bugfix, restart timer1 - // 10.11.98 cg, changed, use fix event time + LeaveCriticalSection(&csT1Lock); + // restart timer1 to get full period of frequency uT1TimerId = timeSetEvent(T1_FREQ,0,(LPTIMECALLBACK)&TimeProc,1,TIME_PERIODIC); - _ASSERT(uT1TimerId); // 11.06.98 cg, new, test if timer1 started + _ASSERT(uT1TimerId); // test if timer1 started return; } diff --git a/sources/Emu48/TYPES.H b/sources/Emu48/TYPES.H index 200e85f..0caaa1b 100644 --- a/sources/Emu48/TYPES.H +++ b/sources/Emu48/TYPES.H @@ -7,16 +7,19 @@ * */ +#define SWORD SHORT // 09.12.99 cg, new, signed 16 Bit variable +#define QWORD ULONGLONG // 22.11.99 cg, new, unsigned 64 Bit variable + #define CHIPSET Chipset_t typedef struct { - WORD wPosX; - WORD wPosY; + SWORD nPosX; // 09.12.99 cg, bugfix, is a signed number + SWORD nPosY; // 09.12.99 cg, bugfix, is a signed number BYTE type; - DWORD Port0Size; // real size of module im KB - DWORD Port1Size; // real size of module im KB - DWORD Port2Size; // 27.06.98 cg, not used any more + DWORD Port0Size; // real size of module in KB + DWORD Port1Size; // real size of module in KB + DWORD Port2Size; // real size of module in KB (HP49G only) LPBYTE Port0; LPBYTE Port1; LPBYTE Port2; @@ -49,15 +52,15 @@ typedef struct BOOL carry; WORD crc; -// UINT uUnused1; // 21.02.99 cg, removed, not used - WORD wPort2Crc; // 21.02.99 cg, new, fingerprint of port2 - WORD wUnused1; // 21.02.99 cg, new, dummy to fill rest of old variable -// UINT Port2_Size; // 25.02.99 cg, removed, not used - DWORD dwKdnCycles; // 25.02.99 cg, cpu cycles at start of 1ms key handler - BOOL Port1_Writeable; - BOOL Port2_Writeable; // 30.05.98 cg, not used - UINT Port2_Bank; // 15.12.98 cg, new, save state of GX port2 FF - UINT Port2_NBanks; // 30.05.98 cg, not used + WORD wPort2Crc; // fingerprint of port2 + WORD wRomCrc; // 20.11.99 cg, new, fingerprint of ROM +// QWORD cycles; // 22.11.99 cg, changed, oscillator cycles + DWORD cycles; // 22.11.99 cg, moved, oscillator cycles + DWORD cycles_reserved; // 22.11.99 cg, reserved for MSB of oscillator cycles + DWORD dwKdnCycles; // 22.11.99 cg, moved, cpu cycles at start of 1ms key handler + + UINT Bank_FF; // save state of HP48GX port2 or state of HP49G ROM FF + UINT Port2_NBanks; // not used BYTE cards_status; BYTE IORam[64]; // I/O hardware register UINT IOBase; // address of I/O modules page @@ -70,19 +73,18 @@ typedef struct BYTE t1; DWORD t2; -// DWORD t2_ticks; // 03.03.98 cg, removed, not used - DWORD cycles; // 03.03.98 cg, new, oscillator cycles + BOOL bShutdnWake; // 20.11.99 cg, moved, flag for wake up from SHUTDN mode BYTE Keyboard_Row[9]; WORD IR15X; - UINT Keyboard_State; // 30.05.98 cg, not used + UINT Keyboard_State; // not used signed short loffset; signed int width; UINT boffset; UINT lcounter; - UINT sync; // 24.08.98 cg, not used + UINT sync; // not used BYTE contrast; BOOL dispon; DWORD start1;