Vampier's quest for assembly [hopefully a n00b guide to assembly]

Pagina 6/21
1 | 2 | 3 | 4 | 5 | | 7 | 8 | 9 | 10 | 11

Van Creepy

Champion (335)

afbeelding van Creepy

04-03-2010, 22:31

Mind if I join in as a assembly and MSX dev noob? I'm experimenting with some basic assembly (loops, conditionals) and MSX (the keyboard in this case). So I started experimenting with waiting for a keypress:

keys    EQU     0xFBE5 // NEWKEY memory area


waitforkey
  ld b,11               // 11 rows total to scan
  ld hl, keys
.loop
  ld a,(hl)             // read the bits from the keyboard
  cp 255        
  jp nz,.keypressed     // keypressed
  inc hl                // next part of keyboard to scan
  djnz .loop            
  jp waitforkey
.keypressed:
  ret

Van Creepy

Champion (335)

afbeelding van Creepy

07-03-2010, 00:28

I'm trying to initialize screen 2 en define one tile, but something seems wrong. I'm only changing VDP R0 and R1 to change to screen 2, and that works. According to most docs the addresses for the charachter table, name table, and color table should be 0000H, 1800H and 2000H, but there not (according to openmsx debugger). Should I set R2 - R6 myself to get those addresses or am I missing something else?

Van Edwin

Paragon (1182)

afbeelding van Edwin

07-03-2010, 01:01

Yes, if you want to change the screen mode by writing VDP registers, then you have to do everything yourself. Which includes setting the correct table addresses and initialising VRAM when needed.

Van MOA

Champion (293)

afbeelding van MOA

07-03-2010, 01:16

Not sure what your question is, but here are some tips:

keys    EQU     0xFBE5 // NEWKEY memory area


waitforkey
  ld b,11
  ld hl, keys
.loop
  ld a,(hl)
  inc a  // INC A can be used instead of CP 255 if you do not further process the value in A
  ret nz  // instead of jumping to a RET, do a conditional RET
  inc l  // use the (faster) INC L instead of INC HL: the LSB never overflows (0xFBE5 + 11 = 0xFBF0)
  djnz .loop
  halt  // the NEWKEY area is updated in the bios ISR, so give the z80 a break
  jr waitforkey  // I'd use JR here instead of JP when speed is not an issue, as its opcode is shorter

Van Edwin

Paragon (1182)

afbeelding van Edwin

07-03-2010, 14:01

MOA: halt here is really not much more than a waste of a byte. The z80 can't actually take a 'break' and there is no timing advantage.

However, as the comment says, this table is updated in the BIOS ISR, so interrupts must be turned on for this routine to work.

Van Creepy

Champion (335)

afbeelding van Creepy

07-03-2010, 14:02

Oh, I had no questions about the waiting for the keypress. Just something I posted for others (newbies like me) to see. But thanks for the tips, I had not discovered "ret nz" and "halt" yet Smile

Van MOA

Champion (293)

afbeelding van MOA

07-03-2010, 23:02

MOA: halt here is really not much more than a waste of a byte. The z80 can't actually take a 'break' and there is no timing advantage.

However, as the comment says, this table is updated in the BIOS ISR, so interrupts must be turned on for this routine to work.

I guess you are right. Modern processors would enter some low power state to save power consumption when a halt is encountered. If a z80 doesn't do that, just keep polling that buffer and save a byte Wink

Van Huey

Prophet (2694)

afbeelding van Huey

29-03-2010, 13:09

Ok. Here is the collision detection routine I made (and use) for my little project. It is based on the collision detection routine of Daniel Bienvenu (so real credits are for him).
Perhaps it is usefull for other beginners (or fun for the experts to laugh at Tongue)

; =============================
; collision
;
; checks colliosn between 2 sprites.
;  
; IX contains the npc sprite
; IY contains the mc/bullet/weap sprite
;
; result is returned in the C flag
;
;
; =============================				
collision:

		ld a,(IX+_NPC_y)			; y pos + 32 + offset
		add a,32				; add 32 because the sprite can be outsid the top of the screen
		add a,(IX+_NPC_yoffset)		
		ld e,a
		ld d,0					; result in de
		
		ld a,(IY+_MC_y)
		add a,32
		add a,(IY+_MC_yoffset)
		ld l,a
		ld h,0				; result in hl

		ld b,(IX+_NPC_ysize)
		
		or a					; reset C flag for sbc
		sbc hl,de				; substract hl with de
		jr nc, 1f				; HL >= DE
		
		ld b,(IY+_MC_ysize)
		
		add hl,de				; restore sbc action before swapping
		ex de,hl
		or a
		sbc hl,de
		
1:
		ld a,l					; holds the y axis difference between collisions windows 
		cp b					; inside the collision window?
		jr nc, endcollision			; no collision possible end the check


		ld a,(IX+_NPC_x)			; x pos + 32 + offset
		add a,32					; add 32 because the sprite can be outsid the top of the screen
		add a,(IX+_NPC_xoffset)		
		ld e,a
		ld d,0					; result in de
		
		ld a,(IY+_MC_x)
		add a,32
		add a,(IY+_MC_xoffset)
		ld l,a
		ld h,0					; result in hl
		
		ld b,(IX+_NPC_xsize)
	
		or a						; reset C flag for sbc
		sbc hl,de					; substract hl with de
		jr nc, 2f					; HL >= DE
		
		ld b,(IY+_MC_xsize)

		
		add hl,de					; restore sbc action before swapping
		ex de,hl
		or a
		sbc hl,de	
					
2:				
		ld a,l						; holds the x axis difference between collisions windows 
		cp b											
		
endcollision:
								; carry holds the result -> C = collide, NC = nocollide.
	ret

Van Edwin

Paragon (1182)

afbeelding van Edwin

30-03-2010, 20:11

That looks rather complicated for what it needs to do. I optimised the hell out of the collision checker for Universe: Unknown since it had to do a lot of them and found that for an 8 bit check you actually only need a few instructions. It takes much more cpu to actually get the data from memory.

;
; Collision
;
;    Check for collision between objects   
;
; IN: IX - first object record
;     IY - second object record
; OUT: Carry set = collision
;
Collision
	ld	b,(IX+loc_x)
	add	(IX+offset_x)
	ld	c,(IX+size_x)
	ld	d,(IY+loc_x)
	add	(IY+offset_x)
	ld	e,(IY+size_x)
	call	CalcCollision
	ret	nc
	ld	b,(IX+loc_y)
	add	(IX+offset_y)
	ld	c,(IX+size_y)
	ld	d,(IY+loc_y)
	add	(IY+offset_y)
	ld	e,(IY+size_y)
	; run through to calccollision

;
; CalcCollision
;
;    1D collision check
;
; IN: B = Location object 1
;     C = Size object 1
;     D = Location object 2
;     E = Size object 2
; OUT: Carry set = collision
;
CalcCollision:
        ld      a,d     
        sub     b
        jr      c,.switch       ; x1>x2
        sub     c
        ret
.switch:
        neg
        sub     e
        ret

Note: This is strictly 8 bit. So you'll need to fiddle with it a bit in order to support EC.
You can even remove the "ld a,d" by using a for input directly. Of course, it's much more efficient to evaluate the storage of data to make retrieval quicker.

Van Huey

Prophet (2694)

afbeelding van Huey

30-03-2010, 23:22

Erh, are U sure this should work? "add (IX+offset_y)" has no effect as 'a' is not used....

Pagina 6/21
1 | 2 | 3 | 4 | 5 | | 7 | 8 | 9 | 10 | 11