Jump to content


P-Machinery: Shared RAM segment blocks

4 replies to this topic




  • 12,117 posts
  • The P-Machinery AGE is almost here!
  • Location:NC, USA

Posted Fri Nov 22, 2013 7:16 AM

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

                ; Global variables

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

                ; Declare variables for the Title state
@@Page          SCRATCH 2
@@Count         SCRATCH 1

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


        ; 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


        ; 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



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


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.


Edited by DZ-Jay, Fri Nov 22, 2013 7:22 AM.

#2 Gemintronic OFFLINE  


    Jason S. - Lead Developer & CEO

  • 9,335 posts

Posted Fri Nov 22, 2013 8:00 AM

In batari BASIC you can relabel the same memory area.


 dim titlescreenchoice = a


 dim player2lives = a



What's the disadvantage of doing it that way as opposed to the way you described?


Not complaining.  Just trying to understand :)




  • Topic Starter
  • 12,117 posts
  • The P-Machinery AGE is almost here!
  • Location:NC, USA

Posted Fri Nov 22, 2013 9:17 AM

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:


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





EDIT: Fixed paragraphs mangled by Tapatalk.

Edited by DZ-Jay, Sat Nov 23, 2013 5:51 AM.

#4 Fushek OFFLINE  



  • 1,577 posts
  • Actively Seeking Spiker!
  • Location:Clevelandish

Posted Fri Nov 22, 2013 10:20 AM

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




  • Topic Starter
  • 12,117 posts
  • The P-Machinery AGE is almost here!
  • Location:NC, USA

Posted Fri Nov 22, 2013 10:46 AM

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.


0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users