Need Help For Snes Emulator Optimizing


rohezal

Advanced Member
Joined
Oct 18, 2009
Messages
1,712
Hi guys,

there is an optimized SNES Emulator for the Freerunner Mobile Phone.

400 MHZ arm chip
128 MB Ram
Debiab or OpenMoko Kernel (Linux)

It isn't very optimized and the phone has problems with its gpu (slow bus and bad documentation / drivers). It should be capable of playing games fullspeed with sound. Optimized it archives around 16-20 frames without sound (I would say) and unoptimized 2 - 4 frames.

Maybe someone can I take a look at it. I would like to help if possible but I can just write C not assembler.

Emulator: http://fz.hobby-site.org/om/gamerunner/sources/
Mobile Phone: http://wiki.openmoko.org/wiki/Freerunner
Distrobution: http://gamerunner.sourceforge.net/games.html
 
FWIW, snes9x4d4p is pretty much full speed with audio, but you often need to clock up to achieve it (as it was a pretty quick port that I did.). A good choice (other than optimizing snes9x4d4p) is PocketSNES from gp2x, as its chalk full of ASM and will run full speed on much lower clock (for conserving battery, etc.)

I didn't look too closely, but I think the one you're referring to is actually a slightly older version of the same one snes94d4p is pulled from - SiENcE's dingoo snes9x.

jeff
 
Thank you for the answer.

By the way the freerunner uses the same arm core as the gp32 and the gp2x: ARM920T core.
This should make porting more easy or? The GP32 and the Freerunner chip are both from samsung.
Samsung S3C2400X01 133 MHZ http://en.wikipedia.org/wiki/GP32
Samsung S3C2442B B54 400MHZ http://wiki.openmoko.org/wiki/Neo_FreeRunner_Hardware

Can I maybe even use the same binary? Thread in Gamerunner / Freerunner board: http://jlime.com/forum/viewtopic.php?f=117&t=2888&p=10219#p10219

Downloading PocketSNES_v650_src.zip (639.0 KB)
http://dl.openhandhelds.org/cgi-bin/wiz.cgi?0,1,0,0,46,390


Can I just compile it and it will run on the freerunner? Or must I port it? Can I just use other cross compilers? Looks like I have to change some things. Can you tell me how I can cross compile? It is possible to just use other tools / include files or have I to modify the .h / .c files?

Triet it, but I dont got the files so it can't compile.

$ make
mcpu=arm920t -mtune=arm920t -static -g -I . -I /opt/open2x/gcc-4.1.1-glibc-2.3.6/include -I/opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/sys-include -O3 -D__GP2X__ -ffast-math -fexpensive-optimizations -finline -finline-functions -msoft-float -falign-functions=32 -falign-loops -falign-labels -falign-jumps -fomit-frame-pointer -fprofile-use -c memset.s -o memset.o
/bin/sh: -mtune=arm920t: not found


Include Files: -I /opt/open2x/gcc-4.1.1-glibc-2.3.6/include -I/opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/sys-include -O3 -D__GP2X__

Cross Compiler: GCC = /opt/open2x/gcc-4.1.1-glibc-2.3.6/bin/arm-open2x-linux-gcc.exe
What is strip?: STRIP = /opt/open2x/gcc-4.1.1-glibc-2.3.6/bin/arm-open2x-linux-strip.exe

Assembler for the chip? : ADSASM = /opt/open2x/gcc-4.1.1-glibc-2.3.6/bin/arm-open2x-linux-as.exe
 
skeezix said:
FWIW, snes9x4d4p is pretty much full speed with audio, but you often need to clock up to achieve it (as it was a pretty quick port that I did.). A good choice (other than optimizing snes9x4d4p) is PocketSNES from gp2x, as its chalk full of ASM and will run full speed on much lower clock (for conserving battery, etc.)

I didn't look too closely, but I think the one you're referring to is actually a slightly older version of the same one snes94d4p is pulled from - SiENcE's dingoo snes9x.

jeff
I wondered about that, howcome you chose to port the much less featured Dingoo MIPS version to the Pandora with no ARM optimizations when the Wiz PocketSNES with ARM optimizations would have run much better and with more features. That had me scratching my head. Well at least it is something for now and is decent for many things.

Hopefully someone will still port PocketSNES and not just say "Oh there already is a SNES emu so I won't bother".
 
Last edited by a moderator:
skeezix has certainly forgotten more about coding than I'll ever learn, but ...

Are you trying to run PocketSNES on the freerunner, or the emulator from the freerunner on the Pandora? Or PocketSNES on the Pandora?

If the latter, skeezix has a post on setting up a cross-compiler here: http://www.rjmitchell.ca/~jeff/blog2009/2010/06/02/getting-up-and-going-with-a-crosscompiler-for-pandora-arm-in-5-minutes/
If you're compiling for the Pandora you'll need to change those arguments to 'make', since the Pandora has a Cortex A8 and not an arm920t.

strip is a utility that reduces file size by removing debugging information from executables.

edit:
DaveC said:
I wondered about that, howcome you chose to port the much less featured Dingoo MIPS version to the Pandora with no ARM optimizations when the Wiz PocketSNES with ARM optimizations would have run much better and with more features. That had me scratching my head. Well at least it is something for now and is decent for many things.
I would imagine PocketSNES is too close to the hardware to be a quick and easy port, at least relative to the Dingoo one. I have no doubt that PocketSNES will be available eventually. :)
 
Last edited by a moderator:
First: I try to port for the Freerunner from GP2X, Wiz and GP32

I wondered about that, howcome you chose to port the much less featured Dingoo MIPS version to the Pandora with no ARM optimizations when the Wiz PocketSNES with ARM optimizations would have run much better and with more features. That had me scratching my head. Well at least it is something for now and is decent for many things.

I tried to port the Wizz Version. But it looks like there is additional hardwware like an 3D Chip on it. I think it would be much smarter to the GP2X SNES emulator for the same CPU. The freerunner has 400 mhz, the GP2X 200 mhz and a 200 mhz float coprozessor. This video of squidgesnes looks very promising. Is the source avaible?
http://www.youtube.com/watch?v=Z3C0K0FBHmY

Other question: The GP32 who has almost the same chip from samsung (just 133 instead 400 mhz) has an NES emulator and a Sega Mega Drive / Genesis Emulator. Is the source avaible? http://www.youtube.com/watch?v=Bxe1MsEoCrE


Tom` said:
If you're compiling for the Pandora you'll need to change those arguments to 'make', since the Pandora has a Cortex A8 and not an arm920t.
strip is a utility that reduces file size by removing debugging information from executables.

Thank your for the informations :) .


Can you tell me where I could find the source if avaible? I'm going to look for a toolchain for crosscompile for the freerunner.

Edit: WAIT... on this page is written that notaz has coded the squidgesnes emulator. Is it "our" notaz? If it is true, he maybe could help me to get the source, if I ask nicely :) .
http://wiki.gp2x.org/wiki/SquidgeSNES

Edit:
Here is my post in the gamerunner board:

Asked for an faster SNES emulator in the open pandora board. got a reply.
They told me to try PocketSnes which is very optimized but needs hacked roms.

Some Video from it. Looks very promising:

GP2X: 200 MHZ Arm920 chip (same as Freerunner) with 200 MHZ but 200 MHZ Float co processor:
Using an other Emulator squidgesnes v0.37 :
http://en.wikipedia.org/wiki/GP2X
http://www.youtube.com/watch?v=Z3C0K0FBHmY

GP32 same ARM Chip (same as freerunner) with 133 mhz, i think we shoould give the sega mega drive / genesis a try:
http://en.wikipedia.org/wiki/GP32
http://www.youtube.com/watch?v=Bxe1MsEoCrE

A phone with similar specs like the freerunner (433 instead of 400 mhz):
http://www.gsmarena.com/samsung_i710-1916.php
http://www.youtube.com/watch?v=3SYpTq8rhKQ

PocketSnes on the Wizz (533 mhz can be overclocked to 800 mhz)
Same Chip but with
http://en.wikipedia.org/wiki/GP2X_Wiz
http://www.youtube.com/watch?v=VlIlkD67zw4

I asked how to port it here: http://www.gp32x.de/board/index.php?/topic/53987-need-help-for-snes-emulator-optimizing/
 
Last edited by a moderator:
So basicly this thread is in the wrong section (not even pandora related, and far far away from any other handhelds on this forums) + you imply that you can code and at least compile your stuff, yet you fail to see the difference between the compilers AND you can't even fix it yourself?

Basicly you look like someone who wants a good SNES emu and shamelessly asks on some other forum so others do it for you.

Even the topic title is misleading because rather than saying: "I want someone to port the emulator to my phone", you imply that an SNES emulator already exists for your phone which should be improved. However, in the topic you ask us (who don't have anything to do with your type of phone) to port a completly different emu.

Actually, all you did was really just ask for someone to do what you want + you entered "make" in a terminal which is also far away from only "needing help" or even trying it yourself.


Topic summary (imHo):

"Someone port this to my phone, I tried "make" on the gp2x code but didn't work, kthxbye"
 
I don't get why people want to run emulators on Freerunner anyway. The performance is massively crippled by the video display (even at low resolutions, especially at 16+bpp) and the only viable controls it has are a single touch touchscreen.. Without external controls playing almost any emulated game is impossible.
 
Exophase said:
Without external controls playing almost any emulated game is impossible.
Tell that to the iPhone crowd.. They at least have multitouch though.
 
Last edited by a moderator:
So basicly this thread is in the wrong section (not even pandora related, and far far away from any other handhelds on this forums) + you imply that you can code and at least compile your stuff, yet you fail to see the difference between the compilers AND you can't even fix it yourself?

No experience with cross compiling sorry. Thats the point a need help. The only thing I did was writing a textbox library and compile via a GUI with all settings done by someone other for a microcontroller last week.

Basicly you look like someone who wants a good SNES emu and shamelessly asks on some other forum so others do it for you.

I must admit it is half true. I can write good C code. But I can't write assembler. I would try to port it, with the right librarys and maybe change some C and CPP code. But if it isnt fast enough I would need someone who can write assembler.

"Someone port this to my phone, I tried "make" on the gp2x code but didn't work, kthxbye"
I need help where to start (almost no cross compile experience), but I would put a fair amount of work into it.

Actually, all you did was really just ask for someone to do what you want + you entered "make" in a terminal which is also far away from only "needing help" or even trying it yourself.
writing later
 
DaveC said:
skeezix said:
FWIW, snes9x4d4p is pretty much full speed with audio, but you often need to clock up to achieve it (as it was a pretty quick port that I did.). A good choice (other than optimizing snes9x4d4p) is PocketSNES from gp2x, as its chalk full of ASM and will run full speed on much lower clock (for conserving battery, etc.)

I didn't look too closely, but I think the one you're referring to is actually a slightly older version of the same one snes94d4p is pulled from - SiENcE's dingoo snes9x.

jeff
I wondered about that, howcome you chose to port the much less featured Dingoo MIPS version to the Pandora with no ARM optimizations when the Wiz PocketSNES with ARM optimizations would have run much better and with more features. That had me scratching my head. Well at least it is something for now and is decent for many things.

Hopefully someone will still port PocketSNES and not just say "Oh there already is a SNES emu so I won't bother".

My assumption was that skeezix ported the Dingoo version because it was based off of a much more recent and feature rich version of SNES9x than PocketSNES.

-God Ginrai
 
Last edited by a moderator:
God Ginrai said:
My assumption was that skeezix ported the Dingoo version because it was based off of a much more recent and feature rich version of SNES9x than PocketSNES.

I disagree, I think he did it because it was less work. I wonder what ever happened to Firefox's PocketSNES port. For that matter, I wonder what ever happened to Firefox.

rohezal said:
I must admit it is half true. I can write good C code. But I can't write assembler. I would try to port it, with the right librarys and maybe change some C and CPP code. But if it isnt fast enough I would need someone who can write assembler.

If you're genuinely good at writing C code then use that skill to write a faster SNES emulator in C, before you look to grinding out ARM ASM for optimization. To be honest, I've never met someone I could legitimately claim is good at C but incapable of learning ARM ASM, or have you even tried?
 
Last edited by a moderator:
Actually, all you did was really just ask for someone to do what you want + you entered "make" in a terminal which is also far away from only "needing help" or even trying it yourself.

Half true. I don't know where to start. I thought hey, there is an emulator written in C. But it's slow. Maybe I can someone here who knows more about it, where the optimizing without ASM is possible. And maybe get some help for it. Then I noticed that there are optimized emulators for the ARM chip. I want to ask which emulator would fit best (I would say squidgesnes because its both Samsung and GP2X and Freerunner have not decent graphic hardware). Then I asked where to find the source and how to cross compile it. Like I said I don't know much about it. Written a few QT programms for MAC, Windows and Linux (Debian). And a bit mikrocontroller stuff.

Even the topic title is misleading because rather than saying: "I want someone to port the emulator to my phone", you imply that an SNES emulator already exists for your phone which should be improved. However, in the topic you ask us (who don't have anything to do with your type of phone) to port a completly different emu.

At first I realy wanted some help for improving an existing emulator. And tried to ask where to start. But after a few posts, I understood that there are allready improved emulators for the same CPU and almost the same chip. I think it would more clever to use this emulators. It's true that you don't have anything to do with the phone. But this is the only emulator board I know, and I hoped that maybe a nice guy would help me. The problem is I'm an emulator noob. No ASM or emulation experience. But I'm happy to learn new things. But I think it would be much work to teach a noob :(.

"Someone port this to my phone, I tried "make" on the gp2x code but didn't work, kthxbye"

I'm sad that it looked this way. I realy want to write code to get a good working emulator to the freerunner. But I realy need help at the start. I don't know not much about emulation. Just that there are 2 ways: Lookup table for commands CPU1 to commands CPU2 in realtime. Way2: compiling stuff in RAM and check if its modified.

Is there a website to learn how write a emulator without asm? Can you help me and answer some questions? When I'm honest I would realy like to get some help via IRC or ICQ. Trying to do some stuff and asking question about it. And there first question is: which emulator to choose and how to cross compile?

If you're genuinely good at writing C code then use that skill to write a faster SNES emulator in C, before you look to grinding out ARM ASM for optimization. To be honest, I've never met someone I could legitimately claim is good at C but incapable of learning ARM ASM, or have you even tried?

In the fall I'm writing my bachelor thesis in computer science. I'm writing C since 9 years and have done 2 big projects in it. But to be honest, I think it was not right to say I'm good in C. It's a realy complex language even withhis few keywords. But I can do the whole design pattern, makro, pointer, pointer to pointer, free, malloc stuff. And write half efficent code (passing pointers to functions, free memory, stay on the stack when possible). And even some meta programming experience in C++ (compiler "hacks". Use templates to compute stuff in compile time).

I never tried assembler. It's a shame I know. But I'm a bit scared of it. Maybe it's a good time now to start to learn it :). In my university there is no teaching in assembler for computer science students. Just for electrical engeeners.


I don't get why people want to run emulators on Freerunner anyway. The performance is massively crippled by the video display (even at low resolutions, especially at 16+bpp) and the only viable controls it has are a single touch touchscreen.. Without external controls playing almost any emulated game is impossible.

The glamo realy sux. But it has 90 MB/s bandwith and run smoothly in 320x240 pixel. Not good but hey, for a small screen its ok. There are some USB gamepad shells like the in the openmoko wiki: http://wiki.openmoko.org/wiki/USB_Gamepad_%28NeoPlay%29

Or in this thread:
http://www.gp32x.de/board/index.php?/topic/53914-looking-for-a-special-gamepad/page__p__865038__fromsearch__1

I think you can use it
 
Last edited by a moderator:
rohezal said:
The glamo realy sux. But it has 90 MB/s bandwith and run smoothly in 320x240 pixel. Not good but hey, for a small screen its ok. There are some USB gamepad shells like the in the openmoko wiki: http://wiki.openmoko...d_%28NeoPlay%29

I can't define "NeoPlay" as anything short of horrifying - save having to make it yourself, it just doesn't look like it can possibly be a good controller. That, and it doesn't have shoulder buttons.

From what I could see before the interface to Glamo isn't anywhere close to 90 MB/s, has something drastic changed in the configuration that somehow made this true? From what I recall (and a googling of the matter) it's actually only a scant 7.3 MB/s, which can't even support 320x240x16bpp @ 60fps. Furthermore, it's shared with the SD card so any access to it will dip things (fortunately it's less of a problem for SNES emulation) and again, unless things have changed in the kernel, there was no DMA to the Glamo so the CPU had to babysit the transfers. So even at 320x240x16bpp @ 30fps you would be burning 4.4 MB/s and 60% of your CPU time. With only 40% of an ARM9 at 400MHz (dunno about the speed of the Freerunner's DRAM) you might struggle to reach 320x240x16bpp @ 30fps anyway (at least with emulators we currently have for ARM), so you could end up reaching equilibrium somewhere else.
 
Last edited by a moderator:
Oh sorry I misread something.

Poor performance + slow bus speed of the Glamo GPU - discussed to death on the mailing lists and IRC.
stable-2.6.26 branch of kernel has wait states lowered, core speed increased from 50MHz to 80MHz and memory speed from 80MHz to 90MHz (the latter is also in stable branch) - these lessen the problem a bit, though it's slow still

I read it was 90 MB/s. But how thin is the bus? Even with 1 bit it should be 90/8 around 11 MB/s. A normal PCI 1.0 bus has 32 bit. Strange. But hey, now I know there the bottleneck is.

PAL televisions have "half frame". First frame: line 1,3,5,7,9,11 ... Second frame: line 2,4,6,8,10 ...
Is it possible to write just half frame to the glamo and save 50% of the bandwith? So we use only 2,2 MB/s and have around 60-70% of cpu time (Why is the glamo blocking the cpu anyway, !"$%&/()). Maybe we can update an outer 10 pixel boarder only every 4th or 6th frame because its in most games not very important and save a bit speed too. The sound issue is surely from the blocked cpu while the image is transfered. Hmm ok I see now some problems. Thank you guys :) .

I can't define "NeoPlay" as anything short of horrifying - save having to make it yourself, it just doesn't look like it can possibly be a good controller. That, and it doesn't have shoulder buttons.

I want to try it :) . Playing SNES on the phone would just rock. But maybe with sme real controller parts. Some eletro engeeners from my university are going to make one for me. In exchange I have to write C code for their micro controllers^^
 
rohezal said:
I read it was 90 MB/s. But how thin is the bus? Even with 1 bit it should be 90/8 around 11 MB/s. A normal PCI 1.0 bus has 32 bit. Strange. But hey, now I know there the bottleneck is.

It's not a serial bus, it's parallel data/address over an asynchronous interface on the SoC's external memory interface. You can see from the schematics that the bus width is 16-bit, but transfers are obviously not one clock cycle. Some fixed number of waitstates on the CPU side are enforced, then the Glamo can further stall things using the nWAIT line when bus contention with its internal VRAM occurs. The contention shouldn't be that frequent, but apparently the nWAIT periods are frequent and long.

The 7.3MB/s number came from TheRasterman back in April 2008. I don't know how he got it, maybe by benchmarking. This amount would probably be aggregate over a long period of time because the actual number of clock cycles an access takes fluctuates.

Internally, the Glamo is probably performing operations synchronous with its clock. So, so long as it still works after the overclock it should be true that the internal waitstates due to contention would be lowered, and apparently it's also true that the external waitstate requirements were lowered. But I can't tell how much from your post, and I can't find any numbers. I do know the 7.3MB/s figure came before the update you're referring to, but I also worked with the Freerunner after that and performance was abysmal, so it couldn't be that substantial.

From what I can gather, the Glamo is really supposed to get data over a synchronous burst interface, but the SoC used can't natively interface it. The async interface was probably meant for accessing registers, not transferring data. If I had the datasheet I could say more. I think picking an accelerator chip that doesn't even have a datasheet available outside of NDA for an "open" device was a pretty bad move. Then when they did any kind of timing analysis or breadboarding against the chip and realized how horribly slow the configuration is they should have just thrown it out. I don't know what made them think the 2D acceleration provided was worth having such a slow framebuffer over, or maybe they were lured by the prospect of eventually having really primitive 3D (which they should have known was not forthcoming). The internal display controller on the SoC might be gimped too, but so long as it runs off of the same SDRAM the CPU writes to it should be much, much better.

rohezal said:
PAL televisions have "half frame". First frame: line 1,3,5,7,9,11 ... Second frame: line 2,4,6,8,10 ...
Is it possible to write just half frame to the glamo and save 50% of the bandwith? So we use only 2,2 MB/s and have around 60-70% of cpu time (Why is the glamo blocking the cpu anyway, !"$%&/()). Maybe we can update an outer 10 pixel boarder only every 4th or 6th frame because its in most games not very important and save a bit speed too. The sound issue is surely from the blocked cpu while the image is transfered. Hmm ok I see now some problems. Thank you guys :) .

You have to ask yourself, is interlacing better than skipping/repeating frames? Interlacing was used on TVs because the screen refresh rate was necessary for the technology, and the display couldn't be repeated because it was transmitted a scanline at a time and not stored per-frame in a framebuffer. The industry has since viewed deinterlacing as a positive step to negate this process and progressive scan to generally be the better option. LCDs like the one on Freerunner are probably not at all well suited for it.

Another problem, one I've personally encountered on the device, is that if you only update part of the screen you can't perform double buffering. Without double buffering the only way to get a tear-free display is to upload the new frame entirely during the vertical blank period, which is often pretty small on LCDs, especially high resolution ones. So you'd be taking a heavily bandwidth limited interface and perform transfers at vsync (may not even have an exposed method on Freerunner's kernel), where now instead of having an entire frame to update you only have a fraction of it. This is of course assuming that the kernel can double buffer the Glamo, but that'd be pretty sad if it couldn't.

I want to try it :) . Playing SNES on the phone would just rock. But maybe with sme real controller parts. Some eletro engeeners from my university are going to make one for me. In exchange I have to write C code for their micro controllers^^

Good luck with that then, let me know how it ends up working..
 
Last edited by a moderator:
Talked to a friend of mine about the emulator and this thread.

Well we looked closer to glamo specs and come with some ideas.
The interlacing idea is not very clever.
The cpu has enough power the bottleneck is the bus.
So it would be clever to use every future on the glamo.

My idea: draw the next image to a framebuffer in RAM. Check if a 16x16 or 32x32 block of the last image has changed. If true draw the new block.
http://wiki.openmoko.org/wiki/Smedia_Glamo_3362 says the glamo can use blits. This would be perfect :) .

May I ask you for your icq or an irc chat where I can ask you some questions when I'm stucked and need help?
 
rohezal said:
Talked to a friend of mine about the emulator and this thread.

Well we looked closer to glamo specs and come with some ideas.
The interlacing idea is not very clever.
The cpu has enough power the bottleneck is the bus.
So it would be clever to use every future on the glamo.

My idea: draw the next image to a framebuffer in RAM. Check if a 16x16 or 32x32 block of the last image has changed. If true draw the new block.
http://wiki.openmoko...edia_Glamo_3362 says the glamo can use blits. This would be perfect :) .

May I ask you for your icq or an irc chat where I can ask you some questions when I'm stucked and need help?

I don't have ICQ, use one of the chat contacts in my profile if you want to reach me. I'm on IRC sometimes on servers like freenode and efnet (as Exophase)

Yes, Glamo has 2D acceleration/blits. But the dirty rectangles approach is going to fail so much of the time for SNES games that it's not worth it. Whenever the screen scrolls, to be precise, or palette changes. There'll be a ton of new overhead for checking all those blocks for changes because you'll be tearing through cache performing the reads. Also, performing all those blits when most or all of the screen changes will be slower than writing straight to the framebuffer because you have to upload then issue the commands to blit. Some work has been done recently to at least make the 2D acceleration operations asynchronous with the CPU, but it's not in a kernel release. You'll probably be hit pretty hard with all of the blits if you have 16x16 or even 32x32 blocks because the setup time and interrupt overhead adds up for all of them.

IMO, the best strategy for interfacing the Glamo is to have a tripling buffering scheme where, all in the same frame:

- CPU draws frame N - 2 into buffer A
- CPU uses DMA to gradually transfer frame N - 1 from buffer B to Glamo's buffer C, so it's spread out over the entire frame duration:
The idea here is that by making the DMA step off of a timer so it won't tie the bus 100% of the time. Although it'll steal many clock cycles and take main memory performance, the CPU will still be able to operate somewhat since it'll be spending a lot of cycles accessing cache instead of SDRAM. This idea has been suggested on the mailing list before.
- Glamo draws frame N from Glamo buffer D

Then at vsync buffers A and B are swapped, as are C and D.

Of course this involves some pretty complex setup and I doubt you can do it without kernel modifcations. You'd basically have to setup the frame rate in advance and hold to it. The actual upload to the Glamo would take significantly longer, but it'll be time where the CPU can generally get work done.
 
Last edited by a moderator:
Back
Top