Add the non functional and the very first version of Emu48 for Android!
11
.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches/build_file_checksums.ser
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
1
app/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
46
app/CMakeLists.txt
Normal file
|
@ -0,0 +1,46 @@
|
|||
# For more information about using CMake with Android Studio, read the
|
||||
# documentation: https://d.android.com/studio/projects/add-native-code.html
|
||||
|
||||
# Sets the minimum version of CMake required to build the native library.
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
|
||||
# Creates and names a library, sets it as either STATIC
|
||||
# or SHARED, and provides the relative paths to its source code.
|
||||
# You can define multiple libraries, and CMake builds them for you.
|
||||
# Gradle automatically packages shared libraries with your APK.
|
||||
|
||||
add_library( # Sets the name of the library.
|
||||
native-lib
|
||||
|
||||
# Sets the library as a shared library.
|
||||
SHARED
|
||||
|
||||
# Provides a relative path to your source file(s).
|
||||
#src/main/cpp/native-lib.cpp
|
||||
src/main/cpp/emu48-jni.c
|
||||
)
|
||||
|
||||
# Searches for a specified prebuilt library and stores the path as a
|
||||
# variable. Because CMake includes system libraries in the search path by
|
||||
# default, you only need to specify the name of the public NDK library
|
||||
# you want to add. CMake verifies that the library exists before
|
||||
# completing its build.
|
||||
|
||||
find_library( # Sets the name of the path variable.
|
||||
log-lib
|
||||
|
||||
# Specifies the name of the NDK library that
|
||||
# you want CMake to locate.
|
||||
log)
|
||||
|
||||
# Specifies libraries CMake should link to your target library. You
|
||||
# can link multiple libraries, such as libraries you define in this
|
||||
# build script, prebuilt third-party libraries, or system libraries.
|
||||
|
||||
target_link_libraries( # Specifies the target library.
|
||||
native-lib
|
||||
|
||||
# Links the target library to the log library
|
||||
# included in the NDK.
|
||||
${log-lib})
|
39
app/build.gradle
Normal file
|
@ -0,0 +1,39 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
applicationId "com.regis.cosnier.emu48"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
cppFlags ""
|
||||
}
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||
implementation 'com.android.support:design:28.0.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
}
|
21
app/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,26 @@
|
|||
package com.regis.cosnier.emu48;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.regis.cosnier.emu48", appContext.getPackageName());
|
||||
}
|
||||
}
|
24
app/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.regis.cosnier.emu48">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
2
app/src/main/assets/calculators/BEEP.48
Normal file
|
@ -0,0 +1,2 @@
|
|||
;01477:6300; disable 10 min auto off (internal, undocumented)
|
||||
017A6:81B1; =makebeep
|
BIN
app/src/main/assets/calculators/REAL48GX.BMP
Normal file
After Width: | Height: | Size: 476 KiB |
BIN
app/src/main/assets/calculators/REAL48SX.BMP
Normal file
After Width: | Height: | Size: 476 KiB |
BIN
app/src/main/assets/calculators/ROM.48G
Normal file
BIN
app/src/main/assets/calculators/ROM.48S
Normal file
935
app/src/main/assets/calculators/real48gx.kml
Normal file
|
@ -0,0 +1,935 @@
|
|||
Global
|
||||
Print "=========================================================="
|
||||
Print ""
|
||||
Print "This Real 48GX graphic is by Eric Rechlin."
|
||||
Print "eric@hpcalc.org http://www.hpcalc.org"
|
||||
Print "Graphic based on a scan by Hewlett-Packard."
|
||||
Print ""
|
||||
Print "Note that contrast support, a touch-sensitive"
|
||||
Print "screen, and hidden NXT and PREV buttons to the"
|
||||
Print "right and left of the menu are implemented."
|
||||
Print ""
|
||||
Print "=========================================================="
|
||||
Title "Eric's Real 48GX for 800x600"
|
||||
Author "Eric Rechlin"
|
||||
Model "G"
|
||||
Rom "ROM.48G"
|
||||
Patch "BEEP.48"
|
||||
Bitmap "REAL48GX.BMP"
|
||||
Debug 0
|
||||
End
|
||||
|
||||
Background
|
||||
Offset 0 0
|
||||
Size 300 531
|
||||
End
|
||||
|
||||
Lcd
|
||||
Zoom 2
|
||||
Offset 19 24
|
||||
Color 0 112 157 114
|
||||
Color 1 112 157 114
|
||||
Color 2 104 145 106
|
||||
Color 3 94 131 95
|
||||
Color 4 85 119 86
|
||||
Color 5 76 106 77
|
||||
Color 6 66 92 67
|
||||
Color 8 57 79 58
|
||||
Color 9 48 67 49
|
||||
Color 10 38 53 38
|
||||
Color 11 29 40 29
|
||||
Color 12 20 28 20
|
||||
Color 13 10 13 10
|
||||
|
||||
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
|
||||
|
||||
Color 47 112 157 114
|
||||
Color 48 104 145 106
|
||||
Color 49 94 131 95
|
||||
Color 50 85 119 86
|
||||
Color 51 76 106 77
|
||||
Color 52 66 92 67
|
||||
Color 53 57 79 58
|
||||
Color 54 48 67 49
|
||||
Color 55 38 53 38
|
||||
Color 56 29 40 29
|
||||
Color 57 20 28 20
|
||||
Color 58 10 13 10
|
||||
Color 59 0 0 0
|
||||
Color 60 0 0 0
|
||||
Color 61 0 0 0
|
||||
Color 62 0 0 0
|
||||
Color 63 0 0 0
|
||||
End
|
||||
|
||||
Annunciator 1
|
||||
Size 16 11
|
||||
Offset 32 11
|
||||
Down 0 531
|
||||
End
|
||||
|
||||
Annunciator 2
|
||||
Size 16 11
|
||||
Offset 75 11
|
||||
Down 16 531
|
||||
End
|
||||
|
||||
Annunciator 3
|
||||
Size 16 11
|
||||
Offset 121 11
|
||||
Down 32 531
|
||||
End
|
||||
|
||||
Annunciator 4
|
||||
Size 16 11
|
||||
Offset 163 11
|
||||
Down 48 531
|
||||
End
|
||||
|
||||
Annunciator 5
|
||||
Size 16 11
|
||||
Offset 207 11
|
||||
Down 64 531
|
||||
End
|
||||
|
||||
Annunciator 6
|
||||
Size 16 11
|
||||
Offset 253 11
|
||||
Down 80 531
|
||||
End
|
||||
|
||||
Button 11
|
||||
Type 5
|
||||
Size 38 26
|
||||
Offset 10 168
|
||||
OutIn 1 16
|
||||
End
|
||||
|
||||
Button 12
|
||||
Type 5
|
||||
Size 38 26
|
||||
Offset 59 168
|
||||
OutIn 8 16
|
||||
End
|
||||
|
||||
Button 13
|
||||
Type 5
|
||||
Size 38 26
|
||||
Offset 107 168
|
||||
OutIn 8 8
|
||||
End
|
||||
|
||||
Button 14
|
||||
Type 5
|
||||
Size 38 26
|
||||
Offset 156 168
|
||||
OutIn 8 4
|
||||
End
|
||||
|
||||
Button 15
|
||||
Type 5
|
||||
Size 38 26
|
||||
Offset 204 168
|
||||
OutIn 8 2
|
||||
End
|
||||
|
||||
Button 16
|
||||
Type 5
|
||||
Size 38 26
|
||||
Offset 252 168
|
||||
OutIn 8 1
|
||||
End
|
||||
|
||||
Button 21
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 10 205
|
||||
OutIn 2 16
|
||||
End
|
||||
|
||||
Button 22
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 59 205
|
||||
OutIn 7 16
|
||||
End
|
||||
|
||||
Button 23
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 107 205
|
||||
OutIn 7 8
|
||||
End
|
||||
|
||||
Button 24
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 156 205
|
||||
OutIn 7 4
|
||||
End
|
||||
|
||||
Button 25
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 204 205
|
||||
OutIn 7 2
|
||||
End
|
||||
|
||||
Button 26
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 252 205
|
||||
OutIn 7 1
|
||||
End
|
||||
|
||||
Button 31
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 10 245
|
||||
OutIn 0 16
|
||||
End
|
||||
|
||||
Button 32
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 59 245
|
||||
OutIn 6 16
|
||||
End
|
||||
|
||||
Button 33
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 107 245
|
||||
OutIn 6 8
|
||||
End
|
||||
|
||||
Button 34
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 156 245
|
||||
OutIn 6 4
|
||||
End
|
||||
|
||||
Button 35
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 204 245
|
||||
OutIn 6 2
|
||||
End
|
||||
|
||||
Button 36
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 252 245
|
||||
OutIn 6 1
|
||||
End
|
||||
|
||||
Button 41
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 10 287
|
||||
OutIn 3 16
|
||||
End
|
||||
|
||||
Button 42
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 59 287
|
||||
OutIn 5 16
|
||||
End
|
||||
|
||||
Button 43
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 107 287
|
||||
OutIn 5 8
|
||||
End
|
||||
|
||||
Button 44
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 156 287
|
||||
OutIn 5 4
|
||||
End
|
||||
|
||||
Button 45
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 204 287
|
||||
OutIn 5 2
|
||||
End
|
||||
|
||||
Button 46
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 252 287
|
||||
OutIn 5 1
|
||||
End
|
||||
|
||||
Button 51
|
||||
Type 5
|
||||
Size 87 30
|
||||
Offset 10 327
|
||||
OutIn 4 16
|
||||
End
|
||||
|
||||
Button 52
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 107 327
|
||||
OutIn 4 8
|
||||
End
|
||||
|
||||
Button 53
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 156 327
|
||||
OutIn 4 4
|
||||
End
|
||||
|
||||
Button 54
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 204 327
|
||||
OutIn 4 2
|
||||
End
|
||||
|
||||
Button 55
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 252 327
|
||||
OutIn 4 1
|
||||
End
|
||||
|
||||
Button 61
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 10 369
|
||||
OutIn 3 32
|
||||
End
|
||||
|
||||
Button 62
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 65 369
|
||||
OutIn 3 8
|
||||
End
|
||||
|
||||
Button 63
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 124 369
|
||||
OutIn 3 4
|
||||
End
|
||||
|
||||
Button 64
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 183 369
|
||||
OutIn 3 2
|
||||
End
|
||||
|
||||
Button 65
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 243 369
|
||||
OutIn 3 1
|
||||
End
|
||||
|
||||
Button 71
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 10 411
|
||||
OutIn 2 32
|
||||
End
|
||||
|
||||
Button 72
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 65 411
|
||||
OutIn 2 8
|
||||
End
|
||||
|
||||
Button 73
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 124 411
|
||||
OutIn 2 4
|
||||
End
|
||||
|
||||
Button 74
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 183 411
|
||||
OutIn 2 2
|
||||
End
|
||||
|
||||
Button 75
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 243 411
|
||||
OutIn 2 1
|
||||
End
|
||||
|
||||
Button 81
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 10 453
|
||||
OutIn 1 32
|
||||
End
|
||||
|
||||
Button 82
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 65 453
|
||||
OutIn 1 8
|
||||
End
|
||||
|
||||
Button 83
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 124 453
|
||||
OutIn 1 4
|
||||
End
|
||||
|
||||
Button 84
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 183 453
|
||||
OutIn 1 2
|
||||
End
|
||||
|
||||
Button 85
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 243 453
|
||||
OutIn 1 1
|
||||
End
|
||||
|
||||
Button 91
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 10 494
|
||||
OutIn 0 32768
|
||||
End
|
||||
|
||||
Button 92
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 65 494
|
||||
OutIn 0 8
|
||||
End
|
||||
|
||||
Button 93
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 124 494
|
||||
OutIn 0 4
|
||||
End
|
||||
|
||||
Button 94
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 183 494
|
||||
OutIn 0 2
|
||||
End
|
||||
|
||||
Button 95
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 243 494
|
||||
OutIn 0 1
|
||||
End
|
||||
|
||||
Button 101
|
||||
Type 3
|
||||
Size 42 14
|
||||
Offset 19 138
|
||||
Virtual
|
||||
OnDown
|
||||
Press 11
|
||||
End
|
||||
OnUp
|
||||
Release 11
|
||||
End
|
||||
End
|
||||
|
||||
Button 102
|
||||
Type 3
|
||||
Size 42 14
|
||||
Offset 63 138
|
||||
Virtual
|
||||
OnDown
|
||||
Press 12
|
||||
End
|
||||
OnUp
|
||||
Release 12
|
||||
End
|
||||
End
|
||||
|
||||
Button 103
|
||||
Type 3
|
||||
Size 42 14
|
||||
Offset 107 138
|
||||
Virtual
|
||||
OnDown
|
||||
Press 13
|
||||
End
|
||||
OnUp
|
||||
Release 13
|
||||
End
|
||||
End
|
||||
|
||||
Button 104
|
||||
Type 3
|
||||
Size 42 14
|
||||
Offset 151 138
|
||||
Virtual
|
||||
OnDown
|
||||
Press 14
|
||||
End
|
||||
OnUp
|
||||
Release 14
|
||||
End
|
||||
End
|
||||
|
||||
Button 105
|
||||
Type 3
|
||||
Size 42 14
|
||||
Offset 195 138
|
||||
Virtual
|
||||
OnDown
|
||||
Press 15
|
||||
End
|
||||
OnUp
|
||||
Release 15
|
||||
End
|
||||
End
|
||||
|
||||
Button 106
|
||||
Type 3
|
||||
Size 42 14
|
||||
Offset 239 138
|
||||
Virtual
|
||||
OnDown
|
||||
Press 16
|
||||
End
|
||||
OnUp
|
||||
Release 16
|
||||
End
|
||||
End
|
||||
|
||||
Button 107
|
||||
Type 5
|
||||
Size 16 16
|
||||
Offset 0 137
|
||||
Virtual
|
||||
OnDown
|
||||
Press 71
|
||||
Press 26
|
||||
End
|
||||
OnUp
|
||||
Release 26
|
||||
Release 71
|
||||
End
|
||||
End
|
||||
|
||||
Button 108
|
||||
Type 5
|
||||
Size 16 16
|
||||
Offset 284 137
|
||||
Virtual
|
||||
OnDown
|
||||
Press 26
|
||||
End
|
||||
OnUp
|
||||
Release 26
|
||||
End
|
||||
End
|
||||
|
||||
Button 109
|
||||
Type 4
|
||||
Size 262 112
|
||||
Offset 19 24
|
||||
Down 19 24
|
||||
NoHold
|
||||
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 45
|
||||
Map 45 71
|
||||
End
|
||||
|
||||
Scancode 46
|
||||
Map 46 81
|
||||
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
|
||||
|
932
app/src/main/assets/calculators/real48sx.kml
Normal file
|
@ -0,0 +1,932 @@
|
|||
Global
|
||||
Print "=========================================================="
|
||||
Print ""
|
||||
Print "This Real 48SX graphic is by Eric Rechlin."
|
||||
Print "eric@hpcalc.org http://www.hpcalc.org"
|
||||
Print "Graphic based on a scan by Hewlett-Packard."
|
||||
Print ""
|
||||
Print "Note that contrast support, a touch-sensitive"
|
||||
Print "screen, and hidden NXT and PREV buttons to the"
|
||||
Print "right and left of the menu are implemented."
|
||||
Print ""
|
||||
Print "=========================================================="
|
||||
Title "Eric's Real 48SX for 800x600"
|
||||
Author "Eric Rechlin"
|
||||
Model "S"
|
||||
Rom "ROM.48S"
|
||||
Patch "BEEP.48"
|
||||
Bitmap "REAL48SX.BMP"
|
||||
Debug 0
|
||||
End
|
||||
|
||||
Background
|
||||
Offset 0 0
|
||||
Size 300 531
|
||||
End
|
||||
|
||||
Lcd
|
||||
Zoom 2
|
||||
Offset 19 24
|
||||
Color 0 112 157 114
|
||||
Color 1 76 106 77
|
||||
Color 2 66 92 67
|
||||
Color 3 57 79 58
|
||||
Color 4 48 67 49
|
||||
Color 5 38 53 38
|
||||
Color 6 29 40 29
|
||||
Color 7 20 28 20
|
||||
Color 8 10 13 10
|
||||
|
||||
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 43 112 157 114
|
||||
Color 44 104 145 106
|
||||
Color 45 94 131 95
|
||||
Color 46 85 119 86
|
||||
Color 47 76 106 77
|
||||
Color 48 66 92 67
|
||||
Color 49 57 79 58
|
||||
Color 50 48 67 49
|
||||
Color 51 38 53 38
|
||||
Color 52 29 40 29
|
||||
Color 53 20 28 20
|
||||
Color 54 10 13 10
|
||||
Color 55 0 0 0
|
||||
Color 56 0 0 0
|
||||
Color 57 0 0 0
|
||||
Color 58 0 0 0
|
||||
Color 59 0 0 0
|
||||
Color 60 0 0 0
|
||||
End
|
||||
|
||||
Annunciator 1
|
||||
Size 16 11
|
||||
Offset 32 11
|
||||
Down 0 531
|
||||
End
|
||||
|
||||
Annunciator 2
|
||||
Size 16 11
|
||||
Offset 75 11
|
||||
Down 16 531
|
||||
End
|
||||
|
||||
Annunciator 3
|
||||
Size 16 11
|
||||
Offset 121 11
|
||||
Down 32 531
|
||||
End
|
||||
|
||||
Annunciator 4
|
||||
Size 16 11
|
||||
Offset 163 11
|
||||
Down 48 531
|
||||
End
|
||||
|
||||
Annunciator 5
|
||||
Size 16 11
|
||||
Offset 207 11
|
||||
Down 64 531
|
||||
End
|
||||
|
||||
Annunciator 6
|
||||
Size 16 11
|
||||
Offset 253 11
|
||||
Down 80 531
|
||||
End
|
||||
|
||||
Button 11
|
||||
Type 5
|
||||
Size 38 26
|
||||
Offset 11 167
|
||||
OutIn 1 16
|
||||
End
|
||||
|
||||
Button 12
|
||||
Type 5
|
||||
Size 38 26
|
||||
Offset 59 167
|
||||
OutIn 8 16
|
||||
End
|
||||
|
||||
Button 13
|
||||
Type 5
|
||||
Size 38 26
|
||||
Offset 107 167
|
||||
OutIn 8 8
|
||||
End
|
||||
|
||||
Button 14
|
||||
Type 5
|
||||
Size 38 26
|
||||
Offset 156 167
|
||||
OutIn 8 4
|
||||
End
|
||||
|
||||
Button 15
|
||||
Type 5
|
||||
Size 38 26
|
||||
Offset 204 167
|
||||
OutIn 8 2
|
||||
End
|
||||
|
||||
Button 16
|
||||
Type 5
|
||||
Size 38 26
|
||||
Offset 252 167
|
||||
OutIn 8 1
|
||||
End
|
||||
|
||||
Button 21
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 11 205
|
||||
OutIn 2 16
|
||||
End
|
||||
|
||||
Button 22
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 59 205
|
||||
OutIn 7 16
|
||||
End
|
||||
|
||||
Button 23
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 107 205
|
||||
OutIn 7 8
|
||||
End
|
||||
|
||||
Button 24
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 156 205
|
||||
OutIn 7 4
|
||||
End
|
||||
|
||||
Button 25
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 204 205
|
||||
OutIn 7 2
|
||||
End
|
||||
|
||||
Button 26
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 252 205
|
||||
OutIn 7 1
|
||||
End
|
||||
|
||||
Button 31
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 11 245
|
||||
OutIn 0 16
|
||||
End
|
||||
|
||||
Button 32
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 59 245
|
||||
OutIn 6 16
|
||||
End
|
||||
|
||||
Button 33
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 107 245
|
||||
OutIn 6 8
|
||||
End
|
||||
|
||||
Button 34
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 156 245
|
||||
OutIn 6 4
|
||||
End
|
||||
|
||||
Button 35
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 204 245
|
||||
OutIn 6 2
|
||||
End
|
||||
|
||||
Button 36
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 252 245
|
||||
OutIn 6 1
|
||||
End
|
||||
|
||||
Button 41
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 11 287
|
||||
OutIn 3 16
|
||||
End
|
||||
|
||||
Button 42
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 59 287
|
||||
OutIn 5 16
|
||||
End
|
||||
|
||||
Button 43
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 107 287
|
||||
OutIn 5 8
|
||||
End
|
||||
|
||||
Button 44
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 156 287
|
||||
OutIn 5 4
|
||||
End
|
||||
|
||||
Button 45
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 204 287
|
||||
OutIn 5 2
|
||||
End
|
||||
|
||||
Button 46
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 252 287
|
||||
OutIn 5 1
|
||||
End
|
||||
|
||||
Button 51
|
||||
Type 5
|
||||
Size 87 30
|
||||
Offset 11 327
|
||||
OutIn 4 16
|
||||
End
|
||||
|
||||
Button 52
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 107 327
|
||||
OutIn 4 8
|
||||
End
|
||||
|
||||
Button 53
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 156 327
|
||||
OutIn 4 4
|
||||
End
|
||||
|
||||
Button 54
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 204 327
|
||||
OutIn 4 2
|
||||
End
|
||||
|
||||
Button 55
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 252 327
|
||||
OutIn 4 1
|
||||
End
|
||||
|
||||
Button 61
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 11 369
|
||||
OutIn 3 32
|
||||
End
|
||||
|
||||
Button 62
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 65 369
|
||||
OutIn 3 8
|
||||
End
|
||||
|
||||
Button 63
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 124 369
|
||||
OutIn 3 4
|
||||
End
|
||||
|
||||
Button 64
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 183 369
|
||||
OutIn 3 2
|
||||
End
|
||||
|
||||
Button 65
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 243 369
|
||||
OutIn 3 1
|
||||
End
|
||||
|
||||
Button 71
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 11 410
|
||||
OutIn 2 32
|
||||
End
|
||||
|
||||
Button 72
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 65 410
|
||||
OutIn 2 8
|
||||
End
|
||||
|
||||
Button 73
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 124 410
|
||||
OutIn 2 4
|
||||
End
|
||||
|
||||
Button 74
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 183 410
|
||||
OutIn 2 2
|
||||
End
|
||||
|
||||
Button 75
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 243 410
|
||||
OutIn 2 1
|
||||
End
|
||||
|
||||
Button 81
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 11 453
|
||||
OutIn 1 32
|
||||
End
|
||||
|
||||
Button 82
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 65 453
|
||||
OutIn 1 8
|
||||
End
|
||||
|
||||
Button 83
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 124 453
|
||||
OutIn 1 4
|
||||
End
|
||||
|
||||
Button 84
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 183 453
|
||||
OutIn 1 2
|
||||
End
|
||||
|
||||
Button 85
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 243 453
|
||||
OutIn 1 1
|
||||
End
|
||||
|
||||
Button 91
|
||||
Type 5
|
||||
Size 38 30
|
||||
Offset 11 494
|
||||
OutIn 0 32768
|
||||
End
|
||||
|
||||
Button 92
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 65 494
|
||||
OutIn 0 8
|
||||
End
|
||||
|
||||
Button 93
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 124 494
|
||||
OutIn 0 4
|
||||
End
|
||||
|
||||
Button 94
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 183 494
|
||||
OutIn 0 2
|
||||
End
|
||||
|
||||
Button 95
|
||||
Type 5
|
||||
Size 48 28
|
||||
Offset 243 494
|
||||
OutIn 0 1
|
||||
End
|
||||
|
||||
Button 101
|
||||
Type 3
|
||||
Size 42 14
|
||||
Offset 19 138
|
||||
Virtual
|
||||
OnDown
|
||||
Press 11
|
||||
End
|
||||
OnUp
|
||||
Release 11
|
||||
End
|
||||
End
|
||||
|
||||
Button 102
|
||||
Type 3
|
||||
Size 42 14
|
||||
Offset 63 138
|
||||
Virtual
|
||||
OnDown
|
||||
Press 12
|
||||
End
|
||||
OnUp
|
||||
Release 12
|
||||
End
|
||||
End
|
||||
|
||||
Button 103
|
||||
Type 3
|
||||
Size 42 14
|
||||
Offset 107 138
|
||||
Virtual
|
||||
OnDown
|
||||
Press 13
|
||||
End
|
||||
OnUp
|
||||
Release 13
|
||||
End
|
||||
End
|
||||
|
||||
Button 104
|
||||
Type 3
|
||||
Size 42 14
|
||||
Offset 151 138
|
||||
Virtual
|
||||
OnDown
|
||||
Press 14
|
||||
End
|
||||
OnUp
|
||||
Release 14
|
||||
End
|
||||
End
|
||||
|
||||
Button 105
|
||||
Type 3
|
||||
Size 42 14
|
||||
Offset 195 138
|
||||
Virtual
|
||||
OnDown
|
||||
Press 15
|
||||
End
|
||||
OnUp
|
||||
Release 15
|
||||
End
|
||||
End
|
||||
|
||||
Button 106
|
||||
Type 3
|
||||
Size 42 14
|
||||
Offset 239 138
|
||||
Virtual
|
||||
OnDown
|
||||
Press 16
|
||||
End
|
||||
OnUp
|
||||
Release 16
|
||||
End
|
||||
End
|
||||
|
||||
Button 107
|
||||
Type 5
|
||||
Size 16 16
|
||||
Offset 0 137
|
||||
Virtual
|
||||
OnDown
|
||||
Press 71
|
||||
Press 26
|
||||
End
|
||||
OnUp
|
||||
Release 26
|
||||
Release 71
|
||||
End
|
||||
End
|
||||
|
||||
Button 108
|
||||
Type 5
|
||||
Size 16 16
|
||||
Offset 284 137
|
||||
Virtual
|
||||
OnDown
|
||||
Press 26
|
||||
End
|
||||
OnUp
|
||||
Release 26
|
||||
End
|
||||
End
|
||||
|
||||
Button 109
|
||||
Type 4
|
||||
Size 262 112
|
||||
Offset 19 24
|
||||
Down 19 24
|
||||
NoHold
|
||||
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 45
|
||||
Map 45 71
|
||||
End
|
||||
|
||||
Scancode 46
|
||||
Map 46 81
|
||||
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
|
||||
|
415
app/src/main/cpp/APPLE.C
Normal file
|
@ -0,0 +1,415 @@
|
|||
/*
|
||||
* apple.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2005 CdB for HP
|
||||
* Copyright (C) 2006 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "Opcodes.h"
|
||||
#include "apple.h"
|
||||
#include "io.h" // I/O register definitions
|
||||
#include "i28f160.h"
|
||||
|
||||
#define w Chipset
|
||||
|
||||
#define _KB(s) ((s) * 1024 * 2)
|
||||
|
||||
#pragma intrinsic(memset,memcpy)
|
||||
|
||||
#include "Ops.h"
|
||||
|
||||
//
|
||||
// ROM buffer access functions
|
||||
//
|
||||
|
||||
static __inline void WrDirtyPage(DWORD d)
|
||||
{
|
||||
if (pbyRomDirtyPage) // using dirty ROM page table
|
||||
{
|
||||
DWORD dwPage = d / ROMPAGESIZE; // this is the page
|
||||
|
||||
_ASSERT(dwPage < dwRomDirtyPageSize);
|
||||
pbyRomDirtyPage[dwPage] = TRUE; // page is dirty
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static __inline void EraseBlock(DWORD d,DWORD dwNibSize)
|
||||
{
|
||||
LPBYTE pbyAddr = pbyRom + d;
|
||||
|
||||
while (dwNibSize--)
|
||||
{
|
||||
WrDirtyPage(d++); // make page dirty
|
||||
*pbyAddr++ = 0x0F; // clear address
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static CONST LPBYTE ppReg[] = { w.A, w.B, w.C, w.D };
|
||||
|
||||
static QWORD DecodeReg64(LPBYTE R, BYTE byNF)
|
||||
{
|
||||
QWORD qwVal = Npack64(R,16); // generate 64bit number from register
|
||||
|
||||
switch (byNF) // field selector
|
||||
{
|
||||
case 0: return (qwVal >> (w.P*4)) & 0xf; // P
|
||||
case 1: return qwVal & ~((QWORD)~0 << ((w.P+1)*4));// WP
|
||||
case 2: return (qwVal >> 8) & 0xf; // XS
|
||||
case 3: return qwVal & 0xfff; // X
|
||||
case 4: return (qwVal >> 60) & 0xf; // S
|
||||
case 5: return (qwVal >> 12) & 0x0000ffffffffffff; // M
|
||||
case 6: return qwVal & 0xff; // B
|
||||
case 7: return qwVal; // W
|
||||
case 15: return qwVal & 0xfffff; // A
|
||||
// default: return qwVal & w.fld[byNF-8]; // F1-F7
|
||||
default: return qwVal;
|
||||
}
|
||||
}
|
||||
|
||||
static void EncodeReg64(QWORD v, LPBYTE R, BYTE byNF)
|
||||
{
|
||||
if (byNF > 7 && byNF < 15) // user mask area F1-F7
|
||||
{
|
||||
// QWORD qwMask = w.fld[byNF-8]; // F1-F7
|
||||
// QWORD qwVal = Npack64(R,16); // original content of register
|
||||
// v = (v & qwMask) | (qwVal & ~qwMask); // mask operation
|
||||
byNF = 7; // write W area
|
||||
}
|
||||
|
||||
Nunpack64(R+F_s[byNF], v, F_l[byNF]);
|
||||
return;
|
||||
}
|
||||
|
||||
static QWORD o80BReg164(LPBYTE I)
|
||||
{
|
||||
_ASSERT((I[5] & 3) < ARRAYSIZEOF(ppReg));
|
||||
return DecodeReg64(ppReg[I[5] & 3], I[6]);
|
||||
}
|
||||
|
||||
static QWORD o80BReg264(LPBYTE I)
|
||||
{
|
||||
_ASSERT((I[5] >> 2) < ARRAYSIZEOF(ppReg));
|
||||
return DecodeReg64(ppReg[I[5] >> 2], I[6]);
|
||||
}
|
||||
|
||||
static void o80BRegWrite(QWORD v, LPBYTE I)
|
||||
{
|
||||
_ASSERT((I[5] & 3) < ARRAYSIZEOF(ppReg));
|
||||
EncodeReg64(v, ppReg[I[5] & 3], I[6]);
|
||||
return;
|
||||
}
|
||||
|
||||
// SETFLDx
|
||||
VOID o80BF7x(LPBYTE I)
|
||||
{
|
||||
QWORD qwVal;
|
||||
|
||||
_ASSERT(FALSE); // not tested so far
|
||||
w.pc+=1; // skip x nibble
|
||||
qwVal = Npack64(w.C,16); // generate 64bit number from C register
|
||||
w.carry = (qwVal == 0) // set carry if field mask = 0
|
||||
|| (I[5] < 8) || (I[5] > 14); // or x argument not in range 8..15
|
||||
|
||||
if (!w.carry) // field mask and argument are valid
|
||||
{
|
||||
_ASSERT(I[5] >= 8 && I[5] <= 14);
|
||||
// w.fld[I[5]-8] = qwVal;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// RPL2 (normal LOOP with preserving Carry)
|
||||
VOID o80B00(VOID)
|
||||
{
|
||||
BYTE p[5];
|
||||
|
||||
Nread(w.A, w.d0, 5); // A=DAT0 A
|
||||
w.d0 = (w.d0 + 5) & 0xFFFFF; // D0=D0+ 5
|
||||
Nread(p, Npack(w.A,5), 5); // PC=(A)
|
||||
w.pc = Npack(p,5);
|
||||
return;
|
||||
}
|
||||
|
||||
// FALSE +5
|
||||
VOID o80B30(VOID)
|
||||
{
|
||||
Ndec(w.D, 5, 0); // D=D-1 A
|
||||
if (w.carry) w.pc = 0x03A9B; // memerr?
|
||||
w.d1 -= 5; // D1=D1- 5 (don't care about carry here)
|
||||
Nwrite(w.A, w.d1, 5); // DAT1=A A
|
||||
o80B00(); // LOOP
|
||||
return;
|
||||
}
|
||||
|
||||
// DOFALSE
|
||||
VOID o80B40(VOID)
|
||||
{
|
||||
w.P = 0; // P= 0
|
||||
PCHANGED;
|
||||
Nunpack(w.C,0x03AC0,5); // LC(5) =FALSE
|
||||
memcpy(w.A, w.C, 5); // A=C A
|
||||
o80B30(); // PC=(A) (call FALSE)
|
||||
return;
|
||||
}
|
||||
|
||||
// MOVEDOWN
|
||||
VOID o80B60(VOID)
|
||||
{
|
||||
BYTE byData[16];
|
||||
DWORD dwC,s;
|
||||
|
||||
for (dwC = Npack(w.C,5); dwC > 0; dwC -= s)
|
||||
{
|
||||
s = ARRAYSIZEOF(byData); // max size for data
|
||||
if (dwC < s) s = dwC;
|
||||
|
||||
Npeek(byData,w.d0,s); // read source without CRC update
|
||||
Nwrite(byData,w.d1,s); // write destination
|
||||
|
||||
w.d0 = (w.d0 + s) & 0xFFFFF;
|
||||
w.d1 = (w.d1 + s) & 0xFFFFF;
|
||||
}
|
||||
|
||||
w.P = 0;
|
||||
PCHANGED;
|
||||
w.carry = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
// MOVEUP
|
||||
VOID o80B70(VOID)
|
||||
{
|
||||
BYTE byData[16];
|
||||
DWORD dwC,s;
|
||||
|
||||
for (dwC = Npack(w.C,5); dwC > 0; dwC -= s)
|
||||
{
|
||||
s = ARRAYSIZEOF(byData); // max size for data
|
||||
if (dwC < s) s = dwC;
|
||||
|
||||
w.d0 = (w.d0 - s) & 0xFFFFF;
|
||||
w.d1 = (w.d1 - s) & 0xFFFFF;
|
||||
|
||||
Npeek(byData,w.d0,s); // read source without CRC update
|
||||
Nwrite(byData,w.d1,s); // write destination
|
||||
}
|
||||
|
||||
w.P = 0;
|
||||
PCHANGED;
|
||||
w.carry = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
// CREATETEMP
|
||||
VOID o80B80(VOID)
|
||||
{
|
||||
DWORD dwC,dwAddress;
|
||||
|
||||
dwC = Npack(w.C,5); // desired size of hole
|
||||
dwAddress = RPL_CreateTemp(dwC,FALSE); // allocate memory
|
||||
if (dwAddress)
|
||||
{
|
||||
w.d0 = dwAddress; // object position
|
||||
w.d1 = (w.d0 + dwC) & 0xFFFFF; // link field of hole
|
||||
w.carry = FALSE; // no error
|
||||
}
|
||||
else
|
||||
{
|
||||
w.carry = TRUE; // error
|
||||
}
|
||||
|
||||
dwC += 6; // desired size + link field
|
||||
Nunpack(w.B,dwC,5); // B[A] = size + 6
|
||||
Nunpack(w.C,dwC,5); // C[A] = size + 6
|
||||
return;
|
||||
}
|
||||
|
||||
// setup basic memory configuration
|
||||
VOID o80B04(VOID)
|
||||
{
|
||||
DWORD a;
|
||||
|
||||
a = Npack(w.C,5); // save C[A]
|
||||
Reset(); // unconfig all devices
|
||||
Nunpack(w.C,0x100,5); // IO: 0x00100
|
||||
Config(); // addr
|
||||
Nunpack(w.C,0x80000,5); // RAM: 0x80000 size 256KB
|
||||
Config(); // size
|
||||
Config(); // addr
|
||||
Nunpack(w.C,a,5); // restore C[A]
|
||||
w.P = 0;
|
||||
PCHANGED;
|
||||
return;
|
||||
}
|
||||
|
||||
// erase flash bank
|
||||
VOID o80B14(VOID)
|
||||
{
|
||||
DWORD dwStart,dwStop;
|
||||
|
||||
BYTE byBank = w.C[15]; // C[S] = bank to erase
|
||||
|
||||
_ASSERT(FALSE); // not tested so far
|
||||
// ROM is logically organized in 16 banks with 128KB
|
||||
dwStart = byBank * _KB(128); // start address
|
||||
dwStop = dwStart + _KB(128); // last address
|
||||
if (byBank == 0) dwStart += _KB(64); // skip boot loader
|
||||
|
||||
// clear bank
|
||||
EraseBlock(dwStart,dwStop-dwStart);
|
||||
|
||||
w.carry = FALSE; // no error
|
||||
return;
|
||||
}
|
||||
|
||||
// write bytes to flash
|
||||
VOID o80B24(VOID)
|
||||
{
|
||||
LPBYTE pbyBuffer;
|
||||
DWORD dwNib,dwAddr,dwSize;
|
||||
|
||||
dwNib = Npack(w.C,5) * 2; // no. of nibbles to copy
|
||||
dwAddr = FlashROMAddr(w.d1); // linear addr in flash chip
|
||||
|
||||
dwSize = dwRomSize - dwAddr; // remaining memory size in flash
|
||||
if (dwNib > dwSize) dwNib = dwSize; // prevent buffer overflow
|
||||
|
||||
pbyBuffer = (LPBYTE) malloc(dwNib); // allocate data buffer
|
||||
if (pbyBuffer != NULL)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
Npeek(pbyBuffer,w.d0,dwNib); // get data
|
||||
|
||||
for (i = 0; i < dwNib; ++i)
|
||||
{
|
||||
WrDirtyPage(dwAddr); // make page dirty
|
||||
pbyRom[dwAddr++] = pbyBuffer[i]; // write data
|
||||
}
|
||||
free(pbyBuffer);
|
||||
}
|
||||
|
||||
w.d0 += dwNib; // update source register
|
||||
w.d1 += dwNib; // update destination register
|
||||
w.carry = FALSE; // no error
|
||||
return;
|
||||
}
|
||||
|
||||
// OUTBYT
|
||||
VOID o80B65(VOID)
|
||||
{
|
||||
// set Transmitting annunciator
|
||||
BYTE byAnn = w.IORam[ANNCTRL+1] | 0x2;
|
||||
WriteIO(&byAnn,ANNCTRL+1,1);
|
||||
|
||||
SendByteUdp((BYTE) Npack(w.A,2)); // send data byte
|
||||
|
||||
w.P = 0;
|
||||
PCHANGED;
|
||||
w.carry = FALSE; // no error
|
||||
return;
|
||||
}
|
||||
|
||||
// CdB for HP: add apples BUSCC commands
|
||||
VOID o80BExt(LPBYTE I) // Saturnator extentions
|
||||
{
|
||||
DWORD a;
|
||||
|
||||
w.pc+=2;
|
||||
switch (I[3]+(I[4]<<4))
|
||||
{
|
||||
case 0x00: o80B00(); break; // RPL2 (preserve Carry)
|
||||
case 0x03: o80B30(); break; // FALSE
|
||||
case 0x04: o80B40(); break; // DOFALSE
|
||||
case 0x05: External(&w); PCHANGED; break; // BEEP2 implemented using Emu48's beep
|
||||
case 0x06: o80B60(); break; // MOVEDOWN
|
||||
case 0x07: o80B70(); break; // MOVEUP
|
||||
case 0x08: o80B80(); break; // CREATETEMP
|
||||
case 0x09: RCKBp(&w); PCHANGED; break; // RCKBp
|
||||
case 0x0A: break; // KEYDN not implemented
|
||||
case 0x0B: break; // no doslow implemented
|
||||
case 0x10: // simulate off function
|
||||
{
|
||||
BOOL bShutdn = TRUE; // shut down
|
||||
|
||||
// only shut down when no timer wake up
|
||||
if (w.IORam[TIMER1_CTRL]&WKE) // WKE bit of timer1 is set
|
||||
{
|
||||
if (ReadT1()&0x08) // and MSB of timer1 is set
|
||||
{
|
||||
w.IORam[TIMER1_CTRL] &= ~WKE; // clear WKE
|
||||
bShutdn = FALSE; // don't shut down
|
||||
}
|
||||
}
|
||||
if (w.IORam[TIMER2_CTRL]&WKE) // WKE bit of timer2 is set
|
||||
{
|
||||
if (ReadT2()&0x80000000) // and MSB of timer2 is set
|
||||
{
|
||||
w.IORam[TIMER2_CTRL] &= ~WKE; // clear WKE
|
||||
bShutdn = FALSE; // don't shut down
|
||||
}
|
||||
}
|
||||
if (w.in==0 && bShutdn) // shut down only when enabled
|
||||
{
|
||||
w.Shutdn = TRUE; // set mode before exit emulation loop
|
||||
bInterrupt = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x11: w.pc+=2; break; // do not do gettime, just skip the RTN after it to fall in the normal gettime function (only valid in untouched ROM)
|
||||
case 0x12: break; // do not do settime, fall in the normal settime function (only valid in untouched ROM)
|
||||
case 0x13: break; // RESETOS not implemented
|
||||
case 0x14: break; // AUTOTEST not implemented
|
||||
case 0x15: break; // NATIVE? not implemented
|
||||
case 0x17: break; // SERIAL not implemented
|
||||
case 0x28: w.HST |= I[5]; w.pc+=1; break; // HST=1.x
|
||||
case 0x29: w.A[4]= w.A[3]= w.A[2]= w.A[0]= 0; if (cCurrentRomType=='Q') w.A[1]=5; else w.A[1]=4; break; // screen height = 0x50 = 80
|
||||
case 0x2A: w.A[4]= w.A[3]= w.A[2]= 0; w.A[1]=8; w.A[0]=3; break; // screen width = 0x83 = 131
|
||||
case 0x2B: w.carry = (cCurrentRomType == '2'); break; // it is medium apple
|
||||
case 0x2C: w.carry = (cCurrentRomType == 'Q'); break; // it is big apple
|
||||
case 0x2E: w.carry = (nCurrentClass == 50); break; // it is big apple V2
|
||||
case 0x30: w.d0address= Npack(w.C,5)>>12; Map(0,0xff); break; //config_disp0 Ca:address 4K data
|
||||
case 0x31: w.d0address=0; Map(0,0xff); RefreshDisp0(); break; //unconfig_disp0 does the refresh
|
||||
case 0x32: RefreshDisp0(); break; //refresh_disp0 force refresh
|
||||
case 0x33: a= Npack(w.C,2); if (a>(DWORD)SCREENHEIGHT) a= SCREENHEIGHT; /* w.lcounter = (SCREENHEIGHT-a) */; w.d0size= a; RefreshDisp0(); break; //set_lines_disp0 nb in Cb
|
||||
case 0x34: w.d0offset= Npack(w.C,5); w.d0offset &= 0x7FF; break; //set_offset_disp0 offset to disp in disp0
|
||||
case 0x35: Nunpack(w.C,w.d0offset,5); break; // native_get_line_disp0
|
||||
case 0x38: w.HST |= I[5]; w.pc+=3; break; // ?HST=1.x not implemented
|
||||
case 0x40: o80B04(); break; // setup basic memory configuration
|
||||
// case 0x41: o80B14(); break; // erase flash bank
|
||||
case 0x42: o80B24(); break; // write bytes into flash
|
||||
// case 0x43: ??? // format flash bank
|
||||
case 0x50: break; // REMON not implemented
|
||||
case 0x51: break; // REMOFF not implemented
|
||||
case 0x56: o80B65(); break; // OUTBYT
|
||||
case 0x57: w.D[0]= w.D[1]= 0; break;
|
||||
case 0x60: break; // ACCESSSD not implemented
|
||||
case 0x61: break; // PORTTAG? not implemented
|
||||
case 0x64: w.carry = FALSE; break; // no SD card inserted
|
||||
case 0x66: w.carry = FALSE; break; // simulate format fail card inserted
|
||||
case 0x7F: w.carry = TRUE; w.pc+=1; break; // SETFLDn not implemented, set carry for failed
|
||||
case 0x80: { QWORD b = o80BReg264(I); o80BRegWrite(b, I); w.pc+=2; break; } // r=s
|
||||
case 0x81: { QWORD a = o80BReg164(I); QWORD b = o80BReg264(I); o80BRegWrite(a+b, I); w.pc+=2; break; } // r=r+s
|
||||
case 0x82: { QWORD a = o80BReg164(I); QWORD b = o80BReg264(I); o80BRegWrite(a-b, I); w.pc+=2; break; } // r=r-s
|
||||
case 0x83: { QWORD a = o80BReg164(I); QWORD b = o80BReg264(I); o80BRegWrite(a*b, I); w.pc+=2; break; } // r=r*s
|
||||
case 0x84: { QWORD a = o80BReg164(I); QWORD b = o80BReg264(I); o80BRegWrite(a/b, I); w.pc+=2; break; } // r=r/s
|
||||
case 0x85: { QWORD a = o80BReg164(I); QWORD b = o80BReg264(I); o80BRegWrite(a%b, I); w.pc+=2; break; } // r=r%s
|
||||
case 0x86: { QWORD b = o80BReg264(I); o80BRegWrite(~b, I); w.pc+=2; break; } // r=-r-1
|
||||
case 0x87: { QWORD b = o80BReg264(I); o80BRegWrite((QWORD)(-(__int64)b), I); w.pc+=2; break; } // r=-r
|
||||
case 0x88: { QWORD a = o80BReg164(I); QWORD b = o80BReg264(I); o80BRegWrite(a<<b, I); w.pc+=2; break; } // r=r<s
|
||||
case 0x89: { QWORD a = o80BReg164(I); QWORD b = o80BReg264(I); o80BRegWrite(a>>b, I); w.pc+=2; break; } // r=r>s
|
||||
case 0x8A: { QWORD a = o80BReg164(I); QWORD b = o80BReg264(I); o80BRegWrite(a^b, I); w.pc+=2; break; } // r=r^s
|
||||
case 0x90: break; // data streamer not implemented
|
||||
case 0xEE: break; // ARMFLUSH not implemented
|
||||
case 0xEF: break; // ARMSYS not implemented
|
||||
case 0xFF: break; // ARMSAT not implemented
|
||||
default: w.pc-= 2;
|
||||
}
|
||||
return;
|
||||
}
|
19
app/src/main/cpp/APPLE.H
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* apple.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2006 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
|
||||
extern VOID o80B00(VOID);
|
||||
extern VOID o80B30(VOID);
|
||||
extern VOID o80B40(VOID);
|
||||
extern VOID o80B60(VOID);
|
||||
extern VOID o80B70(VOID);
|
||||
extern VOID o80B80(VOID);
|
||||
extern VOID o80B04(VOID);
|
||||
extern VOID o80B14(VOID);
|
||||
extern VOID o80B24(VOID);
|
||||
extern VOID o80BExt(LPBYTE I); // Saturnator extentions
|
27
app/src/main/cpp/COLOR.H
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* color.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1999 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
|
||||
#define COLOR_BLACK 0x00000000
|
||||
#define COLOR_MAROON 0x00000080
|
||||
#define COLOR_GREEN 0x00008000
|
||||
#define COLOR_OLIVE 0x00008080
|
||||
#define COLOR_NAVY 0x00800000
|
||||
#define COLOR_PURPLE 0x00800080
|
||||
#define COLOR_TEAL 0x00808000
|
||||
#define COLOR_GRAY 0x00808080
|
||||
#define COLOR_SILVER 0x00C0C0C0
|
||||
#define COLOR_RED 0x000000FF
|
||||
#define COLOR_LIME 0x0000FF00
|
||||
#define COLOR_YELLOW 0x0000FFFF
|
||||
#define COLOR_BLUE 0x00FF0000
|
||||
#define COLOR_FUCHSIA 0x00FF00FF
|
||||
#define COLOR_AQUA 0x00FFFF00
|
||||
#define COLOR_LTGRAY 0x00C0C0C0
|
||||
#define COLOR_DKGRAY 0x00808080
|
||||
#define COLOR_WHITE 0x00FFFFFF
|
89
app/src/main/cpp/CURSOR.C
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Cursor.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2004 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
|
||||
// hand cursor AND mask
|
||||
static CONST BYTE ANDmaskCursor[] =
|
||||
{
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 1111 1111 1111 1111 1111 1111 1111 1111
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 1111 1111 1111 1111 1111 1111 1111 1111
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 1111 1111 1111 1111 1111 1111 1111 1111
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 1111 1111 1111 1111 1111 1111 1111 1111
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 1111 1111 1111 1111 1111 1111 1111 1111
|
||||
0xFF, 0xF3, 0xFF, 0xFF, // 1111 1111 1111 0011 1111 1111 1111 1111
|
||||
0xFF, 0xE1, 0xFF, 0xFF, // 1111 1111 1110 0001 1111 1111 1111 1111
|
||||
0xFF, 0xE1, 0xFF, 0xFF, // 1111 1111 1110 0001 1111 1111 1111 1111
|
||||
0xFF, 0xE1, 0xFF, 0xFF, // 1111 1111 1110 0001 1111 1111 1111 1111
|
||||
0xFF, 0xE1, 0xFF, 0xFF, // 1111 1111 1110 0001 1111 1111 1111 1111
|
||||
0xFF, 0xE0, 0x7F, 0xFF, // 1111 1111 1110 0000 0111 1111 1111 1111
|
||||
0xFF, 0xE0, 0x0F, 0xFF, // 1111 1111 1110 0000 0000 1111 1111 1111
|
||||
0xFF, 0xE0, 0x03, 0xFF, // 1111 1111 1110 0000 0000 0011 1111 1111
|
||||
0xFF, 0xE0, 0x01, 0xFF, // 1111 1111 1110 0000 0000 0001 1111 1111
|
||||
0xFE, 0x20, 0x00, 0xFF, // 1111 1110 0010 0000 0000 0000 1111 1111
|
||||
0xFE, 0x00, 0x00, 0xFF, // 1111 1110 0000 0000 0000 0000 1111 1111
|
||||
0xFE, 0x00, 0x00, 0xFF, // 1111 1110 0000 0000 0000 0000 1111 1111
|
||||
0xFF, 0x00, 0x00, 0xFF, // 1111 1111 0000 0000 0000 0000 1111 1111
|
||||
0xFF, 0x80, 0x00, 0xFF, // 1111 1111 1000 0000 0000 0000 1111 1111
|
||||
0xFF, 0x80, 0x00, 0xFF, // 1111 1111 1000 0000 0000 0000 1111 1111
|
||||
0xFF, 0xC0, 0x00, 0xFF, // 1111 1111 1100 0000 0000 0000 1111 1111
|
||||
0xFF, 0xC0, 0x01, 0xFF, // 1111 1111 1100 0000 0000 0001 1111 1111
|
||||
0xFF, 0xE0, 0x01, 0xFF, // 1111 1111 1110 0000 0000 0001 1111 1111
|
||||
0xFF, 0xE0, 0x01, 0xFF, // 1111 1111 1110 0000 0000 0001 1111 1111
|
||||
0xFF, 0xF0, 0x03, 0xFF, // 1111 1111 1111 0000 0000 0011 1111 1111
|
||||
0xFF, 0xF0, 0x03, 0xFF, // 1111 1111 1111 0000 0000 0011 1111 1111
|
||||
0xFF, 0xF0, 0x03, 0xFF, // 1111 1111 1111 0000 0000 0011 1111 1111
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 1111 1111 1111 1111 1111 1111 1111 1111
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 1111 1111 1111 1111 1111 1111 1111 1111
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 1111 1111 1111 1111 1111 1111 1111 1111
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // 1111 1111 1111 1111 1111 1111 1111 1111
|
||||
0xFF, 0xFF, 0xFF, 0xFF // 1111 1111 1111 1111 1111 1111 1111 1111
|
||||
};
|
||||
|
||||
// hand cursor XOR mask
|
||||
static CONST BYTE XORmaskCursor[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, // 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0x00, 0x00, 0x00, 0x00, // 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0x00, 0x00, 0x00, 0x00, // 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0x00, 0x00, 0x00, 0x00, // 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0x00, 0x00, 0x00, 0x00, // 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0x00, 0x00, 0x00, 0x00, // 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0x00, 0x0C, 0x00, 0x00, // 0000 0000 0000 1100 0000 0000 0000 0000
|
||||
0x00, 0x0C, 0x00, 0x00, // 0000 0000 0000 1100 0000 0000 0000 0000
|
||||
0x00, 0x0C, 0x00, 0x00, // 0000 0000 0000 1100 0000 0000 0000 0000
|
||||
0x00, 0x0C, 0x00, 0x00, // 0000 0000 0000 1100 0000 0000 0000 0000
|
||||
0x00, 0x0C, 0x00, 0x00, // 0000 0000 0000 1100 0000 0000 0000 0000
|
||||
0x00, 0x0D, 0x80, 0x00, // 0000 0000 0000 1101 1000 0000 0000 0000
|
||||
0x00, 0x0D, 0xB0, 0x00, // 0000 0000 0000 1101 1011 0000 0000 0000
|
||||
0x00, 0x0D, 0xB4, 0x00, // 0000 0000 0000 1101 1011 0100 0000 0000
|
||||
0x00, 0x0D, 0xB6, 0x00, // 0000 0000 0000 1101 1011 0110 0000 0000
|
||||
0x00, 0xCF, 0xF6, 0x00, // 0000 0000 1100 1111 1111 0110 0000 0000
|
||||
0x00, 0xEF, 0xFE, 0x00, // 0000 0000 1110 1111 1111 1110 0000 0000
|
||||
0x00, 0x6F, 0xFE, 0x00, // 0000 0000 0110 1111 1111 1110 0000 0000
|
||||
0x00, 0x2F, 0xFE, 0x00, // 0000 0000 0010 1111 1111 1110 0000 0000
|
||||
0x00, 0x3F, 0xFE, 0x00, // 0000 0000 0011 1111 1111 1110 0000 0000
|
||||
0x00, 0x1F, 0xFE, 0x00, // 0000 0000 0001 1111 1111 1110 0000 0000
|
||||
0x00, 0x1F, 0xFC, 0x00, // 0000 0000 0001 1111 1111 1100 0000 0000
|
||||
0x00, 0x0F, 0xFC, 0x00, // 0000 0000 0000 1111 1111 1100 0000 0000
|
||||
0x00, 0x0F, 0xFC, 0x00, // 0000 0000 0000 1111 1111 1100 0000 0000
|
||||
0x00, 0x07, 0xF8, 0x00, // 0000 0000 0000 0111 1111 1000 0000 0000
|
||||
0x00, 0x07, 0xF8, 0x00, // 0000 0000 0000 0111 1111 1000 0000 0000
|
||||
0x00, 0x00, 0x00, 0x00, // 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0x00, 0x00, 0x00, 0x00, // 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0x00, 0x00, 0x00, 0x00, // 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0x00, 0x00, 0x00, 0x00, // 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0x00, 0x00, 0x00, 0x00, // 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
0x00, 0x00, 0x00, 0x00 // 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
};
|
||||
|
||||
HCURSOR CreateHandCursor(VOID)
|
||||
{
|
||||
return CreateCursor(hApp,12,5,32,32,ANDmaskCursor,XORmaskCursor);
|
||||
}
|
182
app/src/main/cpp/DDESERV.C
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* DdeServ.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1998 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h"
|
||||
|
||||
HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv,
|
||||
HSZ hsz1,HSZ hsz2,HDDEDATA hData,
|
||||
DWORD dwData1,DWORD dwData2)
|
||||
{
|
||||
TCHAR *psz,szBuffer[32];
|
||||
HDDEDATA hReturn;
|
||||
LPBYTE lpData,lpHeader;
|
||||
DWORD dwAddress,dwSize,dwLoop,dwIndex;
|
||||
UINT nStkLvl;
|
||||
BOOL bSuccess;
|
||||
|
||||
// disable stack loading items on HP38G, HP39/40G
|
||||
BOOL bStackEnable = cCurrentRomType!='6' && cCurrentRomType!='A' && cCurrentRomType!='E' && cCurrentRomType!='P'; // CdB for HP: add P type
|
||||
|
||||
switch (iType)
|
||||
{
|
||||
case XTYP_CONNECT:
|
||||
// get service name
|
||||
DdeQueryString(idDdeInst,hsz2,szBuffer,ARRAYSIZEOF(szBuffer),0);
|
||||
if (0 != lstrcmp(szBuffer,szAppName))
|
||||
return (HDDEDATA) FALSE;
|
||||
// get topic name
|
||||
DdeQueryString(idDdeInst,hsz1,szBuffer,ARRAYSIZEOF(szBuffer),0);
|
||||
return (HDDEDATA) (INT_PTR) (0 == lstrcmp(szBuffer,szTopic));
|
||||
|
||||
case XTYP_POKE:
|
||||
// quit on models without stack or illegal data format or not in running state
|
||||
if (!bStackEnable || iFmt != uCF_HpObj || nState != SM_RUN)
|
||||
return (HDDEDATA) DDE_FNOTPROCESSED;
|
||||
|
||||
// get item name
|
||||
DdeQueryString(idDdeInst,hsz2,szBuffer,ARRAYSIZEOF(szBuffer),0);
|
||||
nStkLvl = _tcstoul(szBuffer,&psz,10);
|
||||
if (*psz != 0 || nStkLvl < 1) // invalid number format
|
||||
return (HDDEDATA) DDE_FNOTPROCESSED;
|
||||
|
||||
SuspendDebugger(); // suspend debugger
|
||||
bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control
|
||||
|
||||
if (!(Chipset.IORam[BITOFFSET]&DON)) // HP off
|
||||
{
|
||||
// turn on HP
|
||||
KeyboardEvent(TRUE,0,0x8000);
|
||||
Sleep(dwWakeupDelay);
|
||||
KeyboardEvent(FALSE,0,0x8000);
|
||||
}
|
||||
|
||||
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
|
||||
{
|
||||
hReturn = DDE_FNOTPROCESSED;
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
_ASSERT(nState==SM_SLEEP);
|
||||
|
||||
bSuccess = FALSE;
|
||||
|
||||
// get data and size
|
||||
lpData = DdeAccessData(hData,&dwSize);
|
||||
|
||||
// has object length header
|
||||
if (lpData && dwSize >= sizeof(DWORD))
|
||||
{
|
||||
dwIndex = *(LPDWORD) lpData; // object length
|
||||
|
||||
if (dwIndex <= dwSize - sizeof(DWORD))
|
||||
{
|
||||
// reserve unpacked object length memory
|
||||
LPBYTE pbyMem = (LPBYTE) malloc(dwIndex * 2);
|
||||
|
||||
if (pbyMem != NULL)
|
||||
{
|
||||
// copy data and write to stack
|
||||
CopyMemory(pbyMem+dwIndex,lpData+sizeof(DWORD),dwIndex);
|
||||
bSuccess = (WriteStack(nStkLvl,pbyMem,dwIndex) == S_ERR_NO);
|
||||
free(pbyMem); // free memory
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DdeUnaccessData(hData);
|
||||
|
||||
SwitchToState(SM_RUN); // run state
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
_ASSERT(nState==SM_RUN);
|
||||
|
||||
if (bSuccess == FALSE)
|
||||
{
|
||||
hReturn = DDE_FNOTPROCESSED;
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
KeyboardEvent(TRUE,0,0x8000);
|
||||
Sleep(dwWakeupDelay);
|
||||
KeyboardEvent(FALSE,0,0x8000);
|
||||
// wait for sleep mode
|
||||
while (Chipset.Shutdn == FALSE) Sleep(0);
|
||||
hReturn = (HDDEDATA) DDE_FACK;
|
||||
|
||||
cancel:
|
||||
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
|
||||
ResumeDebugger();
|
||||
return hReturn;
|
||||
|
||||
case XTYP_REQUEST:
|
||||
// quit on models without stack or illegal data format or not in running state
|
||||
if (!bStackEnable || iFmt != uCF_HpObj || nState != SM_RUN)
|
||||
return NULL;
|
||||
|
||||
// get item name
|
||||
DdeQueryString(idDdeInst,hsz2,szBuffer,ARRAYSIZEOF(szBuffer),0);
|
||||
nStkLvl = _tcstoul(szBuffer,&psz,10);
|
||||
if (*psz != 0 || nStkLvl < 1) // invalid number format
|
||||
return NULL;
|
||||
|
||||
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
|
||||
return NULL;
|
||||
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
_ASSERT(nState==SM_SLEEP);
|
||||
|
||||
dwAddress = RPL_Pick(nStkLvl); // pick address of stack level "item" object
|
||||
if (dwAddress == 0)
|
||||
{
|
||||
SwitchToState(SM_RUN); // run state
|
||||
return NULL;
|
||||
}
|
||||
dwLoop = dwSize = (RPL_SkipOb(dwAddress) - dwAddress + 1) / 2;
|
||||
|
||||
lpHeader = (Chipset.type == 'X' || Chipset.type == 'Q' || Chipset.type == '2') ? (LPBYTE) BINARYHEADER49 : (LPBYTE) BINARYHEADER48;
|
||||
|
||||
// length of binary header
|
||||
dwIndex = (DWORD) strlen((LPCSTR) lpHeader);
|
||||
|
||||
// size of objectsize + header + object
|
||||
dwSize += dwIndex + sizeof(DWORD);
|
||||
|
||||
// reserve memory
|
||||
if ((lpData = (LPBYTE) malloc(dwSize)) == NULL)
|
||||
{
|
||||
SwitchToState(SM_RUN); // run state
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// save data length
|
||||
*(DWORD *)lpData = dwLoop + dwIndex;
|
||||
|
||||
// copy header
|
||||
memcpy(lpData + sizeof(DWORD),lpHeader,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);
|
||||
free(lpData);
|
||||
|
||||
SwitchToState(SM_RUN); // run state
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
_ASSERT(nState==SM_RUN);
|
||||
|
||||
return hReturn;
|
||||
}
|
||||
return NULL;
|
||||
UNREFERENCED_PARAMETER(hConv);
|
||||
UNREFERENCED_PARAMETER(dwData1);
|
||||
UNREFERENCED_PARAMETER(dwData2);
|
||||
}
|
1104
app/src/main/cpp/DEBUGDLL.C
Normal file
3638
app/src/main/cpp/DEBUGGER.C
Normal file
39
app/src/main/cpp/DEBUGGER.H
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* debugger.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1999 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
|
||||
// breakpoint type definitions
|
||||
#define BP_EXEC 0x01 // code breakpoint
|
||||
#define BP_READ 0x02 // read memory breakpoint
|
||||
#define BP_WRITE 0x04 // write memory breakpoint
|
||||
#define BP_RPL 0x08 // RPL breakpoint
|
||||
#define BP_ACCESS (BP_READ|BP_WRITE) // read/write memory breakpoint
|
||||
|
||||
// breakpoint notify definitions
|
||||
#define BN_ASM 0 // ASM breakpoint
|
||||
#define BN_RPL 1 // RPL breakpoint
|
||||
#define BN_ASM_BT 2 // ASM and RPL breakpoint
|
||||
|
||||
// debugger state definitions
|
||||
#define DBG_SUSPEND -1
|
||||
#define DBG_OFF 0
|
||||
#define DBG_RUN 1
|
||||
#define DBG_STEPINTO 2
|
||||
#define DBG_STEPOVER 3
|
||||
#define DBG_STEPOUT 4
|
||||
|
||||
// debugger.c
|
||||
extern VOID UpdateDbgCycleCounter(VOID);
|
||||
extern BOOL CheckBreakpoint(DWORD dwAddr, DWORD wRange, UINT nType);
|
||||
extern VOID NotifyDebugger(INT nType);
|
||||
extern VOID DisableDebugger(VOID);
|
||||
extern LRESULT OnToolDebug(VOID);
|
||||
extern VOID LoadBreakpointList(HANDLE hFile);
|
||||
extern VOID SaveBreakpointList(HANDLE hFile);
|
||||
extern VOID CreateBackupBreakpointList(VOID);
|
||||
extern VOID RestoreBackupBreakpointList(VOID);
|
1845
app/src/main/cpp/DISASM.C
Normal file
245
app/src/main/cpp/DISMEM.C
Normal file
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* dismem.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2012 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
|
||||
typedef struct // type of model memory mapping
|
||||
{
|
||||
BYTE byType; // calculator type
|
||||
CONST LPBYTE *ppbyNCE1; // NCE1 data
|
||||
CONST DWORD *pdwNCE1Size; // NCE1 size
|
||||
CONST LPBYTE *ppbyNCE2; // NCE2 data
|
||||
CONST DWORD *pdwNCE2Size; // NCE2 size
|
||||
CONST LPBYTE *ppbyCE1; // CE1 data
|
||||
CONST DWORD *pdwCE1Size; // CE1 size
|
||||
CONST LPBYTE *ppbyCE2; // CE2 data
|
||||
CONST DWORD *pdwCE2Size; // CE2 size
|
||||
CONST LPBYTE *ppbyNCE3; // NCE3 data
|
||||
CONST DWORD *pdwNCE3Size; // NCE3 size
|
||||
} MODEL_MAP_T;
|
||||
|
||||
static CONST LPBYTE pbyNoMEM = NULL; // no memory module
|
||||
|
||||
static CONST MODEL_MAP_T MemMap[] =
|
||||
{
|
||||
{
|
||||
0, // default
|
||||
&pbyNoMEM, NULL, // nc.
|
||||
&pbyNoMEM, NULL, // nc.
|
||||
&pbyNoMEM, NULL, // nc.
|
||||
&pbyNoMEM, NULL, // nc.
|
||||
&pbyNoMEM, NULL // nc.
|
||||
},
|
||||
{
|
||||
'6', // HP38G (64K)
|
||||
&pbyRom, &dwRomSize, // ROM
|
||||
&Port0, &Chipset.Port0Size, // RAM
|
||||
&pbyNoMEM, NULL, // nc.
|
||||
&pbyNoMEM, NULL, // nc.
|
||||
&pbyNoMEM, NULL // nc.
|
||||
},
|
||||
{
|
||||
'A', // HP38G
|
||||
&pbyRom, &dwRomSize, // ROM
|
||||
&Port0, &Chipset.Port0Size, // RAM
|
||||
&pbyNoMEM, NULL, // nc.
|
||||
&pbyNoMEM, NULL, // nc.
|
||||
&pbyNoMEM, NULL // nc.
|
||||
},
|
||||
{
|
||||
'E', // HP39/40G
|
||||
&pbyRom, &dwRomSize, // ROM
|
||||
&Port0, &Chipset.Port0Size, // RAM part 1
|
||||
&pbyNoMEM, NULL, // BS
|
||||
&pbyNoMEM, NULL, // nc.
|
||||
&Port2, &Chipset.Port2Size // RAM part 2
|
||||
},
|
||||
{
|
||||
'G', // HP48GX
|
||||
&pbyRom, &dwRomSize, // ROM
|
||||
&Port0, &Chipset.Port0Size, // RAM
|
||||
&pbyNoMEM, NULL, // BS
|
||||
&Port1, &Chipset.Port1Size, // Card slot 1
|
||||
&pbyPort2, &dwPort2Size // Card slot 2
|
||||
},
|
||||
{
|
||||
'S', // HP48SX
|
||||
&pbyRom, &dwRomSize, // ROM
|
||||
&Port0, &Chipset.Port0Size, // RAM
|
||||
&Port1, &Chipset.Port1Size, // Card slot 1
|
||||
&pbyPort2, &dwPort2Size, // Card slot 2
|
||||
&pbyNoMEM, NULL // nc.
|
||||
},
|
||||
{
|
||||
'X', // HP49G
|
||||
&pbyRom, &dwRomSize, // Flash
|
||||
&Port0, &Chipset.Port0Size, // RAM
|
||||
&pbyNoMEM, NULL, // BS
|
||||
&Port1, &Chipset.Port1Size, // Port 1 part 1
|
||||
&Port2, &Chipset.Port2Size // Port 1 part 2
|
||||
},
|
||||
{ // CdB for HP: add Q type
|
||||
'Q', // HP49g+
|
||||
&pbyRom, &dwRomSize, // Flash
|
||||
&Port0, &Chipset.Port0Size, // RAM
|
||||
&pbyNoMEM, NULL, // BS
|
||||
&Port1, &Chipset.Port1Size, // Port 1 part 1
|
||||
&Port2, &Chipset.Port2Size // Port 1 part 2
|
||||
},
|
||||
{ // CdB for HP: add 2 type
|
||||
'2', // HP48gII
|
||||
&pbyRom, &dwRomSize, // ROM
|
||||
&Port0, &Chipset.Port0Size, // RAM
|
||||
&pbyNoMEM, NULL, // BS
|
||||
&pbyNoMEM, NULL, // Port 1 part 1
|
||||
&pbyNoMEM, NULL, // Port 1 part 2
|
||||
},
|
||||
{ // CdB for HP: add P type
|
||||
'P', // HP39g+/gs
|
||||
&pbyRom, &dwRomSize, // ROM
|
||||
&Port0, &Chipset.Port0Size, // RAM
|
||||
&pbyNoMEM, NULL, // BS
|
||||
&pbyNoMEM, NULL, // nc.
|
||||
&Port2, &Chipset.Port2Size // RAM part 2
|
||||
}
|
||||
};
|
||||
|
||||
static MODEL_MAP_T CONST *pMapping = MemMap; // model specific memory mapping
|
||||
static enum MEM_MAPPING eMapType = MEM_MMU; // MMU memory mapping
|
||||
|
||||
static LPBYTE pbyMapData = NULL;
|
||||
static DWORD dwMapDataSize = 0;
|
||||
static DWORD dwMapDataMask = 0;
|
||||
|
||||
BOOL SetMemRomType(BYTE cCurrentRomType)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
pMapping = MemMap; // init default mapping
|
||||
|
||||
// scan for all table entries
|
||||
for (i = 0; i < ARRAYSIZEOF(MemMap); ++i)
|
||||
{
|
||||
if (MemMap[i].byType == cCurrentRomType)
|
||||
{
|
||||
pMapping = &MemMap[i]; // found entry
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL SetMemMapType(enum MEM_MAPPING eType)
|
||||
{
|
||||
BOOL bSucc = TRUE;
|
||||
|
||||
eMapType = eType;
|
||||
|
||||
switch (eMapType)
|
||||
{
|
||||
case MEM_MMU:
|
||||
pbyMapData = NULL; // data
|
||||
dwMapDataSize = 512 * 1024 * 2; // data size
|
||||
dwMapDataMask = dwMapDataSize - 1; // size mask
|
||||
break;
|
||||
case MEM_NCE1:
|
||||
pbyMapData = *pMapping->ppbyNCE1;
|
||||
dwMapDataSize = *pMapping->pdwNCE1Size; // ROM size is always in nibbles
|
||||
dwMapDataMask = dwMapDataSize - 1; // size mask
|
||||
break;
|
||||
case MEM_NCE2:
|
||||
pbyMapData = *pMapping->ppbyNCE2;
|
||||
dwMapDataSize = *pMapping->pdwNCE2Size * 1024 * 2;
|
||||
dwMapDataMask = dwMapDataSize - 1; // size mask
|
||||
break;
|
||||
case MEM_CE1:
|
||||
pbyMapData = *pMapping->ppbyCE1;
|
||||
dwMapDataSize = *pMapping->pdwCE1Size * 1024 * 2;
|
||||
dwMapDataMask = dwMapDataSize - 1; // size mask
|
||||
break;
|
||||
case MEM_CE2:
|
||||
pbyMapData = *pMapping->ppbyCE2;
|
||||
dwMapDataSize = *pMapping->pdwCE2Size * 1024 * 2;
|
||||
dwMapDataMask = dwMapDataSize - 1; // size mask
|
||||
break;
|
||||
case MEM_NCE3:
|
||||
pbyMapData = *pMapping->ppbyNCE3;
|
||||
dwMapDataSize = *pMapping->pdwNCE3Size * 1024 * 2;
|
||||
dwMapDataMask = dwMapDataSize - 1; // size mask
|
||||
break;
|
||||
default: _ASSERT(FALSE);
|
||||
pbyMapData = NULL;
|
||||
dwMapDataSize = 0;
|
||||
dwMapDataMask = 0;
|
||||
bSucc = FALSE;
|
||||
}
|
||||
return bSucc;
|
||||
}
|
||||
|
||||
enum MEM_MAPPING GetMemMapType(VOID)
|
||||
{
|
||||
return eMapType;
|
||||
}
|
||||
|
||||
BOOL GetMemAvail(enum MEM_MAPPING eType)
|
||||
{
|
||||
switch (eType)
|
||||
{
|
||||
case MEM_MMU: return TRUE;
|
||||
case MEM_NCE1: return *pMapping->ppbyNCE1 != NULL;
|
||||
case MEM_NCE2: return *pMapping->ppbyNCE2 != NULL;
|
||||
case MEM_CE1: return *pMapping->ppbyCE1 != NULL;
|
||||
case MEM_CE2: return *pMapping->ppbyCE2 != NULL;
|
||||
case MEM_NCE3: return *pMapping->ppbyNCE3 != NULL;
|
||||
default: _ASSERT(FALSE);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD GetMemDataSize(VOID)
|
||||
{
|
||||
return dwMapDataSize;
|
||||
}
|
||||
|
||||
DWORD GetMemDataMask(VOID)
|
||||
{
|
||||
return dwMapDataMask;
|
||||
}
|
||||
|
||||
BYTE GetMemNib(DWORD *p)
|
||||
{
|
||||
BYTE byVal;
|
||||
|
||||
if (pbyMapData == NULL)
|
||||
{
|
||||
Npeek(&byVal, *p, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
byVal = pbyMapData[*p];
|
||||
}
|
||||
*p = (*p + 1) & dwMapDataMask;
|
||||
return byVal;
|
||||
}
|
||||
|
||||
VOID GetMemPeek(BYTE *a, DWORD d, UINT s)
|
||||
{
|
||||
if (pbyMapData == NULL)
|
||||
{
|
||||
Npeek(a, d, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; s > 0; --s, ++d)
|
||||
{
|
||||
*a++ = pbyMapData[d & dwMapDataMask];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
746
app/src/main/cpp/DISPLAY.C
Normal file
|
@ -0,0 +1,746 @@
|
|||
/*
|
||||
* display.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1995 Sebastien Carlier
|
||||
* Copyright (C) 2002 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "resource.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h"
|
||||
#include "kml.h"
|
||||
|
||||
// #define DEBUG_DISPLAY // switch for DISPLAY debug purpose
|
||||
|
||||
#define NOCOLORSGRAY 8 // no. of colors in gray scale mode
|
||||
#define NOCOLORSBW 2 // no. of colors in black and white mode
|
||||
|
||||
#define DISPLAY_FREQ 19 // display update 1/frequency (1/64) in ms (gray scale mode)
|
||||
|
||||
#define B 0x00000000 // black
|
||||
#define W 0x00FFFFFF // white
|
||||
#define I 0xFFFFFFFF // ignore
|
||||
|
||||
#define LCD_ROW (36*4) // max. pixel per line
|
||||
|
||||
#define GRAYMASK(c) (((((c)-1)>>1)<<24) \
|
||||
|((((c)-1)>>1)<<16) \
|
||||
|((((c)-1)>>1)<<8) \
|
||||
|((((c)-1)>>1)))
|
||||
|
||||
#define DIBPIXEL4(d,p) *((DWORD*)(d)) = ((*((DWORD*)(d)) & dwGrayMask) << 1) | (p); \
|
||||
*((LPBYTE*) &(d)) += 4
|
||||
|
||||
BOOL bGrayscale = FALSE;
|
||||
UINT nBackgroundX = 0;
|
||||
UINT nBackgroundY = 0;
|
||||
UINT nBackgroundW = 0;
|
||||
UINT nBackgroundH = 0;
|
||||
UINT nLcdX = 0;
|
||||
UINT nLcdY = 0;
|
||||
UINT nLcdZoom = 1; // memory DC zoom
|
||||
UINT nGdiXZoom = 1; // GDI x zoom
|
||||
UINT nGdiYZoom = 1; // GDI y zoom
|
||||
HDC hLcdDC = NULL;
|
||||
HDC hMainDC = NULL;
|
||||
HDC hAnnunDC = NULL; // annunciator DC
|
||||
|
||||
BYTE (*GetLineCounter)(VOID) = NULL;
|
||||
VOID (*StartDisplay)(BYTE byInitial) = NULL;
|
||||
VOID (*StopDisplay)(VOID) = NULL;
|
||||
|
||||
static BYTE GetLineCounterGray(VOID);
|
||||
static BYTE GetLineCounterBW(VOID);
|
||||
static VOID StartDisplayGray(BYTE byInitial);
|
||||
static VOID StartDisplayBW(BYTE byInitial);
|
||||
static VOID StopDisplayGray(VOID);
|
||||
static VOID StopDisplayBW(VOID);
|
||||
|
||||
static LPBYTE pbyLcd;
|
||||
|
||||
static HBITMAP hLcdBitmap;
|
||||
static HBITMAP hMainBitmap;
|
||||
static HBITMAP hAnnunBitmap;
|
||||
|
||||
static DWORD Pattern[16];
|
||||
static BYTE Buf[36];
|
||||
|
||||
static DWORD dwGrayMask;
|
||||
|
||||
static LARGE_INTEGER lLcdRef; // reference time for VBL counter
|
||||
static UINT uLcdTimerId = 0;
|
||||
|
||||
static BYTE byVblRef = 0; // VBL stop reference
|
||||
|
||||
static DWORD dwKMLColor[64] = // color table loaded by KML script
|
||||
{
|
||||
W,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,
|
||||
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
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
BITMAPINFOHEADER Lcd_bmih;
|
||||
RGBQUAD bmiColors[NOCOLORSGRAY];
|
||||
} bmiLcd =
|
||||
{
|
||||
{0x28,0/*x*/,0/*y*/,1,8,BI_RGB,0,0,0,NOCOLORSGRAY,0}
|
||||
};
|
||||
|
||||
static __inline VOID BuildPattern(VOID)
|
||||
{
|
||||
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) != 0);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID UpdateContrast(BYTE byContrast)
|
||||
{
|
||||
RGBQUAD c,b;
|
||||
INT i,nColors;
|
||||
|
||||
// table for max. 8 colors
|
||||
const INT nCAdj[] = { 0, 1, 1, 2, 1, 2, 2, 3 };
|
||||
|
||||
// when display is off use contrast 0
|
||||
if ((Chipset.IORam[BITOFFSET] & DON) == 0) byContrast = 0;
|
||||
|
||||
c = *(RGBQUAD*)&dwKMLColor[byContrast]; // pixel on color
|
||||
b = *(RGBQUAD*)&dwKMLColor[byContrast+32]; // pixel off color
|
||||
|
||||
// if background color is undefined, use color 0 for compatibility
|
||||
if (I == *(DWORD*)&b) b = *(RGBQUAD*)&dwKMLColor[0];
|
||||
|
||||
nColors = bGrayscale ? (NOCOLORSGRAY-1) : (NOCOLORSBW-1);
|
||||
|
||||
_ASSERT(nColors <= ARRAYSIZEOF(nCAdj)); // no. of colors must be smaller than entries in the gray color table
|
||||
|
||||
// fill color palette of bitmap
|
||||
for (i = 0; i <= nColors; ++i)
|
||||
{
|
||||
bmiLcd.bmiColors[i] = b;
|
||||
bmiLcd.bmiColors[i].rgbRed += ((INT) c.rgbRed - (INT) b.rgbRed) * nCAdj[i] / nCAdj[nColors];
|
||||
bmiLcd.bmiColors[i].rgbGreen += ((INT) c.rgbGreen - (INT) b.rgbGreen) * nCAdj[i] / nCAdj[nColors];
|
||||
bmiLcd.bmiColors[i].rgbBlue += ((INT) c.rgbBlue - (INT) b.rgbBlue) * nCAdj[i] / nCAdj[nColors];
|
||||
}
|
||||
|
||||
// update palette information
|
||||
_ASSERT(hLcdDC);
|
||||
SetDIBColorTable(hLcdDC,0,ARRAYSIZEOF(bmiLcd.bmiColors),bmiLcd.bmiColors);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue)
|
||||
{
|
||||
dwKMLColor[nId&0x3F] = ((nRed&0xFF)<<16)|((nGreen&0xFF)<<8)|(nBlue&0xFF);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID SetLcdMode(BOOL bMode)
|
||||
{
|
||||
if ((bGrayscale = bMode))
|
||||
{
|
||||
// set pixel update mask
|
||||
dwGrayMask = GRAYMASK(NOCOLORSGRAY);
|
||||
GetLineCounter = GetLineCounterGray;
|
||||
StartDisplay = StartDisplayGray;
|
||||
StopDisplay = StopDisplayGray;
|
||||
}
|
||||
else
|
||||
{
|
||||
// set pixel update mask
|
||||
dwGrayMask = GRAYMASK(NOCOLORSBW);
|
||||
GetLineCounter = GetLineCounterBW;
|
||||
StartDisplay = StartDisplayBW;
|
||||
StopDisplay = StopDisplayBW;
|
||||
}
|
||||
UpdateContrast(Chipset.contrast);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID CreateLcdBitmap(VOID)
|
||||
{
|
||||
// create LCD bitmap
|
||||
bmiLcd.Lcd_bmih.biWidth = LCD_ROW;
|
||||
bmiLcd.Lcd_bmih.biHeight = -SCREENHEIGHT; // CdB for HP: add 64/80 line display for apples
|
||||
_ASSERT(hLcdDC == NULL);
|
||||
VERIFY(hLcdDC = CreateCompatibleDC(hWindowDC));
|
||||
VERIFY(hLcdBitmap = CreateDIBSection(hWindowDC,(BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS,(VOID **)&pbyLcd,NULL,0));
|
||||
hLcdBitmap = (HBITMAP) SelectObject(hLcdDC,hLcdBitmap);
|
||||
_ASSERT(hPalette != NULL);
|
||||
SelectPalette(hLcdDC,hPalette,FALSE); // set palette for LCD DC
|
||||
RealizePalette(hLcdDC); // realize palette
|
||||
BuildPattern(); // build Nibble -> DIB mask pattern
|
||||
SetLcdMode(bGrayscale); // init display update function pointer
|
||||
return;
|
||||
}
|
||||
|
||||
VOID DestroyLcdBitmap(VOID)
|
||||
{
|
||||
// set contrast palette to startup colors
|
||||
WORD i = 0; dwKMLColor[i++] = W;
|
||||
while (i < 32) dwKMLColor[i++] = B;
|
||||
while (i < 64) dwKMLColor[i++] = I;
|
||||
|
||||
GetLineCounter = NULL;
|
||||
StartDisplay = NULL;
|
||||
StopDisplay = NULL;
|
||||
|
||||
if (hLcdDC != NULL)
|
||||
{
|
||||
// destroy LCD bitmap
|
||||
DeleteObject(SelectObject(hLcdDC,hLcdBitmap));
|
||||
DeleteDC(hLcdDC);
|
||||
hLcdDC = NULL;
|
||||
hLcdBitmap = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL CreateMainBitmap(LPCTSTR szFilename)
|
||||
{
|
||||
_ASSERT(hWindowDC != NULL);
|
||||
VERIFY(hMainDC = CreateCompatibleDC(hWindowDC));
|
||||
if (hMainDC == NULL) return FALSE; // quit if failed
|
||||
hMainBitmap = LoadBitmapFile(szFilename);
|
||||
if (hMainBitmap == NULL)
|
||||
{
|
||||
DeleteDC(hMainDC);
|
||||
hMainDC = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
hMainBitmap = (HBITMAP) SelectObject(hMainDC,hMainBitmap);
|
||||
_ASSERT(hPalette != NULL);
|
||||
VERIFY(SelectPalette(hMainDC,hPalette,FALSE));
|
||||
RealizePalette(hMainDC);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID DestroyMainBitmap(VOID)
|
||||
{
|
||||
if (hMainDC != NULL)
|
||||
{
|
||||
// destroy Main bitmap
|
||||
DeleteObject(SelectObject(hMainDC,hMainBitmap));
|
||||
DeleteDC(hMainDC);
|
||||
hMainDC = NULL;
|
||||
hMainBitmap = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// load annunciator bitmap
|
||||
//
|
||||
BOOL CreateAnnunBitmap(LPCTSTR szFilename)
|
||||
{
|
||||
_ASSERT(hWindowDC != NULL);
|
||||
VERIFY(hAnnunDC = CreateCompatibleDC(hWindowDC));
|
||||
if (hAnnunDC == NULL) return FALSE; // quit if failed
|
||||
hAnnunBitmap = LoadBitmapFile(szFilename);
|
||||
if (hAnnunBitmap == NULL)
|
||||
{
|
||||
DeleteDC(hAnnunDC);
|
||||
hAnnunDC = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
hAnnunBitmap = (HBITMAP) SelectObject(hAnnunDC,hAnnunBitmap);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// destroy annunciator bitmap
|
||||
//
|
||||
VOID DestroyAnnunBitmap(VOID)
|
||||
{
|
||||
if (hAnnunDC != NULL)
|
||||
{
|
||||
VERIFY(DeleteObject(SelectObject(hAnnunDC,hAnnunBitmap)));
|
||||
DeleteDC(hAnnunDC);
|
||||
hAnnunDC = NULL;
|
||||
hAnnunBitmap = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//****************
|
||||
//*
|
||||
//* LCD functions
|
||||
//*
|
||||
//****************
|
||||
|
||||
VOID UpdateDisplayPointers(VOID)
|
||||
{
|
||||
EnterCriticalSection(&csLcdLock);
|
||||
{
|
||||
#if defined DEBUG_DISPLAY
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("%.5lx: Update Display Pointer\n"),Chipset.pc);
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
// calculate display width
|
||||
Chipset.width = (34 + Chipset.loffset + (Chipset.boffset / 4) * 2) & 0xFFFFFFFE;
|
||||
Chipset.end1 = Chipset.start1 + MAINSCREENHEIGHT * Chipset.width;
|
||||
if (Chipset.end1 < Chipset.start1)
|
||||
{
|
||||
// calculate first address of main display
|
||||
Chipset.start12 = Chipset.end1 - Chipset.width;
|
||||
// calculate last address of main display
|
||||
Chipset.end1 = Chipset.start1 - Chipset.width;
|
||||
}
|
||||
else
|
||||
{
|
||||
Chipset.start12 = Chipset.start1;
|
||||
}
|
||||
Chipset.end2 = Chipset.start2 + MENUHEIGHT * 34;
|
||||
}
|
||||
LeaveCriticalSection(&csLcdLock);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID UpdateMainDisplay(VOID)
|
||||
{
|
||||
UINT x, y;
|
||||
BYTE *p = pbyLcd+(Chipset.d0size*LCD_ROW); // CdB for HP: add 64/80 line display for apples
|
||||
DWORD d = Chipset.start1;
|
||||
|
||||
#if defined DEBUG_DISPLAY
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("%.5lx: Update Main Display\n"),Chipset.pc);
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(Chipset.IORam[BITOFFSET]&DON))
|
||||
{
|
||||
ZeroMemory(pbyLcd, LCD_ROW * SCREENHEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < MAINSCREENHEIGHT; ++y)
|
||||
{
|
||||
Npeek(Buf,d,36);
|
||||
for (x=0; x<36; ++x) // every 4 pixel
|
||||
{
|
||||
DIBPIXEL4(p,Pattern[Buf[x]]);
|
||||
// check for display buffer overflow
|
||||
_ASSERT(p <= pbyLcd + LCD_ROW * SCREENHEIGHT);
|
||||
}
|
||||
d+=Chipset.width;
|
||||
}
|
||||
}
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
// CdB for HP: add 64/80 line display for apples
|
||||
StretchBlt(hWindowDC, nLcdX, nLcdY+Chipset.d0size*nLcdZoom, 131*nLcdZoom*nGdiXZoom, MAINSCREENHEIGHT*nLcdZoom*nGdiYZoom,
|
||||
hLcdDC, Chipset.boffset, Chipset.d0size, 131, MAINSCREENHEIGHT, SRCCOPY);
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID UpdateMenuDisplay(VOID)
|
||||
{
|
||||
UINT x, y;
|
||||
BYTE *p;
|
||||
DWORD d = Chipset.start2;
|
||||
|
||||
#if defined DEBUG_DISPLAY
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("%.5lx: Update Menu Display\n"),Chipset.pc);
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(Chipset.IORam[BITOFFSET]&DON)) return;
|
||||
if (MENUHEIGHT==0) return; // menu disabled
|
||||
|
||||
// calculate bitmap offset
|
||||
p = pbyLcd + ((Chipset.d0size+MAINSCREENHEIGHT)*LCD_ROW); // CdB for HP: add 64/80 line display for apples
|
||||
for (y = 0; y < MENUHEIGHT; ++y)
|
||||
{
|
||||
Npeek(Buf,d,34); // 34 nibbles are viewed
|
||||
for (x=0; x<34; ++x) // every 4 pixel
|
||||
{
|
||||
DIBPIXEL4(p,Pattern[Buf[x]]);
|
||||
// check for display buffer overflow
|
||||
_ASSERT(p <= pbyLcd + LCD_ROW * SCREENHEIGHT);
|
||||
}
|
||||
// adjust pointer to 36 DIBPIXEL drawing calls
|
||||
p += (36-34) * sizeof(DWORD);
|
||||
d+=34;
|
||||
}
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
// CdB for HP: add 64/80 line display for apples
|
||||
StretchBlt(hWindowDC,
|
||||
nLcdX, nLcdY+(MAINSCREENHEIGHT+Chipset.d0size)*nLcdZoom*nGdiYZoom,
|
||||
131*nLcdZoom*nGdiXZoom, MENUHEIGHT*nLcdZoom*nGdiYZoom,
|
||||
hLcdDC,
|
||||
0, (MAINSCREENHEIGHT+Chipset.d0size),
|
||||
131, MENUHEIGHT,
|
||||
SRCCOPY);
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
return;
|
||||
}
|
||||
|
||||
// CdB for HP: add header management
|
||||
VOID RefreshDisp0()
|
||||
{
|
||||
UINT x, y;
|
||||
BYTE *p;
|
||||
BYTE* d = Chipset.d0memory;
|
||||
|
||||
#if defined DEBUG_DISPLAY
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("%.5lx: Update header Display\n"),Chipset.pc);
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(Chipset.IORam[BITOFFSET]&DON)) return;
|
||||
|
||||
// calculate bitmap offset
|
||||
p = pbyLcd;
|
||||
for (y = 0; y<Chipset.d0size; ++y)
|
||||
{
|
||||
memcpy(Buf,d,34); // 34 nibbles are viewed
|
||||
for (x=0; x<36; ++x) // every 4 pixel
|
||||
{
|
||||
DIBPIXEL4(p,Pattern[Buf[x]]);
|
||||
}
|
||||
d+=34;
|
||||
}
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
StretchBlt(hWindowDC, nLcdX, nLcdY,
|
||||
131*nLcdZoom*nGdiXZoom, Chipset.d0size*nLcdZoom*nGdiYZoom,
|
||||
hLcdDC, Chipset.d0offset, 0, 131, Chipset.d0size, SRCCOPY);
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
|
||||
{
|
||||
UINT x0, x;
|
||||
UINT y0, y;
|
||||
DWORD *p;
|
||||
|
||||
INT lWidth = abs(Chipset.width); // display width
|
||||
|
||||
if (bGrayscale) return; // no direct writing in grayscale mode
|
||||
|
||||
#if defined DEBUG_DISPLAY
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("%.5lx: Write Main Display %x,%u\n"),Chipset.pc,d,s);
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(Chipset.IORam[BITOFFSET]&DON)) // display off
|
||||
return; // no drawing
|
||||
|
||||
if (MAINSCREENHEIGHT == 0) return; // menu disabled
|
||||
|
||||
d -= Chipset.start1; // nibble offset to DISPADDR (start of display)
|
||||
y0 = y = (d / lWidth) + Chipset.d0size; // bitmap row
|
||||
x0 = x = d % lWidth; // bitmap coloumn
|
||||
p = (DWORD*)(pbyLcd + y0*LCD_ROW + x0*sizeof(*p));
|
||||
|
||||
// outside main display area
|
||||
// _ASSERT(y0 >= (INT)Chipset.d0size && y0 < (INT)(MAINSCREENHEIGHT+Chipset.d0size));
|
||||
if (!(y0 >= (INT)Chipset.d0size && y0 < (INT)(MAINSCREENHEIGHT+Chipset.d0size))) return;
|
||||
|
||||
while (s--) // loop for nibbles to write
|
||||
{
|
||||
if (x<36) // only fill visible area
|
||||
{
|
||||
*p = Pattern[*a];
|
||||
}
|
||||
++a; // next value to write
|
||||
++x; // next x position
|
||||
if (((INT) x==lWidth)&&s) // end of display line
|
||||
{
|
||||
x = 0; // first coloumn
|
||||
++y; // next row
|
||||
if (y == (INT) MAINSCREENHEIGHT+Chipset.d0size) break;
|
||||
// recalculate bitmap memory position of new line
|
||||
p = (DWORD*) (pbyLcd+y*LCD_ROW); // CdB for HP: add 64/80 line display for apples
|
||||
}
|
||||
else
|
||||
p++;
|
||||
}
|
||||
if (y==y0) y++;
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
StretchBlt(hWindowDC, nLcdX, nLcdY+y0*nLcdZoom*nGdiYZoom,
|
||||
131*nLcdZoom*nGdiXZoom, (y-y0)*nLcdZoom*nGdiYZoom,
|
||||
hLcdDC, Chipset.boffset, y0, 131, y-y0, SRCCOPY); // CdB for HP: add 64/80 line display for apples
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
|
||||
{
|
||||
UINT x0, x;
|
||||
UINT y0, y;
|
||||
DWORD *p;
|
||||
|
||||
if (bGrayscale) return; // no direct writing in grayscale mode
|
||||
|
||||
#if defined DEBUG_DISPLAY
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("%.5lx: Write Menu Display %x,%u\n"),Chipset.pc,d,s);
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(Chipset.IORam[BITOFFSET]&DON)) return;
|
||||
if (MENUHEIGHT == 0) return; // menu disabled
|
||||
|
||||
d -= Chipset.start2;
|
||||
y0 = y = (d / 34) + MAINSCREENHEIGHT+Chipset.d0size; // bitmap row
|
||||
x0 = x = d % 34;
|
||||
p = (DWORD*)(pbyLcd + y0*LCD_ROW + x0*sizeof(*p));
|
||||
|
||||
// outside menu display area
|
||||
// _ASSERT(y0 >= (INT)(Chipset.d0size+MAINSCREENHEIGHT) && y0 < (INT)(SCREENHEIGHT));
|
||||
if (!(y0 >= (UINT)(Chipset.d0size+MAINSCREENHEIGHT) && y0 < (UINT)(SCREENHEIGHT))) return;
|
||||
|
||||
while (s--) // loop for nibbles to write
|
||||
{
|
||||
if (x<36) // only fill visible area
|
||||
{
|
||||
*p = Pattern[*a];
|
||||
}
|
||||
a++; // next value to write
|
||||
x++; // next x position
|
||||
if ((x==34)&&s) // end of display line
|
||||
{
|
||||
x = 0; // first coloumn
|
||||
y++; // next row
|
||||
if (y == SCREENHEIGHTREAL) break;
|
||||
// recalculate bitmap memory position of new line
|
||||
p=(DWORD*)(pbyLcd+y*LCD_ROW); // CdB for HP: add 64/80 ligne display for apples
|
||||
} else p++;
|
||||
}
|
||||
if (y==y0) y++;
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
StretchBlt(hWindowDC, nLcdX, nLcdY+y0*nLcdZoom*nGdiYZoom,
|
||||
(131*nLcdZoom)*nGdiXZoom, (y-y0)*nLcdZoom*nGdiYZoom,
|
||||
hLcdDC, 0, y0, 131, y-y0, SRCCOPY); // CdB for HP: add 64/80 line display for apples
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID UpdateAnnunciators(VOID)
|
||||
{
|
||||
BYTE c;
|
||||
|
||||
c = (BYTE)(Chipset.IORam[ANNCTRL] | (Chipset.IORam[ANNCTRL+1]<<4));
|
||||
// switch annunciators off if timer stopped
|
||||
if ((c & AON) == 0 || (Chipset.IORam[TIMER2_CTRL] & RUN) == 0)
|
||||
c = 0;
|
||||
|
||||
DrawAnnunciator(1,c&LA1);
|
||||
DrawAnnunciator(2,c&LA2);
|
||||
DrawAnnunciator(3,c&LA3);
|
||||
DrawAnnunciator(4,c&LA4);
|
||||
DrawAnnunciator(5,c&LA5);
|
||||
DrawAnnunciator(6,c&LA6);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID ResizeWindow(VOID)
|
||||
{
|
||||
if (hWnd != NULL) // if window created
|
||||
{
|
||||
RECT rectWindow;
|
||||
RECT rectClient;
|
||||
|
||||
rectWindow.left = 0;
|
||||
rectWindow.top = 0;
|
||||
rectWindow.right = nBackgroundW;
|
||||
rectWindow.bottom = nBackgroundH;
|
||||
|
||||
AdjustWindowRect(&rectWindow,
|
||||
(DWORD) GetWindowLongPtr(hWnd,GWL_STYLE),
|
||||
GetMenu(hWnd) != NULL || IsRectEmpty(&rectWindow));
|
||||
SetWindowPos(hWnd, bAlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0,
|
||||
rectWindow.right - rectWindow.left,
|
||||
rectWindow.bottom - rectWindow.top,
|
||||
SWP_NOMOVE);
|
||||
|
||||
// check if menu bar wrapped to two or more rows
|
||||
GetClientRect(hWnd, &rectClient);
|
||||
if (rectClient.bottom < (LONG) nBackgroundH)
|
||||
{
|
||||
rectWindow.bottom += (nBackgroundH - rectClient.bottom);
|
||||
SetWindowPos (hWnd, NULL, 0, 0,
|
||||
rectWindow.right - rectWindow.left,
|
||||
rectWindow.bottom - rectWindow.top,
|
||||
SWP_NOMOVE | SWP_NOZORDER);
|
||||
}
|
||||
|
||||
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||
{
|
||||
_ASSERT(hWindowDC); // move origin of destination window
|
||||
VERIFY(SetWindowOrgEx(hWindowDC, nBackgroundX, nBackgroundY, NULL));
|
||||
GdiFlush();
|
||||
}
|
||||
LeaveCriticalSection(&csGDILock);
|
||||
InvalidateRect(hWnd,NULL,TRUE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//################
|
||||
//#
|
||||
//# functions for gray scale implementation
|
||||
//#
|
||||
//################
|
||||
|
||||
// main display update routine
|
||||
static VOID CALLBACK LcdProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
|
||||
{
|
||||
EnterCriticalSection(&csLcdLock);
|
||||
{
|
||||
UpdateMainDisplay(); // update display
|
||||
UpdateMenuDisplay();
|
||||
RefreshDisp0(); // CdB for HP: add header management
|
||||
}
|
||||
LeaveCriticalSection(&csLcdLock);
|
||||
|
||||
QueryPerformanceCounter(&lLcdRef); // actual time
|
||||
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(uEventId);
|
||||
UNREFERENCED_PARAMETER(uMsg);
|
||||
UNREFERENCED_PARAMETER(dwUser);
|
||||
UNREFERENCED_PARAMETER(dw1);
|
||||
UNREFERENCED_PARAMETER(dw2);
|
||||
}
|
||||
|
||||
// LCD line counter calculation
|
||||
static BYTE GetLineCounterGray(VOID)
|
||||
{
|
||||
LARGE_INTEGER lLC;
|
||||
BYTE byTime;
|
||||
|
||||
if (uLcdTimerId == 0) // display off
|
||||
return ((Chipset.IORam[LINECOUNT+1] & (LC5|LC4)) << 4) | Chipset.IORam[LINECOUNT];
|
||||
|
||||
QueryPerformanceCounter(&lLC); // get elapsed time since display update
|
||||
|
||||
// elapsed ticks so far
|
||||
byTime = (BYTE) (((lLC.QuadPart - lLcdRef.QuadPart) << 12) / lFreq.QuadPart);
|
||||
|
||||
if (byTime > 0x3F) byTime = 0x3F; // all counts made
|
||||
|
||||
return 0x3F - byTime; // update display between VBL counter 0x3F-0x3E
|
||||
}
|
||||
|
||||
static VOID StartDisplayGray(BYTE byInitial)
|
||||
{
|
||||
if (uLcdTimerId) // LCD update timer running
|
||||
return; // -> quit
|
||||
|
||||
if (Chipset.IORam[BITOFFSET]&DON) // display on?
|
||||
{
|
||||
QueryPerformanceCounter(&lLcdRef); // actual time of top line
|
||||
|
||||
// adjust startup counter to get the right VBL value
|
||||
_ASSERT(byInitial <= 0x3F); // line counter value 0 - 63
|
||||
lLcdRef.QuadPart -= ((LONGLONG) (0x3F - byInitial) * lFreq.QuadPart) >> 12;
|
||||
|
||||
VERIFY(uLcdTimerId = timeSetEvent(DISPLAY_FREQ,0,(LPTIMECALLBACK)&LcdProc,0,TIME_PERIODIC));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static VOID StopDisplayGray(VOID)
|
||||
{
|
||||
BYTE a[2];
|
||||
ReadIO(a,LINECOUNT,2,TRUE); // update VBL at display off time
|
||||
|
||||
if (uLcdTimerId == 0) // timer stopped
|
||||
return; // -> quit
|
||||
|
||||
timeKillEvent(uLcdTimerId); // stop display update
|
||||
uLcdTimerId = 0; // set flag display update stopped
|
||||
|
||||
EnterCriticalSection(&csLcdLock); // update to last condition
|
||||
{
|
||||
UpdateMainDisplay(); // update display
|
||||
UpdateMenuDisplay();
|
||||
RefreshDisp0(); // CdB for HP: add header management
|
||||
}
|
||||
LeaveCriticalSection(&csLcdLock);
|
||||
return;
|
||||
}
|
||||
//################
|
||||
//#
|
||||
//# functions for black and white implementation
|
||||
//#
|
||||
//################
|
||||
|
||||
// LCD line counter calculation in BW mode
|
||||
static BYTE F4096Hz(VOID) // get a 6 bit 4096Hz down counter value
|
||||
{
|
||||
LARGE_INTEGER lLC;
|
||||
|
||||
QueryPerformanceCounter(&lLC); // get counter value
|
||||
|
||||
// calculate 4096 Hz frequency down counter value
|
||||
return -(BYTE)(((lLC.QuadPart - lAppStart.QuadPart) << 12) / lFreq.QuadPart) & 0x3F;
|
||||
}
|
||||
|
||||
static BYTE GetLineCounterBW(VOID) // get line counter value
|
||||
{
|
||||
_ASSERT(byVblRef < 0x40);
|
||||
return (0x40 + F4096Hz() - byVblRef) & 0x3F;
|
||||
}
|
||||
|
||||
static VOID StartDisplayBW(BYTE byInitial)
|
||||
{
|
||||
// get positive VBL difference between now and stop time
|
||||
byVblRef = (0x40 + F4096Hz() - byInitial) & 0x3F;
|
||||
return;
|
||||
}
|
||||
|
||||
static VOID StopDisplayBW(VOID)
|
||||
{
|
||||
BYTE a[2];
|
||||
ReadIO(a,LINECOUNT,2,TRUE); // update VBL at display off time
|
||||
return;
|
||||
}
|
1592
app/src/main/cpp/DISRPL.C
Normal file
25
app/src/main/cpp/DISRPL.H
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* disrpl.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2008 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
|
||||
// RPL platform type
|
||||
#define RPL_P1 (1<<0) // Clamshell without RRP
|
||||
#define RPL_P2 (RPL_P1 | (1<<1)) // Pioneer / Clamshell
|
||||
#define RPL_P3 (RPL_P2 | (1<<2)) // Charlemagne
|
||||
#define RPL_P4 (RPL_P3 | (1<<3)) // Alcuin
|
||||
#define RPL_P5 (RPL_P4 | (1<<4)) // V'ger
|
||||
|
||||
extern DWORD dwRplPlatform; // RPL platform
|
||||
extern BOOL bRplViewName; // show entry point name
|
||||
extern BOOL bRplViewAddr; // show adress
|
||||
extern BOOL bRplViewBin; // show binary data
|
||||
extern BOOL bRplViewAsm; // show ASM code instead of hex data
|
||||
extern BYTE (*RplReadNibble)(DWORD *p); // read nibble function pointer
|
||||
extern DWORD RplSkipObject(DWORD dwAddr);
|
||||
extern LPTSTR RplDecodeObject(DWORD dwAddr, DWORD *pdwNxtAddr);
|
||||
extern LPTSTR RplCreateObjView(DWORD dwStartAddr, DWORD dwEndAddr, BOOL bSingleObj);
|
2288
app/src/main/cpp/EMU48.C
Normal file
459
app/src/main/cpp/EMU48.H
Normal file
|
@ -0,0 +1,459 @@
|
|||
/*
|
||||
* Emu48.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1995 Sebastien Carlier
|
||||
*
|
||||
*/
|
||||
#include "types.h"
|
||||
|
||||
#define HARDWARE "Yorke" // emulator hardware
|
||||
#define MODELS "26AEGPQSX" // valid calculator models
|
||||
#define APPLEHARD "2PQ" // Apple platform calculator models
|
||||
|
||||
#define ARRAYSIZEOF(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
// cards status
|
||||
#define PORT1_PRESENT ((cCurrentRomType=='S')?P1C:P2C)
|
||||
#define PORT1_WRITE ((cCurrentRomType=='S')?P1W:P2W)
|
||||
#define PORT2_PRESENT ((cCurrentRomType=='S')?P2C:P1C)
|
||||
#define PORT2_WRITE ((cCurrentRomType=='S')?P2W:P1W)
|
||||
|
||||
#define BINARYHEADER48 "HPHP48-W"
|
||||
#define BINARYHEADER49 "HPHP49-W"
|
||||
|
||||
#define BIN_FILTER "Port Data File (*.BIN)\0*.BIN\0All Files (*.*)\0*.*\0"
|
||||
#define HP_FILTER "HP Binary Object (*.HP;*.LIB)\0*.HP;*.LIB\0All Files (*.*)\0*.*\0"
|
||||
|
||||
#define CF_HPOBJ "CF_HPOBJ" // clipboard format for DDE
|
||||
|
||||
// CPU cycles in 16384 Hz time frame
|
||||
#define T2CYCLES ((cCurrentRomType=='S')?dwSXCycles:(cCurrentRomType=='G')?dwGXCycles:(cCurrentRomType=='P')?dwGPCycles:(cCurrentRomType=='Q')?dwGPCycles:dwG2Cycles) // CdB for HP: add apples
|
||||
|
||||
#define SM_RUN 0 // states of cpu emulation thread
|
||||
#define SM_INVALID 1
|
||||
#define SM_RETURN 2
|
||||
#define SM_SLEEP 3
|
||||
|
||||
#define S_ERR_NO 0 // stack errorcodes
|
||||
#define S_ERR_OBJECT 1
|
||||
#define S_ERR_BINARY 2
|
||||
#define S_ERR_ASCII 3
|
||||
|
||||
#define BAD_OB (0xFFFFFFFF) // bad object
|
||||
|
||||
#define NO_SERIAL "disabled" // port not open
|
||||
|
||||
#define HP_MNEMONICS FALSE // disassembler mnenomics mode
|
||||
#define CLASS_MNEMONICS TRUE
|
||||
|
||||
#define MACRO_OFF 0 // macro recorder off
|
||||
#define MACRO_NEW 1
|
||||
#define MACRO_PLAY 2
|
||||
|
||||
#define DISP_POINTER 0x01 // defines for display area
|
||||
#define DISP_MAIN 0x02
|
||||
#define DISP_MENUE 0x04
|
||||
#define DISP_ANNUN 0x08
|
||||
|
||||
#define ROMPAGESIZE (1<<12) // ROM dirty page size in nibbles
|
||||
|
||||
// window styles
|
||||
#define STYLE_TITLE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED)
|
||||
#define STYLE_NOTITLE (WS_POPUP|WS_SYSMENU|WS_MINIMIZEBOX|WS_CLIPSIBLINGS)
|
||||
|
||||
// WM_COPYDATA identifier
|
||||
#define CDID_FILENAME 1 // send file name
|
||||
|
||||
// macro to check for valid calculator model
|
||||
#define isModelValid(m) (m != 0 && strchr(MODELS,m) != NULL)
|
||||
#define isModelApple(m) (m != 0 && strchr(APPLEHARD,m) != NULL)
|
||||
|
||||
// values for mapping area
|
||||
enum MMUMAP { M_IO, M_ROM, M_RAM, M_P1, M_P2, M_BS };
|
||||
|
||||
// values for disassembler memory mapping modes
|
||||
enum MEM_MAPPING { MEM_MMU, MEM_NCE1, MEM_NCE2, MEM_CE1, MEM_CE2, MEM_NCE3 };
|
||||
|
||||
// Emu48.c
|
||||
extern HPALETTE hPalette;
|
||||
extern HPALETTE hOldPalette;
|
||||
extern HANDLE hEventShutdn;
|
||||
extern LPTSTR szAppName;
|
||||
extern LPTSTR szTopic;
|
||||
extern LPTSTR szTitle;
|
||||
extern CRITICAL_SECTION csGDILock;
|
||||
extern CRITICAL_SECTION csLcdLock;
|
||||
extern CRITICAL_SECTION csKeyLock;
|
||||
extern CRITICAL_SECTION csIOLock;
|
||||
extern CRITICAL_SECTION csT1Lock;
|
||||
extern CRITICAL_SECTION csT2Lock;
|
||||
extern CRITICAL_SECTION csTxdLock;
|
||||
extern CRITICAL_SECTION csRecvLock;
|
||||
extern CRITICAL_SECTION csSlowLock;
|
||||
extern CRITICAL_SECTION csDbgLock;
|
||||
extern INT nArgc;
|
||||
extern LPCTSTR *ppArgv;
|
||||
extern LARGE_INTEGER lFreq;
|
||||
extern LARGE_INTEGER lAppStart;
|
||||
extern DWORD idDdeInst;
|
||||
extern UINT uCF_HpObj;
|
||||
extern HINSTANCE hApp;
|
||||
extern HWND hWnd;
|
||||
extern HWND hDlgDebug;
|
||||
extern HWND hDlgFind;
|
||||
extern HWND hDlgProfile;
|
||||
extern HWND hDlgRplObjView;
|
||||
extern HDC hWindowDC;
|
||||
extern DWORD dwTColor;
|
||||
extern DWORD dwTColorTol;
|
||||
extern HRGN hRgn;
|
||||
extern HCURSOR hCursorArrow;
|
||||
extern HCURSOR hCursorHand;
|
||||
extern UINT uWaveDevId;
|
||||
extern DWORD dwWakeupDelay;
|
||||
extern BOOL bAutoSave;
|
||||
extern BOOL bAutoSaveOnExit;
|
||||
extern BOOL bSaveDefConfirm;
|
||||
extern BOOL bStartupBackup;
|
||||
extern BOOL bAlwaysDisplayLog;
|
||||
extern BOOL bLoadObjectWarning;
|
||||
extern BOOL bShowTitle;
|
||||
extern BOOL bShowMenu;
|
||||
extern BOOL bAlwaysOnTop;
|
||||
extern BOOL bActFollowsMouse;
|
||||
extern BOOL bClientWinMove;
|
||||
extern BOOL bSingleInstance;
|
||||
extern HANDLE hThread;
|
||||
extern VOID SetWindowTitle(LPCTSTR szString);
|
||||
extern VOID ForceForegroundWindow(HWND hWnd);
|
||||
extern VOID CopyItemsToClipboard(HWND hWnd);
|
||||
|
||||
// mru.c
|
||||
extern BOOL MruInit(UINT nNum);
|
||||
extern VOID MruCleanup(VOID);
|
||||
extern VOID MruAdd(LPCTSTR lpszEntry);
|
||||
extern VOID MruRemove(UINT nIndex);
|
||||
extern VOID MruMoveTop(UINT nIndex);
|
||||
extern UINT MruEntries(VOID);
|
||||
extern LPCTSTR MruFilename(UINT nIndex);
|
||||
extern VOID MruUpdateMenu(HMENU hMenu);
|
||||
extern VOID MruWriteList(VOID);
|
||||
extern VOID MruReadList(VOID);
|
||||
|
||||
// Settings.c
|
||||
extern VOID ReadSettings(VOID);
|
||||
extern VOID WriteSettings(VOID);
|
||||
extern VOID ReadLastDocument(LPTSTR szFileName, DWORD nSize);
|
||||
extern VOID WriteLastDocument(LPCTSTR szFilename);
|
||||
extern VOID ReadSettingsString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpDefault, LPTSTR lpData, DWORD dwSize);
|
||||
extern VOID WriteSettingsString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPTSTR lpData);
|
||||
extern INT ReadSettingsInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, INT nDefault);
|
||||
extern VOID WriteSettingsInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, INT nValue);
|
||||
extern VOID DelSettingsKey(LPCTSTR lpszSection, LPCTSTR lpszEntry);
|
||||
|
||||
// Display.c
|
||||
extern BOOL bGrayscale;
|
||||
extern UINT nBackgroundX;
|
||||
extern UINT nBackgroundY;
|
||||
extern UINT nBackgroundW;
|
||||
extern UINT nBackgroundH;
|
||||
extern UINT nLcdX;
|
||||
extern UINT nLcdY;
|
||||
extern UINT nLcdZoom;
|
||||
extern UINT nGdiXZoom;
|
||||
extern UINT nGdiYZoom;
|
||||
extern HDC hLcdDC;
|
||||
extern HDC hMainDC;
|
||||
extern HDC hAnnunDC;
|
||||
extern BYTE (*GetLineCounter)(VOID);
|
||||
extern VOID (*StartDisplay)(BYTE byInitial);
|
||||
extern VOID (*StopDisplay)(VOID);
|
||||
extern VOID UpdateContrast(BYTE byContrast);
|
||||
extern VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue);
|
||||
extern VOID SetLcdMode(BOOL bMode);
|
||||
extern VOID CreateLcdBitmap(VOID);
|
||||
extern VOID DestroyLcdBitmap(VOID);
|
||||
extern BOOL CreateMainBitmap(LPCTSTR szFilename);
|
||||
extern VOID DestroyMainBitmap(VOID);
|
||||
extern BOOL CreateAnnunBitmap(LPCTSTR szFilename);
|
||||
extern VOID DestroyAnnunBitmap(VOID);
|
||||
extern VOID UpdateDisplayPointers(VOID);
|
||||
extern VOID UpdateMainDisplay(VOID);
|
||||
extern VOID UpdateMenuDisplay(VOID);
|
||||
extern VOID RefreshDisp0(); // CdB for HP: add apples display management
|
||||
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 bEnableSlow;
|
||||
extern BOOL bRealSpeed;
|
||||
extern BOOL bKeySlow;
|
||||
extern BOOL bSoundSlow;
|
||||
extern UINT nOpcSlow;
|
||||
extern BOOL bCommInit;
|
||||
extern CHIPSET Chipset;
|
||||
extern TCHAR szSerialWire[16];
|
||||
extern TCHAR szSerialIr[16];
|
||||
extern DWORD dwSXCycles;
|
||||
extern DWORD dwGXCycles;
|
||||
extern DWORD dwGPCycles; // CdB for HP: add apples speed
|
||||
extern DWORD dwG2Cycles; // CdB for HP: add apples speed
|
||||
extern HANDLE hEventDebug;
|
||||
extern BOOL bDbgAutoStateCtrl;
|
||||
extern INT nDbgState;
|
||||
extern BOOL bDbgNOP3;
|
||||
extern BOOL bDbgCode;
|
||||
extern BOOL bDbgRPL;
|
||||
extern BOOL bDbgSkipInt;
|
||||
extern DWORD dwDbgStopPC;
|
||||
extern DWORD dwDbgRplPC;
|
||||
extern DWORD dwDbgRstkp;
|
||||
extern DWORD dwDbgRstk;
|
||||
extern DWORD *pdwInstrArray;
|
||||
extern WORD wInstrSize;
|
||||
extern WORD wInstrWp;
|
||||
extern WORD wInstrRp;
|
||||
extern VOID SuspendDebugger(VOID);
|
||||
extern VOID ResumeDebugger(VOID);
|
||||
extern VOID CheckSerial(VOID);
|
||||
extern VOID InitAdjustSpeed(VOID);
|
||||
extern VOID AdjKeySpeed(VOID);
|
||||
extern VOID SetSpeed(BOOL bAdjust);
|
||||
extern VOID UpdateKdnBit(VOID);
|
||||
extern BOOL WaitForSleepState(VOID);
|
||||
extern UINT SwitchToState(UINT nNewState);
|
||||
extern UINT WorkerThread(LPVOID pParam);
|
||||
|
||||
// Fetch.c
|
||||
extern VOID EvalOpcode(LPBYTE I);
|
||||
|
||||
// Files.c
|
||||
extern TCHAR szEmuDirectory[MAX_PATH];
|
||||
extern TCHAR szRomDirectory[MAX_PATH];
|
||||
extern TCHAR szCurrentDirectory[MAX_PATH];
|
||||
extern TCHAR szCurrentKml[MAX_PATH];
|
||||
extern TCHAR szBackupKml[MAX_PATH];
|
||||
extern TCHAR szCurrentFilename[MAX_PATH];
|
||||
extern TCHAR szBackupFilename[MAX_PATH];
|
||||
extern TCHAR szBufferFilename[MAX_PATH];
|
||||
extern TCHAR szPort2Filename[MAX_PATH];
|
||||
extern BOOL bDocumentAvail;
|
||||
extern BYTE cCurrentRomType;
|
||||
extern UINT nCurrentClass;
|
||||
extern LPBYTE Port0;
|
||||
extern LPBYTE Port1;
|
||||
extern LPBYTE Port2;
|
||||
extern LPBYTE pbyRom;
|
||||
extern BOOL bRomWriteable;
|
||||
extern DWORD dwRomSize;
|
||||
extern LPBYTE pbyRomDirtyPage;
|
||||
extern DWORD dwRomDirtyPageSize;
|
||||
extern WORD wRomCrc;
|
||||
extern LPBYTE pbyPort2;
|
||||
extern BOOL bPort2Writeable;
|
||||
extern BOOL bPort2IsShared;
|
||||
extern DWORD dwPort2Size;
|
||||
extern DWORD dwPort2Mask;
|
||||
extern WORD wPort2Crc;
|
||||
extern BOOL bBackup;
|
||||
extern VOID SetWindowLocation(HWND hWnd,INT nPosX,INT nPosY);
|
||||
extern DWORD GetCutPathName(LPCTSTR szFileName,LPTSTR szBuffer,DWORD dwBufferLength,INT nCutLength);
|
||||
extern VOID SetWindowPathTitle(LPCTSTR szFileName);
|
||||
extern VOID UpdatePatches(BOOL bPatch);
|
||||
extern BOOL PatchRom(LPCTSTR szFilename);
|
||||
extern BOOL CrcRom(WORD *pwChk);
|
||||
extern BOOL MapRom(LPCTSTR szFilename);
|
||||
extern VOID UnmapRom(VOID);
|
||||
extern BOOL CrcPort2(WORD *pwCrc);
|
||||
extern BOOL MapPort2(LPCTSTR szFilename);
|
||||
extern VOID UnmapPort2(VOID);
|
||||
extern VOID ResetDocument(VOID);
|
||||
extern BOOL NewDocument(VOID);
|
||||
extern BOOL OpenDocument(LPCTSTR 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(LPCTSTR lpstrFilter,LPCTSTR lpstrDefExt);
|
||||
extern BOOL GetSaveObjectFilename(LPCTSTR lpstrFilter,LPCTSTR lpstrDefExt);
|
||||
extern WORD WriteStack(UINT nStkLevel,LPBYTE lpBuf,DWORD dwSize);
|
||||
extern BOOL LoadObject(LPCTSTR szFilename);
|
||||
extern BOOL SaveObject(LPCTSTR szFilename);
|
||||
extern BOOL LoadIconFromFile(LPCTSTR szFilename);
|
||||
extern VOID LoadIconDefault(VOID);
|
||||
extern HBITMAP LoadBitmapFile(LPCTSTR szFilename);
|
||||
extern HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol);
|
||||
|
||||
// Timer.c
|
||||
extern VOID SetHP48Time(VOID);
|
||||
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 bFlashRomArray;
|
||||
extern BYTE disp;
|
||||
extern LPBYTE RMap[256];
|
||||
extern LPBYTE WMap[256];
|
||||
extern DWORD FlashROMAddr(DWORD d);
|
||||
extern VOID Map(BYTE a, BYTE b);
|
||||
extern VOID RomSwitch(DWORD adr);
|
||||
extern VOID Config(VOID);
|
||||
extern VOID Uncnfg(VOID);
|
||||
extern VOID Reset(VOID);
|
||||
extern VOID C_Eq_Id(VOID);
|
||||
extern enum MMUMAP MapData(DWORD d);
|
||||
extern VOID CpuReset(VOID);
|
||||
extern VOID Npeek(BYTE *a, DWORD d, UINT s);
|
||||
extern VOID Nread(BYTE *a, DWORD d, UINT s);
|
||||
extern VOID Nwrite(BYTE *a, DWORD d, UINT s);
|
||||
extern BYTE Read2(DWORD d);
|
||||
extern DWORD Read5(DWORD d);
|
||||
extern VOID Write5(DWORD d, DWORD n);
|
||||
extern VOID Write2(DWORD d, BYTE n);
|
||||
extern VOID IOBit(DWORD d, BYTE b, BOOL s);
|
||||
extern VOID ReadIO(BYTE *a, DWORD b, DWORD s, BOOL bUpdate);
|
||||
extern VOID WriteIO(BYTE *a, DWORD b, DWORD s);
|
||||
|
||||
// Lowbat.c
|
||||
extern BOOL bLowBatDisable;
|
||||
extern VOID StartBatMeasure(VOID);
|
||||
extern VOID StopBatMeasure(VOID);
|
||||
extern VOID GetBatteryState(BOOL *pbLBI, BOOL *pbVLBI);
|
||||
|
||||
// Keyboard.c
|
||||
extern DWORD dwKeyMinDelay;
|
||||
extern VOID ScanKeyboard(BOOL bActive, BOOL bReset);
|
||||
extern VOID KeyboardEvent(BOOL bPress, UINT out, UINT in);
|
||||
|
||||
// Keymacro.c
|
||||
extern INT nMacroState;
|
||||
extern INT nMacroTimeout;
|
||||
extern BOOL bMacroRealSpeed;
|
||||
extern DWORD dwMacroMinDelay;
|
||||
extern VOID KeyMacroRecord(BOOL bPress, UINT out, UINT in);
|
||||
extern LRESULT OnToolMacroNew(VOID);
|
||||
extern LRESULT OnToolMacroPlay(VOID);
|
||||
extern LRESULT OnToolMacroStop(VOID);
|
||||
extern LRESULT OnToolMacroSettings(VOID);
|
||||
|
||||
// Redeye.c
|
||||
extern VOID IrPrinter(BYTE c);
|
||||
|
||||
// Udp.c
|
||||
extern TCHAR szUdpServer[1024];
|
||||
extern WORD wUdpPort;
|
||||
extern VOID ResetUdp(VOID);
|
||||
extern BOOL SendByteUdp(BYTE byData);
|
||||
|
||||
// Stack.c
|
||||
extern BOOL bDetectClpObject;
|
||||
extern LRESULT OnStackCopy(VOID);
|
||||
extern LRESULT OnStackPaste(VOID);
|
||||
|
||||
// RPL.c
|
||||
extern BOOL RPL_GetSystemFlag(INT nFlag);
|
||||
extern DWORD RPL_SkipOb(DWORD d);
|
||||
extern DWORD RPL_ObjectSize(BYTE *o,DWORD s);
|
||||
extern DWORD RPL_CreateTemp(DWORD l,BOOL bGarbageCol);
|
||||
extern UINT RPL_Depth(VOID);
|
||||
extern DWORD RPL_Pick(UINT l);
|
||||
extern VOID RPL_Replace(DWORD n);
|
||||
extern VOID RPL_Push(UINT l,DWORD n);
|
||||
|
||||
// External.c
|
||||
extern VOID External(CHIPSET* w);
|
||||
extern VOID RCKBp(CHIPSET* w);
|
||||
|
||||
// SndEnum.c
|
||||
extern VOID SetSoundDeviceList(HWND hWnd,UINT uDeviceID);
|
||||
|
||||
// Sound.c
|
||||
extern DWORD dwWaveVol;
|
||||
extern DWORD dwWaveTime;
|
||||
extern BOOL SoundAvailable(UINT uDeviceID);
|
||||
extern BOOL SoundGetDeviceID(UINT *puDeviceID);
|
||||
extern BOOL SoundOpen(UINT uDeviceID);
|
||||
extern VOID SoundClose(VOID);
|
||||
extern VOID SoundOut(CHIPSET* w, WORD wOut);
|
||||
extern VOID SoundBeep(DWORD dwFrequency, DWORD dwDuration);
|
||||
|
||||
// DDEserv.c
|
||||
extern HDDEDATA CALLBACK DdeCallback(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, DWORD, DWORD);
|
||||
|
||||
// Dismem.c
|
||||
extern BOOL SetMemRomType(BYTE cCurrentRomType);
|
||||
extern BOOL SetMemMapType(enum MEM_MAPPING eType);
|
||||
extern enum MEM_MAPPING GetMemMapType(VOID);
|
||||
extern BOOL GetMemAvail(enum MEM_MAPPING eType);
|
||||
extern DWORD GetMemDataSize(VOID);
|
||||
extern DWORD GetMemDataMask(VOID);
|
||||
extern BYTE GetMemNib(DWORD *p);
|
||||
extern VOID GetMemPeek(BYTE *a, DWORD d, UINT s);
|
||||
|
||||
// Disasm.c
|
||||
extern BOOL disassembler_mode;
|
||||
extern BOOL disassembler_symb;
|
||||
extern DWORD disassemble(DWORD addr, LPTSTR out);
|
||||
|
||||
// Symbfile.c
|
||||
extern BOOL RplTableEmpty(VOID);
|
||||
extern BOOL RplLoadTable(LPCTSTR lpszFilename);
|
||||
extern VOID RplDeleteTable(VOID);
|
||||
extern LPCTSTR RplGetName(DWORD dwAddr);
|
||||
extern BOOL RplGetAddr(LPCTSTR lpszName, DWORD *pdwAddr);
|
||||
|
||||
// Serial.c
|
||||
extern BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort);
|
||||
extern VOID CommClose(VOID);
|
||||
extern VOID CommSetBaud(VOID);
|
||||
extern BOOL UpdateUSRQ(VOID);
|
||||
extern VOID CommTxBRK(VOID);
|
||||
extern VOID CommTransmit(VOID);
|
||||
extern VOID CommReceive(VOID);
|
||||
|
||||
// Cursor.c
|
||||
extern HCURSOR CreateHandCursor(VOID);
|
||||
|
||||
#if defined _USRDLL // DLL version
|
||||
// Emu48dll.c
|
||||
extern VOID (CALLBACK *pEmuDocumentNotify)(LPCTSTR lpszFilename);
|
||||
extern BOOL DLLCreateWnd(LPCTSTR lpszFilename, LPCTSTR lpszPort2Name);
|
||||
extern BOOL DLLDestroyWnd(VOID);
|
||||
|
||||
// Symbfile.c
|
||||
#define RplGetName(a) NULL // for linking
|
||||
#endif
|
||||
|
||||
// Message Boxes
|
||||
static __inline int InfoMessage(LPCTSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND);}
|
||||
static __inline int AbortMessage(LPCTSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);}
|
||||
static __inline int YesNoMessage(LPCTSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_YESNO|MB_ICONEXCLAMATION|MB_SETFOREGROUND);}
|
||||
static __inline int YesNoCancelMessage(LPCTSTR szMessage,UINT uStyle) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_YESNOCANCEL|MB_ICONEXCLAMATION|MB_SETFOREGROUND|uStyle);}
|
||||
|
||||
// Missing Win32 API calls
|
||||
static __inline LPTSTR DuplicateString(LPCTSTR szString)
|
||||
{
|
||||
UINT uLength = lstrlen(szString) + 1;
|
||||
LPTSTR szDup = (LPTSTR) malloc(uLength*sizeof(szDup[0]));
|
||||
lstrcpy(szDup,szString);
|
||||
return szDup;
|
||||
}
|
||||
|
||||
#define SCREENHEIGHT (cCurrentRomType=='Q' ? 80 : 64) // CdB for HP: add apples display management
|
||||
#define SCREENHEIGHTREAL ((cCurrentRomType=='Q') ? (80-Chipset.d0size) : 64)
|
||||
#define MAINSCREENHEIGHT (((Chipset.lcounter) == 0) ? SCREENHEIGHTREAL : SCREENHEIGHTREAL-64+((Chipset.lcounter)+1))
|
||||
#define MENUHEIGHT (Chipset.lcounter==0?0:64-(Chipset.lcounter+1))
|
638
app/src/main/cpp/EMU48DLL.C
Normal file
|
@ -0,0 +1,638 @@
|
|||
/*
|
||||
* Emu48Dll.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2000 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pch.h"
|
||||
#include "resource.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h"
|
||||
#include "kml.h"
|
||||
#include "debugger.h"
|
||||
|
||||
#include "Emu48Dll.h"
|
||||
|
||||
static LPCTSTR pArgv[3]; // command line memory
|
||||
static ATOM classAtom = INVALID_ATOM; // window class atom
|
||||
static HACCEL hAccel; // accelerator table
|
||||
|
||||
static HSZ hszService, hszTopic; // variables for DDE server
|
||||
|
||||
extern LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
// callback function notify document filename
|
||||
VOID (CALLBACK *pEmuDocumentNotify)(LPCTSTR lpszFilename) = NULL;
|
||||
|
||||
// callback function notify Emu48 closed
|
||||
static VOID (CALLBACK *pEmuClose)(VOID) = NULL;
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Public internal functions
|
||||
//#
|
||||
//################
|
||||
|
||||
//
|
||||
// DllMain
|
||||
//
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
|
||||
{
|
||||
BOOL bSucc = TRUE;
|
||||
|
||||
if (fdwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
WNDCLASS wc;
|
||||
|
||||
wc.style = CS_BYTEALIGNCLIENT;
|
||||
wc.lpfnWndProc = (WNDPROC)MainWndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = hinstDLL;
|
||||
wc.hIcon = LoadIcon(hApp, MAKEINTRESOURCE(IDI_EMU48));
|
||||
wc.hCursor = NULL;
|
||||
wc.hbrBackground = NULL;
|
||||
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
|
||||
wc.lpszClassName = _T("CEmu48");
|
||||
VERIFY(bSucc = ((classAtom = RegisterClass(&wc)) != INVALID_ATOM));
|
||||
}
|
||||
|
||||
if (fdwReason == DLL_PROCESS_DETACH)
|
||||
{
|
||||
if (INVALID_ATOM != classAtom)
|
||||
{
|
||||
VERIFY(UnregisterClass(MAKEINTATOM(classAtom),hinstDLL));
|
||||
classAtom = INVALID_ATOM;
|
||||
}
|
||||
}
|
||||
|
||||
return bSucc;
|
||||
UNREFERENCED_PARAMETER(lpvReserved);
|
||||
}
|
||||
|
||||
//
|
||||
// DLLCreateWnd
|
||||
//
|
||||
BOOL DLLCreateWnd(LPCTSTR lpszFilename, LPCTSTR lpszPort2Name)
|
||||
{
|
||||
typedef DWORD (WINAPI *LPFN_STIP)(HANDLE hThread,DWORD dwIdealProcessor);
|
||||
|
||||
RECT rectWindow;
|
||||
DWORD dwThreadId;
|
||||
LPFN_STIP fnSetThreadIdealProcessor;
|
||||
DWORD dwProcessor;
|
||||
|
||||
BOOL bFileExist = FALSE; // state file don't exist
|
||||
|
||||
hApp = GetModuleHandle(_T("EMU48.DLL"));
|
||||
if (hApp == NULL) return TRUE;
|
||||
|
||||
nArgc = 1; // no argument
|
||||
if (lpszFilename[0])
|
||||
{
|
||||
// try to open given filename
|
||||
HANDLE hFile = CreateFile(lpszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (bFileExist = (hFile != INVALID_HANDLE_VALUE))
|
||||
CloseHandle(hFile);
|
||||
|
||||
ppArgv = pArgv; // command line arguments
|
||||
nArgc = 2; // one argument: state file, no port2 file
|
||||
pArgv[1] = lpszFilename; // name of state file
|
||||
|
||||
if (lpszPort2Name) // port2 filename
|
||||
{
|
||||
nArgc = 3; // two arguments: state file, port2 file
|
||||
pArgv[2] = lpszPort2Name; // name of port2 file
|
||||
}
|
||||
}
|
||||
|
||||
// read emulator settings
|
||||
GetCurrentDirectory(ARRAYSIZEOF(szCurrentDirectory),szCurrentDirectory);
|
||||
ReadSettings();
|
||||
|
||||
// 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(MAKEINTATOM(classAtom),_T("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)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VERIFY(hAccel = LoadAccelerators(hApp,MAKEINTRESOURCE(IDR_MENU)));
|
||||
|
||||
// remove debugger menu entry from resource
|
||||
DeleteMenu(GetMenu(hWnd),ID_TOOL_DEBUG,MF_BYCOMMAND);
|
||||
|
||||
// initialization
|
||||
EmuClearAllBreakpoints();
|
||||
QueryPerformanceFrequency(&lFreq); // init high resolution counter
|
||||
|
||||
szCurrentKml[0] = 0; // no KML file selected
|
||||
SetSpeed(bRealSpeed); // set speed
|
||||
MruInit(0); // init MRU entries
|
||||
|
||||
// create shutdown auto event handle
|
||||
hEventShutdn = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||
if (hEventShutdn == NULL)
|
||||
{
|
||||
DestroyWindow(hWnd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// create debugger auto event handle
|
||||
hEventDebug = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||
if (hEventDebug == NULL)
|
||||
{
|
||||
CloseHandle(hEventShutdn); // close shutdown event handle
|
||||
DestroyWindow(hWnd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
nState = SM_RUN; // init state must be <> nNextState
|
||||
nNextState = SM_INVALID; // go into invalid state
|
||||
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, NULL, CREATE_SUSPENDED, &dwThreadId);
|
||||
if (hThread == NULL)
|
||||
{
|
||||
CloseHandle(hEventDebug); // close debugger event handle
|
||||
CloseHandle(hEventShutdn); // close event handle
|
||||
DestroyWindow(hWnd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// SetThreadIdealProcessor() is available since Windows NT4.0
|
||||
fnSetThreadIdealProcessor = (LPFN_STIP) GetProcAddress(GetModuleHandle(_T("kernel32")),
|
||||
"SetThreadIdealProcessor");
|
||||
|
||||
// bind Saturn CPU emulation thread to current ideal processor
|
||||
dwProcessor = (fnSetThreadIdealProcessor != NULL) // running on NT4.0 or later
|
||||
? fnSetThreadIdealProcessor(hThread,MAXIMUM_PROCESSORS) // get ideal processor no.
|
||||
: 0; // select 1st processor
|
||||
|
||||
// on multiprocessor machines for QueryPerformanceCounter()
|
||||
VERIFY(SetThreadAffinityMask(hThread,(DWORD_PTR) (1 << dwProcessor)));
|
||||
ResumeThread(hThread); // start thread
|
||||
while (nState!=nNextState) Sleep(0); // wait for thread initialized
|
||||
|
||||
idDdeInst = 0; // initialize DDE server
|
||||
if (DdeInitialize(&idDdeInst,(PFNCALLBACK) &DdeCallback,
|
||||
APPCLASS_STANDARD |
|
||||
CBF_FAIL_EXECUTES | CBF_FAIL_ADVISES |
|
||||
CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS,0))
|
||||
{
|
||||
TerminateThread(hThread, 0); // kill emulation thread
|
||||
CloseHandle(hEventDebug); // close debugger event handle
|
||||
CloseHandle(hEventShutdn); // close event handle
|
||||
DestroyWindow(hWnd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// init clipboard format and name service
|
||||
uCF_HpObj = RegisterClipboardFormat(_T(CF_HPOBJ));
|
||||
hszService = DdeCreateStringHandle(idDdeInst,szAppName,0);
|
||||
hszTopic = DdeCreateStringHandle(idDdeInst,szTopic,0);
|
||||
DdeNameService(idDdeInst,hszService,NULL,DNS_REGISTER);
|
||||
|
||||
SoundOpen(uWaveDevId); // open waveform-audio output device
|
||||
|
||||
_ASSERT(hWnd != NULL);
|
||||
_ASSERT(hWindowDC != NULL);
|
||||
|
||||
szBufferFilename[0] = 0;
|
||||
if (bFileExist) // open existing file
|
||||
{
|
||||
lstrcpyn(szBufferFilename,ppArgv[1],ARRAYSIZEOF(szBufferFilename));
|
||||
}
|
||||
if (nArgc == 1) // no argument
|
||||
{
|
||||
ReadLastDocument(szBufferFilename,ARRAYSIZEOF(szBufferFilename));
|
||||
}
|
||||
|
||||
if (szBufferFilename[0]) // given default document
|
||||
{
|
||||
TCHAR szTemp[MAX_PATH+8] = _T("Loading ");
|
||||
RECT rectClient;
|
||||
|
||||
_ASSERT(hWnd != NULL);
|
||||
VERIFY(GetClientRect(hWnd,&rectClient));
|
||||
GetCutPathName(szBufferFilename,&szTemp[8],MAX_PATH,rectClient.right/11);
|
||||
SetWindowTitle(szTemp);
|
||||
if (OpenDocument(szBufferFilename))
|
||||
{
|
||||
MruAdd(szCurrentFilename);
|
||||
ShowWindow(hWnd,SW_SHOWNORMAL);
|
||||
goto start;
|
||||
}
|
||||
}
|
||||
|
||||
SetWindowTitle(_T("New Document"));
|
||||
ShowWindow(hWnd,SW_SHOWNORMAL);
|
||||
|
||||
if (NewDocument())
|
||||
{
|
||||
if (nArgc >= 2)
|
||||
SaveDocumentAs(ppArgv[1]);
|
||||
else
|
||||
SetWindowTitle(_T("Untitled"));
|
||||
goto start;
|
||||
}
|
||||
|
||||
DestroyWindow(hWnd); // clean up system
|
||||
return TRUE;
|
||||
|
||||
start:
|
||||
if (bStartupBackup) SaveBackup(); // make a RAM backup at startup
|
||||
if (pbyRom) SwitchToState(SM_RUN);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// DLLDestroyWnd
|
||||
//
|
||||
BOOL DLLDestroyWnd(VOID)
|
||||
{
|
||||
LPTSTR lpFilePart;
|
||||
|
||||
// clean up DDE server
|
||||
DdeNameService(idDdeInst, hszService, NULL, DNS_UNREGISTER);
|
||||
DdeFreeStringHandle(idDdeInst, hszService);
|
||||
DdeFreeStringHandle(idDdeInst, hszTopic);
|
||||
DdeUninitialize(idDdeInst);
|
||||
|
||||
SoundClose(); // close waveform-audio output device
|
||||
|
||||
// get full path name of szCurrentFilename
|
||||
if (GetFullPathName(szCurrentFilename,ARRAYSIZEOF(szBufferFilename),szBufferFilename,&lpFilePart) == 0)
|
||||
szBufferFilename[0] = 0; // no last document name
|
||||
|
||||
WriteLastDocument(szBufferFilename); // save last document setting
|
||||
WriteSettings(); // save variable settings
|
||||
|
||||
CloseHandle(hThread); // close emulation thread handle
|
||||
CloseHandle(hEventShutdn); // close shutdown event handle
|
||||
CloseHandle(hEventDebug); // close debugger event handle
|
||||
_ASSERT(nState == SM_RETURN); // emulation thread down?
|
||||
ResetDocument();
|
||||
ResetBackup();
|
||||
MruCleanup();
|
||||
_ASSERT(pbyRom == NULL); // rom file unmapped
|
||||
_ASSERT(pbyPort2 == NULL); // port2 file unmapped
|
||||
_ASSERT(pKml == NULL); // KML script not closed
|
||||
_ASSERT(szTitle == NULL); // freed allocated memory
|
||||
_ASSERT(hPalette == NULL); // freed resource memory
|
||||
if (pEmuClose) pEmuClose(); // call notify function
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Public external functions
|
||||
//#
|
||||
//################
|
||||
|
||||
/****************************************************************************
|
||||
* EmuCreate
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func start Emu48 and load Ram file into emulator, if Ram file don't
|
||||
* exist create a new one and save it under the given name
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC BOOL CALLBACK EmuCreate(
|
||||
LPCTSTR lpszFilename) // @parm String with RAM filename
|
||||
{
|
||||
return DLLCreateWnd(lpszFilename, NULL);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* EmuCreateEx
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func start Emu48 and load Ram and Port2 file into emulator, if Ram file
|
||||
* don't exist create a new one and save it under the given name
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC BOOL CALLBACK EmuCreateEx(
|
||||
LPCTSTR lpszFilename, // @parm String with RAM filename
|
||||
LPCTSTR lpszPort2Name) // @parm String with Port2 filename
|
||||
// or NULL for using name inside INI file
|
||||
{
|
||||
return DLLCreateWnd(lpszFilename, lpszPort2Name);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* EmuDestroy
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func close Emu48, free all memory
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC BOOL CALLBACK EmuDestroy(VOID)
|
||||
{
|
||||
if (hWnd == NULL) return TRUE; // Emu48 closed
|
||||
|
||||
// close Emu48 via exit
|
||||
SendMessage(hWnd,WM_SYSCOMMAND,SC_CLOSE,0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* EmuAcceleratorTable
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func load accelerator table of emulator
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc HACCEL: handle of the loaded accelerator table
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC HACCEL CALLBACK EmuAcceleratorTable(
|
||||
HWND *phEmuWnd) // @parm return of emulator window handle
|
||||
{
|
||||
*phEmuWnd = hWnd;
|
||||
return hAccel;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* EmuCallBackClose
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func init CallBack handler to notify caller when Emu48 window close
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC VOID CALLBACK EmuCallBackClose(
|
||||
VOID (CALLBACK *EmuClose)(VOID)) // @parm CallBack function notify caller Emu48 closed
|
||||
{
|
||||
pEmuClose = EmuClose; // set new handler
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* EmuCallBackDocumentNotify
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func init CallBack handler to notify caller for actual document file
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC VOID CALLBACK EmuCallBackDocumentNotify(
|
||||
VOID (CALLBACK *EmuDocumentNotify)(LPCTSTR lpszFilename)) // @parm CallBack function notify document filename
|
||||
{
|
||||
pEmuDocumentNotify = EmuDocumentNotify; // set new handler
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* EmuLoadRamFile
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func load Ram file into emulator
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error (old file reloaded)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC BOOL CALLBACK EmuLoadRamFile(
|
||||
LPCTSTR lpszFilename) // @parm String with RAM filename
|
||||
{
|
||||
BOOL bErr;
|
||||
|
||||
if (pbyRom) SwitchToState(SM_INVALID); // stop emulation thread
|
||||
bErr = !OpenDocument(lpszFilename); // load state file
|
||||
if (pbyRom) SwitchToState(SM_RUN); // restart emulation thread
|
||||
return bErr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* EmuSaveRamFile
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func save the current emulator Ram to file
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error (old file reloaded)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC BOOL CALLBACK EmuSaveRamFile(VOID)
|
||||
{
|
||||
BOOL bErr;
|
||||
|
||||
if (pbyRom == NULL) return TRUE; // fail
|
||||
SwitchToState(SM_INVALID); // stop emulation thread
|
||||
bErr = !SaveDocument(); // save current state file
|
||||
SwitchToState(SM_RUN); // restart emulation thread
|
||||
return bErr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* EmuLoadObject
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func load object file to stack
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC BOOL CALLBACK EmuLoadObject(
|
||||
LPCTSTR lpszObjectFilename) // @parm String with object filename
|
||||
{
|
||||
HANDLE hFile;
|
||||
DWORD dwFileSizeLow;
|
||||
DWORD dwFileSizeHigh;
|
||||
LPBYTE lpBuf;
|
||||
WORD wError = S_ERR_BINARY; // set into error state
|
||||
|
||||
SuspendDebugger(); // suspend debugger
|
||||
bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control
|
||||
|
||||
if (!(Chipset.IORam[BITOFFSET]&DON)) // calculator off, turn on
|
||||
{
|
||||
KeyboardEvent(TRUE,0,0x8000);
|
||||
Sleep(dwWakeupDelay);
|
||||
KeyboardEvent(FALSE,0,0x8000);
|
||||
Sleep(dwWakeupDelay);
|
||||
// wait for sleep mode
|
||||
while(Chipset.Shutdn == FALSE) Sleep(0);
|
||||
}
|
||||
|
||||
if (nState != SM_RUN) goto cancel; // emulator must run to load on object
|
||||
if (WaitForSleepState()) goto cancel; // wait for cpu SHUTDN then sleep state
|
||||
|
||||
_ASSERT(nState == SM_SLEEP);
|
||||
|
||||
hFile = CreateFile(lpszObjectFilename,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SwitchToState(SM_RUN); // run state
|
||||
goto cancel;
|
||||
}
|
||||
dwFileSizeLow = GetFileSize(hFile, &dwFileSizeHigh);
|
||||
if (dwFileSizeHigh != 0)
|
||||
{ // file is too large.
|
||||
SwitchToState(SM_RUN); // run state
|
||||
CloseHandle(hFile);
|
||||
goto cancel;
|
||||
}
|
||||
lpBuf = malloc(dwFileSizeLow*2);
|
||||
if (lpBuf == NULL)
|
||||
{
|
||||
SwitchToState(SM_RUN); // run state
|
||||
CloseHandle(hFile);
|
||||
goto cancel;
|
||||
}
|
||||
ReadFile(hFile, lpBuf+dwFileSizeLow, dwFileSizeLow, &dwFileSizeHigh, NULL);
|
||||
CloseHandle(hFile);
|
||||
|
||||
wError = WriteStack(1,lpBuf,dwFileSizeLow);
|
||||
|
||||
free(lpBuf);
|
||||
|
||||
SwitchToState(SM_RUN); // run state
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
_ASSERT(nState == SM_RUN);
|
||||
KeyboardEvent(TRUE,0,0x8000);
|
||||
Sleep(dwWakeupDelay);
|
||||
KeyboardEvent(FALSE,0,0x8000);
|
||||
while(Chipset.Shutdn == FALSE) Sleep(0);
|
||||
|
||||
cancel:
|
||||
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
|
||||
ResumeDebugger();
|
||||
return wError != S_ERR_NO;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* EmuSaveObject
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func save object on stack to file
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC BOOL CALLBACK EmuSaveObject(
|
||||
LPCTSTR lpszObjectFilename) // @parm String with object filename
|
||||
{
|
||||
BOOL bErr;
|
||||
|
||||
if (nState != SM_RUN) return TRUE; // emulator must run to load on object
|
||||
if (WaitForSleepState()) return TRUE; // wait for cpu SHUTDN then sleep state
|
||||
_ASSERT(nState == SM_SLEEP);
|
||||
bErr = !SaveObject(lpszObjectFilename);
|
||||
SwitchToState(SM_RUN);
|
||||
return bErr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* EmuCalculatorType
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func get ID of current calculator type
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BYTE: '6' = HP38G with 64KB RAM
|
||||
* 'A' = HP38G
|
||||
* 'E' = HP39/40G
|
||||
* 'S' = HP48SX
|
||||
* 'G' = HP48GX
|
||||
* 'X' = HP49G
|
||||
* 'P' = HP39G+
|
||||
* '2' = HP48GII
|
||||
* 'Q' = HP49G+
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC BYTE CALLBACK EmuCalculatorType(VOID)
|
||||
{
|
||||
return Chipset.type;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* EmuSimulateKey
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func simulate a key action
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC VOID CALLBACK EmuSimulateKey(
|
||||
BOOL bKeyState, // @parm TRUE = pressed, FALSE = released
|
||||
UINT out, // @parm key out line
|
||||
UINT in) // @parm key in line
|
||||
{
|
||||
KeyboardEvent(bKeyState,out,in);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* EmuPressOn
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func press On key (emulation must run)
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DECLSPEC VOID CALLBACK EmuPressOn(
|
||||
BOOL bKeyState) // @parm TRUE = pressed, FALSE = released
|
||||
{
|
||||
KeyboardEvent(bKeyState,0,0x8000);
|
||||
}
|
642
app/src/main/cpp/EMU48DLL.H
Normal file
|
@ -0,0 +1,642 @@
|
|||
/*
|
||||
* Emu48Dll.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2000 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
|
||||
#define DECLSPEC __declspec(dllexport)
|
||||
|
||||
//////////////////////////////////
|
||||
//
|
||||
// breakpoint type definitions
|
||||
//
|
||||
//////////////////////////////////
|
||||
|
||||
#define BP_EXEC 0x01 // code breakpoint
|
||||
#define BP_READ 0x02 // read memory breakpoint
|
||||
#define BP_WRITE 0x04 // write memory breakpoint
|
||||
#define BP_RPL 0x08 // RPL breakpoint
|
||||
#define BP_ACCESS (BP_READ|BP_WRITE) // read/write memory breakpoint
|
||||
|
||||
#define BP_ROM 0x8000 // absolute ROM adress breakpoint
|
||||
|
||||
//////////////////////////////////
|
||||
//
|
||||
// REGISTER ACCESS API
|
||||
//
|
||||
//////////////////////////////////
|
||||
|
||||
#define EMU_REGISTER_PC 0
|
||||
#define EMU_REGISTER_D0 1
|
||||
#define EMU_REGISTER_D1 2
|
||||
#define EMU_REGISTER_DUMMY 3
|
||||
#define EMU_REGISTER_AL 4
|
||||
#define EMU_REGISTER_AH 5
|
||||
#define EMU_REGISTER_BL 6
|
||||
#define EMU_REGISTER_BH 7
|
||||
#define EMU_REGISTER_CL 8
|
||||
#define EMU_REGISTER_CH 9
|
||||
#define EMU_REGISTER_DL 10
|
||||
#define EMU_REGISTER_DH 11
|
||||
#define EMU_REGISTER_R0L 12
|
||||
#define EMU_REGISTER_R0H 13
|
||||
#define EMU_REGISTER_R1L 14
|
||||
#define EMU_REGISTER_R1H 15
|
||||
#define EMU_REGISTER_R2L 16
|
||||
#define EMU_REGISTER_R2H 17
|
||||
#define EMU_REGISTER_R3L 18
|
||||
#define EMU_REGISTER_R3H 19
|
||||
#define EMU_REGISTER_R4L 20
|
||||
#define EMU_REGISTER_R4H 21
|
||||
#define EMU_REGISTER_R5L 22
|
||||
#define EMU_REGISTER_R5H 23
|
||||
#define EMU_REGISTER_R6L 24
|
||||
#define EMU_REGISTER_R6H 25
|
||||
#define EMU_REGISTER_R7L 26
|
||||
#define EMU_REGISTER_R7H 27
|
||||
#define EMU_REGISTER_FLAGS 28
|
||||
#define EMU_REGISTER_OUT 29
|
||||
#define EMU_REGISTER_IN 30
|
||||
#define EMU_REGISTER_VIEW1 31
|
||||
#define EMU_REGISTER_VIEW2 32
|
||||
#define EMU_REGISTER_RSTKP 63
|
||||
#define EMU_REGISTER_RSTK0 64
|
||||
#define EMU_REGISTER_RSTK1 65
|
||||
#define EMU_REGISTER_RSTK2 66
|
||||
#define EMU_REGISTER_RSTK3 67
|
||||
#define EMU_REGISTER_RSTK4 68
|
||||
#define EMU_REGISTER_RSTK5 69
|
||||
#define EMU_REGISTER_RSTK6 70
|
||||
#define EMU_REGISTER_RSTK7 71
|
||||
#define EMU_REGISTER_CLKL 72
|
||||
#define EMU_REGISTER_CLKH 73
|
||||
#define EMU_REGISTER_CRC 74
|
||||
|
||||
/**
|
||||
* "FLAGS" register format :
|
||||
*
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | ST |S|x|x|x|K|I|C|M| HST | P |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* M : Mode (0:Hex, 1:Dec)
|
||||
* C : Carry
|
||||
* I : Interrupt pending
|
||||
* K : KDN Interrupts Enabled
|
||||
* S : Shutdn Flag (read only)
|
||||
* x : reserved
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* EmuCreate
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func start Emu48 and load Ram file into emulator, if Ram file don't
|
||||
* exist create a new one and save it under the given name
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuCreate(
|
||||
LPCTSTR lpszFilename); // @parm String with RAM filename
|
||||
|
||||
/****************************************************************************
|
||||
* EmuCreateEx
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func start Emu48 and load Ram and Port2 file into emulator, if Ram file
|
||||
* don't exist create a new one and save it under the given name
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuCreateEx(
|
||||
LPCTSTR lpszFilename, // @parm String with RAM filename
|
||||
LPCTSTR lpszPort2Name); // @parm String with Port2 filename
|
||||
// or NULL for using name inside INI file
|
||||
|
||||
/****************************************************************************
|
||||
* EmuDestroy
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func close Emu48, free all memory
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuDestroy(VOID);
|
||||
|
||||
/****************************************************************************
|
||||
* EmuAcceleratorTable
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func load accelerator table of emulator
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc HACCEL: handle of the loaded accelerator table
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC HACCEL CALLBACK EmuAcceleratorTable(
|
||||
HWND *phEmuWnd); // @parm return of emulator window handle
|
||||
|
||||
/****************************************************************************
|
||||
* EmuCallBackClose
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func init CallBack handler to notify caller when Emu48 window close
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuCallBackClose(
|
||||
VOID (CALLBACK *EmuClose)(VOID)); // @parm CallBack function notify caller Emu48 closed
|
||||
|
||||
/****************************************************************************
|
||||
* EmuCallBackDocumentNotify
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func init CallBack handler to notify caller for actual document file
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuCallBackDocumentNotify(
|
||||
VOID (CALLBACK *EmuDocumentNotify)(LPCTSTR lpszFilename)); // @parm CallBack function notify document filename
|
||||
|
||||
/****************************************************************************
|
||||
* EmuLoadRamFile
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func load Ram file into emulator
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error (old file reloaded)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuLoadRamFile(
|
||||
LPCTSTR lpszFilename); // @parm String with RAM filename
|
||||
|
||||
/****************************************************************************
|
||||
* EmuSaveRamFile
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func save the current emulator Ram to file
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error (old file reloaded)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuSaveRamFile(VOID);
|
||||
|
||||
/****************************************************************************
|
||||
* EmuLoadObject
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func load object file to stack
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuLoadObject(
|
||||
LPCTSTR lpszObjectFilename); // @parm String with object filename
|
||||
|
||||
/****************************************************************************
|
||||
* EmuSaveObject
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func save object on stack to file
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuSaveObject(
|
||||
LPCTSTR lpszObjectFilename); // @parm String with object filename
|
||||
|
||||
/****************************************************************************
|
||||
* EmuCalculatorType
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func get ID of current calculator type
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BYTE: '6' = HP38G with 64KB RAM
|
||||
* 'A' = HP38G
|
||||
* 'E' = HP39/40G
|
||||
* 'S' = HP48SX
|
||||
* 'G' = HP48GX
|
||||
* 'X' = HP49G
|
||||
* 'P' = HP39G+
|
||||
* '2' = HP48GII
|
||||
* 'Q' = HP49G+
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BYTE CALLBACK EmuCalculatorType(VOID);
|
||||
|
||||
/****************************************************************************
|
||||
* EmuSimulateKey
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func simulate a key action
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuSimulateKey(
|
||||
BOOL bKeyState, // @parm TRUE = pressed, FALSE = released
|
||||
UINT out, // @parm key out line
|
||||
UINT in); // @parm key in line
|
||||
|
||||
/****************************************************************************
|
||||
* EmuPressOn
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func press On key (emulation must run)
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuPressOn(
|
||||
BOOL bKeyState); // @parm TRUE = pressed, FALSE = released
|
||||
|
||||
/****************************************************************************
|
||||
* EmuInitLastInstr
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func init a circular buffer area for saving the last instruction
|
||||
* addresses
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuInitLastInstr(
|
||||
WORD wNoInstr, // @parm number of saved instructions,
|
||||
// 0 = frees the memory buffer
|
||||
DWORD *pdwArray); // @parm pointer to linear array
|
||||
|
||||
/****************************************************************************
|
||||
* EmuGetLastInstr
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func return number of valid entries in the last instruction array,
|
||||
* each entry contents a PC address, array[0] contents the oldest,
|
||||
* array[*pwNoEntries-1] the last PC address
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK, TRUE = Error
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuGetLastInstr(
|
||||
WORD *pwNoEntries); // @parm return number of valid entries in array
|
||||
|
||||
/****************************************************************************
|
||||
* EmuRun
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func run emulation
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK
|
||||
* TRUE = Error, Emu48 is running
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuRun(VOID);
|
||||
|
||||
/****************************************************************************
|
||||
* EmuRunPC
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func run emulation until stop address
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuRunPC(
|
||||
DWORD dwAddressPC); // @parm breakpoint address
|
||||
|
||||
/****************************************************************************
|
||||
* EmuStep
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func execute one ASM instruction and return to caller
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuStep(VOID);
|
||||
|
||||
/****************************************************************************
|
||||
* EmuStepOver
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func execute one ASM instruction but skip GOSUB, GOSUBL, GOSBVL
|
||||
* subroutines
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuStepOver(VOID);
|
||||
|
||||
/****************************************************************************
|
||||
* EmuStepOut
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func run emulation until a RTI, RTN, RTNC, RTNCC, RTNNC, RTNSC, RTNSXN,
|
||||
* RTNYES instruction is found above the current stack level
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuStepOut(VOID);
|
||||
|
||||
/****************************************************************************
|
||||
* EmuStop
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func break emulation
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: FALSE = OK
|
||||
* TRUE = Error, no debug notify handler
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuStop(VOID);
|
||||
|
||||
/****************************************************************************
|
||||
* EmuCallBackDebugNotify
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func init CallBack handler to notify caller on debugger breakpoint
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuCallBackDebugNotify(
|
||||
VOID (CALLBACK *EmuDbgNotify)(INT nBreaktype)); // @parm CallBack function notify Debug breakpoint
|
||||
|
||||
/****************************************************************************
|
||||
* EmuCallBackStackNotify
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func init CallBack handler to notify caller on hardware stack change;
|
||||
* if the CallBack function return TRUE, emulation stops behind the
|
||||
* opcode changed hardware stack content, otherwise, if the CallBack
|
||||
* function return FALSE, no breakpoint is set
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuCallBackStackNotify(
|
||||
BOOL (CALLBACK *EmuStackNotify)(VOID)); // @parm CallBack function notify stack changed
|
||||
|
||||
/****************************************************************************
|
||||
* EmuGetRegister
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func read a 32 bit register
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc DWORD: 32 bit value of register
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC DWORD CALLBACK EmuGetRegister(
|
||||
UINT uRegister); // @parm index of register
|
||||
|
||||
/****************************************************************************
|
||||
* EmuSetRegister
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func write a 32 bit register
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuSetRegister(
|
||||
UINT uRegister, // @parm index of register
|
||||
DWORD dwValue); // @parm new 32 bit value
|
||||
|
||||
/****************************************************************************
|
||||
* EmuGetMem
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func read one nibble from the specified mapped address
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuGetMem(
|
||||
DWORD dwMapAddr, // @parm mapped address of Saturn CPU
|
||||
BYTE *pbyValue); // @parm readed nibble
|
||||
|
||||
/****************************************************************************
|
||||
* EmuSetMem
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func write one nibble to the specified mapped address
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuSetMem(
|
||||
DWORD dwMapAddr, // @parm mapped address of Saturn CPU
|
||||
BYTE byValue); // @parm nibble to write
|
||||
|
||||
/****************************************************************************
|
||||
* EmuGetRom
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func return size and base address of mapped ROM
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc LPBYTE: base address of ROM (pointer to original data)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC LPBYTE CALLBACK EmuGetRom(
|
||||
DWORD *pdwRomSize); // @parm return size of ROM in nibbles
|
||||
|
||||
/****************************************************************************
|
||||
* EmuSetBreakpoint
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func set ASM code/data breakpoint
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: TRUE = Error, Breakpoint table full
|
||||
* FALSE = OK, Breakpoint set
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuSetBreakpoint(
|
||||
DWORD dwAddress, // @parm breakpoint address to set
|
||||
UINT nBreakpointType); // @parm breakpoint type to set
|
||||
|
||||
/****************************************************************************
|
||||
* EmuClearBreakpoint
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func clear ASM code/data breakpoint
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc BOOL: TRUE = Error, Breakpoint not found
|
||||
* FALSE = OK, Breakpoint cleared
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC BOOL CALLBACK EmuClearBreakpoint(
|
||||
DWORD dwAddress, // @parm breakpoint address to clear
|
||||
UINT nBreakpointType); // @parm breakpoint type to clear
|
||||
|
||||
/****************************************************************************
|
||||
* EmuClearAllBreakpoints
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func clear all breakpoints
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuClearAllBreakpoints(VOID);
|
||||
|
||||
/****************************************************************************
|
||||
* EmuEnableNop3Breakpoint
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func enable/disable NOP3 breakpoint
|
||||
* stop emulation at Opcode 420 for GOC + (next line)
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuEnableNop3Breakpoint(
|
||||
BOOL bEnable); // @parm stop on NOP3 opcode
|
||||
|
||||
/****************************************************************************
|
||||
* EmuEnableDocodeBreakpoint
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func enable/disable DOCODE breakpoint
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuEnableDoCodeBreakpoint(
|
||||
BOOL bEnable); // @parm stop on DOCODE entry
|
||||
|
||||
/****************************************************************************
|
||||
* EmuEnableRplBreakpoint
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func enable/disable RPL breakpoint
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuEnableRplBreakpoint(
|
||||
BOOL bEnable); // @parm stop on RPL exit
|
||||
|
||||
/****************************************************************************
|
||||
* EmuEnableSkipInterruptCode
|
||||
*****************************************************************************
|
||||
*
|
||||
* @func enable/disable skip single step execution inside the interrupt
|
||||
* handler, this option has no effect on code and data breakpoints
|
||||
*
|
||||
* @xref none
|
||||
*
|
||||
* @rdesc VOID
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN_C DECLSPEC VOID CALLBACK EmuEnableSkipInterruptCode(
|
||||
BOOL bEnable); // @parm TRUE = skip code instructions
|
||||
// inside interrupt service routine
|
645
app/src/main/cpp/ENGINE.C
Normal file
|
@ -0,0 +1,645 @@
|
|||
/*
|
||||
* engine.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1995 Sebastien Carlier
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "Opcodes.h"
|
||||
#include "io.h"
|
||||
#include "debugger.h"
|
||||
|
||||
#define SAMPLE 16384 // speed adjust sample frequency
|
||||
|
||||
BOOL bInterrupt = FALSE;
|
||||
UINT nState = SM_INVALID;
|
||||
UINT nNextState = SM_RUN;
|
||||
BOOL bEnableSlow = TRUE; // slow down is enabled
|
||||
BOOL bRealSpeed = FALSE;
|
||||
BOOL bKeySlow = FALSE; // slow down for key emulation
|
||||
BOOL bSoundSlow = FALSE; // slow down for sound emulation
|
||||
UINT nOpcSlow = 0; // no. of opcodes to slow down
|
||||
BOOL bCommInit = FALSE; // COM port not open
|
||||
|
||||
CHIPSET Chipset;
|
||||
|
||||
TCHAR szSerialWire[16]; // devicename for wire port
|
||||
TCHAR szSerialIr[16]; // devicename for IR port
|
||||
|
||||
DWORD dwSXCycles = 82; // SX cpu cycles in interval
|
||||
DWORD dwGXCycles = 123; // GX cpu cycles in interval
|
||||
DWORD dwGPCycles = 123*3; // g+ cpu cycles in interval // CdB for HP: add apples display management
|
||||
DWORD dwG2Cycles = 123*2; // gII cpu cycles in interval // CdB for HP: add apples display management
|
||||
|
||||
// variables for debugger engine
|
||||
HANDLE hEventDebug; // event handle to stop cpu thread
|
||||
|
||||
BOOL bDbgAutoStateCtrl = TRUE; // debugger suspend control by SwitchToState()
|
||||
INT nDbgState = DBG_OFF; // state of debugger
|
||||
|
||||
BOOL bDbgNOP3 = FALSE; // halt on NOP3 (#420 opcode)
|
||||
BOOL bDbgRPL = FALSE; // halt on RPL entry
|
||||
BOOL bDbgCode = FALSE; // halt on DOCODE entry
|
||||
|
||||
BOOL bDbgSkipInt = FALSE; // execute interrupt handler
|
||||
|
||||
DWORD dwDbgStopPC = -1; // stop address for goto cursor
|
||||
DWORD dwDbgRplPC = -1; // stop address for RPL breakpoint
|
||||
|
||||
DWORD dwDbgRstkp; // stack recursion level of step over end
|
||||
DWORD dwDbgRstk; // possible return address
|
||||
|
||||
DWORD *pdwInstrArray = NULL; // last instruction array
|
||||
WORD wInstrSize = 256; // size of last instruction array
|
||||
WORD wInstrWp; // write pointer of instruction array
|
||||
WORD wInstrRp; // read pointer of instruction array
|
||||
|
||||
static INT nDbgRplBreak = BN_ASM; // flag for RPL breakpoint detection
|
||||
static INT nDbgOldState = DBG_OFF; // old state of debugger for suspend/resume
|
||||
|
||||
static BOOL bCpuSlow = FALSE; // enable/disable real speed
|
||||
|
||||
static DWORD dwEDbgT2 = 0; // debugger timer2 emulation
|
||||
static DWORD dwEDbgCycles = 0; // debugger cycle counter
|
||||
|
||||
static DWORD dwOldCyc; // cpu cycles at last event
|
||||
static DWORD dwSpeedRef; // timer value at last event
|
||||
static DWORD dwTickRef; // sample timer ticks
|
||||
|
||||
#include "Ops.h"
|
||||
|
||||
// save last instruction in circular instruction buffer
|
||||
static __inline VOID SaveInstrAddr(DWORD dwAddr)
|
||||
{
|
||||
EnterCriticalSection(&csDbgLock);
|
||||
{
|
||||
if (pdwInstrArray) // circular buffer allocated
|
||||
{
|
||||
pdwInstrArray[wInstrWp] = dwAddr;
|
||||
wInstrWp = (wInstrWp + 1) % wInstrSize;
|
||||
if (wInstrWp == wInstrRp)
|
||||
wInstrRp = (wInstrRp + 1) % wInstrSize;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&csDbgLock);
|
||||
return;
|
||||
}
|
||||
|
||||
static __inline VOID Debugger(VOID) // debugger part
|
||||
{
|
||||
LARGE_INTEGER lDummyInt; // sample timer ticks
|
||||
BOOL bStopEmulation;
|
||||
LPBYTE I = FASTPTR(Chipset.pc); // get opcode stream
|
||||
|
||||
UpdateDbgCycleCounter(); // update 64 bit cpu cycle counter
|
||||
|
||||
SaveInstrAddr(Chipset.pc); // save pc in last instruction buffer
|
||||
|
||||
nDbgRplBreak = BN_ASM; // notify ASM breakpoint
|
||||
|
||||
// check for code breakpoints
|
||||
bStopEmulation = CheckBreakpoint(Chipset.pc, 1, BP_EXEC);
|
||||
|
||||
// check for memory breakpoints, opcode #14x or #15x
|
||||
if (I[0] == 0x1 && (I[1] == 0x4 || I[1] == 0x5))
|
||||
{
|
||||
DWORD dwData = (I[2] & 0x1) ? Chipset.d1 : Chipset.d0;
|
||||
UINT nType = (I[2] & 0x2) ? BP_READ : BP_WRITE;
|
||||
|
||||
DWORD dwRange;
|
||||
if (I[1] == 0x4) // B,A
|
||||
{
|
||||
dwRange = (I[2] & 0x8) ? 2 : 5;
|
||||
}
|
||||
else // number of nibbles, (P,WP,XS,X,S,M,W)
|
||||
{
|
||||
dwRange = (I[2] & 0x8) ? (I[3]+1) : (F_l[I[3]]);
|
||||
}
|
||||
#if defined DEBUG_DEBUGGER
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("Memory breakpoint %.5lx, %u\n",dwData,dwRange));
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
bStopEmulation |= CheckBreakpoint(dwData, dwRange, nType);
|
||||
}
|
||||
|
||||
// check for step cursor
|
||||
bStopEmulation |= (dwDbgStopPC == Chipset.pc);
|
||||
|
||||
// NOP3, opcode #420 (GOC)
|
||||
if (bDbgNOP3 && I[0] == 0x4 && I[1] == 0x2 && I[2] == 0x0)
|
||||
bStopEmulation = TRUE;
|
||||
|
||||
// stop on first instruction of DOCODE object
|
||||
if (bDbgCode && (Chipset.pc == 0x02DDE || Chipset.pc == 0x02E3C))
|
||||
{
|
||||
// return address
|
||||
DWORD dwAddr = Chipset.rstk[(Chipset.rstkp-1)&7];
|
||||
|
||||
_ASSERT(I[0] == 0 && I[1] == 1); // stopped at RTN opcode
|
||||
|
||||
if (MapData(dwAddr) != M_ROM) // address not in ROM
|
||||
dwDbgStopPC = dwAddr; // then stop
|
||||
}
|
||||
|
||||
// check for RPL breakpoint
|
||||
if (dwDbgRplPC == Chipset.pc)
|
||||
{
|
||||
dwDbgRplPC = -1;
|
||||
nDbgRplBreak = bStopEmulation ? BN_ASM_BT : BN_RPL;
|
||||
bStopEmulation = TRUE;
|
||||
}
|
||||
|
||||
// RPL breakpoints, PC=(A), opcode #808C or PC=(C), opcode #808E
|
||||
if (I[0] == 0x8 && I[1] == 0x0 && I[2] == 0x8 && (I[3] == 0xC || I[3] == 0xE ))
|
||||
{
|
||||
// get next RPL entry
|
||||
DWORD dwAddr = Npack((I[3] == 0xC) ? Chipset.A : Chipset.C,5);
|
||||
|
||||
if (bDbgRPL || CheckBreakpoint(dwAddr, 1, BP_RPL))
|
||||
{
|
||||
BYTE byRplPtr[5];
|
||||
|
||||
Npeek(byRplPtr,dwAddr,5); // get PC address of next opcode
|
||||
dwDbgRplPC = Npack(byRplPtr,5); // set RPL breakpoint
|
||||
}
|
||||
}
|
||||
|
||||
// step over interrupt execution
|
||||
if (bDbgSkipInt && !bStopEmulation && !Chipset.inte)
|
||||
return;
|
||||
|
||||
// check for step into
|
||||
bStopEmulation |= (nDbgState == DBG_STEPINTO);
|
||||
|
||||
// check for step over
|
||||
bStopEmulation |= (nDbgState == DBG_STEPOVER) && dwDbgRstkp == Chipset.rstkp;
|
||||
|
||||
// check for step out, something was popped from hardware stack
|
||||
if (nDbgState == DBG_STEPOUT && dwDbgRstkp == Chipset.rstkp)
|
||||
{
|
||||
_ASSERT(bStopEmulation == FALSE);
|
||||
if ((bStopEmulation = (Chipset.pc == dwDbgRstk)) == FALSE)
|
||||
{
|
||||
// it was C=RSTK, check for next object popped from hardware stack
|
||||
dwDbgRstkp = (Chipset.rstkp-1)&7;
|
||||
dwDbgRstk = Chipset.rstk[dwDbgRstkp];
|
||||
}
|
||||
}
|
||||
|
||||
if (bStopEmulation) // stop condition
|
||||
{
|
||||
StopTimers(); // hold timer values when emulator is stopped
|
||||
if (Chipset.IORam[TIMER2_CTRL]&RUN) // check if timer running
|
||||
{
|
||||
if (dwEDbgT2 == Chipset.t2)
|
||||
{
|
||||
// cpu cycles for one timer2 tick elapsed
|
||||
if ((DWORD) (Chipset.cycles & 0xFFFFFFFF) - dwEDbgCycles
|
||||
>= (SAMPLE / 8192) * (DWORD) T2CYCLES)
|
||||
{
|
||||
--Chipset.t2;
|
||||
// adjust cycles reference
|
||||
dwEDbgCycles += (SAMPLE / 8192) * T2CYCLES;
|
||||
}
|
||||
}
|
||||
else // new timer2 value
|
||||
{
|
||||
// new cycle reference
|
||||
dwEDbgCycles = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
// check rising edge of Bit 8 of timer2
|
||||
if ((dwEDbgT2 & 0x100) == 0 && (Chipset.t2 & 0x100) != 0)
|
||||
Chipset.t1 = (Chipset.t1 - 1) & 0xF;
|
||||
}
|
||||
dwEDbgT2 = Chipset.t2; // timer2 check reference value
|
||||
|
||||
// redraw debugger window and stop
|
||||
NotifyDebugger(nDbgRplBreak);
|
||||
WaitForSingleObject(hEventDebug,INFINITE);
|
||||
|
||||
StartTimers(); // continue timers
|
||||
|
||||
if (nDbgState >= DBG_OFF) // if debugger is active
|
||||
{
|
||||
Chipset.Shutdn = FALSE;
|
||||
Chipset.bShutdnWake = FALSE;
|
||||
}
|
||||
|
||||
// init slow down part
|
||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
QueryPerformanceCounter(&lDummyInt);
|
||||
dwSpeedRef = lDummyInt.LowPart;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID SuspendDebugger(VOID)
|
||||
{
|
||||
// auto control enabled, emulation halted by debugger
|
||||
if (bDbgAutoStateCtrl && nDbgState > DBG_OFF)
|
||||
{
|
||||
nDbgOldState = nDbgState; // save old state
|
||||
nDbgState = DBG_SUSPEND; // suspend state
|
||||
SetEvent(hEventDebug); // exit debugger
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID ResumeDebugger(VOID)
|
||||
{
|
||||
// auto control enabled, debugger is suspended
|
||||
if (bDbgAutoStateCtrl && nDbgState == DBG_SUSPEND)
|
||||
{
|
||||
// active RPL breakpoint
|
||||
if (nDbgRplBreak) dwDbgRplPC = Chipset.pc;
|
||||
nDbgState = nDbgOldState; // set to old debugger state
|
||||
if (Chipset.Shutdn) // inside shutdown
|
||||
SetEvent(hEventShutdn); // leave it to call debugger
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static __inline VOID CheckDisp(BOOL bSync)
|
||||
{
|
||||
if (disp == 0) return; // no display update need
|
||||
|
||||
// update display when drawing top line or display is off
|
||||
if (bSync && GetLineCounter() != 0x3F && (Chipset.IORam[0x00]&8))
|
||||
return;
|
||||
|
||||
_ASSERT((disp & DISP_POINTER) == 0); // display pointer already updated
|
||||
if (disp & DISP_MAIN) UpdateMainDisplay();
|
||||
if (disp & DISP_MENUE) UpdateMenuDisplay();
|
||||
_ASSERT((disp & DISP_ANNUN) == 0); // annunciators already updated
|
||||
disp = 0; // display updated
|
||||
return;
|
||||
}
|
||||
|
||||
static __inline VOID AdjustSpeed(VOID) // adjust emulation speed
|
||||
{
|
||||
// emulation slow down
|
||||
if ( bEnableSlow
|
||||
&& (bCpuSlow || bKeySlow || bSoundSlow || nOpcSlow > 0))
|
||||
{
|
||||
DWORD dwCycles,dwTicks;
|
||||
|
||||
EnterCriticalSection(&csSlowLock);
|
||||
{
|
||||
// cycles elapsed for next check
|
||||
if ((dwCycles = (DWORD) (Chipset.cycles & 0xFFFFFFFF)-dwOldCyc) >= (DWORD) T2CYCLES)
|
||||
{
|
||||
LARGE_INTEGER lAct;
|
||||
do
|
||||
{
|
||||
VERIFY(QueryPerformanceCounter(&lAct));
|
||||
|
||||
// get time difference
|
||||
dwTicks = lAct.LowPart - dwSpeedRef;
|
||||
}
|
||||
// ticks elapsed or negative number (workaround for QueryPerformanceCounter() in Win2k)
|
||||
while (dwTicks <= dwTickRef || (dwTicks & 0x80000000) != 0);
|
||||
|
||||
dwOldCyc += T2CYCLES; // adjust cycles reference
|
||||
dwSpeedRef += dwTickRef; // adjust reference time
|
||||
}
|
||||
|
||||
if (nOpcSlow > 0) --nOpcSlow; // decr. slow down opcode counter
|
||||
}
|
||||
LeaveCriticalSection(&csSlowLock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID CheckSerial(VOID)
|
||||
{
|
||||
// COM port closed and serial on
|
||||
if (bCommInit == FALSE && (Chipset.IORam[IOC] & SON) != 0)
|
||||
{
|
||||
bCommInit = CommOpen(szSerialWire,szSerialIr); // open COM ports
|
||||
}
|
||||
|
||||
// COM port opened and serial off
|
||||
if (bCommInit == TRUE && (Chipset.IORam[IOC] & SON) == 0)
|
||||
{
|
||||
CommClose(); // close COM port
|
||||
bCommInit = FALSE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID InitAdjustSpeed(VOID)
|
||||
{
|
||||
// slow down function not initalized
|
||||
if (!bEnableSlow || (!bCpuSlow && !bKeySlow && !bSoundSlow && nOpcSlow == 0))
|
||||
{
|
||||
LARGE_INTEGER lTime; // sample timer ticks
|
||||
// save reference cycles
|
||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
QueryPerformanceCounter(&lTime); // get timer ticks
|
||||
dwSpeedRef = lTime.LowPart; // save reference time
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID AdjKeySpeed(VOID) // slow down key repeat
|
||||
{
|
||||
WORD i;
|
||||
BOOL bKey;
|
||||
|
||||
bKey = FALSE; // search for a pressed key
|
||||
for (i = 0;i < ARRAYSIZEOF(Chipset.Keyboard_Row) && !bKey;++i)
|
||||
bKey = (Chipset.Keyboard_Row[i] != 0);
|
||||
|
||||
EnterCriticalSection(&csSlowLock);
|
||||
{
|
||||
if (bKey) // key pressed
|
||||
{
|
||||
InitAdjustSpeed(); // init variables if necessary
|
||||
}
|
||||
bKeySlow = bKey; // save new state
|
||||
}
|
||||
LeaveCriticalSection(&csSlowLock);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID SetSpeed(BOOL bAdjust) // set emulation speed
|
||||
{
|
||||
EnterCriticalSection(&csSlowLock);
|
||||
{
|
||||
if (bAdjust) // switch to real speed
|
||||
{
|
||||
InitAdjustSpeed(); // init variables if necessary
|
||||
}
|
||||
bCpuSlow = bAdjust; // save emulation speed
|
||||
}
|
||||
LeaveCriticalSection(&csSlowLock);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID UpdateKdnBit(VOID) // update KDN bit
|
||||
{
|
||||
if ( Chipset.intk
|
||||
&& (Chipset.IORam[TIMER2_CTRL]&RUN) != 0
|
||||
&& (DWORD) (Chipset.cycles & 0xFFFFFFFF) - Chipset.dwKdnCycles > (DWORD) T2CYCLES * 16)
|
||||
IOBit(SRQ2,KDN,Chipset.in != 0);
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL WaitForSleepState(VOID) // wait for cpu SHUTDN then sleep state
|
||||
{
|
||||
DWORD dwRefTime;
|
||||
|
||||
SuspendDebugger(); // suspend debugger
|
||||
|
||||
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(SM_SLEEP); // go to sleep state
|
||||
else
|
||||
ResumeDebugger(); // timeout, resume to debugger
|
||||
|
||||
return SM_SLEEP != nNextState; // state not changed, emulator was busy
|
||||
}
|
||||
|
||||
UINT SwitchToState(UINT nNewState)
|
||||
{
|
||||
UINT nOldState = nState;
|
||||
|
||||
if (nState == nNewState) return nOldState;
|
||||
switch (nState)
|
||||
{
|
||||
case SM_RUN: // Run
|
||||
switch (nNewState)
|
||||
{
|
||||
case SM_INVALID: // -> Invalid
|
||||
nNextState = SM_INVALID;
|
||||
if (Chipset.Shutdn)
|
||||
SetEvent(hEventShutdn);
|
||||
else
|
||||
bInterrupt = TRUE;
|
||||
SuspendDebugger(); // suspend debugger
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
break;
|
||||
case SM_RETURN: // -> Return
|
||||
DisableDebugger(); // disable debugger
|
||||
nNextState = SM_INVALID;
|
||||
if (Chipset.Shutdn)
|
||||
SetEvent(hEventShutdn);
|
||||
else
|
||||
bInterrupt = TRUE;
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
nNextState = SM_RETURN;
|
||||
SetEvent(hEventShutdn);
|
||||
WaitForSingleObject(hThread,INFINITE);
|
||||
break;
|
||||
case SM_SLEEP: // -> Sleep
|
||||
nNextState = SM_SLEEP;
|
||||
bInterrupt = TRUE; // exit main loop
|
||||
SuspendDebugger(); // suspend debugger
|
||||
SetEvent(hEventShutdn); // exit shutdown
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
bInterrupt = FALSE;
|
||||
ResetEvent(hEventDebug);
|
||||
ResetEvent(hEventShutdn);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SM_INVALID: // Invalid
|
||||
switch (nNewState)
|
||||
{
|
||||
case SM_RUN: // -> Run
|
||||
nNextState = SM_RUN;
|
||||
// don't enter opcode loop on interrupt request
|
||||
bInterrupt = Chipset.Shutdn || Chipset.SoftInt;
|
||||
ResumeDebugger();
|
||||
SetEvent(hEventShutdn);
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
break;
|
||||
case SM_RETURN: // -> Return
|
||||
DisableDebugger(); // disable debugger
|
||||
nNextState = SM_RETURN;
|
||||
SetEvent(hEventShutdn);
|
||||
WaitForSingleObject(hThread,INFINITE);
|
||||
break;
|
||||
case SM_SLEEP: // -> Sleep
|
||||
nNextState = SM_SLEEP;
|
||||
SetEvent(hEventShutdn);
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SM_SLEEP: // Sleep
|
||||
switch (nNewState)
|
||||
{
|
||||
case SM_RUN: // -> Run
|
||||
nNextState = SM_RUN;
|
||||
// don't enter opcode loop on interrupt request
|
||||
bInterrupt = (nDbgState == DBG_OFF) && (Chipset.Shutdn || Chipset.SoftInt);
|
||||
ResumeDebugger();
|
||||
SetEvent(hEventShutdn); // leave sleep state
|
||||
break;
|
||||
case SM_INVALID: // -> Invalid
|
||||
nNextState = SM_INVALID;
|
||||
SetEvent(hEventShutdn);
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
break;
|
||||
case SM_RETURN: // -> Return
|
||||
DisableDebugger(); // disable debugger
|
||||
nNextState = SM_INVALID;
|
||||
SetEvent(hEventShutdn);
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
nNextState = SM_RETURN;
|
||||
SetEvent(hEventShutdn);
|
||||
WaitForSingleObject(hThread,INFINITE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return nOldState;
|
||||
}
|
||||
|
||||
UINT WorkerThread(LPVOID pParam)
|
||||
{
|
||||
LARGE_INTEGER lDummyInt; // sample timer ticks
|
||||
QueryPerformanceFrequency(&lDummyInt); // init timer ticks
|
||||
lDummyInt.QuadPart /= SAMPLE; // calculate sample ticks
|
||||
dwTickRef = lDummyInt.LowPart; // sample timer ticks
|
||||
_ASSERT(dwTickRef); // tick resolution error
|
||||
|
||||
loop:
|
||||
while (nNextState == SM_INVALID) // go into invalid state
|
||||
{
|
||||
OnToolMacroStop(); // close open keyboard macro handler
|
||||
CommClose(); // close COM port
|
||||
bCommInit = FALSE; // COM port not open
|
||||
nState = SM_INVALID; // in invalid state
|
||||
WaitForSingleObject(hEventShutdn,INFINITE);
|
||||
if (nNextState == SM_RETURN) // go into return state
|
||||
{
|
||||
nState = SM_RETURN; // in return state
|
||||
return 0; // kill thread
|
||||
}
|
||||
CheckSerial(); // test if UART on
|
||||
}
|
||||
while (nNextState == SM_RUN)
|
||||
{
|
||||
if (nState != SM_RUN)
|
||||
{
|
||||
nState = SM_RUN;
|
||||
// clear port2 status bits
|
||||
Chipset.cards_status &= ~(PORT2_PRESENT | PORT2_WRITE);
|
||||
if (pbyPort2 || Port2) // card plugged in port2
|
||||
{
|
||||
Chipset.cards_status |= PORT2_PRESENT;
|
||||
|
||||
if (bPort2Writeable) // is card writeable
|
||||
Chipset.cards_status |= PORT2_WRITE;
|
||||
}
|
||||
// card detection off and timer running
|
||||
if ((Chipset.IORam[CARDCTL] & ECDT) == 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0)
|
||||
{
|
||||
BOOL bNINT2 = Chipset.IORam[SRQ1] == 0 && (Chipset.IORam[SRQ2] & LSRQ) == 0;
|
||||
BOOL bNINT = (Chipset.IORam[CARDCTL] & SMP) == 0;
|
||||
|
||||
// state of CDT2
|
||||
bNINT2 = bNINT2 && (Chipset.cards_status & (P2W|P2C)) != P2C;
|
||||
// state of CDT1
|
||||
bNINT = bNINT && (Chipset.cards_status & (P1W|P1C)) != P1C;
|
||||
|
||||
IOBit(SRQ2,NINT2,bNINT2);
|
||||
IOBit(SRQ2,NINT,bNINT);
|
||||
}
|
||||
RomSwitch(Chipset.Bank_FF); // select HP49G ROM bank and update memory mapping
|
||||
UpdateContrast(Chipset.contrast);
|
||||
UpdateDisplayPointers();
|
||||
UpdateMainDisplay();
|
||||
UpdateMenuDisplay();
|
||||
RefreshDisp0(); // CdB for HP: add apples display management
|
||||
UpdateAnnunciators();
|
||||
// init speed reference
|
||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
QueryPerformanceCounter(&lDummyInt);
|
||||
dwSpeedRef = lDummyInt.LowPart;
|
||||
SetHP48Time(); // update HP48 time & date
|
||||
// start display counter/update engine
|
||||
StartDisplay((BYTE)(((Chipset.IORam[LINECOUNT+1]<<4)|Chipset.IORam[LINECOUNT])&0x3F));
|
||||
StartBatMeasure(); // start battery measurement
|
||||
StartTimers();
|
||||
}
|
||||
PCHANGED;
|
||||
while (!bInterrupt)
|
||||
{
|
||||
if (nDbgState > DBG_OFF) // debugger active
|
||||
{
|
||||
Debugger();
|
||||
|
||||
// if suspended skip next opcode execution
|
||||
if (nDbgState == DBG_SUSPEND)
|
||||
{
|
||||
if (Chipset.Shutdn) break;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
EvalOpcode(FASTPTR(Chipset.pc)); // execute opcode
|
||||
|
||||
// check for display update in BW mode
|
||||
if (!bGrayscale) CheckDisp(!Chipset.Shutdn);
|
||||
AdjustSpeed(); // adjust emulation speed
|
||||
}
|
||||
bInterrupt = FALSE; // be sure to reenter opcode loop
|
||||
|
||||
// enter SHUTDN handler only in RUN mode
|
||||
if (Chipset.Shutdn && !(nDbgState == DBG_STEPINTO || nDbgState == DBG_STEPOVER))
|
||||
{
|
||||
if (!Chipset.SoftInt) // ignore SHUTDN on interrupt request
|
||||
WaitForSingleObject(hEventShutdn,INFINITE);
|
||||
else
|
||||
Chipset.bShutdnWake = TRUE; // waked by interrupt
|
||||
|
||||
if (Chipset.bShutdnWake) // waked up by timer, keyboard or serial
|
||||
{
|
||||
Chipset.bShutdnWake = FALSE;
|
||||
Chipset.Shutdn = FALSE;
|
||||
// init speed reference
|
||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
QueryPerformanceCounter(&lDummyInt);
|
||||
dwSpeedRef = lDummyInt.LowPart;
|
||||
nOpcSlow = 0; // no opcodes to slow down
|
||||
}
|
||||
}
|
||||
if (Chipset.SoftInt)
|
||||
{
|
||||
Chipset.SoftInt = FALSE;
|
||||
if (Chipset.inte)
|
||||
{
|
||||
Chipset.inte = FALSE;
|
||||
rstkpush(Chipset.pc);
|
||||
Chipset.pc = 0xf;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ASSERT(nNextState != SM_RUN);
|
||||
|
||||
StopDisplay(); // stop display counter/update
|
||||
StopBatMeasure(); // stop battery measurement
|
||||
StopTimers();
|
||||
|
||||
while (nNextState == SM_SLEEP) // go into sleep state
|
||||
{
|
||||
nState = SM_SLEEP; // in sleep state
|
||||
WaitForSingleObject(hEventShutdn,INFINITE);
|
||||
}
|
||||
goto loop;
|
||||
UNREFERENCED_PARAMETER(pParam);
|
||||
}
|
100
app/src/main/cpp/EXTERNAL.C
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* external.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1995 Sebastien Carlier
|
||||
* Copyright (C) 2005 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "ops.h"
|
||||
|
||||
//| 38G | 39G | 40G | 48SX | 48GX | 49G | Name
|
||||
//#F0E4F #80F0F #80F0F #706D2 #80850 #80F0F =SFLAG53_56
|
||||
|
||||
// memory address for flags -53 to -56
|
||||
// CdB for HP: add apples beep management
|
||||
#define SFLAG53_56 ( (cCurrentRomType=='6') \
|
||||
? 0xE0E4F \
|
||||
: ( (cCurrentRomType=='A') \
|
||||
? 0xF0E4F \
|
||||
: ( (cCurrentRomType!='E' && cCurrentRomType!='X' && cCurrentRomType!='P' && cCurrentRomType!='2' && cCurrentRomType!='Q') \
|
||||
? ( (cCurrentRomType=='S') \
|
||||
? 0x706D2 \
|
||||
: 0x80850 \
|
||||
) \
|
||||
: 0x80F0F \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
VOID External(CHIPSET* w) // Beep patch
|
||||
{
|
||||
BYTE fbeep;
|
||||
DWORD freq,dur;
|
||||
|
||||
freq = Npack(w->D,5); // frequency in Hz
|
||||
dur = Npack(w->C,5); // duration in ms
|
||||
Nread(&fbeep,SFLAG53_56,1); // fetch system flags -53 to -56
|
||||
|
||||
w->carry = TRUE; // setting of no beep
|
||||
if (!(fbeep & 0x8) && freq) // bit -56 clear and frequency > 0 Hz
|
||||
{
|
||||
if (freq > 4400) freq = 4400; // high limit of HP (SX)
|
||||
|
||||
SoundBeep(freq,dur); // beeping
|
||||
|
||||
// estimate cpu cycles for beeping time (2MHz / 4MHz)
|
||||
w->cycles += dur * ((cCurrentRomType=='S') ? 2000 : 4000);
|
||||
|
||||
// original routine return with...
|
||||
w->P = 0; // P=0
|
||||
w->intk = TRUE; // INTON
|
||||
w->carry = FALSE; // RTNCC
|
||||
}
|
||||
w->pc = rstkpop();
|
||||
return;
|
||||
}
|
||||
|
||||
VOID RCKBp(CHIPSET* w) // ROM Check Beep patch
|
||||
{
|
||||
DWORD dw2F,dwCpuFreq;
|
||||
DWORD freq,dur;
|
||||
BYTE f,d;
|
||||
|
||||
f = w->C[1]; // f = freq ctl
|
||||
d = w->C[0]; // d = duration ctl
|
||||
|
||||
if (cCurrentRomType == 'S') // Clarke chip with 48S ROM
|
||||
{
|
||||
// CPU strobe frequency @ RATE 14 = 1.97MHz
|
||||
dwCpuFreq = ((14 + 1) * 524288) >> 2;
|
||||
|
||||
dw2F = f * 126 + 262; // F=f*63+131
|
||||
}
|
||||
else // York chip with 48G and later ROM
|
||||
{
|
||||
// CPU strobe frequency @ RATE 27 = 3.67MHz
|
||||
// CPU strobe frequency @ RATE 29 = 3.93MHz
|
||||
dwCpuFreq = ((27 + 1) * 524288) >> 2;
|
||||
|
||||
dw2F = f * 180 + 367; // F=f*90+183.5
|
||||
}
|
||||
|
||||
freq = dwCpuFreq / dw2F;
|
||||
dur = (dw2F * (256 - 16 * d)) * 1000 / 2 / dwCpuFreq;
|
||||
|
||||
if (freq > 4400) freq = 4400; // high limit of HP
|
||||
|
||||
SoundBeep(freq,dur); // beeping
|
||||
|
||||
// estimate cpu cycles for beeping time (2MHz / 4MHz)
|
||||
w->cycles += dur * ((cCurrentRomType=='S') ? 2000 : 4000);
|
||||
|
||||
w->P = 0; // P=0
|
||||
w->carry = FALSE; // RTNCC
|
||||
w->pc = rstkpop();
|
||||
return;
|
||||
}
|
778
app/src/main/cpp/FETCH.C
Normal file
|
@ -0,0 +1,778 @@
|
|||
/*
|
||||
* fetch.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1999 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Opcodes.h"
|
||||
|
||||
#define F 0xFF // F = function
|
||||
|
||||
typedef const struct
|
||||
{
|
||||
LPCVOID pLnk;
|
||||
const DWORD dwTyp;
|
||||
} JMPTAB, *PJMPTAB;
|
||||
|
||||
// jump tables
|
||||
static JMPTAB oF_[] =
|
||||
{
|
||||
(LPCVOID) oF0, F,
|
||||
(LPCVOID) oF1, F,
|
||||
(LPCVOID) oF2, F,
|
||||
(LPCVOID) oF3, F,
|
||||
(LPCVOID) oF4, F,
|
||||
(LPCVOID) oF5, F,
|
||||
(LPCVOID) oF6, F,
|
||||
(LPCVOID) oF7, F,
|
||||
(LPCVOID) oF8, F,
|
||||
(LPCVOID) oF9, F,
|
||||
(LPCVOID) oFA, F,
|
||||
(LPCVOID) oFB, F,
|
||||
(LPCVOID) oFC, F,
|
||||
(LPCVOID) oFD, F,
|
||||
(LPCVOID) oFE, F,
|
||||
(LPCVOID) oFF, F
|
||||
};
|
||||
|
||||
static JMPTAB oE_[] =
|
||||
{
|
||||
(LPCVOID) oE0, F,
|
||||
(LPCVOID) oE1, F,
|
||||
(LPCVOID) oE2, F,
|
||||
(LPCVOID) oE3, F,
|
||||
(LPCVOID) oE4, F,
|
||||
(LPCVOID) oE5, F,
|
||||
(LPCVOID) oE6, F,
|
||||
(LPCVOID) oE7, F,
|
||||
(LPCVOID) oE8, F,
|
||||
(LPCVOID) oE9, F,
|
||||
(LPCVOID) oEA, F,
|
||||
(LPCVOID) oEB, F,
|
||||
(LPCVOID) oEC, F,
|
||||
(LPCVOID) oED, F,
|
||||
(LPCVOID) oEE, F,
|
||||
(LPCVOID) oEF, F
|
||||
};
|
||||
|
||||
static JMPTAB oD_[] =
|
||||
{
|
||||
(LPCVOID) oD0, F,
|
||||
(LPCVOID) oD1, F,
|
||||
(LPCVOID) oD2, F,
|
||||
(LPCVOID) oD3, F,
|
||||
(LPCVOID) oD4, F,
|
||||
(LPCVOID) oD5, F,
|
||||
(LPCVOID) oD6, F,
|
||||
(LPCVOID) oD7, F,
|
||||
(LPCVOID) oD8, F,
|
||||
(LPCVOID) oD9, F,
|
||||
(LPCVOID) oDA, F,
|
||||
(LPCVOID) oDB, F,
|
||||
(LPCVOID) oDC, F,
|
||||
(LPCVOID) oDD, F,
|
||||
(LPCVOID) oDE, F,
|
||||
(LPCVOID) oDF, F
|
||||
};
|
||||
|
||||
static JMPTAB oC_[] =
|
||||
{
|
||||
(LPCVOID) oC0, F,
|
||||
(LPCVOID) oC1, F,
|
||||
(LPCVOID) oC2, F,
|
||||
(LPCVOID) oC3, F,
|
||||
(LPCVOID) oC4, F,
|
||||
(LPCVOID) oC5, F,
|
||||
(LPCVOID) oC6, F,
|
||||
(LPCVOID) oC7, F,
|
||||
(LPCVOID) oC8, F,
|
||||
(LPCVOID) oC9, F,
|
||||
(LPCVOID) oCA, F,
|
||||
(LPCVOID) oCB, F,
|
||||
(LPCVOID) oCC, F,
|
||||
(LPCVOID) oCD, F,
|
||||
(LPCVOID) oCE, F,
|
||||
(LPCVOID) oCF, F
|
||||
};
|
||||
|
||||
static JMPTAB oBb_[] =
|
||||
{
|
||||
(LPCVOID) oBb0, F,
|
||||
(LPCVOID) oBb1, F,
|
||||
(LPCVOID) oBb2, F,
|
||||
(LPCVOID) oBb3, F,
|
||||
(LPCVOID) oBb4, F,
|
||||
(LPCVOID) oBb5, F,
|
||||
(LPCVOID) oBb6, F,
|
||||
(LPCVOID) oBb7, F,
|
||||
(LPCVOID) oBb8, F,
|
||||
(LPCVOID) oBb9, F,
|
||||
(LPCVOID) oBbA, F,
|
||||
(LPCVOID) oBbB, F,
|
||||
(LPCVOID) oBbC, F,
|
||||
(LPCVOID) oBbD, F,
|
||||
(LPCVOID) oBbE, F,
|
||||
(LPCVOID) oBbF, F
|
||||
};
|
||||
|
||||
static JMPTAB oBa_[] =
|
||||
{
|
||||
(LPCVOID) oBa0, F,
|
||||
(LPCVOID) oBa1, F,
|
||||
(LPCVOID) oBa2, F,
|
||||
(LPCVOID) oBa3, F,
|
||||
(LPCVOID) oBa4, F,
|
||||
(LPCVOID) oBa5, F,
|
||||
(LPCVOID) oBa6, F,
|
||||
(LPCVOID) oBa7, F,
|
||||
(LPCVOID) oBa8, F,
|
||||
(LPCVOID) oBa9, F,
|
||||
(LPCVOID) oBaA, F,
|
||||
(LPCVOID) oBaB, F,
|
||||
(LPCVOID) oBaC, F,
|
||||
(LPCVOID) oBaD, F,
|
||||
(LPCVOID) oBaE, F,
|
||||
(LPCVOID) oBaF, F
|
||||
};
|
||||
|
||||
static JMPTAB oB_[] =
|
||||
{
|
||||
(LPCVOID) oBa_, 2,
|
||||
(LPCVOID) oBa_, 2,
|
||||
(LPCVOID) oBa_, 2,
|
||||
(LPCVOID) oBa_, 2,
|
||||
(LPCVOID) oBa_, 2,
|
||||
(LPCVOID) oBa_, 2,
|
||||
(LPCVOID) oBa_, 2,
|
||||
(LPCVOID) oBa_, 2,
|
||||
(LPCVOID) oBb_, 2,
|
||||
(LPCVOID) oBb_, 2,
|
||||
(LPCVOID) oBb_, 2,
|
||||
(LPCVOID) oBb_, 2,
|
||||
(LPCVOID) oBb_, 2,
|
||||
(LPCVOID) oBb_, 2,
|
||||
(LPCVOID) oBb_, 2,
|
||||
(LPCVOID) oBb_, 2
|
||||
};
|
||||
|
||||
static JMPTAB oAb_[] =
|
||||
{
|
||||
(LPCVOID) oAb0, F,
|
||||
(LPCVOID) oAb1, F,
|
||||
(LPCVOID) oAb2, F,
|
||||
(LPCVOID) oAb3, F,
|
||||
(LPCVOID) oAb4, F,
|
||||
(LPCVOID) oAb5, F,
|
||||
(LPCVOID) oAb6, F,
|
||||
(LPCVOID) oAb7, F,
|
||||
(LPCVOID) oAb8, F,
|
||||
(LPCVOID) oAb9, F,
|
||||
(LPCVOID) oAbA, F,
|
||||
(LPCVOID) oAbB, F,
|
||||
(LPCVOID) oAbC, F,
|
||||
(LPCVOID) oAbD, F,
|
||||
(LPCVOID) oAbE, F,
|
||||
(LPCVOID) oAbF, F
|
||||
};
|
||||
|
||||
static JMPTAB oAa_[] =
|
||||
{
|
||||
(LPCVOID) oAa0, F,
|
||||
(LPCVOID) oAa1, F,
|
||||
(LPCVOID) oAa2, F,
|
||||
(LPCVOID) oAa3, F,
|
||||
(LPCVOID) oAa4, F,
|
||||
(LPCVOID) oAa5, F,
|
||||
(LPCVOID) oAa6, F,
|
||||
(LPCVOID) oAa7, F,
|
||||
(LPCVOID) oAa8, F,
|
||||
(LPCVOID) oAa9, F,
|
||||
(LPCVOID) oAaA, F,
|
||||
(LPCVOID) oAaB, F,
|
||||
(LPCVOID) oAaC, F,
|
||||
(LPCVOID) oAaD, F,
|
||||
(LPCVOID) oAaE, F,
|
||||
(LPCVOID) oAaF, F
|
||||
};
|
||||
|
||||
static JMPTAB oA_[] =
|
||||
{
|
||||
(LPCVOID) oAa_, 2,
|
||||
(LPCVOID) oAa_, 2,
|
||||
(LPCVOID) oAa_, 2,
|
||||
(LPCVOID) oAa_, 2,
|
||||
(LPCVOID) oAa_, 2,
|
||||
(LPCVOID) oAa_, 2,
|
||||
(LPCVOID) oAa_, 2,
|
||||
(LPCVOID) oAa_, 2,
|
||||
(LPCVOID) oAb_, 2,
|
||||
(LPCVOID) oAb_, 2,
|
||||
(LPCVOID) oAb_, 2,
|
||||
(LPCVOID) oAb_, 2,
|
||||
(LPCVOID) oAb_, 2,
|
||||
(LPCVOID) oAb_, 2,
|
||||
(LPCVOID) oAb_, 2,
|
||||
(LPCVOID) oAb_, 2
|
||||
};
|
||||
|
||||
static JMPTAB o9b_[] =
|
||||
{
|
||||
(LPCVOID) o9b0, F,
|
||||
(LPCVOID) o9b1, F,
|
||||
(LPCVOID) o9b2, F,
|
||||
(LPCVOID) o9b3, F,
|
||||
(LPCVOID) o9b4, F,
|
||||
(LPCVOID) o9b5, F,
|
||||
(LPCVOID) o9b6, F,
|
||||
(LPCVOID) o9b7, F,
|
||||
(LPCVOID) o9b8, F,
|
||||
(LPCVOID) o9b9, F,
|
||||
(LPCVOID) o9bA, F,
|
||||
(LPCVOID) o9bB, F,
|
||||
(LPCVOID) o9bC, F,
|
||||
(LPCVOID) o9bD, F,
|
||||
(LPCVOID) o9bE, F,
|
||||
(LPCVOID) o9bF, F
|
||||
};
|
||||
|
||||
static JMPTAB o9a_[] =
|
||||
{
|
||||
(LPCVOID) o9a0, F,
|
||||
(LPCVOID) o9a1, F,
|
||||
(LPCVOID) o9a2, F,
|
||||
(LPCVOID) o9a3, F,
|
||||
(LPCVOID) o9a4, F,
|
||||
(LPCVOID) o9a5, F,
|
||||
(LPCVOID) o9a6, F,
|
||||
(LPCVOID) o9a7, F,
|
||||
(LPCVOID) o9a8, F,
|
||||
(LPCVOID) o9a9, F,
|
||||
(LPCVOID) o9aA, F,
|
||||
(LPCVOID) o9aB, F,
|
||||
(LPCVOID) o9aC, F,
|
||||
(LPCVOID) o9aD, F,
|
||||
(LPCVOID) o9aE, F,
|
||||
(LPCVOID) o9aF, F
|
||||
};
|
||||
|
||||
static JMPTAB o9_[] =
|
||||
{
|
||||
(LPCVOID) o9a_, 2,
|
||||
(LPCVOID) o9a_, 2,
|
||||
(LPCVOID) o9a_, 2,
|
||||
(LPCVOID) o9a_, 2,
|
||||
(LPCVOID) o9a_, 2,
|
||||
(LPCVOID) o9a_, 2,
|
||||
(LPCVOID) o9a_, 2,
|
||||
(LPCVOID) o9a_, 2,
|
||||
(LPCVOID) o9b_, 2,
|
||||
(LPCVOID) o9b_, 2,
|
||||
(LPCVOID) o9b_, 2,
|
||||
(LPCVOID) o9b_, 2,
|
||||
(LPCVOID) o9b_, 2,
|
||||
(LPCVOID) o9b_, 2,
|
||||
(LPCVOID) o9b_, 2,
|
||||
(LPCVOID) o9b_, 2
|
||||
};
|
||||
|
||||
static JMPTAB o8B_[] =
|
||||
{
|
||||
(LPCVOID) o8B0, F,
|
||||
(LPCVOID) o8B1, F,
|
||||
(LPCVOID) o8B2, F,
|
||||
(LPCVOID) o8B3, F,
|
||||
(LPCVOID) o8B4, F,
|
||||
(LPCVOID) o8B5, F,
|
||||
(LPCVOID) o8B6, F,
|
||||
(LPCVOID) o8B7, F,
|
||||
(LPCVOID) o8B8, F,
|
||||
(LPCVOID) o8B9, F,
|
||||
(LPCVOID) o8BA, F,
|
||||
(LPCVOID) o8BB, F,
|
||||
(LPCVOID) o8BC, F,
|
||||
(LPCVOID) o8BD, F,
|
||||
(LPCVOID) o8BE, F,
|
||||
(LPCVOID) o8BF, F
|
||||
};
|
||||
|
||||
static JMPTAB o8A_[] =
|
||||
{
|
||||
(LPCVOID) o8A0, F,
|
||||
(LPCVOID) o8A1, F,
|
||||
(LPCVOID) o8A2, F,
|
||||
(LPCVOID) o8A3, F,
|
||||
(LPCVOID) o8A4, F,
|
||||
(LPCVOID) o8A5, F,
|
||||
(LPCVOID) o8A6, F,
|
||||
(LPCVOID) o8A7, F,
|
||||
(LPCVOID) o8A8, F,
|
||||
(LPCVOID) o8A9, F,
|
||||
(LPCVOID) o8AA, F,
|
||||
(LPCVOID) o8AB, F,
|
||||
(LPCVOID) o8AC, F,
|
||||
(LPCVOID) o8AD, F,
|
||||
(LPCVOID) o8AE, F,
|
||||
(LPCVOID) o8AF, F
|
||||
};
|
||||
|
||||
static JMPTAB o81B_[] =
|
||||
{
|
||||
(LPCVOID) o_invalid4, F,
|
||||
(LPCVOID) o81B1, F, // normally o_invalid4, beep patch, Apple: LOOP
|
||||
(LPCVOID) o81B2, F,
|
||||
(LPCVOID) o81B3, F,
|
||||
(LPCVOID) o81B4, F,
|
||||
(LPCVOID) o81B5, F,
|
||||
(LPCVOID) o81B6, F,
|
||||
(LPCVOID) o81B7, F,
|
||||
(LPCVOID) o_invalid4, F, // Apple: SKPTOP
|
||||
(LPCVOID) o_invalid4, F, // Apple: SKBOT
|
||||
(LPCVOID) o_invalid4, F, // Apple: SKIP
|
||||
(LPCVOID) o_invalid4, F, // Apple: SKPLEN
|
||||
(LPCVOID) o_invalid4, F, // Apple: SKPID
|
||||
(LPCVOID) o_invalid4, F, // Apple: $SEMI
|
||||
(LPCVOID) o_invalid4, F, // Apple: DOCOL
|
||||
(LPCVOID) o_invalid4, F
|
||||
};
|
||||
|
||||
static JMPTAB o81Af2_[] =
|
||||
{
|
||||
(LPCVOID) o81Af20, F,
|
||||
(LPCVOID) o81Af21, F,
|
||||
(LPCVOID) o81Af22, F,
|
||||
(LPCVOID) o81Af23, F,
|
||||
(LPCVOID) o81Af24, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o81Af28, F,
|
||||
(LPCVOID) o81Af29, F,
|
||||
(LPCVOID) o81Af2A, F,
|
||||
(LPCVOID) o81Af2B, F,
|
||||
(LPCVOID) o81Af2C, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F
|
||||
};
|
||||
|
||||
static JMPTAB o81Af1_[] =
|
||||
{
|
||||
(LPCVOID) o81Af10, F,
|
||||
(LPCVOID) o81Af11, F,
|
||||
(LPCVOID) o81Af12, F,
|
||||
(LPCVOID) o81Af13, F,
|
||||
(LPCVOID) o81Af14, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o81Af18, F,
|
||||
(LPCVOID) o81Af19, F,
|
||||
(LPCVOID) o81Af1A, F,
|
||||
(LPCVOID) o81Af1B, F,
|
||||
(LPCVOID) o81Af1C, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F
|
||||
};
|
||||
|
||||
static JMPTAB o81Af0_[] =
|
||||
{
|
||||
(LPCVOID) o81Af00, F,
|
||||
(LPCVOID) o81Af01, F,
|
||||
(LPCVOID) o81Af02, F,
|
||||
(LPCVOID) o81Af03, F,
|
||||
(LPCVOID) o81Af04, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o81Af08, F,
|
||||
(LPCVOID) o81Af09, F,
|
||||
(LPCVOID) o81Af0A, F,
|
||||
(LPCVOID) o81Af0B, F,
|
||||
(LPCVOID) o81Af0C, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F
|
||||
};
|
||||
|
||||
static JMPTAB o81A_[] =
|
||||
{
|
||||
(LPCVOID) o81Af0_, 5,
|
||||
(LPCVOID) o81Af1_, 5,
|
||||
(LPCVOID) o81Af2_, 5,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F
|
||||
};
|
||||
|
||||
static JMPTAB o819_[] =
|
||||
{
|
||||
(LPCVOID) o819f0, F,
|
||||
(LPCVOID) o819f1, F,
|
||||
(LPCVOID) o819f2, F,
|
||||
(LPCVOID) o819f3, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F
|
||||
};
|
||||
|
||||
static JMPTAB o818_[] =
|
||||
{
|
||||
(LPCVOID) o818f0x, F,
|
||||
(LPCVOID) o818f1x, F,
|
||||
(LPCVOID) o818f2x, F,
|
||||
(LPCVOID) o818f3x, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o818f8x, F,
|
||||
(LPCVOID) o818f9x, F,
|
||||
(LPCVOID) o818fAx, F,
|
||||
(LPCVOID) o818fBx, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F,
|
||||
(LPCVOID) o_invalid6, F
|
||||
};
|
||||
|
||||
static JMPTAB o81_[] =
|
||||
{
|
||||
(LPCVOID) o810, F,
|
||||
(LPCVOID) o811, F,
|
||||
(LPCVOID) o812, F,
|
||||
(LPCVOID) o813, F,
|
||||
(LPCVOID) o814, F,
|
||||
(LPCVOID) o815, F,
|
||||
(LPCVOID) o816, F,
|
||||
(LPCVOID) o817, F,
|
||||
(LPCVOID) o818_, 4,
|
||||
(LPCVOID) o819_, 4,
|
||||
(LPCVOID) o81A_, 4,
|
||||
(LPCVOID) o81B_, 3,
|
||||
(LPCVOID) o81C, F,
|
||||
(LPCVOID) o81D, F,
|
||||
(LPCVOID) o81E, F,
|
||||
(LPCVOID) o81F, F
|
||||
};
|
||||
|
||||
static JMPTAB o8081_[] =
|
||||
{
|
||||
(LPCVOID) o80810, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F,
|
||||
(LPCVOID) o_invalid5, F
|
||||
};
|
||||
|
||||
static JMPTAB o808_[] =
|
||||
{
|
||||
(LPCVOID) o8080, F,
|
||||
(LPCVOID) o8081_, 4,
|
||||
(LPCVOID) o8082X, F,
|
||||
(LPCVOID) o8083, F,
|
||||
(LPCVOID) o8084n, F,
|
||||
(LPCVOID) o8085n, F,
|
||||
(LPCVOID) o8086n, F,
|
||||
(LPCVOID) o8087n, F,
|
||||
(LPCVOID) o8088n, F,
|
||||
(LPCVOID) o8089n, F,
|
||||
(LPCVOID) o808An, F,
|
||||
(LPCVOID) o808Bn, F,
|
||||
(LPCVOID) o808C, F,
|
||||
(LPCVOID) o808D, F,
|
||||
(LPCVOID) o808E, F,
|
||||
(LPCVOID) o808F, F
|
||||
};
|
||||
|
||||
static JMPTAB o80_[] =
|
||||
{
|
||||
(LPCVOID) o800, F,
|
||||
(LPCVOID) o801, F,
|
||||
(LPCVOID) o802, F,
|
||||
(LPCVOID) o803, F,
|
||||
(LPCVOID) o804, F,
|
||||
(LPCVOID) o805, F,
|
||||
(LPCVOID) o806, F,
|
||||
(LPCVOID) o807, F,
|
||||
(LPCVOID) o808_, 3,
|
||||
(LPCVOID) o809, F,
|
||||
(LPCVOID) o80A, F,
|
||||
(LPCVOID) o80B, F,
|
||||
(LPCVOID) o80Cn, F,
|
||||
(LPCVOID) o80Dn, F,
|
||||
(LPCVOID) o80E, F,
|
||||
(LPCVOID) o80Fn, F
|
||||
};
|
||||
|
||||
static JMPTAB o8_[] =
|
||||
{
|
||||
(LPCVOID) o80_, 2,
|
||||
(LPCVOID) o81_, 2,
|
||||
(LPCVOID) o82n, F,
|
||||
(LPCVOID) o83n, F,
|
||||
(LPCVOID) o84n, F,
|
||||
(LPCVOID) o85n, F,
|
||||
(LPCVOID) o86n, F,
|
||||
(LPCVOID) o87n, F,
|
||||
(LPCVOID) o88n, F,
|
||||
(LPCVOID) o89n, F,
|
||||
(LPCVOID) o8A_, 2,
|
||||
(LPCVOID) o8B_, 2,
|
||||
(LPCVOID) o8Cd4, F,
|
||||
(LPCVOID) o8Dd5, F,
|
||||
(LPCVOID) o8Ed4, F,
|
||||
(LPCVOID) o8Fd5, F
|
||||
};
|
||||
|
||||
static JMPTAB o15_[] =
|
||||
{
|
||||
(LPCVOID) o150a, F,
|
||||
(LPCVOID) o151a, F,
|
||||
(LPCVOID) o152a, F,
|
||||
(LPCVOID) o153a, F,
|
||||
(LPCVOID) o154a, F,
|
||||
(LPCVOID) o155a, F,
|
||||
(LPCVOID) o156a, F,
|
||||
(LPCVOID) o157a, F,
|
||||
(LPCVOID) o158x, F,
|
||||
(LPCVOID) o159x, F,
|
||||
(LPCVOID) o15Ax, F,
|
||||
(LPCVOID) o15Bx, F,
|
||||
(LPCVOID) o15Cx, F,
|
||||
(LPCVOID) o15Dx, F,
|
||||
(LPCVOID) o15Ex, F,
|
||||
(LPCVOID) o15Fx, F
|
||||
};
|
||||
|
||||
static JMPTAB o14_[] =
|
||||
{
|
||||
(LPCVOID) o140, F,
|
||||
(LPCVOID) o141, F,
|
||||
(LPCVOID) o142, F,
|
||||
(LPCVOID) o143, F,
|
||||
(LPCVOID) o144, F,
|
||||
(LPCVOID) o145, F,
|
||||
(LPCVOID) o146, F,
|
||||
(LPCVOID) o147, F,
|
||||
(LPCVOID) o148, F,
|
||||
(LPCVOID) o149, F,
|
||||
(LPCVOID) o14A, F,
|
||||
(LPCVOID) o14B, F,
|
||||
(LPCVOID) o14C, F,
|
||||
(LPCVOID) o14D, F,
|
||||
(LPCVOID) o14E, F,
|
||||
(LPCVOID) o14F, F
|
||||
};
|
||||
|
||||
static JMPTAB o13_[] =
|
||||
{
|
||||
(LPCVOID) o130, F,
|
||||
(LPCVOID) o131, F,
|
||||
(LPCVOID) o132, F,
|
||||
(LPCVOID) o133, F,
|
||||
(LPCVOID) o134, F,
|
||||
(LPCVOID) o135, F,
|
||||
(LPCVOID) o136, F,
|
||||
(LPCVOID) o137, F,
|
||||
(LPCVOID) o138, F,
|
||||
(LPCVOID) o139, F,
|
||||
(LPCVOID) o13A, F,
|
||||
(LPCVOID) o13B, F,
|
||||
(LPCVOID) o13C, F,
|
||||
(LPCVOID) o13D, F,
|
||||
(LPCVOID) o13E, F,
|
||||
(LPCVOID) o13F, F
|
||||
};
|
||||
|
||||
static JMPTAB o12_[] =
|
||||
{
|
||||
(LPCVOID) o120, F,
|
||||
(LPCVOID) o121, F,
|
||||
(LPCVOID) o122, F,
|
||||
(LPCVOID) o123, F,
|
||||
(LPCVOID) o124, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o128, F,
|
||||
(LPCVOID) o129, F,
|
||||
(LPCVOID) o12A, F,
|
||||
(LPCVOID) o12B, F,
|
||||
(LPCVOID) o12C, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o_invalid3, F
|
||||
};
|
||||
|
||||
static JMPTAB o11_[] =
|
||||
{
|
||||
(LPCVOID) o110, F,
|
||||
(LPCVOID) o111, F,
|
||||
(LPCVOID) o112, F,
|
||||
(LPCVOID) o113, F,
|
||||
(LPCVOID) o114, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o118, F,
|
||||
(LPCVOID) o119, F,
|
||||
(LPCVOID) o11A, F,
|
||||
(LPCVOID) o11B, F,
|
||||
(LPCVOID) o11C, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o_invalid3, F
|
||||
};
|
||||
|
||||
static JMPTAB o10_[] =
|
||||
{
|
||||
(LPCVOID) o100, F,
|
||||
(LPCVOID) o101, F,
|
||||
(LPCVOID) o102, F,
|
||||
(LPCVOID) o103, F,
|
||||
(LPCVOID) o104, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o108, F,
|
||||
(LPCVOID) o109, F,
|
||||
(LPCVOID) o10A, F,
|
||||
(LPCVOID) o10B, F,
|
||||
(LPCVOID) o10C, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o_invalid3, F,
|
||||
(LPCVOID) o_invalid3, F
|
||||
};
|
||||
|
||||
static JMPTAB o1_[] =
|
||||
{
|
||||
(LPCVOID) o10_, 2,
|
||||
(LPCVOID) o11_, 2,
|
||||
(LPCVOID) o12_, 2,
|
||||
(LPCVOID) o13_, 2,
|
||||
(LPCVOID) o14_, 2,
|
||||
(LPCVOID) o15_, 2,
|
||||
(LPCVOID) o16x, F,
|
||||
(LPCVOID) o17x, F,
|
||||
(LPCVOID) o18x, F,
|
||||
(LPCVOID) o19d2, F,
|
||||
(LPCVOID) o1Ad4, F,
|
||||
(LPCVOID) o1Bd5, F,
|
||||
(LPCVOID) o1Cx, F,
|
||||
(LPCVOID) o1Dd2, F,
|
||||
(LPCVOID) o1Ed4, F,
|
||||
(LPCVOID) o1Fd5, F
|
||||
};
|
||||
|
||||
static JMPTAB o0E_[] =
|
||||
{
|
||||
(LPCVOID) o0Ef0, F,
|
||||
(LPCVOID) o0Ef1, F,
|
||||
(LPCVOID) o0Ef2, F,
|
||||
(LPCVOID) o0Ef3, F,
|
||||
(LPCVOID) o0Ef4, F,
|
||||
(LPCVOID) o0Ef5, F,
|
||||
(LPCVOID) o0Ef6, F,
|
||||
(LPCVOID) o0Ef7, F,
|
||||
(LPCVOID) o0Ef8, F,
|
||||
(LPCVOID) o0Ef9, F,
|
||||
(LPCVOID) o0EfA, F,
|
||||
(LPCVOID) o0EfB, F,
|
||||
(LPCVOID) o0EfC, F,
|
||||
(LPCVOID) o0EfD, F,
|
||||
(LPCVOID) o0EfE, F,
|
||||
(LPCVOID) o0EfF, F
|
||||
};
|
||||
|
||||
static JMPTAB o0_[] =
|
||||
{
|
||||
(LPCVOID) o00, F,
|
||||
(LPCVOID) o01, F,
|
||||
(LPCVOID) o02, F,
|
||||
(LPCVOID) o03, F,
|
||||
(LPCVOID) o04, F,
|
||||
(LPCVOID) o05, F,
|
||||
(LPCVOID) o06, F,
|
||||
(LPCVOID) o07, F,
|
||||
(LPCVOID) o08, F,
|
||||
(LPCVOID) o09, F,
|
||||
(LPCVOID) o0A, F,
|
||||
(LPCVOID) o0B, F,
|
||||
(LPCVOID) o0C, F,
|
||||
(LPCVOID) o0D, F,
|
||||
(LPCVOID) o0E_, 3,
|
||||
(LPCVOID) o0F, F
|
||||
};
|
||||
|
||||
static JMPTAB o_[] =
|
||||
{
|
||||
(LPCVOID) o0_, 1,
|
||||
(LPCVOID) o1_, 1,
|
||||
(LPCVOID) o2n, F,
|
||||
(LPCVOID) o3X, F,
|
||||
(LPCVOID) o4d2, F,
|
||||
(LPCVOID) o5d2, F,
|
||||
(LPCVOID) o6d3, F,
|
||||
(LPCVOID) o7d3, F,
|
||||
(LPCVOID) o8_, 1,
|
||||
(LPCVOID) o9_, 1,
|
||||
(LPCVOID) oA_, 1,
|
||||
(LPCVOID) oB_, 1,
|
||||
(LPCVOID) oC_, 1,
|
||||
(LPCVOID) oD_, 1,
|
||||
(LPCVOID) oE_, 1,
|
||||
(LPCVOID) oF_, 1
|
||||
};
|
||||
|
||||
// opcode dispatcher
|
||||
VOID EvalOpcode(LPBYTE I)
|
||||
{
|
||||
DWORD dwIndex = 0;
|
||||
PJMPTAB pJmpTab = o_;
|
||||
|
||||
do
|
||||
{
|
||||
_ASSERT(I[dwIndex] <= 0xf); // found packed data
|
||||
pJmpTab = &pJmpTab[I[dwIndex]]; // table entry by opcode
|
||||
dwIndex = pJmpTab->dwTyp; // next pointer type
|
||||
pJmpTab = (PJMPTAB) pJmpTab->pLnk; // next pointer to table/function
|
||||
}
|
||||
while (dwIndex != F); // reference to table? -> again
|
||||
|
||||
((VOID (*)(LPBYTE)) pJmpTab)(I); // call function
|
||||
return;
|
||||
}
|
2727
app/src/main/cpp/FILES.C
Normal file
754
app/src/main/cpp/I28F160.C
Normal file
|
@ -0,0 +1,754 @@
|
|||
/*
|
||||
* i28f160.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2000 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "i28f160.h"
|
||||
|
||||
#define ARRAYSIZEOF(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
// Flash Command Set
|
||||
#define READ_ARRAY 0xFF
|
||||
#define READ_ID_CODES 0x90
|
||||
#define READ_QUERY 0x98
|
||||
#define READ_STATUS_REG 0x70
|
||||
#define CLEAR_STATUS_REG 0x50
|
||||
#define WRITE_BUFFER 0xE8
|
||||
#define WORD_BYTE_PROG1 0x40
|
||||
#define WORD_BYTE_PROG2 0x10
|
||||
#define BLOCK_ERASE 0x20
|
||||
#define BLOCK_ERASE_SUSPEND 0xB0
|
||||
#define BLOCK_ERASE_RESUME 0xD0
|
||||
#define STS_CONFIG 0xB8
|
||||
#define SET_CLR_BLOCK_LOCK 0x60
|
||||
#define FULL_CHIP_ERASE 0x30
|
||||
|
||||
#define CONFIRM 0xD0
|
||||
|
||||
// Status Register Definition
|
||||
#define WSMS 0x80 // WRITE STATE MACHINE STATUS
|
||||
#define ESS 0x40 // ERASE SUSPEND STATUS
|
||||
#define ECLBS 0x20 // ERASE AND CLEAR LOCK-BIT STATUS
|
||||
#define BWSLBS 0x10 // PROGRAM AND SET LOCK-BIT STATUS
|
||||
#define VPPS 0x08 // Vpp STATUS
|
||||
#define BWSS 0x04 // PROGRAM SUSPEND STATUS
|
||||
#define DPS 0x02 // DEVICE PROTECT STATUS
|
||||
|
||||
// Extended Status Register Definition
|
||||
#define WBS 0x80 // WRITE BUFFER STATUS
|
||||
|
||||
// write state defines
|
||||
#define WRS_DATA 0 // idle state
|
||||
#define WRS_WR_BUFFER_N 1 // write buffer no. of data
|
||||
#define WRS_WR_BUFFER_D 2 // write buffer data
|
||||
#define WRS_WR_BUFFER_C 3 // write buffer confirm
|
||||
#define WRS_WR_BYTE 4 // write byte/word
|
||||
#define WRS_BLOCK_ERASE 5 // block erase
|
||||
#define WRS_CHIP_ERASE 6 // full chip erase
|
||||
#define WRS_STS_PIN_CONFIG 7 // STS pin Configuration
|
||||
#define WRS_LOCK_BITS 8 // Set/Clear Block Lock-Bits
|
||||
|
||||
// read state defines
|
||||
#define RDS_DATA 0 // data read
|
||||
#define RDS_ID 1 // read identifier codes
|
||||
#define RDS_QUERY 2 // read query
|
||||
#define RDS_SR 3 // read status register
|
||||
#define RDS_XSR 4 // read extended status register
|
||||
|
||||
// global data
|
||||
WSMSET WSMset;
|
||||
BOOL bWP = FALSE; // WP# = low, locked blocks cannot be erased
|
||||
|
||||
// function prototypes
|
||||
// write function WSM state
|
||||
static VOID WrStateIdle(BYTE a, DWORD d);
|
||||
static VOID WrStateE8(DWORD d);
|
||||
static VOID WrStateE8N(BYTE a, DWORD d);
|
||||
static VOID WrStateE8D(BYTE a, DWORD d);
|
||||
static VOID WrStateE8C(BYTE a, DWORD d);
|
||||
static VOID WrState40(DWORD d);
|
||||
static VOID WrState40D(BYTE a, DWORD d);
|
||||
static VOID WrState20(DWORD d);
|
||||
static VOID WrState20C(BYTE a, DWORD d);
|
||||
static VOID WrState30(DWORD d);
|
||||
static VOID WrState30C(BYTE a, DWORD d);
|
||||
static VOID WrStateB8(DWORD d);
|
||||
static VOID WrStateB8D(BYTE a, DWORD d);
|
||||
static VOID WrState60(DWORD d);
|
||||
static VOID WrState60D(BYTE a, DWORD d);
|
||||
|
||||
static VOID (*CONST fnWrState[])(BYTE a, DWORD d) =
|
||||
{
|
||||
WrStateIdle,
|
||||
WrStateE8N, WrStateE8D, WrStateE8C,
|
||||
WrState40D,
|
||||
WrState20C,
|
||||
WrState30C,
|
||||
WrStateB8D,
|
||||
WrState60D
|
||||
};
|
||||
|
||||
// read function WSM state
|
||||
static BYTE RdStateData(DWORD d);
|
||||
static BYTE RdStateId(DWORD d);
|
||||
static BYTE RdStateQuery(DWORD d);
|
||||
static BYTE RdStateSR(DWORD d);
|
||||
static BYTE RdStateXSR(DWORD d);
|
||||
|
||||
static BYTE (*CONST fnRdState[])(DWORD d) =
|
||||
{
|
||||
RdStateData, RdStateId, RdStateQuery, RdStateSR, RdStateXSR
|
||||
};
|
||||
|
||||
|
||||
// read query table
|
||||
// device address A16-A1, A0 unused
|
||||
static CONST BYTE byQueryTab[] =
|
||||
{
|
||||
// access with "Read Identifier Codes" command
|
||||
// Identifier codes
|
||||
0xB0, // 00, Manufacturer Code
|
||||
0xD0, // 01, Device Code (16 Mbit)
|
||||
0x00, // 02, Block Lock Configuration
|
||||
0x02, // 03, ??
|
||||
|
||||
0x00, // 04, Reserved for vendor-specific information
|
||||
0x00, // 05, "
|
||||
0x00, // 06, "
|
||||
0x00, // 07, "
|
||||
0x00, // 08, "
|
||||
0x00, // 09, "
|
||||
0x00, // 0A, "
|
||||
0x00, // 0B, "
|
||||
0x00, // 0C, "
|
||||
0x00, // 0D, "
|
||||
0x00, // 0E, "
|
||||
0x00, // 0F, "
|
||||
|
||||
// access with "Read Query" command
|
||||
// CFI query identification string
|
||||
0x51, // 10, Query-Unique ASCII string "Q"
|
||||
0x52, // 11, Query-Unique ASCII string "R"
|
||||
0x59, // 12, Query-Unique ASCII string "Y"
|
||||
0x01, // 13, Primary Vendor Command Set and Control Interface ID CODE
|
||||
0x00, // 14, "
|
||||
0x31, // 15, Address for Primary Algorithm Extended Query Table
|
||||
0x00, // 16, "
|
||||
0x00, // 17, Alternate Vendor Command Set and Control Interface ID Code
|
||||
0x00, // 18, "
|
||||
0x00, // 19, Address for Secondary Algorithm Extended Query Table
|
||||
0x00, // 1A, "
|
||||
|
||||
// System interface information
|
||||
0x30, // 1B, Vcc Logic Supply Minimum Program/Erase Voltage (0x27 intel doc, 0x30 real chip)
|
||||
0x55, // 1C, Vcc Logic Supply Maximum Program/Erase Voltage
|
||||
0x30, // 1D, Vpp [Programming] Supply Minimum Program/Erase Voltage (0x27 intel doc, 0x30 real chip)
|
||||
0x55, // 1E, Vpp [Programming] Supply Maximum Program/Erase Voltage
|
||||
0x03, // 1F, Typical Time-Out per Single Byte/Word Program
|
||||
0x06, // 20, Typical Time-Out for Max. Buffer Write
|
||||
0x0A, // 21, Typical Time-Out per Individual Block Erase
|
||||
0x0F, // 22, Typical Time-Out for Full Chip Erase
|
||||
0x04, // 23, Maximum Time-Out for Byte/Word Program
|
||||
0x04, // 24, Maximum Time-Out for Buffer Write
|
||||
0x04, // 25, Maximum Time-Out per Individual Block Erase
|
||||
0x04, // 26, Maximum Time-Out for Full Chip Erase
|
||||
0x15, // 27, Device Size
|
||||
0x02, // 28, Flash Device Interface Description
|
||||
0x00, // 29, "
|
||||
0x05, // 2A, Maximum Number of Bytes in Write Buffer
|
||||
0x00, // 2B, "
|
||||
0x01, // 2C, Number of Erase Block Regions within Device
|
||||
0x1F, // 2D, Erase Block Region Information
|
||||
0x00, // 2E, "
|
||||
0x00, // 2F, "
|
||||
0x01, // 30, "
|
||||
|
||||
// Intel-specific extended query table
|
||||
0x50, // 31, Primary Extended Query Table, Unique ASCII string "P"
|
||||
0x52, // 32, Primary Extended Query Table, Unique ASCII string "R"
|
||||
0x49, // 33, Primary Extended Query Table, Unique ASCII string "I"
|
||||
0x31, // 34, Major Version Number, ASCII
|
||||
0x30, // 35, Minor Version Number, ASCII
|
||||
0x0F, // 36, Optional Feature & Command Support
|
||||
0x00, // 37, "
|
||||
0x00, // 38, "
|
||||
0x00, // 39, "
|
||||
0x01, // 3A, Supported Functions after Suspend
|
||||
0x03, // 3B, Block Status Register Mask
|
||||
0x00, // 3C, "
|
||||
0x50, // 3D, Vcc Logic Supply Optimum Program/Erase voltage
|
||||
0x50, // 3E, Vpp [Programming] Supply Optimum Program/Erase voltage
|
||||
0x00 // 3F, ??
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// ROM buffer access functions
|
||||
//
|
||||
|
||||
static __inline void WrDirtyPage(DWORD d)
|
||||
{
|
||||
if (pbyRomDirtyPage) // using dirty ROM page table
|
||||
{
|
||||
DWORD dwPage = d / ROMPAGESIZE; // this is the page
|
||||
|
||||
_ASSERT(dwPage < dwRomDirtyPageSize);
|
||||
pbyRomDirtyPage[dwPage] = TRUE; // page is dirty
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static __inline void EraseBlock(DWORD d,DWORD dwNibSize)
|
||||
{
|
||||
LPBYTE pbyAddr = pbyRom + d;
|
||||
|
||||
while (dwNibSize--)
|
||||
{
|
||||
WrDirtyPage(d++); // make page dirty
|
||||
*pbyAddr++ = 0x0F; // clear address
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static __inline void WriteByte(DWORD d,BYTE byData)
|
||||
{
|
||||
WrDirtyPage(d); // make page dirty
|
||||
|
||||
_ASSERT(d+1 < dwRomSize); // address valid?
|
||||
*(pbyRom+d) &= (byData & 0x0F); // write LSB
|
||||
*(pbyRom+d+1) &= (byData >> 4); // write MSB
|
||||
return;
|
||||
}
|
||||
|
||||
static __inline BYTE ReadByte(DWORD d)
|
||||
{
|
||||
_ASSERT(d+1 < dwRomSize); // address valid?
|
||||
return *(pbyRom+d)|(*(pbyRom+d+1)<<4); // get byte
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// write state functions
|
||||
//
|
||||
|
||||
static VOID WrStateIdle(BYTE a, DWORD d)
|
||||
{
|
||||
WSMset.bRomArray = FALSE; // register access
|
||||
|
||||
switch(a)
|
||||
{
|
||||
case READ_ARRAY: // read array mode, normal operation
|
||||
WSMset.bRomArray = TRUE; // data array access
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
WSMset.uRdState = RDS_DATA;
|
||||
break;
|
||||
case READ_ID_CODES: // read identifier codes register
|
||||
WSMset.uRdState = RDS_ID;
|
||||
break;
|
||||
case READ_QUERY: // read query register
|
||||
WSMset.uRdState = RDS_QUERY;
|
||||
break;
|
||||
case READ_STATUS_REG: // read status register
|
||||
WSMset.uRdState = RDS_SR;
|
||||
break;
|
||||
case CLEAR_STATUS_REG: // clear status register
|
||||
WSMset.byStatusReg = 0;
|
||||
break;
|
||||
case WRITE_BUFFER: // write to buffer
|
||||
WrStateE8(d);
|
||||
break;
|
||||
case WORD_BYTE_PROG1:
|
||||
case WORD_BYTE_PROG2: // byte/word program
|
||||
WrState40(d);
|
||||
break;
|
||||
case BLOCK_ERASE: // block erase
|
||||
WrState20(d);
|
||||
break;
|
||||
case BLOCK_ERASE_SUSPEND: // block erase, word/byte program suspend
|
||||
WSMset.byStatusReg |= WSMS; // operation suspended
|
||||
WSMset.byStatusReg &= ~ESS; // block erase completed (because no timing emulation)
|
||||
WSMset.byStatusReg &= ~BWSS; // program completed (because no timing emulation)
|
||||
WSMset.uRdState = RDS_SR;
|
||||
break;
|
||||
case BLOCK_ERASE_RESUME: // block erase, word/byte program resume
|
||||
WSMset.byStatusReg &= ~WSMS; // operation in progress
|
||||
WSMset.byStatusReg &= ~ESS; // block erase in progress
|
||||
WSMset.byStatusReg &= ~BWSS; // program in progress
|
||||
WSMset.byStatusReg |= WSMS; // operation completed (because no timing emulation)
|
||||
WSMset.uRdState = RDS_SR;
|
||||
break;
|
||||
case STS_CONFIG:
|
||||
WSMset.bRomArray = bFlashRomArray; // old access mode
|
||||
WrStateB8(d);
|
||||
break;
|
||||
case SET_CLR_BLOCK_LOCK: // set/clear block lock-bits
|
||||
WrState60(d);
|
||||
break;
|
||||
case FULL_CHIP_ERASE: // full chip erase
|
||||
WrState30(d);
|
||||
break;
|
||||
default: // wrong command
|
||||
WSMset.bRomArray = bFlashRomArray; // old access mode
|
||||
break;
|
||||
}
|
||||
|
||||
if (bFlashRomArray != WSMset.bRomArray) // new access mode
|
||||
{
|
||||
bFlashRomArray = WSMset.bRomArray; // change register access
|
||||
Map(0x00,0xFF); // update memory mapping
|
||||
UpdatePatches(bFlashRomArray); // patch/unpatch ROM again
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// write to buffer initial command
|
||||
static VOID WrStateE8(DWORD d)
|
||||
{
|
||||
// @todo add 2nd write buffer implementation
|
||||
// @todo add program timing implementation
|
||||
|
||||
WSMset.byExStatusReg = 0; // no write buffer
|
||||
if (WSMset.byWrite1No == 0) // buffer1 available
|
||||
{
|
||||
WSMset.byWrite1No = 1; // buffer1 in use
|
||||
WSMset.dwWrite1Addr = d; // byte block address of buffer1
|
||||
WSMset.byExStatusReg = WBS; // write buffer available
|
||||
// fill write buffer
|
||||
FillMemory(WSMset.pbyWrite1,ARRAYSIZEOF(WSMset.pbyWrite1),0xFF);
|
||||
WSMset.uWrState = WRS_WR_BUFFER_N; // set state machine
|
||||
WSMset.uRdState = RDS_XSR;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// write to buffer number of byte
|
||||
static VOID WrStateE8N(BYTE a, DWORD d)
|
||||
{
|
||||
if (a < (1 << byQueryTab[0x2A])) // byte is length information
|
||||
{
|
||||
WSMset.byWrite1No += a; // save no. of byte to program
|
||||
WSMset.byWrite1Size = a; // save size to check write buffer boundaries
|
||||
WSMset.dwWrite1Addr = d; // byte block address of buffer1
|
||||
WSMset.byStatusReg &= ~WSMS; // state machine busy
|
||||
WSMset.uWrState = WRS_WR_BUFFER_D;
|
||||
}
|
||||
else
|
||||
{
|
||||
WSMset.byWrite1No = 0; // free write buffer
|
||||
// improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
WSMset.byStatusReg |= WSMS; // data written
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
}
|
||||
WSMset.uRdState = RDS_SR;
|
||||
return;
|
||||
}
|
||||
|
||||
// write to buffer data
|
||||
static VOID WrStateE8D(BYTE a, DWORD d)
|
||||
{
|
||||
// first data byte
|
||||
if (WSMset.byWrite1No == WSMset.byWrite1Size + 1)
|
||||
{
|
||||
DWORD dwBlockMask = ~(((byQueryTab[0x30] << 8) | byQueryTab[0x2F]) * 256 - 1);
|
||||
|
||||
// same block
|
||||
if ((WSMset.dwWrite1Addr & dwBlockMask) == (d & dwBlockMask))
|
||||
{
|
||||
WSMset.dwWrite1Addr = d; // byte block address of buffer1
|
||||
WSMset.pbyWrite1[0] = a; // save byte
|
||||
}
|
||||
else
|
||||
{
|
||||
WSMset.byWrite1No = 0; // free write buffer
|
||||
// improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
WSMset.byStatusReg |= WSMS; // data written
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// write address within buffer
|
||||
if (d >= WSMset.dwWrite1Addr && d <= WSMset.dwWrite1Addr + WSMset.byWrite1Size)
|
||||
{
|
||||
// save byte in buffer
|
||||
WSMset.pbyWrite1[d-WSMset.dwWrite1Addr] = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
WSMset.byWrite1No = 0; // free write buffer
|
||||
// improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
WSMset.byStatusReg |= WSMS; // data written
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (--WSMset.byWrite1No == 0) // last byte written
|
||||
WSMset.uWrState = WRS_WR_BUFFER_C; // goto confirm state
|
||||
return;
|
||||
}
|
||||
|
||||
// write to buffer confirm
|
||||
static VOID WrStateE8C(BYTE a, DWORD d)
|
||||
{
|
||||
if (CONFIRM == a) // write buffer confirm?
|
||||
{
|
||||
BYTE byPos;
|
||||
|
||||
d = WSMset.dwWrite1Addr << 1; // nibble start address
|
||||
|
||||
for (byPos = 0; byPos <= WSMset.byWrite1Size; ++byPos)
|
||||
{
|
||||
a = WSMset.pbyWrite1[byPos]; // get char from buffer
|
||||
|
||||
_ASSERT(d+1 < dwRomSize); // address valid?
|
||||
// no error set in BWSLBS, because I could alway program a "0"
|
||||
WriteByte(d,a); // write byte
|
||||
d += 2; // next address
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WSMset.byWrite1No = 0; // free write buffer
|
||||
// improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
}
|
||||
WSMset.byStatusReg |= WSMS; // data written
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
// byte/word program initial command
|
||||
static VOID WrState40(DWORD d)
|
||||
{
|
||||
WSMset.byStatusReg &= ~WSMS; // state machine busy
|
||||
WSMset.uWrState = WRS_WR_BYTE;
|
||||
WSMset.uRdState = RDS_SR;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// byte/word program data
|
||||
static VOID WrState40D(BYTE a, DWORD d)
|
||||
{
|
||||
// no error set in BWSLBS, because I could alway program a "0"
|
||||
WriteByte(d << 1,a); // write byte
|
||||
WSMset.byStatusReg |= WSMS; // data written
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
// block erase initial command
|
||||
static VOID WrState20(DWORD d)
|
||||
{
|
||||
WSMset.byStatusReg &= ~WSMS; // state machine busy
|
||||
WSMset.uWrState = WRS_BLOCK_ERASE;
|
||||
WSMset.uRdState = RDS_SR;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// block erase data & confirm
|
||||
static VOID WrState20C(BYTE a, DWORD d)
|
||||
{
|
||||
if (CONFIRM == a) // block erase confirm?
|
||||
{
|
||||
// lock bit of block is set
|
||||
if ((WSMset.dwLockCnfg & (1<<(d>>16))) != 0)
|
||||
{
|
||||
WSMset.byStatusReg |= ECLBS; // error in block erasure
|
||||
WSMset.byStatusReg |= DPS; // lock bit detected
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD dwBlockSize = ((byQueryTab[0x30] << 8) | byQueryTab[0x2F]) * 256;
|
||||
|
||||
d &= ~(dwBlockSize-1); // start of block
|
||||
dwBlockSize *= 2; // block size in nibbles
|
||||
_ASSERT(d+dwBlockSize <= dwRomSize); // address valid?
|
||||
EraseBlock(d << 1,dwBlockSize); // erase 128K nibble
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
}
|
||||
WSMset.byStatusReg |= WSMS; // block erased
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
// full chip erase initial command
|
||||
static VOID WrState30(DWORD d)
|
||||
{
|
||||
WSMset.byStatusReg &= ~WSMS; // state machine busy
|
||||
WSMset.uWrState = WRS_CHIP_ERASE;
|
||||
WSMset.uRdState = RDS_SR;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// full chip erase confirm
|
||||
static VOID WrState30C(BYTE a, DWORD d)
|
||||
{
|
||||
if (CONFIRM == a) // chip erase confirm?
|
||||
{
|
||||
UINT i;
|
||||
|
||||
WORD wNoOfBlocks = (byQueryTab[0x2E] << 8) | byQueryTab[0x2D];
|
||||
DWORD dwBlockSize = ((byQueryTab[0x30] << 8) | byQueryTab[0x2F]) * 256;
|
||||
|
||||
DWORD dwBlockAddr = 0;
|
||||
|
||||
dwBlockSize *= 2; // block size in nibbles
|
||||
|
||||
for (i = 0; i <= wNoOfBlocks; ++i) // check all blocks
|
||||
{
|
||||
_ASSERT((i+1)*dwBlockSize <= dwRomSize);
|
||||
|
||||
// lock bit of block is set & WP# = low, locked blocks cannot be erased
|
||||
if ((WSMset.dwLockCnfg & (1<<i)) == 0 || bWP != FALSE)
|
||||
{
|
||||
// clear block lock bit
|
||||
WSMset.dwLockCnfg &= ~(1<<i);
|
||||
|
||||
// erase 128K nibble
|
||||
EraseBlock(dwBlockAddr,dwBlockSize);
|
||||
}
|
||||
|
||||
dwBlockAddr += dwBlockSize; // next block
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
}
|
||||
WSMset.byStatusReg |= WSMS; // chip erased
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// STS pin Configuration initial command
|
||||
static VOID WrStateB8(DWORD d)
|
||||
{
|
||||
WSMset.uWrState = WRS_STS_PIN_CONFIG;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// STS pin Configuration data
|
||||
static VOID WrStateB8D(BYTE a, DWORD d)
|
||||
{
|
||||
// no emulation of STS pin Configuration
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(a);
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// Set/Clear block Lock-Bits initial command
|
||||
static VOID WrState60(DWORD d)
|
||||
{
|
||||
WSMset.byStatusReg &= ~WSMS; // state machine busy
|
||||
WSMset.uWrState = WRS_LOCK_BITS;
|
||||
WSMset.uRdState = RDS_SR;
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// Set/Clear block Lock-Bits confirm
|
||||
static VOID WrState60D(BYTE a, DWORD d)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
switch(a)
|
||||
{
|
||||
case 0x01: // set block lock bit
|
||||
if (bWP) // WP# = high, can change block lock status
|
||||
WSMset.dwLockCnfg |= (1<<(d>>16)); // set block lock bit
|
||||
else
|
||||
WSMset.byStatusReg |= (BWSLBS | DPS); // device protect detect, WP# = low
|
||||
break;
|
||||
case CONFIRM: // clear block lock bits
|
||||
if (bWP) // WP# = high, can change block lock status
|
||||
{
|
||||
WORD wNoOfBlocks = (byQueryTab[0x2E] << 8) | byQueryTab[0x2D];
|
||||
|
||||
for (i = 0; i <= wNoOfBlocks; ++i) // clear all lock bits
|
||||
{
|
||||
WSMset.dwLockCnfg &= ~(1 << i); // clear block lock bit
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WSMset.byStatusReg |= (ECLBS | DPS); // device protect detect, WP# = low
|
||||
}
|
||||
break;
|
||||
default: // improper command sequence
|
||||
WSMset.byStatusReg |= (ECLBS | BWSLBS);
|
||||
}
|
||||
WSMset.byStatusReg |= WSMS; // block lock-bit changed
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// read state functions
|
||||
//
|
||||
|
||||
// read array
|
||||
static BYTE RdStateData(DWORD d)
|
||||
{
|
||||
return ReadByte(d << 1); // get byte
|
||||
}
|
||||
|
||||
// read identifier codes
|
||||
static BYTE RdStateId(DWORD d)
|
||||
{
|
||||
BYTE byData;
|
||||
|
||||
d >>= 1; // A0 is not connected, ignore it
|
||||
if ((d & 0x03) != 0x02) // id code request
|
||||
{
|
||||
d &= 0x03; // data repetition
|
||||
byData = byQueryTab[d]; // get data from first 4 bytes id/query table
|
||||
}
|
||||
else // block lock table
|
||||
{
|
||||
// get data from block lock table
|
||||
byData = (BYTE) ((WSMset.dwLockCnfg >> (d >> 15)) & 1);
|
||||
|
||||
d &= 0x1F; // data repetition
|
||||
if (d >= 4) byData |= 0x02; // set bit 1 on wrong ID adress
|
||||
}
|
||||
return byData;
|
||||
}
|
||||
|
||||
// read query
|
||||
static BYTE RdStateQuery(DWORD d)
|
||||
{
|
||||
BYTE byData;
|
||||
|
||||
d >>= 1; // A0 is not connected, ignore it
|
||||
if ((d & 0x7F) != 0x02) // query request
|
||||
{
|
||||
d &= 0x7F; // data repetition
|
||||
|
||||
// get data from id/query table
|
||||
byData = (d >= 0x40 && d < 0x50) ? 0 : byQueryTab[d&0x3F];
|
||||
}
|
||||
else // block lock table
|
||||
{
|
||||
// get data from block lock table
|
||||
byData = (BYTE) ((WSMset.dwLockCnfg >> (d >> 15)) & 1);
|
||||
}
|
||||
return byData;
|
||||
}
|
||||
|
||||
// read status register
|
||||
static BYTE RdStateSR(DWORD d)
|
||||
{
|
||||
return WSMset.byStatusReg;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
// read extended status register
|
||||
static BYTE RdStateXSR(DWORD d)
|
||||
{
|
||||
return WSMset.byExStatusReg;
|
||||
UNREFERENCED_PARAMETER(d);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
VOID FlashInit(VOID)
|
||||
{
|
||||
// check if locking bit table has more or equal than 32 bit
|
||||
_ASSERT(sizeof(WSMset.dwLockCnfg) * 8 >= 32);
|
||||
|
||||
ZeroMemory(&WSMset,sizeof(WSMset));
|
||||
strcpy((LPSTR) WSMset.byType,"WSM"); // Write State Machine header
|
||||
WSMset.uSize = sizeof(WSMset); // size of this structure
|
||||
WSMset.byVersion = WSMVER; // version of flash implementation structure
|
||||
|
||||
// factory setting of locking bits
|
||||
WSMset.dwLockCnfg = (1 << 0); // first 64KB block is locked
|
||||
|
||||
WSMset.uWrState = WRS_DATA;
|
||||
WSMset.uRdState = RDS_DATA;
|
||||
|
||||
// data mode of ROM
|
||||
WSMset.bRomArray = bFlashRomArray = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
VOID FlashRead(BYTE *a, DWORD d, UINT s)
|
||||
{
|
||||
BYTE v;
|
||||
|
||||
while (s) // each nibble
|
||||
{
|
||||
// output muliplexer
|
||||
_ASSERT(WSMset.uRdState < ARRAYSIZEOF(fnRdState));
|
||||
v = fnRdState[WSMset.uRdState](d>>1);
|
||||
|
||||
if ((d & 1) == 0) // even address
|
||||
{
|
||||
*a++ = v & 0xf; ++d; --s;
|
||||
}
|
||||
if (s && (d & 1)) // odd address
|
||||
{
|
||||
*a++ = v >> 4; ++d; --s;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID FlashWrite(BYTE *a, DWORD d, UINT s)
|
||||
{
|
||||
BYTE v;
|
||||
DWORD p;
|
||||
|
||||
while (s) // each nibble
|
||||
{
|
||||
p = d >> 1; // byte address
|
||||
if (s > 1 && (d & 1) == 0) // more than one byte on even address
|
||||
{
|
||||
v = *a++; // LSB
|
||||
v |= *a++ << 4; // MSB
|
||||
d += 2; s -= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get byte from output muliplexer
|
||||
_ASSERT(WSMset.uRdState < ARRAYSIZEOF(fnRdState));
|
||||
v = fnRdState[WSMset.uRdState](p);
|
||||
|
||||
if (d & 1) // odd address
|
||||
v = (v & 0x0F) | (*a << 4); // replace MSB
|
||||
else // even address
|
||||
v = (v & 0xF0) | *a; // replace LSB
|
||||
++a; ++d; --s;
|
||||
}
|
||||
|
||||
_ASSERT(WSMset.uWrState < ARRAYSIZEOF(fnWrState));
|
||||
fnWrState[WSMset.uWrState](v,p); // WSM
|
||||
}
|
||||
return;
|
||||
}
|
40
app/src/main/cpp/I28F160.H
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* i28f160.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2000 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
|
||||
#define WSMVER 0 // version of flash implementation structure
|
||||
|
||||
#define WSMSET WSMset_t
|
||||
typedef struct
|
||||
{
|
||||
BYTE byType[4]; // "WSM"
|
||||
UINT uSize; // size of this structure
|
||||
BYTE byVersion; // WSM version
|
||||
|
||||
BOOL bRomArray; // copy of bFlashRomArray
|
||||
DWORD dwLockCnfg; // block lock table (32 entries)
|
||||
UINT uWrState; // state of write function WSM
|
||||
UINT uRdState; // state of read function WSM
|
||||
BYTE byStatusReg; // status register
|
||||
BYTE byExStatusReg; // extended status register
|
||||
BYTE byWrite1No; // no. of written data in write buffer1
|
||||
BYTE byWrite1Size; // no. of valid data in write buffer1
|
||||
DWORD dwWrite1Addr; // destination address of buffer1
|
||||
BYTE pbyWrite1[32]; // write buffer1
|
||||
// BYTE byWrite2No; // no. of written data in write buffer2
|
||||
// BYTE byWrite2Size; // no. of valid data in write buffer2
|
||||
// DWORD dwWrite2Addr; // destination address of buffer2
|
||||
// BYTE pbyWrite2[32]; // write buffer2
|
||||
} WSMset_t;
|
||||
|
||||
// i28f160.h
|
||||
extern WSMSET WSMset;
|
||||
extern BOOL bWP;
|
||||
extern VOID FlashInit(VOID);
|
||||
extern VOID FlashRead(BYTE *a, DWORD d, UINT s);
|
||||
extern VOID FlashWrite(BYTE *a, DWORD d, UINT s);
|
154
app/src/main/cpp/IO.H
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* io.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1999 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
|
||||
// I/O addresses without mapping offset
|
||||
#define BITOFFSET 0x00 // Display bit offset and DON
|
||||
#define CRC 0x04 // Crc (16 bit, LSB first)
|
||||
#define LPD 0x08 // Low Power Detection
|
||||
#define LPE 0x09 // Low Power detection Enable
|
||||
#define ANNCTRL 0x0b // Annunciator Control (2 nibble)
|
||||
#define BAUD 0x0d // Baudrate (Bit 2-0)
|
||||
#define CARDCTL 0x0e // card control
|
||||
#define CARDSTAT 0x0f // card status
|
||||
#define IOC 0x10 // IO CONTROL
|
||||
#define RCS 0x11 // RCS
|
||||
#define TCS 0x12 // TCS
|
||||
#define CRER 0x13 // CRER
|
||||
#define RBR_LSB 0x14 // RBR low nibble
|
||||
#define RBR_MSB 0x15 // RBR high nibble
|
||||
#define TBR_LSB 0x16 // TBR low nibble
|
||||
#define TBR_MSB 0x17 // TBR high nibble
|
||||
#define SRQ1 0x18 // SRQ1
|
||||
#define SRQ2 0x19 // SRQ2
|
||||
#define IR_CTRL 0x1a // IR CONTROL
|
||||
#define LCR 0x1c // Led Control Register
|
||||
#define LBR 0x1d // Led Buffer Register
|
||||
#define DISP1CTL 0x20 // Display Start Address
|
||||
#define LINENIBS 0x25 // Display Line Offset
|
||||
#define LINECOUNT 0x28 // Display Line Counter
|
||||
#define TIMER1_CTRL 0x2e // Timer1 Control
|
||||
#define TIMER2_CTRL 0x2f // Timer2 Control
|
||||
#define DISP2CTL 0x30 // Display Secondary Start Address
|
||||
#define TIMER1 0x37 // Timer1 (4 bit)
|
||||
#define TIMER2 0x38 // Timer2 (32 bit, LSB first)
|
||||
|
||||
// 0x00 Display bit offset and DON [DON OFF2 OFF1 OFF0]
|
||||
#define DON 0x08 // Display On
|
||||
#define OFF2 0x04 // Display OFFset Bit2
|
||||
#define OFF1 0x02 // Display OFFset Bit1
|
||||
#define OFF0 0x01 // Display OFFset Bit0
|
||||
|
||||
// 0x08 Low Power Detection [LB2 LB1 LB0 VLBI]
|
||||
#define LB2 0x08 // Low Battery indicator memory port 2
|
||||
#define LB1 0x04 // Low Battery indicator memory port 1
|
||||
#define LB0 0x02 // Low Battery indicator system battery
|
||||
#define VLBI 0x01 // Very Low Battery Indicator
|
||||
|
||||
// 0x09 Low Power detection Enable [ELBI EVLBI GRAM RST]
|
||||
#define ELBI 0x08 // Enable Low Battery Indicator
|
||||
#define EVLBI 0x04 // Enable Very Low Battery Indicator
|
||||
#define GRAM 0x02 // Glitch sensitive RAM
|
||||
#define RST 0x01 // ReSeT
|
||||
|
||||
// 0x0b Annunciator Control [AON XTRA LA6 LA5] [LA4 LA3 LA2 LA1]
|
||||
#define AON 0x80 // Annunciators on
|
||||
#define LXTRA 0x40 // does nothing
|
||||
#define LA6 0x20 // LA6 - Transmitting
|
||||
#define LA5 0x10 // LA5 - Busy
|
||||
#define LA4 0x08 // LA4 - Alert
|
||||
#define LA3 0x04 // LA3 - Alpha
|
||||
#define LA2 0x02 // LA2 - ALT Shift
|
||||
#define LA1 0x01 // LA1 - Shift
|
||||
|
||||
// 0x0d SERIAL Baud Rate [UCK BD2 BD1 BD0]
|
||||
#define UCK 0x08 // Uart ClocK
|
||||
#define BD2 0x04 // BauDrate Bit2
|
||||
#define BD1 0x02 // BauDrate Bit1
|
||||
#define BD0 0x01 // BauDrate Bit0
|
||||
|
||||
// 0x0e Card Control [ECDT RCDT SMP SWINT]
|
||||
#define ECDT 0x08 // Enable Card Detect
|
||||
#define RCDT 0x04 // Run Card Detect
|
||||
#define SMP 0x02 // Set module pulled
|
||||
#define SWINT 0x01 // Software Interrupt
|
||||
|
||||
// 0x0f Card Status [P2W P1W P2C P1C]
|
||||
#define P2W 0x08 // High when Port2 writeable
|
||||
#define P1W 0x04 // High when Port1 writeable
|
||||
#define P2C 0x02 // High when Card in Port2 inserted
|
||||
#define P1C 0x01 // High when Card in Port1 inserted
|
||||
|
||||
// 0x10 Serial I/O Control [SON ETBE ERBF ERBZ]
|
||||
#define SON 0x08 // Serial on
|
||||
#define ETBE 0x04 // Interrupt on transmit buffer empty
|
||||
#define ERBF 0x02 // Interrupt on receive buffer full
|
||||
#define ERBZ 0x01 // Interrupt on receiver busy
|
||||
|
||||
// 0x11 Serial Receive Control/Status [RX RER RBZ RBF]
|
||||
#define RX 0x08 // Rx pin state (read-only)
|
||||
#define RER 0x04 // Receiver error
|
||||
#define RBZ 0x02 // Receiver busy
|
||||
#define RBF 0x01 // Receive buffer full
|
||||
|
||||
// 0x12 Serial Transmit Control/Status [BRK LPB TBZ TBF]
|
||||
#define BRK 0x08 // Break
|
||||
#define LPB 0x04 // Loopback
|
||||
#define TBZ 0x02 // Transmitter busy
|
||||
#define TBF 0x01 // Transmit buffer full
|
||||
|
||||
// 0x18 Service Request Register 1 [ISRQ TSRQ USRQ VSRQ]
|
||||
#define ISRQ 0x08 // IR receiver pulls NINT2
|
||||
#define TSRQ 0x04 // Timer pulls NINT2
|
||||
#define USRQ 0x02 // UART pulls NINT2
|
||||
#define VSRQ 0x01 // VLBI pulls NINT2
|
||||
|
||||
// 0x19 Service Request Register 2 [KDN NINT2 NINT LSRQ]
|
||||
#define KDN 0x08 // Bit set when ON Key or Key Interrupt
|
||||
#define NINT2 0x04 // State of NINT2
|
||||
#define NINT 0x02 // State of NINT
|
||||
#define LSRQ 0x01 // LED driver pulls NINT2
|
||||
|
||||
// 0x1a IR Control Register [IRI EIRU EIRI IRE]
|
||||
#define IRI 0x08 // IR input (read-only)
|
||||
#define EIRU 0x04 // Enable IR UART mode
|
||||
#define EIRI 0x02 // Enable IR interrupt
|
||||
#define IRE 0x01 // IR event
|
||||
|
||||
// 0x1c Led Control Register [LED ELBE LBZ LBF]
|
||||
#define LED 0x08 // Turn on LED
|
||||
#define ELBE 0x04 // Enable Interrupt on Led Buffer empty
|
||||
#define LBZ 0x02 // Led Port Busy
|
||||
#define LBF 0x01 // Led Buffer Full
|
||||
|
||||
// 0x1d Led Buffer Register [0 0 0 LBO] (bits 1-3 read zero)
|
||||
#define LBO 0x01
|
||||
|
||||
// 0x28 Display Line Counter LSB [LC3 LC2 LC1 LC0]
|
||||
#define LC3 0x08 // LC3 - Line Counter Bit3
|
||||
#define LC2 0x04 // LC2 - Line Counter Bit2
|
||||
#define LC1 0x02 // LC1 - Line Counter Bit1
|
||||
#define LC0 0x01 // LC0 - Line Counter Bit0
|
||||
|
||||
// 0x29 Display Line Counter MSB [DA19 M32 LC5 LC4]
|
||||
#define DA19 0x08 // Drive A[19]
|
||||
#define M32 0x04 // Multiplex 32 way
|
||||
#define LC5 0x02 // LC5 - Line Counter Bit5
|
||||
#define LC4 0x01 // LC4 - Line Counter Bit4
|
||||
|
||||
// 0x2e Timer1 Control [SRQ WKE INT XTRA]
|
||||
#define SRQ 0x08 // Service request
|
||||
#define WKE 0x04 // Wake up
|
||||
#define INTR 0x02 // Interrupt
|
||||
#define XTRA 0x01 // Extra function
|
||||
|
||||
// 0x2f Timer2 Control [SRQ WKE INT RUN]
|
||||
#define SRQ 0x08 // Service request
|
||||
#define WKE 0x04 // Wake up
|
||||
#define INTR 0x02 // Interrupt
|
||||
#define RUN 0x01 // Timer run
|
131
app/src/main/cpp/KEYBOARD.C
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* keyboard.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1995 Sebastien Carlier
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h" // I/O definitions
|
||||
|
||||
DWORD dwKeyMinDelay = 50; // minimum time for key hold
|
||||
|
||||
static WORD Keyboard_GetIR(VOID)
|
||||
{
|
||||
WORD r = 0;
|
||||
|
||||
// OR[0:8] are wired on Clarke/Yorke chip
|
||||
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 bActive, BOOL bReset)
|
||||
{
|
||||
// bActive = TRUE -> function called by direct read (A=IN, C=IN, RSI)
|
||||
// FALSE -> function called by 1ms keyboard poll simulation
|
||||
// bReset = TRUE -> Reset Chipset.in interrupt state register
|
||||
// FALSE -> generate interrupt only for new pressed keys
|
||||
|
||||
// keyboard read not active?
|
||||
if (!( bActive || Chipset.Shutdn || Chipset.IR15X
|
||||
|| (Chipset.intk && (Chipset.IORam[TIMER2_CTRL]&RUN) != 0)))
|
||||
{
|
||||
EnterCriticalSection(&csKeyLock);
|
||||
{
|
||||
Chipset.in &= ~0x8000; // remove ON key
|
||||
}
|
||||
LeaveCriticalSection(&csKeyLock);
|
||||
return;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&csKeyLock); // synchronize
|
||||
{
|
||||
BOOL bKbdInt;
|
||||
|
||||
WORD wOldIn = Chipset.in; // save old Chipset.in state
|
||||
|
||||
UpdateKdnBit(); // update KDN bit
|
||||
Chipset.dwKdnCycles = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||
|
||||
Chipset.in = Keyboard_GetIR(); // update Chipset.in register
|
||||
Chipset.in |= Chipset.IR15X; // add ON key
|
||||
|
||||
// interrupt for any new pressed keys?
|
||||
bKbdInt = (Chipset.in && (wOldIn & 0x1FF) == 0) || Chipset.IR15X || bReset;
|
||||
|
||||
// update keyboard interrupt pending flag when 1ms keyboard scan is disabled
|
||||
Chipset.intd = Chipset.intd || (bKbdInt && !Chipset.intk);
|
||||
|
||||
// keyboard interrupt enabled?
|
||||
bKbdInt = bKbdInt && Chipset.intk;
|
||||
|
||||
// interrupt at ON key pressed
|
||||
bKbdInt = bKbdInt || Chipset.IR15X != 0;
|
||||
|
||||
// no interrupt if still inside interrupt service routine
|
||||
bKbdInt = bKbdInt && 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
|
||||
{
|
||||
Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode
|
||||
SetEvent(hEventShutdn); // wake up emulation thread
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Chipset.intd = FALSE; // no keyboard interrupt pending
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&csKeyLock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
VOID KeyboardEvent(BOOL bPress, UINT out, UINT in)
|
||||
{
|
||||
if (nState != SM_RUN) // not in running state
|
||||
return; // ignore key
|
||||
|
||||
KeyMacroRecord(bPress,out,in); // save all keyboard events
|
||||
|
||||
if (in == 0x8000) // ON key ?
|
||||
{
|
||||
Chipset.IR15X = bPress?0x8000:0x0000; // refresh special ON key flag
|
||||
}
|
||||
else
|
||||
{
|
||||
// "out" is outside Keyboard_Row
|
||||
if (out >= ARRAYSIZEOF(Chipset.Keyboard_Row)) return;
|
||||
|
||||
// in &= 0x1FF; // only IR[0:8] are wired on Clarke/Yorke chip
|
||||
|
||||
_ASSERT(out < ARRAYSIZEOF(Chipset.Keyboard_Row));
|
||||
if (bPress) // key pressed
|
||||
Chipset.Keyboard_Row[out] |= in; // set key marker in keyboard row
|
||||
else
|
||||
Chipset.Keyboard_Row[out] &= (~in); // clear key marker in keyboard row
|
||||
}
|
||||
AdjKeySpeed(); // adjust key repeat speed
|
||||
ScanKeyboard(FALSE,FALSE); // update Chipset.in register by 1ms keyboard poll
|
||||
Sleep(dwKeyMinDelay); // hold key state for a definite time
|
||||
return;
|
||||
}
|
337
app/src/main/cpp/KEYMACRO.C
Normal file
|
@ -0,0 +1,337 @@
|
|||
/*
|
||||
* Keymacro.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2004 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "resource.h"
|
||||
#include "Emu48.h"
|
||||
#include "kml.h"
|
||||
|
||||
#define KEYMACROHEAD "Emu-KeyMacro" // macro signature
|
||||
|
||||
#define MIN_SPEED 0
|
||||
#define MAX_SPEED 500
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD dwTime; // elapsed time
|
||||
DWORD dwKeyEvent; // key code
|
||||
} KeyData;
|
||||
|
||||
INT nMacroState = MACRO_OFF;
|
||||
INT nMacroTimeout = MIN_SPEED;
|
||||
BOOL bMacroRealSpeed = TRUE;
|
||||
DWORD dwMacroMinDelay = 0; // minimum macro play key hold time in ms
|
||||
|
||||
static DWORD dwTimeRef;
|
||||
|
||||
static HANDLE hMacroFile = INVALID_HANDLE_VALUE;
|
||||
static HANDLE hEventPlay = NULL;
|
||||
static HANDLE hThreadEv = NULL;
|
||||
|
||||
static VOID InitializeOFN(LPOPENFILENAME ofn)
|
||||
{
|
||||
ZeroMemory((LPVOID)ofn, sizeof(OPENFILENAME));
|
||||
ofn->lStructSize = sizeof(OPENFILENAME);
|
||||
ofn->hwndOwner = hWnd;
|
||||
ofn->Flags = OFN_EXPLORER|OFN_HIDEREADONLY;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// thread playing keys
|
||||
//
|
||||
static DWORD WINAPI EventThread(LPVOID pParam)
|
||||
{
|
||||
DWORD dwRead = 0;
|
||||
DWORD dwData = 0,dwTime = 0;
|
||||
|
||||
while (WaitForSingleObject(hEventPlay,dwTime) == WAIT_TIMEOUT)
|
||||
{
|
||||
if (dwRead != 0) // data read
|
||||
{
|
||||
UINT nIn = (dwData >> 0) & 0xFFFF;
|
||||
UINT nOut = (dwData >> 16) & 0xFF;
|
||||
BOOL bPress = (dwData >> 24) & 0xFF;
|
||||
|
||||
PlayKey(nOut,nIn,bPress);
|
||||
}
|
||||
|
||||
dwTime = nMacroTimeout; // set default speed
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
// read next data element
|
||||
if ( !ReadFile(hMacroFile,&dwData,sizeof(dwData),&dwRead,NULL)
|
||||
|| dwRead != sizeof(dwData))
|
||||
{
|
||||
// play record empty -> quit
|
||||
PostMessage(hWnd,WM_COMMAND,ID_TOOL_MACRO_STOP,0);
|
||||
return 0; // exit on file end
|
||||
}
|
||||
|
||||
if ((dwData & 0x80000000) != 0) // time information
|
||||
{
|
||||
if (bMacroRealSpeed) // realspeed from data
|
||||
{
|
||||
dwTime = dwData & 0x7FFFFFFF;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// hold the key state the minimum macro play key hold time
|
||||
if (dwTime < dwMacroMinDelay) dwTime = dwMacroMinDelay;
|
||||
|
||||
dwTime -= dwKeyMinDelay; // remove the actual key hold time
|
||||
// set negative number to zero
|
||||
if ((dwTime & 0x80000000) != 0) dwTime = 0;
|
||||
break; // got key information
|
||||
}
|
||||
}
|
||||
return 0; // exit on stop
|
||||
UNREFERENCED_PARAMETER(pParam);
|
||||
}
|
||||
|
||||
//
|
||||
// callback function for recording keys
|
||||
//
|
||||
VOID KeyMacroRecord(BOOL bPress, UINT out, UINT in)
|
||||
{
|
||||
if (nMacroState == MACRO_NEW) // save key event
|
||||
{
|
||||
KeyData Data;
|
||||
DWORD dwWritten;
|
||||
|
||||
dwWritten = GetTickCount(); // time reference
|
||||
Data.dwTime = (dwWritten - dwTimeRef);
|
||||
Data.dwTime |= 0x80000000; // set time marker
|
||||
dwTimeRef = dwWritten;
|
||||
|
||||
Data.dwKeyEvent = (bPress & 0xFF);
|
||||
Data.dwKeyEvent = (Data.dwKeyEvent << 8) | (out & 0xFF);
|
||||
Data.dwKeyEvent = (Data.dwKeyEvent << 16) | (in & 0xFFFF);
|
||||
|
||||
// save key event in file
|
||||
WriteFile(hMacroFile,&Data,sizeof(Data),&dwWritten,NULL);
|
||||
_ASSERT(dwWritten == sizeof(Data));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// message handler for save new keyboard macro
|
||||
//
|
||||
LRESULT OnToolMacroNew(VOID)
|
||||
{
|
||||
TCHAR szMacroFile[MAX_PATH];
|
||||
OPENFILENAME ofn;
|
||||
DWORD dwExtensionLength,dwWritten;
|
||||
|
||||
// get filename for saving
|
||||
InitializeOFN(&ofn);
|
||||
ofn.lpstrFilter =
|
||||
_T("Keyboard Macro Files (*.MAC)\0*.MAC\0")
|
||||
_T("All Files (*.*)\0*.*\0");
|
||||
ofn.lpstrDefExt = _T("MAC");
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.lpstrFile = szMacroFile;
|
||||
ofn.lpstrFile[0] = 0;
|
||||
ofn.nMaxFile = ARRAYSIZEOF(szMacroFile);
|
||||
ofn.Flags |= OFN_CREATEPROMPT|OFN_OVERWRITEPROMPT;
|
||||
if (GetSaveFileName(&ofn) == FALSE) return 0;
|
||||
|
||||
// open file for writing
|
||||
hMacroFile = CreateFile(szMacroFile,
|
||||
GENERIC_READ|GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (hMacroFile == INVALID_HANDLE_VALUE) return 0;
|
||||
|
||||
// write header
|
||||
WriteFile(hMacroFile,KEYMACROHEAD,sizeof(KEYMACROHEAD) - 1,&dwWritten,NULL);
|
||||
_ASSERT(dwWritten == (DWORD) strlen(KEYMACROHEAD));
|
||||
|
||||
// write extension length
|
||||
dwExtensionLength = 0; // no extension
|
||||
WriteFile(hMacroFile,&dwExtensionLength,sizeof(dwExtensionLength),&dwWritten,NULL);
|
||||
_ASSERT(dwWritten == sizeof(dwExtensionLength));
|
||||
|
||||
nMacroState = MACRO_NEW;
|
||||
|
||||
MessageBox(hWnd,
|
||||
_T("Press OK to begin to record the Macro."),
|
||||
_T("Macro Recorder"),
|
||||
MB_OK|MB_ICONINFORMATION);
|
||||
|
||||
dwTimeRef = GetTickCount(); // time reference
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// message handler for play keyboard macro
|
||||
//
|
||||
LRESULT OnToolMacroPlay(VOID)
|
||||
{
|
||||
BYTE byHeader[sizeof(KEYMACROHEAD)-1];
|
||||
TCHAR szMacroFile[MAX_PATH];
|
||||
OPENFILENAME ofn;
|
||||
DWORD dwExtensionLength,dwRead,dwThreadId;
|
||||
|
||||
InitializeOFN(&ofn);
|
||||
ofn.lpstrFilter =
|
||||
_T("Keyboard Macro Files (*.MAC)\0*.MAC\0")
|
||||
_T("All Files (*.*)\0*.*\0");
|
||||
ofn.lpstrDefExt = _T("MAC");
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.lpstrFile = szMacroFile;
|
||||
ofn.lpstrFile[0] = 0;
|
||||
ofn.nMaxFile = ARRAYSIZEOF(szMacroFile);
|
||||
ofn.Flags |= OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST;
|
||||
if (GetOpenFileName(&ofn) == FALSE) return 0;
|
||||
|
||||
// open file for Reading
|
||||
hMacroFile = CreateFile(szMacroFile,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (hMacroFile == INVALID_HANDLE_VALUE) return 0;
|
||||
|
||||
// read header
|
||||
ReadFile(hMacroFile,byHeader,sizeof(byHeader),&dwRead,NULL);
|
||||
if ( dwRead != sizeof(byHeader)
|
||||
|| memcmp(byHeader,KEYMACROHEAD,dwRead) != 0)
|
||||
{
|
||||
MessageBox(hWnd,
|
||||
_T("Wrong keyboard macro file format."),
|
||||
_T("Macro Recorder"),
|
||||
MB_OK|MB_ICONSTOP);
|
||||
CloseHandle(hMacroFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read extension length
|
||||
ReadFile(hMacroFile,&dwExtensionLength,sizeof(dwExtensionLength),&dwRead,NULL);
|
||||
if (dwRead != sizeof(dwExtensionLength))
|
||||
{
|
||||
CloseHandle(hMacroFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read extension
|
||||
while (dwExtensionLength-- > 0)
|
||||
{
|
||||
BYTE byData;
|
||||
|
||||
ReadFile(hMacroFile,&byData,sizeof(byData),&dwRead,NULL);
|
||||
if (dwRead != sizeof(byData))
|
||||
{
|
||||
CloseHandle(hMacroFile);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// event for quit playing
|
||||
hEventPlay = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||
|
||||
nMacroState = MACRO_PLAY;
|
||||
|
||||
// start playing thread
|
||||
VERIFY(hThreadEv = CreateThread(NULL,0,&EventThread,NULL,0,&dwThreadId));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// message handler for stop recording/playing
|
||||
//
|
||||
LRESULT OnToolMacroStop(VOID)
|
||||
{
|
||||
if (nMacroState != MACRO_OFF)
|
||||
{
|
||||
if (hEventPlay) // playing keys
|
||||
{
|
||||
// stop playing thread
|
||||
SetEvent(hEventPlay); // quit play loop
|
||||
|
||||
WaitForSingleObject(hThreadEv,INFINITE);
|
||||
CloseHandle(hThreadEv);
|
||||
hThreadEv = NULL;
|
||||
|
||||
CloseHandle(hEventPlay); // close playing keys event
|
||||
hEventPlay = NULL;
|
||||
}
|
||||
|
||||
// macro file open
|
||||
if (hMacroFile != INVALID_HANDLE_VALUE) CloseHandle(hMacroFile);
|
||||
|
||||
nMacroState = MACRO_OFF;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// activate/deactivate slider
|
||||
//
|
||||
static VOID SliderEnable(HWND hDlg,BOOL bEnable)
|
||||
{
|
||||
EnableWindow(GetDlgItem(hDlg,IDC_MACRO_SLOW),bEnable);
|
||||
EnableWindow(GetDlgItem(hDlg,IDC_MACRO_FAST),bEnable);
|
||||
EnableWindow(GetDlgItem(hDlg,IDC_MACRO_SLIDER),bEnable);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Macro settings dialog
|
||||
//
|
||||
static INT_PTR CALLBACK MacroProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
// set slider
|
||||
SendDlgItemMessage(hDlg,IDC_MACRO_SLIDER,TBM_SETRANGE,FALSE,MAKELONG(0,MAX_SPEED-MIN_SPEED));
|
||||
SendDlgItemMessage(hDlg,IDC_MACRO_SLIDER,TBM_SETTICFREQ,MAX_SPEED/10,0);
|
||||
SendDlgItemMessage(hDlg,IDC_MACRO_SLIDER,TBM_SETPOS,TRUE,MAX_SPEED-nMacroTimeout);
|
||||
|
||||
// set button
|
||||
CheckDlgButton(hDlg,bMacroRealSpeed ? IDC_MACRO_REAL : IDC_MACRO_MANUAL,BST_CHECKED);
|
||||
SliderEnable(hDlg,!bMacroRealSpeed);
|
||||
return TRUE;
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDC_MACRO_REAL:
|
||||
SliderEnable(hDlg,FALSE);
|
||||
return TRUE;
|
||||
case IDC_MACRO_MANUAL:
|
||||
SliderEnable(hDlg,TRUE);
|
||||
return TRUE;
|
||||
case IDOK:
|
||||
// get macro data
|
||||
nMacroTimeout = MAX_SPEED - (INT) SendDlgItemMessage(hDlg,IDC_MACRO_SLIDER,TBM_GETPOS,0,0);
|
||||
bMacroRealSpeed = IsDlgButtonChecked(hDlg,IDC_MACRO_REAL);
|
||||
// no break
|
||||
case IDCANCEL:
|
||||
EndDialog(hDlg, LOWORD(wParam));
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
UNREFERENCED_PARAMETER(lParam);
|
||||
}
|
||||
|
||||
LRESULT OnToolMacroSettings(VOID)
|
||||
{
|
||||
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_MACROSET), hWnd, (DLGPROC)MacroProc) == -1)
|
||||
AbortMessage(_T("Macro Dialog Box Creation Error !"));
|
||||
return 0;
|
||||
}
|
2660
app/src/main/cpp/KML.C
Normal file
133
app/src/main/cpp/KML.H
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* kml.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1995 Sebastien Carlier
|
||||
*
|
||||
*/
|
||||
|
||||
#define LEX_BLOCK 0
|
||||
#define LEX_COMMAND 1
|
||||
#define LEX_PARAM 2
|
||||
|
||||
typedef enum eTokenId
|
||||
{
|
||||
TOK_NONE, //0
|
||||
TOK_ANNUNCIATOR, //1
|
||||
TOK_BACKGROUND, //2
|
||||
TOK_IFPRESSED, //3
|
||||
TOK_RESETFLAG, //4
|
||||
TOK_SCANCODE, //5
|
||||
TOK_HARDWARE, //6
|
||||
TOK_MENUITEM, //7
|
||||
TOK_SYSITEM, //8
|
||||
TOK_INTEGER, //9
|
||||
TOK_SETFLAG, //10
|
||||
TOK_RELEASE, //11
|
||||
TOK_VIRTUAL, //12
|
||||
TOK_INCLUDE, //13
|
||||
TOK_NOTFLAG, //14
|
||||
TOK_STRING, //15
|
||||
TOK_GLOBAL, //16
|
||||
TOK_AUTHOR, //17
|
||||
TOK_BITMAP, //18
|
||||
TOK_ZOOMXY, //19
|
||||
TOK_OFFSET, //20
|
||||
TOK_BUTTON, //21
|
||||
TOK_IFFLAG, //22
|
||||
TOK_ONDOWN, //23
|
||||
TOK_NOHOLD, //24
|
||||
TOK_LOCALE, //25
|
||||
TOK_TOPBAR, //26
|
||||
TOK_MENUBAR, //27
|
||||
TOK_TITLE, //28
|
||||
TOK_OUTIN, //29
|
||||
TOK_PATCH, //30
|
||||
TOK_PRINT, //31
|
||||
TOK_DEBUG, //32
|
||||
TOK_COLOR, //33
|
||||
TOK_MODEL, //34
|
||||
TOK_CLASS, //35
|
||||
TOK_PRESS, //36
|
||||
TOK_IFMEM, //37
|
||||
TOK_SCALE, //38
|
||||
TOK_TYPE, //39
|
||||
TOK_SIZE, //40
|
||||
TOK_DOWN, //41
|
||||
TOK_ZOOM, //42
|
||||
TOK_ELSE, //43
|
||||
TOK_ONUP, //44
|
||||
TOK_ICON, //45
|
||||
TOK_EOL, //46
|
||||
TOK_MAP, //47
|
||||
TOK_ROM, //48
|
||||
TOK_VGA, //49
|
||||
TOK_LCD, //50
|
||||
TOK_END //51
|
||||
} TokenId;
|
||||
|
||||
#define TYPE_NONE 00
|
||||
#define TYPE_INTEGER 01
|
||||
#define TYPE_STRING 02
|
||||
|
||||
typedef struct KmlToken
|
||||
{
|
||||
TokenId eId;
|
||||
DWORD nParams;
|
||||
DWORD nLen;
|
||||
LPCTSTR szName;
|
||||
} KmlToken;
|
||||
|
||||
typedef struct KmlLine
|
||||
{
|
||||
struct KmlLine* pNext;
|
||||
TokenId eCommand;
|
||||
DWORD_PTR nParam[6];
|
||||
} KmlLine;
|
||||
|
||||
typedef struct KmlBlock
|
||||
{
|
||||
TokenId eType;
|
||||
DWORD nId;
|
||||
struct KmlLine* pFirstLine;
|
||||
struct KmlBlock* pNext;
|
||||
} KmlBlock;
|
||||
|
||||
#define BUTTON_NOHOLD 0x0001
|
||||
#define BUTTON_VIRTUAL 0x0002
|
||||
typedef struct KmlButton
|
||||
{
|
||||
UINT nId;
|
||||
BOOL bDown;
|
||||
UINT nType;
|
||||
DWORD dwFlags;
|
||||
UINT nOx, nOy;
|
||||
UINT nDx, nDy;
|
||||
UINT nCx, nCy;
|
||||
UINT nOut, nIn;
|
||||
KmlLine* pOnDown;
|
||||
KmlLine* pOnUp;
|
||||
} KmlButton;
|
||||
|
||||
typedef struct KmlAnnunciator
|
||||
{
|
||||
UINT nOx, nOy;
|
||||
UINT nDx, nDy;
|
||||
UINT nCx, nCy;
|
||||
} KmlAnnunciator;
|
||||
|
||||
extern KmlBlock* pKml;
|
||||
extern BOOL DisplayChooseKml(CHAR cType);
|
||||
extern VOID FreeBlocks(KmlBlock* pBlock);
|
||||
extern VOID DrawAnnunciator(UINT nId, BOOL bOn);
|
||||
extern VOID ReloadButtons(BYTE *Keyboard_Row, UINT nSize);
|
||||
extern VOID RefreshButtons(RECT *rc);
|
||||
extern BOOL MouseIsButton(DWORD x, DWORD y);
|
||||
extern VOID MouseButtonDownAt(UINT nFlags, DWORD x, DWORD y);
|
||||
extern VOID MouseButtonUpAt(UINT nFlags, DWORD x, DWORD y);
|
||||
extern VOID MouseMovesTo(UINT nFlags, DWORD x, DWORD y);
|
||||
extern VOID RunKey(BYTE nId, BOOL bPressed);
|
||||
extern VOID PlayKey(UINT nOut, UINT nIn, BOOL bPressed);
|
||||
extern BOOL InitKML(LPCTSTR szFilename, BOOL bNoLog);
|
||||
extern VOID KillKML(VOID);
|
6300
app/src/main/cpp/LODEPNG.C
Normal file
1770
app/src/main/cpp/LODEPNG.H
Normal file
122
app/src/main/cpp/LOWBAT.C
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* lowbat.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2006 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h" // I/O definitions
|
||||
|
||||
// #define BAT_SIMULATION // switch low bat simulation
|
||||
|
||||
#define BAT_FREQ (60*1000) // bat update time in ms (real machine = 60us, HP28C = 60s)
|
||||
|
||||
BOOL bLowBatDisable = FALSE;
|
||||
|
||||
static HANDLE hCThreadBat = NULL;
|
||||
static HANDLE hEventBat;
|
||||
|
||||
static DWORD WINAPI LowBatThread(LPVOID pParam)
|
||||
{
|
||||
BOOL bLBI,bVLBI;
|
||||
|
||||
do
|
||||
{
|
||||
GetBatteryState(&bLBI,&bVLBI); // get battery state
|
||||
|
||||
// very low bat detection
|
||||
bVLBI = bVLBI && (Chipset.IORam[LPE] & EVLBI) != 0;
|
||||
|
||||
IOBit(LPD,VLBI,bVLBI); // set VLBI
|
||||
IOBit(SRQ1,VSRQ,bVLBI); // and service bit
|
||||
|
||||
if (bVLBI) // VLBI detected
|
||||
{
|
||||
Chipset.SoftInt = TRUE;
|
||||
bInterrupt = TRUE;
|
||||
|
||||
if (Chipset.Shutdn) // CPU shut down
|
||||
{
|
||||
Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode
|
||||
SetEvent(hEventShutdn); // wake up emulation thread
|
||||
}
|
||||
}
|
||||
}
|
||||
while (WaitForSingleObject(hEventBat,BAT_FREQ) == WAIT_TIMEOUT);
|
||||
|
||||
return 0;
|
||||
UNREFERENCED_PARAMETER(pParam);
|
||||
}
|
||||
|
||||
VOID StartBatMeasure(VOID)
|
||||
{
|
||||
DWORD dwThreadId;
|
||||
|
||||
if (hCThreadBat) // Bat measuring thread running
|
||||
return; // -> quit
|
||||
|
||||
// event to cancel Bat refresh loop
|
||||
hEventBat = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||
|
||||
VERIFY(hCThreadBat = CreateThread(NULL,0,&LowBatThread,NULL,0,&dwThreadId));
|
||||
return;
|
||||
}
|
||||
|
||||
VOID StopBatMeasure(VOID)
|
||||
{
|
||||
if (hCThreadBat == NULL) // thread stopped
|
||||
return; // -> quit
|
||||
|
||||
SetEvent(hEventBat); // leave Bat update thread
|
||||
WaitForSingleObject(hCThreadBat,INFINITE);
|
||||
CloseHandle(hCThreadBat);
|
||||
hCThreadBat = NULL; // set flag Bat update stopped
|
||||
CloseHandle(hEventBat); // close Bat event
|
||||
return;
|
||||
}
|
||||
|
||||
VOID GetBatteryState(BOOL *pbLBI, BOOL *pbVLBI)
|
||||
{
|
||||
#if defined BAT_SIMULATION
|
||||
switch (GetPrivateProfileInt(_T("LowBat"),_T("Level"),2,_T(".\\Lowbat.ini")))
|
||||
{
|
||||
case 0: // empty
|
||||
*pbLBI = TRUE;
|
||||
*pbVLBI = TRUE;
|
||||
break;
|
||||
case 1: // low
|
||||
*pbLBI = TRUE;
|
||||
*pbVLBI = FALSE;
|
||||
break;
|
||||
default: // full
|
||||
*pbLBI = FALSE;
|
||||
*pbVLBI = FALSE;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
SYSTEM_POWER_STATUS sSps;
|
||||
|
||||
*pbLBI = FALSE; // no battery warning
|
||||
*pbVLBI = FALSE;
|
||||
|
||||
VERIFY(GetSystemPowerStatus(&sSps));
|
||||
|
||||
// low bat emulation enabled and battery powered
|
||||
if (!bLowBatDisable && sSps.ACLineStatus == AC_LINE_OFFLINE)
|
||||
{
|
||||
// on critical battery state make sure that lowbat flag is also set
|
||||
if ((sSps.BatteryFlag & BATTERY_FLAG_CRITICAL) != 0)
|
||||
sSps.BatteryFlag |= BATTERY_FLAG_LOW;
|
||||
|
||||
// low bat detection
|
||||
*pbLBI = ((sSps.BatteryFlag & BATTERY_FLAG_LOW) != 0);
|
||||
|
||||
// very low bat detection
|
||||
*pbVLBI = ((sSps.BatteryFlag & BATTERY_FLAG_CRITICAL) != 0);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
1851
app/src/main/cpp/MOPS.C
Normal file
353
app/src/main/cpp/MRU.C
Normal file
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
* mru.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2007 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "resource.h"
|
||||
#include "Emu48.h"
|
||||
|
||||
static TCHAR szOriginal[MAX_PATH] = _T("");
|
||||
|
||||
static LPTSTR *ppszFiles = NULL; // pointer to MRU table
|
||||
static UINT nEntry = 0; // no. of MRU entries
|
||||
|
||||
static BOOL GetMenuPosForId(HMENU hMenu, UINT nItem, HMENU *phMruMenu, UINT *pnMruPos)
|
||||
{
|
||||
HMENU hSubMenu;
|
||||
UINT i,nID,nMaxID;
|
||||
|
||||
nMaxID = GetMenuItemCount(hMenu);
|
||||
for (i = 0; i < nMaxID; ++i)
|
||||
{
|
||||
nID = GetMenuItemID(hMenu,i); // get ID
|
||||
|
||||
if (nID == 0) continue; // separator or invalid command
|
||||
|
||||
if (nID == (UINT)-1) // possibly a popup menu
|
||||
{
|
||||
hSubMenu = GetSubMenu(hMenu,i); // try to get handle to popup menu
|
||||
if (hSubMenu != NULL) // it's a popup menu
|
||||
{
|
||||
// recursive search
|
||||
if (GetMenuPosForId(hSubMenu,nItem,phMruMenu,pnMruPos))
|
||||
return TRUE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nID == nItem) // found ID
|
||||
{
|
||||
*phMruMenu = hMenu; // remember menu and position
|
||||
*pnMruPos = i;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL MruInit(UINT nNum)
|
||||
{
|
||||
HMENU hMenu = GetMenu(hWnd); // main menu
|
||||
if (hMenu == NULL) return FALSE; // failed, no menu bar
|
||||
|
||||
_ASSERT(ppszFiles == NULL); // MRU already initialized
|
||||
|
||||
// no. of files in MRU list
|
||||
nEntry = ReadSettingsInt(_T("MRU"),_T("FileCount"),nNum);
|
||||
|
||||
if (nEntry > 0) // allocate MRU table
|
||||
{
|
||||
// create MRU table
|
||||
if ((ppszFiles = (LPTSTR *) malloc(nEntry * sizeof(*ppszFiles))) == NULL)
|
||||
return FALSE;
|
||||
|
||||
// fill each entry
|
||||
for (nNum = 0; nNum < nEntry; ++nNum)
|
||||
ppszFiles[nNum] = NULL;
|
||||
|
||||
MruReadList(); // read actual MRU list
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID MruCleanup(VOID)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
MruWriteList(); // write actual MRU list
|
||||
|
||||
if (ppszFiles != NULL) // table defined
|
||||
{
|
||||
for (i = 0; i < nEntry; ++i) // cleanup each entry
|
||||
{
|
||||
if (ppszFiles[i] != NULL)
|
||||
free(ppszFiles[i]); // cleanup entry
|
||||
}
|
||||
|
||||
free(ppszFiles); // free table
|
||||
ppszFiles = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID MruAdd(LPCTSTR lpszEntry)
|
||||
{
|
||||
TCHAR szFilename[MAX_PATH];
|
||||
LPTSTR lpFilePart;
|
||||
UINT i;
|
||||
|
||||
if (ppszFiles != NULL) // MRU initialized
|
||||
{
|
||||
_ASSERT(nEntry > 0); // must have entries
|
||||
|
||||
// get full path name
|
||||
GetFullPathName(lpszEntry,ARRAYSIZEOF(szFilename),szFilename,&lpFilePart);
|
||||
|
||||
// look if entry is already in table
|
||||
for (i = 0; i < nEntry; ++i)
|
||||
{
|
||||
// already in table -> quit
|
||||
if ( ppszFiles[i] != NULL
|
||||
&& lstrcmpi(ppszFiles[i],szFilename) == 0)
|
||||
{
|
||||
MruMoveTop(i); // move to top and update menu
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
i = nEntry - 1; // last index
|
||||
if (ppszFiles[i] != NULL)
|
||||
free(ppszFiles[i]); // free oldest entry
|
||||
|
||||
for (; i > 0; --i) // move old entries 1 line down
|
||||
{
|
||||
ppszFiles[i] = ppszFiles[i-1];
|
||||
}
|
||||
|
||||
// add new entry to top
|
||||
ppszFiles[0] = DuplicateString(szFilename);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID MruRemove(UINT nIndex)
|
||||
{
|
||||
// MRU initialized and index inside valid range
|
||||
if (ppszFiles != NULL && nIndex < nEntry)
|
||||
{
|
||||
free(ppszFiles[nIndex]); // free entry
|
||||
|
||||
for (; nIndex < nEntry - 1; ++nIndex) // move below entries 1 line up
|
||||
{
|
||||
ppszFiles[nIndex] = ppszFiles[nIndex+1];
|
||||
}
|
||||
|
||||
ppszFiles[nIndex] = NULL; // clear last line
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID MruMoveTop(UINT nIndex)
|
||||
{
|
||||
// MRU initialized and index inside valid range
|
||||
if (ppszFiles != NULL && nIndex < nEntry)
|
||||
{
|
||||
LPTSTR lpszEntry = ppszFiles[nIndex];// remember selected entry
|
||||
|
||||
for (; nIndex > 0; --nIndex) // move above entries 1 line down
|
||||
{
|
||||
ppszFiles[nIndex] = ppszFiles[nIndex-1];
|
||||
}
|
||||
|
||||
ppszFiles[0] = lpszEntry; // insert entry on top
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
UINT MruEntries(VOID)
|
||||
{
|
||||
return nEntry;
|
||||
}
|
||||
|
||||
LPCTSTR MruFilename(UINT nIndex)
|
||||
{
|
||||
LPCTSTR lpszName = _T("");
|
||||
|
||||
// MRU initialized and index inside valid range
|
||||
if (ppszFiles != NULL && nIndex < nEntry)
|
||||
{
|
||||
lpszName = ppszFiles[nIndex];
|
||||
}
|
||||
return lpszName;
|
||||
}
|
||||
|
||||
VOID MruUpdateMenu(HMENU hMenu)
|
||||
{
|
||||
TCHAR szCurPath[MAX_PATH];
|
||||
BOOL bEmpty;
|
||||
UINT i;
|
||||
|
||||
if (hMenu != NULL) // have menu
|
||||
{
|
||||
HMENU hMruMenu; // menu handle for MRU list
|
||||
UINT nMruPos; // insert position for MRU list
|
||||
|
||||
_ASSERT(IsMenu(hMenu)); // validate menu handle
|
||||
|
||||
// search for menu position of ID_FILE_MRU_FILE1
|
||||
if (GetMenuPosForId(hMenu,ID_FILE_MRU_FILE1,&hMruMenu,&nMruPos))
|
||||
{
|
||||
if (*szOriginal == 0) // get orginal value of first MRU entry
|
||||
{
|
||||
VERIFY(GetMenuString(hMruMenu,nMruPos,szOriginal,ARRAYSIZEOF(szOriginal),MF_BYPOSITION));
|
||||
}
|
||||
|
||||
if (nEntry == 0) // kill MRU menu entry
|
||||
{
|
||||
// delete MRU menu
|
||||
DeleteMenu(hMruMenu,nMruPos,MF_BYPOSITION);
|
||||
|
||||
// delete the following separator
|
||||
_ASSERT((GetMenuState(hMruMenu,nMruPos,MF_BYPOSITION) & MF_SEPARATOR) != 0);
|
||||
DeleteMenu(hMruMenu,nMruPos,MF_BYPOSITION);
|
||||
}
|
||||
|
||||
if (ppszFiles != NULL) // MRU initialized
|
||||
{
|
||||
_ASSERT(nEntry > 0); // must have entries
|
||||
|
||||
// delete all menu entries
|
||||
for (i = 0; DeleteMenu(hMenu,ID_FILE_MRU_FILE1+i,MF_BYCOMMAND) != FALSE; ++i) { }
|
||||
|
||||
// check if MRU list is empty
|
||||
for (bEmpty = TRUE, i = 0; bEmpty && i < nEntry; ++i)
|
||||
{
|
||||
bEmpty = (ppszFiles[i] == NULL);
|
||||
}
|
||||
|
||||
if (bEmpty) // MRU list is empty
|
||||
{
|
||||
// fill with orginal string
|
||||
VERIFY(InsertMenu(hMruMenu,nMruPos,MF_STRING|MF_BYPOSITION|MF_GRAYED,ID_FILE_MRU_FILE1,szOriginal));
|
||||
return;
|
||||
}
|
||||
|
||||
// current directory
|
||||
GetCurrentDirectory(ARRAYSIZEOF(szCurPath),szCurPath);
|
||||
|
||||
for (i = 0; i < nEntry; ++i) // add menu entries
|
||||
{
|
||||
if (ppszFiles[i] != NULL) // valid entry
|
||||
{
|
||||
TCHAR szMenuname[2*MAX_PATH+3];
|
||||
TCHAR szFilename[MAX_PATH];
|
||||
LPTSTR lpFilePart,lpszPtr;
|
||||
|
||||
// check if file path and current path is identical
|
||||
if (GetFullPathName(ppszFiles[i],ARRAYSIZEOF(szFilename),szFilename,&lpFilePart))
|
||||
{
|
||||
TCHAR szCutname[MAX_PATH];
|
||||
|
||||
*(lpFilePart-1) = 0; // devide path and name
|
||||
|
||||
// name is current directory -> use only name
|
||||
if (lstrcmpi(szCurPath,szFilename) == 0)
|
||||
{
|
||||
// short name view
|
||||
}
|
||||
else
|
||||
{
|
||||
// full name view
|
||||
lpFilePart = ppszFiles[i];
|
||||
}
|
||||
|
||||
// cut filename to fit into menu
|
||||
GetCutPathName(lpFilePart,szCutname,ARRAYSIZEOF(szCutname),36);
|
||||
lpFilePart = szCutname;
|
||||
|
||||
// adding accelerator key
|
||||
lpszPtr = szMenuname;
|
||||
*lpszPtr++ = _T('&');
|
||||
*lpszPtr++ = _T('0') + ((i + 1) % 10);
|
||||
*lpszPtr++ = _T(' ');
|
||||
|
||||
// copy file to view buffer and expand & to &&
|
||||
while (*lpFilePart != 0)
|
||||
{
|
||||
if (*lpFilePart == _T('&'))
|
||||
{
|
||||
*lpszPtr++ = *lpFilePart;
|
||||
}
|
||||
*lpszPtr++ = *lpFilePart++;
|
||||
}
|
||||
*lpszPtr = 0;
|
||||
|
||||
VERIFY(InsertMenu(hMruMenu,nMruPos+i,
|
||||
MF_STRING|MF_BYPOSITION,ID_FILE_MRU_FILE1+i,
|
||||
szMenuname));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID MruWriteList(VOID)
|
||||
{
|
||||
TCHAR szItemname[32];
|
||||
UINT i;
|
||||
|
||||
if (nEntry > 0)
|
||||
{
|
||||
// no. of files in MRU list
|
||||
WriteSettingsInt(_T("MRU"),_T("FileCount"),nEntry);
|
||||
|
||||
for (i = 0; i < nEntry; ++i) // add menu entries
|
||||
{
|
||||
_ASSERT(ppszFiles != NULL); // MRU not initialized
|
||||
wsprintf(szItemname,_T("File%d"),i+1);
|
||||
if (ppszFiles[i] != NULL)
|
||||
{
|
||||
WriteSettingsString(_T("MRU"),szItemname,ppszFiles[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
DelSettingsKey(_T("MRU"),szItemname);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID MruReadList(VOID)
|
||||
{
|
||||
TCHAR szFilename[MAX_PATH];
|
||||
TCHAR szItemname[32];
|
||||
UINT i;
|
||||
|
||||
for (i = 0; i < nEntry; ++i) // add menu entries
|
||||
{
|
||||
_ASSERT(ppszFiles != NULL); // MRU not initialized
|
||||
|
||||
wsprintf(szItemname,_T("File%d"),i+1);
|
||||
ReadSettingsString(_T("MRU"),szItemname,_T(""),szFilename,ARRAYSIZEOF(szFilename));
|
||||
|
||||
if (ppszFiles[i] != NULL) // already filled
|
||||
{
|
||||
free(ppszFiles[i]); // free entry
|
||||
ppszFiles[i] = NULL; // clear last line
|
||||
}
|
||||
|
||||
if (*szFilename) // read a valid entry
|
||||
{
|
||||
ppszFiles[i] = DuplicateString(szFilename);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
2463
app/src/main/cpp/OPCODES.C
Normal file
445
app/src/main/cpp/OPCODES.H
Normal file
|
@ -0,0 +1,445 @@
|
|||
/*
|
||||
* opcodes.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1999 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
|
||||
#define PCHANGED ((void)(F_s[0]=Chipset.P,F_l[1]=Chipset.P+1))
|
||||
#define INTERRUPT ((void)(Chipset.SoftInt=TRUE,bInterrupt=TRUE))
|
||||
|
||||
extern UINT F_s[16];
|
||||
extern UINT F_l[16];
|
||||
|
||||
extern VOID o00(LPBYTE I); // RTNSXM
|
||||
extern VOID o01(LPBYTE I); // RTN
|
||||
extern VOID o02(LPBYTE I); // RTNSC
|
||||
extern VOID o03(LPBYTE I); // RTNCC
|
||||
extern VOID o04(LPBYTE I); // SETHEX
|
||||
extern VOID o05(LPBYTE I); // SETDEC
|
||||
extern VOID o06(LPBYTE I); // RSTK=C
|
||||
extern VOID o07(LPBYTE I); // C=RSTK
|
||||
extern VOID o08(LPBYTE I); // CLRST
|
||||
extern VOID o09(LPBYTE I); // C=ST
|
||||
extern VOID o0A(LPBYTE I); // ST=C
|
||||
extern VOID o0B(LPBYTE I); // CSTEX
|
||||
extern VOID o0C(LPBYTE I); // P=P+1
|
||||
extern VOID o0D(LPBYTE I); // P=P-1
|
||||
extern VOID o0Ef0(LPBYTE I); // A=A&B f
|
||||
extern VOID o0Ef1(LPBYTE I); // B=B&C f
|
||||
extern VOID o0Ef2(LPBYTE I); // C=C&A f
|
||||
extern VOID o0Ef3(LPBYTE I); // D=D&C f
|
||||
extern VOID o0Ef4(LPBYTE I); // B=B&A f
|
||||
extern VOID o0Ef5(LPBYTE I); // C=C&B f
|
||||
extern VOID o0Ef6(LPBYTE I); // A=A&C f
|
||||
extern VOID o0Ef7(LPBYTE I); // C=C&D f
|
||||
extern VOID o0Ef8(LPBYTE I); // A=A!B f
|
||||
extern VOID o0Ef9(LPBYTE I); // B=B!C f
|
||||
extern VOID o0EfA(LPBYTE I); // C=C!A f
|
||||
extern VOID o0EfB(LPBYTE I); // D=D!C f
|
||||
extern VOID o0EfC(LPBYTE I); // B=B!A f
|
||||
extern VOID o0EfD(LPBYTE I); // C=C!B f
|
||||
extern VOID o0EfE(LPBYTE I); // A=A!C f
|
||||
extern VOID o0EfF(LPBYTE I); // C=C!D f
|
||||
extern VOID o0F(LPBYTE I); // RTI
|
||||
extern VOID o100(LPBYTE I); // R0=A W
|
||||
extern VOID o101(LPBYTE I); // R1=A W
|
||||
extern VOID o102(LPBYTE I); // R2=A W
|
||||
extern VOID o103(LPBYTE I); // R3=A W
|
||||
extern VOID o104(LPBYTE I); // R4=A W
|
||||
extern VOID o108(LPBYTE I); // R0=C W
|
||||
extern VOID o109(LPBYTE I); // R1=C W
|
||||
extern VOID o10A(LPBYTE I); // R2=C W
|
||||
extern VOID o10B(LPBYTE I); // R3=C W
|
||||
extern VOID o10C(LPBYTE I); // R4=C W
|
||||
extern VOID o110(LPBYTE I); // A=R0 W
|
||||
extern VOID o111(LPBYTE I); // A=R1 W
|
||||
extern VOID o112(LPBYTE I); // A=R2 W
|
||||
extern VOID o113(LPBYTE I); // A=R3 W
|
||||
extern VOID o114(LPBYTE I); // A=R4 W
|
||||
extern VOID o118(LPBYTE I); // C=R0 W
|
||||
extern VOID o119(LPBYTE I); // C=R1 W
|
||||
extern VOID o11A(LPBYTE I); // C=R2 W
|
||||
extern VOID o11B(LPBYTE I); // C=R3 W
|
||||
extern VOID o11C(LPBYTE I); // C=R4 W
|
||||
extern VOID o120(LPBYTE I); // AR0EX W
|
||||
extern VOID o121(LPBYTE I); // AR1EX W
|
||||
extern VOID o122(LPBYTE I); // AR2EX W
|
||||
extern VOID o123(LPBYTE I); // AR3EX W
|
||||
extern VOID o124(LPBYTE I); // AR4EX W
|
||||
extern VOID o128(LPBYTE I); // CR0EX W
|
||||
extern VOID o129(LPBYTE I); // CR1EX W
|
||||
extern VOID o12A(LPBYTE I); // CR2EX W
|
||||
extern VOID o12B(LPBYTE I); // CR3EX W
|
||||
extern VOID o12C(LPBYTE I); // CR4EX W
|
||||
extern VOID o130(LPBYTE I); // D0=A
|
||||
extern VOID o131(LPBYTE I); // D1=A
|
||||
extern VOID o132(LPBYTE I); // AD0EX
|
||||
extern VOID o133(LPBYTE I); // AD1EX
|
||||
extern VOID o134(LPBYTE I); // D0=C
|
||||
extern VOID o135(LPBYTE I); // D1=C
|
||||
extern VOID o136(LPBYTE I); // CD0EX
|
||||
extern VOID o137(LPBYTE I); // CD1EX
|
||||
extern VOID o138(LPBYTE I); // D0=AS
|
||||
extern VOID o139(LPBYTE I); // D1=AS
|
||||
extern VOID o13A(LPBYTE I); // AD0XS
|
||||
extern VOID o13B(LPBYTE I); // AD1XS
|
||||
extern VOID o13C(LPBYTE I); // D0=CS
|
||||
extern VOID o13D(LPBYTE I); // D1=CS
|
||||
extern VOID o13E(LPBYTE I); // CD0XS
|
||||
extern VOID o13F(LPBYTE I); // CD1XS
|
||||
extern VOID o140(LPBYTE I); // DAT0=A A
|
||||
extern VOID o141(LPBYTE I); // DAT0=A A
|
||||
extern VOID o144(LPBYTE I); // DAT0=C A
|
||||
extern VOID o145(LPBYTE I); // DAT1=C A
|
||||
extern VOID o148(LPBYTE I); // DAT0=A B
|
||||
extern VOID o149(LPBYTE I); // DAT1=A B
|
||||
extern VOID o14C(LPBYTE I); // DAT0=C B
|
||||
extern VOID o14D(LPBYTE I); // DAT1=C B
|
||||
extern VOID o142(LPBYTE I); // A=DAT0 A
|
||||
extern VOID o143(LPBYTE I); // A=DAT1 A
|
||||
extern VOID o146(LPBYTE I); // C=DAT0 A
|
||||
extern VOID o147(LPBYTE I); // C=DAT1 A
|
||||
extern VOID o14A(LPBYTE I); // A=DAT0 B
|
||||
extern VOID o14B(LPBYTE I); // A=DAT1 B
|
||||
extern VOID o14E(LPBYTE I); // C=DAT0 B
|
||||
extern VOID o14F(LPBYTE I); // C=DAT0 B
|
||||
extern VOID o150a(LPBYTE I); // DAT0=A a
|
||||
extern VOID o151a(LPBYTE I); // DAT1=A a
|
||||
extern VOID o154a(LPBYTE I); // DAT0=C a
|
||||
extern VOID o155a(LPBYTE I); // DAT1=C a
|
||||
extern VOID o152a(LPBYTE I); // A=DAT0 a
|
||||
extern VOID o153a(LPBYTE I); // A=DAT1 a
|
||||
extern VOID o156a(LPBYTE I); // C=DAT0 a
|
||||
extern VOID o157a(LPBYTE I); // C=DAT1 a
|
||||
extern VOID o158x(LPBYTE I); // DAT0=A x
|
||||
extern VOID o159x(LPBYTE I); // DAT1=A x
|
||||
extern VOID o15Cx(LPBYTE I); // DAT0=C x
|
||||
extern VOID o15Dx(LPBYTE I); // DAT1=C x
|
||||
extern VOID o15Ax(LPBYTE I); // A=DAT0 x
|
||||
extern VOID o15Bx(LPBYTE I); // A=DAT1 x
|
||||
extern VOID o15Ex(LPBYTE I); // C=DAT0 x
|
||||
extern VOID o15Fx(LPBYTE I); // C=DAT1 x
|
||||
extern VOID o16x(LPBYTE I); // D0=D0+ (n+1)
|
||||
extern VOID o17x(LPBYTE I); // D1=D1+ (n+1)
|
||||
extern VOID o18x(LPBYTE I); // D0=D0- (n+1)
|
||||
extern VOID o19d2(LPBYTE I); // D0=(2) #dd
|
||||
extern VOID o1Ad4(LPBYTE I); // D0=(4) #dddd
|
||||
extern VOID o1Bd5(LPBYTE I); // D0=(5) #ddddd
|
||||
extern VOID o1Cx(LPBYTE I); // D1=D1- (n+1)
|
||||
extern VOID o1Dd2(LPBYTE I); // D1=(2) #dd
|
||||
extern VOID o1Ed4(LPBYTE I); // D1=(4) #dddd
|
||||
extern VOID o1Fd5(LPBYTE I); // D1=(5) #ddddd
|
||||
extern VOID o2n(LPBYTE I); // P= n
|
||||
extern VOID o3X(LPBYTE I); // LCHEX
|
||||
extern VOID o4d2(LPBYTE I); // GOC #dd
|
||||
extern VOID o5d2(LPBYTE I); // GONC
|
||||
extern VOID o6d3(LPBYTE I); // GOTO
|
||||
extern VOID o7d3(LPBYTE I); // GOSUB
|
||||
extern VOID o800(LPBYTE I); // OUT=CS
|
||||
extern VOID o801(LPBYTE I); // OUT=C
|
||||
extern VOID o802(LPBYTE I); // A=IN
|
||||
extern VOID o803(LPBYTE I); // C=IN
|
||||
extern VOID o804(LPBYTE I); // UNCNFG
|
||||
extern VOID o805(LPBYTE I); // CONFIG
|
||||
extern VOID o806(LPBYTE I); // C=ID
|
||||
extern VOID o807(LPBYTE I); // SHUTDN
|
||||
extern VOID o8080(LPBYTE I); // INTON
|
||||
extern VOID o80810(LPBYTE I); // RSI
|
||||
extern VOID o8082X(LPBYTE I); // LA
|
||||
extern VOID o8083(LPBYTE I); // BUSCB
|
||||
extern VOID o8084n(LPBYTE I); // ABIT=0 n
|
||||
extern VOID o8085n(LPBYTE I); // ABIT=1 n
|
||||
extern VOID o8086n(LPBYTE I); // ?ABIT=0 n
|
||||
extern VOID o8087n(LPBYTE I); // ?ABIT=1 n
|
||||
extern VOID o8088n(LPBYTE I); // CBIT=0 n
|
||||
extern VOID o8089n(LPBYTE I); // CBIT=1 n
|
||||
extern VOID o808An(LPBYTE I); // ?CBIT=0 n
|
||||
extern VOID o808Bn(LPBYTE I); // ?CBIT=1 n
|
||||
extern VOID o808C(LPBYTE I); // PC=(A)
|
||||
extern VOID o808D(LPBYTE I); // BUSCD
|
||||
extern VOID o808E(LPBYTE I); // PC=(C)
|
||||
extern VOID o808F(LPBYTE I); // INTOFF
|
||||
extern VOID o809(LPBYTE I); // C+P+1 - HEX MODE
|
||||
extern VOID o80A(LPBYTE I); // RESET
|
||||
extern VOID o80B(LPBYTE I); // BUSCC
|
||||
extern VOID o80Cn(LPBYTE I); // C=P n
|
||||
extern VOID o80Dn(LPBYTE I); // P=C n
|
||||
extern VOID o80E(LPBYTE I); // SREQ?
|
||||
extern VOID o80Fn(LPBYTE I); // CPEX n
|
||||
extern VOID o810(LPBYTE I); // ASLC
|
||||
extern VOID o811(LPBYTE I); // BSLC
|
||||
extern VOID o812(LPBYTE I); // CSLC
|
||||
extern VOID o813(LPBYTE I); // DSLC
|
||||
extern VOID o814(LPBYTE I); // ASRC
|
||||
extern VOID o815(LPBYTE I); // BSRC
|
||||
extern VOID o816(LPBYTE I); // CSRC
|
||||
extern VOID o817(LPBYTE I); // DSRC
|
||||
extern VOID o818f0x(LPBYTE I); // A=A+x+1 f
|
||||
extern VOID o818f1x(LPBYTE I); // B=B+x+1 f
|
||||
extern VOID o818f2x(LPBYTE I); // C=C+x+1 f
|
||||
extern VOID o818f3x(LPBYTE I); // D=D+x+1 f
|
||||
extern VOID o818f8x(LPBYTE I); // A=A-x-1 f
|
||||
extern VOID o818f9x(LPBYTE I); // B=B-x-1 f
|
||||
extern VOID o818fAx(LPBYTE I); // C=C-x-1 f
|
||||
extern VOID o818fBx(LPBYTE I); // D=D-x-1 f
|
||||
extern VOID o819f0(LPBYTE I); // ASRB.F
|
||||
extern VOID o819f1(LPBYTE I); // BSRB.F
|
||||
extern VOID o819f2(LPBYTE I); // CSRB.F
|
||||
extern VOID o819f3(LPBYTE I); // DSRB.F
|
||||
extern VOID o81Af00(LPBYTE I); // R0=A.F f
|
||||
extern VOID o81Af01(LPBYTE I); // R1=A.F f
|
||||
extern VOID o81Af02(LPBYTE I); // R2=A.F f
|
||||
extern VOID o81Af03(LPBYTE I); // R3=A.F f
|
||||
extern VOID o81Af04(LPBYTE I); // R4=A.F f
|
||||
extern VOID o81Af08(LPBYTE I); // R0=C.F f
|
||||
extern VOID o81Af09(LPBYTE I); // R1=C.F f
|
||||
extern VOID o81Af0A(LPBYTE I); // R2=C.F f
|
||||
extern VOID o81Af0B(LPBYTE I); // R3=C.F f
|
||||
extern VOID o81Af0C(LPBYTE I); // R4=C.F f
|
||||
extern VOID o81Af10(LPBYTE I); // A=R0.F f
|
||||
extern VOID o81Af11(LPBYTE I); // A=R1.F f
|
||||
extern VOID o81Af12(LPBYTE I); // A=R2.F f
|
||||
extern VOID o81Af13(LPBYTE I); // A=R3.F f
|
||||
extern VOID o81Af14(LPBYTE I); // A=R4.F f
|
||||
extern VOID o81Af18(LPBYTE I); // C=R0.F f
|
||||
extern VOID o81Af19(LPBYTE I); // C=R1.F f
|
||||
extern VOID o81Af1A(LPBYTE I); // C=R2.F f
|
||||
extern VOID o81Af1B(LPBYTE I); // C=R3.F f
|
||||
extern VOID o81Af1C(LPBYTE I); // C=R4.F f
|
||||
extern VOID o81Af20(LPBYTE I); // AR0EX.F f
|
||||
extern VOID o81Af21(LPBYTE I); // AR1EX.F f
|
||||
extern VOID o81Af22(LPBYTE I); // AR2EX.F f
|
||||
extern VOID o81Af23(LPBYTE I); // AR3EX.F f
|
||||
extern VOID o81Af24(LPBYTE I); // AR4EX.F f
|
||||
extern VOID o81Af28(LPBYTE I); // CR0EX.F f
|
||||
extern VOID o81Af29(LPBYTE I); // CR1EX.F f
|
||||
extern VOID o81Af2A(LPBYTE I); // CR2EX.F f
|
||||
extern VOID o81Af2B(LPBYTE I); // CR3EX.F f
|
||||
extern VOID o81Af2C(LPBYTE I); // CR4EX.F f
|
||||
extern VOID o81B2(LPBYTE I); // PC=A
|
||||
extern VOID o81B3(LPBYTE I); // PC=C
|
||||
extern VOID o81B4(LPBYTE I); // A=PC
|
||||
extern VOID o81B5(LPBYTE I); // C=PC
|
||||
extern VOID o81B6(LPBYTE I); // APCEX
|
||||
extern VOID o81B7(LPBYTE I); // CPCEX
|
||||
extern VOID o81C(LPBYTE I); // ASRB
|
||||
extern VOID o81D(LPBYTE I); // BSRB
|
||||
extern VOID o81E(LPBYTE I); // CSRB
|
||||
extern VOID o81F(LPBYTE I); // DSRB
|
||||
extern VOID o82n(LPBYTE I); // HST=0 m
|
||||
extern VOID o83n(LPBYTE I); // ?HST=0 m
|
||||
extern VOID o84n(LPBYTE I); // ST=0 n
|
||||
extern VOID o85n(LPBYTE I); // ST=1 n
|
||||
extern VOID o86n(LPBYTE I); // ?ST=0 n
|
||||
extern VOID o87n(LPBYTE I); // ?ST=1 n
|
||||
extern VOID o88n(LPBYTE I); // ?P# n
|
||||
extern VOID o89n(LPBYTE I); // ?P= n
|
||||
extern VOID o8A0(LPBYTE I); // ?A=B A
|
||||
extern VOID o8A1(LPBYTE I); // ?B=C A
|
||||
extern VOID o8A2(LPBYTE I); // ?C=A A
|
||||
extern VOID o8A3(LPBYTE I); // ?D=C A
|
||||
extern VOID o8A4(LPBYTE I); // ?A#B A
|
||||
extern VOID o8A5(LPBYTE I); // ?B#C A
|
||||
extern VOID o8A6(LPBYTE I); // ?C#A A
|
||||
extern VOID o8A7(LPBYTE I); // ?D#C A
|
||||
extern VOID o8A8(LPBYTE I); // ?A=0 A
|
||||
extern VOID o8A9(LPBYTE I); // ?B=0 A
|
||||
extern VOID o8AA(LPBYTE I); // ?C=0 A
|
||||
extern VOID o8AB(LPBYTE I); // ?D=0 A
|
||||
extern VOID o8AC(LPBYTE I); // ?A#0 A
|
||||
extern VOID o8AD(LPBYTE I); // ?B#0 A
|
||||
extern VOID o8AE(LPBYTE I); // ?C#0 A
|
||||
extern VOID o8AF(LPBYTE I); // ?D#0 A
|
||||
extern VOID o8B0(LPBYTE I); // ?A>B A
|
||||
extern VOID o8B1(LPBYTE I); // ?B>C A
|
||||
extern VOID o8B2(LPBYTE I); // ?C>A A
|
||||
extern VOID o8B3(LPBYTE I); // ?D>C A
|
||||
extern VOID o8B4(LPBYTE I); // ?A<B A
|
||||
extern VOID o8B5(LPBYTE I); // ?B<C A
|
||||
extern VOID o8B6(LPBYTE I); // ?C<A A
|
||||
extern VOID o8B7(LPBYTE I); // ?D<C A
|
||||
extern VOID o8B8(LPBYTE I); // ?A>=B A
|
||||
extern VOID o8B9(LPBYTE I); // ?B>=C A
|
||||
extern VOID o8BA(LPBYTE I); // ?C>=A A
|
||||
extern VOID o8BB(LPBYTE I); // ?D>=C A
|
||||
extern VOID o8BC(LPBYTE I); // ?A<=B A
|
||||
extern VOID o8BD(LPBYTE I); // ?B<=C A
|
||||
extern VOID o8BE(LPBYTE I); // ?C<=A A
|
||||
extern VOID o8BF(LPBYTE I); // ?D<=C A
|
||||
extern VOID o8Cd4(LPBYTE I); // GOLONG #dddd
|
||||
extern VOID o8Dd5(LPBYTE I); // GOVLNG #ddddd
|
||||
extern VOID o8Ed4(LPBYTE I); // GOSUBL #dddd
|
||||
extern VOID o8Fd5(LPBYTE I); // GOSBVL #ddddd
|
||||
extern VOID o9a0(LPBYTE I); // ?A=B f
|
||||
extern VOID o9a1(LPBYTE I); // ?B=C f
|
||||
extern VOID o9a2(LPBYTE I); // ?C=A f
|
||||
extern VOID o9a3(LPBYTE I); // ?D=C f
|
||||
extern VOID o9a4(LPBYTE I); // ?A#B f
|
||||
extern VOID o9a5(LPBYTE I); // ?B#C f
|
||||
extern VOID o9a6(LPBYTE I); // ?C#A f
|
||||
extern VOID o9a7(LPBYTE I); // ?D#C f
|
||||
extern VOID o9a8(LPBYTE I); // ?A=0 f
|
||||
extern VOID o9a9(LPBYTE I); // ?B=0 f
|
||||
extern VOID o9aA(LPBYTE I); // ?C=0 f
|
||||
extern VOID o9aB(LPBYTE I); // ?D=0 f
|
||||
extern VOID o9aC(LPBYTE I); // ?A#0 f
|
||||
extern VOID o9aD(LPBYTE I); // ?B#0 f
|
||||
extern VOID o9aE(LPBYTE I); // ?C#0 f
|
||||
extern VOID o9aF(LPBYTE I); // ?D#0 f
|
||||
extern VOID o9b0(LPBYTE I); // ?A>B f
|
||||
extern VOID o9b1(LPBYTE I); // ?B>C f
|
||||
extern VOID o9b2(LPBYTE I); // ?C>A f
|
||||
extern VOID o9b3(LPBYTE I); // ?D>C f
|
||||
extern VOID o9b4(LPBYTE I); // ?A<B f
|
||||
extern VOID o9b5(LPBYTE I); // ?B<C f
|
||||
extern VOID o9b6(LPBYTE I); // ?C<A f
|
||||
extern VOID o9b7(LPBYTE I); // ?D<C f
|
||||
extern VOID o9b8(LPBYTE I); // ?A>=B f
|
||||
extern VOID o9b9(LPBYTE I); // ?B>=C f
|
||||
extern VOID o9bA(LPBYTE I); // ?C>=A f
|
||||
extern VOID o9bB(LPBYTE I); // ?D>=C f
|
||||
extern VOID o9bC(LPBYTE I); // ?A<=B f
|
||||
extern VOID o9bD(LPBYTE I); // ?B<=C f
|
||||
extern VOID o9bE(LPBYTE I); // ?C<=A f
|
||||
extern VOID o9bF(LPBYTE I); // ?D<=C f
|
||||
extern VOID oAa0(LPBYTE I); // A=A+B f
|
||||
extern VOID oAa1(LPBYTE I); // B=B+C f
|
||||
extern VOID oAa2(LPBYTE I); // C=C+A f
|
||||
extern VOID oAa3(LPBYTE I); // D=D+C f
|
||||
extern VOID oAa4(LPBYTE I); // A=A+A f
|
||||
extern VOID oAa5(LPBYTE I); // B=B+B f
|
||||
extern VOID oAa6(LPBYTE I); // C=C+C f
|
||||
extern VOID oAa7(LPBYTE I); // D=D+D f
|
||||
extern VOID oAa8(LPBYTE I); // B=B+A f
|
||||
extern VOID oAa9(LPBYTE I); // C=C+B f
|
||||
extern VOID oAaA(LPBYTE I); // A=A+C f
|
||||
extern VOID oAaB(LPBYTE I); // C=C+D f
|
||||
extern VOID oAaC(LPBYTE I); // A=A-1 f
|
||||
extern VOID oAaD(LPBYTE I); // B=B-1 f
|
||||
extern VOID oAaE(LPBYTE I); // C=C-1 f
|
||||
extern VOID oAaF(LPBYTE I); // D=D-1 f
|
||||
extern VOID oAb0(LPBYTE I); // A=0 f
|
||||
extern VOID oAb1(LPBYTE I); // B=0 f
|
||||
extern VOID oAb2(LPBYTE I); // C=0 f
|
||||
extern VOID oAb3(LPBYTE I); // D=0 f
|
||||
extern VOID oAb4(LPBYTE I); // A=B f
|
||||
extern VOID oAb5(LPBYTE I); // B=C f
|
||||
extern VOID oAb6(LPBYTE I); // C=A f
|
||||
extern VOID oAb7(LPBYTE I); // D=C f
|
||||
extern VOID oAb8(LPBYTE I); // B=A f
|
||||
extern VOID oAb9(LPBYTE I); // C=B f
|
||||
extern VOID oAbA(LPBYTE I); // A=C f
|
||||
extern VOID oAbB(LPBYTE I); // C=D f
|
||||
extern VOID oAbC(LPBYTE I); // ABEX f
|
||||
extern VOID oAbD(LPBYTE I); // BCEX f
|
||||
extern VOID oAbE(LPBYTE I); // CAEX f
|
||||
extern VOID oAbF(LPBYTE I); // DCEX f
|
||||
extern VOID oBa0(LPBYTE I); // A=A-B f
|
||||
extern VOID oBa1(LPBYTE I); // B=B-C f
|
||||
extern VOID oBa2(LPBYTE I); // C=C-A f
|
||||
extern VOID oBa3(LPBYTE I); // D=D-C f
|
||||
extern VOID oBa4(LPBYTE I); // A=A+1 f
|
||||
extern VOID oBa5(LPBYTE I); // B=B+1 f
|
||||
extern VOID oBa6(LPBYTE I); // C=C+1 f
|
||||
extern VOID oBa7(LPBYTE I); // D=D+1 f
|
||||
extern VOID oBa8(LPBYTE I); // B=B-A f
|
||||
extern VOID oBa9(LPBYTE I); // C=C-B f
|
||||
extern VOID oBaA(LPBYTE I); // A=A-C f
|
||||
extern VOID oBaB(LPBYTE I); // C=C-D f
|
||||
extern VOID oBaC(LPBYTE I); // A=B-A f
|
||||
extern VOID oBaD(LPBYTE I); // B=C-B f
|
||||
extern VOID oBaE(LPBYTE I); // C=A-C f
|
||||
extern VOID oBaF(LPBYTE I); // D=C-D f
|
||||
extern VOID oBb0(LPBYTE I); // ASL f
|
||||
extern VOID oBb1(LPBYTE I); // BSL f
|
||||
extern VOID oBb2(LPBYTE I); // CSL f
|
||||
extern VOID oBb3(LPBYTE I); // DSL f
|
||||
extern VOID oBb4(LPBYTE I); // ASR f
|
||||
extern VOID oBb5(LPBYTE I); // BSR f
|
||||
extern VOID oBb6(LPBYTE I); // CSR f
|
||||
extern VOID oBb7(LPBYTE I); // DSR f
|
||||
extern VOID oBb8(LPBYTE I); // A=-A f
|
||||
extern VOID oBb9(LPBYTE I); // B=-B f
|
||||
extern VOID oBbA(LPBYTE I); // C=-C f
|
||||
extern VOID oBbB(LPBYTE I); // D=-D f
|
||||
extern VOID oBbC(LPBYTE I); // A=-A-1 f
|
||||
extern VOID oBbD(LPBYTE I); // B=-B-1 f
|
||||
extern VOID oBbE(LPBYTE I); // C=-C-1 f
|
||||
extern VOID oBbF(LPBYTE I); // D=-D-1 f
|
||||
extern VOID oC0(LPBYTE I); // A=A+B A
|
||||
extern VOID oC1(LPBYTE I); // B=B+C A
|
||||
extern VOID oC2(LPBYTE I); // C=C+A A
|
||||
extern VOID oC3(LPBYTE I); // D=D+C A
|
||||
extern VOID oC4(LPBYTE I); // A=A+A A
|
||||
extern VOID oC5(LPBYTE I); // B=B+B A
|
||||
extern VOID oC6(LPBYTE I); // C=C+C A
|
||||
extern VOID oC7(LPBYTE I); // D=D+D A
|
||||
extern VOID oC8(LPBYTE I); // B=B+A A
|
||||
extern VOID oC9(LPBYTE I); // C=C+B A
|
||||
extern VOID oCA(LPBYTE I); // A=A+C A
|
||||
extern VOID oCB(LPBYTE I); // C=C+D A
|
||||
extern VOID oCC(LPBYTE I); // A=A-1 A
|
||||
extern VOID oCD(LPBYTE I); // B=B-1 A
|
||||
extern VOID oCE(LPBYTE I); // C=C-1 A
|
||||
extern VOID oCF(LPBYTE I); // D=D-1 A
|
||||
extern VOID oD0(LPBYTE I); // A=0 A
|
||||
extern VOID oD1(LPBYTE I); // B=0 A
|
||||
extern VOID oD2(LPBYTE I); // C=0 A
|
||||
extern VOID oD3(LPBYTE I); // D=0 A
|
||||
extern VOID oD4(LPBYTE I); // A=B A
|
||||
extern VOID oD5(LPBYTE I); // B=C A
|
||||
extern VOID oD6(LPBYTE I); // C=A A
|
||||
extern VOID oD7(LPBYTE I); // D=C A
|
||||
extern VOID oD8(LPBYTE I); // B=A A
|
||||
extern VOID oD9(LPBYTE I); // C=B A
|
||||
extern VOID oDA(LPBYTE I); // A=C A
|
||||
extern VOID oDB(LPBYTE I); // C=D A
|
||||
extern VOID oDC(LPBYTE I); // ABEX
|
||||
extern VOID oDD(LPBYTE I); // BCEX
|
||||
extern VOID oDE(LPBYTE I); // CAEX
|
||||
extern VOID oDF(LPBYTE I); // DCEX
|
||||
extern VOID oE0(LPBYTE I); // A=A-B A
|
||||
extern VOID oE1(LPBYTE I); // B=B-C A
|
||||
extern VOID oE2(LPBYTE I); // C=C-A A
|
||||
extern VOID oE3(LPBYTE I); // D=D-C A
|
||||
extern VOID oE4(LPBYTE I); // A=A+1 A
|
||||
extern VOID oE5(LPBYTE I); // B=B+1 A
|
||||
extern VOID oE6(LPBYTE I); // C=C+1 A
|
||||
extern VOID oE7(LPBYTE I); // D=D+1 A
|
||||
extern VOID oE8(LPBYTE I); // B=B-A A
|
||||
extern VOID oE9(LPBYTE I); // C=C-B A
|
||||
extern VOID oEA(LPBYTE I); // A=A-C A
|
||||
extern VOID oEB(LPBYTE I); // C=C-D A
|
||||
extern VOID oEC(LPBYTE I); // A=B-A A
|
||||
extern VOID oED(LPBYTE I); // B=C-B A
|
||||
extern VOID oEE(LPBYTE I); // C=A-C A
|
||||
extern VOID oEF(LPBYTE I); // D=C-D A
|
||||
extern VOID oF0(LPBYTE I); // ASL A
|
||||
extern VOID oF1(LPBYTE I); // BSL A
|
||||
extern VOID oF2(LPBYTE I); // CSL A
|
||||
extern VOID oF3(LPBYTE I); // DSL A
|
||||
extern VOID oF4(LPBYTE I); // ASR A
|
||||
extern VOID oF5(LPBYTE I); // BSR A
|
||||
extern VOID oF6(LPBYTE I); // CSR A
|
||||
extern VOID oF7(LPBYTE I); // DSR A
|
||||
extern VOID oF8(LPBYTE I); // A=-A A
|
||||
extern VOID oF9(LPBYTE I); // B=-B A
|
||||
extern VOID oFA(LPBYTE I); // C=-C A
|
||||
extern VOID oFB(LPBYTE I); // D=-D A
|
||||
extern VOID oFC(LPBYTE I); // A=-A-1 A
|
||||
extern VOID oFD(LPBYTE I); // B=-B-1 A
|
||||
extern VOID oFE(LPBYTE I); // C=-C-1 A
|
||||
extern VOID oFF(LPBYTE I); // D=-D-1 A
|
||||
|
||||
extern VOID o_invalid3(LPBYTE I);
|
||||
extern VOID o_invalid4(LPBYTE I);
|
||||
extern VOID o_invalid5(LPBYTE I);
|
||||
extern VOID o_invalid6(LPBYTE I);
|
||||
|
||||
extern VOID o_goyes3(LPBYTE I);
|
||||
extern VOID o_goyes5(LPBYTE I);
|
||||
|
||||
extern VOID o81B1(LPBYTE I); // beep patch
|
476
app/src/main/cpp/OPS.H
Normal file
|
@ -0,0 +1,476 @@
|
|||
/*
|
||||
* ops.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1995 Sebastien Carlier
|
||||
*
|
||||
*/
|
||||
|
||||
#define NFunpack(a, b, f) Nunpack((a)+F_s[f], b, F_l[f])
|
||||
#define NFread(a, b, f) Nread((a)+F_s[f], b, F_l[f])
|
||||
#define NFwrite(a, b, f) Nwrite((a)+F_s[f], b, F_l[f])
|
||||
#define NFcopy(a, b, f) memcpy((a)+F_s[f], (b)+F_s[f], F_l[f])
|
||||
#define NFxchg(a, b, f) Nxchg((a)+F_s[f], (b)+F_s[f], F_l[f])
|
||||
#define NFadd(a, b, f) Nadd((a)+F_s[f], (b)+F_s[f], F_l[f])
|
||||
#define NFsub(a, b, f) Nsub((a)+F_s[f], (b)+F_s[f], F_l[f])
|
||||
#define NFrsub(a, b, f) Nrsub((a)+F_s[f], (b)+F_s[f], F_l[f])
|
||||
#define NFand(a, b, f) Nand((a)+F_s[f], (b)+F_s[f], F_l[f])
|
||||
#define NFor(a, b, f) Nor((a)+F_s[f], (b)+F_s[f], F_l[f])
|
||||
#define NFzero(a,f) memset((a)+F_s[f], 0, F_l[f])
|
||||
#define NFpack(a, f) Npack((a)+F_s[f], F_l[f])
|
||||
#define NFinc(a, f) Ninc(a, F_l[f], F_s[f])
|
||||
#define NFdec(a, f) Ndec(a, F_l[f], F_s[f])
|
||||
#define NFnot(a, f) Nnot((a)+F_s[f], F_l[f])
|
||||
#define NFneg(a, f) Nneg((a)+F_s[f], F_l[f])
|
||||
#define NFsl(a, f) Nsl((a)+F_s[f], F_l[f])
|
||||
#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 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])
|
||||
#define TFz(a, f) Tz((a)+F_s[f], F_l[f])
|
||||
#define TFne(a, b, f) Tne((a)+F_s[f], (b)+F_s[f], F_l[f])
|
||||
#define TFae(a, b, f) Tae((a)+F_s[f], (b)+F_s[f], F_l[f])
|
||||
#define TFbe(a, b, f) Tbe((a)+F_s[f], (b)+F_s[f], F_l[f])
|
||||
#define TFnz(a, f) Tnz((a)+F_s[f], F_l[f])
|
||||
|
||||
static __inline LPBYTE FASTPTR(DWORD d)
|
||||
{
|
||||
static BYTE pbyNULL[21];
|
||||
LPBYTE lpbyPage;
|
||||
DWORD u, v;
|
||||
|
||||
d &= 0xFFFFF; // handle address overflows
|
||||
|
||||
u = d >> 12; // page
|
||||
v = d & 0xFFF; // offset
|
||||
|
||||
if ( !(Chipset.IOCfig && ((d & 0xFFFC0) == Chipset.IOBase))
|
||||
&& RMap[u] != NULL // page valid
|
||||
&& ( v < 0x1000 - ARRAYSIZEOF(pbyNULL) // complete opcode inside page
|
||||
// or next page continue linear addressing
|
||||
|| (RMap[u] + 0x1000 == RMap[(u+1) & (ARRAYSIZEOF(RMap)-1)])
|
||||
)
|
||||
)
|
||||
{
|
||||
lpbyPage = RMap[u] + v; // full address
|
||||
}
|
||||
else
|
||||
{
|
||||
lpbyPage = pbyNULL; // memory allocation
|
||||
Npeek(lpbyPage, d, ARRAYSIZEOF(pbyNULL)); // fill with data (LAHEX + 16 digits = longest opcode)
|
||||
}
|
||||
return lpbyPage;
|
||||
}
|
||||
|
||||
static __inline void rstkpush(DWORD d)
|
||||
{
|
||||
Chipset.rstk[Chipset.rstkp] = d;
|
||||
Chipset.rstkp=(Chipset.rstkp+1)&7;
|
||||
}
|
||||
|
||||
static __inline DWORD rstkpop(VOID)
|
||||
{
|
||||
DWORD r;
|
||||
|
||||
Chipset.rstkp=(Chipset.rstkp-1)&7;
|
||||
r = Chipset.rstk[Chipset.rstkp];
|
||||
Chipset.rstk[Chipset.rstkp] = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
static __inline DWORD Npack(BYTE *a, UINT s)
|
||||
{
|
||||
DWORD r = 0;
|
||||
|
||||
while (s--) r = (r<<4)|a[s];
|
||||
return r;
|
||||
}
|
||||
|
||||
static __inline VOID Nunpack(BYTE *a, DWORD b, UINT s)
|
||||
{
|
||||
for (; s>0; --s) { *a++ = (BYTE)(b&0xf); b>>=4; }
|
||||
}
|
||||
|
||||
static __inline QWORD Npack64(BYTE *a, UINT s)
|
||||
{
|
||||
QWORD r = 0;
|
||||
|
||||
while (s--) r = (r<<4)|a[s];
|
||||
return r;
|
||||
}
|
||||
|
||||
static __inline VOID Nunpack64(BYTE *a, QWORD b, UINT s)
|
||||
{
|
||||
UINT i;
|
||||
for (i=0; i<s; i++) { a[i] = (BYTE)(b&0xf); b>>=4; }
|
||||
}
|
||||
|
||||
static __inline void Nxchg(BYTE *a, BYTE *b, UINT s)
|
||||
{
|
||||
BYTE X[16];
|
||||
|
||||
memcpy(X, b, s);
|
||||
memcpy(b, a, s);
|
||||
memcpy(a, X, s);
|
||||
}
|
||||
|
||||
static __inline void Ninc(BYTE *a, UINT s, UINT d)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
if (Chipset.mode_dec)
|
||||
{
|
||||
BYTE c = 1;
|
||||
for (i=d; i<s+d; ++i)
|
||||
{
|
||||
// no register wrap
|
||||
_ASSERT(i < ARRAYSIZEOF(((CHIPSET *) NULL)->A));
|
||||
|
||||
// illegal number in dec mode
|
||||
if (a[i] >= 10) a[i] &= 0x7;
|
||||
|
||||
a[i] += c;
|
||||
c = (a[i] >= 10);
|
||||
if (c) a[i] -= 10;
|
||||
}
|
||||
Chipset.carry = (c==1);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=d; i<s+d; ++i)
|
||||
{
|
||||
// no register wrap
|
||||
_ASSERT(i < ARRAYSIZEOF(((CHIPSET *) NULL)->A));
|
||||
|
||||
a[i]++;
|
||||
if (a[i] < 16)
|
||||
{
|
||||
Chipset.carry = FALSE;
|
||||
return;
|
||||
}
|
||||
a[i] -= 16;
|
||||
}
|
||||
Chipset.carry = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static __inline void Ninc16(BYTE *a, UINT s, UINT d)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
for (i=d; i<s+d; ++i)
|
||||
{
|
||||
a[i&0xf]++;
|
||||
if (a[i&0xf] < 16)
|
||||
{
|
||||
Chipset.carry = FALSE;
|
||||
return;
|
||||
}
|
||||
a[i&0xf] -= 16;
|
||||
}
|
||||
Chipset.carry = TRUE;
|
||||
}
|
||||
|
||||
static __inline void Nincx(BYTE *a, UINT s)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
for (i=0; i<s; ++i)
|
||||
{
|
||||
a[i]++;
|
||||
if (a[i] < 16)
|
||||
{
|
||||
Chipset.carry = FALSE;
|
||||
return;
|
||||
}
|
||||
a[i] -= 16;
|
||||
}
|
||||
Chipset.carry = TRUE;
|
||||
}
|
||||
|
||||
static __inline void Ndec(BYTE *a, UINT s, UINT d)
|
||||
{
|
||||
UINT i;
|
||||
BYTE cBase = Chipset.mode_dec ? 10 : 16;
|
||||
|
||||
for (i=d; i<s+d; ++i)
|
||||
{
|
||||
// no register wrap
|
||||
_ASSERT(i < ARRAYSIZEOF(((CHIPSET *) NULL)->A));
|
||||
|
||||
a[i]--;
|
||||
if ((a[i] & 0xF0) == 0) // check overflow
|
||||
{
|
||||
Chipset.carry = FALSE;
|
||||
return;
|
||||
}
|
||||
a[i] += cBase;
|
||||
}
|
||||
Chipset.carry = TRUE;
|
||||
}
|
||||
|
||||
static __inline void Ndec16(BYTE *a, UINT s, UINT d)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
for (i=d; i<s+d; ++i)
|
||||
{
|
||||
a[i&0xf]--;
|
||||
if (a[i&0xf] < 16)
|
||||
{
|
||||
Chipset.carry = FALSE;
|
||||
return;
|
||||
}
|
||||
a[i&0xf] += 16;
|
||||
}
|
||||
Chipset.carry = TRUE;
|
||||
}
|
||||
|
||||
static __inline void Nadd(BYTE *a, BYTE *b, UINT s)
|
||||
{
|
||||
UINT i;
|
||||
BYTE c = 0;
|
||||
BYTE cBase = Chipset.mode_dec ? 10 : 16;
|
||||
|
||||
for (i=0; i<s; ++i)
|
||||
{
|
||||
// illegal number in dec mode
|
||||
if (a[i] >= cBase) a[i] &= 0x7;
|
||||
|
||||
a[i] += b[i] + c;
|
||||
if (a[i] >= cBase)
|
||||
{
|
||||
a[i] -= cBase;
|
||||
c = 1;
|
||||
}
|
||||
else
|
||||
c = 0;
|
||||
}
|
||||
Chipset.carry = (c==1);
|
||||
}
|
||||
|
||||
static __inline void Nsub(BYTE *a, BYTE *b, UINT s)
|
||||
{
|
||||
UINT i;
|
||||
BYTE c = 0;
|
||||
BYTE cBase = Chipset.mode_dec ? 10 : 16;
|
||||
|
||||
for (i=0; i<s; ++i)
|
||||
{
|
||||
a[i] = a[i] - b[i] - c;
|
||||
if ((a[i] & 0xF0) != 0) // check overflow
|
||||
{
|
||||
a[i] += cBase;
|
||||
// illegal number in dec mode
|
||||
if ((a[i] & 0xF0) != 0) a[i] &= 0x7;
|
||||
c = 1;
|
||||
}
|
||||
else
|
||||
c = 0;
|
||||
}
|
||||
Chipset.carry = (c==1);
|
||||
}
|
||||
|
||||
static __inline void Nrsub(BYTE *a, BYTE *b, UINT s)
|
||||
{
|
||||
UINT i;
|
||||
BYTE c = 0;
|
||||
BYTE cBase = Chipset.mode_dec ? 10 : 16;
|
||||
|
||||
for (i=0; i<s; ++i)
|
||||
{
|
||||
a[i] = b[i] - a[i] - c;
|
||||
if ((a[i] & 0xF0) != 0) // check overflow
|
||||
{
|
||||
a[i] += cBase;
|
||||
// illegal number in dec mode
|
||||
if ((a[i] & 0xF0) != 0) a[i] &= 0x7;
|
||||
c = 1;
|
||||
}
|
||||
else
|
||||
c = 0;
|
||||
}
|
||||
Chipset.carry = (c==1);
|
||||
}
|
||||
|
||||
static __inline void Nand(BYTE *a, BYTE *b, UINT s)
|
||||
{
|
||||
while (s--) a[s] &= b[s];
|
||||
}
|
||||
|
||||
static __inline void Nor(BYTE *a, BYTE *b, UINT s)
|
||||
{
|
||||
while (s--) a[s] |= b[s];
|
||||
}
|
||||
|
||||
static __inline void Nnot(BYTE *a, UINT s)
|
||||
{
|
||||
BYTE cBase = Chipset.mode_dec ? 9 : 15;
|
||||
|
||||
while (s--)
|
||||
{
|
||||
a[s] = cBase - a[s];
|
||||
if ((a[s] & 0xF0) != 0) // check overflow (dec mode only)
|
||||
a[s] &= 0x7;
|
||||
}
|
||||
Chipset.carry = FALSE;
|
||||
}
|
||||
|
||||
static __inline void Nneg(BYTE *a, UINT s)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
for (i=0; i<s && a[i]==0; ++i) { } // search for non-zero digit
|
||||
if ((Chipset.carry = (i!=s))) // value was non-zero
|
||||
{
|
||||
BYTE cBase = Chipset.mode_dec ? 9 : 15;
|
||||
|
||||
_ASSERT(a[i] > 0); // check for non-zero digit
|
||||
for (--a[i]; i<s; ++i)
|
||||
{
|
||||
a[i] = cBase - a[i];
|
||||
if ((a[i] & 0xF0) != 0) // check overflow (dec mode only)
|
||||
a[i] &= 0x7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static __inline void Nsl(BYTE *a, UINT s)
|
||||
{
|
||||
while (--s) a[s] = a[s-1];
|
||||
*a = 0;
|
||||
}
|
||||
|
||||
static __inline void Nslc(BYTE *a, UINT s)
|
||||
{
|
||||
BYTE c = a[s-1];
|
||||
|
||||
while (--s) a[s] = a[s-1];
|
||||
*a = c;
|
||||
}
|
||||
|
||||
static __inline void Nsr(BYTE *a, UINT s)
|
||||
{
|
||||
if (*a) Chipset.HST |= SB;
|
||||
while (--s) { *a = a[1]; a++; }
|
||||
*a = 0;
|
||||
}
|
||||
|
||||
static __inline void Nsrc(BYTE *a, UINT s)
|
||||
{
|
||||
BYTE c = *a;
|
||||
|
||||
if (c) Chipset.HST |= SB;
|
||||
while (--s) { *a = a[1]; a++; }
|
||||
*a = c;
|
||||
}
|
||||
|
||||
static __inline void Nsrb(BYTE *a, UINT s)
|
||||
{
|
||||
if (*a & 1) Chipset.HST |= SB;
|
||||
while (--s)
|
||||
{
|
||||
*a >>= 1;
|
||||
*a |= ((a[1] & 1) << 3);
|
||||
a++;
|
||||
}
|
||||
*a >>= 1;
|
||||
}
|
||||
|
||||
static __inline void Nbit0(BYTE *a, UINT b)
|
||||
{
|
||||
a[b>>2] &= ~(1<<(b&3));
|
||||
}
|
||||
|
||||
static __inline void Nbit1(BYTE *a, UINT b)
|
||||
{
|
||||
a[b>>2] |= 1<<(b&3);
|
||||
}
|
||||
|
||||
static __inline void Tbit0(BYTE *a, UINT b)
|
||||
{
|
||||
Chipset.carry = ((a[b>>2] & (1<<(b&3))) == 0);
|
||||
}
|
||||
|
||||
static __inline void Tbit1(BYTE *a, UINT b)
|
||||
{
|
||||
Chipset.carry = ((a[b>>2] & (1<<(b&3))) != 0);
|
||||
}
|
||||
|
||||
static __inline void Te(BYTE *a, BYTE *b, UINT s)
|
||||
{
|
||||
while (s--)
|
||||
{
|
||||
if (a[s]!=b[s])
|
||||
{
|
||||
Chipset.carry = FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Chipset.carry = TRUE;
|
||||
}
|
||||
|
||||
static __inline void Tne(BYTE *a, BYTE *b, UINT s)
|
||||
{
|
||||
while (s--)
|
||||
{
|
||||
if (a[s]!=b[s])
|
||||
{
|
||||
Chipset.carry = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Chipset.carry = FALSE;
|
||||
}
|
||||
|
||||
static __inline void Tz(BYTE *a, UINT s)
|
||||
{
|
||||
while (s--)
|
||||
{
|
||||
if (a[s]!=0)
|
||||
{
|
||||
Chipset.carry = FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Chipset.carry = TRUE;
|
||||
}
|
||||
|
||||
static __inline void Tnz(BYTE *a, UINT s)
|
||||
{
|
||||
while (s--)
|
||||
{
|
||||
if (a[s]!=0)
|
||||
{
|
||||
Chipset.carry = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Chipset.carry = FALSE;
|
||||
}
|
||||
|
||||
static __inline void Ta(BYTE *a, BYTE *b, UINT s)
|
||||
{
|
||||
while (--s) if (a[s]!=b[s]) break;
|
||||
Chipset.carry = (a[s]>b[s]);
|
||||
}
|
||||
|
||||
static __inline void Tb(BYTE *a, BYTE *b, UINT s)
|
||||
{
|
||||
while (--s) if (a[s]!=b[s]) break;
|
||||
Chipset.carry = (a[s]<b[s]);
|
||||
}
|
||||
|
||||
static __inline void Tae(BYTE *a, BYTE *b, UINT s)
|
||||
{
|
||||
while (--s) if (a[s]!=b[s]) break;
|
||||
Chipset.carry = (a[s]>=b[s]);
|
||||
}
|
||||
|
||||
static __inline void Tbe(BYTE *a, BYTE *b, UINT s)
|
||||
{
|
||||
while (--s) if (a[s]!=b[s]) break;
|
||||
Chipset.carry = (a[s]<=b[s]);
|
||||
}
|
5
app/src/main/cpp/PCH.C
Normal file
|
@ -0,0 +1,5 @@
|
|||
//
|
||||
// PCH.C
|
||||
//
|
||||
|
||||
#include "pch.h"
|
93
app/src/main/cpp/PCH.H
Normal file
|
@ -0,0 +1,93 @@
|
|||
//
|
||||
// PCH.H
|
||||
//
|
||||
|
||||
#define _WIN32_IE 0x0200
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <shellapi.h>
|
||||
#include <commctrl.h>
|
||||
#include <shlobj.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <direct.h>
|
||||
#include <conio.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
#if !defined VERIFY
|
||||
#if defined _DEBUG
|
||||
#define VERIFY(f) _ASSERT(f)
|
||||
#else // _DEBUG
|
||||
#define VERIFY(f) ((VOID)(f))
|
||||
#endif // _DEBUG
|
||||
#endif // _VERIFY
|
||||
|
||||
#if !defined INVALID_SET_FILE_POINTER
|
||||
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
||||
#endif
|
||||
|
||||
#if !defined INVALID_FILE_ATTRIBUTES
|
||||
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
||||
#endif
|
||||
|
||||
#if !defined GWLP_USERDATA
|
||||
#define GWLP_USERDATA GWL_USERDATA
|
||||
#endif
|
||||
|
||||
#if !defined GCLP_HCURSOR
|
||||
#define GCLP_HCURSOR GCL_HCURSOR
|
||||
#endif
|
||||
|
||||
#if !defined IDC_HAND // Win2k specific definition
|
||||
#define IDC_HAND MAKEINTRESOURCE(32649)
|
||||
#endif
|
||||
|
||||
#if _MSC_VER <= 1200 // missing type definition in the MSVC6.0 SDK and earlier
|
||||
#define SetWindowLongPtr SetWindowLong
|
||||
#define GetWindowLongPtr GetWindowLong
|
||||
#define SetClassLongPtr SetClassLong
|
||||
#define GetClassLongPtr GetClassLong
|
||||
typedef SIZE_T DWORD_PTR, *PDWORD_PTR;
|
||||
typedef ULONG ULONG_PTR, *PULONG_PTR;
|
||||
typedef LONG LONG_PTR, *PLONG_PTR;
|
||||
#endif
|
||||
|
||||
#if _MSC_VER >= 1400 // valid for VS2005 and later
|
||||
#if defined _M_IX86
|
||||
#pragma comment(linker,"/manifestdependency:\" \
|
||||
type='win32' \
|
||||
name='Microsoft.Windows.Common-Controls' \
|
||||
version='6.0.0.0' processorArchitecture='x86' \
|
||||
publicKeyToken='6595b64144ccf1df' \
|
||||
language='*'\"")
|
||||
#elif defined _M_IA64
|
||||
#pragma comment(linker,"/manifestdependency:\" \
|
||||
type='win32' \
|
||||
name='Microsoft.Windows.Common-Controls' \
|
||||
version='6.0.0.0' processorArchitecture='ia64' \
|
||||
publicKeyToken='6595b64144ccf1df' \
|
||||
language='*'\"")
|
||||
#elif defined _M_X64
|
||||
#pragma comment(linker,"/manifestdependency:\" \
|
||||
type='win32' \
|
||||
name='Microsoft.Windows.Common-Controls' \
|
||||
version='6.0.0.0' processorArchitecture='amd64' \
|
||||
publicKeyToken='6595b64144ccf1df' \
|
||||
language='*'\"")
|
||||
#else
|
||||
#pragma comment(linker,"/manifestdependency:\" \
|
||||
type='win32' \
|
||||
name='Microsoft.Windows.Common-Controls' \
|
||||
version='6.0.0.0' processorArchitecture='*' \
|
||||
publicKeyToken='6595b64144ccf1df' \
|
||||
language='*'\"")
|
||||
#endif
|
||||
#endif
|
177
app/src/main/cpp/REDEYE.C
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* redeye.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2011 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h"
|
||||
|
||||
#define ERR_CHAR 127 // character for transfer error
|
||||
|
||||
#define H1 0x78
|
||||
#define H2 0xE6
|
||||
#define H3 0xD5
|
||||
#define H4 0x8B
|
||||
|
||||
// HP redeye correction masks
|
||||
static CONST BYTE byEmask[] = { H1, H2, H3, H4 };
|
||||
|
||||
static __inline UINT MAX(UINT a, UINT b)
|
||||
{
|
||||
return (a>b)?a:b;
|
||||
}
|
||||
|
||||
static __inline BYTE Parity(BYTE b)
|
||||
{
|
||||
b ^= (b >> 4);
|
||||
b ^= (b >> 2);
|
||||
b ^= (b >> 1);
|
||||
return b & 1;
|
||||
}
|
||||
|
||||
static __inline BYTE CreateCorrectionBits(BYTE b)
|
||||
{
|
||||
UINT i;
|
||||
BYTE byVal = 0;
|
||||
|
||||
for (i = 0; i < ARRAYSIZEOF(byEmask);++i)
|
||||
{
|
||||
byVal <<= 1;
|
||||
byVal |= Parity((BYTE) (b & byEmask[i]));
|
||||
}
|
||||
return byVal;
|
||||
}
|
||||
|
||||
static __inline WORD CorrectData(WORD wData,WORD wMissed)
|
||||
{
|
||||
while ((wMissed & 0xFF) != 0) // clear every missed bit in data area
|
||||
{
|
||||
BYTE byBitMask;
|
||||
|
||||
// detect valid H(i) mask
|
||||
WORD wMi = 0x800; // first M(i) bit
|
||||
INT i = 0; // index to first H(i) mask
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if ((wMissed & wMi) == 0) // possible valid mask
|
||||
{
|
||||
_ASSERT(i < ARRAYSIZEOF(byEmask));
|
||||
|
||||
// select bit to correct
|
||||
byBitMask = wMissed & byEmask[i];
|
||||
|
||||
if (Parity(byBitMask)) // only one bit set (parity odd)
|
||||
break; // -> valid H(i) mask
|
||||
}
|
||||
|
||||
wMi >>= 1; // next M(i) bit
|
||||
i++; // next H(i) mask
|
||||
}
|
||||
|
||||
// correct bit with H(i) mask
|
||||
wMissed ^= byBitMask; // clear this missed bit
|
||||
|
||||
// parity odd -> wrong data value
|
||||
if (Parity((BYTE) ((wData & byEmask[i]) ^ ((wData & wMi) >> 8))))
|
||||
wData ^= byBitMask; // correct value
|
||||
}
|
||||
return wData & 0xFF; // only data byte is correct
|
||||
}
|
||||
|
||||
VOID IrPrinter(BYTE c)
|
||||
{
|
||||
static INT nFrame = 0; // frame counter
|
||||
static DWORD dwData = 0; // half bit data container
|
||||
static INT nStart = 0; // frame counter disabled
|
||||
|
||||
BOOL bLSRQ;
|
||||
|
||||
dwData = (dwData << 1) | (c & LBO); // grab the last 32 bit send through IR
|
||||
|
||||
// Led Service ReQuest on Led Buffer Empty enabled
|
||||
bLSRQ = (Chipset.IORam[LCR] & ELBE) != 0;
|
||||
|
||||
IOBit(SRQ2,LSRQ,bLSRQ); // update LSRQ bit
|
||||
if (bLSRQ) // interrupt on Led Buffer Empty enabled
|
||||
{
|
||||
Chipset.SoftInt = TRUE; // execute interrupt
|
||||
bInterrupt = TRUE;
|
||||
}
|
||||
|
||||
// HP40G and HP49G have no IR transmitter Led
|
||||
if ((cCurrentRomType == 'E' && nCurrentClass == 40) || cCurrentRomType == 'X')
|
||||
return;
|
||||
|
||||
if (nFrame == 0) // waiting for start bit condition
|
||||
{
|
||||
if ((dwData & 0x3F) == 0x07) // start bit condition (000111 pattern)
|
||||
{
|
||||
nStart = 1; // enable frame counter
|
||||
}
|
||||
}
|
||||
|
||||
if (nFrame == 24) // 24 half bit received
|
||||
{
|
||||
INT i;
|
||||
|
||||
WORD wData = 0; // data container
|
||||
WORD wMissed = 0; // missed bit container
|
||||
INT nCount = 0; // no. of missed bits
|
||||
|
||||
nFrame = 0; // reset for next character
|
||||
nStart = 0; // disable frame counter
|
||||
|
||||
// separate to data and missed bits
|
||||
for (i = 0; i < 12; ++i) // 12 bit frames
|
||||
{
|
||||
BYTE b = (BYTE) (dwData & 3); // last 2 half bits
|
||||
|
||||
if (b == 0x0 || b == 0x3) // illegal half bit combination
|
||||
{
|
||||
wMissed |= (1 << i); // this is a missed bit
|
||||
++nCount; // incr. number of missed bits
|
||||
}
|
||||
else // valid data bit
|
||||
{
|
||||
wData |= ((b >> 1) << i); // add data bit
|
||||
}
|
||||
dwData >>= 2; // next 2 half bits
|
||||
}
|
||||
|
||||
if (nCount <= 2) // error can be fixed
|
||||
{
|
||||
BYTE byOrgParity,byNewParity;
|
||||
|
||||
byOrgParity = wData >> 8; // the original parity information with missed bits
|
||||
byNewParity = ~(wMissed >> 8); // missed bit mask for recalculated parity
|
||||
|
||||
if (nCount > 0) // error correction
|
||||
{
|
||||
wData = CorrectData(wData,wMissed);
|
||||
}
|
||||
|
||||
wData &= 0xFF; // remove parity information
|
||||
|
||||
// recalculate parity data
|
||||
byNewParity &= CreateCorrectionBits((BYTE) wData);
|
||||
|
||||
// wrong parity
|
||||
if (byOrgParity != byNewParity)
|
||||
wData = ERR_CHAR; // character for transfer error
|
||||
}
|
||||
else
|
||||
{
|
||||
wData = ERR_CHAR; // character for transfer error
|
||||
}
|
||||
|
||||
SendByteUdp((BYTE) wData); // send data byte
|
||||
return;
|
||||
}
|
||||
nFrame += nStart; // next frame
|
||||
return;
|
||||
}
|
253
app/src/main/cpp/RESOURCE.H
Normal file
|
@ -0,0 +1,253 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by Emu48.rc
|
||||
//
|
||||
#define IDM_DEBUG_SETTINGS 0x0010
|
||||
#define IDI_EMU48 100
|
||||
#define IDR_MENU 101
|
||||
#define IDM_MENU 102
|
||||
#define IDR_DEBUG 103
|
||||
#define IDR_DEBUG_TOOLBAR 104
|
||||
#define IDR_DEBUG_CODE 105
|
||||
#define IDR_DEBUG_MEM 106
|
||||
#define IDR_DEBUG_STACK 107
|
||||
#define IDB_CHECKBOX 108
|
||||
#define IDD_ABOUT 109
|
||||
#define IDD_SET_GENERAL 110
|
||||
#define IDD_SET_MEMORY 111
|
||||
#define IDD_SET_PERIPHERAL 112
|
||||
#define IDD_CHOOSEKML 113
|
||||
#define IDD_KMLLOG 114
|
||||
#define IDD_DISASM 115
|
||||
#define IDD_DEBUG 116
|
||||
#define IDD_NEWVALUE 117
|
||||
#define IDD_ENTERADR 118
|
||||
#define IDD_BREAKEDIT 119
|
||||
#define IDD_ENTERBREAK 120
|
||||
#define IDD_INSTRUCTIONS 121
|
||||
#define IDD_WRITEONLYREG 122
|
||||
#define IDD_FIND 123
|
||||
#define IDD_PROFILE 124
|
||||
#define IDD_RPLVIEW 125
|
||||
#define IDD_MACROSET 126
|
||||
#define IDD_DEBUG_MEMSAVE 127
|
||||
#define IDD_DEBUG_MEMLOAD 128
|
||||
#define IDD_DEBUG_SETTINGS 129
|
||||
#define IDC_REALSPEED 1000
|
||||
#define IDC_GRAYSCALE 1001
|
||||
#define IDC_ALWAYSONTOP 1002
|
||||
#define IDC_ACTFOLLOWSMOUSE 1003
|
||||
#define IDC_SINGLEINSTANCE 1004
|
||||
#define IDC_AUTOSAVE 1005
|
||||
#define IDC_AUTOSAVEONEXIT 1006
|
||||
#define IDC_OBJECTLOADWARNING 1007
|
||||
#define IDC_SHOWTITLE 1008
|
||||
#define IDC_SHOWMENU 1009
|
||||
#define IDC_ALWAYSDISPLOG 1010
|
||||
#define IDC_PORT1EN 1011
|
||||
#define IDC_PORT1WR 1012
|
||||
#define IDC_PORT2ISSHARED 1013
|
||||
#define IDC_PORT2WR 1014
|
||||
#define IDC_PORT2 1015
|
||||
#define IDC_PORT2LOAD 1016
|
||||
#define IDC_IR_ADDR 1017
|
||||
#define IDC_IR_PORT 1018
|
||||
#define IDC_WIRE 1019
|
||||
#define IDC_IR 1020
|
||||
#define IDC_EMUDIR 1021
|
||||
#define IDC_EMUDIRSEL 1022
|
||||
#define IDC_UPDATE 1023
|
||||
#define IDC_KMLSCRIPT 1024
|
||||
#define IDC_AUTHOR 1025
|
||||
#define IDC_TITLE 1026
|
||||
#define IDC_KMLLOG 1027
|
||||
#define IDC_VERSION 1028
|
||||
#define IDC_LICENSE 1029
|
||||
#define IDC_DISASM_WIN 1030
|
||||
#define IDC_DISASM_MODE_TEXT 1031
|
||||
#define IDC_DISASM_MODE 1032
|
||||
#define IDC_DISASM_MODULE 1033
|
||||
#define IDC_DISASM_HP 1034
|
||||
#define IDC_DISASM_CLASS 1035
|
||||
#define IDC_ADDRESS 1036
|
||||
#define IDC_DISASM_ADR 1037
|
||||
#define IDC_DISASM_NEXT 1038
|
||||
#define IDC_DISASM_COPY 1039
|
||||
#define IDC_DEBUG_CODE 1040
|
||||
#define IDC_STATIC_CODE 1041
|
||||
#define IDC_STATIC_REGISTERS 1042
|
||||
#define IDC_STATIC_MEMORY 1043
|
||||
#define IDC_STATIC_STACK 1044
|
||||
#define IDC_REG_A 1045
|
||||
#define IDC_REG_B 1046
|
||||
#define IDC_REG_C 1047
|
||||
#define IDC_REG_D 1048
|
||||
#define IDC_REG_R0 1049
|
||||
#define IDC_REG_R1 1050
|
||||
#define IDC_REG_R2 1051
|
||||
#define IDC_REG_R3 1052
|
||||
#define IDC_REG_R4 1053
|
||||
#define IDC_REG_D0 1054
|
||||
#define IDC_REG_D1 1055
|
||||
#define IDC_REG_P 1056
|
||||
#define IDC_REG_PC 1057
|
||||
#define IDC_REG_OUT 1058
|
||||
#define IDC_REG_IN 1059
|
||||
#define IDC_REG_ST 1060
|
||||
#define IDC_REG_CY 1061
|
||||
#define IDC_REG_MODE 1062
|
||||
#define IDC_REG_MP 1063
|
||||
#define IDC_REG_SR 1064
|
||||
#define IDC_REG_SB 1065
|
||||
#define IDC_REG_XM 1066
|
||||
#define IDC_MISC_INT 1067
|
||||
#define IDC_MISC_KEY 1068
|
||||
#define IDC_MISC_BS 1069
|
||||
#define IDC_NEWVALUE 1070
|
||||
#define IDC_ENTERADR 1071
|
||||
#define IDC_DEBUG_MEM 1072
|
||||
#define IDC_DEBUG_MEM_ADDR 1073
|
||||
#define IDC_DEBUG_MEM_COL0 1074
|
||||
#define IDC_DEBUG_MEM_COL1 1075
|
||||
#define IDC_DEBUG_MEM_COL2 1076
|
||||
#define IDC_DEBUG_MEM_COL3 1077
|
||||
#define IDC_DEBUG_MEM_COL4 1078
|
||||
#define IDC_DEBUG_MEM_COL5 1079
|
||||
#define IDC_DEBUG_MEM_COL6 1080
|
||||
#define IDC_DEBUG_MEM_COL7 1081
|
||||
#define IDC_DEBUG_MEM_TEXT 1082
|
||||
#define IDC_DEBUG_DATA_FILE 1083
|
||||
#define IDC_DEBUG_DATA_BUT 1084
|
||||
#define IDC_DEBUG_DATA_STARTADDR 1085
|
||||
#define IDC_DEBUG_DATA_ENDADDR 1086
|
||||
#define IDC_DEBUG_SET_SYMB 1087
|
||||
#define IDC_DEBUG_SET_MODEL 1088
|
||||
#define IDC_DEBUG_SET_FILE 1089
|
||||
#define IDC_DEBUG_SET_BROWSE 1090
|
||||
#define IDC_DEBUG_STACK 1091
|
||||
#define IDC_STATIC_BREAKPOINT 1092
|
||||
#define IDC_BREAKEDIT_ADD 1093
|
||||
#define IDC_BREAKEDIT_DELETE 1094
|
||||
#define IDC_BREAKEDIT_WND 1095
|
||||
#define IDC_STATIC_MMU 1096
|
||||
#define IDC_MMU_IO_A 1097
|
||||
#define IDC_MMU_NCE2_A 1098
|
||||
#define IDC_MMU_CE1_A 1099
|
||||
#define IDC_MMU_CE2_A 1100
|
||||
#define IDC_MMU_NCE3_A 1101
|
||||
#define IDC_MMU_IO_S 1102
|
||||
#define IDC_MMU_CE1_S 1103
|
||||
#define IDC_MMU_CE2_S 1104
|
||||
#define IDC_MMU_NCE2_S 1105
|
||||
#define IDC_MMU_NCE3_S 1106
|
||||
#define IDC_STATIC_MISC 1107
|
||||
#define IDC_MISC_BS_TXT 1108
|
||||
#define IDC_INSTR_TEXT 1109
|
||||
#define IDC_INSTR_CODE 1110
|
||||
#define IDC_INSTR_COPY 1111
|
||||
#define IDC_INSTR_CLEAR 1112
|
||||
#define IDC_PROFILE_LASTCYCLES 1113
|
||||
#define IDC_PROFILE_LASTTIME 1114
|
||||
#define IDC_BPCODE 1115
|
||||
#define IDC_BPRPL 1116
|
||||
#define IDC_BPACCESS 1117
|
||||
#define IDC_BPREAD 1118
|
||||
#define IDC_BPWRITE 1119
|
||||
#define IDC_FIND_DATA 1120
|
||||
#define IDC_FIND_PREV 1121
|
||||
#define IDC_FIND_NEXT 1122
|
||||
#define IDC_FIND_ASCII 1123
|
||||
#define IDC_ADDR20_24 1124
|
||||
#define IDC_ADDR25_27 1125
|
||||
#define IDC_ADDR28_29 1126
|
||||
#define IDC_ADDR30_34 1127
|
||||
#define IDC_RPLVIEW_DATA 1128
|
||||
#define IDC_MACRO_SLOW 1129
|
||||
#define IDC_MACRO_FAST 1130
|
||||
#define IDC_MACRO_SLIDER 1131
|
||||
#define IDC_MACRO_REAL 1132
|
||||
#define IDC_MACRO_MANUAL 1133
|
||||
#define IDC_SOUND_SLIDER 1134
|
||||
#define IDC_SOUND_DEVICE 1135
|
||||
#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_HELP_TOPICS 40012
|
||||
#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
|
||||
#define ID_TOOL_DEBUG 40022
|
||||
#define ID_TOOL_MACRO_RECORD 40023
|
||||
#define ID_TOOL_MACRO_PLAY 40024
|
||||
#define ID_TOOL_MACRO_STOP 40025
|
||||
#define ID_TOOL_MACRO_SETTINGS 40026
|
||||
#define ID_DEBUG_RUN 40027
|
||||
#define ID_DEBUG_RUNCURSOR 40028
|
||||
#define ID_DEBUG_STEP 40029
|
||||
#define ID_DEBUG_STEPOVER 40030
|
||||
#define ID_DEBUG_BREAK 40031
|
||||
#define ID_DEBUG_STEPOUT 40032
|
||||
#define ID_DEBUG_CANCEL 40033
|
||||
#define ID_BREAKPOINTS_SETBREAK 40034
|
||||
#define ID_BREAKPOINTS_CODEEDIT 40035
|
||||
#define ID_BREAKPOINTS_CLEARALL 40036
|
||||
#define ID_BREAKPOINTS_NOP3 40037
|
||||
#define ID_BREAKPOINTS_DOCODE 40038
|
||||
#define ID_BREAKPOINTS_RPL 40039
|
||||
#define ID_DEBUG_CODE_GOADR 40040
|
||||
#define ID_DEBUG_CODE_GOPC 40041
|
||||
#define ID_DEBUG_CODE_SETPCTOSELECT 40042
|
||||
#define ID_DEBUG_CODE_PREVPCO 40043
|
||||
#define ID_DEBUG_CODE_NEXTPCO 40044
|
||||
#define ID_DEBUG_MEM_GOADR 40045
|
||||
#define ID_DEBUG_MEM_GOPC 40046
|
||||
#define ID_DEBUG_MEM_GOD0 40047
|
||||
#define ID_DEBUG_MEM_GOD1 40048
|
||||
#define ID_DEBUG_MEM_GOSTACK 40049
|
||||
#define ID_DEBUG_MEM_FNONE 40050
|
||||
#define ID_DEBUG_MEM_FADDR 40051
|
||||
#define ID_DEBUG_MEM_FPC 40052
|
||||
#define ID_DEBUG_MEM_FD0 40053
|
||||
#define ID_DEBUG_MEM_FD1 40054
|
||||
#define ID_DEBUG_MEM_FIND 40055
|
||||
#define ID_DEBUG_MEM_MAP 40056
|
||||
#define ID_DEBUG_MEM_NCE1 40057
|
||||
#define ID_DEBUG_MEM_NCE2 40058
|
||||
#define ID_DEBUG_MEM_CE1 40059
|
||||
#define ID_DEBUG_MEM_CE2 40060
|
||||
#define ID_DEBUG_MEM_NCE3 40061
|
||||
#define ID_DEBUG_MEM_SAVE 40062
|
||||
#define ID_DEBUG_MEM_LOAD 40063
|
||||
#define ID_DEBUG_MEM_RPLVIEW 40064
|
||||
#define ID_DEBUG_STACK_PUSH 40065
|
||||
#define ID_DEBUG_STACK_POP 40066
|
||||
#define ID_DEBUG_STACK_MODIFY 40067
|
||||
#define ID_INTR_STEPOVERINT 40068
|
||||
#define ID_INFO_LASTINSTRUCTIONS 40069
|
||||
#define ID_INFO_PROFILE 40070
|
||||
#define ID_INFO_WRITEONLYREG 40071
|
||||
#define ID_FILE_MRU_FILE1 40100
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 130
|
||||
#define _APS_NEXT_COMMAND_VALUE 40072
|
||||
#define _APS_NEXT_CONTROL_VALUE 1136
|
||||
#define _APS_NEXT_SYMED_VALUE 109
|
||||
#endif
|
||||
#endif
|
459
app/src/main/cpp/RPL.C
Normal file
|
@ -0,0 +1,459 @@
|
|||
/*
|
||||
* rpl.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1995 Sebastien Carlier
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "ops.h"
|
||||
#include "io.h"
|
||||
|
||||
//| 38G | 39G | 40G | 48SX | 48GX | 49G | Name
|
||||
//#F0688 #806E9 #806E9 #7056A #806E9 #806E9 =TEMPOB
|
||||
//#F068D #806EE #806EE #7056F #806EE #806EE =TEMPTOP
|
||||
//#F0692 #806F3 #806F3 #70574 #806F3 #806F3 =RSKTOP (B)
|
||||
//#F0697 #806F8 #806F8 #70579 #806F8 #806F8 =DSKTOP (D1)
|
||||
//#F069C #806FD #806FD #7057E #806FD #806FD =EDITLINE
|
||||
//#F0DEA #80E9B #80E9B #7066E #807ED #80E9B =AVMEM (D)
|
||||
//#F0705 #8076B #8076B #705B0 #8072F #8076B =INTRPPTR (D0)
|
||||
//#F0E42 #80F02 #80F02 #706C5 #80843 #80F02 =SystemFlags
|
||||
|
||||
#define TEMPOB ((cCurrentRomType=='S')?0x7056A:0x806E9)
|
||||
#define TEMPTOP ((cCurrentRomType=='S')?0x7056F:0x806EE)
|
||||
#define RSKTOP ((cCurrentRomType=='S')?0x70574:0x806F3)
|
||||
#define DSKTOP ((cCurrentRomType=='S')?0x70579:0x806F8)
|
||||
#define EDITLINE ((cCurrentRomType=='S')?0x7057E:0x806FD)
|
||||
// CdB for HP: add apples
|
||||
#define AVMEM ((cCurrentRomType!='X' && cCurrentRomType!='2' && cCurrentRomType!='Q')?((cCurrentRomType=='S')?0x7066E:0x807ED):0x80E9B)
|
||||
#define INTRPPTR ((cCurrentRomType!='X' && cCurrentRomType!='2' && cCurrentRomType!='Q')?((cCurrentRomType=='S')?0x705B0:0x8072F):0x8076B)
|
||||
#define SYSTEMFLAGS ((cCurrentRomType!='X' && cCurrentRomType!='2' && cCurrentRomType!='Q')?((cCurrentRomType=='S')?0x706C5:0x80843):0x80F02)
|
||||
|
||||
#define DOINT 0x02614 // Precision Integer (HP49G)
|
||||
#define DOLNGREAL 0x0263A // Precision Real (HP49G)
|
||||
#define DOLNGCMP 0x02660 // Precision Complex (HP49G)
|
||||
#define DOMATRIX 0x02686 // Symbolic matrix (HP49G)
|
||||
#define DOFLASHP 0x026AC // Flash PTR (HP49G)
|
||||
#define DOAPLET 0x026D5 // Aplet (HP49G)
|
||||
#define DOMINIFONT 0x026FE // Mini Font (HP49G)
|
||||
#define DOBINT 0x02911 // System Binary
|
||||
#define DOREAL 0x02933 // Real
|
||||
#define DOEREL 0x02955 // Long Real
|
||||
#define DOCMP 0x02977 // Complex
|
||||
#define DOECMP 0x0299D // Long Complex
|
||||
#define DOCHAR 0x029BF // Character
|
||||
#define DOARRY 0x029E8 // Array
|
||||
#define DOLNKARRY 0x02A0A // Linked Array
|
||||
#define DOCSTR 0x02A2C // String
|
||||
#define DOHSTR 0x02A4E // Binary Integer
|
||||
#define DOLIST 0x02A74 // List
|
||||
#define DORRP 0x02A96 // Directory
|
||||
#define DOSYMB 0x02AB8 // Algebraic
|
||||
#define DOEXT 0x02ADA // Unit
|
||||
#define DOTAG 0x02AFC // Tagged
|
||||
#define DOGROB 0x02B1E // Graphic
|
||||
#define DOLIB 0x02B40 // Library
|
||||
#define DOBAK 0x02B62 // Backup
|
||||
#define DOEXT0 0x02B88 // Library Data
|
||||
#define DOEXT1 0x02BAA // Reserved 1, ACcess PoinTeR (HP48GX and later)
|
||||
#define DOEXT2 0x02BCC // Reserved 2, Font (HP49G)
|
||||
#define DOEXT3 0x02BEE // Reserved 3
|
||||
#define DOEXT4 0x02C10 // Reserved 4
|
||||
#define DOCOL 0x02D9D // Program
|
||||
#define DOCODE 0x02DCC // Code
|
||||
#define DOIDNT 0x02E48 // Global Name
|
||||
#define DOLAM 0x02E6D // Local Name
|
||||
#define DOROMP 0x02E92 // XLIB Name
|
||||
#define SEMI 0x0312B // ;
|
||||
|
||||
#define GARBAGECOL 0x0613E // =GARBAGECOL entry for HP48S/G and HP49G
|
||||
|
||||
// check for Metakernel version
|
||||
#define METAKERNEL Metakernel()
|
||||
|
||||
// search for "MDGKER:MK2.30" or "MDGKER:PREVIE" in port1 of a HP48GX
|
||||
static BOOL Metakernel(VOID)
|
||||
{
|
||||
BOOL bMkDetect = FALSE;
|
||||
|
||||
// card in slot1 of a HP48GX enabled
|
||||
if (cCurrentRomType=='G' && Port1 && Chipset.cards_status & PORT1_PRESENT)
|
||||
{
|
||||
// check for Metakernel string "MDGKER:"
|
||||
if (!strncmp((LPCSTR) &Port1[12],"\xD\x4\x4\x4\x7\x4\xB\x4\x5\x4\x2\x5\xA\x3",14))
|
||||
{
|
||||
bMkDetect = TRUE; // Metakernel detected
|
||||
// check for "MK"
|
||||
if (!strncmp((LPCSTR) &Port1[26],"\xD\x4\xB\x4",4))
|
||||
{
|
||||
// get version number
|
||||
WORD wVersion = ((Port1[30] * 10) + Port1[34]) * 10
|
||||
+ Port1[36];
|
||||
|
||||
// version newer then V2.30, then compatible with HP OS
|
||||
bMkDetect = (wVersion <= 230);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bMkDetect;
|
||||
}
|
||||
|
||||
static DWORD RPL_GarbageCol(VOID) // RPL variables must be in system RAM
|
||||
{
|
||||
CHIPSET OrgChipset;
|
||||
DWORD dwAVMEM;
|
||||
|
||||
// only for HP48SX, HP48GX, HP49G, HP48gII and HP49g+
|
||||
_ASSERT( cCurrentRomType == 'S' || cCurrentRomType == 'G' || cCurrentRomType == 'X'
|
||||
|| cCurrentRomType == '2' || cCurrentRomType == 'Q');
|
||||
|
||||
OrgChipset = Chipset; // save original chipset
|
||||
|
||||
// entry for =GARBAGECOL
|
||||
Chipset.P = 0; // P=0
|
||||
Chipset.mode_dec = FALSE; // hex mode
|
||||
Chipset.pc = GARBAGECOL; // =GARBAGECOL entry
|
||||
rstkpush(0xFFFFF); // return address for stopping
|
||||
|
||||
while (Chipset.pc != 0xFFFFF) // wait for stop address
|
||||
{
|
||||
EvalOpcode(FASTPTR(Chipset.pc)); // execute opcode
|
||||
}
|
||||
|
||||
dwAVMEM = Npack(Chipset.C,5); // available AVMEM
|
||||
Chipset = OrgChipset; // restore original chipset
|
||||
return dwAVMEM;
|
||||
}
|
||||
|
||||
BOOL RPL_GetSystemFlag(INT nFlag)
|
||||
{
|
||||
DWORD dwAddr;
|
||||
BYTE byMask,byFlag;
|
||||
|
||||
_ASSERT(nFlag > 0); // first flag is 1
|
||||
|
||||
// calculate memory address and bit mask
|
||||
dwAddr = SYSTEMFLAGS + (nFlag - 1) / 4;
|
||||
byMask = 1 << ((nFlag - 1) & 0x3);
|
||||
|
||||
Npeek(&byFlag,dwAddr,sizeof(byFlag));
|
||||
return (byFlag & byMask) != 0;
|
||||
}
|
||||
|
||||
DWORD RPL_SkipOb(DWORD d)
|
||||
{
|
||||
BYTE X[8];
|
||||
DWORD n, l;
|
||||
|
||||
Npeek(X,d,5);
|
||||
n = Npack(X, 5); // read prolog
|
||||
switch (n)
|
||||
{
|
||||
case DOFLASHP: l = (cCurrentRomType!='X' && cCurrentRomType!='2' && cCurrentRomType!='Q') ? 5 : 12; break; // Flash PTR (HP49G) // CdB for HP: add apples
|
||||
case DOBINT: l = 10; break; // System Binary
|
||||
case DOREAL: l = 21; break; // Real
|
||||
case DOEREL: l = 26; break; // Long Real
|
||||
case DOCMP: l = 37; break; // Complex
|
||||
case DOECMP: l = 47; break; // Long Complex
|
||||
case DOCHAR: l = 7; break; // Character
|
||||
case DOROMP: l = 11; break; // XLIB Name
|
||||
case DOMATRIX: // Symbolic matrix (HP49G)
|
||||
if (cCurrentRomType!='X' && cCurrentRomType!='2' && cCurrentRomType!='Q') // CdB for HP: add apples
|
||||
{
|
||||
l = 5;
|
||||
break;
|
||||
}
|
||||
case DOLIST: // List
|
||||
case DOSYMB: // Algebraic
|
||||
case DOEXT: // Unit
|
||||
case DOCOL: // Program
|
||||
n=d+5;
|
||||
do
|
||||
{
|
||||
d=n; n=RPL_SkipOb(d);
|
||||
} while (d!=n);
|
||||
return n+5;
|
||||
case SEMI: return d; // SEMI
|
||||
case DOIDNT: // Global Name
|
||||
case DOLAM: // Local Name
|
||||
case DOTAG: // Tagged
|
||||
Npeek(X,d+5,2); n = 7 + Npack(X,2)*2;
|
||||
return RPL_SkipOb(d+n);
|
||||
case DORRP: // Directory
|
||||
d+=8;
|
||||
n = Read5(d);
|
||||
if (n==0)
|
||||
{
|
||||
return d+5;
|
||||
}
|
||||
else
|
||||
{
|
||||
d+=n;
|
||||
Npeek(X,d,2);
|
||||
n = Npack(X,2)*2 + 4;
|
||||
return RPL_SkipOb(d+n);
|
||||
}
|
||||
case DOINT: // Precision Integer (HP49G)
|
||||
case DOAPLET: // Aplet (HP49G)
|
||||
case DOMINIFONT: // Mini Font (HP49G)
|
||||
if (cCurrentRomType!='X' && cCurrentRomType!='2' && cCurrentRomType!='Q') // CdB for HP: add apples
|
||||
{
|
||||
l = 5;
|
||||
break;
|
||||
}
|
||||
case DOARRY: // Array
|
||||
case DOLNKARRY: // Linked Array
|
||||
case DOCSTR: // String
|
||||
case DOHSTR: // Binary Integer
|
||||
case DOGROB: // Graphic
|
||||
case DOLIB: // Library
|
||||
case DOBAK: // Backup
|
||||
case DOEXT0: // Library Data
|
||||
case DOEXT1: // Reserved 1
|
||||
if (n == DOEXT1 && cCurrentRomType != 'S')
|
||||
{
|
||||
// on HP48G series and later interpreted as DOACPTR
|
||||
l = 15; break; // ACcess PoinTeR
|
||||
break;
|
||||
}
|
||||
case DOEXT2: // Reserved 2, Font (HP49G)
|
||||
case DOEXT3: // Reserved 3
|
||||
case DOEXT4: // Reserved 4
|
||||
case DOCODE: // Code
|
||||
l = 5+Read5(d+5);
|
||||
break;
|
||||
case DOLNGREAL: // Precision Real (HP49G)
|
||||
l = 5;
|
||||
if (cCurrentRomType=='X')
|
||||
{
|
||||
l += Read5(d+l);
|
||||
l += Read5(d+l);
|
||||
}
|
||||
break;
|
||||
case DOLNGCMP: // Precision Complex (HP49G)
|
||||
l = 5;
|
||||
if (cCurrentRomType=='X')
|
||||
{
|
||||
l += Read5(d+l);
|
||||
l += Read5(d+l);
|
||||
l += Read5(d+l);
|
||||
l += Read5(d+l);
|
||||
}
|
||||
break;
|
||||
default: return d+5;
|
||||
}
|
||||
return d+l;
|
||||
}
|
||||
|
||||
DWORD RPL_ObjectSize(BYTE *o,DWORD s)
|
||||
{
|
||||
#define SERIES49 (cCurrentRomType=='X' || cCurrentRomType=='2' || cCurrentRomType=='Q')
|
||||
|
||||
DWORD n, l = 0;
|
||||
|
||||
if (s < 5) return BAD_OB; // size too small for prolog
|
||||
n = Npack(o,5); // read prolog
|
||||
switch (n)
|
||||
{
|
||||
case DOFLASHP: l = (SERIES49) ? 12 : 5; break; // Flash PTR (HP49G)
|
||||
case DOBINT: l = 10; break; // System Binary
|
||||
case DOREAL: l = 21; break; // Real
|
||||
case DOEREL: l = 26; break; // Long Real
|
||||
case DOCMP: l = 37; break; // Complex
|
||||
case DOECMP: l = 47; break; // Long Complex
|
||||
case DOCHAR: l = 7; break; // Character
|
||||
case DOROMP: l = 11; break; // XLIB Name
|
||||
case DOMATRIX: // Symbolic matrix (HP49G)
|
||||
if (!SERIES49)
|
||||
{
|
||||
l = 5;
|
||||
break;
|
||||
}
|
||||
case DOLIST: // List
|
||||
case DOSYMB: // Algebraic
|
||||
case DOEXT: // Unit
|
||||
case DOCOL: // Program
|
||||
n = 5; // prolog length
|
||||
do
|
||||
{
|
||||
l += n;
|
||||
if (l > s) return BAD_OB; // prevent negative size argument
|
||||
n = RPL_ObjectSize(o+l,s-l); // get new object
|
||||
if (n == BAD_OB) return BAD_OB; // buffer overflow
|
||||
}
|
||||
while (n);
|
||||
l += 5;
|
||||
break;
|
||||
case SEMI: l = 0; break; // SEMI
|
||||
case DOIDNT: // Global Name
|
||||
case DOLAM: // Local Name
|
||||
case DOTAG: // Tagged
|
||||
if (s < 5 + 2) return BAD_OB;
|
||||
l = 7 + Npack(o+5,2) * 2; // prolog + name length
|
||||
if (l > s) return BAD_OB; // prevent negative size argument
|
||||
n = RPL_ObjectSize(o+l,s-l); // get new object
|
||||
if (n == BAD_OB) return BAD_OB; // buffer overflow
|
||||
l += n;
|
||||
break;
|
||||
case DORRP: // Directory
|
||||
if (s < 8 + 5) return BAD_OB;
|
||||
n = Npack(o+8,5);
|
||||
if (n == 0) // empty dir
|
||||
{
|
||||
l = 13;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = 8 + n;
|
||||
if (s < l + 2) return BAD_OB;
|
||||
n = Npack(o+l,2) * 2 + 4;
|
||||
l += n;
|
||||
if (l > s) return BAD_OB; // prevent negative size argument
|
||||
n = RPL_ObjectSize(o+l,s-l); // next rrp
|
||||
if (n == BAD_OB) return BAD_OB; // buffer overflow
|
||||
l += n;
|
||||
}
|
||||
break;
|
||||
case DOINT: // Precision Integer (HP49G)
|
||||
case DOAPLET: // Aplet (HP49G)
|
||||
case DOMINIFONT: // Mini Font (HP49G)
|
||||
if (!SERIES49)
|
||||
{
|
||||
l = 5;
|
||||
break;
|
||||
}
|
||||
case DOARRY: // Array
|
||||
case DOLNKARRY: // Linked Array
|
||||
case DOCSTR: // String
|
||||
case DOHSTR: // Binary Integer
|
||||
case DOGROB: // Graphic
|
||||
case DOLIB: // Library
|
||||
case DOBAK: // Backup
|
||||
case DOEXT0: // Library Data
|
||||
case DOEXT1: // Reserved 1
|
||||
if (n == DOEXT1 && cCurrentRomType != 'S')
|
||||
{
|
||||
// on HP48G series and later interpreted as DOACPTR
|
||||
l = 15; break; // ACcess PoinTeR
|
||||
break;
|
||||
}
|
||||
case DOEXT2: // Reserved 2, Font (HP49G)
|
||||
case DOEXT3: // Reserved 3
|
||||
case DOEXT4: // Reserved 4
|
||||
case DOCODE: // Code
|
||||
if (s < 5 + 5) return BAD_OB;
|
||||
l = 5 + Npack(o+5,5);
|
||||
break;
|
||||
case DOLNGREAL: // Precision Real (HP49G)
|
||||
l = 5;
|
||||
if (SERIES49)
|
||||
{
|
||||
if (s < l + 5) return BAD_OB;
|
||||
l += Npack(o+l,5);
|
||||
if (s < l + 5) return BAD_OB;
|
||||
l += Npack(o+l,5);
|
||||
}
|
||||
break;
|
||||
case DOLNGCMP: // Precision Complex (HP49G)
|
||||
l = 5;
|
||||
if (SERIES49)
|
||||
{
|
||||
if (s < l + 5) return BAD_OB;
|
||||
l += Npack(o+l,5);
|
||||
if (s < l + 5) return BAD_OB;
|
||||
l += Npack(o+l,5);
|
||||
if (s < l + 5) return BAD_OB;
|
||||
l += Npack(o+l,5);
|
||||
if (s < l + 5) return BAD_OB;
|
||||
l += Npack(o+l,5);
|
||||
}
|
||||
break;
|
||||
default: l = 5;
|
||||
}
|
||||
return (s >= l) ? l : BAD_OB;
|
||||
|
||||
#undef SERIES49
|
||||
}
|
||||
|
||||
DWORD RPL_CreateTemp(DWORD l,BOOL bGarbageCol)
|
||||
{
|
||||
DWORD a, b, c;
|
||||
BYTE *p;
|
||||
|
||||
l += 6; // memory for link field (5) + marker (1) and end
|
||||
b = Read5(RSKTOP); // tail address of rtn stack
|
||||
c = Read5(DSKTOP); // top of data stack
|
||||
if ((b+l)>c && bGarbageCol) // there's not enough memory to move DSKTOP
|
||||
{
|
||||
RPL_GarbageCol(); // do a garbage collection
|
||||
b = Read5(RSKTOP); // reload tail address of rtn stack
|
||||
c = Read5(DSKTOP); // reload top of data stack
|
||||
}
|
||||
if ((b+l)>c) return 0; // check if now there's enough memory to move DSKTOP
|
||||
a = Read5(TEMPTOP); // tail address of top object
|
||||
Write5(TEMPTOP, a+l); // adjust new end of top object
|
||||
Write5(RSKTOP, b+l); // adjust new end of rtn stack
|
||||
Write5(AVMEM, (c-b-l)/5); // calculate free memory (*5 nibbles)
|
||||
p = (LPBYTE) malloc(b-a); // move down rtn stack
|
||||
Npeek(p,a,b-a);
|
||||
Nwrite(p,a+l,b-a);
|
||||
free(p);
|
||||
Write5(a+l-5,l); // set object length field
|
||||
return (a+1); // return base address of new object
|
||||
}
|
||||
|
||||
UINT RPL_Depth(VOID)
|
||||
{
|
||||
return (Read5(EDITLINE) - Read5(DSKTOP)) / 5 - 1;
|
||||
}
|
||||
|
||||
DWORD RPL_Pick(UINT l)
|
||||
{
|
||||
DWORD stkp;
|
||||
|
||||
_ASSERT(l > 0); // first stack element is one
|
||||
if (l == 0) return 0;
|
||||
if (METAKERNEL) ++l; // Metakernel support
|
||||
if (RPL_Depth() < l) return 0; // not enough elements on stack
|
||||
stkp = Read5(DSKTOP) + (l-1)*5;
|
||||
return Read5(stkp); // return object address
|
||||
}
|
||||
|
||||
VOID RPL_Replace(DWORD n)
|
||||
{
|
||||
DWORD stkp;
|
||||
|
||||
stkp = Read5(DSKTOP);
|
||||
if (METAKERNEL) stkp+=5; // Metakernel support
|
||||
Write5(stkp,n);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID RPL_Push(UINT l,DWORD n)
|
||||
{
|
||||
UINT i;
|
||||
DWORD stkp, avmem;
|
||||
|
||||
if (l > RPL_Depth() + 1) return; // invalid stack level
|
||||
|
||||
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
|
||||
|
||||
if (METAKERNEL) ++l; // Metakernel, save MK object on stack level 1
|
||||
|
||||
stkp = Read5(DSKTOP) - 5; // get pointer of new stack level 1
|
||||
Write5(DSKTOP,stkp); // save it
|
||||
|
||||
for (i = 1; i < l; ++i) // move down stack level entries before insert pos
|
||||
{
|
||||
Write5(stkp,Read5(stkp+5)); // move down stack level entry
|
||||
stkp += 5; // next stack entry
|
||||
}
|
||||
|
||||
Write5(stkp,n); // save pointer of new object on given stack level
|
||||
return;
|
||||
}
|
388
app/src/main/cpp/SERIAL.C
Normal file
|
@ -0,0 +1,388 @@
|
|||
/*
|
||||
* Serial.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1998 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h"
|
||||
|
||||
#define INTERRUPT ((void)(Chipset.SoftInt=TRUE,bInterrupt=TRUE))
|
||||
|
||||
// state of USRQ
|
||||
#define NINT2ERBZ ((Chipset.IORam[IOC] & (SON | ERBZ)) == (SON | ERBZ) && (Chipset.IORam[RCS] & RBZ) != 0)
|
||||
#define NINT2ERBF ((Chipset.IORam[IOC] & (SON | ERBF)) == (SON | ERBF) && (Chipset.IORam[RCS] & RBF) != 0)
|
||||
#define NINT2ETBE ((Chipset.IORam[IOC] & (SON | ETBE)) == (SON | ETBE) && (Chipset.IORam[TCS] & TBF) == 0)
|
||||
|
||||
#define NINT2USRQ (NINT2ERBZ || NINT2ERBF || NINT2ETBE)
|
||||
|
||||
static HANDLE hComm = NULL;
|
||||
|
||||
static HANDLE hCThreadTxd;
|
||||
static HANDLE hCThreadEv;
|
||||
|
||||
static HANDLE hEventTxd;
|
||||
static BOOL bWriting;
|
||||
static BYTE tbr;
|
||||
|
||||
static BOOL bReading;
|
||||
static BYTE cBuffer[32];
|
||||
static WORD nRp;
|
||||
static DWORD dwBytesRead;
|
||||
|
||||
static DWORD WINAPI TransmitThread(LPVOID pParam)
|
||||
{
|
||||
OVERLAPPED osWr = { 0 };
|
||||
|
||||
osWr.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
while (bWriting)
|
||||
{
|
||||
WaitForSingleObject(hEventTxd,INFINITE);
|
||||
if (bWriting)
|
||||
{
|
||||
DWORD dwWritten;
|
||||
if (!WriteFile(hComm,(LPCVOID) &tbr,1,&dwWritten,&osWr))
|
||||
if (GetLastError() == ERROR_IO_PENDING)
|
||||
GetOverlappedResult(hComm,&osWr,&dwWritten,TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(osWr.hEvent); // close write event handle
|
||||
return 0;
|
||||
UNREFERENCED_PARAMETER(pParam);
|
||||
}
|
||||
|
||||
static DWORD WINAPI EventThread(LPVOID pParam)
|
||||
{
|
||||
DWORD dwEvent;
|
||||
|
||||
bReading = TRUE; // flag for SerialThread started
|
||||
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)
|
||||
{
|
||||
Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode
|
||||
SetEvent(hEventShutdn); // wake up emulation thread
|
||||
}
|
||||
}
|
||||
if (dwEvent & EV_TXEMPTY) // signal transmit buffer empty
|
||||
{
|
||||
IOBit(TCS,TBZ,FALSE); // clear transmitter busy bit
|
||||
CommTransmit(); // check for new char to transmit
|
||||
}
|
||||
if (dwEvent & EV_ERR) // signal error received
|
||||
{
|
||||
DWORD dwError;
|
||||
|
||||
ClearCommError(hComm,&dwError,NULL);
|
||||
if (dwError & (CE_FRAME | CE_OVERRUN | CE_BREAK))
|
||||
IOBit(RCS,RER,TRUE); // receiver error
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
UNREFERENCED_PARAMETER(pParam);
|
||||
}
|
||||
|
||||
BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort)
|
||||
{
|
||||
COMMTIMEOUTS CommTimeouts = { MAXDWORD, 0L, 0L, 0L, 0L };
|
||||
|
||||
LPCTSTR strPort = (Chipset.IORam[IR_CTRL] & EIRU) ? strIrPort : strWirePort;
|
||||
|
||||
_ASSERT(Chipset.IORam[IOC] & SON); // UART on
|
||||
CommClose(); // close port if already open
|
||||
|
||||
if (lstrcmp(strPort, _T(NO_SERIAL))) // port defined
|
||||
{
|
||||
TCHAR szDevice[256] = _T("\\\\.\\");
|
||||
|
||||
// check if device buffer is big enough
|
||||
_ASSERT(lstrlen(szDevice) + lstrlen(strPort) < (INT) ARRAYSIZEOF(szDevice));
|
||||
if (lstrlen(szDevice) + lstrlen(strPort) >= (INT) ARRAYSIZEOF(szDevice))
|
||||
return hComm != NULL;
|
||||
|
||||
_tcscat(szDevice,strPort); // device name
|
||||
hComm = CreateFile(szDevice,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
|
||||
if (hComm != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD dwThreadId;
|
||||
|
||||
nRp = 0; // reset receiver state
|
||||
dwBytesRead = 0L;
|
||||
|
||||
SetCommTimeouts(hComm,&CommTimeouts);
|
||||
CommSetBaud();
|
||||
|
||||
CommTxBRK(); // update BRK condition
|
||||
|
||||
// event to transmit character
|
||||
hEventTxd = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||||
|
||||
// create char transmit handler
|
||||
bWriting = TRUE;
|
||||
hCThreadTxd = CreateThread(NULL,0,&TransmitThread,NULL,CREATE_SUSPENDED,&dwThreadId);
|
||||
_ASSERT(hCThreadTxd);
|
||||
SetThreadPriority(hCThreadTxd,THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
ResumeThread(hCThreadTxd); // start thread
|
||||
|
||||
// create Comm event handler
|
||||
bReading = FALSE;
|
||||
SetCommMask(hComm,EV_RXCHAR | EV_TXEMPTY | EV_ERR); // event on RX, TX, error
|
||||
hCThreadEv = CreateThread(NULL,0,&EventThread,NULL,CREATE_SUSPENDED,&dwThreadId);
|
||||
_ASSERT(hCThreadEv);
|
||||
SetThreadPriority(hCThreadEv,THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
ResumeThread(hCThreadEv); // start thread
|
||||
while (!bReading) Sleep(0); // wait for SerialThread started
|
||||
}
|
||||
else
|
||||
hComm = NULL;
|
||||
}
|
||||
|
||||
#if defined DEBUG_SERIAL
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("COM port %s.\n"),hComm ? _T("opened"): _T("open error"));
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
return hComm != NULL;
|
||||
}
|
||||
|
||||
VOID CommClose(VOID)
|
||||
{
|
||||
if (hComm != NULL) // port open
|
||||
{
|
||||
// workaround to fix problems with some Kermit server programs
|
||||
// reason: on one hand we have the character transmitting time base on the
|
||||
// selected baudrate, on the other hand the time between sending the last
|
||||
// character and closing the port. The last time is much longer on the real
|
||||
// calculator than on the emulator running at full speed, therefore the
|
||||
// slow down time on the emulator
|
||||
Sleep(25); // slow down time
|
||||
|
||||
bReading = FALSE; // kill event thread
|
||||
SetCommMask(hComm,0L); // clear all events and force WaitCommEvent to return
|
||||
WaitForSingleObject(hCThreadEv,INFINITE);
|
||||
CloseHandle(hCThreadEv);
|
||||
|
||||
bWriting = FALSE; // kill write thread
|
||||
SetEvent(hEventTxd); // continue write thread
|
||||
WaitForSingleObject(hCThreadTxd,INFINITE);
|
||||
CloseHandle(hCThreadTxd);
|
||||
|
||||
CloseHandle(hEventTxd); // close Txd event
|
||||
CloseHandle(hComm); // close port
|
||||
hComm = NULL;
|
||||
#if defined DEBUG_SERIAL
|
||||
OutputDebugString(_T("COM port closed.\n"));
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID CommSetBaud(VOID)
|
||||
{
|
||||
if (hComm != NULL)
|
||||
{
|
||||
const DWORD dwBaudrates[] = { 1200, 1920, 2400, 3840, 4800, 7680, 9600, 15360,
|
||||
14400, 19200, 38400, 57600, 115200, 115200, 115200, 115200 };
|
||||
|
||||
DCB dcb;
|
||||
UINT uBaudIndex;
|
||||
|
||||
uBaudIndex = isModelApple(cCurrentRomType)
|
||||
? Chipset.IORam[BAUD]
|
||||
: Chipset.IORam[BAUD] & 0x7;
|
||||
|
||||
ZeroMemory(&dcb,sizeof(dcb));
|
||||
dcb.DCBlength = sizeof(dcb);
|
||||
dcb.BaudRate = dwBaudrates[uBaudIndex];
|
||||
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 = TWOSTOPBITS;
|
||||
|
||||
#if defined DEBUG_SERIAL
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
wsprintf(buffer,_T("CommsetBaud: %ld\n"),dcb.BaudRate);
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
SetCommState(hComm,&dcb);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL UpdateUSRQ(VOID) // USRQ handling
|
||||
{
|
||||
BOOL bUSRQ = NINT2USRQ;
|
||||
IOBit(SRQ1,USRQ,bUSRQ); // update USRQ bit
|
||||
return bUSRQ;
|
||||
}
|
||||
|
||||
VOID CommTxBRK(VOID)
|
||||
{
|
||||
if (Chipset.IORam[TCS] & BRK) // BRK condition
|
||||
{
|
||||
if (hComm != NULL) // com port open
|
||||
{
|
||||
// abort data transfer
|
||||
PurgeComm(hComm,PURGE_TXABORT | PURGE_TXCLEAR);
|
||||
SetCommBreak(hComm); // set into BRK state
|
||||
}
|
||||
|
||||
// TBF and TBZ bits of TCS are undefined
|
||||
|
||||
if (Chipset.IORam[TCS] & LPB) // is loopback bit set
|
||||
{
|
||||
dwBytesRead = nRp = 0; // clear receive buffer
|
||||
cBuffer[dwBytesRead++] = 0; // save character in receive buffer
|
||||
|
||||
CommReceive(); // receive available byte
|
||||
IOBit(RCS,RER,TRUE); // receiver error (no stop bit)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hComm != NULL) // com port open
|
||||
{
|
||||
ClearCommBreak(hComm); // clear BRK state
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID CommTransmit(VOID)
|
||||
{
|
||||
BOOL bTxChar = FALSE;
|
||||
|
||||
EnterCriticalSection(&csTxdLock);
|
||||
if ( (Chipset.IORam[TCS] & TBZ) == 0 // transmitter not busy
|
||||
&& (Chipset.IORam[TCS] & TBF) != 0) // transmit buffer full
|
||||
{
|
||||
tbr = (Chipset.IORam[TBR_MSB] << 4) | Chipset.IORam[TBR_LSB];
|
||||
|
||||
IOBit(TCS,TBF,FALSE); // clear transmit buffer full bit
|
||||
IOBit(TCS,TBZ,TRUE); // set transmitter busy bit
|
||||
|
||||
bTxChar = TRUE;
|
||||
}
|
||||
LeaveCriticalSection(&csTxdLock);
|
||||
|
||||
if (bTxChar) // character to transmit
|
||||
{
|
||||
#if defined DEBUG_SERIAL
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
if (isprint(tbr))
|
||||
wsprintf(buffer,_T("-> '%c'\n"),tbr);
|
||||
else
|
||||
wsprintf(buffer,_T("-> %02X\n"),tbr);
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Chipset.IORam[TCS] & LPB) // is loopback bit set
|
||||
{
|
||||
if (dwBytesRead == 0) nRp = 0; // no character received, reset read pointer
|
||||
cBuffer[nRp+dwBytesRead] = tbr; // save character in receive buffer
|
||||
++dwBytesRead;
|
||||
|
||||
CommReceive(); // receive available byte
|
||||
}
|
||||
|
||||
if (hComm != NULL) // com port open
|
||||
{
|
||||
SetEvent(hEventTxd); // write TBR byte
|
||||
}
|
||||
else
|
||||
{
|
||||
IOBit(TCS,TBZ,FALSE); // clear transmitter busy bit
|
||||
}
|
||||
}
|
||||
if (UpdateUSRQ()) // update USRQ bit
|
||||
INTERRUPT;
|
||||
return;
|
||||
}
|
||||
|
||||
VOID CommReceive(VOID)
|
||||
{
|
||||
OVERLAPPED os = { 0 };
|
||||
|
||||
if (!(Chipset.IORam[IOC] & SON)) // UART off
|
||||
{
|
||||
dwBytesRead = 0L; // no bytes received
|
||||
return;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&csRecvLock);
|
||||
do
|
||||
{
|
||||
if (Chipset.IORam[RCS] & RBF) // receive buffer full
|
||||
break;
|
||||
|
||||
// reject reading if com port is closed and not whole operation
|
||||
if (hComm && dwBytesRead == 0L) // com port open and buffer empty
|
||||
{
|
||||
if (ReadFile(hComm,&cBuffer,sizeof(cBuffer),&dwBytesRead,&os) == FALSE)
|
||||
dwBytesRead = 0L;
|
||||
else // bytes received
|
||||
nRp = 0; // reset read pointer
|
||||
}
|
||||
|
||||
if (dwBytesRead == 0L) // receive buffer empty
|
||||
break;
|
||||
|
||||
#if defined DEBUG_SERIAL
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
if (isprint(cBuffer[nRp]))
|
||||
wsprintf(buffer,_T("<- '%c'\n"),cBuffer[nRp]);
|
||||
else
|
||||
wsprintf(buffer,_T("<- %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 (UpdateUSRQ()) // update USRQ bit
|
||||
INTERRUPT;
|
||||
}
|
||||
while (FALSE);
|
||||
LeaveCriticalSection(&csRecvLock);
|
||||
return;
|
||||
}
|
313
app/src/main/cpp/SETTINGS.C
Normal file
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* settings.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2000 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "i28f160.h"
|
||||
|
||||
// #define REGISTRY // use registry instead of *.ini file
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Low level subroutines
|
||||
//#
|
||||
//################
|
||||
|
||||
#if !defined REGISTRY
|
||||
|
||||
// INI-file handling
|
||||
|
||||
#if !defined EMU48_INI
|
||||
#define EMU48_INI "Emu48.ini"
|
||||
#endif
|
||||
|
||||
#define ReadString(sec,key,dv,v,sv) GetPrivateProfileString(sec,key,dv,v,sv,_T(EMU48_INI))
|
||||
#define ReadInt(sec,key,dv) GetPrivateProfileInt(sec,key,dv,_T(EMU48_INI));
|
||||
#define WriteString(sec,key,v) WritePrivateProfileString(sec,key,v,_T(EMU48_INI))
|
||||
#define WriteInt(sec,key,v) WritePrivateProfileInt(sec,key,v,_T(EMU48_INI))
|
||||
#define DelKey(sec,key) WritePrivateProfileString(sec,key,NULL,_T(EMU48_INI))
|
||||
|
||||
static BOOL WritePrivateProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue, LPCTSTR lpszFilename)
|
||||
{
|
||||
TCHAR s[16];
|
||||
wsprintf(s,_T("%i"),nValue);
|
||||
return WritePrivateProfileString(lpszSection, lpszEntry, s, lpszFilename);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// registry handling
|
||||
|
||||
#if !defined REGISTRYKEY
|
||||
#define REGISTRYKEY "Software\\Emu48"
|
||||
#endif
|
||||
|
||||
#define ReadString(sec,key,dv,v,sv) GetRegistryString(sec,key,dv,v,sv)
|
||||
#define ReadInt(sec,key,dv) GetRegistryInt(sec,key,dv)
|
||||
#define WriteString(sec,key,v) WriteReg(sec,key,REG_SZ,(BYTE *) v,(lstrlen(v)+1) * sizeof(*v))
|
||||
#define WriteInt(sec,key,v) WriteReg(sec,key,REG_DWORD,(BYTE *) &v,sizeof(int))
|
||||
#define DelKey(sec,key) DelReg(sec,key)
|
||||
|
||||
static VOID ReadReg(LPCTSTR lpSubKey, LPCTSTR lpValueName, LPBYTE lpData, DWORD *pdwSize)
|
||||
{
|
||||
TCHAR lpKey[256] = _T(REGISTRYKEY) _T("\\");
|
||||
|
||||
DWORD retCode,dwType;
|
||||
HKEY hKey;
|
||||
|
||||
lstrcat(lpKey, lpSubKey); // full registry key
|
||||
|
||||
retCode = RegOpenKeyEx(HKEY_CURRENT_USER,
|
||||
lpKey,
|
||||
0,
|
||||
KEY_QUERY_VALUE,
|
||||
&hKey);
|
||||
if (retCode == ERROR_SUCCESS)
|
||||
{
|
||||
retCode = RegQueryValueEx(hKey,lpValueName,NULL,&dwType,lpData,pdwSize);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
if (retCode != ERROR_SUCCESS) // registry entry not found
|
||||
*pdwSize = 0; // return zero size
|
||||
return;
|
||||
}
|
||||
|
||||
static BOOL WriteReg(LPCTSTR lpSubKey, LPCTSTR lpValueName, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
|
||||
{
|
||||
TCHAR lpKey[256] = _T(REGISTRYKEY) _T("\\");
|
||||
|
||||
DWORD retCode;
|
||||
HKEY hKey;
|
||||
DWORD dwDisposition;
|
||||
|
||||
lstrcat(lpKey, lpSubKey); // full registry key
|
||||
|
||||
retCode = RegCreateKeyEx(HKEY_CURRENT_USER,
|
||||
lpKey,
|
||||
0,_T(""),
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_WRITE,
|
||||
NULL,
|
||||
&hKey,
|
||||
&dwDisposition);
|
||||
_ASSERT(retCode == ERROR_SUCCESS);
|
||||
|
||||
RegSetValueEx(hKey,lpValueName,0,dwType,lpData,cbData);
|
||||
RegCloseKey(hKey);
|
||||
return retCode == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static BOOL DelReg(LPCTSTR lpSubKey, LPCTSTR lpValueName)
|
||||
{
|
||||
TCHAR lpKey[256] = _T(REGISTRYKEY) _T("\\");
|
||||
|
||||
DWORD retCode;
|
||||
HKEY hKey;
|
||||
|
||||
lstrcat(lpKey, lpSubKey); // full registry key
|
||||
|
||||
retCode = RegOpenKeyEx(HKEY_CURRENT_USER,
|
||||
lpKey,
|
||||
0,
|
||||
KEY_SET_VALUE,
|
||||
&hKey);
|
||||
if (retCode == ERROR_SUCCESS)
|
||||
{
|
||||
retCode = RegDeleteValue(hKey,lpValueName);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
return retCode == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static DWORD GetRegistryString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpDefault, LPTSTR lpData, DWORD dwSize)
|
||||
{
|
||||
// buffer size in bytes
|
||||
DWORD dwBufSize = dwSize * sizeof(*lpData);
|
||||
|
||||
ReadReg(lpszSection,lpszEntry,(LPBYTE) lpData,&dwBufSize);
|
||||
if (dwBufSize == 0)
|
||||
{
|
||||
lstrcpyn(lpData,lpDefault,dwSize);
|
||||
dwSize = lstrlen(lpData);
|
||||
}
|
||||
else
|
||||
{
|
||||
dwSize = (dwBufSize / sizeof(*lpData)) - 1;
|
||||
}
|
||||
return dwSize;
|
||||
}
|
||||
|
||||
static UINT GetRegistryInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, INT nDefault)
|
||||
{
|
||||
UINT nValue;
|
||||
DWORD dwSize = sizeof(nValue);
|
||||
|
||||
ReadReg(lpszSection,lpszEntry,(LPBYTE) &nValue,&dwSize);
|
||||
return dwSize ? nValue : nDefault;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Public functions
|
||||
//#
|
||||
//################
|
||||
|
||||
VOID ReadSettings(VOID)
|
||||
{
|
||||
// Files
|
||||
ReadString(_T("Files"),_T("Emu48Directory"),szCurrentDirectory,szEmuDirectory,ARRAYSIZEOF(szEmuDirectory));
|
||||
ReadString(_T("Files"),_T("RomDirectory"),_T(""),szRomDirectory,ARRAYSIZEOF(szRomDirectory));
|
||||
bAutoSave = ReadInt(_T("Files"),_T("AutoSave"),bAutoSave);
|
||||
bAutoSaveOnExit = ReadInt(_T("Files"),_T("AutoSaveOnExit"),bAutoSaveOnExit);
|
||||
bSaveDefConfirm = ReadInt(_T("Files"),_T("SaveDefaultConfirm"),bSaveDefConfirm);
|
||||
bStartupBackup = ReadInt(_T("Files"),_T("StartupBackup"),bStartupBackup);
|
||||
bLoadObjectWarning = ReadInt(_T("Files"),_T("LoadObjectWarning"),bLoadObjectWarning);
|
||||
// Port2
|
||||
bPort2IsShared = ReadInt(_T("Port2"),_T("IsShared"),bPort2IsShared);
|
||||
ReadString(_T("Port2"),_T("Filename"),_T("SHARED.BIN"),szPort2Filename,ARRAYSIZEOF(szPort2Filename));
|
||||
// KML
|
||||
bAlwaysDisplayLog = ReadInt(_T("KML"),_T("AlwaysDisplayLog"),bAlwaysDisplayLog);
|
||||
// Debugger
|
||||
wInstrSize = ReadInt(_T("Debugger"),_T("LastInstrBufSize"),wInstrSize);
|
||||
// Disassembler
|
||||
disassembler_mode = ReadInt(_T("Disassembler"),_T("Mnemonics"),disassembler_mode);
|
||||
disassembler_symb = ReadInt(_T("Disassembler"),_T("Symbolic"),disassembler_symb);
|
||||
// Emulator
|
||||
bShowTitle = ReadInt(_T("Emulator"),_T("ShowTitle"),bShowTitle);
|
||||
bShowMenu = ReadInt(_T("Emulator"),_T("ShowMenu"),bShowMenu);
|
||||
bAlwaysOnTop = ReadInt(_T("Emulator"),_T("AlwaysOnTop"),bAlwaysOnTop);
|
||||
bActFollowsMouse = ReadInt(_T("Emulator"),_T("ActivationFollowsMouse"),bActFollowsMouse);
|
||||
bClientWinMove = ReadInt(_T("Emulator"),_T("ClientWinMove"),bClientWinMove);
|
||||
bSingleInstance = ReadInt(_T("Emulator"),_T("SingleInstance"),bSingleInstance);
|
||||
bRealSpeed = ReadInt(_T("Emulator"),_T("RealSpeed"),bRealSpeed);
|
||||
dwSXCycles = ReadInt(_T("Emulator"),_T("SXCycles"),dwSXCycles);
|
||||
dwGXCycles = ReadInt(_T("Emulator"),_T("GXCycles"),dwGXCycles);
|
||||
dwGPCycles = ReadInt(_T("Emulator"),_T("GPCycles"),dwGPCycles); // CdB for HP: add apples
|
||||
dwG2Cycles = ReadInt(_T("Emulator"),_T("G2Cycles"),dwG2Cycles); // CdB for HP: add apples
|
||||
dwKeyMinDelay = ReadInt(_T("Emulator"),_T("KeyMinDelay"),dwKeyMinDelay);
|
||||
dwWakeupDelay = ReadInt(_T("Emulator"),_T("WakeupDelay"),dwWakeupDelay);
|
||||
bGrayscale = ReadInt(_T("Emulator"),_T("Grayscale"),bGrayscale);
|
||||
uWaveDevId = ReadInt(_T("Emulator"),_T("WaveDeviceId"),uWaveDevId);
|
||||
dwWaveVol = ReadInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol);
|
||||
dwWaveTime = ReadInt(_T("Emulator"),_T("WaveTime"),dwWaveTime);
|
||||
// LowBat
|
||||
bLowBatDisable = ReadInt(_T("LowBat"),_T("Disable"),bLowBatDisable);
|
||||
// Macro
|
||||
bMacroRealSpeed = ReadInt(_T("Macro"),_T("RealSpeed"),bMacroRealSpeed);
|
||||
nMacroTimeout = ReadInt(_T("Macro"),_T("ReplayTimeout"),nMacroTimeout);
|
||||
dwMacroMinDelay = ReadInt(_T("Macro"),_T("KeyMinDelay"),dwMacroMinDelay);
|
||||
// IrPrinter
|
||||
ReadString(_T("IrPrinter"),_T("Address"),szUdpServer,szUdpServer,ARRAYSIZEOF(szUdpServer));
|
||||
wUdpPort = ReadInt(_T("IrPrinter"),_T("Port"),wUdpPort);
|
||||
// Serial
|
||||
ReadString(_T("Serial"),_T("Wire"),_T(NO_SERIAL),szSerialWire,ARRAYSIZEOF(szSerialWire));
|
||||
ReadString(_T("Serial"),_T("Ir"),_T(NO_SERIAL),szSerialIr,ARRAYSIZEOF(szSerialIr));
|
||||
// ROM
|
||||
bRomWriteable = ReadInt(_T("ROM"),_T("Writeable"),bRomWriteable);
|
||||
bWP = ReadInt(_T("ROM"),_T("WP#"),bWP);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID WriteSettings(VOID)
|
||||
{
|
||||
// Files
|
||||
WriteString(_T("Files"),_T("Emu48Directory"),szEmuDirectory);
|
||||
WriteInt(_T("Files"),_T("AutoSave"),bAutoSave);
|
||||
WriteInt(_T("Files"),_T("AutoSaveOnExit"),bAutoSaveOnExit);
|
||||
WriteInt(_T("Files"),_T("SaveDefaultConfirm"),bSaveDefConfirm);
|
||||
WriteInt(_T("Files"),_T("StartupBackup"),bStartupBackup);
|
||||
WriteInt(_T("Files"),_T("LoadObjectWarning"),bLoadObjectWarning);
|
||||
// Port2
|
||||
WriteInt(_T("Port2"),_T("IsShared"),bPort2IsShared);
|
||||
WriteString(_T("Port2"),_T("Filename"),szPort2Filename);
|
||||
// KML
|
||||
WriteInt(_T("KML"),_T("AlwaysDisplayLog"),bAlwaysDisplayLog);
|
||||
// Debugger
|
||||
WriteInt(_T("Debugger"),_T("LastInstrBufSize"),wInstrSize);
|
||||
// Disassembler
|
||||
WriteInt(_T("Disassembler"),_T("Mnemonics"),disassembler_mode);
|
||||
WriteInt(_T("Disassembler"),_T("Symbolic"),disassembler_symb);
|
||||
// Emulator
|
||||
WriteInt(_T("Emulator"),_T("ShowTitle"),bShowTitle);
|
||||
WriteInt(_T("Emulator"),_T("ShowMenu"),bShowMenu);
|
||||
WriteInt(_T("Emulator"),_T("AlwaysOnTop"),bAlwaysOnTop);
|
||||
WriteInt(_T("Emulator"),_T("ActivationFollowsMouse"),bActFollowsMouse);
|
||||
WriteInt(_T("Emulator"),_T("ClientWinMove"),bClientWinMove);
|
||||
WriteInt(_T("Emulator"),_T("SingleInstance"),bSingleInstance);
|
||||
WriteInt(_T("Emulator"),_T("RealSpeed"),bRealSpeed);
|
||||
WriteInt(_T("Emulator"),_T("SXCycles"),dwSXCycles);
|
||||
WriteInt(_T("Emulator"),_T("GXCycles"),dwGXCycles);
|
||||
WriteInt(_T("Emulator"),_T("GPCycles"),dwGPCycles); // CdB for HP: add apples
|
||||
WriteInt(_T("Emulator"),_T("G2Cycles"),dwG2Cycles); // CdB for HP: add apples
|
||||
WriteInt(_T("Emulator"),_T("KeyMinDelay"),dwKeyMinDelay);
|
||||
WriteInt(_T("Emulator"),_T("WakeupDelay"),dwWakeupDelay);
|
||||
WriteInt(_T("Emulator"),_T("Grayscale"),bGrayscale);
|
||||
WriteInt(_T("Emulator"),_T("WaveDeviceId"),uWaveDevId);
|
||||
WriteInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol);
|
||||
WriteInt(_T("Emulator"),_T("WaveTime"),dwWaveTime);
|
||||
// LowBat
|
||||
WriteInt(_T("LowBat"),_T("Disable"),bLowBatDisable);
|
||||
// Macro
|
||||
WriteInt(_T("Macro"),_T("RealSpeed"),bMacroRealSpeed);
|
||||
WriteInt(_T("Macro"),_T("ReplayTimeout"),nMacroTimeout);
|
||||
WriteInt(_T("Macro"),_T("KeyMinDelay"),dwMacroMinDelay);
|
||||
// IrPrinter
|
||||
WriteString(_T("IrPrinter"),_T("Address"),szUdpServer);
|
||||
WriteInt(_T("IrPrinter"),_T("Port"),wUdpPort);
|
||||
// Serial
|
||||
WriteString(_T("Serial"),_T("Wire"),szSerialWire);
|
||||
WriteString(_T("Serial"),_T("Ir"),szSerialIr);
|
||||
// ROM
|
||||
WriteInt(_T("ROM"),_T("Writeable"),bRomWriteable);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID ReadLastDocument(LPTSTR szFilename, DWORD nSize)
|
||||
{
|
||||
ReadString(_T("Files"),_T("LastDocument"),_T(""),szFilename,nSize);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID WriteLastDocument(LPCTSTR szFilename)
|
||||
{
|
||||
WriteString(_T("Files"),_T("LastDocument"),szFilename);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID ReadSettingsString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpDefault, LPTSTR lpData, DWORD dwSize)
|
||||
{
|
||||
ReadString(lpszSection,lpszEntry,lpDefault,lpData,dwSize);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID WriteSettingsString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPTSTR lpData)
|
||||
{
|
||||
WriteString(lpszSection,lpszEntry,lpData);
|
||||
return;
|
||||
}
|
||||
|
||||
INT ReadSettingsInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, INT nDefault)
|
||||
{
|
||||
return ReadInt(lpszSection,lpszEntry,nDefault);
|
||||
}
|
||||
|
||||
VOID WriteSettingsInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, INT nValue)
|
||||
{
|
||||
WriteInt(lpszSection,lpszEntry,nValue);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID DelSettingsKey(LPCTSTR lpszSection, LPCTSTR lpszEntry)
|
||||
{
|
||||
DelKey(lpszSection,lpszEntry);
|
||||
return;
|
||||
}
|
102
app/src/main/cpp/SNDDEF.H
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* snddef.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2015 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
|
||||
#include <initguid.h>
|
||||
|
||||
#if _MSC_VER >= 1600 // valid for VS2010 and later
|
||||
|
||||
#include <DSound.h>
|
||||
#include <Dsconf.h>
|
||||
|
||||
#else // create the necessary definitions manually
|
||||
|
||||
//
|
||||
// IKsPropertySet
|
||||
//
|
||||
|
||||
#ifndef _IKsPropertySet_
|
||||
#define _IKsPropertySet_
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct IKsPropertySet;
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef struct IKsPropertySet *LPKSPROPERTYSET;
|
||||
|
||||
DEFINE_GUID(IID_IKsPropertySet, 0x31efac30, 0x515c, 0x11d0, 0xa9, 0xaa, 0x00, 0xaa, 0x00, 0x61, 0xbe, 0x93);
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IKsPropertySet
|
||||
|
||||
DECLARE_INTERFACE_(IKsPropertySet, IUnknown)
|
||||
{
|
||||
// IUnknown methods
|
||||
STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID*) PURE;
|
||||
STDMETHOD_(ULONG,AddRef) (THIS) PURE;
|
||||
STDMETHOD_(ULONG,Release) (THIS) PURE;
|
||||
|
||||
// IKsPropertySet methods
|
||||
STDMETHOD(Get) (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength,
|
||||
LPVOID pPropertyData, ULONG ulDataLength, PULONG pulBytesReturned) PURE;
|
||||
STDMETHOD(Set) (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength,
|
||||
LPVOID pPropertyData, ULONG ulDataLength) PURE;
|
||||
STDMETHOD(QuerySupport) (THIS_ REFGUID rguidPropSet, ULONG ulId, PULONG pulTypeSupport) PURE;
|
||||
};
|
||||
|
||||
#endif // _IKsPropertySet_
|
||||
|
||||
// DirectSound Configuration Component GUID {11AB3EC0-25EC-11d1-A4D8-00C04FC28ACA}
|
||||
DEFINE_GUID(CLSID_DirectSoundPrivate, 0x11ab3ec0, 0x25ec, 0x11d1, 0xa4, 0xd8, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
|
||||
|
||||
// DirectSound Device Properties {84624F82-25EC-11d1-A4D8-00C04FC28ACA}
|
||||
DEFINE_GUID(DSPROPSETID_DirectSoundDevice, 0x84624f82, 0x25ec, 0x11d1, 0xa4, 0xd8, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A = 1,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1 = 2,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1 = 3,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W = 4,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A = 5,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W = 6,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A = 7,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W = 8,
|
||||
} DSPROPERTY_DIRECTSOUNDDEVICE;
|
||||
|
||||
#ifdef UNICODE
|
||||
#define DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W
|
||||
#else // UNICODE
|
||||
#define DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A
|
||||
#endif // UNICODE
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DIRECTSOUNDDEVICE_TYPE_EMULATED,
|
||||
DIRECTSOUNDDEVICE_TYPE_VXD,
|
||||
DIRECTSOUNDDEVICE_TYPE_WDM
|
||||
} DIRECTSOUNDDEVICE_TYPE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DIRECTSOUNDDEVICE_DATAFLOW_RENDER,
|
||||
DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE
|
||||
} DIRECTSOUNDDEVICE_DATAFLOW;
|
||||
|
||||
typedef struct _DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA
|
||||
{
|
||||
DIRECTSOUNDDEVICE_TYPE Type; // Device type
|
||||
DIRECTSOUNDDEVICE_DATAFLOW DataFlow; // Device dataflow
|
||||
GUID DeviceId; // DirectSound device id
|
||||
LPTSTR Description; // Device description
|
||||
LPTSTR Module; // Device driver module
|
||||
LPTSTR Interface; // Device interface
|
||||
ULONG WaveDeviceId; // Wave device id
|
||||
} DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA, *PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA;
|
||||
|
||||
#endif
|
256
app/src/main/cpp/SNDENUM.C
Normal file
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* SndEnum.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2015 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "snddef.h"
|
||||
|
||||
typedef HRESULT (WINAPI *LPFNDLLGETCLASSOBJECT)(REFCLSID,REFIID,LPVOID *);
|
||||
static LPFNDLLGETCLASSOBJECT pfnDllGetClassObject = NULL;
|
||||
|
||||
//
|
||||
// create a IKsPropertySet interface
|
||||
//
|
||||
static __inline HRESULT DirectSoundPrivateCreate(LPKSPROPERTYSET *ppKsPropertySet)
|
||||
{
|
||||
LPCLASSFACTORY pClassFactory = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
// create a class factory object
|
||||
#if defined __cplusplus
|
||||
hr = pfnDllGetClassObject(CLSID_DirectSoundPrivate,IID_IClassFactory,(LPVOID *) &pClassFactory);
|
||||
#else
|
||||
hr = pfnDllGetClassObject(&CLSID_DirectSoundPrivate,&IID_IClassFactory,(LPVOID *) &pClassFactory);
|
||||
#endif
|
||||
|
||||
// create the DirectSoundPrivate object and query for an IKsPropertySet interface
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
#if defined __cplusplus
|
||||
hr = pClassFactory->CreateInstance(NULL,IID_IKsPropertySet,(LPVOID *) ppKsPropertySet);
|
||||
#else
|
||||
hr = pClassFactory->lpVtbl->CreateInstance(pClassFactory,NULL,&IID_IKsPropertySet,(LPVOID *) ppKsPropertySet);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pClassFactory) // release the class factory object
|
||||
{
|
||||
#if defined __cplusplus
|
||||
pClassFactory->Release();
|
||||
#else
|
||||
pClassFactory->lpVtbl->Release(pClassFactory);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (FAILED(hr) && *ppKsPropertySet) // handle failure
|
||||
{
|
||||
#if defined __cplusplus
|
||||
(*ppKsPropertySet)->Release();
|
||||
#else
|
||||
(*ppKsPropertySet)->lpVtbl->Release(*ppKsPropertySet);
|
||||
#endif
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
//
|
||||
// get the device information about a DirectSound GUID.
|
||||
//
|
||||
static BOOL GetInfoFromDSoundGUID(CONST GUID *lpGUID, UINT *puWaveDeviceID)
|
||||
{
|
||||
LPKSPROPERTYSET pKsPropertySet = NULL;
|
||||
HRESULT hr;
|
||||
BOOL bSuccess = FALSE;
|
||||
|
||||
hr = DirectSoundPrivateCreate(&pKsPropertySet);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ULONG ulBytesReturned = 0;
|
||||
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA sDirectSoundDeviceDescription;
|
||||
|
||||
ZeroMemory(&sDirectSoundDeviceDescription,sizeof(sDirectSoundDeviceDescription));
|
||||
sDirectSoundDeviceDescription.DeviceId = *lpGUID;
|
||||
|
||||
// get the size of the direct sound device description
|
||||
#if defined __cplusplus
|
||||
hr = pKsPropertySet->Get(
|
||||
DSPROPSETID_DirectSoundDevice,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
||||
NULL,
|
||||
0,
|
||||
&sDirectSoundDeviceDescription,
|
||||
sizeof(sDirectSoundDeviceDescription),
|
||||
&ulBytesReturned
|
||||
);
|
||||
#else
|
||||
hr = pKsPropertySet->lpVtbl->Get(pKsPropertySet,
|
||||
&DSPROPSETID_DirectSoundDevice,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
||||
NULL,
|
||||
0,
|
||||
&sDirectSoundDeviceDescription,
|
||||
sizeof(sDirectSoundDeviceDescription),
|
||||
&ulBytesReturned
|
||||
);
|
||||
#endif
|
||||
|
||||
if (SUCCEEDED(hr) && ulBytesReturned)
|
||||
{
|
||||
PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA psDirectSoundDeviceDescription = NULL;
|
||||
|
||||
// fetch the direct sound device description
|
||||
psDirectSoundDeviceDescription = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA) malloc(ulBytesReturned);
|
||||
if (psDirectSoundDeviceDescription != NULL)
|
||||
{
|
||||
// init structure with data from length request
|
||||
*psDirectSoundDeviceDescription = sDirectSoundDeviceDescription;
|
||||
|
||||
#if defined __cplusplus
|
||||
hr = pKsPropertySet->Get(
|
||||
DSPROPSETID_DirectSoundDevice,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
||||
NULL,
|
||||
0,
|
||||
psDirectSoundDeviceDescription,
|
||||
ulBytesReturned,
|
||||
&ulBytesReturned
|
||||
);
|
||||
#else
|
||||
hr = pKsPropertySet->lpVtbl->Get(pKsPropertySet,
|
||||
&DSPROPSETID_DirectSoundDevice,
|
||||
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
|
||||
NULL,
|
||||
0,
|
||||
psDirectSoundDeviceDescription,
|
||||
ulBytesReturned,
|
||||
&ulBytesReturned
|
||||
);
|
||||
#endif
|
||||
|
||||
if ((bSuccess = SUCCEEDED(hr)))
|
||||
{
|
||||
// the requested device ID
|
||||
*puWaveDeviceID = psDirectSoundDeviceDescription->WaveDeviceId;
|
||||
}
|
||||
free(psDirectSoundDeviceDescription);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined __cplusplus
|
||||
pKsPropertySet->Release();
|
||||
#else
|
||||
pKsPropertySet->lpVtbl->Release(pKsPropertySet);
|
||||
#endif
|
||||
}
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
//
|
||||
// callback function for DirectSoundEnumerate()
|
||||
//
|
||||
static BOOL CALLBACK DSEnumProc(LPGUID lpGUID,LPCTSTR lpszDesc,LPCTSTR lpszDrvName,LPVOID lpContext)
|
||||
{
|
||||
HWND hWnd = (HWND) lpContext; // window handle of the combo box
|
||||
|
||||
if (lpGUID != NULL) // NULL only for "Primary Sound Driver"
|
||||
{
|
||||
UINT uDevID;
|
||||
|
||||
if (GetInfoFromDSoundGUID(lpGUID,&uDevID))
|
||||
{
|
||||
WAVEOUTCAPS woc;
|
||||
|
||||
// has device the necessary capabilities?
|
||||
if ( waveOutGetDevCaps(uDevID,&woc,sizeof(woc)) == MMSYSERR_NOERROR
|
||||
&& (woc.dwFormats & WAVE_FORMAT_4M08) != 0)
|
||||
{
|
||||
// copy product name and wave device ID to combo box
|
||||
LONG i = (LONG) SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM) lpszDesc);
|
||||
SendMessage(hWnd,CB_SETITEMDATA,i,uDevID);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
UNREFERENCED_PARAMETER(lpszDrvName);
|
||||
}
|
||||
|
||||
// set listfield for sound device combo box
|
||||
VOID SetSoundDeviceList(HWND hWnd,UINT uDeviceID)
|
||||
{
|
||||
typedef BOOL (CALLBACK *LPDSENUMCALLBACK)(LPGUID, LPCTSTR, LPCTSTR, LPVOID);
|
||||
typedef HRESULT (WINAPI *LPFN_SDE)(LPDSENUMCALLBACK lpDSEnumCallback,LPVOID lpContext);
|
||||
LPFN_SDE pfnDirectSoundEnumerate = NULL;
|
||||
|
||||
UINT uSelectDevice,uDevID,uDevNo;
|
||||
|
||||
HMODULE hDSound = LoadLibrary(_T("dsound.dll"));
|
||||
|
||||
if (hDSound != NULL) // direct sound dll found
|
||||
{
|
||||
#if defined _UNICODE
|
||||
pfnDirectSoundEnumerate = (LPFN_SDE) GetProcAddress(hDSound,"DirectSoundEnumerateW");
|
||||
#else
|
||||
pfnDirectSoundEnumerate = (LPFN_SDE) GetProcAddress(hDSound,"DirectSoundEnumerateA");
|
||||
#endif
|
||||
pfnDllGetClassObject = (LPFNDLLGETCLASSOBJECT) GetProcAddress(hDSound,"DllGetClassObject");
|
||||
}
|
||||
|
||||
SendMessage(hWnd,CB_RESETCONTENT,0,0);
|
||||
|
||||
// preset selector
|
||||
uSelectDevice = (UINT) SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM) _T("Standard Audio"));
|
||||
SendMessage(hWnd,CB_SETITEMDATA,uSelectDevice,WAVE_MAPPER);
|
||||
|
||||
// check for direct sound interface functions
|
||||
if (pfnDirectSoundEnumerate != NULL && pfnDllGetClassObject != NULL)
|
||||
{
|
||||
// copy product name and wave device ID to combo box
|
||||
if (SUCCEEDED(pfnDirectSoundEnumerate((LPDSENUMCALLBACK) DSEnumProc,hWnd)))
|
||||
{
|
||||
UINT i;
|
||||
|
||||
uDevNo = (UINT) SendMessage(hWnd,CB_GETCOUNT,0,0);
|
||||
for (i = 0; i < uDevNo; ++i)
|
||||
{
|
||||
// translate device ID to combo box position
|
||||
uDevID = (UINT) SendMessage(hWnd,CB_GETITEMDATA,i,0);
|
||||
|
||||
if (uDevID == uDeviceID) uSelectDevice = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // direct sound not available, detect over wave capabilities
|
||||
{
|
||||
WAVEOUTCAPS woc;
|
||||
|
||||
uDevNo = waveOutGetNumDevs();
|
||||
for (uDevID = 0; uDevID < uDevNo; ++uDevID)
|
||||
{
|
||||
if ( waveOutGetDevCaps(uDevID,&woc,sizeof(woc)) == MMSYSERR_NOERROR
|
||||
&& (woc.dwFormats & WAVE_FORMAT_4M08) != 0)
|
||||
{
|
||||
// copy product name and wave device ID to combo box
|
||||
LONG i = (LONG) SendMessage(hWnd,CB_ADDSTRING,0,(LPARAM) woc.szPname);
|
||||
SendMessage(hWnd,CB_SETITEMDATA,i,uDevID);
|
||||
|
||||
if (uDevID == uDeviceID) uSelectDevice = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// activate last selected combo box item
|
||||
SendMessage(hWnd,CB_SETCURSEL,uSelectDevice,0L);
|
||||
|
||||
if (hDSound != NULL) // direct sound dll loaded
|
||||
{
|
||||
pfnDllGetClassObject = NULL;
|
||||
VERIFY(FreeLibrary(hDSound));
|
||||
}
|
||||
return;
|
||||
}
|
557
app/src/main/cpp/SOUND.C
Normal file
|
@ -0,0 +1,557 @@
|
|||
/*
|
||||
* sound.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2013 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
|
||||
// #define DEBUG_SOUND // switch for sound debug purpose
|
||||
// #define SINE_APPROX // sine signal approximation
|
||||
|
||||
#define SAMPLES_PER_SEC 44100 // sound sampling rate
|
||||
#define MILLISEC_PER_BUFFER 20 // time period of each sound buffer
|
||||
|
||||
#define NO_OF_BUFFERS 3 // number of reserve buffers before playing
|
||||
|
||||
typedef struct _MSAMPLE
|
||||
{
|
||||
LPBYTE pbyData;
|
||||
DWORD dwBufferLength;
|
||||
DWORD dwPosition;
|
||||
// buffer admin part
|
||||
DWORD dwIndex; // index to count no. of sample buffers
|
||||
struct _MSAMPLE* pNext; // pointer to next sample buffer
|
||||
} MSAMPLE, *PMSAMPLE;
|
||||
|
||||
DWORD dwWaveVol = 64; // wave sound volume
|
||||
DWORD dwWaveTime = MILLISEC_PER_BUFFER; // time period (in ms) of each sound buffer
|
||||
|
||||
static HWAVEOUT hWaveDevice = NULL; // handle to the waveform-audio output device
|
||||
static HANDLE hThreadWave = NULL; // thread handle of sound message handler
|
||||
static DWORD dwThreadWaveId = 0; // thread id of sound message handler
|
||||
static UINT uHeaders = 0; // no. of sending wave headers
|
||||
static PMSAMPLE psHead = NULL; // head of sound samples
|
||||
static PMSAMPLE psTail = NULL; // tail of sound samples
|
||||
|
||||
static CRITICAL_SECTION csSoundLock; // critical section for sound emulation
|
||||
static DWORD dwSoundBufferLength; // sound buffer length for the given time period
|
||||
|
||||
static VOID FlushSample(VOID);
|
||||
|
||||
//
|
||||
// sound message handler thread
|
||||
//
|
||||
static DWORD WINAPI SoundWndProc(LPVOID pParam)
|
||||
{
|
||||
MSG msg;
|
||||
|
||||
while (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if (msg.message == MM_WOM_DONE)
|
||||
{
|
||||
HWAVEOUT hwo = (HWAVEOUT) msg.wParam;
|
||||
PWAVEHDR pwh = (PWAVEHDR) msg.lParam;
|
||||
|
||||
VERIFY(waveOutUnprepareHeader(hwo,pwh,sizeof(*pwh)) == MMSYSERR_NOERROR);
|
||||
free(pwh->lpData); // free waveform data
|
||||
free(pwh); // free wavefom header
|
||||
|
||||
_ASSERT(uHeaders > 0);
|
||||
--uHeaders; // finished header
|
||||
|
||||
FlushSample(); // check for new sample
|
||||
|
||||
if (uHeaders == 0) // no wave headers in transmission
|
||||
{
|
||||
bSoundSlow = FALSE; // no sound slow down
|
||||
bEnableSlow = TRUE; // reenable CPU slow down possibility
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
UNREFERENCED_PARAMETER(pParam);
|
||||
}
|
||||
|
||||
//
|
||||
// create sound message handler thread
|
||||
//
|
||||
static BOOL CreateWaveThread(VOID)
|
||||
{
|
||||
_ASSERT(hThreadWave == NULL);
|
||||
|
||||
// create sound message handler thread
|
||||
hThreadWave = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&SoundWndProc,NULL,0,&dwThreadWaveId);
|
||||
return hThreadWave != NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// destroy sound message handler thread
|
||||
//
|
||||
static VOID DestroyWaveThread(VOID)
|
||||
{
|
||||
if (hThreadWave != NULL) // sound message handler thread running
|
||||
{
|
||||
// shut down thread
|
||||
while (!PostThreadMessage(dwThreadWaveId,WM_QUIT,0,0))
|
||||
Sleep(0);
|
||||
WaitForSingleObject(hThreadWave,INFINITE);
|
||||
CloseHandle(hThreadWave);
|
||||
hThreadWave = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// add sample buffer to tail of sample job list
|
||||
//
|
||||
static __inline VOID AddSoundBuf(PMSAMPLE psData)
|
||||
{
|
||||
_ASSERT(psData != NULL); // there must be a sample
|
||||
psData->pNext = NULL; // last sample in job list
|
||||
|
||||
// add sample to list
|
||||
EnterCriticalSection(&csSoundLock);
|
||||
{
|
||||
if (psTail == NULL) // root
|
||||
{
|
||||
psData->dwIndex = 0; // this is the root index
|
||||
|
||||
_ASSERT(psHead == NULL);
|
||||
psHead = psTail = psData; // add sample at head
|
||||
}
|
||||
else // add at tail
|
||||
{
|
||||
// use next index
|
||||
psData->dwIndex = psTail->dwIndex + 1;
|
||||
|
||||
psTail->pNext = psData; // add sample at tail
|
||||
psTail = psData;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&csSoundLock);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// remove sample buffer from head of sample job list
|
||||
//
|
||||
static __inline BOOL GetSoundBuf(PMSAMPLE *ppsData)
|
||||
{
|
||||
BOOL bSucc;
|
||||
|
||||
EnterCriticalSection(&csSoundLock);
|
||||
{
|
||||
if ((bSucc = (psHead != NULL))) // data in head
|
||||
{
|
||||
*ppsData = psHead; // get sample
|
||||
psHead = psHead->pNext; // and remove it from head
|
||||
if (psHead == NULL) // was last one in head
|
||||
{
|
||||
psTail = NULL; // so tail is also the last one
|
||||
}
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&csSoundLock);
|
||||
return bSucc;
|
||||
}
|
||||
|
||||
//
|
||||
// number of sample buffers in sample job list
|
||||
//
|
||||
static DWORD GetSoundBufSize(VOID)
|
||||
{
|
||||
DWORD dwNoSamples;
|
||||
|
||||
EnterCriticalSection(&csSoundLock);
|
||||
{
|
||||
// no. of samples in buffer
|
||||
dwNoSamples = (psTail == NULL)
|
||||
? 0
|
||||
: (psTail->dwIndex - psHead->dwIndex) + 1;
|
||||
}
|
||||
LeaveCriticalSection(&csSoundLock);
|
||||
return dwNoSamples;
|
||||
}
|
||||
|
||||
//
|
||||
// allocate new sample buffer and add the
|
||||
// buffer to the tail of the sample job list
|
||||
//
|
||||
static __inline BOOL AllocSample(PMSAMPLE *ppsData)
|
||||
{
|
||||
// alloc new sample buffer
|
||||
*ppsData = (PMSAMPLE) malloc(sizeof(**ppsData));
|
||||
|
||||
if (*ppsData != NULL)
|
||||
{
|
||||
(*ppsData)->dwPosition = 0; // begin of buffer
|
||||
(*ppsData)->dwBufferLength = dwSoundBufferLength;
|
||||
(*ppsData)->pbyData = (LPBYTE) malloc((*ppsData)->dwBufferLength);
|
||||
if ((*ppsData)->pbyData != NULL)
|
||||
{
|
||||
// buffers allocated
|
||||
_ASSERT(*ppsData != NULL && (*ppsData)->pbyData != NULL);
|
||||
|
||||
AddSoundBuf(*ppsData); // add sample buffer to list
|
||||
}
|
||||
else
|
||||
{
|
||||
free(*ppsData); // data alloc failed, delete sample buffer
|
||||
*ppsData = NULL;
|
||||
}
|
||||
}
|
||||
return *ppsData != NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// write samples to sample buffer
|
||||
//
|
||||
static BOOL AddSamples(DWORD dwSamples, BYTE byLevel)
|
||||
{
|
||||
PMSAMPLE psData;
|
||||
DWORD dwBufSamples;
|
||||
#if defined SINE_APPROX
|
||||
INT w,s,ss,x,y;
|
||||
#endif
|
||||
|
||||
BOOL bSucc = TRUE;
|
||||
|
||||
if (dwSamples == 0) return TRUE; // nothing to add
|
||||
|
||||
#if defined SINE_APPROX
|
||||
// calculate constants
|
||||
w = (INT) (byLevel - 0x80); // max. wave level
|
||||
s = (INT) dwSamples; // interval length (pi)
|
||||
ss = s * s; // interval length ^ 2
|
||||
x = 1; // sample no.
|
||||
#endif
|
||||
|
||||
EnterCriticalSection(&csSoundLock);
|
||||
{
|
||||
psData = psTail; // get last sample buffer
|
||||
|
||||
do
|
||||
{
|
||||
// number of free sound samples in current buffer
|
||||
dwBufSamples = (psData != NULL)
|
||||
? (psData->dwBufferLength - psData->dwPosition)
|
||||
: 0;
|
||||
|
||||
if (dwBufSamples == 0) // sample buffer is full
|
||||
{
|
||||
// alloc new sample buffer
|
||||
VERIFY(bSucc = AllocSample(&psData));
|
||||
if (!bSucc) break;
|
||||
|
||||
_ASSERT( psData != NULL
|
||||
&& psData->pbyData != NULL
|
||||
&& psData->dwPosition == 0);
|
||||
dwBufSamples = psData->dwBufferLength;
|
||||
}
|
||||
|
||||
if (dwSamples < dwBufSamples) // free sample buffer is larger then needed
|
||||
dwBufSamples = dwSamples; // fill only the necessary no. of samples
|
||||
|
||||
dwSamples -= dwBufSamples; // remaining samples after buffer fill
|
||||
|
||||
// fill buffer with level for beep
|
||||
#if defined SINE_APPROX
|
||||
for (; dwBufSamples > 0; --dwBufSamples)
|
||||
{
|
||||
// sine approximation function
|
||||
y = w - w * (4 * x * (x - s) + ss ) / ss;
|
||||
++x; // next sample
|
||||
|
||||
psData->pbyData[psData->dwPosition++] = (BYTE) (y + 0x80);
|
||||
}
|
||||
#else
|
||||
FillMemory(&psData->pbyData[psData->dwPosition],dwBufSamples,byLevel);
|
||||
psData->dwPosition += dwBufSamples;
|
||||
#endif
|
||||
}
|
||||
while (dwSamples > 0);
|
||||
}
|
||||
LeaveCriticalSection(&csSoundLock);
|
||||
return bSucc;
|
||||
}
|
||||
|
||||
//
|
||||
// write sample buffer from head of sample job list
|
||||
// to waveform-audio output device and delete the
|
||||
// sample buffer control from head of sample job list
|
||||
//
|
||||
static VOID FlushSample(VOID)
|
||||
{
|
||||
PMSAMPLE psData;
|
||||
|
||||
_ASSERT(hWaveDevice != NULL);
|
||||
|
||||
if (GetSoundBuf(&psData) == TRUE) // fetch sample buffer
|
||||
{
|
||||
PWAVEHDR pwh;
|
||||
|
||||
// allocate new wave header
|
||||
if ((pwh = (PWAVEHDR) malloc(sizeof(*pwh))) != NULL)
|
||||
{
|
||||
pwh->lpData = (LPSTR) psData->pbyData;
|
||||
pwh->dwBufferLength = psData->dwPosition;
|
||||
pwh->dwBytesRecorded = 0;
|
||||
pwh->dwUser = 0;
|
||||
pwh->dwFlags = 0;
|
||||
pwh->dwLoops = 0;
|
||||
|
||||
++uHeaders; // add header
|
||||
|
||||
// prepare sample
|
||||
VERIFY(waveOutPrepareHeader(hWaveDevice,pwh,sizeof(*pwh)) == MMSYSERR_NOERROR);
|
||||
|
||||
// send sample
|
||||
VERIFY(waveOutWrite(hWaveDevice,pwh,sizeof(*pwh)) == MMSYSERR_NOERROR);
|
||||
}
|
||||
free(psData); // delete sample buffer
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// 44.1 kHz, mono, 8-bit waveform-audio output device available
|
||||
//
|
||||
BOOL SoundAvailable(UINT uDeviceID)
|
||||
{
|
||||
WAVEOUTCAPS woc;
|
||||
return waveOutGetDevCaps(uDeviceID,&woc,sizeof(woc)) == MMSYSERR_NOERROR
|
||||
&& (woc.dwFormats & WAVE_FORMAT_4M08) != 0;
|
||||
}
|
||||
|
||||
//
|
||||
// get the device ID of the current waveform-audio output device
|
||||
//
|
||||
BOOL SoundGetDeviceID(UINT *puDeviceID)
|
||||
{
|
||||
BOOL bSucc = FALSE;
|
||||
|
||||
if (hWaveDevice) // have sound device
|
||||
{
|
||||
bSucc = (waveOutGetID(hWaveDevice,puDeviceID) == MMSYSERR_NOERROR);
|
||||
}
|
||||
return bSucc;
|
||||
}
|
||||
|
||||
//
|
||||
// open waveform-audio output device
|
||||
//
|
||||
BOOL SoundOpen(UINT uDeviceID)
|
||||
{
|
||||
// check if sound device is already open
|
||||
if (hWaveDevice == NULL && SoundAvailable(uDeviceID))
|
||||
{
|
||||
WAVEFORMATEX wf;
|
||||
BOOL bSucc;
|
||||
|
||||
wf.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wf.nChannels = 1;
|
||||
wf.nSamplesPerSec = SAMPLES_PER_SEC;
|
||||
wf.wBitsPerSample = 8;
|
||||
wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8;
|
||||
wf.nAvgBytesPerSec = wf.nBlockAlign * wf.nSamplesPerSec;
|
||||
wf.cbSize = 0;
|
||||
|
||||
InitializeCriticalSection(&csSoundLock);
|
||||
|
||||
// sound buffer length for the given time period
|
||||
dwSoundBufferLength = SAMPLES_PER_SEC * dwWaveTime / 1000;
|
||||
|
||||
if ((bSucc = CreateWaveThread())) // create sound message handler
|
||||
{
|
||||
// create a sound device, use the CALLBACK_THREAD flag because with the
|
||||
// CALLBACK_FUNCTION flag unfortunately the called callback function
|
||||
// can only call a specific set of Windows functions. Attempting to
|
||||
// call other functions at the wrong time will result in a deadlock.
|
||||
bSucc = (waveOutOpen(&hWaveDevice,uDeviceID,&wf,dwThreadWaveId,0,CALLBACK_THREAD) == MMSYSERR_NOERROR);
|
||||
}
|
||||
if (!bSucc)
|
||||
{
|
||||
DestroyWaveThread(); // shut down message thread
|
||||
DeleteCriticalSection(&csSoundLock);
|
||||
hWaveDevice = NULL;
|
||||
}
|
||||
}
|
||||
return hWaveDevice != NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// close waveform-audio output device
|
||||
//
|
||||
VOID SoundClose(VOID)
|
||||
{
|
||||
if (hWaveDevice != NULL)
|
||||
{
|
||||
EnterCriticalSection(&csSoundLock);
|
||||
{
|
||||
while (psHead != NULL) // cleanup remaining sample buffers
|
||||
{
|
||||
PMSAMPLE psNext = psHead->pNext;
|
||||
|
||||
free(psHead->pbyData);
|
||||
free(psHead);
|
||||
psHead = psNext;
|
||||
}
|
||||
psTail = NULL;
|
||||
}
|
||||
LeaveCriticalSection(&csSoundLock);
|
||||
|
||||
// abandon all pending wave headers
|
||||
VERIFY(waveOutReset(hWaveDevice) == MMSYSERR_NOERROR);
|
||||
|
||||
DestroyWaveThread(); // shut down message thread
|
||||
|
||||
VERIFY(waveOutClose(hWaveDevice) == MMSYSERR_NOERROR);
|
||||
DeleteCriticalSection(&csSoundLock);
|
||||
hWaveDevice = NULL;
|
||||
}
|
||||
uHeaders = 0; // no wave headers in transmission
|
||||
bSoundSlow = FALSE; // no sound slow down
|
||||
bEnableSlow = TRUE; // reenable CPU slow down possibility
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// calculate the wave level from the beeper bit state
|
||||
//
|
||||
static BYTE WaveLevel(WORD wOut)
|
||||
{
|
||||
wOut >>= 11; // mask out beeper bit OR[11]
|
||||
return (BYTE) (wOut & 0x01) + 1; // return 1 or 2
|
||||
}
|
||||
|
||||
//
|
||||
// decode change of beeper OUT bits
|
||||
//
|
||||
VOID SoundOut(CHIPSET* w, WORD wOut)
|
||||
{
|
||||
static DWORD dwLastCyc; // last timer value at beeper bit change
|
||||
|
||||
DWORD dwCycles,dwDiffSatCycles,dwDiffCycles,dwCpuFreq,dwSamples;
|
||||
BYTE byWaveLevel;
|
||||
|
||||
// sound device not opened or waveform-audio output device not available
|
||||
if (hWaveDevice == NULL)
|
||||
return;
|
||||
|
||||
// actual timestamp
|
||||
dwCycles = (DWORD) (w->cycles & 0xFFFFFFFF);
|
||||
|
||||
dwDiffSatCycles = dwCycles - dwLastCyc; // time difference from syncpoint in original Saturn cycles
|
||||
|
||||
// theoretical CPU frequency from given T2CYCLES
|
||||
dwCpuFreq = T2CYCLES * 16384;
|
||||
|
||||
if (dwDiffSatCycles > dwCpuFreq / 2) // frequency < 1 Hz
|
||||
{
|
||||
dwLastCyc = dwCycles; // initial call for start beeping
|
||||
return;
|
||||
}
|
||||
|
||||
// estimated CPU cycles for Clarke/Yorke chip
|
||||
dwDiffCycles = (cCurrentRomType == 'S')
|
||||
? (dwDiffSatCycles * 26) / 25 // Clarke * 1.04
|
||||
: (dwDiffSatCycles * 11) / 10; // Yorke * 1.10
|
||||
|
||||
// adjust original CPU cycles
|
||||
w->cycles += (dwDiffCycles - dwDiffSatCycles);
|
||||
dwLastCyc = (DWORD) (w->cycles & 0xFFFFFFFF); // new syncpoint
|
||||
|
||||
// calculate no. of sound samples from CPU cycles, !! intermediate result maybe > 32bit !!
|
||||
dwSamples = (DWORD) ((2 * (QWORD) dwDiffCycles + 1) * SAMPLES_PER_SEC / 2 / dwCpuFreq);
|
||||
|
||||
if (dwSamples == 0) // frequency too high -> play nothing
|
||||
return;
|
||||
|
||||
#if defined DEBUG_SOUND
|
||||
{
|
||||
TCHAR buffer[256];
|
||||
|
||||
// calculate rounded time in us
|
||||
QWORD lDuration = 1000000 * (2 * (QWORD) dwDiffCycles + 1) / (2 * dwCpuFreq);
|
||||
|
||||
wsprintf(buffer,_T("State %u: Time = %I64u us f = %u Hz, Time = %I64u us f = %u Hz\n"),
|
||||
wOut >> 11,lDuration,(DWORD) (1000000 / 2 / lDuration),
|
||||
(QWORD) dwSamples * 1000000 / SAMPLES_PER_SEC,SAMPLES_PER_SEC / 2 / dwSamples);
|
||||
OutputDebugString(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
// begin of beep
|
||||
if (uHeaders == 0 && GetSoundBufSize() == 0)
|
||||
{
|
||||
// use silence buffers to start output engine
|
||||
AddSamples(dwSoundBufferLength * NO_OF_BUFFERS,0x80);
|
||||
}
|
||||
|
||||
// offset for wave level
|
||||
byWaveLevel = 0x80 + (BYTE) (dwWaveVol * (WaveLevel(wOut) - WaveLevel(w->out)) / 2);
|
||||
|
||||
AddSamples(dwSamples,byWaveLevel); // add samples to latest wave sample buffer
|
||||
|
||||
if (GetSoundBufSize() > NO_OF_BUFFERS) // have more than 3 wave sample buffers
|
||||
{
|
||||
FlushSample(); // send 2 of them
|
||||
FlushSample();
|
||||
}
|
||||
|
||||
// ran out of buffers -> disable CPU slow down
|
||||
EnterCriticalSection(&csSlowLock);
|
||||
{
|
||||
InitAdjustSpeed(); // init variables if necessary
|
||||
bEnableSlow = (GetSoundBufSize() > 1);
|
||||
}
|
||||
LeaveCriticalSection(&csSlowLock);
|
||||
|
||||
if (bSoundSlow == FALSE)
|
||||
{
|
||||
EnterCriticalSection(&csSlowLock);
|
||||
{
|
||||
InitAdjustSpeed(); // init variables if necessary
|
||||
bSoundSlow = TRUE; // CPU slow down
|
||||
}
|
||||
LeaveCriticalSection(&csSlowLock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// beep with frequency (Hz) and duration (ms)
|
||||
//
|
||||
VOID SoundBeep(DWORD dwFrequency, DWORD dwDuration)
|
||||
{
|
||||
QWORD lPeriods;
|
||||
DWORD dwSamples;
|
||||
BYTE byLevel;
|
||||
|
||||
// waveform-audio output device opened and have frequency
|
||||
if (hWaveDevice && dwFrequency > 0)
|
||||
{
|
||||
// samples for 1/2 of time period
|
||||
dwSamples = SAMPLES_PER_SEC / 2 / dwFrequency;
|
||||
|
||||
// overall half periods
|
||||
lPeriods = (QWORD) dwFrequency * dwDuration / 500;
|
||||
|
||||
while (lPeriods-- > 0) // create sample buffers
|
||||
{
|
||||
// signal level
|
||||
byLevel = 0x80 + (BYTE) ((((DWORD) lPeriods & 1) * 2 - 1) * (dwWaveVol / 2));
|
||||
|
||||
AddSamples(dwSamples,byLevel); // add half period sample
|
||||
}
|
||||
|
||||
while (GetSoundBufSize() > 0) // samples in job list
|
||||
FlushSample(); // send sample buffer
|
||||
}
|
||||
Sleep(dwDuration);
|
||||
return;
|
||||
}
|
834
app/src/main/cpp/STACK.C
Normal file
|
@ -0,0 +1,834 @@
|
|||
/*
|
||||
* stack.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2005 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "io.h"
|
||||
|
||||
#define fnRadix 51 // fraction mark
|
||||
#define fnApprox 105 // exact / approx. mode (HP49G)
|
||||
|
||||
#define DOINT 0x02614 // Precision Integer (HP49G)
|
||||
#define DOREAL 0x02933 // Real
|
||||
#define DOCMP 0x02977 // Complex
|
||||
#define DOCSTR 0x02A2C // String
|
||||
|
||||
BOOL bDetectClpObject = TRUE; // try to detect clipboard object
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Low level subroutines
|
||||
//#
|
||||
//################
|
||||
|
||||
static LPTSTR Trim(LPCTSTR cp)
|
||||
{
|
||||
LPCTSTR pcWs = _T(" \t\n\r"); // valid whitespace characters
|
||||
|
||||
LPTSTR pc;
|
||||
DWORD dwFirst,dwLast;
|
||||
|
||||
dwLast = lstrlen(cp); // last position in string (EOS)
|
||||
|
||||
// trim leading and tailing whitespace characters
|
||||
dwFirst = (DWORD) _tcsspn(cp,pcWs); // position of 1st non whitespace character
|
||||
|
||||
// search for position behind last non whitespace character
|
||||
while (dwLast > dwFirst && _tcschr(pcWs,cp[dwLast-1]) != NULL)
|
||||
--dwLast;
|
||||
|
||||
dwLast = 1 + dwLast - dwFirst; // calculate buffer length
|
||||
|
||||
if ((pc = (LPTSTR) malloc(dwLast * sizeof(*pc))) != NULL)
|
||||
{
|
||||
lstrcpyn(pc,&cp[dwFirst],dwLast); // copy relevant data + EOS
|
||||
}
|
||||
return pc;
|
||||
}
|
||||
|
||||
static INT RPL_GetZInt(BYTE CONST *pbyNum,INT nIntLen,LPTSTR cp,INT nSize)
|
||||
{
|
||||
INT i = 0; // character counter
|
||||
|
||||
_ASSERT(nSize > 0); // target buffer size
|
||||
|
||||
if (nIntLen > 1) // has sign nibble
|
||||
{
|
||||
--nIntLen; // remove sign from digit length
|
||||
|
||||
// check for valid sign
|
||||
_ASSERT(pbyNum[nIntLen] == 0 || pbyNum[nIntLen] == 9);
|
||||
if (pbyNum[nIntLen] == 9) // negative number
|
||||
{
|
||||
*cp++ = _T('-'); // add sign
|
||||
--nSize; // dec dest buffer size
|
||||
++i; // wrote one character
|
||||
}
|
||||
}
|
||||
|
||||
if (nIntLen >= nSize) return 0; // dest buffer overflow
|
||||
i += nIntLen; // adjust character counter
|
||||
|
||||
while (nIntLen-- > 0) // write all digits
|
||||
{
|
||||
// check for valid digit
|
||||
_ASSERT(pbyNum[nIntLen] >= 0 && pbyNum[nIntLen] <= 9);
|
||||
*cp++ = _T('0') + pbyNum[nIntLen]; // and write
|
||||
}
|
||||
*cp = 0; // set EOS
|
||||
return i;
|
||||
}
|
||||
|
||||
static __inline INT SetZInt(LPCTSTR cp,LPBYTE pbyNum,INT nSize)
|
||||
{
|
||||
BYTE bySign;
|
||||
INT nStrLen,nNumSize;
|
||||
|
||||
_ASSERT(nSize > 0); // target buffer size
|
||||
|
||||
nStrLen = lstrlen(cp); // source string length
|
||||
|
||||
if ( nStrLen == 0 // empty string
|
||||
// precisition integer contain only these numbers
|
||||
|| _tcsspn(cp,_T("0123456789+-")) != (SIZE_T) nStrLen)
|
||||
return 0;
|
||||
|
||||
bySign = (*cp != _T('-')) ? 0 : 9; // set sign nibble
|
||||
if (*cp == _T('-') || *cp == _T('+')) // skip sign character
|
||||
{
|
||||
++cp;
|
||||
--nStrLen;
|
||||
}
|
||||
|
||||
if (nStrLen == 1 && *cp == _T('0')) // special code for zero
|
||||
{
|
||||
*pbyNum = 0; // zero data
|
||||
return 1; // finish
|
||||
}
|
||||
|
||||
// nStrLen = no. of digits without sign
|
||||
if (nStrLen >= nSize) // destination buffer too small
|
||||
return 0;
|
||||
|
||||
nNumSize = nStrLen + 1; // no. of written data
|
||||
|
||||
while (--nStrLen >= 0) // eval all digits
|
||||
{
|
||||
TCHAR c = cp[nStrLen];
|
||||
|
||||
// only '0' .. '9' are valid here
|
||||
if (!((c >= _T('0')) || (c <= _T('9'))))
|
||||
return 0;
|
||||
|
||||
c -= _T('0');
|
||||
*pbyNum++ = (BYTE) c;
|
||||
}
|
||||
*pbyNum = bySign; // add sign
|
||||
|
||||
return nNumSize;
|
||||
}
|
||||
|
||||
static INT RPL_SetZInt(LPCTSTR cp,LPBYTE pbyNum,INT nSize)
|
||||
{
|
||||
LPTSTR pszData;
|
||||
|
||||
INT s = 0;
|
||||
|
||||
if ((pszData = Trim(cp)) != NULL) // create a trimmed working copy of the string
|
||||
{
|
||||
s = SetZInt(pszData,pbyNum,nSize);
|
||||
free(pszData);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static INT RPL_GetBcd(BYTE CONST *pbyNum,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPTSTR cp,INT nSize)
|
||||
{
|
||||
BYTE byNib;
|
||||
LONG v,lExp;
|
||||
BOOL bPflag,bExpflag;
|
||||
INT i;
|
||||
|
||||
lExp = 0;
|
||||
for (v = 1; nExpLen--; v *= 10) // fetch exponent
|
||||
{
|
||||
lExp += (LONG) *pbyNum++ * v; // calc. exponent
|
||||
}
|
||||
|
||||
if (lExp > v / 2) lExp -= v; // negative exponent
|
||||
|
||||
lExp -= nMantLen - 1; // set decimal point to end of mantissa
|
||||
|
||||
i = 0; // first character
|
||||
bPflag = FALSE; // show no decimal point
|
||||
bExpflag = FALSE; // show no exponent
|
||||
|
||||
// scan mantissa
|
||||
for (v = (LONG) nMantLen - 1; v >= 0 || bPflag; v--)
|
||||
{
|
||||
if (v >= 0L) // still mantissa digits left
|
||||
byNib = *pbyNum++;
|
||||
else
|
||||
byNib = 0; // zero for negativ exponent
|
||||
|
||||
if (!i) // still delete zeros at end
|
||||
{
|
||||
if (byNib == 0 && lExp && v > 0) // delete zeros
|
||||
{
|
||||
lExp++; // adjust exponent
|
||||
continue;
|
||||
}
|
||||
|
||||
// TRUE at x.E
|
||||
bExpflag = v + lExp >= nMantLen || lExp < -nMantLen;
|
||||
bPflag = !bExpflag && v < -lExp; // decimal point flag at neg. exponent
|
||||
}
|
||||
|
||||
// set decimal point
|
||||
if ((bExpflag && v == 0) || (!lExp && i))
|
||||
{
|
||||
if (i >= nSize) return 0; // dest buffer overflow
|
||||
cp[i++] = cDec; // write decimal point
|
||||
if (v < 0) // no mantissa digits any more
|
||||
{
|
||||
if (i >= nSize) return 0; // dest buffer overflow
|
||||
cp[i++] = _T('0'); // write heading zero
|
||||
}
|
||||
bPflag = FALSE; // finished with negativ exponents
|
||||
}
|
||||
|
||||
if (v >= 0 || bPflag)
|
||||
{
|
||||
if (i >= nSize) return 0; // dest buffer overflow
|
||||
cp[i++] = (TCHAR) byNib + _T('0'); // write character
|
||||
}
|
||||
|
||||
lExp++; // next position
|
||||
}
|
||||
|
||||
if (*pbyNum == 9) // negative number
|
||||
{
|
||||
if (i >= nSize) return 0; // dest buffer overflow
|
||||
cp[i++] = _T('-'); // write sign
|
||||
}
|
||||
|
||||
if (i >= nSize) return 0; // dest buffer overflow
|
||||
cp[i] = 0; // set EOS
|
||||
|
||||
for (v = 0; v < (i / 2); v++) // reverse string
|
||||
{
|
||||
TCHAR cNib = cp[v]; // swap chars
|
||||
cp[v] = cp[i-v-1];
|
||||
cp[i-v-1] = cNib;
|
||||
}
|
||||
|
||||
// write number with exponent
|
||||
if (bExpflag)
|
||||
{
|
||||
if (i + 5 >= nSize) return 0; // dest buffer overflow
|
||||
i += wsprintf(&cp[i],_T("E%d"),lExp-1);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static __inline INT SetBcd(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPBYTE pbyNum,INT nSize)
|
||||
{
|
||||
TCHAR cVc[] = _T(".0123456789eE+-");
|
||||
|
||||
BYTE byNum[80];
|
||||
INT i,nIp,nDp,nMaxExp;
|
||||
LONG lExp;
|
||||
|
||||
cVc[0] = cDec; // replace decimal char
|
||||
|
||||
if ( nMantLen + nExpLen >= nSize // destination buffer too small
|
||||
|| !*cp // empty string
|
||||
|| _tcsspn(cp,cVc) != (SIZE_T) lstrlen(cp) // real contain only these numbers
|
||||
|| (SIZE_T) lstrlen(cp) >= ARRAYSIZEOF(byNum)) // ignore too long reals
|
||||
return 0;
|
||||
|
||||
byNum[0] = (*cp != _T('-')) ? 0 : 9; // set sign nibble
|
||||
if (*cp == _T('-') || *cp == _T('+')) // skip sign character
|
||||
cp++;
|
||||
|
||||
// only '.', '0' .. '9' are valid here
|
||||
if (!((*cp == cDec) || (*cp >= _T('0')) || (*cp <= _T('9'))))
|
||||
return 0;
|
||||
|
||||
nIp = 0; // length of integer part
|
||||
if (*cp != cDec) // no decimal point
|
||||
{
|
||||
// count integer part
|
||||
while (*cp >= _T('0') && *cp <= _T('9'))
|
||||
byNum[++nIp] = *cp++ - _T('0');
|
||||
if (!nIp) return 0;
|
||||
}
|
||||
|
||||
// only '.', 'E', 'e' or end are valid here
|
||||
if (!(!*cp || (*cp == cDec) || (*cp == _T('E')) || (*cp == _T('e'))))
|
||||
return 0;
|
||||
|
||||
nDp = 0; // length of decimal part
|
||||
if (*cp == cDec) // decimal point
|
||||
{
|
||||
cp++; // skip '.'
|
||||
|
||||
// count decimal part
|
||||
while (*cp >= _T('0') && *cp <= _T('9'))
|
||||
byNum[nIp + ++nDp] = *cp++ - _T('0');
|
||||
}
|
||||
|
||||
// count number of heading zeros in mantissa
|
||||
for (i = 0; byNum[i+1] == 0 && i + 1 < nIp + nDp; ++i) { }
|
||||
|
||||
if (i > 0) // have to normalize
|
||||
{
|
||||
INT j;
|
||||
|
||||
nIp -= i; // for later ajust of exponent
|
||||
for (j = 1; j <= nIp + nDp; ++j) // normalize mantissa
|
||||
byNum[j] = byNum[j + i];
|
||||
}
|
||||
|
||||
if (byNum[1] == 0) // number is 0
|
||||
{
|
||||
ZeroMemory(pbyNum,nMantLen + nExpLen + 1);
|
||||
return nMantLen + nExpLen + 1;
|
||||
}
|
||||
|
||||
for (i = nIp + nDp; i < nMantLen;) // fill rest of mantissa with 0
|
||||
byNum[++i] = 0;
|
||||
|
||||
// must be 'E', 'e' or end
|
||||
if (!(!*cp || (*cp == _T('E')) || (*cp == _T('e'))))
|
||||
return 0;
|
||||
|
||||
lExp = 0;
|
||||
if (*cp == _T('E') || *cp == _T('e'))
|
||||
{
|
||||
cp++; // skip 'E'
|
||||
|
||||
i = FALSE; // positive exponent
|
||||
if (*cp == _T('-') || *cp == _T('+'))
|
||||
{
|
||||
i = (*cp++ == _T('-')); // adjust exponent sign
|
||||
}
|
||||
|
||||
// exponent symbol must be followed by number
|
||||
if (*cp < _T('0') || *cp > _T('9')) return 0;
|
||||
|
||||
while (*cp >= _T('0') && *cp <= _T('9'))
|
||||
lExp = lExp * 10 + *cp++ - _T('0');
|
||||
|
||||
if (i) lExp = -lExp;
|
||||
}
|
||||
|
||||
if (*cp != 0) return 0;
|
||||
|
||||
// adjust exponent value with exponent from normalized mantissa
|
||||
lExp += nIp - 1;
|
||||
|
||||
// calculate max. posive exponent
|
||||
for (nMaxExp = 5, i = 1; i < nExpLen; ++i)
|
||||
nMaxExp *= 10;
|
||||
|
||||
// check range of exponent
|
||||
if ((lExp < 0 && -lExp >= nMaxExp) || (lExp >= nMaxExp))
|
||||
return 0;
|
||||
|
||||
if (lExp < 0) lExp += 2 * nMaxExp; // adjust negative offset
|
||||
|
||||
for (i = nExpLen; i > 0; --i) // convert number into digits
|
||||
{
|
||||
byNum[nMantLen + i] = (BYTE) (lExp % 10);
|
||||
lExp /= 10;
|
||||
}
|
||||
|
||||
// copy to target in reversed order
|
||||
for (i = nMantLen + nExpLen; i >= 0; --i)
|
||||
*pbyNum++ = byNum[i];
|
||||
|
||||
return nMantLen + nExpLen + 1;
|
||||
}
|
||||
|
||||
static INT RPL_SetBcd(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPBYTE pbyNum,INT nSize)
|
||||
{
|
||||
LPTSTR pszData;
|
||||
|
||||
INT s = 0;
|
||||
|
||||
if ((pszData = Trim(cp)) != NULL) // create a trimmed working copy of the string
|
||||
{
|
||||
s = SetBcd(pszData,nMantLen,nExpLen,cDec,pbyNum,nSize);
|
||||
free(pszData);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static INT RPL_GetComplex(BYTE CONST *pbyNum,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPTSTR cp,INT nSize)
|
||||
{
|
||||
INT nLen,nPos;
|
||||
TCHAR cSep;
|
||||
|
||||
cSep = (cDec == _T('.')) // current separator
|
||||
? _T(',') // radix mark '.' -> ',' separator
|
||||
: _T(';'); // radix mark ',' -> ';' separator
|
||||
|
||||
nPos = 0; // write buffer position
|
||||
|
||||
if (nSize < 5) return 0; // target buffer to small
|
||||
nSize -= 4; // reserved room for (,)\0
|
||||
|
||||
cp[nPos++] = _T('('); // start of complex number
|
||||
|
||||
// real part
|
||||
nLen = RPL_GetBcd(pbyNum,nMantLen,nExpLen,cDec,&cp[1],nSize);
|
||||
if (nLen == 0) return 0; // target buffer to small
|
||||
|
||||
_ASSERT(nLen <= nSize);
|
||||
|
||||
nPos += nLen; // actual buffer postion
|
||||
nSize -= nLen; // remainder target buffer size
|
||||
|
||||
cp[nPos++] = cSep; // write of complex number seperator
|
||||
|
||||
// imaginary part
|
||||
nLen = RPL_GetBcd(&pbyNum[16],nMantLen,nExpLen,cDec,&cp[nPos],nSize);
|
||||
if (nLen == 0) return 0; // target buffer to small
|
||||
|
||||
nPos += nLen; // actual buffer postion
|
||||
|
||||
cp[nPos++] = _T(')'); // end of complex number
|
||||
cp[nPos] = 0; // EOS
|
||||
|
||||
_ASSERT(lstrlen(cp) == nPos);
|
||||
|
||||
return nPos;
|
||||
}
|
||||
|
||||
static INT RPL_SetComplex(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPBYTE pbyNum,INT nSize)
|
||||
{
|
||||
LPTSTR pcSep,pszData;
|
||||
INT nLen;
|
||||
TCHAR cSep;
|
||||
|
||||
nLen = 0; // read data length
|
||||
|
||||
cSep = (cDec == _T('.')) // current separator
|
||||
? _T(',') // radix mark '.' -> ',' separator
|
||||
: _T(';'); // radix mark ',' -> ';' separator
|
||||
|
||||
if ((pszData = Trim(cp)) != NULL) // create a trimmed working copy of the string
|
||||
{
|
||||
INT nStrLength = lstrlen(pszData); // string length
|
||||
|
||||
// complex number with brackets around
|
||||
if ( nStrLength > 0
|
||||
&& pszData[0] == _T('(')
|
||||
&& pszData[nStrLength - 1] == _T(')'))
|
||||
{
|
||||
pszData[--nStrLength] = 0; // replace ')' with EOS
|
||||
|
||||
// search for number separator
|
||||
if ((pcSep = _tcschr(pszData+1,cSep)) != NULL)
|
||||
{
|
||||
INT nLen1st;
|
||||
|
||||
*pcSep = 0; // set EOS for 1st substring
|
||||
|
||||
// decode 1st substring
|
||||
nLen1st = RPL_SetBcd(pszData+1,nMantLen,nExpLen,cDec,&pbyNum[0],nSize);
|
||||
if (nLen1st > 0)
|
||||
{
|
||||
// decode 2nd substring
|
||||
nLen = RPL_SetBcd(pcSep+1,nMantLen,nExpLen,cDec,&pbyNum[nMantLen+nExpLen+1],nSize-nLen1st);
|
||||
if (nLen > 0)
|
||||
{
|
||||
nLen += nLen1st; // complete Bcd length
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(pszData);
|
||||
}
|
||||
return nLen;
|
||||
}
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Object subroutines
|
||||
//#
|
||||
//################
|
||||
|
||||
static TCHAR GetRadix(VOID)
|
||||
{
|
||||
// get locale decimal point
|
||||
// GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SDECIMAL,&cDecimal,1);
|
||||
|
||||
return RPL_GetSystemFlag(fnRadix) ? _T(',') : _T('.');
|
||||
}
|
||||
|
||||
static INT DoInt(DWORD dwAddress,LPTSTR cp,INT nSize)
|
||||
{
|
||||
LPBYTE lpbyData;
|
||||
INT nLength,nIntLen;
|
||||
|
||||
nIntLen = Read5(dwAddress) - 5; // no. of digits
|
||||
if (nIntLen <= 0) return 0; // error in calculator object
|
||||
|
||||
nLength = 0;
|
||||
if ((lpbyData = (LPBYTE) malloc(nIntLen)))
|
||||
{
|
||||
// get precisition integer object content and decode it
|
||||
Npeek(lpbyData,dwAddress+5,nIntLen);
|
||||
nLength = RPL_GetZInt(lpbyData,nIntLen,cp,nSize);
|
||||
free(lpbyData);
|
||||
}
|
||||
return nLength;
|
||||
}
|
||||
|
||||
static INT DoReal(DWORD dwAddress,LPTSTR cp,INT nSize)
|
||||
{
|
||||
BYTE byNumber[16];
|
||||
|
||||
// get real object content and decode it
|
||||
Npeek(byNumber,dwAddress,ARRAYSIZEOF(byNumber));
|
||||
return RPL_GetBcd(byNumber,12,3,GetRadix(),cp,nSize);
|
||||
}
|
||||
|
||||
static INT DoComplex(DWORD dwAddress,LPTSTR cp,INT nSize)
|
||||
{
|
||||
BYTE byNumber[32];
|
||||
|
||||
// get complex object content and decode it
|
||||
Npeek(byNumber,dwAddress,ARRAYSIZEOF(byNumber));
|
||||
return RPL_GetComplex(byNumber,12,3,GetRadix(),cp,nSize);
|
||||
}
|
||||
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Stack routines
|
||||
//#
|
||||
//################
|
||||
|
||||
//
|
||||
// ID_STACK_COPY
|
||||
//
|
||||
LRESULT OnStackCopy(VOID) // copy data from stack
|
||||
{
|
||||
TCHAR cBuffer[128];
|
||||
HANDLE hClipObj;
|
||||
LPBYTE lpbyData;
|
||||
DWORD dwAddress,dwObject,dwSize;
|
||||
UINT uClipboardFormat;
|
||||
|
||||
_ASSERT(nState == SM_RUN); // emulator must be in RUN state
|
||||
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
|
||||
{
|
||||
InfoMessage(_T("The emulator is busy."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ASSERT(nState == SM_SLEEP);
|
||||
|
||||
if ((dwAddress = RPL_Pick(1)) == 0) // pick address of level1 object
|
||||
{
|
||||
MessageBeep(MB_OK); // error beep
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (dwObject = Read5(dwAddress)) // select object
|
||||
{
|
||||
case DOINT: // Precision Integer (HP49G)
|
||||
case DOREAL: // real object
|
||||
case DOCMP: // complex object
|
||||
dwAddress += 5; // object content
|
||||
|
||||
switch (dwObject)
|
||||
{
|
||||
case DOINT: // Precision Integer (HP49G)
|
||||
// get precision integer object content and decode it
|
||||
dwSize = DoInt(dwAddress,cBuffer,ARRAYSIZEOF(cBuffer));
|
||||
break;
|
||||
case DOREAL: // real object
|
||||
// get real object content and decode it
|
||||
dwSize = DoReal(dwAddress,cBuffer,ARRAYSIZEOF(cBuffer));
|
||||
break;
|
||||
case DOCMP: // complex object
|
||||
// get complex object content and decode it
|
||||
dwSize = DoComplex(dwAddress,cBuffer,ARRAYSIZEOF(cBuffer));
|
||||
break;
|
||||
}
|
||||
|
||||
// calculate buffer size
|
||||
dwSize = (dwSize + 1) * sizeof(*cBuffer);
|
||||
|
||||
// memory allocation for clipboard data
|
||||
if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,dwSize)) == NULL)
|
||||
goto error;
|
||||
|
||||
if ((lpbyData = (LPBYTE) GlobalLock(hClipObj)))
|
||||
{
|
||||
// copy data to memory
|
||||
CopyMemory(lpbyData,cBuffer,dwSize);
|
||||
GlobalUnlock(hClipObj); // unlock memory
|
||||
}
|
||||
|
||||
#if defined _UNICODE
|
||||
uClipboardFormat = CF_UNICODETEXT;
|
||||
#else
|
||||
uClipboardFormat = CF_TEXT;
|
||||
#endif
|
||||
break;
|
||||
case DOCSTR: // string
|
||||
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 ((lpbyData = (LPBYTE) GlobalLock(hClipObj))) // lock memory
|
||||
{
|
||||
// copy data into clipboard buffer
|
||||
for (dwAddress += 5;dwSize-- > 0;dwAddress += 2,++lpbyData)
|
||||
*lpbyData = Read2(dwAddress);
|
||||
*lpbyData = 0; // set EOS
|
||||
|
||||
GlobalUnlock(hClipObj); // unlock memory
|
||||
}
|
||||
uClipboardFormat = CF_TEXT; // always text
|
||||
break;
|
||||
default:
|
||||
MessageBeep(MB_OK); // error beep
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (OpenClipboard(hWnd))
|
||||
{
|
||||
if (EmptyClipboard())
|
||||
SetClipboardData(uClipboardFormat,hClipObj);
|
||||
else
|
||||
GlobalFree(hClipObj);
|
||||
CloseClipboard();
|
||||
}
|
||||
else // clipboard open failed
|
||||
{
|
||||
GlobalFree(hClipObj);
|
||||
}
|
||||
|
||||
error:
|
||||
SwitchToState(SM_RUN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// ID_STACK_PASTE
|
||||
//
|
||||
LRESULT OnStackPaste(VOID) // paste data to stack
|
||||
{
|
||||
#if defined _UNICODE
|
||||
#define CF_TEXTFORMAT CF_UNICODETEXT
|
||||
#else
|
||||
#define CF_TEXTFORMAT CF_TEXT
|
||||
#endif
|
||||
|
||||
HANDLE hClipObj;
|
||||
|
||||
BOOL bSuccess = FALSE;
|
||||
|
||||
// check if clipboard format is available
|
||||
if (!IsClipboardFormatAvailable(CF_TEXTFORMAT))
|
||||
{
|
||||
MessageBeep(MB_OK); // error beep
|
||||
return 0;
|
||||
}
|
||||
|
||||
SuspendDebugger(); // suspend debugger
|
||||
bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control
|
||||
|
||||
// calculator off, turn on
|
||||
if (!(Chipset.IORam[BITOFFSET]&DON))
|
||||
{
|
||||
KeyboardEvent(TRUE,0,0x8000);
|
||||
Sleep(dwWakeupDelay);
|
||||
KeyboardEvent(FALSE,0,0x8000);
|
||||
|
||||
// wait for sleep mode
|
||||
while (Chipset.Shutdn == FALSE) Sleep(0);
|
||||
}
|
||||
|
||||
_ASSERT(nState == SM_RUN); // emulator must be in RUN state
|
||||
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
|
||||
{
|
||||
InfoMessage(_T("The emulator is busy."));
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
_ASSERT(nState == SM_SLEEP);
|
||||
|
||||
if (OpenClipboard(hWnd))
|
||||
{
|
||||
if ((hClipObj = GetClipboardData(CF_TEXTFORMAT)))
|
||||
{
|
||||
LPCTSTR lpstrClipdata;
|
||||
LPBYTE lpbyData;
|
||||
|
||||
if ((lpstrClipdata = (LPCTSTR) GlobalLock(hClipObj)))
|
||||
{
|
||||
BYTE byNumber[128];
|
||||
DWORD dwAddress;
|
||||
INT s;
|
||||
|
||||
do
|
||||
{
|
||||
if (bDetectClpObject) // autodetect clipboard object enabled
|
||||
{
|
||||
// HP49G or HP49G+ in exact mode
|
||||
if ( (cCurrentRomType == 'X' || cCurrentRomType == 'Q')
|
||||
&& !RPL_GetSystemFlag(fnApprox))
|
||||
{
|
||||
// try to convert string to HP49 precision integer
|
||||
s = RPL_SetZInt(lpstrClipdata,byNumber,sizeof(byNumber));
|
||||
|
||||
if (s > 0) // is a real number for exact mode
|
||||
{
|
||||
// get TEMPOB memory for HP49 precision integer object
|
||||
dwAddress = RPL_CreateTemp(s+5+5,TRUE);
|
||||
if ((bSuccess = (dwAddress > 0)))
|
||||
{
|
||||
Write5(dwAddress,DOINT); // prolog
|
||||
Write5(dwAddress+5,s+5); // size
|
||||
Nwrite(byNumber,dwAddress+10,s); // data
|
||||
|
||||
// push object to stack
|
||||
RPL_Push(1,dwAddress);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// try to convert string to real format
|
||||
_ASSERT(16 <= ARRAYSIZEOF(byNumber));
|
||||
s = RPL_SetBcd(lpstrClipdata,12,3,GetRadix(),byNumber,sizeof(byNumber));
|
||||
|
||||
if (s > 0) // is a real number
|
||||
{
|
||||
_ASSERT(s == 16); // length of real number BCD coded
|
||||
|
||||
// get TEMPOB memory for real object
|
||||
dwAddress = RPL_CreateTemp(16+5,TRUE);
|
||||
if ((bSuccess = (dwAddress > 0)))
|
||||
{
|
||||
Write5(dwAddress,DOREAL); // prolog
|
||||
Nwrite(byNumber,dwAddress+5,s); // data
|
||||
|
||||
// push object to stack
|
||||
RPL_Push(1,dwAddress);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// try to convert string to complex format
|
||||
_ASSERT(32 <= ARRAYSIZEOF(byNumber));
|
||||
s = RPL_SetComplex(lpstrClipdata,12,3,GetRadix(),byNumber,sizeof(byNumber));
|
||||
|
||||
if (s > 0) // is a real complex
|
||||
{
|
||||
_ASSERT(s == 32); // length of complex number BCD coded
|
||||
|
||||
// get TEMPOB memory for complex object
|
||||
dwAddress = RPL_CreateTemp(16+16+5,TRUE);
|
||||
if ((bSuccess = (dwAddress > 0)))
|
||||
{
|
||||
Write5(dwAddress,DOCMP); // prolog
|
||||
Nwrite(byNumber,dwAddress+5,s); // data
|
||||
|
||||
// push object to stack
|
||||
RPL_Push(1,dwAddress);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// any other format
|
||||
{
|
||||
DWORD dwSize = lstrlen(lpstrClipdata);
|
||||
if ((lpbyData = (LPBYTE) malloc(dwSize * 2)))
|
||||
{
|
||||
LPBYTE lpbySrc,lpbyDest;
|
||||
DWORD dwLoop;
|
||||
|
||||
#if defined _UNICODE
|
||||
// copy data UNICODE -> ASCII
|
||||
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,
|
||||
lpstrClipdata, dwSize,
|
||||
(LPSTR) lpbyData+dwSize, dwSize, NULL, NULL);
|
||||
#else
|
||||
// copy data
|
||||
memcpy(lpbyData+dwSize,lpstrClipdata,dwSize);
|
||||
#endif
|
||||
|
||||
// unpack data
|
||||
lpbySrc = lpbyData+dwSize;
|
||||
lpbyDest = lpbyData;
|
||||
dwLoop = dwSize;
|
||||
while (dwLoop-- > 0)
|
||||
{
|
||||
BYTE byTwoNibs = *lpbySrc++;
|
||||
*lpbyDest++ = (BYTE) (byTwoNibs & 0xF);
|
||||
*lpbyDest++ = (BYTE) (byTwoNibs >> 4);
|
||||
}
|
||||
|
||||
dwSize *= 2; // size in nibbles
|
||||
|
||||
// get TEMPOB memory for string object
|
||||
dwAddress = RPL_CreateTemp(dwSize+10,TRUE);
|
||||
if ((bSuccess = (dwAddress > 0)))
|
||||
{
|
||||
Write5(dwAddress,DOCSTR); // String
|
||||
Write5(dwAddress+5,dwSize+5); // length of String
|
||||
Nwrite(lpbyData,dwAddress+10,dwSize); // data
|
||||
|
||||
// push object to stack
|
||||
RPL_Push(1,dwAddress);
|
||||
}
|
||||
free(lpbyData);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (FALSE);
|
||||
|
||||
GlobalUnlock(hClipObj);
|
||||
}
|
||||
}
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
SwitchToState(SM_RUN); // run state
|
||||
while (nState!=nNextState) Sleep(0);
|
||||
_ASSERT(nState == SM_RUN);
|
||||
|
||||
if (bSuccess == FALSE) // data not copied
|
||||
goto cancel;
|
||||
|
||||
KeyboardEvent(TRUE,0,0x8000);
|
||||
Sleep(dwWakeupDelay);
|
||||
KeyboardEvent(FALSE,0,0x8000);
|
||||
|
||||
// wait for sleep mode
|
||||
while (Chipset.Shutdn == FALSE) Sleep(0);
|
||||
|
||||
cancel:
|
||||
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
|
||||
ResumeDebugger();
|
||||
return 0;
|
||||
#undef CF_TEXTFORMAT
|
||||
}
|
257
app/src/main/cpp/SYMBFILE.C
Normal file
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
* symbfile.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2008 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
|
||||
//################
|
||||
//#
|
||||
//# Saturn Object File Reading
|
||||
//#
|
||||
//################
|
||||
|
||||
#define RECORD_BLOCK 256 // block size
|
||||
#define OS_RESOLVED 0x8000 // resolved symbol
|
||||
#define OS_RELOCATABLE 0x4000 // relocatable symbol
|
||||
|
||||
#define SAT_ID "Saturn3" // saturn block header
|
||||
#define SYMB_ID "Symb" // symbol block header
|
||||
|
||||
#define HASHENTRIES 199 // size of hash table
|
||||
|
||||
typedef struct _REFDATA
|
||||
{
|
||||
LPTSTR lpszName; // symbol name
|
||||
DWORD dwAddr; // resolved address
|
||||
struct _REFDATA* pNext;
|
||||
} REFDATA, *PREFDATA;
|
||||
|
||||
static PREFDATA ppsBase[HASHENTRIES]; // base of symbol references (initialized with NULL)
|
||||
|
||||
static __inline DWORD GetHash(DWORD dwVal)
|
||||
{
|
||||
return dwVal % HASHENTRIES; // hash function
|
||||
}
|
||||
|
||||
static DWORD GetBigEndian(LPBYTE pbyData, INT nSize)
|
||||
{
|
||||
DWORD dwVal = 0;
|
||||
|
||||
while (nSize-- > 0)
|
||||
{
|
||||
dwVal <<= 8;
|
||||
dwVal += *pbyData++;
|
||||
}
|
||||
return dwVal;
|
||||
}
|
||||
|
||||
//
|
||||
// check if entry table is empty
|
||||
//
|
||||
BOOL RplTableEmpty(VOID)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
BOOL bEmpty = TRUE;
|
||||
|
||||
// check if hash table is empty
|
||||
for (i = 0; bEmpty && i < ARRAYSIZEOF(ppsBase); ++i)
|
||||
{
|
||||
bEmpty = (ppsBase[i] == NULL); // check if empty
|
||||
}
|
||||
return bEmpty;
|
||||
}
|
||||
|
||||
//
|
||||
// load entry table
|
||||
//
|
||||
BOOL RplLoadTable(LPCTSTR lpszFilename)
|
||||
{
|
||||
BYTE byPage[RECORD_BLOCK]; // record page size
|
||||
HANDLE hFile;
|
||||
DWORD dwFileLength,dwCodeLength,dwNoSymbols,dwNoReferences;
|
||||
DWORD dwFilePos,dwBytesRead,dwSymb,dwPageIndex,dwResolvedSymb;
|
||||
BOOL bSymbol,bSucc;
|
||||
|
||||
bSucc = FALSE;
|
||||
|
||||
hFile = CreateFile(lpszFilename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
dwResolvedSymb = 0; // no resolved symbols added
|
||||
bSymbol = TRUE; // next set is a symbol
|
||||
|
||||
// read first page
|
||||
ReadFile(hFile,byPage,sizeof(byPage),&dwBytesRead,NULL);
|
||||
if (dwBytesRead == sizeof(byPage) && memcmp(byPage,SAT_ID,7) == 0)
|
||||
{
|
||||
// file length in bytes
|
||||
dwFileLength = GetBigEndian(byPage+7,sizeof(WORD)) * sizeof(byPage);
|
||||
|
||||
// code area in nibbles
|
||||
dwCodeLength = GetBigEndian(byPage+9,sizeof(DWORD));
|
||||
|
||||
// no. of symbols & references
|
||||
dwNoSymbols = GetBigEndian(byPage+13,sizeof(WORD));
|
||||
|
||||
// no. of references
|
||||
dwNoReferences = GetBigEndian(byPage+15,sizeof(WORD));
|
||||
|
||||
// convert code area length into no. of pages
|
||||
dwPageIndex = (dwCodeLength + (2 * sizeof(byPage) - 1)) / (2 * sizeof(byPage));
|
||||
|
||||
// calculate no. of code pages
|
||||
dwFilePos = dwPageIndex * sizeof(byPage);
|
||||
|
||||
// jump to begin of symbols by skipping no. of code pages
|
||||
bSucc = SetFilePointer(hFile,dwFilePos,NULL,FILE_CURRENT) != INVALID_SET_FILE_POINTER;
|
||||
|
||||
dwFilePos += sizeof(byPage); // actual file position
|
||||
}
|
||||
|
||||
// read all symbol pages
|
||||
for (dwPageIndex = 256, dwSymb = 0; bSucc && dwSymb < dwNoSymbols; dwPageIndex += 42)
|
||||
{
|
||||
if (dwPageIndex >= 256) // read complete page
|
||||
{
|
||||
// read new symbol page
|
||||
ReadFile(hFile,byPage,sizeof(byPage),&dwBytesRead,NULL);
|
||||
dwFilePos += dwBytesRead; // update file position
|
||||
if ( dwFilePos > dwFileLength
|
||||
|| dwBytesRead != sizeof(byPage)
|
||||
|| memcmp(byPage,SYMB_ID,4) != 0)
|
||||
{
|
||||
bSucc = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
dwPageIndex = 4; // begin of new symbol
|
||||
}
|
||||
|
||||
if (bSymbol) // this is the 42 byte symbol set
|
||||
{
|
||||
WORD wSymbolType = (WORD) GetBigEndian(byPage+dwPageIndex+36,sizeof(WORD));
|
||||
|
||||
// check if it's a resolved or relocatable symbol
|
||||
bSymbol = (wSymbolType & OS_RESOLVED) != 0;
|
||||
|
||||
if (bSymbol) ++dwResolvedSymb; // added resolved symbol
|
||||
|
||||
if (wSymbolType == OS_RESOLVED) // resolved symbol type
|
||||
{
|
||||
TCHAR szSymbolName[36+1],*pcPtr;
|
||||
PREFDATA pData;
|
||||
DWORD dwHash;
|
||||
|
||||
#if defined _UNICODE
|
||||
{
|
||||
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,(LPCSTR)byPage+dwPageIndex,36,
|
||||
szSymbolName,ARRAYSIZEOF(szSymbolName));
|
||||
szSymbolName[36] = 0; // set EOS
|
||||
}
|
||||
#else
|
||||
{
|
||||
lstrcpyn(szSymbolName,(LPCSTR)byPage+dwPageIndex,ARRAYSIZEOF(szSymbolName));
|
||||
}
|
||||
#endif
|
||||
|
||||
// cut symbol name at first space character
|
||||
if ((pcPtr = _tcschr(szSymbolName,_T(' '))) != NULL)
|
||||
*pcPtr = 0; // set EOS
|
||||
|
||||
// allocate symbol memory
|
||||
VERIFY(pData = (PREFDATA) malloc(sizeof(*pData)));
|
||||
pData->lpszName = DuplicateString(szSymbolName);
|
||||
pData->dwAddr = GetBigEndian(byPage+dwPageIndex+38,sizeof(DWORD));
|
||||
|
||||
// add to hash table
|
||||
dwHash = GetHash(pData->dwAddr);
|
||||
pData->pNext = ppsBase[dwHash];
|
||||
ppsBase[dwHash] = pData;
|
||||
}
|
||||
|
||||
++dwSymb; // got symbol
|
||||
}
|
||||
else // 42 byte fill reference
|
||||
{
|
||||
bSymbol = TRUE; // nothing to do, next is a symbol set
|
||||
}
|
||||
}
|
||||
|
||||
bSucc = bSucc && (dwFilePos <= dwFileLength)
|
||||
&& (dwNoSymbols == (dwResolvedSymb + dwNoReferences));
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
if (!bSucc) RplDeleteTable(); // delete current table
|
||||
return bSucc;
|
||||
}
|
||||
|
||||
//
|
||||
// delete entry table
|
||||
//
|
||||
VOID RplDeleteTable(VOID)
|
||||
{
|
||||
PREFDATA pData;
|
||||
DWORD i;
|
||||
|
||||
// clear hash entries
|
||||
for (i = 0; i < ARRAYSIZEOF(ppsBase); ++i)
|
||||
{
|
||||
while (ppsBase[i] != NULL) // walk through all datasets
|
||||
{
|
||||
pData = ppsBase[i]->pNext;
|
||||
free(ppsBase[i]->lpszName);
|
||||
free(ppsBase[i]);
|
||||
ppsBase[i] = pData;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// return name for given entry address
|
||||
//
|
||||
LPCTSTR RplGetName(DWORD dwAddr)
|
||||
{
|
||||
PREFDATA pData = ppsBase[GetHash(dwAddr)];
|
||||
|
||||
// walk through all datasets of hash entry
|
||||
for (; pData != NULL; pData = pData->pNext)
|
||||
{
|
||||
if (pData->dwAddr == dwAddr) // found address
|
||||
return pData->lpszName; // return symbol name
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// return entry address for given name
|
||||
//
|
||||
BOOL RplGetAddr(LPCTSTR lpszName, DWORD *pdwAddr)
|
||||
{
|
||||
PREFDATA pData;
|
||||
DWORD i;
|
||||
|
||||
// check for every dataset in hash table
|
||||
for (i = 0; i < ARRAYSIZEOF(ppsBase); ++i)
|
||||
{
|
||||
// walk through all datasets of hash entry
|
||||
for (pData = ppsBase[i]; pData != NULL; pData = pData->pNext)
|
||||
{
|
||||
// found symbol name
|
||||
if (lstrcmp(lpszName,pData->lpszName) == 0)
|
||||
{
|
||||
*pdwAddr = pData->dwAddr; // return address
|
||||
return FALSE; // found
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE; // not found
|
||||
}
|
435
app/src/main/cpp/TIMER.C
Normal file
|
@ -0,0 +1,435 @@
|
|||
/*
|
||||
* timer.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1995 Sebastien Carlier
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
#include "ops.h"
|
||||
#include "io.h" // I/O definitions
|
||||
|
||||
#define AUTO_OFF 10 // Time in minutes for 'auto off'
|
||||
|
||||
// Ticks for 'auto off'
|
||||
#define OFF_TIME ((ULONGLONG) (AUTO_OFF * 60) << 13)
|
||||
|
||||
// memory address for clock and auto off
|
||||
// S(X) = 0x70052-0x70070, G(X) = 0x80058-0x80076, 49G = 0x80058-0x80076
|
||||
#define RPLTIME ((cCurrentRomType=='S')?0x52:0x58)
|
||||
|
||||
#define T1_FREQ 62 // Timer1 1/frequency in ms
|
||||
#define T2_FREQ 8192 // Timer2 frequency
|
||||
|
||||
static BOOL bStarted = FALSE;
|
||||
static BOOL bOutRange = FALSE; // flag if timer value out of range
|
||||
static UINT uT1TimerId = 0;
|
||||
static UINT uT2TimerId = 0;
|
||||
|
||||
static BOOL bNINT2T1 = FALSE; // state of NINT2 affected from timer1
|
||||
static BOOL bNINT2T2 = FALSE; // state of NINT2 affected from timer2
|
||||
|
||||
static BOOL bAccurateTimer; // flag if accurate timer is used
|
||||
static LARGE_INTEGER lT2Ref; // counter value at timer2 start
|
||||
static TIMECAPS tc; // timer information
|
||||
static UINT uT2MaxTicks; // max. timer2 ticks handled by one timer event
|
||||
|
||||
static DWORD dwT2Ref; // timer2 value at last timer2 access
|
||||
static DWORD dwT2Cyc; // cpu cycle counter at last timer2 access
|
||||
|
||||
static void CALLBACK TimeProc(UINT uEventId, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2);
|
||||
|
||||
static DWORD CalcT2(VOID) // calculate timer2 value
|
||||
{
|
||||
DWORD dwT2 = Chipset.t2; // get value from chipset
|
||||
if (bStarted) // timer2 running
|
||||
{
|
||||
LARGE_INTEGER lT2Act;
|
||||
DWORD dwT2Dif;
|
||||
|
||||
// timer should run a little bit faster (10%) than maschine in authentic speed mode
|
||||
DWORD dwCycPerTick = (9 * T2CYCLES) / 5;
|
||||
|
||||
QueryPerformanceCounter(&lT2Act); // actual time
|
||||
// calculate realtime timer2 ticks since reference point
|
||||
dwT2 -= (DWORD)
|
||||
(((lT2Act.QuadPart - lT2Ref.QuadPart) * T2_FREQ)
|
||||
/ lFreq.QuadPart);
|
||||
|
||||
dwT2Dif = dwT2Ref - dwT2; // timer2 ticks since last request
|
||||
|
||||
// checking if the MSB of dwT2Dif can be used as sign flag
|
||||
_ASSERT((DWORD) tc.wPeriodMax < ((1<<(sizeof(dwT2Dif)*8-1))/8192)*1000);
|
||||
|
||||
// 2nd timer call in a 32ms time frame or elapsed time is negative (Win2k bug)
|
||||
if (!Chipset.Shutdn && ((dwT2Dif > 0x01 && dwT2Dif <= 0x100) || (dwT2Dif & 0x80000000) != 0))
|
||||
{
|
||||
DWORD dwT2Ticks = ((DWORD) (Chipset.cycles & 0xFFFFFFFF) - dwT2Cyc) / dwCycPerTick;
|
||||
|
||||
// estimated < real elapsed timer2 ticks or negative time
|
||||
if (dwT2Ticks < dwT2Dif || (dwT2Dif & 0x80000000) != 0)
|
||||
{
|
||||
// real time too long or got negative time elapsed
|
||||
dwT2 = dwT2Ref - dwT2Ticks; // estimated timer2 value from CPU cycles
|
||||
dwT2Cyc += dwT2Ticks * dwCycPerTick; // estimated CPU cycles for the timer2 ticks
|
||||
}
|
||||
else
|
||||
{
|
||||
// reached actual time -> new synchronizing
|
||||
dwT2Cyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF) - dwCycPerTick;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// valid actual time -> new synchronizing
|
||||
dwT2Cyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF) - dwCycPerTick;
|
||||
}
|
||||
|
||||
// check if timer2 interrupt is active -> no timer2 value below 0xFFFFFFFF
|
||||
if ( Chipset.inte
|
||||
&& (dwT2 & 0x80000000) != 0
|
||||
&& (!Chipset.Shutdn || (Chipset.IORam[TIMER2_CTRL]&WKE))
|
||||
&& (Chipset.IORam[TIMER2_CTRL]&INTR)
|
||||
)
|
||||
{
|
||||
dwT2 = 0xFFFFFFFF;
|
||||
dwT2Cyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF) - dwCycPerTick;
|
||||
}
|
||||
|
||||
dwT2Ref = dwT2; // new reference time
|
||||
}
|
||||
return dwT2;
|
||||
}
|
||||
|
||||
static VOID CheckT1(BYTE nT1)
|
||||
{
|
||||
// implementation of TSRQ
|
||||
bNINT2T1 = (Chipset.IORam[TIMER1_CTRL]&INTR) != 0 && (nT1&8) != 0;
|
||||
IOBit(SRQ1,TSRQ,bNINT2T1 || bNINT2T2);
|
||||
|
||||
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 and INT or WAKE bit is set
|
||||
if ((Chipset.IORam[TIMER1_CTRL]&(WKE|INTR)) != 0)
|
||||
Chipset.IORam[TIMER1_CTRL] |= SRQ; // set SRQ
|
||||
// cpu not sleeping and T1 -> Interrupt
|
||||
if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER1_CTRL]&WKE))
|
||||
&& (Chipset.IORam[TIMER1_CTRL]&INTR))
|
||||
{
|
||||
Chipset.SoftInt = TRUE;
|
||||
bInterrupt = TRUE;
|
||||
}
|
||||
// cpu sleeping and T1 -> Wake Up
|
||||
if (Chipset.Shutdn && (Chipset.IORam[TIMER1_CTRL]&WKE))
|
||||
{
|
||||
Chipset.IORam[TIMER1_CTRL] &= ~WKE; // clear WKE bit
|
||||
Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode
|
||||
SetEvent(hEventShutdn); // wake up emulation thread
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static VOID CheckT2(DWORD dwT2)
|
||||
{
|
||||
// implementation of TSRQ
|
||||
bNINT2T2 = (Chipset.IORam[TIMER2_CTRL]&INTR) != 0 && (dwT2&0x80000000) != 0;
|
||||
IOBit(SRQ1,TSRQ,bNINT2T1 || bNINT2T2);
|
||||
|
||||
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 and INT or WAKE bit is set
|
||||
if ((Chipset.IORam[TIMER2_CTRL]&(WKE|INTR)) != 0)
|
||||
Chipset.IORam[TIMER2_CTRL] |= SRQ; // set SRQ
|
||||
// cpu not sleeping and T2 -> Interrupt
|
||||
if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER2_CTRL]&WKE))
|
||||
&& (Chipset.IORam[TIMER2_CTRL]&INTR))
|
||||
{
|
||||
Chipset.SoftInt = TRUE;
|
||||
bInterrupt = TRUE;
|
||||
}
|
||||
// cpu sleeping and T2 -> Wake Up
|
||||
if (Chipset.Shutdn && (Chipset.IORam[TIMER2_CTRL]&WKE))
|
||||
{
|
||||
Chipset.IORam[TIMER2_CTRL] &= ~WKE; // clear WKE bit
|
||||
Chipset.bShutdnWake = TRUE; // wake up from SHUTDN mode
|
||||
SetEvent(hEventShutdn); // wake up emulation thread
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static VOID RescheduleT2(BOOL bRefPoint)
|
||||
{
|
||||
UINT uDelay;
|
||||
_ASSERT(uT2TimerId == 0); // timer2 must stopped
|
||||
if (bRefPoint) // save reference time
|
||||
{
|
||||
dwT2Ref = Chipset.t2; // timer2 value at last timer2 access
|
||||
dwT2Cyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF); // cpu cycle counter at last timer2 access
|
||||
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
|
||||
}
|
||||
if ((bOutRange = uDelay > uT2MaxTicks)) // delay greater maximum delay
|
||||
uDelay = uT2MaxTicks; // wait maximum delay time
|
||||
uDelay = (uDelay * 125 + 1023) / 1024; // timer delay in ms (1000/8192 = 125/1024)
|
||||
uDelay = __max(tc.wPeriodMin,uDelay); // wait minimum delay of timer
|
||||
_ASSERT(uDelay <= tc.wPeriodMax); // inside maximum event delay
|
||||
// start timer2; schedule event, when Chipset.t2 will be zero
|
||||
VERIFY(uT2TimerId = timeSetEvent(uDelay,0,&TimeProc,2,TIME_ONESHOT));
|
||||
return;
|
||||
}
|
||||
|
||||
static VOID AbortT2(VOID)
|
||||
{
|
||||
_ASSERT(uT2TimerId);
|
||||
timeKillEvent(uT2TimerId); // kill event
|
||||
uT2TimerId = 0; // then reset var
|
||||
return;
|
||||
}
|
||||
|
||||
static void CALLBACK TimeProc(UINT uEventId, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
|
||||
{
|
||||
if (uEventId == 0) return; // illegal EventId
|
||||
|
||||
if (uEventId == uT1TimerId) // called from timer1 event (default period 16 Hz)
|
||||
{
|
||||
EnterCriticalSection(&csT1Lock);
|
||||
{
|
||||
Chipset.t1 = (Chipset.t1-1)&0xF;// decrement timer value
|
||||
CheckT1(Chipset.t1); // test timer1 control bits
|
||||
}
|
||||
LeaveCriticalSection(&csT1Lock);
|
||||
return;
|
||||
}
|
||||
if (uEventId == uT2TimerId) // called from timer2 event, Chipset.t2 should be zero
|
||||
{
|
||||
EnterCriticalSection(&csT2Lock);
|
||||
{
|
||||
uT2TimerId = 0; // single shot timer timer2 stopped
|
||||
if (!bOutRange) // timer event elapsed
|
||||
{
|
||||
// timer2 overrun, test timer2 control bits else restart timer2
|
||||
Chipset.t2 = CalcT2(); // calculate new timer2 value
|
||||
CheckT2(Chipset.t2); // test timer2 control bits
|
||||
}
|
||||
RescheduleT2(!bOutRange); // restart timer2
|
||||
}
|
||||
LeaveCriticalSection(&csT2Lock);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
UNREFERENCED_PARAMETER(uMsg);
|
||||
UNREFERENCED_PARAMETER(dwUser);
|
||||
UNREFERENCED_PARAMETER(dw1);
|
||||
UNREFERENCED_PARAMETER(dw2);
|
||||
}
|
||||
|
||||
VOID SetHP48Time(VOID) // set date and time
|
||||
{
|
||||
SYSTEMTIME ts;
|
||||
ULONGLONG ticks, time;
|
||||
DWORD dw;
|
||||
WORD crc, i;
|
||||
BYTE p[4];
|
||||
|
||||
_ASSERT(sizeof(ULONGLONG) == 8); // check size of datatype
|
||||
|
||||
GetLocalTime(&ts); // local time, _ftime() cause memory/resource leaks
|
||||
|
||||
// calculate days until 01.01.0000 (Erlang BIF localtime/0)
|
||||
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 + 719528L); // days from year 0
|
||||
|
||||
ticks = (ULONGLONG) dw; // convert to 64 bit
|
||||
|
||||
// convert into seconds and add time
|
||||
ticks = ticks * 24L + (ULONGLONG) ts.wHour;
|
||||
ticks = ticks * 60L + (ULONGLONG) ts.wMinute;
|
||||
ticks = ticks * 60L + (ULONGLONG) ts.wSecond;
|
||||
|
||||
// create timerticks = (s + ms) * 8192
|
||||
ticks = (ticks << 13) | (((ULONGLONG) ts.wMilliseconds << 10) / 125);
|
||||
|
||||
ticks += Chipset.t2; // add actual timer2 value
|
||||
|
||||
time = ticks; // save for calc. timeout
|
||||
time += OFF_TIME; // add 10 min for auto off
|
||||
|
||||
dw = RPLTIME; // HP addresses for clock in port0
|
||||
|
||||
crc = 0x0; // reset crc value
|
||||
for (i = 0; i < 13; ++i, ++dw) // write date and time
|
||||
{
|
||||
*p = (BYTE) ticks & 0xf;
|
||||
crc = (crc >> 4) ^ (((crc ^ ((WORD) *p)) & 0xf) * 0x1081);
|
||||
Port0[dw] = *p; // always store in port0
|
||||
ticks >>= 4;
|
||||
}
|
||||
|
||||
Nunpack(p,crc,4); // write crc
|
||||
memcpy(Port0+dw,p,4); // always store in port0
|
||||
|
||||
dw += 4; // HP addresses for timeout
|
||||
|
||||
for (i = 0; i < 13; ++i, ++dw) // write time for auto off
|
||||
{
|
||||
Port0[dw] = (BYTE) time & 0xf; // always store in port0
|
||||
time >>= 4;
|
||||
}
|
||||
|
||||
Port0[dw] = 0xf; // always store in port0
|
||||
return;
|
||||
}
|
||||
|
||||
VOID StartTimers(VOID)
|
||||
{
|
||||
if (bStarted) // timer running
|
||||
return; // -> quit
|
||||
if (Chipset.IORam[TIMER2_CTRL]&RUN) // start timer1 and timer2 ?
|
||||
{
|
||||
bStarted = TRUE; // flag timer running
|
||||
// initialisation of NINT2 lines
|
||||
bNINT2T1 = (Chipset.IORam[TIMER1_CTRL]&INTR) != 0 && (Chipset.t1 & 8) != 0;
|
||||
bNINT2T2 = (Chipset.IORam[TIMER2_CTRL]&INTR) != 0 && (Chipset.t2 & 0x80000000) != 0;
|
||||
timeGetDevCaps(&tc,sizeof(tc)); // get timer resolution
|
||||
|
||||
// max. timer2 ticks that can be handled by one timer event
|
||||
uT2MaxTicks = __min((0xFFFFFFFF / 1024),tc.wPeriodMax);
|
||||
uT2MaxTicks = __min((0xFFFFFFFF - 1023) / 125,uT2MaxTicks * 1024 / 125);
|
||||
|
||||
CheckT1(Chipset.t1); // check for timer1 interrupts
|
||||
CheckT2(Chipset.t2); // check for timer2 interrupts
|
||||
// set timer resolution to greatest possible one
|
||||
bAccurateTimer = (timeBeginPeriod(tc.wPeriodMin) == TIMERR_NOERROR);
|
||||
// set timer1 with given period
|
||||
VERIFY(uT1TimerId = timeSetEvent(T1_FREQ,0,&TimeProc,1,TIME_PERIODIC));
|
||||
RescheduleT2(TRUE); // start timer2
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
VOID StopTimers(VOID)
|
||||
{
|
||||
if (!bStarted) // timer stopped
|
||||
return; // -> quit
|
||||
if (uT1TimerId != 0) // timer1 running
|
||||
{
|
||||
// Critical Section handler may cause a dead lock
|
||||
timeKillEvent(uT1TimerId); // stop timer1
|
||||
uT1TimerId = 0; // set flag timer1 stopped
|
||||
}
|
||||
if (uT2TimerId != 0) // timer2 running
|
||||
{
|
||||
EnterCriticalSection(&csT2Lock);
|
||||
{
|
||||
Chipset.t2 = CalcT2(); // update chipset timer2 value
|
||||
}
|
||||
LeaveCriticalSection(&csT2Lock);
|
||||
AbortT2(); // stop timer2 outside critical section
|
||||
}
|
||||
bStarted = FALSE;
|
||||
if (bAccurateTimer) // "Accurate timer" running
|
||||
{
|
||||
timeEndPeriod(tc.wPeriodMin); // finish service
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD ReadT2(VOID)
|
||||
{
|
||||
DWORD dwT2;
|
||||
EnterCriticalSection(&csT2Lock);
|
||||
{
|
||||
dwT2 = CalcT2(); // calculate timer2 value or if stopped last timer value
|
||||
CheckT2(dwT2); // 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) // timer2 running
|
||||
AbortT2(); // stop timer2
|
||||
EnterCriticalSection(&csT2Lock);
|
||||
{
|
||||
Chipset.t2 = dwValue; // set new value
|
||||
CheckT2(Chipset.t2); // test timer2 control bits
|
||||
if (bStarted) // timer running
|
||||
RescheduleT2(TRUE); // restart timer2
|
||||
}
|
||||
LeaveCriticalSection(&csT2Lock);
|
||||
return;
|
||||
}
|
||||
|
||||
BYTE ReadT1(VOID)
|
||||
{
|
||||
BYTE nT1;
|
||||
EnterCriticalSection(&csT1Lock);
|
||||
{
|
||||
nT1 = Chipset.t1; // read timer1 value
|
||||
CheckT1(nT1); // update timer1 control bits
|
||||
}
|
||||
LeaveCriticalSection(&csT1Lock);
|
||||
return nT1;
|
||||
}
|
||||
|
||||
VOID SetT1(BYTE byValue)
|
||||
{
|
||||
BOOL bEqual;
|
||||
|
||||
_ASSERT(byValue < 0x10); // timer1 is only a 4bit counter
|
||||
|
||||
EnterCriticalSection(&csT1Lock);
|
||||
{
|
||||
bEqual = (Chipset.t1 == byValue); // check for same value
|
||||
}
|
||||
LeaveCriticalSection(&csT1Lock);
|
||||
if (bEqual) return; // same value doesn't restart timer period
|
||||
|
||||
if (uT1TimerId != 0) // timer1 running
|
||||
{
|
||||
timeKillEvent(uT1TimerId); // stop timer1
|
||||
uT1TimerId = 0; // set flag timer1 stopped
|
||||
}
|
||||
EnterCriticalSection(&csT1Lock);
|
||||
{
|
||||
Chipset.t1 = byValue; // set new timer1 value
|
||||
CheckT1(Chipset.t1); // test timer1 control bits
|
||||
}
|
||||
LeaveCriticalSection(&csT1Lock);
|
||||
if (bStarted) // timer running
|
||||
{
|
||||
// restart timer1 to get full period of frequency
|
||||
VERIFY(uT1TimerId = timeSetEvent(T1_FREQ,0,&TimeProc,1,TIME_PERIODIC));
|
||||
}
|
||||
return;
|
||||
}
|
124
app/src/main/cpp/TYPES.H
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* types.h
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 1995 Sebastien Carlier
|
||||
*
|
||||
*/
|
||||
|
||||
// HST bits
|
||||
#define XM 1
|
||||
#define SB 2
|
||||
#define SR 4
|
||||
#define MP 8
|
||||
|
||||
#define SWORD SHORT // signed 16 Bit variable
|
||||
#define QWORD ULONGLONG // unsigned 64 Bit variable
|
||||
|
||||
#define CHIPSET Chipset_t
|
||||
typedef struct
|
||||
{
|
||||
SWORD nPosX; // position of window
|
||||
SWORD nPosY;
|
||||
BYTE type; // calculator type
|
||||
|
||||
DWORD Port0Size; // real size of module in KB
|
||||
DWORD Port1Size; // real size of module in KB
|
||||
DWORD Port2Size; // real size of module in KB (HP49G only)
|
||||
DWORD dwUnused0; // not used, was memory pointer Port0
|
||||
DWORD dwUnused1; // not used, was memory pointer Port1
|
||||
DWORD dwUnused2; // not used, was memory pointer 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;
|
||||
WORD wPort2Crc; // fingerprint of port2
|
||||
WORD wRomCrc; // fingerprint of ROM
|
||||
#if defined _USRDLL // DLL version
|
||||
QWORD cycles; // oscillator cycles
|
||||
#else // EXE version
|
||||
DWORD cycles; // oscillator cycles
|
||||
DWORD cycles_reserved; // reserved for MSB of oscillator cycles
|
||||
#endif
|
||||
DWORD dwKdnCycles; // cpu cycles at start of 1ms key handler
|
||||
|
||||
UINT Bank_FF; // save state of HP48GX port2 or state of HP49G ROM FF
|
||||
UINT FlashRomState; // WSM state of flash memory (unused)
|
||||
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;
|
||||
|
||||
BOOL bShutdnWake; // flag for wake up from SHUTDN mode
|
||||
|
||||
BYTE Keyboard_Row[9];
|
||||
WORD IR15X;
|
||||
UINT Keyboard_State; // not used
|
||||
|
||||
signed short loffset;
|
||||
signed int width;
|
||||
UINT boffset;
|
||||
UINT lcounter;
|
||||
UINT sync; // not used
|
||||
BYTE contrast;
|
||||
BOOL dispon; // not used
|
||||
DWORD start1;
|
||||
DWORD start12;
|
||||
DWORD end1;
|
||||
DWORD start2, end2;
|
||||
|
||||
// CdB for HP: add apples header
|
||||
DWORD d0size; // no. of header display lines
|
||||
BYTE d0memory[4096*2]; // memory for header display area
|
||||
DWORD d0offset; // offset inside the header display for the content
|
||||
DWORD d0address; // address in saturn addr area for d0memory (2 pages)
|
||||
// BOOL d0Cfig; // modul configured
|
||||
} Chipset_t;
|
||||
|
||||
// additional Saturnator registers and Apple hardware
|
||||
typedef struct
|
||||
{
|
||||
BYTE byType[4]; // "SPL" Saturn PLus
|
||||
|
||||
QWORD fld[7]; // user defined field masks F1-F7
|
||||
|
||||
BOOL d0Cfig; // display memory modul configured
|
||||
DWORD d0address; // address in saturn addr area for d0memory (2 pages)
|
||||
DWORD d0size; // no. of header display lines
|
||||
DWORD d0offset; // offset inside the display memory for the content
|
||||
BYTE d0memory[4096*2]; // 4KB memory for header display area
|
||||
} APPLE_CHIPSET;
|
79
app/src/main/cpp/UDP.C
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* udp.c
|
||||
*
|
||||
* This file is part of Emu48
|
||||
*
|
||||
* Copyright (C) 2011 Christoph Gießelink
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
#include "Emu48.h"
|
||||
|
||||
TCHAR szUdpServer[1024] = _T("localhost");
|
||||
WORD wUdpPort = 5025; // scpi-raw
|
||||
|
||||
static IN_ADDR ip_addr = { 255, 255, 255, 255 };
|
||||
|
||||
VOID ResetUdp(VOID)
|
||||
{
|
||||
ip_addr.s_addr = INADDR_NONE; // invalidate saved UDP address
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL SendByteUdp(BYTE byData)
|
||||
{
|
||||
WSADATA wsd;
|
||||
SOCKET sClient;
|
||||
SOCKADDR_IN sServer;
|
||||
|
||||
BOOL bErr = TRUE;
|
||||
|
||||
VERIFY(WSAStartup(MAKEWORD(1,1),&wsd) == 0);
|
||||
|
||||
if (ip_addr.s_addr == INADDR_NONE) // IP address not specified
|
||||
{
|
||||
LPSTR lpszIpAddr;
|
||||
|
||||
#if defined _UNICODE
|
||||
DWORD dwLength = lstrlen(szUdpServer) + 1;
|
||||
|
||||
if ((lpszIpAddr = (LPSTR) _alloca(dwLength)) == NULL)
|
||||
return TRUE; // server not found
|
||||
|
||||
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,
|
||||
szUdpServer, dwLength,
|
||||
lpszIpAddr, dwLength, NULL, NULL);
|
||||
#else
|
||||
lpszIpAddr = szUdpServer;
|
||||
#endif
|
||||
|
||||
ip_addr.s_addr = inet_addr(lpszIpAddr);
|
||||
|
||||
// not a valid ip address -> try to get ip address from name server
|
||||
if (ip_addr.s_addr == INADDR_NONE)
|
||||
{
|
||||
PHOSTENT host = gethostbyname(lpszIpAddr);
|
||||
if (host == NULL)
|
||||
{
|
||||
return TRUE; // server not found
|
||||
}
|
||||
|
||||
ip_addr.s_addr = ((PIN_ADDR) host->h_addr_list[0])->s_addr;
|
||||
}
|
||||
}
|
||||
|
||||
// create UDP socket
|
||||
if ((sClient = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET)
|
||||
{
|
||||
sServer.sin_family = AF_INET;
|
||||
sServer.sin_port = htons(wUdpPort);
|
||||
sServer.sin_addr.s_addr = ip_addr.s_addr;
|
||||
|
||||
// transmit data byte
|
||||
bErr = sendto(sClient, (LPCCH) &byData, sizeof(byData), 0, (LPSOCKADDR) &sServer, sizeof(sServer)) == SOCKET_ERROR;
|
||||
closesocket(sClient);
|
||||
}
|
||||
|
||||
WSACleanup(); // cleanup network stack
|
||||
return bErr;
|
||||
}
|
14
app/src/main/cpp/emu48-jni.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// Created by cosnier on 12/11/2018.
|
||||
//
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_regis_cosnier_emu48_MainActivity_stringFromJNI(
|
||||
JNIEnv *env,
|
||||
jobject thisz) {
|
||||
// std::string hello = "Hello from C++";
|
||||
// return env->NewStringUTF(hello.c_str());
|
||||
return (*env)->NewStringUTF(env, "Hello from JNI !");
|
||||
}
|
68
app/src/main/java/com/regis/cosnier/emu48/MainActivity.java
Normal file
|
@ -0,0 +1,68 @@
|
|||
package com.regis.cosnier.emu48;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.TextView;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
// Used to load the 'native-lib' library on application startup.
|
||||
static {
|
||||
System.loadLibrary("native-lib");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show();
|
||||
}
|
||||
});
|
||||
|
||||
// Example of a call to a native method
|
||||
TextView tv = (TextView) findViewById(R.id.sample_text);
|
||||
tv.setText(stringFromJNI());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
int id = item.getItemId();
|
||||
|
||||
//noinspection SimplifiableIfStatement
|
||||
if (id == R.id.action_settings) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* A native method that is implemented by the 'native-lib' native library,
|
||||
* which is packaged with this application.
|
||||
*/
|
||||
public native String stringFromJNI();
|
||||
}
|
34
app/src/main/res/drawable-v24/ic_launcher_foreground.xml
Normal file
|
@ -0,0 +1,34 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
170
app/src/main/res/drawable/ic_launcher_background.xml
Normal file
|
@ -0,0 +1,170 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#008577"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
33
app/src/main/res/layout/activity_main.xml
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main" />
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
app:srcCompat="@android:drawable/ic_dialog_email" />
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
21
app/src/main/res/layout/content_main.xml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:context=".MainActivity"
|
||||
tools:showIn="@layout/activity_main">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sample_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World!"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
10
app/src/main/res/menu/menu_main.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="com.regis.cosnier.emu48.MainActivity">
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 15 KiB |
6
app/src/main/res/values/colors.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#008577</color>
|
||||
<color name="colorPrimaryDark">#00574B</color>
|
||||
<color name="colorAccent">#D81B60</color>
|
||||
</resources>
|
3
app/src/main/res/values/dimens.xml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
</resources>
|
4
app/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<resources>
|
||||
<string name="app_name">Emu48</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
</resources>
|
20
app/src/main/res/values/styles.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,17 @@
|
|||
package com.regis.cosnier.emu48;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
27
build.gradle
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
15
gradle.properties
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Project-wide Gradle settings.
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
172
gradlew
vendored
Normal file
|
@ -0,0 +1,172 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
84
gradlew.bat
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
9
local.properties
Normal file
|
@ -0,0 +1,9 @@
|
|||
## This file must *NOT* be checked into Version Control Systems,
|
||||
# as it contains information specific to your local configuration.
|
||||
#
|
||||
# Location of the SDK. This is only used by Gradle.
|
||||
# For customization when using a Version Control System, please read the
|
||||
# header note.
|
||||
#Mon Nov 12 10:19:12 CET 2018
|
||||
ndk.dir=C\:\\Users\\cosnier\\AppData\\Local\\Android\\Sdk\\ndk-bundle
|
||||
sdk.dir=C\:\\Users\\cosnier\\AppData\\Local\\Android\\Sdk
|
1
settings.gradle
Normal file
|
@ -0,0 +1 @@
|
|||
include ':app'
|