EgonOlsen71 / basicv2

A Commodore (CBM) BASIC V2 interpreter/compiler written in Java
https://egonolsen71.github.io/basicv2/
The Unlicense
85 stars 15 forks source link

Making it slower #5

Closed nietoperz809 closed 7 years ago

nietoperz809 commented 7 years ago

Some prgs written for the C64 delay execution using loops. That's almost ineffective in your BASIC system. I suggest an argument in the constructor (e.g. boolean slowMode), which slows down the BASIC VM to a level like that of the original C64.

This program is a howling siren:

300 FOR I = 0 TO 24 : POKE 54272 + I, 0 : NEXT 310 POKE 54276, 33 : REM SAWTOOTH WAVE OSC1 320 POKE 54286, 3 : REM CONTROL FREQ. OSC3 330 POKE 54290, 16 : REM TRIANGLE WAVE 0SC3 340 POKE 54296, 175 : REM FULL VOL. & SELECT B AND-PASS & DISC. OSC3 FROM AUDIO 350 POKE 54295, 1 : REM NO RES'NCE & CHOOSE OSCI FOR FILTER 360 POKE 54293, 255 : POKE 54294, 78 : REM CUTOFF FREQUENCY 370 POKE 54278, 240 : REM FULL SUSTAIN/FASTEST RELEASE RATE 375 FOR T = 1 TO 3000000 380 F = 20000 + PEEK (54299) 20 : REM ADD OSC3 OUTPUT TO BASE FREQUENCY 390 HF = INT (F/256) : LF = F-256 HF : REM SPLIT NEW FREQUENCY INTO HIGH/LOW BYTES 400 POKE 54272, LF : POKE 54273, HF : REM SET NEWOSCI FREQUENCY 410 NEXT : POKE 54276, 32 : POKE 54296, 0 420 END

In the original code, line 375 counts only up to 300.

EgonOlsen71 commented 7 years ago

It's almost impossible to slow it down to the original C64's level, because the timing of the different commands is completely different. However, I added the option to add a tracer implementation to a BASIC program and a simple implementation of it for delaying the execution to a (more or less) fixed command/second rate. Maybe that helps!?

nietoperz809 commented 7 years ago

That will help, indeed. Building a time-accurate C64 emulation is a big effort and not worth the pain. However, it would be nice if I could run programs without checking every loop. There's no problem if some codes run twice as fast as on a real 64. But if they execute at light speed, there shurely is a problem.

EgonOlsen71 commented 7 years ago

If needed, you could implement your own Tracer instead and only delay commands in a particular line or particular commands or something like that.

EgonOlsen71 commented 7 years ago

I think I found a better solution for actual busy wait loops (the one in your example isn't one) like

10 FORI=0TO100:NEXT

or

10 FOR I=0TO1000 20 REM wait... 30 NEXTI

You can now set a loop mode in Basic (before calling compile). In LoopMode.REMOVE or LoopMode.DELAY, the compiler tries to detect these busy wait loops and replaces them with basically a NOP (REMOVE) or a delay (DELAY) that is close to what it would take a C64 to execute the loop. This doesn't apply to your example, but it might come in handy in other situations.