Jump to content
IGNORED

Program size issue


Recommended Posts

I am trying to understand how to add more space as my game seems to be hitting a limit.

 

I originally had put ASM ORG $B000 just after my game loop and it solved my problem. But now it seems to be happening again.

 

I inserted ASM ORG $C100 several lines down and I no longer get the error when I try to compile the program, it runs but I get a bunch of GROM characters all over the place. 

 

Perhaps I am not understanding how this works?

 

Link to comment
Share on other sites

It sounds good to me. See contrib/42k.bas for which addresses the segments cover:

 

REM SEGMENT ADDRESS RANGE  SIZE  NOTES
REM ======= ============== ===== =====
REM    0    $5000 to $6FFF $2000 - Default segment
REM    1    $A000 to $BFFF $2000
REM    2    $C040 to $FFFF $3FC0 - Avoid STIC aliasing.
REM    3    $2100 to $2FFF $0F00
REM    4    $7100 to $7FFF $0F00 - Avoid EXEC's ECS ROM probe.
REM    5    $4810 to $4FFF $0800 - Account for game's ECS ROM mapping out code.

 

Do you have a block of graphics definitions that would cross two segments with an ASM ORG in the middle? I'm not sure if that would be the case, but just like I mentioned to Mik's Arcade, enable generation of list files if you already don't, and look through those for your labels to see which addresses those end up at.

Link to comment
Share on other sites

funny, i literally just ran into this issue with my program yesterday.

 

I don't know for a fact, but I would try taking out the ASM ORG $C100 and test moving the ASM ORG $B0000 down further in the code. I think you might have it in before the section actually runs out thus wasting some space.  I could be wrong, but give it a try.

 

Hopefully one of the gurus chimes in with a more intelligent reply. By the time I ran into this issue, it was occuring well after my main loop and down past most of my GOTO and SUBLOB logic so that is where I put my ASM.  Of course your main loop might be bigger than mine.... 

 

EDIT: And now that Carlsson beat me to the punch, this DID occur to me after I added  the DATA statements for a new screen I built using IntyColor.  Now, all of my music, bitmaps and data statements are in the segment after the ASM statement....hopefully that is right...haha

Edited by Mik's Arcade
Link to comment
Share on other sites

Personally I like to have the structure main code - subroutines - generic data - graphics definitions - screen cards - music but you can have it any order. Some like to interleave graphics with subroutines for a logic flow what belongs together. By checking the list file, you can also compute which sections are larger or smaller, which ones you could move up or down in order to optimize memory usage within a segment. Just avoid having a subroutine, a block of graphics etc overflow a segment or force an ORG statement in the middle of it. Move all of it to a new segment, perhaps rearrange something smaller to fit in its space.

Link to comment
Share on other sites

I know that Oscar once suggested to me that I check the list file, but I don't see that anywhere. All I can find is a .cfg and when I open it I see this:

 

[mapping]
$0000 - $0443 = $5000
$0444 - $1343 = $C100
$1344 - $2343 = $D000
$2344 - $3343 = $E000
$3344 - $3A40 = $F000

Edited by Brian's Man Cave
Link to comment
Share on other sites

9 minutes ago, Brian's Man Cave said:

I know that Oscar once suggested to me that I check the list file, but I don't see that anywhere. All I can find is a .cfg and when I open it I see this:

 

[mapping]
$0000 - $0443 = $5000
$0444 - $1343 = $C100
$1344 - $2343 = $D000
$2344 - $3343 = $E000
$3344 - $3A40 = $F000

Yes, keep an eye on the .cfg and know how to interpret it.  In fact, I have my Make script display the contents of this file after successful assembly, so I can monitor the growth of the ROM image.

 

Right away, I see what's up.  You have a block that started at $C100 and went all the way into the $Fxxx range.  Try to limit $F000 to graphics, lookup tables, and metadata.

 

All my projects are broken up into multiple .bas files, and my main.bas is little more than a bunch of INCLUDE statements, as you can see on page 283 of the Advanced Game Programming book.  What you want to do in your case is have a block of code use the 8K space available from $A000-BFFF, and the remainder use the space from $C100-DFFF (you can start at $C040 instead of $C100).

 

I can help you further if need be.

Edited by Zendocon
Typo
Link to comment
Share on other sites

It seems like you're having ASM ORG quite early on, since you only use around 13% of the first segment. While utilizing 100% might be near impossible depending on how your program is structured, I think 85-90% should almost always be doable.

 

I remembered that the list file is generated by as1600, not the compiler. Are you using the SDK? I think there is a build script that gives the -l parameter to the assembler.

  • Like 1
Link to comment
Share on other sites

Just now, Brian's Man Cave said:

Here is how my program is laid out:

 

variables

game loop

bitmaps 

Screens

Procedures

Good.  I assume those are in separate files.  That will make it easy to shuffle things around with a bunch of INCLUDE statements.

 

Depending on how large those blocks are, your Bitmaps and Screens can probably safely go into $F000.  Variables has no effect on the ROM size.  Your Game Loop and Procedures might have to be broken up into multiple files, since your total ROM size is ~14.5K right now ($3A40 is the last virtual ROM address in your .cfg file).

Link to comment
Share on other sites

A couple more points:

 

You'll know if you overflow past the end of $F000, because as1600 will suddenly throw a large number of errors.

 

It wasn't mentioned in the original Game Programming book, but try to stay out of the $E000 range, because that will jeopardize ECS compatibility.  LTO Flash can use a little bankswitching to work around that issue, if you flag your ROM as ECS incompatible (that's what I ended up doing for Blix & Chocolate Mine).

  • Like 1
Link to comment
Share on other sites

42 minutes ago, carlsson said:

It seems like you're having ASM ORG quite early on, since you only use around 13% of the first segment. While utilizing 100% might be near impossible depending on how your program is structured, I think 85-90% should almost always be doable.

 

I remembered that the list file is generated by as1600, not the compiler. Are you using the SDK? I think there is a build script that gives the -l parameter to the assembler.

 

The SDK generates those files automatically when using the "INTYBUILD" tool.

 

41 minutes ago, Brian's Man Cave said:

Yes I am using the SDK

 

The next version of the SDK will include a ROM segment selector macro.  If you want to use this right now, let me know, and I can send the the module that manages the segments, and a copy of the altered "prologue.bas" and "epilogue.bas" files.

 

The macro is of the format:

;; ======================================================================== ;;
;;  ROM.SwitchSeg seg                                                       ;;
;;  Switches the program counter to a different ROM segment. It also closes ;;
;;  the currently open segment.                                             ;;
;;                                                                          ;;
;;  ARGUMENTS                                                               ;;
;;      seg         The ROM segment to open.                                ;;
;;                                                                          ;;
;;  OUTPUT                                                                  ;;
;;      _rom.error  -1 on failure.                                          ;;
;; ======================================================================== ;;
MACRO   ROM.SwitchSeg seg

 

And it defines the following 6 segments, taken from the "CART.MAC" macro library from the SDK-1600.

                ; --------------------------------------
                ; Memory map for 42K ROM cartridge
                ; --------------------------------------
                ;   SEGMENT     RANGE
                ;      0        $5000 - $6FFF :  8K
                ;      1        $A000 - $BFFF :  8K
                ;      2        $C040 - $FFFF : 16K
                ;      3        $2100 - $2FFF :  4K
                ;      4        $7100 - $7FFF :  4K
                ;      5        $4800 - $4FFF :  2K
                ;
                ;      CARTRAM  $8040 - $9EFF :  8K
                ; --------------------------------------

 

The macro will form part of the SDK working environment, and default to ROM Segment  #0 ($5000 - $6FFF), which is the default right now as well.

 

To switch segments, all you need to do is invoke the macro like this:

' Switch to Segment #2
    ASM ROM.SwitchSeg 2

 

If you know the size of the data or code you need, you could use the "ROM.AutoSeg" macro, which will pick the first segment available that has at least that capacity:

' Find a segment that can fit 2000 words
    ROM.AutoSeg 2000

 

It will also help you figure out how to allocate your segments by illustrating their current usage, like this:

IntyBASIC SDK Compiler Build Script (intybuild)
   Created by:   DZ-Jay
   Version:      1.2.3
   Last updated: 10/09/2021

Compiling...
Assembling...
 
ROM USAGE:
    =======================================================
        Segment        Size       Used      Available
    =======================================================
    ROM Seg #0           8K         629      7563 words
    ROM Seg #1           8K        2170      6022 words
    ROM Seg #2          16K       16315         5 words
    ROM Seg #3           4K           0      3840 words
    ROM Seg #4           4K           0      3840 words
    ROM Seg #5           2K          14      2034 words
    =======================================================
             TOTAL:     42K       19128     23304 words
    =======================================================
 ERROR SUMMARY - ERRORS DETECTED 0
               -  WARNINGS       0

 

When a segment overflows, you will obviously get an error and assemblage will fail, but the "Available" column will tell you which segment overflowed and by how much.  For example:
 

IntyBASIC SDK Compiler Build Script (intybuild)
   Created by:   DZ-Jay
   Version:      1.2.3
   Last updated: 10/09/2021

Compiling...
Assembling...
 
ROM USAGE:
    =======================================================
        Segment        Size       Used      Available
    =======================================================
    ROM Seg #0           8K       16944     -8752 words
    ROM Seg #1           8K        2170      6022 words
    ROM Seg #2          16K           0     16320 words
    ROM Seg #3           4K           0      3840 words
    ROM Seg #4           4K           0      3840 words
    ROM Seg #5           2K          14      2034 words
    =======================================================
             TOTAL:     42K       19128     23304 words
    =======================================================
 ERROR SUMMARY - ERRORS DETECTED 1
               -  WARNINGS       0

ERROR: AS1600 assemblage failed.

 

In the above example, I can see that Segment #0 has overflown by 8,752 words.  I can then inspect my code to see which parts are in Segment #0 and split it further into other segments.

 

This becomes a lot easier to do if you split your code into multiple modules, like for data or subroutines.  Then you can do something like this:

' Include data modules
  ASM ROM.SwitchSeg 1
  INCLUDE "sprites.bas"
  INCLUDE "music.bas"

  ASM ROM.SwitchSeg 2
  INCLUDE "velocity.bas"

' Include subroutine modules
  ASM ROM.SwitchSeg 3
  INCLUDE "collision-lib.bas"
  INCLUDE "input-lib.bas"

 

Let me know if you wish to use this feature now, and I'll send you a PM with the details and instructions.

 

      -dZ.

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

30 minutes ago, Zendocon said:

A couple more points:

 

You'll know if you overflow past the end of $F000, because as1600 will suddenly throw a large number of errors.

 

It wasn't mentioned in the original Game Programming book, but try to stay out of the $E000 range, because that will jeopardize ECS compatibility.  LTO Flash can use a little bankswitching to work around that issue, if you flag your ROM as ECS incompatible (that's what I ended up doing for Blix & Chocolate Mine).

That's a good point.  For ROMs that are going to be played on the emulator or on an LTO Flash, that's mostly a non-issue, since both JLP boards (like the LTO Flash) and the jzIntv emulator support bank-switching.  For games to be distributed in non-JLP cartridges, this needs to be considered.

 

    -dZ.

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

this is a great topic and vey helpful to me as I just bumped up against this issue for the first time, too.

 

This adds a lot more details on how to handle the issue.

 

great stuff, thanks everyone for the tips and explanations.  I would never be able to make a game without all the help I get here. I'm so dumb I cant even create a topic in the right subforum these days.  

 

 

Edited by Mik's Arcade
Link to comment
Share on other sites

1 minute ago, Brian's Man Cave said:

I am trying this and its just putting out errors:

 

ASM ORG $a000
include"rags_game_loop.bas"

ASM ORG $c100
include"rags_procedures.bas"

ASM ORG $F000 
include"rags_streets.bas"

Send me the SDK project and I'll take a look at it to see what's wrong.  You can just ZIP up the entire project folder for your game.

 

  -dZ.

Link to comment
Share on other sites

I took a peek at the source code and built it locally and ...

 

Long story short:  Two of the modules are over 8K, so only one can fit in the 16K segment at $C040, and there is no other contiguous block that can fit the other.

 

I've recommended to split the data module into smaller modules, to keep them under 8K each and spread the load around.

 

    -dZ.

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

33 minutes ago, Brian's Man Cave said:

I am trying this and its just putting out errors:

 

ASM ORG $a000
include"rags_game_loop.bas"

ASM ORG $c100
include"rags_procedures.bas"

ASM ORG $F000 
include"rags_streets.bas"

What are the errors?  If IntyBASIC compiles with no errors but as1600 throws a bunch of errors with no explanation, then "rags_streets.bas" is probably overflowing past the end of $F000.

 

Otherwise, everything looks fine so far.

Link to comment
Share on other sites

Recommendations for the absolute novice.

 

1. Remove all the ASM ORG statements from your program.

2. Recompile your program (make sure it doesn't generate errors).

3. Read the generated LST file. (this file is generated by the assembler as1600).

4. Follow the address where each instruction is put (the 4 hexadecimal digits at the left).

5. Notice how each line of your original source code is alongside as comments.

6. All IntyBASIC programs start at $5000, when you find a cross over $7000 you need to insert the first ASM ORG statement (just before PROCEDURE or before a block of data). I would suggest ASM ORG $A000.

7. Recompile your program.

8. Read again the generated LST file.

9. Follow the address and watch how your program is assembled at $A000 at the point where you inserted ASM ORG $A000.

10. Check if something spills over $c000. At this point I would suggest ASM ORG $C100.

 

Other segments available for use are $2100-$2fff (ASM ORG $2100) and $4810-$4fff (ASM ORG $4810).

 

Symptons of crossing over $7000: The screen becomes purple and your game doesn't boot. (This is because the EXEC BIOS thinks there is a cartridge at $7000, it checks this first before checking $5000).

 

Notice you need to check for as1600 total number of errors, because if you exceed $ffff then as1600 will throw an error for >each< assembler instruction exceeding the address space.

 

Finally, you need to verify each time that you don't have exceeded these segments, but you don't need to read each time your whole program. This is as easy as listing the .CFG file (also generated by the assembler).

 

Edited by nanochess
  • Like 3
Link to comment
Share on other sites

13 hours ago, nanochess said:

Recommendations for the absolute novice.

 

1. Remove all the ASM ORG statements from your program.

2. Recompile your program (make sure it doesn't generate errors).

3. Read the generated LST file. (this file is generated by the assembler as1600).

4. Follow the address where each instruction is put (the 4 hexadecimal digits at the left).

5. Notice how each line of your original source code is alongside as comments.

6. All IntyBASIC programs start at $5000, when you find a cross over $7000 you need to insert the first ASM ORG statement (just before PROCEDURE or before a block of data). I would suggest ASM ORG $A000.

7. Recompile your program.

8. Read again the generated LST file.

9. Follow the address and watch how your program is assembled at $A000 at the point where you inserted ASM ORG $A000.

10. Check if something spills over $c000. At this point I would suggest ASM ORG $C100.

 

Other segments available for use are $2100-$2fff (ASM ORG $2100) and $4810-$4fff (ASM ORG $4810).

 

Symptons of crossing over $7000: The screen becomes purple and your game doesn't boot. (This is because the EXEC BIOS thinks there is a cartridge at $7000, it checks this first before checking $5000).

 

Notice you need to check for as1600 total number of errors, because if you exceed $ffff then as1600 will throw an error for >each< assembler instruction exceeding the address space.

 

Finally, you need to verify each time that you don't have exceeded these segments, but you don't need to read each time your whole program. This is as easy as listing the .CFG file (also generated by the assembler).

 

I think this is really too complicated.  I'm sure people can figure it out, but they have bigger fish to fry, what with getting up to speed with IntyBASIC and learning the ropes of making a video game -- there has to be a better way.

 

I think a post-processing step (like intySmap, but after assemblage) could help to analyze errors in the assembly listing file and try to provide details related to ROM overruns.  As you've suggested, all the information is there, and those are machine-readable files, so it should be possible to help the absolute novice a bit more.

 

I'll try to get something done for the next version of the SDK, but there are much smarter people than me in this forum.  The "ROM Segment" feature I added to the SDK is one possible solution, but it forces people into using a specific memory map, which may or may not be desirable.  It also requires small changes to the epilogue and prologue to incorporate it.

 

In the absence of a linker, I'm sure something that makes ROM segment overflow more clear and guides programmers on how to allocate their code, would be of great help to many.  :)

 

    -dZ.

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

49 minutes ago, cmadruga said:

Please keep us bank switching aficionados in mind ;-)

Managing segments AND pages simultaneously feels like solving a jigsaw at times.

 

The solution I'm planning to implement for the IntyBASIC SDK would give the choice of different memory maps that support or not JLP with bank-switching.  For the memory maps that support bank-switching, one option could be to support "dynamic segments," in which instead of just selecting a ROM segment, you select a ROM segment and a page (from 0 to 15).

 

My idea is to give a simple, no-frills option to those starting, without encumbering them with any further complications of banks and switching; while also giving options to those who want or need that power.

 

The ultimate "no-frills" option would be to let the programmer do his or her thing without intervention (Pure! Ultimate! Powah!), and providing a post-build tool that provides information based on the output LISTING file that can alert to issues and guide decisions to address them.  The SDK already runs IntySMap as part of its build process, so such a ROM-check tool can be added afterwards.

 

I'll see if I can come up with something for this ROM-check tool, but it would be ideal if someone with better skills than me would take this on.  I don't have any programming tools around to build Windows/Mac/Linux programs, and even if I did, it's been at least a decade since the last time I used anything other Perl, Python, or as1600.  This is why the SDK uses Perl scripts (Mac) or COMMAND.COM batch scripts (Windows).  :dunce:

 

    -dZ.

Edited by DZ-Jay
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...