diff --git a/Processes/CONEXSourceCut/CONEXSourceCut.cc b/Processes/CONEXSourceCut/CONEXSourceCut.cc
index c3109315c9f66784a24c68ce2bddf3c952fe4649..a312349085fe00e08c2df5123c8a8e8d65b0d208 100644
--- a/Processes/CONEXSourceCut/CONEXSourceCut.cc
+++ b/Processes/CONEXSourceCut/CONEXSourceCut.cc
@@ -9,6 +9,7 @@
  */
 
 #include <corsika/process/conex_source_cut/CONEXSourceCut.h>
+#include <corsika/random/RNGManager.h>
 #include <corsika/units/PhysicalConstants.h>
 #include <algorithm>
 #include <iomanip>
@@ -27,9 +28,9 @@ corsika::process::EProcessReturn CONEXSourceCut::DoSecondaries(
   while (p != vS.end()) {
     Code const pid = p.GetPID();
 
-    auto const it = std::find_if(em_codes_.cbegin(), em_codes_.cend(),
+    auto const it = std::find_if(egs_em_codes_.cbegin(), egs_em_codes_.cend(),
                                  [=](auto const& p) { return pid == p.first; });
-    if (it == em_codes_.cend()) {
+    if (it == egs_em_codes_.cend()) {
       continue; // no EM particle
     }
 
@@ -42,8 +43,8 @@ corsika::process::EProcessReturn CONEXSourceCut::DoSecondaries(
         energy / 1_MeV; // total energy, TODO: check if maybe kinetic should be used
 
     auto coords = position.GetCoordinates(conexObservationCS_) / 1_m;
-    double x = coords[0];
-    double y = coords[1];
+    double x = coords[0].magnitude();
+    double y = coords[1].magnitude();
 
     double altitude = ((position - center_).norm() - conex::earthRadius) / 1_m;
 
@@ -61,9 +62,9 @@ corsika::process::EProcessReturn CONEXSourceCut::DoSecondaries(
     double time = (p.GetTime() * units::constants::c - groundDist_) / 1_m;
 
     // fill u,v,w momentum direction in EGS frame
-    double u = direction.dot(y_sf_);
-    double v = direction.dot(x_sf_);
-    double w = direction.dot(showerAxis_.GetDirection());
+    double u = direction.dot(y_sf_).magnitude();
+    double v = direction.dot(x_sf_).magnitude();
+    double w = direction.dot(showerAxis_.GetDirection()).magnitude();
 
     int iri = 2; // EGS medium air
 
@@ -84,21 +85,17 @@ corsika::process::EProcessReturn CONEXSourceCut::DoSecondaries(
 
 void CONEXSourceCut::Init() {}
 
-void CONEXSourceCut::SolveCE() {
-  int zero = 0;
-  int iCEmode = 1;
-  conex::HadronCascade_(id, nshtot_, zero, iCEmode);
-  conex::SolveMomentEquations_(zero);
-}
+void CONEXSourceCut::SolveCE() { conex::conexcascade_(); }
 
 CONEXSourceCut::CONEXSourceCut(geometry::Point center, environment::ShowerAxis showerAxis,
                                units::si::LengthType groundDist,
                                units::si::GrammageType Xcut,
-                               units::si::EnergyType primaryEnergy)
+                               units::si::HEPEnergyType primaryEnergy,
+                               particles::PDGCode primaryID)
     : center_{center}
     , showerAxis_{showerAxis}
     , groundDist_{groundDist}
-    , conexObservation_{std::invoke([]() {
+    , conexObservationCS_{std::invoke([&]() {
       auto const& c8cs = center.GetCoordinateSystem();
       auto const showerCore =
           showerAxis.GetStart() + showerAxis.GetDirection() * groundDist;
@@ -110,31 +107,34 @@ CONEXSourceCut::CONEXSourceCut(geometry::Point center, environment::ShowerAxis s
           c8cs, intermediateCS2); // either this way or vice versa... TODO: test this!
       return geometry::CoordinateSystem(c8cs, transform);
     })}
-    , x_sf_{geometry::Vector<dimensionless_d>{conexObservationCS_, 0., 0., 1.}
-                .cross(showerAxis_.GetDirection())
-                .normalized()}
+    , x_sf_{std::invoke([&]() {
+      return geometry::Vector<length_d>{conexObservationCS_, 0._m, 0._m, 1._m}
+          .cross(showerAxis_.GetDirection())
+          .normalized();
+    })}
     , y_sf_{showerAxis_.GetDirection().cross(x_sf_)} {
-  auto id = static_cast<int>(InitialParticle_(particles::GetPDG(pid)));
-  conex::eprima_ = primaryEnergy / 1_GeV;
-  nshtot = 1;                         // not sure about this...
-  conex::fehcut_ = conex::femcut_ = ; // what?
-  conex::ehcut_ = max(enymin, min(1.d10, eprima / aNbrNucl * fehcut));
-  conex::emcut_ = max(enymin, min(1.d10, eprima / aNbrNucl * femcut));
-
-  // set phisho, thetas
-  geometry::Vector<dimensionless_d> ez{conexObservationCS_, 0., 0., 1.};
-  auto const c = showerAxis_.GetDirection().dot(ez);
-  auto const theta = M_PI - std::acos(c);
-  conex::cxbas4_::thetas_ = theta * 180;
+
+  double eprima = primaryEnergy / 1_GeV;
+
+  // set phi, theta
+  geometry::Vector<length_d> ez{conexObservationCS_, {0._m, 0._m, 1_m}};
+  auto const c = showerAxis_.GetDirection().dot(ez) / 1_m;
+  double theta = 180 * (M_PI - std::acos(c));
 
   auto const showerAxisConex =
       showerAxis_.GetDirection().GetComponents(conexObservationCS_);
-  auto const phi = std::atan2(-showerAxisConex.GetY(), showerAxisConex.GetX());
-  conex::cxbas4_::phisho_ = phi * 180;
+  double phi = 180 * std::atan2(-showerAxisConex.GetY().magnitude(),
+                                showerAxisConex.GetX().magnitude());
+  double XmaxP_ = Xcut / (1_g / 1_cm / 1_cm);
+
+  int ipart = static_cast<int>(primaryID);
+  auto rng = corsika::random::RNGManager::GetInstance().GetRandomStream("cascade");
 
-  // call ranfgt(seed)?
+  double dimpact = 0.; // valid only if shower core is fixed on the observation plane; for
+                       // skimming showers an offset is needed like in CONEX
 
-  cxthin_::ethin = 0;
+  std::array<int, 3> ioseed{static_cast<int>(rng()), static_cast<int>(rng()),
+                            static_cast<int>(rng())};
 
-  conex::cxoutput1_::XminP_ = conex::cxoutput1_::XmaxP_ = Xcut / (1_g / 1_cm / 1_cm);
+  conex::conexrun_(ipart, eprima, theta, phi, dimpact, ioseed.data());
 }
diff --git a/Processes/CONEXSourceCut/CONEXSourceCut.h b/Processes/CONEXSourceCut/CONEXSourceCut.h
index 3dced0507552bd0e89b931448e14f36153bf12b5..918f6b1f3156c5fb260cde9aef1373d39a29f824 100644
--- a/Processes/CONEXSourceCut/CONEXSourceCut.h
+++ b/Processes/CONEXSourceCut/CONEXSourceCut.h
@@ -11,6 +11,9 @@
 #ifndef _corsika_process_particle_cut_CONEXSourceCut_h_
 #define _corsika_process_particle_cut_CONEXSourceCut_h_
 
+#include <corsika/environment/ShowerAxis.h>
+#include <corsika/geometry/Point.h>
+#include <corsika/geometry/Vector.h>
 #include <corsika/particles/ParticleProperties.h>
 #include <corsika/process/SecondariesProcess.h>
 #include <corsika/setup/SetupStack.h>
@@ -18,20 +21,20 @@
 
 namespace conex {
   extern "C" {
-  extern struct cxcut_ {
+  extern struct {
     double eecut;
     double epcut;
     double ehcut;
     double emcut;
-  };
+  } cxcut_;
 
-  extern struct cxsubcut_ {
+  extern struct {
     double feecut_;
     double fehcut_;
     double femcut_;
-  };
+  } cxsubcut_;
 
-  extern struct cxbas4_ {
+  extern struct {
     double eprima_;
     double thetas_;
     double costhet_;
@@ -44,94 +47,14 @@ namespace conex {
     double XminSlant;
     double HGrd;
     double distMaxi;
-  };
-
-  extern struct cxoptl_ {
-    struct dptl_ {
-      double px, py, pz, E, m; // 5-momentum
-      double x, y;
-      double h;
-      double t;
-      double id;
-      double weight;
-      double generation;
-      double Xslant;
-      double lateralX, lateralY;
-      double slantDistance;
-    };
-  };
-
-  extern struct cxbas6_ {
-    double altitude;
-    double RadGrd;
-    double DistALt;
-    double dphmaxi0;
-    double dphlim0;
-    double dphmin0;
-    bool goOutGrd;
-  };
-
-  extern struct cxetc_ {
-    int mode;
-    int iwrt;
-    int i1DMC;
-    int iphonu;
-  };
-
-  extern struct cxthin_ {
-    double thin;
-    double ethin;
-    double wtmax;
-    double rthmax;
-    int iothin;
-  };
-
-  extern struct cxoutput3_ {
-    std::array<std::array<double, 4>, mxPxpro + 2> XmaxShow;
-    std::array<std::array<double, 5>, mxPxpro + 2> XmaxMean;
-    std::array<std::array<double, maximz>, mxPxpro> XmaxProf;
-    int iXmax;
-  };
-
-  int constexpr mxExpro = 1;
-  int constexpr mxPxpro = 10,
-
-                int constexpr maximE = 281;
-
-// CONEX ifdef
-#ifdef __SAVEMEMO__
-  int constexpr maximZ = 201;
-#else
-  int constexpr maximZ = 3701;
-#endif
-
-  extern struct cxoutput1_ {
-    std::array<std::array<std::array<double, maximZ>, mxExpro>, mxPxpro + 2> XProf,
-        XmeanP, XmeanP2;
-    std::array<double, mxExpro> EMCutP, HaCutP;
-    double XminP;
-    double XmaxP;
-    int nminX;
-    int nmaxX;
-    int mZEMHa;
-    int ifout;
-    int ivers;
-    bool lheader;
-  };
-
-  /*
-          common/cxoutput3/XmaxShow(4,-1:mxPxpro),XmaxMean(5,-1:mxPxpro)
-       &,XmaxProf(maximz,-1:mxPxpro),iXmax
-        common/cxoutput1/XProf(maximz,mxExpro,-1:mxPxpro)
-       &,XmeanP(maximz,mxExpro,-1:mxPxpro)
-       &,XmeanP2(maximz,mxExpro,-1:mxPxpro)
-       &,EMCutP(mxExpro),HaCutP(mxExpro),XminP,XmaxP
-       &,nminX,nmaxX,mZEMHa,ifout,ivers,lheader
-  */
-
-  int InitialParticle_(int&);
-  void HadronCascade_(int&, int&, int&, int&);
-  void SolveMomentEquations_(int&);
+  } cxbas4_;
+
+  // ipart,energy,theta,phi,dimpact,ioseed
+  void conexrun_(int& ipart, double& energy, double& theta, double& phi, double& dimpact,
+                 int ioseed[3]);
+  void conexcascade_();
+  void hadroncascade_(int&, int&, int&, int&);
+  void solvemomentequations_(int&);
   void show_(int& iqi, double& ei, double& xmi, double& ymi, double& zmi, double& dmi,
              double& xi, double& yi, double& zi, double& tmi, double& ui, double& vi,
              double& wi, int& iri, double& wti, int& latchi);
@@ -146,8 +69,10 @@ namespace corsika::process {
     class CONEXSourceCut : public process::SecondariesProcess<CONEXSourceCut> {
 
     public:
-      CONEXSourceCut(geometry::Point const& center, environment::ShowerAxis const&,
-                     units::si::LengthType, units::si::GrammageType);
+      CONEXSourceCut(geometry::Point center, environment::ShowerAxis showerAxis,
+                     units::si::LengthType groundDist, units::si::GrammageType Xcut,
+                     units::si::HEPEnergyType primaryEnergy,
+                     particles::PDGCode primaryID);
       corsika::process::EProcessReturn DoSecondaries(corsika::setup::StackView&);
 
       void Init();
@@ -157,18 +82,15 @@ namespace corsika::process {
     private:
       //! CONEX e.m. particle codes
       static std::array<std::pair<particles::Code, int>, 3> constexpr egs_em_codes_{
-          {particles::Code::Gamma, 0},
-          {particles::Code::Electron, -1},
-          {particles::Code::Positron, -1}};
-
-      int egs_calls_{1};
-      int nshtot_{1};
+          {{particles::Code::Gamma, 0},
+           {particles::Code::Electron, -1},
+           {particles::Code::Positron, -1}}};
 
-      units::si::LengthType groundDist_; //!< length from injection point to shower core
-      geometry::Point const center_;     //!< center of CONEX Earth
+      geometry::Point const center_; //!< center of CONEX Earth
       environment::ShowerAxis const& showerAxis_;
+      units::si::LengthType groundDist_; //!< length from injection point to shower core
       geometry::CoordinateSystem const conexObservationCS_; //!< CONEX observation frame
-      Vector<units::si::dimensionless_d> const x_sf_,
+      geometry::Vector<units::si::dimensionless_d> const x_sf_,
           y_sf_; //!< unit vectors of CONEX shower frame, z_sf is shower axis direction
     };
   } // namespace conex_source_cut