Jump to content
RevEng

7800basic beta, the release thread

Recommended Posts

12 hours ago, batari said:

What would happen if I made a 12-high zone, aside from wasted space? Does it mean the sprites won't work correctly if I tweak the DLL to 12 high zones?

At a minimum, any line in the top portion of the sprite that has an offset in the zone greater than 11 wouldn't appear. I'm pretty sure there would be some additional glitching on the bottom-portion of the sprite too, though I'd need to trace the code to describe the effect in any detail.

 

12 hours ago, batari said:

As for the 12-high pixels for the standard kernel, the only way I can see that could match things up is to use three 8-high 7800 characters stacked vertically for every two playfield pixels high. It shouldn't be that hard to do. A potential issue with this, though, is converting the 48 bytes of playfield data to 288 bytes of character data in 7800basic. It can be helped with a lot of lookup tables and unrolled loops, but still that is a lot of stores. It'll take thousands of cycles to convert that.

If you're willing to update them during the visible screen (there might be perceptible shearing if there are regular updates) you probably have the cycles to do it. With DMA running and a modest 160A screen with double-wide characters you'll have about 10000 6502 cycles leftover.

 

But as you point out, playfield: needs to be converted anyway. It would just be easier to directly use 7800basic alphadata+plotmap. Something like this...

playfield:
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
end

Could become something like this...


 alphachars '.X'
 alphadata screen1map tileset_blocks
 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
end

; you also need to "plotmap" this map somewhere onto the screen
; and include a PNG graphic called tileset_blocks.png in your code
; with graphics for the 2 characters.

 

Things like pfpixel and pfread would require updates to pokechar and peekchar. (pfpixel/pokechar would need a different setup for the playfield though, as you'd need RAM based characters)

 

  • Like 1

Share this post


Link to post
Share on other sites
5 hours ago, Karl G said:

I had thought that the standard kernel had 16 scanline high blocks, not 12. The play area is 88 double scanlines high, so (88*2) / 11 playfield rows = 16

 

At any rate, doing 11 rows of characters with 16 scanline high zones for the playfield would leave one zone below that to do the score and the equivalent of pfscore bars for a total of 192 scanlines.

Yep, you are right! I thought it was 16, but I opened up a bB game last night and went through the scanlines in the Stella debugger. For some reason I counted 12 lines. Today, with the same game, it is clearly 16. I have no idea how that happened.

 

Anyway, 16 makes it a TON easier for sure.

Share this post


Link to post
Share on other sites
4 hours ago, RevEng said:

At a minimum, any line in the top portion of the sprite that has an offset in the zone greater than 11 wouldn't appear. I'm pretty sure there would be some additional glitching on the bottom-portion of the sprite too, though I'd need to trace the code to describe the effect in any detail.

 

If you're willing to update them during the visible screen (there might be perceptible shearing if there are regular updates) you probably have the cycles to do it. With DMA running and a modest 160A screen with double-wide characters you'll have about 10000 6502 cycles leftover.

 

But as you point out, playfield: needs to be converted anyway. It would just be easier to directly use 7800basic alphadata+plotmap. Something like this...


playfield:
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 X..............................X
 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
end

Could become something like this...


 alphachars '.X'
 alphadata screen1map tileset_blocks
 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'X..............................X'
 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
end

; you also need to "plotmap" this map somewhere onto the screen
; and include a PNG graphic called tileset_blocks.png in your code
; with graphics for the 2 characters.

 

Things like pfpixel and pfread would require updates to pokechar and peekchar. (pfpixel/pokechar would need a different setup for the playfield though, as you'd need RAM based characters)

 

So just to clarify, is the font data in ROM or RAM, and are the characters (the X and .) in ROM or RAM?

Share this post


Link to post
Share on other sites

[edit - beat by Karl, but something odd seems to have happened to his post.]

 

The font graphic data is in ROM, imported into the correct place and format via the incgraphic command.

 

In the example I used, the character strings are in ROM. The RAM version of my example is nearly the same, except you dim a buffer "dim charbuffer=$2200" and use "memcpy screen1map charbuffer 288" (or whatever the size is) to populate it, and then plotmap the "charbuffer" ram buffer instead of the "screen1map" rom.

Share this post


Link to post
Share on other sites

I found a bB demo from the RT site that includes playfield pixel destruction, and converted it to 7800Basic. I didn't delete any of the old code, but I put comments with the tag "7800Basic" before any code I added or commented-out with a brief explanation for the change. The source zip contains the original bB example (ex_sprite_with_missile_and_pfpixel_destruction.bas) and the converted version for 7800Basic (bb7800.78b).

 

Obviously for such a trivial case, it would have probably been easier to rewrite it, but it may serve as a useful example of the dynamic RAM "playfield", and some of the other changes that are needed for a bB project.

 

Original bB example:

ex_sprite_with_missile_and_pfpixel_destruction_bas.thumb.png.eded34ba18750e3def266ef94ac1fc6a.png

 

Converted 7800 version:

1125830927_ScreenShot2021-04-09at10_30_09AM.thumb.png.96dd17f7a2f2ad388f34e82b99ba5619.png

 

ROMs:

ex_sprite_with_missile_and_pfpixel_destruction.bas.bin

bb7800.78b.a78

 

Source zip:

bb7800.zip

  • Like 2

Share this post


Link to post
Share on other sites

On the subject of porting from bB, and also because it would be useful on its own, how feasible would it to be to add a feature to 7800Basic that would allow a user function to be run each visible zone? I was thinking it would be handy for updating e.g. a palette color or the background color for each zone.

Share this post


Link to post
Share on other sites

Arbitrary user-interrupts (other than the current near-top, near-bottom, and offscreen ones) aren't planned in the near future. An NMI color change interrupt needs minimal overhead to be reliable - otherwise, adding more dma increases the chance of the color change not taking effect until the next scanline, to the point where the heaviest DMA limits can cause a miss in the most minimal color change code.

 

I may change this in the future if I take on an NMI handling rewrite, but honestly I have a few different pieces I'd like in place before I consider that, to avoid painting myself into a corner.

  • Like 2

Share this post


Link to post
Share on other sites
On 4/10/2021 at 8:20 PM, RevEng said:

Arbitrary user-interrupts (other than the current near-top, near-bottom, and offscreen ones) aren't planned in the near future. An NMI color change interrupt needs minimal overhead to be reliable - otherwise, adding more dma increases the chance of the color change not taking effect until the next scanline, to the point where the heaviest DMA limits can cause a miss in the most minimal color change code.

 

I may change this in the future if I take on an NMI handling rewrite, but honestly I have a few different pieces I'd like in place before I consider that, to avoid painting myself into a corner.

RevEng
Can you see any way to "draw" on the screen effectively with Maria by manipulating the bitmap drawing?  
Like how would one approach drawing the missiles in Missile Command? 

Share this post


Link to post
Share on other sites
3 hours ago, fultonbot said:

RevEng
Can you see any way to "draw" on the screen effectively with Maria by manipulating the bitmap drawing?  
Like how would one approach drawing the missiles in Missile Command? 

The quick answer to arbitrary bitmap drawing is to use RAM-backed sprites. Basically you have a series of sprites that cover the screen and point at different segments of RAM, and you have line drawing routines that update that RAM. There isn't an easy way to do this in 7800basic right now. @SmittyB's Plink game uses pretty much this technique for dynamic backgrounds, though it's not doing full-screen bitmaps. (they repeat vertically)

 

That said, I don't think Missile Command actually needs bitmap display, if you just limit the number of angles the missiles can come in at. (The 2600 version doesn't pull off arbitrary angles either, and the missile aspect of the game compares very well to the arcade). Given that approach, you can just draw the missile segments with sprites. (pulling this off quick enough would likely require the Under The Hood technique)

Share this post


Link to post
Share on other sites
24 minutes ago, RevEng said:

The quick answer to arbitrary bitmap drawing is to use RAM-backed sprites. Basically you have a series of sprites that cover the screen and point at different segments of RAM, and you have line drawing routines that update that RAM. There isn't an easy way to do this in 7800basic right now. @SmittyB's Plink game uses pretty much this technique for dynamic backgrounds, though it's not doing full-screen bitmaps. (they repeat vertically)

 

That said, I don't think Missile Command actually needs bitmap display, if you just limit the number of angles the missiles can come in at. (The 2600 version doesn't pull off arbitrary angles either, and the missile aspect of the game compares very well to the arcade). Given that approach, you can just draw the missile segments with sprites. (pulling this off quick enough would likely require pre-the Under The Hood technique)

I think I'll try the 2nd method for the fun of it.

 

  • Like 1

Share this post


Link to post
Share on other sites

The title screen in Plink does use a full-screen bitmap for the cyan, but even with the monochrome 320A mode the CPU time is a noticeable limiting factor to how much can be drawn in one frame.

There are plenty of optimisations that can be made over what I did in Plink, and I think somebody could make a version of Missile Command with this technique, but there would have to be some clever compromises somewhere to make it playable at any real speed.

There's a lot of potential in bitmapping, but I'd say it's best limited to things where frame rate isn't important.

  • Like 2

Share this post


Link to post
Share on other sites

Possibly a dumb question, but why do 48K games compile to produce a 32K bin file? In this particular case, if I change it to actually be a 32K game, it doesn't have enough space.

 

Edit: Nevermind. Wrong file.

Share this post


Link to post
Share on other sites

I checked Danger Zone which is a 48K ROM, both the A78 and BIN are 48K.

 

I think you might have found the Tardis compiler Karl :D 

  • Haha 2

Share this post


Link to post
Share on other sites
6 minutes ago, Muddyfunster said:

I checked Danger Zone which is a 48K ROM, both the A78 and BIN are 48K.

 

I think you might have found the Tardis compiler Karl :D 

Or I was looking at a different version of my game. Oops. Looks like my 48K game is actually 48K, after all.

Share this post


Link to post
Share on other sites

I found an interesting...issue (maybe?) when tinkering with some code today.

 

This code works fine, but if I swap the palette entry for the plotsprite here to a variable that I imaginatively called "palette" I get a compile error. (branch out of range).

if xpos1_88 >64 && xpos1_88 < 170 then plotsprite fireball 4 xpos1_88 48 : plotsprite fireball 4 xpos1_88 80 

 

This in comparison, will not compile. As noted the only difference is using a variable for the palette. The variable is in use elsewhere without issue.

if xpos1_88 >64 && xpos1_88 < 170 then plotsprite fireball palette xpos1_88 48 : plotsprite fireball palette xpos1_88 80 

 

If this is a "known" restriction that I've overlooked - apologies :)

 

 

Share this post


Link to post
Share on other sites

It's sorta known. (no need for apologies!)

 

There's a few statements that eat a lot of rom, and as such cause branch-errors in the if...then logic. Resolving it requires a bit of re-write, and probably will grow the usage of if...then by a few bytes for each one, so I've been putting it off. For now, you can work-around by putting the rom-hungry statement on it's own line and using if...then to conditionally jump past the statement.

 

As for the reason why plotsprite triggers the issue with a variable pallete failing but a constant one working... variable palletes use a bit more rom. plotsprite appears to be on the cusp of the if...then hungry-statement issue.

  • Thanks 1

Share this post


Link to post
Share on other sites
On 3/10/2021 at 2:20 AM, Muddyfunster said:

Nothing was offscreen and that's what confused me, the box_collision sample was 32,16 also and I have a slightly smaller other sprite at 14,13. If part was offscreen I could understand it getting a bit upset.

 

I thought my positioning variables were off, so I hardcoded the actual values in to test it in the engine, same result, no collision on the first 16 pixels from the left.  Once I split the collision check into 2 checks, it's fine.

 

Further investigation :

 

Here's the funny thing. The issue with 32pixel wide collision box only occurs on the first sprite of that type. If I add 3 in a line starting at 0 so they are positioned 0,32,64 then only the first 16 pixels of first sprite are ignored, rest are fine. I can consistently reproduce it. There must be something influencing the check or one of the variables elsewhere.

 

My code chunk in full.


 if lava=false then goto skip_lava_col_w2
 for var69 = 1 to max_lava_chunks
 mytempx = lava_x[var69] 
 mytempy = lava_y[var69]
  if boxcollision(ship_x_hi,ship_y_hi,14,13,mytempx,mytempy,32,16) then player_explode = true
 next
skip_lava_col_w2

I'll investigate some more to make sure nothing is contaminating the positioning vars or anything.

 

 

Just had this pop up again.

 

I was doing some tests with a box collision on a 24x40 sprite, the top 20 or so pixels are ignored unless I split the check into into 3 parts, effectively, 24x8, 24x16 and 24x16. 

 

I was checking the smallest parameter box vs the bigger parameter box (like in the example above). I tried swapping the order in which the parameters are checked so I'm checking the bigger sprites box first. It worked fine with just 1 check.

 

I had another collision check with the same sprite that was working, when I checked, the large box was being called first, the smaller sprite second.

 

So in summary I found that :

 

This works :

if boxcollision(boss_x_hi, boss_y_hi,24,40,mytempx_hi, mytempy_hi,4, 1) then blah blah blah

 

This does not :

if boxcollision(mytempx_hi, mytempy_hi,4, 1, boss_x_hi, boss_y_hi,24,40) then  blah blah blah


Not sure what that means, other than I have a solution to a problem only I was having :) , but I thought I'd share that incase it's helpful to anyone else.

 

I'll be able to go back and remove the lava workaround now as well :)

 

  • Like 2

Share this post


Link to post
Share on other sites
2 hours ago, Muddyfunster said:

Just had this pop up again.

 

I was doing some tests with a box collision on a 24x40 sprite, the top 20 or so pixels are ignored unless I split the check into into 3 parts, effectively, 24x8, 24x16 and 24x16. 

 

I was checking the smallest parameter box vs the bigger parameter box (like in the example above). I tried swapping the order in which the parameters are checked so I'm checking the bigger sprites box first. It worked fine with just 1 check.

 

I had another collision check with the same sprite that was working, when I checked, the large box was being called first, the smaller sprite second.

 

So in summary I found that :

 

This works :


if boxcollision(boss_x_hi, boss_y_hi,24,40,mytempx_hi, mytempy_hi,4, 1) then blah blah blah

 

This does not :


if boxcollision(mytempx_hi, mytempy_hi,4, 1, boss_x_hi, boss_y_hi,24,40) then  blah blah blah


Not sure what that means, other than I have a solution to a problem only I was having :) , but I thought I'd share that incase it's helpful to anyone else.

 

I'll be able to go back and remove the lava workaround now as well :)

 

Awesome work-around. I have an idea at what's at the heart of this, but it's not easily solved. Basically the 8-bit values can underflow near or past the 0 coordinate edges. To work around it, I add an offset, but that can only go so far before you introduce the opposite problem at the max-coordinate screen edges. So Y box checks are reliable up to heights of (256-192)/2, or 32. X box checks are reliable up to widths of (256-160)/2, or 48. Beyond that, things get unreliable at the screen edges.

 

This could be fixed by using 16-bit math, but that would cripple the performance. I do need to document these limitations better. Really this all dawned on me some time after boxcollision was written.

  • Like 3
  • Thanks 2

Share this post


Link to post
Share on other sites

What can cause this compilation error?

 

7800basic compilation complete.
User-defined 7800.asm found in current directory
Read $2000 bytes of cartridge data.
Invalid byte at $FFF8, should be $FF!

 

For me, it hit when I put playsfx in an if/then statement, and went away when I re-coded it to avoid having that statement as part of the if/then statement.

Share this post


Link to post
Share on other sites

The playsfx is one of those inflated statements that cause the if...then logic to trigger an out of range branch. Are there messages elsewhere saying the source wasn't resolvable? 

 

This particular error you've flagged is actually issued by 7800sign, which gets run post-compilation. It's noting the rom is malformed.

Share this post


Link to post
Share on other sites
1 hour ago, RevEng said:

The playsfx is one of those inflated statements that cause the if...then logic to trigger an out of range branch. Are there messages elsewhere saying the source wasn't resolvable? 

 

This particular error you've flagged is actually issued by 7800sign, which gets run post-compilation. It's noting the rom is malformed.

No; there were no errors prior to that one that I could see. Here is the full output:

 

Karls-MBP:SpacePeril kdgarris$ 7800bas SpacePeril.78b

Using "" flavored 7800basic binaries
  Location: /Users/kdgarris/Downloads/7800basic/
  Version: 7800basic v0.18 (14:27:37, Mar 14 2021)
Using "" flavored dasm binary.
  Location: /usr/local/bin/dasm
  Version: DASM 2.20.14

Starting build of SpacePeril.78b
7800basic v0.18 Mar 14 2021 14:27:37

*** (): INFO, GFX Block #0 starts @ $C000
        stars_tile spaceventure_tiles spaceventure_tiles_tallsprite_00
        spaceventure_tiles_tallsprite_01
        spaceventure_tiles_tallsprite_02
        spaceventure_tiles_tallsprite_03
        spaceventure_tiles_tallsprite_04
        spaceventure_tiles_tallsprite_05
        spaceventure_tiles_tallsprite_06
        spaceventure_tiles_tallsprite_07
        spaceventure_tiles_tallsprite_08
        spaceventure_tiles_tallsprite_09
        spaceventure_tiles_tallsprite_10
        spaceventure_tiles_tallsprite_11
        spaceventure_tiles_tallsprite_12
        spaceventure_tiles_tallsprite_13
        spaceventure_tiles_tallsprite_14
        spaceventure_tiles_tallsprite_15
        spaceventure_tiles_tallsprite_16
        spaceventure_tiles_tallsprite_17
        spaceventure_tiles_tallsprite_18 asteroid_wall
        asteroid_wall_tallsprite_00 asteroid_wall_tallsprite_01
        asteroid_wall_tallsprite_02 asteroid_wall_tallsprite_03
        asteroid_wall_tallsprite_04 asteroid_wall_tallsprite_05
        alphabet_8_wide shipsquare shipsquare_n shipsquare_ne
        shipsquare_e shipsquare_se shipsquare_s shipsquare_sw
        shipsquare_w shipsquare_nw pink_transponder pink_transponder_2
        energy_cube attractor attractor_2 cannon cannon_2 transfigurator
        transfigurator_2 voidstone scavenger scavenger_2 spaceblob
        spaceblob_l spaceblob_r spaceblob_eat spaceblob_swallowed
        spaceblob_slain forcefield forcefield2 forcefield3 forcefield4
        shot shot2
*** (): INFO, GFX block #0 has 320 bytes left (20 x 16 bytes)


*** (): INFO, DMA hole #0 starts @ $D000
        no code defined for DMA hole

*** (): INFO, GFX Block #1 starts @ $E000
        titletext2 titletext2_tallsprite_00 titletext2_tallsprite_01
        titleship2 titleship2_tallsprite_00 titleship2_tallsprite_01
        titleship2_tallsprite_02 titleship2_tallsprite_03 titlefire
*** (): INFO, GFX block #1 has 1376 bytes left (86 x 16 bytes)


7800basic compilation complete.
User-defined 7800.asm found in current directory
Read $2000 bytes of cartridge data.
Invalid byte at $FFF8, should be $FF!

7800header 0.13 Mar 14 2021 14:27:38
  opened parameter file a78info.cfg
7800makecc2 v0.1
  The ROM 'SpacePeril.78b.bin' is compatible with CC2.

 

Share this post


Link to post
Share on other sites

Ok, can you send me the list file from a broken compile in PM? That might help me track down why dasm didn't report choking on the assembly, despite the fact it only created a malformed 8k rom.

  • Thanks 1

Share this post


Link to post
Share on other sites

Looking at this, it appears that a multi-line statement with end doesn't play nice when it's part of an if...then. It trips up the preprocessor, which prematurely ends the program.

 

I think this one is just going to be a documented limitation for now. Multi-line statements in a single-line if...then is going to be clumsy anyway, from a syntax perspective. Maybe at some point I'll take a whack at adding a blockif statement.

  • Like 1

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