diff --git a/Processes/CONEXSourceCut/CONEXSourceCut.cc b/Processes/CONEXSourceCut/CONEXSourceCut.cc
index d82ecb7ead67e94ba2df3f478802a28e99450b5f..c3109315c9f66784a24c68ce2bddf3c952fe4649 100644
--- a/Processes/CONEXSourceCut/CONEXSourceCut.cc
+++ b/Processes/CONEXSourceCut/CONEXSourceCut.cc
@@ -9,10 +9,10 @@
  */
 
 #include <corsika/process/conex_source_cut/CONEXSourceCut.h>
+#include <corsika/units/PhysicalConstants.h>
 #include <algorithm>
 #include <iomanip>
-
-using namespace std;
+#include <utility>
 
 using namespace corsika::process::conex_source_cut;
 using namespace corsika::units::si;
@@ -22,20 +22,61 @@ using namespace corsika::setup;
 corsika::process::EProcessReturn CONEXSourceCut::DoSecondaries(
     corsika::setup::StackView& vS) {
   auto p = vS.begin();
+  HEPEnergyType const energy = p.GetEnergy();
+
   while (p != vS.end()) {
     Code const pid = p.GetPID();
-    HEPEnergyType const energy = p.GetEnergy();
 
-    if (std::find(em_codes_.cbegin(), em_codes_.cend(), pid) != em_codes_.cend()) {
-      std::cout << "CONEXSourceCut: removing " << pid << " " << std::scientific << energy
-                << std::endl;
-
-      p.Delete();
+    auto const it = std::find_if(em_codes_.cbegin(), em_codes_.cend(),
+                                 [=](auto const& p) { return pid == p.first; });
+    if (it == em_codes_.cend()) {
+      continue; // no EM particle
     }
 
-    else {
-      ++p;
-    }
+    auto const& position = p.GetPosition();
+    auto const direction = p.GetMomentum().normalized();
+
+    int egs_pid = it->second;
+
+    double E =
+        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 altitude = ((position - center_).norm() - conex::earthRadius) / 1_m;
+
+    double slantDistance =
+        (position - showerAxis_.GetStart()).dot(showerAxis_.GetDirection()) / 1_m;
+
+    // lateral coordinates in CONEX shower frame
+    auto const d = position - showerAxis_.GetStart();
+    auto const dShowerPlane = d - d.parallelProjectionOnto(showerAxis_.GetDirection());
+    double lateralX = dShowerPlane.dot(x_sf_) / 1_m;
+    double lateralY = dShowerPlane.dot(y_sf_) / 1_m;
+
+    double slantX = showerAxis_.projectedX(position) * (1_cm * 1_cm / 1_g);
+
+    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());
+
+    int iri = 2; // EGS medium air
+
+    double weight = 1;
+
+    int latchin = 1; // generation, we don't have the actual value...
+
+    std::cout << "CONEXSourceCut: removing " << pid << " " << std::scientific << energy
+              << std::endl;
+    p.Delete();
+
+    conex::show_(egs_pid, E, x, y, altitude, slantDistance, lateralX, lateralY, slantX,
+                 time, u, v, w, iri, weight, latchin);
   }
 
   return corsika::process::EProcessReturn::eOk;
@@ -43,4 +84,57 @@ corsika::process::EProcessReturn CONEXSourceCut::DoSecondaries(
 
 void CONEXSourceCut::Init() {}
 
-CONEXSourceCut::CONEXSourceCut() {}
+void CONEXSourceCut::SolveCE() {
+  int zero = 0;
+  int iCEmode = 1;
+  conex::HadronCascade_(id, nshtot_, zero, iCEmode);
+  conex::SolveMomentEquations_(zero);
+}
+
+CONEXSourceCut::CONEXSourceCut(geometry::Point center, environment::ShowerAxis showerAxis,
+                               units::si::LengthType groundDist,
+                               units::si::GrammageType Xcut,
+                               units::si::EnergyType primaryEnergy)
+    : center_{center}
+    , showerAxis_{showerAxis}
+    , groundDist_{groundDist}
+    , conexObservation_{std::invoke([]() {
+      auto const& c8cs = center.GetCoordinateSystem();
+      auto const showerCore =
+          showerAxis.GetStart() + showerAxis.GetDirection() * groundDist;
+      auto const translation = showerCore - center;
+      auto const intermediateCS = c8cs.translate(translation.GetComponents(c8cs));
+      auto const intermediateCS2 = intermediateCS.RotateToZ(translation);
+
+      auto const transform = geometry::CoordinateSystem::GetTransformation(
+          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()}
+    , 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;
+
+  auto const showerAxisConex =
+      showerAxis_.GetDirection().GetComponents(conexObservationCS_);
+  auto const phi = std::atan2(-showerAxisConex.GetY(), showerAxisConex.GetX());
+  conex::cxbas4_::phisho_ = phi * 180;
+
+  // call ranfgt(seed)?
+
+  cxthin_::ethin = 0;
+
+  conex::cxoutput1_::XminP_ = conex::cxoutput1_::XmaxP_ = Xcut / (1_g / 1_cm / 1_cm);
+}
diff --git a/Processes/CONEXSourceCut/CONEXSourceCut.h b/Processes/CONEXSourceCut/CONEXSourceCut.h
index 037451bb37d8b4d8006165c9270608c2d1981774..3dced0507552bd0e89b931448e14f36153bf12b5 100644
--- a/Processes/CONEXSourceCut/CONEXSourceCut.h
+++ b/Processes/CONEXSourceCut/CONEXSourceCut.h
@@ -16,19 +16,160 @@
 #include <corsika/setup/SetupStack.h>
 #include <corsika/units/PhysicalUnits.h>
 
+namespace conex {
+  extern "C" {
+  extern struct cxcut_ {
+    double eecut;
+    double epcut;
+    double ehcut;
+    double emcut;
+  };
+
+  extern struct cxsubcut_ {
+    double feecut_;
+    double fehcut_;
+    double femcut_;
+  };
+
+  extern struct cxbas4_ {
+    double eprima_;
+    double thetas_;
+    double costhet_;
+    double phisho_;
+    int muse;
+    int musz;
+    double c2bas;
+    double sinthet;
+    double sinphi;
+    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&);
+  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);
+  }
+
+  corsika::units::si::LengthType constexpr earthRadius{6371315 *
+                                                       corsika::units::si::meter};
+} // namespace conex
+
 namespace corsika::process {
   namespace conex_source_cut {
     class CONEXSourceCut : public process::SecondariesProcess<CONEXSourceCut> {
 
     public:
-      CONEXSourceCut();
+      CONEXSourceCut(geometry::Point const& center, environment::ShowerAxis const&,
+                     units::si::LengthType, units::si::GrammageType);
       corsika::process::EProcessReturn DoSecondaries(corsika::setup::StackView&);
 
       void Init();
 
+      void SolveCE();
+
     private:
-      static std::array<particles::Code, 3> constexpr em_codes_{
-          particles::Code::Gamma, particles::Code::Electron, particles::Code::Positron};
+      //! 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};
+
+      units::si::LengthType groundDist_; //!< length from injection point to shower core
+      geometry::Point const center_;     //!< center of CONEX Earth
+      environment::ShowerAxis const& showerAxis_;
+      geometry::CoordinateSystem const conexObservationCS_; //!< CONEX observation frame
+      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
 } // namespace corsika::process