Jump to content
IGNORED

Part 7 - Menu


SpiceWare

Recommended Posts

Added menu

 

Source Code

 

Download and unzip this in your shared directory.

Collect3_20200208.zip

 

ROM for reference

collect3_20200208.bin

 

 

Menu

 

Implemented a menu using the 2-color 48 pixel kernel.  Menu is fully functional, though Option 1 and 2 don't affect anything except the display of a check or X.

 

Selected values for Players and Arena will affect the display of the game screen.

 

Players 1, Arena 1

collect3.thumb.png.cff8d59c200c31441e061bb6e176a91b.png

 

Only 1 player in a black arena

collect3_1.thumb.png.2962d68ffc768135ab74dbc1af0b7161.png

 

Players 2, Arena 2

collect3_3.thumb.png.d5dfe3c699d542a58f89f4651da862b1.png

 

2 players in a red arena

collect3_2.thumb.png.426e23a3ece2bf50143b8dc2ae524af2.png

 

When implementing this I had to move the layout of Display Data to the end of collect3.asm to prevent label mismatch errors:

dasm collect3.asm -f3 -ocollect3.bin -lcollect3.lst -scollect3.sym
collect3.asm (215): error: Label mismatch...
 --> _BUF_MENU_CONTROL 000c                  
collect3.asm (216): error: Label mismatch...
 --> _BUF_MENU_COLORS 000c 

 

 

48 pixel 2 color kernel

 

The 48 pixel kernel was developed for Stay Frosty 2. It works by using the players as stencils:

 

710905968_ScreenShot2020-02-08at7_01_10PM.thumb.png.dd9635e79ae354ff6d8c2f2c4dc8c57b.png

 

The players are colored black, so all the 1 bits will be black while all the 0 bits will show through the underlying colors of the background and playfield.

 

The playfield and background colors is set to black for the left side of the screen, changed just before the 48 pixel display begins, then changed back to black for the right side of the screen.  The color change doesn't happen at exactly the right time, so the missiles are used to hide the transition.  You can see that by using Stella's Developer Keys to toggle both missiles (ALT + C and ALT + V for Linux or Windows, COMMAD + C and COMMAND + V for Mac):

 

collect3_1.thumb.png.281cddf1f4d1c114bd23b723757b7cd8.png

 

Toggling Fixed Debug Colors mode (ALT + COMMA or COMMAND + COMMA) will reveal the layout (be sure to toggle the missiles back on!):

 

collect3.thumb.png.78f6a5928d04b5dd8bb1909488b7d0ef.png

 

The playfield is limited to coloring 4 adjacent pixels at a time, but you can use the ball to fine-tune where the second color shows up - you can see it used for the 3 in COLLECT 3.

 

The playfield can be changed for each entry. This menu doesn't show it off to great effect as just the game title uses a different playfield layout.

 

Some new constants were added to control the spacing in the menu. Whenever you modify the menu make sure to also modify these constants to maintain the 262 scanline count.

; controls spacing in main menu
MM_TITLE_GAP        = 20    ; gap after game title
MM_OPTION_GAP       = 8     ; gap between options
MM_START_GAP        = 20    ; gab before START option
MM_LOGO_GAP         = 20    ; gap before company logo
MM_END              = $80
_MM_OPTION_HEIGHT   = 7   

Only the constant for Option Height is directly used by the C code, so it's prefixed with the _.

 

There are 3 datastreams used by the menu.

; datastream usage for Menu
_DS_MENU_GRAPHICS    = DS0DATA
_DS_MENU_CONTROL     = DS1DATA
_DS_MENU_COLORS      = DS2DATA

 

The graphics datastream contains the graphics as shown on the screen, with an initial value set for each option.  The value will be overwritten if the value is different than the initial value.

 

The control datastream holds the playfield pattern used for each entry, the position of the ball (set to 0 if not using it), the height of the option, and the number of extra scanlines to show after the option. Setting extra scanlines to $80 triggers the end of the menu.  

_MENU_CONTROL:
        .byte %00000000     ; PF0
        .byte %01000000     ; PF1
        .byte %00000000     ; PF2
        .byte 100           ; ball X location
        .byte _MENU_LOGO_HEIGHT ; rows
        .byte MM_TITLE_GAP  ; extra scanlines
        
_MENU_FIRST_OPTION_ID = (* - _MENU_CONTROL) / 6         
_MENU_PLAYERS_ID = (* - _MENU_CONTROL) / 6
        .byte %11100000     ; PF0
        .byte %11000000     ; PF1
        .byte %00000000     ; PF2
        .byte 0             ; ball X location
        .byte _MM_OPTION_HEIGHT             ; rows
        .byte MM_OPTION_GAP ; extra scanlines

...

_MENU_START_ID = (* - _MENU_CONTROL) / 6
        .byte %00000000     ; PF0
        .byte %00000000     ; PF1
        .byte %00000000     ; PF2
        .byte 0             ; ball X location
        .byte _MM_OPTION_HEIGHT             ; rows
        .byte MM_END        ; extra scanlines      

 

The SpiceWare logo is not part of menu control as it uses a different kernel to extend the lines left and right.

 

In the C code MenuOverScan() has been updated to call new function ProcessMenuJoystick() - but only if the user hasn't pressed GAME RESET on the console.

 

MenuVerticalBlank() has been updated to do a mass-copy that sets default values for the menu's graphics, control, and colors datastreams.  The colors are then updated for NTSC/PAL/SECAM by using ColorConvert(). Next menu options are updated if they need to show a different graphic than the default one.  Lastly one of the colors for the selected option will be flashed using the frame counter.

 

 

C data in 6507 source

 

For most of my projects I've only used a single 4K bank for 6507 code. It usually ends up quite full, so data that's not directly accessed by the 6507 is put either in the C code, or after the compiled ARM code.  An example of data in the C code is the color table used to test the new Arena menu option:

 

const unsigned char arena_color[4] =
{
        _BLACK,
        _RED,
        _GREEN,
        _BLUE
};

 

Graphic data can also be stored in the C code, though I had 2 conflicts with doing so.

  1. I already have tools that convert images for the format used by dasm.
  2. Lists of images use up twice as much ROM when stored in C code as it does when stored in the 6507 code.

 

#1 is a minor issue.  #2 can be a major issue, even with a 32K game. As an example Draconian has 136 images in the table which takes up 272 bytes in the 6507 code. If the table was in the C code it would have taken 544 bytes.

 

Because of this I've taken to putting the graphics and related data (like the menu control) in the 6507 source file. It's located after the ARM code, and before the banks of 6507 code.

 

There is something to be aware of when doing this - because the build process is this:

  1. assemble 6507 code to create defines_from_dasm_for_c.h
  2. compile C code to create ARM routines
  3. assemble 6507 to create final ROM

 

Step 1 uses the previously compiled ARM code, which will likely change size in step 2. This can make things move in the ROM when step 3 is done.

 

So the data is broken up into 2 groups, ARM Indirect Data and ARM Direct Data.

 

ARM Indirect Data is data the C code doesn't directly access.  You can tell it's not accessed because the labels are not prefixed with a _ character, so they don't end up in defines_from_dasm_for_c.h:

 

1885815655_ScreenShot2020-02-08at7_58_04PM.thumb.png.f705fc58ef8af2a841fabec1ac9697f0.png

 

ARM Direct Data is directly accessed by the C code.  We use an ORG to prevent it from shifting around during the 3 steps of the build process.  You'll notice the graphic images of PLAYER_LEFT and PLAYER_RIGHT seen above are in the table _IMAGE_GRAPHICS seen below.  The C code uses this table to access the graphics.

 

1934708372_ScreenShot2020-02-08at7_59_19PM.thumb.png.581f82041af109dffc1feeb78b90f79b.png

 

The ORG value will need to be adjusted as the project is developed.

  • Like 1
Link to comment
Share on other sites

I tweaked the playfield values for the menu to better show how the second color works. This will be in the source when I post Part 8.

 

_MENU_CONTROL:
        .byte %00000000     ; PF0
        .byte %01000000     ; PF1
        .byte %00000000     ; PF2
        .byte 100           ; ball X location
        .byte _MENU_LOGO_HEIGHT ; rows
        .byte MM_TITLE_GAP  ; extra scanlines
        
_MENU_FIRST_OPTION_ID = (* - _MENU_CONTROL) / 6         
_MENU_PLAYERS_ID = (* - _MENU_CONTROL) / 6
        .byte %00000000     ; PF0
        .byte %01000000     ; PF1
        .byte %00000000     ; PF2
        .byte 0             ; ball X location
        .byte _MM_OPTION_HEIGHT             ; rows
        .byte MM_OPTION_GAP ; extra scanlines

_MENU_ARENA_ID = (* - _MENU_CONTROL) / 6
        .byte %00000000     ; PF0
        .byte %01000000     ; PF1
        .byte %00000000     ; PF2
        .byte 0             ; ball X location
        .byte _MM_OPTION_HEIGHT             ; rows
        .byte MM_OPTION_GAP ; extra scanlines
        
_MENU_OPTION1_ID = (* - _MENU_CONTROL) / 6
        .byte %00000000     ; PF0
        .byte %11000000     ; PF1
        .byte %00000000     ; PF2
        .byte 0             ; ball X location
        .byte _MM_OPTION_HEIGHT             ; rows
        .byte MM_OPTION_GAP ; extra scanlines

_MENU_OPTION2_ID = (* - _MENU_CONTROL) / 6
        .byte %00000000     ; PF0
        .byte %11000000     ; PF1
        .byte %00000000     ; PF2
        .byte 0             ; ball X location
        .byte _MM_OPTION_HEIGHT             ; rows
        .byte MM_OPTION_GAP ; extra scanlines
        
_MENU_TV_TYPE_ID = (* - _MENU_CONTROL) / 6
        .byte %11100000     ; PF0
        .byte %11000000     ; PF1
        .byte %00000000     ; PF2
        .byte 0             ; ball X location
        .byte _MM_OPTION_HEIGHT             ; rows
        .byte MM_START_GAP  ; extra scanlines
        
_MENU_START_ID = (* - _MENU_CONTROL) / 6
        .byte %00000000     ; PF0
        .byte %00000000     ; PF1
        .byte %00000000     ; PF2
        .byte 0             ; ball X location
        .byte _MM_OPTION_HEIGHT             ; rows
        .byte MM_END        ; extra scanlines        
        
_MENU_CONTROL_SIZE = * - _MENU_CONTROL

 

 

collect3.thumb.png.0c68f5f60bf370f64d9bd29d78121bd9.png

 

Players, Arena, Option 1 and Option 2 now use less playfield for the second color. TV Type was unchanged as SECAM needs that extra playfield pixel.

collect3_1.thumb.png.99aa53da22617c98c991a093846fda53.png

 

Missiles disabled to better show playfield usage.

collect3_2.thumb.png.d04fdc874fc0da09cf9405b939bfc211.png

  • Like 1
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...