Zum Inhalt springen
View in the app

A better way to browse. Learn more.

Fachinformatiker.de

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Empfohlene Antworten

Veröffentlicht

Hallo zusammen,

ich versuche, aus einem alten DOS Spiel die Grafiken zu lesen.
Das klappt soweit auch schon sehr gut, aber es gibt in dem Spiel auch komprimierte Grafiken.
Nun war ich nicht ganz Faul, und habe mir den Source für die ScummVM angeschaut.
Die kann das Spiel auch darstellen.

Dort bin ich auch auf die Dekomprimierungsroutine gestoßen:

	byte *AGOSEngine::vc10_uncompressFlip(const byte *src, uint16 w, uint16 h) {
	    w *= 8;
	    byte *dst, *dstPtr, *srcPtr;
	    byte color;
	    int8 cur = -0x80;
	    uint i, w_cur = w;
	    dstPtr = _videoBuf1 + w;
	    do {
	        dst = dstPtr;
	        uint h_cur = h;
	        if (cur == -0x80)
	            cur = *src++;
	        for (;;) {
	            if (cur >= 0) {
	                /* rle_same */
	                color = *src++;
	                do {
	                    *dst = color;
	                    dst += w;
	                    if (!--h_cur) {
	                        if (--cur < 0)
	                            cur = -0x80;
	                        else
	                            src--;
	                        goto next_line;
	                    }
	                } while (--cur >= 0);
	            } else {
	                /* rle_diff */
	                do {
	                    *dst = *src++;
	                    dst += w;
	                    if (!--h_cur) {
	                        if (++cur == 0)
	                            cur = -0x80;
	                        goto next_line;
	                    }
	                } while (++cur != 0);
	            }
	            cur = *src++;
	        }
	    next_line:
	        dstPtr++;
	    } while (--w_cur);
	    srcPtr = dstPtr = _videoBuf1 + w;
	    do {
	        dst = dstPtr;
	        for (i = 0; i != w; ++i) {
	            byte b = srcPtr[i];
	            b = (b >> 4) | (b << 4);
	            *--dst = b;
	        }
	        srcPtr += w;
	        dstPtr += w;
	    } while (--h);
	    return _videoBuf1;
	}



Das byte[]_videoBuf1 ist 32000 Bytes gross. (160x200 Pixel)

Nun habe ich versucht, diese Routine in Java umzuwandeln, aber stoße absolut an meine Grenzen für das Verständnis von C++:

	
	    byte[] vc10_uncompressFlip(byte[] src, int w, int h) {
	        w *= 8;
	        int dst;
	        int soff = 0;
	        int dstPtr;
	        int srcPtr;
	        byte color;
	        int cur = -0x80;
	        int i, w_cur = w;
	        dstPtr = w; //we really write to videoMemory
	        boolean break1 = false;
	        soff = 0;
	        nextline:
	        do {
	            dst = dstPtr;
	            int h_cur = h;
	            if (cur == -0x80) {
	                cur = src[soff++];
	            }
	            for (;;) {
	                if (cur >= 0) {
	                    /* rle_same */
	                    color = src[soff++];
	                    do {
	                        _videoBuf1[dst] = color;
	                        dst += w;
	                        if (--h_cur != 0) {
	                            if (--cur < 0) {
	                                cur = -0x80;
	                            } else {
	                                soff--;
	                            }
	                            break1 = true;
	                            break;
	                        }
	                    } while (--cur >= 0);
	                } else {
	                    /* rle_diff */
	                    do {
	                        _videoBuf1[dst] = src[soff++];
	                        dst += w;
	                        if (--h_cur != 0) {
	                            if (++cur == 0) {
	                                cur = -0x80;
	                            }
	                            break1 = true;
	                            break;
	                        }
	                    } while (++cur != 0);
	                }
	                if (break1) {
	                    break1 = false;
	                    break;
	                }
	                cur = src[soff++];
	            }
	            dstPtr++;
	        } while (--w_cur != 0);
	        dstPtr = w;
	        srcPtr = dstPtr;
	        do {
	            dst = dstPtr;
	            for (i = 0; i != w; ++i) {
	                int b = _videoBuf1[i + srcPtr] & 0x0ff;
	                b = (b >> 4) | (b << 4);
	                _videoBuf1[--dst] = (byte) b;
	            }
	            srcPtr += w;
	            dstPtr += w;
	        } while (--h >= 0);
	        return _videoBuf1;
	    }



Wer kann mir hier weiter helfen?
Ich verstehe weder die DO-Schleifen wirklich, noch, wie ich ein "Replacement" für das "goto" schaffen kann.
Wer traut sich zu, den obigen Code möglichst 1:1 bzw, so, dass ich es verstehe, in einen Pseudo-Code zu wandeln?

LG
Markus

  • Autor

Ok, habs herausgefunden (Zumindest so, dass es für meine Bedürfnisse funktioniert)
 

	
	    public byte[] readCompressed(byte[] srcData, int offset, int w, int h) {
	        w /= 2;
	        int len = -80;
	        byte color;
	        int dOff = 0;
	        int wCur = w;
	        int hCur;
	        do {
	            hCur = h;
	            int dOff2 = dOff;
	            if (len == -80) {
	                len = srcData[offset++];
	                if ((len & 0x80) != 0) {
	                    len = -128 + (len & 0x7f);
	                }
	            }
	            boolean stop = false;
	            for (; !stop;) {
	                if (len >= 0) {
	                    color = srcData[offset++];
	                    do {
	                        dstData[dOff2] = color;
	                        dOff2 += w;
	                        if (--hCur == 0) {
	                            if (--len < 0) {
	                                len = -80;
	                            } else {
	                                offset--;
	                            }
	                            stop = true;
	                        }
	                    } while (!stop && (--len >= 0));
	                } else {
	                    do {
	                        dstData[dOff2] = srcData[offset++];
	                        dOff2 += w;
	                        if (--hCur == 0) {
	                            if (++len == 0) {
	                                len = -80;
	                            }
	                            stop = true;
	                        }
	                    } while (!stop && ++len != 0);
	                }
	                if (!stop) {
	                    len = srcData[offset++];
	                    if ((len & 0x80) != 0) {
	                        len = -128 + (len & 0x7f);
	                    }
	                }
	            }
	            dOff++;
	        } while (--wCur > 0);
	        return dstData;
	    }

Bearbeitet von Devilmarkus

Erstelle ein Konto oder melde dich an, um einen Kommentar zu schreiben.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.