News:

11 March 2016 - Forum Rules

Main Menu

Why would you do this? (SCD 68k)

Started by Spinner 8, March 05, 2012, 11:38:21 AM

Previous topic - Next topic

Spinner 8

So I'm trying to figure out the graphics compression for a Sega CD game. It seems like pretty basic stuff, only a handful of lines, but I'm kind of stumped as to a certain bit in there. It seems to consist of a lot of strings of values, preceded by a four-byte control code.


FF:55FC  1E 18  MOVE.b  (A0)+,D7
FF:55FE  E1 8F  LSL.L   #0,D7
FF:5600  1E 18  MOVE.b  (A0)+,D7
FF:5602  E1 8F  LSL.L   #0,D7
FF:5604  1E 18  MOVE.b  (A0)+,D7
FF:5606  E1 8F  LSL.L   #0,D7
FF:5608  1E 18  MOVE.b  (A0)+,D7


Is this right, that D7 is being shifted zero bits to the left? What could be the possible benefit of that? And then immediately overwriting it with a new byte? Is "#0" just some kind of weird secret debugger code for "eight"? :)

Also is there some kind of ridiculously verbose mode for Gens Tracer? I'm quite the beginner when it comes to assembly, and it would be nice to see this code being processed over and over again to see what it does with different values. The only trace that Gens Tracer shows for me is for the initial control code of 00000000, which isn't helpful. :)

mziab

Try using trace modes 0 and 1, the ones which log to hook.txt. They don't seem to do any filtering.

Spinner 8

No, 0 and 1 both only log each instruction once. I think I managed to figure it out, though; it was just a matter of me starting the trace too early. I set hook_log.txt to

hook_rd1 7 2174ee 21751c

where 2174ee is the location of one of the control codes, and the 7 meant that it would automatically start tracing once it read that memory location, and not before. It still only logs each instruction once, but it makes a lot more sense now:

FF:55FC  1E 18  MOVE.b  (A0)+,D7     D7=00000000 xnZvc
** [FF:55FC] R08 = 03 [2174EE]
FF:55FE  E1 8F  LSL.L   #0,D7        D7=00000003 xnzvc
FF:5600  1E 18  MOVE.b  (A0)+,D7     D7=00000300 xnzvc
** [FF:5600] R08 = DF [2174EF]
FF:5602  E1 8F  LSL.L   #0,D7        D7=000003DF xNzvc
FF:5604  1E 18  MOVE.b  (A0)+,D7     D7=0003DF00 xnzvc
** [FF:5604] R08 = FF [2174F0]
FF:5606  E1 8F  LSL.L   #0,D7        D7=0003DFFF xNzvc
FF:5608  1E 18  MOVE.b  (A0)+,D7     D7=03DFFF00 xnzvc
** [FF:5608] R08 = F1 [2174F1]
FF:560A  30 3C  MOVE.w  #$000F,D0    D7=03DFFFF1 xNzvc


So I guess I was right and "LSL.L #0,D7" shifts D7 by a byte, but that still doesn't make any sense to me.

mziab

#3
That's odd. The code suggests hook tracing doesn't check if the given opcode was "mapped", unlike trace logging. Oh well, at least you found a solution.

Anyway, mednafen has a pretty nifty Genesis debugger with read and write breakpoints, so if you want to step through the code and see what's going on, that's also a good alternative. You'll need to use a recent WIP version, though. Genesis emulation is a pretty fresh feature, only introduced in 0.9.18-wip, if memory serves. The debugger takes some getting used to, but it's otherwise perfectly serviceable.

EDIT:

Quote from: README3. Using hook_pc* <start> -1 will blindly log data starting from your address.
   Useful for tracking math algorithms or hard-to-understand bugs.

Basically, what I said is only true of execution hooks, but not others. Never mind then.

LostTemplar

I don't have any experience with 68000 assembly, but the only thing I can think of is that maybe the code is written that way to overcome data alignment? As far as I know, for word and long-word accesses, the data has to be at even addresses. Do the control codes sometimes appear at odd addresses? Otherwise it should have sufficed to do a long-word MOVE, as this is all the part seems to do.

Spinner 8

Quote from: LostTemplar on March 05, 2012, 03:31:10 PM
As far as I know, for word and long-word accesses, the data has to be at even addresses.

Is that true? That would make sense then, since those long-words are on both odd and even addresses. I was wondering that myself. :)

It still doesn't explain why the left-shift works the way it does. Maybe since the LSL opcode only has three bits dedicated to the rotation amount, 0 actually could mean the same as 8. But, none of the documents I've read have ever made mention of it.

Quote from: mziab on March 05, 2012, 01:49:20 PM
Anyway, mednafen has a pretty nifty Genesis debugger with read and write breakpoints, so if you want to step through the code and see what's going on, that's also a good alternative. You'll need to use a recent WIP version, though. Genesis emulation is a pretty fresh feature, only introduced in 0.9.18-wip, if memory serves. The debugger takes some getting used to, but it's otherwise perfectly serviceable.

That's neat, Mednafen's PCE debugger came in handy when I was figuring out the font in Die Hard, but it's too bad Sega CD emulation hasn't been added yet. Guess I'm stuck with Gens Tracer and Gens KMod for now.

LostTemplar

Quote from: Spinner 8 on March 05, 2012, 05:18:36 PM
Is that true? That would make sense then, since those long-words are on both odd and even addresses. I was wondering that myself. :)

A lot of CPUs have that kind of limitation (unaligned data would need two accesses -> inefficient). According to Wikipedia, it was lifted with the 68020, though.

Quote from: Spinner 8 on March 05, 2012, 05:18:36 PM
It still doesn't explain why the left-shift works the way it does. Maybe since the LSL opcode only has three bits dedicated to the rotation amount, 0 actually could mean the same as 8. But, none of the documents I've read have ever made mention of it.
Quote from: http://wpage.unina.it/rcanonic/didattica/ce1/docs/68000.pdf
An immediate count permits a shift of 1 to 8 places.

This is the best I could find :) But a lot of instruction set architectures do it this way since shifting by a value of 0 would be a waste of opcode space. As your emulator is obviously executing it correctly the disassembler could be so kind to notate it in a more readable way, though.

Spinner 8

Crap, you're right! Well I stand corrected. :)

I figured out the compression this afternoon; pretty simple stuff. Now I just need to code a decompressor (and a recompressor, once I think I can manage it).

RedComet

Yeah, a shift value of 8 is encoded in the instruction word as 000. Give Regen a try. It has a nice debugger.
Twilight Translations - More than just Dragonball Z. :P

Djinn

It's just loading of the 32-bit value into register. From Z80 I think, because it have one byte access only.
Your disassembler shows instructions lsl.l #8,d7 incorrect.

andlabs

Yes, that block of code just reads a little-endian long from a0 to d7.

Out of curiosity, what game is this and what is the context?