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:
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).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.
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
Code: Select all
lda #@SPRGO(SPRITE_GO|EVER_ON) sta SPRGO @ stz CPUSLEEP lda SPRSYS and #@SPRSYS(SPRITEWORKING) bne @- stz SDONEACK
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 ).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.
I think that all.