is there a trick to overlap characters

Basic and Machine Language

Moderator: Moderators

Post Reply
User avatar
aitsch
Vic 20 Amateur
Posts: 51
Joined: Sun Mar 08, 2020 12:54 pm
Location: Germany NS

is there a trick to overlap characters

Post by aitsch »

one of the most frustrating fact for me when i programming games for the vic-20 is that there seems to be no possibility to overlap the grafics (characters).

today i've looked some youtube videos about "new" games for vics and it seems that some titles make these overlaps of their characters.
maybe i am wrong and they didn't use modified characters for their grafics but it was enough for me to place my question here.

so are there known technics for overlapping or other tricks to make the illusuion of it or something to alleviate that one character delete the other?

aitsch
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: is there a trick to overlap characters?

Post by Mike »

The programs in question inevitably work with a pool of user defined characters.

Not only are the movable objects placed in their own small bitmap (which then allows for pixel-wise movement), but background objects and other moving objects are merged into said bitmap. This merge procedure either uses EOR (rather crude), OR (somewhat o.k.ish) or AND NOT mask + EOR pattern, the latter which allows for all four possible single pixel operations: set, reset, invert, leave alone ('transparent').

And no, the VIC-I does not have any extra DMA channels which allow for hardware sprites. You need to do everything in software. And attribute, i.e. colour clash will occur regardless.


Edit: some games 'flicker' two characters on alternate frames. That might 'trick' some people into seeing merged characters, but ultimately, they still flicker.
User avatar
AndyH
Vic 20 Afficionado
Posts: 364
Joined: Thu Jun 17, 2004 5:51 am
Website: https://www.hewco.uk
Location: UK
Occupation: Developer

Re: is there a trick to overlap characters

Post by AndyH »

There is code and other information available on Denial to do a lot of these tricks if you search around. Mike (and others) have also created a program that extends BASIC to generate a full screen bitmap mode using re-definable characters. Good place to start is here: http://sleepingelephant.com/ipw-web/bul ... f=2&t=6338

I've created what I call VBM (Vic Bitmap Mode) using these principals in Turbo Rascal http://turborascal.com that abstract a lot of the technical and set up stuff and provide a number of commands for working on the bitmap, including software sprites. You can do all the display modes mentioned above.

I'm currently looking at add 'local' bitmap mode support to Turbo Rascal, using the method Mike describes above, which has its own advantages and disadvantages.
--
AndyH
HEWCO | Vic 20 blog
User avatar
aitsch
Vic 20 Amateur
Posts: 51
Joined: Sun Mar 08, 2020 12:54 pm
Location: Germany NS

Re: is there a trick to overlap characters

Post by aitsch »

thanks for your answers.
now i know there is no spuky and magic trick outside to overlap characters.
what i already knew is, that there are no hardware sprites in VIC-I chip but thanks for reminding :wink:

i've played around with ORA to overlap a moving character with background grafics, inspired of your ideas.

the soloution works as follows:
- the original characters in the FROM- and TO-positions will be copied to separate addresses and modified there
- the bitwise movement is done invisible in separate addresses (tape buffer), lets say shadow movement.
- after a step is done (8 x 1 pixel wide), ORA matches the current shadow movement with the original background char to the character FROM and character TO adresses.
- when the movement is finished the FROM position will be exchanged with the original character

here is my simple result:

Code: Select all

; ################# addresses ###################
BSOUT=$ffd2
zp=$fd
zp2=$fb
tmp=$02
tmp2=$42
adrCharFrom=$1200
adrCharTo=$1208
adrCharMaster=$1210
adrCharToTmp=$0334
adrCharFromTmp=$033c

; ############### character vars ################
dir=$aa
olddir=$ab
xpos=$ac
ypos=$ad
oldxpos=$ae
oldypos=$af
action=$b0
backgrnd=$b1
oldbackgrnd=$b2


; #################### const ####################
UP=0
DOWN=UP+1
LEFT=UP+2
RIGHT=UP+3
SPEED=$20
CHAR=64

; ######### addresses for shadow movement ########
*=$0334
!byte $00,$00,$00,$00,$00,$00,$00,$00 ; char FromTmp
!byte $00,$00,$00,$00,$00,$00,$00,$00 ; char ToTmp

; #######        working characters        #######

*=$1200
!byte $00,$00,$00,$00,$00,$00,$00,$00 ; char From
!byte $00,$00,$00,$00,$00,$00,$00,$00 ; char To
!byte $18,$4c,$26,$1f,$26,$4c,$18,$00 ; char Master


*=$1001
!byte $0b,$08, $e2,$07, $9e, $20, $34, $38, $36, $34, $00,$00, $00


*=$1300

jsr init

; ##############################################################################
; #                                   Main
; ##############################################################################         
!zone main
  main                                
                                      jsr prepareCharMovement
                                      jsr moveRight
                                      dec stepCount
                                      bpl main
                                      jsr init.restart
                                      jmp main
                                      ;rts

  stepCount
    !byte $00
                                      
; ##############################################################################
; #                     shift character to right dir
; ##############################################################################
!zone prepareCharMovement
  prepareCharMovement                 ; load old original background character and set address
                                      lda backgrnd
                                      sta oldbackgrnd
                                      cmp #32
                                      bmi .asl_0
                                      inc oldBackgndAdr+2   ; inc HiByte
  .asl_0                              asl
                                      asl
                                      asl                   ; *8
                                      sta oldBackgndAdr+1
                                      ; load Character position
                                      ldy xpos
                                      sty oldxpos
                                      ldx ypos
                                      stx oldypos
                                      lda #CHAR
                                      jsr printChar
                                      iny                   ; step right
                                      sty xpos
                                      lda (zp),y
                                      sta backgrnd          ; save new original background character
                                      cmp #32
                                      bmi .asl_1
                                      inc backgnd_adr+2     ; inc HiByte
                                      inc newBackgndAdr+2   ; inc HiByte
  .asl_1                              asl
                                      asl
                                      asl                   ; * 8
                                      sta backgnd_adr+1     ; set backgrund address
                                      sta newBackgndAdr+1   ; set backgrund address
                                      ldx #7
                                      ; copy backgrund char to new Position (CharTo)
                backgnd_adr           lda $1000,x
                                      sta adrCharTo,x
                                      ; copy Master to Tmp
                                      lda adrCharMaster,x
                                      sta adrCharFromTmp,x
                                      lda #0                ; delete CharTmp
                                      sta adrCharToTmp,x
                                      dex
                                      bpl backgnd_adr
                                      ; write CharTo to new position
                                      lda #CHAR+1
                                      sta (zp),y
                                      rts
                                      
; ##############################################################################
; #                     shift character to right dir
; ##############################################################################
!zone moveRight
    moveRight                         ldx #7
                                      ldy #8
                                      
    .scroll_r                         ; shadow shifting (not visible)
                                      lsr adrCharFromTmp,x
                                      ror adrCharToTmp,x
                                      dex
                                      bpl .scroll_r
                                      jsr wait
                                      ldx #7
                                      dey
                                      bmi .end
                                      ; ORA partly shited shadow char with backgroung char
    .ora                              lda adrCharToTmp,x
                newBackgndAdr         ora $1000,x
                                      sta adrCharTo,x           ; to position
                                      
                                      lda adrCharFromTmp,x
                oldBackgndAdr         ora $1000,x
                                      sta adrCharFrom,x         ; from position
                                      dex
                                      bpl .ora
                                      ldx #7
                                      bne .scroll_r
    .end                              ; restore the original char to old position
                                      ldx oldypos
                                      ldy oldxpos
                                      lda oldbackgrnd
                                      jsr printChar
                                      ; copy bytes adrCharTo -> adrCharFrom
                                      ldx #7
    .loop                             lda adrCharTo,x
                                      sta adrCharFrom,x
                                      dex
                                      bpl .loop
                                      ; restore HiByte-adr to $1000
                                      lda #$10              
                                      sta newBackgndAdr+2
                                      sta oldBackgndAdr+2
                                      sta backgnd_adr+2
                                      rts
                                      
; ##############################################################################
; #                          Y-coordinates to screen address
; ##############################################################################         
!zone table4xy  
table4xy  

                                      lda screenLo,x
                                      sta zp
                                      sta zp2
                                      lda #$1f
                                      cpx #12
                                      bpl .table4xy1
                                      lda #$1e
  .table4xy1                          sta zp+1
                                      clc
                                      adc #120
                                      sta zp2+1
                                      rts 

screenLo
  !byte $00,$16,$2C,$42,$58,$6E,$84,$9A,$B0,$C6,$DC
  !byte $F2,$8,$1E,$34,$4A,$60,$76,$8C,$A2,$B8,$CE,$E4

; ##############################################################################
; #                               print char to xy
; ##############################################################################  
!zone printChar
  printChar                           pha
                                      jsr table4xy
                                      pla
                                      sta (zp),y
                                      lda #6
                                      sta (zp2),y
                                      rts
                                      
; ##############################################################################
; #                                   W A I T
; ##############################################################################         

!zone wait
    wait                              txa
                                      pha
                                      tya
                                      pha
                                      ldy #SPEED
    .startx                           
                                      ldx #$ff
    .wait_loop
                                      dex
                                      bne .wait_loop
                                      dey
                                      bpl .startx
                                      pla
                                      tay
                                      pla
                                      tax
                                      rts   
                                      
; ##############################################################################
; #                                   I N I T
; ##############################################################################    
!zone init  
  init                                lda #$fc
                                      sta $9005         ; char pointer to $1000
                                      lda #147          
                                      jsr BSOUT         ; clear screen
                                      
                                      ; copy characters to $1000
                                      ldx #0
                                      ldy #2
  .loop                               lda $8000,x
  .newchar                            sta $1000,x
                                      dex
                                      bne .loop
                                      inc .loop+2
                                      inc .newchar+2
                                      dey
                                      bne .loop
                                      
  .restart                            ; ABCDE...T
                                      ldy #0
                                      sty xpos
                                      ldx #10
                                      stx ypos
  .loopABC                            jsr table4xy
                                      tya
                                      jsr printChar
                                      iny
                                      cpy #21
                                      bne .loopABC
                                      lda #32
                                      jsr printChar
                                      
                                      ; set ... values
                                      lda #32
                                      sta backgrnd
                                      lda #$15
                                      sta stepCount
                                      rts
                                      
and yes, this code is not perfect. it should only show how it could work.

the music plays in this two methods:
- prepareCharMovement
- moveRight

the advantage is, that this technique is acceptable for static background grafics in simple games.
the detriment is, that the background always need to have the same color like the moving character.

what do you think about it?

aitsch
Attachments
overlap.zip
(519 Bytes) Downloaded 32 times
Last edited by aitsch on Sun Apr 19, 2020 9:52 am, edited 2 times in total.
User avatar
tokra
Vic 20 Scientist
Posts: 1123
Joined: Tue Apr 27, 2010 5:32 pm
Location: Scheessel, Germany

Re: is there a trick to overlap characters

Post by tokra »

Have you had a look a the Software Sprite Stack by Robert Hurst that has been released on this forum in 2009?

http://sleepingelephant.com/ipw-web/bul ... php?t=3252

This was used for Berzerk MMX and Quikman by the same author which you can find in his repository as well:

https://github.com/theflyingape/

No need to re-invent the wheel :)
User avatar
aitsch
Vic 20 Amateur
Posts: 51
Joined: Sun Mar 08, 2020 12:54 pm
Location: Germany NS

Re: is there a trick to overlap characters

Post by aitsch »

hi tokra,

thanks for your answer.
i'm programming in 6502-assembly for more or less 1 year. so i am a rookie in coding the vic.
i've heard from this sprite api but it is very complex and not so easy to understand.
for this api an ram extension of 8kb is recommended.

the level here is very high but i'm looking for the low hanging fruits, try to understand how the things work and what is possible with an standard vic-20 (unexpanded).

re-inverting the wheel was not my goal but comprehending what's going on.

that are the reasons why i've coded this example.

aitsch
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: is there a trick to overlap characters?

Post by Mike »

aitsch wrote:what do you think about it?
Works as supposed. :)

Of course you will want to have all preparing steps done invisibly, i.e.:
  • work out the position of the 'mini-bitmap' in the text screen,
  • make a copy of the screen codes at that place,
  • retrieve their background character definitions and write them to a pool of replacement character definitions,
  • merge pattern definition into replacement character definitions.
Up to now, nothing noticable has happened on screen, but the next step 'blinks' the object into existence:
  • write screen codes of the replacement characters to text screen.
When the object is moved (or just made disappear), you would restore the original screen codes first.

Note I did not specify how the pattern definition is supposed to be constructed. It may either be constructed/shifted on-the-fly as the merge procedure takes place, or get the data from a pool of pre-shifted definitions. The latter method is faster but needs more space.

Ideally, the change of screen codes should only happen when the raster beam is somewhere else. :wink:
the detriment is, that the background always need to have the same color like the moving character.
That is alleviated a bit with multi-colour mode, at the expense of resolution. And you'll most probably want to use a masking technique, simply OR-ing in pattern data will not produce satisfactory results.

If the background scenery can get away with a somewhat less horizontal resolution (ho-hum) then doing inline splits of the background colour might be the weapon of choice, as seen in Victragic's implementation of Pitfall in 2013 ...

Other than that, as tokra already wrote, a sharp look at rhurst's Triple-S library is wholeheartedly recommended.
Post Reply