What I think will be critical with your solution is the enemy management. The cost of plotting directly in VRAM animated objects after the PNT has been updated rises very quickly with the number of items and explodes when objects are larger than one tile (if you want to add clipping with the border).
Maybe I've misunderstood, but now you have PNT update in the ISR, so you could consider to implement all the tile animations in RAM (included bullets). You need to unpack the whole level (or a large part of it) in ram as tiles and copy a window of it during the ISR. All the logic for enemy management and bullets should result faster if you can resolve it by reading an writing in ram.
Level is already unpacked in a RAM buffer (when the screen need to be scrolled the code unpack from tilemap the needed row and/or column). Only bullets are directly addressed during the isr, map is updated in RAM outside the isr. I'll try to modify the bullet management directly on RAM buffer, now that I'll copy it ti VRAM every frame so bullet speed won't be affected...
screen RAM buffer is 640 bytes, level is too big to fully unpack it to RAM: 137x51 4x4char tiles, so 548x204 chars = 111972 bytes... as you can see, even packed it is 6987 bytes long... (and this is only level1_1, size isn't the same for all levels)
What about unpacking a window larger than the screen and update only the rows/columns of the section that changes?
The best size is twice the width and twice the height of the window screen.
Align the buffer to a 256 multiple in ram. If you put an and 63 to the ram address you get a circular buffer for the screen where you need only to unpack the new columns when the player moves.
This will help you with the clipping of the enemies larger than one tile.
Wait, probably you can just test if the x of the window is less than 32. If it is less than 32 you can copy it as a row, if it is larger you can copy it in two steps, from x to 63 and from 0 to (63-x)
Nice! Looking forward to it!
I already actually unpack only the column and/or row when the player moves. I retrieve the tile inside the tilemap and then, using the xoffset and yoffset (that can vary from 0 to 3) I know wich row/columns I have to unpack from each tile.
Ibtried your way, before, but doing so the scrolling had some indecision when unpacking the tiles (so every 4 steps) because other 3 scrolling steps were obtained by simply offsetting the screen pointer in such unpacked part of map.
Anyway, using 4x4 tiles and unpacking only the needed row/columns, if an enemy is a fixed one (like turrets) done by chars it will be correctly clipped because its image will be unpacked in the same way (only needed/row columns). I plan to put the "event" tiles in RAM so they can be dinamically modified.
Moving enemies, instead, will be sprite based.
this because i do a lot hooked in the isr (...)
Despite they are probably very different projects, this is what I do in one of my current projects:
- Hooked on the ISR (H.TIMI): currently nothing; planned: just the music replayer
halt
- Unrolled
OTIR
of the NAMTBL (32x22=704 bytes in my case) from RAM buffer in both PAL and NTSC. Depending on the ISR, this fits within V-Blank.. or you can use unrolledOTIR
for two thirds of the screen and only use the classic way for the last third in NTSC (1) - OUTI loop for writing the SPRATR. My sprites are mostly on the lower half of the screen, so I do this after the NAMTBL
- And, after that, I read the input, do the game logic, rendering the "background" in the RAM buffer and updating the SPRATR buffer on the go.
As you see, the idea is to "pack" all the VRAM writes at the beginning of the frame without any logic to spend the least possible so I can blit the highest number of bytes using unrolled OTIR
. The point (1) in particular may be interesting to you because if you can unroll 400 or 500 bytes you will gain some frame time.
Thx for all of your contributes, everyone!
Suggestions and hints are always welcome
This way, if i missed, understimated or forgotten something I'll get all the help I need and be pointed to the right way
I love MSX community!
How much time does it take to set up vram for a charset bullet
;HL is in the range 0x4000 ... 0x7fff ld a,l out 0x99 ld a,h out 0x99 -- 34 cycles
The MSX can do this 2000 times in a PAL frame! Not per second but per frame! So... what was the question?
This gives the quick answer that the time is taken somewhere else.
It's not that simple:
Before do that you jave to retreive values from a table aligned to gain speed:
Byte 0: 1/0 active/inactive
Byte 1: address low byte
Byte 2: address high byte
Byte 3: horizontal pos 0-31
Then:
Ld a,(hl) Out (99h),a Inc l Ld a,(hl) Add a,64 (you forgot this) Out (99h),a Ld a,bullet shape value (there are 5 shapes) Out (98h),a
And here are missing other operation needed to update address for next frame (or eventually set bullet as inactive due to screen exit or background collision) and to decide wich bullet shape use...