Es preferible usar los comandos de VRAM
Mi forma de hacerlo es con una rutina que lee un buffer de datos que tengo en RAM que seteo con los datos que necesita y luego lanzo la rutina que carga esos datos a la VRAM y ejecuto el comando.
Te pongo la rutina y un ejemplo.
Esta es la rutina para hacer comandos a la VRAM:
; //////////////////////////////////////
; ///////// _VDPCMD  ///////////////////
; //////////////////////////////////////
; Ejecuta un comando al VDP con datos ordenados en puntero HL
; HL = Puntero de datos de comando 
;	(  SXL,  SXH,  SYL,  SYH,  DXL, DXH, DYL,DYH,
;	 INCXL,INCXH,INCYL,INCYH, COLO, ARG, CMD)
; Toca : BC,HL
_VDPCMD:
	; Bucle de espera a bit CE 
	call	WAIT_CE
	ld	A,20h	  ; Comando comença al Reg 20h
	out	[099h],A
	ld	A,80h+11h ; Reg 11h Ini. per enviar bytes seguits a Reg Seguits
	out	[099h],A
	
	ld	B,15
	ld	C,09Bh	  ; Port VDP per indirecte
@@LOOP:
	outi
	ld	A,B
	cp	0
	jp	nz,@@LOOP
	
	; Bucle de espera a bit CE 
	call	WAIT_CE
	
	ret
; //////////////////////////////////////
; ///////// WAIT_CE  ///////////////////
; //////////////////////////////////////
; Espera a que el bit 0 del R2 de Status estigui a 0 per començar o acabar _VDPCOM
WAIT_CE:
	ld	A,02h
	out	[099h],A
	ld	A,80h+0Fh  ; Llegim el Reg 02h posant 2 a Reg 0Fh
	out	[099h],A
	in	A,[099h]
	and	1
	jp	nz,WAIT_CE
	; Abans de marxar recoloquem el REG STATUS 0 a Reg 0Fh
	ld	A,00h
	out	[099h],A
	ld	A,80h+0Fh  
	out	[099h],A
	ret
Y en RAM tengo este array de datos declarado. Verás que está comentado lo que significa cada byte:
VDPCOMDATA:	.ds	15	; 0: Source XL
				; 1: Source XH [Normal a cero si SCR 5]
				; 2: Source YL 
				; 3: Source YH [Page 0-3]
				; 4: Destiny XL
				; 5: Destiny XH [Normal a cero si SCR 5]
				; 6: Destiny YL
				; 7: Destiny YH [Page 0-3]
				; 8: Width XL
				; 9: Width XH [Normal a cero si SCR5]
				;10: Height YL
				;11: Height YH [Normal a cero si SCR5]
				;12: Color Register
				;13: Arguments [Habitual 000000-EQ-MAJ = 00h para VRAM<->VRAM]
				;14: Comando a ejecutar
				;	HighSpeed CMD: (Que conozco)
				;		000h: Stop
				;		0D0h: Copy Rectangle VRAM->VRAM
Y esto es lo que haría en el código del juego si quiero copiar cachos de pantalla.
   ld   IX,VDPCOMDATA
   ld   [IX+0],
   ;....( setear todos los valores que corresponden [desde IX+0 a IX+14] con lo que quiero hacer, coordenadas y tamaños)...
   ld   [IX+14],0D0h   ;CMD 0D0h HMMM Copy Rectangle
   ; Lanzar el comando
   ld   HL,VDPCOMDATA   ; Envio CMD a la VRAM
   ; Aqui realiza los push que necesites guardar (ojo que el siguiente CALL toca registros)
   call   _VDPCMD
   ; Recupera datos anteriores con POP si hiciera falta.   
Mirate : 
http://problemkaputt.de/portar.htm#vdpregisters20h2ehmsx2videocommandregistersPara entender un poco que hace cada dato que se envia a los registros.
Te recomiendo tambien la lectura del PDF  yamaha_v9938_MSX2.pdf en la página 54 hacia delante. Especialmente la página 62 que es el comando que te interesa de copiar de VRAM a VRAM
http://www.textfiles.com/bitsavers/pdf/yamaha/Yamaha_V9938_MSX-Video_Technical_Data_Book_Aug85.pdf