Writing / Reading VRAM - noob questions

Pagina 1/9
| 2 | 3 | 4 | 5 | 6

Door siudym

Resident (39)

afbeelding van siudym

12-12-2021, 00:01

Hello
I'm toootally new to MSX assembler. I don't really understand VRAM writing.
For example, I save a simple 8x8 graphic to a VRAM Pattern Table:

LD HL,3800h ; VRAM address
LD A,%11111111
CALL 004DH
LD HL,3801h
LD A,%10000001
CALL 004DH
LD HL,3802h
LD A,%10100101
CALL 004DH
LD HL,3803h
LD A,%10100101
CALL 004DH
LD HL,3804h
LD A,%10000001
CALL 004DH
LD HL,3805h
LD A,%10111101
CALL 004DH
LD HL,3806h
LD A,%10000001
CALL 004DH
LD HL,3807h
LD A,%11111111
CALL 004DH

How can this be done more easily without using the BIOS Call?

Aangemeld of registreer om reacties te plaatsen

Van santiontanon

Paragon (1639)

afbeelding van santiontanon

12-12-2021, 04:02

Without getting into doing it manually, an easy way that only uses a single BIOS call is this (I know you wanted "without the BIOS call, but to get started, it's much easier if you do a BIOS call, as shown below):

Have this data somewhere in your rom/ram:

data_to_copy:
    db %11111111, %10000001, %10100101, %10100101, %10000001, %10111101, %10000001, %11111111

And then you can copy it like this (where LDIRVM is 0x005C):

    ld hl,data_to_copy  ; data to copy
    ld de,0x3800  ; address in VRAM to copy to
    ld bc,8  ; number of bytes to copy
    call LDIRVM

LDIRVM is not very fast (it's easy to do 2x faster or more if you write your custom assembler routine), but it will still be about 10x faster than the method you describe above, and it is also the easiest way.

Van siudym

Resident (39)

afbeelding van siudym

12-12-2021, 09:54

Thanks. I'm just getting started with MSX and it's quite complicated at the beginning.

Could you show an example of copying eg 768 bytes to VRAM 1800h-1AFF - without using BIOS CALL? (Using LDIRVM you only need to write 768 to BC.)

Van ARTRAG

Enlighted (6846)

afbeelding van ARTRAG

12-12-2021, 10:16

Look here for a description of the main bios calls
https://www.msx.org/wiki/Main-ROM_BIOS

If you want avoid the BIOS, e.g. because you have paged out the ROM, this code should do the work independently by the VBLANK status. If you know that you are in VBLANK the code can optimised to max speed as unrolled outi

	xor a
	di                          ; set VRAM address to 1800h
	out (99h),a            ;  lower byte 00
	ld a,18h + 040h     ; upper byte 18h with flag to set the bus in write mode
	ei
	out (99h),a            ; note that this is protected by the ei instruction

	ld hl,data
	ld bc,0098h          ; set b to 0 -> 256 bytes to be written per loop
	ld a,3                   ; repeat 3 times 256 bytes
loop:
	outi                   ; send the data (HL) to port 98h
	jp nz,loop            ; the inner loop is exactly 29 cycles. If you are not in VBLANK this is the max speed for msx1. 
	dec a
	jr nz,loop

The inner loop is exactly 29 cycles. If you are not in VBLANK this is the max speed for msx1. Shorter loops will result in data lost in the transfer. During VBLANK or on msx2 the loop can be faster.

Van siudym

Resident (39)

afbeelding van siudym

12-12-2021, 11:31

Good to know.

I'm not sure about the "GSPSIZ" feature - it only reads the current sprite size? If that works, how do I set the sprite size to 16x16?

Van ARTRAG

Enlighted (6846)

afbeelding van ARTRAG

12-12-2021, 11:42

008Ah (GSPSIZ)

Function: Returns the current sprite size
Entry: None
Output: A = Sprite size (8 when 16 x 16, 8 when 8 x 8)
F = CY flag is set when the size is 16 x 16, otherwise reset
Modify: AF

The description is broken, it returns the result in A, I think it return 16 for 16x16 sprites. Anyway be aware that it only works if you set the VDP register using the BIOS. There is no way to read the actual value of the VDP registers, so the BIOS save their values in RAM each time you update them using its calls. If you set VDP registers using the I/O ports, the BIOS will return invalid results in this kind of calls

Van Grauw

Ascended (10604)

afbeelding van Grauw

12-12-2021, 12:29

Even when accessing the VDP directly, I still find it good practice to update the register mirrors in RAM.

Van siudym

Resident (39)

afbeelding van siudym

12-12-2021, 12:53

Is this code that copies Sprite Attribute WRAM to VRAM correct?

	xor a
	di			; set VRAM address to 1800h
	out (99h),a		; lower byte 00
	ld a,1Bh + 040h		; upper byte 1Bh with flag to set the bus in write mode (1B00-1B7F VRAM: Sprite Attributes (128))
	ei
	out (99h),a		; note that this is protected by the ei instruction

	ld hl,C000h		; 128 byte Sprite Attributes Buffer in WRAM (C000-C07F)
	ld bc,0098h		; set b to 0 -> 256 bytes to be written per loop

loop:
	outi			; send the data (HL) to port 98h
	jp nz,loop		; the inner loop is exactly 29 cycles. If you are not in VBLANK this is the max speed for msx1.

Are there any things I need to keep in mind when operating sprites in MSX1?

Van ARTRAG

Enlighted (6846)

afbeelding van ARTRAG

12-12-2021, 13:36

No, you need to copy 128 bytes, not 256

Do you know how outi works?
http://www.z80.info/zip/z80-documented.pdf

Van siudym

Resident (39)

afbeelding van siudym

12-12-2021, 13:57

I still miss a lot about the Z80.

Reads from (HL) and writes to the (C) port. HL is then incremented, and B is decremented.

Not tested:

UpdateBuff:

	LD HL,1B00h						; point to start of SA in vram.

	PUSH AF
	LD A,L
	OUT (99h),A
	LD A,H
	OR $40
	OUT (99h),A
	POP AF

	LD B,128 (127?)						; amount of bytes to output.
	LD C,98h						; destination is vdp data port.
	LD HL,C000h						; source is start of sat buffer.

UpdateBuff_Loop:
	OUTI
	JR NZ,UpdateBuff_Loop
	RET

Van ARTRAG

Enlighted (6846)

afbeelding van ARTRAG

12-12-2021, 13:58

Not optimal, but it can work IF you protect with DI/EI the two writes to 99H

Pagina 1/9
| 2 | 3 | 4 | 5 | 6