Timing of BIOS routines, such as BIOS_WRTVRM

Page 3/3
1 | 2 |

By zeilemaker54

Champion (278)

zeilemaker54's picture

12-07-2020, 11:18

theNestruo wrote:

I honestly think that you try the "easy" way (i.e.: use the BIOS) and then, if you face a performance problem, profile where the actual bottleneck is and improve that part. This will save you a lot of time fiddling with problems that maybe don't exist.

Very good point. The example of the BIOS routine WRTVRM (a MSX1 bios call) is actually a good example why BIOS is to be preffered.
The MSX1 code:
07CD: push af
call A07DF ; SETWRT
ex (sp),hl
ex (sp),hl
pop af
out (098H),a
ret

; Subroutine SETWRT
; Inputs ________________________
; Outputs ________________________

A07DF: ld a,l
di
out (099H),a
ld a,h
and 03FH
or 040H
out (099H),a
ei
ret

vs the MSX2 and up code:
C07D7: PUSH AF
CALL C07F4 ; SETWRT
EX (SP),HL
EX (SP),HL
POP AF
OUT (98H),A
RET

C07F4: XOR A
DI
OUT (99H),A
LD A,128+14
OUT (99H),A ; vdp register 14 = 0 (adres the first 16 Kb vram)
LD A,L
OUT (99H),A
LD A,H
AND 3FH
OR 40H
OUT (99H),A ; setup vdp for writing
EI
RET

The MSX2 and up version of the code makes sure it is compatible with MSX1, by forcing VDP register 14 to zero (first 16 KB of the VRAM)

By Grauw

Ascended (9181)

Grauw's picture

12-07-2020, 13:56

albs_br wrote:
            ld a, l
            di
            out (0x99), a
            nop
            nop
            set 6, h                    ; Set write flag
            ld a, h
            out (0x99), a

Only VRAM access needs a wait. That is, I/O to port 98H. Access to registers and setting the VRAM address poointer (99H) needs no wait. So these nops are unnecessary.

albs_br wrote:
            pop af
            nop
            nop
            nop
            ei
            out (0x98), a

And the nops here are also unnecessary, because only the time relative to the previous access to port 98H counts*, and since you’re doing only one at a time there is plenty of wait time in-between.

* Actually to be a little more specific, if you change the VRAM address while a previous VRAM write is not processed yet, it will run into trouble, so there needs to be sufficient wait time (the call + ret and other instructions present now is already plenty). Additionally, if you read from VRAM, you must also wait 8 µs between setting the read address and actually reading it, so that the VDP can ready the value.

By Dolphin101546015

Champion (271)

Dolphin101546015's picture

12-07-2020, 14:44

VSCode + Z80 Assembly Meter, let counting of code size and cycles for ZX Spectrum and MSX (MSX commands require more cycles)
Look at info bar:

By pgimeno

Master (191)

pgimeno's picture

12-07-2020, 15:01

If the interrupt routine does not access VDP registers other than the status register, you don't need to keep the interrupts disabled during writes to port 98h.

By albs_br

Expert (68)

albs_br's picture

12-07-2020, 17:44

theNestruo wrote:

Have you tried actually using BIOS' LDIRVM to transfer the SPRATR RAM buffer? How does it perform? Is there a bottleneck there?

Yes, and it is becaming slow with just two enemies on screen (each enemy uses 3 sprites). I plan to have 5 enemies at same time, it will be so slow as BASIC.

theNestruo wrote:

BIOS is usually reviled as "non-performant" by experienced programmers (or programmers with the not-invented-here syndrome), but unless you are coding an VDP intensive game, with lots of sprites, scrolling, pattern redefinition, etc., it will probably perform good enough.

I'm sure there is lots of other bottlenecks, for example, I was treating the sprites attr table as a 16-bit address, using INC HL to go to the next, but now I load H only one time and use inc L, since the HI byte is always the same.

I understand your point, using for example the VBLANK is few gain in speed and don't worth the headache, but this kind of VDP direct access vs BIOS seem to me worth the effort.

By theNestruo

Master (158)

theNestruo's picture

12-07-2020, 18:17

albs_br wrote:
theNestruo wrote:

Have you tried actually using BIOS' LDIRVM to transfer the SPRATR RAM buffer? How does it perform? Is there a bottleneck there?

Yes, and it is becaming slow with just two enemies on screen (each enemy uses 3 sprites). I plan to have 5 enemies at same time, it will be so slow as BASIC.

I'm pretty sure your problem is somewhere else.

I'm blitting the entire SPRATR on every frame in a single LDRIVM (or split in two LDIRVMs if the flickering routine applies), and it is no way that slow. The entire SPRATR; regardless the numer of enemies (source code).
Even if you were WRTVRMing the separate bytes, that's 2enemies x 3sprites x 4bytes = 24bytes every frame. 24 bytes is the half of my fading effect (that WRTVRMs 48 characters -two columns- in the NAMTBL), and it fits under a frame (source code).
Actually, even a full NAMTBL blit (768bytes) on every frame is possible (source code).

There is no way that blitting 24 bytes to the VRAM is the reason that your code is so slow.

By albs_br

Expert (68)

albs_br's picture

12-07-2020, 19:56

Oh god, I forgot about these two guys:

LDIRMV
Function : Block transfer to memory from VRAM
LDIRVM
Function : Block transfer to VRAM from memory

This should be enought to make the 128 bytes buffer fast. And Yes, there are (many) bottlenecks somewhere else.

What is the tool you guys use to find these bottlenecks (profiler?) ?

Thanks a lot for the help

By albs_br

Expert (68)

albs_br's picture

12-07-2020, 20:39

PS. The Z80 meter extension fo VS code that I use is yours: https://github.com/theNestruo/z80-asm-meter-vscode

Such a small world

Page 3/3
1 | 2 |