From dc12da9a1714365076149d83908e127c5e0d8e6c Mon Sep 17 00:00:00 2001 From: Gwenhael Le Moine Date: Tue, 19 Mar 2024 22:24:30 +0100 Subject: [PATCH] 1999-03-31: Updated to version 1.10 --- BEEP.EXT | 1 + CP_48G3.BMP | Bin 0 -> 217526 bytes CP_48G3.KML | 595 +++++ CP_48S3.BMP | Bin 0 -> 217436 bytes CP_48S3.KML | 587 +++++ Convert.exe | Bin 0 -> 22528 bytes DEFAULTG.BMP | Bin 0 -> 75510 bytes DEFAULTG.KML | 392 +++ DEFAULTS.BMP | Bin 0 -> 75510 bytes DEFAULTS.KML | 392 +++ EMU48.EXE | Bin 0 -> 176128 bytes EMU48.TXT | 29 +- EMU48SP.TXT | 137 ++ Emu48/Emu48.aps | Bin 16856 -> 0 bytes Emu48/Emu48.c | 979 -------- Emu48/Emu48.h | 159 -- Emu48/Emu48.ncb | Bin 91136 -> 0 bytes Emu48/display.c | 483 ---- Emu48/engine.c | 206 -- Emu48/external.c | 31 - Emu48/keyboard.c | 92 - Emu48/mops.c | 988 -------- Emu48/opcodes.h | 2089 ---------------- Emu48/resource.h | 64 - Emu48/timer.c | 208 -- Emu48/types.h | 87 - FLOAT_GX.BMP | Bin 0 -> 151308 bytes FLOAT_GX.KML | 401 ++++ JC.BMP | Bin 0 -> 61558 bytes JC.KML | 364 +++ JEMAC.KML | 710 ++++++ Keyboard.kmi | 352 +++ MkShared.exe | Bin 0 -> 21504 bytes PROBLEMS.TXT | 37 + ROMDUMP.EXE | Bin 0 -> 60928 bytes ROMDUMP.TXT | 27 + ROMDUMP/MainFrm.cpp | 83 - ROMDUMP/MainFrm.h | 31 - ROMDUMP/RES/LCD1.BMP | Bin 17014 -> 0 bytes ROMDUMP/RES/ROMDUMP.ICO | Bin 1078 -> 0 bytes ROMDUMP/RES/ROMDUMP.RC2 | 13 - ROMDUMP/ROMDUMP.H | 43 - ROMDUMP/ROMDump.rc | 239 -- ROMDUMP/Romdump.cpp | 83 - ROMDUMP/Romdump.mak | 392 --- ROMDUMP/Romdump.mdp | Bin 37376 -> 0 bytes ROMDUMP/STDAFX.CPP | 6 - ROMDUMP/STEP1.CPP | 58 - ROMDUMP/STEP1.H | 39 - ROMDUMP/Serial.cpp | 391 --- ROMDUMP/Serial.h | 14 - ROMDUMP/Stdafx.h | 16 - ROMDUMP/Step2.cpp | 226 -- ROMDUMP/Step2.h | 43 - ROMDUMP/about.cpp | 52 - ROMDUMP/about.h | 31 - ROMDUMP/resource.h | 28 - TRUELCD.KMI | 31 + sources/COPYING.TXT | 339 +++ {Convert => sources/Convert}/Convert.mak | 0 {Convert => sources/Convert}/Convert.mdp | Bin {Convert => sources/Convert}/Main.c | 0 sources/EMU48.TXT | 237 ++ sources/Emu48/CHANGES.TXT | 672 ++++++ sources/Emu48/DDESERV.C | 137 ++ sources/Emu48/DISASM.C | 1899 +++++++++++++++ sources/Emu48/DISPLAY.C | 753 ++++++ sources/Emu48/EMU48.C | 1611 +++++++++++++ sources/Emu48/EMU48.DSP | 194 ++ sources/Emu48/EMU48.DSW | 29 + sources/Emu48/EMU48.H | 219 ++ Emu48/Emu48.ico => sources/Emu48/EMU48.ICO | Bin Emu48/Emu48.rc => sources/Emu48/EMU48.RC | 143 +- sources/Emu48/ENGINE.C | 379 +++ sources/Emu48/EXTERNAL.C | 64 + {Emu48 => sources/Emu48}/Emu48.mak | 0 {Emu48 => sources/Emu48}/Emu48.mdp | Bin Emu48/fetch.h => sources/Emu48/FETCH.H | 2 +- Emu48/files.c => sources/Emu48/FILES.C | 212 +- sources/Emu48/KEYBOARD.C | 164 ++ Emu48/kml.c => sources/Emu48/KML.C | 334 ++- Emu48/kml.h => sources/Emu48/KML.H | 0 sources/Emu48/MOPS.C | 1377 +++++++++++ sources/Emu48/OPCODES.H | 2405 +++++++++++++++++++ Emu48/ops.h => sources/Emu48/OPS.H | 253 +- Emu48/pch.c => sources/Emu48/PCH.C | 0 Emu48/pch.h => sources/Emu48/PCH.H | 1 + sources/Emu48/RESOURCE.H | 80 + Emu48/rpl.c => sources/Emu48/RPL.C | 38 +- sources/Emu48/SERIAL.C | 231 ++ sources/Emu48/SERIAL.H | 44 + sources/Emu48/TIMER.C | 403 ++++ sources/Emu48/TYPES.H | 92 + {MkShared => sources/MkShared}/Main.c | 0 {MkShared => sources/MkShared}/MkShared.mak | 0 {MkShared => sources/MkShared}/MkShared.mdp | Bin 96 files changed, 15931 insertions(+), 7610 deletions(-) create mode 100644 BEEP.EXT create mode 100644 CP_48G3.BMP create mode 100644 CP_48G3.KML create mode 100644 CP_48S3.BMP create mode 100644 CP_48S3.KML create mode 100644 Convert.exe create mode 100644 DEFAULTG.BMP create mode 100644 DEFAULTG.KML create mode 100644 DEFAULTS.BMP create mode 100644 DEFAULTS.KML create mode 100644 EMU48.EXE create mode 100644 EMU48SP.TXT delete mode 100644 Emu48/Emu48.aps delete mode 100644 Emu48/Emu48.c delete mode 100644 Emu48/Emu48.h delete mode 100644 Emu48/Emu48.ncb delete mode 100644 Emu48/display.c delete mode 100644 Emu48/engine.c delete mode 100644 Emu48/external.c delete mode 100644 Emu48/keyboard.c delete mode 100644 Emu48/mops.c delete mode 100644 Emu48/opcodes.h delete mode 100644 Emu48/resource.h delete mode 100644 Emu48/timer.c delete mode 100644 Emu48/types.h create mode 100644 FLOAT_GX.BMP create mode 100644 FLOAT_GX.KML create mode 100644 JC.BMP create mode 100644 JC.KML create mode 100644 JEMAC.KML create mode 100644 Keyboard.kmi create mode 100644 MkShared.exe create mode 100644 PROBLEMS.TXT create mode 100644 ROMDUMP.EXE create mode 100644 ROMDUMP.TXT delete mode 100644 ROMDUMP/MainFrm.cpp delete mode 100644 ROMDUMP/MainFrm.h delete mode 100644 ROMDUMP/RES/LCD1.BMP delete mode 100644 ROMDUMP/RES/ROMDUMP.ICO delete mode 100644 ROMDUMP/RES/ROMDUMP.RC2 delete mode 100644 ROMDUMP/ROMDUMP.H delete mode 100644 ROMDUMP/ROMDump.rc delete mode 100644 ROMDUMP/Romdump.cpp delete mode 100644 ROMDUMP/Romdump.mak delete mode 100644 ROMDUMP/Romdump.mdp delete mode 100644 ROMDUMP/STDAFX.CPP delete mode 100644 ROMDUMP/STEP1.CPP delete mode 100644 ROMDUMP/STEP1.H delete mode 100644 ROMDUMP/Serial.cpp delete mode 100644 ROMDUMP/Serial.h delete mode 100644 ROMDUMP/Stdafx.h delete mode 100644 ROMDUMP/Step2.cpp delete mode 100644 ROMDUMP/Step2.h delete mode 100644 ROMDUMP/about.cpp delete mode 100644 ROMDUMP/about.h delete mode 100644 ROMDUMP/resource.h create mode 100644 TRUELCD.KMI create mode 100644 sources/COPYING.TXT rename {Convert => sources/Convert}/Convert.mak (100%) rename {Convert => sources/Convert}/Convert.mdp (100%) rename {Convert => sources/Convert}/Main.c (100%) create mode 100644 sources/EMU48.TXT create mode 100644 sources/Emu48/CHANGES.TXT create mode 100644 sources/Emu48/DDESERV.C create mode 100644 sources/Emu48/DISASM.C create mode 100644 sources/Emu48/DISPLAY.C create mode 100644 sources/Emu48/EMU48.C create mode 100644 sources/Emu48/EMU48.DSP create mode 100644 sources/Emu48/EMU48.DSW create mode 100644 sources/Emu48/EMU48.H rename Emu48/Emu48.ico => sources/Emu48/EMU48.ICO (100%) rename Emu48/Emu48.rc => sources/Emu48/EMU48.RC (59%) create mode 100644 sources/Emu48/ENGINE.C create mode 100644 sources/Emu48/EXTERNAL.C rename {Emu48 => sources/Emu48}/Emu48.mak (100%) rename {Emu48 => sources/Emu48}/Emu48.mdp (100%) rename Emu48/fetch.h => sources/Emu48/FETCH.H (93%) rename Emu48/files.c => sources/Emu48/FILES.C (80%) create mode 100644 sources/Emu48/KEYBOARD.C rename Emu48/kml.c => sources/Emu48/KML.C (78%) rename Emu48/kml.h => sources/Emu48/KML.H (100%) create mode 100644 sources/Emu48/MOPS.C create mode 100644 sources/Emu48/OPCODES.H rename Emu48/ops.h => sources/Emu48/OPS.H (63%) rename Emu48/pch.c => sources/Emu48/PCH.C (100%) rename Emu48/pch.h => sources/Emu48/PCH.H (78%) create mode 100644 sources/Emu48/RESOURCE.H rename Emu48/rpl.c => sources/Emu48/RPL.C (76%) create mode 100644 sources/Emu48/SERIAL.C create mode 100644 sources/Emu48/SERIAL.H create mode 100644 sources/Emu48/TIMER.C create mode 100644 sources/Emu48/TYPES.H rename {MkShared => sources/MkShared}/Main.c (100%) rename {MkShared => sources/MkShared}/MkShared.mak (100%) rename {MkShared => sources/MkShared}/MkShared.mdp (100%) diff --git a/BEEP.EXT b/BEEP.EXT new file mode 100644 index 0000000..006f2ff --- /dev/null +++ b/BEEP.EXT @@ -0,0 +1 @@ +017A6:81B1 diff --git a/CP_48G3.BMP b/CP_48G3.BMP new file mode 100644 index 0000000000000000000000000000000000000000..b8278aac54db1aa2c93b969bf405a69b9f534993 GIT binary patch literal 217526 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%0DRGCNL5Yi$FQ)zD z6Wp?J#&6gKiT9?XJ)2yxvRLl1LNfR;r|AB;yQC*G@*LQpFKFSpsrR-p)l@n<9XuiE zbnz{Lg37yXX5tFmIYquY?qBlsLyBy%q*)){A5W+!{GNt#+#YCtrF!kq6NbgB-Z1g> z&QrO7@C_=wcO9bp4t-;T?qzbnx7p?Bi^r}ealgg& zbK?%~TBms5+}JsRG@B>)pxO?-Z^@;&r}sR5i`(Ow!+gBe%1q>QZ@+)xotHlkLsz8Ln+W4+)0f8+Rl!*v4~#x9*T?u{e}_ITdfBxXI7w#k`QO4$Zaz=I>=oAPv3r zvcfG)^y2Fi(+CES`FbMu{+->~jeVXCn{q&7+Ks1}Zyw@XN;AAGGa?yHgD93J#G6T4(oD0{`EIyE4xKEwzKZ2RF48J8b9r=#Azb*QD1t1;(ML`8DY^PJwagX?{(5jZtgyUz1+r6c~pdKEG~G8!50gFSf2Ln&y*Ora-ApO|KF)wU`23 zCuxq;ewYGX_l9X3p+MK&n6?oLOnQwF3(!fgbJAi-`E|j1VPvKkUw1YV(+iqp*CXq+{D3M@=tXit zN1I`)*V*QmxZ*3&UyoTcpXPY~3bQN7&w$GAO!F%jj0Z?}kGL)2E1r3|Nq<15Mlrug zF8L>yr0TU|enHO4{0b3J0P#fT&D0t1U(0woTF?xr?9QSWUpsQbXz#+ZMmfD+FY0N` zFOiGpm(H+6FI5GhbMuY9_eZ)OWg9oYE?6&}3>clB03C^3oYYoak33gses%O72}IQL z#_|nhaJi&CH>+MWfiQz`*9RUP(@P~Glhoraz0uT^0E|*LgLk>}izWkyOO6NVMT6w| z^#Q&d{V1Ubj6ogR(=QdK7fS`fFoj8D(~Gs2-ICGR+3ypi*ZWDx^v1gE-jB^S2MQN1 z_T$C ztY~)5Z(tZsFg2$mD-MJ1UqKo@#X%_eTEgU@`PE_2dNDGEL(#V=2uAZue*=^G#ZE~u z+7i7mdUQgw`t?YHF)0Ri!{(Pn?j**!pqqUZ>|FG+D^G;cVEE9`OPd)2O)xYJ&a6;t z5;B4g7bEwnj5jb40%v;J{A%b$+T3_Q)AU5%xIr4y^(bx==W??TxBPR_Ysud2d})Om zWkBWp;&H~XL@y%P7WpcOV7 zq?$8me(b-0<>*we(A#Wggk4+#PK9!m;m_^ttOVL{FXj9SM!1kU*K;D6E2CE&Qd5|L z$`7!_kUn$KMq28bUz_DdBdKi7W(})K>FYZ`FAYn5&QpQ1T3au>rzS_faVITYX*Ek& zB_1uyzP>7heu1cMXR*}hocmh4rd}<=GrWD$Yup5w^ct&I?UpdLwG|kVoH9Y*&~^Vm DFk!To literal 0 HcmV?d00001 diff --git a/CP_48G3.KML b/CP_48G3.KML new file mode 100644 index 0000000..01d26b8 --- /dev/null +++ b/CP_48G3.KML @@ -0,0 +1,595 @@ +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 "==========================================================" + Print "" + Print "A few improvements by Sebastien Carlier, the author of Emu48." + Print "Please visit the Emu48 Official Homepage :" + Print "http://www.geocities.com/CapeCanaveral/5948/index.html" + Print "" + Print "Thanks for using Emu48 !" + Print "" + Print "==========================================================" + Title "Casey's Gx with Toolbar and Touch Screen" + Author "Casey Patterson && Sebastien Carlier" + Model "G" + Rom "ROM.48G" + Patch "BEEP.EXT" + Bitmap "cp_48g3.bmp" + Debug 1 +End + +Background + Offset 0 0 + Size 302 517 +End + +Lcd + Zoom 2 + Offset 20 52 + Color 0 255 255 255 + Color 1 255 255 255 + Color 2 255 255 255 + Color 3 255 255 255 + Color 4 255 255 255 + 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 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 15 11 + Offset 41 37 + Down 16 517 +End + +Annunciator 2 + Size 15 11 + Offset 82 37 + Down 32 517 +End + +Annunciator 3 + Size 13 11 + Offset 123 37 + Down 48 517 +End + +Annunciator 4 + Size 15 11 + Offset 164 37 + Down 64 517 +End + +Annunciator 5 + Size 11 11 + Offset 205 37 + Down 80 517 +End + +Annunciator 6 + Size 12 11 + Offset 246 37 + Down 96 517 +End + +Button 11 + Size 37 26 + Offset 8 190 + Down 0 528 + OutIn 1 16 +End +Button 12 + Size 37 26 + Offset 58 190 + Down 0 528 + OutIn 8 16 +End +Button 13 + Size 37 26 + Offset 108 190 + Down 0 528 + OutIn 8 8 +End +Button 14 + Size 37 26 + Offset 158 190 + Down 0 528 + OutIn 8 4 +End +Button 15 + Size 37 26 + Offset 208 190 + Down 0 528 + OutIn 8 2 +End +Button 16 + Size 37 26 + Offset 258 190 + Down 0 528 + OutIn 8 1 +End + +Button 21 + Size 37 26 + Offset 8 227 + Down 37 528 + OutIn 2 16 +End +Button 22 + Size 38 26 + Offset 57 227 + OutIn 7 16 + Down 74 528 +End +Button 23 + Size 37 26 + Offset 108 227 + OutIn 7 8 + Down 112 528 +End +Button 24 + Size 37 26 + Offset 158 227 + OutIn 7 4 + Down 149 528 +End +Button 25 + Size 37 26 + Offset 208 227 + OutIn 7 2 + Down 186 528 +End +Button 26 + Size 37 26 + Offset 258 227 + OutIn 7 1 + Down 223 528 +End + +Button 31 + Size 37 26 + Offset 8 264 + OutIn 0 16 + Down 260 528 +End +Button 32 + Size 37 26 + Offset 58 264 + OutIn 6 16 + Down 0 554 +End +Button 33 + Size 37 26 + Offset 108 264 + OutIn 6 8 + Down 37 554 +End +Button 34 + Size 37 26 + Offset 158 264 + OutIn 6 4 + Down 74 554 +End +Button 35 + Size 37 26 + Offset 208 264 + OutIn 6 2 + Down 111 554 +End +Button 36 + Size 37 26 + Offset 258 264 + OutIn 6 1 + Down 148 554 +End + +Button 41 + Size 37 26 + Offset 8 301 + OutIn 3 16 + Down 185 554 +End +Button 42 + Size 37 26 + Offset 58 301 + OutIn 5 16 + Down 222 554 +End +Button 43 + Size 37 26 + Offset 108 301 + OutIn 5 8 + Down 259 554 +End +Button 44 + Size 37 26 + Offset 158 301 + OutIn 5 4 + Down 0 580 +End +Button 45 + Size 37 26 + Offset 208 301 + OutIn 5 2 + Down 37 580 +End +Button 46 + Size 37 26 + Offset 258 301 + OutIn 5 1 + Down 74 580 +End + +Button 51 + Size 87 26 + Offset 8 338 + OutIn 4 16 + Down 111 580 +End +Button 52 + Size 37 26 + Offset 108 338 + OutIn 4 8 + Down 198 580 +End +Button 53 + Size 37 26 + Offset 158 338 + OutIn 4 4 + Down 235 580 +End +Button 54 + Size 37 26 + Offset 208 338 + OutIn 4 2 + Down 0 606 +End +Button 55 + Size 37 26 + Offset 258 338 + OutIn 4 1 + Down 37 606 +End + +Button 61 + Size 37 26 + Offset 8 375 + OutIn 3 32 + Down 74 606 +End +Button 62 + Size 48 26 + Offset 67 375 + OutIn 3 8 + Down 222 606 +End +Button 63 + Size 48 26 + Offset 127 375 + OutIn 3 4 + Down 0 632 +End +Button 64 + Size 48 26 + Offset 187 375 + OutIn 3 2 + Down 48 632 +End +Button 65 + Size 48 26 + Offset 247 375 + OutIn 3 1 + Down 96 632 +End + +Button 71 + Size 37 26 + Offset 8 412 + OutIn 2 32 + Down 111 606 +End +Button 72 + Size 48 26 + Offset 67 412 + OutIn 2 8 + Down 144 632 +End +Button 73 + Size 48 26 + Offset 127 412 + OutIn 2 4 + Down 192 632 +End +Button 74 + Size 48 26 + Offset 187 412 + OutIn 2 2 + Down 240 632 +End +Button 75 + Size 48 26 + Offset 247 412 + OutIn 2 1 + Down 0 658 +End + +Button 81 + Size 37 26 + Offset 8 449 + OutIn 1 32 + Down 148 606 +End +Button 82 + Size 48 26 + Offset 67 449 + OutIn 1 8 + Down 48 658 +End +Button 83 + Size 48 26 + Offset 127 449 + OutIn 1 4 + Down 96 658 +End +Button 84 + Size 48 26 + Offset 187 449 + OutIn 1 2 + Down 144 658 +End +Button 85 + Size 48 26 + Offset 247 449 + OutIn 1 1 + Down 192 658 +End + +Button 91 + Size 37 26 + Offset 8 486 + OutIn 0 32768 + Down 185 606 +End +Button 92 + Size 48 26 + Offset 67 486 + OutIn 0 8 + Down 240 658 +End +Button 93 + Size 48 26 + Offset 127 486 + OutIn 0 4 + Down 0 684 +End +Button 94 + Size 48 26 + Offset 187 486 + OutIn 0 2 + Down 48 684 +End +Button 95 + Size 48 26 + Offset 247 486 + OutIn 0 1 + Down 96 684 +End + +Button 101 + Type 3 + Size 42 16 + Offset 20 164 + Virtual + OnDown + Press 11 + End + OnUp + Release 11 + End +End +Button 102 + Type 3 + Size 42 16 + Offset 64 164 + Virtual + OnDown + Press 12 + End + OnUp + Release 12 + End +End +Button 103 + Type 3 + Size 42 16 + Offset 108 164 + Virtual + OnDown + Press 13 + End + OnUp + Release 13 + End +End +Button 104 + Type 3 + Size 42 16 + Offset 152 164 + Virtual + OnDown + Press 14 + End + OnUp + Release 14 + End +End +Button 105 + Type 3 + Size 42 16 + Offset 196 164 + Virtual + OnDown + Press 15 + End + OnUp + Release 15 + End +End +Button 106 + Type 3 + Size 42 16 + Offset 240 164 + Virtual + OnDown + Press 16 + End + OnUp + Release 16 + End +End + +Button 107 + Type 4 + Size 262 112 + Offset 20 52 + Down 20 52 + NoHold +End + +Button 108 + Size 10 12 + Offset 288 168 + Down 288 591 + Virtual + OnDown + Press 26 + End + OnUp + Release 26 + End +End + +Button 110 + Type 1 + Size 23 22 + Offset 23 5 + NoHold + OnUp + MenuItem 1 + End +End +Button 111 + Type 1 + Size 23 22 + Offset 46 5 + NoHold + OnUp + MenuItem 2 + End +End +Button 112 + Type 1 + Size 23 22 + Offset 69 5 + NoHold + OnUp + MenuItem 3 + End +End +Button 113 + Type 1 + Size 23 22 + Offset 97 5 + NoHold + OnUp + MenuItem 6 + End +End +Button 114 + Type 1 + Size 23 22 + Offset 125 5 + NoHold + OnUp + MenuItem 8 + End +End +Button 115 + Type 1 + Size 23 22 + Offset 148 5 + NoHold + OnUp + MenuItem 7 + End +End +Button 116 + Type 1 + Size 23 22 + Offset 171 5 + NoHold + OnUp + MenuItem 17 + End +End +Button 117 + Type 1 + Size 23 22 + Offset 199 5 + NoHold + OnUp + MenuItem 9 + End +End +Button 118 + Type 1 + Size 23 22 + Offset 222 5 + NoHold + OnUp + MenuItem 10 + End +End +Button 119 + Type 1 + Size 23 22 + Offset 250 5 + NoHold + OnUp + MenuItem 11 + End +End + +Include "Keyboard.kmi" diff --git a/CP_48S3.BMP b/CP_48S3.BMP new file mode 100644 index 0000000000000000000000000000000000000000..2ffea41e539feaa60772b0c7ac46c5a793f445ab GIT binary patch literal 217436 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 Y73)fHCAu;eWiRqjU%$ToM`_^y0^R`+=Kufz literal 0 HcmV?d00001 diff --git a/DEFAULTG.BMP b/DEFAULTG.BMP new file mode 100644 index 0000000000000000000000000000000000000000..e63f0d603bcd4b9c4c6b924ae0233e26a72854ff GIT binary patch literal 75510 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 VqA5*Ud?hN5>MXvFqA5+f`9E>bBg+5) literal 0 HcmV?d00001 diff --git a/DEFAULTG.KML b/DEFAULTG.KML new file mode 100644 index 0000000..4031e83 --- /dev/null +++ b/DEFAULTG.KML @@ -0,0 +1,392 @@ +Global + Title "Emu48's Default Faceplate for HP48G/GX" + Author "Sebastien Carlier" + Model "G" + Rom "ROM.48G" + Patch "BEEP.EXT" + Debug 0 + Bitmap "DEFAULTG.BMP" +End + +Background + Offset 0 0 + Size 302 485 +End + +Lcd + Zoom 2 + Offset 20 20 + Color 0 255 255 255 + Color 1 255 255 255 + Color 2 255 255 255 + Color 3 255 255 255 + Color 4 255 255 255 + 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 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 15 11 + Offset 41 4 + Down 16 485 +End + +Annunciator 2 + Size 15 11 + Offset 82 4 + Down 32 485 +End + +Annunciator 3 + Size 13 11 + Offset 123 4 + Down 48 485 +End + +Annunciator 4 + Size 15 11 + Offset 164 4 + Down 64 485 +End + +Annunciator 5 + Size 11 11 + Offset 205 4 + Down 80 485 +End + +Annunciator 6 + Size 12 11 + Offset 246 4 + Down 96 485 +End + +Button 11 + Type 1 + Size 36 25 + Offset 8 158 + OutIn 1 16 +End +Button 12 + Type 1 + Size 36 25 + Offset 58 158 + OutIn 8 16 +End +Button 13 + Type 1 + Size 36 25 + Offset 108 158 + OutIn 8 8 +End +Button 14 + Type 1 + Size 36 25 + Offset 158 158 + OutIn 8 4 +End +Button 15 + Type 1 + Size 36 25 + Offset 208 158 + OutIn 8 2 +End +Button 16 + Type 1 + Size 36 25 + Offset 258 158 + OutIn 8 1 +End + +Button 21 + Type 1 + Size 36 25 + Offset 8 195 + OutIn 2 16 +End +Button 22 + Type 1 + Size 36 25 + Offset 58 195 + OutIn 7 16 +End +Button 23 + Type 1 + Size 36 25 + Offset 108 195 + OutIn 7 8 +End +Button 24 + Type 1 + Size 36 25 + Offset 158 195 + OutIn 7 4 +End +Button 25 + Type 1 + Size 36 25 + Offset 208 195 + OutIn 7 2 +End +Button 26 + Type 1 + Size 36 25 + Offset 258 195 + OutIn 7 1 +End + +Button 31 + Type 1 + Size 36 25 + Offset 8 232 + OutIn 0 16 +End +Button 32 + Type 1 + Size 36 25 + Offset 58 232 + OutIn 6 16 +End +Button 33 + Type 1 + Size 36 25 + Offset 108 232 + OutIn 6 8 +End +Button 34 + Type 1 + Size 36 25 + Offset 158 232 + OutIn 6 4 +End +Button 35 + Type 1 + Size 36 25 + Offset 208 232 + OutIn 6 2 +End +Button 36 + Type 1 + Size 36 25 + Offset 258 232 + OutIn 6 1 +End + +Button 41 + Type 1 + Size 36 25 + Offset 8 269 + OutIn 3 16 +End +Button 42 + Type 1 + Size 36 25 + Offset 58 269 + OutIn 5 16 +End +Button 43 + Type 1 + Size 36 25 + Offset 108 269 + OutIn 5 8 +End +Button 44 + Type 1 + Size 36 25 + Offset 158 269 + OutIn 5 4 +End +Button 45 + Type 1 + Size 36 25 + Offset 208 269 + OutIn 5 2 +End +Button 46 + Type 1 + Size 36 25 + Offset 258 269 + OutIn 5 1 +End + +Button 51 + Type 1 + Size 86 25 + Offset 8 306 + OutIn 4 16 +End +Button 52 + Type 1 + Size 36 25 + Offset 108 306 + OutIn 4 8 +End +Button 53 + Type 1 + Size 36 25 + Offset 158 306 + OutIn 4 4 +End +Button 54 + Type 1 + Size 36 25 + Offset 208 306 + OutIn 4 2 +End +Button 55 + Type 1 + Size 36 25 + Offset 258 306 + OutIn 4 1 +End + +Button 61 + Type 1 + Size 36 25 + Offset 8 343 + OutIn 3 32 +End +Button 62 + Type 1 + Size 47 25 + Offset 67 343 + OutIn 3 8 +End +Button 63 + Type 1 + Size 47 25 + Offset 127 343 + OutIn 3 4 +End +Button 64 + Type 1 + Size 47 25 + Offset 187 343 + OutIn 3 2 +End +Button 65 + Type 1 + Size 47 25 + Offset 247 343 + OutIn 3 1 +End + +Button 71 + Type 1 + Size 36 25 + Offset 8 380 + OutIn 2 32 +End +Button 72 + Type 1 + Size 47 25 + Offset 67 380 + OutIn 2 8 +End +Button 73 + Type 1 + Size 47 25 + Offset 127 380 + OutIn 2 4 +End +Button 74 + Type 1 + Size 47 25 + Offset 187 380 + OutIn 2 2 +End +Button 75 + Type 1 + Size 47 25 + Offset 247 380 + OutIn 2 1 +End + +Button 81 + Type 1 + Size 36 25 + Offset 8 417 + OutIn 1 32 +End +Button 82 + Type 1 + Size 47 25 + Offset 67 417 + OutIn 1 8 +End +Button 83 + Type 1 + Size 47 25 + Offset 127 417 + OutIn 1 4 +End +Button 84 + Type 1 + Size 47 25 + Offset 187 417 + OutIn 1 2 +End +Button 85 + Type 1 + Size 47 25 + Offset 247 417 + OutIn 1 1 +End + +Button 91 + Type 1 + Size 36 25 + Offset 8 454 + OutIn 0 32768 +End +Button 92 + Type 1 + Size 47 25 + Offset 67 454 + OutIn 0 8 +End +Button 93 + Type 1 + Size 47 25 + Offset 127 454 + OutIn 0 4 +End +Button 94 + Type 1 + Size 47 25 + Offset 187 454 + OutIn 0 2 +End +Button 95 + Type 1 + Size 47 25 + Offset 247 454 + OutIn 0 1 +End + +Include "Keyboard.kmi" diff --git a/DEFAULTS.BMP b/DEFAULTS.BMP new file mode 100644 index 0000000000000000000000000000000000000000..89a8d5ea9c1d2c301b45ba7d8be69cf5f2b49e9e GIT binary patch literal 75510 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 literal 0 HcmV?d00001 diff --git a/DEFAULTS.KML b/DEFAULTS.KML new file mode 100644 index 0000000..3b2c525 --- /dev/null +++ b/DEFAULTS.KML @@ -0,0 +1,392 @@ +Global + Title "Emu48's Default Faceplate for HP48S/SX" + Author "Sebastien Carlier" + Model "S" + Rom "ROM.48S" + Patch "BEEP.EXT" + Debug 0 + Bitmap "DEFAULTS.BMP" +End + +Background + Offset 0 0 + Size 302 485 +End + +Lcd + Zoom 2 + Offset 20 20 + Color 0 255 255 255 + 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 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 15 11 + Offset 41 4 + Down 16 485 +End + +Annunciator 2 + Size 15 11 + Offset 82 4 + Down 32 485 +End + +Annunciator 3 + Size 13 11 + Offset 123 4 + Down 48 485 +End + +Annunciator 4 + Size 15 11 + Offset 164 4 + Down 64 485 +End + +Annunciator 5 + Size 11 11 + Offset 205 4 + Down 80 485 +End + +Annunciator 6 + Size 12 11 + Offset 246 4 + Down 96 485 +End + +Button 11 + Type 1 + Size 36 25 + Offset 8 158 + OutIn 1 16 +End +Button 12 + Type 1 + Size 36 25 + Offset 58 158 + OutIn 8 16 +End +Button 13 + Type 1 + Size 36 25 + Offset 108 158 + OutIn 8 8 +End +Button 14 + Type 1 + Size 36 25 + Offset 158 158 + OutIn 8 4 +End +Button 15 + Type 1 + Size 36 25 + Offset 208 158 + OutIn 8 2 +End +Button 16 + Type 1 + Size 36 25 + Offset 258 158 + OutIn 8 1 +End + +Button 21 + Type 1 + Size 36 25 + Offset 8 195 + OutIn 2 16 +End +Button 22 + Type 1 + Size 36 25 + Offset 58 195 + OutIn 7 16 +End +Button 23 + Type 1 + Size 36 25 + Offset 108 195 + OutIn 7 8 +End +Button 24 + Type 1 + Size 36 25 + Offset 158 195 + OutIn 7 4 +End +Button 25 + Type 1 + Size 36 25 + Offset 208 195 + OutIn 7 2 +End +Button 26 + Type 1 + Size 36 25 + Offset 258 195 + OutIn 7 1 +End + +Button 31 + Type 1 + Size 36 25 + Offset 8 232 + OutIn 0 16 +End +Button 32 + Type 1 + Size 36 25 + Offset 58 232 + OutIn 6 16 +End +Button 33 + Type 1 + Size 36 25 + Offset 108 232 + OutIn 6 8 +End +Button 34 + Type 1 + Size 36 25 + Offset 158 232 + OutIn 6 4 +End +Button 35 + Type 1 + Size 36 25 + Offset 208 232 + OutIn 6 2 +End +Button 36 + Type 1 + Size 36 25 + Offset 258 232 + OutIn 6 1 +End + +Button 41 + Type 1 + Size 36 25 + Offset 8 269 + OutIn 3 16 +End +Button 42 + Type 1 + Size 36 25 + Offset 58 269 + OutIn 5 16 +End +Button 43 + Type 1 + Size 36 25 + Offset 108 269 + OutIn 5 8 +End +Button 44 + Type 1 + Size 36 25 + Offset 158 269 + OutIn 5 4 +End +Button 45 + Type 1 + Size 36 25 + Offset 208 269 + OutIn 5 2 +End +Button 46 + Type 1 + Size 36 25 + Offset 258 269 + OutIn 5 1 +End + +Button 51 + Type 1 + Size 86 25 + Offset 8 306 + OutIn 4 16 +End +Button 52 + Type 1 + Size 36 25 + Offset 108 306 + OutIn 4 8 +End +Button 53 + Type 1 + Size 36 25 + Offset 158 306 + OutIn 4 4 +End +Button 54 + Type 1 + Size 36 25 + Offset 208 306 + OutIn 4 2 +End +Button 55 + Type 1 + Size 36 25 + Offset 258 306 + OutIn 4 1 +End + +Button 61 + Type 1 + Size 36 25 + Offset 8 343 + OutIn 3 32 +End +Button 62 + Type 1 + Size 47 25 + Offset 67 343 + OutIn 3 8 +End +Button 63 + Type 1 + Size 47 25 + Offset 127 343 + OutIn 3 4 +End +Button 64 + Type 1 + Size 47 25 + Offset 187 343 + OutIn 3 2 +End +Button 65 + Type 1 + Size 47 25 + Offset 247 343 + OutIn 3 1 +End + +Button 71 + Type 1 + Size 36 25 + Offset 8 380 + OutIn 2 32 +End +Button 72 + Type 1 + Size 47 25 + Offset 67 380 + OutIn 2 8 +End +Button 73 + Type 1 + Size 47 25 + Offset 127 380 + OutIn 2 4 +End +Button 74 + Type 1 + Size 47 25 + Offset 187 380 + OutIn 2 2 +End +Button 75 + Type 1 + Size 47 25 + Offset 247 380 + OutIn 2 1 +End + +Button 81 + Type 1 + Size 36 25 + Offset 8 417 + OutIn 1 32 +End +Button 82 + Type 1 + Size 47 25 + Offset 67 417 + OutIn 1 8 +End +Button 83 + Type 1 + Size 47 25 + Offset 127 417 + OutIn 1 4 +End +Button 84 + Type 1 + Size 47 25 + Offset 187 417 + OutIn 1 2 +End +Button 85 + Type 1 + Size 47 25 + Offset 247 417 + OutIn 1 1 +End + +Button 91 + Type 1 + Size 36 25 + Offset 8 454 + OutIn 0 32768 +End +Button 92 + Type 1 + Size 47 25 + Offset 67 454 + OutIn 0 8 +End +Button 93 + Type 1 + Size 47 25 + Offset 127 454 + OutIn 0 4 +End +Button 94 + Type 1 + Size 47 25 + Offset 187 454 + OutIn 0 2 +End +Button 95 + Type 1 + Size 47 25 + Offset 247 454 + OutIn 0 1 +End + +Include "Keyboard.kmi" diff --git a/EMU48.EXE b/EMU48.EXE new file mode 100644 index 0000000000000000000000000000000000000000..97698a8082dfa696c0852b314abb6fabedc71da6 GIT binary patch literal 176128 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

n+jNiU9y| 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 literal 0 HcmV?d00001 diff --git a/EMU48.TXT b/EMU48.TXT index 95eb475..104c4bb 100644 --- a/EMU48.TXT +++ b/EMU48.TXT @@ -1,7 +1,7 @@ - Emu48 - A freeware HP48 Emulator for Windows 95 and NT + Emu48 - A freeware HP48 Emulator for Windows 95, 98 and NT @@ -9,20 +9,16 @@ * 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 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. -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 +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. 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. + 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. @@ -39,7 +35,7 @@ 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. + 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 @@ -92,7 +88,7 @@ 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 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. @@ -189,7 +185,11 @@ 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 : - http://www.geocities.com/CapeCanaveral/5948/index.html + http://www.epita.fr/~sebc/Emu48 + +Service packs are maintained by Christoph Gießelink : + + http://privat.swol.de/ChristophGiesselink/ Other graphics and scripts are available at Casey's Emu48 Graphics Page : http://www.gulftel.com/~pattersc/emu48/ @@ -231,7 +231,6 @@ Paper Mail: E-Mail: sebc@epita.fr - sebc@anet.fr Homepage: - http://www.geocities.com/CapeCanaveral/5948/index.html + http://www.epita.fr/~sebc diff --git a/EMU48SP.TXT b/EMU48SP.TXT new file mode 100644 index 0000000..33c9168 --- /dev/null +++ b/EMU48SP.TXT @@ -0,0 +1,137 @@ + + + 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/Emu48/Emu48.aps b/Emu48/Emu48.aps deleted file mode 100644 index be01e5c47c926212fc376e1ee813419d20c645f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16856 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 bmessage == WM_QUIT) return TRUE; - TranslateMessage(msg); - DispatchMessage(msg); - } - return FALSE; -} - - -int PASCAL WinMain(HANDLE hInst, HANDLE hPrevInst, LPSTR lpCmdLine, int nCmdShow) -{ - MSG msg; - WNDCLASS wc; - RECT rectWindow; - - hApp = hInst; - - wc.style = CS_BYTEALIGNCLIENT; - wc.lpfnWndProc = (WNDPROC)MainWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInst; - wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_EMU48)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = NULL; - wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU); - wc.lpszClassName = "CEmu48"; - - if (!RegisterClass(&wc)) - { - AbortMessage( - "CEmu48 class registration failed.\n" - "This application will now terminate."); - return FALSE; - } - - // Create window - - rectWindow.left = 0; - rectWindow.top = 0; - rectWindow.right = 256; - rectWindow.bottom = 0; - AdjustWindowRect(&rectWindow, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, TRUE); - - hWnd = CreateWindow("CEmu48", "Emu48", - WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, - CW_USEDEFAULT, CW_USEDEFAULT, - rectWindow.right - rectWindow.left, - rectWindow.bottom - rectWindow.top, - NULL,NULL,hApp,NULL - ); - - if (hWnd == NULL) - { - AbortMessage("Window creation failed.\n"); - return FALSE; - } - - ShowWindow(hWnd, nCmdShow); - - if (FlushMessages(&msg)) return msg.wParam; - - // initialization - - GetCurrentDirectory(260, szCurrentDirectory); - - ReadSettings(); - - szNoTitle = "Emu48 "VERSION; - - UpdateWindowStatus(); - - nState = 1; // thread starts in an invalid state - nNextState = 1; - hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, NULL, 0, &lThreadId); - if (hThread == NULL) - { - AbortMessage("Thread creation failed."); - return FALSE; - } - - MapPort2(szPort2Filename); - - if (lpCmdLine[0]) - { - CHAR szTemp[256] = "Loading "; - strcat(szTemp, lpCmdLine); - SetWindowTitle(szTemp); - if (FlushMessages(&msg)) return msg.wParam; - if (OpenDocument(lpCmdLine)) - goto start; - } - - GetPrivateProfileString("Files","LastDocument",NULL,szBufferFilename,260,EMU48_INI); - if (szBufferFilename[0]) - { - CHAR szTemp[256] = "Loading "; - strcat(szTemp, szBufferFilename); - SetWindowTitle(szTemp); - if (FlushMessages(&msg)) return msg.wParam; - if (OpenDocument(szBufferFilename)) - goto start; - } - - SetWindowTitle("New Document"); - if (FlushMessages(&msg)) return msg.wParam; - if (NewDocument()) - { - SetWindowTitle("Untitled"); - goto start; - } - - ResetDocument(); - SetWindowTitle(NULL); - -start: - if (pbyRom) SwitchToState(0); - - while (GetMessage(&msg, NULL, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - SwitchToState(2); - ResetDocument(); - ResetBackup(); - cCurrentRomType = 0; - KillKML(); - UnmapPort2(); - - return msg.wParam; - UNREFERENCED_PARAMETER(lpCmdLine); - UNREFERENCED_PARAMETER(hPrevInst); -} diff --git a/Emu48/Emu48.h b/Emu48/Emu48.h deleted file mode 100644 index 2c0d8db..0000000 --- a/Emu48/Emu48.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Emu48.h - * - * This file is part of Emu48 - * - * Copyright (C) 1995 Sebastien Carlier - * - */ - -#include "types.h" - -// Emu48.c -extern HPALETTE hPalette; -extern LPSTR szTitle; -extern HANDLE hApp; -extern HWND hWnd; -extern HDC hWindowDC; -extern BOOL bPort2IsShared; -extern BOOL bAlwaysDisplayLog; -extern UINT uTimer1Period; -extern VOID SetWindowTitle(LPSTR szString); -extern VOID UpdateWindowStatus(); - -// Display.c -extern UINT nBackgroundX; -extern UINT nBackgroundY; -extern UINT nBackgroundW; -extern UINT nBackgroundH; -extern UINT nLcdX; -extern UINT nLcdY; -extern BOOL bLcdDoubled; -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(); -extern VOID DestroyLcdBitmap(); -extern BOOL CreateMainBitmap(LPSTR szFilename); -extern VOID DestroyMainBitmap(); -extern VOID UpdateDisplayPointers(); -extern VOID UpdateMainDisplay(); -extern VOID UpdateMenuDisplay(); -extern VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s); -extern VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s); -extern VOID UpdateAnnunciators(); -extern VOID ResizeWindow(); - -// Engine.c -extern BOOL bInterrupt; -extern UINT nState; -extern UINT nNextState; -extern HANDLE hThread; -extern CHIPSET Chipset; -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); - -// Files.c -extern char szEmu48Directory[260]; -extern char szCurrentDirectory[260]; -extern char szCurrentKml[260]; -extern char szBackupKml[260]; -extern char szCurrentFilename[260]; -extern char szBackupFilename[260]; -extern char szBufferFilename[260]; -extern char szPort2Filename[260]; -extern LPBYTE pbyRom; -extern DWORD dwRomSize; -extern char cCurrentRomType; -extern LPBYTE pbyPort2; -extern BOOL bPort2Writeable; -extern BOOL bPort2IsShared; -extern DWORD dwPort2Mask; -extern UINT nPort2Bank; -extern BOOL bBackup; -extern BOOL MapRom(LPCSTR szFilename); -extern VOID UnmapRom(); -extern BOOL MapPort2(LPCSTR szFilename); -extern VOID UnmapPort2(); -extern BOOL PatchRom(LPCSTR szFilename); -extern VOID ResetDocument(); -extern BOOL NewDocument(); -extern BOOL OpenDocument(LPCSTR szFilename); -extern BOOL SaveDocument(); -extern BOOL SaveDocumentAs(LPCTSTR szFilename); -extern BOOL SaveBackup(); -extern BOOL RestoreBackup(); -extern BOOL ResetBackup(); -extern BOOL GetOpenFilename(); -extern BOOL GetSaveAsFilename(); -extern BOOL GetLoadObjectFilename(); -extern BOOL GetSaveObjectFilename(); -extern BOOL LoadObject(LPCSTR szFilename); -extern BOOL SaveObject(LPCSTR szFilename); -extern HBITMAP LoadBitmapFile(LPCSTR szFilename); - -// Timer.c -extern BOOL bAccurateTimer; -extern UINT uT1Period; -extern VOID StartTimers(); -extern VOID StopTimers(); -extern DWORD ReadT2(); -extern VOID SetT2(DWORD dwValue); -extern BYTE ReadT1(); -extern VOID SetT1(BYTE byValue); - -// MOps.c -extern LPBYTE RMap[256]; -extern LPBYTE WMap[256]; -extern VOID Map(BYTE a, BYTE b); -extern VOID Config(); -extern VOID Uncnfg(); -extern VOID Reset(); -extern VOID C_Eq_Id(); -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); -extern VOID Nwrite2(BYTE *a, DWORD d); -extern VOID Nread5(BYTE *a, DWORD d); -extern VOID Nwrite5(BYTE *a, DWORD d); -extern BYTE Read2(DWORD d); -extern DWORD Read5(DWORD d); -extern VOID Write5(DWORD d, DWORD n); -extern VOID ReadIO(BYTE *a, DWORD b, DWORD s); -extern VOID WriteIO(BYTE *a, DWORD b, DWORD s); - -// Keyboard.c -extern WORD Keyboard_GetIR(); -extern VOID ScanKeyboard(); -extern VOID KeyboardEvent(BOOL bPress, UINT out, UINT in); - -// RPL.c -extern DWORD RPL_SkipOb(DWORD d); -extern DWORD RPL_ObjectSize(BYTE *o); -extern DWORD RPL_CreateTemp(DWORD l); -extern DWORD RPL_Pick(UINT l); -extern VOID RPL_Replace(DWORD n); -extern VOID RPL_Push(DWORD n); - -// in External.c -extern VOID External(CHIPSET* w); - -// Message Boxes -static __inline int InfoMessage(LPCSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND);} -static __inline int AbortMessage(LPCSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);} -static __inline int YesNoMessage(LPCSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_YESNO|MB_ICONEXCLAMATION|MB_SETFOREGROUND);} -static __inline int YesNoCancelMessage(LPCSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_YESNOCANCEL|MB_ICONEXCLAMATION|MB_SETFOREGROUND);} - -// Missing Win32 API calls -static __inline LPSTR DuplicateString(LPCSTR szString) -{ - UINT uLength = strlen(szString) + 1; - LPSTR szDup = LocalAlloc(0,uLength+1); - CopyMemory(szDup,szString,uLength); - return szDup; -} diff --git a/Emu48/Emu48.ncb b/Emu48/Emu48.ncb deleted file mode 100644 index 872d0f60b252629e189e4db69fb3418b1f3f0f4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91136 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 diff --git a/Emu48/display.c b/Emu48/display.c deleted file mode 100644 index a16d224..0000000 --- a/Emu48/display.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * display.c - * - * This file is part of Emu48 - * - * Copyright (C) 1995 Sebastien Carlier - * - */ -#include "pch.h" -#include "resource.h" -#include "Emu48.h" -#include "kml.h" - -#define LCD1_ROW 144 -#define LCD2_ROW 288 - -UINT nBackgroundX = 0; -UINT nBackgroundY = 0; -UINT nBackgroundW = 0; -UINT nBackgroundH = 0; -UINT nLcdX = 0; -UINT nLcdY = 0; -BOOL bLcdDoubled = FALSE; -LPBYTE pbyLcd; -HDC hLcdDC; -HDC hMainDC; -static HBITMAP hLcdBitmap; -static HBITMAP hMainBitmap; -static HBITMAP hOldLcdBitmap; -static HBITMAP hOldMainBitmap; - -#define B 0xFFFFFF -#define W 0x000000 -static struct -{ - BITMAPINFOHEADER Lcd_bmih; - DWORD dwColor[32]; -} bmiLcd = -{ - {0x28,0/*x*/,0/*y*/,1,8,BI_RGB,0,0,0,32,0}, - { - B,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W, - W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W - } -}; -#undef B -#undef W - -static DWORD Pattern4[16]; -static DWORD Pattern2[4]; - -VOID UpdateContrast(BYTE byContrast) -{ - if (bLcdDoubled) - { - BYTE c = byContrast; - Pattern2[0] = 0; - Pattern2[1] = (c<<8)|(c); - Pattern2[2] = (c<<24)|(c<<16); - Pattern2[3] = (c<<24)|(c<<16)|(c<<8)|(c); - } - else - { - DWORD c = (DWORD)byContrast; - FillMemory(Pattern4, 16*sizeof(DWORD), 0); - Pattern4[0x1] = c; - Pattern4[0x3] = c; - Pattern4[0x5] = c; - Pattern4[0x7] = c; - Pattern4[0x9] = c; - Pattern4[0xB] = c; - Pattern4[0xD] = c; - Pattern4[0xF] = c; - c<<=8; - Pattern4[0x2] |= c; - Pattern4[0x3] |= c; - Pattern4[0x6] |= c; - Pattern4[0x7] |= c; - Pattern4[0xA] |= c; - Pattern4[0xB] |= c; - Pattern4[0xE] |= c; - Pattern4[0xF] |= c; - c<<=8; - Pattern4[0x4] |= c; - Pattern4[0x5] |= c; - Pattern4[0x6] |= c; - Pattern4[0x7] |= c; - Pattern4[0xC] |= c; - Pattern4[0xD] |= c; - Pattern4[0xE] |= c; - Pattern4[0xF] |= c; - c<<=8; - Pattern4[0x8] |= c; - Pattern4[0x9] |= c; - Pattern4[0xA] |= c; - Pattern4[0xB] |= c; - Pattern4[0xC] |= c; - Pattern4[0xD] |= c; - Pattern4[0xE] |= c; - Pattern4[0xF] |= c; - } - return; -} - -VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue) -{ - bmiLcd.dwColor[nId&0x1F] = (nRed&0xFF)|((nGreen&0xFF)<<8)|((nBlue&0xFF)<<16); - return; -} - -VOID CreateLcdBitmap() -{ - // create LCD bitmap - if (bLcdDoubled) - { - bmiLcd.Lcd_bmih.biWidth = LCD2_ROW; - bmiLcd.Lcd_bmih.biHeight = -128; - } - else - { - bmiLcd.Lcd_bmih.biWidth = LCD1_ROW; - bmiLcd.Lcd_bmih.biHeight = -64; - } - hLcdDC = CreateCompatibleDC(hWindowDC); - hLcdBitmap = CreateDIBSection(hLcdDC, (BITMAPINFO*)&bmiLcd, - DIB_RGB_COLORS, (LPVOID*)&pbyLcd, NULL, 0); - hOldLcdBitmap = SelectObject(hLcdDC, hLcdBitmap); - UpdateContrast(0x10); -} - -VOID DestroyLcdBitmap() -{ - if (hLcdDC != NULL) - { - // destroy LCD bitmap - SelectObject(hLcdDC, hOldLcdBitmap); - DeleteObject(hLcdBitmap); - DeleteDC(hLcdDC); - hLcdDC = NULL; - hLcdBitmap = NULL; - hOldLcdBitmap = NULL; - } - return; -} - -BOOL CreateMainBitmap(LPSTR szFilename) -{ - hMainDC = CreateCompatibleDC(hWindowDC); - hMainBitmap = LoadBitmapFile(szFilename); - if (hMainBitmap == NULL) - { - DeleteDC(hMainDC); - return FALSE; - } - hOldMainBitmap = SelectObject(hMainDC, hMainBitmap); - SelectPalette(hMainDC, hPalette, FALSE); - return TRUE; -} - -VOID DestroyMainBitmap() -{ - if (hMainDC != NULL) - { - // destroy Main bitmap - SelectObject(hMainDC, hOldMainBitmap); - DeleteObject(hMainBitmap); - DeleteDC(hMainDC); - hMainDC = NULL; - hMainBitmap = NULL; - hOldMainBitmap = NULL; - } - return; -} - -//**************** -//* -//* LCD functions -//* -//**************** - -VOID UpdateDisplayPointers() -{ - if (Chipset.boffset&4) - { - Chipset.width = Chipset.loffset + 36; - } - else - { - Chipset.width = Chipset.loffset + 34; - } - Chipset.end1 = Chipset.start1 + (Chipset.lcounter+1)*Chipset.width; - if (Chipset.end1 < Chipset.start1) - { - Chipset.start12 = Chipset.end1; - Chipset.end1 = Chipset.start1; - } - else - { - Chipset.start12 = Chipset.start1; - } - Chipset.end2 = Chipset.start2 + (63 - Chipset.lcounter)*34; -} - -static BYTE Buf[36]; -static BOOL bScreenIsClean = FALSE; - -VOID UpdateMainDisplay() -{ - UINT x, y; - DWORD d = Chipset.start1; - BYTE *p = pbyLcd; - - if (!Chipset.dispon) - { - if (!bScreenIsClean) - { - bScreenIsClean = TRUE; - if (bLcdDoubled) - FillMemory(pbyLcd, LCD2_ROW*64, 0); - else - FillMemory(pbyLcd, LCD1_ROW*64, 0); - } - return; - } - bScreenIsClean = FALSE; - if (bLcdDoubled) - { - for (y=0; y<=Chipset.lcounter; y++) - { - Npeek(Buf,d,36); - for (x=0; x<36; x++,p+=8) - { - *((DWORD*)(p+0))=Pattern2[Buf[x]&3]; - *((DWORD*)(p+4))=Pattern2[Buf[x]>>2]; - } - CopyMemory(p, p-LCD2_ROW, LCD2_ROW); - p+=LCD2_ROW; - d+=Chipset.width; - } - BitBlt(hWindowDC, nLcdX, nLcdY, 262, (Chipset.lcounter+1)*2, hLcdDC, Chipset.boffset*2, 0, SRCCOPY); - } - else - { - for (y=0; y<=Chipset.lcounter; y++) - { - Npeek(Buf,d,36); - for (x=0; x<36; x++,p+=4) *((DWORD*)p)=Pattern4[Buf[x]]; - d+=Chipset.width; - } - BitBlt(hWindowDC, nLcdX, nLcdY, 131, Chipset.lcounter+1, hLcdDC, Chipset.boffset, 0, SRCCOPY); - } -} - -VOID UpdateMenuDisplay() -{ - UINT x, y; - DWORD d = Chipset.start2; - - if (!Chipset.dispon) return; - if (Chipset.lcounter==0x3F) return; // menu disabled - if (bLcdDoubled) - { - BYTE *p = pbyLcd + ((Chipset.lcounter+1)*2*LCD2_ROW); - for (y=Chipset.lcounter+1; y<64; y++) - { - Npeek(Buf,d,36); - for (x=0; x<36; x++,p+=8) - { - *((DWORD*)(p+0))=Pattern2[Buf[x]&3]; - *((DWORD*)(p+4))=Pattern2[Buf[x]>>2]; - } - CopyMemory(p, p-LCD2_ROW, LCD2_ROW); - p+=LCD2_ROW; - d+=34; - } - BitBlt(hWindowDC, nLcdX, nLcdY+(Chipset.lcounter+1)*2, 262, (63-Chipset.lcounter)*2, hLcdDC, 0, (Chipset.lcounter+1)*2, SRCCOPY); - } - else - { - BYTE *p = pbyLcd + (Chipset.lcounter+1)*LCD1_ROW; - for (y=Chipset.lcounter+1; y<64; y++) - { - Npeek(Buf,d,36); - for (x=0; x<36; x++,p+=4) *((DWORD*)p)=Pattern4[Buf[x]]; - d+=34; - } - BitBlt(hWindowDC, nLcdX, nLcdY+(Chipset.lcounter+1), 131, 63-Chipset.lcounter, hLcdDC, 0, Chipset.lcounter+1, SRCCOPY); - } - return; -} - -VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s) -{ - 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; - if ((x0*4+Chipset.boffset)>=131) return; - if (bLcdDoubled) - { - 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; - } - if (y0!=y) - { - y++; - y0<<=1; y<<=1; - BitBlt(hWindowDC, nLcdX, nLcdY+y0, 262, y-y0, hLcdDC, Chipset.boffset*2, y0, SRCCOPY); - } - else - { - x0<<=3; x<<=3; - if (x>262) x=262; - y0<<=1; y<<=1; - BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, 2, hLcdDC, x0+Chipset.boffset*2, y0, SRCCOPY); - } - } - else - { - 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++; - } - if (y0!=y) - { - BitBlt(hWindowDC, nLcdX, nLcdY+y0, 131, y-y0+1, hLcdDC, Chipset.boffset, y0, SRCCOPY); - } - else - { - x0<<=2; x<<=2; - if (x>131) x=131; - BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, 1, hLcdDC, x0+Chipset.boffset, y0, SRCCOPY); - } - } - return; -} - -VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s) -{ - UINT x0, x; - UINT y0, y; - DWORD *p; - - if (Chipset.width<0) return; - if (Chipset.lcounter==0x3F) return; // menu disabled - d -= Chipset.start2; - y0 = y = (d / 34) + (Chipset.lcounter+1); - x0 = x = d % 34; - if ((x0*4)>=131) return; - if (bLcdDoubled) - { - p = (DWORD*)(pbyLcd + y0*LCD2_ROW*2 + x0*8); - while (s--) - { - if (x<34) - { - p[72] = p[0] = Pattern2[(*a)&3]; - p[73] = p[1] = Pattern2[(*a)>>2]; - } - a++; - x++; - if ((x==34)&&s) - { - x=0; - y++; - if (y==64) break; - p=(DWORD*)(pbyLcd+y*LCD2_ROW*2); - } else p+=2; - } - if (y0!=y) - { - y0<<=1; y<<=1; - BitBlt(hWindowDC, nLcdX, nLcdY+y0, 262, y-y0+2, hLcdDC, 0, y0, SRCCOPY); - } - else - { - x0<<=3; x<<=3; - y0<<=1; y<<=1; - if (x>262) x=262; - BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, y-y0+2, hLcdDC, x0, y0, SRCCOPY); - } - } - else - { - p = (DWORD*)(pbyLcd + y0*LCD1_ROW + x0*4); - while (s--) - { - if (x<34) *p = Pattern4[*a]; - a++; - x++; - if ((x==34)&&s) - { - x=0; - y++; - if (y==64) break; - p=(DWORD*)(pbyLcd+y*LCD1_ROW); - } else p++; - } - if (y0!=y) - { - BitBlt(hWindowDC, nLcdX, nLcdY+y0, 131, y-y0+1, hLcdDC, 0, y0, SRCCOPY); - } - else - { - x0<<=2; x<<=2; - if (x>131) x=131; - BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x-x0, y-y0+1, hLcdDC, x0, y0, SRCCOPY); - } - } - return; -} - -VOID UpdateAnnunciators() -{ - BYTE c; - - c = (BYTE)(Chipset.IORam[0xB] | (Chipset.IORam[0xC]<<4)); - if (!(c&0x80)) c=0; - DrawAnnunciator(1,c&0x01); - DrawAnnunciator(2,c&0x02); - DrawAnnunciator(3,c&0x04); - DrawAnnunciator(4,c&0x08); - DrawAnnunciator(5,c&0x10); - DrawAnnunciator(6,c&0x20); - return; -} - -VOID ResizeWindow() -{ - RECT rectWindow; - RECT rectClient; - - rectWindow.left = 0; - rectWindow.top = 0; - rectWindow.right = nBackgroundW; - rectWindow.bottom = nBackgroundH; - AdjustWindowRect(&rectWindow, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, TRUE); - SetWindowPos (hWnd, (HWND)NULL, 0, 0, - rectWindow.right - rectWindow.left, - rectWindow.bottom - rectWindow.top, - SWP_NOMOVE | SWP_NOZORDER); - GetClientRect(hWnd, &rectClient); - AdjustWindowRect(&rectClient, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, TRUE); - if (rectClient.bottom < rectWindow.bottom) - { - rectWindow.bottom += (rectWindow.bottom - rectClient.bottom); - SetWindowPos (hWnd, (HWND)NULL, 0, 0, - rectWindow.right - rectWindow.left, - rectWindow.bottom - rectWindow.top, - SWP_NOMOVE | SWP_NOZORDER); - } - InvalidateRect(hWnd,NULL,TRUE); - return; -} \ No newline at end of file diff --git a/Emu48/engine.c b/Emu48/engine.c deleted file mode 100644 index 0a16ba5..0000000 --- a/Emu48/engine.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * engine.c - * - * This file is part of Emu48 - * - * Copyright (C) 1995 Sebastien Carlier - * - */ -#include "pch.h" -#include "Emu48.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 FASTPTR(d) (RMap[d>>12]+(d&0xFFF)) -static __inline LPBYTE FASTPTR(DWORD d) -{ - return RMap[d>>12]+(d&0xFFF); -} - -#include "Ops.h" - -BOOL bInterrupt = FALSE; -UINT nState = 1; -UINT nNextState = 0; -CHIPSET Chipset; - -UINT SwitchToState(UINT nNewState) -{ - UINT nOldState = nState; - - if (nState == nNewState) return nOldState; - switch (nState) - { - case 0: // Run - switch (nNewState) - { - case 1: // -> Invalid - nNextState = 1; - if (Chipset.Shutdn) - ResumeThread(hThread); - else - bInterrupt = TRUE; - while (nState!=nNextState) Sleep(0); - UpdateWindowStatus(); - break; - case 2: // -> Return - nNextState = 1; - if (Chipset.Shutdn) - ResumeThread(hThread); - else - bInterrupt = TRUE; - while (nState!=nNextState) Sleep(0); - nNextState = 2; - ResumeThread(hThread); - while (nState!=nNextState) Sleep(0); - UpdateWindowStatus(); - break; - case 3: // -> Sleep - nNextState = 3; - if (Chipset.Shutdn) - ResumeThread(hThread); - else - bInterrupt = TRUE; - while (nState!=nNextState) Sleep(0); - break; - } - break; - case 1: // Invalid - switch (nNewState) - { - case 0: // -> Run - nNextState = 0; - bInterrupt = FALSE; - ResumeThread(hThread); - while (nState!=nNextState) Sleep(0); - UpdateWindowStatus(); - break; - case 2: // -> Return - nNextState = 2; - ResumeThread(hThread); - while (nState!=nNextState) Sleep(0); - break; - case 3: // -> Sleep - nNextState = 3; - ResumeThread(hThread); - while (nState!=nNextState) Sleep(0); - UpdateWindowStatus(); - break; - } - break; - case 3: // Sleep - switch (nNewState) - { - case 0: // -> Run - nNextState = 0; - if (Chipset.Shutdn) bInterrupt=TRUE; - ResumeThread(hThread); - //while (nState!=nNextState) Sleep(0); - break; - case 1: // -> Invalid - nNextState = 1; - ResumeThread(hThread); - while (nState!=nNextState) Sleep(0); - UpdateWindowStatus(); - break; - case 2: // -> Return - nNextState = 1; - ResumeThread(hThread); - while (nState!=nNextState) Sleep(0); - nNextState = 2; - ResumeThread(hThread); - while (nState!=nNextState) Sleep(0); - UpdateWindowStatus(); - break; - } - break; - } - return nOldState; -} - -UINT WorkerThread(LPVOID pParam) -{ -loop: - while (nNextState == 1) - { - nState = 1; - SuspendThread(hThread); - if (nNextState == 2) - { - nState = 2; - return 0; - } - } - while (nNextState == 0) - { - if (nState!=0) - { - nState = 0; - if (Chipset.type == 'S') - { - 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; - } - UpdateDisplayPointers(); - UpdateMainDisplay(); - UpdateMenuDisplay(); - UpdateAnnunciators(); - StartTimers(); - } - PCHANGED; - while (!bInterrupt) - { - LPBYTE I = FASTPTR(w.pc); -/**/#include "Fetch.h" -/**/#include "Opcodes.h" - } - if (Chipset.Shutdn) - { - bInterrupt = FALSE; - SuspendThread(hThread); - Chipset.Shutdn = FALSE; - } - if (Chipset.SoftInt) - { - bInterrupt = FALSE; - Chipset.SoftInt = FALSE; - if (Chipset.inte) - { - Chipset.inte = FALSE; - rstkpush(Chipset.pc); - Chipset.pc = 0xf; - } - } - if (nNextState != 0) - { - StopTimers(); - Chipset.cards_status &= (Chipset.type=='S')?0x5:0xA; - } - } - while (nNextState == 3) - { - nState = 3; - SuspendThread(hThread); - } - goto loop; - UNREFERENCED_PARAMETER(pParam); -} diff --git a/Emu48/external.c b/Emu48/external.c deleted file mode 100644 index 8d0496f..0000000 --- a/Emu48/external.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * external.c - * - * This file is part of Emu48 - * - * Copyright (C) 1995 Sebastien Carlier - * - */ -#include "pch.h" -#include "Emu48.h" - -static __inline VOID Return(CHIPSET* w) -{ - w->rstkp=(w->rstkp-1)&7; - w->pc = w->rstk[w->rstkp]; - w->rstk[w->rstkp] = 0; - return; -} - -VOID External(CHIPSET* w) -{ - if (w->pc==0x017A6) // Beep - { - MessageBeep(0xFFFFFFFF); - //Beep(600,50); - Return(w); - return; - } - w->pc +=4; - return; -} diff --git a/Emu48/keyboard.c b/Emu48/keyboard.c deleted file mode 100644 index 8b0f8da..0000000 --- a/Emu48/keyboard.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * keyboard.c - * - * This file is part of Emu48 - * - * Copyright (C) 1995 Sebastien Carlier - * - */ -#include "pch.h" -#include "Emu48.h" - -WORD Keyboard_GetIR() -{ - WORD r = 0; - - if (Chipset.out==0) return 0; - if (Chipset.out&0x001) r|=Chipset.Keyboard_Row[0]; - if (Chipset.out&0x002) r|=Chipset.Keyboard_Row[1]; - if (Chipset.out&0x004) r|=Chipset.Keyboard_Row[2]; - if (Chipset.out&0x008) r|=Chipset.Keyboard_Row[3]; - if (Chipset.out&0x010) r|=Chipset.Keyboard_Row[4]; - if (Chipset.out&0x020) r|=Chipset.Keyboard_Row[5]; - if (Chipset.out&0x040) r|=Chipset.Keyboard_Row[6]; - if (Chipset.out&0x080) r|=Chipset.Keyboard_Row[7]; - if (Chipset.out&0x100) r|=Chipset.Keyboard_Row[8]; - return r; -} - -VOID ScanKeyboard() -{ - 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); - } - } - - return; -} - -VOID KeyboardEvent(BOOL bPress, UINT out, UINT in) -{ - if (nState != 0) - return; - if (in == 0x8000) - { - Chipset.IR15X = bPress?0x8000:0x0000; - } - else - { - _ASSERT(out<9); - if (bPress) - { - if (((Chipset.Keyboard_Row[out]&in) == 0) && (Chipset.inte==FALSE) && (Chipset.intk)) - Chipset.intd = TRUE; - Chipset.Keyboard_Row[out] |= in; - } - else - Chipset.Keyboard_Row[out] &= (~in); - } - ScanKeyboard(); - return; -} diff --git a/Emu48/mops.c b/Emu48/mops.c deleted file mode 100644 index dc4bdf1..0000000 --- a/Emu48/mops.c +++ /dev/null @@ -1,988 +0,0 @@ -/* - * mops.c - * - * This file is part of Emu48 - * - * Copyright (C) 1995 Sebastien Carlier - * - */ -#include "pch.h" -#include "Emu48.h" -#define SXCONFIG 1 - -// CRC calculation -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) -{ - Chipset.crc = (WORD)((Chipset.crc>>4)^crc_table[(Chipset.crc^nib)&0xf]); -} - -LPBYTE RMap[256] = {NULL,}; -LPBYTE WMap[256] = {NULL,}; - -static __inline UINT MIN(UINT a, UINT b) -{ - return (ab)?a:b; -} - -static VOID MapP0(BYTE a, BYTE b) -{ - UINT i; - DWORD p, m; - - a = (BYTE)MAX(a,Chipset.P0Base); - b = (BYTE)MIN(b,Chipset.P0End); - m = (Chipset.Port0Size*2048)-1; - p = ((a-Chipset.P0Base)<<12)&m; - for (i=a; i<=b; i++) - { - RMap[i]=Chipset.Port0 + p; - WMap[i]=Chipset.Port0 + p; - p = (p+0x1000)&m; - } - return; -} - -static VOID MapBS(BYTE a, BYTE b) -{ - UINT i; - DWORD p, m; - - a = (BYTE)MAX(a,Chipset.BSBase); - b = (BYTE)MIN(b,Chipset.BSEnd); - m = (dwRomSize-1)&0xFF000; - p = a*0x1000; - for (i=a;i<=b;i++) - { - RMap[i]=pbyRom + p; - WMap[i]=NULL; - p = (p+0x1000)&m; - } - return; -} - -static VOID MapP1(BYTE a, BYTE b) -{ - UINT i; - DWORD p, m; - - if (Chipset.Port1 == NULL) return; - a = (BYTE)MAX(a,Chipset.P1Base); - b = (BYTE)MIN(b,Chipset.P1End); - m = (Chipset.Port1Size*2048)-1; - p = ((a-Chipset.P1Base)<<12)&m; - if (Chipset.Port1_Writeable) - { - for (i=a; i<=b; i++) - { - RMap[i]=Chipset.Port1 + p; - WMap[i]=Chipset.Port1 + p; - p = (p+0x1000)&m; - } - } - else - { - for (i=a; i<=b; i++) - { - RMap[i]=Chipset.Port1 + p; - WMap[i]=NULL; - p = (p+0x1000)&m; - } - } - return; -} - -static VOID MapP2(BYTE a, BYTE b) -{ - UINT i; - DWORD p, m; - LPBYTE pbyTemp; - - if (pbyPort2 == NULL) return; - pbyTemp = pbyPort2 + (nPort2Bank << 18); - a = (BYTE)MAX(a,Chipset.P2Base); - b = (BYTE)MIN(b,Chipset.P2End); - m = (Chipset.Port2Size*2048)-1; - p = ((a-Chipset.P2Base)<<12)&m; - if (bPort2Writeable) - { - for (i=a; i<=b; i++) - { - RMap[i]=pbyTemp + p; - WMap[i]=pbyTemp + p; - p = (p+0x1000)&m; - } - } - else - { - for (i=a; i<=b; i++) - { - RMap[i]=pbyTemp + p; - WMap[i]=NULL; - p = (p+0x1000)&m; - } - } - return; -} - -static VOID MapROM(BYTE a, BYTE b) -{ - UINT i; - DWORD p, m; - - m = (dwRomSize-1)&0xFF000; - p = a*0x1000; - for (i=a;i<=b;i++) - { - RMap[i]=pbyRom + p; - WMap[i]=NULL; - p = (p+0x1000)&m; - } - return; -} - -VOID Map(BYTE a, BYTE b) -{ - -#if SXCONFIG - if (cCurrentRomType=='S') - { - MapROM(a,b); - if (Chipset.BSCfig) MapBS(a,b); - if (Chipset.P2Cfig) MapP2(a,b); - if (Chipset.P1Cfig) MapP1(a,b); - if (Chipset.P0Cfig) MapP0(a,b); - return; - } -#endif - MapROM(a,b); - if (Chipset.P2Cfig) MapP2(a,b); - if (Chipset.P1Cfig) MapP1(a,b); - if (Chipset.BSCfig) MapBS(a,b); - if (Chipset.P0Cfig) MapP0(a,b); - return; -} - -//////////////////////////////////////////////////////////////////////////////// -// -// Bus Commands -// -//////////////////////////////////////////////////////////////////////////////// - -VOID Config() -{ - DWORD d = Npack(Chipset.C,5); - BYTE b = (BYTE)(d>>12); - BYTE s = (BYTE)(b^0xFF); - -#if SXCONFIG - if (cCurrentRomType=='S') - { - if (!Chipset.IOCfig) - { - Chipset.IOCfig=TRUE; - Chipset.IOBase=d&0xFFFC0; - Map(b,b); - return; - } - if (!Chipset.P0Cfg2) - { - Chipset.P0Cfg2=TRUE; - Chipset.P0Size=s; - return; - } - if (!Chipset.P0Cfig) - { - Chipset.P0Cfig = TRUE; - Chipset.P0Base = (BYTE)b; - Chipset.P0End = (BYTE)(b+Chipset.P0Size); - Map(Chipset.P0Base,Chipset.P0End); - return; - } - if (!Chipset.P1Cfg2) - { - Chipset.P1Cfg2 = TRUE; - Chipset.P1Size = (BYTE)s; - return; - } - if (!Chipset.P1Cfig) - { - Chipset.P1Cfig = TRUE; - Chipset.P1Base = (BYTE)b; - Chipset.P1End = (BYTE)(b+Chipset.P1Size); - Map(Chipset.P1Base,Chipset.P1End); - return; - } - if (!Chipset.P2Cfg2) - { - Chipset.P2Cfg2 = TRUE; - Chipset.P2Size = (BYTE)s; - return; - } - if (!Chipset.P2Cfig) - { - Chipset.P2Cfig = TRUE; - Chipset.P2Base = (BYTE)b; - Chipset.P2End = (BYTE)(b+Chipset.P2Size); - Map(Chipset.P2Base,Chipset.P2End); - return; - } - if (!Chipset.BSCfg2) - { - Chipset.BSCfg2=TRUE; - Chipset.BSSize=s; - return; - } - if (!Chipset.BSCfig) - { - Chipset.BSCfig = TRUE; - Chipset.BSBase = (BYTE)b; - Chipset.BSEnd = (BYTE)(b+Chipset.BSSize); - Map(Chipset.BSBase,Chipset.BSEnd); - return; - } - return; - } -#endif - if (!Chipset.IOCfig) - { - Chipset.IOCfig=TRUE; - Chipset.IOBase=d&0xFFFC0; - Map(b,b); - return; - } - if (!Chipset.P0Cfg2) - { - Chipset.P0Cfg2=TRUE; - Chipset.P0Size=s; - return; - } - if (!Chipset.P0Cfig) - { - Chipset.P0Cfig = TRUE; - Chipset.P0Base = (BYTE)b; - Chipset.P0End = (BYTE)(b+Chipset.P0Size); - Map(Chipset.P0Base,Chipset.P0End); - return; - } - if (!Chipset.BSCfg2) - { - Chipset.BSCfg2=TRUE; - Chipset.BSSize=s; - return; - } - if (!Chipset.BSCfig) - { - Chipset.BSCfig = TRUE; - Chipset.BSBase = (BYTE)b; - Chipset.BSEnd = (BYTE)(b+Chipset.BSSize); - Map(Chipset.BSBase,Chipset.BSEnd); - return; - } - if (!Chipset.P1Cfg2) - { - Chipset.P1Cfg2 = TRUE; - Chipset.P1Size = (BYTE)s; - return; - } - if (!Chipset.P1Cfig) - { - Chipset.P1Cfig = TRUE; - Chipset.P1Base = (BYTE)b; - Chipset.P1End = (BYTE)(b+Chipset.P1Size); - Map(Chipset.P1Base,Chipset.P1End); - return; - } - if (!Chipset.P2Cfg2) - { - Chipset.P2Cfg2 = TRUE; - Chipset.P2Size = (BYTE)s; - return; - } - if (!Chipset.P2Cfig) - { - Chipset.P2Cfig = TRUE; - Chipset.P2Base = (BYTE)b; - Chipset.P2End = (BYTE)(b+Chipset.P2Size); - Map(Chipset.P2Base,Chipset.P2End); - return; - } - return; -} - -VOID Uncnfg() -{ - DWORD d=Npack(Chipset.C,5); - BYTE b=(BYTE)(d>>12); - -#if SXCONFIG - if (cCurrentRomType=='S') - { - if ((Chipset.IOCfig)&&(d==Chipset.IOBase)) {Chipset.IOCfig=FALSE;Chipset.IOBase=0x100000;Map(b,b);return;} - if ((Chipset.P0Cfig)&&(b==Chipset.P0Base)) {Chipset.P0Cfig=FALSE;Chipset.P0Cfg2=FALSE;Map(Chipset.P0Base,Chipset.P0End);return;} - if ((Chipset.P1Cfig)&&(b==Chipset.P1Base)) {Chipset.P1Cfig=FALSE;Chipset.P1Cfg2=FALSE;Map(Chipset.P1Base,Chipset.P1End);return;} - if ((Chipset.P2Cfig)&&(b==Chipset.P2Base)) {Chipset.P2Cfig=FALSE;Chipset.P2Cfg2=FALSE;Map(Chipset.P2Base,Chipset.P2End);return;} - if ((Chipset.BSCfig)&&(b==Chipset.BSBase)) {Chipset.BSCfig=FALSE;Chipset.BSCfg2=FALSE;Map(Chipset.BSBase,Chipset.BSEnd);return;} - return; - } -#endif - if ((Chipset.IOCfig)&&(d==Chipset.IOBase)) {Chipset.IOCfig=FALSE;Chipset.IOBase=0x100000;Map(b,b);return;} - if ((Chipset.P0Cfig)&&(b==Chipset.P0Base)) {Chipset.P0Cfig=FALSE;Chipset.P0Cfg2=FALSE;Map(Chipset.P0Base,Chipset.P0End);return;} - if ((Chipset.BSCfig)&&(b==Chipset.BSBase)) {Chipset.BSCfig=FALSE;Chipset.BSCfg2=FALSE;Map(Chipset.BSBase,Chipset.BSEnd);return;} - if ((Chipset.P1Cfig)&&(b==Chipset.P1Base)) {Chipset.P1Cfig=FALSE;Chipset.P1Cfg2=FALSE;Map(Chipset.P1Base,Chipset.P1End);return;} - if ((Chipset.P2Cfig)&&(b==Chipset.P2Base)) {Chipset.P2Cfig=FALSE;Chipset.P2Cfg2=FALSE;Map(Chipset.P2Base,Chipset.P2End);return;} - return; -} - -VOID Reset() -{ - - Chipset.IOCfig=FALSE;Chipset.IOBase=0x100000; - Chipset.P0Cfig=FALSE;Chipset.P0Cfg2=FALSE;Chipset.P0Base=0;Chipset.P0Size=0;Chipset.P0End=0; - Chipset.BSCfig=FALSE;Chipset.BSCfg2=FALSE;Chipset.BSBase=0;Chipset.BSSize=0;Chipset.BSEnd=0; - Chipset.P1Cfig=FALSE;Chipset.P1Cfg2=FALSE;Chipset.P1Base=0;Chipset.P1Size=0;Chipset.P1End=0; - Chipset.P2Cfig=FALSE;Chipset.P2Cfg2=FALSE;Chipset.P2Base=0;Chipset.P2Size=0;Chipset.P2End=0; - Map(0x00,0xFF); - return; -} - -VOID C_Eq_Id() -{ -#if SXCONFIG - if (cCurrentRomType=='S') - { - if (!Chipset.IOCfig) {Nunpack(Chipset.C,(Chipset.IOBase*0x1000)^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 (!Chipset.P1Cfg2) {Nunpack(Chipset.C,(Chipset.P1Size*0x1000)^0xFF005,5);return;} - if (!Chipset.P1Cfig) {Nunpack(Chipset.C,(Chipset.P1Base*0x1000)^0x000F6,5);return;} - if (!Chipset.P2Cfg2) {Nunpack(Chipset.C,(Chipset.P2Size*0x1000)^0xFF007,5);return;} - if (!Chipset.P2Cfig) {Nunpack(Chipset.C,(Chipset.P2Base*0x1000)^0x000F8,5);return;} - if (!Chipset.BSCfg2) {Nunpack(Chipset.C,(Chipset.BSSize*0x1000)^0xFF001,5);return;} - if (!Chipset.BSCfig) {Nunpack(Chipset.C,(Chipset.BSBase*0x1000)^0x000F2,5);return;} - memset(Chipset.C,0,5); - return; - } -#endif - if (!Chipset.IOCfig) {Nunpack(Chipset.C,(Chipset.IOBase*0x1000)^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 (!Chipset.BSCfg2) {Nunpack(Chipset.C,(Chipset.BSSize*0x1000)^0xFF005,5);return;} - if (!Chipset.BSCfig) {Nunpack(Chipset.C,(Chipset.BSBase*0x1000)^0x000F6,5);return;} - if (!Chipset.P1Cfg2) {Nunpack(Chipset.C,(Chipset.P1Size*0x1000)^0xFF007,5);return;} - if (!Chipset.P1Cfig) {Nunpack(Chipset.C,(Chipset.P1Base*0x1000)^0x000F8,5);return;} - if (!Chipset.P2Cfg2) {Nunpack(Chipset.C,(Chipset.P2Size*0x1000)^0xFF001,5);return;} - if (!Chipset.P2Cfig) {Nunpack(Chipset.C,(Chipset.P2Base*0x1000)^0x000F2,5);return;} - memset(Chipset.C,0,5); - return; -} - -VOID Npeek(BYTE *a, DWORD d, UINT s) -{ - DWORD u, v; - UINT c; - BYTE *p; - - do - { - 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; -} - -VOID Nread(BYTE *a, DWORD d, UINT s) -{ - DWORD u, v; - UINT c; - BYTE *p; - - do - { - if ((d&0xFFFC0)==Chipset.IOBase) - { - v = d&0x3F; - c = MIN(s,0x40-v); - ReadIO(a,v,c); - } - else - { - u = d>>12; - v = d&0xFFF; - c = MIN(s,0x1000-v); - if ((p=RMap[u]) != NULL) - { - memcpy(a, p+v, c); - for (u=0; u=Chipset.start12)) - WriteToMainDisplay(a,d,s); - if ((d=Chipset.start2)) - WriteToMenuDisplay(a,d,s); - do - { - if ((d&0xFFFC0)==Chipset.IOBase) - { - v = d&0x3F; - c = MIN(s,0x40-v); - WriteIO(a, v, c); - } - else - { - u = d>>12; - v = d&0xFFF; - c = MIN(s,0x1000-v); - if ((p=WMap[u]) != NULL) memcpy(p+v, a, c); - } - a+=c; - d+=c; - } while (s-=c); - return; -} - -VOID Nread2(BYTE *a, DWORD d) -{ - DWORD u, v; - BYTE *p; - - if ((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; -} - -VOID Nwrite2(BYTE *a, DWORD d) -{ - DWORD u, v; - BYTE *p; - - if ((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; -} - -VOID Nread5(BYTE *a, DWORD d) -{ - DWORD u, v; - BYTE *p; - - if ((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; -} - -VOID Nwrite5(BYTE *a, DWORD d) -{ - DWORD u, v; - BYTE *p; - - if ((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]; - } -} - -DWORD Read5(DWORD d) -{ - BYTE p[8]; - - Npeek(p,d,5); - return Npack(p,5); -} - -BYTE Read2(DWORD d) -{ - BYTE p[2]; - - Npeek(p,d,2); - return (BYTE)(p[0]|(p[1]<<4)); -} - -VOID Write5(DWORD d, DWORD n) -{ - BYTE p[8]; - - Nunpack(p,n,5); - Nwrite(p,d,5); - return; -} - -VOID ReadIO(BYTE *a, DWORD b, DWORD s) -{ - DWORD d = b; - - do - { - switch (d) - { - case 0x00: *a = (Chipset.dispon<<3)|Chipset.boffset; break; - case 0x01: *a = Chipset.contrast&0xF; break; - case 0x02: *a = Chipset.contrast>>4; break; - case 0x03: *a = 0; - case 0x04: *a = (Chipset.crc )&0xF; break; - case 0x05: *a = (Chipset.crc>> 4)&0xF; break; - case 0x06: *a = (Chipset.crc>> 8)&0xF; break; - case 0x07: *a = (Chipset.crc>>12)&0xF; break; - case 0x08: *a = 0; break; -// case 0x09: *a = Chipset.IORam[0x09]; break; - case 0x0A: *a = 0; break; -// case 0x0B: *a = Chipset.IORam[0x0B]; break; -// case 0x0C: *a = Chipset.IORam[0x0C]; break; -// case 0x0D: *a = Chipset.IORam[0x0D]; break; -// case 0x0E: *a = Chipset.IORam[0x0E]; break; - case 0x0F: *a = Chipset.cards_status; break; -// case 0x10: *a = Chipset.IORam[0x10]; break; -// case 0x11: *a = Chipset.IORam[0x11]; break; - case 0x12: *a = 0; break; - case 0x13: *a = 0; break; - case 0x14: *a = 0; Chipset.IORam[0x11]&=0xE; break; - case 0x15: *a = 0; Chipset.IORam[0x11]&=0xE; break; - case 0x16: *a = 0; break; - case 0x17: *a = 0; break; -// case 0x18: *a = Chipset.IORam[0x18]; break; -// case 0x19: *a = Chipset.IORam[0x19]; break; - case 0x1A: *a = 0; break; - case 0x1B: *a = 0; break; - case 0x1C: *a = 0; break; - case 0x1D: *a = 0; break; -// case 0x1E: *a = Chipset.IORam[0x1E]; break; -// case 0x1F: *a = Chipset.IORam[0x1F]; break; - case 0x20: *a = 3; break; - case 0x21: *a = 3; break; - case 0x22: *a = 3; break; - case 0x23: *a = 3; break; - case 0x24: *a = 3; break; - case 0x25: *a = 3; break; - case 0x26: *a = 3; break; - case 0x27: *a = 3; break; - case 0x28: - if (Chipset.sync) - Chipset.sync--; - else - Chipset.sync=Chipset.lcounter+1; - *a = Chipset.sync&0xF; - break; - case 0x29: - if (d==b) - { - if (Chipset.sync) - Chipset.sync--; - else - Chipset.sync=Chipset.lcounter+1; - } - *a = Chipset.sync&0xF; - break; - case 0x2A: *a = 0; break; - case 0x2B: *a = 0; break; - case 0x2C: *a = 0; break; - case 0x2D: *a = 0; break; -// case 0x2E: *a = Chipset.IORam[0x2E]; break; -// case 0x2F: *a = Chipset.IORam[0x2F]; break; - case 0x30: *a = 3; break; - case 0x31: *a = 3; break; - case 0x32: *a = 3; break; - case 0x33: *a = 3; break; - case 0x34: *a = 3; break; - case 0x35: *a = 0; break; - case 0x36: *a = 0; break; - case 0x37: *a = ReadT1(); break; - case 0x38: Nunpack(a, ReadT2() , s); return; - case 0x39: Nunpack(a, ReadT2()>> 4, s); return; - case 0x3A: Nunpack(a, ReadT2()>> 8, s); return; - case 0x3B: Nunpack(a, ReadT2()>>12, s); return; - case 0x3C: Nunpack(a, ReadT2()>>16, s); return; - case 0x3D: Nunpack(a, ReadT2()>>20, s); return; - case 0x3E: Nunpack(a, ReadT2()>>24, s); return; - case 0x3F: Nunpack(a, ReadT2()>>28, s); return; - default: *a = Chipset.IORam[d]; - } - d++; a++; - } while (--s); - return; -} - -VOID WriteIO(BYTE *a, DWORD b, DWORD s) -{ - DWORD d=b; - BYTE c; - BYTE disp=0; - - if (d>=0x38) - { - Nunpack(Chipset.IORam+0x38, ReadT2(), 8); - memcpy(Chipset.IORam+d,a,s); - SetT2(Npack(Chipset.IORam+0x38,8)); - return; - } - do - { - c = *a; - switch (d) - { -// 00100 = NS:DISPIO -// 00100 @ Display bit offset and DON [DON OFF2 OFF1 OFF0] -// 00100 @ 3 nibs for display offset (scrolling), DON=Display ON - case 0x00: - if ((c^Chipset.IORam[d])&8) - { - Chipset.dispon = c>>3; - disp|=7; - } - if ((c^Chipset.IORam[d])&7) - { - Chipset.boffset = c&7; - disp|=3; - } - Chipset.IORam[d] = c; - break; - -// 00101 = NS:CONTRLSB -// 00101 @ Contrast Control [CON3 CON2 CON1 CON0] -// 00101 @ Higher value = darker screen - case 0x01: - if (c!=Chipset.IORam[d]) - { - Chipset.IORam[d]=c; - Chipset.contrast = (Chipset.contrast&0x10)|c; - UpdateContrast(Chipset.contrast); - disp|=7; - } - break; - -// 00102 = NS:DISPTEST -// 00102 @ Display test [VDIG LID TRIM CON4] [LRT LRTD LRTC BIN] -// 00102 @ Normally zeros - case 0x02: - if (c!=Chipset.IORam[d]) - { - Chipset.IORam[d]=c; - Chipset.contrast = (Chipset.contrast&0x0f)|((c&1)<<4); - UpdateContrast(Chipset.contrast); - disp|=7; - } - break; - - case 0x03: Chipset.IORam[d]=c; break; - -// 00104 = HP:CRC -// 00104 @ 16 bit hardware CRC (104-107) (X^16+X^12+X^5+1) -// 00104 @ crc = ( crc >> 4 ) ^ ( ( ( crc ^ nib ) & 0x000F ) * 0x1081 ); - case 0x04: Chipset.crc = (Chipset.crc&0xfff0)|(c*0x0001); break; - case 0x05: Chipset.crc = (Chipset.crc&0xff0f)|(c*0x0010); break; - case 0x06: Chipset.crc = (Chipset.crc&0xf0ff)|(c*0x0100); break; - case 0x07: Chipset.crc = (Chipset.crc&0x0fff)|(c*0x1000); break; - -// 00108 = NS:POWERSTATUS -// 00108 @ Low power registers (108-109) -// 00108 @ [LB2 LB1 LB0 VLBI] (read only) -// 00108 @ LowBat(2) LowBat(1) LowBat(S) VeryLowBat - case 0x08: break; // read-only - -// 00109 = NS:POWERCTRL -// 00109 @ [ELBI EVLBI GRST RST] (read/write) - case 0x09: Chipset.IORam[d]=c; break; - -// 0010A = NS:MODE -// 0010A @ Mode Register (read-only) - case 0x0A: break; // read-only - -// 0010B = HP:ANNCTRL -// 0010B @ Annunciator control [LA4 LA3 LA2 LA1] = [ alarm alpha -> <- ] - case 0x0B: - case 0x0C: - if (c!=Chipset.IORam[d]) - { - Chipset.IORam[d] = c; - disp|=8; - } - break; - -// 0010D = NS:BAU -// 0010D @ Serial baud rate [UCK BD2 BD1 BD0] (bit 3 is read-only) -// 0010D @ 3 bits = {1200 1920 2400 3840 4800 7680 9600 15360} - case 0x0D: Chipset.IORam[d]=(Chipset.IORam[d]&8)|(c&7); break; // bit 3 is read-only - -// 0010E = NS:CARDCTRL -// 0010E @ [ECDT RCDT SMP SWINT] (read/write) -// 0010E @ Enable Card Det., Run Card Det., Set Module Pulled, Software interrupt - case 0x0E: - Chipset.IORam[d]=c; -#if 1 - if ( (RMap[4]!=(pbyRom+0x4000)) && (12 != c) ) - { - c |= 0x10; - } -#endif - if (c&1) - { - Chipset.SoftInt = TRUE; - bInterrupt = TRUE; - } - if (c&2) - { - Chipset.HST |= 8; // MP -// Chipset.SoftInt = TRUE; -// bInterrupt = TRUE; - } - break; - -// 0010F = NS:CARDSTATUS -// 0010F @ [P2W P1W P2C P1C] (read-only) Port 2 writable .. Port 1 inserted - case 0x0F: break; // read-only - -// 00110 = HP:IOC -// 00110 @ Serial I/O Control [SON ETBE ERBF ERBZ] -// 00110 @ Serial On, Interrupt On Recv.Buf.Empty, Full, Buzy - case 0x10: Chipset.IORam[d]=c; break; - -// 00111 = HP:RCS -// 00111 Serial Receive Control/Status [RX RER RBZ RBF] (bit 3 is read-only) - case 0x11: Chipset.IORam[d]=(Chipset.IORam[d]&8)|(c&7); break; - -// 00112 = HP:TCS -// 00112 @ Serial Transmit Control/Status [BRK LPB TBZ TBF] - case 0x12: Chipset.IORam[d]=c; break; - -// 00113 = HP:CRER -// 00113 @ Serial Clear RER (writing anything clears RER bit) - case 0x13: Chipset.IORam[0x11]&=0xB; Chipset.IORam[0x11]&=0xB; - -// 00114 = HP:RBR -// 00114 @ Serial Receive Buffer Register (Reading clears RBF bit) -// 00114 @ [RX RER RBZ RBF] - case 0x14: break; // probably read-only - case 0x15: break; // probably read-only - -// 00116 = HP:TBR -// 00116 @ Serial Transmit Buffer Register (Writing sets TBF bit) - case 0x16: Chipset.IORam[d]=c; Chipset.IORam[0x12]|=1; break; - case 0x17: Chipset.IORam[d]=c; Chipset.IORam[0x12]|=1; break; - -// 00118 = NS:SRR -// 00118 @ Service Request Register (read-only) -// 00118 @ [ISRQ TSRQ USRQ VSRQ] [KDN NINT2 NINT LSRQ] - case 0x18: break; // read-only - case 0x19: break; // read-only - -// 0011A = HP:IRC -// 0011A @ IR Control Register [IRI EIRU EIRI IRE] (bit 3 is read-only) -// 0011A @ IR Input, Enable IR UART mode, Enable IR Interrupt, IR Event - case 0x1A: Chipset.IORam[d]=(Chipset.IORam[d]&8)|(c&7); break; - -// 0011B = NS:BASENIBOFF -// 0011B @ Used as addressto get BASENIB from 11F to the 5th nibble - case 0x1B: break; - -// 0011C = NS:LCR -// 0011C @ Led Control Register [LED ELBE LBZ LBF] (Setting LED is draining) - case 0x1C: Chipset.IORam[d]=c; break; - -// 0011D = NS:LBR -// 0011D @ Led Buffer Register [0 0 0 LBO] (bits 1-3 read zero) - case 0x1D: Chipset.IORam[d]=c&1; break; - -// 0011E = NS:SCRATCHPAD -// 0011E @ Scratch pad - case 0x1E: Chipset.IORam[d]=c; break; - -// 0011F = NS:BASENIB -// 0011F @ 7 or F for base memory - case 0x1F: Chipset.IORam[d]=c; break; - -// 00120 = NS:DISPADDR -// 00120 @ Display Start Address (write only) -// 00120 @ bit 0 is ignored (display must start on byte boundary) - case 0x20: - if (s>=5) - { - b = Npack(a,5)&0xFFFFE; - if (b != Chipset.start1) - { - Chipset.start1 = b; - disp|=3; - } - b = d; - } - Chipset.IORam[d]=c; - break; -// case 0x21: Chipset.IORam[d]=c; break; -// case 0x22: Chipset.IORam[d]=c; break; -// case 0x23: Chipset.IORam[d]=c; break; -// case 0x24: Chipset.IORam[d]=c; break; - -// 00125 = NS:LINEOFFS -// 00125 @ Display Line offset (write only) (no of bytes skipped after each line) -// 00125 @ MSG sign extended - case 0x25: - if (s>=3) - { - signed short lo = (signed short)Npack(a, 3); - if (lo&0x800) lo-=0x1000; - if (lo==Chipset.loffset) break; - Chipset.loffset = lo; - disp|=3; - } - break; - -// 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 - case 0x28: Chipset.IORam[d]=c; break; - case 0x29: - Chipset.IORam[d]=c; - d = Npack(Chipset.IORam+0x28,2)&0x3F; - if (Chipset.lcounter != d) - { - Chipset.lcounter = d; - disp|=7; - } - break; - - case 0x2A: break; - case 0x2B: break; - case 0x2C: break; - case 0x2D: break; - -// 0012E = NS:TIMER1CTRL -// 0012E @ TIMER1 Control [SRQ WKE INT XTRA] - case 0x2E: Chipset.IORam[d]=c&0xE; break; - -// 0012F = NS:TIMER2CTRL -// 0012F @ TIMER2 Control [SRQ WKE INT RUN] - case 0x2F: -// if ((Chipset.IORam[d]^c)&1) -// // RUN changed - Chipset.IORam[d]=c; - if (c&1) - StartTimers(); - else - StopTimers(); - break; - -// 00130 = NS:MENUADDR -// 00130 @ Display Secondary Start Address (write only) (30-34) -// 00130 @ Menu Display Address, no line offsets - case 0x30: - if (s>=5) - { - b = Npack(a,5)&0xFFFFE; - if (b != Chipset.start2) - { - Chipset.start2 = b; - disp|=5; - } - b = d; - } - Chipset.IORam[d]=c; - break; -// case 0x31: Chipset.IORam[d]=c; break; -// case 0x32: Chipset.IORam[d]=c; break; -// case 0x33: Chipset.IORam[d]=c; break; -// case 0x34: Chipset.IORam[d]=c; break; - - case 0x35: break; - case 0x36: break; - -// 00137 = HP:TIMER1 -// 00137 @ Decremented 16 times/s - case 0x37: - SetT1(Chipset.t1); - break; - -// 00138 = HP:TIMER2 -// 00138 @ hardware timer (38-3F), decremented 8192 times/s - // nothing - fall through to default - - default: Chipset.IORam[d]=c; - } - a++; d++; - } while (--s); - if (disp&1) UpdateDisplayPointers(); - if (disp&2) UpdateMainDisplay(); - if (disp&4) UpdateMenuDisplay(); - if (disp&8) UpdateAnnunciators(); - return; -} diff --git a/Emu48/opcodes.h b/Emu48/opcodes.h deleted file mode 100644 index 48001e3..0000000 --- a/Emu48/opcodes.h +++ /dev/null @@ -1,2089 +0,0 @@ -/* - * opcodes.h - * - * This file is part of Emu48 - * - * Copyright (C) 1995 Sebastien Carlier - * - */ - -o00: // RTNSXM -{ - w.pc = rstkpop(); - w.HST |= XM; - continue; -} - -o01: // RTN -{ - w.pc = rstkpop(); - continue; -} - -o02: // RTNSC -{ - w.pc = rstkpop(); - w.carry = TRUE; - continue; -} - -o03: // RTNCC -{ - w.pc = rstkpop(); - w.carry = FALSE; - continue; -} - -o04: // SETHEX -{ - w.pc+=2; - w.mode_dec=FALSE; - continue; -} - -o05: // SETDEC -{ - w.pc+=2; - w.mode_dec = TRUE; - continue; -} - -o06: // RSTK=C -{ - w.pc+=2; - rstkpush(Npack(w.C,5)); - continue; -} - -o07: // C=RSTK -{ - w.pc+=2; - Nunpack(w.C,rstkpop(),5); - continue; -} - -o08: // CLRST -{ - w.pc+=2; - memset(w.ST, 0, 3); - continue; -} - -o09: // C=ST -{ - w.pc+=2; - memcpy(w.C, w.ST, 3); - continue; -} - -o0A: // ST=C -{ - w.pc+=2; - memcpy(w.ST, w.C, 3); - continue; -} - -o0B: // CSTEX -{ - w.pc+=2; - Nxchg(w.C, w.ST, 3); - continue; -} - -o0C: // P=P+1 -{ - 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.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.pc+=4; - NFand(w.A,w.B,I[2]); - continue; -} -o0Ef1: // B=B&C f -{ - w.pc+=4; - NFand(w.B,w.C,I[2]); - continue; -} -o0Ef2: // C=C&A f -{ - w.pc+=4; - NFand(w.C,w.A,I[2]); - continue; -} -o0Ef3: // D=D&C f -{ - w.pc+=4; - NFand(w.D,w.C,I[2]); - continue; -} -o0Ef4: // B=B&A f -{ - w.pc+=4; - NFand(w.B,w.A,I[2]); - continue; -} -o0Ef5: // C=C&B f -{ - w.pc+=4; - NFand(w.C,w.B,I[2]); - continue; -} -o0Ef6: // A=A&C f -{ - w.pc+=4; - NFand(w.A,w.C,I[2]); - continue; -} -o0Ef7: // C=C&D f -{ - w.pc+=4; - NFand(w.C,w.D,I[2]); - continue; -} - -o0Ef8: // A=A!B f -{ - w.pc+=4; - NFor(w.A,w.B,I[2]); - continue; -} -o0Ef9: // B=B!C f -{ - w.pc+=4; - NFor(w.B,w.C,I[2]); - continue; -} -o0EfA: // C=C!A f -{ - w.pc+=4; - NFor(w.C,w.A,I[2]); - continue; -} -o0EfB: // D=D!C f -{ - w.pc+=4; - NFor(w.D,w.C,I[2]); - continue; -} -o0EfC: // B=B!A f -{ - w.pc+=4; - NFor(w.B,w.A,I[2]); - continue; -} -o0EfD: // C=C!B f -{ - w.pc+=4; - NFor(w.C,w.B,I[2]); - continue; -} -o0EfE: // A=A!C f -{ - w.pc+=4; - NFor(w.A,w.C,I[2]); - continue; -} -o0EfF: // C=A!D f -{ - w.pc+=4; - NFor(w.C,w.D,I[2]); - continue; -} - -o0F: // RTI -{ - w.pc = rstkpop(); - w.inte = TRUE; - if (w.IR15X) - INTERRUPT; - if (w.intd) - { - w.intd = FALSE; - INTERRUPT; - } - continue; -} - -o100: // R0=A W -{ - w.pc+=3; - memcpy(w.R0, w.A, 16); - continue; -} - -o101: // R1=A W -{ - w.pc+=3; - memcpy(w.R1, w.A, 16); - continue; -} - -o102: // R2=A W -{ - w.pc+=3; - memcpy(w.R2, w.A, 16); - continue; -} - -o103: // R3=A W -{ - w.pc+=3; - memcpy(w.R3, w.A, 16); - continue; -} - -o104: // R4=A W -{ - w.pc+=3; - memcpy(w.R4, w.A, 16); - continue; -} - -o108: // R0=C W -{ - w.pc+=3; - memcpy(w.R0, w.C, 16); - continue; -} - -o109: // R1=C W -{ - w.pc+=3; - memcpy(w.R1, w.C, 16); - continue; -} - -o10A: // R2=C W -{ - w.pc+=3; - memcpy(w.R2, w.C, 16); - continue; -} - -o10B: // R3=C W -{ - w.pc+=3; - memcpy(w.R3, w.C, 16); - continue; -} - -o10C: // R4=C W -{ - w.pc+=3; - memcpy(w.R4, w.C, 16); - continue; -} - -o110: // A=R0 W -{ - w.pc+=3; - memcpy(w.A, w.R0, 16); - continue; -} - -o111: // A=R1 W -{ - w.pc+=3; - memcpy(w.A, w.R1, 16); - continue; -} - -o112: // A=R2 W -{ - w.pc+=3; - memcpy(w.A, w.R2, 16); - continue; -} - -o113: // A=R3 W -{ - w.pc+=3; - memcpy(w.A, w.R3, 16); - continue; -} - -o114: // A=R4 W -{ - w.pc+=3; - memcpy(w.A, w.R4, 16); - continue; -} - -o118: // C=R0 W -{ - w.pc+=3; - memcpy(w.C, w.R0, 16); - continue; -} - -o119: // C=R1 W -{ - w.pc+=3; - memcpy(w.C, w.R1, 16); - continue; -} - -o11A: // C=R2 W -{ - w.pc+=3; - memcpy(w.C, w.R2, 16); - continue; -} - -o11B: // C=R3 W -{ - w.pc+=3; - memcpy(w.C, w.R3, 16); - continue; -} - -o11C: // C=R4 W -{ - w.pc+=3; - memcpy(w.C, w.R4, 16); - continue; -} - -o120: // AR0EX W -{ - w.pc+=3; - Nxchg(w.A, w.R0, 16); - continue; -} - -o121: // AR1EX W -{ - w.pc+=3; - Nxchg(w.A, w.R1, 16); - continue; -} - -o122: // AR2EX W -{ - w.pc+=3; - Nxchg(w.A, w.R2, 16); - continue; -} - -o123: // AR3EX W -{ - w.pc+=3; - Nxchg(w.A, w.R3, 16); - continue; -} - -o124: // AR4EX W -{ - w.pc+=3; - Nxchg(w.A, w.R4, 16); - continue; -} - -o128: // CR0EX W -{ - w.pc+=3; - Nxchg(w.C, w.R0, 16); - continue; -} - -o129: // CR1EX W -{ - w.pc+=3; - Nxchg(w.C, w.R1, 16); - continue; -} - -o12A: // CR2EX W -{ - w.pc+=3; - Nxchg(w.C, w.R2, 16); - continue; -} - -o12B: // CR3EX W -{ - w.pc+=3; - Nxchg(w.C, w.R3, 16); - continue; -} - -o12C: // CR4EX W -{ - w.pc+=3; - Nxchg(w.C, w.R4, 16); - continue; -} - -o130: // D0=A -{ - w.pc+=3; - w.d0=Npack(w.A,5); - continue; -} - -o131: // D1=A -{ - 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.pc+=3; - continue; -} - -o133: // AD1EX -{ - DWORD d=w.d1; - w.d1=Npack(w.A,5); - Nunpack(w.A,d,5); - w.pc+=3; - continue; -} - -o134: // D0=C -{ - w.pc+=3; - w.d0=Npack(w.C,5); - continue; -} - -o135: // D1=C -{ - 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.pc+=3; - continue; -} - -o137: // CD1EX -{ - DWORD d=w.d1; - w.d1=Npack(w.C,5); - Nunpack(w.C,d,5); - w.pc+=3; - continue; -} - -o138:// D0=AS -{ - w.pc+=3; - *((WORD*)&w.d0)=(WORD)Npack(w.A,4); - continue; -} - -o139: // D1=AS -{ - 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.pc+=3; - continue; -} - -o13B: // AD1XS -{ - DWORD d=w.d1; - *((WORD*)&w.d1)=(WORD)Npack(w.A,4); - Nunpack(w.A,d,4); - w.pc+=3; - continue; -} - -o13C: // D0=CS -{ - w.pc+=3; - *((WORD*)&w.d0)=(WORD)Npack(w.C,4); - continue; -} - -o13D: // D1=CS -{ - 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.pc+=3; - continue; -} - -o13F: // AD1XS -{ - DWORD d=w.d1; - *((WORD*)&w.d1)=(WORD)Npack(w.C,4); - Nunpack(w.C,d,4); - w.pc+=3; - continue; -} - -o140: w.pc+=3; Nwrite5(w.A, w.d0); continue; // DAT0=A A -o141: w.pc+=3; Nwrite5(w.A, w.d1); continue; // DAT1=A A -o144: w.pc+=3; Nwrite5(w.C, w.d0); continue; // DAT0=C A -o145: w.pc+=3; Nwrite5(w.C, w.d1); continue; // DAT1=C A -o148: w.pc+=3; Nwrite2(w.A, w.d0); continue; // DAT0=A B -o149: w.pc+=3; Nwrite2(w.A, w.d1); continue; // DAT1=A B -o14C: w.pc+=3; Nwrite2(w.C, w.d0); continue; // DAT0=C B -o14D: w.pc+=3; Nwrite2(w.C, w.d1); continue; // DAT1=C B - -o142: w.pc+=3; Nread5(w.A, w.d0); continue; // A=DAT0 A -o143: w.pc+=3; Nread5(w.A, w.d1); continue; // A=DAT1 A -o146: w.pc+=3; Nread5(w.C, w.d0); continue; // C=DAT0 A -o147: w.pc+=3; Nread5(w.C, w.d1); continue; // C=DAT1 A -o14A: w.pc+=3; Nread2(w.A, w.d0); continue; // A=DAT0 B -o14B: w.pc+=3; Nread2(w.A, w.d1); continue; // A=DAT1 B -o14E: w.pc+=3; Nread2(w.C, w.d0); continue; // C=DAT0 B -o14F: w.pc+=3; Nread2(w.C, w.d1); continue; // C=DAT0 B - -o150a: w.pc+=4; NFwrite(w.A, w.d0, I[3]); continue;// DAT0=A a -o151a: w.pc+=4; NFwrite(w.A, w.d1, I[3]); continue;// DAT1=A a -o154a: w.pc+=4; NFwrite(w.C, w.d0, I[3]); continue;// DAT0=C a -o155a: w.pc+=4; NFwrite(w.C, w.d1, I[3]); continue;// DAT1=C a -o152a: w.pc+=4; NFread(w.A, w.d0, I[3]); continue;// A=DAT0 a -o153a: w.pc+=4; NFread(w.A, w.d1, I[3]); continue;// A=DAT1 a -o156a: w.pc+=4; NFread(w.C, w.d0, I[3]); continue;// C=DAT0 a -o157a: w.pc+=4; NFread(w.C, w.d1, I[3]); continue;// C=DAT1 a - -o158x: w.pc+=4; Nwrite(w.A, w.d0, I[3]+1); continue;// DAT0=A x -o159x: w.pc+=4; Nwrite(w.A, w.d1, I[3]+1); continue;// DAT1=A x -o15Cx: w.pc+=4; Nwrite(w.C, w.d0, I[3]+1); continue;// DAT0=C x -o15Dx: w.pc+=4; Nwrite(w.C, w.d1, I[3]+1); continue;// DAT1=C x -o15Ax: w.pc+=4; Nread(w.A, w.d0, I[3]+1); continue;// A=DAT0 x -o15Bx: w.pc+=4; Nread(w.A, w.d1, I[3]+1); continue;// A=DAT1 x -o15Ex: w.pc+=4; Nread(w.C, w.d0, I[3]+1); continue;// C=DAT0 x -o15Fx: w.pc+=4; Nread(w.C, w.d1, I[3]+1); continue; // C=DAT1 x - -o16x: // D0=D0+ (n+1) -{ - 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.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.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.pc+=4; - *((BYTE*)&w.d0)=(BYTE)Npack(I+2,2); - continue; -} - -o1Ad4: // D0=(4) #dddd -{ - w.pc+=6; - *((WORD*)&w.d0)=(WORD)Npack(I+2,4); - continue; -} - -o1Bd5: // D0=(5) #ddddd -{ - w.pc+=7; - w.d0=Npack(I+2,5); - continue; -} - -o1Cx: // D1=D1- (n+1) -{ - 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.pc+=4; - *((BYTE*)&w.d1)=(BYTE)Npack(I+2,2); - continue; -} - -o1Ed4: // D1=(4) #dddd -{ - w.pc+=6; - *((WORD*)&w.d1)=(WORD)Npack(I+2,4); - continue; -} - -o1Fd5: // D1=(5) #ddddd -{ - w.pc+=7; - w.d1=Npack(I+2,5); - continue; -} - -o2n: // P= n -{ - w.pc+=2; - w.P=I[1]; - PCHANGED; - continue; -} - -o3X: // LCHEX -{ - UINT n=I[1]+1; - UINT d=16-w.P; - 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.pc+=3; - } - else - { - signed char jmp=I[1]+(I[2]<<4); - if (jmp) - w.pc+=jmp+1; - else - w.pc=rstkpop(); - w.pc&=0xFFFFF; - } - continue; -} - -o5d2: // GONC -{ - if (w.carry) - { - w.pc+=3; - } - else - { - signed char jmp=I[1]+(I[2]<<4); - if (jmp) - w.pc+=jmp+1; - else - w.pc=rstkpop(); - 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.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.pc&=0xFFFFF; - continue; -} - -o800: // OUT=CS -{ - w.pc+=3; - w.out = (w.out&0xff0) | w.C[0]; - ScanKeyboard(); - continue; -} - -o801: // OUT=C -{ - w.pc+=3; - w.out = (WORD)Npack(w.C, 3); - ScanKeyboard(); - continue; -} - -o802: // A=IN -{ - w.pc+=3; - Nunpack(w.A, w.in, 4); - continue; -} - -o803: // C=IN -{ - w.pc+=3; - Nunpack(w.C, w.in, 4); - continue; -} - -o804: // UNCNFG -{ - w.pc+=3; - Uncnfg(); - continue; -} - -o805: // CONFIG -{ - w.pc+=3; - Config(); - continue; -} - -o806: // C=ID -{ - w.pc+=3; - C_Eq_Id(); - continue; -} - -o807: // SHUTDN -{ - w.pc+=3; - if (w.in==0) - { - bInterrupt = TRUE; - w.Shutdn = TRUE; - } - continue; -} - -o8080: // INTON -{ - w.pc+=4; - w.intk = TRUE; - ScanKeyboard(); - continue; -} - -o80810: // RSI -{ - w.pc+=5; - w.intk = TRUE; - ScanKeyboard(); - continue; -} - -o8082X: // LA -{ - UINT n=I[4]+1; - UINT d=16-w.P; - 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.pc+=4; - continue; -} - -o8084n: // ABIT=0 n -{ - w.pc+=5; - Nbit0(w.A, I[4]); - continue; -} - -o8085n: // ABIT=1 n -{ - w.pc+=5; - Nbit1(w.A, I[4]); - continue; -} - -o8086n: // ?ABIT=0 n -{ - w.pc+=5; - Tbit0(w.A, I[4]); - GOYES5; -} - -o8087n: // ?ABIT=1 n -{ - w.pc+=5; - Tbit1(w.A, I[4]); - GOYES5; -} - -o8088n: // CBIT=0 n -{ - w.pc+=5; - Nbit0(w.C, I[4]); - continue; -} - -o8089n: // CBIT=1 n -{ - w.pc+=5; - Nbit1(w.C, I[4]); - continue; -} -o808An: // ?CBIT=0 n -{ - w.pc+=5; - Tbit0(w.C, I[4]); - GOYES5; -} - -o808Bn: // ?CBIT=1 n -{ - w.pc+=5; - Tbit1(w.C, I[4]); - GOYES5; -} - -o808C: // PC=(A) -{ - w.pc=Read5(Npack(w.A,5)); - continue; -} - -o808D: // BUSCD -{ - w.pc+=4; - InfoMessage("BUSCD instruction executed."); - continue; -} - -o808E: // PC=(C) -{ - w.pc=Read5(Npack(w.C,5)); - continue; -} - -o808F: // INTOFF -{ - w.pc+=4; - w.intk = FALSE; - ScanKeyboard(); - continue; -} - -o809: // C+P+1 - HEX MODE -{ - w.pc+=3; - w.C[0]+=w.P; Nincx(w.C,5); - continue; -} - -o80A: // RESET -{ - w.pc+=3; - Reset(); - continue; -} - -o80B: // BUSCC -{ - w.pc+=3; - InfoMessage("BUSCC instruction executed."); - continue; -} - -o80Cn: // C=P n -{ - w.pc+=4; - w.C[I[3]] = w.P; - continue; -} - -o80Dn: // P=C n -{ - w.pc+=4; - w.P = w.C[I[3]]; - PCHANGED; - continue; -} - -o80E: // SREQ -{ - 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.pc+=4; - continue; -} - -o810: // ASLC -{ - w.pc+=3; - Nslc(w.A, 16); - continue; -} - -o811: // BSLC -{ - w.pc+=3; - Nslc(w.B, 16); - continue; -} - -o812: // CSLC -{ - w.pc+=3; - Nslc(w.C, 16); - continue; -} - -o813: // DSLC -{ - w.pc+=3; - Nslc(w.D, 16); - continue; -} - -o814: // ASRC -{ - w.pc+=3; - Nsrc(w.A, 16); - continue; -} - -o815: // BSRC -{ - w.pc+=3; - Nsrc(w.B, 16); - continue; -} - -o816: // CSRC -{ - w.pc+=3; - Nsrc(w.C, 16); - continue; -} - -o817: // DSRC -{ - w.pc+=3; - Nsrc(w.D, 16); - continue; -} - -o818f0x: // A=A+x+1 f -{ - w.pc+=6; - w.A[F_s[I[3]]]+=I[5]; - NFinc(w.A,I[3]); - continue; -} - -o818f1x: // B=B+x+1 f -{ - w.pc+=6; - w.B[F_s[I[3]]]+=I[5]; - NFinc(w.B,I[3]); - continue; -} - -o818f2x: // C=C+x+1 f -{ - w.pc+=6; - w.C[F_s[I[3]]]+=I[5]; - NFinc(w.C,I[3]); - continue; -} - -o818f3x: // D=D+x+1 f -{ - w.pc+=6; - w.D[F_s[I[3]]]+=I[5]; - NFinc(w.D,I[3]); - continue; -} - -o818f8x: // A=A-x-1 f -{ - w.pc+=6; - w.A[F_s[I[3]]]-=I[5]; - NFdec(w.A,I[3]); - continue; -} - -o818f9x: // B=B-x-1 f -{ - w.pc+=6; - w.B[F_s[I[3]]]-=I[5]; - NFdec(w.B,I[3]); - continue; -} - -o818fAx: // C=C-x-1 f -{ - w.pc+=6; - w.C[F_s[I[3]]]-=I[5]; - NFdec(w.C,I[3]); - continue; -} - -o818fBx: // D=D-x-1 f -{ - w.pc+=6; - w.D[F_s[I[3]]]-=I[5]; - NFdec(w.D,I[3]); - continue; -} - -o819f0: // ASRB -{ - w.pc+=5; - NFsrb(w.A, I[3]); - continue; -} - -o819f1: // BSRB -{ - w.pc+=5; - NFsrb(w.B, I[3]); - continue; -} - -o819f2: // CSRB -{ - w.pc+=5; - NFsrb(w.C, I[3]); - continue; -} - -o819f3: // DSRB -{ - w.pc+=5; - NFsrb(w.D, I[3]); - continue; -} - -o81Af00: // R0=A f -{ - w.pc+=6; - NFcopy(w.R0, w.A, I[3]); - continue; -} - -o81Af01: // R1=A f -{ - w.pc+=6; - NFcopy(w.R1, w.A, I[3]); - continue; -} - -o81Af02: // R2=A f -{ - w.pc+=6; - NFcopy(w.R2, w.A, I[3]); - continue; -} - -o81Af03: // R3=A f -{ - w.pc+=6; - NFcopy(w.R3, w.A, I[3]); - continue; -} - -o81Af04: // R4=A f -{ - w.pc+=6; - NFcopy(w.R4, w.A, I[3]); - continue; -} - -o81Af08: // R0=C f -{ - w.pc+=6; - NFcopy(w.R0, w.C, I[3]); - continue; -} - -o81Af09: // R1=C f -{ - w.pc+=6; - NFcopy(w.R1, w.C, I[3]); - continue; -} - -o81Af0A: // R2=C f -{ - w.pc+=6; - NFcopy(w.R2, w.C, I[3]); - continue; -} - -o81Af0B: // R3=C f -{ - w.pc+=6; - NFcopy(w.R3, w.C, I[3]); - continue; -} - -o81Af0C: // R4=C f -{ - w.pc+=6; - NFcopy(w.R4, w.C, I[3]); - continue; -} - -o81Af10: // A=R0 f -{ - w.pc+=6; - NFcopy(w.A, w.R0, I[3]); - continue; -} - -o81Af11: // A=R1 f -{ - w.pc+=6; - NFcopy(w.A, w.R1, I[3]); - continue; -} - -o81Af12: // A=R2 f -{ - w.pc+=6; - NFcopy(w.A, w.R2, I[3]); - continue; -} - -o81Af13: // A=R3 f -{ - w.pc+=6; - NFcopy(w.A, w.R3, I[3]); - continue; -} - -o81Af14: // A=R4 f -{ - w.pc+=6; - NFcopy(w.A, w.R4, I[3]); - continue; -} - -o81Af18: // C=R0 f -{ - w.pc+=6; - NFcopy(w.C, w.R0, I[3]); - continue; -} - -o81Af19: // C=R1 f -{ - w.pc+=6; - NFcopy(w.C, w.R1, I[3]); - continue; -} - -o81Af1A: // C=R2 f -{ - w.pc+=6; - NFcopy(w.C, w.R2, I[3]); - continue; -} - -o81Af1B: // C=R3 f -{ - w.pc+=6; - NFcopy(w.C, w.R3, I[3]); - continue; -} - -o81Af1C: // C=R4 f -{ - w.pc+=6; - NFcopy(w.C, w.R4, I[3]); - continue; -} - -o81Af20: // AR0EX f -{ - w.pc+=6; - NFxchg(w.A, w.R0, I[3]); - continue; -} - -o81Af21: // AR1EX f -{ - w.pc+=6; - NFxchg(w.A, w.R1, I[3]); - continue; -} - -o81Af22: // AR2EX f -{ - w.pc+=6; - NFxchg(w.A, w.R2, I[3]); - continue; -} - -o81Af23: // AR3EX f -{ - w.pc+=6; - NFxchg(w.A, w.R3, I[3]); - continue; -} - -o81Af24: // AR4EX f -{ - w.pc+=6; - NFxchg(w.A, w.R4, I[3]); - continue; -} - -o81Af28: // CR0EX f -{ - w.pc+=6; - NFxchg(w.C, w.R0, I[3]); - continue; -} - -o81Af29: // CR1EX f -{ - w.pc+=6; - NFxchg(w.C, w.R1, I[3]); - continue; -} - -o81Af2A: // CR2EX f -{ - w.pc+=6; - NFxchg(w.C, w.R2, I[3]); - continue; -} - -o81Af2B: // CR3EX f -{ - w.pc+=6; - NFxchg(w.C, w.R3, I[3]); - continue; -} - -o81Af2C: // CR4EX f -{ - w.pc+=6; - NFxchg(w.C, w.R4, I[3]); - continue; -} - -o81B2: // PC=A -{ - w.pc = Npack(w.A,5); - continue; -} - -o81B3: // PC=C -{ - w.pc = Npack(w.C,5); - continue; -} - -o81B4: // A=PC -{ - w.pc+=4; - Nunpack(w.A,w.pc,5); - continue; -} - -o81B5: // C=PC -{ - w.pc+=4; - Nunpack(w.C,w.pc,5); - continue; -} - -o81B6: // APCEX -{ - DWORD d=w.pc+4; - w.pc=Npack(w.A,5); - Nunpack(w.A,d,5); - continue; -} - -o81B7: // CPCEX -{ - DWORD d=w.pc+4; - w.pc=Npack(w.C,5); - Nunpack(w.C,d,5); - continue; -} - -o81C: // ASRB -{ - w.pc+=3; - Nsrb(w.A, 16); - continue; -} - -o81D: // BSRB -{ - w.pc+=3; - Nsrb(w.B, 16); - continue; -} - -o81E: // CSRB -{ - w.pc+=3; - Nsrb(w.C, 16); - continue; -} - -o81F: // DSRB -{ - w.pc+=3; - Nsrb(w.D, 16); - continue; -} - -o82n: // HST=0 m -{ - w.pc+=3; - w.HST&=~I[2]; - continue; -} - -o83n: // ?HST=0 m -{ - w.pc+=3; - if ((w.HST&I[2])==0) - w.carry=TRUE; - else - w.carry=FALSE; - GOYES3; -} - -o84n: // ST=0 n -{ - w.pc+=3; - Nbit0(w.ST, I[2]); - continue; -} - -o85n: // ST=1 n -{ - w.pc+=3; - Nbit1(w.ST, I[2]); - continue; -} - -o86n: // ?ST=0 n -{ - w.pc+=3; - Tbit0(w.ST, I[2]); - GOYES3; -} - -o87n: // ?ST=1 n -{ - w.pc+=3; - Tbit1(w.ST, I[2]); - GOYES3; -} - -o88n: // ?P# n -{ - w.pc+=3; - if (w.P!=I[2]) - w.carry=TRUE; - else - w.carry=FALSE; - GOYES3; -} - -o89n: // ?P= n -{ - w.pc+=3; - if (w.P==I[2]) - w.carry=TRUE; - else - w.carry=FALSE; - GOYES3; -} - -o8A0: // ?A=B A -{ - w.pc+=3; - Te(w.A, w.B, 5); - GOYES3; -} - -o8A1: // ?B=C A -{ - w.pc+=3; - Te(w.B, w.C, 5); - GOYES3; -} - -o8A2: // ?C=A A -{ - w.pc+=3; - Te(w.C, w.A, 5); - GOYES3; -} - -o8A3: // ?D=C A -{ - w.pc+=3; - Te(w.D, w.C, 5); - GOYES3; -} - -o8A4: // ?A#B A -{ - w.pc+=3; - Tne(w.A, w.B, 5); - GOYES3; -} - -o8A5: // ?B#C A -{ - w.pc+=3; - Tne(w.B, w.C, 5); - GOYES3; -} - -o8A6: // ?C#A A -{ - w.pc+=3; - Tne(w.C, w.A, 5); - GOYES3; -} - -o8A7: // ?D#C A -{ - w.pc+=3; - Tne(w.D, w.C, 5); - GOYES3; -} - -o8A8: // ?A=0 A -{ - w.pc+=3; - Tz(w.A, 5); - GOYES3; -} - -o8A9: // ?B=0 A -{ - w.pc+=3; - Tz(w.B, 5); - GOYES3; -} - -o8AA: // ?C=0 A -{ - w.pc+=3; - Tz(w.C, 5); - GOYES3; -} - -o8AB: // ?D=0 A -{ - w.pc+=3; - Tz(w.D, 5); - GOYES3; -} - -o8AC: // ?A#0 A -{ - w.pc+=3; - Tnz(w.A, 5); - GOYES3; -} - -o8AD: // ?B#0 A -{ - w.pc+=3; - Tnz(w.B, 5); - GOYES3; -} - -o8AE: // ?C#0 A -{ - w.pc+=3; - Tnz(w.C, 5); - GOYES3; -} - -o8AF: // ?D#0 A -{ - w.pc+=3; - Tnz(w.D, 5); - GOYES3; -} - -o8B0: // ?A>B A -{ - w.pc+=3; - Ta(w.A, w.B, 5); - GOYES3; -} - -o8B1: // ?B>C A -{ - w.pc+=3; - Ta(w.B, w.C, 5); - GOYES3; -} - -o8B2: // ?C>A A -{ - w.pc+=3; - Ta(w.C, w.A, 5); - GOYES3; -} - -o8B3: // ?D>C A -{ - w.pc+=3; - Ta(w.D, w.C, 5); - GOYES3; -} - -o8B4: // ?A=B A -{ - w.pc+=3; - Tae(w.A, w.B, 5); - GOYES3; -} - -o8B9: // ?B>=C A -{ - w.pc+=3; - Tae(w.B, w.C, 5); - GOYES3; -} - -o8BA: // ?C>=A A -{ - w.pc+=3; - Tae(w.C, w.A, 5); - GOYES3; -} - -o8BB: // ?D>=C A -{ - w.pc+=3; - Tae(w.D, w.C, 5); - GOYES3; -} - -o8BC: // ?A<=B A -{ - w.pc+=3; - Tbe(w.A, w.B, 5); - GOYES3; -} - -o8BD: // ?B<=C A -{ - w.pc+=3; - Tbe(w.B, w.C, 5); - GOYES3; -} - -o8BE: // ?C<=A A -{ - w.pc+=3; - Tbe(w.C, w.A, 5); - GOYES3; -} - -o8BF: // ?D<=C A -{ - 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.pc&=0xFFFFF; - continue; -} - -o8Dd5: // GOVLNG #ddddd -{ - 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.pc&=0xFFFFF; - continue; -} - -o8Fd5: // GOSBVL #ddddd -{ - rstkpush(w.pc+7); - w.pc=Npack(I+2, 5); - continue; -} - -// ?r=s f -o9a0: w.pc+=3; TFe(w.A, w.B, I[1]); GOYES3; -o9a1: w.pc+=3; TFe(w.B, w.C, I[1]); GOYES3; -o9a2: w.pc+=3; TFe(w.C, w.A, I[1]); GOYES3; -o9a3: w.pc+=3; TFe(w.D, w.C, I[1]); GOYES3; - - // ?r#s f -o9a4: w.pc+=3; TFne(w.A, w.B, I[1]); GOYES3; -o9a5: w.pc+=3; TFne(w.B, w.C, I[1]); GOYES3; -o9a6: w.pc+=3; TFne(w.C, w.A, I[1]); GOYES3; -o9a7: w.pc+=3; TFne(w.D, w.C, I[1]); GOYES3; - - // ?r=0 f -o9a8: w.pc+=3; TFz(w.A, I[1]); GOYES3; -o9a9: w.pc+=3; TFz(w.B, I[1]); GOYES3; -o9aA: w.pc+=3; TFz(w.C, I[1]); GOYES3; -o9aB: w.pc+=3; TFz(w.D, I[1]); GOYES3; - - // ?r#0 f -o9aC: w.pc+=3; TFnz(w.A, I[1]); GOYES3; -o9aD: w.pc+=3; TFnz(w.B, I[1]); GOYES3; -o9aE: w.pc+=3; TFnz(w.C, I[1]); GOYES3; -o9aF: w.pc+=3; TFnz(w.D, I[1]); GOYES3; - - // ?s>r f -o9b0: w.pc+=3; TFa(w.A, w.B, I[1]&7); GOYES3; -o9b1: w.pc+=3; TFa(w.B, w.C, I[1]&7); GOYES3; -o9b2: w.pc+=3; TFa(w.C, w.A, I[1]&7); GOYES3; -o9b3: w.pc+=3; TFa(w.D, w.C, I[1]&7); GOYES3; - - // ?r=s f -o9b8: w.pc+=3; TFae(w.A, w.B, I[1]&7); GOYES3; -o9b9: w.pc+=3; TFae(w.B, w.C, I[1]&7); GOYES3; -o9bA: w.pc+=3; TFae(w.C, w.A, I[1]&7); GOYES3; -o9bB: w.pc+=3; TFae(w.D, w.C, I[1]&7); GOYES3; - - // ?r<=s f -o9bC: w.pc+=3; TFbe(w.A, w.B, I[1]&7); GOYES3; -o9bD: w.pc+=3; TFbe(w.B, w.C, I[1]&7); GOYES3; -o9bE: w.pc+=3; TFbe(w.C, w.A, I[1]&7); GOYES3; -o9bF: w.pc+=3; TFbe(w.D, w.C, I[1]&7); GOYES3; - - // r=r+s f -oAa0: w.pc+=3; NFadd(w.A, w.B, I[1]); continue; -oAa1: w.pc+=3; NFadd(w.B, w.C, I[1]); continue; -oAa2: w.pc+=3; NFadd(w.C, w.A, I[1]); continue; -oAa3: w.pc+=3; NFadd(w.D, w.C, I[1]); continue; - - // r=r+r f -oAa4: w.pc+=3; NFdbl(w.A, I[1]); continue; -oAa5: w.pc+=3; NFdbl(w.B, I[1]); continue; -oAa6: w.pc+=3; NFdbl(w.C, I[1]); continue; -oAa7: w.pc+=3; NFdbl(w.D, I[1]); continue; - - // s=s+r f -oAa8: w.pc+=3; NFadd(w.B, w.A, I[1]); continue; -oAa9: w.pc+=3; NFadd(w.C, w.B, I[1]); continue; -oAaA: w.pc+=3; NFadd(w.A, w.C, I[1]); continue; -oAaB: w.pc+=3; NFadd(w.C, w.D, I[1]); continue; - - // r=r-1 f -oAaC: w.pc+=3; NFdec(w.A, I[1]); continue; -oAaD: w.pc+=3; NFdec(w.B, I[1]); continue; -oAaE: w.pc+=3; NFdec(w.C, I[1]); continue; -oAaF: w.pc+=3; NFdec(w.D, I[1]); continue; - - // r=0 f -oAb0: w.pc+=3; NFzero(w.A, I[1]&7); continue; -oAb1: w.pc+=3; NFzero(w.B, I[1]&7); continue; -oAb2: w.pc+=3; NFzero(w.C, I[1]&7); continue; -oAb3: w.pc+=3; NFzero(w.D, I[1]&7); continue; - - // r=s f -oAb4: w.pc+=3; NFcopy(w.A, w.B, I[1]&7); continue; -oAb5: w.pc+=3; NFcopy(w.B, w.C, I[1]&7); continue; -oAb6: w.pc+=3; NFcopy(w.C, w.A, I[1]&7); continue; -oAb7: w.pc+=3; NFcopy(w.D, w.C, I[1]&7); continue; - - // s=r f -oAb8: w.pc+=3; NFcopy(w.B, w.A, I[1]&7); continue; -oAb9: w.pc+=3; NFcopy(w.C, w.B, I[1]&7); continue; -oAbA: w.pc+=3; NFcopy(w.A, w.C, I[1]&7); continue; -oAbB: w.pc+=3; NFcopy(w.C, w.D, I[1]&7); continue; - - // rsEX f -oAbC: w.pc+=3; NFxchg(w.A, w.B, I[1]&7); continue; -oAbD: w.pc+=3; NFxchg(w.B, w.C, I[1]&7); continue; -oAbE: w.pc+=3; NFxchg(w.C, w.A, I[1]&7); continue; -oAbF: w.pc+=3; NFxchg(w.D, w.C, I[1]&7); continue; - - // r=r-s f -oBa0: w.pc+=3; NFsub(w.A, w.B, I[1]); continue; -oBa1: w.pc+=3; NFsub(w.B, w.C, I[1]); continue; -oBa2: w.pc+=3; NFsub(w.C, w.A, I[1]); continue; -oBa3: w.pc+=3; NFsub(w.D, w.C, I[1]); continue; - - // r=r+1 f -oBa4: w.pc+=3; NFinc(w.A, I[1]); continue; -oBa5: w.pc+=3; NFinc(w.B, I[1]); continue; -oBa6: w.pc+=3; NFinc(w.C, I[1]); continue; -oBa7: w.pc+=3; NFinc(w.D, I[1]); continue; - - // s=s-r f -oBa8: w.pc+=3; NFsub(w.B, w.A, I[1]); continue; -oBa9: w.pc+=3; NFsub(w.C, w.B, I[1]); continue; -oBaA: w.pc+=3; NFsub(w.A, w.C, I[1]); continue; -oBaB: w.pc+=3; NFsub(w.C, w.D, I[1]); continue; - - // r=s-r f -oBaC: w.pc+=3; NFrsub(w.A, w.B, I[1]); continue; -oBaD: w.pc+=3; NFrsub(w.B, w.C, I[1]); continue; -oBaE: w.pc+=3; NFrsub(w.C, w.A, I[1]); continue; -oBaF: w.pc+=3; NFrsub(w.D, w.C, I[1]); continue; - - // rSL f -oBb0: w.pc+=3; NFsl(w.A, I[1]&7); continue; -oBb1: w.pc+=3; NFsl(w.B, I[1]&7); continue; -oBb2: w.pc+=3; NFsl(w.C, I[1]&7); continue; -oBb3: w.pc+=3; NFsl(w.D, I[1]&7); continue; - - // rSR f -oBb4: w.pc+=3; NFsr(w.A, I[1]&7); continue; -oBb5: w.pc+=3; NFsr(w.B, I[1]&7); continue; -oBb6: w.pc+=3; NFsr(w.C, I[1]&7); continue; -oBb7: w.pc+=3; NFsr(w.D, I[1]&7); continue; - - // r=-r f -oBb8: w.pc+=3; NFneg(w.A, I[1]&7); continue; -oBb9: w.pc+=3; NFneg(w.B, I[1]&7); continue; -oBbA: w.pc+=3; NFneg(w.C, I[1]&7); continue; -oBbB: w.pc+=3; NFneg(w.D, I[1]&7); continue; - - // r=-r-1 f -oBbC: w.pc+=3; NFnot(w.A, I[1]&7); continue; -oBbD: w.pc+=3; NFnot(w.B, I[1]&7); continue; -oBbE: w.pc+=3; NFnot(w.C, I[1]&7); continue; -oBbF: w.pc+=3; NFnot(w.D, I[1]&7); continue; - - // r=r+s -oC0: w.pc+=2; Nadd(w.A, w.B, 5); continue; -oC1: w.pc+=2; Nadd(w.B, w.C, 5); continue; -oC2: w.pc+=2; Nadd(w.C, w.A, 5); continue; -oC3: w.pc+=2; Nadd(w.D, w.C, 5); continue; - - // r=r+r A -oC4: w.pc+=2; Ndbl(w.A, 5); continue; -oC5: w.pc+=2; Ndbl(w.B, 5); continue; -oC6: w.pc+=2; Ndbl(w.C, 5); continue; -oC7: w.pc+=2; Ndbl(w.D, 5); continue; - - // s=s+r A -oC8: w.pc+=2; Nadd(w.B, w.A, 5); continue; -oC9: w.pc+=2; Nadd(w.C, w.B, 5); continue; -oCA: w.pc+=2; Nadd(w.A, w.C, 5); continue; -oCB: w.pc+=2; Nadd(w.C, w.D, 5); continue; - - // r=r-1 A -oCC: w.pc+=2; Ndec(w.A, 5); continue; -oCD: w.pc+=2; Ndec(w.B, 5); continue; -oCE: w.pc+=2; Ndec(w.C, 5); continue; -oCF: w.pc+=2; Ndec(w.D, 5); continue; - - // r=0 A -oD0: w.pc+=2; memset(w.A, 0, 5); continue; -oD1: w.pc+=2; memset(w.B, 0, 5); continue; -oD2: w.pc+=2; memset(w.C, 0, 5); continue; -oD3: w.pc+=2; memset(w.D, 0, 5); continue; - - // r=s A -oD4: w.pc+=2; memcpy(w.A, w.B, 5); continue; -oD5: w.pc+=2; memcpy(w.B, w.C, 5); continue; -oD6: w.pc+=2; memcpy(w.C, w.A, 5); continue; -oD7: w.pc+=2; memcpy(w.D, w.C, 5); continue; - - // s=r A -oD8: w.pc+=2; memcpy(w.B, w.A, 5); continue; -oD9: w.pc+=2; memcpy(w.C, w.B, 5); continue; -oDA: w.pc+=2; memcpy(w.A, w.C, 5); continue; -oDB: w.pc+=2; memcpy(w.C, w.D, 5); continue; - - // rsEX -oDC: w.pc+=2; Nxchg(w.A, w.B, 5); continue; -oDD: w.pc+=2; Nxchg(w.B, w.C, 5); continue; -oDE: w.pc+=2; Nxchg(w.C, w.A, 5); continue; -oDF: w.pc+=2; Nxchg(w.D, w.C, 5); continue; - - // r=r-s A -oE0: w.pc+=2; Nsub(w.A, w.B, 5); continue; -oE1: w.pc+=2; Nsub(w.B, w.C, 5); continue; -oE2: w.pc+=2; Nsub(w.C, w.A, 5); continue; -oE3: w.pc+=2; Nsub(w.D, w.C, 5); continue; - - // r=r+1 A -oE4: w.pc+=2; Ninc(w.A, 5); continue; -oE5: w.pc+=2; Ninc(w.B, 5); continue; -oE6: w.pc+=2; Ninc(w.C, 5); continue; -oE7: w.pc+=2; Ninc(w.D, 5); continue; - - // s=s-r A -oE8: w.pc+=2; Nsub(w.B, w.A, 5); continue; -oE9: w.pc+=2; Nsub(w.C, w.B, 5); continue; -oEA: w.pc+=2; Nsub(w.A, w.C, 5); continue; -oEB: w.pc+=2; Nsub(w.C, w.D, 5); continue; - - // r=s-r A -oEC: w.pc+=2; Nrsub(w.A, w.B, 5); continue; -oED: w.pc+=2; Nrsub(w.B, w.C, 5); continue; -oEE: w.pc+=2; Nrsub(w.C, w.A, 5); continue; -oEF: w.pc+=2; Nrsub(w.D, w.C, 5); continue; - - // rSL A -oF0: w.pc+=2; Nsl(w.A, 5); continue; -oF1: w.pc+=2; Nsl(w.B, 5); continue; -oF2: w.pc+=2; Nsl(w.C, 5); continue; -oF3: w.pc+=2; Nsl(w.D, 5); continue; - - // rSR A -oF4: w.pc+=2; Nsr(w.A, 5); continue; -oF5: w.pc+=2; Nsr(w.B, 5); continue; -oF6: w.pc+=2; Nsr(w.C, 5); continue; -oF7: w.pc+=2; Nsr(w.D, 5); continue; - - // r=-r A -oF8: w.pc+=2; Nneg(w.A, 5); continue; -oF9: w.pc+=2; Nneg(w.B, 5); continue; -oFA: w.pc+=2; Nneg(w.C, 5); continue; -oFB: w.pc+=2; Nneg(w.D, 5); continue; - - // r=-r-1 A -oFC: w.pc+=2; Nnot(w.A, 5); continue; -oFD: w.pc+=2; Nnot(w.B, 5); continue; -oFE: w.pc+=2; Nnot(w.C, 5); continue; -oFF: w.pc+=2; Nnot(w.D, 5); continue; - - // invalid, unknown length : reset -o_invalid: -{ - w.pc=0; - continue; -} - -// length is guessed, just skip -o_invalid3: -{ - w.pc+=3; - continue; -} - -o_invalid4: -{ - w.pc+=4; - continue; -} - -o_invalid5: -{ - w.pc+=5; - continue; -} - -o_invalid6: -{ - w.pc+=6; - continue; -} - -o_goyes3: -{ - signed char jmp = I[3]+(I[4]<<4); - if (jmp) - w.pc=(w.pc+jmp)&0xFFFFF; - else - w.pc=rstkpop(); - continue; -} - -o_goyes5: -{ - signed char jmp = I[5]+(I[6]<<4); - if (jmp) - w.pc=(w.pc+jmp)&0xFFFFF; - else - w.pc=rstkpop(); - continue; -} - -//////// EXTENSIONS //////// -o81B0: - // ?Win48 - w.HST |= SB; - w.pc+=4; - continue; - -o81B1: - External(&w); - continue; -//////////////////////////// diff --git a/Emu48/resource.h b/Emu48/resource.h deleted file mode 100644 index 46a5319..0000000 --- a/Emu48/resource.h +++ /dev/null @@ -1,64 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by Emu48.rc -// -#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 110 -#define IDC_PORT1WR 1000 -#define IDC_AUTOSAVE 1001 -#define IDC_AUTOSAVEONEXIT 1002 -#define IDC_EMU48DIR 1003 -#define IDC_BROWSEDIR 1004 -#define IDC_REFRESH 1004 -#define IDC_KMLSCRIPT 1005 -#define IDC_AUTHOR 1006 -#define IDC_TITLE 1007 -#define IDC_KMLLOG 1008 -#define IDC_VERSION 1010 -#define IDC_PORT2ISSHARED 1011 -#define IDC_PORT2 1012 -#define IDC_T1PERIOD 1013 -#define IDC_ALWAYSDISPLOG 1016 -#define IDC_T1DEFAULT 1019 -#define IDC_NAME 1020 -#define IDC_REGTEXT 1021 -#define IDC_CODE 1022 -#define IDC_REGISTER 1022 -#define IDC_UPDATE 1024 -#define IDC_USEMMTIMER 1025 -#define IDC_LICENSE 1026 -#define ID_FILE_NEW 40001 -#define ID_FILE_OPEN 40002 -#define ID_FILE_SAVE 40003 -#define ID_FILE_SAVEAS 40004 -#define ID_FILE_EXIT 40005 -#define ID_VIEW_COPY 40006 -#define ID_VIEW_SETTINGS 40007 -#define ID_VIEW_RESET 40008 -#define ID_OBJECT_LOAD 40009 -#define ID_OBJECT_SAVE 40010 -#define ID_ABOUT 40011 -#define ID_FILE_CLOSE 40013 -#define ID_BACKUP_SAVE 40014 -#define ID_BACKUP_RESTORE 40015 -#define ID_BACKUP_DELETE 40016 -#define ID_VIEW_SCRIPT 40017 -#define ID_HELP_REGISTER 40018 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 112 -#define _APS_NEXT_COMMAND_VALUE 40019 -#define _APS_NEXT_CONTROL_VALUE 1027 -#define _APS_NEXT_SYMED_VALUE 108 -#endif -#endif diff --git a/Emu48/timer.c b/Emu48/timer.c deleted file mode 100644 index c8d8940..0000000 --- a/Emu48/timer.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * timer.c - * - * This file is part of Emu48 - * - * Copyright (C) 1995 Sebastien Carlier - * - */ -#include "pch.h" -#include "Emu48.h" - -BOOL bAccurateTimer = TRUE; -UINT uT1Period = 62; - -static BOOL bStarted = FALSE; -static UINT uT1TimerId = 0; -static UINT uT2TimerId = 0; -static DWORD dwT1Ticks = 0; -static DWORD dwT2Init = 0; -static DWORD dwT2Step = 0; -static DWORD dwT2Ticks = 0; - -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 CheckT1() -{ - _ASSERT(bStarted); - if ((Chipset.t1&8) == 0) - { - Chipset.IORam[0x2E] &= 0x7; // clear bit 3 - return; - } - if (Chipset.IORam[0x2E]&4) - { // T1 -> Wake Up - if (Chipset.Shutdn) - { - ResumeThread(hThread); - Chipset.IORam[0x2E] &= 0xB; // clear bit 2 - Chipset.IORam[0x2E] |= 0x8; // set bit 3 - } - } - if (Chipset.IORam[0x2E]&2) - { // T1 -> Interrupt - Chipset.IORam[0x2E] |= 0x8; // set bit 3 - Chipset.SoftInt = TRUE; - bInterrupt=TRUE; - } - return; -} - -static VOID CheckT2() -{ - _ASSERT(bStarted); - if ((Chipset.t2&0x80000000) == 0) - { - Chipset.IORam[0x2F] &= 7; // clear bit 3 - return; - } - if (Chipset.IORam[0x2F]&4) - { // T2 -> Wake Up - if (Chipset.Shutdn) - { - ResumeThread(hThread); - Chipset.IORam[0x2F] &= 0xB; // clear bit 2 - Chipset.IORam[0x2F] |= 0x8; // set bit 3 - } - } - if (Chipset.IORam[0x2F]&2) - { // T2 -> Interrupt - Chipset.IORam[0x2F] |= 0x8; // set bit 3 - Chipset.SoftInt = TRUE; - bInterrupt=TRUE; - } - return; -} - -static VOID RescheduleT2() -{ - _ASSERT(uT2TimerId == 0); - dwT2Init = timeGetTime(); - dwT2Ticks = dwT2Init; - uT2TimerId = timeSetEvent(MAX(16,Chipset.t2>>3),0,(LPTIMECALLBACK)&TimeProc,2,TIME_ONESHOT); - return; -} - -static VOID AbortT2() -{ - _ASSERT(uT2TimerId != 0); - uT2TimerId = 0; - timeKillEvent(uT2TimerId); - return; -} - -static void CALLBACK TimeProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) -{ - if (!bStarted) - return; - if ((uT1TimerId!=0) && (uEventId == uT1TimerId)) - { - Chipset.t1 = (Chipset.t1-1)&0xF; - CheckT1(); - return; - } - if ((uT2TimerId!=0) && (uEventId == uT2TimerId)) - { - uT2TimerId = 0; - Chipset.t2 = 0xFFFFFFFF; - CheckT2(); - RescheduleT2(); - return; - } - return; - UNREFERENCED_PARAMETER(uMsg); -} - - -VOID StartTimers() -{ - if (bStarted) - return; - if (Chipset.IORam[0x2F]&1) - { - bStarted = TRUE; - if (bAccurateTimer) - { - MMRESULT uResult; - uResult = timeBeginPeriod(1); - if (uResult!=TIMERR_NOERROR) - bAccurateTimer=FALSE; - } - uT1TimerId = timeSetEvent(uT1Period,0,(LPTIMECALLBACK)&TimeProc,1,TIME_PERIODIC); - RescheduleT2(); - } - return; -} - -VOID StopTimers() -{ - if (!bStarted) - return; - Chipset.t2 = ReadT2(); - if (uT1TimerId != 0) - { - timeKillEvent(uT1TimerId); - uT1TimerId = 0; - } - if (uT2TimerId != 0) - AbortT2(); - bStarted = FALSE; - if (bAccurateTimer) - { - timeEndPeriod(1); - } - return; -} - -DWORD ReadT2() -{ - DWORD dwT2; - if (!bStarted) - { - dwT2 = Chipset.t2; - } - else - { - DWORD dwNow = timeGetTime(); - if (dwNow == dwT2Ticks) - { - if (dwT2Step < 7) - dwT2Step++; - return Chipset.t2-(8*(dwNow-dwT2Init)+dwT2Step); - } - dwT2Step = 0; - dwT2Ticks = dwNow; - dwT2 = Chipset.t2-8*(dwNow-dwT2Init); - } - return dwT2; -} - -VOID SetT2(DWORD dwValue) -{ - if (!bStarted) - { - Chipset.t2 = dwValue; - return; - } - if (uT2TimerId != 0) - AbortT2(); - Chipset.t2 = dwValue; - CheckT2(); - RescheduleT2(); - return; -} - -BYTE ReadT1() -{ - return Chipset.t1; -} - -VOID SetT1(BYTE byValue) -{ - Chipset.t1 = byValue&0xF; - CheckT1(); - return; -} - diff --git a/Emu48/types.h b/Emu48/types.h deleted file mode 100644 index 5c6ed91..0000000 --- a/Emu48/types.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * types.h - * - * This file is part of Emu48 - * - * Copyright (C) 1995 Sebastien Carlier - * - */ - -#define CHIPSET Chipset_t -typedef struct -{ - WORD wPosX; - WORD wPosY; - BYTE type; - - DWORD Port0Size; - DWORD Port1Size; - DWORD Port2Size; - LPBYTE Port0; - LPBYTE Port1; - LPBYTE Port2; - - DWORD pc; - DWORD d0; - DWORD d1; - DWORD rstkp; - DWORD rstk[8]; - BYTE A[16]; - BYTE B[16]; - BYTE C[16]; - BYTE D[16]; - BYTE R0[16]; - BYTE R1[16]; - BYTE R2[16]; - BYTE R3[16]; - BYTE R4[16]; - BYTE ST[4]; - BYTE HST; - BYTE P; - WORD out; - WORD in; - BOOL SoftInt; - BOOL Shutdn; - BOOL mode_dec; - BOOL inte; - BOOL intk; - BOOL intd; - BOOL carry; - - WORD crc; - UINT uUnused1; - UINT Port2_Size; - BOOL Port1_Writeable; - BOOL Port2_Writeable; - UINT Port2_Bank; - UINT Port2_NBanks; - BYTE cards_status; - BYTE IORam[64]; - UINT IOBase; - BOOL IOCfig; - BYTE P0Base, BSBase, P1Base, P2Base; - BYTE P0Size, BSSize, P1Size, P2Size; - BYTE P0End, BSEnd, P1End, P2End; - BOOL P0Cfig, BSCfig, P1Cfig, P2Cfig; - BOOL P0Cfg2, BSCfg2, P1Cfg2, P2Cfg2; - - BYTE t1; - DWORD t2; - DWORD t2_ticks; - - BYTE Keyboard_Row[9]; - WORD IR15X; - UINT Keyboard_State; - - signed short loffset; - signed int width; - UINT boffset; - UINT lcounter; - UINT sync; - BYTE contrast; - BOOL dispon; - DWORD start1; - DWORD start12; - DWORD end1; - DWORD start2, end2; -} Chipset_t; diff --git a/FLOAT_GX.BMP b/FLOAT_GX.BMP new file mode 100644 index 0000000000000000000000000000000000000000..cf7328a04f0fdf05c5447f977c54668ec655333f GIT binary patch literal 151308 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 literal 0 HcmV?d00001 diff --git a/FLOAT_GX.KML b/FLOAT_GX.KML new file mode 100644 index 0000000..13f8831 --- /dev/null +++ b/FLOAT_GX.KML @@ -0,0 +1,401 @@ +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 "Floating Buttons for GX" + Author "Casey Patterson" + Model "G" + Rom "ROM.48G" + Patch "BEEP.EXT" + Debug 0 + Bitmap "float_gx.bmp" +End + +Background + Offset 0 0 + Size 302 485 +End + +Lcd + Zoom 2 + Offset 20 20 + Color 0 255 255 255 + 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 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 15 11 + Offset 41 4 + Down 16 485 +End + +Annunciator 2 + Size 15 11 + Offset 82 4 + Down 32 485 +End + +Annunciator 3 + Size 13 11 + Offset 123 4 + Down 48 485 +End + +Annunciator 4 + Size 15 11 + Offset 164 4 + Down 64 485 +End + +Annunciator 5 + Size 11 11 + Offset 205 4 + Down 80 485 +End + +Annunciator 6 + Size 12 11 + Offset 246 4 + Down 96 485 +End + +Button 11 + Size 38 27 + Offset 8 158 + Down 6 156 + OutIn 1 16 +End +Button 12 + Size 38 27 + Offset 58 158 + Down 56 156 + OutIn 8 16 +End +Button 13 + Size 38 27 + Offset 108 158 + Down 106 156 + OutIn 8 8 +End +Button 14 + Size 38 27 + Offset 158 158 + Down 156 156 + OutIn 8 4 +End +Button 15 + Size 38 27 + Offset 208 158 + Down 206 156 + OutIn 8 2 +End +Button 16 + Size 38 27 + Offset 258 158 + Down 256 156 + OutIn 8 1 +End + +Button 21 + Size 38 27 + Offset 8 195 + Down 6 193 + OutIn 2 16 +End +Button 22 + Size 38 27 + Offset 58 195 + Down 56 193 + OutIn 7 16 +End +Button 23 + Size 38 27 + Offset 108 195 + Down 106 193 + OutIn 7 8 +End +Button 24 + Size 38 27 + Offset 158 195 + Down 156 193 + OutIn 7 4 +End +Button 25 + Size 38 27 + Offset 208 195 + Down 206 193 + OutIn 7 2 +End +Button 26 + Size 38 27 + Offset 258 195 + Down 256 193 + OutIn 7 1 +End + +Button 31 + Size 38 27 + Offset 8 232 + Down 6 230 + OutIn 0 16 +End +Button 32 + Size 38 27 + Offset 58 232 + Down 56 230 + OutIn 6 16 +End +Button 33 + Size 38 27 + Offset 108 232 + Down 106 230 + OutIn 6 8 +End +Button 34 + Size 38 27 + Offset 158 232 + Down 156 230 + OutIn 6 4 +End +Button 35 + Size 38 27 + Offset 208 232 + Down 206 230 + OutIn 6 2 +End +Button 36 + Size 38 27 + Offset 258 232 + Down 256 230 + OutIn 6 1 +End + +Button 41 + Size 38 27 + Offset 8 269 + Down 6 267 + OutIn 3 16 +End +Button 42 + Size 38 27 + Offset 58 269 + Down 56 267 + OutIn 5 16 +End +Button 43 + Size 38 27 + Offset 108 269 + Down 106 267 + OutIn 5 8 +End +Button 44 + Size 38 27 + Offset 158 269 + Down 156 267 + OutIn 5 4 +End +Button 45 + Size 38 27 + Offset 208 269 + Down 206 267 + OutIn 5 2 +End +Button 46 + Size 38 27 + Offset 258 269 + Down 256 267 + OutIn 5 1 +End + +Button 51 + Size 88 27 + Offset 8 306 + Down 6 304 + OutIn 4 16 +End +Button 52 + Size 38 27 + Offset 108 306 + Down 106 304 + OutIn 4 8 +End +Button 53 + Size 38 27 + Offset 158 306 + Down 156 304 + OutIn 4 4 +End +Button 54 + Size 38 27 + Offset 208 306 + Down 206 304 + OutIn 4 2 +End +Button 55 + Size 38 27 + Offset 258 306 + Down 256 304 + OutIn 4 1 +End + +Button 61 + Size 38 27 + Offset 8 343 + Down 6 341 + OutIn 3 32 +End +Button 62 + Size 49 27 + Offset 67 343 + Down 65 341 + OutIn 3 8 +End +Button 63 + Size 49 27 + Offset 127 343 + Down 125 341 + OutIn 3 4 +End +Button 64 + Size 49 27 + Offset 187 343 + Down 185 341 + OutIn 3 2 +End +Button 65 + Size 49 27 + Offset 247 343 + Down 245 341 + OutIn 3 1 +End + +Button 71 + Size 36 25 + Offset 8 380 + Down 6 378 + OutIn 2 32 +End +Button 72 + Size 49 27 + Offset 67 380 + Down 65 378 + OutIn 2 8 +End +Button 73 + Size 49 27 + Offset 127 380 + Down 125 378 + OutIn 2 4 +End +Button 74 + Size 49 27 + Offset 187 380 + Down 185 378 + OutIn 2 2 +End +Button 75 + Size 49 27 + Offset 247 380 + Down 245 378 + OutIn 2 1 +End + +Button 81 + Size 36 25 + Offset 8 417 + Down 6 415 + OutIn 1 32 +End +Button 82 + Size 49 27 + Offset 67 417 + Down 65 415 + OutIn 1 8 +End +Button 83 + Size 49 27 + Offset 127 417 + Down 125 415 + OutIn 1 4 +End +Button 84 + Size 49 27 + Offset 187 417 + Down 185 415 + OutIn 1 2 +End +Button 85 + Size 49 27 + Offset 247 417 + Down 245 415 + OutIn 1 1 +End + +Button 91 + Size 38 27 + Offset 8 454 + Down 6 452 + OutIn 0 32768 +End +Button 92 + Size 49 27 + Offset 67 454 + Down 65 451 + OutIn 0 8 +End +Button 93 + Size 49 27 + Offset 127 454 + Down 125 452 + OutIn 0 4 +End +Button 94 + Size 49 27 + Offset 187 454 + Down 185 452 + OutIn 0 2 +End +Button 95 + Size 49 27 + Offset 247 454 + Down 245 452 + OutIn 0 1 +End + +Include "Keyboard.kmi" diff --git a/JC.BMP b/JC.BMP new file mode 100644 index 0000000000000000000000000000000000000000..92d366c7eea5530af31d2c8319cdc250f6195463 GIT binary patch literal 61558 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�lW67CEP`9ncDjc87gh~Ot^;KsAsT%uuLCRC?UT37|iQJ@dl(5&uZ3q{b2kCVVXsw!+s7QJ?fRhENEN2MEhy z_8%9}B>-n;1Yc`#K^`)>>vG7CQ=8_e%`YhY$1Av3+O2*0cKlHOI8|XRe4PT;DK9S% z1;gRXK_wDW$V?9W5c*`K#7QS;Ic6Z;HH(U8e7RsC-oq>TuKZA<9W4Ul8mwxCW&TW_ zIB|ZexQu^8g-Z_?kPC{ z``6;}wcEGX65;mIzsRfJ(S~q2B7{9bf;5MQ6i%r|gHDAS@nKCK7I@n6#Ay0wu&>T2 zp`MzsKa!ecbFh?iQ)g$WvsH%9_Oq*#`JA6-xRc88_u!fs3WPd`D|>p%9R#gCIL_Dl+`p$knd;&}7x(p{Ms?of(3>ENuiXJ>HZ`K&Mv+f3`nKOa~Kr&>z5 z&@K);XPIKqB=hO>!WlX%3Mc%(k8dX^KSaB}mPH4dG-n1*-7u`rO^WYh-u0DYeG4Sr zo-pzHZ`uNTqS800cZjxR*ub7!8s}`tVQfi&7N`JQ97baq9$vH>*46}TI2vXp&eD~;3!!fmNxNmtv~kkz)(RKD{q2iMh|rGyA4qj2 AX#fBK literal 0 HcmV?d00001 diff --git a/JC.KML b/JC.KML new file mode 100644 index 0000000..0eadb32 --- /dev/null +++ b/JC.KML @@ -0,0 +1,364 @@ +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.KML b/JEMAC.KML new file mode 100644 index 0000000..7dc72cc --- /dev/null +++ b/JEMAC.KML @@ -0,0 +1,710 @@ +Global + Title "Jemac's Gx" + Author "Jeffery L. McMahan" + Model "G" + Rom "ROM.48G" + Patch "BEEP.EXT" + Bitmap "jemac.bmp" + Debug 0 +End + +Background + Offset 0 0 + Size 324 703 +End + +Lcd + Zoom 2 + Offset 34 86 + 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 17 12 + Offset 45 74 + Down 0 708 +End + +Annunciator 2 + Size 17 12 + Offset 85 74 + Down 17 708 +End + +Annunciator 3 + Size 16 12 + Offset 125 74 + Down 34 708 +End + +Annunciator 4 + Size 18 12 + Offset 165 74 + Down 50 708 +End + +Annunciator 5 + Size 16 12 + Offset 225 74 + Down 68 708 +End + +Annunciator 6 + Size 16 12 + Offset 265 74 + Down 84 708 +End + +Button 11 + Type 1 + Size 32 21 + Offset 34 278 + OutIn 1 16 +End +Button 12 + Type 1 + Size 32 21 + Offset 80 278 + OutIn 8 16 +End +Button 13 + Type 1 + Size 32 21 + Offset 126 278 + OutIn 8 8 +End +Button 14 + Type 1 + Size 32 21 + Offset 172 278 + OutIn 8 4 +End +Button 15 + Type 1 + Size 32 21 + Offset 218 278 + OutIn 8 2 +End +Button 16 + Type 1 + Size 32 21 + Offset 264 278 + OutIn 8 1 +End + +Button 21 + Type 1 + Size 32 24 + Offset 34 324 + OutIn 2 16 +End +Button 22 + Type 1 + Size 32 24 + Offset 80 324 + OutIn 7 16 +End +Button 23 + Type 1 + Size 32 24 + Offset 126 324 + OutIn 7 8 +End +Button 24 + Type 1 + Size 32 24 + Offset 172 324 + OutIn 7 4 +End +Button 25 + Type 1 + Size 32 24 + Offset 218 324 + OutIn 7 2 +End +Button 26 + Type 1 + Size 32 24 + Offset 264 324 + OutIn 7 1 +End + +Button 31 + Type 1 + Size 32 24 + Offset 34 369 + OutIn 0 16 +End +Button 32 + Type 1 + Size 32 24 + Offset 80 369 + OutIn 6 16 +End +Button 33 + Type 1 + Size 32 24 + Offset 126 369 + OutIn 6 8 +End +Button 34 + Type 1 + Size 32 24 + Offset 172 369 + OutIn 6 4 +End +Button 35 + Type 1 + Size 32 24 + Offset 218 369 + OutIn 6 2 +End +Button 36 + Type 1 + Size 32 24 + Offset 264 369 + OutIn 6 1 +End + +Button 41 + Type 1 + Size 32 24 + Offset 34 414 + OutIn 3 16 +End +Button 42 + Type 1 + Size 32 24 + Offset 80 414 + OutIn 5 16 +End +Button 43 + Type 1 + Size 32 24 + Offset 126 414 + OutIn 5 8 +End +Button 44 + Type 1 + Size 32 24 + Offset 172 414 + OutIn 5 4 +End +Button 45 + Type 1 + Size 32 24 + Offset 218 414 + OutIn 5 2 +End +Button 46 + Type 1 + Size 32 24 + Offset 264 414 + OutIn 5 1 +End + +Button 51 + Type 1 + Size 77 24 + Offset 34 459 + OutIn 4 16 +End +Button 52 + Type 1 + Size 32 24 + Offset 126 459 + OutIn 4 8 +End +Button 53 + Type 1 + Size 32 24 + Offset 172 459 + OutIn 4 4 +End +Button 54 + Type 1 + Size 32 24 + Offset 218 459 + OutIn 4 2 +End +Button 55 + Type 1 + Size 32 24 + Offset 264 459 + OutIn 4 1 +End + +Button 61 + Type 1 + Size 32 24 + Offset 34 504 + OutIn 3 32 +End +Button 62 + Type 1 + Size 42 24 + Offset 86 504 + OutIn 3 8 +End +Button 63 + Type 1 + Size 42 24 + Offset 142 504 + OutIn 3 4 +End +Button 64 + Type 1 + Size 42 24 + Offset 198 504 + OutIn 3 2 +End +Button 65 + Type 1 + Size 42 24 + Offset 254 504 + OutIn 3 1 +End + +Button 71 + Type 1 + Size 32 24 + Offset 34 549 + OutIn 2 32 +End +Button 72 + Type 1 + Size 42 24 + Offset 86 549 + OutIn 2 8 +End +Button 73 + Type 1 + Size 42 24 + Offset 142 549 + OutIn 2 4 +End +Button 74 + Type 1 + Size 42 24 + Offset 198 549 + OutIn 2 2 +End +Button 75 + Type 1 + Size 42 24 + Offset 254 549 + OutIn 2 1 +End + +Button 81 + Type 1 + Size 32 24 + Offset 34 594 + OutIn 1 32 +End +Button 82 + Type 1 + Size 42 24 + Offset 86 594 + OutIn 1 8 +End +Button 83 + Type 1 + Size 42 24 + Offset 142 594 + OutIn 1 4 +End +Button 84 + Type 1 + Size 42 24 + Offset 198 594 + OutIn 1 2 +End +Button 85 + Type 1 + Size 42 24 + Offset 254 594 + OutIn 1 1 +End + +Button 91 + Type 1 + Size 32 24 + Offset 34 639 + OutIn 0 32768 +End +Button 92 + Type 1 + Size 42 24 + Offset 86 639 + OutIn 0 8 +End +Button 93 + Type 1 + Size 42 24 + Offset 142 639 + OutIn 0 4 +End +Button 94 + Type 1 + Size 42 24 + Offset 198 639 + OutIn 0 2 +End +Button 95 + Type 1 + Size 42 24 + Offset 254 639 + 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 32 + Map 32 94 +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/Keyboard.kmi b/Keyboard.kmi new file mode 100644 index 0000000..45a578d --- /dev/null +++ b/Keyboard.kmi @@ -0,0 +1,352 @@ + +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 32 + Map 32 94 +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 48 + Map 48 92 +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 144 + IfPressed 144 + NotFlag 3 + End +End + +Scancode 186 + IfFlag 0 + Map 186 81 + Map 186 95 + End +End + +Scancode 188 + IfFlag 0 + Map 188 71 + Else + Map 188 71 + Map 188 93 + End +End + +Scancode 190 + IfFlag 0 + Map 190 81 + Else + Map 190 93 + End +End + +Scancode 191 + IfFlag 0 + Map 191 71 + Map 191 55 + Else + Map 191 65 + End +End + +Scancode 192 + IfFlag 0 + IfPressed 192 + NotFlag 2 + IfFlag 2 + Press 61 + Else + Release 61 + End + End + Else + Map 192 61 + 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/MkShared.exe b/MkShared.exe new file mode 100644 index 0000000000000000000000000000000000000000..f022dcf92000ce2904ecea93dd56da76bab355ec GIT binary patch literal 21504 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 literal 0 HcmV?d00001 diff --git a/PROBLEMS.TXT b/PROBLEMS.TXT new file mode 100644 index 0000000..377e034 --- /dev/null +++ b/PROBLEMS.TXT @@ -0,0 +1,37 @@ +Known bugs and restrictions of Emu48 V1.10 +------------------------------------------ + +- 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 baudrates 1920, 3840, 7680 and 15360 aren't emulated on most + operating systems + Windows 95a 1920, 3840, 7680 work, 15360 fail + Windows 98 all baudrates fail + 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 +- read on an unconfigured address (open data bus) will not show the + same value like a real calculator +- the G(X) hardware signals BEN and DA19 aren't fully supported, + 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 +- 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 +- Shell OS: clock isn't synchronized with real time + +03/11/99 (c) by Christoph Gießelink, cgiess@swol.de diff --git a/ROMDUMP.EXE b/ROMDUMP.EXE new file mode 100644 index 0000000000000000000000000000000000000000..147ded2ffed9b4e5bc0ac28166f009e6cbade289 GIT binary patch literal 60928 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 CPDsiC literal 0 HcmV?d00001 diff --git a/ROMDUMP.TXT b/ROMDUMP.TXT new file mode 100644 index 0000000..5eeb9c1 --- /dev/null +++ b/ROMDUMP.TXT @@ -0,0 +1,27 @@ +######################################## +# # +# ROMDump Wizard # +# # +######################################## + +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. + +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) + +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! + +If you have any problems, please don't ask me. I'm busy enough +with my work. + +-- Christoph Gießelink diff --git a/ROMDUMP/MainFrm.cpp b/ROMDUMP/MainFrm.cpp deleted file mode 100644 index b5695c0..0000000 --- a/ROMDUMP/MainFrm.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// MainFrm.cpp : implementation of the CMainFrame class -// - -#include "stdafx.h" -#include "ROMDump.h" - -#include "MainFrm.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// CMainFrame - -BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) - //{{AFX_MSG_MAP(CMainFrame) - ON_WM_PAINT() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CMainFrame constructor -CMainFrame::CMainFrame(HICON icon) -{ - //{{AFX_DATA_INIT(CAboutDlg) - //}}AFX_DATA_INIT - - Create(AfxRegisterWndClass(0,0,0,icon),"ROMDump Wizard",WS_MAXIMIZE|WS_OVERLAPPEDWINDOW,rectDefault,NULL,NULL,0,NULL); -} - -///////////////////////////////////////////////////////////////////////////// -// CMainFrame message handlers - -BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) -{ - // TODO: Modify the Window class or styles here by modifying - // the CREATESTRUCT cs - - return CFrameWnd::PreCreateWindow(cs); -} - -void CMainFrame::DoDataExchange(CDataExchange* pDX) -{ - CFrameWnd::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CAboutDlg) - //}}AFX_DATA_MAP -} - -void CMainFrame::OnPaint() -{ - CPaintDC dc(this); // device context for painting - RECT rect; - DWORD dy, y; - int i; - - GetClientRect(&rect); - dy = rect.bottom<<8; - for (i=0,y=0; i<256; i++) - { - CBrush brush(i<<16); - rect.top = y>>16; - y += dy; - rect.bottom = y>>16; - if (rect.top!=rect.bottom) dc.FillRect(&rect, &brush); - } - { - CFont font, *o_font; - CBrush brush(0xFFFFFF); - font.CreateFont(72,0,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET,OUT_DEVICE_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,DEFAULT_PITCH|TMPF_TRUETYPE|FF_ROMAN,"Times New Roman"); - o_font = dc.SelectObject(&font); - GetClientRect(&rect); - dc.SetBkMode(TRANSPARENT); - dc.BeginPath(); - dc.TextOut(10,0,"ROMDump Wizard"); - dc.EndPath(); - dc.SelectClipPath(RGN_AND); - dc.FillRect(&rect,&brush); - dc.SelectObject(o_font); - } -} diff --git a/ROMDUMP/MainFrm.h b/ROMDUMP/MainFrm.h deleted file mode 100644 index 4110719..0000000 --- a/ROMDUMP/MainFrm.h +++ /dev/null @@ -1,31 +0,0 @@ -// MainFrm.h : interface of the CMainFrame class -// -///////////////////////////////////////////////////////////////////////////// - -class CMainFrame : public CFrameWnd -{ -public: - CMainFrame(HICON icon); // window constructor - -// Frame Data - //{{AFX_DATA(CMainFrame) - //}}AFX_DATA - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CMainFrame) - public: - virtual BOOL PreCreateWindow(CREATESTRUCT& cs); - protected: - virtual void DoDataExchange(CDataExchange* pDX); - //}}AFX_VIRTUAL - -// Generated message map functions -protected: - //{{AFX_MSG(CMainFrame) - afx_msg void OnPaint(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -///////////////////////////////////////////////////////////////////////////// diff --git a/ROMDUMP/RES/LCD1.BMP b/ROMDUMP/RES/LCD1.BMP deleted file mode 100644 index 1860427402a94d5e4398eccde9cb55218b6b0ece..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17014 zcmeHMOP1U=3~axbmvxSjb9nD-_z0fu9BppqpsD~8A}OiWmYQ0GGfjdZP$+<(9zTEo z@$378?U(ic+UM_YkH@Et-yVNiZ_U>s{^K9WwED#GNqh7rKEA%bY{bHE{yu*HhGZZ6 zfy%m{qxLaU{=7&*A|12+)Q~%)-P~F%9nm;#i!^mT7F)Ay9&e=I-7?huR}m zCavKX2Y9K`9~|{tL0JC}?1TTv1PXpy4?+?I4*2B&Q9jV*I$*9wTQjPD)Yu}GaQ7d_ zJdFb)CJv0k7>yM1F*?nKO4`y>0Lj2296f}P>p)172!D<6%@W-m=xh#%qeh8gt@Fxz z7SxIrG7|^SQ3G}woNdTLnV1@mzGhOc16I^1(GZr(n_kJ?p%e{fw6x)M4iTOs!uRbe zZK=Z|xCKJ>6(Z*4BQW_T zOs?OFgC_%uV&B&xvQskb=_S{)r||chYnhWGa&-w2b)b!WA&Nn3FMdmaqO(ve`0E@z zd*ClPq=1oKQjvMx-rzvBBf%QE_$UDrZ?+J1@W@zzd8vb2a_|Z#m5|v(`znXBj|^Sw z8HFtYL?aQfm@I)s#u#0}0VfbEi^U;hn!I=)U|(`^A=^7@;X!z0U&0W8vEWDFy134P zh|5SN2)xRqpcajS)M+bK--TtuB))%NBd%abzl@^DM-(m=Ydh` zd6>lk%u2ex7u5OAfcn7(6yH#06|!J3Yw93-SH7JC??v2VT@q%%GeAk3cd!a@5(N4z zM;%Jp{a(!Fu$mq>#8;Wns^v=yUSasI|9f*X2ZqlaUdnXGNvCDC4tL*wL@ zNb7j%ZrTp$8vA8lcY1O~w@Le+`_}y)9E?@GpR@eNRVI^GNH} z_YP822;fb`Og+7n4?7aBBX;wN` z?k>dIXOxhKXc3-cSmtr)mChvA)inCd29-()6d8I_haHXFJBDJ3b!!?LFBsp9gYJcA z1=8SXO?t^2{qSCF*w>|0hj|>hrQ9$hmUhi$vaJ=V1_SiNiG%KYn)c;Dz-Mvp!GXCdWn~Tekm8f7ai9n)XJ7>K5WvoZ+u0D7 zvp6umcO3^i51=TH!(0Z+K|O`j+Lk)pfPY&2_$u zFkC6N%sq2%uSl0|7a{nQ^w2?Xr!m;+!_&~(P}V!WU9I&Np57zi=JTA_l#QIX*3##F zN=$Kmu4rF};({4rPaDON=70J;tU~a_^K6kOMpp~gBk0GoZa_cY$~naUPAy!ahmYL! z2$stVX8U9d&t+n`oQ>UHx9NuY>|43MK5t#%WeB`+81SwK-e_cbng%sc*Jb%#XZV^Y NVKo5ux-5TmhF?f454`{Y diff --git a/ROMDUMP/RES/ROMDUMP.RC2 b/ROMDUMP/RES/ROMDUMP.RC2 deleted file mode 100644 index 54a7f1b..0000000 --- a/ROMDUMP/RES/ROMDUMP.RC2 +++ /dev/null @@ -1,13 +0,0 @@ -// -// ROMDUMP.RC2 - resources Microsoft Visual C++ does not edit directly -// - -#ifdef APSTUDIO_INVOKED - #error this file is not editable by Microsoft Visual C++ -#endif //APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// Add manually edited resources here... - -///////////////////////////////////////////////////////////////////////////// diff --git a/ROMDUMP/ROMDUMP.H b/ROMDUMP/ROMDUMP.H deleted file mode 100644 index 4f8279c..0000000 --- a/ROMDUMP/ROMDUMP.H +++ /dev/null @@ -1,43 +0,0 @@ -// ROMDump.h : main header file for the ROMDUMP application -// - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including this file for PCH -#endif - -#include "resource.h" // main symbols - -#define HP48S 0 -#define HP48G 1 -extern int Port; -extern int Type; - -///////////////////////////////////////////////////////////////////////////// -// CROMDumpApp: -// See ROMDump.cpp for the implementation of this class -// - -class CROMDumpApp : public CWinApp -{ -public: - CROMDumpApp(); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CROMDumpApp) - public: - virtual BOOL InitInstance(); - //}}AFX_VIRTUAL - -// Implementation - - //{{AFX_MSG(CROMDumpApp) - afx_msg void OnAppAbout(); - // NOTE - the ClassWizard will add and remove member functions here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - - -///////////////////////////////////////////////////////////////////////////// diff --git a/ROMDUMP/ROMDump.rc b/ROMDUMP/ROMDump.rc deleted file mode 100644 index bb33cba..0000000 --- a/ROMDUMP/ROMDump.rc +++ /dev/null @@ -1,239 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// French (France) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA) -#ifdef _WIN32 -LANGUAGE LANG_FRENCH, SUBLANG_FRENCH -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "#define _AFX_NO_SPLITTER_RESOURCES\r\n" - "#define _AFX_NO_OLE_RESOURCES\r\n" - "#define _AFX_NO_TRACKER_RESOURCES\r\n" - "#define _AFX_NO_PROPERTY_RESOURCES\r\n" - "\r\n" - "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)\r\n" - "#ifdef _WIN32\r\n" - "LANGUAGE 12, 1\r\n" - "#pragma code_page(1252)\r\n" - "#endif\r\n" - "#include ""res\\ROMDump.rc2"" // non-Microsoft Visual C++ edited resources\r\n" - "#include ""l.fra\\afxres.rc"" // Standard components\r\n" - "#endif\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDR_MAINFRAME ICON DISCARDABLE "res\\ROMDump.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 241, 50 -STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | - DS_CENTERMOUSE | WS_CHILD | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "About ROMDump Wizard" -FONT 8, "MS Sans Serif" -BEGIN - ICON IDR_MAINFRAME,IDC_STATIC,11,14,18,20 - LTEXT "ROMDump Wizard version 0.2",IDC_STATIC,39,12,155,8, - SS_NOPREFIX - LTEXT "Copyright © 1996,1997 Sebastien Carlier",IDC_STATIC,39, - 28,155,8 - DEFPUSHBUTTON "OK",IDOK,202,29,32,14,WS_GROUP -END - -IDD_STEP1 DIALOGEX 0, 0, 208, 226 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "ROMDump Wizard - Step 1" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - DEFPUSHBUTTON "&Ok",IDOK,7,205,50,14 - PUSHBUTTON "&Cancel",IDCANCEL,79,205,50,14 - PUSHBUTTON "&Help",IDHELP,151,205,50,14 - CONTROL "COM&1",IDC_PORT1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | - WS_TABSTOP,45,67,36,10 - CONTROL "COM&2",IDC_PORT2,"Button",BS_AUTORADIOBUTTON,104,67,36, - 10 - CONTROL "COM&3",IDC_PORT3,"Button",BS_AUTORADIOBUTTON,45,82,36, - 10 - CONTROL "COM&4",IDC_PORT4,"Button",BS_AUTORADIOBUTTON,104,81,36, - 10 - CTEXT "Select the port to which you HP48 is connected :", - IDC_STATIC,7,53,194,8 - CONTROL 132,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE,14, - 116,179,82,WS_EX_DLGMODALFRAME - CTEXT "Then check the IO parameters of your HP48 :",IDC_STATIC, - 7,103,194,8 - LTEXT "The ROMDump Wizard will help you to dump the content of your HP48's ROM. This process is very difficult for most users, so I hope this Wizard will save you some time. Please be patient while it is getting the ROM, it might take as much as an hour.", - IDC_STATIC,7,7,194,42,SS_SUNKEN -END - -IDD_STEP2 DIALOG DISCARDABLE 0, 0, 186, 66 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "ROMDump Wizard - Step 2" -FONT 8, "MS Sans Serif" -BEGIN - PUSHBUTTON "Cancel",IDCANCEL,68,45,50,14 - PUSHBUTTON "OK",IDOK,7,45,50,14,WS_DISABLED - PUSHBUTTON "&Help",IDHELP,129,45,50,14 - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER,7, - 23,172,14 - CTEXT "Preparing your HP48 to transfer the ROM :",IDC_STATE,7, - 7,172,8 -END - - -#ifndef _MAC -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,0,0,1 - PRODUCTVERSION 1,0,0,1 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x21L -#else - FILEFLAGS 0x20L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", "\0" - VALUE "FileDescription", "ROMDump Wizard\0" - VALUE "FileVersion", "0.01ß\0" - VALUE "InternalName", "ROMDUMP\0" - VALUE "LegalCopyright", "Copyright © 1996 Sébastien Carlier\0" - VALUE "OriginalFilename", "ROMDUMP.EXE\0" - VALUE "ProductName", "ROMDump Wizard\0" - VALUE "ProductVersion", "0.01ß\0" - VALUE "SpecialBuild", "Evaluation version\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // !_MAC - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE -BEGIN - IDD_ABOUTBOX, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 234 - TOPMARGIN, 7 - BOTTOMMARGIN, 42 - END - - IDD_STEP1, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 201 - TOPMARGIN, 7 - BOTTOMMARGIN, 219 - END - - IDD_STEP2, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 179 - TOPMARGIN, 7 - BOTTOMMARGIN, 59 - END -END -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Bitmap -// - -IDB_LCD1 BITMAP DISCARDABLE "res\\lcd1.bmp" -#endif // French (France) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// -#define _AFX_NO_SPLITTER_RESOURCES -#define _AFX_NO_OLE_RESOURCES -#define _AFX_NO_TRACKER_RESOURCES -#define _AFX_NO_PROPERTY_RESOURCES - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA) -#ifdef _WIN32 -LANGUAGE 12, 1 -#pragma code_page(1252) -#endif -#include "res\ROMDump.rc2" // non-Microsoft Visual C++ edited resources -#include "l.fra\afxres.rc" // Standard components -#endif -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/ROMDUMP/Romdump.cpp b/ROMDUMP/Romdump.cpp deleted file mode 100644 index 16a6cb0..0000000 --- a/ROMDUMP/Romdump.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// ROMDump.cpp : Defines the class behaviors for the application. -// - -#include "stdafx.h" -#include "ROMDump.h" -#include "MainFrm.h" -#include "About.h" -#include "Step1.h" -#include "Step2.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -int Type; - -///////////////////////////////////////////////////////////////////////////// -// CROMDumpApp - -BEGIN_MESSAGE_MAP(CROMDumpApp, CWinApp) - //{{AFX_MSG_MAP(CROMDumpApp) - ON_COMMAND(ID_APP_ABOUT, OnAppAbout) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code! - //}}AFX_MSG_MAP - // Standard file based document commands -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CROMDumpApp construction - -CROMDumpApp::CROMDumpApp() -{ - // TODO: add construction code here, - // Place all significant initialization in InitInstance -} - -///////////////////////////////////////////////////////////////////////////// -// The one and only CROMDumpApp object - -CROMDumpApp theApp; - -///////////////////////////////////////////////////////////////////////////// -// CROMDumpApp initialization - -BOOL CROMDumpApp::InitInstance() -{ - // Standard initialization - // If you are not using these features and wish to reduce the size - // of your final executable, you should remove from the following - // the specific initialization routines you do not need. - -#ifdef _AFXDLL - Enable3dControls(); // Call this when using MFC in a shared DLL -#else - Enable3dControlsStatic(); // Call this when linking to MFC statically -#endif - - CMainFrame* pMainFrame = new CMainFrame(LoadIcon(IDR_MAINFRAME)); - m_pMainWnd = pMainFrame; - pMainFrame->ShowWindow(m_nCmdShow); - pMainFrame->UpdateWindow(); - - CAboutDlg dlg; - dlg.Create(IDD_ABOUTBOX,m_pMainWnd); - dlg.ShowWindow(SW_SHOW); - - return TRUE; -} - -///////////////////////////////////////////////////////////////////////////// -// CROMDumpApp commands -///////////////////////////////////////////////////////////////////////////// - -// App command to run the dialog -void CROMDumpApp::OnAppAbout() -{ - CAboutDlg aboutDlg; - aboutDlg.DoModal(); -} - diff --git a/ROMDUMP/Romdump.mak b/ROMDUMP/Romdump.mak deleted file mode 100644 index 4b42b85..0000000 --- a/ROMDUMP/Romdump.mak +++ /dev/null @@ -1,392 +0,0 @@ -# Microsoft Developer Studio Generated NMAKE File, Format Version 40001 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Application" 0x0101 - -!IF "$(CFG)" == "" -CFG=ROMDump - Win32 Debug -!MESSAGE No configuration specified. Defaulting to ROMDump - Win32 Debug. -!ENDIF - -!IF "$(CFG)" != "ROMDump - Win32 Release" && "$(CFG)" !=\ - "ROMDump - 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 "Romdump.mak" CFG="ROMDump - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "ROMDump - Win32 Release" (based on "Win32 (x86) Application") -!MESSAGE "ROMDump - 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 -# PROP Target_Last_Scanned "ROMDump - Win32 Debug" -MTL=mktyplib.exe -RSC=rc.exe -CPP=cl.exe - -!IF "$(CFG)" == "ROMDump - Win32 Release" - -# PROP BASE Use_MFC 6 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 6 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -OUTDIR=.\Release -INTDIR=.\Release - -ALL : "$(OUTDIR)\Romdump.exe" - -CLEAN : - -@erase ".\Release\Romdump.exe" - -@erase ".\Release\About.obj" - -@erase ".\Release\Romdump.pch" - -@erase ".\Release\MainFrm.obj" - -@erase ".\Release\Serial.obj" - -@erase ".\Release\ROMDump.obj" - -@erase ".\Release\StdAfx.obj" - -@erase ".\Release\Step2.obj" - -@erase ".\Release\Step1.obj" - -@erase ".\Release\ROMDump.res" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c -CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\ - "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)/Romdump.pch" /Yu"stdafx.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" /d "_AFXDLL" -# ADD RSC /l 0x40c /d "NDEBUG" /d "_AFXDLL" -RSC_PROJ=/l 0x40c /fo"$(INTDIR)/ROMDump.res" /d "NDEBUG" /d "_AFXDLL" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/Romdump.bsc" -BSC32_SBRS= -LINK32=link.exe -# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386 -# ADD LINK32 /nologo /subsystem:windows /machine:I386 -LINK32_FLAGS=/nologo /subsystem:windows /incremental:no\ - /pdb:"$(OUTDIR)/Romdump.pdb" /machine:I386 /out:"$(OUTDIR)/Romdump.exe" -LINK32_OBJS= \ - "$(INTDIR)/About.obj" \ - "$(INTDIR)/MainFrm.obj" \ - "$(INTDIR)/Serial.obj" \ - "$(INTDIR)/ROMDump.obj" \ - "$(INTDIR)/StdAfx.obj" \ - "$(INTDIR)/Step2.obj" \ - "$(INTDIR)/Step1.obj" \ - "$(INTDIR)/ROMDump.res" - -"$(OUTDIR)\Romdump.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) - $(LINK32) @<< - $(LINK32_FLAGS) $(LINK32_OBJS) -<< - -!ELSEIF "$(CFG)" == "ROMDump - Win32 Debug" - -# PROP BASE Use_MFC 6 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 6 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -OUTDIR=.\Debug -INTDIR=.\Debug - -ALL : "$(OUTDIR)\Romdump.exe" - -CLEAN : - -@erase ".\Debug\vc40.pdb" - -@erase ".\Debug\Romdump.pch" - -@erase ".\Debug\vc40.idb" - -@erase ".\Debug\Romdump.exe" - -@erase ".\Debug\MainFrm.obj" - -@erase ".\Debug\ROMDump.obj" - -@erase ".\Debug\Serial.obj" - -@erase ".\Debug\Step2.obj" - -@erase ".\Debug\StdAfx.obj" - -@erase ".\Debug\About.obj" - -@erase ".\Debug\Step1.obj" - -@erase ".\Debug\ROMDump.res" - -@erase ".\Debug\Romdump.ilk" - -@erase ".\Debug\Romdump.pdb" - -"$(OUTDIR)" : - if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" - -# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c -CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ - /D "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)/Romdump.pch" /Yu"stdafx.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" /d "_AFXDLL" -# ADD RSC /l 0x40c /d "_DEBUG" /d "_AFXDLL" -RSC_PROJ=/l 0x40c /fo"$(INTDIR)/ROMDump.res" /d "_DEBUG" /d "_AFXDLL" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -BSC32_FLAGS=/nologo /o"$(OUTDIR)/Romdump.bsc" -BSC32_SBRS= -LINK32=link.exe -# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 -# ADD LINK32 /nologo /subsystem:windows /debug /machine:I386 -LINK32_FLAGS=/nologo /subsystem:windows /incremental:yes\ - /pdb:"$(OUTDIR)/Romdump.pdb" /debug /machine:I386 /out:"$(OUTDIR)/Romdump.exe" -LINK32_OBJS= \ - "$(INTDIR)/MainFrm.obj" \ - "$(INTDIR)/ROMDump.obj" \ - "$(INTDIR)/Serial.obj" \ - "$(INTDIR)/Step2.obj" \ - "$(INTDIR)/StdAfx.obj" \ - "$(INTDIR)/About.obj" \ - "$(INTDIR)/Step1.obj" \ - "$(INTDIR)/ROMDump.res" - -"$(OUTDIR)\Romdump.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 "ROMDump - Win32 Release" -# Name "ROMDump - Win32 Debug" - -!IF "$(CFG)" == "ROMDump - Win32 Release" - -!ELSEIF "$(CFG)" == "ROMDump - Win32 Debug" - -!ENDIF - -################################################################################ -# Begin Source File - -SOURCE=.\ROMDump.cpp -DEP_CPP_ROMDU=\ - ".\StdAfx.h"\ - ".\ROMDump.h"\ - ".\MainFrm.h"\ - ".\About.h"\ - ".\Step1.h"\ - ".\Step2.h"\ - - -"$(INTDIR)\ROMDump.obj" : $(SOURCE) $(DEP_CPP_ROMDU) "$(INTDIR)"\ - "$(INTDIR)\Romdump.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\StdAfx.cpp -DEP_CPP_STDAF=\ - ".\StdAfx.h"\ - - -!IF "$(CFG)" == "ROMDump - Win32 Release" - -# ADD CPP /Yc"stdafx.h" - -BuildCmds= \ - $(CPP) /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\ - "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)/Romdump.pch" /Yc"stdafx.h" /Fo"$(INTDIR)/"\ - /c $(SOURCE) \ - - -"$(INTDIR)\StdAfx.obj" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)" - $(BuildCmds) - -"$(INTDIR)\Romdump.pch" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)" - $(BuildCmds) - -!ELSEIF "$(CFG)" == "ROMDump - Win32 Debug" - -# ADD CPP /Yc"stdafx.h" - -BuildCmds= \ - $(CPP) /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ - /D "_AFXDLL" /D "_MBCS" /Fp"$(INTDIR)/Romdump.pch" /Yc"stdafx.h"\ - /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c $(SOURCE) \ - - -"$(INTDIR)\StdAfx.obj" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)" - $(BuildCmds) - -"$(INTDIR)\Romdump.pch" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)" - $(BuildCmds) - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\MainFrm.cpp -DEP_CPP_MAINF=\ - ".\StdAfx.h"\ - ".\ROMDump.h"\ - ".\MainFrm.h"\ - - -"$(INTDIR)\MainFrm.obj" : $(SOURCE) $(DEP_CPP_MAINF) "$(INTDIR)"\ - "$(INTDIR)\Romdump.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\ROMDump.rc -DEP_RSC_ROMDUM=\ - ".\res\ROMDump.ico"\ - ".\res\lcd1.bmp"\ - ".\res\ROMDump.rc2"\ - - -"$(INTDIR)\ROMDump.res" : $(SOURCE) $(DEP_RSC_ROMDUM) "$(INTDIR)" - $(RSC) $(RSC_PROJ) $(SOURCE) - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\About.cpp -DEP_CPP_ABOUT=\ - ".\StdAfx.h"\ - ".\ROMDump.h"\ - ".\About.h"\ - - -"$(INTDIR)\About.obj" : $(SOURCE) $(DEP_CPP_ABOUT) "$(INTDIR)"\ - "$(INTDIR)\Romdump.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\Step1.cpp -DEP_CPP_STEP1=\ - ".\StdAfx.h"\ - ".\ROMDump.h"\ - ".\Step1.h"\ - ".\Serial.h"\ - - -"$(INTDIR)\Step1.obj" : $(SOURCE) $(DEP_CPP_STEP1) "$(INTDIR)"\ - "$(INTDIR)\Romdump.pch" - - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\Step2.cpp - -!IF "$(CFG)" == "ROMDump - Win32 Release" - -DEP_CPP_STEP2=\ - ".\StdAfx.h"\ - ".\ROMDump.h"\ - ".\Step2.h"\ - ".\Serial.h"\ - - -"$(INTDIR)\Step2.obj" : $(SOURCE) $(DEP_CPP_STEP2) "$(INTDIR)"\ - "$(INTDIR)\Romdump.pch" - - -!ELSEIF "$(CFG)" == "ROMDump - Win32 Debug" - -DEP_CPP_STEP2=\ - ".\StdAfx.h"\ - ".\ROMDump.h"\ - ".\Step2.h"\ - ".\Serial.h"\ - -NODEP_CPP_STEP2=\ - ".\DumpRangeBin"\ - - -"$(INTDIR)\Step2.obj" : $(SOURCE) $(DEP_CPP_STEP2) "$(INTDIR)"\ - "$(INTDIR)\Romdump.pch" - - -!ENDIF - -# End Source File -################################################################################ -# Begin Source File - -SOURCE=.\Serial.cpp -DEP_CPP_SERIA=\ - ".\StdAfx.h"\ - ".\ROMDump.h"\ - ".\Serial.h"\ - ".\Step2.h"\ - - -"$(INTDIR)\Serial.obj" : $(SOURCE) $(DEP_CPP_SERIA) "$(INTDIR)"\ - "$(INTDIR)\Romdump.pch" - - -# End Source File -# End Target -# End Project -################################################################################ diff --git a/ROMDUMP/Romdump.mdp b/ROMDUMP/Romdump.mdp deleted file mode 100644 index 780cbded9603fb786057e12b5af27541c7569a61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37376 zcmeI4TXWk)6vvO7OYNpqu<2!IUt6LP;PN>sqEi=x%oOPcfo?bq zeQQc-)tVSdRMtu?^Jn+{Sa4R*4iO*%M1Tko0U|&IhyW2F0z`la5CI}^00{gRiyVp! z0Q>?Y&g%e#L?Ju|fgb3^6`&}@;0W}=QRsh+wq&~B3B;faB7P8Jht~gm8uUp7hyW2F z0z`la5CI}U1c(3;AOb|-01=?|zXLRwZG>_h2H*rd11Dh+hTs$ox6ubR*{=j*xcb}W zIseB;p(vb1LFa)Gr&^p9JrKDb%NV+C8s&=_VJnQHSlaKGrcExd`Zd`4vmr^gWxHPG zEU#H|SzFdCT(?C#@#+D1FpyFdZdvRD%_z&ZX6SxpFIM*FbT%(9b2ep~hUwR!GY?|3 z2Fvq`Vb=Z9b69#ZS1$8qxy*99Wt%l6+~0YuKRs*c3PzymHMvyAZr2rF4I91UbfT}J zt16Q;t7=$Uxc*D5A4-{~TxV&crmL3I1y{N1yKxUKPG!r6Y%_`LhFL*x=BnJ3^}ysS zG#T_vv^7oTtW;-rxM}!(e7#|i)A_or*ldAYwQ>ON8#EYpd&qgtI>!jR`YqZVb8Y6< zxVcm|?)v?IhgB!ss)8*mt1Pp^l~up?d#pX~*51<9%`Jbxx>Gsb=F8kfKFyr}5lses zlg1^ku&j*T1$Y&!@^Cn> zDW+i=OE$|~xbWyWi*vLaA9(7juG(Ft+EVYLY%43H0PfD1zccRdOaT0fZGMOR%#9h* znl>Up1c(3;AOb{y2oM1xKm>@uej`BZfBS93o~*xL#8RaHe6mRQRc~kDSvU*N!8v#y zUH}F!LVREOPtNXyz!6CO?6;@&UjSPF1)%lc6PFdEHdrz*sVuoT&XUs=eBEZrI~q&QVVT6@POG@H`?1s3+sATg zZn5BfOJ#4PfY1AqPiI7Vwi=gsskWS4Fe+-TQcYBq6)gU+7Po9wURqCxZ&|}L68q}L zzQWMMvw?@`NO1JKnvQW`^_66qjjT_MC@i_;cO$|T$1=HvJ*uH*V&8WY8$TcP9W?da zELloibZ-R~R;^^!Et^*+@z|Rx4=*UVzNhGN`WajH_A zxLouG*ZCAtE7fWwa=pDi3bvZUK@nZ--npUtzjLEaOnF(;vu0&Sn1T~biA1ioM>R0|shO!%VaiD~_kus9yyWE>%rSFgjrnEv zvGdCUFLT-A+hrKv4F4J*%`3rCgS>KeQ(o~K2LtbCmY`unW?@0NMm%WTkXwwvW}Doi zV|sQ{OJh%1h~YHJDvgGFDz7~CQ=u`T_;j38fzrqxOCxx};$#w>%ftnXGtqk^*5_YE zRAhXlAqp9sAV1-X-O9dIxp?^HuO6J@oXxpB3Lnk6V%cod8yzeZ(hGRW)CZZHvboId z99|1}#r=s*voHSOQYMS@cF5vrq8OfALk7){E*xv+y{OwbaCkmze&8T!DUl`yeTm}6 zT-3aNW2R|c@6IDl>P6%mvqTevE|ufe#vo)QUgh{uimuefGeakmi!11u1 zfb5yX{3y4w@mXzQbJ&Hkm4%CAJBzWz78b#YjF-c$W9su`(iD7ts8!_AvZ9VAN)?3I z$|UH>RK{9cMZIy_!lRz(pmbxAMr>Qqdu+tqadY2A`k<{72+;apCya9I7)k%xnoTFv zq+_3x{6TKv#D}{MIvVM1Tko0U|&Ih(PBONI(*=21a2F#$f{9 zf=lo=T!t$!30L7Ac(-%GbVTF>;y1W(8zKEiARB48OH2BX1`SF09@VaCgBowwx&k7+ zS-V*qL^p2t*o|A~eq~r@M*0sFZjk;XKfmeTH<13rm172)0h458AsHE7vb0h@1h>se z|KaLUP -#include -#include -#include "romdump.h" -#include "Serial.h" -#include "Step2.h" // for Progress control - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -#define PACKET_START 1 -#define PACKET_STOP 13 -#define CHR(ch) (((ch)+32)&0xFF) -#define NUM(ch) ((ch)-32) - -static DWORD crc1[16] = -{ - 0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387, - 0x8408, 0x9489, 0xA50A, 0xB58B, 0xC60C, 0xD68D, 0xE70E, 0xF78F -}; -static DWORD crc2[16] = -{ - 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, - 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7 -}; - -int Port = 0; -char *sPort = "COMx"; -HANDLE hCom; -BYTE pkt[1024]; - -BOOL SerialOpen() -{ - BOOL fSuccess; - DCB dcb; - - sPort[3] = Port+'0'; - hCom = CreateFile(sPort,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); - if (hCom == INVALID_HANDLE_VALUE) return FALSE; - fSuccess = GetCommState(hCom, &dcb); - if (!fSuccess) - { - CloseHandle(hCom); - return FALSE; - } - dcb.BaudRate = 9600; - dcb.fBinary = 1; - dcb.ByteSize = 8; - dcb.Parity = 0; - dcb.StopBits = 0; - dcb.fDtrControl = 0; - dcb.fRtsControl = 0; - dcb.fOutX = 1; - dcb.fInX = 1; - fSuccess = SetCommState(hCom, &dcb); - if (!fSuccess) - { - CloseHandle(hCom); - return FALSE; - } - return TRUE; -} - -void SerialClose() -{ - CloseHandle(hCom); - return; -} - -BYTE chk1(BYTE *pkt) -{ - BYTE chk; - for (chk=0; *pkt; pkt++) chk += *pkt; - return ((chk>>6)+chk)&0x3F; -} - -WORD chk3(BYTE *pkt) -{ - DWORD crc; - BYTE c; - for (crc = 0; *pkt != '\0'; pkt++) - { - c = ((BYTE)crc) ^ (*pkt); - crc = (crc>>8) ^ (crc1[c>>4] ^ crc2[c&0x0F]); - } - return (WORD)crc; -} - -BOOL SendPKT(BYTE type, int n, char *d) -{ - DWORD len = strlen(d); - - pkt[0] = PACKET_START; - pkt[1] = CHR((BYTE)len+2+(n?3:1)); - pkt[2] = CHR(n); - pkt[3] = type; - strcpy((char*)(pkt+4),d); - len += 4; - pkt[len] = 0; - - if (n) - { // 16-bit CRC - WORD crc = chk3(pkt+1); - pkt[len++] = CHR((crc>>12)&0x0F); - pkt[len++] = CHR((crc>>6)&0x3F); - pkt[len++] = CHR(crc&0x3F); - } - else - { // 6-bit chksum - pkt[len++] = CHR(chk1(pkt+1)); - } - pkt[len++] = PACKET_STOP; - pkt[len] = 0; - - WriteFile(hCom, pkt, len, &len, NULL); - return pkt[len]; -} - -BYTE RecvPKT() -{ - int timeout = 10; - DWORD len; - - pkt[0] = 0; - while (timeout--) - { - ReadFile(hCom, pkt, 1, &len, NULL); - if (pkt[0]==1) break; // received a packed ! - if (pkt[0]=='0') ASSERT(FALSE); - } - if (!timeout) return 0; - ReadFile(hCom, pkt+1, 3, &len, NULL); - len = NUM(pkt[1])-1; - ReadFile(hCom, pkt+4, len, &len, NULL); - if (pkt[len+3]!=PACKET_STOP) return 0; - pkt[len+4] = 0; - return pkt[3]; -} - -char *DataPKT(char *data, DWORD *len) -{ - char *p = (char*)(pkt+4), *q; - int i, n = NUM(pkt[1])-5, j, l; - - for (i=0, l=0; i>4) * 24; - - result = (char*)malloc(len+1); - result[len] = 0; - -l1: SendPKT('I',0,"~* @-#Y3"); - t = RecvPKT(); - if (t!='Y') // not ACK ? - { - if (t=='E') return NULL; // ERROR, abort - if (t=='N') goto l1; // NAK, resend - if (t==0) goto l1; // received nothing, resend - ASSERT(FALSE); - } - SendPKT('C',0,cmd); - ReadFile(hCom, result, len, &len, NULL); - do t=RecvPKT(); while (t!='E'); - Sleep(5); - return result; -} - -__inline nib(char c) {return (c<='9')?(c-'0'):(c-'A'+10);} - -BYTE *DumpRangeBin(CStep2 *dlg,DWORD a, DWORD b) -{ - char buf[32]; - DWORD d, c, len; - BYTE *res; - BYTE t; - - wsprintf(buf,"##%05lX ##%05lX ROMDump",a,b); - dlg->m_Progress.SetRange(0,(b-a)>>4); - dlg->m_Progress.SetStep(1); - dlg->m_Progress.SetPos(0); - - res = (BYTE*)malloc(b-a); - -l1: SendPKT('I',0,"~* @-#Y3"); - t = RecvPKT(); - if (t!='Y') // not ACK ? - { - if (t=='E') return NULL; // ERROR, abort - if (t=='N') goto l1; // NAK, resend - if (t==0) goto l1; // received nothing, resend - ASSERT(FALSE); - } - SendPKT('C',0,buf); - for (d=a; dm_Progress.StepIt(); - } - do t=RecvPKT(); while (t!='E'); - Sleep(5); - return res; -} - -static WORD wCRC; - -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) -{ - wCRC = (WORD)((wCRC>>4)^crc_table[(wCRC^nib)&0xf]); -} - -BOOL CheckROM(LPBYTE pRom, UINT uType) -{ - DWORD dwD0, dwD1; - WORD wRomCRC; - UINT i; - DWORD dwBase = 0x00000; - UINT nPass = 0; - UINT nPasses; - - switch (uType) - { - case HP48G: - nPasses = 2; - break; - case HP48S: - nPasses = 1; - break; - default: - return TRUE; - } - - for (dwD0=0x00100; dwD0<0x00140; dwD0++) pRom[dwD0]=0; - -again: - - wRomCRC = pRom[dwBase+0x7FFFC] - |(pRom[dwBase+0x7FFFD]<<4) - |(pRom[dwBase+0x7FFFE]<<8) - |(pRom[dwBase+0x7FFFF]<<12); - - wCRC = 0x0000; - dwD0 = dwBase + 0x00000; - dwD1 = dwBase + 0x40000; - do - { - for (i=0; i<16; i++) CRC(pRom[dwD0+i]); - for (i=0; i<16; i++) CRC(pRom[dwD1+i]); - dwD0 += 16; - dwD1 += 16; - } while (dwD0&0x3FFFF); - - if (wCRC!=0xFFFF) return FALSE; - if (++nPass == nPasses) return TRUE; - - dwBase += 0x80000; - goto again; - - return TRUE; -} diff --git a/ROMDUMP/Serial.h b/ROMDUMP/Serial.h deleted file mode 100644 index 0194d70..0000000 --- a/ROMDUMP/Serial.h +++ /dev/null @@ -1,14 +0,0 @@ -extern int Port; -extern HANDLE hCom; -extern BYTE pkt[1024]; -extern BOOL SerialOpen(); -extern void SerialClose(); -extern BOOL SendPKT(BYTE type, int n, char *d); -extern BYTE RecvPKT(); -extern char *CommandPKT(char *cmd, DWORD *len); -extern char *DumpRange(DWORD a, DWORD b); -#ifdef _STEP2_ -extern BYTE *DumpRangeBin(CStep2 *dlg,DWORD a, DWORD b); -#endif -extern BOOL CheckROM(LPBYTE pRom, UINT uType); - diff --git a/ROMDUMP/Stdafx.h b/ROMDUMP/Stdafx.h deleted file mode 100644 index edbbdc0..0000000 --- a/ROMDUMP/Stdafx.h +++ /dev/null @@ -1,16 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -//#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers - -#include // MFC core and standard components -#include // MFC extensions -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows 95 Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - - - - diff --git a/ROMDUMP/Step2.cpp b/ROMDUMP/Step2.cpp deleted file mode 100644 index 9ad16c6..0000000 --- a/ROMDUMP/Step2.cpp +++ /dev/null @@ -1,226 +0,0 @@ -// Step2.cpp : implementation file -// -#include "stdafx.h" -#include -#include "romdump.h" -#include "Step2.h" -#include "Serial.h" - -#define STEPS 8+14 -#define STEPIT dlg->m_Progress.StepIt() - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// CStep2 dialog - - -CStep2::CStep2(CWnd* pParent /*=NULL*/) - : CDialog(CStep2::IDD, pParent) -{ - //{{AFX_DATA_INIT(CStep2) - //}}AFX_DATA_INIT -} - - -void CStep2::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CStep2) - DDX_Control(pDX, IDC_STATE, m_State); - DDX_Control(pDX, IDOK, m_Ok); - DDX_Control(pDX, IDC_PROGRESS, m_Progress); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CStep2, CDialog) - //{{AFX_MSG_MAP(CStep2) - ON_WM_DESTROY() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CStep2 message handlers - -int CStep2::OpenError() -{ - MessageBox("Fatal error:\nCannot open serial port !","ROMDump Wizard - Error",MB_ICONSTOP|MB_OK); - EndDialog(IDCANCEL); - return 0; -} - -int CStep2::WriteError() -{ - MessageBox("Fatal error:\nCannot write to serial port !","ROMDump Wizard - Error",MB_ICONSTOP|MB_OK); - EndDialog(IDCANCEL); - return 0; -} - -int CStep2::ReadError() -{ - MessageBox("Fatal error:\nCannot read from serial port !","ROMDump Wizard - Error",MB_ICONSTOP|MB_OK); - EndDialog(IDCANCEL); - return 0; -} - -int CStep2::ProtocolError(int i) -{ - char buffer[32]; - wsprintf(buffer, "Protocol Error (%i)", i); - MessageBox(buffer,"ROMDump Wizard - Error",MB_ICONSTOP|MB_OK); - EndDialog(IDCANCEL); - return 0; -} - -char *ROMDump[] = -{ - "GROB 8 553 D9D20D8A812BF8111920BB000D9D2049703CCD20F14008F511108FC1523203481000C", // 1 - "A13114B31A48409EA508508418F2D7608FD8F3520340FFFF0EF681AF048F2D7608FD8F3520340FFF", // 2 - "F0EF681AF031F0110080820815901DD0808206159081AF13340FFF68B61481AF0181AF1CD5340FFF", // 3 - "68BD40D5EC5606C7181AF0277E1808240000781AF0381AF13340FFF78B66060108706063416D9081", // 4 - "AF0181AF1CD5340FFF78BD40D5EC5606A1181AF02870C17B21341F00F8FFB620791165F034000F78", // 5 - "0434000E7804725134000FF80534000F780534000FF80534000E7805808240000881AF0381AF1334", // 6 - "0FFFB8B63581AF0181AF1CD5340FFFB8BD40D5EC5606E6081AF027480345F00C8FAC620727080824", // 7 - "0000C81AF0381AF1381AF0181AF1CD5340FFFF8BD40D5EC4A181AF0271308518F5F008732077711F", // 8 - "0110080820015908F5E0108D3415081B58082415000C2134870D01F1F0076A001F5F008808240510", // 9 - "0F4D8152715771547151716F17FCD57E01861531B000F714E1BA960814E8089714C1B8210014C340", //10 - "000C80480481AF1113081AF1281AF00747031A37CD0156776507E9016F81AF10818F8F52D861B334", //11 - "0000C8058058058051BA960814E8088714C1B8210014C1B040F714E01AF531F0AE76C20132D61328", //12 - "0F480F080F480F380F180F3D53140AE7AE2A897D10BF5A6F5FE0131D07A2031A07220018082103A6", //13 - "280821939EEC08082170A621F2110015B0808707F1D6114D010000000000000000B2130B2130", //14 - NULL -}; - -DWORD WINAPI Step2_Thread(LPVOID lpdlg) -{ - FILE *rom; - CStep2 *dlg = (CStep2*)lpdlg; - BYTE *res; - DWORD len; - int i, j; - -//1-open serial port - if (SerialOpen()==FALSE) return dlg->OpenError(); - STEPIT; -//2-ask for server mode - if (dlg->MessageBox("Please put your HP48 in SERVER mode.","ROMDump Wizard",MB_OKCANCEL)==IDCANCEL) - { - dlg->EndDialog(IDCANCEL); - return 0; - } - STEPIT; -//3-delete ROMDump if it already exists - res = (BYTE*)CommandPKT("CLEAR HEX 'ROMDump' PURGE",&len); - if (res==NULL) dlg->ProtocolError(1); - free(res); - STEPIT; -//4-send ROMDump to the HP48 - do SendPKT('S',0,"~* @-#Y3"); while (RecvPKT()!='Y'); - j = 0; - SendPKT('F',++j,"ROMDump"); - if (RecvPKT()!='Y') dlg->ProtocolError(4); - STEPIT; - i=0; - while (ROMDump[i]) - { - SendPKT('D',++j,ROMDump[i]); - if (RecvPKT()!='Y') dlg->ProtocolError(5+10*i); - i++; - STEPIT; - } - SendPKT('Z',++j,""); - if (RecvPKT()!='Y') dlg->ProtocolError(6); - SendPKT('B',++j,""); - if (RecvPKT()!='Y') dlg->ProtocolError(7); -//5-assemble ROMDump - res = (BYTE*)CommandPKT("ROMDump OBJ#Í ##4017h SYSEVAL ##56B6h SYSEVAL DROP NEWOB 'ROMDump' STO",&len); - if (res==NULL) dlg->ProtocolError(1); - free(res); - STEPIT; -//6-execute ROMDump to get HP48 type (G/S) -// dlg->MessageBox("Your HP48 will say 'Port Closed'. Just ignore it.","ROMDump Wizard", MB_OK); - res = (BYTE*)DumpRange(0x7FFF0,0x7FFFF); - if ((res[6]=='4')&&(res[7]=='8')) - Type = HP48S; - else - Type = HP48G; - free(res); - STEPIT; -//7-ok, now display the type and dump - dlg->m_State.SetWindowText("Now dumping the ROM..."); - switch (Type) - { - case HP48S: - dlg->MessageBox("An HP48S/SX was detected.\n","ROMDump Wizard",MB_OK); - res = DumpRangeBin(dlg,0x00000,0x7FFFF); - if (RecvPKT()!='E') dlg->ProtocolError(9); - if (res==NULL) - { - dlg->MessageBox("Error while transfering the ROM.\n","ROMDump Wizard",MB_OK); - dlg->EndDialog(IDCANCEL); - return 0; - } - if (!CheckROM(res,HP48S)) - { - dlg->MessageBox("ROM CRC check fails. Try again.\n","ROMDump Wizard",MB_OK); - dlg->EndDialog(IDCANCEL); - return 0; - } - rom = fopen("ROM.48S","wb"); - for (i=0; i<=0x7FFFF; i++) fputc(res[i]&0xF, rom); - fclose(rom); - break; - case HP48G: - dlg->MessageBox("An HP48G/GX was detected.\n","ROMDump Wizard",MB_OK); - res = DumpRangeBin(dlg,0x00000,0xFFFFF); - if (res==NULL) - { - dlg->MessageBox("Error while transfering the ROM.\n","ROMDump Wizard",MB_OK); - dlg->EndDialog(IDCANCEL); - return 0; - } - if (!CheckROM(res,HP48G)) - { - dlg->MessageBox("ROM CRC check fails. Try again.\n","ROMDump Wizard",MB_OK); - dlg->EndDialog(IDCANCEL); - return 0; - } - rom = fopen("ROM.48G","wb"); - for (i=0; i<=0xFFFFF; i++) fputc(res[i]&0xF, rom); - fclose(rom); - break; - } - STEPIT; -//8-delete ROMDump - res = (BYTE*)CommandPKT("'ROMDump' PURGE",&len); - if (res==NULL) dlg->ProtocolError(1); - free(res); - STEPIT; -// All done ! - dlg->EndDialog(IDOK); - return 0; -} - -BOOL CStep2::OnInitDialog() -{ - DWORD id_thread; - CDialog::OnInitDialog(); - - m_Progress.SetRange(0,STEPS); - m_Progress.SetStep(1); - m_Progress.SetPos(0); - h_thread = CreateThread(NULL,0,&Step2_Thread,(LPVOID)this,0,&id_thread); - return TRUE; -} - -void CStep2::OnDestroy() -{ - TerminateThread(h_thread,(DWORD)(-1)); - SerialClose(); - CDialog::OnDestroy(); -} diff --git a/ROMDUMP/Step2.h b/ROMDUMP/Step2.h deleted file mode 100644 index 983f3c9..0000000 --- a/ROMDUMP/Step2.h +++ /dev/null @@ -1,43 +0,0 @@ -// Step2.h : header file -// -#define _STEP2_ - -///////////////////////////////////////////////////////////////////////////// -// CStep2 dialog -class CStep2 : public CDialog -{ -// Construction -public: - CStep2(CWnd* pParent = NULL); // standard constructor - int OpenError(); - int WriteError(); - int ReadError(); - int ProtocolError(int i); - -// Dialog Data - //{{AFX_DATA(CStep2) - enum { IDD = IDD_STEP2 }; - CStatic m_State; - CButton m_Ok; - CProgressCtrl m_Progress; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CStep2) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - HANDLE h_thread; - - // Generated message map functions - //{{AFX_MSG(CStep2) - virtual BOOL OnInitDialog(); - afx_msg void OnDestroy(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; diff --git a/ROMDUMP/about.cpp b/ROMDUMP/about.cpp deleted file mode 100644 index d65c7c1..0000000 --- a/ROMDUMP/about.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// About.cpp : about box dialog -// - -#include "stdafx.h" -#include "ROMDump.h" - -#include "About.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// CAboutDlg dialog used for App About - -CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) -{ - //{{AFX_DATA_INIT(CAboutDlg) - //}}AFX_DATA_INIT -} - -void CAboutDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CAboutDlg) - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) - //{{AFX_MSG_MAP(CAboutDlg) - // No message handlers - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -/* - { - } - { - CStep1 dlg; - dlg.Create(IDD_STEP1,m_pMainWnd); - dlg.ShowWindow(SW_SHOW); - if (nResponse != IDOK) return FALSE; - - } - { - CStep2 dlg; - nResponse = dlg.Create(IDD_STEP2,m_pMainWnd); - if (nResponse != IDOK) return FALSE; - } -*/ \ No newline at end of file diff --git a/ROMDUMP/about.h b/ROMDUMP/about.h deleted file mode 100644 index fdfbe74..0000000 --- a/ROMDUMP/about.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// About.h : about box header file -// - - -///////////////////////////////////////////////////////////////////////////// -// CAboutDlg dialog used for App About - -class CAboutDlg : public CDialog -{ -public: - CAboutDlg(); - -// Dialog Data - //{{AFX_DATA(CAboutDlg) - enum { IDD = IDD_ABOUTBOX }; - //}}AFX_DATA - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CAboutDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - //{{AFX_MSG(CAboutDlg) - // No message handlers - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; diff --git a/ROMDUMP/resource.h b/ROMDUMP/resource.h deleted file mode 100644 index 5e32c86..0000000 --- a/ROMDUMP/resource.h +++ /dev/null @@ -1,28 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by ROMDump.rc -// -#define IDD_ABOUTBOX 100 -#define IDR_MAINFRAME 128 -#define IDR_ROMDUMTYPE 129 -#define IDD_STEP1 130 -#define IDD_STEP2 131 -#define IDB_LCD1 132 -#define IDC_PORT1 1001 -#define IDC_PORT2 1002 -#define IDC_PORT3 1003 -#define IDC_PROGRESS 1003 -#define IDC_PORT4 1004 -#define IDC_STATE 1006 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 134 -#define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1007 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/TRUELCD.KMI b/TRUELCD.KMI new file mode 100644 index 0000000..4470e97 --- /dev/null +++ b/TRUELCD.KMI @@ -0,0 +1,31 @@ +Color 0 130 173 161 +Color 1 128 166 159 +Color 2 124 160 154 +Color 3 119 155 148 +Color 4 115 149 143 +Color 5 110 143 137 +Color 6 106 137 132 +Color 8 102 132 126 +Color 9 98 126 121 +Color 10 93 120 115 +Color 11 89 114 110 +Color 12 83 109 104 +Color 13 79 103 99 +Color 14 74 97 93 +Color 15 70 91 88 +Color 16 65 86 82 +Color 17 61 80 77 +Color 18 57 74 71 +Color 19 53 68 66 +Color 20 48 63 60 +Color 21 44 57 55 +Color 22 39 51 49 +Color 23 35 46 44 +Color 24 31 41 38 +Color 25 27 35 33 +Color 26 22 29 27 +Color 27 18 23 22 +Color 28 13 18 16 +Color 29 9 12 11 +Color 30 4 6 5 +Color 31 0 0 0 diff --git a/sources/COPYING.TXT b/sources/COPYING.TXT new file mode 100644 index 0000000..a43ea21 --- /dev/null +++ b/sources/COPYING.TXT @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Convert/Convert.mak b/sources/Convert/Convert.mak similarity index 100% rename from Convert/Convert.mak rename to sources/Convert/Convert.mak diff --git a/Convert/Convert.mdp b/sources/Convert/Convert.mdp similarity index 100% rename from Convert/Convert.mdp rename to sources/Convert/Convert.mdp diff --git a/Convert/Main.c b/sources/Convert/Main.c similarity index 100% rename from Convert/Main.c rename to sources/Convert/Main.c diff --git a/sources/EMU48.TXT b/sources/EMU48.TXT new file mode 100644 index 0000000..95eb475 --- /dev/null +++ b/sources/EMU48.TXT @@ -0,0 +1,237 @@ + + + + Emu48 - A freeware HP48 Emulator for Windows 95 and NT + + + + **************** + * 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) + +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. + +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 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. + +- 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. + +- 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 ! + + 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. + + 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. + +* 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. + + + + **************** + * 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. + +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. + +Check that the path in the "Emu48 Directory" text area is correct. Modify it if +the directory in which you installed Emu48 is not the directory displayed. +Click the refresh button ("V") after modifying it to update the list box. + +Choose a KML script in the list box. If you have put a G/GX ROM dump in Emu48's +directory, choose a script for G/GX. If you have put a S/SX ROM dump in Emu48's +directory, choose a script for S/SX. +Several scripts are included in the common archive : + * Emu48's Default Faceplate for HP48G/GX + * Emu48's Default Faceplate for HP48S/SX + These two are simple scripts, and they use the bitmap from Win48 2.05. + * Casey's Gx with Toolbar and Touch Screen + * Casey's Sx with Toolbar and Touch Screen + These script uses many advanced features, and is a good demonstration of + the power of Emu48's scripting language, KML. Try it, it is really great ! + * Floating buttons + This one looks really great. + * Small but realistic HP48 Gx + This one has been designed for small resolutions such as 640x480. + Note: some things in this script have to be be fixed. + + If you want other great scripts, visit Casey's Emu48 homepage : + http://www.gulftel.com/~pattersc/emu48/ + + And if you are interested in 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 + +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. + + + + ******************* + * 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 : + MkShared +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. + +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). + +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. + + + + ******************** + * SPECIAL FEATURES * + ******************** + +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. + + + + ******************** + * 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. + + + + *********** + * 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 : + + http://www.geocities.com/CapeCanaveral/5948/index.html + +Other graphics and scripts are available at Casey's Emu48 Graphics Page : + http://www.gulftel.com/~pattersc/emu48/ + + + + *************** + * LEGAL STUFF * + *************** + + 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 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. + + + + ************** + * The Author * + ************** + +Paper Mail: + Sebastien Carlier + 10 Allee des bergeronnettes + 35340 LIFFRE + FRANCE + +E-Mail: + sebc@epita.fr + sebc@anet.fr + +Homepage: + http://www.geocities.com/CapeCanaveral/5948/index.html diff --git a/sources/Emu48/CHANGES.TXT b/sources/Emu48/CHANGES.TXT new file mode 100644 index 0000000..567e6de --- /dev/null +++ b/sources/Emu48/CHANGES.TXT @@ -0,0 +1,672 @@ +Service Pack 10 for Emu48 Version 1.0 + +DISPLAY.C +- use only one pattern field for all display resolutions +- added new display contrast scheme +- bugfix in function WriteToMainDisplay(), calculated source memory + address was illegal memory pointer + +EMU48.C +- bugfix in functions OnFileExit() and OnSysClose(), stop emulation + thread before saving emulation data +- changed function Disasm(), changed list box from single to multi + selectable items, added button to copy selected items to + clipboard +- 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 + +EMU48.H +- removed extern declaration of global function +- extern declaration of global variable and functions + +EMU48.RC +- added button in dialog IDD_DISASM +- reinsert button IDC_UPDATE in dialog IDD_CHOOSEKML +- changed version and copyright + +ENGINE.C +- functions CheckSerial() and AdjustSpeed() are inline coded now +- new function UpdateKdnBit() for updating the KDN bit by the 1ms + keyboard interrupt handler + +FILES.C +- added new function CrcPort2() to get a fingerprint of port2 +- changed function OpenDocument(), check fingerprint of port2 +- changed function SaveDocument(), update fingerprint of port2 + +KEYBOARD.C +- changed function Keyboard_GetIR() to static +- bugfix in function ScanKeyboard(), added fixes for the KDN bit + implementation and update keyboard interrupt pending flag when + 1ms keyboard handler is disabled + +KML.C +- bugfix in function ParseLine(), caused memory leaks when an error + occured +- bugfix in function ParseLines(), fixed a windows program abort on + some KML script or line include errors +- bugfix in function ParseBlock(), abort parsing on KML script + errors +- bugfix in function ParseBlocks(), fixed a windows program abort on + block include errors +- bugfix in function FreeLines(), caused memory leaks when different + argument types are used in a line + +MOPS.C +- added new function IOBit() +- bugfix in function ReadIO(), update the KDN bit in the SRQ2 + register (0x119) before reading + +OPCODES.H +- bugfix in A=IN and C=IN command, update KDN bit in the SRQ + register +- bugfix in all r=r+CON fs,n and r=r-CON fs,n opcodes, they always + work in HEX mode +- changes in INTON, INTOFF and RTI for KDN bit implementation +- changed RTI command, execute pending key interrupt only if enabled +- changed RSI command, set key interrupt pending flag also when 1ms + keyboard handler is disabled +- bugfix in INTON command, execute interrupt if key interrupt is + pending + +OPS.H +- added new inline functions Ninc16() and Ndec16() + +RESOURCE.H +- added/changed definitions +- removed ID_HELP_REGISTER + +TYPES.H +- use position of the uUnused1 variable for fingerprint of port2 +- use position of the Port2_Size variable for cpu cycles at start of + 1ms key interrupt handler + + +Service Pack 9 for Emu48 Version 1.0 + +DISASM.C +- changed output of HP Mnemonic P=n + +DISPLAY.C +- bugfix in function UpdateMainDisplay(), with off display and Zoom + > 1 only a part of the display was cleared +- changed function UpdateMenuDisplay(), use a common pointer offset + calculation and display output part now + +EMU48.C +- changed function OnViewCopy(), changed screen clipboard format + from CF_BITMAP to CF_DIB +- bugfix in function OnViewReset(), must unconfig MMU on reset too +- changed function OnAbout(), don't stop emulation while viewing + About box +- moved initialize/remove of the Critical Section part from message + handler to main program + +EMU48.H +- removed extern declaration of global variables and functions + +EMU48.RC +- changed design of IDD_ABOUT +- changed version and copyright + +ENGINE.C +- bugfix in function FASTPTR(), code execution is possible in IO + register area as well + +FETCH.H +- removed jump to extension opcode 81B0 + +FILES.C +- removed global variable + +MOPS.C +- bugfix in function MapP0(), MapP1(), MapP2(), MapBS(), mapping + area may have holes +- bugfix in function MapBS(), no read from ROM at mapped bank + switch control area +- bugfix in function MapP2(), if G(X) ROM select port2 only if + DA19=0 and BEN=1, now the saved bank switch control information is + used +- bugfix in function MapROM(), if G(X) ROM and DA19=0 (ROM disabled) + then mirror lower ROM at #80000 (AR18=0) +- 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 +- 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() +- bugfix in function ReadIO(), several minor fixes in the LINECOUNT + register (0x128,0x129) emulation +- bugfix in function ReadIO(), the TIMER1CTRL and TIMER2CTRL + register (0x12E,0x12F) must be updated before reading +- bugfix in function WriteIO(), don't clear the XTRA bit in the + TIMER1CTRL register (0x12E) while setting +- bugfix in function WriteIO(), after setting new TIMER1CTRL and + TIMER2CTRL register (0x12E,0x12F) values the control bit + condition must be checked +- bugfix in function WriteIO(), handle start/stop of the LINECOUNT + register when the DON bit in the DISPIO (0x100) register has + changed +- bugfix in function WriteIO(), force new ROM mapping if DA19 in + the MSB LINECOUNT (0x129) register has changed on a G(X) ROM + +OPCODES.H +- Nwrite2() replaced by Nwrite() +- Nwrite5() replaced by Nwrite() +- Nread2() replaced by Nread() for the BS 'r=datx fsd' bugfix +- Nread5() replaced by Nread() for the BS 'r=datx fsd' bugfix +- bugfix in RTI command, generate interrupt if ON key is pressed +- bugfix in RSI command, don't set key interrupt pending flag if + INTOFF command is active +- removed extension opcode 81B0 + +TIMER.C +- removed assertions in function CheckT1() and CheckT2() that the + timers must run +- moved initialize/remove of Critical Section handler from the + function StartTimers() and StopTimers() to main program for bugfix + the problems with the Critical Section area of the function + ReadT1() and ReadT2() when the timers are stopped +- bugfix in function ReadT2(), timer2 was always running + +TYPES.H +- use Port2_Bank variable to save state of GX port2 Flip-Flop + + +Service Pack 8 for Emu48 Version 1.0 + +DISASM.C +- changed function read_nibble() to disassemble modules +- added new mapping functions for function read_nibble() +- bugfix in function append_imm_nibble(), HP Mnemonic hex number + was showed as decimal number + +EMU48.C +- changed variable types of function WinMain() +- added "drag and drop" implementation for HP objects +- added some features to function Disasm() +- removed all parts handled with the global variables bAccurateTimer + and uT1Period +- bugfix in function Disasm(), button "Next Address" caused a + windows program abort if the given address was outside of the + cpu address area +- bugfix in function UpdateWindowStatus(), Menuitem Tools + "Disassembler..." must be disabled when document file is closed +- bugfix in function OnStackPaste(), fixed problem when HP is off +- bugfix in function OnObjectLoad(), solve problem when calculator + is off and bugfixed method to switch emulator into sleep state +- bugfix in function OnObjectSave(), bugfixed method to switch + emulator into sleep state + +EMU48.DSP +- added library shell32.lib + +EMU48.H +- bugfix of variable hApp, used wrong type +- extern declaration of global variables +- removed extern declaration of global variables +- added some disassembler defines + +EMU48.RC +- added my name to dialog IDD_ABOUT +- added some radio buttons to dialog IDD_DISASM +- removed Timers part from dialog IDD_SETTINGS +- changed version and copyright + +ENGINE.C +- added global variable +- removed global variable +- bugfix in function AdjKeySpeed(), slow down whole emulation now, + when a key is pressed + +KEYBOARD.C +- changed key event signal in function KeyboardEvent() + +MOPS.C +- bugfix in function Uncnfg(), I/O mapped address area begin and end + on a 64 nibble boundary, Chipset.IOBase must be saved for the C=ID + command +- bugfix in function C_Eq_Id(), don't shift Chipset.IOBase for ID +- changed function Nread(), Nwrite(), Nread2(), Nwrite2(), Nread5() + and Nwrite5(), test Chipset.IOCfig as well for mapping + +OPCODES.H +- removed InfoMessage in BUSCB, BUSCC and BUSCD opcode, emulate as + NOP +- bugfix in RTI command, don't return from interrupt at timer1/2 + interrupt condition +- bugfix in SHUTDN command, don't shut down at timer1/2 wake up + condition +- bugfix in RSI command, detection of interrupt is in service was + wrong + +PCH.H +- added include shellapi.h + +RESOURCE.H +- added several definitions +- removed IDC_BROWSEDIR, IDC_REFRESH, IDC_USEMMTIMER, IDC_T1PERIOD, + IDC_T1DEFAULT + +TIMER.C +- removed global variables bAccurateTimer and uT1Period, replaced by + a static variable and a constant +- changed function CheckT1() and function CheckT2(), use function + parameter for the timer value now +- changed function ReadT1() and function ReadT2(), update timer + control bits after reading +- bugfix in function RescheduleT2(), execute timer2 event when MSB + of timer changed to update timer2 control register +- bugfix in function TimeProc(), waiting for timer2 overrun prevents + access to the timer2 value from the cpu emulation thread and reset + of variable uT2TimerId was outside synchronized area +- bugfix in function CheckT1() and function CheckT2(), fixed SRQ bit + handling +- bugfix in function SetT1() and function SetT2(), update timer + control bits and check for interrupts after setting +- bugfix in function StopTimers() and function SetT2(), killing + timer1 or timer2 in a Critical Section part may cause a dead lock + with the timer callback function (function timeKillEvent() waits + for the finish of the corresponding callback function, but the + callback function is locked by the Critical Section handler) + + +Service Pack 7 for Emu48 Version 1.0 + +DISASM.C +- new modul with disassembler + +DISPLAY.C +- bugfixes in function UpdateDisplayPointers(), next line offset was + sometimes wrong and the addresses of the main display area were + wrong when next line offset was negative +- new implementation of function WriteToMainDisplay(), fixed several + bugs (no output when next line offset was negative, sometimes + problems with left margin values > 4 and garbage on display) +- bugfix in function WriteToMenuDisplay(), menu wasn't updated + when next line offset was negative + +EMU48.C +- added global variable +- added semaphor handling for key scan +- added disassembler dialog box and menu entry +- bugfix in function OnViewCopy(), the clipboard wasn't closed when + EmptyClipboard() failed +- bugfix in function OnKeyDown(), suppress autorepeat feature of + keyboard + +EMU48.DSP +- added disasm.c source + +EMU48.H +- extern declaration of global variables +- added function prototypes + +EMU48.RC +- added Menuitem Tools "Disassembler..." +- changed version and copyright + +ENGINE.C +- added global variable +- bugfix in function AdjKeySpeed(), exit delay loop when a key + event has occured and use Chipset.Keyboard_Row[] instead of + Chipset.in to detect a pressed key + +FILES.C +- function LoadBitmapFile() save old hWindowDC palette now +- bugfix in function SaveDocumentAs(), previous opened file wasn't + closed + +KEYBOARD.C +- bugfix in function ScanKeyboard(), code part must be synchronized + and an interrupt was only generated when all input lines has been + low (no keys pressed) +- added parameter to function ScanKeyboard(), parameter indicates if + the Chipset.in interrupt register should be reset +- added key event signal in function KeyboardEvent() +- workaround in function KeyboardEvent(), hold key state for a + definite time + +KML.C +- bugfix in function ParseLines() and ParseBlocks(), allocated + memory for string parameter of include token wasn't freed +- bugfix in function KillKML(), palette resource couldn't freed, + when hWindowDC was open + +MOPS.C +- bugfix in function WriteIO(), the Chipset.start1 variable only + was updated when five nibbles at the DISPADDR register (0x120) + has been written +- bugfix in function WriteIO(), the Chipset.loffset variable only + was updated when three nibbles at the LINEOFFS register (0x125) + has been written +- bugfix in function WriteIO(), the Chipset.lcounter variable only + was updated when the MSB of the LINECOUNT register (0x129) has + been written +- bugfix in function WriteIO(), the Chipset.start2 variable only + was updated when five nibbles at the MENUADDR register (0x130) + has been written +- bugfix in function ReadIO(), the LINECOUNT register (0x128-0x129) + is a down counter + +OPCODES.H +- changed RSI command for thread synchronize + +RESOURCE.H +- added several definitions + +TIMER.C +- bugfix in function SetAccesstime(), sync time values must always + save in port0 and not at the mapped address +- bugfix in function RescheduleT2(), used wrong event time when + reference point for timer2 value wasn't saved + + +Service Pack 6 for Emu48 Version 1.0 + +DDESERV.C +- bugfix in XTYP_POKE part, fixed problem when HP is off + +DISPLAY.C +- added X4 display size parts + +EMU48.C +- changed function OnViewCopy() for X4 display size +- init lFreq variable for high performance counter here now + +EMU48.H +- changed type and name of bLcdDoubled to nLcdDoubled +- extern declaration of global variables + +EMU48.RC +- changed version and copyright + +EXTERNAL.C +- changed high limit of frequency, use SX specification +- added high limit of beep duration, use SX specification +- estimate cpu cycles for beep time +- adjust some cpu flags and registers modified by the original code + +KML.C +- changed TOK_ZOOM implementation in function InitLcd() + +MOPS.C +- changed implementation of registers 0x128-0x12D in function + ReadIO() + +OPCODES.H +- update field select table in "EXTENSION opcode o81B1" + +TIMER.C +- moved static lFreq variable to modul EMU48.C + + +Service Pack 5a for Emu48 Version 1.0 + +EMU48.C +- bugfix in OnPaint(), must redraw annunciators + + +Service Pack 5 for Emu48 Version 1.0 + +DDESERV.C +- return DDE error if emulator state couldn't change to sleep state + +EMU48.C +- added Copy/Paste Clipboard data from/to stack (strings only) + +EMU48.H +- extern declaration of global variables +- added function prototypes + +EMU48.RC +- added Menuitem Edit "Copy String" and "Paste String" +- fixed multiple use of accelerator keys +- changed version and copyright + +ENGINE.C +- added function WaitForSleepState(), wait for the SHUTDN command + -> stack isn't in use (when the clock is displayed, a time string + was sometimes on stack instead of the loaded item), then switch to + state 3 (Sleep state) +- added function AdjKeySpeed(), slow down key repetition + +FILES.C +- save mapping size of port2 in global variable +- optimized calculation of bank switch mask in MapPort2() + +MOPS.C +- bugfix in MapP0(), data offset was wrong +- bugfix in MapP1(), data offset was wrong +- bugfix in MapP2(), data offset was wrong and real size of modul + was zero +- bugfix in MapBS(), wrong pointer in mirrored data page +- bugfix in MapROM(), wrong pointer in mirrored data page +- bugfix in MapP0(), MapP1(), MapP2(), MapBS(), Config(), Uncnfg(), + mapped address area begin and end on a mapping size boundary +- bugfix in Map(), the access priority of CE1 and CE2 was wrong + (SX: port1<->port2, GX: port1<->bank select) +- bugfix in Uncnfg(), the unconfig priority of CE1 and CE2 was wrong + (SX: port1<->port2, GX: port1<->bank select) +- Map(), size optimized implementation +- Config(), size optimized implementation +- Uncnfg(), size optimized implementation +- C_Eq_Id(), size optimized implementation + +OPCODES.H +- insert key slow down in A=IN and C=IN + +RESOURCE.H +- added ID_STACK_COPY and ID_STACK_PASTE + + +Service Pack 4 for Emu48 Version 1.0 + +EMU48.C +- added code for port1 disable +- changed the default box setting of "Accurate Timer" in checked + +EMU48.RC +- added item "Port 1 is Plugged" +- changed version and copyright + +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 + or after the RSI command when a bit in the IN register is set + +MOPS.C +- bugfix in WriteIO(), TIMER1 was loaded with the current value + +OPCODES.H +- bugfix in INTON and INTOFF command, they aren't able to generate a + keyboard interrupt +- bugfix in RSI command, call interrupt routine or set interrupt + pending flag if a bit of the IN register is high +- RTI command changed, doesn't handle ON key here +- added InfoMessage for BUSCB command + +RESOURCE.H +- added IDC_PORT1EN + +SERIAL.C +- bugfix, synchronize threads for receive char + +TIMER.C +- changed function CheckT1(), quite similar to V1.0 with minor fixes +- changed function CheckT2(), minor fixes +- bugfix in function SetT1(), decrement value after full period, + don't check for interrupts after setting +- bugfix in function SetT2(), don't check for interrupts after + setting + + +Service Pack 3 for Emu48 Version 1.0 + +DDESERV.C +- new modul for DDE communication + +EMU48.C +- init DDE callback function and name service +- added section [Serial] in INI-File +- added combobox update in dialog box handler + +EMU48.DSP +- new makefile for MSVC 5.0 + +EMU48.H +- extern declaration of global variables +- added function prototypes + +EMU48.RC +- added block "Serial" +- changed version and copyright + +ENGINE.C +- bugfix in SetSpeed(), may enable "realspeed" with illegal + reference counts +- bugfix in SwitchToState(), switching from "Invalid" or "Sleep" + state into another, ResumeThread() may called before + SuspendThread() (unsynchronized threads) +- added code for serial device + +FILES.C +- separated stack writing code from LoadObject() to WriteStack() + +MOPS.C +- added global variables +- changed code in ReadIO() for BAUD, IO CONTROL, RCS, TCS, RBR, + SREQ?, IR CONTROL for serial support +- changed code in WriteIO() for BAUD, IOC, TBR, IRC for serial + support + +RESOURCE.H +- added IDC_WIRE and IDC_IR + +SERIAL.C +- new modul for serial support + +SERIAL.H +- new header with serial definitions + + +Service Pack 2 for Emu48 Version 1.0 + +DISPLAY.C +- bugfix in UpdateMainDisplay(), update display even if it's off + +EMU48.C +- added section [Emulator] in INI-File +- added checkbox update in dialog box handler + +EMU48.H +- extern declaration of variables + +EMU48.RC +- added item "Authentic Calculator Speed" +- changed version and copyright + +ENGINE.C +- added code to slow down emulation + +RESOURCE.H +- added IDC_REALSPEED + + +Service Pack 1 for Emu48 Version 1.0 + +DISPLAY.C +- red and blue has been changed in SetLcdColor() +- use display contrast value from chipset and not the default + value in CreateLcdBitmap() +- use semaphores to avoid GDI trouble with NT in + UpdateMainDisplay(), UpdateMenuDisplay(), WriteToMainDisplay() + and WriteToMenuDisplay() +- execute ResizeWindow() only if window exist +- bugfix in draw part of WriteToMainDisplay() + +EMU48.C +- version changed +- added global variable +- added semaphor handling to avoid GDI trouble with NT that prevent + graphic update sometimes +- added message for right mouse key +- bugfix of a parameter of GetPrivateProfileString() +- removed SwitchToState() and KillKML() at end of program +- eliminated memory leak caused by SetWindowTitle() +- function OnPaint() may returned without calling EndPaint() +- execute UpdateWindowStatus() only if window exist + +EMU48.H +- extern declaration of global variable +- added VOID as parameter in function prototypes + +EMU48.RC +- added/changed version and copyright + +EXTERNAL.C +- bugfix, check if beeper enabled +- changed beeper emulation, more realistic with Windows NT + +FILES.C +- avoid an open handle and adjust file attributes in + LoadBitmapFile() +- the WORD to int conversion used in function SetWindowPos() + failed; windows with negative position data wouldn't pop up with + NT (NT GDI is 32 bit coded, Windows 95 mostly 16 bit -> the + failed conversion doesn't matter with Windows 95) +- bugfix in close file handling of function OpenDocument() +- InitKML() need chipset for contrast setting in RestoreBackup() + +KML.C +- added global variables +- use semaphores to avoid GDI trouble with NT in DrawButton() and + DrawAnnunciator() +- added function ReleaseAllButtons() +- changed mouse handling for pressing more than one key + +OPCODES.H +- added S(X) oscillator cycles for each command +- bugfix in A=IN and C=IN command to emulate a saturn bug, on real + machines the assembler commands only work on an even address +- bugfix in all r=r+CON fs,n and r=r-CON fs,n opcodes to emulate a + saturn bug, on real machines commands with a single field selector + cause an overrun to other fields of the register +- NFdbl() replaced by NFadd() +- Ndbl() replaced by Nadd() + +OPS.H +- NFinc() definition changed +- NFdec() definition changed +- NFdbl() definition removed +- Ndbl() function removed +- changed implementation of Ninc(), added offset variable +- changed implementation of Ndec(), added offset variable +- optimized implementation of Nadd() +- optimized implementation of Nsub() +- optimized implementation of Nrsub() +- optimized implementation of Nnot() +- optimized implementation of Nneg() + +TIMER.C +- added global variables, defines and constants +- added function SetAccesstime() for setting the correct time +- bugfix in AbortT2() which prevent updating the clock sometime +- changed implementation of CheckT1() to correct blink frequency + of input cursor +- changed implementation of ReadT2() using a high resolution + timer to minimize skipping timer2 values +- bugfix in SetT2(), always check timer2 control register +- solved a problem with timer2 counts greater than 16.67 min. +- bugfix of wrong timer1/2 values (unsynchronized threads) + +TYPES.H +- use position of the t2_ticks variable for oscillator cycles + + +(c) by Christoph Gießelink, cgiess@swol.de diff --git a/sources/Emu48/DDESERV.C b/sources/Emu48/DDESERV.C new file mode 100644 index 0000000..6d9b138 --- /dev/null +++ b/sources/Emu48/DDESERV.C @@ -0,0 +1,137 @@ +/* + * DdeServ.c + * + * This file is part of Emu48 + * + * Copyright (C) 1998 Christoph Gießelink + * + */ +#include "pch.h" +#include "Emu48.h" + +HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv, + HSZ hsz1,HSZ hsz2,HDDEDATA hData, + DWORD dwData1,DWORD dwData2) +{ + BYTE szBuffer[32]; + HDDEDATA hReturn; + LPBYTE lpData; + DWORD dwAddress,dwSize,dwLoop,dwIndex; + BOOL bSuccess; + + switch (iType) + { + case XTYP_CONNECT: + DdeQueryString(idDdeInst,hsz2,szBuffer,sizeof(szBuffer),0); + if (0 != strcmp(szBuffer,szAppName)) + return (HDDEDATA) FALSE; + DdeQueryString(idDdeInst,hsz1,szBuffer,sizeof(szBuffer),0); + return (HDDEDATA) (0==strcmp(szBuffer,szTopic)); + + case XTYP_POKE: + // illegal data format or not in running state + if (iFmt != uCF_HpObj || nState != 0) + return (HDDEDATA) DDE_FNOTPROCESSED; + + DdeAccessData(hData,&dwSize); // fetch data size + DdeUnaccessData(hData); + + // reserve memory + if ((lpData = (LPBYTE) LocalAlloc(LMEM_FIXED,dwSize * 2)) == NULL) + return (HDDEDATA) DDE_FNOTPROCESSED; + + if (!Chipset.dispon) // 25.08.98 cg, moved, 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 + { + LocalFree(lpData); // free memory + return (HDDEDATA) DDE_FNOTPROCESSED; + } + + while (nState!=nNextState) Sleep(0); + _ASSERT(nState==3); + + // fetch data and write to stack + DdeGetData(hData,(LPBYTE) &dwIndex,sizeof(DWORD),0L); + if (dwIndex <= dwSize - sizeof(DWORD)) + dwSize = dwIndex; + dwSize = DdeGetData(hData,lpData+dwSize,dwSize,sizeof(DWORD)); + bSuccess = (WriteStack(lpData,dwSize) == S_ERR_NO); + LocalFree(lpData); // free memory + + SwitchToState(0); // run state + while (nState!=nNextState) Sleep(0); + _ASSERT(nState==0); + + if (bSuccess == FALSE) + return (HDDEDATA) DDE_FNOTPROCESSED; + + KeyboardEvent(TRUE,0,0x8000); + Sleep(200); + KeyboardEvent(FALSE,0,0x8000); + // wait for sleep mode + while(Chipset.Shutdn == FALSE) Sleep(0); + + return (HDDEDATA) DDE_FACK; + + case XTYP_REQUEST: + // illegal data format or not in running state + if (iFmt != uCF_HpObj || nState != 0) + return NULL; + + if (WaitForSleepState()) // 16.06.98 cg, wait for cpu SHUTDN then sleep state + return NULL; + + while (nState!=nNextState) Sleep(0); + _ASSERT(nState==3); + + dwAddress = RPL_Pick(1); // pick address of level1 object + if (dwAddress == 0) + { + SwitchToState(0); // run state + return NULL; + } + dwLoop = dwSize = (RPL_SkipOb(dwAddress) - dwAddress + 1) / 2; + + // length of binary header + dwIndex = sizeof(BINARYHEADER) - 1; + + // size of objectsize + header + object + dwSize += dwIndex + sizeof(DWORD); + + // reserve memory + if ((lpData = (LPBYTE) LocalAlloc(LMEM_FIXED,dwSize)) == NULL) + { + SwitchToState(0); // run state + return NULL; + } + + // save data length + *(DWORD *)lpData = dwLoop + dwIndex; + + // copy header + memcpy(lpData + sizeof(DWORD),BINARYHEADER,dwIndex); + + // copy data + for (dwIndex += sizeof(DWORD);dwLoop--;++dwIndex,dwAddress += 2) + lpData[dwIndex] = Read2(dwAddress); + + // write data + hReturn = DdeCreateDataHandle(idDdeInst,lpData,dwSize,0,hsz2,iFmt,0); + LocalFree(lpData); + + SwitchToState(0); // run state + while (nState!=nNextState) Sleep(0); + _ASSERT(nState==0); + + return hReturn; + } + return NULL; +} diff --git a/sources/Emu48/DISASM.C b/sources/Emu48/DISASM.C new file mode 100644 index 0000000..1cada8e --- /dev/null +++ b/sources/Emu48/DISASM.C @@ -0,0 +1,1899 @@ +/* + * Disasm.c + * + * This file is part of Emu48, a ported version of x48 + * + * Copyright (C) 1994 Eddie C. Dost + * Copyright (C) 1998 Christoph Gießelink + * + */ +#include "pch.h" +#include "Emu48.h" + +#define TAB_SKIP 8 + +BOOL disassembler_mode = HP_MNEMONICS; +WORD disassembler_map = MEM_MAP; + +static char *hex[] = +{ + "0123456789ABCDEF", + "0123456789abcdef", +}; + +static char *opcode_0_tbl[32] = +{ + /* + * HP Mnemonics + */ + "RTNSXM", "RTN", "RTNSC", "RTNCC", + "SETHEX", "SETDEC", "RSTK=C", "C=RSTK", + "CLRST", "C=ST", "ST=C", "CSTEX", + "P=P+1", "P=P-1", "(NULL)", "RTI", + /* + * Class Mnemonics + */ + "rtnsxm", "rtn", "rtnsc", "rtncc", + "sethex", "setdec", "push", "pop", + "clr.3 st", "move.3 st, c", "move.3 c, st", "exg.3 c, st", + "inc.1 p", "dec.1 p", "(null)", "rti" +}; + +static char *op_str_0[16] = +{ + /* + * HP Mnemonics + */ + "A=A%cB", "B=B%cC", "C=C%cA", "D=D%cC", + "B=B%cA", "C=C%cB", "A=A%cC", "C=C%cD", + /* + * Class Mnemonics + */ + "b, a", "c, b", "a, c", "c, d", + "a, b", "b, c", "c, a", "d, c" +}; + +static char *op_str_1[16] = +{ + /* + * HP Mnemonics + */ + "DAT0=A", "DAT1=A", "A=DAT0", "A=DAT1", + "DAT0=C", "DAT1=C", "C=DAT0", "C=DAT1", + /* + * Class Mnemonics + */ + "a, (d0)", "a, (d1)", "(d0), a", "(d1), a", + "c, (d0)", "c, (d1)", "(d0), c", "(d1), c" +}; + +static char *in_str_80[32] = +{ + /* + * HP Mnemonics + */ + "OUT=CS", "OUT=C", "A=IN", "C=IN", + "UNCNFG", "CONFIG", "C=ID", "SHUTDN", + NULL, "C+P+1", "RESET", "BUSCC", + NULL, NULL, "SREQ?", NULL, + /* + * Class Mnemonics + */ + "move.s c, out", "move.3 c, out", "move.4 in, a", "move.4 in, c", + "uncnfg", "config", "c=id", "shutdn", + NULL, "add.a p+1, c", "reset", "buscc", + NULL, NULL, "sreq?", NULL +}; + +static char *in_str_808[32] = +{ + /* + * HP Mnemonics + */ + "INTON", NULL, NULL, "BUSCB", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + "PC=(A)", "BUSCD", "PC=(C)", "INTOFF", + /* + * Class Mnemonics + */ + "inton", NULL, NULL, "buscb", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + "jmp (a)", "buscd", "jmp (c)", "intoff" +}; + +static char *op_str_81[8] = +{ + /* + * HP Mnemonics + */ + "A", "B", "C", "D", + /* + * Class Mnemonics + */ + "a", "b", "c", "d", +}; + +static char *in_str_81b[32] = +{ + /* + * HP Mnemonics + */ + NULL, NULL, "PC=A", "PC=C", + "A=PC", "C=PC", "APCEX", "CPCEX", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + /* + * Class Mnemonics + */ + NULL, NULL, "jmp a", "jmp c", + "move.a pc, a", "move.a pc, c", "exg.a a, pc", "exg.a c, pc", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +}; + +static char *in_str_9[16] = +{ + /* + * HP Mnemonics + */ + "=", "#", "=", "#", + ">", "<", ">=", "<=", + /* + * Class Mnemonics + */ + "eq", "ne", "eq", "ne", + "gt", "lt", "ge", "le" +}; + +static char *op_str_9[16] = +{ + /* + * HP Mnemonics + */ + "?A%sB", "?B%sC", "?C%sA", "?D%sC", + "?A%s0", "?B%s0", "?C%s0", "?D%s0", + /* + * Class Mnemonics + */ + "a, b", "b, c", "c, a", "d, c", + "a, 0", "b, 0", "c, 0", "d, 0" +}; + +static char *op_str_af[32] = +{ + /* + * HP Mnemonics + */ + "A=A%sB", "B=B%sC", "C=C%sA", "D=D%sC", + "A=A%sA", "B=B%sB", "C=C%sC", "D=D%sD", + "B=B%sA", "C=C%sB", "A=A%sC", "C=C%sD", + "A=B%sA", "B=C%sB", "C=A%sC", "D=C%sD", + /* + * Class Mnemonics + */ + "b, a", "c, b", "a, c", "c, d", + "a, a", "b, b", "c, c", "d, d", + "a, b", "b, c", "c, a", "d, c", + "b, a", "c, b", "a, c", "c, d" +}; + +static char hp_reg_1_af[] = "ABCDABCDBCACABAC"; +static char hp_reg_2_af[] = "0000BCACABCDBCCD"; + +static char *field_tbl[32] = +{ + /* + * HP Mnemonics + */ + "P", "WP", "XS", "X", + "S", "M", "B", "W", + "P", "WP", "XS", "X", + "S", "M", "B", "A", + /* + * Class Mnemonics + */ + ".p", ".wp", ".xs", ".x", + ".s", ".m", ".b", ".w", + ".p", ".wp", ".xs", ".x", + ".s", ".m", ".b", ".a", +}; + +static char *hst_bits[8] = +{ + /* + * HP Mnemonics + */ + "XM", "SB", "SR", "MP", + /* + * Class Mnemonics + */ + "xm", "sb", "sr", "mp", +}; + + +// static functions + +// 10.11.98 cg, added new mapping functions + +static BYTE rn_map (DWORD *p) +{ + DWORD d = *p; + + *p = ++(*p) & 0xFFFFF; + + _ASSERT(d < 0x100000); + return *(RMap[d>>12]+(d&0xFFF)); +} + +static BYTE rn_rom (DWORD *p) +{ + DWORD d = *p; + + *p = ++(*p) & (dwRomSize - 1); + + _ASSERT(d < dwRomSize); + return *(pbyRom + d); +} + +static BYTE rn_ram (DWORD *p) +{ + DWORD d = *p; + + *p = ++(*p) & (Chipset.Port0Size * 2048 - 1); + + _ASSERT(d < Chipset.Port0Size * 2048); + return *(Chipset.Port0 + d); +} + +static BYTE rn_port1 (DWORD *p) +{ + DWORD d = *p; + + *p = ++(*p) & (Chipset.Port1Size * 2048 - 1); + + _ASSERT(d < Chipset.Port1Size * 2048); + return *(Chipset.Port1 + d); +} + +static BYTE rn_port2 (DWORD *p) +{ + DWORD d = *p; + + *p = ++(*p) & (((dwPort2Mask + 1) << 17) - 1); + + _ASSERT(d < ((dwPort2Mask + 1) << 17)); + return *(pbyPort2 + d); +} + +static BYTE read_nibble (DWORD *p) +{ + BYTE (*pnread[])(DWORD *) = { rn_map, rn_rom, rn_ram, rn_port1, rn_port2 }; + + _ASSERT(disassembler_map < sizeof(pnread) / sizeof(pnread[0])); + return pnread[disassembler_map](p); +} + +// general functions + +static int read_int (DWORD *addr, int n) +{ + int i, t; + + for (i = 0, t = 0; i < n; i++) + t |= read_nibble (addr) << (i * 4); + + return t; +} + +static char *append_str (char *buf, char *str) +{ + while ((*buf = *str++)) + buf++; + return buf; +} + +static char *append_tab (char *buf) +{ + int n; + char *p; + + n = TAB_SKIP - (strlen (buf) % TAB_SKIP); + p = &buf[strlen (buf)]; + while (n--) + *p++ = ' '; + *p = 0; + return p; +} + +static char *append_field (char *buf, BYTE fn) +{ + buf = append_str (buf, field_tbl[fn + 16 * disassembler_mode]); + return buf; +} + +static char *append_imm_nibble (char *buf, DWORD *addr, int n) +{ + int i; + char t[16]; + + if (disassembler_mode == CLASS_MNEMONICS) + { + *buf++ = '#'; + 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++) + t[i] = hex[disassembler_mode][read_nibble (addr)]; + for (i = n - 1; i >= 0; i--) + { + *buf++ = t[i]; + } + *buf = 0; + } + else + { + wsprintf (t, "%d", read_nibble (addr)); + buf = append_str (buf, t); + } + return buf; +} + +static char *append_addr (char *buf, DWORD addr) +{ + int shift; + long mask; + + if (disassembler_mode == CLASS_MNEMONICS) + { + *buf++ = '$'; + } + for (mask = 0xf0000, shift = 16; mask != 0; mask >>= 4, shift -= 4) + *buf++ = hex[disassembler_mode][(addr & mask) >> shift]; + *buf = 0; + return buf; +} + +static char *append_r_addr (char *buf, DWORD * pc, long disp, int n, int offset) +{ + long sign; + + sign = 1 << (n * 4 - 1); + if (disp & sign) + disp |= ~(sign - 1); + *pc += disp; + + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (disp < 0) + { + buf = append_str(buf, "-"); + disp = -disp - offset; + } + else + { + buf = append_str(buf, "+"); + disp += offset; + } + buf = append_addr(buf, disp); + break; + case CLASS_MNEMONICS: + if (disp < 0) + { + buf = append_str(buf, "-"); + disp = -disp - offset; + } + else + { + buf = append_str(buf, "+"); + disp += offset; + } + buf = append_addr (buf, disp); + break; + default: + buf = append_str (buf, "Unknown disassembler mode"); + break; + } + return buf; +} + +static char *append_pc_comment (char *buf, DWORD pc) +{ + char *p = buf; + + 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; + } + return p; +} + + +static char *append_hst_bits (char *buf, int n) +{ + int i; + char *p = buf; + + switch (disassembler_mode) + { + case HP_MNEMONICS: + 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; + + case CLASS_MNEMONICS: + while (strlen (buf) < 4 * TAB_SKIP) + p = append_tab (buf); + p = &buf[strlen (buf)]; + p = append_str (p, "; hst bits: "); + + for (buf = p, 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; + + default: + p = append_str (p, "Unknown disassembler mode"); + break; + } + + return p; +} + + +static char *disasm_1 (DWORD *addr, char *out) +{ + BYTE n; + BYTE fn; + char *p; + char buf[20]; + char c; + + p = out; + switch (n = read_nibble (addr)) + { + case 0: + case 1: + fn = read_nibble (addr); + fn = (fn & 7); + if (fn > 4) + fn -= 4; + switch (disassembler_mode) + { + case HP_MNEMONICS: + c = (char) ((fn < 8) ? 'A' : 'C'); + if (n == 0) + wsprintf (buf, "R%d=%c", fn, c); + else + wsprintf (buf, "%c=R%d", c, fn); + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, "move.w"); + p = append_tab (out); + c = (char) ((fn < 8) ? 'a' : 'c'); + if (n == 0) + wsprintf (buf, "%c, r%d", c, fn); + else + wsprintf (buf, "r%d, %c", fn, c); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 2: + fn = read_nibble (addr); + fn = (fn & 7); + if (fn > 4) + fn -= 4; + switch (disassembler_mode) + { + case HP_MNEMONICS: + c = (char) ((fn < 8) ? 'A' : 'C'); + wsprintf (buf, "%cR%dEX", c, fn); + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, "exg.w"); + p = append_tab (out); + c = (char) ((fn < 8) ? 'a' : 'c'); + wsprintf (buf, "%c, r%d", c, fn); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 3: + n = read_nibble (addr); + switch (disassembler_mode) + { + case HP_MNEMONICS: + c = (n & 4) ? 'C' : 'A'; + if (n & 2) + { + if (n < 8) + { + wsprintf (buf, "%cD%dEX", c, (n & 1)); + } + else + { + wsprintf (buf, "%cD%dXS", c, (n & 1)); + } + } + else + { + if (n < 8) + { + wsprintf (buf, "D%d=%c", (n & 1), c); + } + else + { + wsprintf (buf, "D%d=%cS", (n & 1), c); + } + } + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, (n & 2) ? "exg." : "move."); + p = append_str (p, (n < 8) ? "a" : "4"); + p = append_tab (out); + c = (n & 4) ? 'c' : 'a'; + wsprintf (buf, "%c, d%d", c, (n & 1)); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 4: + case 5: + fn = read_nibble (addr); + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (out, op_str_1[(fn & 7) + 8 * disassembler_mode]); + p = append_tab (out); + if (n == 4) + { + p = append_str (p, (fn < 8) ? "A" : "B"); + } + else + { + n = read_nibble (addr); + if (fn < 8) + { + p = append_field (p, n); + } + else + { + wsprintf (buf, "%d", n + 1); + p = append_str (p, buf); + } + } + break; + case CLASS_MNEMONICS: + p = append_str (out, "move"); + if (n == 4) + { + p = append_str (p, "."); + p = append_str (p, (fn < 8) ? "a" : "b"); + } + else + { + n = read_nibble (addr); + if (fn < 8) + { + p = append_field (p, n); + } + else + { + wsprintf (buf, ".%d", n + 1); + p = append_str (p, buf); + } + } + p = append_tab (out); + p = append_str (p, op_str_1[(fn & 7) + 8 * disassembler_mode]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 6: + case 7: + case 8: + case 0xc: + fn = read_nibble (addr); + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (n == 6 || n == 8) + p = append_str (out, "D0=D0"); + else + p = append_str (out, "D1=D1"); + if (n < 8) + p = append_str (p, "+"); + else + p = append_str (p, "-"); + p = append_tab (out); + wsprintf (buf, "%d", fn + 1); + p = append_str (p, buf); + break; + case CLASS_MNEMONICS: + if (n < 8) + p = append_str (out, "add.a"); + else + p = append_str (out, "sub.a"); + p = append_tab (out); + wsprintf (buf, "#%d, ", fn + 1); + p = append_str (p, buf); + if (n == 6 || n == 8) + p = append_str (p, "d0"); + else + p = append_str (p, "d1"); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 9: + case 0xa: + case 0xb: + case 0xd: + case 0xe: + case 0xf: + c = (char) ((n < 0xd) ? '0' : '1'); + switch (n & 3) + { + case 1: + n = 2; + break; + case 2: + n = 4; + break; + case 3: + n = 5; + break; + } + switch (disassembler_mode) + { + case HP_MNEMONICS: + wsprintf (buf, "D%c=(%d)", c, n); + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, addr, n); + break; + case CLASS_MNEMONICS: + if (n == 5) + { + wsprintf (buf, "move.a"); + } + else + if (n == 4) + { + wsprintf (buf, "move.as"); + } + else + { + wsprintf (buf, "move.b"); + } + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, addr, n); + wsprintf (buf, ", d%c", c); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + default: + break; + } + return p; +} + +static char *disasm_8 (DWORD *addr, char *out) +{ + BYTE n; + BYTE fn; + char *p = out; + char c; + char buf[20]; + DWORD disp, pc; + + fn = read_nibble (addr); + switch (fn) + { + case 0: + n = read_nibble (addr); + if (NULL != (p = in_str_80[n + 16 * disassembler_mode])) + { + p = append_str (out, p); + return p; + } + switch (n) + { + case 8: + fn = read_nibble (addr); + if (NULL != (p = in_str_808[fn + 16 * disassembler_mode])) + { + p = append_str (out, p); + return p; + } + switch (fn) + { + case 1: + n = read_nibble (addr); + if (n == 0) + { + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (out, "RSI"); + break; + case CLASS_MNEMONICS: + p = append_str (out, "rsi"); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + } + break; + case 2: + n = read_nibble (addr); + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (n < 5) + { + wsprintf (buf, "LA(%d)", n + 1); + } + else + { + wsprintf (buf, "LAHEX"); + } + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, addr, n + 1); + break; + case CLASS_MNEMONICS: + wsprintf (buf, "move.%d", n + 1); + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, addr, n + 1); + wsprintf (buf, ", a.p"); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 4: + case 5: + case 8: + case 9: + switch (disassembler_mode) + { + case HP_MNEMONICS: + wsprintf (buf, "%cBIT=%d", (fn & 8) ? 'C' : 'A', + (fn & 1) ? 1 : 0); + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, addr, 1); + break; + case CLASS_MNEMONICS: + p = append_str (out, (fn & 1) ? "bset" : "bclr"); + p = append_tab (out); + p = append_imm_nibble (p, addr, 1); + p = append_str (p, (fn & 8) ? ", c" : ", a"); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 6: + case 7: + case 0xa: + case 0xb: + n = read_nibble (addr); + pc = *addr; + disp = read_int (addr, 2); + + switch (disassembler_mode) + { + case HP_MNEMONICS: + c = (char) ((fn < 0xa) ? 'A' : 'C'); + wsprintf (buf, "?%cBIT=%d", c, (fn & 1) ? 1 : 0); + p = append_str (out, buf); + p = append_tab (out); + wsprintf (buf, "%d", n); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", GOYES "); + p = append_r_addr (p, &pc, disp, 2, 5); + p = append_pc_comment (out, pc); + } + else + p = append_str (p, ", RTNYES"); + break; + case CLASS_MNEMONICS: + c = (char) ((fn < 0xa) ? 'a' : 'c'); + p = append_str (out, (disp == 0) ? "rt" : "b"); + p = append_str (p, (fn & 1) ? "bs" : "bc"); + p = append_tab (out); + wsprintf (buf, "#%d, %c", n, c); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", "); + p = append_r_addr (p, &pc, disp, 2, 5); + p = append_pc_comment (out, pc); + } + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + default: + break; + } + break; + + case 0xc: + case 0xd: + case 0xf: + fn = read_nibble (addr); + switch (disassembler_mode) + { + case HP_MNEMONICS: + wsprintf (buf, (n == 0xf) ? "%c%cEX" : "%c=%c", + (n == 0xd) ? 'P' : 'C', (n == 0xd) ? 'C' : 'P'); + p = append_str (out, buf); + p = append_tab (out); + wsprintf (buf, "%d", fn); + p = append_str (p, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, (n == 0xf) ? "exg.1" : "move.1"); + p = append_tab (out); + wsprintf (buf, (n == 0xd) ? "p, c.%d" : "c.%d, p", fn); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + default: + break; + } + break; + + case 1: + switch (n = read_nibble (addr)) + { + case 0: + case 1: + case 2: + case 3: + switch (disassembler_mode) + { + case HP_MNEMONICS: + wsprintf (buf, "%sSLC", op_str_81[(n & 3) + 4 * disassembler_mode]); + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, "rol.w"); + p = append_tab (out); + p = append_str (p, "#4, "); + p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 4: + case 5: + case 6: + case 7: + switch (disassembler_mode) + { + case HP_MNEMONICS: + wsprintf (buf, "%sSRC", op_str_81[(n & 3) + 4 * disassembler_mode]); + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, "ror.w"); + p = append_tab (out); + p = append_str (p, "#4, "); + p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 8: + fn = read_nibble (addr); + n = read_nibble (addr); + switch (disassembler_mode) + { + case HP_MNEMONICS: + wsprintf (buf, "%s=%s%cCON", + op_str_81[(n & 3) + 4 * disassembler_mode], + op_str_81[(n & 3) + 4 * disassembler_mode], + (n < 8) ? '+' : '-'); + p = append_str (out, buf); + p = append_tab (out); + p = append_field (p, fn); + fn = read_nibble (addr); + wsprintf (buf, ", %d", fn + 1); + p = append_str (p, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, (n < 8) ? "add" : "sub"); + p = append_field (p, fn); + p = append_tab (out); + fn = read_nibble (addr); + wsprintf (buf, "#%d, ", fn + 1); + p = append_str (p, buf); + p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 9: + switch (disassembler_mode) + { + case HP_MNEMONICS: + wsprintf (buf, "%sSRB.F", + op_str_81[(n & 3) + 4 * disassembler_mode]); + p = append_str (out, buf); + p = append_tab (out); + p = append_field (p, read_nibble (addr)); + break; + case CLASS_MNEMONICS: + p = append_str (out, "lsr"); + p = append_field (p, read_nibble (addr)); + p = append_tab (out); + p = append_str (p, "#1, "); + p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 0xa: + fn = read_nibble (addr); + n = read_nibble (addr); + if (n > 2) + break; + c = (char) read_nibble (addr); + if (((int) c & 7) > 4) + break; + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (n == 2) + { + wsprintf (buf, "%cR%dEX.F", ((int) c < 8) ? 'A' : 'C', + (int) c & 7); + } + else + if (n == 1) + { + wsprintf (buf, "%c=R%d.F", ((int) c < 8) ? 'A' : 'C', + (int) c & 7); + } + else + { + wsprintf (buf, "R%d=%c.F", (int) c & 7, + ((int) c < 8) ? 'A' : 'C'); + } + p = append_str (out, buf); + p = append_tab (out); + p = append_field (p, fn); + break; + case CLASS_MNEMONICS: + p = append_str (out, (n == 2) ? "exg" : "move"); + p = append_field (p, fn); + p = append_tab (out); + if (n == 1) + { + wsprintf (buf, "r%d", (int) c & 7); + p = append_str (p, buf); + } + else + p = append_str (p, ((int) c < 8) ? "a" : "c"); + p = append_str (p, ", "); + if (n == 1) + p = append_str (p, ((int) c < 8) ? "a" : "c"); + else + { + wsprintf (buf, "r%d", (int) c & 7); + p = append_str (p, buf); + } + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 0xb: + n = read_nibble (addr); + if ((n < 2) || (n > 7)) + break; + + p = append_str (out, in_str_81b[n + 16 * disassembler_mode]); + break; + + case 0xc: + case 0xd: + case 0xe: + case 0xf: + switch (disassembler_mode) + { + case HP_MNEMONICS: + wsprintf (buf, "%sSRB", op_str_81[(n & 3) + 4 * disassembler_mode]); + p = append_str (out, buf); + break; + case CLASS_MNEMONICS: + p = append_str (out, "lsr.w"); + p = append_tab (out); + p = append_str (p, "#1, "); + p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + default: + break; + } + break; + + case 2: + n = read_nibble (addr); + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (n == 0xf) + { + p = append_str (out, "CLRHST"); + } + else + { + p = append_hst_bits (out, n); + p = append_str (p, "=0"); + } + break; + case CLASS_MNEMONICS: + p = append_str (out, "clr.1"); + p = append_tab (out); + wsprintf (buf, "#%d, hst", n); + p = append_str (p, buf); + p = append_hst_bits (out, n); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 3: + n = read_nibble (addr); + pc = *addr; + disp = read_int (addr, 2); + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (out, "?"); + p = append_hst_bits (p, n); + p = append_str (p, "=0"); + p = append_tab (out); + if (disp != 0) + { + p = append_str (p, "GOYES "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + else + p = append_str (p, "RTNYES"); + break; + case CLASS_MNEMONICS: + p = append_str (out, (disp == 0) ? "rt" : "b"); + p = append_str (p, "eq.1"); + p = append_tab (out); + wsprintf (buf, "#%d, hst", n); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + p = append_hst_bits (out, n); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 4: + case 5: + switch (disassembler_mode) + { + case HP_MNEMONICS: + wsprintf (buf, "ST=%d", (fn == 4) ? 0 : 1); + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, addr, 1); + break; + case CLASS_MNEMONICS: + p = append_str (out, (fn == 4) ? "bclr" : "bset"); + p = append_tab (out); + p = append_imm_nibble (p, addr, 1); + p = append_str (p, ", st"); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 6: + case 7: + n = read_nibble (addr); + pc = *addr; + disp = read_int (addr, 2); + switch (disassembler_mode) + { + case HP_MNEMONICS: + wsprintf (buf, "?ST=%d", (fn == 6) ? 0 : 1); + p = append_str (out, buf); + p = append_tab (out); + wsprintf (buf, "%d", n); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", GOYES "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + else + p = append_str (p, ", RTNYES"); + break; + case CLASS_MNEMONICS: + p = append_str (out, (disp == 0) ? "rt" : "b"); + p = append_str (p, (fn == 6) ? "bc" : "bs"); + p = append_tab (out); + wsprintf (buf, "#%d, st", n); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 8: + case 9: + n = read_nibble (addr); + pc = *addr; + disp = read_int (addr, 2); + switch (disassembler_mode) + { + case HP_MNEMONICS: + wsprintf (buf, "?P%c", (fn == 8) ? '#' : '='); + p = append_str (out, buf); + p = append_tab (out); + wsprintf (buf, "%d", n); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", GOYES "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + else + p = append_str (p, ", RTNYES"); + break; + case CLASS_MNEMONICS: + p = append_str (out, (disp == 0) ? "rt" : "b"); + p = append_str (p, (fn == 8) ? "ne.1" : "eq.1"); + p = append_tab (out); + wsprintf (buf, "#%d, p", n); + p = append_str (p, buf); + if (disp != 0) + { + p = append_str (p, ", "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 0xc: + case 0xe: + pc = *addr; + if (fn == 0xe) + pc += 4; + disp = read_int (addr, 4); + switch (disassembler_mode) + { + case HP_MNEMONICS: + 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); + 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); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 0xd: + case 0xf: + pc = read_int (addr, 5); + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (out, (fn == 0xd) ? "GOVLNG" : "GOSBVL"); + p = append_tab (out); + p = append_addr (p, pc); + break; + case CLASS_MNEMONICS: + p = append_str (out, (fn == 0xd) ? "jmp" : "jsr"); + p = append_tab (out); + p = append_addr (p, pc); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + default: + break; + } + return p; +} + + +// public functions + +DWORD disassemble (DWORD addr, LPSTR out) +{ + BYTE n; + BYTE fn; + char *p = out; + char c; + char buf[20]; + DWORD disp, pc; + + switch (n = read_nibble (&addr)) + { + case 0: + if ((n = read_nibble (&addr)) != 0xe) + { + p = append_str (out, opcode_0_tbl[n + 16 * disassembler_mode]); + break; + } + fn = read_nibble (&addr); + n = read_nibble (&addr); + switch (disassembler_mode) + { + case HP_MNEMONICS: + wsprintf (buf, op_str_0[(n & 7) + 8 * HP_MNEMONICS], + (n < 8) ? '&' : '!'); + p = append_str (out, buf); + p = append_tab (out); + p = append_field (p, fn); + break; + case CLASS_MNEMONICS: + p = append_str (out, (n < 8) ? "and" : "or"); + p = append_field (p, fn); + p = append_tab (out); + p = append_str (p, op_str_0[(n & 7) + 8 * CLASS_MNEMONICS]); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 1: + p = disasm_1 (&addr, out); + break; + + case 2: + n = read_nibble (&addr); + 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); + p = append_str (out, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 3: + fn = read_nibble (&addr); + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (fn < 5) + { + wsprintf (buf, "LC(%d)", fn + 1); + } + else + { + wsprintf (buf, "LCHEX"); + } + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, &addr, fn + 1); + break; + case CLASS_MNEMONICS: + wsprintf (buf, "move.%d", fn + 1); + p = append_str (out, buf); + p = append_tab (out); + p = append_imm_nibble (p, &addr, fn + 1); + wsprintf (buf, ", c.p"); + p = append_str (p, buf); + break; + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 4: + case 5: + pc = addr; + disp = read_int (&addr, 2); + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (disp == 2) + { + p = append_str (out, "NOP3"); + break; + } + wsprintf (buf, (disp == 0) ? "RTN%sC" : "GO%sC", (n == 4) ? "" : "N"); + p = append_str (out, buf); + if (disp != 0) + { + p = append_tab (out); + p = append_r_addr (p, &pc, disp, 2, 1); + p = append_pc_comment (out, pc); + } + break; + + case CLASS_MNEMONICS: + if (disp == 2) + { + p = append_str (out, "nop3"); + break; + } + p = append_str (out, (disp == 0) ? "rtc" : "bc"); + p = append_str (p, (n == 4) ? "s" : "c"); + if (disp != 0) + { + p = append_tab (out); + p = append_r_addr (p, &pc, disp, 2, 1); + p = append_pc_comment (out, pc); + } + break; + + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 6: + pc = addr; + disp = read_int (&addr, 3); + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (disp == 3) + { + p = append_str (out, "NOP4"); + break; + } + if (disp == 4) + { + p = append_str (out, "NOP5"); + break; + } + p = append_str (out, "GOTO"); + p = append_tab (out); + p = append_r_addr (p, &pc, disp, 3, 1); + p = append_pc_comment (out, pc); + break; + + case CLASS_MNEMONICS: + if (disp == 3) + { + p = append_str (out, "nop4"); + break; + } + if (disp == 4) + { + p = append_str (out, "nop5"); + break; + } + 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); + break; + + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 7: + pc = addr + 3; + disp = read_int (&addr, 3); + switch (disassembler_mode) + { + case HP_MNEMONICS: + p = append_str (out, "GOSUB"); + p = append_tab (out); + p = append_r_addr (p, &pc, disp, 3, 4); + p = append_pc_comment (out, pc); + 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); + break; + + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + case 8: + fn = read_nibble (&addr); /* PEEK */ + --addr; + if (fn != 0xa && fn != 0xb) + { + p = disasm_8 (&addr, out); + break; + } + /* Fall through */ + + case 9: + fn = read_nibble (&addr); + if (n == 8) + { + c = (char) ((fn == 0xa) ? 0 : 1); + fn = 0xf; + } + else + { + c = (char) ((fn < 8) ? 0 : 1); + fn &= 7; + } + + n = read_nibble (&addr); + pc = addr; + disp = read_int (&addr, 2); + + switch (disassembler_mode) + { + case HP_MNEMONICS: + if ((c == 0) && (n >= 8)) + wsprintf (buf, op_str_9[(n & 3) + 8 * HP_MNEMONICS + 4], + in_str_9[((n >> 2) & 3) + 4 * c + 8 * HP_MNEMONICS]); + else + wsprintf (buf, op_str_9[(n & 3) + 8 * HP_MNEMONICS], + in_str_9[((n >> 2) & 3) + 4 * c + 8 * HP_MNEMONICS]); + p = append_str (out, buf); + p = append_tab (out); + p = append_field (p, fn); + p = append_str (p, ", "); + p = append_str (p, (disp == 0) ? "RTNYES" : "GOYES "); + if (disp != 0) + { + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + break; + + case CLASS_MNEMONICS: + p = append_str (out, (disp == 0) ? "rt" : "b"); + p = append_str (p, in_str_9[((n >> 2) & 3) + 4 * c + 8 * CLASS_MNEMONICS]); + p = append_field (p, fn); + p = append_tab (out); + if ((c == 0) && (n >= 8)) + p = append_str (p, op_str_9[(n & 3) + 8 * CLASS_MNEMONICS + 4]); + else + p = append_str (p, op_str_9[(n & 3) + 8 * CLASS_MNEMONICS]); + if (disp != 0) + { + p = append_str (p, ", "); + p = append_r_addr (p, &pc, disp, 2, 3); + p = append_pc_comment (out, pc); + } + break; + + default: + p = append_str (out, "Unknown disassembler mode"); + break; + } + break; + + default: + switch (n) + { + case 0xa: + fn = read_nibble (&addr); + c = (char) ((fn < 8) ? 0 : 1); + fn &= 7; + disp = 0xa; + break; + case 0xb: + fn = read_nibble (&addr); + c = (char) ((fn < 8) ? 0 : 1); + fn &= 7; + disp = 0xb; + break; + case 0xc: + case 0xd: + fn = 0xf; + c = (char) (n & 1); + disp = 0xa; + break; + case 0xe: + case 0xf: + fn = 0xf; + c = (char) (n & 1); + disp = 0xb; + break; + default: + fn = 0; + disp = 0; + c = 0; + break; + } + + n = read_nibble (&addr); + pc = 0; + + switch (disp) + { + case 0xa: + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (c == 0) + { + if (n < 0xc) + { + p = "+"; + } + else + { + p = "%c=%c-1"; + pc = 2; + } + } + else + { + if (n < 4) + { + p = "%c=0"; + pc = 1; + } + else + if (n >= 0xc) + { + p = "%c%cEX"; + pc = 3; + } + else + { + p = "%c=%c"; + pc = 3; + } + } + break; + + case CLASS_MNEMONICS: + if (c == 0) + { + if (n < 0xc) + { + p = "add"; + } + else + { + p = "dec"; + pc = 1; + } + } + else + { + if (n < 4) + { + p = "clr"; + pc = 1; + } + else + if (n >= 0xc) + { + p = "exg"; + } + else + { + p = "move"; + if (n < 8) + n -= 4; + } + } + break; + + default: + p = append_str (out, "Unknown disassembler mode"); + return addr; + } + break; + + case 0xb: + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (c == 0) + { + if (n >= 0xc) + { + p = "-"; + } + else + if ((n >= 4) && (n <= 7)) + { + p = "%c=%c+1"; + pc = 2; + n -= 4; + } + else + { + p = "-"; + } + } + else + { + if (n < 4) + { + p = "%cSL"; + pc = 1; + } + else + if (n < 8) + { + p = "%cSR"; + pc = 1; + } + else + if (n < 0xc) + { + p = "%c=%c-1"; + pc = 2; + } + else + { + p = "%c=-%c-1"; + pc = 2; + } + } + break; + + case CLASS_MNEMONICS: + if (c == 0) + { + if (n >= 0xc) + { + p = "subr"; + } + else + if ((n >= 4) && (n <= 7)) + { + p = "inc"; + pc = 1; + n -= 4; + } + else + { + p = "sub"; + } + } + else + { + pc = 1; + if (n < 4) + { + p = "lsl"; + } + else + if (n < 8) + { + p = "lsr"; + } + else + if (n < 0xc) + { + p = "neg"; + } + else + { + p = "not"; + } + } + break; + + default: + p = append_str (out, "Unknown disassembler mode"); + return addr; + } + break; + + } + + switch (disassembler_mode) + { + case HP_MNEMONICS: + if (pc == 0) + { + wsprintf (buf, op_str_af[n + 16 * HP_MNEMONICS], p); + } + else + if (pc == 1) + { + wsprintf (buf, p, (n & 3) + 'A'); + } + else + if (pc == 2) + { + wsprintf (buf, p, (n & 3) + 'A', (n & 3) + 'A'); + } + else + { + wsprintf (buf, p, hp_reg_1_af[n], hp_reg_2_af[n]); + } + p = append_str (out, buf); + p = append_tab (out); + p = append_field (p, fn); + break; + + case CLASS_MNEMONICS: + p = append_str (out, p); + p = append_field (p, fn); + p = append_tab (out); + if (pc == 1) + { + wsprintf (buf, "%c", (n & 3) + 'a'); + p = append_str (p, buf); + } + else + { + p = append_str (p, op_str_af[n + 16 * CLASS_MNEMONICS]); + } + break; + + default: + p = append_str (p, "Unknown disassembler mode"); + break; + } + break; + } + *p = 0; + + return addr; +} + diff --git a/sources/Emu48/DISPLAY.C b/sources/Emu48/DISPLAY.C new file mode 100644 index 0000000..3b887b7 --- /dev/null +++ b/sources/Emu48/DISPLAY.C @@ -0,0 +1,753 @@ +/* + * display.c + * + * This file is part of Emu48 + * + * Copyright (C) 1995 Sebastien Carlier + * + */ +#include "pch.h" +#include "resource.h" +#include "Emu48.h" +#include "kml.h" + +#define LCD1_ROW 144 +#define LCD2_ROW 288 +#define LCD3_ROW 576 // 24.08.98 cg, new, X4 display + +UINT nBackgroundX = 0; +UINT nBackgroundY = 0; +UINT nBackgroundW = 0; +UINT nBackgroundH = 0; +UINT nLcdX = 0; +UINT nLcdY = 0; +UINT nLcdDoubled = 1; // 24.08.98 cg, changed to integer var +LPBYTE pbyLcd; +HDC hLcdDC = NULL; // 22.01.98 cg, new, for security only +HDC hMainDC = NULL; // 22.01.98 cg, new, for security only +static HBITMAP hLcdBitmap; +static HBITMAP hMainBitmap; +static HBITMAP hOldLcdBitmap; +static HBITMAP hOldMainBitmap; + +#define B 0x00FFFFFF +#define W 0x00000000 +#define I 0xFFFFFFFF +static struct +{ + BITMAPINFOHEADER Lcd_bmih; + DWORD dwColor[64]; +} bmiLcd = +{ + {0x28,0/*x*/,0/*y*/,1,8,BI_RGB,0,0,0,64,0}, + { + W,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B, + B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B, + I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I, + I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I + } +}; +#undef B +#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 + +VOID UpdateContrast(BYTE byContrast) // 23.02.99 cg, changed, new implementation +{ + DWORD c = byContrast; + DWORD b = byContrast + 0x20; + if (bmiLcd.dwColor[b] == 0xFFFFFFFF) b = 0; + + _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); + + if (nLcdDoubled == 1) + { + WORD i,j; + for (i=0; i<16; ++i) + { + Pattern[i] = 0; + for (j=8; j>0; j>>=1) + { + Pattern[i] = (Pattern[i] << 8) | ((i&j) ? c : b); + } + } + } + + c = (c<<8) | c; + b = (b<<8) | b; + + if (nLcdDoubled == 2) + { + Pattern[0] = (b<<16)|b; + Pattern[1] = (b<<16)|c; + Pattern[2] = (c<<16)|b; + Pattern[3] = (c<<16)|c; + } + + c = (c<<16) | c; + b = (b<<16) | b; + + if (nLcdDoubled == 4) + { + Pattern[0] = b; + Pattern[1] = c; + } + return; +} + +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; +} + +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 +} + +VOID DestroyLcdBitmap() +{ + WORD i; + // 23.02.99 cg, new, clear background colors + for (i=32; i< 64; ++i) bmiLcd.dwColor[i] = 0xFFFFFFFF; + + if (hLcdDC != NULL) + { + // destroy LCD bitmap + SelectObject(hLcdDC, hOldLcdBitmap); + DeleteObject(hLcdBitmap); + DeleteDC(hLcdDC); + hLcdDC = NULL; + hLcdBitmap = NULL; + hOldLcdBitmap = NULL; + } + return; +} + +BOOL CreateMainBitmap(LPSTR szFilename) +{ + hMainDC = CreateCompatibleDC(hWindowDC); + hMainBitmap = LoadBitmapFile(szFilename); + if (hMainBitmap == NULL) + { + DeleteDC(hMainDC); + return FALSE; + } + hOldMainBitmap = SelectObject(hMainDC, hMainBitmap); + SelectPalette(hMainDC, hPalette, FALSE); + return TRUE; +} + +VOID DestroyMainBitmap() +{ + if (hMainDC != NULL) + { + // destroy Main bitmap + SelectObject(hMainDC, hOldMainBitmap); + DeleteObject(hMainBitmap); + DeleteDC(hMainDC); + hMainDC = NULL; + hMainBitmap = NULL; + hOldMainBitmap = NULL; + } + return; +} + +//**************** +//* +//* LCD functions +//* +//**************** + +VOID UpdateDisplayPointers() +{ + // 09.09.98 cg, bugfix, 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 + Chipset.start12 = Chipset.end1 - Chipset.width; + // 09.09.98 cg, bugfix, calculate last address of main display + Chipset.end1 = Chipset.start1 - Chipset.width; + } + else + { + Chipset.start12 = Chipset.start1; + } + Chipset.end2 = Chipset.start2 + (63 - Chipset.lcounter) * 34; +} + +static BYTE Buf[36]; +static BOOL bScreenIsClean = FALSE; + +VOID UpdateMainDisplay() // 29.04.98 cg, bugfix, update display even if it's off +{ + UINT x, y; + INT nLines; + DWORD d = Chipset.start1; + BYTE *p = pbyLcd; + + if (!Chipset.dispon) + { + nLines = 64; + 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); + } + } + 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) + { + for (y=0; y<=Chipset.lcounter; y++) + { + Npeek(Buf,d,36); + for (x=0; x<36; x++) + { + *(((DWORD*)p)++)=Pattern[Buf[x]&1]; + *(((DWORD*)p)++)=Pattern[(Buf[x]>>1) & 1]; + *(((DWORD*)p)++)=Pattern[(Buf[x]>>2) & 1]; + *(((DWORD*)p)++)=Pattern[(Buf[x]>>3) & 1]; + } + CopyMemory(p, p-LCD3_ROW, LCD3_ROW); + p+=LCD3_ROW; + CopyMemory(p, p-LCD3_ROW*2, LCD3_ROW*2); + p+=LCD3_ROW*2; + d+=Chipset.width; + } + } + // 24.08.98 cg, end of new part + if (nLcdDoubled == 2) // 24.08.98 cg, new var type + { + for (y=0; y<=Chipset.lcounter; y++) + { + Npeek(Buf,d,36); + for (x=0; x<36; x++) + { + *(((DWORD*)p)++)=Pattern[Buf[x]&3]; + *(((DWORD*)p)++)=Pattern[Buf[x]>>2]; + } + CopyMemory(p, p-LCD2_ROW, LCD2_ROW); + p+=LCD2_ROW; + d+=Chipset.width; + } + } + if (nLcdDoubled == 1) // 24.08.98 cg, new var type + { + for (y=0; y<=Chipset.lcounter; y++) + { + Npeek(Buf,d,36); + for (x=0; x<36; x++) *(((DWORD*)p)++)=Pattern[Buf[x]]; + d+=Chipset.width; + } + } + } + EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, 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 + } + LeaveCriticalSection(&csGDILock); // 22.01.98 cg + return; +} + +VOID UpdateMenuDisplay() +{ + UINT x, y; + BYTE *p; + DWORD d = Chipset.start2; + + 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 + 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 + for (x=0; x<36; x++) + { + *(((DWORD*)p)++)=Pattern[Buf[x]&1]; + *(((DWORD*)p)++)=Pattern[(Buf[x]>>1) & 1]; + *(((DWORD*)p)++)=Pattern[(Buf[x]>>2) & 1]; + *(((DWORD*)p)++)=Pattern[(Buf[x]>>3) & 1]; + } + CopyMemory(p, p-LCD3_ROW, LCD3_ROW); + p+=LCD3_ROW; + CopyMemory(p, p-LCD3_ROW*2, LCD3_ROW*2); + p+=LCD3_ROW*2; + d+=34; + } + } + // 24.08.98 cg, end of new part + if (nLcdDoubled == 2) // 24.08.98 cg, new var type + { + for (y=Chipset.lcounter+1; y<64; y++) + { + Npeek(Buf,d,34); // 01.02.99 cg, only 34 nibbles are viewed + for (x=0; x<36; x++) + { + *(((DWORD*)p)++)=Pattern[Buf[x]&3]; + *(((DWORD*)p)++)=Pattern[Buf[x]>>2]; + } + CopyMemory(p, p-LCD2_ROW, LCD2_ROW); + p+=LCD2_ROW; + d+=34; + } + } + if (nLcdDoubled == 1) // 24.08.98 cg, new var type + { + for (y=Chipset.lcounter+1; y<64; y++) + { + Npeek(Buf,d,34); // 01.02.99 cg, only 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 + { + // 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 + } + LeaveCriticalSection(&csGDILock); // 22.01.98 cg + 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; + + INT lWidth = abs(Chipset.width); // display width + + d -= Chipset.start1; // nibble offset to DISPADDR (start of display) + d += 64 * lWidth; // make positive offset + y0 = abs((INT) d / lWidth - 64); // bitmap row + x0 = (INT) d % lWidth; // bitmap coloumn + y = y0; x = x0; // load loop variables + + // outside main display area + _ASSERT(y0 >= 0 && y0 <= (INT) Chipset.lcounter); + + // illegal zoom factor + _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); + + // calculate memory position in LCD bitmap + p = (DWORD*) (pbyLcd + y0*LCD1_ROW*nLcdDoubled*nLcdDoubled + + x0*sizeof(bmiLcd.dwColor[0])*nLcdDoubled); + + while (s--) // loop for nibbles to write + { + if (x<36) // only fill visible area + { + if (nLcdDoubled == 4) + { + p[432] = p[288] = p[144] = p[0] = Pattern[(*a)&1]; + p[433] = p[289] = p[145] = p[1] = Pattern[((*a)>>1) &1]; + p[434] = p[290] = p[146] = p[2] = Pattern[((*a)>>2) &1]; + p[435] = p[291] = p[147] = p[3] = Pattern[((*a)>>3) &1]; + } + if (nLcdDoubled == 2) + { + p[72] = p[0] = Pattern[(*a)&3]; + p[73] = p[1] = Pattern[(*a)>>2]; + } + if (nLcdDoubled == 1) + { + *p = Pattern[*a]; + } + } + ++a; // next value to write + ++x; // next x position + if ((x==lWidth)&&s) // end of display line + { + // end of main display area + if (y == (INT) Chipset.lcounter) break; + + x = 0; // first coloumn + ++y; // next row + // recalculate bitmap memory position of new line + p = (DWORD*) (pbyLcd+y*LCD1_ROW*nLcdDoubled*nLcdDoubled); + } + else + p += nLcdDoubled; // next x position in bitmap + } + + // update window region + if (y0 != y) // changed more than one line + { + x0 = 0; // no x-position offset + x = 131; // redraw complete lines + + ++y; // redraw this line as well + } + else + { + x0 <<= 2; x <<= 2; // x-position in pixel + _ASSERT(x >= x0); // can't draw negative number of pixel + x -= x0; // number of pixels to update + + x0 -= Chipset.boffset; // adjust x-position with left margin + if (x0 < 0) x0 = 0; + + if (x0 > 131) x0 = 131; // cut right borders + if (x+x0 > 131) x = 131 - x0; + + y = y0 + 1; // draw one line + } + + x0 <<= nLcdDoubled / 2; // adjust dimensions to pixel size + x <<= nLcdDoubled / 2; + y0 <<= nLcdDoubled / 2; + y <<= nLcdDoubled / 2; + + EnterCriticalSection(&csGDILock); + { + BitBlt(hWindowDC, nLcdX+x0, nLcdY+y0, x, y-y0, hLcdDC, x0+Chipset.boffset*nLcdDoubled, y0, SRCCOPY); + 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; +} + +VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s) +{ + UINT x0, x; + 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 + _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); + if (nLcdDoubled == 4) + { + p = (DWORD*)(pbyLcd + y0*LCD3_ROW*4 + x0*16); + while (s--) + { + if (x<34) + { + p[432] = p[288] = p[144] = p[0] = Pattern[(*a)&1]; + p[433] = p[289] = p[145] = p[1] = Pattern[((*a)>>1) &1]; + p[434] = p[290] = p[146] = p[2] = Pattern[((*a)>>2) &1]; + p[435] = p[291] = p[147] = p[3] = Pattern[((*a)>>3) &1]; + } + a++; + x++; + if ((x==34)&&s) + { + x=0; + y++; + if (y==64) 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) + { + y0<<=2; y<<=2; + BitBlt(hWindowDC, nLcdX, nLcdY+y0, 524, y-y0+4, hLcdDC, 0, y0, SRCCOPY); + } + else + { + x0<<=4; x<<=4; + y0<<=2; y<<=2; + 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 + } + LeaveCriticalSection(&csGDILock); // 22.01.98 cg + } + // 24.08.98 cg, new, new part for X4 + if (nLcdDoubled == 2) // 24.08.98 cg, new var type + { + p = (DWORD*)(pbyLcd + y0*LCD2_ROW*2 + x0*8); + while (s--) + { + if (x<34) + { + p[72] = p[0] = Pattern[(*a)&3]; + p[73] = p[1] = Pattern[(*a)>>2]; + } + a++; + x++; + if ((x==34)&&s) + { + x=0; + y++; + if (y==64) 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) + { + y0<<=1; y<<=1; + BitBlt(hWindowDC, nLcdX, nLcdY+y0, 262, y-y0+2, hLcdDC, 0, y0, SRCCOPY); + } + else + { + x0<<=3; x<<=3; + y0<<=1; y<<=1; + 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 + } + 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<34) *p = Pattern[*a]; + a++; + x++; + if ((x==34)&&s) + { + x=0; + y++; + if (y==64) 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, 0, y0, SRCCOPY); + } + else + { + x0<<=2; x<<=2; + 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 + } + LeaveCriticalSection(&csGDILock); // 22.01.98 cg + } + return; +} + +VOID UpdateAnnunciators() +{ + BYTE c; + + c = (BYTE)(Chipset.IORam[0xB] | (Chipset.IORam[0xC]<<4)); + if (!(c&0x80)) c=0; + DrawAnnunciator(1,c&0x01); + DrawAnnunciator(2,c&0x02); + DrawAnnunciator(3,c&0x04); + DrawAnnunciator(4,c&0x08); + DrawAnnunciator(5,c&0x10); + DrawAnnunciator(6,c&0x20); + return; +} + +VOID ResizeWindow() +{ + RECT rectWindow; + RECT rectClient; + + if (hWnd == NULL) return; // 30.01.98 cg, bugfix, return if window closed + + rectWindow.left = 0; + rectWindow.top = 0; + rectWindow.right = nBackgroundW; + rectWindow.bottom = nBackgroundH; + AdjustWindowRect(&rectWindow, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, TRUE); + SetWindowPos (hWnd, (HWND)NULL, 0, 0, + rectWindow.right - rectWindow.left, + rectWindow.bottom - rectWindow.top, + SWP_NOMOVE | SWP_NOZORDER); + GetClientRect(hWnd, &rectClient); + AdjustWindowRect(&rectClient, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, TRUE); + if (rectClient.bottom < rectWindow.bottom) + { + rectWindow.bottom += (rectWindow.bottom - rectClient.bottom); + SetWindowPos (hWnd, (HWND)NULL, 0, 0, + rectWindow.right - rectWindow.left, + rectWindow.bottom - rectWindow.top, + SWP_NOMOVE | SWP_NOZORDER); + } + InvalidateRect(hWnd,NULL,TRUE); + return; +} \ No newline at end of file diff --git a/sources/Emu48/EMU48.C b/sources/Emu48/EMU48.C new file mode 100644 index 0000000..7de057f --- /dev/null +++ b/sources/Emu48/EMU48.C @@ -0,0 +1,1611 @@ +/* + * Emu48.c + * + * This file is part of Emu48 + * + * Copyright (C) 1995 Sebastien Carlier + * + */ +#include "pch.h" +#include "resource.h" +#include "Emu48.h" +#include "kml.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 MAXPORTS 16 // 20.05.98 cg, 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 + +#ifdef _DEBUG +LPSTR szNoTitle = "Emu48 "VERSION" Debug"; +#else +LPSTR szNoTitle = "Emu48 "VERSION; // 20.01.98 cg, changed +#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 szTitle = NULL; + +static const char szLicence[] = + "This program is free software; you can redistribute it and/or modify\r\n" + "it under the terms of the GNU General Public License as published by\r\n" + "the Free Software Foundation; either version 2 of the License, or\r\n" + "(at your option) any later version.\r\n" + "\r\n" + "This program is distributed in the hope that it will be useful,\r\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n" + "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."; + + +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 +HANDLE hThread; +DWORD lThreadId; +BOOL bAutoSave = FALSE; +BOOL bAutoSaveOnExit = TRUE; +BOOL bAlwaysDisplayLog = TRUE; + +static BOOL bRealSpeed = FALSE; + +//################ +//# +//# Window Status +//# +//################ + +VOID SetWindowTitle(LPSTR szString) +{ + if (szTitle) + { + LocalFree(szTitle); + } + if (szString) + { + szTitle = DuplicateString(szString); + } + else + { + szTitle = NULL; + } + if (szTitle) + { + SetWindowText(hWnd, szTitle); + } + else + { + SetWindowText(hWnd, szNoTitle); + } + return; +} + +VOID UpdateWindowStatus() +{ + HMENU hMenu; + + if (hWnd == NULL) return; // 30.01.98 cg, bugfix, 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); + 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 + EnableMenuItem(hMenu,ID_TOOL_DISASM,MF_ENABLED); + } + else + { + EnableMenuItem(hMenu,ID_FILE_SAVE,MF_GRAYED); + EnableMenuItem(hMenu,ID_FILE_SAVEAS,MF_GRAYED); + EnableMenuItem(hMenu,ID_FILE_CLOSE,MF_ENABLED); + EnableMenuItem(hMenu,ID_BACKUP_SAVE,MF_GRAYED); + EnableMenuItem(hMenu,ID_VIEW_COPY,MF_GRAYED); + 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) + { + EnableMenuItem(hMenu,ID_BACKUP_RESTORE,MF_ENABLED); + EnableMenuItem(hMenu,ID_BACKUP_DELETE,MF_ENABLED); + } + else + { + EnableMenuItem(hMenu,ID_BACKUP_RESTORE,MF_GRAYED); + EnableMenuItem(hMenu,ID_BACKUP_DELETE,MF_GRAYED); + } + return; +} + + + +//################ +//# +//# Settings +//# +//################ + +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 +static VOID SetCommList(HWND hDlg,int nIDDlgItem,char *szSetting) +{ + HANDLE hComm; + BOOL bAdd; + WORD wCount, wIndex = 1; + char szBuffer[16]; + + WPARAM wSelect = 0; // set select to disabled + SendDlgItemMessage(hDlg,nIDDlgItem,CB_ADDSTRING,0,(LPARAM) NO_SERIAL); + + for (wCount = 1;wCount <= MAXPORTS;++wCount) + { + wsprintf(szBuffer,"COM%u",wCount); + if (bAdd = (strcmp(szBuffer,szSetting) == 0)) + wSelect = wIndex; + + // test if COM port is valid + hComm = CreateFile(szBuffer,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); + if(hComm != INVALID_HANDLE_VALUE) + { + BOOL bError = CloseHandle(hComm); + _ASSERT(bError); + bAdd = TRUE; + } + + if (bAdd) // add item to combobox + { + SendDlgItemMessage(hDlg,nIDDlgItem,CB_ADDSTRING,0,(LPARAM) szBuffer); + ++wIndex; + } + } + 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 + 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 + 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 + { + EnableWindow(GetDlgItem(hDlg,IDC_WIRE),FALSE); + EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE); + } + return TRUE; + case WM_COMMAND: + if (wParam == IDOK) + { + // BOOL bTranslated; + // UINT uNewT1Period; + if (Chipset.Port1Size) + { + 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; + if (IsDlgButtonChecked(hDlg, IDC_PORT1EN)) + { + Chipset.cards_status |= PORT1_PRESENT; + if (Chipset.Port1_Writeable) + Chipset.cards_status |= PORT1_WRITE; + } + if (Chipset.inte) + { + Chipset.Shutdn = FALSE; + Chipset.SoftInt = TRUE; + bInterrupt = TRUE; + } + Map(0x00,0xFF); + SwitchToState(nOldState); + } + // 23.04.98 cg, new, 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 + 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 + GetDlgItemText(hDlg,IDC_WIRE,szSerialWire,sizeof(szSerialWire)); + GetDlgItemText(hDlg,IDC_IR ,szSerialIr ,sizeof(szSerialIr)); + EndDialog(hDlg, wParam); + } + if (wParam == IDCANCEL) + { + 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); +} + + +//################ +//# +//# Save Helper +//# +//################ + +// +// UINT SaveChanges(BOOL bAuto); +// Return code : +// IDYES File successfuly saved +// IDNO File not saved +// IDCANCEL Cancel command +// +static UINT SaveChanges(BOOL bAuto) +{ + UINT uReply; + + if (pbyRom == NULL) return IDNO; + + if (bAuto) + uReply = IDYES; + else + uReply = YesNoCancelMessage("Do you want to save changes ?"); + + if (uReply != IDYES) return uReply; + + if (szCurrentFilename[0]==0) + { // Save As... + uReply = GetSaveAsFilename(); + if (uReply != IDOK) return uReply; + if (!SaveDocumentAs(szBufferFilename)) return IDCANCEL; + WritePrivateProfileString("Files","LastDocument",szCurrentFilename,EMU48_INI); + return IDYES; + } + + SaveDocument(); + return IDYES; +} + + + +//################ +//# +//# Message Handlers +//# +//################ + +// +// WM_CREATE +// +static LRESULT OnCreate(HWND hWindow) +{ + hWnd = hWindow; + hWindowDC = GetDC(hWnd); + DragAcceptFiles(hWnd,TRUE); // 05.02.99 cg & Will Laughlin, moved, support dropped files + return 0; +} + +// +// WM_DESTROY +// +static LRESULT OnDestroy(HWND hWindow) +{ + DragAcceptFiles(hWnd,FALSE); // 05.02.99 cg & Will Laughlin, no WM_DROPFILES message any more + SwitchToState(2); + WriteSettings(); + 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 + hWnd = NULL; + PostQuitMessage(0); + return 0; + UNREFERENCED_PARAMETER(hWindow); +} + +// +// WM_PAINT +// +static LRESULT OnPaint(HWND hWindow) +{ + PAINTSTRUCT Paint; + HDC hPaintDC; + + hPaintDC = BeginPaint(hWindow, &Paint); + if (hMainDC != NULL) // 30.01.98 cg, bugfix, EndPaint() was not called + { + 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 + RefreshButtons(); + } + } + EndPaint(hWindow, &Paint); + return 0; +} + +// +// 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; + + // get number of files dropped + wNumFiles = DragQueryFile (hFilesInfo,(UINT)-1,NULL,0); + + if (!Chipset.dispon) // calculator off, turn on + { + // turn on HP + KeyboardEvent(TRUE,0,0x8000); + Sleep(200); + KeyboardEvent(FALSE,0,0x8000); + } + + _ASSERT(nState == 0); // Emulator must be in RUN state + if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state + { + DragFinish (hFilesInfo); + InfoMessage("The emulator is busy."); + return 0; + } + + while (nState!=nNextState) Sleep(0); + _ASSERT(nState==3); + + // get each name and load it into the emulator + for (wIndex = 0;wIndex < wNumFiles;++wIndex) + { + DragQueryFile (hFilesInfo,wIndex,(LPSTR) szFileName,sizeof(szFileName)); + + // szFileName has file name, now try loading it + if ((bSuccess = LoadObject(szFileName)) == FALSE) + break; + } + + DragFinish (hFilesInfo); + SwitchToState(0); // run state + while (nState!=nNextState) Sleep(0); + _ASSERT(nState==0); + + if (bSuccess == FALSE) // data not copied + return 0; + + KeyboardEvent(TRUE,0,0x8000); + Sleep(200); + KeyboardEvent(FALSE,0,0x8000); + // wait for sleep mode + while(Chipset.Shutdn == FALSE) Sleep(0); + return 0; +} + +// +// ID_FILE_NEW +// +static LRESULT OnFileNew() +{ + UINT uReply; + + SaveBackup(); + if (pbyRom) + { + SwitchToState(1); + uReply = SaveChanges(bAutoSave); + if (uReply==IDCANCEL) goto cancel; + } + NewDocument(); + SetWindowTitle("Untitled"); + UpdateWindowStatus(); +cancel: + if (pbyRom) SwitchToState(0); + return 0; +} + +// +// ID_FILE_OPEN +// +static LRESULT OnFileOpen() +{ + UINT uReply; + + if (pbyRom) + { + SwitchToState(1); + uReply = SaveChanges(bAutoSave); + if (uReply==IDCANCEL) goto cancel; + } + if (GetOpenFilename()) + { + OpenDocument(szBufferFilename); + } +cancel: + if (pbyRom) + { + SwitchToState(0); + } + return 0; +} + +// +// ID_FILE_SAVE +// +static LRESULT OnFileSave() +{ + if (pbyRom == NULL) return 0; + SwitchToState(1); + SaveChanges(TRUE); + SwitchToState(0); + return 0; +} + +// +// ID_FILE_SAVEAS +// +static LRESULT OnFileSaveAs() +{ + UINT uReply; + + if (pbyRom == NULL) return 0; + SwitchToState(1); + + uReply = GetSaveAsFilename(); + if (uReply != IDOK) + { + SwitchToState(0); + return 0; + } + if (!SaveDocumentAs(szBufferFilename)) + { + SwitchToState(0); + return 0; + } + WritePrivateProfileString("Files","LastDocument",szCurrentFilename,EMU48_INI); + + SwitchToState(0); + return 0; +} + +// +// ID_FILE_CLOSE +// +static LRESULT OnFileClose() +{ + if (pbyRom == NULL) return 0; + SwitchToState(1); + if (SaveChanges(bAutoSave)!=IDCANCEL) + { + KillKML(); + ResetDocument(); + SetWindowTitle(NULL); + } + else + { + SwitchToState(0); + } + return 0; +} + +// +// 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() +{ + SwitchToState(2); // 21.02.99 cg, bugfix, hold emulation thread first + if (SaveChanges(bAutoSaveOnExit) == IDCANCEL) + { + return 0; + } + DestroyWindow(hWnd); + return 0; +} + +// +// ID_STACK_COPY +// +static LRESULT OnStackCopy() // 17.06.98 cg, new, copy data from stack +{ + HANDLE hClipObj; + LPBYTE lpData; + DWORD dwAddress,dwSize; + + _ASSERT(nState == 0); // Emulator must be in RUN state + if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state + { + InfoMessage("The emulator is busy."); + return 0; + } + + while (nState!=nNextState) Sleep(0); + _ASSERT(nState==3); + + if ((dwAddress = RPL_Pick(1)) == 0) // pick address of level1 object + { + MessageBeep(MB_OK); // error beep + goto error; + } + + if (Read5(dwAddress) != 0x02A2C) // string object + { + MessageBeep(MB_OK); // error beep + goto error; + } + + dwAddress += 5; // address of string length + dwSize = (Read5(dwAddress) - 5) / 2; // length of string + + // memory allocation for clipboard data + if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,dwSize + 1)) == NULL) + goto error; + + if (lpData = GlobalLock(hClipObj)) // lock memory + { + // copy data into clipboard buffer + for (dwAddress += 5;dwSize-- > 0;dwAddress += 2,++lpData) + *lpData = Read2(dwAddress); + *lpData = 0; // set end of string + + GlobalUnlock(hClipObj); // unlock memory + + if (OpenClipboard(hWnd)) + { + if (EmptyClipboard()) + SetClipboardData(CF_TEXT,hClipObj); + else + GlobalFree(hClipObj); + CloseClipboard(); + } + } + else // lock memory failed + { + GlobalFree(hClipObj); + } + +error: + SwitchToState(0); + return 0; +} + +// +// ID_STACK_PASTE +// +static LRESULT OnStackPaste() // 17.06.98 cg, new, 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); + Sleep(200); + KeyboardEvent(FALSE,0,0x8000); + // wait for sleep mode + while(Chipset.Shutdn == FALSE) Sleep(0); + } + + _ASSERT(nState == 0); // Emulator must be in RUN state + if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state + { + InfoMessage("The emulator is busy."); + return 0; + } + + while (nState!=nNextState) Sleep(0); + _ASSERT(nState==3); + + if (OpenClipboard(hWnd)) + { + if ( IsClipboardFormatAvailable(CF_TEXT) + || IsClipboardFormatAvailable(CF_OEMTEXT)) + { + if (hClipObj = GetClipboardData(CF_TEXT)) + { + if (lpClipdata = GlobalLock(hClipObj)) + { + DWORD dwSize = strlen(lpClipdata); + if (lpData = (LPBYTE) LocalAlloc(LMEM_FIXED,dwSize * 2)) + { + memcpy(lpData+dwSize,lpClipdata,dwSize); // copy data + bSuccess = (WriteStack(lpData,dwSize) == S_ERR_NO); + LocalFree(lpData); + } + GlobalUnlock(hClipObj); + } + } + } + else // unknown clipboard format + { + MessageBeep(MB_OK); // error beep + } + CloseClipboard(); + } + + SwitchToState(0); // run state + while (nState!=nNextState) Sleep(0); + _ASSERT(nState == 0); + + if (bSuccess == FALSE) // data not copied + return 0; + + KeyboardEvent(TRUE,0,0x8000); + Sleep(200); + KeyboardEvent(FALSE,0,0x8000); + // wait for sleep mode + while(Chipset.Shutdn == FALSE) Sleep(0); + return 0; +} + +// +// ID_VIEW_COPY +// +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 + #define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4) + #define PALVERSION 0x300 + + BITMAP bm; + LPBITMAPINFOHEADER lpbi; + PLOGPALETTE ppal; + HBITMAP hBmp; + HDC hBmpDC; + HANDLE hClipObj; + WORD wBits; + DWORD dwLen, dwSizeImage; + + _ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4); + hBmp = CreateCompatibleBitmap(hLcdDC,131*nLcdDoubled,64*nLcdDoubled); + hBmpDC = CreateCompatibleDC(hLcdDC); + hBmp = SelectObject(hBmpDC,hBmp); + BitBlt(hBmpDC, 0, 0, 131*nLcdDoubled, 64*nLcdDoubled, hLcdDC, 0, 0, SRCCOPY); + hBmp = SelectObject(hBmpDC,hBmp); + + // fill BITMAP structure for size information + GetObject(hBmp, sizeof(bm), &bm); + + wBits = bm.bmPlanes * bm.bmBitsPixel; + // make sure bits per pixel is valid + if (wBits <= 1) + wBits = 1; + else if (wBits <= 4) + wBits = 4; + else if (wBits <= 8) + wBits = 8; + else // if greater than 8-bit, force to 24-bit + wBits = 24; + + dwSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * wBits) * bm.bmHeight; + + // calculate memory size to store CF_DIB data + dwLen = sizeof(BITMAPINFOHEADER) + dwSizeImage; + if (wBits != 24) // a 24 bitcount DIB has no color table + { + // add size for color table + dwLen += (1 << wBits) * sizeof(RGBQUAD); + } + + // memory allocation for clipboard data + if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE, dwLen)) != NULL) + { + lpbi = GlobalLock(hClipObj); + // initialize BITMAPINFOHEADER + lpbi->biSize = sizeof(BITMAPINFOHEADER); + lpbi->biWidth = bm.bmWidth; + lpbi->biHeight = bm.bmHeight; + lpbi->biPlanes = 1; + lpbi->biBitCount = wBits; + lpbi->biCompression = BI_RGB; + lpbi->biSizeImage = dwSizeImage; + lpbi->biXPelsPerMeter = 0; + lpbi->biYPelsPerMeter = 0; + lpbi->biClrUsed = 0; + lpbi->biClrImportant = 0; + // get bitmap color table and bitmap data + GetDIBits(hBmpDC, hBmp, 0, lpbi->biHeight, (LPBYTE)lpbi + dwLen - dwSizeImage, + (LPBITMAPINFO)lpbi, DIB_RGB_COLORS); + GlobalUnlock(hClipObj); + SetClipboardData(CF_DIB, hClipObj); + + // get number of entries in the logical palette + GetObject(hPalette,sizeof(WORD),&wBits); + + // memory allocation for temporary palette data + if ((ppal = LocalAlloc(LPTR, sizeof(LOGPALETTE) + wBits * sizeof(PALETTEENTRY))) != NULL) + { + ppal->palVersion = PALVERSION; + ppal->palNumEntries = wBits; + GetPaletteEntries(hPalette, 0, wBits, ppal->palPalEntry); + SetClipboardData(CF_PALETTE, CreatePalette(ppal)); + LocalFree(ppal); + } + } + DeleteDC(hBmpDC); + 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); +#endif + } + CloseClipboard(); + } + // 22.09.98 cg, end of bugfix + return 0; +} + +// +// ID_VIEW_RESET +// +static LRESULT OnViewReset() +{ + if (nState!=0) return 0; + 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; + SwitchToState(0); + } + return 0; +} + +// +// ID_VIEW_SETTINGS +// +static LRESULT OnViewSettings() +{ + ReadSettings(); + if (nState == 1) UnmapPort2(); + if (DialogBox(hApp, MAKEINTRESOURCE(IDD_SETTINGS), hWnd, (DLGPROC)SettingsProc) == -1) + AbortMessage("Settings Dialog Creation Error !"); + if (nState == 1) MapPort2(szPort2Filename); + WriteSettings(); + return 0; +} + +// +// ID_VIEW_SCRIPT +// +static LRESULT OnViewScript() +{ + CHAR cType = cCurrentRomType; + if (nState!=0) + { + InfoMessage("You cannot change the KML script when Emu48 is not running.\n" + "Use the File,New menu item to create a new calculator."); + return 0; + } + SwitchToState(1); +retry: + if (!DisplayChooseKml(cType)) goto ok; + if (!InitKML(szCurrentKml,FALSE)) + { + if (AbortMessage("This KML Script has errors.\nPress Ok to try to find a correct script.")==IDCANCEL) + { + if (szCurrentFilename[0]) + OnFileSave(); + else + OnFileSaveAs(); + goto ok; + } + goto retry; + } +ok: + if (pbyRom) SwitchToState(0); + return 0; +} + +// +// ID_BACKUP_SAVE +// +static LRESULT OnBackupSave() +{ + UINT nOldState; + if (pbyRom == NULL) return 0; + nOldState = SwitchToState(1); + SaveBackup(); + SwitchToState(nOldState); + return 0; +} + +// +// ID_BACKUP_RESTORE +// +static LRESULT OnBackupRestore() +{ + SwitchToState(1); + RestoreBackup(); + if (pbyRom) SwitchToState(0); + return 0; +} + +// +// ID_BACKUP_DELETE +// +static LRESULT OnBackupDelete() +{ + ResetBackup(); + return 0; +} + +// +// ID_OBJECT_LOAD +// +static LRESULT OnObjectLoad() +{ + static BOOL bWarning = TRUE; + + if (!Chipset.dispon) // 10.11.98 cg, new, calculator off, turn on + { + // turn on HP + KeyboardEvent(TRUE,0,0x8000); + Sleep(200); + KeyboardEvent(FALSE,0,0x8000); + } + + if (nState!=0) + { + InfoMessage("The emulator must be running to load an object."); + return 0; + } + + if (WaitForSleepState()) // 10.11.98 cg, changed, wait for cpu SHUTDN then sleep state + { + InfoMessage("The emulator is busy."); + return 0; + } + + while (nState!=nNextState) Sleep(0); + _ASSERT(nState==3); + + if (bWarning) + { + UINT uReply = YesNoCancelMessage( + "Warning: Trying to load an object while the emulator is busy \n" + "will certainly result in a memory lost. Before loading an object \n" + "you should be sure that the HP48 is not doing anything. \n" + "Do you want to see this warning next time you try to load an object ?"); + switch (uReply) + { + case IDYES: + break; + case IDNO: + bWarning = FALSE; + break; + case IDCANCEL: + SwitchToState(0); + return 0; + } + } + + if (!GetLoadObjectFilename()) + { + SwitchToState(0); + return 0; + } + + if (!LoadObject(szBufferFilename)) + { + SwitchToState(0); + return 0; + } + + SwitchToState(0); // run state + while (nState!=nNextState) Sleep(0); + _ASSERT(nState==0); + 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; +} + +// +// ID_OBJECT_SAVE +// +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 + return 0; + + while (nState!=nNextState) Sleep(0); + _ASSERT(nState==3); + + if (!GetSaveObjectFilename()) + { + SwitchToState(0); + return 0; + } + + SaveObject(szBufferFilename); + + SwitchToState(0); + + return 0; +} + +// +// ID_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; + + LONG i; + LPINT lpnCount; + char *cpStop,szAddress[256] = "0"; + + switch (message) + { + case WM_INITDIALOG: + // 10.11.98 cg, new, 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)); + SendDlgItemMessage(hDlg,IDC_DISASM_RAM,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDC_DISASM_PORT1,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDC_DISASM_PORT2,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDC_DISASM_MNEMONICS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDC_DISASM_HP,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDC_DISASM_CLASS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0)); + SendDlgItemMessage(hDlg,IDC_DISASM_MAP,BM_SETCHECK,1,0); + SendDlgItemMessage(hDlg,IDC_DISASM_HP,BM_SETCHECK,1,0); + // 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 + dwAddress = strtoul(szAddress,&cpStop,16); + dwAddressMax = 0x100000; // 10.11.98 cg, new, greatest address (mapped mode) + return TRUE; + case WM_COMMAND: + switch(wParam) + { + // 10.11.98 cg, new, decode radio buttons + case IDC_DISASM_MAP: + disassembler_map = MEM_MAP; + dwAddressMax = 0x100000; + break; + case IDC_DISASM_ROM: + disassembler_map = MEM_ROM; + dwAddressMax = dwRomSize; + break; + case IDC_DISASM_RAM: + disassembler_map = MEM_RAM; + dwAddressMax = Chipset.Port0Size * 2048; + break; + case IDC_DISASM_PORT1: + disassembler_map = MEM_PORT1; + dwAddressMax = ((Chipset.cards_status & PORT1_PRESENT) != 0) ? (Chipset.Port1Size * 2048) : 0; + break; + case IDC_DISASM_PORT2: + disassembler_map = MEM_PORT2; + dwAddressMax = (dwPort2Mask != 0) ? ((dwPort2Mask + 1) << 17) : 0; + break; + case IDC_DISASM_HP: + disassembler_mode = HP_MNEMONICS; + break; + case IDC_DISASM_CLASS: + disassembler_mode = CLASS_MNEMONICS; + break; + // 10.11.98 cg, end of new part + case IDOK: + SendDlgItemMessage(hDlg,IDC_DISASM_ADR,EM_SETSEL,0,-1); + GetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress,sizeof(szAddress)); + // test if valid hex address + for (i = 0; i < (LONG) strlen(szAddress); ++i) + { + if (isxdigit(szAddress[i]) == FALSE) + return FALSE; + } + dwAddress = strtoul(szAddress,&cpStop,16); + // no break + case IDC_DISASM_NEXT: + if (dwAddress >= dwAddressMax) // 10.11.98 cg, bugfix, moved check from IDOK + return FALSE; + i = wsprintf(szAddress,"%05lX ",dwAddress); + dwAddress = disassemble(dwAddress,&szAddress[i]); + // 12.02.99 cg, changed, implementation for multi selectable items + 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 + case IDC_DISASM_COPY: + // get number of selections + if ((i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETSELCOUNT,0,0)) == 0) + break; // no items selected + + if ((lpnCount = (LPINT) LocalAlloc(LMEM_FIXED,i * sizeof(INT))) != NULL) + { + HANDLE hClipObj; + LONG j,lMem = 0; + + // get indexes of selected items + i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETSELITEMS,i,(LPARAM) lpnCount); + for (j = 0;j < i;++j) // scan all selected items + { + // calculate total amount of needed memory + lMem += SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETTEXTLEN,lpnCount[j],0) + 2; + } + // allocate clipboard data + if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,lMem + 1)) != NULL) + { + LPBYTE lpData; + + if (lpData = GlobalLock(hClipObj)) + { + for (j = 0;j < i;++j) // scan all selected items + { + lpData += SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETTEXT,lpnCount[j],(LPARAM) lpData); + *lpData++ = '\r'; + *lpData++ = '\n'; + } + *lpData = 0; // set end of string + GlobalUnlock(hClipObj); // unlock memory + } + + if (OpenClipboard(hWnd)) + { + if (EmptyClipboard()) + SetClipboardData(CF_TEXT,hClipObj); + else + GlobalFree(hClipObj); + CloseClipboard(); + } + else // clipboard open failed + { + GlobalFree(hClipObj); + } + } + LocalFree(lpnCount); // free item table + } + break; + // 12.02.99 cg, end of new part + case IDCANCEL: + EndDialog(hDlg, wParam); + break; + } + break; + } + return FALSE; + UNREFERENCED_PARAMETER(lParam); + UNREFERENCED_PARAMETER(hDlg); +} + +// +// ID_ABOUT +// +static BOOL CALLBACK About(HWND hDlg, UINT message, DWORD wParam, LONG lParam) +{ + + switch (message) + { + case WM_INITDIALOG: + SetDlgItemText(hDlg,IDC_VERSION,szNoTitle); + SetDlgItemText(hDlg,IDC_LICENSE,szLicence); + return TRUE; + case WM_COMMAND: + if ((wParam==IDOK)||(wParam==IDCANCEL)) + { + EndDialog(hDlg, wParam); + break; + } + break; + } + return FALSE; + UNREFERENCED_PARAMETER(lParam); + UNREFERENCED_PARAMETER(hDlg); +} + +static LRESULT OnToolDisasm() // 15.07.98 cg, new, disasm dialogbox call +{ + if (pbyRom) SwitchToState(3); + if (DialogBox(hApp, MAKEINTRESOURCE(IDD_DISASM), hWnd, (DLGPROC)Disasm) == -1) + AbortMessage("Disassembler Dialog Box Creation Error !"); + if (pbyRom) SwitchToState(0); + return 0; +} + +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; +} + +static LRESULT OnLButtonDown(UINT nFlags, WORD x, WORD y) +{ + if (nState==0) MouseButtonDownAt(nFlags, x,y); + return 0; +} + +static LRESULT OnLButtonUp(UINT nFlags, WORD x, WORD y) +{ + if (nState==0) MouseButtonUpAt(nFlags, x,y); + return 0; +} + +static LRESULT OnMouseMove(UINT nFlags, WORD x, WORD y) +{ + if (nState==0) MouseMovesTo(nFlags, x,y); + return 0; +} + +static LRESULT OnKeyDown(int nVirtKey, DWORD lKeyData) +{ + // 03.09.98 cg, bugfix, call RunKey() only once (suppress autorepeat feature) + if (nState==0 && (lKeyData & 0x40000000)==0) + RunKey((BYTE)nVirtKey, TRUE); + return 0; +} + +static LRESULT OnKeyUp(int nVirtKey, DWORD lKeyData) +{ + if (nState==0) RunKey((BYTE)nVirtKey, FALSE); + return 0; + UNREFERENCED_PARAMETER(lKeyData); +} + +static 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; + case WM_QUERYNEWPALETTE: + if (hPalette) + { + SelectPalette(hWindowDC, hPalette, FALSE); + if (RealizePalette(hWindowDC)) + { + InvalidateRect(hWindow,NULL,TRUE); + return TRUE; + } + } + return FALSE; + case WM_PALETTECHANGED: + if ((HWND)wParam == hWindow) break; + if (hPalette) + { + SelectPalette(hWindowDC, hPalette, FALSE); + if (RealizePalette(hWindowDC)) + { + // UpdateColors(hWindowDC); + InvalidateRect (hWnd, (LPRECT) (NULL), 1); + } + } + return FALSE; + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case ID_FILE_NEW: return OnFileNew(); + case ID_FILE_OPEN: return OnFileOpen(); + case ID_FILE_SAVE: return OnFileSave(); + 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_VIEW_COPY: return OnViewCopy(); + case ID_VIEW_RESET: return OnViewReset(); + case ID_VIEW_SETTINGS: return OnViewSettings(); + case ID_VIEW_SCRIPT: return OnViewScript(); + case ID_BACKUP_SAVE: return OnBackupSave(); + case ID_BACKUP_RESTORE:return OnBackupRestore(); + 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_ABOUT: return OnAbout(); + } + break; + case WM_SYSCOMMAND: + switch (LOWORD(wParam)) + { + case SC_CLOSE: return OnSysClose(); + } + break; + case WM_RBUTTONDOWN: // 01.10.97 cg, for holding key pressed + 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)); + case WM_KEYUP: return OnKeyUp((int)wParam, lParam); + case WM_KEYDOWN: return OnKeyDown((int)wParam, lParam); + } + return DefWindowProc(hWindow, uMsg, wParam, lParam); +} + +static BOOL FlushMessages(LPMSG msg) +{ + while (PeekMessage(msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg->message == WM_QUIT) return TRUE; + TranslateMessage(msg); + DispatchMessage(msg); + } + return FALSE; +} + +// 01.11.98 cg, bugfix, changed varible type of first two arguments +int PASCAL 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 + + hApp = hInst; + + wc.style = CS_BYTEALIGNCLIENT; + wc.lpfnWndProc = (WNDPROC)MainWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInst; + wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_EMU48)); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU); + wc.lpszClassName = "CEmu48"; + + if (!RegisterClass(&wc)) + { + AbortMessage( + "CEmu48 class registration failed.\n" + "This application will now terminate."); + return FALSE; + } + + // Create window + + rectWindow.left = 0; + rectWindow.top = 0; + rectWindow.right = 256; + rectWindow.bottom = 0; + AdjustWindowRect(&rectWindow, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, TRUE); + + hWnd = CreateWindow("CEmu48", "Emu48", + WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, + CW_USEDEFAULT, CW_USEDEFAULT, + rectWindow.right - rectWindow.left, + rectWindow.bottom - rectWindow.top, + NULL,NULL,hApp,NULL + ); + + if (hWnd == NULL) + { + AbortMessage("Window creation failed.\n"); + return FALSE; + } + + ShowWindow(hWnd, nCmdShow); + + if (FlushMessages(&msg)) return msg.wParam; + + // initialization + QueryPerformanceFrequency(&lFreq); // 24.08.98 cg, 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(); + + nState = 1; // thread starts in an invalid state + nNextState = 1; + hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, NULL, 0, &lThreadId); + if (hThread == NULL) + { + AbortMessage("Thread creation failed."); + 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 + if (DdeInitialize(&idDdeInst,(PFNCALLBACK) &DdeCallback, + APPCLASS_STANDARD | + CBF_FAIL_EXECUTES | CBF_FAIL_ADVISES | + CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS,0)) + { + AbortMessage("Could not initialize server!"); + return FALSE; + } + + if (__argc >= 2) // 20.02.99 cg, changed, use decoded parameter line + { + CHAR szTemp[256] = "Loading "; + strcat(szTemp, __argv[1]); // 20.02.99 cg, changed, use decoded parameter line + SetWindowTitle(szTemp); + if (FlushMessages(&msg)) return msg.wParam; + if (OpenDocument(__argv[1])) // 20.02.99 cg, changed, use decoded parameter line + goto start; + } + + // 09.12.97 cg, bugfix, function parameter + GetPrivateProfileString("Files","LastDocument","",szBufferFilename,sizeof(szBufferFilename),EMU48_INI); + if (szBufferFilename[0]) + { + CHAR szTemp[256] = "Loading "; + strcat(szTemp, szBufferFilename); + SetWindowTitle(szTemp); + if (FlushMessages(&msg)) return msg.wParam; + if (OpenDocument(szBufferFilename)) + goto start; + } + + SetWindowTitle("New Document"); + if (FlushMessages(&msg)) return msg.wParam; + if (NewDocument()) + { + SetWindowTitle("Untitled"); + goto start; + } + + 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 + + // 13.05.98 cg, new, 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); + } + + // 13.05.98 cg, new, 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 + + // SwitchToState(2); // 27.01.98 cg, removed, done in WM_DESTROY + _ASSERT(nState == 2); // 30.01.98 cg, set by WM_DESTROY + 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 + + return msg.wParam; + UNREFERENCED_PARAMETER(lpCmdLine); + UNREFERENCED_PARAMETER(hPrevInst); +} diff --git a/sources/Emu48/EMU48.DSP b/sources/Emu48/EMU48.DSP new file mode 100644 index 0000000..0f2cfc4 --- /dev/null +++ b/sources/Emu48/EMU48.DSP @@ -0,0 +1,194 @@ +# Microsoft Developer Studio Project File - Name="Emu48" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=Emu48 - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Emu48.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Emu48.mak" CFG="Emu48 - Win32 Release" +!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 + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.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 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 BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib /nologo /subsystem:windows /machine:I386 + +!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 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 BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib /nologo /subsystem:windows /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "Emu48 - Win32 Release" +# Name "Emu48 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\ddeserv.c +# End Source File +# Begin Source File + +SOURCE=.\disasm.c +# End Source File +# Begin Source File + +SOURCE=.\display.c +# End Source File +# Begin Source File + +SOURCE=.\Emu48.c +# End Source File +# Begin Source File + +SOURCE=.\Emu48.rc + +!IF "$(CFG)" == "Emu48 - Win32 Release" + +!ELSEIF "$(CFG)" == "Emu48 - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\engine.c +# End Source File +# Begin Source File + +SOURCE=.\external.c +# End Source File +# Begin Source File + +SOURCE=.\files.c +# End Source File +# Begin Source File + +SOURCE=.\keyboard.c +# End Source File +# Begin Source File + +SOURCE=.\kml.c +# End Source File +# Begin Source File + +SOURCE=.\mops.c +# End Source File +# Begin Source File + +SOURCE=.\pch.c +# ADD CPP /Yc"pch.h" +# End Source File +# Begin Source File + +SOURCE=.\rpl.c +# End Source File +# Begin Source File + +SOURCE=.\serial.c +# End Source File +# Begin Source File + +SOURCE=.\timer.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\Emu48.h +# End Source File +# Begin Source File + +SOURCE=.\kml.h +# End Source File +# Begin Source File + +SOURCE=.\Ops.h +# End Source File +# Begin Source File + +SOURCE=.\pch.h +# End Source File +# Begin Source File + +SOURCE=.\types.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\Emu48.ico +# End Source File +# End Group +# End Target +# End Project diff --git a/sources/Emu48/EMU48.DSW b/sources/Emu48/EMU48.DSW new file mode 100644 index 0000000..48cb9a3 --- /dev/null +++ b/sources/Emu48/EMU48.DSW @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Emu48"=.\Emu48.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/sources/Emu48/EMU48.H b/sources/Emu48/EMU48.H new file mode 100644 index 0000000..4b7d684 --- /dev/null +++ b/sources/Emu48/EMU48.H @@ -0,0 +1,219 @@ +/* + * Emu48.h + * + * This file is part of Emu48 + * + * Copyright (C) 1995 Sebastien Carlier + * + */ +#include "types.h" + +#define BINARYHEADER "HPHP48-W" // 11.05.98 cg, new + +#define S_ERR_NO 0 // 11.05,98 cg, new, 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 PORT_CLOSE 0 // 20.05.98 cg, new, COM port status +#define PORT_WIRE 1 +#define PORT_IR 2 + +#define HP_MNEMONICS FALSE // 10.11.98 cg, new, disassembler mnenomics mode +#define CLASS_MNEMONICS TRUE + +#define MEM_MAP 0 // 10.11.98 cg, new, memory module definition +#define MEM_ROM 1 +#define MEM_RAM 2 +#define MEM_PORT1 3 +#define MEM_PORT2 4 + +// 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 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 HWND hWnd; +extern HDC hWindowDC; +extern BOOL bPort2IsShared; +extern BOOL bAlwaysDisplayLog; +extern UINT uTimer1Period; +extern VOID SetWindowTitle(LPSTR szString); +extern VOID UpdateWindowStatus(VOID); + +// 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 VOID UpdateContrast(BYTE byContrast); +extern VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue); +extern VOID CreateLcdBitmap(VOID); +extern VOID DestroyLcdBitmap(VOID); +extern BOOL CreateMainBitmap(LPSTR szFilename); +extern VOID DestroyMainBitmap(VOID); +extern VOID UpdateDisplayPointers(VOID); +extern VOID UpdateMainDisplay(VOID); +extern VOID UpdateMenuDisplay(VOID); +extern VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s); +extern VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s); +extern VOID UpdateAnnunciators(VOID); +extern VOID ResizeWindow(VOID); + +// Engine.c +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 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 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); + +// Files.c +extern char szEmu48Directory[260]; +extern char szCurrentDirectory[260]; +extern char szCurrentKml[260]; +extern char szBackupKml[260]; +extern char szCurrentFilename[260]; +extern char szBackupFilename[260]; +extern char szBufferFilename[260]; +extern char szPort2Filename[260]; +extern LPBYTE pbyRom; +extern DWORD dwRomSize; +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 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 BOOL MapRom(LPCSTR szFilename); +extern VOID UnmapRom(VOID); +extern BOOL MapPort2(LPCSTR szFilename); +extern VOID UnmapPort2(VOID); +extern BOOL PatchRom(LPCSTR szFilename); +extern VOID ResetDocument(VOID); +extern BOOL NewDocument(VOID); +extern BOOL OpenDocument(LPCSTR szFilename); +extern BOOL SaveDocument(VOID); +extern BOOL SaveDocumentAs(LPCTSTR szFilename); +extern BOOL SaveBackup(VOID); +extern BOOL RestoreBackup(VOID); +extern BOOL ResetBackup(VOID); +extern BOOL GetOpenFilename(VOID); +extern BOOL GetSaveAsFilename(VOID); +extern BOOL GetLoadObjectFilename(VOID); +extern BOOL GetSaveObjectFilename(VOID); +extern BOOL LoadObject(LPCSTR szFilename); +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 StartTimers(VOID); +extern VOID StopTimers(VOID); +extern DWORD ReadT2(VOID); +extern VOID SetT2(DWORD dwValue); +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); + +// 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 KeyboardEvent(BOOL bPress, UINT out, UINT in); + +// RPL.c +extern DWORD RPL_SkipOb(DWORD d); +extern DWORD RPL_ObjectSize(BYTE *o); +extern DWORD RPL_CreateTemp(DWORD l); +extern DWORD RPL_Pick(UINT l); +extern VOID RPL_Replace(DWORD n); +extern VOID RPL_Push(DWORD n); + +// External.c +extern VOID External(CHIPSET* w); + +// DDEserv.c +extern HDDEDATA CALLBACK DdeCallback(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, DWORD, DWORD); + +// Disasm.c +extern BOOL disassembler_mode; +extern WORD disassembler_map; +extern DWORD disassemble (DWORD addr, LPSTR out); + +// Serial.c +extern WORD CommConnect(VOID); +extern VOID CommOpen(LPSTR strWirePort,LPSTR strIrPort); +extern VOID CommClose(VOID); +extern VOID CommSetBaud(VOID); +extern VOID CommTransmit(VOID); +extern VOID CommReceive(VOID); + +// Message Boxes +static __inline int InfoMessage(LPCSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND);} +static __inline int AbortMessage(LPCSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);} +static __inline int YesNoMessage(LPCSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_YESNO|MB_ICONEXCLAMATION|MB_SETFOREGROUND);} +static __inline int YesNoCancelMessage(LPCSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_YESNOCANCEL|MB_ICONEXCLAMATION|MB_SETFOREGROUND);} + +// Missing Win32 API calls +static __inline LPSTR DuplicateString(LPCSTR szString) +{ + UINT uLength = strlen(szString) + 1; + LPSTR szDup = LocalAlloc(LMEM_FIXED,uLength); // 27.01.98 cg, adjust memsize + CopyMemory(szDup,szString,uLength); + return szDup; +} diff --git a/Emu48/Emu48.ico b/sources/Emu48/EMU48.ICO similarity index 100% rename from Emu48/Emu48.ico rename to sources/Emu48/EMU48.ICO diff --git a/Emu48/Emu48.rc b/sources/Emu48/EMU48.RC similarity index 59% rename from Emu48/Emu48.rc rename to sources/Emu48/EMU48.RC index 5fc1d51..3d3635c 100644 --- a/Emu48/Emu48.rc +++ b/sources/Emu48/EMU48.RC @@ -28,13 +28,13 @@ LANGUAGE LANG_FRENCH, SUBLANG_FRENCH // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,9,9,0 - PRODUCTVERSION 0,9,9,0 + FILEVERSION 1,1,0,0 + PRODUCTVERSION 1,1,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG - FILEFLAGS 0x1L + FILEFLAGS 0x21L #else - FILEFLAGS 0x0L + FILEFLAGS 0x20L #endif FILEOS 0x40004L FILETYPE 0x1L @@ -45,13 +45,14 @@ BEGIN BLOCK "00000000" BEGIN VALUE "CompanyName", "Sebastien Carlier\0" - VALUE "FileDescription", "Emu48\0" - VALUE "FileVersion", "0, 9, 9, 0\0" + VALUE "FileDescription", "HP48 Emulator\0" + VALUE "FileVersion", "1, 1, 0, 0\0" VALUE "InternalName", "Emu48\0" - VALUE "LegalCopyright", "Copyright © 1996\0" + VALUE "LegalCopyright", "Copyright © 1999\0" VALUE "OriginalFilename", "Emu48.exe\0" VALUE "ProductName", "Emu48\0" - VALUE "ProductVersion", "0, 9, 9, 0\0" + VALUE "ProductVersion", "1, 1, 0, 0\0" + VALUE "SpecialBuild", "Service Pack 10, Christoph Gießelink\0" END END BLOCK "VarFileInfo" @@ -87,7 +88,7 @@ BEGIN MENUITEM "Save &As...", ID_FILE_SAVEAS, GRAYED MENUITEM "&Close", ID_FILE_CLOSE, GRAYED MENUITEM SEPARATOR - MENUITEM "&Settings...", ID_VIEW_SETTINGS + MENUITEM "S&ettings...", ID_VIEW_SETTINGS MENUITEM SEPARATOR MENUITEM "E&xit", ID_FILE_EXIT END @@ -95,7 +96,11 @@ BEGIN BEGIN MENUITEM "&Load Object...", ID_OBJECT_LOAD MENUITEM "&Save Object...", ID_OBJECT_SAVE - MENUITEM "&Copy Screen", ID_VIEW_COPY, GRAYED + 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 @@ -109,6 +114,10 @@ BEGIN 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 @@ -147,49 +156,54 @@ END // Dialog // -IDD_ABOUT DIALOGEX 0, 0, 261, 194 +IDD_ABOUT DIALOGEX 0, 0, 261, 160 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "About Emu48" -FONT 8, "MS Sans Serif" +FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN - ICON IDI_EMU48,IDC_STATIC,7,6,21,20,SS_REALSIZEIMAGE, + ICON IDI_EMU48,IDC_STATIC,7,6,20,20,SS_REALSIZEIMAGE, WS_EX_TRANSPARENT - LTEXT "",IDC_VERSION,32,6,151,8,NOT WS_GROUP - LTEXT "Copyright © 1997 Sébastien Carlier",IDC_STATIC,32,18, - 151,8 + LTEXT "",IDC_VERSION,29,6,151,8,NOT WS_GROUP + LTEXT "Copyright © 1999 Sébastien Carlier && Christoph Gießelink", + IDC_STATIC,29,18,181,8 DEFPUSHBUTTON "OK",IDOK,215,12,39,14 EDITTEXT IDC_LICENSE,7,33,247,112,ES_MULTILINE | ES_AUTOHSCROLL | - ES_READONLY,WS_EX_DLGMODALFRAME + ES_READONLY END -IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 162, 180 +IDD_SETTINGS DIALOGEX 0, 0, 167, 178 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Settings" -FONT 8, "MS Sans Serif" +FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN + GROUPBOX "General",IDC_STATIC,7,4,153,63 + GROUPBOX "Memory Cards",IDC_STATIC,7,70,153,50 + GROUPBOX "Serial Ports",IDC_STATIC,7,124,153,27 + CONTROL "Authentic Calculator Speed",IDC_REALSPEED,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,13,13,104,10 CONTROL "Automatically Save Files",IDC_AUTOSAVE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,14,16,92,10 + BS_AUTOCHECKBOX | WS_TABSTOP,13,26,89,10 CONTROL "Automatically Save Files On Exit",IDC_AUTOSAVEONEXIT, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,29,117,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,39,114,10 CONTROL "Always display KML Compilation Result", IDC_ALWAYSDISPLOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, - 14,42,138,10 + 13,52,136,10 + CONTROL "Port 1 is Plugged",IDC_PORT1EN,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,13,79,67,10 CONTROL "Port 1 is Writeable",IDC_PORT1WR,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,70,73,10 - CONTROL "Port 2 Is Shared",IDC_PORT2ISSHARED,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,83,65,10 - LTEXT "Port 2 File :",IDC_STATIC,13,96,37,8 - EDITTEXT IDC_PORT2,51,94,99,12,ES_AUTOHSCROLL - LTEXT "Timer 1 Period :",IDC_STATIC,13,136,60,9 - EDITTEXT IDC_T1PERIOD,73,134,35,12,ES_AUTOHSCROLL - PUSHBUTTON "&Default",IDC_T1DEFAULT,109,134,41,12 - DEFPUSHBUTTON "&Ok",IDOK,7,159,50,14 - PUSHBUTTON "&Cancel",IDCANCEL,105,159,50,14 - GROUPBOX "General",IDC_STATIC,7,7,148,50 - GROUPBOX "Memory Cards",IDC_STATIC,7,61,148,50 - GROUPBOX "Timers",IDC_STATIC,7,113,148,40 - CONTROL "Accurate Timer (may be slower)",IDC_USEMMTIMER,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,123,136,10 + BS_AUTOCHECKBOX | WS_TABSTOP,84,79,69,10 + CONTROL "Port 2 is Shared",IDC_PORT2ISSHARED,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,13,92,65,10 + LTEXT "Port 2 File :",IDC_STATIC,13,105,37,8 + EDITTEXT IDC_PORT2,51,103,104,12,ES_AUTOHSCROLL + LTEXT "Wire:",IDC_STATIC,13,136,17,8 + COMBOBOX IDC_WIRE,31,134,48,42,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP,WS_EX_LEFTSCROLLBAR + LTEXT "IR:",IDC_STATIC,89,136,9,8 + COMBOBOX IDC_IR,107,134,48,43,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + DEFPUSHBUTTON "&Ok",IDOK,9,157,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,107,157,50,14 END IDD_CHOOSEKML DIALOG DISCARDABLE 0, 0, 186, 66 @@ -225,6 +239,37 @@ BEGIN WS_BORDER | WS_VSCROLL | NOT WS_TABSTOP,WS_EX_CLIENTEDGE END +IDD_DISASM DIALOGEX 0, 0, 255, 165 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Disassembler" +FONT 8, "Courier New", 0, 0, 0x1 +BEGIN + LTEXT "Address (HEX):",IDC_ADDRESS,7,147,46,8 + EDITTEXT IDC_DISASM_ADR,56,145,36,12,ES_AUTOHSCROLL + PUSHBUTTON "&Next Address",IDC_DISASM_NEXT,99,144,47,14 + PUSHBUTTON "&Copy Data",IDC_DISASM_COPY,150,144,47,14 + PUSHBUTTON "Cancel",IDCANCEL,201,144,47,14 + GROUPBOX "Module",IDC_DISASM_MODULE,7,5,166,26 + CONTROL "Map",IDC_DISASM_MAP,"Button",BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP,14,16,28,10 + CONTROL "ROM",IDC_DISASM_ROM,"Button",BS_AUTORADIOBUTTON,45,16, + 28,10 + CONTROL "RAM",IDC_DISASM_RAM,"Button",BS_AUTORADIOBUTTON,76,16, + 28,10 + CONTROL "Port 1",IDC_DISASM_PORT1,"Button",BS_AUTORADIOBUTTON, + 107,16,28,10 + CONTROL "Port 2",IDC_DISASM_PORT2,"Button",BS_AUTORADIOBUTTON, + 138,16,28,10 + GROUPBOX "Mnemonics",IDC_DISASM_MNEMONICS,180,5,68,26 + CONTROL "HP",IDC_DISASM_HP,"Button",BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP,187,16,24,10 + CONTROL "Class",IDC_DISASM_CLASS,"Button",BS_AUTORADIOBUTTON,215, + 16,31,10 + LISTBOX IDC_DISASM_WIN,7,37,241,100,NOT LBS_NOTIFY | + LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL | + WS_TABSTOP,WS_EX_NOPARENTNOTIFY +END + ///////////////////////////////////////////////////////////////////////////// // @@ -234,22 +279,6 @@ END #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO DISCARDABLE BEGIN - IDD_ABOUT, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 254 - TOPMARGIN, 6 - BOTTOMMARGIN, 187 - END - - IDD_SETTINGS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 155 - TOPMARGIN, 7 - BOTTOMMARGIN, 173 - END - IDD_CHOOSEKML, DIALOG BEGIN LEFTMARGIN, 7 @@ -265,6 +294,14 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 160 END + + IDD_DISASM, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 248 + TOPMARGIN, 5 + BOTTOMMARGIN, 158 + END END #endif // APSTUDIO_INVOKED diff --git a/sources/Emu48/ENGINE.C b/sources/Emu48/ENGINE.C new file mode 100644 index 0000000..b11bb4d --- /dev/null +++ b/sources/Emu48/ENGINE.C @@ -0,0 +1,379 @@ +/* + * engine.c + * + * This file is part of Emu48 + * + * Copyright (C) 1995 Sebastien Carlier + * + */ +#include "pch.h" +#include "Emu48.h" +#include "Serial.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" + +BOOL bInterrupt = FALSE; +UINT nState = 1; +UINT nNextState = 0; +BOOL bKeySlow = FALSE; // 18.11.98 cg, new, 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 + +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 + +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 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 __inline VOID CheckSerial(VOID) // 17.05.98 cg, new function + // 25.02.99 cg, changed, inline coded now +{ + if (ioc_acc) // IOC changed + { + ioc_acc = FALSE; + + // COM port closed and serial on + if (bCommInit == FALSE && (Chipset.IORam[IO_CTRL] & 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) + { + 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)) + { + Chipset.Shutdn = FALSE; + INTERRUPT; + } + } +} + +static __inline VOID AdjustSpeed(VOID) // 23.04.98 cg, new, adjust emulation speed + // 25.02.99 cg, changed, inline coded now +{ + if (bRealSpeed || bKeySlow) // 18.11.98 cg, changed, slow down + { + // cycles elapsed for next check + if (Chipset.cycles-dwOldCyc >= (DWORD) T2CYCLES) + { + LARGE_INTEGER lAct; + do + { + BOOL bErr = QueryPerformanceCounter(&lAct); + _ASSERT(bErr); // no high-resolution performance counter + } + while(lAct.LowPart-dwSpeedRef <= dwTickRef); + + dwOldCyc += T2CYCLES; // adjust cycles reference + dwSpeedRef += dwTickRef; // adjust reference time + } + } + 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 +{ + WORD i; + BOOL bKey; + + if (bRealSpeed) return; // no need to slow down + + bKey = FALSE; // search for a pressed key + for (i = 0;i < sizeof(Chipset.Keyboard_Row) / sizeof(Chipset.Keyboard_Row[0]) && !bKey;++i) + bKey = (Chipset.Keyboard_Row[i] != 0); + + if (!bKeySlow && bKey) // key pressed, init variables + { + LARGE_INTEGER lTime; // sample timer ticks + dwOldCyc = Chipset.cycles; // save reference cycles + QueryPerformanceCounter(&lTime); // get timer ticks + dwSpeedRef = lTime.LowPart; // save reference time + } + bKeySlow = bKey; // save new state + return; +} + +VOID SetSpeed(BOOL bAdjust) // 23.04.98 cg, new, set emulation speed +{ + if (bAdjust) // 15.05.98 cg, changed, switch to real speed + { + LARGE_INTEGER lTime; // sample timer ticks + dwOldCyc = Chipset.cycles; // save reference cycles + QueryPerformanceCounter(&lTime); // get timer ticks + dwSpeedRef = lTime.LowPart; // save reference time + } + bRealSpeed = bAdjust; // 15.05.98 cg, bugfix, save emulation speed +} + +VOID UpdateKdnBit(VOID) // 25.02.99 cg, new, update KDN bit +{ + if (Chipset.intk && Chipset.cycles - 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 +{ + DWORD dwRefTime = timeGetTime(); + + // wait for the SHUTDN command with 1.5 sec timeout + while (timeGetTime() - dwRefTime < 1500L && !Chipset.Shutdn) + Sleep(0); + + if (Chipset.Shutdn) // not timeout, cpu is down + SwitchToState(3); // go to sleep state + + return 3 != nNextState; // state not changed, emulator was busy +} + +UINT SwitchToState(UINT nNewState) +{ + UINT nOldState = nState; + + if (nState == nNewState) return nOldState; + switch (nState) + { + case 0: // Run + switch (nNewState) + { + case 1: // -> Invalid + nNextState = 1; + if (Chipset.Shutdn) + ResumeThread(hThread); + else + bInterrupt = TRUE; + while (nState!=nNextState) Sleep(0); + UpdateWindowStatus(); + break; + case 2: // -> Return + nNextState = 1; + if (Chipset.Shutdn) + ResumeThread(hThread); + else + bInterrupt = TRUE; + while (nState!=nNextState) Sleep(0); + nNextState = 2; + ResumeThread(hThread); + while (nState!=nNextState) Sleep(0); + UpdateWindowStatus(); + break; + case 3: // -> Sleep + nNextState = 3; + if (Chipset.Shutdn) + ResumeThread(hThread); + else + bInterrupt = TRUE; + while (nState!=nNextState) Sleep(0); + break; + } + break; + case 1: // Invalid + switch (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); + 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); + 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); + while (nState!=nNextState) Sleep(0); + UpdateWindowStatus(); + break; + } + break; + case 3: // Sleep + switch (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); + 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); + 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); + 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); + while (nState!=nNextState) Sleep(0); + UpdateWindowStatus(); + break; + } + break; + } + return nOldState; +} + +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 + +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 + nState = 1; // in invalid state + SuspendThread(hThread); // sleep thread + 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 + } + while (nNextState == 0) + { + if (nState!=0) + { + nState = 0; + if (Chipset.type == 'S') + { + 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; + } + UpdateDisplayPointers(); + UpdateMainDisplay(); + UpdateMenuDisplay(); + UpdateAnnunciators(); + // 23.04.98 cg, new, init speed reference + dwOldCyc = Chipset.cycles; + QueryPerformanceCounter(&lDummyInt); + dwSpeedRef = lDummyInt.LowPart; + // 23.04.98 cg, end of init + 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 + + CheckSerial(); // 17.05.98 cg, serial support + AdjustSpeed(); // 23.04.98 cg, adjust emulation speed + } + if (Chipset.Shutdn) + { + 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 + } + if (Chipset.SoftInt) + { + bInterrupt = FALSE; + Chipset.SoftInt = FALSE; + if (Chipset.inte) + { + Chipset.inte = FALSE; + rstkpush(Chipset.pc); + Chipset.pc = 0xf; + } + } + if (nNextState != 0) + { + StopTimers(); + Chipset.cards_status &= (Chipset.type=='S')?0x5:0xA; + } + } + while (nNextState == 3) // go into sleep state + { + nState = 3; // in sleep state + SuspendThread(hThread); // sleep thread + } + goto loop; + UNREFERENCED_PARAMETER(pParam); +} diff --git a/sources/Emu48/EXTERNAL.C b/sources/Emu48/EXTERNAL.C new file mode 100644 index 0000000..8f36a7b --- /dev/null +++ b/sources/Emu48/EXTERNAL.C @@ -0,0 +1,64 @@ +/* + * external.c + * + * This file is part of Emu48 + * + * Copyright (C) 1995 Sebastien Carlier + * + */ +#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) + +static __inline VOID Return(CHIPSET* w) +{ + w->rstkp=(w->rstkp-1)&7; + w->pc = w->rstk[w->rstkp]; + w->rstk[w->rstkp] = 0; + return; +} + +VOID External(CHIPSET* w) +{ + if (w->pc==0x017A6) // Beep + { + // begin with patch + // 02.02.98 cg, changed for better emulation + 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; // 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) + + if (dur > 1048575) // 22.07.98 cg, high limit of HP (SX) + dur = 1048575; + + 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; + } + w->pc +=4; + return; +} diff --git a/Emu48/Emu48.mak b/sources/Emu48/Emu48.mak similarity index 100% rename from Emu48/Emu48.mak rename to sources/Emu48/Emu48.mak diff --git a/Emu48/Emu48.mdp b/sources/Emu48/Emu48.mdp similarity index 100% rename from Emu48/Emu48.mdp rename to sources/Emu48/Emu48.mdp diff --git a/Emu48/fetch.h b/sources/Emu48/FETCH.H similarity index 93% rename from Emu48/fetch.h rename to sources/Emu48/FETCH.H index 7632bee..68e74fb 100644 --- a/Emu48/fetch.h +++ b/sources/Emu48/FETCH.H @@ -380,7 +380,7 @@ o81B_: switch(I[3]) { //////// EXTENSIONS //////// -case 0x0: goto o81B0; +// case 0x0: goto o81B0; // 05.01.99 cg, removed, unused extension case 0x1: goto o81B1; //////////////////////////// case 0x2: goto o81B2; diff --git a/Emu48/files.c b/sources/Emu48/FILES.C similarity index 80% rename from Emu48/files.c rename to sources/Emu48/FILES.C index b780bb2..3b15ab4 100644 --- a/Emu48/files.c +++ b/sources/Emu48/FILES.C @@ -30,8 +30,9 @@ 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 dwPort2Mask = 0; -UINT nPort2Bank = 0; +// UINT nPort2Bank = 0; // 15.12.98 cg, removed, not used any more static BYTE pbySignatureE[16] = "Emu48 Document\xFE"; static BYTE pbySignatureW[16] = "Win48 Document\xFE"; @@ -40,6 +41,59 @@ static HANDLE hCurrentFile = NULL; static CHIPSET BackupChipset; BOOL bBackup = FALSE; +//################ +//# +//# Subroutine for Write on Stack +//# +//################ + +WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // 11.05.98 cg, new, separated from LoadObject() +{ + BOOL bBinary; + DWORD dwLength, dwAddress, i; + + bBinary = ((lpBuf[dwSize+0]=='H') + && (lpBuf[dwSize+1]=='P') + && (lpBuf[dwSize+2]=='H') + && (lpBuf[dwSize+3]=='P') + && (lpBuf[dwSize+4]=='4') + && (lpBuf[dwSize+5]=='8') + && (lpBuf[dwSize+6]=='-')); + + for (i=0; i>4); + } + + if (bBinary == TRUE) + { // load as binary + dwLength = RPL_ObjectSize(lpBuf+16); + dwAddress = RPL_CreateTemp(dwLength); + if (dwAddress == 0) return S_ERR_BINARY; + + // 23.05.98 cg, optimized + Nwrite(lpBuf+16, dwAddress, dwLength); + } + else + { // load as string + BYTE lpHead[5]; + dwLength = dwSize*2; + dwAddress = RPL_CreateTemp(dwLength+10); + if (dwAddress == 0) return S_ERR_ASCII; + + Nunpack(lpHead,0x02A2C,5); + Nwrite(lpHead,dwAddress,5); + Nunpack(lpHead,dwLength+5,5); + Nwrite(lpHead,dwAddress+5,5); + // 23.05.98 cg, optimized + Nwrite(lpBuf, dwAddress+10, dwLength); + } + RPL_Push(dwAddress); + return S_ERR_NO; +} + //################ @@ -118,6 +172,21 @@ VOID UnmapRom() //# //################ +static WORD CrcPort2(VOID) // 20.02.99 cg, new, calculate fingerprint of port2 +{ + DWORD dwCount; + DWORD dwFileSize; + WORD wCrc = 0; + + if (pbyPort2==NULL) return wCrc; // port2 isn't available + dwFileSize = GetFileSize(hPort2File, &dwCount); // get real filesize + _ASSERT(dwCount == 0); // isn't created by MapPort2() + + for (dwCount = 0;dwCount < dwFileSize; ++dwCount) + wCrc = (wCrc >> 4) ^ (((wCrc ^ ((WORD) pbyPort2[dwCount])) & 0xf) * 0x1081); + return wCrc; +} + BOOL MapPort2(LPCSTR szFilename) { DWORD dwFileSizeLo; @@ -128,6 +197,7 @@ BOOL MapPort2(LPCSTR szFilename) return FALSE; } bPort2Writeable = TRUE; + dwPort2Size = 0; // 26.06.98 cg, new, reset size of port2 SetCurrentDirectory(szEmu48Directory); if (bPort2IsShared) @@ -175,14 +245,7 @@ BOOL MapPort2(LPCSTR szFilename) bPort2Writeable = FALSE; return FALSE; } - dwPort2Mask = 0; - dwFileSizeHi = dwFileSizeLo >> 18; - while ((dwFileSizeHi&1)==0) - { - dwPort2Mask = (dwPort2Mask<<1)+1; - dwFileSizeHi>>=1; - } - dwPort2Mask = (dwPort2Mask<<1)+1; + dwPort2Mask = (dwFileSizeLo >> 17) - 1; // 26.06,98 cg, optimized, calculate bank switching mask if (bPort2Writeable) hPort2Map = CreateFileMapping(hPort2File, NULL, PAGE_READWRITE, 0, dwFileSizeLo, NULL); else @@ -209,6 +272,8 @@ BOOL MapPort2(LPCSTR szFilename) bPort2Writeable = FALSE; return FALSE; } + dwPort2Size = dwFileSizeLo / 2048; // 26.06.98 cg, new, mapping size of port2 + if (dwPort2Size > 128) dwPort2Size = 128; return TRUE; } @@ -221,6 +286,7 @@ VOID UnmapPort2() pbyPort2 = NULL; hPort2Map = NULL; hPort2File = NULL; + dwPort2Size = 0; // 26.06.98 cg, new, reset size of port2 dwPort2Mask = 0; bPort2Writeable = FALSE; return; @@ -501,13 +567,14 @@ BOOL OpenDocument(LPCSTR szFilename) Chipset.Port0 = NULL; Chipset.Port1 = NULL; - SetWindowPos(hWnd,NULL,(int)Chipset.wPosX,(int)Chipset.wPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); + // 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); if (szCurrentKml == NULL) { if (!DisplayChooseKml(Chipset.type)) { - CloseHandle(hFile); + // CloseHandle(hFile); // 29.01.98 cg, bugfix, will be close at end of function goto restore; } } @@ -515,7 +582,7 @@ BOOL OpenDocument(LPCSTR szFilename) { if (!DisplayChooseKml(Chipset.type)) { - CloseHandle(hFile); + // CloseHandle(hFile); // 29.01.98 cg, bugfix, will be close at end of function goto restore; } } @@ -546,6 +613,13 @@ BOOL OpenDocument(LPCSTR szFilename) if (lBytesRead != Chipset.Port1Size*2048) goto read_err; } + if (Chipset.wPort2Crc != CrcPort2()) // 21.02.99 cg, new, port2 changed + { + 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 + } + lstrcpy(szCurrentFilename, szFilename); hCurrentFile = hFile; Map(0x00,0xFF); @@ -556,7 +630,7 @@ BOOL OpenDocument(LPCSTR szFilename) read_err: AbortMessage("This file must be truncated, and cannot be loaded."); restore: - if (INVALID_HANDLE_VALUE == hFile) + if (INVALID_HANDLE_VALUE != hFile) // 29.01.98 cg, bugfix, close if valid handle CloseHandle(hFile); RestoreBackup(); ResetBackup(); @@ -583,6 +657,8 @@ BOOL SaveDocument() return FALSE; } + Chipset.wPort2Crc = CrcPort2(); // 21.02.99 cg, new, save fingerprint of port2 + nLength = strlen(szCurrentKml); WriteFile(hCurrentFile, &nLength, sizeof(nLength), &lBytesWritten, NULL); WriteFile(hCurrentFile, szCurrentKml, nLength, &lBytesWritten, NULL); @@ -599,27 +675,31 @@ BOOL SaveDocumentAs(LPCTSTR szFilename) { HANDLE hFile = INVALID_HANDLE_VALUE; - if (hCurrentFile) + if (hCurrentFile) // already file in use { if (lstrcmpi(szFilename, szCurrentFilename)==0) { - hFile = hCurrentFile; + hFile = hCurrentFile; // same file, do not open a new one } } - if (hFile == INVALID_HANDLE_VALUE) + 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); } - if (hFile == INVALID_HANDLE_VALUE) + 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; } - lstrcpy(szCurrentFilename, szFilename); - hCurrentFile = hFile; - SetWindowTitle(szCurrentFilename); - UpdateWindowStatus(); - return SaveDocument(); + 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 + UpdateWindowStatus(); // and draw it + return SaveDocument(); // save current content } @@ -651,6 +731,8 @@ BOOL RestoreBackup() { if (!bBackup) return FALSE; ResetDocument(); + // 02.02.98 cg, moved, need chipset for contrast setting in InitKML() + CopyMemory(&Chipset, &BackupChipset, sizeof(Chipset)); if (!InitKML(szBackupKml,TRUE)) { InitKML(szCurrentKml,TRUE); @@ -667,7 +749,8 @@ BOOL RestoreBackup() szCurrentFilename[0] = 0; } } - CopyMemory(&Chipset, &BackupChipset, sizeof(Chipset)); + // 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); @@ -808,16 +891,13 @@ BOOL GetSaveObjectFilename() //# //################ -BOOL LoadObject(LPCSTR szFilename) +BOOL LoadObject(LPCSTR szFilename) // 11.05.98 cg, changed, separated stack writing part { HANDLE hFile; DWORD dwFileSizeLow; DWORD dwFileSizeHigh; - DWORD lBytesRead; LPBYTE lpBuf; - BOOL bKermit = FALSE; - DWORD dwLength, dwAddress; - DWORD i; + WORD wError; hFile = CreateFile(szFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; @@ -833,66 +913,22 @@ BOOL LoadObject(LPCSTR szFilename) CloseHandle(hFile); return FALSE; } - ReadFile(hFile, lpBuf+dwFileSizeLow, dwFileSizeLow, &lBytesRead, NULL); + ReadFile(hFile, lpBuf+dwFileSizeLow, dwFileSizeLow, &dwFileSizeHigh, NULL); CloseHandle(hFile); - if ((lpBuf[dwFileSizeLow+0]=='H') - &&(lpBuf[dwFileSizeLow+1]=='P') - &&(lpBuf[dwFileSizeLow+2]=='H') - &&(lpBuf[dwFileSizeLow+3]=='P') - &&(lpBuf[dwFileSizeLow+4]=='4') - &&(lpBuf[dwFileSizeLow+5]=='8') - &&(lpBuf[dwFileSizeLow+6]=='-')) bKermit = TRUE; + wError = WriteStack(lpBuf,dwFileSizeLow); - for (i=0; i>4); - } + if (wError == S_ERR_BINARY) + AbortMessage("The HP48 has not enough free memory left to load this binary file."); + + if (wError == S_ERR_ASCII) + AbortMessage("The HP48 has not enough free memory left to load this text file."); - if (bKermit == TRUE) - { // load as binary - dwLength = RPL_ObjectSize(lpBuf+16); - dwAddress = RPL_CreateTemp(dwLength); - if (dwAddress == 0) - { - LocalFree(lpBuf); - AbortMessage("The HP48 has not enough free memory left to load this binary file."); - return FALSE; - } - for (i=0; i PAGE_READONLY + hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (hMap == NULL) { CloseHandle(hFile); return NULL; } - pbyFile = MapViewOfFile(hMap, FILE_MAP_COPY, 0, 0, 0); + // 19.01.98 cg, bugfix, opend with GENERIC_READ -> PAGE_READONLY -> FILE_MAP_READ + pbyFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); if (pbyFile == NULL) { CloseHandle(hMap); @@ -1065,8 +1103,10 @@ 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 hPalette = CreateBIPalette(&pBmi->bmiHeader); - SelectPalette(hWindowDC, hPalette, FALSE); + // 11.09.98 cg, save old palette + hOldPalette = SelectPalette(hWindowDC, hPalette, FALSE); RealizePalette(hWindowDC); if (FALSE&&(pBmi->bmiHeader.biBitCount <= 8)) diff --git a/sources/Emu48/KEYBOARD.C b/sources/Emu48/KEYBOARD.C new file mode 100644 index 0000000..5191007 --- /dev/null +++ b/sources/Emu48/KEYBOARD.C @@ -0,0 +1,164 @@ +/* + * keyboard.c + * + * This file is part of Emu48 + * + * Copyright (C) 1995 Sebastien Carlier + * + */ +#include "pch.h" +#include "Emu48.h" + +static WORD Keyboard_GetIR(VOID) // 13.02.99 cg, make function static +{ + WORD r = 0; + + if (Chipset.out==0) return 0; + if (Chipset.out&0x001) r|=Chipset.Keyboard_Row[0]; + if (Chipset.out&0x002) r|=Chipset.Keyboard_Row[1]; + if (Chipset.out&0x004) r|=Chipset.Keyboard_Row[2]; + if (Chipset.out&0x008) r|=Chipset.Keyboard_Row[3]; + if (Chipset.out&0x010) r|=Chipset.Keyboard_Row[4]; + if (Chipset.out&0x020) r|=Chipset.Keyboard_Row[5]; + if (Chipset.out&0x040) r|=Chipset.Keyboard_Row[6]; + if (Chipset.out&0x080) r|=Chipset.Keyboard_Row[7]; + if (Chipset.out&0x100) r|=Chipset.Keyboard_Row[8]; + return r; +} + +VOID ScanKeyboard(BOOL bReset) // 02.09.98 cg, changed, add flag for key state reset +{ + // 02.09.98 cg, new, changed implementation + // bReset = TRUE -> Reset Chipset.in interrupt state register + // FALSE -> generate interrupt only for new pressed keys + + EnterCriticalSection(&csKeyLock); // synchronize + { + BOOL bKbdInt; + + WORD wOldIn = Chipset.in; // save old Chipset.in state + + // 26.02.99 cg, bugfix, update KDN bit + UpdateKdnBit(); + Chipset.dwKdnCycles = Chipset.cycles; + + // update Chipset.in register + Chipset.in = Keyboard_GetIR() | Chipset.IR15X; + + // interrrupt for any new pressed keys ? + bKbdInt = ((Chipset.in & (Chipset.in ^ wOldIn)) != 0) || bReset; + + // 01.03.99 cg, bugfix, update keyboard interrupt pending flag + Chipset.intd = Chipset.intd || (bKbdInt && !Chipset.intk); + + // 28.02.99 cg, changed, keyboard interrupt enabled + bKbdInt = bKbdInt && (Chipset.intk || Chipset.IR15X != 0) && Chipset.inte; + + if (Chipset.in != 0) // any key pressed + { + if (bKbdInt) // interrupt enabled + { + Chipset.SoftInt = TRUE; // interrupt request + bInterrupt = TRUE; // exit emulation loop + } + + if (Chipset.Shutdn) // cpu sleeping + ResumeThread(hThread); // wake up + } + else + { + Chipset.intd = FALSE; // 01.03.99 cg, bugfix, 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; +} + +VOID KeyboardEvent(BOOL bPress, UINT out, UINT in) +{ + if (nState != 0) // not in running state + return; // ignore key + if (in == 0x8000) // ON key ? + { + Chipset.IR15X = bPress?0x8000:0x0000; // refresh special ON key flag + } + else + { + _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 + return; +} diff --git a/Emu48/kml.c b/sources/Emu48/KML.C similarity index 78% rename from Emu48/kml.c rename to sources/Emu48/KML.C index 25f6bee..ba32c63 100644 --- a/Emu48/kml.c +++ b/sources/Emu48/KML.C @@ -116,6 +116,9 @@ 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 + //################ //# //# Compilation Result @@ -336,7 +339,8 @@ static BOOL CALLBACK ChooseKMLProc(HWND hDlg, UINT message, DWORD wParam, LONG l if (wParam == IDC_UPDATE) { DestroyKmlList(); - GetDlgItemText(hDlg,IDC_EMU48DIR,szEmu48Directory,260); + // 01.02.98 cg, calculate size of buffer + GetDlgItemText(hDlg,IDC_EMU48DIR,szEmu48Directory,sizeof(szEmu48Directory)); CreateKmlList(); hList = GetDlgItem(hDlg,IDC_KMLSCRIPT); SendMessage(hList, CB_RESETCONTENT, 0, 0); @@ -352,7 +356,8 @@ static BOOL CALLBACK ChooseKMLProc(HWND hDlg, UINT message, DWORD wParam, LONG l } if (wParam == IDOK) { - GetDlgItemText(hDlg,IDC_EMU48DIR,szEmu48Directory,260); + // 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); nIndex = SendMessage(hList, CB_GETITEMDATA, nIndex, 0); @@ -618,8 +623,7 @@ loop: if (eToken != TOK_EOL) { PrintfToLog("%i: Too many parameters (%i expected).", nLexLine, j); - LocalFree(pLine); - return NULL; + goto errline; // 09.03.99 cg, bugfix, free memory of arguments } return pLine; } @@ -628,8 +632,7 @@ loop: if (eToken != TOK_INTEGER) { PrintfToLog("%i: Parameter %i of %s must be an integer.", nLexLine, j+1, pLexToken[i].szName); - LocalFree(pLine); - return NULL; + goto errline; // 09.03.99 cg, bugfix, free memory of arguments } pLine->nParam[j++] = nLexInteger; nParams >>= 3; @@ -640,14 +643,28 @@ loop: if (eToken != TOK_STRING) { PrintfToLog("%i: Parameter %i of %s must be a string.", nLexLine, j+1, pLexToken[i].szName); - LocalFree(pLine); - return NULL; + goto errline; // 09.03.99 cg, bugfix, free memory of arguments } pLine->nParam[j++] = (DWORD)szLexString; nParams >>= 3; goto 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); + + nParams = pLexToken[i].nParams; // get argument types of command + for (i=0; inParam[i]); + } + nParams >>= 3; // next argument type + } + // 09.03.99 cg, end of bugfix LocalFree(pLine); return NULL; } @@ -721,12 +738,15 @@ static Line* ParseLines() if (IsBlock(eToken)) nLevel++; if (eToken == TOK_INCLUDE) { - eToken = Lex(LEX_PARAM); - if (eToken != TOK_STRING) + LPSTR szFilename; // 11.09.98 cg + 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 goto abort; } + szFilename = szLexString; // 11.09.98 cg, save pointer to allocated memory if (pFirst) { pLine->pNext = IncludeLines(szLexString); @@ -735,6 +755,9 @@ 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 + goto abort; while (pLine->pNext) pLine=pLine->pNext; continue; } @@ -758,6 +781,8 @@ static Line* ParseLines() { pLine = pFirst = ParseLine(eToken); } + if (pLine == NULL) // 09.03.99 cg, bugfix, parsing error + goto abort; } if (nLinesIncludeLevel) { @@ -768,10 +793,9 @@ static Line* ParseLines() abort: if (pFirst) { - pLine->pNext = NULL; + // pLine->pNext = NULL; // 09.03.99 cg, bugfix, pLine == NULL ! FreeLines(pFirst); } - FatalError(); return NULL; } @@ -822,6 +846,12 @@ static Block* ParseBlock(TokenId eType) pBlock->pFirstLine = ParseLines(); + if (pBlock->pFirstLine == NULL) // 09.03.99 cg, bugfix, break on ParseLines error + { + LocalFree(pBlock); + pBlock = NULL; + } + return pBlock; } @@ -892,16 +922,22 @@ static Block* ParseBlocks() { if (eToken == TOK_INCLUDE) { - eToken = Lex(LEX_PARAM); - if (eToken != TOK_STRING) + LPSTR szFilename; // 11.09.98 cg + 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 goto abort; } + szFilename = szLexString; // 11.09.98 cg, 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 + goto abort; while (pBlock->pNext) pBlock=pBlock->pNext; continue; } @@ -912,6 +948,7 @@ static Block* ParseBlocks() if (pBlock == NULL) { AddToLog("Invalid block."); + FatalError(); // 09.03.99 cg, moved from abort part goto abort; } } @@ -919,7 +956,6 @@ static Block* ParseBlocks() return pFirst; abort: if (pFirst) FreeBlocks(pFirst); - FatalError(); return NULL; } @@ -1040,7 +1076,9 @@ static Line* InitLcd(Block* pBlock) nLcdY = pLine->nParam[1]; break; case TOK_ZOOM: - bLcdDoubled = (pLine->nParam[0]==2); + nLcdDoubled = pLine->nParam[0]; // 24.08.98 cg, changed var type + if (nLcdDoubled != 1 && nLcdDoubled != 2 && nLcdDoubled != 4) + nLcdDoubled = 1; break; case TOK_COLOR: SetLcdColor(pLine->nParam[0],pLine->nParam[1],pLine->nParam[2],pLine->nParam[3]); @@ -1277,22 +1315,25 @@ static VOID FreeLines(Line* pLine) Line* pThisLine = pLine; UINT i = 0; DWORD nParams; - while (pLexToken[i].nLen) + while (pLexToken[i].nLen) // search in all token definitions { + // break when token definition found if (pLexToken[i].eId == pLine->eCommand) break; - i++; + i++; // next token definition } - nParams = pLexToken[i].nParams; - i = 0; - while ((nParams&7)) + nParams = pLexToken[i].nParams; // get argument types of command + i = 0; // first parameter + while ((nParams&7)) // argument left { - if ((nParams&7) == TYPE_STRING) + if ((nParams&7) == TYPE_STRING) // string type { - LocalFree((LPVOID)pLine->nParam[i++]); + // 09.03.99 cg, bugfix, free string without incr. parameter buffer + LocalFree((LPVOID)pLine->nParam[i]); } - nParams >>= 3; + i++; // 09.03.99 cg, bugfix, incr. parameter buffer index + nParams >>= 3; // next argument type } - pLine = pLine->pNext; + pLine = pLine->pNext; // get next line LocalFree(pThisLine); } return; @@ -1323,7 +1364,11 @@ VOID KillKML() DestroyMainBitmap(); if (hPalette) { - DeleteObject(hPalette); + BOOL err; + // 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 hPalette = NULL; } bClicking = FALSE; @@ -1408,84 +1453,89 @@ static VOID DrawButton(UINT nId) UINT x0 = pButton[nId].nOx; UINT y0 = pButton[nId].nOy; - switch (pButton[nId].nType) + EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems { - case 0: - if (pButton[nId].bDown) + switch (pButton[nId].nType) { - BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, pButton[nId].nDx, pButton[nId].nDy, SRCCOPY); + case 0: + if (pButton[nId].bDown) + { + BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, pButton[nId].nDx, pButton[nId].nDy, SRCCOPY); + } + else + { + BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, x0, y0, SRCCOPY); + } + break; + case 1: + if (pButton[nId].bDown) + { + UINT x1 = x0+pButton[nId].nCx-1; + UINT y1 = y0+pButton[nId].nCy-1; + BitBlt(hWindowDC, x0+3,y0+3,pButton[nId].nCx-5,pButton[nId].nCy-5,hMainDC,x0+2,y0+2,SRCCOPY); + SelectObject(hWindowDC, GetStockObject(BLACK_PEN)); + MoveToEx(hWindowDC, x0,y0, NULL); LineTo(hWindowDC, x1,y0); + MoveToEx(hWindowDC, x0,y0, NULL); LineTo(hWindowDC, x0,y1); + SelectObject(hWindowDC, GetStockObject(WHITE_PEN)); + MoveToEx(hWindowDC, x1,y0, NULL); LineTo(hWindowDC, x1,y1); + MoveToEx(hWindowDC, x0,y1, NULL); LineTo(hWindowDC, x1+1,y1); + } + else + { + BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, x0, y0, SRCCOPY); + } + break; + case 2: + break; + case 3: + if (pButton[nId].bDown) + { + PatBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, DSTINVERT); + } + else + { + RECT Rect; + Rect.left = x0; + Rect.right = x0 + pButton[nId].nCx; + Rect.top = y0; + Rect.bottom = y0 + pButton[nId].nCy; + InvalidateRect(hWnd, &Rect, 0); + } + break; + case 4: + if (pButton[nId].bDown) + { + BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, x0, y0, SRCCOPY); + } + else + { + RECT Rect; + Rect.left = x0; + Rect.right = x0 + pButton[nId].nCx; + Rect.top = y0; + Rect.bottom = y0 + pButton[nId].nCy; + InvalidateRect(hWnd, &Rect, 0); + } + break; + case 5: + if (pButton[nId].bDown) + { + BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, pButton[nId].nDx, pButton[nId].nDy, SRCCOPY); + } + else + { + BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, x0, y0, SRCCOPY); + } + break; + default: + if (pButton[nId].bDown) + PatBlt(hWindowDC, x0,y0, pButton[nId].nCx, pButton[nId].nCy, BLACKNESS); + else + BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, x0, y0, SRCCOPY); } - else - { - BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, x0, y0, SRCCOPY); - } - break; - case 1: - if (pButton[nId].bDown) - { - UINT x1 = x0+pButton[nId].nCx-1; - UINT y1 = y0+pButton[nId].nCy-1; - BitBlt(hWindowDC, x0+3,y0+3,pButton[nId].nCx-5,pButton[nId].nCy-5,hMainDC,x0+2,y0+2,SRCCOPY); - SelectObject(hWindowDC, GetStockObject(BLACK_PEN)); - MoveToEx(hWindowDC, x0,y0, NULL); LineTo(hWindowDC, x1,y0); - MoveToEx(hWindowDC, x0,y0, NULL); LineTo(hWindowDC, x0,y1); - SelectObject(hWindowDC, GetStockObject(WHITE_PEN)); - MoveToEx(hWindowDC, x1,y0, NULL); LineTo(hWindowDC, x1,y1); - MoveToEx(hWindowDC, x0,y1, NULL); LineTo(hWindowDC, x1+1,y1); - } - else - { - BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, x0, y0, SRCCOPY); - } - break; - case 2: - break; - case 3: - if (pButton[nId].bDown) - { - PatBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, DSTINVERT); - } - else - { - RECT Rect; - Rect.left = x0; - Rect.right = x0 + pButton[nId].nCx; - Rect.top = y0; - Rect.bottom = y0 + pButton[nId].nCy; - InvalidateRect(hWnd, &Rect, 0); - } - break; - case 4: - if (pButton[nId].bDown) - { - BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, x0, y0, SRCCOPY); - } - else - { - RECT Rect; - Rect.left = x0; - Rect.right = x0 + pButton[nId].nCx; - Rect.top = y0; - Rect.bottom = y0 + pButton[nId].nCy; - InvalidateRect(hWnd, &Rect, 0); - } - break; - case 5: - if (pButton[nId].bDown) - { - BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, pButton[nId].nDx, pButton[nId].nDy, SRCCOPY); - } - else - { - BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, x0, y0, SRCCOPY); - } - break; - default: - if (pButton[nId].bDown) - PatBlt(hWindowDC, x0,y0, pButton[nId].nCx, pButton[nId].nCy, BLACKNESS); - else - BitBlt(hWindowDC, x0, y0, pButton[nId].nCx, pButton[nId].nCy, hMainDC, x0, y0, SRCCOPY); + GdiFlush(); // 22.01.98 cg } + LeaveCriticalSection(&csGDILock); // 22.01.98 cg return; } @@ -1555,6 +1605,20 @@ static VOID ReleaseButtonById(UINT nId) return; } +static VOID ReleaseAllButtons(VOID) // 01.10.97 cg, new, release all buttons +{ + UINT i; + for (i=0; i=6) return; - if (bOn) + EnterCriticalSection(&csGDILock); // 22.01.98 cg, bugfix, solving NT GDI problems { - BitBlt(hWindowDC, - pAnnunciator[nId].nOx, pAnnunciator[nId].nOy, - pAnnunciator[nId].nCx, pAnnunciator[nId].nCy, - hMainDC, - pAnnunciator[nId].nDx, pAnnunciator[nId].nDy, - SRCCOPY); - } - else - { - BitBlt(hWindowDC, - pAnnunciator[nId].nOx, pAnnunciator[nId].nOy, - pAnnunciator[nId].nCx, pAnnunciator[nId].nCy, - hMainDC, - pAnnunciator[nId].nOx, pAnnunciator[nId].nOy, - SRCCOPY); + if (bOn) + { + BitBlt(hWindowDC, + pAnnunciator[nId].nOx, pAnnunciator[nId].nOy, + pAnnunciator[nId].nCx, pAnnunciator[nId].nCy, + hMainDC, + pAnnunciator[nId].nDx, pAnnunciator[nId].nDy, + SRCCOPY); + } + else + { + BitBlt(hWindowDC, + pAnnunciator[nId].nOx, pAnnunciator[nId].nOy, + pAnnunciator[nId].nCx, pAnnunciator[nId].nCy, + hMainDC, + pAnnunciator[nId].nOx, pAnnunciator[nId].nOy, + SRCCOPY); + } + GdiFlush(); // 22.01.98 cg } + LeaveCriticalSection(&csGDILock); // 22.01.98 cg return; } @@ -1622,27 +1691,41 @@ VOID MouseButtonDownAt(UINT nFlags, DWORD x, DWORD y) { if (pButton[i].dwFlags&BUTTON_NOHOLD) { - bClicking = TRUE; - uButtonClicked = i; - pButton[i].bDown = TRUE; - DrawButton(i); + if (nFlags&MK_LBUTTON) // 01.10.97 cg, use only with left mouse button + { + bClicking = TRUE; + uButtonClicked = i; + pButton[i].bDown = TRUE; + DrawButton(i); + } return; } if (pButton[i].dwFlags&BUTTON_VIRTUAL) { + if (!(nFlags&MK_LBUTTON)) // 01.10.97 cg, 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 PressButton(i); return; } } - UNREFERENCED_PARAMETER(nFlags); } VOID MouseButtonUpAt(UINT nFlags, DWORD x, DWORD y) { UINT i; +// begin with patch + if (bPressed) // 01.10.97 cg, emulator key pressed + { + ReleaseAllButtons(); // 01.10.97 cg, 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 (!bClicking) return; // normal emulation key -> quit +// continue with original part + if (pButton[uButtonClicked].dwFlags&BUTTON_NOHOLD) { if (ClipButton(x,y, uButtonClicked) != pButton[uButtonClicked].bDown) diff --git a/Emu48/kml.h b/sources/Emu48/KML.H similarity index 100% rename from Emu48/kml.h rename to sources/Emu48/KML.H diff --git a/sources/Emu48/MOPS.C b/sources/Emu48/MOPS.C new file mode 100644 index 0000000..312c874 --- /dev/null +++ b/sources/Emu48/MOPS.C @@ -0,0 +1,1377 @@ +/* + * mops.c + * + * This file is part of Emu48 + * + * Copyright (C) 1995 Sebastien Carlier + * + */ +#include "pch.h" +#include "Emu48.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 + +// 30.06.98 cg, new, 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 + +static BYTE byVblRef = 0; // 14.01.99 cg, new, VBL stop reference + +// CRC calculation +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) +{ + Chipset.crc = (WORD)((Chipset.crc>>4)^crc_table[(Chipset.crc^nib)&0xf]); +} + +// LCD line counter calculation + +static BYTE F4096Hz(VOID) // 14.01.99 cg, new, get a 6 bit 4096Hz down counter value +{ + LARGE_INTEGER lLC; + + QueryPerformanceCounter(&lLC); // get counter value + // calculate 4096 Hz frequency down counter value + return -(BYTE)((lLC.LowPart * 4096) / lFreq.LowPart) & 0x3F; +} + +// port mapping + +LPBYTE RMap[256] = {NULL,}; +LPBYTE WMap[256] = {NULL,}; + +static __inline UINT MIN(UINT a, UINT b) +{ + return (ab)?a:b; +} + +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 + 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 + for (i=a; i<=b; i++) + { + // 21.01.99 cg, bugfix, mapping area may have holes + if (((i ^ Chipset.P0Base) & ~Chipset.P0Size) == 0) + { + RMap[i]=Chipset.Port0 + p; + WMap[i]=Chipset.Port0 + p; + } + p = (p+0x1000)&m; + } + return; +} + +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 + 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 + if (((i ^ Chipset.BSBase) & ~Chipset.BSSize) == 0) + { + RMap[i] = NULL; // 15.12.98 cg, bugfix, no read cycle, open data bus + WMap[i] = NULL; + } + // p = (p+0x1000)&m; // 15.12.98 cg, removed + } + return; +} + +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 + 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 + { + 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]=Chipset.Port1 + p; // save page address for read + WMap[i]=Chipset.Port1 + p; // save page address for write + } + p = (p+0x1000)&m; // next page, mirror page if real size smaller allocated size + } + } + else // port1 read only + { + 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]=Chipset.Port1 + p; // save page address for read + WMap[i]=NULL; // no writing + } + p = (p+0x1000)&m; // next page, mirror page if real size smaller allocated size + } + } + return; +} + +static VOID MapP2(BYTE a, BYTE b) +{ + UINT i; + 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 + 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 + for (i=a; i<=b; i++) // fill mapping area with not configured + { + // 21.01.99 cg, bugfix, mapping area may have holes + if (((i ^ Chipset.P2Base) & ~Chipset.P2Size) == 0) + { + RMap[i] = NULL; + WMap[i] = NULL; + } + } + // SX: CE2.2 = CE2 + // GX: CE2.2 = BEN & /DA19 & /NCE3 + if (cCurrentRomType == 'S' || ((Chipset.IORam[0x29]&0x8) == 0 && (Chipset.Port2_Bank&0x40))) + { + if (bPort2Writeable) + { + for (i=a; i<=b; i++) + { + // 21.01.99 cg, bugfix, mapping area may have holes + if (((i ^ Chipset.P2Base) & ~Chipset.P2Size) == 0) + { + RMap[i]=pbyTemp + p; + WMap[i]=pbyTemp + p; + } + p = (p+0x1000)&m; + } + } + else + { + for (i=a; i<=b; i++) + { + // 21.01.99 cg, bugfix, mapping area may have holes + if (((i ^ Chipset.P2Base) & ~Chipset.P2Size) == 0) + { + RMap[i]=pbyTemp + p; + } + p = (p+0x1000)&m; + } + } + } + // 15.12.98 cg, end of bugfix + return; +} + +static VOID MapROM(BYTE a, BYTE b) +{ + UINT i; + DWORD p, m; + + m = (dwRomSize-1)&0xFF000; // ROM address mask for mirroring + // 15.12.98 cg, bugfix, 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 + for (i=a;i<=b;i++) // scan each 2KB page + { + RMap[i]=pbyRom + p; // save page address for read + WMap[i]=NULL; // no writing + p = (p+0x1000)&m; // next page, mirror page if real size smaller allocated size + } + return; +} + +VOID Map(BYTE a, BYTE b) // maps 2KB pages with priority +{ + // 25.06.98 cg, size optimized implementation + // priority order is HDW, RAM, CE2, CE1, NCE3, ROM + MapROM(a,b); // ROM, lowest priority, always mapped + if (cCurrentRomType=='S') + { + 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) + } + else + { + 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.P0Cfig) MapP0(a,b); // RAM, highest priority (execpt HDW) + return; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Bus Commands +// +//////////////////////////////////////////////////////////////////////////////// + +VOID Config() // configure modules in fixed order +{ + DWORD d = Npack(Chipset.C,5); // decode size or address + 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 + { + Chipset.IOCfig = TRUE; + Chipset.IOBase = d&0xFFFC0; // save HDW base on a 64 nib boundary + Map(b,b); + return; + } + if (!Chipset.P0Cfg2) // RAM size, port0 + { + Chipset.P0Cfg2 = TRUE; + Chipset.P0Size = s; // offset to last used page + return; + } + if (!Chipset.P0Cfig) // RAM address, port0 + { + Chipset.P0Cfig = TRUE; + Chipset.P0Base = b; // save first page address + b &= ~Chipset.P0Size; // 30.06.98 cg, bugfix, 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 + return; + } + if (cCurrentRomType=='S') + { + if (!Chipset.P1Cfg2) // CE1 size, port1 + { + Chipset.P1Cfg2 = TRUE; + Chipset.P1Size = s; + return; + } + if (!Chipset.P1Cfig) // CE1 address, port1 + { + Chipset.P1Cfig = TRUE; + Chipset.P1Base = b; + b &= ~Chipset.P1Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary + Chipset.P1End = b+Chipset.P1Size; + Map(b,Chipset.P1End); // 30.06.98 cg, bugfix, refresh mapping + return; + } + if (!Chipset.P2Cfg2) // CE2 size, port2 + { + Chipset.P2Cfg2 = TRUE; + Chipset.P2Size = s; + return; + } + if (!Chipset.P2Cfig) // CE2 address, port2 + { + Chipset.P2Cfig = TRUE; + Chipset.P2Base = b; + b &= ~Chipset.P2Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary + Chipset.P2End = b+Chipset.P2Size; + Map(b,Chipset.P2End); // 30.06.98 cg, bugfix, refresh mapping + return; + } + if (!Chipset.BSCfg2) // NCE3 size, not used in S(X) + { + Chipset.BSCfg2 = TRUE; + Chipset.BSSize = s; + return; + } + if (!Chipset.BSCfig) // NCE3 address, not used in S(X) + { + Chipset.BSCfig = TRUE; + Chipset.BSBase = b; + b &= ~Chipset.BSSize; // 30.06.98 cg, bugfix, adjust base to mapping boundary + Chipset.BSEnd = b+Chipset.BSSize; + Map(b,Chipset.BSEnd); // 30.06.98 cg, bugfix, refresh mapping + return; + } + } + else + { + if (!Chipset.BSCfg2) // CE1 size, bank select + { + Chipset.BSCfg2 = TRUE; + Chipset.BSSize = s; + return; + } + if (!Chipset.BSCfig) // CE1 address, bank select + { + Chipset.BSCfig = TRUE; + Chipset.BSBase = b; + b &= ~Chipset.BSSize; // 30.06.98 cg, bugfix, adjust base to mapping boundary + Chipset.BSEnd = b+Chipset.BSSize; + Map(b,Chipset.BSEnd); // 30.06.98 cg, bugfix, refresh mapping + return; + } + if (!Chipset.P1Cfg2) // CE2 size, port1 + { + Chipset.P1Cfg2 = TRUE; + Chipset.P1Size = s; + return; + } + if (!Chipset.P1Cfig) // CE2 address, port1 + { + Chipset.P1Cfig = TRUE; + Chipset.P1Base = b; + b &= ~Chipset.P1Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary + Chipset.P1End = b+Chipset.P1Size; + Map(b,Chipset.P1End); // 30.06.98 cg, bugfix, refresh mapping + return; + } + if (!Chipset.P2Cfg2) // NCE3 size, port2 + { + Chipset.P2Cfg2 = TRUE; + Chipset.P2Size = s; + return; + } + if (!Chipset.P2Cfig) // NCE3 address, port2 + { + Chipset.P2Cfig = TRUE; + Chipset.P2Base = b; + b &= ~Chipset.P2Size; // 30.06.98 cg, bugfix, adjust base to mapping boundary + Chipset.P2End = b+Chipset.P2Size; + Map(b,Chipset.P2End); // 30.06.98 cg, bugfix, refresh mapping + return; + } + } + return; +} + +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') + { + // 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 + { + // 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;} + } + return; +} + +VOID Reset() +{ + Chipset.IOCfig=FALSE;Chipset.IOBase=0x100000; + Chipset.P0Cfig=FALSE;Chipset.P0Cfg2=FALSE;Chipset.P0Base=0;Chipset.P0Size=0;Chipset.P0End=0; + Chipset.BSCfig=FALSE;Chipset.BSCfg2=FALSE;Chipset.BSBase=0;Chipset.BSSize=0;Chipset.BSEnd=0; + Chipset.P1Cfig=FALSE;Chipset.P1Cfg2=FALSE;Chipset.P1Base=0;Chipset.P1Size=0;Chipset.P1End=0; + Chipset.P2Cfig=FALSE;Chipset.P2Cfg2=FALSE;Chipset.P2Base=0;Chipset.P2Size=0;Chipset.P2End=0; + Map(0x00,0xFF); // refresh mapping + return; +} + +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 (!Chipset.P1Cfg2) {Nunpack(Chipset.C,(Chipset.P1Size*0x1000)^0xFF005,5);return;} + if (!Chipset.P1Cfig) {Nunpack(Chipset.C,(Chipset.P1Base*0x1000)^0x000F6,5);return;} + if (!Chipset.P2Cfg2) {Nunpack(Chipset.C,(Chipset.P2Size*0x1000)^0xFF007,5);return;} + if (!Chipset.P2Cfig) {Nunpack(Chipset.C,(Chipset.P2Base*0x1000)^0x000F8,5);return;} + 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 + { + if (!Chipset.BSCfg2) {Nunpack(Chipset.C,(Chipset.BSSize*0x1000)^0xFF005,5);return;} + if (!Chipset.BSCfig) {Nunpack(Chipset.C,(Chipset.BSBase*0x1000)^0x000F6,5);return;} + if (!Chipset.P1Cfg2) {Nunpack(Chipset.C,(Chipset.P1Size*0x1000)^0xFF007,5);return;} + if (!Chipset.P1Cfig) {Nunpack(Chipset.C,(Chipset.P1Base*0x1000)^0x000F8,5);return;} + if (!Chipset.P2Cfg2) {Nunpack(Chipset.C,(Chipset.P2Size*0x1000)^0xFF001,5);return;} + if (!Chipset.P2Cfig) {Nunpack(Chipset.C,(Chipset.P2Base*0x1000)^0x000F2,5);return;} + } + memset(Chipset.C,0,5); + return; +} + +VOID Npeek(BYTE *a, DWORD d, UINT s) +{ + DWORD u, v; + UINT c; + BYTE *p; + + do + { + 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; +} + +VOID Nread(BYTE *a, DWORD d, UINT s) +{ + DWORD u, v; + UINT c; + BYTE *p; + + do + { + // 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping + if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase)) + { + v = d&0x3F; + c = MIN(s,0x40-v); + ReadIO(a,v,c); + } + 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)) + { + Chipset.Port2_Bank = v+c; // save FF value + Map(Chipset.P2Base,Chipset.P2End); + } + // 15.12.98 cg, end of bugfix + if ((p=RMap[u]) != NULL) + { + memcpy(a, p+v, c); + for (u=0; uChipset.start12)) + { + p = a; // copy source ptr + u = d; // copy destination ptr + c = MIN(s,Chipset.end1-d); // number of nibbles to copy + + if (d < Chipset.start12) // first address is out of display area + { + u = Chipset.start12; // set destination ptr to start of display area + c -= Chipset.start12 - d; // - number of bytes that aren't in display area + p += Chipset.start12 - d; // adjust source ptr + } + WriteToMainDisplay(p,u,c); + } + if ((dChipset.start2)) + { + p = a; // copy source ptr + u = d; // copy destination ptr + c = MIN(s,Chipset.end2-d); // number of nibbles to copy + + if (d < Chipset.start2) // first address is out of display area + { + u = Chipset.start2; // set destination ptr to start of display area + c -= Chipset.start2 - d; // - number of bytes that are not in display area + p += Chipset.start2 - d; // adjust source ptr + } + WriteToMenuDisplay(p,u,c); + } + // 09.01.99 cg, end of bugfix + do + { + // 03.12.98 cg, changed, test Chipset.IOCfig as well for mapping + if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase)) + { + v = d&0x3F; + c = MIN(s,0x40-v); + WriteIO(a, v, c); + } + else + { + u = d>>12; + v = d&0xFFF; + c = MIN(s,0x1000-v); + if ((p=WMap[u]) != NULL) memcpy(p+v, a, c); + } + a+=c; + d+=c; + } while (s-=c); + 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]; + + Npeek(p,d,5); + return Npack(p,5); +} + +BYTE Read2(DWORD d) +{ + BYTE p[2]; + + Npeek(p,d,2); + return (BYTE)(p[0]|(p[1]<<4)); +} + +VOID Write5(DWORD d, DWORD n) +{ + BYTE p[8]; + + Nunpack(p,n,5); + Nwrite(p,d,5); + return; +} + +VOID IOBit(DWORD d, BYTE b, BOOL s) // 24.02.99 cg, new, set/clear bit in I/O section +{ + EnterCriticalSection(&csIOLock); + { + if (s) + Chipset.IORam[d] |= b; // set bit + else + Chipset.IORam[d] &= ~b; // clear bit + } + LeaveCriticalSection(&csIOLock); +} + +VOID ReadIO(BYTE *a, DWORD d, DWORD s) // 24.08.98 cg, changed 2nd var name +{ + // 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 + + #if defined DEBUG_IO // 21.01.99 cg, new + { + char buffer[256]; + wsprintf(buffer,"%.5lx: IO read : %02x,%u\n",Chipset.pc,d,s); + OutputDebugString(buffer); + } + #endif + + do + { + switch (d) + { + case 0x00: *a = (Chipset.dispon<<3)|Chipset.boffset; break; + case 0x01: *a = Chipset.contrast&0xF; break; + case 0x02: *a = Chipset.contrast>>4; break; + case 0x03: *a = 0; + case 0x04: *a = (Chipset.crc )&0xF; break; + case 0x05: *a = (Chipset.crc>> 4)&0xF; break; + case 0x06: *a = (Chipset.crc>> 8)&0xF; break; + case 0x07: *a = (Chipset.crc>>12)&0xF; break; + case 0x08: *a = 0; break; +// case 0x09: *a = Chipset.IORam[d]; break; + case 0x0A: *a = 0; break; +// 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 + { + char buffer[256]; + wsprintf(buffer,"%.5lx: BAUD Read: %x\n",Chipset.pc,*a); + OutputDebugString(buffer); + } + #endif + break; +// case 0x0E: *a = Chipset.IORam[d]; break; + case 0x0F: *a = Chipset.cards_status; break; + case 0x10: // IO CONTROL + *a = Chipset.IORam[d]; // 17.05.98 cg, return IO CONTROL value + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: IOC Read: %x\n",Chipset.pc,*a); + OutputDebugString(buffer); + } + #endif + break; + case 0x11: // RCS + *a = Chipset.IORam[d]; // 17.05.98 cg, return RCS value + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: RCS Read: %x\n",Chipset.pc,*a); + OutputDebugString(buffer); + } + #endif + break; + case 0x12: // TCS + *a = Chipset.IORam[d]; // 17.05.98 cg, new, return TCS value + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: TCS Read: %x\n",Chipset.pc,*a); + OutputDebugString(buffer); + } + #endif + break; + case 0x13: // CRER + *a = 0; + 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 + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: RBR %s Read: %x\n",Chipset.pc,(d==0x14) ? "LSB" : "MSB",*a); + OutputDebugString(buffer); + } + #endif + break; + case 0x16: // TBR LSB + case 0x17: // TBR MSB + *a = 0; + break; + case 0x19: // SREQ? MSB + UpdateKdnBit(); // 25.02.99 cg, bugfix, update KDN bit + // no break! + case 0x18: // SREQ? LSB + *a = Chipset.IORam[d]; // 17.05.95, new, return SREQ value + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: SEQ %s Read: %x\n",Chipset.pc,(d==0x18) ? "LSB" : "MSB",*a); + OutputDebugString(buffer); + } + #endif + break; + case 0x1A: // IR CONTROL + *a = Chipset.IORam[d]; // 17.05.98 cg, new, return IR CONTROL value + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: IRC Read: %x\n",Chipset.pc,*a); + OutputDebugString(buffer); + } + #endif + break; + case 0x1B: *a = 0; break; + case 0x1C: *a = 0; break; + case 0x1D: *a = 0; break; +// case 0x1E: *a = Chipset.IORam[0x1E]; break; +// case 0x1F: *a = Chipset.IORam[0x1F]; break; + case 0x20: *a = 3; break; + case 0x21: *a = 3; break; + case 0x22: *a = 3; break; + case 0x23: *a = 3; break; + case 0x24: *a = 3; break; + 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; + // save line information in IO registers + Chipset.IORam[0x28] = c & 0xF; + Chipset.IORam[0x29] = (Chipset.IORam[0x29] & 0xC) | (c >> 4); + } + } + *a = Chipset.IORam[d]; + + if (d==0x29) // address 0x29 is mirrored to 0x2A-0x2D + { + Chipset.IORam[0x2A] = *a; + Chipset.IORam[0x2B] = *a; + Chipset.IORam[0x2C] = *a; + Chipset.IORam[0x2D] = *a; + } + break; +// case 0x2A: *a = 0; break; +// 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]; + break; + case 0x2F: + 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; + case 0x33: *a = 3; break; + case 0x34: *a = 3; break; + case 0x35: *a = 0; break; + case 0x36: *a = 0; break; + case 0x37: *a = ReadT1(); break; + case 0x38: Nunpack(a, ReadT2() , s); return; + case 0x39: Nunpack(a, ReadT2()>> 4, s); return; + case 0x3A: Nunpack(a, ReadT2()>> 8, s); return; + case 0x3B: Nunpack(a, ReadT2()>>12, s); return; + case 0x3C: Nunpack(a, ReadT2()>>16, s); return; + case 0x3D: Nunpack(a, ReadT2()>>20, s); return; + case 0x3E: Nunpack(a, ReadT2()>>24, s); return; + case 0x3F: Nunpack(a, ReadT2()>>28, s); return; + default: *a = Chipset.IORam[d]; + } + d++; a++; + } while (--s); + if (rbr_acc) CommReceive(); // 17.05.98 cg, new, look for new character + return; +} + +VOID WriteIO(BYTE *a, DWORD d, DWORD s) // 07.09.98 cg, changed 2nd var name +{ + // DWORD d=b; // 07.09.98 cg, removed + DWORD b; // 07.09.98 cg, new + 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 + + #if defined DEBUG_IO // 21.01.99 cg, new + { + char buffer[256]; + DWORD j; + int i; + + i = wsprintf(buffer,"%.5lx: IO write: %02x,%u = ",Chipset.pc,d,s); + for (j = 0;j < s;++j,++i) + { + buffer[i] = a[j]; + if (buffer[i] > 9) buffer[i] += 0x27; + buffer[i] += '0'; + } + buffer[i++] = '\n'; + buffer[i] = 0; + + OutputDebugString(buffer); + } + #endif + + if (d>=0x38) + { + Nunpack(Chipset.IORam+0x38, ReadT2(), 8); + memcpy(Chipset.IORam+d,a,s); + SetT2(Npack(Chipset.IORam+0x38,8)); + return; + } + do + { + c = *a; + switch (d) + { +// 00100 = NS:DISPIO +// 00100 @ Display bit offset and DON [DON OFF2 OFF1 OFF0] +// 00100 @ 3 nibs for display offset (scrolling), DON=Display ON + case 0x00: + if ((c^Chipset.IORam[d])&8) // DON bit changed + { + Chipset.dispon = c>>3; + disp|=7; + + // 14.01.99 cg, bugfix, adjust VBL counter start/stop values + if (Chipset.dispon) // display is on + { + // get positive VBL difference between now and stop time + byVblRef = ( 0x40 + + F4096Hz() + - (((Chipset.IORam[0x29] << 4) | Chipset.IORam[0x28]) & 0x3F) + ) & 0x3F; + } + else // display is off + { + 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; + } + Chipset.IORam[d] = c; + break; + +// 00101 = NS:CONTRLSB +// 00101 @ Contrast Control [CON3 CON2 CON1 CON0] +// 00101 @ Higher value = darker screen + case 0x01: + if (c!=Chipset.IORam[d]) + { + Chipset.IORam[d]=c; + Chipset.contrast = (Chipset.contrast&0x10)|c; + UpdateContrast(Chipset.contrast); + disp|=7; + } + break; + +// 00102 = NS:DISPTEST +// 00102 @ Display test [VDIG LID TRIM CON4] [LRT LRTD LRTC BIN] +// 00102 @ Normally zeros + case 0x02: + if (c!=Chipset.IORam[d]) + { + Chipset.IORam[d]=c; + Chipset.contrast = (Chipset.contrast&0x0f)|((c&1)<<4); + UpdateContrast(Chipset.contrast); + disp|=7; + } + break; + + case 0x03: Chipset.IORam[d]=c; break; + +// 00104 = HP:CRC +// 00104 @ 16 bit hardware CRC (104-107) (X^16+X^12+X^5+1) +// 00104 @ crc = ( crc >> 4 ) ^ ( ( ( crc ^ nib ) & 0x000F ) * 0x1081 ); + case 0x04: Chipset.crc = (Chipset.crc&0xfff0)|(c*0x0001); break; + case 0x05: Chipset.crc = (Chipset.crc&0xff0f)|(c*0x0010); break; + case 0x06: Chipset.crc = (Chipset.crc&0xf0ff)|(c*0x0100); break; + case 0x07: Chipset.crc = (Chipset.crc&0x0fff)|(c*0x1000); break; + +// 00108 = NS:POWERSTATUS +// 00108 @ Low power registers (108-109) +// 00108 @ [LB2 LB1 LB0 VLBI] (read only) +// 00108 @ LowBat(2) LowBat(1) LowBat(S) VeryLowBat + case 0x08: break; // read-only + +// 00109 = NS:POWERCTRL +// 00109 @ [ELBI EVLBI GRST RST] (read/write) + case 0x09: Chipset.IORam[d]=c; break; + +// 0010A = NS:MODE +// 0010A @ Mode Register (read-only) + case 0x0A: break; // read-only + +// 0010B = HP:ANNCTRL +// 0010B @ Annunciator control [LA4 LA3 LA2 LA1] = [ alarm alpha -> <- ] + case 0x0B: + case 0x0C: + if (c!=Chipset.IORam[d]) + { + Chipset.IORam[d] = c; + disp|=8; + } + break; + +// 0010D = NS:BAUD +// 0010D @ Serial baud rate [UCK BD2 BD1 BD0] (bit 3 is read-only) +// 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 + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: BAUD write: %x\n",Chipset.pc,Chipset.IORam[d]); + OutputDebugString(buffer); + } + #endif + break; + +// 0010E = NS:CARDCTRL +// 0010E @ [ECDT RCDT SMP SWINT] (read/write) +// 0010E @ Enable Card Det., Run Card Det., Set Module Pulled, Software interrupt + case 0x0E: + Chipset.IORam[d]=c; +#if 1 + if ( (RMap[4]!=(pbyRom+0x4000)) && (12 != c) ) + { + c |= 0x10; + } +#endif + if (c&1) + { + Chipset.SoftInt = TRUE; + bInterrupt = TRUE; + } + if (c&2) + { + Chipset.HST |= 8; // MP +// Chipset.SoftInt = TRUE; +// bInterrupt = TRUE; + } + break; + +// 0010F = NS:CARDSTATUS +// 0010F @ [P2W P1W P2C P1C] (read-only) Port 2 writable .. Port 1 inserted + case 0x0F: break; // read-only + +// 00110 = HP:IOC +// 00110 @ Serial I/O Control [SON ETBE ERBF ERBZ] +// 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 + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: IOC write: %x\n",Chipset.pc,Chipset.IORam[d]); + OutputDebugString(buffer); + } + #endif + break; + +// 00111 = HP:RCS +// 00111 Serial Receive Control/Status [RX RER RBZ RBF] (bit 3 is read-only) + case 0x11: + Chipset.IORam[d]=(Chipset.IORam[d]&8)|(c&7); + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: RCS write: %x\n",Chipset.pc,Chipset.IORam[d]); + OutputDebugString(buffer); + } + #endif + break; + +// 00112 = HP:TCS +// 00112 @ Serial Transmit Control/Status [BRK LPB TBZ TBF] + case 0x12: + Chipset.IORam[d]=c; + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: TCS write: %x\n",Chipset.pc,Chipset.IORam[d]); + OutputDebugString(buffer); + } + #endif + break; + +// 00113 = HP:CRER +// 00113 @ Serial Clear RER (writing anything clears RER bit) + case 0x13: + Chipset.IORam[0x11]&=0xB; + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: CRER write: %x\n",Chipset.pc,Chipset.IORam[d]); + OutputDebugString(buffer); + } + #endif + break; + +// 00114 = HP:RBR +// 00114 @ Serial Receive Buffer Register (Reading clears RBF bit) +// 00114 @ [RX RER RBZ RBF] + case 0x14: break; // read-only + case 0x15: break; // read-only + +// 00116 = HP:TBR +// 00116 @ Serial Transmit Buffer Register (Writing sets TBF bit) + case 0x16: + case 0x17: + Chipset.IORam[d]=c; + Chipset.IORam[0x12]|=1; + tbr_acc = TRUE; // 17.05.98 cg, new, new TBR value + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: TBR %s write: %x\n",Chipset.pc,(d==0x16) ? "LSB" : "MSB",*a); + OutputDebugString(buffer); + } + #endif + break; + +// 00118 = NS:SRR +// 00118 @ Service Request Register (read-only) +// 00118 @ [ISRQ TSRQ USRQ VSRQ] [KDN NINT2 NINT LSRQ] + case 0x18: break; // read-only + case 0x19: break; // read-only + +// 0011A = HP:IRC +// 0011A @ IR Control Register [IRI EIRU EIRI IRE] (bit 3 is read-only) +// 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 + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"%.5lx: IRC write: %x\n",Chipset.pc,Chipset.IORam[d]); + OutputDebugString(buffer); + } + #endif + break; + +// 0011B = NS:BASENIBOFF +// 0011B @ Used as addressto get BASENIB from 11F to the 5th nibble + case 0x1B: break; + +// 0011C = NS:LCR +// 0011C @ Led Control Register [LED ELBE LBZ LBF] (Setting LED is draining) + case 0x1C: Chipset.IORam[d]=c; break; + +// 0011D = NS:LBR +// 0011D @ Led Buffer Register [0 0 0 LBO] (bits 1-3 read zero) + case 0x1D: Chipset.IORam[d]=c&1; break; + +// 0011E = NS:SCRATCHPAD +// 0011E @ Scratch pad + case 0x1E: Chipset.IORam[d]=c; break; + +// 0011F = NS:BASENIB +// 0011F @ 7 or 8 for base memory + case 0x1F: Chipset.IORam[d]=c; break; + +// 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: + case 0x23: + case 0x24: + 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 + if (cCurrentRomType != 'S' && d == 0x29) + { + if ((c^Chipset.IORam[d])&8) // DA19 changed + { + Chipset.IORam[d]=c; // save new DA19 + 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; + case 0x2C: break; + case 0x2D: break; + +// 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 + 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 + if (c&1) + StartTimers(); + else + StopTimers(); + break; + +// 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: + case 0x33: + case 0x34: + 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; + +// 00137 = HP:TIMER1 +// 00137 @ Decremented 16 times/s + case 0x37: + SetT1(c); // 11.06.98 cg, bugfix, set new value + break; + +// 00138 = HP:TIMER2 +// 00138 @ hardware timer (38-3F), decremented 8192 times/s + // nothing - fall through to default + + default: Chipset.IORam[d]=c; + } + a++; d++; + } while (--s); + + if (bDISPADDR) // 07.09.98 cg, new, addr 0x120-0x124 changed + { + b = Npack(Chipset.IORam+0x20,5)&0xFFFFE; + if (b != Chipset.start1) + { + Chipset.start1 = b; + disp|=3; + } + } + if (bLINEOFFS) // 07.09.98 cg, new, 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; + } + } + if (bLINECOUNT) // 07.09.98 cg, new, addr 0x128-0x129 changed + { + b = Npack(Chipset.IORam+0x28,2)&0x3F; + if (Chipset.lcounter != b) + { + Chipset.lcounter = b; + disp|=7; + } + } + if (bMENUADDR) // 07.09.98 cg, new, addr 0x130-0x134 changed + { + b = Npack(Chipset.IORam+0x30,5)&0xFFFFE; + if (b != Chipset.start2) + { + Chipset.start2 = b; + disp|=5; + } + } + + 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(); + return; +} diff --git a/sources/Emu48/OPCODES.H b/sources/Emu48/OPCODES.H new file mode 100644 index 0000000..5081465 --- /dev/null +++ b/sources/Emu48/OPCODES.H @@ -0,0 +1,2405 @@ +/* + * opcodes.h + * + * This file is part of Emu48 + * + * Copyright (C) 1995 Sebastien Carlier + * + */ + +// 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; +//////////////////////////// diff --git a/Emu48/ops.h b/sources/Emu48/OPS.H similarity index 63% rename from Emu48/ops.h rename to sources/Emu48/OPS.H index dbc5bdf..ec5a0ee 100644 --- a/Emu48/ops.h +++ b/sources/Emu48/OPS.H @@ -6,7 +6,7 @@ * Copyright (C) 1995 Sebastien Carlier * */ -#pragma warning(disable:4244) +// #pragma warning(disable:4244) // Fields start and length static UINT F_s[16] = {0/*P*/,0,2,0,15,3,0,0,0,0,0,0,0,0,0,0}; @@ -24,14 +24,13 @@ 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_s[f], F_l[f]) -#define NFdec(a, f) Ndec((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 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]) #define NFsr(a, f) Nsr((a)+F_s[f], F_l[f]) #define NFsrb(a, f) Nsrb((a)+F_s[f], F_l[f]) -#define NFdbl(a, f) Ndbl((a)+F_s[f], F_l[f]) #define TFe(a, b, f) Te((a)+F_s[f], (b)+F_s[f], F_l[f]) #define TFa(a, b, f) Ta((a)+F_s[f], (b)+F_s[f], F_l[f]) #define TFb(a, b, f) Tb((a)+F_s[f], (b)+F_s[f], F_l[f]) @@ -81,30 +80,44 @@ static __inline void Nxchg(BYTE *a, BYTE *b, UINT s) memcpy(a, X, s); } -static __inline void Ninc(BYTE *a, UINT s) +// 24.03.98 cg, changed, new implementation +static __inline void Ninc(BYTE *a, UINT s, UINT d) { UINT i; - - if (Chipset.mode_dec) + BYTE cBase = Chipset.mode_dec ? 10 : 16; + + for (i=d; i=10) { a[i]-=10; c=1; } else c=0; - } - } - else - { - for (i=0; i=16) { a[i]-=16; c=1; } else c=0; - } - } - if (c==1) - Chipset.carry=TRUE; - else - Chipset.carry=FALSE; -} + BYTE cBase = Chipset.mode_dec ? 10 : 16; -static __inline void Ndbl(BYTE *a, UINT s) -{ - UINT i; - BYTE b[16]; - BYTE c = 0; - - if (Chipset.mode_dec) + for (i=0; i= cBase) { - a[i] += b[i] + c; - if (a[i]>=10) { a[i]-=10; c=1; } else c=0; + a[i] -= cBase; + c = 1; } + else + c = 0; } - else - { - memcpy(b, a, s); - for (i=0; i=16) { a[i]-=16; c=1; } else c=0; - } - } - if (c==1) - Chipset.carry=TRUE; - else - Chipset.carry=FALSE; + 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; BYTE c = 0; + BYTE cBase = Chipset.mode_dec ? 10 : 16; - if (Chipset.mode_dec) + for (i=0; i= cBase) { - a[i] -= (BYTE)(b[i]+c); - if (a[i]>=10) { a[i]+=10; c=1; } else c=0; + a[i] += cBase; + c = 1; } + else + c = 0; } - else - { - for (i=0; i=16) { a[i]+=16; c=1; } else c=0; - } - } - if (c==1) - Chipset.carry=TRUE; - else - Chipset.carry=FALSE; + 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; BYTE c = 0; - - if (Chipset.mode_dec) + BYTE cBase = Chipset.mode_dec ? 10 : 16; + + for (i=0; i= cBase) { - a[i] = (BYTE)(b[i]-(a[i]+c)); - if (a[i]>=10) { a[i]+=10; c=1; } else c=0; + a[i] += cBase; + c = 1; } + else + c = 0; } - else - { - for (i=0; i=16) { a[i]+=16; c=1; } else c=0; - } - } - if (c==1) - Chipset.carry=TRUE; - else - Chipset.carry=FALSE; + Chipset.carry = (c==1); } +// 25.03.98 cg, end of new implementation static __inline void Nand(BYTE *a, BYTE *b, UINT s) { @@ -265,41 +247,34 @@ 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) { - if (Chipset.mode_dec) - while (s--) (BYTE)(a[s]=9-a[s]); - else - while (s--) (BYTE)(a[s]=15-a[s]); + BYTE cBase = Chipset.mode_dec ? 9 : 15; + + 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; - - for (i=0; i +#include #include #include #include diff --git a/sources/Emu48/RESOURCE.H b/sources/Emu48/RESOURCE.H new file mode 100644 index 0000000..e5f7d4a --- /dev/null +++ b/sources/Emu48/RESOURCE.H @@ -0,0 +1,80 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Emu48.rc +// +#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 IDC_PORT1WR 1000 +#define IDC_AUTOSAVE 1001 +#define IDC_AUTOSAVEONEXIT 1002 +#define IDC_EMU48DIR 1003 +#define IDC_KMLSCRIPT 1004 +#define IDC_AUTHOR 1005 +#define IDC_TITLE 1006 +#define IDC_KMLLOG 1007 +#define IDC_VERSION 1008 +#define IDC_PORT2ISSHARED 1009 +#define IDC_PORT2 1010 +#define IDC_ALWAYSDISPLOG 1011 +#define IDC_NAME 1012 +#define IDC_REGTEXT 1013 +#define IDC_CODE 1014 +#define IDC_REGISTER 1015 +#define IDC_UPDATE 1016 +#define IDC_LICENSE 1017 +#define IDC_REALSPEED 1018 +#define IDC_PORT1EN 1019 +#define IDC_WIRE 1020 +#define IDC_IR 1021 +#define IDC_DISASM_WIN 1022 +#define IDC_DISASM_MAP 1023 +#define IDC_DISASM_ROM 1024 +#define IDC_DISASM_RAM 1025 +#define IDC_DISASM_PORT1 1026 +#define IDC_DISASM_PORT2 1027 +#define IDC_DISASM_MODULE 1028 +#define IDC_DISASM_HP 1029 +#define IDC_DISASM_CLASS 1030 +#define IDC_DISASM_MNEMONICS 1031 +#define IDC_ADDRESS 1032 +#define IDC_DISASM_ADR 1033 +#define IDC_DISASM_NEXT 1034 +#define IDC_DISASM_COPY 1035 +#define ID_FILE_NEW 40001 +#define ID_FILE_OPEN 40002 +#define ID_FILE_SAVE 40003 +#define ID_FILE_SAVEAS 40004 +#define ID_FILE_EXIT 40005 +#define ID_VIEW_COPY 40006 +#define ID_VIEW_SETTINGS 40007 +#define ID_VIEW_RESET 40008 +#define ID_OBJECT_LOAD 40009 +#define ID_OBJECT_SAVE 40010 +#define ID_ABOUT 40011 +#define ID_FILE_CLOSE 40013 +#define ID_BACKUP_SAVE 40014 +#define ID_BACKUP_RESTORE 40015 +#define ID_BACKUP_DELETE 40016 +#define ID_VIEW_SCRIPT 40017 +#define ID_STACK_COPY 40019 +#define ID_STACK_PASTE 40020 +#define ID_TOOL_DISASM 40021 + +// 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_SYMED_VALUE 108 +#endif +#endif diff --git a/Emu48/rpl.c b/sources/Emu48/RPL.C similarity index 76% rename from Emu48/rpl.c rename to sources/Emu48/RPL.C index 299fc0c..0f42608 100644 --- a/Emu48/rpl.c +++ b/sources/Emu48/RPL.C @@ -9,7 +9,6 @@ #include "pch.h" #include "Emu48.h" - //| SX | GX | Name //#7056A #806E9 =TEMPOB //#7056F #806EE =TEMPTOP @@ -161,29 +160,31 @@ DWORD RPL_CreateTemp(DWORD l) l += 6; a = Read5(TEMPTOP); - b = Read5(RSKTOP); // start of available mem - c = Read5(DSKTOP); // end of available mem - if ((b+l)>c) return 0; // check if there is enough memory - Write5(TEMPTOP, a+l); // adjust end of temporary objects - Write5(RSKTOP, b+l); // adjust start of available mem - Write5(AVMEM, (c-(b+l))/5); // free memory (*5 nibbles) + b = Read5(RSKTOP); // start of available mem + c = Read5(DSKTOP); // end of available mem + if ((b+l)>c) return 0; // check if there is enough memory + Write5(TEMPTOP, a+l); // adjust end of temporary objects + Write5(RSKTOP, b+l); // adjust start of available mem + Write5(AVMEM, (c-(b+l))/5); // free memory (*5 nibbles) p = (BYTE*)LocalAlloc(0,b-a); Npeek(p,a,b-a); Nwrite(p,a+l,b-a); LocalFree(p); - Write5(a+l-5,l); // set temporary object length field - return (a+1); // return temporary object address + Write5(a+l-5,l); // set temporary object length field + return (a+1); // return temporary object address } DWORD RPL_Pick(UINT l) { DWORD stkp; - + + _ASSERT(l > 0); // 12.11.98 cg, new, 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 VOID RPL_Replace(DWORD n) { DWORD stkp; @@ -192,18 +193,19 @@ VOID RPL_Replace(DWORD n) Write5(stkp,n); return; } +#endif VOID RPL_Push(DWORD n) { DWORD stkp, avmem; - avmem = Read5(AVMEM); - if (avmem==0) return; - avmem--; - Write5(AVMEM,avmem); - stkp = Read5(DSKTOP); - stkp-=5; - Write5(stkp,n); - Write5(DSKTOP,stkp); + avmem = Read5(AVMEM); // amount of free memory + if (avmem==0) return; // no memory free + avmem--; // fetch memory + Write5(AVMEM,avmem); // save new amount of free memory + stkp = Read5(DSKTOP); // get pointer to stack level 1 + stkp-=5; // fetch new stack entry + Write5(stkp,n); // save pointer to new object on stack level 1 + Write5(DSKTOP,stkp); // save new pointer to stack level 1 return; } diff --git a/sources/Emu48/SERIAL.C b/sources/Emu48/SERIAL.C new file mode 100644 index 0000000..2155cf7 --- /dev/null +++ b/sources/Emu48/SERIAL.C @@ -0,0 +1,231 @@ +/* + * Serial.c + * + * This file is part of Emu48 + * + * Copyright (C) 1998 Christoph Gießelink + * + */ +#include "pch.h" +#include "Emu48.h" +#include "Serial.h" + +#define INTERRUPT ((void)(Chipset.SoftInt=TRUE,bInterrupt=TRUE)) + +static OVERLAPPED os = { 0 }; +static HANDLE hComm = NULL; +static HANDLE hCThread = NULL; +static DWORD lSerialThreadId = 0; +static BOOL bReading = TRUE; +static WORD wPort = PORT_CLOSE; + +static CRITICAL_SECTION csRecv; // 01.06.98 cg, new, critical section for receive byte + +static DWORD WINAPI SerialThread(LPVOID pParam) +{ + DWORD dwEvent; + SetCommMask(hComm,EV_RXCHAR); // event on RX + while (bReading) + { + _ASSERT(hComm != NULL); + WaitCommEvent(hComm,&dwEvent,NULL); // wait for serial event + if (dwEvent & EV_RXCHAR) // signal char received + { + CommReceive(); // get data + // interrupt request and emulation thread down + if (Chipset.SoftInt && Chipset.Shutdn) + ResumeThread(hThread); // wake up emulation thread + } + } + lSerialThreadId = 0; // signal serial thread is down + return 0; + UNREFERENCED_PARAMETER(pParam); +} + + +WORD CommConnect(VOID) +{ + return wPort; +} + +VOID CommOpen(LPSTR strWirePort,LPSTR strIrPort) +{ + COMMTIMEOUTS CommTimeouts = { MAXDWORD, 0L, 0L, 0L, 0L }; + + LPSTR strPort = (Chipset.IORam[IR_CTRL] & EIRU) ? strIrPort : strWirePort; + + if (hComm != NULL) // port already open + CloseHandle(hComm); + + if (strcmp(strPort,NO_SERIAL)) // port defined + { + hComm = CreateFile(strPort, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL); + + if(hComm != INVALID_HANDLE_VALUE) + { + // 01.06.98 cg, bugfix, initialize critical section + InitializeCriticalSection(&csRecv); + + wPort = (Chipset.IORam[IR_CTRL] & EIRU) ? PORT_IR : PORT_WIRE; + SetCommTimeouts(hComm,&CommTimeouts); + CommSetBaud(); + + // set event RXD handler + bReading = TRUE; + hCThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&SerialThread,NULL,0,&lSerialThreadId); + _ASSERT(lSerialThreadId); + } + else + hComm = NULL; + } + + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"COM port %s.\n",hComm ? "opened": "open error"); + OutputDebugString(buffer); + } + #endif +} + +VOID CommClose(VOID) +{ + if (hComm != NULL) // port open + { + bReading = FALSE; // kill read thread + SetCommMask(hComm,0L); // clear all events and force WaitCommEvent to return + while (lSerialThreadId != 0) Sleep(0); // wait for termination + CloseHandle(hComm); // close port + hComm = NULL; + #if defined DEBUG_SERIAL + OutputDebugString("COM port closed.\n"); + #endif + DeleteCriticalSection(&csRecv); // 01.06.98 cg, bugfix, release critical section + wPort = PORT_CLOSE; + } +} + +VOID CommSetBaud(VOID) +{ + if (hComm != NULL) + { + const DWORD dwBaudrates[] = { 1200, 1920, 2400, 3840, 4800, 7680, 9600, 15360 }; + + DCB dcb; + + FillMemory(&dcb,sizeof(dcb),0); + dcb.DCBlength = sizeof(dcb); + dcb.BaudRate = dwBaudrates[Chipset.IORam[BAUD] & 0x7]; + dcb.fBinary = TRUE; + dcb.fParity = TRUE; + dcb.fOutxCtsFlow = FALSE; + dcb.fOutxDsrFlow = FALSE; + dcb.fDtrControl = DTR_CONTROL_DISABLE; + dcb.fDsrSensitivity = FALSE; + dcb.fOutX = FALSE; + dcb.fErrorChar = FALSE; + dcb.fNull = FALSE; + dcb.fRtsControl = RTS_CONTROL_DISABLE; + dcb.fAbortOnError = FALSE; // may changed in further implementations + dcb.ByteSize = 8; + dcb.Parity = NOPARITY; // no parity check, emulated by software + dcb.StopBits = ONESTOPBIT; + + #if defined DEBUG_SERIAL + { + char buffer[256]; + wsprintf(buffer,"CommsetBaud: %ld\n",dcb.BaudRate); + OutputDebugString(buffer); + } + #endif + + SetCommState(hComm,&dcb); + } +} + +VOID CommTransmit(VOID) +{ + DWORD dwWritten; + + BYTE tbr = (Chipset.IORam[TBR_MSB] << 4) | Chipset.IORam[TBR_LSB]; + + #if defined DEBUG_SERIAL + { + char buffer[256]; + if (isprint(tbr)) + wsprintf(buffer,"-> '%c'\n",tbr); + else + wsprintf(buffer,"-> %02X\n",tbr); + OutputDebugString(buffer); + } + #endif + + if (hComm != NULL) // wire 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 + INTERRUPT; +} + +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 + { + dwBytesRead = 0L; // no bytes received + return; + } + + EnterCriticalSection(&csRecv); // 01.06.98 cg, bugfix, synchronize + do + { + if (Chipset.IORam[RCS] & RBF) // receive buffer full + break; + + if (dwBytesRead == 0L) // buffer empty + { + if(ReadFile(hComm,&cBuffer,sizeof(cBuffer),&dwBytesRead,&os) == FALSE) + dwBytesRead = 0L; + else // bytes received + nRp = 0; // reset read pointer + } + + if(dwBytesRead == 0L) // receive buffer empty + break; + + #if defined DEBUG_SERIAL + { + char buffer[256]; + if (isprint(cBuffer[nRp])) + wsprintf(buffer,"<- '%c'\n",cBuffer[nRp]); + else + wsprintf(buffer,"<- %02X\n",cBuffer[nRp]); + OutputDebugString(buffer); + } + #endif + + Chipset.IORam[RBR_MSB] = (cBuffer[nRp] >> 4); + Chipset.IORam[RBR_LSB] = (cBuffer[nRp] & 0x0f); + ++nRp; + --dwBytesRead; + + Chipset.IORam[RCS] |= RBF; // receive buffer full + if (Chipset.IORam[IO_CTRL] & ERBF) // interrupt on recv buffer full + INTERRUPT; + } + while(0); + LeaveCriticalSection(&csRecv); // 01.06.98 cg +} diff --git a/sources/Emu48/SERIAL.H b/sources/Emu48/SERIAL.H new file mode 100644 index 0000000..5fd63e2 --- /dev/null +++ b/sources/Emu48/SERIAL.H @@ -0,0 +1,44 @@ +/* + * 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/TIMER.C b/sources/Emu48/TIMER.C new file mode 100644 index 0000000..540983c --- /dev/null +++ b/sources/Emu48/TIMER.C @@ -0,0 +1,403 @@ +/* + * timer.c + * + * This file is part of Emu48 + * + * Copyright (C) 1995 Sebastien Carlier + * + */ +#include "pch.h" +#include "Emu48.h" + +#define AUTO_OFF 10 // 25.02.98 cg, new, Time in minutes for 'auto off' + +// 25.02.98 cg, new, Ticks for 01.01.1970 00:00:00 +#define UNIX_0_TIME 0x0001cf2e8f800000 + +// 25.02.98 cg, new, 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 +#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 + +static BOOL bStarted = FALSE; +static BOOL bOutRange = FALSE; // 21.04.98 cg, new, 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 __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 +{ + SYSTEMTIME ts; + LONGLONG ticks, time; + DWORD dw; + WORD crc, i; + BYTE p[4]; + + _ASSERT(sizeof(LONGLONG) == 8); // check size of datatype + + GetLocalTime(&ts); // local time, _ftime() cause memory/resource leaks + + // calculate days until 01.01.1970 + dw = (DWORD) ts.wMonth; + if (dw > 2) + dw -= 3L; + else + { + dw += 9L; + --ts.wYear; + } + dw = (DWORD) ts.wDay + (153L * dw + 2L) / 5L; + dw += (146097L * (((DWORD) ts.wYear) / 100L)) / 4L; + dw += (1461L * (((DWORD) ts.wYear) % 100L)) / 4L; + dw -= 719469L; + + // convert into seconds and add time + dw = dw * 24L + (DWORD) ts.wHour; + dw = dw * 60L + (DWORD) ts.wMinute; + dw = dw * 60L + (DWORD) ts.wSecond; + + // create timerticks = (s + ms) * 8192 + ticks = ((LONGLONG) dw << 13) | (((LONGLONG) ts.wMilliseconds << 10) / 125); + + ticks += UNIX_0_TIME; // add offset ticks from year 0 + ticks += (LONG) Chipset.t2; // add actual timer2 value + + 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 + + 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 + ticks >>= 4; + } + + Nunpack(p,crc,4); // write crc + memcpy(Chipset.Port0+dw,p,4); // 30.09.98, bugfix, 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 + Chipset.Port0[dw] = (BYTE) time & 0xf; + time >>= 4; + } + + Chipset.Port0[dw] = 0xf; // 30.09.98, bugfix, 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 + return; // -> quit + 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" + bAccurateTimer = (timeBeginPeriod(1) == TIMERR_NOERROR); + // } + timeGetDevCaps(&tc,sizeof(tc)); // 21.04.98 cg, 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 + RescheduleT2(TRUE); // start timer2 + } + return; +} + +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 + 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 + { + Chipset.t2 = CalcT2(); // 21.04.98 cg, update chipset timer2 value + // AbortT2(); // 02.12.98 cg, removed, stop timer2 later + } + LeaveCriticalSection(&csT2Lock); // 21.04.98 cg + AbortT2(); // 02.12.98 cg, bugfix, stop timer2 here + } + bStarted = FALSE; + if (bAccurateTimer) // "Accurate timer" running + { + timeEndPeriod(1); // finish service + } + return; +} + +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 + dwT2 = bStarted ? CalcT2() : Chipset.t2; + CheckT2(dwT2); // 25.11.98 cg, new, update timer2 control bits + } + LeaveCriticalSection(&csT2Lock); + return dwT2; +} + +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 + 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 + if (bStarted) // timer running + RescheduleT2(TRUE); // restart timer2 + } + LeaveCriticalSection(&csT2Lock); + return; +} + +BYTE ReadT1(VOID) +{ + BYTE nT1; + EnterCriticalSection(&csT1Lock); // 21.04.98 cg, bugfix, synchronize + { + nT1 = Chipset.t1; // read timer1 value + CheckT1(nT1); // 25.11.98 cg, new, update timer1 control bits + } + LeaveCriticalSection(&csT1Lock); // 21.04.98 cg + 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 + { + Chipset.t1 = byValue&0xF; // set new timer1 value + CheckT1(Chipset.t1); // 25.11.98 cg, readded, 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 + uT1TimerId = timeSetEvent(T1_FREQ,0,(LPTIMECALLBACK)&TimeProc,1,TIME_PERIODIC); + _ASSERT(uT1TimerId); // 11.06.98 cg, new, test if timer1 started + return; +} diff --git a/sources/Emu48/TYPES.H b/sources/Emu48/TYPES.H new file mode 100644 index 0000000..200e85f --- /dev/null +++ b/sources/Emu48/TYPES.H @@ -0,0 +1,92 @@ +/* + * types.h + * + * This file is part of Emu48 + * + * Copyright (C) 1995 Sebastien Carlier + * + */ + +#define CHIPSET Chipset_t +typedef struct +{ + WORD wPosX; + WORD wPosY; + 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 + LPBYTE Port0; + LPBYTE Port1; + LPBYTE Port2; + + DWORD pc; + DWORD d0; + DWORD d1; + DWORD rstkp; + DWORD rstk[8]; + BYTE A[16]; + BYTE B[16]; + BYTE C[16]; + BYTE D[16]; + BYTE R0[16]; + BYTE R1[16]; + BYTE R2[16]; + BYTE R3[16]; + BYTE R4[16]; + BYTE ST[4]; + BYTE HST; + BYTE P; + WORD out; + WORD in; + BOOL SoftInt; + BOOL Shutdn; + BOOL mode_dec; + BOOL inte; // interrupt status flag (FALSE = int in service) + BOOL intk; // 1 ms keyboard scan flag (TRUE = enable) + BOOL intd; // keyboard interrupt pending (TRUE = int pending) + 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 + BYTE cards_status; + BYTE IORam[64]; // I/O hardware register + UINT IOBase; // address of I/O modules page + BOOL IOCfig; // I/O module configuration flag + BYTE P0Base, BSBase, P1Base, P2Base; // address of modules first 2KB page + BYTE P0Size, BSSize, P1Size, P2Size; // mapped size of module in 2KB + BYTE P0End, BSEnd, P1End, P2End; // address of modules last 2KB page + BOOL P0Cfig, BSCfig, P1Cfig, P2Cfig; // module address configuration flag + BOOL P0Cfg2, BSCfg2, P1Cfg2, P2Cfg2; // module size configuration flag + + BYTE t1; + DWORD t2; +// DWORD t2_ticks; // 03.03.98 cg, removed, not used + + DWORD cycles; // 03.03.98 cg, new, oscillator cycles + + BYTE Keyboard_Row[9]; + WORD IR15X; + UINT Keyboard_State; // 30.05.98 cg, not used + + signed short loffset; + signed int width; + UINT boffset; + UINT lcounter; + UINT sync; // 24.08.98 cg, not used + BYTE contrast; + BOOL dispon; + DWORD start1; + DWORD start12; + DWORD end1; + DWORD start2, end2; +} Chipset_t; diff --git a/MkShared/Main.c b/sources/MkShared/Main.c similarity index 100% rename from MkShared/Main.c rename to sources/MkShared/Main.c diff --git a/MkShared/MkShared.mak b/sources/MkShared/MkShared.mak similarity index 100% rename from MkShared/MkShared.mak rename to sources/MkShared/MkShared.mak diff --git a/MkShared/MkShared.mdp b/sources/MkShared/MkShared.mdp similarity index 100% rename from MkShared/MkShared.mdp rename to sources/MkShared/MkShared.mdp