Jump to content
IGNORED

Colecovision recharged BASIC compiler: CVBasic v0.4.0 (now with compression and MSX support!)


Recommended Posts

43 minutes ago, Jess Ragan said:

Not to say that I'll make games or anything crazy like that, but how does building tile graphics work on the ColecoVision? Instead of each 8x8 tile being two colors like it is on the Spectrum, each horizontal line of an 8x8 tile can be two colors? That's kind of weird.

 

Also, does anyone have a direct link to a PNG converter? There's some software on ColecoVision.dk, but a lot of those links are broken, and the file I did manage to find was in .TAR format. That's a Linux thing... I was looking for Windows software.

I always use Paint .net in Windows. It is free, and you can read easily PNG files and convert them to BMP format.

 

Link to comment
Share on other sites

The command line tool "tmscolor" takes a BMP as input and generates ColecoVision graphics as far as it can. Regarding your question on colour resolution, I believe for character mode it is 1 fg + 1 bg per cell just like ZX (but weird grouping of 8 characters at a time sharing both) but in bitmap mode you get higher colour resolution.

Link to comment
Share on other sites

14 hours ago, Jess Ragan said:

I've got PNG to BMP converters (including Paint Dot Net), but not PNG to ColecoVision converters. Is there a way to convert BMP to a ColecoVision format?

 

I forgot completely that I don't have written a manual for TMSColor. In case of doubt, you can run any of my programs without arguments, and some will show a tiny user's manual, however, nothing like a full-blown note of tips and tricks.

 

First, make sure your image uses the vdp_colors.bmp palette. If you are going to use a photograph, make sure it has good contrast/brightness.

 

Fewest possible tiles (mazes, rooms, and tilemaps)

 

For converting an image using the fewest tiles possible use this:

 

    tmscolor -t128 -b your_image.bmp your_image.bas your_image

 

The -t128 indicates that you are going to use the fewest tiles for this image (it could be a tilemap) and you want to use character 128 onwards (there are 256 available, however, you probably need some for indicators and scores).

 

The -b argument indicates that you are going to generate CVBasic source code.

 

The third argument is your source image, the fourth argument is the target BAS file, and the fifth argument is the label used for the image data (you need a different label for each image on your program).

 

The .BAS generated file contains code to draw the image on the screen. Use the argument -n to remove this code (still it will appear in a comment).

 

High-resolution images

 

High-resolution images are the ones mapped 1-to-1 to VRAM memory. TMSColor can accept any size of the image (the only requirement is that width/height are a multiple of 8 pixels), however, the easiest one to handle is 256x192 pixels (the size of the whole screen)

 

    tmscolor -b your_image.bmp your_image.bas your_image

 

The generated VDP image will use only the available colors or the closest one arithmetically (for pictures you should use the option -p1 or -p2 with dither).

 

However, a 256x192 image will use 12 KB of ROM space. This is a lot of space. Adding the -z switch you'll get Pletter compression in the output (and the space saving is great!)

 

As before, the .BAS generated file contains code to draw the image on the screen. Use the argument -n to remove this code.

 

An excellent example is available on Camelot Knights (see the bitmap camelot_title.bmp and read the camelot_title.bas file to see the code and the command line used to generate it)

 

Sprites

 

Sprites are 16x16 bitmapped things that the Video Display Processor (VDP) can overimpose on the background. You can define 64 of these sprites statically (there is 2K of VRAM allocated for this), or you can create a tileset of sprites that can be redefined on-the-go. However, I'll concentrate in the static 64 sprites' table, where each 16x16 pixels sprite is put together into a 128x128 pixels bitmaps (or any other size containing 64 sprites or less)

 

    tmscolor -s -b your_sprites.bmp your_sprites.bas your_sprites

 

The generated BAS file will have the sprites in the required format for the VDP, along with the code needed to load it.

 

As before, use the argument -n to remove the code, or the argument -z to get Pletter compression.

 

An excellent example is available on Camelot Knights (see the bitmap camelot_sprites.bmp and read the camelot_sprites.bas file to see the code and the command line used to generate it)

 

Pro-tips

 

If you have a great deal of animation, you can run the same command for your sprite, and then define the sprite in real-time, typically just after the WAIT statement.

 

    DEFINE SPRITE 0,1,VARPTR your_sprite_big_table(sprite_frame * 32)

 

This works for a single sprite, for defining two sprites at the same time:

 

    DEFINE SPRITE 0,2,VARPTR your_sprite_big_table(sprite_frame * 64)

 

Notice these two cannot be used with Pletter, as each sprite would have a different length.

 

References:

* https://forums.atariage.com/topic/363252-camelot-knights-game/

 

  • Like 2
Link to comment
Share on other sites

@nanochess  If you were going to make it smooth scroll what would you do?

 

On the sega genesis I could have two sets of tiles: original and partially scrolled.  One frame would have original tiles then on the other partially scrolled.  After that the process would repeat except one layer of tiles farther.

Link to comment
Share on other sites

49 minutes ago, Gemintronic said:

@nanochess  If you were going to make it smooth scroll what would you do?

 

On the sega genesis I could have two sets of tiles: original and partially scrolled.  One frame would have original tiles then on the other partially scrolled.  After that the process would repeat except one layer of tiles farther.

That's a hyper-complicated one. I'll try to explain it easily

 

1. You need your map in two versions: tiled 8x8, and displaced 4 pixels vertically (I don't think you can get any smoother than that)

2. You need to pass both through TMSColor, using tiling mode, and make sure both can coexist in the bitmap definitions (for example, one using 48 tiles and the other 60 tiles, not exceeding 256 tiles minus any tile you need to display letters and digits, etc)

3. The VDP has exactly one extra kilobyte of VRAM unused, where you can build a hidden screen buffer. Lets call this variable 'hidden_screen'.

4. When hidden_screen is zero, you build your level in the $1800-$1aff area using the SCREEN statement (see Camelot Knights)

5. When hidden_screen is one, you build your level in the $1c00-$1eff area using the SCREEN statement (plus 1024 in the target offset).

6. Just after the WAIT statement you switch screens off using this:

[code]

WAIT

REM Switch visual screen

IF hidden_screen = 0 THEN

    hidden_screen = 1

    ASM LD BC,$0602

    ASM CALL WRTVDP

ELSE

    hidden_screen = 0

    ASM LD BC,$0702

    ASM CALL WRTVDP

END IF

[/code]

7. Alternatively if you don't mind tearing, you could build your screen on the display screen without any screen switching code (forgetting steps 4, 5 and 6).

 

Notice you can build the background in two frames (two WAIT statements), switching the screen in the first frame (the first WAIT statement).

 

  • Thanks 1
Link to comment
Share on other sites

Hey there, making a small demo for the SMSPower competition, I think I find some bug..

 

I'm not able to display:

Quote

\

I can see the Tile at 92 ($5C), but when I try to

Quote

PRINT AT 0, "\"

I get the Tile 00.

 

 

I also have problems decreasing a variable (no problem with increasing).

For example:

 

Quote

    #life = #life + 2
    GOSUB update_life

 

Is not a problem but with:

 

Quote

    #life = #life - 2
    GOSUB update_life

 

I get some crazy value.

Link to comment
Share on other sites

Quote

PRINT AT 0, "\"

i do not know that BASIC , did not have the time to test yet....   but i would expect that PRINT AT  would have 3  parameters,  like  PRINT AT  X,Y,"TEXT"  .   Did you not just forget to put the Y value in your statement?

Link to comment
Share on other sites

10 minutes ago, youki said:

i do not know that BASIC , did not have the time to test yet....   but i would expect that PRINT AT  would have 3  parameters,  like  PRINT AT  X,Y,"TEXT"  .   Did you not just forget to put the Y value in your statement?

 

Looking at the manual it, er, looks like the PRINT AT command treats the tiles as a one dimensional array.
 

PRINT [AT [expr]][,]["string"]

     Prints the given string at the current cursor coordinate (or
     selected via the AT value 0 to 767).

 

Using other BASIC dialects I am also used to being able to position the "cursor" using X and Y values.  Something to get used to.

 

  • Like 1
Link to comment
Share on other sites

I guess I should ask if there's any plans to support peripherals like the Super Controller dial, the roller controller, the steering wheel, etc. A homebrew game that uses analog control could have a lot of promise! Bit Corporation made a Breakout clone called Strike It for the ColecoVision, but it loses something without the instant response of a dial.

Link to comment
Share on other sites

9 minutes ago, carlsson said:

Perhaps the compiler has some escape function so you need \\ to get a single backslash.

 

For the variable #life, what is its current value and is the variable signed to support negative values?

You are right for the \\ thank you ;)

 

My #life value start at 100, sometimes the decreasing work sometimes I get value like 980 instead of 98.

 

I don't think there is support for negative values as before 0 you have 65535.

Link to comment
Share on other sites

11 minutes ago, Révo said:

My #life value start at 100, sometimes the decreasing work sometimes I get value like 980 instead of 98.

 

By reading me I can now see the problem^^

 

edit: fixed, probably not the best way, but it's working fine now!

 

Quote

update_life:    PROCEDURE
    PRINT AT 5,"   "
    PRINT AT 0,"Life:"
    PRINT AT 5,#life,""
    END

 

Edited by Révo
Link to comment
Share on other sites

On 3/22/2024 at 6:05 AM, Révo said:

By reading me I can now see the problem^^

 

edit: fixed, probably not the best way, but it's working fine now!

 

 

I would suggest doing:

 

  PRINT AT 5,#life," "

 

Link to comment
Share on other sites

1 hour ago, carlsson said:

I haven't begun using CvBASIC yet. Don't you need <> before the variable to print its value?

This syntax isn't implemented yet. Any use of an expression will output the value. I need to have a zero-padded option and a space-padded option.

  • Like 1
Link to comment
Share on other sites

8 hours ago, Jess Ragan said:

I guess I should ask if there's any plans to support peripherals like the Super Controller dial, the roller controller, the steering wheel, etc. A homebrew game that uses analog control could have a lot of promise! Bit Corporation made a Breakout clone called Strike It for the ColecoVision, but it loses something without the instant response of a dial.

I'll think about it.

Link to comment
Share on other sites

On 3/18/2024 at 7:08 AM, carlsson said:

The command line tool "tmscolor" takes a BMP as input and generates ColecoVision graphics as far as it can. Regarding your question on colour resolution, I believe for character mode it is 1 fg + 1 bg per cell just like ZX (but weird grouping of 8 characters at a time sharing both) but in bitmap mode you get higher colour resolution.

I thought it was 2 colors per 8x1 scanline for each 8x8 tile. I could be wrong though...

Link to comment
Share on other sites

9 minutes ago, ZippyOasys said:

I thought it was 2 colors per 8x1 scanline for each 8x8 tile. I could be wrong though...

CVBasic starts by default in the higher resolution mode of 2 colors per 8x1 scanline. This is significatively better than ZX Spectrum or Intellivision.

 

There is also MODE 2 where each 8 characters share a single foreground/background color.

Link to comment
Share on other sites

8 minutes ago, ZippyOasys said:

I thought it was 2 colors per 8x1 scanline for each 8x8 tile. I could be wrong though...

Correct.

 

On the ColecoVision, the background color is actually one of the 16 available colors, and it's the color that is displayed on the TV screen borders outside the 256x192 display. Any pixel inside the 256x192 display can also be set to that color, and it's the only color that can be set via software to be any of the other 15 colors at any time.

 

So let's say you want to simulate a lightning strike (but not necessarily with any lightning graphics, just a flash of white across the screen with a thunder sound effect) you can do this easily on the ColecoVision by setting your "sky" graphics to use the background color, and then change the background color to white with a single quick command to the video display processor, and then reset the background color back to its original value (black, blue, whatever). Do that a few times while the thunder sound effect is playing, and you've got a nice storm effect.  :)

 

  • Like 1
Link to comment
Share on other sites

But wait, all of you are talking about bitmapped mode now, not character based mode? How do you detect which background character your sprite hits, other than having a list of coordinates?

 

'Cause if the 9918A has a character mode with a colour map that is 32x192, I have been missing out on something.

Edited by carlsson
Link to comment
Share on other sites

1 hour ago, carlsson said:

But wait, all of you are talking about bitmapped mode now, not character based mode? How do you detect which background character your sprite hits, other than having a list of coordinates?

 

'Cause if the 9918A has a character mode with a colour map that is 32x192, I have been missing out on something.

The TMS9918A screen is separated in three areas (the top one, the middle one, and the bottom one). Each of these areas comprises 256 characters of 8x8 pixels that can be defined to any bitmap/color combination (with the 2 colors per line limitation).

 

CVBasic creates a mode that is kind of "easy" to understand. You can define 256 characters, and place this character anywhere on the screen using the pattern area in VRAM ($1800-$1aff addresses).

 

Each time you define a character with CVBasic (using DEFINE CHAR and DEFINE COLOR), the routines in CVBasic duplicate these data to the three areas.

 

For example, defining the character 128 with DEFINE CHAR will copy 8 bits to VRAM $0400-$0407, $0c00-$0c07, and $1400-$1407. The color data will be in $2400-$2407, $2c00-$2c07, and $3400-$3407.

 

How to determine which character you hit with a sprite?
 

row = (y_sprite + 8 ) / 8

col = (x_sprite + 8 ) / 8

IF VPEEK($1800 + row * 32 + col) = character_number THEN REM we hit the expected character number

 

This will be the most used mode (CVBasic MODE 0) because it provides an easy way to handle tiles, and also an easy way to detect hits against tiles.

 

How to relate color and bitmaps? Let's take an example of Viboritas.bas


 

    DEFINE CHAR 128,1,bitmap_data

    DEFINE COLOR 128,1,color_data


    VPOKE $1800,128     ' Draw it in the upper-left corner of the screen.

    WHILE 1: WEND


bitmap_data:

    BITMAP "........"
    BITMAP "XXXXXXX."
    BITMAP "XXXXXXX."
    BITMAP "........"
    BITMAP "XXX.XXXX"
    BITMAP "XXX.XXXX"
    BITMAP "........"
    BITMAP "........"


color_data:

    DATA BYTE $11,$6E,$6E,$6E,$6E,$6E,$6E,$11

 

The periods are taken as zero bits, and the X letters are taken as one bits. That is zero and one.

 

The VDP processor will interpret zero as background color, and one as foreground color.

 

The color data has two nibbles (4-bit hexadecimal digits) for each row of the character. The upper nibble (bits 7-4) is the foreground color, while the lower nibble (bits 3-0) is the background color.

 

So this bitmap in particular will have a top line in black ($11), followed by six lines with red bricks and gray cement ($6e), followed by a final line in black ($11).

 

This color management is a lot better than the Intellivision and Spectrum one, where only two colors could be used for the whole character.

 

 

  • Like 1
Link to comment
Share on other sites

On 3/22/2024 at 3:12 PM, nanochess said:

I would suggest doing:

 

  PRINT AT 5,#life," 

 

I get garbage with that..

 

Btw I'm looking for a way to forbid a variable to go under 0. Is it possible? Example: if my variable is money and I make a shop I don't want to make credit ^^

Link to comment
Share on other sites

5 hours ago, Révo said:

I get garbage with that..

 

Btw I'm looking for a way to forbid a variable to go under 0. Is it possible? Example: if my variable is money and I make a shop I don't want to make credit ^^

Maybe you didn't noticed the single space between quotes to clean when life changes between 100 and 99.

 

For the other case, test the variable before decreasing.

 

IF life > 0 THEN life = life - 1

 

Or also:

 

IF money >= number THEN money = money - number

Link to comment
Share on other sites

I've been playing around with this - I'm pretty excited to see what the next iterations might bring!  Also, I'm looking forward to enhanced documentation concerning sprites/bitmap implementation etc as well as memory maps (and if possible links).  Learning by tweaking your examples, I found that changing just one minor value causes catastrophic problems and I don't know why. I have sooooo many questions... Thanks for this - great job!

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