Ornate metrics

Under construction. Last Update: 2010/11/01 22:33 +0900

Overview

How to obtain the metrics (x, y, width, height) of wall/floor ornates?

DM Atari ST version has metrics information per ornate image and facing (front/right).
DM snes version also does.

The raw data index is 0x3D. 61th raw data (0 based index) is the compressed image of the displayed image "iron ring hanger".

Memo

Any clue to know

I knew DM snes uses DSP-2 to combine two images into one (DSP-2 Op 05h).

I also knew there is an offscreen plane bitmap (168 x 128, the size of dungeon viewport).

SNES seems to use bit-plane format for bitmap. However, Original DM (Atari ST ver) uses 4-bits packed-pixel format. Its conversion is done by DSP-2 Op 01h.

And the conversion is done in a lump, just constant times, not one by one.

So, I thought that there may be big off-screen plane to render dungeon viewport beforehand.

And... the metrics (x, y coordinations and so on) for off-screen plane is required to composite an image into off-screen plane.

Byte offset for offscreen bitmap

$04/88A5 A4 EF       LDY $EF    [$00:01EF]   A:0009 X:8000 Y:800A D:0100 DB:3F S:1F01 P:eNvmxdIzcHC:0010 VC:113 00 FL:65505
$04/88A7 C8          INY                     A:0009 X:8000 Y:2BF4 D:0100 DB:3F S:1F01 P:envmxdIzcHC:0042 VC:113 00 FL:65505

The above LDY remembers offset of offscreen packed-pixel bitmap image.

In this case, it is 2BF4. 0x2BF4 - 0x2000 → 0xBF4

0xBF4 is offset of offscreen viewport bitmap. viewport has 168 x 128.

The bitmap's orientation is scan line based. Scan to x-direction (right direction). If end of line, then go to next line (down direction) and go back to most left in x-axis.

In 4bpp bitmap format, 168 pixels are represented in 84 bytes. Just divide the pixels by 2.

0xBF4 ÷ 84 → 36 … 36

Left 36 is y-axis location in pixels. Right 36 is x-axis location in bytes.

The bitmap is 4bpp. So multiply x by 2.

36 × 2 → 72.

Thus, 72 is x-axis location in pixels.

Width count

$04/88A8 20 8C 00    JSR $008C  [$04:008C]   A:0009 X:8000 Y:2BF5 D:0100 DB:3F S:1F01 P:envmxdIzcHC:0056 VC:113 00 FL:65505
$04/008C 54 7E 3F    MVN 7E 3F               A:0009 X:8000 Y:2BF5 D:0100 DB:3F S:1EFF P:envmxdIzcHC:0102 VC:113 00 FL:65506
$04/008C 54 7E 3F    MVN 7E 3F               A:0008 X:8001 Y:2BF6 D:0100 DB:7E S:1EFF P:envmxdIzcHC:0154 VC:113 00 FL:65506
$04/008C 54 7E 3F    MVN 7E 3F               A:0007 X:8002 Y:2BF7 D:0100 DB:7E S:1EFF P:envmxdIzcHC:0206 VC:113 00 FL:65506
$04/008C 54 7E 3F    MVN 7E 3F               A:0006 X:8003 Y:2BF8 D:0100 DB:7E S:1EFF P:envmxdIzcHC:0258 VC:113 00 FL:65506
$04/008C 54 7E 3F    MVN 7E 3F               A:0005 X:8004 Y:2BF9 D:0100 DB:7E S:1EFF P:envmxdIzcHC:0310 VC:113 00 FL:65506
$04/008C 54 7E 3F    MVN 7E 3F               A:0004 X:8005 Y:2BFA D:0100 DB:7E S:1EFF P:envmxdIzcHC:0362 VC:113 00 FL:65506
$04/008C 54 7E 3F    MVN 7E 3F               A:0003 X:8006 Y:2BFB D:0100 DB:7E S:1EFF P:envmxdIzcHC:0414 VC:113 00 FL:65506
$04/008C 54 7E 3F    MVN 7E 3F               A:0002 X:8007 Y:2BFC D:0100 DB:7E S:1EFF P:envmxdIzcHC:0466 VC:113 00 FL:65506
$04/008C 54 7E 3F    MVN 7E 3F               A:0001 X:8008 Y:2BFD D:0100 DB:7E S:1EFF P:envmxdIzcHC:0518 VC:113 00 FL:65506
$04/008C 54 7E 3F    MVN 7E 3F               A:0000 X:8009 Y:2BFE D:0100 DB:7E S:1EFF P:envmxdIzcHC:0570 VC:113 00 FL:65506
$04/008F 60          RTS                     A:FFFF X:800A Y:2BFF D:0100 DB:7E S:1EFF P:envmxdIzcHC:0622 VC:113 00 FL:65506
$04/88AB E2 30       SEP #$30                A:FFFF X:800A Y:2BFF D:0100 DB:7E S:1F01 P:envmxdIzcHC:0664 VC:113 00 FL:65505

MVN repeats 10 times. A scan line, 10 bytes (20 pixels) are to be transferred from DSP-2 chip RAM to SNES RAM.

$04/8896 68          PLA                     A:FFFF X:845F Y:800A D:0100 DB:3F S:1EFF P:eNvmxdIzcHC:1164 VC:112 00 FL:65505
$04/8897 48          PHA                     A:0009 X:845F Y:800A D:0100 DB:3F S:1F01 P:envmxdIzcHC:1200 VC:112 00 FL:65505

And width count is "popped" and then "pushed". It is 9. If you take A=9 to MVN, MVN repeats 10 times.

Memo

horizontal rule

$04/866F A7 F3       LDA [$F3]  [$03:891F]   A:0001 X:007E Y:0004 D:0100 DB:7E S:1F02 P:envmxdIZCHC:0464 VC:106 00 FL:65505
$04/8671 29 FF 00    AND #$00FF              A:5F48 X:007E Y:0004 D:0100 DB:7E S:1F02 P:envmxdIzCHC:0520 VC:106 00 FL:65505
$04/8674 85 D4       STA $D4    [$00:01D4]   A:0048 X:007E Y:0004 D:0100 DB:7E S:1F02 P:envmxdIzCHC:0544 VC:106 00 FL:65505
$04/8676 A0 01 00    LDY #$0001              A:0048 X:007E Y:0004 D:0100 DB:7E S:1F02 P:envmxdIzCHC:0576 VC:106 00 FL:65505
$04/8679 B7 F3       LDA [$F3],y[$03:8920]   A:0048 X:007E Y:0001 D:0100 DB:7E S:1F02 P:envmxdIzCHC:0624 VC:106 00 FL:65505
$04/867B 29 FF 00    AND #$00FF              A:245F X:007E Y:0001 D:0100 DB:7E S:1F02 P:envmxdIzCHC:0680 VC:106 00 FL:65505
$04/867E 85 D2       STA $D2    [$00:01D2]   A:005F X:007E Y:0001 D:0100 DB:7E S:1F02 P:envmxdIzCHC:0704 VC:106 00 FL:65505

In this code,

0x48 → BYTE [00:01D4]
0x5F → BYTE [00:01D2]

0x5F - 0x48 → 23.

This should mean the width, where the width is 24.

Consider that this ornate is rendered at (0x48, y1)-(0x5F, y2).

0x5F - 0x48 + 1 → 24.

It is that.

horizontal rule

$04/8740 A5 D2       LDA $D2    [$00:01D2]   A:001C X:007E Y:0000 D:0100 DB:7E S:1F02 P:envmxdIzCHC:0028 VC:110 00 FL:65505
$04/8742 38          SEC                     A:005F X:007E Y:0000 D:0100 DB:7E S:1F02 P:envmxdIzCHC:0060 VC:110 00 FL:65505
$04/8743 E5 D4       SBC $D4    [$00:01D4]   A:005F X:007E Y:0000 D:0100 DB:7E S:1F02 P:envmxdIzCHC:0074 VC:110 00 FL:65505
$04/8745 1A          INC A                   A:0017 X:007E Y:0000 D:0100 DB:7E S:1F02 P:envmxdIzCHC:0106 VC:110 00 FL:65505
$04/8746 4A          LSR A                   A:0018 X:007E Y:0000 D:0100 DB:7E S:1F02 P:envmxdIzCHC:0120 VC:110 00 FL:65505
$04/8747 85 DA       STA $DA    [$00:01DA]   A:000C X:007E Y:0000 D:0100 DB:7E S:1F02 P:envmxdIzcHC:0134 VC:110 00 FL:65505

00:01D2 and 00:01D4 seem to have important ones.

       BYTE [00:01D2] → 0x5F
0x5F - BYTE [00:01D4] → 0x17

Thus, 00:01D4 → 0x48 (equals to 72)

0x18 equals to 24. It is the ornate image's width.

LSR divides the width by 2. 24 ÷ 2 → 12.

Store 12 to 00:01DA.

horizontal rule

$04/8790 C6 DA       DEC $DA    [$00:01DA]   A:00FF X:00FF Y:0000 D:0100 DB:7E S:1F02 P:envmxdIZCHC:0788 VC:110 00 FL:65505
$04/8792 A5 DA       LDA $DA    [$00:01DA]   A:00FF X:00FF Y:0000 D:0100 DB:7E S:1F02 P:envmxdIzCHC:0842 VC:110 00 FL:65505

The above DEC seems to decrases the width (equal to 12). 12 - 1 → 11

horizontal rule

$04/8856 A4 DA       LDY $DA    [$00:01DA]   A:000A X:002A Y:0000 D:0100 DB:7E S:1F01 P:envMXdIzcHC:0340 VC:111 00 FL:65505
$04/8858 F0 55       BEQ $55    [$88AF]      A:000A X:002A Y:000B D:0100 DB:7E S:1F01 P:envMXdIzcHC:0364 VC:111 00 FL:65505

The above LDY seems to read the 11.

horizontal rule

$04/886C 88          DEY                     A:0011 X:00AA Y:000B D:0100 DB:7E S:1F01 P:envMXdIzcHC:0866 VC:111 00 FL:65505
$04/886D F0 40       BEQ $40    [$88AF]      A:0011 X:00AA Y:000A D:0100 DB:7E S:1F01 P:envMXdIzcHC:0880 VC:111 00 FL:65505

The above DEY seems to decrease the Y. 11 - 1 → 10

horizontal rule

Credits

Posted source code is disassembled from DM SNES JP 1.0.

Captured/Disassembled by Geiger's Snes9x Debugger.

The hex-editor's screenshots were presented by "BinaryEditor Stirling".