BMLL command V9990 on interleave doesn't work

Pagina 1/2
| 2

Door Mumbly

Resident (49)

afbeelding van Mumbly

27-12-2017, 12:04


I try to make a BMLL command on an interleave resolution (512/424), it works on open msx but not on real hardware, I presume one of the vdp register is not set as expected for real hardware, I did the test with the g9klib as well as my own lib and both are giving the same strange result in real hardware (black dots are from time to time copyed).

Anybody has experienced such issue, and eventually found a solution ?

writemask is set to #FFFF

; LDIR but in VRAM
; BC: nbre of bytes
; HL: source
; DE: destination

ld a,(SHVramAddr)
ld (ix),l
ld (ix+1),h
ld (ix+2),a

ld a,(HVramAddr)
ld (ix+3),e
ld (ix+4),d
ld (ix+5),a

ld (ix+6),c
ld (ix+7),b
ld (ix+8),0


call CopyVramToVram

test will all the registers sets that could be involved as paramater to the command (same result)


ld a,l
OUT (G9K_REG_DATA),a ; Source Low 32
xor a
OUT (G9K_REG_DATA),A ; dummy write 33
ld a,h
OUT (G9K_REG_DATA),a ; Source mid 34
ld a,(SHVramAddr)
OUT (G9K_REG_DATA),a ; Source high 35

ld a,e
OUT (G9K_REG_DATA),a ; Destination Low 36
xor a
OUT (G9K_REG_DATA),A ; dummy write 37 DX
ld a,d
OUT (G9K_REG_DATA),a ; Destination mid 38
ld a,(HVramAddr)
OUT (G9K_REG_DATA),a ; Destination High 39

ld a,c
OUT (G9K_REG_DATA),a ; Number of bytes Low 40
xor a
OUT (G9K_REG_DATA),A ; dummy write 41
ld a,b
OUT (G9K_REG_DATA),a ; Number of bytes mid 42
xor a
OUT (G9K_REG_DATA),a ; Number of bytes High 43

xor a
OUT (G9K_REG_DATA),a ; Number of bytes High 44 DIX DIY
ld a,%00001100
ld a,#ff


Aangemeld of registreer om reacties te plaatsen

Van msd

Paragon (1375)

afbeelding van msd

27-12-2017, 16:47

Which interface mode do you use? It could be that you have to use a different write mask. This is documenten in the v9990 manual , but not clearly.

Van Mumbly

Resident (49)

afbeelding van Mumbly

27-12-2017, 18:17

@MSD, what do you mean by interface mode ? you mean the display mode, it's the B3

LD BC,G9K_SCR0_8BIT*256 + G9K_SCR0_XIM512;G9K_SCR0_XIM256
LD DE, 256 * 1 + 0 ; 0-> noninterlace
CALL SetScreenMode

; Set default blitter settings
G9kWriteReg G9K_ARG,0
CALL SetCmdWriteMask

Van msd

Paragon (1375)

afbeelding van msd

27-12-2017, 19:35

I think you need to change the writemask, the memory is devided into two banks.

Van Grauw

Ascended (8618)

afbeelding van Grauw

27-12-2017, 19:56

When you encounter any such kind of difference between real hardware and emulation, also file an issue with openMSX’s bugtracking, you’ll help out the next person trying it and possibly yourself as well Smile.

Van Manel46

Champion (489)

afbeelding van Manel46

27-12-2017, 20:08

Why do not you use LMMM, instead of BMLL?
It's for points. Origin X, Y Destination X, Y Size X, Y And finally you execute command ..

Van Mumbly

Resident (49)

afbeelding van Mumbly

27-12-2017, 23:49

It works actually, but not in a real linear way, I mean the real hardware is buffering the source area to copy and override (by block) the destination area in one shot, which is not the case apparently of open msx (byte per byte).
So if you overlap a little the source and the destination area, the result won’t be the same.
In my use case, I used bmll to simulate an ldir in vram, so it’s a byte per byte transfer, the real vdp doesn’t behave like this. I’ll contact people from open msx to be sure, but the simulation I did seems to confirm this.

Van GhostwriterP

Hero (527)

afbeelding van GhostwriterP

28-12-2017, 11:23

I knew this did not work if there was one byte difference between source and destination; I suspected at the time the vdp must be reading ahead or something. So, my question is, does it not work as desired with any overlap regardless the distance between source and destination?

Van Manuel

Ascended (15977)

afbeelding van Manuel

28-12-2017, 12:51

If you can find out how it works exactly, we can implement it in openMSX...

Van Mumbly

Resident (49)

afbeelding van Mumbly

29-12-2017, 01:04

@Ghostwriter, yes that’s the point, if the difference in bytes between the destination and the source is less than the expected bytes to move (overlap case) then it will move not the same way than in open msx

@Manuel in openmsx, I presume you are moving bytes per bytes, right ?

Van Manuel

Ascended (15977)

afbeelding van Manuel

29-12-2017, 10:57

Looks like it:

void V9990CmdEngine::executeBMLL(EmuTime::param limit)
        // TODO DIX DIY?
        auto delta = getTiming(BMLL_TIMING);
        const byte* lut = Mode::getLogOpLUT(LOG);
        while (engineTime < limit) {
                engineTime += delta;
                // VRAM always mapped as in Bx modes
                byte srcColor = vram.readVRAMBx(srcAddress);
                unsigned addr = V9990VRAM::transformBx(dstAddress);
                byte dstColor = vram.readVRAMDirect(addr);
                byte newColor = Mode::logOp(lut, srcColor, dstColor);
                byte mask = (addr & 0x40000) ? (WM >> 8) : (WM & 0xFF);
                byte result = (dstColor & ~mask) | (newColor & mask);
                vram.writeVRAMDirect(addr, result);
                srcAddress = (srcAddress + 1) & 0x7FFFF;
                dstAddress = (dstAddress + 1) & 0x7FFFF;
                if (!--nbBytes) {
Pagina 1/2
| 2