diff --git a/Makefile b/Makefile
index de38e2f3..f8256f00 100644
--- a/Makefile
+++ b/Makefile
@@ -930,7 +930,7 @@ testremote: build/kernal_custom.rom build/basic_custom.rom $(TARGET_CHR_PXL) bui
x64 -kernal build/kernal_custom.rom -basic build/basic_custom.rom -chargen $(TARGET_CHR_PXL) -moncommands build/symbols_custom.vs -remotemonitor
testsimilarity: $(TOOL_SIMILARITY) $(DIR_TST38)/OUTx_x.BIN $(ROM_CBM_KERNAL) $(ROM_CBM_BASIC)
- $(TOOL_SIMILARITY) $(ROM_CBM_KERNAL) $(DIR_TST38)/OUTx_x.BIN
+ $(TOOL_SIMILARITY) $(ROM_CBM_KERNAL) $(DIR_TST38)/OUTx_x.BIN --basic --high
$(TOOL_SIMILARITY) $(ROM_CBM_BASIC) $(DIR_TST38)/OUTx_x.BIN --basic
build/testresults: testsuite/unit/testresults.cc
diff --git a/STATUS.md b/STATUS.md
index 01fd551c..da4fea08 100644
--- a/STATUS.md
+++ b/STATUS.md
@@ -265,7 +265,7 @@ Floating point mathematical routines - not official, but well known and broadly
| `$E264` | `cos_FAC1` | PARTIAL | not fully tested yet |
| `$E26B` | `sin_FAC1` | PARTIAL | not fully tested yet |
| `$E2B4` | `tan_FAC1` | PARTIAL | not fully tested yet |
-| `$E30E` | `atn_FAC1` | PARTIAL | not fully tested yet |
+| `$E30E` | `atn_FAC1` | DONE | From the Microsoft BASIC, original name: ATN |
diff --git a/src/basic/math_trans/e30e.atn_FAC1.s b/src/basic/math_trans/e30e.atn_FAC1.s
index c58a811c..e620adf8 100644
--- a/src/basic/math_trans/e30e.atn_FAC1.s
+++ b/src/basic/math_trans/e30e.atn_FAC1.s
@@ -2,9 +2,13 @@
;; #LAYOUT# * BASIC_0 #TAKE
;; #LAYOUT# * * #IGNORE
-;
+; This file is under the MIT license, it contains code released by Microsoft Corporation.
+; See LICENSE for more information.
+
; Math package - arc tangent of FAC1
;
+; This is verified to be identical to the original Microsoft implementation where it was named ATN
+;
; See also:
; - [CM64] Computes Mapping the Commodore 64 - page 211
; - https://www.c64-wiki.com/wiki/Floating_point_arithmetic
@@ -23,41 +27,34 @@
atn_FAC1:
- lda FAC1_sign ; Save sign of FAC1 on the stack
- pha
- lda #$00 ; FAC1 = abs(FAC1)
- sta FAC1_sign
- sta TEMPF1 ; AX not scaled
-
- lda #const_ONE
- jsr FCOMP
- bmi atn_skipscale
-
- lda #const_ONE
- jsr div_MEM_FAC1
- inc TEMPF1 ; AX scaled
-
-atn_skipscale:
- lda #poly_atn
- jsr poly1_FAC1
-
- lda TEMPF1
- beq atn_skipoffset
-
- lda #const_HALF_PI
- jsr sub_MEM_FAC1
-
-atn_skipoffset:
- pla
- bpl atn_out
- jmp toggle_sign_FAC1
-
-atn_out:
- rts
+ lda FAC1_sign ; What is sign?
+ pha ; (Meanwhile save it for later)
+ bpl ATN1
+ jsr toggle_sign_FAC1 ; If negative, negate FAC1, use arctan(x) = -arctan(-x)
+ATN1:
+ lda FAC1_exponent
+ pha ; Save this too for later
+ cmp #$81 ; See if FAC1 >= 1.0
+ bcc ATN2 ; It is less than 1
+ lda #const_ONE
+ jsr div_MEM_FAC1 ; Compute reciprocal. Use arctan(x) = pi/2 - arctan(1/x)
+ATN2:
+ lda #poly_atn
+ jsr poly1_FAC1
+ pla
+ cmp #$81 ; Was original argument < 1 ?
+ bcc ATN3 ; Yes
+ lda #const_HALF_PI
+ jsr sub_MEM_FAC1 ; Subtract arctan from pi/2
+ATN3:
+ pla ; Was original argument positive?
+ bpl ATN4 ; Yes
+ jmp toggle_sign_FAC1 ; If negative, negate result
+ATN4:
+ rts
} else {
diff --git a/tools/similarity.c b/tools/similarity.c
index 51bd6f0f..69eb4f75 100644
--- a/tools/similarity.c
+++ b/tools/similarity.c
@@ -20,7 +20,7 @@ int matches[MAX_SIZE];
int phase_mask[MAX_SIZE+MAX_SIZE];
-#define NUM_CHUNKS 9
+#define NUM_CHUNKS 10
// Pairs of start, end memory addresses of known exact similarity with the open source Microsoft BASIC
unsigned short microsoft_basic_chunks[NUM_CHUNKS * 2] = {
0xB391, 0xB39D,
@@ -32,6 +32,7 @@ unsigned short microsoft_basic_chunks[NUM_CHUNKS * 2] = {
0xBDB3, 0xBDC1,
0xBDDD, 0xBF51,
0xBFB4, 0xBFEC,
+ 0xE30E, 0xE33D,
};
@@ -40,6 +41,7 @@ int main(int argc,char **argv)
{
int verbose=0;
int basic = 0;
+ int high =0;
if (argc<3) {
fprintf(stderr,"usage: similarity [--verbose] [--basic]\n");
@@ -51,6 +53,8 @@ int main(int argc,char **argv)
verbose = 1;
} else if (!strcmp(argv[i], "--basic")) {
basic = 1;
+ } else if (!strcmp(argv[i], "--high")) {
+ high = 1;
} else {
fprintf(stderr, "Unrecognised directive.\n");
exit(-1);
@@ -94,11 +98,21 @@ int main(int argc,char **argv)
if (basic) {
for (int i = 0; i < NUM_CHUNKS; i++) {
for (int addr = microsoft_basic_chunks[i * 2]; addr <= microsoft_basic_chunks[i * 2 + 1]; addr++) {
- short index = addr - 0xA000;
- if (f1[index] != f2[index]) {
- printf("BASIC does not match MS BASIC at %X (%X != %X)\n", addr, f1[index], f2[index]);
+ short index1, index2;
+ if (high && addr < 0xE000 || !high && addr >= 0xE000) {
+ continue;
}
- f1[index] = 0xFF;
+ if (!high) {
+ index1 = addr - 0xA000;
+ index2 = index1;
+ } else {
+ index1 = addr - 0xE000;
+ index2 = addr - 0xA000;
+ }
+ if (f1[index1] != f2[index2]) {
+ printf("BASIC does not match MS BASIC at %X (%X != %X)\n", addr, f1[index1], f2[index2]);
+ }
+ f1[index1] = 0xFF;
}
}
}