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'
|