Is the ECS BASIC really just blocked waiting on the EXEC? I thought that it was synchronized with the EXEC in that the EXEC is the one which "ticks" the interpreter engine. In that way, the ECS BASIC is just another "game" running off the EXEC in EXEC time.
Consequently, keys are read at 20 Hz, and each statement is executed on an EXEC "tick" boundary (every 20 Hz).
Perhaps this is what you meant, but I guess I make a distinction between something like an IntyBASIC program, which runs in its own game loop and then has to "WAIT" for the ISR to synchronize, and an EXEC program which are just a bunch of subroutines triggered by the EXEC itself as it chug alongs in its game engine loop. I always thought the ECS BASIC was the latter.
ECS BASIC is not implemented as an EXEC "process", in terms of its timer-driven process table.
The ECS BASIC interpreter loop does, however, synchronize with the EXEC's 20Hz phase counter, blocking the "RUN" loop from progressing. The top of the keyword interpretation loop has this:
; main interpreter outer loop during 'RUN'
MVI G_0102, R0 ; 2E25 Get current EXEC phase
CMPI #$0002, R0 ; 2E27 Is it phase 2 or higher?
BGE L_2E2C ; 2E29 Proceed with execution
PULR R7 ; 2E2B Otherwise, don't.
When you launch BASIC in the fastest execution mode—it is actually sensitive to the "slow down" mode based on pressing 1, 2, 3 instead of DISC, if memory serves—it watches the EXEC variable at $102 to determine which part of the 20Hz cycle it's in. It ordinarily counts down 2, 1, 0, 2, 1, 0. (In slower modes, it counts down from a higher number, which is how it achieves its slow-down.) Here's a trace of $102 from an EXEC based game (Astrosmash). You'll note it briefly takes on the value 3, but that's in anticipation of it getting decremented. It's a 20Hz cadence if you do the math on the cycle counts. ECS BASIC would only see the 2, 1, and 0, if I'm not mistaken.
WR a=$0102 d=0003 CP-1610 (PC = $1097) t=5247326
WR a=$0102 d=0002 CP-1610 (PC = $1130) t=5259726
WR a=$0102 d=0001 CP-1610 (PC = $1130) t=5274666
WR a=$0102 d=0000 CP-1610 (PC = $1130) t=5289600
WR a=$0102 d=0003 CP-1610 (PC = $1097) t=5291985
WR a=$0102 d=0002 CP-1610 (PC = $1130) t=5304533
WR a=$0102 d=0001 CP-1610 (PC = $1130) t=5319468
WR a=$0102 d=0000 CP-1610 (PC = $1130) t=5334402
WR a=$0102 d=0003 CP-1610 (PC = $1097) t=5336693
So, the run loop is literally synchronizing with the EXEC by watching an EXEC state variable and busy-waiting. If an ECS BASIC statement takes less than 1/20th of a second to execute, it gets rounded up to 1/20th of a second. If an ECS BASIC statement takes longer than 1/20th of a second to execute, its execution time effectively gets rounded up to the next 20Hz boundary. Every statement ultimately seems to take some multiple of 1/20th of a second thanks to this busy-wait.
That's why I say that the execution penalty incurred due to the EXEC doesn't reside entirely inside the EXEC. Much of it is in the busy-wait outside the EXEC in the main interpreter loop, in this synchronization point that waits for the EXEC to get into one of the 3 phases of its 20Hz cycle.
Ironically, it appears you can speed up ECS BASIC by selecting a slower EXEC speed (pressing 1, 2, or 3 at the menu). I'll have to experiment with that later.
Edited by intvnut, Sun Nov 4, 2018 2:55 PM.