Working on a new Data Viewer like ADGE

Use this forum to discuss dungeon editors and other tools, like DMute (by George Gilbert, also working for RTC dungeons), DM Builder (by Sphenx), and ADGE by `rain. Includes DM editing tips and tricks.
Forum rules
Please read the Forum rules and policies before posting.
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Working on a new Data Viewer like ADGE

Post by Cycl0ne »

For the V3.6 (LAY1) Game.dat File (at the moment).

I created all decoder now (IMG1/IMG2/TXT2/COD2/...) and fighting with gui design:
Image

Feedback welcome. Its coded in Python -> Sourcecode will follow on github.
User avatar
ChristopheF
Encyclopedist
Posts: 1538
Joined: Sun Oct 24, 1999 2:36 pm
Location: France
Contact:

Re: Working on a new Data Viewer like ADGE

Post by ChristopheF »

Always nice to see new projects!
What are your plans? Do you have any unique, never seen before, features in mind?
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

No not really Christophe, its just a DataDecoder with GUI (like your VBS Decoder). A more complete ADGE. ADGE lacks the LAY and correct PAL handling, only taking the 1.0 DM game.dat File. Maybe some bugfixes. Not sure..

And it will use python to be more modern than .NET which was transfered from VB6.

What i already extracted and sorted (and the most main reason) is the LAY1 Structure:
Group #1: General:
Group #2: Screens:
Group #3: Doors:
Group #4: WallsDoorFrame:
Group #5: Stairs:
Group #6: Pits:
Group #7: DisplayCreature:
Group #8: DisplayItemsA:
Group #9: DisplayItemsB:
Group #10: CloudsLightning:
Group #11: WallOrnateText:
Group #12: FloorOrnates:
Group #13: DoorGfx:
Group #14: OpeningDoor:
Group #15: DoorButton:
Group #16: DialogBox:
Group #17: CharacterSheet:
Group #18: Inventory:
Group #19: ScreenTopPart:
Group #20: Magic:
Group #21: Attacks:
Group #22: Movement:
Group #23: ChampionIcons:
General :
{'self': 1, 'align': 9, 'parent': 0, 'x': 320, 'y': 200}
{'self': 2, 'align': 1, 'parent': 1, 'x': 0, 'y': 0}
{'self': 3, 'align': 9, 'parent': 0, 'x': 224, 'y': 136}
{'self': 4, 'align': 1, 'parent': 3, 'x': 0, 'y': 0}
{'self': 5, 'align': 10, 'parent': 2, 'x': 0, 'y': 0}
{'self': 6, 'align': 10, 'parent': 4, 'x': 0, 'y': 0}
{'self': 7, 'align': 1, 'parent': 3, 'x': 0, 'y': 33}
{'self': 8, 'align': 9, 'parent': 2, 'x': 87, 'y': 45}
{'self': 9, 'align': 3, 'parent': 8, 'x': 319, 'y': 168}
{'self': 10, 'align': 9, 'parent': 2, 'x': 87, 'y': 45}
{'self': 11, 'align': 2, 'parent': 10, 'x': 319, 'y': 77}
{'self': 12, 'align': 9, 'parent': 2, 'x': 87, 'y': 33}
{'self': 13, 'align': 3, 'parent': 12, 'x': 319, 'y': 74}
{'self': 14, 'align': 9, 'parent': 2, 'x': 320, 'y': 27}
{'self': 15, 'align': 4, 'parent': 14, 'x': 0, 'y': 199}
{'self': 16, 'align': 9, 'parent': 2, 'x': 87, 'y': 6}
{'self': 17, 'align': 1, 'parent': 16, 'x': 233, 'y': 33}

ALIGNMENTLIST = {
0: {"align": "CENTER", "description": "Center at coordinates (Data words are X and Y coordinates)"},
1: {"align": "TOP_LEFT", "description": "Align top left at coordinates (Data words are X and Y coordinates)"},
2: {"align": "TOP_RIGHT", "description": "Align top right at coordinates (Data words are X and Y coordinates)"},
3: {"align": "BOTTOM_RIGHT", "description": "Align bottom right at coordinates (Data words are X and Y coordinates)"},
4: {"align": "BOTTOM_LEFT", "description": "Align bottom left at coordinates (Data words are X and Y coordinates)"},
5: {"align": "TOP_CENTER", "description": "Align top and center horizontally at coordinates (Data words are X and Y coordinates)"},
6: {"align": "RIGHT_CENTER", "description": "Align right and center vertically at coordinates (Data words are X and Y coordinates)"},
7: {"align": "BOTTOM_CENTER", "description": "Align bottom and center horizontally at coordinates (Data words are X and Y coordinates)"},
8: {"align": "LEFT_CENTER", "description": "Align left and center vertically at coordinates (Data words are X and Y coordinates)"},
9: {"align": "DIMENSIONS", "description": "Dimensions Width x Height (Data words are width and height). Only type that never starts a list."},

# Extended rules with margins
10: {"align": "CENTER_MARGINS", "description": "Center at coordinates with margins applied"},
11: {"align": "TOP_LEFT_MARGINS", "description": "Align top left at coordinates with margins applied"},
12: {"align": "TOP_RIGHT_MARGINS", "description": "Align top right at coordinates with margins applied"},
13: {"align": "BOTTOM_RIGHT_MARGINS", "description": "Align bottom right at coordinates with margins applied"},
14: {"align": "BOTTOM_LEFT_MARGINS", "description": "Align bottom left at coordinates with margins applied"},
15: {"align": "TOP_CENTER_MARGINS", "description": "Align top and center horizontally at coordinates with margins applied"},
16: {"align": "RIGHT_CENTER_MARGINS", "description": "Align right and center vertically at coordinates with margins applied"},
17: {"align": "BOTTOM_CENTER_MARGINS", "description": "Align bottom and center horizontally at coordinates with margins applied"},
18: {"align": "LEFT_CENTER_MARGINS", "description": "Align left and center vertically at coordinates with margins applied"},
}

Not sure if it is for someone really useful. I will only implement DataRead, no DataWrite (RLE decoding of the IMG1/2 Files was hell enough, cant thing of a RLE Encoding.. :-)

Oh and while we are at it. I read that i follow the whole list of LAY1 to understand the X and Y + W and H.. but how do i handle the Alignments then? exp:
1 DIMENSIONS, 0, 320, 200

6 LEFT CENTER, 1, 0, 0
10 CENTER, 6, 0, 0

i go from 10 to 6 to 1 .. how do i calc then the Aligns?
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

Oh and one benefit (like the javascript game) it will be opensource. So anyone in the next 30 Years can look into it and enhance it ;-)
User avatar
ChristopheF
Encyclopedist
Posts: 1538
Joined: Sun Oct 24, 1999 2:36 pm
Location: France
Contact:

Re: Working on a new Data Viewer like ADGE

Post by ChristopheF »

Oh and while we are at it. I read that i follow the whole list of LAY1 to understand the X and Y + W and H.. but how do i handle the Alignments then? exp:
1 DIMENSIONS, 0, 320, 200
I don't know... Did you have a look at ReDMCSB source code? The answer must be in there (in file COORD.C).
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

i will take a look into it.. not sure where i decompressed it :-D

was this the latest? ReDMCSB_WIP20210206
User avatar
ChristopheF
Encyclopedist
Posts: 1538
Joined: Sun Oct 24, 1999 2:36 pm
Location: France
Contact:

Re: Working on a new Data Viewer like ADGE

Post by ChristopheF »

Yes, that's the one
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

Thanks, i found it:

Code: Select all

                while (L2298_ps_LayoutRecord->ParentRecordIndex) {
                                switch (L2306_i_) {
                                        default:
                                                return NULL;
                                        case 0:
                                                L2301_ -= ((L2299_ps_LayoutRecord2->Data2 + 1) >> 1);
                                        case 5:
                                                L2300_i_ -= ((L2299_ps_LayoutRecord2->Data1 + 1) >> 1);
                                                break;
                                        case 3:
                                                L2301_ -= L2299_ps_LayoutRecord2->Data2 - 1;
                                        case 2:
                                                L2300_i_ -= L2299_ps_LayoutRecord2->Data1 - 1;
                                                break;
                                        case 6:
                                                L2300_i_ -= L2299_ps_LayoutRecord2->Data1 - 1;
                                        case 8:
                                                L2301_ -= (L2299_ps_LayoutRecord2->Data2 + 1) >> 1;
                                                break;
                                        case 7:
                                                L2300_i_ -= (L2299_ps_LayoutRecord2->Data1 + 1) >> 1;
                                        case 4:
                                                L2301_ -= L2299_ps_LayoutRecord2->Data2 - 1;
                                        case 1:
                                                break;
iterating through all parents and doing stuff.. I wonder what Editor they had which took all this into account.. :o
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

Hey Christophe,

question: Whats means CPSF in the code? i see it all over the place added to functions and vars: _CPSF ?
User avatar
ChristopheF
Encyclopedist
Posts: 1538
Joined: Sun Oct 24, 1999 2:36 pm
Location: France
Contact:

Re: Working on a new Data Viewer like ADGE

Post by ChristopheF »

CPSF = Copy Protection Scheme F
This is the way I identified all functions/variables involved in the copy protection in one way or another. There are a lot as you can see.
In the Documentation folder, the file CopyProtection.htm contains all the details explaining each scheme of the very sophisticated copy protection of the game.
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

Ah thank you so i can ignore.. now while fetching fresh data from dungeon, i got another question:
a) http://dmweb.free.fr/?q=node/217
002Ch (44) 224 bytes - Map definitions
---
08h (08) 1 word: Map size
Bits 15-11: Map height - 1
Bits 10-6: Map width - 1

it should say +1, since the values in the dungeon.dat is (example: 25 and 12 for level 13) but the dungeon is 26 and 13 in size (the code counts from 0 ... 25 and from 0 .. 12

b) when reading the dungeon.dat (compressed/not compressed).. i got gaps at the end of the dungeon. this is not documented in the wiki. what data lies between the dungeon?
exp: Level 13 ends at 12352, the rawmapdata ends at 12366.. what with those 14bytes? Same with the other level with other gaps..


and the text is also confusing:
Each map is defined by a variable number of bytes. For each map in order, there is one byte per tile, plus one byte for each creature graphic, wall decoration graphic, floor decoration graphic and door decoration graphics (in that order). The number of graphics of each kind is specified in the map definition section.


it reads as if in the raw data are more than 1 byte per tile.
User avatar
ChristopheF
Encyclopedist
Posts: 1538
Joined: Sun Oct 24, 1999 2:36 pm
Location: France
Contact:

Re: Working on a new Data Viewer like ADGE

Post by ChristopheF »

a) Map 13 of the dungeon has width=26 height=13, and in dungeon.dat the data is 25x12 so it means that the stored values are indeed width - 1 and height - 1

b) The bytes for a map contain: one byte for each tile, then the following bytes (what you call gaps but they are not) represent creatures that are allowed on the map, the wall decorations for the map, the floor decorations and the door decorations. The number of bytes for each type is defined in the header.
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

ok could you write it a bit more detailed on the page please?
Since i read: the value you get you subtract -1. But with the word: Stored values are -1 of real data sounds better. or write: youu need to add +1 to get the real size.

and for b) ah ok also here the english text is misleading. it says:
For each map in order, there is one byte per tile, plus one byte for each creature graphic, wall decoration graphic, floor decoration graphic and door decoration graphics (in that order).

this you can read:
1 byte tile, 1byte creature, 1byte wall, 1byte floor, 1door. The "plus one byte" ..

maybe something like this could clarify:

Hdr.width +1 * hdr.height+1 = amount of bytes of the tiles. (Attention: The Map is stored in Y and then X ! Rows wise)
After that follows lists of different things (lenght through map header):
creatures (amount in Map Header 0xc)
wall decoration (amount in Map Header 0xa)
floor decoration (amount in Map Header 0xa)
door decoration (amount in Map Header 0xc)

--
ok from my analytics, how does the game know how to set special wall ornates like the water fountain to a wall? i couldnt find a clue.

and another question of example level 5:
RandomWallOrnamentCount: 4
WallOrnamentCount: 14

so 4 of the list can be placed random where the flag (N/E/S/W RANDOM DECOR WALL) is set. but how are the other 10 being placed?

output of my pthon script looks good:
RawMapDataByteOffset: 4464
OffsetMapX: 5, OffsetMapY: 5
Width: 32, Height: 32, Level: 5
RandomFloorOrnamentCount: 0
FloorOrnamentCount: 3
RandomWallOrnamentCount: 4
WallOrnamentCount: 14
Difficulty: 2
CreatureTypeCount: 3
DoorOrnamentCount: 4
DoorSet1: 1, DoorSet0: 0
WallSet: 0, FloorSet: 0
User avatar
Sphenx
On Master
Posts: 566
Joined: Sun Sep 09, 2001 11:23 am
Contact:

Re: Working on a new Data Viewer like ADGE

Post by Sphenx »

Wall ornates and Floor ornates work the same.
There are either "randomly" set (from the random ornament count list) or "explicitly" set using actuator/sensor objects through the gfx id within.

So if you have:
RandomWallOrnamentCount: 4
WallOrnamentCount: 14
only the first 4 ornates of the gfx list can be used as random ornates. The others can't be used randomly and will be set through actuator/sensor objects (if used).

Now for the random part, you need to change the lower bits of the tiles values to potentially get a random gfx through the pseudo-randomness pattern.
For example:
0x00 is a wall tile with no randomness.
0x08 is a wall tile that may hold random gfx (from the 4 possible of the list)
0x20 is a floor tile with no randomness.
0x28 is a floor tile that may hold random gfx (from the floor random ornament list)

the last question is about the pseudo-randomness pattern : not every tile with the "random" value set will actually produce a random gfx. This will follow a special pattern (activating randomness more like in a diagonal repetitive pattern through the map) that is a combination of "dungeon random seed" (first value in dungeon header) and some algorithm.
I believe Christophe will be able to point this algorithm in the code.
User avatar
ChristopheF
Encyclopedist
Posts: 1538
Joined: Sun Oct 24, 1999 2:36 pm
Location: France
Contact:

Re: Working on a new Data Viewer like ADGE

Post by ChristopheF »

I have updated the doc with clarifications.

Regarding random ornaments on floors and walls, you can check function F0170_DUNGEON_GetRandomOrnamentOrdinal (both its content, and where it is called from). This is all in file DUNGEON.C in the ReDMCSB source code.
Note that for wall tiles there are actually 4 bits to allow/block random ornaments: one for each face of the wall. For corridor tiles there is only one such bit.

Code: Select all

#define MASK0x0001_WALL_WEST_RANDOM_ORNAMENT_ALLOWED              0x0001
#define MASK0x0002_WALL_SOUTH_RANDOM_ORNAMENT_ALLOWED             0x0002
#define MASK0x0004_WALL_EAST_RANDOM_ORNAMENT_ALLOWED              0x0004
#define MASK0x0008_WALL_NORTH_RANDOM_ORNAMENT_ALLOWED             0x0008

#define MASK0x0008_CORRIDOR_RANDOM_ORNAMENT_ALLOWED               0x0008
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

@Sphenx: Thanks for the clarification. The code i alread found. there are 2 functions:
F0169_DUNGEON_GetRandomOrnamentIndex
F0170_DUNGEON_GetRandomOrnamentOrdinal

This i already implemented last year in the Javascript Version (a bit different with different results, but overall the same):
* is the flag set: Random Ornaments? Then do a RND(30) < =ListSize -> get the elements in the random list to show.

But as mentioned, the non rnd elements i was sceptic. There is a postion in Map 2 (Map 1 when counting from 0) there is a Fountain. but not in the CSB/DMute Editor seeable. Seems it is a random item.. didnt check but this explains it.

@christophe: MUCH BETTER !!! Yes, good job ! Only thing still missing: WARNING, MAP is organized Y and then X and not X and Y as people may think

i created a small python class which uncompress (when needed) the Dungeon.dat and then you can crunch through the data. I will upload it to github, so people can use it to dig into the dungeon.dat. But i need to code the part of the 16 list + data before finish, at the moment i skip them.

Code: Select all

        print("DungeonColumnCount", col)
        data = dungeon.read_data(col*2)
        print("Count SFTC: ",self.hdr['SquareFirstThingCount']*2)
        data = dungeon.read_data(self.hdr['SquareFirstThingCount']*2)
        print("Count TextDataWordCount: ",self.hdr['TextDataWordCount']*2)
        data = dungeon.read_data(self.hdr['TextDataWordCount']*2)
        
        data = dungeon.read_data(self.hdr['ThingCount'][0]*4)  #         4,   /* Door */
        data = dungeon.read_data(self.hdr['ThingCount'][1]*6)  #         6,   /* Teleporter */
        data = dungeon.read_data(self.hdr['ThingCount'][2]*4)  #         4,   /* Text String */
        data = dungeon.read_data(self.hdr['ThingCount'][3]*8)  #         8,   /* Sensor */
        data = dungeon.read_data(self.hdr['ThingCount'][4]*16) #         16,  /* Group */
        data = dungeon.read_data(self.hdr['ThingCount'][5]*4)  #         4,   /* Weapon */
        data = dungeon.read_data(self.hdr['ThingCount'][6]*4)  #         4,   /* Armour */
        data = dungeon.read_data(self.hdr['ThingCount'][7]*4)  #         4,   /* Scroll */
        data = dungeon.read_data(self.hdr['ThingCount'][8]*4)  #         4,   /* Potion */
        data = dungeon.read_data(self.hdr['ThingCount'][9]*8)  #         8,   /* Container */
        data = dungeon.read_data(self.hdr['ThingCount'][10]*4) #         4,   /* Junk */
        data = dungeon.read_data(self.hdr['ThingCount'][11]*0) #         0,   /* Unused */
        data = dungeon.read_data(self.hdr['ThingCount'][12]*0) #         0,   /* Unused */
        data = dungeon.read_data(self.hdr['ThingCount'][13]*0) #         0,   /* Unused */
        data = dungeon.read_data(self.hdr['ThingCount'][14]*8) #         8,   /* Projectile */
        data = dungeon.read_data(self.hdr['ThingCount'][15]*4) #         4    /* Explosion */
User avatar
Sphenx
On Master
Posts: 566
Joined: Sun Sep 09, 2001 11:23 am
Contact:

Re: Working on a new Data Viewer like ADGE

Post by Sphenx »

What is the location of that fountain ?
User avatar
ChristopheF
Encyclopedist
Posts: 1538
Joined: Sun Oct 24, 1999 2:36 pm
Location: France
Contact:

Re: Working on a new Data Viewer like ADGE

Post by ChristopheF »

I have added a clarification for the order of tile bytes.

The fountain is located at (01,10,14) as seen here: http://dmweb.free.fr/?q=node/135 and is indeed created as a random decoration, because placing an explicit fountain there is not possible: it would require a sensor on the tile that is outside of the map limits.
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

Nah i was refering to: (01,04,20) .. But yes, this confirms its random. While the one at: (1,6,44) is placed with the sensor(off).
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

Ok here is a first Version, now with the complete decoded List Items (16):

https://github.com/cycl0ne/DungeonMasterTools/tree/main
User avatar
Sphenx
On Master
Posts: 566
Joined: Sun Sep 09, 2001 11:23 am
Contact:

Re: Working on a new Data Viewer like ADGE

Post by Sphenx »

ChristopheF wrote: Sat Mar 02, 2024 11:17 am Regarding random ornaments on floors and walls, you can check function F0170_DUNGEON_GetRandomOrnamentOrdinal (both its content, and where it is called from). This is all in file DUNGEON.C in the ReDMCSB source code.
Thanks for the info, I have checked this code is also existing in DM2, but for some reason not giving the same expected random ornament. There may be something slightly different I have not spotted yet.
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

Hey Spehnx, got the same issue, cut the code for the randomcalc into a small c prg, maybe Christophef can give a clue. I tried it with 19/19 for the size, 18 18 , mapindex 1 and 0 and all variants.. i cant get the correct random number like the game.

Code: Select all

#include <stdio.h>

int G0272_i_CurrentMapIndex  = 0;
int G0273_i_CurrentMapWidth  = 18;
int G0274_i_CurrentMapHeight = 18;

int F0169_DUNGEON_GetRandomOrnamentIndex(int P0301_ui_Value1, int  P0302_ui_Value2, int P0303_i_Modulo)
{
        return ((((P0301_ui_Value1 * 31417) >> 1) + (P0302_ui_Value2 * 11) + 99) >> 2) % P0303_i_Modulo; 
		/* Pseudorandom number generator */
}

int F0170_DUNGEON_GetRandomOrnamentOrdinal(int P0304_B_RandomOrnamentAllowed,int P0305_i_OrnamentCount, int P0306_i_MapX, int P0307_i_MapY, int P0308_i_Modulo)
{
    if (!P0304_B_RandomOrnamentAllowed) return 0;
    int L0305_i_RandomOrnamentIndex;
    
    L0305_i_RandomOrnamentIndex = F0169_DUNGEON_GetRandomOrnamentIndex(
        2000 + (P0306_i_MapX << 5) + P0307_i_MapY, 
		3000 + (G0272_i_CurrentMapIndex << 6) + G0273_i_CurrentMapWidth + G0274_i_CurrentMapHeight, P0308_i_Modulo);
		printf("RandomOrnamentIndex: %d \n", L0305_i_RandomOrnamentIndex);
		printf("P0305_i_OrnamentCount: %d \n", P0305_i_OrnamentCount);
		if (L0305_i_RandomOrnamentIndex < P0305_i_OrnamentCount)
        {
            return L0305_i_RandomOrnamentIndex+1;
        }
        return 0;
}

#define normalize(a) (a%0x3)

int main() {
    // Write C code here
    printf("Try programiz.pro\n");
    int P0314_i_MapX = 12;
    int P0315_i_MapY = 3;
//    int P0314_i_MapX = 17;
//    int P0315_i_MapY = 11;

    int P0313_i_Direction = 0;
    int c = F0170_DUNGEON_GetRandomOrnamentOrdinal(1, 4,P0314_i_MapX, ++P0315_i_MapY * (normalize(P0313_i_Direction) + 1), 30);
    printf("ValueRet: %d\n", c);
    c = F0170_DUNGEON_GetRandomOrnamentOrdinal(1, 4,P0314_i_MapX, P0315_i_MapY * (normalize(++P0313_i_Direction) + 1), 30);
    printf("ValueRet: %d\n", c);
    c = F0170_DUNGEON_GetRandomOrnamentOrdinal(1, 4,P0314_i_MapX, P0315_i_MapY * (normalize(++P0313_i_Direction) + 1), 30);
    printf("ValueRet: %d\n", c);
    c = F0170_DUNGEON_GetRandomOrnamentOrdinal(1, 4,P0314_i_MapX, P0315_i_MapY-- * (normalize(++P0313_i_Direction) + 1), 30);
    printf("ValueRet: %d\n", c);

    return 0;
}
User avatar
Paul Stevens
CSBwin Guru
Posts: 4318
Joined: Sun Apr 08, 2001 6:00 pm
Location: Madison, Wisconsin, USA

Re: Working on a new Data Viewer like ADGE

Post by Paul Stevens »

You did not say what size your 'int' is.
The Original Atari code used int16_t for these calculations.

Code: Select all

i16 Hash(i16 P1,i16 P2,i16 P3)
{ // Called from only one place in program.
  // P1 is a function of mapX, mapY
  // P2 is a function of level, width, and height
  // P3 is a small integer like 30 used as arithmetic modulus.
  // Result is     hash(P1,P2,dungeonDatIndex[0]) % P3
  dReg D0, D1;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  D0L = (ui16)P1 * 31417;
  D0W = (I16)((D0W >>= 1) & 0x7fff);
  D1L = (ui16)P2 * 11;
  D0W = sw(D0W + D1W);
  D0W = sw(D0W + d.dungeonDatIndex->Sentinel()); // = 13 in my game
  D0W = (I16)((D0W >> 2) & 0x3fff);
  D0L &= 0xffff;
  D0W = sw(D0L % (ui16)(P3));
  return D0W;
}

Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

ahhh thanks .. thats the clue.. i will dig further into it.. of course.. the first multiplication with *31417 is 0x4cf0fc8 thats hiiiiighhhhhh :-D
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

one last question:
// P1 is a function of mapX, mapY
// P2 is a function of level, width, and height

will mapx/y and level width and height the normal C values? (0,0 = first square or 1,1 first square) and same with width: 18,18 or 19,19 for the first level as example?
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

lol, the online c compiler is buggy :-D everytime i press compile&run i get different values.. ok back to scratchboard..
User avatar
Paul Stevens
CSBwin Guru
Posts: 4318
Joined: Sun Apr 08, 2001 6:00 pm
Location: Madison, Wisconsin, USA

Re: Working on a new Data Viewer like ADGE

Post by Paul Stevens »

Here is the code: I believe mapX/Y are zero-based; width/height
are the number of columns/rows ; facing is 0=n 1=e etc.

Code: Select all

i16 RandomWallDecoration(i16 P1,i16 P2,i32 mapX,i32 P4,i16 probability)
{ //P4 = n*mapY  where n=facing
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  i16 LOCAL_2;
  if (P1 != 0)
  {
    LOCAL_2 = Hash(
                (I16)(2000 + (mapX<<5) + P4),
                (I16)(3000 + (d.LoadedLevel<<6) + d.width + d.height),
                probability);
    if (LOCAL_2 < P2)
    {
      return sw(LOCAL_2 + 1);
    };
  };
  return 0;
}

void TAG00a4a2(SUMMARIZEROOMDATA *rslt ,
               i16 P2,       //12
               i16 P3,       //14
               i16 P4,       //16
               i32 facing,   //18
               i32 mapX,     //20
               i32 mapY,     //22
               i32 P8)       //24
{
  i16 numDecoration, i;
  numDecoration = d.pCurLevelDesc->NumRandomWallDecoration();
  rslt->decorations[0] = RandomWallDecoration(
                             P2,
                             numDecoration,
                             mapX,
                             (mapY+1)*(((facing+1)&3)+1),
                             30);
  rslt->decorations[1] = RandomWallDecoration(
                             P3,
                             numDecoration,
                             mapX,
                             (mapY+1)*(((facing+2)&3)+1),
                             30);
  rslt->decorations[2] = RandomWallDecoration(
                             P4,
                             numDecoration,
                             mapX,
                             (mapY+1)*(((facing+3)&3)+1),
                             30);
  if (    (P8 != 0)
       || (mapX < 0)
       || (mapX >= d.width)
       || (mapY < 0)
       || (mapY >= d.height) )

  {
    for (i = 2; i <= 4; i++)
    {
      if (IsAlcove(sw(rslt->decorations[i-2]-1)))
      {
        rslt->decorations[i-2] = 0;
      };
    };
  };
}
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

I implemented it like yours for the c version to see if my python does the same:

Code: Select all

short F0169_DUNGEON_GetRandomOrnamentIndex(unsigned short P0301_ui_Value1, unsigned short  P0302_ui_Value2, unsigned short P0303_i_Modulo)
{
        int d0l = (uint16_t)P0301_ui_Value1 * 31417;
        short d0w = (d0l & 0xffff);
        d0w = (int16_t)(( d0w>>= 1) &0x7fff);

        int d1l = (uint16_t)P0302_ui_Value2 * 11;
        d0w = d0w + (d1l &0xffff);
        d0w = d0w + 99;
        d0w = (int16_t) ((d0w>>2)&0x3fff);
        d0w = d0w & 0xffff;

        d0w = d0w% P0303_i_Modulo;
        return d0w;
		/* Pseudorandom number generator */
}

int F0170_DUNGEON_GetRandomOrnamentOrdinal(int P0304_B_RandomOrnamentAllowed,int P0305_i_OrnamentCount, int P0306_i_MapX, int P0307_i_MapY, int P0308_i_Modulo)
{
    if (!P0304_B_RandomOrnamentAllowed) return 0;
    int L0305_i_RandomOrnamentIndex;
    
    L0305_i_RandomOrnamentIndex = F0169_DUNGEON_GetRandomOrnamentIndex(2000 + (P0306_i_MapX << 5) + P0307_i_MapY,  3000 + (G0272_i_CurrentMapIndex << 6) + G0273_i_CurrentMapWidth + G0274_i_CurrentMapHeight, P0308_i_Modulo);
		if (L0305_i_RandomOrnamentIndex < P0305_i_OrnamentCount)
        {
            return L0305_i_RandomOrnamentIndex + 1;
        }
        return 0;
}
My Values for the map:
int G0272_i_CurrentMapIndex = 0;
int G0273_i_CurrentMapWidth = 18;
int G0274_i_CurrentMapHeight = 18;

switching to 19 .. same.. its like finding the needle in a haystack :-D

but no chance.. on map 0 in location 3,4 should be ordinal 4.. (iron ring)
and on map 0 location 12,4 ordinal 3 (grate)

but i get different random numbers..

---

ok i tried now the amiga version 3.6.. it has different oranaments on other walls.. so maybe the pc version is different..
Cycl0ne
Craftsman
Posts: 103
Joined: Mon Apr 19, 2010 11:33 am

Re: Working on a new Data Viewer like ADGE

Post by Cycl0ne »

but from christophef source they both use the same code. very very strange...

left amige, right pc same position after the start the first turn..

Image
User avatar
Paul Stevens
CSBwin Guru
Posts: 4318
Joined: Sun Apr 08, 2001 6:00 pm
Location: Madison, Wisconsin, USA

Re: Working on a new Data Viewer like ADGE

Post by Paul Stevens »

If you like, I'll take the time to debug the Atari code and report all
the parameters, intermediate values, and result. It will be tedious
and a bit time-consuming so let me know if this would be helpful.
I don't mind doing it but wouldn't want my effort to be wasted.
Actually, my code could be wrong! I never compared the emulated
Atari random decorations with the results of CSBwin. I compared gameplay
but gameplay would not be affected by random decoration errors.
Let me know.....
Post Reply

Return to “Editors and Tools (DMute, DM Builder, ADGE, etc.)”