mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Redefine the trig functions to divide circles into 1.0 turns (#1060)
This makes their behavior consistent across Q settings Fixes #1059
This commit is contained in:
49
man/rgbasm.5
49
man/rgbasm.5
@@ -57,8 +57,8 @@ and ending with
|
|||||||
.Ql */ .
|
.Ql */ .
|
||||||
It can be split across multiple lines, or occur in the middle of an expression:
|
It can be split across multiple lines, or occur in the middle of an expression:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
X = /* the value of x
|
DEF X = /* the value of x
|
||||||
should be 3 */ 3
|
should be 3 */ 3
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Sometimes lines can be too long and it may be necessary to split them.
|
Sometimes lines can be too long and it may be necessary to split them.
|
||||||
@@ -168,20 +168,20 @@ Valid print types are:
|
|||||||
Examples:
|
Examples:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
SECTION "Test", ROM0[2]
|
SECTION "Test", ROM0[2]
|
||||||
X: ;\ This works with labels **whose address is known**
|
X: ;\ This works with labels **whose address is known**
|
||||||
Y = 3 ;\ This also works with variables
|
DEF Y = 3 ;\ This also works with variables
|
||||||
SUM equ X + Y ;\ And likewise with numeric constants
|
DEF SUM EQU X + Y ;\ And likewise with numeric constants
|
||||||
; Prints "%0010 + $3 == 5"
|
; Prints "%0010 + $3 == 5"
|
||||||
PRINTLN "{#05b:X} + {#x:Y} == {d:SUM}"
|
PRINTLN "{#05b:X} + {#x:Y} == {d:SUM}"
|
||||||
|
|
||||||
rsset 32
|
rsset 32
|
||||||
PERCENT rb 1 ;\ Same with offset constants
|
DEF PERCENT rb 1 ;\ Same with offset constants
|
||||||
VALUE = 20
|
DEF VALUE = 20
|
||||||
RESULT = MUL(20.0, 0.32)
|
DEF RESULT = MUL(20.0, 0.32)
|
||||||
; Prints "32% of 20 = 6.40"
|
; Prints "32% of 20 = 6.40"
|
||||||
PRINTLN "{d:PERCENT}% of {d:VALUE} = {f:RESULT}"
|
PRINTLN "{d:PERCENT}% of {d:VALUE} = {f:RESULT}"
|
||||||
|
|
||||||
WHO equs STRLWR("WORLD")
|
DEF WHO EQUS STRLWR("WORLD")
|
||||||
; Prints "Hello world!"
|
; Prints "Hello world!"
|
||||||
PRINTLN "Hello {s:WHO}!"
|
PRINTLN "Hello {s:WHO}!"
|
||||||
.Ed
|
.Ed
|
||||||
@@ -350,18 +350,18 @@ The trigonometry functions (
|
|||||||
.Ic SIN ,
|
.Ic SIN ,
|
||||||
.Ic COS ,
|
.Ic COS ,
|
||||||
.Ic TAN ,
|
.Ic TAN ,
|
||||||
etc) are defined in terms of a circle divided into 65535.0 degrees.
|
etc) are defined in terms of a circle divided into 1.0 "turns" (equal to 2pi radians or 360 degrees).
|
||||||
.Pp
|
.Pp
|
||||||
These functions are useful for automatic generation of various tables.
|
These functions are useful for automatic generation of various tables.
|
||||||
For example:
|
For example:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
; Generate a 256-byte sine table with values in the range [0, 128]
|
; Generate a table of sine values from sin(0.0) to sin(1.0), with
|
||||||
; (shifted and scaled from the range [-1.0, 1.0])
|
; amplitude scaled from [-1.0, 1.0] to [0.0, 128.0]
|
||||||
ANGLE = 0.0
|
DEF turns = 0.0
|
||||||
REPT 256
|
REPT 256
|
||||||
db (MUL(64.0, SIN(ANGLE)) + 64.0) >> 16
|
db MUL(64.0, SIN(turns) + 1.0) >> 16
|
||||||
ANGLE = ANGLE + 256.0 ; 256.0 = 65536 degrees / 256 entries
|
DEF turns += 1.0 / 256
|
||||||
ENDR
|
ENDR
|
||||||
.Ed
|
.Ed
|
||||||
.Ss String expressions
|
.Ss String expressions
|
||||||
The most basic string expression is any number of characters contained in double quotes
|
The most basic string expression is any number of characters contained in double quotes
|
||||||
@@ -1011,7 +1011,7 @@ DEF ARRAY_SIZE EQU 4
|
|||||||
DEF COUNT = 2
|
DEF COUNT = 2
|
||||||
DEF COUNT = 3
|
DEF COUNT = 3
|
||||||
DEF COUNT = ARRAY_SIZE + COUNT
|
DEF COUNT = ARRAY_SIZE + COUNT
|
||||||
COUNT = COUNT*2
|
DEF COUNT *= 2
|
||||||
;\ COUNT now has the value 14
|
;\ COUNT now has the value 14
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
@@ -1753,13 +1753,12 @@ You can also use
|
|||||||
.Ic REPT
|
.Ic REPT
|
||||||
to generate tables on the fly:
|
to generate tables on the fly:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
; Generate a 256-byte sine table with values in the range [0, 128]
|
; Generate a table of square values from 0**2 = 0 to 100**2 = 10000
|
||||||
; (shifted and scaled from the range [-1.0, 1.0])
|
DEF x = 0
|
||||||
ANGLE = 0.0
|
REPT 101
|
||||||
REPT 256
|
dw x * x
|
||||||
db (MUL(64.0, SIN(ANGLE)) + 64.0) >> 16
|
DEF x += 1
|
||||||
ANGLE = ANGLE + 256.0 ; 256.0 = 65536 degrees / 256 entries
|
ENDR
|
||||||
ENDR
|
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
As in macros, you can also use the escape sequence
|
As in macros, you can also use the escape sequence
|
||||||
|
|||||||
@@ -24,9 +24,9 @@
|
|||||||
#define fix2double(i) ((double)((i) / fix_PrecisionFactor()))
|
#define fix2double(i) ((double)((i) / fix_PrecisionFactor()))
|
||||||
#define double2fix(d) ((int32_t)round((d) * fix_PrecisionFactor()))
|
#define double2fix(d) ((int32_t)round((d) * fix_PrecisionFactor()))
|
||||||
|
|
||||||
// pi*2 radians == 2**fixPrecision fixed-point "degrees"
|
// 2*pi radians == 1 turn
|
||||||
#define fdeg2rad(f) ((f) * (M_PI * 2) / fix_PrecisionFactor())
|
#define turn2rad(f) ((f) * (M_PI * 2))
|
||||||
#define rad2fdeg(r) ((r) * fix_PrecisionFactor() / (M_PI * 2))
|
#define rad2turn(r) ((r) / (M_PI * 2))
|
||||||
|
|
||||||
uint8_t fixPrecision;
|
uint8_t fixPrecision;
|
||||||
|
|
||||||
@@ -51,37 +51,37 @@ void fix_Print(int32_t i)
|
|||||||
|
|
||||||
int32_t fix_Sin(int32_t i)
|
int32_t fix_Sin(int32_t i)
|
||||||
{
|
{
|
||||||
return double2fix(sin(fdeg2rad(fix2double(i))));
|
return double2fix(sin(turn2rad(fix2double(i))));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t fix_Cos(int32_t i)
|
int32_t fix_Cos(int32_t i)
|
||||||
{
|
{
|
||||||
return double2fix(cos(fdeg2rad(fix2double(i))));
|
return double2fix(cos(turn2rad(fix2double(i))));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t fix_Tan(int32_t i)
|
int32_t fix_Tan(int32_t i)
|
||||||
{
|
{
|
||||||
return double2fix(tan(fdeg2rad(fix2double(i))));
|
return double2fix(tan(turn2rad(fix2double(i))));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t fix_ASin(int32_t i)
|
int32_t fix_ASin(int32_t i)
|
||||||
{
|
{
|
||||||
return double2fix(rad2fdeg(asin(fix2double(i))));
|
return double2fix(rad2turn(asin(fix2double(i))));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t fix_ACos(int32_t i)
|
int32_t fix_ACos(int32_t i)
|
||||||
{
|
{
|
||||||
return double2fix(rad2fdeg(acos(fix2double(i))));
|
return double2fix(rad2turn(acos(fix2double(i))));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t fix_ATan(int32_t i)
|
int32_t fix_ATan(int32_t i)
|
||||||
{
|
{
|
||||||
return double2fix(rad2fdeg(atan(fix2double(i))));
|
return double2fix(rad2turn(atan(fix2double(i))));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t fix_ATan2(int32_t i, int32_t j)
|
int32_t fix_ATan2(int32_t i, int32_t j)
|
||||||
{
|
{
|
||||||
return double2fix(rad2fdeg(atan2(fix2double(i), fix2double(j))));
|
return double2fix(rad2turn(atan2(fix2double(i), fix2double(j))));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t fix_Mul(int32_t i, int32_t j)
|
int32_t fix_Mul(int32_t i, int32_t j)
|
||||||
|
|||||||
38
test/asm/trigonometry.asm
Normal file
38
test/asm/trigonometry.asm
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
for Q, 2, 31
|
||||||
|
OPT Q.{d:Q}
|
||||||
|
|
||||||
|
assert sin(0.25) == 1.0
|
||||||
|
assert asin(1.0) == 0.25
|
||||||
|
|
||||||
|
assert sin(0.0) == 0.0
|
||||||
|
assert asin(0.0) == 0.0
|
||||||
|
|
||||||
|
assert cos(0.0) == 1.0
|
||||||
|
assert acos(1.0) == 0.0
|
||||||
|
|
||||||
|
if Q > 2 ; can't represent 0.125 in Q.2
|
||||||
|
assert tan(0.125) == 1.0
|
||||||
|
assert atan(1.0) == 0.125
|
||||||
|
else
|
||||||
|
assert tan(0.0) == 0.0
|
||||||
|
assert atan(0.0) == 0.0
|
||||||
|
endc
|
||||||
|
endr
|
||||||
|
|
||||||
|
SECTION "sine", ROM0[0]
|
||||||
|
OPT Q.16
|
||||||
|
; Generate a table of sine values from sin(0.0) to sin(1.0), with
|
||||||
|
; amplitude scaled from [-1.0, 1.0] to [0.0, 128.0]
|
||||||
|
DEF turns = 0.0
|
||||||
|
REPT 256
|
||||||
|
db MUL(64.0, SIN(turns) + 1.0) >> 16
|
||||||
|
DEF turns += 1.0 / 256
|
||||||
|
ENDR
|
||||||
|
|
||||||
|
|
||||||
|
SECTION "cosine", ROM0[256]
|
||||||
|
OPT Q.8
|
||||||
|
; 32 samples of cos(x) from x=0 to x=pi radians=0.5 turns
|
||||||
|
for x, 0.0, 0.5, 0.5 / 32
|
||||||
|
dw cos(x)
|
||||||
|
endr
|
||||||
0
test/asm/trigonometry.err
Normal file
0
test/asm/trigonometry.err
Normal file
0
test/asm/trigonometry.out
Normal file
0
test/asm/trigonometry.out
Normal file
BIN
test/asm/trigonometry.out.bin
Normal file
BIN
test/asm/trigonometry.out.bin
Normal file
Binary file not shown.
Reference in New Issue
Block a user