Skip to content

Add icnt_factor and g_realtime keyboard shortcuts#172

Open
alicela1n wants to merge 1 commit intodingusdev:masterfrom
alicela1n:icnt_controls
Open

Add icnt_factor and g_realtime keyboard shortcuts#172
alicela1n wants to merge 1 commit intodingusdev:masterfrom
alicela1n:icnt_controls

Conversation

@alicela1n
Copy link
Copy Markdown
Contributor

@alicela1n alicela1n commented Apr 3, 2026

Added controls to increment/decrement icnt_factor and toggle g_realtime for testing and debugging purposes.
LeftAlt - = -> increment_icnt_factor();
LeftAlt - - -> decrement_icnt_factor();
LeftAlt - r -> toggle_g_realtime();

I'm using LeftAlt as the modifier key to prevent accidental toggling and not conflict with Control shortcuts.

Added controls to increment/decrement icnt_factor and toggle g_realtime
for testing and debugging purposes.
Left Alt = -> increment_icnt_factor();
Left Alt - -> decrement_icnt_factor();
Left Alt r -> toggle_g_realtime();
@dingusdev
Copy link
Copy Markdown
Owner

dingusdev commented Apr 3, 2026

Some commentary from joevt:

That's something I've wanted to add. In addition, we need a counter with more precision to allow for CPU clock calculations that match a real Mac. For example, the pm6100 has these results for different values of icnt_factor:

    icnt_factor =
//          // 1 instruction =        // PDM cpu clock calculated at 0x403036CC in r3
//      11; // 2048 ns =    0.488 MHz // 00068034 =   0.426036 MHz = 2347.219 ns // floppy doesn't work
//      10; // 1024 ns =    0.977 MHz // 000D204C =   0.860236 MHz = 1162.471 ns // invalid
//       9; //  512 ns =    1.953 MHz // 001A6081 =   1.728641 MHz =  578.489 ns // invalid
//       8; //  256 ns =    3.906 MHz // 0034E477 =   3.466359 MHz =  288.487 ns // invalid
//       7; //  128 ns =    7.813 MHz // 0069E54C =   6.939980 MHz =  144.092 ns // invalid
//       6; //   64 ns =   15.625 MHz // 00D3E6F5 =  13.887221 MHz =   72.008 ns //
//       5; //   32 ns =   31.250 MHz // 01A7B672 =  27.768434 MHz =   36.012 ns //
         4; //   16 ns =   62.500 MHz // 034F0F0F =  55.512847 MHz =   18.013 ns // 6100/60 in Apple System Profiler
//       3; //    8 ns =  125.000 MHz // 069E1E1E = 111.025694 MHz =    9.006 ns // invalid
//       2; //    4 ns =  250.000 MHz // 0D3C3C3C = 222.051388 MHz =    4.503 ns // invalid
//       1; //    2 ns =  500.000 MHz // 1A611A7B = 442.571387 MHz =    2.259 ns // invalid
//       0; //    1 ns = 1500.000 MHz // 3465B2D9 = 879.080153 MHz =    1.137 ns // invalid
//
//      (10,60] = 50, (60,73] = 66, (73,100] = 80 MHz
//      [0,10] MHz = invalid clock for PDM gestalt calculation
//      (100,∞) MHz = invalid clock for PDM gestalt calculation

So we use icnt_factor = 4 as the default.

Our current nanoseconds calculator just does this:
g_icycles << icnt_factor

and g_icycles is incremented for every PPC instruction.
g_icycles++

Instead of icnt_factor = 4, we could have a icnt_increment = 16 and g_icycles would be incremented like this:
g_icycles += icnt_increment;

This gives the nanoseconds calculator 4 extra bits of precision. We could add more bits if necessary.

@alicela1n
Copy link
Copy Markdown
Contributor Author

alicela1n commented Apr 3, 2026

setting g_icycles += icnt_increment; as well as declaring int icnt_increment = 16 causes the emulator to get stuck on a black screen and fail to start with the message ERR| Cuda: invalid packet (too few data)!

@joevt
Copy link
Copy Markdown
Contributor

joevt commented Apr 3, 2026

If you use g_icycles += icnt_increment then you should remove << icnt_factor or set icnt_factor to 0. For higher precision, it should be >> icnt_factor and icnt_factor should be > 0.

@joevt
Copy link
Copy Markdown
Contributor

joevt commented Apr 3, 2026

Should think about this more.

The reason I suggested g_icycles += icnt_increment is so that we don't need to add a multiply. Is removing a multiply periodically (process_events is not called for every instruction) counteract the performance decrease of changing g_icycles ++ to g_icycles += icnt_increment (which happens for every instruction)?

If we use g_icycles += icnt_increment then g_icycles is no longer counting instructions - it is counting fixed point virtual nanoseconds.

In any case, we need to modify both get_virt_time_ns and process_events so that they behave correctly with the new interpretation of g_icycles and icnt_factor.

@joevt
Copy link
Copy Markdown
Contributor

joevt commented Apr 3, 2026

If using icnt_increment then ppcexec should copy it to a local variable so that it doesn't need to be read from RAM for every instruction? In that case, changing icnt_increment would require a method to reload the local variable such as by setting power_on to false.

If using g_icycles++ in ppcexec and a multiply in get_virt_time_ns, then process_events would need a divide. yuck.

@joevt
Copy link
Copy Markdown
Contributor

joevt commented Apr 3, 2026

Changes incorporating the icnt_increment suggestions should probably be in a different commit. We should try this pull request as is.

@alicela1n
Copy link
Copy Markdown
Contributor Author

alicela1n commented Apr 4, 2026

Something to be aware of is changing icnt_factor on the fly does cause the emulator to freeze for several seconds (sometimes up to a minute), and setting g_realtime to true causes the emulator to get really slow on my M4 MacBook Air.

@joevt
Copy link
Copy Markdown
Contributor

joevt commented Apr 4, 2026

Should implement the frame rate suggestion of #169 to see what's going on.
Do we need a frame skip option?
Is there a faster way to get nanoseconds than mach_absolute_time on APPLE?
Is timebase_info.numer == timebase_info.denom true or false for Apple Silicon?

@alicela1n
Copy link
Copy Markdown
Contributor Author

alicela1n commented Apr 4, 2026

Should implement the frame rate suggestion of #169 to see what's going on.

I think it's a good idea.

Is there a faster way to get nanoseconds than mach_absolute_time on APPLE?

I don't believe so, Apple recommends using clock_gettime_nsec_np() over mach_absolute_time() these days but it's likely a wrapper around mach_absolute_time().

Is timebase_info.numer == timebase_info.denom true or false for Apple Silicon?

False, I added an entry in the code to print in the logs to verify this.

@joevt
Copy link
Copy Markdown
Contributor

joevt commented Apr 5, 2026

Something to be aware of is changing icnt_factor on the fly does cause the emulator to freeze for several seconds (sometimes up to a minute), and setting g_realtime to true causes the emulator to get really slow on my M4 MacBook Air.

If virtual nanoseconds is at 2 minutes and you change icnt_factor from 4 to 3 then that changes how virtual nanoseconds is calculated and now virtual nanoseconds is at 1 minute which means nothing in the TimerManager queue is going to happen for at least a virtual minute.

So you have to make sure the current virtual nanoseconds doesn't change when changing how the virtual nanoseconds is calculated because the TimerManager queue and maybe some other devices may depend on the time. I've updated your commit in my fork:
joevt@451698f

Does the updated commit improve what you see on your M4 with regards to freezing when changing icnt_factor on the fly?

Does the updated commit improve what you see on your M4 with regards to setting g_realtime to true?

I set the minimum icnt_factor to 0 because C++ doesn't support negative shifts.

If I try icnt_factor of 8, then problems occur and I have to go down to 7 or 6. Maybe the problem is with device emulation or maybe some devices (ViaCuda especially) don't like super slow CPUs (a high icnt_factor means more virtual nanoseconds occur per instruction).

@joevt
Copy link
Copy Markdown
Contributor

joevt commented Apr 6, 2026

g_realtime can be toggled in Mac OS 8 without issues, but it always causes a problem in Mac OS X (at least after the Finder appears).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants