Putting an image in the screen?

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

Door Daemos

Paragon (2044)

afbeelding van Daemos

12-01-2011, 21:58

After fidling around I finally got the hang of all this assembly stuff but the VDP still remains a mystery to me. I have read the V9938 manual 10 times over and my brains hurt by now.

So I send some bits and bytes to the VDP port and I eventually manage to change the screen mode and even change it back after hitting the esc key but I really just cannot understand how to put something into that screen.

I have tried putting some bytes into the vram in the hope to see something happen on screen5 but all I get is a line of white dots on a blue screen. No colors, just anoying white dots. These dots are my written bits though but the adressing into the vram memory also doesn't turn out as I expect.

Basicly: How can I for example, by just writing bits and bytes into the vram position a block/line whatever on the screen in the color I want?

Does the VDP read the contents of the VRAM automaticly and displays this onto the screen?

Aangemeld of registreer om reacties te plaatsen

Van Edwin

Paragon (1182)

afbeelding van Edwin

12-01-2011, 22:18

If you set the screen mode properly and if you wrote the right data in the right place and if the palette is initialised properly, you would see something on screen. A lot of ifs there though.

First of all, how do you set the screen mode? The common (and simple) way using BIOS? Or manually by writing the vdp registers?

Van commodorejohn

Expert (92)

afbeelding van commodorejohn

12-01-2011, 22:34

It varies significantly depending on the screen mode. Screen 5 is just a linear bitmap though, two pixels to a byte. What are you writing to where in the VRAM?

Van Daemos

Paragon (2044)

afbeelding van Daemos

12-01-2011, 22:50

Here comes the code. Took some time to extract it of the MSX machine.


        ORG   &HC000
CHMOD:  EQU   &H5F



;screen mode 5 using bios call

        LD    A,5
        CALL  CHMOD


;set vram adress and vram to write mode

        DI
        LD    A,0
        OUT   (&H99),A
        LD    A,45+128
        OUT   (&H99),A
        LD    A,0
        OUT   (&H99),A
        LD    A,&B01000000
        OUT   (&H99),A

        EI

;write this random stuff into vram

        LD    B,128           ;one whole line of bytes into vram
LOOPV:  LD    A,&B00010000
        OUT   (&H98),A
        DJNZ  LOOPV




the result is a line of white pixels on the screen. I am getting close but I fail to understand something.

Van Edwin

Paragon (1182)

afbeelding van Edwin

12-01-2011, 23:14

Hmmmm, that's not quite right. The first set of outs writes 0 to register 45. Which is command argument register. This won't have any effect on its own.

The second initialises the lower bits of the VRAM write pointer to zero. However, you don't have the upper 3 bits anywhere, which makes me think you meant to write to register 14 instead of 45.

Then you write 128 bytes of $10, which is a black pixel and a transparent pixel next to each other and filling the whole first line with that. If you background colour was still default blue, then you should see a black stippled line on a blue background if you change register 45 to 14.

Van Daemos

Paragon (2044)

afbeelding van Daemos

12-01-2011, 23:39

Yes the register change has worked out for me. The V9938 reworked manual seems to have a mistake as the text indeed states register 14 while the picture states register 45.

The line can now be positioned to the screen as I wish.

I also indeed see the black stippled line. Shouldn't there be something like 16 colors in the pallete. I tried some binary combinations but it all turns white/black or light blue. oO

I guess the VDP needs some kind of palette info write?

Van Edwin

Paragon (1182)

afbeelding van Edwin

12-01-2011, 23:48

By default you get the a palette similar to MSX1 (this is written by BIOS when you used the $5F call). Also, don't forget there are two pixels in one byte. So if you want red line, use $88.

Of course, if you're actually out to draw a line, you would use the command engine to do that for you. This manual data writing is mostly used to upload graphics to VRAM.

Van norakomi

Paragon (1136)

afbeelding van norakomi

13-01-2011, 13:42

I guess the VDP needs some kind of palette info write?to change the palette you can use this routine,
it writes 32 bytes for the 16 palette colors.

ld hl,palette
call setpalette
ret

SetPalette:
xor a
di
out ($99),a
ld a,16+128
out ($99),a
ld bc,$209A
otir
ei
ret

some extra info can be found here:
http://map.grauw.nl/

Van Daemos

Paragon (2044)

afbeelding van Daemos

13-01-2011, 15:08

Smile Yes your info has got me started.

After going on all night I finally got to understand this Vram thingy good and I have utilised the examples given to finally dram a 16x16 block onto the screen. For fun I have also build in some keypresses that change the color of the block.

Strange is though, when I write the backround color into register 7 only the upper and lower band of the screen turn black. The middle screen area always stay blue. Is there a command to change that as well? or do you simply fill the entire vram with for example black pixels and then overwrite the wanted pixels with the stuff you want?

From what I understand from the manual I am able to write 4 screen mode 5 screens over 4 pages of ram (128kb) I can switch between these. Is that the way game makers utilise scrolling by moving screen data from these pages? Or for example fastly switch between screen images?

second thing. How do you load a bitmap from disk as data? This is propably a question that will outcome with a very long awnser but some backround theory will do much good Wink

Van Edwin

Paragon (1182)

afbeelding van Edwin

13-01-2011, 21:59

The background colour is only visible in the border and through colour 0 (transparent). The BIOS screen mode change filled the screen with the default background colour, which was blue and not transparent. So yes, if you want to change it, you'll have to fill VRAM with a different colour (using the command engine high speed fill is best).

Scrolling is an interesting topic, but horizontal is not the easiest and best get familiar with the basics first.

I'm too lazy to explain loading data from disk. You'll have to look into BDOS calls using FCB (DOS1) or file handles (DOS2). You could start here, but maybe someone has a better reference.

Van commodorejohn

Expert (92)

afbeelding van commodorejohn

13-01-2011, 22:13

You'll be best served by looking through the MSX-DOS documentation, but here's some source for a viewer program I wrote. It uses screen 8 instead of 5, but it should give you enough of a clue to get started with.

	include	"msxbios.asm"
	
	org	0x0100	; CP/M & MSX-DOS start address
	
start:
	; open file
	ld	c,	0x0f	; C = BDOS function #
	ld	de,	fcb
	call	5
	or	a,	a
	jp	nz,	err1
	
	; set disk-transfer address
	ld	c,	0x1a
	ld	de,	buffer
	call	5
	
	ld	a,	0x00
	ld	(fcb+0x20),	a	; must clear out the FCB before using!
	ld	(fcb+0x21),	a
	ld	(fcb+0x22),	a
	ld	(fcb+0x23),	a
	ld	(fcb+0x24),	a
	ld	(fcb+0x0f),	a	; record size, high byte
	ld	a,	0x80
	ld	(fcb+0x0e),	a	; record size, low byte
	
	; read 384 128-byte records
	ld	c,	0x27	; block read
	ld	de,	fcb
	ld	hl,	0x0180	; number of records
	call	5
	or	a,	a
	jp	nz,	err2
	
	; close file
	ld	c,	0x10
	ld	de,	fcb
	call	5
	
	; set screen mode and copy frame buffer to VRAM
	ld	a,	0x08	; screen mode (I think)
	ld	iy,	0xfc00
	ld	ix,	chgmod
	call	calslt	; perform inter-slot call to BIOS
	
	di
	ld	a,	0x00	; This sets it to 192 lines
	out	(0x99),	a
	ld	a,	0x89
	out	(0x99),	a
	
	ld	a,	0x00	; set the border color to black
	out	(0x99),	a
	ld	a,	0x87
	out	(0x99),	a
	ei
	
	ld	bc,	0xc000
	ld	de,	0x0000
	ld	hl,	buffer
	call	copy	; copy block to VRAM
	
end:	; exit procedure
	ld	c,	0x01
	call	5	; wait for keypress
	; set screen mode and copy frame buffer to VRAM
	ld	a,	0x00	; screen mode
	ld	iy,	0xfc00
	ld	ix,	chgmod
	call	calslt	; perform inter-slot call to BIOS
	di
	ld	a,	0xf4	; set the border color to blue
	out	(0x99),	a
	ld	a,	0x87
	out	(0x99),	a
	ei
abort:
	ld	c,	0x00
	call	5	; terminate
	
copy:	; this code is not very pretty, probably better to use an inter-slot call to LDIRMV
	di
	ld	a,	0x00	; set register #14 (video A14-A16) to 0
	out	(0x99),	a
	ld	a,	0x8e
	out	(0x99),	a
	ld	a,	e		; set VRAM address
	out	(0x99),	a
	ld	a,	d
	and	a,	0x3f
	or	a,	0x40
	out	(0x99),	a
	ei
	
	push	bc
	pop	de
	ld	c,	0x98
	; do partial block first
	ld	b,	e
	otir
	ld	a,	0x00
	cp	d	; is there more to go?
	jp	z,	.d	; if not, exit
.l:	ld	b,	0x00	; copy a full 256 bytes
	otir
	dec	d
	jp	nz,	.l
.d:	ret
	
err1:	; file not found
	ld	de,	em1
	ld	c,	0x09
	call	5
	jp	abort
	
err2:	; file is < 48KB
	ld	de,	em2
	ld	c,	0x09
	call	5
	jp	abort
	
fcb:	equ	0x5c	; points to the first filename parameter at program startup
	
;	db	0x00		; logical drive
;fn:	ds	11,	' '		; file name, extension
;ex:	db	0x00		; extent number
;	ds	19,	0x00	; reserved
;cr:	db	0x00
;	ds	4,	0x00
	
em1:
	db	'File not found!',0x0d,0x0a,'$'	; CP/M strings end with '$' for some weird reason
em2:
	db	'File too short!',0x0d,0x0a,'$'
	
;buffer:	; must come after the end of the program
buffer:	equ	0x200
Pagina 1/5
| 2 | 3 | 4 | 5