Few thoughts on hardware sprites

Post Reply
laoong
Posts: 9
Joined: Thu Aug 08, 2019 10:51 am

Few thoughts on hardware sprites

Post by laoong » Mon Oct 14, 2019 9:48 am

Hi @akuyou. You haven't setup a topic for Lesson P32 on hardware sprites on Lynx and it happens that I've learned few thing the hard way while writing an entry to Atari Lynx 30th Birthday Programming Competition.
First of all the Handy emulator is pretty poor and it's extremely easy to write code that works on emulator and does not work on real hardware. Luckily I've borrowed a unit from a friend and could check everything.

I was actually trying to run your code and it did not work the same as in emulator. The reason is that it lacked few initialization bytes that are preinitialized on the emulator, but are not on the hardware - You haven't initialized HSIZOFF and VSIZOFF Suzy registers. They are documented in section 6.2.7:
Horizontal and Vertical Size Offset
In order to balance the visual 'bump' that occurs at the reference point of a multi- quadrant sized sprite, we implemented a 'cheat' value of initial offset for both horizontal and vertical size. They are programmed independently at the time of sprite engine initialization. For horizontal, the left direction offset is forced to zero, and the right direction offset is programmed to 007F. For vertical, the up direction offset is forced to zero, and the down direction offset is programmed to 007F.

When using specific sizes to achieve specific effects, these offsets must be taken into account. You may also program them to any 16 bit value you desire. They are common to all sprites, so remember to set them back if you want the usual offset correction.
The sprite was strangely stretched to whole screen when they weren't initialized. For my code it worked to set both to $007F (apparently it's a good value for 1st quadrant).

I think that it's also wise to initialize the screen specifying desired refresh rate. A sample code with specifying 60 Hz (sorry for exotic syntax):

Code: Select all

.enum @hback
HZ37 = 255  ;lowest possible: 37.2 Hz, 256 us per line
HZ50 = 189
HZ60 = 158
HZ75 = 126
HZ78 = 120  ;highest possible: 78.7 Hz
.ende

.enum @pbkup
HZ37 = 67  ;lowest possible: 37.2 Hz
HZ50 = 49
HZ60 = 41
HZ75 = 32
HZ78 = 31  ;highest possible: 78.7 Hz
.ende

  lda #@hback(HZ60)
  sta HCOUNT_BACKUP
  lda #104 ;backup value for vertical scan timer (== 102 vertical lines plus 2)
  sta VCOUNT_BACKUP
  lda #@pbkup(HZ60)
  sta PBKUP
  lda #@TIM_CONTROLA(ENABLE_RELOAD|ENABLE_COUNT)
  sta HCOUNT_CONTROLA
  lda #@TIM_CONTROLA(ENABLE_RELOAD|ENABLE_COUNT|AUD_LINKING)
  sta VCOUNT_CONTROLA
Next thing: although you are not using interrupts in the examples I thinks it's wise to talk to Suzy in interrupt-aware manner. It's because the CPU wakes up after interrupt and does not fall asleep automatically. The code needs to check whether the drawing has ended and go to sleep if not:

Code: Select all

  lda #@SPRGO(SPRITE_GO|EVER_ON)
  sta SPRGO
@ stz CPUSLEEP
  lda SPRSYS
  and #@SPRSYS(SPRITEWORKING)
  bne @- 
  stz SDONEACK
The last thing that I would like to mention is about this EVERON thing and why your first SCB byte is altered. I was puzzled with it too but I've figured it out. The EVERON bit is actually documented:
At a particular point in the life of a sprite, it may move in such a manner that it no longer appears on the screen. It may also have started its life off-screen. It appears to be useful to the software to know that a sprite is completely off-screen. The function used to discover this truth is called 'Everon' and is enabled by the 'Everonoff' bit. The function is enabled when the Sprite Engine is started with an 05 instead of an 01 at 'SPRGO'. This function will cause the 'Everon' bit to reflect the off- screen situation of a particular sprite. This bit is returned to each SCB in bit 7 of the collision depository. The bit will be a '0' if Everon is disabled or if the sprite is ever on the screen. The bit is a '1' only when Everon is enabled (Everonoff-is on) and the sprite is neveron the screen.
It means that even if you're not using hardware collision detection, the collision depository will be updated each time the sprite is actually drawn on the screen. The tricky thing is that the "collision depository" isn't in arbitrary location but you must specify it's offset to SCB's beginning by writing the COLLOFF register. I just write there $0002 so the SCB's SPRCOL field is updated and not the SPRCTL0 (it's now obvious why it's altered when you know about it :)).

I think that all.

Cheers,
laoo.

User avatar
akuyou
Posts: 563
Joined: Mon Apr 22, 2019 3:19 am
Contact:

Re: Few thoughts on hardware sprites

Post by akuyou » Wed Oct 16, 2019 9:19 pm

Great! Thanks for the info, I'll go over this, and update my tutorial source accordingly.

Thanks for sharing your experience with real hardware!

By the way, I'd forgotton abot making the hardware sprite threads... I'll do it soon - and I'll move this post to that thread when I do.
Chibi Akuma(s) Comedy-Horror 8-bit Bullet Hell shooter! // 「チビ悪魔」可笑しいゴシックSTG ! // Work in Progress: ChibiAliens

Interested in CPU's :Z80,6502,68000,6809,ARM,8086,RISC-V
Learning: 65816,ARM,8086,6809

Post Reply

Return to “Atari Lynx Assembly Programming”