Jump to content

Recommended Posts

My voice encoder needs a word per channel per frame. Using 3 channels, it takes 6 bytes per frame, i.e. 360 bytes per second of speech.

So I think DZG should safely fit in a plain rom without bank switching.

The current problems are about partitioning the code and the data across the holes in the memory layout, but the whole rom atm is barely 30K

 

 

Then that should be easily addressed using the ORG statement.

Share this post


Link to post
Share on other sites

I think distribution of game over the 42K space is pretty easy.

 

Although somewhat illogical because programmer should monitor the occupation of the memory map over several programs.

 

  1. Compile your program wonkie.bas
  2. Assemble your program (wonkie.asm -> wonkie.bin + wonkie.cfg)
  3. Read the cfg file (the map file)
  4. Draw a rectangle in paper showing addresses $0000-$ffff, draw frontiers showing addresses available for cartridges, mark the CFG file zones in this rectangle.
  5. If any zone crosses over any cartridge frontier, then your program will crash.
  6. Insert ASM ORG $xxxx statements over your code. Repeat step 4 and 5 to check if your program now fits.

 

You'll note that when developing is easiest to keep static data in upper segments because you know the size.

 

The assembler code is hardest to "distribute" over, but you can select your "finished" procedures and keep all them in a segment, getting it to grow as you work.

Share this post


Link to post
Share on other sites

Thanks! I succeeded to assemble and get a .CFG file

Only I cannot get what it means exacly

 

Here it is the one from dfg.bin

[mapping]
$0000 - $08F7 = $2100
$08F8 - $0905 = $4800
$0906 - $1905 = $5000
$1906 - $1DAA = $6000
$1DAB - $2A4C = $A000
$2A4D - $3137 = $C040

[vars]
ecs = 1

But I was expecting code in these areas:

REM -------------------------------------------------------------------------
REM 42K ROM memory map
REM -------------------------------------------------------------------------
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.
REM -------------------------------------------------------------------------

Why my code seems allocated below 0x5000 ?

Share this post


Link to post
Share on other sites

What I have done for my game is create a kind of "pre processor" as a quick-and-dirty .NET console app. It takes the DATA statements, counts the words/commas, and then re-organizes the .BAS file and inserts ASM ORG statements.

 

I think distribution of game over the 42K space is pretty easy.

 

Although somewhat illogical because programmer should monitor the occupation of the memory map over several programs.

 

  1. Compile your program wonkie.bas
  2. Assemble your program (wonkie.asm -> wonkie.bin + wonkie.cfg)
  3. Read the cfg file (the map file)
  4. Draw a rectangle in paper showing addresses $0000-$ffff, draw frontiers showing addresses available for cartridges, mark the CFG file zones in this rectangle.
  5. If any zone crosses over any cartridge frontier, then your program will crash.
  6. Insert ASM ORG $xxxx statements over your code. Repeat step 4 and 5 to check if your program now fits.

 

You'll note that when developing is easiest to keep static data in upper segments because you know the size.

 

The assembler code is hardest to "distribute" over, but you can select your "finished" procedures and keep all them in a segment, getting it to grow as you work.

Share this post


Link to post
Share on other sites

What I have done for my game is create a kind of "pre processor" as a quick-and-dirty .NET console app. It takes the DATA statements, counts the words/commas, and then re-organizes the .BAS file and inserts ASM ORG statements.

Ok, good enough while your important data isn't break into separate pieces.

 

I intend to put someday automatic code ordering but that would involve structuring DATA segments, kind of STARTDATA and ENDDATA.

  • Like 1

Share this post


Link to post
Share on other sites

Ok, good enough while your important data isn't break into separate pieces.

 

I intend to put someday automatic code ordering but that would involve structuring DATA segments, kind of STARTDATA and ENDDATA.

 

But do you really need STARTDATA and ENDDATA when you have a fancy compiler? ;) I do that in my framework because I am (ab)using the pre-processor and there is very limited information that I have on a single pass. Couldn't IntyBASIC just collect all data statements and break them (if necessary) when it finds a naturally occurring boundary, such as a label, opcode, procedure open/close, etc.? For instance:

  ' [A]
  ' ... code ...
  If (foo = 0) Then Goto @@Somewhere
  Return
  ' [-]

  ' [B]
@@table1:
  Data $0000, $0000, $0000, $0000
  Data $0000, $0000, $0000, $0000
  Data $0000, $0000, $0000, $0000
  Data $0000, $0000, $0000, $0000
  ' [-]

  ' [A]
@@Somewhere:
  Call DoSomething
  Return
  ' [-]

  ' [C]
@@table2:
  Data $0000, $0000, $0000, $0000
  Data $0000, $0000, $0000, $0000
  ' [-]

  ' [D]
@@table3:
  Data $0000, $0000, $0000, $0000
  Data $0000, $0000, $0000, $0000
  ' [-]

  ' A
  End
  ' [-]

  ' [E]
  ' ... code ...

The above would result in five distinct blocks that could be rendered, if necessary, in different segments (A, B, C, D, and E). Of course, this wouldn't work if the programmer gets too fancy with overlapping data segments, but there is no reason why IntyBASIC could promote and support a certain way of organizing code.

 

The idea is that procedure code must not cross boundaries, and that contiguous data blocks must fit within a single segment. The former is easy to detect; the latter could be inferred from its usage.

 

Explicit "Begin" and "End" boundaries for Data statements are fine; I just think they are a crutch and that there may be enough information to always Do The Right Thing as long as the programmer conforms to certain simple conventions which are not really onerous.

 

-dZ.

Edited by DZ-Jay
  • Like 1

Share this post


Link to post
Share on other sites

Just make an IDE that keeps a word count of every instruction and automatically shifts things as necessary. In real-time. As you watch.

 

Sadly, this is roughly what my subconscious does as I approach our 42K barrier.

Share this post


Link to post
Share on other sites

The strategy I use for ROM allocation (which I have to employ every time I decide to make a change to my game since it's such a cow!), is as follows:

  • Store procedures in their own module file, or group small related procedures together in the same module. Typically, I make a distinction between "public" procedures (those available to the general program), and "private" procedures (those that serve as utility functions for a specific routine). I tend to group "private" procedures within the same module as the "public" one they support.
  • I further categorize my modules into "code" and "data," and try to keep modules for each category together with their kind. "Code" modules contain utility functions and sub-routines; while "data" modules include look-up tables, graphics data, etc. Thus, my libraries fall neatly into "code segment" and "data segment."
  • I use the INCLUDE directive at the top of my "main" module to include all modules. As mentioned above, I neatly group them by category. So it looks something like this:
;; ======================================================================== ;;
;;  DATA                                                                    ;;
;; ======================================================================== ;;

    ; BACKGROUND DATA
    INCLUDE "data/intro/intro_drops.dat"
    INCLUDE "data/intro/intro_btab.dat"
    INCLUDE "data/scene/scene_gift_btab.dat"
    INCLUDE "data/scene/scene_trap_btab.dat"
    INCLUDE "data/scene/scene_title_btab.dat"
    INCLUDE "data/maze/maze_base.dat"
    INCLUDE "data/maze/maze_info.dat"
    INCLUDE "data/maze/maze_btab.dat"
    INCLUDE "data/maze/maze_vmap.dat"
    INCLUDE "data/menu/menu_btab.dat"

    ; AUTO-PILOT SCRIPTS
    INCLUDE "data/scripts/aps_winner.aps"
    INCLUDE "data/scripts/aps_seq_1.aps"
    INCLUDE "data/scripts/aps_seq_2.aps"
    INCLUDE "data/scripts/aps_seq_3.aps"
    INCLUDE "data/scripts/aps_seq_4.aps"
    INCLUDE "data/scripts/aps_seq_5.aps"
    INCLUDE "data/scripts/aps_seq_6.aps"
    INCLUDE "data/scripts/aps_seq_7.aps"
    INCLUDE "data/scripts/aps_seq_8.aps"
    INCLUDE "data/scripts/aps_elf.aps"

;; ======================================================================== ;;
;;  CODE                                                                    ;;
;; ======================================================================== ;;

    ; UTILITIES
    INCLUDE "util/stic_util.asm"
    INCLUDE "util/ctrl_util.asm"
    INCLUDE "util/sprite_util.asm"
    INCLUDE "util/vmap_util.asm"
    INCLUDE "util/level_util.asm"
    INCLUDE "util/str_util.asm"
    INCLUDE "util/intro_util.asm"
    INCLUDE "util/task_util.asm"
    INCLUDE "util/random_util.asm"

    ; SPRITE MOVEMENT
    INCLUDE "game/move/mv_badtoy.asm"
    INCLUDE "game/move/mv_elf.asm"
    INCLUDE "game/move/mv_ghost.asm"
    INCLUDE "game/move/mv_snowman.asm"
    INCLUDE "game/move/mv_pathfinder.asm"
    INCLUDE "game/move/mv_enemy.asm"

    ; OBJECT COLLISION
    INCLUDE "game/collision/c_items.asm"
    INCLUDE "game/collision/c_candy.asm"
    INCLUDE "game/collision/c_present.asm"
    INCLUDE "game/collision/c_ghost.asm"
    INCLUDE "game/collision/c_snowman.asm"
    INCLUDE "game/collision/c_badtoy.asm"

Now, if the entire program and its data were small enough to fit into the default segment, then I'd be done. However, as the size of the program increases and reaches or exceeds the limits of the default segment, my first strategy is to split it into "Code" and "Data" segments. For this I have a handy macro that just injects the necessary ORG directive to switch segments. My "default" segments are typically the default for "Code" and the largest one available for "Data". Following the CART.MAC memory map, it'll be segments #0 and #2, respectively:

; --------------------------------------
; Memory map for 42K ROM cartridge
; --------------------------------------
;   SEGMENT     RANGE
;      0        $5000 - $6FFF :  8K  <-- Code
;      1        $A000 - $BFFF :  8K
;      2        $C040 - $FFFF : 16K  <-- Data
;      3        $2000 - $2FFF :  4K
;      4        $7100 - $7FFF :  4K
;      5        $4800 - $4FFF :  2K

  • As the code and data modules grow, I start breaking up my module groups and placing them in different segments. I don't give it much thought, just pick the next segment available and split the modules between them.

 

My main module then starts to look like this:

;; ======================================================================== ;;
;;  DATA                                                                    ;;
;; ======================================================================== ;;

    ; BACKGROUND DATA
    ROMSEG  2    ; Use Segment #2

    INCLUDE "data/intro/intro_drops.dat"
    INCLUDE "data/intro/intro_btab.dat"
    INCLUDE "data/scene/scene_gift_btab.dat"
    INCLUDE "data/scene/scene_trap_btab.dat"
    INCLUDE "data/scene/scene_title_btab.dat"
    INCLUDE "data/maze/maze_base.dat"
    INCLUDE "data/maze/maze_info.dat"
    INCLUDE "data/maze/maze_btab.dat"
    INCLUDE "data/maze/maze_vmap.dat"
    INCLUDE "data/menu/menu_btab.dat"

    ; AUTO-PILOT SCRIPTS
    INCLUDE "data/scripts/aps_winner.aps"
    INCLUDE "data/scripts/aps_seq_1.aps"
    INCLUDE "data/scripts/aps_seq_2.aps"
    INCLUDE "data/scripts/aps_seq_3.aps"
    INCLUDE "data/scripts/aps_seq_4.aps"
    INCLUDE "data/scripts/aps_seq_5.aps"
    INCLUDE "data/scripts/aps_seq_6.aps"
    INCLUDE "data/scripts/aps_seq_7.aps"
    INCLUDE "data/scripts/aps_seq_8.aps"
    INCLUDE "data/scripts/aps_elf.aps"

;; ======================================================================== ;;
;;  CODE                                                                    ;;
;; ======================================================================== ;;

    ; UTILITIES
    ROMSEG  0    ; Use Segment #0

    INCLUDE "util/stic_util.asm"
    INCLUDE "util/ctrl_util.asm"
    INCLUDE "util/sprite_util.asm"
    INCLUDE "util/vmap_util.asm"
    INCLUDE "util/level_util.asm"
    INCLUDE "util/str_util.asm"
    INCLUDE "util/intro_util.asm"
    INCLUDE "util/task_util.asm"
    INCLUDE "util/random_util.asm"

  • As I start reaching the limits of the initial segments, I start playing what I call "musical ROM segments" :grin:, which is pretty much just shuffling stuff around until I get a successful build.
  • On a pinch, I could calculate the size of a module and see where I can squeeze it. For data modules, this is rather straightforward since it's a matter of counting the DECLEs (DATA statements). However, this is seldom necessary (at least to me), since I can just easily move the INCLUDE directives around and get it out of the way.
  • Obviously I need to mind any dependencies between modules. However, in practice, this is not really an issue and I mainly try to keep the modules small and concise for this reason.

Eventually, my main module stars to get messy with the ROMSEG directive as I shuffle stuff around, but it is still easy to follow and group all modules, and does not require much thought or cognitive burden. This is an excerpt of my final source, for illustration:

;; ======================================================================== ;;
;;  BACKGROUND DATA                                                         ;;
;; ======================================================================== ;;
    ROMSEG  1
    INCLUDE "data/intro/intro_btab.dat"
    INCLUDE "data/scene/scene_trap_btab.dat"
    INCLUDE "data/scene/scene_gift_btab.dat"

    ROMSEG  4
    INCLUDE "data/intro/intro_drops.dat"

    ROMSEG  0
    INCLUDE "data/scene/scene_title_btab.dat"

    ROMSEG  2
    INCLUDE "data/maze/maze_base.dat"
    INCLUDE "data/maze/maze_info.dat"
    INCLUDE "data/maze/maze_btab.dat"
    INCLUDE "data/maze/maze_vmap.dat"
    INCLUDE "data/menu/menu_btab.dat"

Notice that nothing changes in the actual code, and it's just a matter of shuffling things around until they fall on a spot that builds. It also helps that I have a handy library that prints out the used and available ROM space. I rely on this output as a guide to know where I can stuff things better.


ROM USAGE:
    Used:
      Segment 0  (8K): 8157 words.
      Segment 1  (8K): 7853 words.
      Segment 2 (15K): 16150 words.
      Segment 3  (3K): 3837 words.
      Segment 4  (3K): 3838 words.
      Segment 5  (2K): 2041 words.
                TOTAL: 41876 words.
 
    Available:
      Segment 0  (8K): 35 words.
      Segment 1  (8K): 372 words.
      Segment 2 (15K): 200 words.
      Segment 3  (3K): 3 words.
      Segment 4  (3K): 2 words.
      Segment 5  (2K): 7 words.
                TOTAL: 619 words.

I do the above on Assembly Language, but I don't see why it wouldn't work with IntyBASIC. The segment selecting macros can be implemented using the IntyBASIC user macros, and the compiler already supports the INCLUDE directive. Plus, modularization of code and data tables is always a good practice. :)

 

-dZ.

 

 

EDIT: Updated with relevant illustrative examples.

Edited by DZ-Jay
  • Like 3

Share this post


Link to post
Share on other sites

New version using compiler v1.2.7

New voice player integrated using VARPTR in data

 

Do you have a new binary to share?

 

By the way, not that I expect you to still be waiting for it, but the DZ Gorf screen I was working on is still making its way up through my TO DO queue. I'll get to it soon (along with the new and Mac version of the SDK). Sorry.

 

In the meantime, I'd like to try out your latest bin with voice samples, if possible. :)

 

-dZ.

Share this post


Link to post
Share on other sites

 

Here you can find the last update of a test game born to test intybasic and overgrow out of control

 

update:

 

 

6 kinds of enemies:

 

1 spinning left

2 spinning right

3 linear at random position

4 linear close main ship position

5 zig zag

6 homing (now slower than the main ship)

 

Features:

- Speed tuning, variable speeds for warp, enemies and ship

- Level increases after you pass the 6th enemy type (shown in the top right corner, in yellow)

- You pass to a new swarm after that 5 enemies of a given type have been killed

- Support for score and lives

- Gyrus controls on 16 directions

- Game over sequence

- New animation for the space warp

- Slowed bullets from main ship

- New music (2 channel chords courtesy of First Spear)

- Game over music (courtesy of First Spear)

- Bosses appear after each 6 waves (no interaction ATM, press buttons to cycle them all and enter to skip the boss phase)

- New title screen

- Added 5 sfx and 5 voice samples in the test screen
Now compiled with IntyBasic v1.2.8

 

 

 

Is this the newest rom? I have a previous rom, want to make sure.

 

Is there a way you can post multiple rom versions?

 

:P

Share this post


Link to post
Share on other sites

Nice! How do you record an avi file in the inty emulator?

In the latest jzintv version you press Alt Win+A to start/finish recording (Cmd A in Mac)

 

The generated file can be directly uploaded to Youtube.

Share this post


Link to post
Share on other sites

jzIntv v1.0 under windows seems to not support ALT+A

Where should I find the video file after recording ?

Edited by artrag

Share this post


Link to post
Share on other sites

I believe the video file gets saved to the same directory that jzintv is located. The file you're looking for will be named "avi_0000.avi" and subsequent videos increment the number in the file name.

Share this post


Link to post
Share on other sites

No way to get an AVI file with ALT+A

All I get is a .IMV file when I press some function key (I think F9 or something like that)

But I do not know a way to use IMV files in youtube

 

 

PS

I compiled the game with in v1.2.9 and I uploaded it in the first post. All seems to work fine.

Share this post


Link to post
Share on other sites

Recording of a video in windows is Windows key and A, works in windows 7.

In windows 10 try F8-A

 

Or edit the kbd hack file.

  • Like 1

Share this post


Link to post
Share on other sites

No way to get an AVI file with ALT+A

All I get is a .IMV file when I press some function key (I think F9 or something like that)

But I do not know a way to use IMV files in youtube

 

 

PS

I compiled the game with in v1.2.9 and I uploaded it in the first post. All seems to work fine.

 

 

Recording of a video in windows is Windows key and A, works in windows 7.

In windows 10 try F8-A

 

Or edit the kbd hack file.

 

Sorry, my fault, I've corrected my post, Tarzilla is right.

Share this post


Link to post
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.

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