Jump to content
IGNORED

7800 BEAD header


RevEng

Recommended Posts

As a side project, I've been working on a rudimentary terminal program for the 7800. Some day I see the 7800 as being capable of downloading game binaries directly from online sources, or alternate media like a savekey. Games could even download their own updates, and run them from RAM.

 

To avoid having to parse something like the A78 header with the 6502, I've come up with a succinct embedable header. The header doesn't need to actually be in the code path, but will only spoil the X register if it is.

 

[edit - old version of the header has been removed. See the spec for the correct info]

 

A device with a bios and semi-persistent ram might even scan certain memory locations for a BEAD header, or check the start of an inserted SaveKey, and offer to run the binary.

 

Hoping that sharing this info might stoke some imagination.

  • Like 3
Link to comment
Share on other sites

I like this idea, but have similar concerns with the current draft as with the *.a78 header. In particular, I don't think there should be any ambiguity with what the payload is (RAM-resident executable, Fixed 16K - 32K ROM image, etc.) and what's up with Pokey. The latter is a real issue, as Pokeys are being dropped all over the address space willy-nilly. We need clear indication as to if a Pokey is included and where it is.

 

Nintendo's embedded headers used in the GameBoy are a good reference. These are detailed enough to clearly describe a cartridge's contents, but still simple enough to parse on an 8-Bit CPU without much fuss. More importantly, there's a good distinction between hardware description and software features.

 

Something like a double bead :

$BE,$AD,$FM,$BE,$AD,$SS

 

...or an extended bead :

$BE,$AD,$FM,$18,$90,$xx,$SS,[data] where the $18,$90 is a clc,bcc to skip over more fields.

 

These could give more information such as the payload size(s) or clarify features.

Where $FM specifies the payload features and mapper (if any), something like :

%FFFF.... == %VHX?
\- V == AtariVox
 - H == High Score Cartridge
 - X == XM
 - ...etc

%....MMMM
\- %1111 == Executable Payload (i.e. load into RAM and run in place)
 - %0000 == Mapperless 16K - 32K
 - %0001 == Mapperless 48K
 - %0010 == SUPER
 - %1000 == Activision
 - %1001 == Absolute
 - ...etc

 

The $SS could be a type-specific field. So this would be tied to $FM's %MMMM and give more information about what features exclusive to that mapper are used.

 

 

Addendum : How about *.b78 as an extension?

 

Edited by TailChao
  • Like 1
Link to comment
Share on other sites

3 hours ago, TailChao said:

I like this idea, but have similar concerns with the current draft as with the *.a78 header. In particular, I don't think there should be any ambiguity with what the payload is (RAM-resident executable, Fixed 16K - 32K ROM image, etc.) and what's up with Pokey. The latter is a real issue, as Pokeys are being dropped all over the address space willy-nilly. We need clear indication as to if a Pokey is included and where it is.

I should have spelled it out, but the intention was for pokey to be strictly pokey@450, which has become a homebrew standard of sorts. For this header to have meaning, we need a platform with RAM or equivalent, like XM, MPC, CPUWIZ's other cart formats - and $450 is common to all of those. It's trivial to modify commercial games to use pokey@450 instead of 4000, so even those could be bead'ized. (though fitting the bead in would be a bit more work)

 

I like the double-bead idea, with the base bead giving basic platform info, and extended beads giving future (hopefully esoteric) hardware options. That way first gen bead hardware might still be able to load software that specifies an extended bead, by simply ignoring it.

 

On your suggestions for payload... with this header I'm not trying to do away with a78 headers for emulators. Rather I want to make it easier to load 7800 homebrew executables on real hardware, from sources that aren't trivial to seek through. I don't think the extended payload would be worth the extra parsing, when the reality is that we're not likely to see homebrew in Activision or Absolute formats. We're not having to prep AtariVox, controllers, etc., so they're not needed in BEAD. XM is covered by it's constituent peripherals in the current base bead. 

 

I think keeping the base bead features limited to a single byte, supporting foreseeable hardware, is key. I'm ok that this trades away some theoretical flexibility. I think it's more important for bead support to be cheap, both codewise and romwise. 

  • Like 1
Link to comment
Share on other sites

Ah, thanks for the clarification :)

 

I did get the impression this was just intended as a simple executable header, but it's always a little difficult to not try and cover all use cases. That considered, not having any indication as to where the data are going is a source of concern, as...

 

On 7/15/2019 at 1:22 PM, RevEng said:

A device with a bios and semi-persistent ram might even scan certain memory locations for a BEAD header, or check the start of an inserted SaveKey, and offer to run the binary.

...this could even be a stock unit with just a modified BIOS and SaveKey. The particular scenario I'm thinking of is running manufacturing tests and pulling data from the SaveKey into the 7800's internal RAM or even the cartridge's EXRAM, but this might be a bit too much.

 

 

So with the desire to keep BEAD a tiny executable descriptor - I'd only move the "reserved" bits of F1 to the MSBs (since these might become significant enough to BIT / bmi / bvs over) and formally add the option to put a build tag or description after the BEAD.

 

Effectively : $BE,$AD,[F1],$18,$90,[SS],"My Program (05/21/1984) v3",0

 

This way information which doesn't have to be in the filename (if any) can stay out, and if you're going to use the same binary for both BEAD-loading and ROM-ing it's a little more convenient to track.

 

1 hour ago, RevEng said:

I think keeping the base bead features limited to a single byte, supporting foreseeable hardware, is key. I'm ok that this trades away some theoretical flexibility. I think it's more important for bead support to be cheap, both codewise and romwise. 

Agreed.

  • Like 1
Link to comment
Share on other sites

1 hour ago, TailChao said:

That considered, not having any indication as to where the data are going is a source of concern, as...

 

...this could even be a stock unit with just a modified BIOS and SaveKey. The particular scenario I'm thinking of is running manufacturing tests and pulling data from the SaveKey into the 7800's internal RAM or even the cartridge's EXRAM, but this might be a bit too much.

Indirectly the start location is there, but it's just not covering your scenarios. e.g. 16k would start at C000, 32K would start at 8000, etc.  

 

So maybe some ram segments could be added to the formats?

;       %00000nnn : 0=16k 1=32k 2=48k 3=128k 4=144k 5=@1800 6=@2200 7=@4000

 

The loads into ram segments would't have the 6502 vectors, so in that case the bead loader would just jump to the start of the segment. I'm also thinking that a segment load would as long as the natural segment length, if loaded from savekey. (since there's no EOF)

 

Moving the reserved bit to MSB works for me. I also like the extended bead with descriptor string.

 

[edit - Just considering if there should be a way to mark a bead as non-executable (ie. for data) and then string beads together. It would be neat, but too much scope creep.]

 

Link to comment
Share on other sites

Hmm, I'd actually pull it back a little.
How about this?

$BE,$AD,[F1],$18,$90,[SS],"Description",0,...

F1 : %vHYPRDSS
\- v == Reserved (set to '0')
 - H == High Score Cartridge
 - Y == Yamaha
 - P == Pokey
 - R == ROF
 - DSS == Data Type and Size
   \- %000 : 16K @ $C000 - $FFFF
    - %001 : 32K @ $8000 - $FFFF 
    - %010 : 48K @ $4000 - $FFFF
    - %011 : reserved
    - %100 : 4K @ $1800 - $27FF
    - %101 : reserved
    - %110 : 16K @ $4000 - $7FFF
    - %111 : reserved

 

 

16 hours ago, RevEng said:

The loads into ram segments would't have the 6502 vectors, so in that case the bead loader would just jump to the start of the segment. I'm also thinking that a segment load would as long as the natural segment length, if loaded from savekey. (since there's no EOF)

Yeah, each bead's size is given by the header - so creating a string of beads wouldn't require a directory. I do like this flexibility in storing the beads.

 

Since the header can be executed-over, I'd think all beads should support this as an entry point - whether or not they actually have vectors for the 6502.

 

 

16 hours ago, RevEng said:

[edit - Just considering if there should be a way to mark a bead as non-executable (ie. for data) and then string beads together. It would be neat, but too much scope creep.]

Marking a bead as non-executable would be a nice feature, but once we start getting into arbitrary data it's going to require arbitrary payload sizes. I'd recommend keeping the beads as-is for now, and then if non-executable beads are desired in the future, they can be implemented using the "v" bit and perhaps a double-bead header.

Link to comment
Share on other sites

Agreed all around!

 

Any objection to swapping the reserved bit at %101, and the %100 segment? That way the 2 available reserved bits can be later used for either a full format or a segment, without splitting the nice grouping of formats and segments.

 

When I get a chance I'll write up the spec at 7800.8bitdev.org, and update the first post here too.

Link to comment
Share on other sites

Cool!

 

1 hour ago, RevEng said:

Any objection to swapping the reserved bit at %101, and the %100 segment? That way the 2 available reserved bits can be later used for either a full format or a segment, without splitting the nice grouping of formats and segments.

 

If you mean like this...

 - DSS == Data Type and Size
   \- %000 : 16K @ $C000 - $FFFF
    - %001 : 32K @ $8000 - $FFFF 
    - %010 : 48K @ $4000 - $FFFF
    - %011 : reserved
    - %100 : 4K @ $1800 - $27FF
    - %101 : 16K @ $4000 - $7FFF
    - %110 : reserved
    - %111 : reserved

...that's totally fine. As long as the RAM / EXRAM targets are clearly separated from the 16K / 32K / 48K types I'm happy :)

 

 

1 hour ago, RevEng said:

When I get a chance I'll write up the spec at 7800.8bitdev.org, and update the first post here too.

Great, I'll put bead dispatch support on my BupSystem grocery list - with the *.b78 extension if that's okay. The feature list for v0.9.6.0 is currently locked (should be released in early August), but this shouldn't be too much effort to add later. Hopefully when later arrives there'll be some beads to test with!

Link to comment
Share on other sites

I was thinking more like this...

 - DSS == Data Type and Size
   \- %000 : 16K @ $C000 - $FFFF
    - %001 : 32K @ $8000 - $FFFF 
    - %010 : 48K @ $4000 - $FFFF
    - %011 : reserved
    - %100 : reserved
    - %101 : 4K @ $1800 - $27FF
    - %110 : 16K @ $4000 - $7FFF
    - %111 : reserved

...so at some point the middle reserved values can either become 2 formats, 1 format+1 segment, or 2 segments. (Without mixing up our grouping of formats and segments.)

 

The b78 extension sounds good. The test beads shouldn't be a problem, for full format types anyway. The first place I'm putting them is in 7800basic, so I can just recompile any of the code samples or games.

 

I'm also planning to work on a reference loader, targeting XM hardware.

Link to comment
Share on other sites

Looks good so far!

 

A few observations :

  • In the Minimal BEAD Header section : "DSS types that don't have memory covering the 6502 reset vector will begin execution from the bead header" - it should be clarified that even BEADs with reset vectors should allow the use of their header as an entry point.
  • In the Extended BEAD Header section : "It should be noted that the $18,$90 bytes are the 6502 CLS and BCC opcodes..." should be "...CLC and BCC..."
  • Nitpick : We're using BEAD, Bead, and bead to refer to the header - should probably just stick with one (I vote for BEAD).

 

I don't think any credit is required but using my handle is fine.

 

One thought for future expansion, the description string is using a clc/bcc hop over its content. We could use different hops (sec/bcs, LDA#0/beq etc.) for different types of data. Might be helpful for when arbitrary nonexecutable blocks arrive.

Link to comment
Share on other sites

Thanks for the typo catch, and the nitpick - I'll stick with BEAD.

 

I'm not sold on the requirement that the reset vector should be ignored when present... it would certainly make it harder to convert commercial games to bead. It also adds friction to adoption by homebrewers.

 

The reset vector adds a small bit of handling code, but I think it's worth it.

 

 

 

 

Link to comment
Share on other sites

22 hours ago, RevEng said:

I'm not sold on the requirement that the reset vector should be ignored when present... it would certainly make it harder to convert commercial games to bead. It also adds friction to adoption by homebrewers.

Ah, I'm not saying the reset vectors should be ignored completely - but rather it would be polite for BEAD software to support both entry points. At most it's going to add three more bytes for a jmp $hhll or jmp ($hhll), and then the software could know whether it was started from a loader (and allow dropping back to your terminal / shell) or run directly from a cold start.

 

Of course, this could just be more feature creep ;)

Link to comment
Share on other sites

Ok, I compromised on the point a bit...

  • DSS types that don't have memory covering the 6502 reset vector will begin execution from the BEAD header. For executables with DSS types that do cover the reset vector, it's strongly encouraged that code execution beginning at the header location works correctly, as some BEAD loader implementations may not begin execution at the reset vector address.

...that way deviations are on the BEAD executable creator.

 

I've updated the spec with the mentioned updates so far. I have minimal BEAD headers in 7800basic already for the non-segment formats, but I'm going to upgrade that to an extended header, and also work on some minimal loader reference implementations.

 

I think we're done, but if you or anyone else has more suggestions, feel free to fire away.

 

 

 

 

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