MSX-C Library has a msx_bios() that I am sure is for using the MSX-BIOS functions in global beyond the translated ones in the library itself.
That's correct (it's called calbio(), though). It's defined as:
VOID calbio(adrs, reg) NAT adrs; REGS *reg;
Where adrs is the address of the BIOS routine you want to call (0000h to 3FFFh), and reg is a pointer to a struct containing the registers you want to pass to the function:
typedef struct regs { tiny f; tiny a; NAT bc; NAT de; NAT hl; } REGS;
The otir() requires that you get the VDP port from the bios variable. Then it is the same compatibility as LDIRVM.
The MSX C code of LDIRVM that was posted, it has exactly the 29 cycles loop as the otir29() I posted, that is the slower loop for MSX1. But the MSX2 can go in 18 cycles with otir().
So, you wrote a function that works well in a particular, especific situation, and it is slightly faster than the generic function that can be used in any situation. Cool. Document it and post it online so people can use it.
This discussion is making me tired already.
This discussion is making me tired already.
Share your great knowledge, but please don't get emotionally involved. Just leave it there, and people will pick it up, or not. Some people will be open to your suggestions; others just like to hear themselves talk. Don't be calling in the wilderness¹. ;-)
This discussion is making me tired already.
Share your great knowledge,
My knowledge isn't that great. There are several people here(*) who know so much more than me. Those are the people actually doing stuff, instead of just writing articles on a blog.
(*) And a few others who know even more, but have been banned from this site.
This discussion is making me tired already.
Share your great knowledge,
My knowledge isn't that great. There are several people here(*) who know so much more than me. Those are the people actually doing stuff, instead of just writing articles on a blog.
(*) And a few others who know even more, but have been banned from this site.
You are right Javi, let's avoid unproductive discussions. Sorry to ear that about people that has good techical knowledge about oor system, it would be a great help for the comunity
@hit9918 please let me insist about not using put sprite like in BASIC way. Because:
- Using put sprite one by one you can get a frame in screen where not all sprites are update at time. Do the copy all at once on interrupt and all sprites will be updated at the same time.
- Using only one copy RAM -> VRAM takes 29 cycles. 29 vs 18 cycles are not really a concern, you have more than 3 million (more than 59000 per interrupt at 60Hz), so better search for bottlenecks in another place. Also, if you copy at once, you use 29 cycles + copy cycles when put 1 up to 32 sprites, if you put the otir() one by one, you use 18 when putting one, 18x2 when putting 2, 18x3 when putting 3, and 18x32 = 576 when putting 32, + copy cycles. So which one is faster, and safer?
- If you need to get sprite data, simply use the data in RAM, is even much faster for CPU than from VRAM. Why do you want the sprite data in VRAM except for drawing them?.
Let me show how I would do the put sprite, I don't remember the SAT data required so I only will put some aproximation:
struct {x, y, ...} sprite_data; // an entry for SAT
sprite_data sprites[32]; //our 32 sprites = to the full SAT
put_sprite(TINY index, sprite_data *data)
{
sprites[i].x = data->x;
--- //copy all the other data
}
If you don't want to make sprites[32] global, pass as parameter too.
So in sprites[32] we have our SAT copy in RAM, that is much faster to access from the CPU. If you pass as parameter, you can have multiple SAT on RAM for anything you could use them, like some way of handling the sprite order, and then copy the one you want to VRAM. For split-screen sprite handling is a vast advantage, you have a SAT for each part of the screen, and copy each SAT on its corresponding interrupt.
In global, is much more versatile.
On interrupt, you do the one time full copy of sprites[32] to the SAT, only once, that is even much faster than multiple small copies.
I think we must remember that C is still a higher level language. As for ultimate performance on a Z80, C is not going to provide it. So I don’t see much point in trying to worry about specific numbers of CPU cycles. If anything, it smells a lot like premature optimisation (something us asm coders have a tendency to do ). Make software first, then if it turns out it is too slow you can worry about optimisation, first on an algorithmic level, then on a cycle micro-optimisation level.
One thing that stuck out to me about the otir function is that suddenly you have to be worried about accessing the VRAM too fast in certain screen modes or VDP versions. I do not think this is something you want to deal with in a higher level language. The whole point of using C is to get away from asm-level details like that.
Make software first, then if it turns out it is too slow you can worry about optimisation, first on an algorithmic level, then on a cycle micro-optimisation level.
The whole point of using C is to get away from asm-level details like that.
Totally agree with both points
Grauw++
Grauw++
Object-Oriented?