コード例 #1
0
ファイル: Level.cs プロジェクト: zipplet/WL1-Editor
        public static List <KeyValuePair <int, int> > GetCourseIds(Rom rom)
        {
            //convert course id => course no using data in ROM
            rom.SetBank(0);
            var courseIdToNo = new List <KeyValuePair <int, int> >();

            for (int i = 0; i <= 0x2A; i++)
            {
                int levelpointer = rom.ReadWord(0x0534 + i * 2);
                int courseNo     = (levelpointer - 0x0587) / 3;
                courseIdToNo.Add(new KeyValuePair <int, int>(i, courseNo));
            }

            return(courseIdToNo);
        }
コード例 #2
0
ファイル: Level.cs プロジェクト: zipplet/WL1-Editor
        public static bool SaveChanges(Rom rom, int course, string filePath, out string errorMessage)
        {
            //rom expansion give new banks for level data
            rom.ExpandTo1MB();

            SaveBlocksToRom(rom, course);
            if (!SaveObjectsToRom(rom, course, out errorMessage))
            {
                return(false);
            }

            rom.FixCRC();
            rom.Save(filePath);
            return(true);
        }
コード例 #3
0
ファイル: Level.cs プロジェクト: zipplet/WL1-Editor
        public static int SearchWarp(Rom rom, int course, int sector)
        {
            rom.SetBank(0xC);
            //search sector that target that sector
            for (int i = 0; i < 32; i++)
            {
                int warp = rom.ReadWord(0x4F30 + course * 64 + i * 2);

                if (rom.ReadByte(warp) == sector)
                {
                    return(warp);
                }
            }

            return(-1);
        }
コード例 #4
0
ファイル: Level.cs プロジェクト: zipplet/WL1-Editor
        public static void DumpBonusSprites(Rom rom)
        {
            Array.Clear(tiles8x8.Bits, 0, tiles8x8.Bits.Length);
            //bonus sprites
            rom.SetBank(0x5);
            Dump8x8Tiles(rom, 0x4C81, 23, 0, 0x1E, enemyPalette, true);

            rom.SetBank(0x11);
            Dump8x8Tiles(rom, 0x7300, 4, 16 + 23, 0x1E, enemyPalette, true);

            rom.SetBank(0xF);
            int[] sprites = { 0x4ACB, 0x4AEB, 0x4ADB, 0x4AFB, 0x4B0B, 0x4B1B, 0x4B2B, 0x4B4B, 0x4B5B };
            for (int i = 0; i < sprites.Length; i++)
            {
                DumpSprite(rom, 8 + i * 16, 16, sprites[i], tilesObjects);
            }
        }
コード例 #5
0
ファイル: Level.cs プロジェクト: zipplet/WL1-Editor
        static void FindEnemiesData(Rom rom, int enemiesPointer, out int enemyId, out int tilesPointer)
        {
            byte[] pattern =
            {
                0x3E, 0x00,                       //ld  a, ..
                0xEA, 0x2F, 0xA3,                 //ld  (A32F),a
                0x3E, 0x00,                       //ld  a, ..
                0xEA, 0x30, 0xA3,                 //ld  (A330),a
                0x01, 0x00, 0x00,                 //ld  bc, ..
                0xCD, 0xA7, 0x40                  //call 40A7
            };

            rom.SetBank(0x7);
            int position = enemiesPointer;

            while (rom.ReadByte(position) != 0xC9)            //ret
            {
                bool match = true;
                for (int j = 0; j < pattern.Length; j++)
                {
                    byte valueFromRom   = rom.ReadByte(position + j);
                    byte valueToCompare = pattern[j];

                    if (valueToCompare != 0x00 && valueFromRom != valueToCompare)
                    {
                        match = false;
                        break;
                    }
                }

                if (match)
                {
                    enemyId      = rom.ReadByte(position + 6) << 8 | rom.ReadByte(position + 1);
                    tilesPointer = rom.ReadByte(position + 12) << 8 | rom.ReadByte(position + 11);
                    return;
                }

                position++;
            }

            throw new Exception("cannot find enemies data");
        }
コード例 #6
0
ファイル: Level.cs プロジェクト: zipplet/WL1-Editor
        static byte[] RLEDecompressObjects(Rom rom, int enemiesData)
        {
            int position = 0;

            byte[] decompressed = new byte[0x2000];

            while (position < decompressed.Length)
            {
                byte data = rom.ReadByte(enemiesData++);
                decompressed[position++] = (byte)(data >> 4);
                decompressed[position++] = (byte)(data & 0xF);

                byte repeat = rom.ReadByte(enemiesData++);
                for (int i = 0; i < repeat; i++)
                {
                    decompressed[position++] = 0;
                    decompressed[position++] = 0;
                }
            }

            return(decompressed);
        }
コード例 #7
0
ファイル: MainForm.cs プロジェクト: zipplet/WL1-Editor
        void LoadToolStripMenuItemClick(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            openFileDialog1.Filter = "GB ROM Image (*.gb)|*.gb";

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                Rom newRom = new Rom();
                newRom.Load(openFileDialog1.FileName);
                if (newRom.Title == "SUPERMARIOLAND3")
                {
                    rom = newRom;
                    LoadLevelCombobox();
                    Level.DumpBonusSprites(rom);
                    Level.DumpPlayerSprite(rom);
                    romFilePath = openFileDialog1.FileName;

                    if (levelComboBox.SelectedIndex == 0)
                    {
                        LevelComboBoxSelectedIndexChanged(sender, e);
                    }
                    else
                    {
                        levelComboBox.SelectedIndex = 0;
                    }

                    toolboxToolStripMenuItem.Enabled = true;
                    saveAsToolStripMenuItem.Enabled  = true;
                    levelComboBox.Visible            = true;
                    LevelPanel.Visible = true;
                }
                else
                {
                    MessageBox.Show("Please select a valid WarioLand 1 rom", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
コード例 #8
0
ファイル: Level.cs プロジェクト: tigrouind/WL1-Editor
        public static void Dump16x16Tiles(Rom rom, int tileindexaddress, Bitmap gfx8, Graphics g, bool switchA, bool switchB)
        {
            for(int n = 0 ; n < 16 ; n++)
            {
                for(int i = 0 ; i < 8 ; i++)
                {
                    int tileIndex = i + n * 8;
                    tileIndex = Level.Switch(tileIndex, switchA, switchB);

                    for(int k = 0 ; k < 2 ; k++)
                    {
                        for(int j = 0 ; j < 2 ; j++)
                        {
                            byte subTileIndex = rom.ReadByte(tileindexaddress + tileIndex * 4 + k * 2 + j);

                            g.DrawImage(gfx8,
                                    new Rectangle(j * 8 + i * 16, k * 8 + n * 16, 8, 8),
                                    new Rectangle((subTileIndex % 16) * 8, ((subTileIndex) / 16) * 8, 8, 8),
                                    GraphicsUnit.Pixel);
                        }
                    }
                }
            }
        }
コード例 #9
0
ファイル: Level.cs プロジェクト: tigrouind/WL1-Editor
        public static void Dump8x8Tiles(Rom rom, int gfxaddress, Bitmap gfx8, int tiles, int rowpos, byte palette)
        {
            for(int n = 0 ; n < tiles ; n++)
            {
                for(int j = 0 ; j < 8 ; j++)
                {
                    byte data0 = rom.ReadByte(gfxaddress++);
                    byte data1 = rom.ReadByte(gfxaddress++);

                    for(int i = 0 ; i < 8 ; i++)
                    {
                        int pixelA = (data0 >> (7 - i)) & 0x1;
                        int pixelB = (data1 >> (7 - i)) & 0x1;
                        int pixel = pixelA + pixelB * 2;
                        int palindex = (palette >> pixel * 2) & 0x3;

                        int x = i + n%16 * 8;
                        int y = j + (n/16 + rowpos) * 8;

                        gfx8.SetPixel(x, y, paletteColors[palindex]);
                    }
                }
            }
        }
コード例 #10
0
ファイル: Level.cs プロジェクト: zipplet/WL1-Editor
        static Rectangle DumpSprite(Rom rom, int posx, int posy, int spriteAddress, DirectBitmap tilesDest)
        {
            Rectangle rectangle = Rectangle.Empty;
            int       pos       = spriteAddress;

            pos = rom.ReadWord(pos);
            pos++;             //skip sprite flags

            while (rom.ReadByte(pos) != 0x80)
            {
                int spx, spy;
                unchecked
                {
                    spy = (sbyte)rom.ReadByte(pos++) + posy;
                    spx = (sbyte)rom.ReadByte(pos++) + posx;
                }
                int spriteData  = rom.ReadByte(pos++);
                int spriteIndex = (spriteData & 0x3F);

                DumpSpriteInternal(spx, spy, spriteIndex, spriteData, tilesDest, ref rectangle);
            }

            return(rectangle);
        }
コード例 #11
0
ファイル: Level.cs プロジェクト: zipplet/WL1-Editor
        static Rectangle DumpSpritePlayer(Rom rom, int posx, int posy, int spriteAddress, bool horizontalFlip)
        {
            Rectangle rectangle = Rectangle.Empty;
            int       pos       = spriteAddress;

            Func <sbyte, sbyte> hflip = x => (sbyte)(horizontalFlip ? ((~(sbyte)x) - 7) : x);

            pos = rom.ReadWord(pos);
            while (rom.ReadByte(pos) != 0x80)
            {
                int spx, spy;
                unchecked
                {
                    spy = (sbyte)rom.ReadByte(pos++) + posy;
                    spx = hflip((sbyte)rom.ReadByte(pos++)) + posx;
                }
                int spriteIndex = rom.ReadByte(pos++);
                int spriteFlags = rom.ReadByte(pos++) ^ (horizontalFlip ? 0x40 : 0x00);

                DumpSpriteInternal(spx, spy, spriteIndex, spriteFlags, playerSprite, ref rectangle);
            }

            return(rectangle);
        }
コード例 #12
0
ファイル: Level.cs プロジェクト: tigrouind/WL1-Editor
        public static int SearchWarp(Rom rom, int course, int sector)
        {
            rom.SetBank(0xC);
            int warp = rom.ReadWord(0x4F30 + course * 64 + sector * 2);
            if(rom.ReadByte(warp) != 32)
            {
                //search sector that target that sector
                for(int i = 0 ; i < 32 ; i++)
                {
                    warp = rom.ReadWord(0x4F30 + course * 64 + i * 2);

                    if(rom.ReadByte(warp) == sector)
                    {
                        return warp;
                    }
                }
            }

            return -1;
        }
コード例 #13
0
ファイル: Level.cs プロジェクト: tigrouind/WL1-Editor
        public static bool SaveObjectsToRom(Rom rom, int course, out string errorMessage)
        {
            byte[][] enemyData = new byte[0x2B][];

            //save objects
            rom.SetBank(0x7);
            for(int i = 0 ; i < 0x2B ; i++)
            {
                int objectsPos = rom.ReadWord(0x4199 + i * 2);
                enemyData[i] = RLEDecompressObjects(rom, objectsPos).Take(0x2000).ToArray();
            }
            enemyData[course]= objectsData;

            int objectSize = enemyData.Sum(x => RLECompressObjects(x).Count());
            if(objectSize > 4198)
            {
                errorMessage = string.Format("Object data is too big to fit in ROM.\r\nPlease remove at least {0} byte(s).", objectSize - 4198);
                return false;
            }

            int startPos = rom.ReadWord(0x4199);
            for(int i = 0 ; i < 0x2B ; i++)
            {
                rom.WriteWord(0x4199 + i * 2, (ushort)startPos);

                byte[] data = RLECompressObjects(enemyData[i]).ToArray();
                rom.WriteBytes(startPos, data);
                startPos += data.Length;
            }

            errorMessage = string.Empty;
            return true;
        }
コード例 #14
0
ファイル: Level.cs プロジェクト: tigrouind/WL1-Editor
        public static bool SaveChanges(Rom rom, int course, string filePath, out string errorMessage)
        {
            //rom expansion give new banks for level data
            rom.ExpandTo1MB();

            SaveBlocksToRom(rom, course);
            if(!SaveObjectsToRom(rom, course, out errorMessage))
            {
                return false;
            }

            rom.FixCRC();
            rom.Save(filePath);
            return true;
        }
コード例 #15
0
ファイル: Level.cs プロジェクト: tigrouind/WL1-Editor
        public static void SaveBlocksToRom(Rom rom, int course)
        {
            //grab all levels data at once
            byte[][] allTiles = new byte[0x2B][];

            for(int i = 0 ; i < 0x2B ; i++)
            {
                rom.SetBank(0xC);
                int headerposition = rom.ReadWord(0x4560 + i * 2);
                int tilebank = rom.ReadByte(headerposition + 9);
                int tilesubbank = rom.ReadByte(headerposition + 10);

                rom.SetBank(tilebank);
                int tilePosition = rom.ReadWord(0x4000 + tilesubbank * 2);
                byte[] tileData = RLEDecompressTiles(rom, tilePosition).Take(0x3000).ToArray();
                allTiles[i] = tileData;
            }

            Array.Copy(levelData, allTiles[course], 0x3000);

            //write them back to ROM
            byte bank = 0x20;
            byte subbank = 0;
            int writePosition = 0x4040; //first 64 bytes are reserved for level pointers
            for(int i = 0 ; i < 0x2B ; i++)
            {
                byte[] tileData = RLECompressTiles(allTiles[i]).ToArray();
                if((writePosition + tileData.Length) >= 0x8000 || subbank >= 32)
                {
                    //no more space, switch to another bank
                    bank++;
                    subbank = 0;
                    writePosition = 0x4040;
                }

                //write data to bank
                rom.SetBank(bank);
                rom.WriteWord(0x4000 + subbank * 2, (ushort)writePosition);
                rom.WriteBytes(writePosition, tileData);

                //update level header
                rom.SetBank(0xC);
                int headerposition = rom.ReadWord(0x4560 + i * 2);
                rom.WriteByte(headerposition + 9, bank);
                rom.WriteByte(headerposition + 10, subbank);

                subbank++;
                writePosition += tileData.Length;
            }
        }
コード例 #16
0
ファイル: Level.cs プロジェクト: tigrouind/WL1-Editor
 public static IEnumerable<byte> RLEDecompressTiles(Rom rom, int tilesdata)
 {
     while(true)
     {
         byte data = rom.ReadByte(tilesdata++);
         if((data & 0x80) == 0x80)
         {
             data = (byte)(data & 0x7F);
             byte rep = rom.ReadByte(tilesdata++);
             for(int j = 0 ; j <= rep ; j++)
             {
                 yield return data;
             }
         }
         else
         {
             yield return data;
         }
     }
 }
コード例 #17
0
ファイル: Level.cs プロジェクト: tigrouind/WL1-Editor
        public static IEnumerable<byte> RLEDecompressObjects(Rom rom, int enemiesData)
        {
            while(true)
            {
                byte data = rom.ReadByte(enemiesData++);
                yield return (byte)(data >> 4);
                yield return (byte)(data & 0xF);

                byte repeat = rom.ReadByte(enemiesData++);
                for(int i = 0 ; i < repeat ; i++)
                {
                    yield return 0;
                    yield return 0;
                }
            }
        }
コード例 #18
0
ファイル: Level.cs プロジェクト: zipplet/WL1-Editor
        public static void DumpLevel(Rom rom, int course, int warp, bool reloadAll, int switchMode, int paletteIndex, int animatedTileIndex, bool reloadAnimatedTilesOnly)
        {
            int  tilebank;
            int  tileaddressB;
            int  tileaddressA;
            int  tileanimated;
            int  blockindex;
            byte palette;
            int  enemiesData;

            rom.SetBank(0xC);
            int header = rom.ReadWord(0x4560 + course * 2);

            if (warp != -1)
            {
                //load warp
                tilebank          = rom.ReadByte(warp + 11);
                tileaddressB      = rom.ReadWord(warp + 12);
                tileaddressA      = rom.ReadWord(warp + 14);
                tileanimated      = rom.ReadWord(warp + 18);
                blockindex        = rom.ReadWord(warp + 20);
                animatedTilesMask = rom.ReadByte(warp + 9);
                palette           = rom.ReadByte(warp + 10);
                enemiesData       = rom.ReadWord(warp + 22);
            }
            else
            {
                //or header
                tilebank          = rom.ReadByte(header + 0);
                tileaddressB      = rom.ReadWord(header + 1);
                tileaddressA      = rom.ReadWord(header + 3);
                tileanimated      = rom.ReadWord(header + 7);
                blockindex        = rom.ReadWord(header + 11);
                animatedTilesMask = rom.ReadByte(header + 26);
                palette           = rom.ReadByte(header + 27);
                enemiesData       = rom.ReadWord(header + 28);
            }

            Color[] paletteColors = palettes[paletteIndex];
            if (!reloadAnimatedTilesOnly)
            {
                int enemiesIdsPointer, enemiesTiles;
                FindEnemiesData(rom, enemiesData, out enemiesIdsPointer, out enemiesTiles);
                DumpEnemiesSprites(rom, enemiesIdsPointer, enemiesTiles);

                //dump 8x8 tiles
                Array.Clear(tiles8x8.Bits, 0, tiles8x8.Width * tiles8x8.Height);
                rom.SetBank(0x11);
                Dump8x8Tiles(rom, tileaddressA, 2 * 16, 0 * 16, palette, paletteColors);
                rom.SetBank(tilebank);
                Dump8x8Tiles(rom, tileaddressB, 6 * 16, 2 * 16, palette, paletteColors);
            }

            if (animatedTilesMask != 0)
            {
                rom.SetBank(0x11);
                Dump8x8Tiles(rom, tileanimated + animatedTileIndex * 16 * 4, 4, 2 * 16, palette, paletteColors);
            }

            //dump 16x16 tiles
            if (reloadAnimatedTilesOnly)
            {
                DumpAnimated16x16Tiles(paletteColors[0]);
            }
            else
            {
                rom.SetBank(0xB);
                Dump16x16Tiles(rom, blockindex, switchMode, paletteColors[0], out animated16x16Tiles, out animated8x8Tiles);
            }

            if (reloadAll)
            {
                //dump 16x16 blocks
                rom.SetBank(0xC);
                int blockbank   = rom.ReadByte(header + 9);
                int blockubbank = rom.ReadByte(header + 10);

                rom.SetBank(blockbank);
                int tilesdata = rom.ReadWord(0x4000 + blockubbank * 2);
                levelData = RLEDecompressTiles(rom, tilesdata);

                //dump scroll
                rom.SetBank(0xC);
                scrollData = rom.ReadBytes(0x4000 + course * 32, 32);

                //dump objects
                rom.SetBank(0x7);
                int objectsPosition = rom.ReadWord(0x4199 + course * 2);
                objectsData = RLEDecompressObjects(rom, objectsPosition);

                //dump warps
                rom.SetBank(0xC);
                warps = new Byte[32];
                for (int i = 0; i < 32; i++)
                {
                    int warpdata = rom.ReadWord(0x4F30 + course * 64 + i * 2);
                    warps[i] = rom.ReadByte(warpdata);
                }

                warioPosition    = rom.ReadWordSwap(header + 15) + rom.ReadWordSwap(header + 13) * 8192;
                warioRightFacing = (rom.ReadByte(header + 18) & 0x20) == 0;
            }
        }
コード例 #19
0
ファイル: Level.cs プロジェクト: tigrouind/WL1-Editor
        public static void DumpLevel(Rom rom, int course, int warp, Bitmap tiles8x8, Bitmap tiles16x16, bool reloadAll, bool switchA, bool switchB, int paletteIndex)
        {
            rom.SetBank(0xC);
            int header = rom.ReadWord(0x4560 + course * 2);

            int tilebank = rom.ReadByte(header + 0);
            int tileaddressB = rom.ReadWord(header + 1);
            int tileaddressA = rom.ReadWord(header + 3);
            int tileanimated = rom.ReadWord(header + 7);

            int blockbank = rom.ReadByte(header + 9);
            int blockubbank = rom.ReadByte(header + 10);
            int blockindex = rom.ReadWord(header + 11);
            byte palette = rom.ReadByte(header + 27);

            //load warp
            if(warp != -1)
            {
                tilebank = rom.ReadByte(warp + 11);
                tileaddressB = rom.ReadWord(warp + 12);
                tileaddressA = rom.ReadWord(warp + 14);
                tileanimated = rom.ReadWord(warp + 18);
                blockindex = rom.ReadWord(warp + 20);
                palette = rom.ReadByte(warp + 10);
            }

            //set palette
            paletteColors = palettes[paletteIndex];

            //dump 8x8 blocks
              	using(Graphics g = Graphics.FromImage(tiles8x8))
              	{
              		g.Clear(paletteColors[0]);
              		rom.SetBank(0x11);
                Dump8x8Tiles(rom, tileaddressA, tiles8x8, 2*16, 0, palette);
                rom.SetBank(tilebank);
                Dump8x8Tiles(rom, tileaddressB, tiles8x8, 6*16, 2, palette);
                rom.SetBank(0x11);
                Dump8x8Tiles(rom, tileanimated, tiles8x8, 4, 2, palette);

              	}

            //dump 16x16 blocks
              	using(Graphics g = Graphics.FromImage(tiles16x16))
              	{
              		g.Clear(paletteColors[0]);
                rom.SetBank(0xB);
                Dump16x16Tiles(rom, blockindex, tiles8x8, g, switchA, switchB);
              	}

              	if(reloadAll)
              	{
              	//dump level
              		rom.SetBank(blockbank);
                int tilesdata = rom.ReadWord(0x4000 + blockubbank * 2);
                levelData = RLEDecompressTiles(rom, tilesdata).Take(0x3000).ToArray();

                //dump scroll
                rom.SetBank(0xC);
                scrollData = rom.ReadBytes(0x4000 + course * 32, 32);

                //dump objects
                rom.SetBank(0x7);
                int objectsPosition = rom.ReadWord(0x4199 + course * 2);
                objectsData = RLEDecompressObjects(rom, objectsPosition).Take(0x2000).ToArray();

                //dump warps
                rom.SetBank(0xC);
                warps = new Byte[32];
                for(int i = 0 ; i < 32 ; i++)
                {
                    int warpdata = rom.ReadWord(0x4F30 + course * 64 + i * 2);
                    warps[i] = rom.ReadByte(warpdata);
                }

                warioPosition = rom.ReadWordSwap(header + 15) + rom.ReadWordSwap(header + 13) * 8192;
              	}
        }
コード例 #20
0
ファイル: MainForm.cs プロジェクト: tigrouind/WL1-Editor
        void LoadToolStripMenuItemClick(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.Filter = "GB ROM Image (*.gb)|*.gb";

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                Rom newRom = new Rom();
                newRom.Load(openFileDialog1.FileName);
                if (newRom.Title == "SUPERMARIOLAND3")
                {
                    rom = newRom;
                    LoadLevelCombobox();
                    romFilePath = openFileDialog1.FileName;

                    if(levelComboBox.SelectedIndex == 0)
                        LevelComboBoxSelectedIndexChanged(sender, e);
                    else
                        levelComboBox.SelectedIndex = 0;

                    saveToolStripMenuItem.Enabled = true;
                    saveAsToolStripMenuItem.Enabled = true;
                    levelComboBox.Visible = true;
                    LevelPanel.Visible = true;
                    tilesPictureBox.Visible = true;
                    objectPictureBox.Visible = true;
                }
                else
                {
                    MessageBox.Show("Please select a valid WarioLand 1 rom", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

            }
        }