Putting an image in the screen?

Страница 2/5
1 | | 3 | 4 | 5

By Daemos

Paragon (2044)

Аватар пользователя Daemos

14-01-2011, 23:17

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

Took some time to think this little routine over but after some scrolling through my z-80 manual and trying out I figured line by line what you are doing here. NOW that is code beyond the point of efficiency and I mean that in a positive way. You basicly do xor a because it saves M + T cycles compared to ld a,0. And I guess you do the same for ld bc,&h209a

Now lets see if I understand it right here:


	ld	hl,palette ;load the predefined palette data into the memory
	call	setpalette ;call the routine below
	ret ;return after finished

SetPalette:
	xor		a ;put register a to 0 with just 1M and 4 T states
	di ;disable interupt to make sure things wont go wrong
	out		($99),a ;select palette adres 0
	ld		a,16+128 ;set pallete register
	out		($99),a ;tell VDP about it
	ld		bc,$209A ;very clever basicly you do something like:
;ld b,&h20 ;select amount of writes 32 times
;ld c,&h9a ;port 3 of the VDP, can't find proper documentation on this can you please shed more light on this?? EDIT: found out about this one. 
;Furthermore using ld bc uses about 2-3 M states less

	otir ;Took me a very long time to figure this one but basicly it keeps writing to port
;defined by register c, b times and keeps incrementing hl until b is zero and then continues
	ei ;enable interupt again
	ret ;return to position where the call came from

I am actually getting good at this ASM stuff. Thank you all so far on your helpfull responses.

I will look into the BDOS calls asap. I have furthermore tried the fast copy to vram trick and it works Smile black backround yeah!

By Edwin

Paragon (1182)

Аватар пользователя Edwin

15-01-2011, 01:40

That's pretty accurate. Some comments though:
ld hl,palette ;load the predefined palette data into the memory
Better say "point HL to predefined palette data in memory at label 'palette'"

And with OTIR you forgot to mention that it reads a byte from address pointed to by HL before it writes it to port C. I assume you did get that though.

Seems you're making quick progress indeed. Keep it up!

By Daemos

Paragon (2044)

Аватар пользователя Daemos

15-01-2011, 21:01

Ok with all your help I have come this far Smile writing a square on a black screen that changes color upon keypress and offcourse the shift (huh!!??, yes I was lazy) key exits the program.

;Write a colored block on a black backround
;space key changes the color of the block
;shift exits the program

        ORG   &HC000
CHMOD:  EQU   &H5F ;bios call change screen to A



;screen mode 5

        LD    A,5
        CALL  CHMOD

;set backround color
        DI
        LD    A,&B00000001 ;black
        OUT   (&H99),A
        LD    A,7+128
        EI
        OUT   (&H99),A

;write VRAM full of black stuff

        DI
        LD    A,0
        OUT   (&H99),A
        LD    A,14+128
        OUT   (&H99),A
        LD    A,0
        OUT   (&H99),A
        SET   6,A
        OUT   (&H99),A
        EI
        HALT ;Wait until finished, the Z80 continues way faster then this set operation

        LD    BC,&H80D4 ;norakomi speed trick ;)
        XOR   A

BLOOP:
        OUT   (&H98),A ;write 128 bytes at each loop
        DJNZ  BLOOP
        DEC   C ;211 times so VMRAM is full of black
        XOR   A
        CP    C ;211 times completed??
        LD    B,128 
        LD    A,0 ;use ld this time or zero flag gets set!
        JP    NZ,BLOOP ;211 times?? no?? write another 128 bytes. yes?? done.

      

;write something in VMRAM
;Determine X position in D
DRAW:   LD    H,0
        INC   C ;change color of block
        LD    D,32
        SET   7,D
        LD    E,0
        SET   6,E
        JR    SETVDP

ADDE:   RES   7,D ;check adress if full reset MSB and add 1 bit to higher adress counter
        INC   E
        RET


SETVDP: DI
        LD    A,&B00000001
        OUT   (&H99),A
        LD    A,14+128
        OUT   (&H99),A
        LD    A,D
        OUT   (&H99),A
        LD    A,E
        OUT   (&H99),A
        LD    B,8        
        EI

;write this random stuff into vram

LOOPV:  LD    A,C ;write 8 bytes of data in ram C determines the color
        OUT   (&H98),A
        DJNZ  LOOPV
        LD    A,D
        RLC   A ;check adress if full reset MSB and add 1 bit to higher adress counter

        CALL  NC,ADDE
        LD    A,D
        LD    D,128 ;shift VRAM adress one whole line and write back in D
        ADD   D
        LD    D,A



        INC   H ;lines written
        LD    A,16 ;16 lines written?? end writing to VRAM. result a perfect square on the screen.
        CP    H
        JP    NZ,SETVDP



;init wicked screen manupilation

LOOP:
        LD    HL,&HFBED ;check for spacekey.
        LD    A,(HL)
        BIT   0,A

        JR    Z,DRAW ;true?? redraw square over older one in new color.

        JR    KEY

KEY:

        LD    HL,&HFBEB
        LD    A,(HL)
        BIT   0,A
        JR    Z,STOPP
        JR    LOOP

;shift pressed?? stop program set screen back to 0

STOPP: 
        LD    A,0
        CALL  CHMOD ;screen 0

        RET


        END  

Especially the writing the block into VRAM. There has GOT to be a easier way of doing this right?

What about the making of the black backround. This is not engine high speed fill command. How can that be done in code?

By Edwin

Paragon (1182)

Аватар пользователя Edwin

15-01-2011, 22:57

The command engine is the easier way. Look at the MAP link that norakomi gave you for examples on how to use vdp commands.

Also, your description of "halt" is way off. It waits for the next interrupt. In this case it's likely the VDP vblank interrupt, meaning that the monitor is just done drawing the frame. But there really is nothing that needs waiting for. Unless it is to prevent tearing during display, but you'd turn displaying for that.

By Daemos

Paragon (2044)

Аватар пользователя Daemos

16-01-2011, 01:00

When I do no put in the halt command the VRAM fill with black pixels fails. It starts filling at the adress given of the other command. I dont know why but the halt fixes the problem. I will check the assembly pages again if I can come up with even better ways of doing this black fill.

By GhostwriterP

Paladin (683)

Аватар пользователя GhostwriterP

16-01-2011, 11:47

Looking at your loop structure I could not help suggesting the following:

        LD    C,&D4
        XOR   A
CLOOP:
        LD B,128
BLOOP:
        OUT   (&H98),A ;write 128 bytes at each loop
        DJNZ  BLOOP
        DEC   C ;211 times so VMRAM is full of black
        JP    NZ,CLOOP ;211 times?? no?? write another 128 bytes. yes?? done.

or:

        LD    BC,&6A
        XOR   A
BLOOP:
        OUT   (&H98),A ;write 256 bytes at each loop
        DJNZ  BLOOP
        DEC   C ;106 x 256 bytes VMRAM is full of black
        JP    NZ,BLOOP ;106 times?? no?? write another 256 bytes. yes?? done.

Note that 'DEC C' also sets the zero flag and hence no comparison needs to be made with zero using 'CP C' command.

By Daemos

Paragon (2044)

Аватар пользователя Daemos

16-01-2011, 14:22

Way more efficient. Thanks. Btw shouldn't the b register somehow get set back to 128 in the second example?

By hap

Paragon (2042)

Аватар пользователя hap

16-01-2011, 15:00

no, b is 0: 256 times.

By GhostwriterP

Paladin (683)

Аватар пользователя GhostwriterP

16-01-2011, 15:05

In the second example b is initialized as 0 (ld bc,&006A). Starting a djnz loop with zero, 0 equals 256.
Once the djnz loop is completed b is already 0 (=256) for the next loop.

By Daemos

Paragon (2044)

Аватар пользователя Daemos

16-01-2011, 15:17

Ah Smile I see. Very clever and very fast. Your example works btw but I have found an even faster way. It requires like a ten times more in code but the screen gets filled up in less then a millisecond.

The manual calls it: high speed move VDP to VRAM. you will think by now: duuh we have been telling you that way before you tried this filling stuff. Eek! sorry. learning comes in steady steps and sometimes you learn new things by going the other way.

The B register thingy explanes some of my code behaviour as well. Now I understand why some programs where doing wierd things because B was set to 255.

But now comes a new question. You can actually see the filling of the screen happen which is offcourse not pretty. The solution is to disable the screen display for the moment of execution and reenable it after the execution is completed. I understand how to do that however I have to change the blanking bit in register 1. Offcourse the other bits need to remain intact or else...
How can I read out the previous byte out of the register so that I can set the right bit and shoot it back into the VDP?
I allready know about the BIOS call that does the actual same thing but there are plenty of bits that cannot be set via BIOS calls.

Страница 2/5
1 | | 3 | 4 | 5