Video: Lesson P31 - Hardware Sprites on the MSX1!

MSX & MSX2 including the V9990 GPU (V9K)
John
Posts: 40
Joined: Tue Mar 24, 2020 1:18 am

Re: Video: Lesson P31 - Hardware Sprites on the MSX1!

Post by John » Sat May 02, 2020 3:18 am

Hi,

I have gone through your tutorial (video and the writing) of
using tiles for simulating sprites on the MSX-1.
I have copied and pasted your code ,from
your files, into a simpler cartridge program that
has only MSX1 code-
(instead of leaving in all the code for all the
different platforms and using multiple files).
The only change I made to your code was to comment
out the line

ld hl, BitmapFont

in DOINIT since I do not require it
and I don't thinks fonts are used for
drawing the sprite-also I am just initialising
the screen 1 by simply calling the BIOS
address &006F.

The program, compiles without errors, but does not fully work-
it draws the tiles in the right place
but the tiles are not redefined as a sprite-see
the image,
The sprite used is yours from the Lesson.
So where is the bug?
Code is below. Also all used files are attached.


org &4000
db "AB";
dw Programstart ;
dw Programend ;
dw Programstart


INIT32 equ &006F



VdpOut_Data equ &98 ;For Data writes
VdpOut_Control equ &99 ;For Reg settings /Selecting Dest addr in VRAM





Programstart:
call INIT32 ; SCREEN 1


ld de,128
ld hl, SpriteData
ld bc, SpriteDataEnd-SpriteData
call DefineTiles

;We need to fill an area with numeric tiles, then we'll set those tiles to our chibiko character


ld bc,&0303 ;Start Position in BC
ld hl,&0606 ;Width/Height of the area to fill with tiles in HL

ld de,128

call FillAreaWithTiles ;Fill a grid area with consecutive tiles

Looppause:
jp Looppause


;------ code below is pasted copied and pasted from diffrent tutorials

GetColMemPos: ;Get a BC (XY) color memory pos, 32 chars per line, 8 bytes of color per char,
; this command uses Y as a bitmap line number (0-192), not a tile number (0-24)
push bc
ld a,c
and %11111000
and %11111000
rrca
rrca
rrca
or &20 ;Colors start at &2000
ld h,a
ld a,b
and %00011111
rlca
rlca
rlca
ld b,a
ld a,c
and %00000111
or b
ld l,a
call VDP_SetWriteAddress
pop bc
ret


CopyToVDP: ;Send data to the VDP using OUT commands
push bc
push hl
ex de,hl
call VDP_SetWriteAddress
pop hl
pop bc
inc b
inc c
CopyToVDP2:
ld a,(hl)
out (VdpOut_Data),a
inc hl
dec c
jr nz,CopyToVDP2
dec b
jr nz,CopyToVDP2
ret

ScreenINIT:
ret
DOINIT:

ld a, %00000010 ;mode 2
out (VdpOut_Control),a
ld a,128+0 ;0 - - - - - - M2 EXTVID
out (VdpOut_Control),a

ld a, %01000000 ;(show screen)
out (VdpOut_Control),a
ld a,128+1 ;1 4/16K BL GINT M1 M3 - SI MAG
out (VdpOut_Control),a

ld a, %10011111 ;Color table address ;%10011111=tile mode ; %11111111= bitmap mode
out (VdpOut_Control),a
ld a,128+3 ;3 CT13 CT12 CT11 CT10 CT9 CT8 CT7 CT6
out (VdpOut_Control),a
;in mode 2 control register #3 has a different meaning. Only bit 7 (CT13) sets the CT address.
;Somewhat like control register #4 for the PG, bits 6 - 0 are an ANDmask over the top 7 bits of the character number.



;Set Sprite attrib table to &1B00
ld a,%00110110
out (VdpOut_Control),a
ld a,128+5
out (VdpOut_Control),a



;ld a,%00000000
;out (VdpOut_Control),a
;ld a,128+11
;out (VdpOut_Control),a

;Set Sprite Pattern table to &3800
ld a,%00000111
out (VdpOut_Control),a
ld a,128+6
out (VdpOut_Control),a


ld a, %00000000 ;Pattern table address
out (VdpOut_Control),a
ld a,128+4 ;4 - - - - - PG13 PG12 PG11
out (VdpOut_Control),a
ld a, &F0 ;Text color
out (VdpOut_Control),a
ld a,128+7 ;7 TC3 TC2 TC1 TC0 BD3 BD2 BD1 BD0
out (VdpOut_Control),a

; ld hl, BitmapFont dont need for tile based software sprites
ld de, &0000 ; $8000
ld bc, 8*96 ; the ASCII char
call CopyToVDP ; load tile data


CLS:
ld hl,&1800 ;Set all the tiles to Zero
call VDP_SetWriteAddress
ld bc,&17FF
;ld d,0
FillRpt:
xor a; ;Write a Zero
out (VdpOut_Data),a
dec bc
ld a,b
or c
jr nz, FillRpt


ld hl,&2000 ;Clear all the color info, 8 lines per tile, 32x24 tiles=&1800
call VDP_SetWriteAddress
ld a,0
ld bc,&1800
FillRptnb:
ld a,&F0 ;Foreground / Background... F0=White/Black
out (VdpOut_Data),a
dec bc
ld a,b
or c
jr nz, FillRptnb
ret

VDP_SetReadAddress:
ld C,0 ;Bit 6=0 when reading, 1 when writing
jr VDP_SetAddress
prepareVram:
VDP_SetWriteAddress:
ld C,64 ;&40/64/Bit6
VDP_SetAddress:
ld a, l
out (VdpOut_Control), a
ld a, h
or C
out (VdpOut_Control), a
ret

SetHardwareSprite:
rlca ;4 bytes per sprite
rlca
push bc
push hl
ld h,&1B ;Sprite Attribs start at &1B00
ld l,a
call VDP_SetWriteAddress
pop hl
pop bc
ld a,c
out (VdpOut_Data),a ;y
ld a,B
out (VdpOut_Data),a ;x
ld a,h
out (VdpOut_Data),a ;Pattern
ld a,l
out (VdpOut_Data),a ;Color + 'EC'
;'EC' - early clock - shifts sprite 32 pixels left so sprites can be offscreen left

ld a,%00001000 ;turn on sprites
out (VdpOut_Control),a ;Set up Vram [VR=1] [SPD=SpriteDisable]
ld a,128+8
out (VdpOut_Control),a ;R#8 [MS ] [LP ] [TP ] [CB ] [VR ] [ 0 ] [SPD] [BW ]
ret



FillAreaWithTiles: ;Fill an area with consecutively numbered tiles, so we can simulate a bitmap area
;BC = X,Y
;HL = W,H
;DE = Start Tile
ld a,h
add b
ld h,a

ld a,l
add c
ld l,a
FillAreaWithTiles_Yagain:
push bc
push de
push hl
call GetVDPScreenPos
pop hl
pop de

FillAreaWithTiles_Xagain:
ld a,e
out (VdpOut_Data),a
inc e
inc b
ld a,b
cp h
jr nz,FillAreaWithTiles_Xagain
pop bc

inc c
ld a,c
cp l
jr nz,FillAreaWithTiles_Yagain

ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Write Tile data to Vram
;Tile patterns start at &0000 - each tile is 8 bytes... we have 256 available.
;In theory, The tilemap supports 768 tiles, the first 1/3rd for the top part of the screen,
;The 2nd for the middle, and 3rd for the bottom... we use it to fake a bitmap mode, but it's slow, so we're not using it here.
DefineTiles: ;BC=Bytecount, HL=source, DE=Destination
push bc
ex de,hl
call prepareVram
ex de,hl
pop bc
DefineTiles2:
ld a,(hl)
out (VdpOut_Data),a
inc hl
dec bc
ld a,b
or c
jp nz,DefineTiles2
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetVDPScreenPos: ;Move the VDP write pointer to a memory location by XY location
push bc ;B=Xpos (0-31), C=Ypos (0-23)
ld h,0
ld l,c
or a
rl l ;32 bytes per line, so shift L left 5 times, and push any overflow into H
rl h
rl l
rl h
rl l
rl h
rl l
rl h
rl l
rl h
ld a,l
or b ;Or in the X co-ordinate
ld l,a
ld a,h
or &18 ;Tilemap starts at &1800
ld h,a
call VDP_SetWriteAddress
pop bc
ret

SpriteData:
incbin "C:\Spriteswithtiles\RawMSX1.RAW"
;;;;; the test sprite (from the tutorial) is in a folder named Sprites with tiles
SpriteDataEnd:

Programend:
org &C000;
Attachments
Spritewithtilesfiles_.zip
(2.97 KiB) Downloaded 429 times
1.PNG
1.PNG (74.53 KiB) Viewed 6807 times

Voyager_sput
Posts: 15
Joined: Tue Jan 07, 2020 11:45 am

Re: Video: Lesson P31 - Hardware Sprites on the MSX1!

Post by Voyager_sput » Sun May 03, 2020 10:22 am

Hello John,

You almost had it. Note, i'm by far not a Z80 programmer (i'm more into 6502), but I got your code working.

The problem was in line 24 of your code:

Code: Select all

ld de,128
Loading the DE register for 128 tiles. But you should load it with 128 tiles with a size of 8 bytes per tiles, so like this:

Code: Select all

ld de,128*8
That should load Chibiko properly on your screen. Note 2) Chibiko is a bit white. As far as I understand the MSX1, you still need to load in the pallet data for the bitmap to get any colors on screen for the sprite.
Attachments
chibiko-msx1.PNG
chibiko-msx1.PNG (15.48 KiB) Viewed 6805 times

John
Posts: 40
Joined: Tue Mar 24, 2020 1:18 am

Re: Video: Lesson P31 - Hardware Sprites on the MSX1!

Post by John » Mon May 04, 2020 3:13 pm

Hi Voyager_Sput,

Thanks . But there is another more subtle bug when I tried to use this code for animating sprites. Adding a simple infinite loop to the code , the relevant changes to the code is shown below, shows the bug



Programstart:
call INIT32 ; SCREEN 1

Programstartwithoutclearscreen:
ld de,128*8
ld hl, SpriteData
ld bc, SpriteDataEnd-SpriteData
call DefineTiles

;We need to fill an area with numeric tiles, then we'll set those tiles to our chibiko character


ld bc,&0303 ;Start Position in BC
ld hl,&0606 ;Width/Height of the area to fill with tiles in HL

ld de,128

call FillAreaWithTiles ;Fill a grid area with consecutive tiles


jp Programstartwithoutclearscreen


;------ code below is pasted copied and pasted from diffrent tutorials



all I have done is add a simple infinite loop using the label Programstartwithoutclearscreen
everything else is the same as before (with your bugfix regarding register de of course).

The result is garbage/corruption added to the screen (screen shot attached)-you have to wait a while for the garbage to appear-maybe up to a minute.

For animating sprites, say using 2 frames, I would repeatedly
use the Definetiles subroutine, in an indefinite or infinite loop,
reloading the tiles for each frame of the sprite animation. But
this will cause the screen to go corrupt with garbage as described above. So where is the bug?
Attachments
2.PNG
2.PNG (34.82 KiB) Viewed 6801 times

Voyager_sput
Posts: 15
Joined: Tue Jan 07, 2020 11:45 am

Re: Video: Lesson P31 - Hardware Sprites on the MSX1!

Post by Voyager_sput » Mon May 04, 2020 8:07 pm

Hi John,

That's a tough one. The definetiles part is fine, if I put the Programstartwithoutclearscreen: label lower, it still corrupts. Something is happening with the FillAreaWithTiles function. But i'm not sure what....

It's like something is corrupting a register or overflowing somewhere causing this weird behavior. I'm just not sure if it's a problem in the FillAreaWithTiles function or the GetVDPScreenPos function. The drawing is very dependent on the BC,HL, DE and A register. Any one of them could become corrupted somewhere along the line, I just can't see it. The pushes and pop's seem to be in place just fine.

I'd advise setting up some monitoring function (perhaps Keiths own function) or a debugger so you can see the state of the registers at certain points. The corruption appears instant, but given how fast it's running, it could very well have done 10's or 100's of loops before some memory value or register suddenly gets unexpected values. The way it looks now, something is overflowing so part of Chibiko are (also) loaded to her right, scrolling through some tiles. Perhaps that part also overflows eventually, causing the explosion of tiles in the botton of the screen (after about 17 seconds).

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

Re: Video: Lesson P31 - Hardware Sprites on the MSX1!

Post by akuyou » Tue May 05, 2020 12:04 pm

Firstly make sure you've got interrupts disabled - the interrupt handler may mess with the VDP, so could be causing this.

If that fails, The VDP can take a little time to process the OUT commands... so put a few NOPs after each OUT and see if that fixes it.
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

John
Posts: 40
Joined: Tue Mar 24, 2020 1:18 am

Re: Video: Lesson P31 - Hardware Sprites on the MSX1!

Post by John » Wed Jun 24, 2020 8:39 pm

Hello Keith,

I don not understand why you say words that mean
you need to use a buffer for MSX-1 scrolling up an down (vertically)
and/or there is no hardware scrolling on MSX-1 machines
in your recent video

Lesson P59 - Hardware scrolling on the MSX 1/2/2+
at
https://www.youtube.com/watch?v=-vKt68TUyXs


Because there is vertical hardware scrolling in screen 1 mode
of MSX-1 (I don't know if the following works in screen 2).
Since each tile graphic is a character then printing a
return character at the extreme bottom right of the page
will create a new line and thus shift all the characters vertically
upwards by one character.Then a new line of of graphical characters
needs to be drawn at the bottom of the screen.
So there is hardware scrolling on MSX-1
but as far as understand, it is limited to, 8 pixels at a time,vertical scrolling upwards or downwards in screen 1.

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

Re: Video: Lesson P31 - Hardware Sprites on the MSX1!

Post by akuyou » Thu Jun 25, 2020 7:10 am

Well, it's quite possible I am incorrect, I only did minimal research into the video, as it was a patreon request on a topic I've not looked at before.

But can I ask.. you describe a procedure here, but do not describe how the hardware does it... it sounds like you're describing what the screen does in basic or via OS calls -Are you sure this is not a software function like I described - where the OS/Basic are moving the entire Vram contents (as I did in my soft scroll) - just because the OS does it for you does not define it as a 'Hardware scroll'

If it is a hardware scroll, it would have to be done purely by manipulating VDP registers without moving any tile/color ram around... do you know what VDP registers are being altered to produce the effect you describe?

quoting Grauw's site (who's far more familiar with the MSX than I):
"The MSX1 VDP does not really have hardware support for scrolling"
http://map.grauw.nl/articles/scrolling.php

I'm not trying to say you are wrong, I'm just asking for more clarity to ensure we both understand what we're saying.
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

John
Posts: 40
Joined: Tue Mar 24, 2020 1:18 am

Re: Video: Lesson P31 - Hardware Sprites on the MSX1!

Post by John » Thu Jun 25, 2020 10:45 pm

Hello Keith,

I recall I read it somewhere but don't recall
where as it was so long ago.
If I can remember the reference I will let you know.
Early 1980s home computers , for example, like the MSX and ZX spectrum
and others a main application for them computers was text applications
(e.g. business applications) hence the tile
based (or character graphics) implemented by the MSX-1 VDP chip-in other
words the hardware was made for text applications.

"just because the OS does it for you does not define it as a 'Hardware scroll"
What it boils down to is if there is a advantage of using
the ROM hardware BIOS call in this way compared to a user made
scroll routine in software-that advantage may be speed
or saving memory (e.g. a smaller buffer or no buffer). In my programs (made in assembly language) it saves
speed and memory using the scroll method I described in the
previous message.

Of course we are only discussing vertical and horizontal scrolling so far-there is also other types of scrolling e.g. pseudo 3D scrolling e.g. as seen in MSX-1 game Antarctic Adventure, I don't know if we can build an algorithm around the VDP hardware for some sort of pseudo 3D scrolling.

John
Posts: 40
Joined: Tue Mar 24, 2020 1:18 am

Re: Video: Lesson P31 - Hardware Sprites on the MSX1!

Post by John » Tue Jul 14, 2020 6:22 pm

"If you can't keep your program below 16k, I think one way or another you're going to have to learn about bank switching."

Now I understand how to do bank switching and hence I am paging in the
required 16K memory to show the screen. So I can now show the desired background image using all three tile banks in screen 2 mode. So now I want to do some vertical scrolling in 8 pixel increments. on the image that uses the three tile bank screen 2 mode,all the 768 tiles are different in the image.

it seems that each tiles bank has to stay in its own area, I mean the top, middle, and bottom tile banks stay within the top third,middle third, and bottom third of the screen. In other words, if all 768 tiles are unique, then any tile is limited in position to some third of the screen.

So we can not put a tile in the first tile bank drawn to the extreme bottom right of the screen? Right?

That would mean vertical scrolling is not possible using the method I had in mind.

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

Re: Video: Lesson P31 - Hardware Sprites on the MSX1!

Post by akuyou » Wed Jul 15, 2020 3:21 am

Yes, you are correct - I'm pretty sure there's no way around it.

Any tile that can scroll between all 3 'areas' would have to be defined in all 3 (presumably with the same tile number)

I'm not sure where that leave vertical scrolling on the MSX... Unless you have some clever ideas to exploit this (like objects that move with the screen - staying in their 3rd), It's probably easiest to just use the '256' tile mode without the 3 area split.
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 “MSX & MSX2 Assembly Programming”