Jump to content
IGNORED

A Couple Useful Tools


Cybearg

Recommended Posts

Since I'm lazy, I made myself a little program called SpriteAid for configuring IntyBasic sprite options and another, bigger program called IntyMapper to allow me to visually draw out screens for IntyBasic.

 

I'm sure both programs are a bit buggy as I'm a very inexperienced programmer, but hopefully they will be useful to someone besides just myself. Enjoy!

IntyMapper.zip

SpriteAid.zip

  • Like 7
Link to comment
Share on other sites

Hurray for lazy programmers and their fantastic tools!

 

You know what also works for me, procrastination: when I convince myself that I must finish a project, such as a new game, there is no force in the inverse--Natural or Devine--that will move me to do it. I'll do every other thing within my grasp to avoid that single task including, but not limited to, new tools and a new programming framework for Intellivision games.

 

Once I finish the framework, it's just a matter of convincing myself that another unrelated task is just as important. Perhaps then I'll manage to finish my next game. ;)

  • Like 2
Link to comment
Share on other sites

Well if you have any cool tools of your own, I'd love to see 'em shared! I was surprised that there wasn't already a map editing tool for Intellivision, unless one DOES exist and I just didn't hear about it.

Unfortunately, my tools tend to be one-offs or specialized scripts for my games. The framework, however, is real and generalized.

 

P-Machinery v2.0 aims to be a fully-featured, event-driven, object-oriented game development framework. It has a rather sophisticated high-level interface built entirely out of macros that abstracts the inner workings of the framework, which in turn abstracts the hardware and its idiosyncrasies.

 

Many parts are already completed, but it won't really be useful for games until I implement the sprite kernel sub-system. As of now, the completed parts are:

  • Macro core library (i.e., the framework to build the framework)
  • High-level and actually useful error reporting framework for the entire macro library
  • ROM segment manager
  • RAM allocation manager ("static" virtual memory)
  • Support for "RAM Segments" and game-state module-scoped variable allocation.
  • Support for assembly-time sophisticated abstract data types, such as Structures, Records, Enumerations, String Lists, Bit-Fields/Maps, etc.
  • Core game engine state machine
  • Module-based game state definition sub-system
  • Flexible and extensible, "plug-in" based, event-driven Hand-Controller/Keyboard input kernel
  • 32-bit Pseudo-Random Number Generator
  • System Event and User Task queues
  • System clock and timer infrastructure with automatic calibration of PAL and NTSC frame-rates
  • One-shot and repeating timed events sub-system
  • Detailed ROM/RAM usage statistics report at assembly-time, by segment or module.

The framework is not a compiler nor a high-level assembler, but it aims to provide many high-level abstractions to assembly games.

 

It's hard to convey how it works, and how much effort and cognitive strain it tries to save, so here's an example of my test driver for the timer sub-system.

 

;;==========================================================================;;
;; Title:       P-Machinery Test Driver                                     ;;
;; By:          DZ-Jay                                                      ;;
;; Description: A simple test driver of the P-Machinery game engine.        ;;
;;                                                                          ;;
;;==========================================================================;;
;; Copyright © 2014, James Pujals (DZ-Jay), <dz-game@techunlimited.net>.    ;;
;;==========================================================================;;

;; ======================================================================== ;;
;; PROGRAM SET-UP                                                           ;;
;; ======================================================================== ;;

                ; Loads core libraries.
                INCLUDE "macro/pm_prog.mac"

                ; Starts a P-Machinery program.
                ; It initializes the ROM header, sets up the framework
                ; environment, initializes the ROM and RAM "global"
                ; segments, sets up the default title screen, and prepares
                ; the boot sequence.
                PROG.Start "P-MACH TEST", "DZ-Jay", 2014

                    ; Import timer test module
                    LIB.Include  "tests/test-timer.asm"

                    ; Tell P-Machinery which state to engage on start-up
                    STATE.SetInitial(Test, Wait)

                ; End a P-Machinery program.  It closes all open structures,
                ; performs general accounting of environment, calculates
                ; memory usage, and does any other sanity checks of
                ; dependencies.
                PROG.End

;; ======================================================================== ;;
;;  END OF LINE.                                                            ;;
;; ======================================================================== ;;

And here is the "test-timer.asm" module:

 

;;==========================================================================;;
;; Copyright © 2014, James Pujals (DZ-Jay), <dz-game@techunlimited.net>.    ;;
;;==========================================================================;;

        ; Tell P-Machinery of your intention to use the general
        ; "Two-Player" (Double) hand-controller input handler.
        IO.UseDecoder(GeneralDouble)

        ; Define a new state: Test
        STATE.Start Test

;; ======================================================================== ;;
;;  INPUT_DISP - Defines dispatch table for input event handlers.           ;;
;;      Input handler dispatcher:                                           ;;
;;          KeyUp       1 DECLE                                             ;;
;;          DiscUp      1 DECLE                                             ;;
;;          ActionUp    1 DECLE                                             ;;
;;          KeyDown     1 DECLE                                             ;;
;;          DiscDown    1 DECLE                                             ;;
;;          ActionDown  1 DECLE                                             ;;
;; ======================================================================== ;;
INPUT_DISP      PROC
                DECLE   PM.NULL
                DECLE   PM.NULL
                DECLE   PM.NULL
                DECLE   PM.NULL
                DECLE   @@ActDown       ; Only handle Action-Down Event
                DECLE   PM.NULL

                ; --------------------------------------
                ; Process Action Button event:
                ;   When the bottom-right button is
                ;   pressed on any of the controllers,
                ;   do the following:
                ;       Left controller:  set timer
                ;       Right controller: clear timer
                ; --------------------------------------
@@ActDown:      UNPKL   R3,     R1                      ; R1: Button id; R3: Controller port id

                CMPI    #HAND.ACTION.BottomRight, R1    ; \_ Was bottom-right button pushed
                BNEQ    @@__skip                        ; /

                CMPI    #HAND.PORT.Player1,     R3      ; \_ For player1: set timer
                BEQ     @@SetTimer                      ; /

                CMPI    #HAND.PORT.Player2,     R3      ; \_ For player2: clear timer
                BEQ     @@ClearTimer                    ; /

@@__skip:       JR      R5

                ; --------------------------------------
                ; Set timers
                ; --------------------------------------
@@SetTimer:     BEGIN

                ; StartRepeatEvent():
                ;   Starts a repeating event immediately.
                ;   Arguments:
                ;       timer - The timer number to use (0..PM.TIMER_COUNT).
                ;       rate  - The repeating rate frequency or period.
                ;       units - The units of the repeating rate frequency or period.
                ;             - Available values are:
                ;                   Jiffy   Internal clock units.
                ;                   Fps     Frames per second.
                ;                   kFps    Thousand frames per second.
                ;                   Hz      Hertz (same as Fps).
                ;                   kHz     Kilo-Hertz (same as kFps).
                ;                   Sec     Seconds.
                ;                   mSec    Milli-seconds.
                ;       task  - A pointer to a task to execute when the event triggers.
                ;       data  - An optional data argument to pass to the task.
                TIMER.StartRepeatEvent(0, 1, Sec, @@EventOn,  PM.NULL)

                ; SetRepeatEvent():
                ;   Schedules a repeating event to start after a given delay.
                ;   Arguments:
                ;       timer - The timer number to use (0..PM.TIMER_COUNT).
                ;       delay - An initial delay before the first event.
                ;       rate  - The repeating rate frequency or period.
                ;       units - The units of the repeating rate frequency or period.
                ;             - Available values are:
                ;                   Jiffy   Internal clock units.
                ;                   Fps     Frames per second.
                ;                   kFps    Thousand frames per second.
                ;                   Hz      Hertz (same as Fps).
                ;                   kHz     Kilo-Hertz (same as kFps).
                ;                   Sec     Seconds.
                ;                   mSec    Milli-seconds.
                ;       task  - A pointer to a task to execute when the event triggers.
                ;       data  - An optional data argument to pass to the task.
                TIMER.SetRepeatEvent  (1, 400, 1000, mSec, @@EventOff, PM.NULL)

                RETURN

                ; --------------------------------------
                ; Clear timers
                ; --------------------------------------
@@ClearTimer:   BEGIN

                ; CancelEvent():
                ;   Cancels an active timed event.
                ;   Arguments:
                ;       timer - The timer number to use (0..PM.TIMER_COUNT).
                TIMER.CancelEvent(0)
                TIMER.CancelEvent(1)

                RETURN

                ; --------------------------------------
                ; EVENT: On (Draw character on the screen)
                ; --------------------------------------
@@EventOn:      BEGIN
                MVII    #BACKTAB.Base + 9,      R2
                MVII    #($0010 SHL 3) OR CS.Red, R1
                MVO@    R1,     R2
                RETURN

                ; --------------------------------------
                ; EVENT: Off (Delete character from the screen)
                ; --------------------------------------
@@EventOff:     BEGIN
                MVII    #BACKTAB.Base + 9,      R2
                CLRR    R1
                MVO@    R1,     R2
                RETURN
                ENDP

                ; AddSub()
                ;   Define sub-states for a given state
                ;   Arguments:
                ;       sub   - The name of the new sub-state.
                ;       ctrl  - The name of a registered controller decoder routine.
                ;       disp  - The address of the event dispatch record.
                ;       opts  - A word defining the option flags for the state.
                STATE.AddSub(Wait, GeneralDouble, INPUT_DISP, PM.NULL)

        ; End state definition
        STATE.End
  • Like 1
Link to comment
Share on other sites

By the way, most of those function-looking macros automatically detect between calling with a register or immediate values, and even optimize for the specific registers accepted by the underlying procedures. This is framework-wide, and enforced with assertions that provide useful error messages when the Right Thing cannot be unambiguously discerned.

 

Calling conventions are standardized across procedures, so its easy to chain them or integrate them with the task queue and timed events sub-systems.

 

Also notice that most code is declarative and not procedural. You declare your game states, define event handlers, and let the game engine tie them together and do its thing.

 

Like I said, it's a work in progress and still has many more parts to go before it becomes actually useful for making games. However, once it reaches critical mass, I intend to release it openly and provide full documentation and support, including plenty of examples.

 

dZ.

  • Like 2
Link to comment
Share on other sites

I can't really say I understand what it's for or how it works, but awesome! It sounds like a sort of IntyBasic, except with a custom-built, object-oriented language.

Well, it's still assembly language. The higher-level stuff is in the programming model rather than in the syntax (although there's tons of macro magic going on to elevate the syntax as well).

 

In any case, I apologize for hijacking your read. I'll try to take a look at your tools tonight and offer feedback if I have it.

Link to comment
Share on other sites

I should have done this in the first post, but here are some screenshots and examples.

SpriteAid
post-34988-0-52477300-1413320012_thumb.png


IntyMapper

Color Stack Mode
post-34988-0-62775800-1413320027_thumb.png
post-34988-0-82248800-1413320120_thumb.png
sunny_day.csv.txt

Foreground-Background Mode
post-34988-0-35336400-1413320051_thumb.pngpost-34988-0-06394900-1413320052_thumb.png

post-34988-0-44225400-1413320498_thumb.pngpost-34988-0-64582300-1413320809_thumb.png

post-34988-0-70919000-1413320124_thumb.png
greenhead_games.csv.txt

Peek at the Green Games output:

screen_0:
data $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
data $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000

data $0000,$0000,$0000,$0CB0,$0400,$0400,$0400,$0400,$0400,$0400
data $0400,$0400,$0400,$0400,$0400,$0400,$08AA,$0000,$0000,$0000

data $0000,$0000,$0000,$0400,$0400,$0538,$0590,$0528,$0528,$0570
data $0468,$0540,$0528,$0508,$0520,$0400,$0400,$0000,$0000,$0000

...

screen_1:
data $3ABC,$3B3C,$3B3C,$3B3C,$3B3C,$3B3C,$3B3C,$3B3C,$3B3C,$3B3C
data $3B3C,$3B3C,$3B3C,$3B3C,$3B3C,$3AB4,$3200,$3200,$3200,$3200

data $3200,$3ABA,$3AB1,$3ABA,$3AB1,$3ABA,$3AB1,$3ABA,$3AB1,$3ABA
data $3AB1,$3ABA,$3AB1,$3ABA,$3AB1,$3200,$3200,$3200,$3200,$3200

...

screen_2:
data $3200,$3200,$3200,$3200,$3200,$3200,$3200,$3200,$3200,$3200
data $3200,$3200,$3200,$3200,$3200,$3200,$3200,$3200,$3200,$3200
 
data $3200,$3200,$3200,$3200,$3200,$3200,$3200,$3200,$3200,$3200
data $3200,$3200,$3AA4,$3B3C,$3B3C,$3B3C,$3B3C,$3B3C,$2050,$3B3C
 
data $3200,$3200,$3200,$3200,$3200,$3200,$3200,$3200,$3200,$3200
data $3200,$3200,$3ABC,$3B3C,$3B3C,$3B3C,$3B3C,$3B3C,$3B3C,$3B3C

...


greenhead_games_map.txt

 

I'm sure someone who knows what they're doing can come up with much better stuff than my samples, here.

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

OK, played with it some - very nice for an "inexperienced programmer". How did you get the GRAM tiles in there, for those last pics? Is that what the import .csv does?

 

This is actually pretty feature-complete for what you're aiming for, but a couple of things would be keen. 1. a way to start over (new, clear, whatever) without restarting the app. 2. A grid showing the 8x8 cards. The first might be fairly easy, the second I'm not sure.

 

I know I'll be messing around with this in the near future.

Link to comment
Share on other sites

OMG I want to have a crack at that tile editor! Do you draw with it and it figures out the code?

If you mean drawing with tiles and it spits out the formatted screen data, then yup!

 

OK, played with it some - very nice for an "inexperienced programmer". How did you get the GRAM tiles in there, for those last pics? Is that what the import .csv does?

 

This is actually pretty feature-complete for what you're aiming for, but a couple of things would be keen. 1. a way to start over (new, clear, whatever) without restarting the app. 2. A grid showing the 8x8 cards. The first might be fairly easy, the second I'm not sure.

 

I know I'll be messing around with this in the near future.

If you have the STIC set to one of the GRAM options (whether stack or fgbg) a "Load" button appears. It will let you select your own tileset to replace the default GRAM tileset. It's looking for 16 x 4 16-pixel square tiles (so 256 x 64). Most likely you'll want to actually create a 128x32 tileset using 8x8 tiles, then uprez it to 16x16 tiles. That's what I did in those examples and, yes, that's what those sample images do.

 

The .csv files are created with the "save" button. They're just the raw numbers for the program to read using the "load" button. If you want the values formatted for IntyBasic, use the "export" button.

 

Noted on the clear button--that should be easy to implement. What do you mean by the tile thing, though? Just that you want to have an option for clearly seeing a grid between the on-screen tiles?

Link to comment
Share on other sites

Noted on the clear button--that should be easy to implement. What do you mean by the tile thing, though? Just that you want to have an option for clearly seeing a grid between the on-screen tiles?

 

Basically yeah. Given that everything is designed around the card grid, in my brain I find this stuff easier to work with when I can see the actual grid pattern superimposed on things. I don't know how useful it actually would be because it's not like we're trying to align things to it - the program already does that. I was thinking about cases where I'm visualizing where I'd put MOBs and whatnot to pretty things up. Or if I wanted to add some more GRAM cards but wanted to pre-visualize where'd they'd fit in, or what have you.

 

Like I said, not sure how useful it would even be. Certainly a togglable item or it could be annoying.

Link to comment
Share on other sites

After expressing my concerns about ROM space, I have added a COMPRESS option to export compressed map data, like so:

 

 

REM 69 unique cards

card_table:
data $0000, $01E1, $0079, $05A1, $05A9, $0679, $0601, $063E, $0609, $43A4
data $42FC, $43AC, $05B9, $02F8, $0626, $00D6, $0076, $43B4, $43BC, $068E
...
data $0309, $0321, $02F9, $0091, $0461, $0419, $0351, $0399, $0319
REM 1680 bytes in map
screen_0:
data $00,$00,$00,$00,$01,$00,$00,$00,$00,$02
data $01,$03,$04,$05,$02,$01,$02,$01,$00,$00
...
screen_1:
data $06,$07,$08,$05,$00,$00,$00,$00,$00,$00
data $00,$00,$00,$00,$00,$00,$00,$00,$00,$00
... etc.

 

I also applied a number of bug fixes, so it's worth getting this version.

IntyMapper_1.2.zip

 

post-34988-0-65911800-1413576089_thumb.png

Edited by Cybearg
  • Like 1
Link to comment
Share on other sites

How are you compressing data?

While export directly exports the map's values to separate tables with one word per tile, compress instead creates a table of unique card values, then all the map tables use 1 byte to reference the unique values in the card table, allowing each screen to be expressed with 240 bytes instead of 240 words, nearly cutting map size in half. It's nanochess's suggestion for how to compress map data in the thread I linked to.

 

I tried to compare the 2 outputs - but the new program won't export OR compress. It gives me the "save as" dialog, but when I click save it doesn't actually create the files. No idea what I could be doing wrong.

That's... concerning. I didn't change the export functionality at all. I just downloaded the .zip and tried it again to make sure, but I couldn't replicate your problem--it saved fine and I don't see anything in the code that would be stopping it from saving unless you hit cancel or something.

 

Are you getting any kind of error, or do you save and literally nothing happens--no new files whatsoever? Does the program continue to function as normal? Can you walk me through the process you took?

 

Is anyone else having a similar problem?

Edited by Cybearg
Link to comment
Share on other sites

Are you getting any kind of error, or do you save and literally nothing happens--no new files whatsoever? Does the program continue to function as normal? Can you walk me through the process you took?

 

To be honest, I never actually tired saving before. So it could be an issue I've always had.

 

And I figured out partly what's going on. If I try to save, export or compress into the directory IntyMapper is in, it won't work. Just returns to the app like nothing happened. But if I save anywhere else, it works fine. So there ya go.

Link to comment
Share on other sites

And I figured out partly what's going on. If I try to save, export or compress into the directory IntyMapper is in, it won't work. Just returns to the app like nothing happened. But if I save anywhere else, it works fine. So there ya go.

Confirmed. I have the same problem. Unfortunately, it's nothing that I can fix as it is apparently a problem with the GameMaker functions that I call to open/save files. Sorry for the inconvenience, but at least we've got it figured out. :)

 

I also noticed a couple inconsistencies in IntyMapper's GROM tileset compared to the Intellivision's. 1.2.1 corrects this inconsistency.

 

IntyMapper_1.2.1.zip

Link to comment
Share on other sites

Really silly behaviour. It won't let me save in a subdir of it, either. Oh well, it's the tool's fault.

 

Here's one for ya - when I save a map, and then open it later, it doesn't retain the color stack details. Everything else is saved, including the actual tiles where I advance the stack, but the stack itself is all black. So I had to remember what I set each entry to and then magically a lot of stuff showed up again :)

Link to comment
Share on other sites

Here's one for ya - when I save a map, and then open it later, it doesn't retain the color stack details. Everything else is saved, including the actual tiles where I advance the stack, but the stack itself is all black. So I had to remember what I set each entry to and then magically a lot of stuff showed up again :)

True, I don't currently save that. I figured I'd wait until someone asked for it, so I'll implement saving the color stack sometime soon. :)
Link to comment
Share on other sites

And here you go. New save files will include stack colors and will replace existing stack colors when a save file with stack colors is opened.

 

I experimented with also auto-opening custom GRAM images, but I didn't have much luck getting it to work, plus it would probably lead to crash central if map files were shared between people without identical file structures, so it's probably best to keep that as a load-when-you-need-it sort of thing.

 

IntyMapper-1.2.2.zip

Link to comment
Share on other sites

  • 2 weeks later...

Found a ... well I'm not sure if it's a "bug" per se, but it's confusing.

 

When you save the color stack info at the top of a file, it uses hex values. However, IntyBASIC requires you to use full decimal. ie: say you use orange - IntyMapper outputs 0,A,0,0 whereas IntyBASIC requires you to use MODE 0,10,0,0,0. Or 0,$A,0,0 I suppose would work as well.

 

Small thing that had me scratching my head for a few mins this morning.

Edited by freeweed
  • Like 1
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...