Scaling hardware?

Ask anything your want about Mega/SegaCD programming.

Moderator: Mask of Destiny

RamiroR
Interested
Posts: 18
Joined: Tue Jun 02, 2009 10:45 pm

Scaling hardware?

Post by RamiroR » Wed Mar 30, 2011 12:15 am

Has anyone here managed to actually do something with it? I just seriously DON'T UNDERSTAND the principle the way it is explained on the documents..

Chilly Willy
Very interested
Posts: 2854
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Wed Mar 30, 2011 5:23 am

The stamp map is a name table much like the Layer A and B tables in the Genesis - it's a map of tiles that makes the display. In the case of the stamp map, it makes the image that will be rotated/scaled.

You specify the start position in the output bitmap, how wide the output will be (in pixels), and how tall it will be (in lines). Then for each line: pull entry from trace table - the trace table entry has the start x, start y, delta x, and delta y values giving the starting position in the source stamp map, as well as the deltas; then output a pixel from the starting position and add the deltas to that position for the next position. Repeat for all pixels in the line, then pull the next trace table entry and do the next line.

The start values and deltas are fixed point numbers to allow fine control over the scaling/rotating. The start values are 13.3 fixed point, and the deltas are 4.11 fixed point. The ASIC handles the values as 13.11 24-bit fixed point numbers when tracing a line. The start values are always positive, while the deltas have a sign bit in the msb of the word.

RamiroR
Interested
Posts: 18
Joined: Tue Jun 02, 2009 10:45 pm

Post by RamiroR » Thu Mar 31, 2011 6:19 pm

Wow.
Thank you, so much. I think you'd tried to explain me this some other time. But now I really get it. It's still quite a mess to rotate an image, or scale it, lots of coding headache for me, yay.

It's funny to think that when I first heard of the Mega CD and its scaling/rotation capabilities, I thought you had some simple "x scale" "y scale" and even "degrees" numbers to set.

RamiroR
Interested
Posts: 18
Joined: Tue Jun 02, 2009 10:45 pm

Post by RamiroR » Thu Mar 31, 2011 6:28 pm

Also, I'm guessing I'm gonna need fixed point sine and cosines tables.. do you know where I can get one?

Chilly Willy
Very interested
Posts: 2854
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Thu Mar 31, 2011 9:17 pm

RamiroR wrote:Also, I'm guessing I'm gonna need fixed point sine and cosines tables.. do you know where I can get one?
You'll find them in FPSs like Doom or Wolf3D.

They're easy enough to generate - you'll find code on google all over, and there are sites that will even generate tables for you:

http://www.daycounter.com/Calculators/S ... ator.phtml

RamiroR
Interested
Posts: 18
Joined: Tue Jun 02, 2009 10:45 pm

Post by RamiroR » Sat Apr 02, 2011 12:57 am

So, I've been thinking a lot about it, and maths seem to be needed for rotation. And I SUCK at maths.
The main problem is determining the delta values for each angle, so that the image keeps its correct size. I've been trying to understand how I could do this and this is how I understand it so far:
Image
Here I'm showing how I THINK a image can be rotated 45 degrees clockwise. I don't know if this makes sense, I am BAD at maths.

mic_
Very interested
Posts: 265
Joined: Tue Aug 12, 2008 12:26 pm
Location: Sweden
Contact:

Post by mic_ » Sat Apr 02, 2011 5:51 pm

The deltas when drawing one line should be

dx = cos(a) / scaling
dy = sin(a) / scaling

To update the starting position for the next line you use another pair of deltas:

dxdy = sin(a) / scaling
dydy = cos(a) / scaling

And the starting position for the first line, with the rotation center at v,w should be:

startx = dx*(x-v) + dxdy*(y-w)
starty = dy*(x-v) + dydy*(y-w)

Eke
Very interested
Posts: 864
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Sat Jan 07, 2012 10:08 am

I was wondering about the timing of GFX operations.

Gens is using some kind of timing table based on the number of tiles to draw per line but I don't know where the results come from. As for the formula given in the official manual, I have some hard time figuring what it means.

I understand that the minimal number of cycles is proportional to the image buffer Vdot size but then i can't figure the relation with Hdot size and Hdot offset (what does SHR means btw ? Logical shift to the right ? Does not make much sense...)

Has anyone some more infos or measurements ?

Chilly Willy
Very interested
Posts: 2854
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Sat Jan 07, 2012 6:29 pm

Unfortunately, the timing is the worst part of the current scans of the SCD docs. It is also the part with the least said about it in the docs. Right now, I think you just have to do an example and time it. My own guess as to timing is to remember that the word ram requires three clock cycles per access, the ASIC works one pixel at a time, then multiply by the number of accesses per operation to calculate one pixel, then add four access per line for the trace table fetches. That should get you close to a real world figure.

Eke
Very interested
Posts: 864
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Sat Apr 14, 2012 9:01 am

I had some time working on Mega CD emulation for genesis plus and ended up with US BIOS fully running and rotation/scaling effects working correctly.

As for timings, I started making blind calculations using the number of theoretical accesses, i.e at least 2 for start position, then for each dot:

- 2 access for deltas (unless it is latched somewhere for the whole line)
- 1 access for stamp map table
- 1 access for stamp generator
- 1 access for reading image buffer source pixel
- 1 access for writing pixel back to image buffer

I thought initially the number of clocks per access should be one CPU clock (= 4 ASIC clocks) as the RAM used is rated at 80ns but using 3 CPU clocks like you are saying might be a little bit more accurate. Where is this coming from anyway ?

Anyway, this is working fine with these timings although I am not able to emulate real games yet.

I also tried other BIOS images but oddly, japanese and european Mega CD 1 BIOS only show static Mega CD logos, without any rotating/scaling effects and without SEGA logo moivng around. BIOS is not freezed either as I can enter the menu just fine. Does someone know if those BIOS are doing anything special compared to US one regarding graphical effects ? Or faced the same issue when initially emulating BIOS ?

EDIT: figured those 2 BIOS make use of Timer Interrupt to synchronize GFX effects, proper emulation of level 3 interrupts fixed the intro.

Chilly Willy
Very interested
Posts: 2854
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Sat Apr 14, 2012 2:43 pm

Eke wrote:I thought initially the number of clocks per access should be one CPU clock (= 4 ASIC clocks) as the RAM used is rated at 80ns but using 3 CPU clocks like you are saying might be a little bit more accurate. Where is this coming from anyway ?
The part of the timing you CAN read specifically states that every CPU access and every refresh cycle adds exactly three cycles to the total time needed for the operation. Clearly, three clock cycles is the fundamental bus cycle time for word ram.

Eke
Very interested
Posts: 864
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Sun Apr 15, 2012 11:14 am

You must be right, I initially interpreted the manual was saying that CPU access time is multiplied by 3 in case of access during graphics operation, not that total number of CPU clocks = number of access x 3, but now that you mention it, it seems more logical indeed
:)

Chilly Willy
Very interested
Posts: 2854
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Sun Apr 15, 2012 5:19 pm

Yeah, it was worded funny, but if you've read enough translated tech manuals before, you could figure out what they meant. That's half the fun of Japanese manuals - wading through the Engrish. :lol:

Anywho, it's possible that those three clocks could be broken into 1 cycle for bus arbitration and two for the actual cycle. We really don't know how the ASIC handles the bus at all. If it were indeed that way, it's POSSIBLE that the when the ASIC doesn't need to arbitrate for the bus that it can do accesses every two cycles... every cycle would assume using fast page mode or something similar, and I don't see Sega going that far for an add-on released in the early 90's.

Nemesis
Very interested
Posts: 773
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Mon Apr 16, 2012 12:29 pm

One thing I'm interested in with the scaling hardware is the contents of the missing page 45 from the MegaCD Hardware Manual. If you look at the table of contents, it said page 45 detailed a "Special case" with the rotation scaling. I'm really curious as to what that special case might be. The documentation in the "MegaCD Software Development Manual" doesn't seem to mention any kind of special case when dealing with rotation, but it does seem like a more abbreviated manual.

tristanseifert
Interested
Posts: 35
Joined: Tue Sep 06, 2011 2:16 am
Location: Austin, TX
Contact:

Post by tristanseifert » Sat Apr 21, 2012 11:32 pm

Has anyone ever written functional code to scale and/or rotate an image? I've been trying to figure out how to do it, but I just haven't been getting places as I just can not figure out certain things (the format of the stamp map (I'd assume it's just a word to indicate the tile in the art area)) but I've come up with this code to rotate an image a tiny bit, but I haven't been able t test it yet due to the reasons above. Anyways, here's the code (if someone can figure out how to make it work that'd be fantastical™)

Code: Select all

		org		$8200								; Offset for the Scaling code in PRG RAM
		
; Stamp Map Table: $A0000
; Image buffer: $9E000
; Line Definition Table: $96000
;
; Sub CPU Bitfield - $FFFF802F
; |---- Bit 0: Set when GFX op is done
; Main CPU Bitfield - $FFFF801F
; |---- Bit 0: Set when Main CPU transfer of tiles to VRAM has completed.

EntryPoint:
		andi.b	#$FA, $FF8003						; Set 2 Mbit mode
		nop
		ori.b	#2, $FF8003							; Make sure the Word RAM is returned to us.
		move.b	#0, ($FFFF802F).w					; Clear GFX ops flag
		
@waitOnASIC:
		btst	#15, ($FFFF8058).w					; Is the ASIC ready?
		bne.s	@waitOnASIC							; If not, wait until the ASIC is ready.
		
		moveq	#0, d0								; Clear d0
		move.l	d0, d1								; Clear d1
		moveq	#$4, d2								; Offset Y by 4 pixels
		lea		LineDefinitionTable, a0				; Load line definition table to a0
		move.w	#$FFF, d0							; Loop through all 4096 entries		
		
@initLineDefs:
		cmp.b	#8, d1								; Have we processed 8 lines so far?
		bne.s	@writeValue							; If not, write the value.
		
		addq.w	#1, d1								; Increase Y value.
		
@writeValue:
		move.w	d1, 2(a0)							; Write the Y value.
		move.w	d2, 6(a0)							; Set ∆Y to equal 4
		lea		$8(a0), a0							; Increase the address pointer to the next line def
		dbf		d0, @initLineDefs					; Loop until all definitions are written.
		
		lea		$96000, a0							; Location of line definition table in Word RAM
		lea		LineDefinitionTable, a1				; Line definition table is in a1
		move.w	#(LDT_End-LineDefinitionTable), d0	; Get the length of the line definition table to d0
		lsr.w	#1, d0								; Divide by 2 to get length in words
		
@copyLDTLoop:
		move.w	(a1)+, (a0)+						; Copy a byte of the line definition table
		dbf		d0, @copyLDTLoop					; Loop until the entire table is written.
		
		move.w	#$5, ($FFFF8058).w					; 16x16 stamps, 16x16 screen size, exceeded data is repeated
		move.w	#$8000, ($FFFF805A).w				; Location of stamp map table ($A0000)
		move.w	#$1F, ($FFFF805C).w					; 32 vertical cells
		move.w	#$7800, ($FFFF805E).w				; Image buffer at $9E000
		move.w	#0, ($FFFF8060).w					; First offset in image buffer
		move.w	#$140, ($FFFF8062).w				; Write 320 horizontal pixels
		move.w	#$E0, ($FFFF8064).w					; Write 224 vertitical lines
		move.w	#$5800, ($FFFF8066).w				; Line definition table at $96000 (Also begins graphics op)

@waitForASICCompletion:
		btst	#15, ($FFFF8058).w					; Is the ASIC done?
		bne.s	@waitForASICCompletion				; If not, wait until the ASIC is done.
		
		ori.b	#1, $FF8003							; Return Word RAM to Main CPU
@waitForWRAMSwap:
		nop
		btst	#0, $FF8003							; Has the RAM been returned yet?
		beq.s	@waitForWRAMSwap					; If not, check again.
		
		bset	#0, ($FFFF802F).w					; Set the GFX operation complete flag.

		rept	$20									; 64 no-operations is enough for the Main CPU to notice we're done
		nop
		nop
		endr
		
@waitForMainCPU:
		btst	#0, ($FFFF801F).w					; Is the Main CPU done transferring data?
		bne.s	@waitForMainCPU						; Wait until that bit becomes 0 (indicates complete DMA transfer of art)

		rts											; Return control to Sub CPU code
		
LineDefinitionTable:
		rept	$1000
		dc.w	0, 0, 0, 0							; X, Y, ΔX, Δy
		endr
LDT_End:
[/code]

Post Reply