Jump to content
IGNORED

P-Machinery: Shared RAM segment blocks


DZ-Jay

Recommended Posts

NOTE: This is the first in a series of articles I intend to write to discuss new features to be included in the upcoming P-Machinery v2.0, a.k.a. P-Machinery AGE (Advanced Game Engine).


Re-Introducing RAM Segments.
P-Machinery 1.0 introduced the concept of "RAM Segments." These are blocks of RAM statically allocated to be used exclusively on a given game state. This allowed multiple parts of the game to use all available RAM for its own purposes. For instance, you may need 50 bytes for variables to store game-play state, but you may not need that during the Title sequence.

The RAM Segment framework included support for a single "Global" segment. This allowed you to allocate memory that will be excluded from all subsequent RAM segments. All global variables (including framework-specific ones) were to be declared here.

RAM Segments in P-Machinery 1.0 worked like this:

First, you declare the start of your RAM allocation with the RAMSTART directive, somewhere at the top of your code.:

                ; Start RAM allocation
                RAMSTART

                ; Global variables
CARD_BLITTER    SYSTEM  1
TRAP_SCR_STEP   SCRATCH 1
TRAP_SCR_RET    SCRATCH 2

This initializes the RAM manager and automatically creates the "Global" segment. From this point on, all variables declared using the framework memory allocation directives were defined in the "Global" segment.

Next, you define a new segment for each of your game states using the RAMSEG_START() directive. Any subsequent variable definitions will be allocated to the new segment. You can use the RAMSEG_START() directive as many times as you'd like, and each one would start allocating variables at the end of the Global segment.

                ; Start new RAM segment
                RAMSEG_START(Title)

                ; Declare variables for the Title state
CREDITS         STRUCT  0
@@Page          SCRATCH 2
@@Count         SCRATCH 1
                ENDS

This mechanism is clearly very useful and powerful, but it does have some limitations. One obvious drawback is that all segments (with the exception of the "Global" one) share the same memory space. This means that each segment is expected to be mutually exclusive to any other.

In this model, there is no way to declare a variable that is shared among multiple, but not all, segments. The closest way would be to declare it in the "Global" segment, but that would prevent you from re-using that memory in another segment that could use it for a different purpose.


Enter Shared Memory Blocks.
P-Machinery AGE expands on this primitive memory management model in many ways. One of these is that RAM segments are automatically created for you when defining a new game state. Another more important feature is what I call Shared Memory Blocks.

Shared Memory Blocks allows you to define a custom RAM segment, declare variables for it, and associate it to one or more RAM segments. It works in a sort of inheritance model, where you define a "parent" segment, and any subsequent child segments extend it by including it at its base.

So for instance, let's say that you have a set of variables for sprite handling that you want to use within the Title and Play game states, but nowhere else. You can declare a custom RAM segment to contain them, and have the Title and Play segments inherit from it. Like this:

        ; Start a new custom RAM segment
        MEM.RAM.SEG.Start SpriteInfo

            ; Declare shared variables
            MEM.RAM.WordVar SPR_XY
            MEM.RAM.ByteVar SPR_COLOR

        MEM.RAM.SEG.End

        ; Define a new state: Title
        ; With RAM segment extending SpriteInfo
        STATE.Start Title, SpriteInfo

            ; Declare state-specific variables
            MEM.RAM.ByteVar TITLE_STR
            MEM.RAM.ByteVar TITLE_COLOR

        STATE.End

        ; Define a new state: Play
        ; With RAM segment extending SpriteInfo
        STATE.Start Play, SpriteInfo

            ; Declare state-specific variables
            MEM.RAM.WordVar PLAYER_SCORE
            MEM.RAM.ByteVar PLAYER_LIVES

        STATE.End

 

For any other segment that does not require inheritance, just use an attribute of "None." This will treat it in the same way as the old P-Machinery:

    ; Define a new state: Game-Over
    ; With no inheritance for RAM segment
    STATE.Start GameOver, None

        ; Declare state-specific variables
        MEM.RAM.WordVar FOO
        MEM.RAM.WordVar BAR
        MEM.RAM.WordVar BAZ

    STATE.End

In conclusion, Shared Memory Blocks allow for a more versatile memory allocation model in the new P-Machinery AGE. Memory is still statically allocated, but segment overlap and RAM overflow is handled automatically for the programmer so that he may concentrate on game logic, and ultimately work at a higher cognitive level.

-dZ.

Edited by DZ-Jay
  • Like 3
Link to comment
Share on other sites

There is obviously no disadvantage in that. The main difference is that P-Machinery is not a compiler. ;)

 

It is a framework and a programming model built on a library of macros that extend the functionality of the assembler. You are still programming at a low level, just not too close to the bare metal.

 

P-Machinery doesn't offer true memory management like Batari Basic or a true compiler would. All it does is keep track of which memory cells have been assigned to labels, so that the programmer doesn't have to keep track of which parts of memory are still free, or figure out the physical addresses of his own variables. It also abstracts the many physical RAM segments available (e.g., on-board vs. cartridge-based vs. expansion module, etc.) so it all looks like a pool of 8-bit Bytes or 16-bit Words.

 

The allocation directives also take care of physical segment boundaries, so if you allocate a "record" structure, you can be sure it is contiguous, and take advantage of that fact. It is all a rather "high-ish" level of dealing with low-level memory in Assembly Language.

 

You can obviously create aliases to any variable, since they are merely label symbols on memory addresses. This is how I overcame that limitation in Christmas Carol. However, you lose sight of segment boundaries and available RAM. It also pollutes your code with potentially cognitive dissonant associations, such as:

PLAYER_SCORE   EQU   SPRITE_POS

Just because that label happens to be convenient and of the same size you need.

 

-dZ.

 

 

EDIT: Fixed paragraphs mangled by Tapatalk.

Edited by DZ-Jay
  • Like 1
Link to comment
Share on other sites

Thanks for doing this ... hopefully having a solid framework will draw more programmers to the fray (and maybe help develop some new ones!)

That's one of my aims. Of course, my main objective is to simplify and expedite my own game development. But I want to make sure it is useful to others as well.

 

That's why any feedback is welcomed.

 

dZ.

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