Scaling hardware?

Ask anything your want about Mega/SegaCD programming.

Moderator: Mask of Destiny

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

Post by Chilly Willy » Sat Apr 21, 2012 11:53 pm

Just use $80xx.w for all hardware references. Leave off all the Fs.

There's no such thing as btst #15.

Code: Select all

loop:
    btst    #15,word_ptr
    bne.s   loop
should be

Code: Select all

loop:
    tst.w   word_ptr
    bmi.s   loop
You could also do

Code: Select all

loop:
    btst    #7,hi_byte_of_word_ptr
    bne.s   loop
Some assemblers will assume that's what you mean when you try to do bit operations over 7, but it's sloppy programming relying on a questionable assumption by a specific revision of an assembler.

If you plan to use more bits from the register, this would be more proper

Code: Select all

loop:
    move.w  word_ptr,d0
    bmi.s   loop

tristanseifert
Interested
Posts: 35
Joined: Tue Sep 06, 2011 2:16 am
Location: /dev/sa0
Contact:

Post by tristanseifert » Sun Apr 22, 2012 12:06 am

Chilly Willy wrote:Just use $80xx.w for all hardware references. Leave off all the Fs.
Well yes, but the fact that my values are wrapped in ($FFFF80xx).w's makes the assembler automagically convert. If I do it the other way, I just get confused. Personal preference, I presume.
Chilly Willy wrote: There's no such thing as btst #15.

Code: Select all

loop:
    btst    #15,word_ptr
    bne.s   loop
should be

Code: Select all

loop:
    tst.w   word_ptr
    bmi.s   loop
You could also do

Code: Select all

loop:
    btst    #7,hi_byte_of_word_ptr
    bne.s   loop
Some assemblers will assume that's what you mean when you try to do bit operations over 7, but it's sloppy programming relying on a questionable assumption by a specific revision of an assembler.

If you plan to use more bits from the register, this would be more proper

Code: Select all

loop:
    move.w  word_ptr,d0
    bmi.s   loop
Meh... just had to point out my shitty coding skills =P But yeah, ASM68k didn't bitch about it and converted it automagically I presume, so I assumed it was perfectly fine. I guess your way works, too. But at least now I can rest assured knowing my code is proper =P

But of course, this brings me back to my original question. Has anyone ever gotten the scaling HW working?

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

Post by Chilly Willy » Sun Apr 22, 2012 3:22 am

I saw $FF80xx in a number of places, and that WON'T convert. Of course, $FF80xx is fine, it just uses a long absolute address instead of a short. In order to avoid mixing the two, it's better to just use $80xx instead. But, that's just a matter of coding preference and everyone is entitled to their own. :D

You might use my mode 1 example to try running scaling tests on the CD. That avoids needing to make a bootable cd, and all that entails. Just add a command to my cd.s file that runs code for scaling instead of playing a CD.

tristanseifert
Interested
Posts: 35
Joined: Tue Sep 06, 2011 2:16 am
Location: /dev/sa0
Contact:

Post by tristanseifert » Sun Apr 22, 2012 3:59 am

Chilly Willy wrote:I saw $FF80xx in a number of places, and that WON'T convert. Of course, $FF80xx is fine, it just uses a long absolute address instead of a short. In order to avoid mixing the two, it's better to just use $80xx instead. But, that's just a matter of coding preference and everyone is entitled to their own. :D

You might use my mode 1 example to try running scaling tests on the CD. That avoids needing to make a bootable cd, and all that entails. Just add a command to my cd.s file that runs code for scaling instead of playing a CD.
That is indeed true. Access to ROM might make testing quite a bit easier. I have a Mode 2 testbed I wrote, so I might try it using that.

You wouldn't by any strange chance know the format for the stamp table? Is it just like the MD name table format?

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

Post by Chilly Willy » Sun Apr 22, 2012 5:38 pm

Not quite. First, stamps can be two sizes - 16x16 or 32x32. The register at 8058 controls the stamp map:

b2 = SMS - stamp map size; 0 = 256x256, 1 = 4096x4096
b1 = STS - stamp size; 0 = 16x16, 1 = 32x32
b0 = RPT - repeat; 0 = clamp to stamp map, 1 = repeat stamp map

The repeat bit is like clamping the texture on a regular VDP, or setting it to wrap.

The stamp map entries are a word with the bits set like this:
b15 = HFLP - horizontal flip
b14-13 = RT1-0 - rotation; 00 = no rotation, 01 = 90 degrees, 10 = 180, 11 = 270 degrees (all counter-clockwise); note that the h-flip is done first before the rotate bits are considered.
b12-11 = 0
b10-0 = stamp index

The stamps themselves are NOT laid out like tiles in the MD - the 16x16 stamp is actually laid out as sixteen 4x4 tiles. Each tile is like this

Code: Select all

0 1 2 3
4 5 6 7
8 9 A B
C D E F
and the tiles are laid out like this:

Code: Select all

0 4 8 C
1 5 9 D
2 6 A E
3 7 B F
32x32 stamps are very similar, being made of 4x4 tiles as well. You layout 64 tiles in an 8x8 pattern to make the 32x32 stamp. Go vertically, then horizontally, just like the 16x16 stamp.

Code: Select all

0 8 G O W e m u
1 9 H P X f n v
2 A I Q Y g o w
3 B J R Z h p x
4 C K S a i q y
5 D L T b j r z
6 E M U c k s a'
7 F N V d l t b'
Stamps always start at offset 0 in the word ram, and stamp 0 cannot be used for image data - it CAN be used by the CPU as scratch ram. Note that when using 32x32 stamps, the two lsb of the stamp index are ignored. You can think of it like four 16x16 stamps being used to make a single 32x32 stamp, just with the layout above instead of actually being four 16x16 stamps laid out. So you actually only have 511 stamps in 32x32 mode.

The stamp map base address sets the address of the stamp map, whose entries were shown above. The number of valid offset bits in the base address depends on the stamp map size and the stamp size.

If the stamp map is 256x256:
16x16 stamps: b15-7 = A17-9
32x32 stamps: b15-5 = A17-7
and if the stamp map is 4096 x4096:
16x16 stamps: b15 = A17 (should be set to 1)
32x32 stamps: b15-13 = A17-A15

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Sun Apr 22, 2012 8:39 pm

Chilly Willy wrote:The stamps themselves are NOT laid out like tiles in the MD - the 16x16 stamp is actually laid out as sixteen 4x4 tiles. Each tile is like this

Code: Select all

0 1 2 3
4 5 6 7
8 9 A B
C D E F
That doesn't sound right. Those should be 8x8 tiles (according to the manual).

Otherwise, your description of the layout is spot on.

tristanseifert
Interested
Posts: 35
Joined: Tue Sep 06, 2011 2:16 am
Location: /dev/sa0
Contact:

Post by tristanseifert » Sun Apr 22, 2012 8:45 pm

TascoDLX wrote:
Chilly Willy wrote:The stamps themselves are NOT laid out like tiles in the MD - the 16x16 stamp is actually laid out as sixteen 4x4 tiles. Each tile is like this

Code: Select all

0 1 2 3
4 5 6 7
8 9 A B
C D E F
That doesn't sound right. Those should be 8x8 tiles (according to the manual).

Otherwise, your description of the layout is spot on.
That would be correct if that was to describe 32x32 mode - you need 4 horizontal 8x8 tiles to get 32x32 pixels.

However, to make 16 horizontal pixels, you would need four 4x4 tiles. Hopefully any of that made sense.

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Sun Apr 22, 2012 9:06 pm

tristanseifert wrote:That would be correct if that was to describe 32x32 mode - you need 4 horizontal 8x8 tiles to get 32x32 pixels.

However, to make 16 horizontal pixels, you would need four 4x4 tiles. Hopefully any of that made sense.
That would make a whole lot more sense if there was such a thing as a 4x4 tile. :P

16x16 stamp (from 8x8 tiles)

Code: Select all

A C
B D
32x32 stamp (from 8x8 tiles)

Code: Select all

A E I M
B F J N
C G K O
D H L P
Clear?

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

Post by Chilly Willy » Sun Apr 22, 2012 11:59 pm

Uh... not enough coffee this morning. :lol:

It's 8x8 tiles. Look at TascoDLX's post for how they are laid out.

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

Post by Eke » Sat May 05, 2012 4:33 pm

Does anyone know if Sonic CD title screen uses the rotation/scaling hardware for the clouds ?

I have trouble getting them right and basically validated my implementation through the various BIOS animations that demonstrates this feature and did not notice anything wrong.

Any ideas where this might comes from ?


Image


I also have a question regarding Word-RAM and mode switching: to which part is assigned Word-RAM when switching from 1M to 2M mode ? I assume that if RET bit is set as well, it is set to MAIN-CPU side but is it the default ? What if RET bit is not set when MODE bit is changed from 1 to 0 ?

Also, do any games rely on banks interlacing when mode is switched ? Or is it safe to simply emulate them as two consecutive banks and assume games would simply setup Word-RAM data again after mode is changed and not care about what was previously written ? It indeed makes a lot of things simpler for memory accesses and I doesn't like the idea of using two 256K buffers and copying everything back from one to another when mode is switched like Gens is doing. But the simple fact it does made me think it was maybe required by some game ?

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Sat May 05, 2012 7:36 pm

Yeah, the sonic CD intro uses the scaling rotation chip.
And yeah, some games relies on data conservation after memory bank mode switch. Indeed the way it is done in Gens is not elegant, i did it for faster memory read / write access but i would do it differently today.

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Sat May 05, 2012 9:45 pm

Eke wrote:I also have a question regarding Word-RAM and mode switching: to which part is assigned Word-RAM when switching from 1M to 2M mode ? I assume that if RET bit is set as well, it is set to MAIN-CPU side but is it the default ? What if RET bit is not set when MODE bit is changed from 1 to 0 ?
Basically the same rules apply in both 1M and 2M with regards to the 2M assignment.
- If DMNA is set by main (regardless of the current mode), sub will get the wordram when switched to 2M.
- Conversely, if RET is set by sub, main will get it when it swtiches to 2M.
- Obviously synchronization matters (i.e., last one wins out).

Also:
- If RET is cleared by sub (e.g., to switch the 1M bank), 2M assignment is not affected.
- If DMNA is cleared by main, a 'swap request' is signaled to the sub (not accurately described in the manual). This will affect the register bits that are read, but not the wordram assignments.

Both Rise of the Dragon and Ultraverse Prime depend on correct emulation of this behavior. ROTD sets DMNA in 1M mode, and UP sets RET in 1M mode (bank switching) before switching to 2M. All of this is based on my personal testing a couple years back.

Note that this has never worked right in Fusion. ROTD is broken in v3.64, but works in all prior versions. UP works in v3.64, but is broken in all prior versions.

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

Post by Eke » Sun May 06, 2012 11:14 am

Stef wrote:Yeah, the sonic CD intro uses the scaling rotation chip.
Indeed, there was a bug in my code for 32x32 dot stamps. It seems BIOS only use 16x16 stamps so I did not notice it earlier. Sonic CD clouds are fine now. Still have some issues with intro FMV but it's probably more related to CD buffer or DMA.
Stef wrote:And yeah, some games relies on data conservation after memory bank mode switch. Indeed the way it is done in Gens is not elegant, i did it for faster memory read / write access but i would do it differently today.
Ah, I see, good to know. The way I handle this actually is with a single 512K RAM and by shifting address by one then add an offset (0 or 2 depending on the accessed bank) for bank access in 1M mode. Only problem I need to solve is when games want to run code from Word-RAM bank in 1M mode since my CPU core only allows direct memory pointer access when doing PC-relative reads, for optimization.

Basically the same rules apply in both 1M and 2M with regards to the 2M assignment.
- If DMNA is set by main (regardless of the current mode), sub will get the wordram when switched to 2M.
- Conversely, if RET is set by sub, main will get it when it swtiches to 2M.
- Obviously synchronization matters (i.e., last one wins out).

Thanks for the insight.
So what you mean is that there is actually two values for DMNA, the one that can be read and the one that is written ? Because as said below, setting DMNA in 1M mode would not do anything (i.e no swap request to SUB-CPU). Otherwise, i don't see how Word-RAM can be switched to SUB-CPU side on 1M->2M mode switch since DMNA bit always appears cleared once bank swap is finished in 1M mode. Or am I missing something ?
Also:
- If RET is cleared by sub (e.g., to switch the 1M bank), 2M assignment is not affected.
Hum, so that means that if MAIN-CPU does not set DMNA bit in 1M mode,
Word-RAM will always be returned to MAIN-CPU when switching to 2M mode, no matter of the current value of RET bit or the value set when writing register to switch mode. That's a though one.
- If DMNA is cleared by main, a 'swap request' is signaled to the sub (not accurately described in the manual). This will affect the register bits that are read, but not the wordram assignments.
Yes, I noticed that. In fact, this is only correctly documented in the MAIN-CPU register section of Mega CD Hardware Manual.


I have another question regarding Word-RAM: the manual says that VDP read-out is slow when doing DMA and I understand that words can be read incorrectly becaus eof that. But why incrementing the source address in VDP registers would fix this issue. I can't seem to find a good explanation from hardware point of view. Same things happens with SVP on-board RAM by the way.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Sun May 06, 2012 11:34 am

Eke wrote: Indeed, there was a bug in my code for 32x32 dot stamps. It seems BIOS only use 16x16 stamps so I did not notice it earlier. Sonic CD clouds are fine now. Still have some issues with intro FMV but it's probably more related to CD buffer or DMA.
Right, i now remember i experienced the same problem : got the BIOS ok but then sonic CD intro was glitchy because it uses 32x32 mode unlike BIOS (but BIOS is nice to test almost all others features as overwrite mode).
Stef wrote: Ah, I see, good to know. The way I handle this actually is with a single 512K RAM and by shifting address by one then add an offset (0 or 2 depending on the accessed bank) for bank access in 1M mode.
Yeah this is the way you should implement it so whatever is memory mode you preserve data.
Only problem I need to solve is when games want to run code from Word-RAM bank in 1M mode since my CPU core only allows direct memory pointer access when doing PC-relative reads, for optimization.
He maybe that was the reason why i did this "memory conversion" on mode change, my CPU fetch region was direct memory reference only ;) You have to uses callback for your fetch region if you want to avoid that.

TascoDLX
Very interested
Posts: 262
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Sun May 06, 2012 12:37 pm

So what you mean is that there is actually two values for DMNA, the one that can be read and the one that is written ?
Yes, I would say there are different values across the board.

As far as reads go:
- RET and DMNA in 2M mode reflect the wordram assignment as usual.
- RET bit in 1M mode reflects the bank assignment.
- DMNA bit in 1M mode reflects the 'swap request'.

Here's a special case to consider:

Suppose wordram is in 1M mode and RET is set, so the regval is 5 <101>. Then main sets DMNA, which appears to have no effect since the regval is still 5 <101>. Now, sub clears the MODE bit. What's the regval now? Of course, it's 2 <010>. ;)
Hum, so that means that if MAIN-CPU does not set DMNA bit in 1M mode, Word-RAM will always be returned to MAIN-CPU when switching to 2M mode, no matter of the current value of RET bit or the value set when writing register to switch mode. That's a though one.
That is assuming RET bit gets set in the course of bank switching. If the sub just flips the mode bit up and down, it wouldn't lose wordram access. Nor if it only cleared RET to get the latter bank.

But yes, I would say main is more likely to get it in the course of normal operation. Not that I would call flipping back and forth between 1M and 2M modes to be normal operation, but perhaps just occasional. If I were programming a switch from 1M to 2M, I would have the sub write 1 <001> to the reg and handle sync from there. Eliminate the guesswork.

Post Reply