diff --git a/extras/acs/srb2defs.acs b/extras/acs/srb2defs.acs
index 895b8e7e41a7c73243a291271a81a07ee2f5f352..321f1beefcaf547db1a16ef6cf45eb5926eb2c49 100644
--- a/extras/acs/srb2defs.acs
+++ b/extras/acs/srb2defs.acs
@@ -29,7 +29,7 @@
 #define GAME_HIDEANDSEEK        6
 #define GAME_CTF                7
 
-// Actor properties you can get/set -----------------------------------------
+// Actor properties you can get/set
 
 #define APROP_X             0
 #define APROP_Y             1
@@ -146,7 +146,7 @@
 #define SECPROP_Arg0Str              25
 #define SECPROP_Arg1Str              26
 
-// Render Styles ------------------------------------------------------------
+// Render styles
 
 #define STYLE_Copy            0   // Just copy the image to the screen
 #define STYLE_Translucent     1   // Draw translucent
@@ -183,19 +183,20 @@
 #define SECSPAC_FloorMissile           1024      // when a projectile touches the floor of this sector
 #define SECSPAC_CeilingMissile         2048      // when a projectile touches the ceiling of this sector
 
-// Teams -----------------------------------------------------------
+// Teams
 
 #define NO_TEAM                 0
 #define TEAM_RED                1
 #define TEAM_BLUE               2
 
 // Bot types
+
 #define BOT_NONE    0
 #define BOT_2PAI    1
 #define BOT_2PHUMAN 2
 #define BOT_MPAI    3
 
-// Colors ----------------------------------------------------------
+// Colors
 
 #define SKINCOLOR_NONE 0
 #define SKINCOLOR_WHITE 1
diff --git a/extras/acs/srb2special.acs b/extras/acs/srb2special.acs
index bb76e4c1d33f158f743e0c792b4dfcf5f1ed2ad2..4aadea8d717fd3934f00ccfa547254f4be33f8f8 100644
--- a/extras/acs/srb2special.acs
+++ b/extras/acs/srb2special.acs
@@ -31,8 +31,11 @@ special
 	-321:Thing_Dye(1),
 	-322:Teleport(2,3),
 	-323:SetViewpoint(1,2),
-	-324:Thing_TrackAngle(4,6),
-	-325:Thing_StopTrackingAngle(1),
+	// -324:Thing_Spawn(1), // NOTE: would it be better to implement Spawn? (https://zdoom.org/wiki/Spawn)
+	-325:Thing_TrackAngle(4,6),
+	-326:Thing_StopTrackingAngle(1),
+	// -327:GiveShield(1,2),
+	// -328:GivePowerUp(1,2),
 	-500:CameraWait(1),
 	-503:SetLineRenderStyle(3),
 	-504:MapWarp(2),
@@ -43,6 +46,19 @@ special
 	-510:MusicRestore(0),
 	-512:MusicDim(1),
 
+	// -600:StartConversation(),
+
+	-700:Tan(1),
+	-701:Arcsin(1),
+	-702:Arccos(1),
+	-703:Hypot(2),
+	-704:Sqrt(1),
+	-705:Floor(1),
+	-706:Ceil(1),
+	-707:Round(1),
+	-710:InvAngle(1),
+	-711:OppositeColor(1),
+
 	// SRB2 linedef types (400-499)
 	// Not all are implemented
 	400:Floor_SetHeight(2),
@@ -66,7 +82,6 @@ special
 	429:Sector_Crush(1,2),
 	432:Switch2DMode(0,1),
 	433:GravityFlip(0,2),
-	// 434:AwardPowerUp(2), // to reimplement
 	435:Plane_ChangeScrollerDirection(2),
 	436:FOF_Shatter(2),
 	437:LockPlayer(1,2),
@@ -88,9 +103,7 @@ special
 	454:FOF_StopFading(2),
 	455:Colormap_Fade(3,4),
 	456:Colormap_StopFading(1),
-	// 459:StartConversation(), // to reimplement
 	460:AwardRings(1,2),
-	// 461:Thing_Spawn(2), // to implement (use the actor names; SRB2 doesn't have spawn numbers)
 	462:StopTimer(0),
 	464:TriggerEggCapsule(1,2),
 	466:SetLevelFailureState(1),
diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp
index 45cfbce6f5cab279500da552adfceb343bc0f0f0..1e4303b530a38924ddc977704feb47a0a3431e0b 100644
--- a/src/acs/call-funcs.cpp
+++ b/src/acs/call-funcs.cpp
@@ -33,6 +33,7 @@
 #include "../d_player.h"
 #include "../r_defs.h"
 #include "../r_state.h"
+#include "../r_main.h"
 #include "../p_polyobj.h"
 #include "../taglist.h"
 #include "../p_local.h"
@@ -43,6 +44,7 @@
 #include "../hu_stuff.h"
 #include "../s_sound.h"
 #include "../r_textures.h"
+#include "../m_fixed.h"
 #include "../m_cond.h"
 #include "../r_skins.h"
 #include "../z_zone.h"
@@ -3557,3 +3559,197 @@ bool CallFunc_SetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, A
 
 	return false;
 }
+
+/*--------------------------------------------------
+	static angle_t ACS_GetAngle(int angle)
+
+		Converts a fixed-point angle to a Doom angle.
+--------------------------------------------------*/
+static angle_t ACS_GetAngle(int angle)
+{
+	return FixedAngle(angle * 360);
+}
+
+/*--------------------------------------------------
+	static void ACS_PushAngle(ACSVM::Thread *thread, angle_t angle)
+
+		Pushes an angle to the stack (really a fixed-point number.)
+--------------------------------------------------*/
+static void ACS_PushAngle(ACSVM::Thread *thread, angle_t angle)
+{
+	thread->dataStk.push(FixedDiv(AngleFixed(angle), 360*FRACUNIT));
+}
+
+/*--------------------------------------------------
+	bool CallFunc_Sin(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+
+		Returns the sine of a fixed-point number.
+--------------------------------------------------*/
+bool CallFunc_Sin(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+{
+	(void)argC;
+	ACS_PushAngle(thread, FINESINE((ACS_GetAngle(argV[0])>>ANGLETOFINESHIFT) & FINEMASK));
+	return false;
+}
+
+/*--------------------------------------------------
+	bool CallFunc_Cos(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+
+		Returns the cosine of a fixed-point number.
+--------------------------------------------------*/
+bool CallFunc_Cos(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+{
+	(void)argC;
+	ACS_PushAngle(thread, FINECOSINE((ACS_GetAngle(argV[0])>>ANGLETOFINESHIFT) & FINEMASK));
+	return false;
+}
+
+/*--------------------------------------------------
+	bool CallFunc_Tan(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+
+		Returns the tangent of a fixed-point number.
+--------------------------------------------------*/
+bool CallFunc_Tan(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+{
+	(void)argC;
+	ACS_PushAngle(thread, FINETANGENT(((ACS_GetAngle(argV[0])+ANGLE_90)>>ANGLETOFINESHIFT) & 4095));
+	return false;
+}
+
+/*--------------------------------------------------
+	bool CallFunc_Asin(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+
+		Returns arcsin(x), where x is a fixed-point number.
+--------------------------------------------------*/
+bool CallFunc_Arcsin(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+{
+	(void)argC;
+	ACS_PushAngle(thread, -FixedAcos(argV[0]) + ANGLE_90);
+	return false;
+}
+
+/*--------------------------------------------------
+	bool CallFunc_Acos(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+
+		Returns arccos(x), where x is a fixed-point number.
+--------------------------------------------------*/
+bool CallFunc_Arccos(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+{
+	(void)argC;
+	ACS_PushAngle(thread, FixedAcos(argV[0]));
+	return false;
+}
+
+/*--------------------------------------------------
+	bool CallFunc_Hypot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+
+		Returns hypot(x, y), where x and y are fixed-point numbers.
+--------------------------------------------------*/
+bool CallFunc_Hypot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+{
+	(void)argC;
+	thread->dataStk.push(R_PointToDist2(0, 0, argV[0], argV[1]));
+	return false;
+}
+
+/*--------------------------------------------------
+	bool CallFunc_Sqrt(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+
+		Returns the square root of a fixed-point number.
+--------------------------------------------------*/
+bool CallFunc_Sqrt(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+{
+	(void)argC;
+
+	int x = argV[0];
+
+	fixed_t result = 0;
+
+	if (x < 0)
+	{
+		CONS_Alert(CONS_WARNING, "Sqrt: square root domain error\n");
+	}
+	else
+	{
+		result = FixedSqrt(x);
+	}
+
+	thread->dataStk.push(result);
+
+	return false;
+}
+
+/*--------------------------------------------------
+	bool CallFunc_Floor(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+
+		Returns floor(x), where x is a fixed-point number.
+--------------------------------------------------*/
+bool CallFunc_Floor(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+{
+	(void)argC;
+	thread->dataStk.push(FixedFloor(argV[0]));
+	return false;
+}
+
+/*--------------------------------------------------
+	bool CallFunc_Ceil(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+
+		Returns ceil(x), where x is a fixed-point number.
+--------------------------------------------------*/
+bool CallFunc_Ceil(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+{
+	(void)argC;
+	thread->dataStk.push(FixedCeil(argV[0]));
+	return false;
+}
+
+/*--------------------------------------------------
+	bool CallFunc_Round(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+
+		Returns round(x), where x is a fixed-point number.
+--------------------------------------------------*/
+bool CallFunc_Round(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+{
+	(void)argC;
+	thread->dataStk.push(FixedRound(argV[0]));
+	return false;
+}
+
+/*--------------------------------------------------
+	bool CallFunc_InvAngle(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+
+		Returns the inverse of an angle.
+--------------------------------------------------*/
+bool CallFunc_InvAngle(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+{
+	(void)argC;
+	ACS_PushAngle(thread, InvAngle(ACS_GetAngle(argV[0])));
+	return false;
+}
+
+/*--------------------------------------------------
+	bool CallFunc_OppositeColor(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+
+		Returns the opposite of a color.
+--------------------------------------------------*/
+bool CallFunc_OppositeColor(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
+{
+	(void)argC;
+
+	int color = argV[0];
+
+	int result = 0;
+
+	if (color < 1 || color >= numskincolors)
+	{
+		CONS_Alert(CONS_WARNING, "OppositeColor: out of range\n");
+	}
+	else
+	{
+		result = skincolors[color].invcolor;
+	}
+
+	thread->dataStk.push(result);
+
+	return false;
+}
diff --git a/src/acs/call-funcs.hpp b/src/acs/call-funcs.hpp
index 5f4c494a8ceb709866651817f3e966b982317d6c..5d29182572177a0fbf7ac70b391f79f7f47a2d5f 100644
--- a/src/acs/call-funcs.hpp
+++ b/src/acs/call-funcs.hpp
@@ -111,4 +111,17 @@ bool CallFunc_SetSectorProperty(ACSVM::Thread *thread, const ACSVM::Word *argV,
 bool CallFunc_GetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
 bool CallFunc_SetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
 
+bool CallFunc_Sin(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
+bool CallFunc_Cos(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
+bool CallFunc_Tan(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
+bool CallFunc_Arcsin(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
+bool CallFunc_Arccos(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
+bool CallFunc_Hypot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
+bool CallFunc_Sqrt(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
+bool CallFunc_Floor(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
+bool CallFunc_Ceil(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
+bool CallFunc_Round(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
+bool CallFunc_InvAngle(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
+bool CallFunc_OppositeColor(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
+
 #endif // __SRB2_ACS_CALL_FUNCS_HPP__
diff --git a/src/acs/environment.cpp b/src/acs/environment.cpp
index f0a7ca7da01d7b51bd6b93247b9c2114993f2a31..626ad00c269d8f4bb07600493fa78fe77101c57e 100644
--- a/src/acs/environment.cpp
+++ b/src/acs/environment.cpp
@@ -111,6 +111,8 @@ Environment::Environment()
 	// 181 to 189: Implemented by ACSVM
 
 	// 203 to 217: Implemented by ACSVM
+	addCodeDataACS0(220, {"",        2, addCallFunc(CallFunc_Sin)});
+	addCodeDataACS0(221, {"",        2, addCallFunc(CallFunc_Cos)});
 
 	// 225 to 243: Implemented by ACSVM
 
@@ -178,8 +180,11 @@ Environment::Environment()
 	addFuncDataACS0( 321, addCallFunc(CallFunc_SetObjectDye));
 	addFuncDataACS0( 322, addCallFunc(CallFunc_Teleport));
 	addFuncDataACS0( 323, addCallFunc(CallFunc_SetViewpoint));
-	addFuncDataACS0( 324, addCallFunc(CallFunc_TrackObjectAngle));
-	addFuncDataACS0( 325, addCallFunc(CallFunc_StopTrackingObjectAngle));
+	// addFuncDataACS0( 324, addCallFunc(CallFunc_SpawnObject));
+	addFuncDataACS0( 325, addCallFunc(CallFunc_TrackObjectAngle));
+	addFuncDataACS0( 326, addCallFunc(CallFunc_StopTrackingObjectAngle));
+	// addFuncDataACS0( 327, addCallFunc(CallFunc_GiveShield));
+	// addFuncDataACS0( 328, addCallFunc(CallFunc_GivePowerUp));
 
 	addFuncDataACS0( 500, addCallFunc(CallFunc_CameraWait));
 	addFuncDataACS0( 503, addCallFunc(CallFunc_SetLineRenderStyle));
@@ -190,6 +195,19 @@ Environment::Environment()
 	addFuncDataACS0( 509, addCallFunc(CallFunc_MusicStopAll));
 	addFuncDataACS0( 510, addCallFunc(CallFunc_MusicRestore));
 	addFuncDataACS0( 512, addCallFunc(CallFunc_MusicDim));
+
+	// addFuncDataACS0( 600, addCallFunc(CallFunc_StartConversation));
+
+	addFuncDataACS0( 700, addCallFunc(CallFunc_Tan));
+	addFuncDataACS0( 701, addCallFunc(CallFunc_Arcsin));
+	addFuncDataACS0( 702, addCallFunc(CallFunc_Arccos));
+	addFuncDataACS0( 703, addCallFunc(CallFunc_Hypot));
+	addFuncDataACS0( 704, addCallFunc(CallFunc_Sqrt));
+	addFuncDataACS0( 705, addCallFunc(CallFunc_Floor));
+	addFuncDataACS0( 706, addCallFunc(CallFunc_Ceil));
+	addFuncDataACS0( 707, addCallFunc(CallFunc_Round));
+	addFuncDataACS0( 710, addCallFunc(CallFunc_InvAngle));
+	addFuncDataACS0( 711, addCallFunc(CallFunc_OppositeColor));
 }
 
 ACSVM::Thread *Environment::allocThread()
diff --git a/src/m_fixed.h b/src/m_fixed.h
index f40c7b30870baffdd978cec0ecb447b65f74ba6f..f89517b6b8fa3e648d9592ead78dc7e6b74c2183 100644
--- a/src/m_fixed.h
+++ b/src/m_fixed.h
@@ -20,6 +20,10 @@
 #include <stdlib.h>
 #endif
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*!
   \brief bits of the fraction
 */
@@ -357,4 +361,8 @@ void FM_MultMatrix(matrix_t *dest, const matrix_t *multme);
 void FM_Translate(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z);
 void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z);
 
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
 #endif //m_fixed.h
diff --git a/src/r_main.h b/src/r_main.h
index aedfeb6ad0f2ca2a0caaba771f38e44ad29e1142..73331aa43544123a47985821906dc6eb1e3e6ad2 100644
--- a/src/r_main.h
+++ b/src/r_main.h
@@ -19,6 +19,10 @@
 #include "r_textures.h"
 #include "m_perfstats.h" // ps_metric_t
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 //
 // POV related.
 //
@@ -158,4 +162,9 @@ void R_RenderPlayerView(player_t *player);
 
 // add commands related to engine, at game startup
 void R_RegisterEngineStuff(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
 #endif