I would do something similar what CMAllen suggested, but you can get everything you need with one variable and a couple different functions.
First you want to store the lowest possible time value, which in your case is milliseconds. If you wanted you could even use microseconds since GM supports that with the
delta_time variable. I personally use delta_time to increment the time variable because you can either use it for microseconds or you can multiply it by 0.001 and that will give you milliseconds. As the documentation states, delta_time returns the time between the current step and the last step so you need to increment your time every step.
Create
Code:
timerMS=0 //overall time in milliseconds
Step
Code:
timerMS += delta_time * 0.001; //add time passed since last step in milliseconds
Now that you have an accurate millisecond timer, you can make a couple scripts that convert that time in milliseconds to the whichever measurement of time you need.
The following functions all take the timerMS variable as an argument
scr_CurrentMS(time) --returns current millisecond value for this specific second
Code:
//returns the remainder of timerMS / 1000 which gives you the current millisecond value
return argument0 mod 1000;
scr_TotalSec(time) --returns overall seconds
Code:
//returns the floored quotient of timerMS / 1000 which gives you overall time in seconds
return argument0 div 1000
scr_CurrentSec(time) --returns current second value for this specific minute
Code:
//returns remainder of totalTimeInSeconds / 60 which gives you the current second value
return scr_TotalSec(argument0) mod 60
scr_CurrentMin(time) --returns current minute value for this specific hour
Code:
//returns the floored quotient of totalTimeInSeconds / 60 which gives you the current minute value
return scr_TotalSec(argument0) div 60
I put these scripts together in my head while converting an old script I had that did something similar but did the time starting from seconds and went up to hours. I haven't actually plugged these into GM but everything should work as you'd expect. Let me know if you have any issues understanding what is happening. I commented it a good amount to hopefully explain clearly what is going on. It's all really simple math.
Also I should mention that at a certain point you'll want to reset your timerMS value so you don't have to worry about integer overflow. There are 86,400,000 milliseconds in a day and since GM uses the double data type you should have no issue getting an entire day into your timer and probably way more. You mentioned this is a speed-running game so you shouldn't have any issues with integer overflow, but it's just something to remember.