Jump to content
IGNORED

Classic99 with XB crashes with CPU Overdrive


SteveB

Recommended Posts

Hi,

 

once more I am developing an XB game with XB256 ... but this time I ran into an odd problem. I use the CPU Overdrive of Classic99 to "emulate the speed" of the compiled program when still interpreting and debugging. Suddenly the screen turns like this:

 

image.thumb.png.6c31c3622e14bab907e37dede19b9905.png

 

With CPU Throttling "Normal" the program runs fine (ok, crawling would be more appropriate than running). This happens with XB 1.1 and XB 2.9 GEM and with the current Classic99 and a two year old version I revived for testing, and the unsupported x64 version. Sometimes a small change to the program like inserting a REM line make it run again, but only until I continue developing and change the code in other places.

 

I nailed it down to the quickly repeated call to this function:

 

sub xcharinv(a$,b$)
  b$=""
  for i=1 to len(a$)
    b$ = b$ & seg$("FEDCBA987654321",pos("0123456789ABCDEF",seg$(a$,i,1),1),1)
  next i
subend

 

It invertes the hex-pattarn from a character-definition, nothing fancy and nothing with graphics. Once I disable this call, everything else works fine. I am not sure if this can easily reproduced on another PC with a different configuration running Classic99. For now I continue with un-invereted chars, which looks ugly on screen but will do for now while developing.

 

RXB2022D seems to get over this char re-definition, but runs into an infinite loop later on, which the other XB variants handle well. I haven't figured out what causes this incompatibility yet, I guess Rich would be interested.

 

Very seldom I get errors when starting the program like "Syntax error in line 30", while line 30 looks okay ... entering "run" again without changing anything runs the program without error. This looks like a nasty timing issue, doesn't it?

 

Has anyone else experienced something similar in the past?  

 

Steve

 

PS: This stripped-down code crashed every third or fourth run on my system in CPU Overdrive. Otherwise it will just black the screen for some seconds, as I removed all actual programming of the game to have a short demo.

 

100 CALL LINK("SCRN2")
110 CALL LINK("SCREEN",2)
120 call clear
130 call prepfont
140 dim adr(8),cnt(8),wl$(20),wx(20),wy(20),ch(25),pz(12,28),x1(7),x2(7),y2(7),xxx$(50)
150 randomize
160 bs=8448
170 bs=-24576
180 end
30000 sub prepfont
30010 for i=0 to 25
30020 call charpat(65+i,a$)
30030 CALL LINK("CHAR2",i,"80FEFEFEFEFEFEFF",i+165,a$)
30040 call xcharinv(a$,b$)
30050 call char(i+65,b$)
30060 next i
30070 for i=0 to 3
30080 CALL LINK("COLOR2",i-3,12,2,i+17,2,12)
30090 next i
30100 CALL LINK("CHAR2",160,"00FFFFFFFFFFFFFF")
30110 CALL LINK("CHAR2",161,"7F7F7F7F7F7F7F00")
30120 CALL LINK("CHAR2",162,"7F7F7F7F7F7F7F7F")
30130 CALL LINK("CHAR2",163,"FFFFFFFFFFFFFF00")
30140 subend
30150 sub xcharinv(a$,b$)
30160 b$=""
30170 for i=1 to len(a$)
30180 b$ = b$ & seg$("FEDCBA987654321",pos("0123456789ABCDEF",seg$(a$,i,1),1),1)
30190 next i
30200 subend

 

image.thumb.png.f62c0d28d184c10cb49fb78ae678d10e.png

Edited by SteveB
Demo added
  • Like 1
Link to comment
Share on other sites

Your stripped down sample has a bunch of CALL LINKs in it, so I can't directly test it under XB 1.1... I'm wary about testing under GEM because I know Harry's code tends to use interrupts extensively, and I won't be able to determine whether a fault is due to Classic99 or just the change in timing.

 

The thing to remember is that CPU overdrive replaces the CPU with a new one that runs much faster - but does not change the timing on the rest of the system. This means that race conditions will be exacerbated and more likely to occur. Some tricks on the TI - for instance, replacing DSK1.LOAD with a different program name when booting up XB, depend on the relationship between interrupts and CPU speed, and don't always work when the CPU is accelerated. It's very possible that you've found a race in Extended BASIC.

 

I replaced the LINKs with XB calls and fixed up the numbers to be legal on standard XB, and ran the code repeatedly without an issue. Your sub there uses a lot of string space - VDP is continuously being hit and even on normal XB it needs to do frequent garbage collection. If you're running in bitmap I would image it's even more frequent. Perhaps the race is there...?

 

I tried the whole program in XB256, and it does reproduce. It looks like garbage collection is involved, but at the speed it's running it's tough for me to be 100% sure (I'm just watching the heatmap to see when it happens.) I don't know enough about XB internals to really troubleshoot on my side, but it fascinates me that the built-in CALLs can be lost like that. It doesn't happen in System Maximum, which speeds up the emulation as a whole (rather than just the CPU), further supporting the race condition theory.

 

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

Thank you for taking a look. I am also in contact with Harry and we all seem to agree that garbage collection in combination with the interrupts of XB256 might be causing the problem. In my other XB256 programs I also use strings a lot, but mostly reading characters. 

 

I tried a lot of variants for my - I think - clever short code to invert a hexstr-pattern in XB:

sub xcharinv(a$,b$)
  b$=""
  for i=1 to len(a$)
    b$ = b$ & seg$("FEDCBA9876543210",pos("0123456789ABCDEF",seg$(a$,i,1),1),1)
  next i
subend

 

i.e. I tried to ease the nested seg$, sparing one string by using 17-i as an index:

sub zcharinv(a$,b$)
  b$=""
  s2$="0123456789ABCDEF"
  for i=1 to len(a$)
    start=pos(S2$,seg$(a$,i,1),1)
    b$ = b$ & seg$(S2$,17-start,1)
  next i
subend

the "crash" became now more predictable. When it crashed, it left a blue square at the same location during various tests.

 

I also converted the routines from SUB/SUBEND to GOSUB/RETURN, but the crash remains. The same result by inlined the code, sparing the subroutine-call. No improvement.

 

Furthermore I used CALL SOUNDS to slow down the zcharinv() variant:

 

call sound(20,109+i*i,10)

call sound(50,109+i*i,10)

call sound(75,109+i*i,10)

call sound(100,109+i*i,10)

 

Even the last one, taking more than 1.6 seconds per char-inversion, was prone to the symptom. Delays are not a cure.

 

To verify the previous findings, I wrote a nonsense-string-wrangler:

call SCRN2
call screen2(2)
call clear

a$="abcdefghijklmnopqrstuvwxyz"

for i=1 to 100
  a  = len(a$)
  print i;a
  a$ = seg$(a$,rnd*a+1,rnd*a)&seg$(a$,1,rnd*a)&seg$(a$,rnd*a+1,rnd*a)
  a  = len(a$)
  if a>150 then a$=seg$(a$,rnd*a/2,a/2)
next i
print a$

end

FIAD for XB: testmin

 

When I comment the first two lines it runs okay, when they are active the display gets corrupted. A CALL DELAY of 100 or even 200ms in the loop does not help. Sometimes before the 30th iteration the screen gets corrupted. I had no hard crashes though.

 

Harry hinted me to enable GRAM >6000 may help in XB 1.1 and indeed, I was not able to provoke the chrash anymore. XB 2.9 did not improve with GRAM enabled.

 

Under no circumstances I was able to crash RXB2022D, even when increasing the loop and dropping the PRINT.

 

So for anyone running in the same problem: Intense string usage with XB256 in Classic99 CPU Overdrive mode, use either XB 1.1 with GRAM >6000 enabled or RXB

 

I hope this helps someone.

 

Steve

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Hi Rich,

 

I found why my program runs into an infinite loop in RXB2022D ... CALL GCHAR does not work on SCREEN2 of XB256, it always return 32 in my example (or perhaps that is just because SCREEN1 is empty?). Do you have a static base for the video RAM in GCHAR?

 

100 CALL LINK("SCRN2")
110 FOR i=1 TO 22
120 CALL HCHAR(i,4,i*10,1)
130 CALL GCHAR(i,4,c)
140 DISPLAY AT(i,6):c
150 NEXT i

image.thumb.png.dc1dcdbc93f4fcf2e086eaf91329c0e9.png

So this is not an option for me right now.

 

Link to comment
Share on other sites

8 hours ago, SteveB said:

I am also in contact with Harry and we all seem to agree that garbage collection in combination with the interrupts of XB256 might be causing the problem.

Oh, neat!  This is very interesting to me, because Advanced BASIC (for the Geneve) has a similar problem that happens "randomly" during variable assignment and as best I could tell, during garbage collection/string compactionl.  The result is usually a string that greatly exceeds the maximum string length, or crashes the program, or locks the interpreter.  If I remember correctly, the error manifests during subprogram calls and/or returns from the subprogram more frequently than the base program.   I got lost trying to trace the code and ran out of time in early 2022, so I never got back to debugging it.  I know my issue has no ties to classic99 however, if you and Harry find the underlying cause is related to strings/garbage, I'd be very interested in the details.

Link to comment
Share on other sites

I think the Garbage Collection in XB ROMs and GROMs is why 256 has an issue.

Moving VDP pointers around before Garbage Collection takes place is going to get real complicated fast.

Adding an Interrupt routine too will just make it much worse to track down the problem.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...