Jump to content
Opry99er

Short and Sweet (SSGC) contest

Recommended Posts

It's actually even a little more improved than the version in my game thread, as I keep honing the code. By the time the contest is over the entire game will be 7 bytes long. ;)

 

Save it for the smack talk!

Share this post


Link to post
Share on other sites

It's actually even a little more improved than the version in my game thread, as I keep honing the code. By the time the contest is over the entire game will be 7 bytes long. ;)

 

Save it for the smack talk!

 

Ha ha ha! I missed that myself until I re-read it. :)

 

Oh, and let me add, ZombXB is flipping brilliant. Good game Tursi!

Share this post


Link to post
Share on other sites
When my main loop detected a COINC I deleted one sprite and immediately did another CALL COINC to determine if the earlier collision was with a specific sprite. This would occasionally give a false positive even though there was no possible collision as only one sprite was in the area. This was a problem like I said until I added some instructions between the delay and the second CALL COINC.... I don't know the exact internals but I do suspect that XB was outrunning the console interrupt routine. If is walks like a duck.....

 

You're assuming only one possible scenario, but I can give you the same "false" positive with the direct access mechanism:

 

The problem space is:

 

a. CALL COINC - detects the collision

b. Your code responds by moving one of the sprites

c. CALL COINC - reads the VDP again, still sees a collision

 

Your assumption is based on this process occurring:

 

1. VDP interrupt occurs, console copies status register to scratchpad (Clears VDP status)

2. CALL COINC reads from scratch pad, detects collision

3. Your code responds by moving one of the sprites

4. CALL COINC reads from scratch pad again, STILL detects collision

5. VDP Interrupt occurs, console copies status register to scratchpad (Clears VDP status)

 

... and your goal with the delay fix was to move step 4 to after step 5.

 

This is what I think happened:

 

1. CALL COINC reads from VDP, detects collision (clears VDP status)

2. Your code detects the collision...

3. VDP draws the screen again, sees collision, sets status again

4. ...your code moves one of the sprites - status bit stays set until it's read!

5. CALL COINC reads from VDP, detects collision again

6. VDP interrupt occurs, console copies status register to scratchpad (clears VDP status if it's still set)

 

And your fix, adding a delay, simply moves step 5 after step 6, similar to the other scenario.

 

Remember that unlike in today's emulators, the VDP sets the status register the instant it detects a collision, not at the bottom of the frame (which is when Win994A and MESS set it), and Classic99's setting of that bit is completely detached from real time right now, even though it can do it separate from the frame. So if it was in emulation you saw it, I wouldn't count it. Also remember that Extended BASIC can keep interrupts disabled for longer than 1/60th of a second -- if interrupts don't run, then the interrupt routine can't clear the VDP status bit. (Of course, this same argument /also/ works for your theory, too, since it shows why XB can appear to outrun the console interrupt. It's not that XB is that fast, it's that it blocks it.) Finally, the collision bit remains set until it's read, no matter how many times the screen has been drawn and regardless as to whether the sprites are still colliding.

 

I thought Ben had previously mentioned that he'd had CALL COINC miss obvious collisions, and that I'd reproduced that. That supports the theory of it racing with the console interrupt routine. I tried this short piece of test code just now:

 

10 CALL CHAR(42,RPT$("F",16))
20 CALL SPRITE(#1,42,2,100,100)
30 CALL SPRITE(#2,42,4,104,104)
40 CALL COINC(ALL,C)
50 PRINT C
60 GOTO 40

 

The sprites are /always/ touching so C should always return a collision, but in fact it frequently returns no collision. If you change it to a CALL PEEK() of the location that the register is copied to: CALL PEEK(-31877,C) -- this alternates between 160 and 128. 128 is the interrupt bit, and we would expect it to always be set (and it is). The other bit is value 32, which is the sprite collision bit. Bizarrely, it's not always set either in Classic99, meaning we're either racing the chip again (but we are in vblank when it is copied, so we shouldn't be), or something else is ALSO reading the register. I'm inclined to be suspicious of those results, though, and will try them on the real machine (unless someone beats me to it.)

 

I'll work out the right answer when I get some time at home, but it's not so cut and dried.. you can have those symptoms either way. I think we should find out. :)

 

 

 

I believe Ben's Issue was accessing both the scratch pad location and the VDP REG directly while interrupts were enabled so he was causing the problem of missed COINC's. My understanding is that the console ISR checks the VDP ROR and stores it in the scratch pad location. It would then seem that if XB accessed the VDP ROR directly that could cause a huge problem. It may very well be the case but unless someone has evidence otherwise I would be skeptical.

 

The code I ran on the real deal is as follows

 

10 call clear

20 call char(65,"FFFFFFFFFFFFFFFF")

30 call sprite(#1,65,2,25,25)

40 call sprite(#2,65,2,28,28)

50 call coinc(all,c)

60 if c<>-1 then 50

70 call delsprite (#2)

74 call color(#1,16)

75 call color(#1,2)

80 call coinc(all,c)

90 if c<>-1 then 30

 

without lines 74 & 75 in the program falls out every time

without line 74 the program works a bit then falls out

Share this post


Link to post
Share on other sites

OK, I finally just downloaded and tried Flyguy and ZomBXB... both are awesome! Great work, you guys. I'm trying to work out the gameplay on another idea I have for the contest, now that Enemy Lines is turning into another 'full-size' game. Y'all are making me have to step up my game... I wish I could draw a tenth as well as any of you guys. :)

Share this post


Link to post
Share on other sites

OK! My contest entry is now complete. I stand at 13 code lines and 2 Data lines. I think I can probably bum a line or two still, although I will likely use a few additional lines to create an introductory screen and maybe even some music.

It was a really hard battle between feature creep and playability, and the program went through several iterations to achieve a decent balance. Definitely a fun exercise and a welcome diversion from assembly, although I did miss the level of control over the machine I have with the latter.

 

Walid

Share this post


Link to post
Share on other sites

Freakin' excellent!!!!! I bet it's a killer!!! At 13 lines, you could burn another 17 on an intro screen, in game instructions--- whatever you want!!! :). This is cool... Welcome, Walid--- your programming prowess and knowledge of the TI will be much appreciated

Share this post


Link to post
Share on other sites

I did a little research here on the COINC issue.

 

My CALL COINC app on the real machine -- frequent coincidence misses, as expected.

Using CALL PEEK to the scratchpad -- reports 156 and 188. That's 9C and BC. 9C sets interrupt (expected), and 5th sprite number 28 (but 5th sprite flag not set). That's a bug I can fix in Classic99 ;) Anyway.. BC simply adds the coincidence flag. So that means that just peeking the scratchpad copy is ALSO not reliable, which I find interesting!

 

With the real behaviour confirmed, back into the debugger. First, see who reads from the VDP status register. In debugging with the COINC version of the program running, it's always the console interrupt that reads it, coming from the GPL interpreter. This seems to discount my theory that XB reads it directly (you win!) So why does the interrupt routine miss collisions, when it should be reading at the end of the frame?

 

I likewise checked, and nothing else writes to >837B. So that's good, we have likely got an accurate copy of the VDP status. I checked who READS that value, too, and it's a GPL memory access from XB GROM - likely the COINC. Confirmed this by removing the COINC - no more breakpoint.

 

So far confirmed:

-Yes, CALL COINC reads scratchpad

-Yes, nothing except the console interrupt reads the VDP status byte.

-Coincidences in a tight loop are still missed!

 

Outpacing the vertical blank shouldn't matter... you can read a RAM location as many times as you want and the value won't change. So I don't fully understand why it's getting no collisions on some frames, since that's coming from the video chip by all appearances. So a bit baffling, but good to be aware of anyway, and you found a workaround..

 

Thanks for putting up with it!

 

Thanks everyone for the ZomBXB comments, too. :) It occurred to me that I'm not trying to save memory, I should have used magnify 3 sprites instead. But that's okay, it works fine. ;)

Share this post


Link to post
Share on other sites

--> So why does the interrupt routine miss collisions, when it should be reading at the end of the frame?

 

I really don't think the ISR is missing the collisions. I believe that the COINC,DELSPRITE,COINCE series is occurring before the ISR is activated again IE XB is outrunning the VDP interrupt. This would explain the fall out every time with no delay, sometimes with 1 delay and never with 2 delays. I would be interesting to know if the sprite routines are in the ROM or GROM. I suspect the ROM due to the speed. Any ideas?

 

Perhaps XB is faster than I previously thought.... :-)

Share this post


Link to post
Share on other sites

I'm actually pretty surprised the amount of work I'm doing and how responsive the system has been. Of course, I'm probably fully loaded and as soon as I add more game elements, I'm probably screwed.

 

--> So why does the interrupt routine miss collisions, when it should be reading at the end of the frame?

 

I really don't think the ISR is missing the collisions. I believe that the COINC,DELSPRITE,COINCE series is occurring before the ISR is activated again IE XB is outrunning the VDP interrupt. This would explain the fall out every time with no delay, sometimes with 1 delay and never with 2 delays. I would be interesting to know if the sprite routines are in the ROM or GROM. I suspect the ROM due to the speed. Any ideas?

 

Perhaps XB is faster than I previously thought.... :-)

Share this post


Link to post
Share on other sites

Once you've done a few XB games, it becomes pretty apparent which functions work well together (i.e. Which ones don't "fight" each other for supremacy) and also the best way to manage your gameloop to keep it as tight and small as possible, branching out with GOSUBS. The cool part is building your loop to facilitate ONLY the most absolutely necessary "checks" and then realizing your entire loop takes up only 3 lines--- the rest is setup and GOSUBs. To spill the beans, I've started a 30 liner myself--- it won't count towards the contest, but I caught this bug too--- and I gotta have one on the compilation disk. :). Anyone who contributes a game will receive a free compilation disk, in 5.25 or in 3.5" format---courtesy of Opry99er. When the contest is over, just send me your address and I'll send one your way!

Share this post


Link to post
Share on other sites

--> So why does the interrupt routine miss collisions, when it should be reading at the end of the frame?

 

I really don't think the ISR is missing the collisions. I believe that the COINC,DELSPRITE,COINCE series is occurring before the ISR is activated again IE XB is outrunning the VDP interrupt. This would explain the fall out every time with no delay, sometimes with 1 delay and never with 2 delays. I would be interesting to know if the sprite routines are in the ROM or GROM. I suspect the ROM due to the speed. Any ideas?

 

That's my problem, that doesn't explain it. That theory has potential for your case, but makes no sense in mine.

 

Look at the example program that I'm working with, not your example. My sprites are not moving. They are always touching. So the COINC should never return 'no coincidence'. But it does, and so does the CALL PEEK. If the ISR is the only thing writing that memory location, as my debugger tests suggest, then yes, the ISR /is/ missing coincidences. This is observation and not supposition.

 

Let's start with the simpler of the two cases.

Share this post


Link to post
Share on other sites

Why do you recommend gosubs? That is extra stack manipulation and steals clock cycles. Right now, I've got my entire game loop with no externalized operations. Just a tight loop. What would be a really good thing to have at some point is documentation on how long each operation takes... But, I'm sure nobody has time for that.

 

I've got a few more things to put into my game loop - I'm going for all the marbles in my game, else I'll fall back to my "less good" strategy. I'm pretty amazed at how many moving objects (w/o sprites) one can have :)

 

-H

 

Once you've done a few XB games, it becomes pretty apparent which functions work well together (i.e. Which ones don't "fight" each other for supremacy) and also the best way to manage your gameloop to keep it as tight and small as possible, branching out with GOSUBS. The cool part is building your loop to facilitate ONLY the most absolutely necessary "checks" and then realizing your entire loop takes up only 3 lines--- the rest is setup and GOSUBs. To spill the beans, I've started a 30 liner myself--- it won't count towards the contest, but I caught this bug too--- and I gotta have one on the compilation disk. :). Anyone who contributes a game will receive a free compilation disk, in 5.25 or in 3.5" format---courtesy of Opry99er. When the contest is over, just send me your address and I'll send one your way!

Share this post


Link to post
Share on other sites

I use GOSUBs when an IF THEN is true--- it doesn't eat much of anything. For instance:: pseudo-code

 

100 2 SPRITEs moving

200 IF COINC then GOSUB 1000

300 CALL JOYST

400 GOTO 200

1000 PRINT "DEATH" :: subtract a life :: increase enemy speed :: return

 

all this does is checks for a SPRITE

coinc, goes to the next line, and loops. The info in line 1000 may be quite extensive--- adding 1 to the score, printing several things, resetting the screen. I use this method because it is exclusionary--- if there is no COINC, no extra time is wasted. Additionally, it helps organize your conditionals into chunks--- obviously the space constraint

of a 30 line game requires that you use fewer lines, but code with SUBs is easy to read, understand, and modify. Conversely, in a game this size, you need not worry about memory constraints. ;). Speed test it with and without a GOSUB... This is something we discussed on the list a few months ago... The difference is infinitesimal. But of course, this is just one method.

Share this post


Link to post
Share on other sites

Hey Owen, one more request regarding the competition - can we have REM statements that don't count towards the total? I like having those because my code is so compressed and variable names are so short, it helps me remember what does what.

 

Not a problem if we can't have them, I'll strip them out before posting. But figured I'd bring it up in case it's okay.

Share this post


Link to post
Share on other sites

Try using this method.... Put your REMs in the last DATA lines in the game (if you haven't used them all up). Just don't READ them.

 

DATA 240 E$=eggplant

 

in line 240, your E$ variable means eggplant. Or at the end of your line of code, use REM

 

100 IF E$(5)+X=THEN.... REM E$=eggplant

 

Something like that maybe? An exclation point works the same as REM at the end of a line. Hope that helps--- but 30 and 10 will be the max. :). Sorry brotha--- good question though.

Share this post


Link to post
Share on other sites

The ! does not work in my environment for some reason, it always throws a syntax error. And none of my lines are short enough to add comments to the end. :)

 

It's fine, I'll keep them in until I submit it and then rip them out of the public version. :thumbsup:

Share this post


Link to post
Share on other sites

Cool. I might be mistaken-- the ! may only work at the beginning of a line... Sorry, Tursi or someone might have a brilliant way to get around it. :). I do not

Share this post


Link to post
Share on other sites

I do all my dev in a text editor and paste the code into classic99... my code looks like this

 

 

REM my code initializes better than your code

10 initialize

REM my code plays better than yours

20 run game

REM my graphics look better than yours

40 DATA my, graphics, rock

 

By putting comments as REM lines they can be pasted, but do not wind up as code. Sneaky, eh?

 

The ! does not work in my environment for some reason, it always throws a syntax error. And none of my lines are short enough to add comments to the end. :)

 

It's fine, I'll keep them in until I submit it and then rip them out of the public version. :thumbsup:

Share this post


Link to post
Share on other sites

--> So why does the interrupt routine miss collisions, when it should be reading at the end of the frame?

 

I really don't think the ISR is missing the collisions. I believe that the COINC,DELSPRITE,COINCE series is occurring before the ISR is activated again IE XB is outrunning the VDP interrupt. This would explain the fall out every time with no delay, sometimes with 1 delay and never with 2 delays. I would be interesting to know if the sprite routines are in the ROM or GROM. I suspect the ROM due to the speed. Any ideas?

 

That's my problem, that doesn't explain it. That theory has potential for your case, but makes no sense in mine.

 

Look at the example program that I'm working with, not your example. My sprites are not moving. They are always touching. So the COINC should never return 'no coincidence'. But it does, and so does the CALL PEEK. If the ISR is the only thing writing that memory location, as my debugger tests suggest, then yes, the ISR /is/ missing coincidences. This is observation and not supposition.

 

Let's start with the simpler of the two cases.

 

I should have paid more attention to what you wrote ;-/...

 

I tested your code on my console and saw the results first hand. Your code on my console resulted in about 50 percent missed hits. That seems disheartening for XB programming. Now the strange gets stranger......

 

I got sick of trying to keep track of the scrolling ones and zeros so I changed the print format to..STR$(ABS©); in order to just see the 1's and 0's. This resulted in a reduction of misses to about 1.4 percent. On a whim I turned off all sprite motion with CALL LOAD(-31806,64) and got zero missed COINC's (out of 1000 tries.) This is beyond my scope so I will defer to your expertness in things of this nature but I would suspect that something other than the ISR is reading the VDP ROR or the scratch pad location is getting changed by some lurking XB/console bug. Perhaps a call to the TI software engineers is in order ;-)

Share this post


Link to post
Share on other sites

So are you telling me that all the games I played 30 years ago could've sucked less? Also, since you talk about CALL COINC reading at the end of the frame, does that mean using it will slow down my game unless I get lucky that it runs near the end of a frame? That stinks.

 

 

--> So why does the interrupt routine miss collisions, when it should be reading at the end of the frame?

 

I really don't think the ISR is missing the collisions. I believe that the COINC,DELSPRITE,COINCE series is occurring before the ISR is activated again IE XB is outrunning the VDP interrupt. This would explain the fall out every time with no delay, sometimes with 1 delay and never with 2 delays. I would be interesting to know if the sprite routines are in the ROM or GROM. I suspect the ROM due to the speed. Any ideas?

 

That's my problem, that doesn't explain it. That theory has potential for your case, but makes no sense in mine.

 

Look at the example program that I'm working with, not your example. My sprites are not moving. They are always touching. So the COINC should never return 'no coincidence'. But it does, and so does the CALL PEEK. If the ISR is the only thing writing that memory location, as my debugger tests suggest, then yes, the ISR /is/ missing coincidences. This is observation and not supposition.

 

Let's start with the simpler of the two cases.

 

I should have paid more attention to what you wrote ;-/...

 

I tested your code on my console and saw the results first hand. Your code on my console resulted in about 50 percent missed hits. That seems disheartening for XB programming. Now the strange gets stranger......

 

I got sick of trying to keep track of the scrolling ones and zeros so I changed the print format to..STR$(ABS©); in order to just see the 1's and 0's. This resulted in a reduction of misses to about 1.4 percent. On a whim I turned off all sprite motion with CALL LOAD(-31806,64) and got zero missed COINC's (out of 1000 tries.) This is beyond my scope so I will defer to your expertness in things of this nature but I would suspect that something other than the ISR is reading the VDP ROR or the scratch pad location is getting changed by some lurking XB/console bug. Perhaps a call to the TI software engineers is in order ;-)

Edited by unhuman

Share this post


Link to post
Share on other sites

By putting comments as REM lines they can be pasted, but do not wind up as code. Sneaky, eh?

 

Good deal! That works for me, then. :)

Share this post


Link to post
Share on other sites

I tested your code on my console and saw the results first hand. Your code on my console resulted in about 50 percent missed hits. That seems disheartening for XB programming. Now the strange gets stranger......

 

I got sick of trying to keep track of the scrolling ones and zeros so I changed the print format to..STR$(ABS©); in order to just see the 1's and 0's. This resulted in a reduction of misses to about 1.4 percent. On a whim I turned off all sprite motion with CALL LOAD(-31806,64) and got zero missed COINC's (out of 1000 tries.) This is beyond my scope so I will defer to your expertness in things of this nature but I would suspect that something other than the ISR is reading the VDP ROR or the scratch pad location is getting changed by some lurking XB/console bug. Perhaps a call to the TI software engineers is in order ;-)

 

Thanks, Marc. VERY interesting on the turning off of sprite motion... this kind of suggests to me that the interrupt routine itself might be running long (ie: by the time we cache the value, the VDP is into the next frame? Still a theory with holes though.) At this point, though... I don't really have the cycles to dig deeper, I'm just relieved to see I'm not crazy. ;) Let's just leave it as a known for now and scratch our heads about it later.

 

So are you telling me that all the games I played 30 years ago could've sucked less? Also, since you talk about CALL COINC reading at the end of the frame, does that mean using it will slow down my game unless I get lucky that it runs near the end of a frame? That stinks.

 

Oh no.. it doesn't wait for the end of the frame. It just reads a cached memory address. But that address is updated at the end of the frame. CALL COINC itself shouldn't add any delay to the program, that much we did settle. :)

Share this post


Link to post
Share on other sites

OHHH NOOOO!!!!!! I was just starting to make some money and a damn zombie ate my farmhand!!!

 

TIFarm2.jpg

 

Freakin awesome, man. =)

Share this post


Link to post
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.

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...