@echo off
:: ==========================================================================
::  Ferminux Network - START MINING (CPU)
::
::  Double-click this file. It asks for your payout address and how many CPU
::  threads to use, remembers both, then starts ferminux-geth mining.
::
::  Notes for whoever edits this next:
::   * Delayed expansion is DISABLED on purpose. Input is read with `set /p`,
::     and with delayed expansion ON an exclamation mark in pasted input is
::     silently eaten. Loops use GOTO, not FOR blocks, so plain %VAR%
::     expansion is always current.
::   * NEVER put a `call :sub` and a test of the variable it sets inside the
::     same parenthesised block: the whole block is expanded before any of it
::     runs, so the test would read the value from before the call.
::   * Every comparison quotes both sides, so &  |  >  ^ in pasted input
::     cannot break out of the command line.
::   * Hex validation strips the 16 hex digits out of the string; whatever
::     survives is a non-hex character. Batch string substitution is
::     case-insensitive, so a-f and A-F are covered in one pass.
::   * Redirections are written BEFORE the command (`>"%CFG%" echo x`) so no
::     trailing space is ever written into the settings file.
::   * The script never exits without a pause - see :fail / :done.
:: ==========================================================================
setlocal EnableExtensions DisableDelayedExpansion
title Ferminux Network - CPU Mining

set "HERE=%~dp0"
set "EXE=%HERE%ferminux-geth.exe"
set "PORT=30303"
set "IPCNAME=ferminux.ipc"

cls
echo.
echo   ====================================================================
echo    FERMINUX NETWORK   -   CPU MINING
echo   ====================================================================
echo.

:: ---------------------------------------------------------------------
:: 1. Is the binary actually here?
:: ---------------------------------------------------------------------
if exist "%EXE%" goto :have_exe
echo   PROBLEM: ferminux-geth.exe is not in this folder:
echo.
echo       %HERE%
echo.
echo   Nine times out of ten this means the ZIP was never extracted.
echo   Windows lets you look inside a ZIP file as if it were a folder,
echo   but programs cannot run from in there.
echo.
echo   FIX: close this window. Right-click the ZIP file you downloaded,
echo        choose "Extract All...", open the folder it creates, and
echo        double-click START-MINING.bat in THAT folder.
goto :fail
:have_exe

if defined LOCALAPPDATA goto :have_appdata
echo   PROBLEM: Windows did not set the LOCALAPPDATA variable, so this
echo   script cannot work out where to store the chain data.
echo.
echo   FIX: press the Windows key, type cmd, press Enter, then drag
echo        START-MINING.bat into that window and press Enter.
goto :fail
:have_appdata

set "DATADIR=%LOCALAPPDATA%\Ferminux"
set "DAGDIR=%LOCALAPPDATA%\Ethash"
if not exist "%DATADIR%" mkdir "%DATADIR%" >nul 2>&1

:: ---------------------------------------------------------------------
:: 2. Where do the saved settings live?
::    Next to this script if that folder is writable (keeps the package
::    portable), otherwise inside the data directory.
:: ---------------------------------------------------------------------
set "CFG=%HERE%ferminux-config.txt"
copy /y nul "%HERE%fmx-write-test.tmp" >nul 2>&1
if exist "%HERE%fmx-write-test.tmp" (
  del "%HERE%fmx-write-test.tmp" >nul 2>&1
) else (
  set "CFG=%DATADIR%\ferminux-config.txt"
)

set "ADDR="
set "THREADS="
if exist "%CFG%" (
  for /f "usebackq eol=# tokens=1,* delims==" %%A in ("%CFG%") do (
    if /i "%%A"=="address" set "ADDR=%%B"
    if /i "%%A"=="threads" set "THREADS=%%B"
  )
)

:: Anything loaded from disk is re-validated - never trust the file.
if not defined ADDR goto :cfg_addr_done
set "V_IN=%ADDR%"
call :validate_addr
if not "%V_OK%"=="1" set "ADDR="
:cfg_addr_done

if not defined THREADS goto :cfg_threads_done
set "V_IN=%THREADS%"
call :validate_num
if not "%V_OK%"=="1" set "THREADS="
:cfg_threads_done

:: ---------------------------------------------------------------------
:: 3. Payout address
:: ---------------------------------------------------------------------
if defined ADDR goto :have_addr

echo   STEP 1 of 2 - WHERE SHOULD YOUR FMX GO?
echo   --------------------------------------------------------------------
echo   Mining pays rewards straight to a wallet address. It looks like
echo   this: 0x followed by 40 letters and numbers.
echo.
echo   Do not have one yet? Open https://wallet.ferminux.net in your
echo   browser and create a wallet - it takes about a minute and it is
echo   free. Copy the address that starts with 0x.
echo.
echo   You do NOT type a password or a seed phrase here. This is only the
echo   public address. Nobody, this program included, can spend from it.
echo.

:ask_addr
set "ADDR_IN="
set /p "ADDR_IN=  Paste your 0x address and press Enter: "
set "V_IN=%ADDR_IN%"
call :trim
call :validate_addr
if "%V_OK%"=="1" goto :addr_confirm
echo.
echo   That does not look like a Ferminux address.
echo   It must start with 0x and have exactly 40 more characters, each
echo   one a digit 0-9 or a letter a-f. For example:
echo       0x1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d
echo.
echo   If you copied it with quote marks around it, leave those out -
echo   paste only the address itself.
echo.
echo   Tip: in this window you can paste with a right-click if Ctrl+V
echo        does nothing.
echo.
goto :ask_addr

:addr_confirm
set "ADDR=%V_IN%"
echo.
echo   Read it back carefully. One wrong character sends every reward you
echo   ever mine to an address nobody can open:
echo.
echo       %ADDR:~0,2% %ADDR:~2,4% %ADDR:~6,4% %ADDR:~10,4% %ADDR:~14,4% %ADDR:~18,4% %ADDR:~22,4% %ADDR:~26,4% %ADDR:~30,4% %ADDR:~34,4% %ADDR:~38,4%
echo.
set "YN="
set /p "YN=  Is that exactly right? (Y = yes, anything else = retype): "
if /i "%YN%"=="y" goto :have_addr
if /i "%YN%"=="yes" goto :have_addr
set "ADDR="
echo.
goto :ask_addr

:have_addr

:: ---------------------------------------------------------------------
:: 4. Thread count
:: ---------------------------------------------------------------------
set /a CORES=NUMBER_OF_PROCESSORS+0
if not defined CORES set "CORES=2"
if %CORES% LSS 1 set /a CORES=2
set /a SUGGEST=CORES-2
if %SUGGEST% LSS 1 set /a SUGGEST=1

if defined THREADS goto :have_threads

echo.
echo   STEP 2 of 2 - HOW HARD SHOULD YOUR PC WORK?
echo   --------------------------------------------------------------------
echo   Mining uses your processor. Each "thread" is one worker. More
echo   threads earn more, but the PC gets slower, louder and hotter, and
echo   draws more electricity.
echo.
echo   This PC reports %CORES% processor threads.
echo   Suggested: %SUGGEST%  (leaves 2 free so Windows stays responsive)
echo.

:ask_threads
set "TH_IN="
set /p "TH_IN=  How many threads? (press Enter for %SUGGEST%): "
if not defined TH_IN set "TH_IN=%SUGGEST%"
set "V_IN=%TH_IN%"
call :trim
call :validate_num
if "%V_OK%"=="1" goto :threads_ok
echo.
echo   Please type a whole number between 1 and 99, for example 2.
echo.
goto :ask_threads

:threads_ok
set "THREADS=%V_IN%"

:have_threads
if %THREADS% GTR %CORES% (
  echo.
  echo   Note: this PC has %CORES% threads, so %CORES% will be used.
  set "THREADS=%CORES%"
)

:: ---------------------------------------------------------------------
:: 5. Remember the answers
:: ---------------------------------------------------------------------
>"%CFG%"  2>nul echo # Ferminux mining settings. Delete this file to be asked again.
>>"%CFG%" 2>nul echo address=%ADDR%
>>"%CFG%" 2>nul echo threads=%THREADS%

:: ---------------------------------------------------------------------
:: 6. Summary, first-run DAG warning, launch
:: ---------------------------------------------------------------------
cls
echo.
echo   ====================================================================
echo    FERMINUX NETWORK   -   CPU MINING
echo   ====================================================================
echo.
echo    Payout address : %ADDR%
echo    CPU threads    : %THREADS% of %CORES%
echo    Chain data     : %DATADIR%
echo    Mining data    : %DAGDIR%
echo    Settings file  : %CFG%
echo.

if exist "%DAGDIR%\full-*" goto :dag_ready

echo   ------------------------- FIRST RUN --------------------------------
echo   Before it can mine, Ethash has to build a big lookup table called
echo   the DAG. Expect:
echo.
echo     * about 1.1 GB written to %DAGDIR%
echo     * a few minutes of 100%% CPU while it is generated
echo     * about 1.1 GB of memory held for as long as you mine
echo.
echo   Make sure at least 2.5 GB of disk space is free. This happens once;
echo   the next start is immediate. Roughly every 2.5 days the DAG grows a
echo   few MB and rebuilds in the background - that is normal too.
echo.
echo   While the log says "Generating DAG in progress", nothing is wrong.
echo   --------------------------------------------------------------------
echo.
goto :launch

:dag_ready
echo   The mining DAG already exists, so mining starts right away.
echo.

:launch
echo   Leave this window open. Closing it stops mining.
echo   To stop: press Ctrl+C and answer Y, or just close the window.
echo.
echo   Watch your balance at https://explorer.ferminux.net - paste your
echo   address into the search box. A reward is credited in the same block
echo   you find, so it shows up as soon as the explorer indexes it.
echo.
set "GO="
set /p "GO=  Press Enter to start mining (or type N to cancel): "
if /i "%GO%"=="n" (
  echo.
  echo   Cancelled. Nothing was started.
  goto :done
)

echo.
echo   Starting ferminux-geth. Command:
echo.
echo     ferminux-geth.exe --datadir "%DATADIR%" --ethash.dagdir "%DAGDIR%" --syncmode full --cache 512 --port %PORT% --ipcpath %IPCNAME% --mine --miner.threads %THREADS% --miner.etherbase %ADDR%
echo.
echo   --------------------------------------------------------------------
echo.

"%EXE%" --datadir "%DATADIR%" --ethash.dagdir "%DAGDIR%" --syncmode full --cache 512 --port %PORT% --ipcpath %IPCNAME% --mine --miner.threads %THREADS% --miner.etherbase "%ADDR%"
set "RC=%ERRORLEVEL%"

echo.
echo   --------------------------------------------------------------------
if "%RC%"=="0" (
  echo   ferminux-geth stopped normally. Mining has ended.
  goto :done
)

echo   ferminux-geth stopped with error code %RC%.
echo.
echo   Most likely causes, in order:
echo.
echo    * "Failed to start IPC" or "datadir already used" - Ferminux is
echo      already running in another window. Only one copy can run at a
echo      time. Close the other window and try again.
echo    * "bind: ... permitted" on port %PORT% - something else is using
echo      that port, or Windows Firewall blocked it. When Windows asks,
echo      allow ferminux-geth on Private networks.
echo    * "etherbase must be explicitly specified" - the saved address is
echo      damaged. Delete this file and run again:
echo          %CFG%
echo    * Disk filled up while writing the DAG - free space here:
echo          %DAGDIR%
echo.
echo   Scroll up. The last few lines above normally say exactly what
echo   happened; copy them if you need to ask for help.
goto :fail

:: =====================================================================
::  Subroutines
:: =====================================================================

:: --- strip leading and trailing spaces/tabs from V_IN ----------------
:trim
if not defined V_IN goto :eof
for /f "tokens=*" %%a in ("%V_IN%") do set "V_IN=%%a"
:trim_tail
if not defined V_IN goto :eof
if "%V_IN:~-1%"==" " (
  set "V_IN=%V_IN:~0,-1%"
  goto :trim_tail
)
goto :eof

:: --- V_OK=1 if V_IN is 0x plus exactly 40 hex characters -------------
:validate_addr
set "V_OK=0"
if not defined V_IN goto :eof
if /i not "%V_IN:~0,2%"=="0x" goto :eof
if "%V_IN:~41,1%"=="" goto :eof
if not "%V_IN:~42,1%"=="" goto :eof
set "V_REST=%V_IN:~2%"
set "V_REST=%V_REST:0=%"
set "V_REST=%V_REST:1=%"
set "V_REST=%V_REST:2=%"
set "V_REST=%V_REST:3=%"
set "V_REST=%V_REST:4=%"
set "V_REST=%V_REST:5=%"
set "V_REST=%V_REST:6=%"
set "V_REST=%V_REST:7=%"
set "V_REST=%V_REST:8=%"
set "V_REST=%V_REST:9=%"
set "V_REST=%V_REST:a=%"
set "V_REST=%V_REST:b=%"
set "V_REST=%V_REST:c=%"
set "V_REST=%V_REST:d=%"
set "V_REST=%V_REST:e=%"
set "V_REST=%V_REST:f=%"
if defined V_REST goto :eof
set "V_OK=1"
goto :eof

:: --- V_OK=1 if V_IN is 1-2 digits, no leading zero -------------------
:validate_num
set "V_OK=0"
if not defined V_IN goto :eof
if "%V_IN:~0,1%"=="0" goto :eof
if not "%V_IN:~2,1%"=="" goto :eof
set "V_REST=%V_IN%"
set "V_REST=%V_REST:0=%"
set "V_REST=%V_REST:1=%"
set "V_REST=%V_REST:2=%"
set "V_REST=%V_REST:3=%"
set "V_REST=%V_REST:4=%"
set "V_REST=%V_REST:5=%"
set "V_REST=%V_REST:6=%"
set "V_REST=%V_REST:7=%"
set "V_REST=%V_REST:8=%"
set "V_REST=%V_REST:9=%"
if defined V_REST goto :eof
set "V_OK=1"
goto :eof

:fail
echo.
echo   ====================================================================
echo    Press any key to close this window.
echo   ====================================================================
pause >nul
exit /b 1

:done
echo.
echo   ====================================================================
echo    Press any key to close this window.
echo   ====================================================================
pause >nul
exit /b 0
