Jump to content
IGNORED

singen 1024 bytes


Recommended Posts

is there an 6502 pendant to this z80 code:

 

;	_____		 __
;   /  _  \_______|  | ______  ______
;  /  /_\  \_  __ \  |/ /  _ \/  ___/
; /	|	\  | \/	<  <_> )___ \
; \____|__  /__|  |__|_ \____/____  >
;		 \/		   \/		 \/
; Generate a 1024 bytes long, 8bits, sinus-like curve.
; Grim/Arkos^Semilanceata

; Configuration
;cnf_math_singen_sizeopt_store	equ &2000
;cnf_math_singen_unsigned	equ 0

			; **********************************
			; * GENERATE 1024Bytes SINUS CURVE *
			; **********************************
				LET def_math_singen_sizeopt_store	= cnf_math_singen_sizeopt_store AND &FC00
				
math_singen_sizeopt:
			; Where is stored the sinus curve used as reference (1024bytes)
			; Address must be (and will be forced) at any &400 boundary.

			; autoconfig / do not change anything below
				LET def_math_singen_sizeopt_lenght 	= 1024
				LET def_math_singen_sizeopt_store_h	= def_math_singen_sizeopt_store/256
				LET def_math_singen_sizeopt_and_mask	= &03
				LET def_math_singen_sizeopt_or_mask	= def_math_singen_sizeopt_store_h AND &FC
				LET def_math_singen_sizeopt_store_q3	= def_math_singen_sizeopt_store_h+2
				LET def_math_singen_sizeopt_store_q4	= def_math_singen_sizeopt_store_h+3
			; Parabolic approximation:
			; sin(a) = ( (a-1)^2 ) - 1 @a[0, pi/2]

			; used here :
			; sin(a) = a^2 @ a[0,pi/2]
	
			; [0, 2pi] => [0, 1024]
	
			; 39 bytes long / 6405 NOPs
			; try to beat diz ! =)
	
				xor a
				
				ld bc, def_math_singen_sizeopt_store_q3*256 + def_math_singen_sizeopt_store_q4
				ld l,a
				ld e,l
				exx
				
				ld b,a; 256
				ld d,b
_math_singen_sizeopt_loop		
				ld c,b
				dec b
				ld e,b
				ld h,d
				ld l,d
_math_singen_sizeopt_square			add hl,de
				djnz _math_singen_sizeopt_square
					
				ld a,h
				exx
				
				rra
				ifndef cnf_math_singen_unsigned
					sub 128
				endif
				
				ld d,b
				ld h,c
				
				dec l
				
				ld (de),a; 3rd Quad
				ld (hl),a; 4th Quad
				
				cpl

				res 1,d
				res 1,h
				
				ld (de),a; 1st Quad
				ld (hl),a; 2nd Quad
				
				inc e
				
				exx
				
				ld b,c
				djnz _math_singen_sizeopt_loop
				
				ifndef cnf_math_singen_inline
					ret
				endif

Link to comment
Share on other sites

No one else has responded so I'll take a whack.

 

I can't read that Z80 gibberish so I'm not really sure what it's doing ;)

 

You can generate squares by accumulating a constantly varying difference.

That is, the difference between consecutive squares goes up linearly.

So to create a parabola you increment a counter and accumulate the

the count as you go.

 

This code is just off the top of my head and not really tested so take it with a grain of salt.

 

y is used for the counter (and table pointer)

x is used as a table pointer to mirror

eor #$FF flips it around the horizontal axis

 

sin0 is the first quadrant, sin1 the second etc

 

The count is accumulated with the low byte in lo and the high byte in a

and/or the table

 

 ldx #$FF
lda #$00
sta lo
tay
clc
bcc ENTER_LOOP

LOOP
tya
adc lo
sta lo
lda #$00
ADC sin3-1,y
ENTER_LOOP
sta sin3,y
sta sin2,x
eor #$FF
sta sin1,y
sta sin0,x
dex
iny
bne LOOP

 

 

(Edited to make it look a lot more like a sine and a lot less like an inverted cosine :P )

Edited by bogax
Link to comment
Share on other sites

thx. so in theory I would need a 256 byte sin first quadrant?

 

I have 256 byte singens f.e. :

 

//calc "sine" (or more like a set of parabolas)...

		ldy #$ff
!loop:	
loa:			lda #$18
		adc #$07
		sta loa+1
		bcc !+
		inc hia+1
		clc
!:
lo:			adc #0
		sta lo+1
		pla
hia:			adc #0
		pha
		sta sine128+$c0,x
		sta sine128-$40,y
		eor #$7f
		sta sine128+$40,x
		sta sine128-$c0,y

		inx
		dey
		cpx #$40
		bne !loop-


		ldx #0
// copy sine...
!:
		txa
		and #$40
		lsr
		lsr
		adc #$e0
		sta d018s,x
		txa
		and #$3f
		tay

		lda #%10101010
		sta sprite0-1,y
		lsr
		sta sprite1-1,y
		lda #%11111111
		sta sprite2-1,y

ls:			lda sine128+$20,y
		lsr
		adc #$60
ss:			sta sine2,x
		inx
		bne !-

		dec ss+2
		lda ls+1
		adc #$40
		sta ls+1
		bcc !-

 

ok...it is c64 code...

Link to comment
Share on other sites

well... and with this version is there a chance for a fixed point version? f.e. 8.8?

 

As in 16 bits total with 8 integral and 8 fractional bits ?

 

Not sure there's any point, a parabola is just not that close to a sine.

It only gives you something like 4 bits of accuracy in the worst case

 

I think the fractional part would be nonsense except for just a few table

entries

 

I did 256 bytes per quadrant because it looked to me like that was what the

Z80 code was doing and because it fit neatly with using the y register as

the counter.

 

What exactly do you want to end up with? Four quadrants in 256 entries in 8.8 format?

 

 

I might also mention that the code I posted does not result in 2's complement

althought that would be easy enough to do.

Link to comment
Share on other sites

I have seen a lot of singens in 256 byte or 1k intros for c64 and speccy.... and as I realised that they all use kind of parabolic approximation which I forgot completly... ;)

 

but they are not using "real" sinus/cosinus for calculation but for sinus like effects.... so maybe forget my fixed point thing... ;)

 

another interesting way would be to use the build in basic and floating point maths... that would be cool, too...

Link to comment
Share on other sites

Just for the hell of it, here's a couple that do 256 byte tables.

 

Not as neat, I couldn't think of an elegant way to use y for

the counter.

 

They're basically the same, one using selfmodifying code.

 

   ldx #$3F
  lda #$00
  tay
  sta cntr_lo
  sta cntr_hi
  sta acc_lo
  clc
  bcc ENTER_LOOP

LOOP
  lda cntr_lo
  adc #$10
  sta cntr_lo
  lda cntr_hi
  adc #$00
  sta cntr_hi
  lda acc_lo
  adc cntr_lo
  sta acc_lo
  lda sin+191,y
  adc cntr_hi
ENTER_LOOP
  sta sin+192,y
  sta sin+128,x
  eor #$FF
  sta sin+64,y
  sta sin,x
  iny
  dex
  bpl LOOP

 

   ldx #$3F
  lda #$00
  tay
  clc
  bcc ENTER_LOOP

LOOP
  lda #$00	   ;cntr_lo
  adc #$10
  sta LOOP+1	 ;sta cntr_lo
  bcc SKIP
  inc CNTR_HI+1 
SKIP
  lda #$00	   ;acc_lo
  adc LOOP+1	 ;add cntr_lo
  sta SKIP+1	 ;sta acc_lo
  lda sin+191,y
CNTR_HI
  adc #$00	   ;cntr_hi
ENTER_LOOP
  sta sin+192,y
  sta sin+128,x
  eor #$FF
  sta sin+64,y
  sta sin,x
  iny
  dex
  bpl LOOP

Link to comment
Share on other sites

  • 2 months later...
I have seen a lot of singens in 256 byte or 1k intros for c64 and speccy.... and as I realised that they all use kind of parabolic approximation which I forgot completly... ;)

 

but they are not using "real" sinus/cosinus for calculation but for sinus like effects.... so maybe forget my fixed point thing... ;)

 

another interesting way would be to use the build in basic and floating point maths... that would be cool, too...

The floating point ROM does not contain the sin() function, it's unfortunately in the BASIC rom, not in the mathpack. Anyhow, the implementation there is also pretty naive, it uses a 6th order Taylor approximation (thus, just a higher order polynomial) and is slow and not very precise. A much faster algorithm that can be implemented with a short table entirely in integer math is the CORDIC algorithm, used in the first pocket calculators. The idea is neat, and the table size is much shorter. Here's a short intro:

 

http://en.wikipedia.org/wiki/CORDIC

 

I've a C implementation of a cordic-based "arctan" function - requires a short table (depending on the precision you need), and only additions, subtractions and shifts. No multiplications, no division. Ideal for the 6502. Atari engineers had no big clue about mathematics when implementing the math-pack, I afraid.

 

So long,

Thomas

  • Like 1
Link to comment
Share on other sites

  • 5 years later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...