Jump to content
  • 0
Hugo4IT

How to display sprites?

Question

Hello people,

I have been doing some trial&error lately on how to get the Commander X16 into graphics mode and displaying sprites.
Currently, my code is this and it outputs this. I use the ACME Cross Compiler if thats any special. I have tried to find it out myself by looking at the documentation but i haven't been able to make it work.
I have also tried looking at the source code of other games but most of the games with sprites are made in BASIC (I want to make it in Assembly) or aren't open source.
I have also searched online and searched on this forum but could not find anything regarding displaying sprites in assembly

 

 

Edited by Hugo4IT

Share this post


Link to post
Share on other sites

Recommended Posts

  • 0
2 minutes ago, Hugo4IT said:
.include "x16.inc"
   
  .org $080D
  .segment "STARTUP"
  .segment "INIT"
  .segment "ONCE"
 

.segment "CODE"
 

what do these lines do ^ because i have never heard of a .segment?

That is required by the ca65 assembler. Basically, you need to put your executable code in the "CODE" segment. The other segments are required by the default X16 configuration, but you don't actually have to put anything there. You can use these segments to place different instructions and data in different parts of memory, rather than just all together. There are a whole host of different things you can do with ca65, and you can check out this rabbit hole to explore more: https://www.cc65.org/doc/ca65.html

  • Thanks 1

Share this post


Link to post
Share on other sites
  • 0

SlithyMatt's game is a good example of how to use sprites in general and how to take full advantage of the VERA.  The X16 kernal also supplies the GRAPH API that you're using in your code, but that's mostly a utility for doing simple drawing operations, such as drawing lines, shapes, images, or text, without having to worry about setting up layers or other underlying stuff. 

In case you're curious about what was wrong with your current code, I don't think you need to reinitialize GRAPH with GRAPH_init.  I believe that's only if you want to switch the GRAPH API to point to a different framework than the default.  You seem to also be missing switching to screen 128 mode, which you would generally do first, so you'd add something like:

Quote

lda #$80

jsr $FF5F

With that, you shouldn't need the code that configures the layers since switching to screen 128 mode does that for you.

A good place to see the usage of the GRAPH API is in the code for the test command in the BASIC source:

https://github.com/commanderx16/x16-rom/blob/master/basic/test.s

Edit: One more thing, you're setting the color to $1C, but there's only 16 colors available in layer 1 with screen 128 mode.

Edited by Ender
  • Thanks 1

Share this post


Link to post
Share on other sites
  • 0
13 hours ago, Ender said:

SlithyMatt's game is a good example of how to use sprites in general and how to take full advantage of the VERA.  The X16 kernal also supplies the GRAPH API that you're using in your code, but that's mostly a utility for doing simple drawing operations, such as drawing lines, shapes, images, or text, without having to worry about setting up layers or other underlying stuff. 

In case you're curious about what was wrong with your current code, I don't think you need to reinitialize GRAPH with GRAPH_init.  I believe that's only if you want to switch the GRAPH API to point to a different framework than the default.  You seem to also be missing switching to screen 128 mode, which you would generally do first, so you'd add something like:

With that, you shouldn't need the code that configures the layers since switching to screen 128 mode does that for you.

A good place to see the usage of the GRAPH API is in the code for the test command in the BASIC source:

https://github.com/commanderx16/x16-rom/blob/master/basic/test.s

Edit: One more thing, you're setting the color to $1C, but there's only 16 colors available in layer 1 with screen 128 mode.

a few questions:

  • What is screen 128 mode?
  • Is there any way to get more color like 256 color mode?

Share this post


Link to post
Share on other sites
  • 0

If you're wondering why I am not marking an awnser:

I first want to get it working myself and make a new file where i start graphics mode and display a sprite and mark that as the awnser so people looking this up online have exactly what they need
OR if someone posts an awnser specifically stating how to display sprites with a tiny bit of code.

Edited by Hugo4IT

Share this post


Link to post
Share on other sites
  • 0
6 hours ago, Hugo4IT said:

a few questions:

  • What is screen 128 mode?
  • Is there any way to get more color like 256 color mode?

Screen 128 mode is basically just a mode where you can use the GRAPH API, and in BASIC, you can use the extended X16 drawing instructions, such as LINE, RECT, etc.  Those BASIC commands use the GRAPH API internally, but you need to be in screen 128 mode to use them.

If your goal is to use sprites, I don't think there's a real way to use them with the GRAPH API, so you don't have to worry about it or screen 128 mode.  I was just explaining those things in case you were wondering how to get your code in the original post to work (clear the screen and fill it with a color).

Share this post


Link to post
Share on other sites
  • 0
22 hours ago, SlithyMatt said:

That is required by the ca65 assembler. Basically, you need to put your executable code in the "CODE" segment. The other segments are required by the default X16 configuration, but you don't actually have to put anything there. You can use these segments to place different instructions and data in different parts of memory, rather than just all together. There are a whole host of different things you can do with ca65, and you can check out this rabbit hole to explore more: https://www.cc65.org/doc/ca65.html

lda #>(VRAM_palette>>4)
ldx #<(VRAM_palette>>4)
ldy #<palette_fn
jsr loadvram

What do those ^ lines to (the < > and >> in particular)
i found that they are low/high byte operators and shifters but what do you use them for in this example?

sorry if im asking to much questions, i just love learning

Also, what do those numbers in brackets mean?  ↓

; A = VRAM address (19:12)
; X = VRAM address (11:4)
; Y = filename address (7:0)

Edited by Hugo4IT

Share this post


Link to post
Share on other sites
  • 0

Lets say that VRAM_palette = $55AA = 0101 0101 1010 1010 in binary.

>>4 means shift right 4 times so VRAM_palette will become 0000 0101 0101 1010 = $055A

Then the < takes the low part of the 16bit value = $5A while > takes the high part = $05

The number in the brackets refer to the bits being used... See the VERA documentation.

https://github.com/commanderx16/x16-docs/blob/master/VERA Programmer's Reference.md

Edited by JimmyDansbo

Share this post


Link to post
Share on other sites
  • 0
17 minutes ago, Hugo4IT said:

What do those ^ lines

Jimmy got the rest, but the caret (^) gets the bank number, or just whatever your number has beyond 16 bits. So, if you have an address constant like this:

VRAM_ADDR = $12345

You can get the 1 with ^, the 23 with > and the 45 with <

 

Share this post


Link to post
Share on other sites
  • 0

Hi Hugo,

I wrote a pretty detailed description of how CX16 graphics work and how to use from BASIC:

Vera Basics: https://www.8bitcoding.com/p/vera-overview.html

How to display Sprite: https://www.8bitcoding.com/p/sprites-in-basic.html

Below is source code of exactly the same program as is described in above tutorial just written in Assembly.

; Assembly Demo of Sprite 
; System: Commander X16
; Version: Emulator R.38+
; Author: Dusan Strakl
; Date: December 2020
; Compiler: CC65
; Build using:  cl65 -t cx16 Sprite1.asm -o SPRITE1.PRG
 
.org $080D
.segment "STARTUP"
.segment "INIT"
.segment "ONCE"
.segment "CODE"
 
; I/O Registers
VERA_LOW    = $9F20
VERA_MID    = $9F21
VERA_HIGH   = $9F22
VERA_DATA0  = $9F23
VERA_CTRL   = $9F25
 
 
;******************************************************************************
main:
 
; Define Sprite
    stz VERA_CTRL
    lda #$10
    sta VERA_HIGH
    lda #$40
    sta VERA_MID
    stz VERA_LOW
 
    ldy #0
:   lda data,Y
    sta VERA_DATA0
    iny 
    bne :-
 
; Initiate Sprite
    lda $9F29
    ora #%01000000
    sta $9F29
 
    lda #$11
    sta VERA_HIGH
    lda #$FC
    sta VERA_MID
    stz VERA_LOW
 
    stz VERA_DATA0
    lda #$82
    sta VERA_DATA0
    stz VERA_DATA0
    stz VERA_DATA0
    stz VERA_DATA0
    stz VERA_DATA0
    lda #%00001100
    sta VERA_DATA0
    lda #%01010000
    sta VERA_DATA0
 
    rts
 
data:   .byte 16,16,16,16,16,160000000000
        .byte 16,38,38,38,38,38,16000000000
        .byte 16,50,50,50,50,38,16000000000
        .byte 16,50,50,50,38,160000000000
        .byte 16,50,50,50,50,38,16000000000
        .byte 16,50,16,16,50,50,38,1600000000
        .byte  0,16,160,16,50,50,38,160000000
        .byte  00000,16,50,50,38,16000000
        .byte  000000,16,50,50,38,1600000
        .byte  0000000,16,50,16000000
        .byte  00000000,160000000
        .byte  0000000000000000
        .byte  0000000000000000
        .byte  0000000000000000
        .byte  0000000000000000
        .byte  0000000000000000

 

Edited by DusanStrakl

Share this post


Link to post
Share on other sites
  • 0
On 12/17/2020 at 5:12 AM, DusanStrakl said:

Hi Hugo,

I wrote a pretty detailed description of how CX16 graphics work and how to use from BASIC:

Vera Basics: https://www.8bitcoding.com/p/vera-overview.html

How to display Sprite: https://www.8bitcoding.com/p/sprites-in-basic.html

Below is source code of exactly the same program as is described in above tutorial just written in Assembly.

; Assembly Demo of Sprite 
; System: Commander X16
; Version: Emulator R.38+
; Author: Dusan Strakl
; Date: December 2020
; Compiler: CC65
; Build using:  cl65 -t cx16 Sprite1.asm -o SPRITE1.PRG
 
.org $080D
.segment "STARTUP"
.segment "INIT"
.segment "ONCE"
.segment "CODE"
 
; I/O Registers
VERA_LOW    = $9F20
VERA_MID    = $9F21
VERA_HIGH   = $9F22
VERA_DATA0  = $9F23
VERA_CTRL   = $9F25
 
 
;******************************************************************************
main:
 
; Define Sprite
    stz VERA_CTRL
    lda #$10
    sta VERA_HIGH
    lda #$40
    sta VERA_MID
    stz VERA_LOW
 
    ldy #0
:   lda data,Y
    sta VERA_DATA0
    iny 
    bne :-
 
; Initiate Sprite
    lda $9F29
    ora #%01000000
    sta $9F29
 
    lda #$11
    sta VERA_HIGH
    lda #$FC
    sta VERA_MID
    stz VERA_LOW
 
    stz VERA_DATA0
    lda #$82
    sta VERA_DATA0
    stz VERA_DATA0
    stz VERA_DATA0
    stz VERA_DATA0
    stz VERA_DATA0
    lda #%00001100
    sta VERA_DATA0
    lda #%01010000
    sta VERA_DATA0
 
    rts
 
data:   .byte 16,16,16,16,16,160000000000
        .byte 16,38,38,38,38,38,16000000000
        .byte 16,50,50,50,50,38,16000000000
        .byte 16,50,50,50,38,160000000000
        .byte 16,50,50,50,50,38,16000000000
        .byte 16,50,16,16,50,50,38,1600000000
        .byte  0,16,160,16,50,50,38,160000000
        .byte  00000,16,50,50,38,16000000
        .byte  000000,16,50,50,38,1600000
        .byte  0000000,16,50,16000000
        .byte  00000000,160000000
        .byte  0000000000000000
        .byte  0000000000000000
        .byte  0000000000000000
        .byte  0000000000000000
        .byte  0000000000000000

 

Thanks so much! this almost solved this question. Can you just explain to me: How do i display a .bin file?
after you have awnsered that question, i'll mark your comment as the awnser

Edited by Hugo4IT

Share this post


Link to post
Share on other sites
  • 0
wow, Hugo is pretty demanding

Dusan, do you have a tutorial on loading .bin files as well?

Otherwise, Hugo, have a look at this, it might help explain the missing part:

https://cx16.dk/png2bin/

Be sure to follow the link to the example: https://gist.github.com/JimmyDansbo/f955378ee4f1087c2c286fcd6956e223 and read the comment I added

Wow, thanks a lot for those comments, i will flag your comment as an awnser!

 

 

 

Share this post


Link to post
Share on other sites
  • 0
4 hours ago, JimmyDansbo said:

wow, Hugo is pretty demanding 😉

Dusan, do you have a tutorial on loading .bin files as well?

Otherwise, Hugo, have a look at this, it might help explain the missing part:

https://cx16.dk/png2bin/

Be sure to follow the link to the example: https://gist.github.com/JimmyDansbo/f955378ee4f1087c2c286fcd6956e223 and read the comment I added

Just one last question: where did you learn all of this?

Share this post


Link to post
Share on other sites
  • 0
2 hours ago, Hugo4IT said:

Just one last question: where did you learn all of this?

The streets, man!

But I also had an academic and professional background in assembly programming and embedded systems development, so picking up 65C02 and the VERA interface was pretty easy. I think others around here have a similar background and were waiting for something like this to come around, just like me.

Share this post


Link to post
Share on other sites
  • 0

I just posted full tutorial around above code here:

https://www.8bitcoding.com/p/sprites-in-assembly-i-setup.html

 

10 hours ago, JimmyDansbo said:

wow, Hugo is pretty demanding 😉

Haha yes. It looks like he will renew support from you 🙂

 

5 hours ago, Hugo4IT said:

Just one last question: where did you learn all of this?

yes, like Matt said. Most of us learned assembly the hard way in the pre-internet days. I also spent most of my career in software development and used too many languages and platforms to list. Now I am in sales for large software services company and still like to code for fun.

Share this post


Link to post
Share on other sites
  • 0
12 hours ago, Hugo4IT said:

Just one last question: where did you learn all of this?

I have been programming as a hobby for many years, but I startet learning assembly for the 6502 about a year ago. I wrote a small description of my own attempts and frustrations.

I have then been following people like SlithyMatt, DusanStrakl and Johan Kårlin, reading their source code and guides as well as reading through both the Commander X16 Programmer's Reference Guide and VERA Programmer's Reference many many times.

I especially have a hard time getting my head around the addressing in VERA when not all bits are used, like in the sprite attributes.

Share this post


Link to post
Share on other sites
  • 0
On 12/19/2020 at 3:10 AM, DusanStrakl said:

I just posted full tutorial around above code here:

https://www.8bitcoding.com/p/sprites-in-assembly-i-setup.html

In the tutorial you point out:

"Please not that in the current version of emulator position 0,0 is in the top left corner of the visible screen. It means that sprite can’t be drawn left or above the visible screen to allow for gradual entry into the visibility. I am assuming this might change in the future and this text will be updated accordingly."

I asked about this in this post https://www.commanderx16.com/forum/index.php?/topic/350-outside-objects-coming-into-view/

So you think they are going to change that behavior?

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

There is actually nothing to wait for : ). Sprites can absolutely be displayed partially on the top or left edge of the screen. Positions are represented by 10 bits (= 0 - 1023) and wrap around which means that 1024 is the same as 0. Let's say you have a sprite that is 32 pixels wide. If you set the horizontal position to 1024 - 16  = 1008, the right half of it will be visible. 

Edited by Johan Kårlin
  • Like 2
  • Thanks 2

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)
On 1/3/2021 at 6:30 AM, SplitSpine said:

In the tutorial you point out:

"Please not that in the current version of emulator position 0,0 is in the top left corner of the visible screen. It means that sprite can’t be drawn left or above the visible screen to allow for gradual entry into the visibility. I am assuming this might change in the future and this text will be updated accordingly."

I asked about this in this post https://www.commanderx16.com/forum/index.php?/topic/350-outside-objects-coming-into-view/

So you think they are going to change that behavior?

That was my understanding, obviously I didn't test the border values enough. I will have to go back and update my tutorial.

On 1/3/2021 at 8:09 AM, Johan Kårlin said:

There is actually nothing to wait for : ). Sprites can absolutely be displayed partially on the top or left edge of the screen. Positions are represented by 10 bits (= 0 - 1023) and wrap around which means that 1024 is the same as 0. Let's say you have a sprite that is 32 pixels wide. If you set the horizontal position to 1024 - 16  = 1008, the right half of it will be visible. 

Thanks for this Johan.

It essentially means that 10 bit number for X and Y position is treated as signed binary where:

11 1111 1111 = -1

11 1111 1110 = -2

11 1111 1101 = -3

etc.

but of course that is not completely consistent across the whole range because for example when we put Sprite at X = 600 which is binary  10 0101 1000 and therefore technically negative number it behaves as unsigned 10 bit value.

Edited by DusanStrakl

Share this post


Link to post
Share on other sites
  • 0
Posted (edited)

Whether sprite positions are signed or unsigned numbers is a matter of preference as I see it. A binary number does not know if it is negative or not, the interpretation is up to you. The problem with seeing it as a  signed number is as you point out that after position 511 comes -512 but your sprite is still visible in the right part of the screen if your resolution is 640x480 which can be confusing. The advantage is that you can push the sprite over the top and left border by just setting the position to -1 which is more intuitive than setting it to 1023.

When making scrolling games you constantly calculate sprite positions. I use 16 bits arithmetics. It works fine because the 6 most significant bits are just ignored by VERA. For example -1 = 65535 = %1111 1111 1111 1111 but it is also -1 if you just look at the 10 least significant bits. In the end I check if the calculated position is between -256 and 512 (requires only checking of the upper byte), if not I disable it. This is to avoid the risk of having sprites disappering to the right and suddenly turn up on the left and vice versa.

Edited by Johan Kårlin
  • Like 2

Share this post


Link to post
Share on other sites
  • 0

(half offtopic: thankfully we don't have to deal with sprite multiplexers anymore as we had on the C64 which only had 8 hardware sprites 🙂)

Share this post


Link to post
Share on other sites
  • 0
44 minutes ago, desertfish said:

(half offtopic: thankfully we don't have to deal with sprite multiplexers anymore as we had on the C64 which only had 8 hardware sprites 🙂)

You say that, but the VERA still has a finite number of work units for drawing sprites per line, so in busy scenes you might just have to pull out that multiplexer logic anyways. To see the limitations I'm talking about, check out my old "race car" demo:

The drawing glitches in the road are because the road itself is created from a series of 64x64 pixel sprites, in part to fake having a third layer of parallax, but also to push the per-line draw limits of the VERA.

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
Answer this question...

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


×
×
  • Create New...

Important Information

Please review our Terms of Use