public void SauveSpriteCmp(string fileName, string version) { byte[] ret = MakeSprite(); byte[] sprCmp = new byte[ret.Length]; int l = PackDepack.Pack(ret, ret.Length, sprCmp, 0); StreamWriter sw = SaveAsm.OpenAsm(fileName, version); SaveAsm.GenereDatas(sw, sprCmp, l, 16); SaveAsm.CloseAsm(sw); main.SetInfo("Sauvegarde sprite assembleur compacté ok."); }
private int PackWinDC(byte[] bufOut, ref int sizeDepack, int topBottom, bool razDiff, int modeLigne, bool optimSpeed) { int xFin = 0; int xDeb = BitmapCpc.NbCol; int yDeb = BitmapCpc.NbLig; int yFin = 0; int lStart = 0, lEnd = BitmapCpc.NbLig, xStart = 0, xEnd = BitmapCpc.NbCol; if (razDiff) { Array.Clear(BufPrec, 0, BufPrec.Length); } // Copier l'image cpc dans le buffer de travail img.bitmapCpc.CreeBmpCpc(img.BmpLock, null); if (chkZoneVert.Checked) { xStart = topBottom < 1 ? 0 : BitmapCpc.NbCol >> 1; xEnd = topBottom == 0 ? BitmapCpc.NbCol >> 1 : BitmapCpc.NbCol; } else { lStart = topBottom < 1 ? 0 : BitmapCpc.NbLig >> 1; lEnd = topBottom == 0 ? BitmapCpc.NbLig >> 1 : BitmapCpc.NbLig; } // Recherche les "coordonnées" de l'image différente par rapport à la précédente for (int l = lStart; l < lEnd; l += modeLigne) { int adr = BitmapCpc.GetAdrCpc(l << 1); for (int oct = xStart; oct < xEnd; oct++) { if (img.bitmapCpc.bmpCpc[adr + oct] != BufPrec[adr + oct]) { xDeb = Math.Min(xDeb, oct); xFin = Math.Max(xFin, oct); yDeb = Math.Min(yDeb, l); yFin = Math.Max(yFin, l); BufPrec[adr + oct] = img.bitmapCpc.bmpCpc[adr + oct]; } } } int tailleX = xFin > xDeb ? xFin - xDeb + 1 : 0; int tailleY = (yFin + 1 - yDeb) / modeLigne; int length = tailleX * tailleY; if (length > 0) { Array.Clear(bLigne, 0, bLigne.Length); int pos = 0, AdrEcr; bLigne[pos++] = (byte)tailleX; bLigne[pos++] = (byte)tailleY; if (!optimSpeed) { AdrEcr = 0xC000 + xDeb + (yDeb >> 3) * BitmapCpc.NbCol + (yDeb & 7) * 0x800; bLigne[pos++] = (byte)(AdrEcr & 0xFF); bLigne[pos++] = (byte)(AdrEcr >> 8); } if (chkCol.Checked) { // passage en mode "colonne par colonne" for (int x = xDeb; x <= xFin; x++) { for (int l = 0; l < tailleY * modeLigne; l += modeLigne) { int offsetEcr = ((l + yDeb) >> 3) * BitmapCpc.NbCol + ((l + yDeb) & 7) * 0x800 + x; if (optimSpeed) { AdrEcr = 0xC000 + offsetEcr; bLigne[pos++] = (byte)(AdrEcr & 0xFF); bLigne[pos++] = (byte)(AdrEcr >> 8); } bLigne[pos++] = BufPrec[offsetEcr]; } } } else { // Passage en mode "ligne à ligne" for (int l = yDeb; l <= yFin; l += modeLigne) { int offsetEcr = (l >> 3) * BitmapCpc.NbCol + (l & 7) * 0x800 + xDeb; if (optimSpeed) { AdrEcr = 0xC000 + offsetEcr; bLigne[pos++] = (byte)(AdrEcr & 0xFF); bLigne[pos++] = (byte)(AdrEcr >> 8); } Array.Copy(BufPrec, offsetEcr, bLigne, pos, tailleX); pos += tailleX; } } int lpack = PackDepack.Pack(bLigne, pos, bufOut, 0); sizeDepack = length + 4; return(lpack); } else { return(0); } }
/* * private int PackWinDC4(byte[] bufOut, bool razDiff = false) { * int[] xFin = { 0, 0, 0, 0 }; * int[] xDeb = { img.NbCol, img.NbCol, img.NbCol, img.NbCol }; * int[] yDeb = { img.NbLig, img.NbLig, img.NbLig, img.NbLig }; * int[] yFin = { 0, 0, 0, 0 }; * int[] ld = { 0, 0, img.NbLig >> 1, img.NbLig >> 1 }; * int[] lf = { img.NbLig >> 1, img.NbLig >> 1, img.NbLig, img.NbLig }; * int[] od = { 0, img.NbCol >> 1, 0, img.NbCol >> 1 }; * int[] of = { img.NbCol >> 1, img.NbCol, img.NbCol >> 1, img.NbCol }; * if (razDiff) * Array.Clear(BufPrec, 0, BufPrec.Length); * * // Copier l'image cpc dans le buffer de travail * img.bitmapCpc.CreeBmpCpc(img.BmpLock); * * int posBufOut = 1; * byte nbZone = 0; * // Recherche les "coordonnées" de l'image différente par rapport à la précédente * for (int i = 0; i < 4; i++) { * for (int l = ld[i]; l < lf[i]; l++) { * int adr = img.GetAdrCpc(l << 1); * for (int oct = od[i]; oct < of[i]; oct++) { * if (img.bitmapCpc.bmpCpc[adr + oct] != BufPrec[adr + oct]) { * xDeb[i] = Math.Min(xDeb[i], oct); * xFin[i] = Math.Max(xFin[i], oct); * yDeb[i] = Math.Min(yDeb[i], l); * yFin[i] = Math.Max(yFin[i], l); * BufPrec[adr + oct] = img.bitmapCpc.bmpCpc[adr + oct]; * } * } * } * if (xFin[i] >= xDeb[i] && yFin[i] >= yDeb[i]) { * int nbOctets = xFin[i] - xDeb[i] + 1; * int length = nbOctets * (yFin[i] + 1 - yDeb[i]); * Array.Clear(bLigne, 0, bLigne.Length); * int AdrEcr = xDeb[i] + (yDeb[i] >> 3) * img.NbCol + (yDeb[i] & 7) * 0x800; * bLigne[0] = (byte)AdrEcr; * bLigne[1] = (byte)(AdrEcr >> 8); * bLigne[2] = (byte)(xFin[i] - xDeb[i] + 1); * bLigne[3] = (byte)(yFin[i] - yDeb[i] + 1); * // Passage en mode "ligne à ligne * int pos = 4; * for (int l = yDeb[i]; l <= yFin[i]; l++) { * Array.Copy(BufPrec, (l >> 3) * img.NbCol + (l & 7) * 0x800 + xDeb[i], bLigne, pos, nbOctets); * pos += nbOctets; * } * posBufOut = PackDepack.Pack(bLigne, length, bufOut, posBufOut); * nbZone++; * } * } * bufOut[0] = nbZone; * return posBufOut; * } */ private int PackAscii(byte[] bufOut, ref int sizeDepack, bool razDiff, bool firstFrame, bool imageMode, bool perte = false) { int posDiff = 0, lastPosDiff = 0, nDiff = 0; byte nbModif = 0; int tailleMax = (BitmapCpc.NbLig * BitmapCpc.NbCol) >> 3; if (razDiff) { Array.Clear(OldImgAscii, 0, OldImgAscii.Length); } if (perte) { for (int i = BitmapCpc.NbCol; i < tailleMax - BitmapCpc.NbCol; i++) { if (OldImgAscii[i - 1] == img.bitmapCpc.imgAscii[i - 1] && OldImgAscii[i + 1] == img.bitmapCpc.imgAscii[i + 1] && OldImgAscii[i - BitmapCpc.NbCol] == img.bitmapCpc.imgAscii[i - BitmapCpc.NbCol] && OldImgAscii[i + BitmapCpc.NbCol] == img.bitmapCpc.imgAscii[i + BitmapCpc.NbCol]) { img.bitmapCpc.imgAscii[i] = OldImgAscii[i]; } } } for (int i = 0; i < tailleMax; i++) { byte oldAsc = OldImgAscii[i]; byte newAsc = img.bitmapCpc.imgAscii[i]; if (nbModif == 255 || (oldAsc != newAsc) || firstFrame) { if (oldAsc != newAsc) { nDiff++; lastPosDiff = (posDiff + 2); } DiffImage[posDiff++] = (byte)nbModif; DiffImage[posDiff++] = newAsc; nbModif = 0; if (posDiff >= DiffImage.Length) { break; } } else { nbModif++; } } Array.Copy(img.bitmapCpc.imgAscii, OldImgAscii, OldImgAscii.Length); sizeDepack = img.bitmapCpc.imgAscii.Length + 4; if (nDiff == 0 && rbFrameFull.Checked) { if (rbFrameFull.Checked) { BufTmp[0] = (byte)'I'; lastAscii = 'I'; return(PackDepack.Pack(BufTmp, 1, bufOut, 0)); } else { img.main.SetInfo("Impossible d'ajouter image identique..."); return(0); } } else { BufTmp[0] = (byte)'O'; Array.Copy(img.bitmapCpc.imgAscii, 0, BufTmp, 1, tailleMax); int lo = rbFrameO.Checked || imageMode?PackDepack.Pack(img.bitmapCpc.imgAscii, tailleMax, BufPrec, 0) : PackDepack.Pack(BufTmp, tailleMax + 1, BufPrec, 0); posDiff = Math.Min(lastPosDiff, posDiff); if (rbFrameD.Checked || imageMode) { BufTmp[0] = (byte)(posDiff >> 1); BufTmp[1] = (byte)(posDiff >> 9); Array.Copy(DiffImage, 0, BufTmp, 2, posDiff); } else { BufTmp[0] = (byte)'D'; BufTmp[1] = (byte)(posDiff >> 1); BufTmp[2] = (byte)(posDiff >> 9); Array.Copy(DiffImage, 0, BufTmp, 3, posDiff); } int ldRaw = posDiff + (rbFrameD.Checked ? 2 : 3); int ld = PackDepack.Pack(BufTmp, ldRaw, bufOut, 0); if (ld > ldRaw) { img.main.SetInfo("Perte de " + (ld - ldRaw).ToString() + " octets..."); } if (lo > ld && !rbFrameO.Checked || rbFrameD.Checked) { if (imageMode) { rbFrameFull.Checked = false; rbFrameD.Checked = true; } lastAscii = 'D'; return(ld); } else { Array.Copy(BufPrec, bufOut, lo); if (imageMode) { rbFrameFull.Checked = false; rbFrameO.Checked = true; } lastAscii = 'O'; return(lo); } } }
private int PackDirectMem(byte[] bufOut, ref int sizeDepack, bool newMethode, bool razDiff) { if (razDiff) { Array.Clear(BufPrec, 0, BufPrec.Length); } // Copier l'image cpc dans le buffer de travail img.bitmapCpc.CreeBmpCpc(img.BmpLock, null); byte[] src = img.bitmapCpc.bmpCpc; int maxSize = (BitmapCpc.NbCol) + ((BitmapCpc.NbLig - 1) >> 3) * (BitmapCpc.NbCol) + ((BitmapCpc.NbLig - 1) & 7) * 0x800; if (maxSize >= 0x4000) { maxSize += 0x3800; } int maxDelta = newMethode ? 127 : 255; // Recherche les "coordonnées" de l'image différente par rapport à la précédente int bc = 0, posDiff = 0; byte deltaAdr = 0; for (int adr = 0; adr < maxSize; adr++) { byte o = BufPrec[adr]; byte n = src[adr]; if (deltaAdr == 127 || (o != n)) { if (newMethode && adr < maxSize - 256 && BufPrec[adr + 1] != src[adr + 1] && BufPrec[adr + 2] != src[adr + 2] && src[adr + 1] == n && src[adr + 2] == n) { DiffImage[posDiff++] = (byte)(deltaAdr | 0x80); bc++; int d = 0; while (d < 255 && src[adr + d] == n) { d++; } DiffImage[posDiff++] = (byte)d; DiffImage[posDiff++] = n; deltaAdr = 0; adr += d - 1; } else { DiffImage[posDiff++] = (byte)deltaAdr; DiffImage[posDiff++] = n; bc++; deltaAdr = 0; if (posDiff >= DiffImage.Length) { break; } } } else { deltaAdr++; } } BufTmp[0] = (byte)(bc); BufTmp[1] = (byte)(bc >> 8); Buffer.BlockCopy(DiffImage, 0, BufTmp, 2, posDiff); int lPack = PackDepack.Pack(BufTmp, posDiff + 2, bufOut, 0); Array.Copy(src, BufPrec, BufPrec.Length); sizeDepack = posDiff + 2; return(lPack); }
public Bitmap CreateImageFromCpc(int length, Param par, bool isSprite = false) { if (!isSprite) { if (bmpCpc[0] == 'M' && bmpCpc[1] == 'J' && bmpCpc[2] == 'H') { DepactOCP(); } else if (bmpCpc[0] == 'P' && bmpCpc[1] == 'K' && (bmpCpc[2] == 'O' || bmpCpc[2] == 'V' || bmpCpc[2] == 'S')) { DepactPK(); } else { if (!InitDatas()) { if (length == 16384) { nbCol = 80; nbLig = 200; } else if (length < 32000) { int l = PackDepack.Depack(bmpCpc, 0, bufTmp); Array.Copy(bufTmp, bmpCpc, l); if (!InitDatas()) { cpcPlus = false; nbCol = maxColsCpc; nbLig = maxLignesCpc; SetPalette(bmpCpc, 0x600, cpcPlus); } } else { if (length > 0x4000) { nbCol = maxColsCpc; nbLig = maxLignesCpc; } } } } } par.cpcPlus = cpcPlus; // Rendu dans un bitmap PC DirectBitmap loc = new DirectBitmap(nbCol << 3, nbLig * 2); for (int y = 0; y < nbLig << 1; y += 2) { int mode = (modeVirtuel >= 5 ? 1 : modeVirtuel >= 3 ? (y & 2) == 0 ? modeVirtuel - 2 : modeVirtuel - 3 : modeVirtuel); int adrCPC = isSprite ? nbCol * (y >> 1) : GetAdrCpc(y); int xBitmap = 0; for (int x = 0; x < nbCol; x++) { byte octet = bmpCpc[adrCPC + x]; switch (mode) { case 0: loc.SetHorLineDouble(xBitmap, y, 4, GetPalCPC(Palette[(octet >> 7) + ((octet & 0x20) >> 3) + ((octet & 0x08) >> 2) + ((octet & 0x02) << 2)])); loc.SetHorLineDouble(xBitmap + 4, y, 4, GetPalCPC(Palette[((octet & 0x40) >> 6) + ((octet & 0x10) >> 2) + ((octet & 0x04) >> 1) + ((octet & 0x01) << 3)])); xBitmap += 8; break; case 1: loc.SetHorLineDouble(xBitmap, y, 2, GetPalCPC(Palette[((octet >> 7) & 1) + ((octet >> 2) & 2)])); loc.SetHorLineDouble(xBitmap + 2, y, 2, GetPalCPC(Palette[((octet >> 6) & 1) + ((octet >> 1) & 2)])); loc.SetHorLineDouble(xBitmap + 4, y, 2, GetPalCPC(Palette[((octet >> 5) & 1) + ((octet >> 0) & 2)])); loc.SetHorLineDouble(xBitmap + 6, y, 2, GetPalCPC(Palette[((octet >> 4) & 1) + ((octet << 1) & 2)])); xBitmap += 8; break; case 2: for (int i = 8; i-- > 0;) { loc.SetPixel(xBitmap, y, GetPalCPC(Palette[(octet >> i) & 1])); loc.SetPixel(xBitmap++, y + 1, GetPalCPC(Palette[(octet >> i) & 1])); } break; } } } return(loc.Bitmap); }
private void DepactPK() { byte[] Palette = new byte[0x100]; // Valeurs par défaut cpcPlus = false; nbCol = 80; nbLig = 200; // //PKSL -> 320x200 STD //PKS3 -> 320x200 Mode 3 //PKSP -> 320x200 PLUS //PKVL -> Overscan STD //PKVP -> Overscan PLUS // cpcPlus = (bmpCpc[3] == 'P') || (bmpCpc[2] == 'O'); bool Overscan = (bmpCpc[2] == 'V') || (bmpCpc[3] == 'V'); bool Std = (bmpCpc[2] == 'S' && bmpCpc[3] == 'L'); if (Std) { for (int i = 0; i < 17; i++) { Palette[i] = bmpCpc[i + 4]; } } int l = PackDepack.Depack(bmpCpc, Std ? 21 : 4, bufTmp); if (Std) { int i = 0; for (int x = 0; x < 80; x++) { for (int y = 0; y < 200; y++) { bmpCpc[x + GetAdrCpc(y << 1)] = bufTmp[i++]; } } } else { Array.Copy(bufTmp, bmpCpc, l); } if (Overscan) { nbCol = maxColsCpc; nbLig = maxLignesCpc; SetPalette(bmpCpc, 0x600, cpcPlus); } else { if (Std) { SetPalette(Palette, 0, cpcPlus); } else { SetPalette(bmpCpc, 0x17D0, cpcPlus); } } }
static public int SauveScr(string fileName, BitmapCpc bitmapCpc, ImageCpc img, Param param, bool compact, string version = null, int[,] colMode5 = null) { byte[] bufPack = new byte[0x8000]; bool overscan = (BitmapCpc.NbLig * BitmapCpc.NbCol > 0x3F00); if (param.withPalette && version == null) { if (param.cpcPlus) { ModePal[0] = (byte)(BitmapCpc.modeVirtuel | 0x8C); int k = 1; for (int i = 0; i < 16; i++) { ModePal[k++] = (byte)(((BitmapCpc.Palette[i] >> 4) & 0x0F) | (BitmapCpc.Palette[i] << 4)); ModePal[k++] = (byte)(BitmapCpc.Palette[i] >> 8); } } else { ModePal[0] = (byte)BitmapCpc.modeVirtuel; for (int i = 0; i < 16; i++) { ModePal[1 + i] = (byte)BitmapCpc.Palette[i]; } } } byte[] imgCpc = bitmapCpc.bmpCpc; if (!overscan) { Buffer.BlockCopy(ModePal, 0, imgCpc, 0x17D0, ModePal.Length); if (param.withCode && version == null) { if (param.cpcPlus) { Buffer.BlockCopy(CodeP0, 0, imgCpc, 0x07D0, CodeP0.Length); Buffer.BlockCopy(CodeP1, 0, imgCpc, 0x0FD0, CodeP1.Length); Buffer.BlockCopy(CodeP3, 0, imgCpc, 0x1FD0, CodeP3.Length); } else { Buffer.BlockCopy(CodeStd, 0, imgCpc, 0x07D0, CodeStd.Length); } if (BitmapCpc.modeVirtuel == 3 || BitmapCpc.modeVirtuel == 4) { Buffer.BlockCopy(codeEgx0, 0, imgCpc, 0x37D0, codeEgx0.Length); Buffer.BlockCopy(codeEgx1, 0, imgCpc, 0x2FD0, codeEgx1.Length); imgCpc[0x07F2] = 0xD0; imgCpc[0x07F3] = 0xF7; // CALL 0xF7D0 imgCpc[0x37FA] = 0xEF; // Call 0xEFD0 } } } else { if (BitmapCpc.NbLig * BitmapCpc.NbCol > 0x4000) { Buffer.BlockCopy(ModePal, 0, imgCpc, 0x600, ModePal.Length); if (param.withCode && version == null) { if (param.cpcPlus) { Buffer.BlockCopy(CodeOvP, 0, imgCpc, 0x621, CodeOvP.Length); } else { Buffer.BlockCopy(CodeOv, 0, imgCpc, 0x611, CodeOv.Length); } if (BitmapCpc.modeVirtuel == 3 || BitmapCpc.modeVirtuel == 4) { Buffer.BlockCopy(codeEgx0, 0, imgCpc, 0x1600, codeEgx0.Length); Buffer.BlockCopy(codeEgx1, 0, imgCpc, 0x1640, codeEgx1.Length); if (param.cpcPlus) { imgCpc[0x669] = 0xCD; imgCpc[0x66A] = 0x00; imgCpc[0x66B] = 0x18; // CALL #1800 } else { imgCpc[0x631] = 0x00; imgCpc[0x632] = 0x18; // CALL #1800 } imgCpc[0x1629] = 0x40; imgCpc[0x162A] = 0x18; // CALL #1840 } } } } short startAdr = (short)(overscan ? 0x200 : 0xC000); short exec = (short)(overscan ? param.cpcPlus ? 0x821 : 0x811 : 0xC7D0); CpcAmsdos entete; int lg = BitmapCpc.BitmapSize; if (compact) { lg = PackDepack.Pack(bitmapCpc.bmpCpc, lg, bufPack, 0) + 1; // Prendre 1 octet de marge ? if (param.withCode && version == null) { Buffer.BlockCopy(codeDepack, 0, bufPack, lg, codeDepack.Length); bufPack[lg + 4] = (byte)(startAdr & 0xFF); bufPack[lg + 5] = (byte)(startAdr >> 8); startAdr = (short)(0xA657 - (lg + codeDepack.Length)); bufPack[lg + 1] = (byte)(startAdr & 0xFF); bufPack[lg + 2] = (byte)(startAdr >> 8); bufPack[lg + 32] = (byte)(exec & 0xFF); bufPack[lg + 33] = (byte)(exec >> 8); lg += codeDepack.Length; exec = (short)(0xA657 - codeDepack.Length); } else { startAdr = (short)(0xA657 - lg); exec = 0; } } if (version != null) { // Sauvegarde source assembleur StreamWriter sw = SaveAsm.OpenAsm(fileName, version); int org = 0xA500 - lg - (BitmapCpc.modeVirtuel == 5 ? 600 : 0); sw.WriteLine(" ORG #"+ org.ToString("X4")); sw.WriteLine(" Nolist"); sw.WriteLine("ImageCmp:"); SaveAsm.GenereDatas(sw, bufPack, lg, 16); sw.WriteLine(" List"); if (param.withCode) { sw.WriteLine(" RUN $"); sw.WriteLine("_StartDepack:"); if (BitmapCpc.modeVirtuel == 3 || BitmapCpc.modeVirtuel == 4) { SaveAsm.GenereAfficheModeEgx(sw, BitmapCpc.Palette, overscan); } else { SaveAsm.GenereFormatEcran(sw); if (BitmapCpc.modeVirtuel == 5) { SaveAsm.GenereAfficheModeX(sw, colMode5, overscan); } else { SaveAsm.GenereAfficheStd(sw, img, BitmapCpc.modeVirtuel, BitmapCpc.Palette, overscan); } } } SaveAsm.CloseAsm(sw); } else { entete = CpcSystem.CreeEntete(fileName, startAdr, (short)lg, exec); BinaryWriter fp = new BinaryWriter(new FileStream(fileName, FileMode.Create)); fp.Write(CpcSystem.AmsdosToByte(entete)); fp.Write(compact ? bufPack : bitmapCpc.bmpCpc, 0, lg); fp.Close(); } return(lg); }