Ticket #8598: nut-allocate2.diff

File nut-allocate2.diff, 11.4 KB (added by eriktorbjorn, 14 years ago)

Proof-of-concept patch against current SVN

  • engines/scumm/smush/smush_player.cpp

     
    10421042                        _sf[1] = new SmushFont(_vm, true, false);
    10431043                        _sf[2] = new SmushFont(_vm, true, false);
    10441044                        _sf[3] = new SmushFont(_vm, true, false);
    1045                         _sf[0]->loadFont("scummfnt.nut");
    1046                         _sf[1]->loadFont("techfnt.nut");
    1047                         _sf[2]->loadFont("titlfnt.nut");
    1048                         _sf[3]->loadFont("specfnt.nut");
     1045                        _sf[0]->loadFont("scummfnt.nut", false);
     1046                        _sf[1]->loadFont("techfnt.nut", false);
     1047                        _sf[2]->loadFont("titlfnt.nut", false);
     1048                        _sf[3]->loadFont("specfnt.nut", false);
    10491049                }
    10501050        } else if (_vm->_game.id == GID_DIG) {
    10511051                if (!(_vm->_game.features & GF_DEMO)) {
    10521052                        for (i = 0; i < 4; i++) {
    10531053                                sprintf(file_font, "font%d.nut", i);
    10541054                                _sf[i] = new SmushFont(_vm, i != 0, false);
    1055                                 _sf[i]->loadFont(file_font);
     1055                                _sf[i]->loadFont(file_font, false);
    10561056                        }
    10571057                }
    10581058        } else if (_vm->_game.id == GID_CMI) {
     
    10611061                                break;
    10621062                        sprintf(file_font, "font%d.nut", i);
    10631063                        _sf[i] = new SmushFont(_vm, false, true);
    1064                         _sf[i]->loadFont(file_font);
     1064                        _sf[i]->loadFont(file_font, false);
    10651065                }
    10661066        } else {
    10671067                error("SmushPlayer::setupAnim() Unknown font setup for game");
  • engines/scumm/charset.cpp

     
    16091609                        break;
    16101610                sprintf(fontname, "font%d.nut", i);
    16111611                _fr[i] = new NutRenderer(_vm);
    1612                 if (!(_fr[i]->loadFont(fontname))) {
     1612                if (!(_fr[i]->loadFont(fontname, true))) {
    16131613                        delete _fr[i];
    16141614                        _fr[i] = NULL;
    16151615                }
  • engines/scumm/insane/insane.cpp

     
    6666                readFileToMem("minedriv.flu", &_smush_minedrivFlu);
    6767                readFileToMem("minefite.flu", &_smush_minefiteFlu);
    6868                _smush_bensgoggNut = new NutRenderer(_vm);
    69                 _smush_bensgoggNut->loadFont("bensgogg.nut");
     69                _smush_bensgoggNut->loadFont("bensgogg.nut", false);
    7070                _smush_bencutNut = new NutRenderer(_vm);
    71                 _smush_bencutNut->loadFont("bencut.nut");
     71                _smush_bencutNut->loadFont("bencut.nut", false);
    7272        }
    7373
    7474        _smush_iconsNut = new NutRenderer(_vm);
    75         _smush_iconsNut->loadFont("icons.nut");
     75        _smush_iconsNut->loadFont("icons.nut", false);
    7676        _smush_icons2Nut = new NutRenderer(_vm);
    77         _smush_icons2Nut->loadFont("icons2.nut");
     77        _smush_icons2Nut->loadFont("icons2.nut", false);
    7878}
    7979
    8080Insane::~Insane(void) {
  • engines/scumm/nut_renderer.cpp

     
    3030NutRenderer::NutRenderer(ScummEngine *vm) :
    3131        _vm(vm),
    3232        _loaded(false),
    33         _numChars(0) {
     33        _numChars(0),
     34        _decodedData(0) {
    3435        memset(_chars, 0, sizeof(_chars));
    3536}
    3637
    3738NutRenderer::~NutRenderer() {
    38         for (int i = 0; i < _numChars; i++) {
    39                 delete []_chars[i].src;
     39        delete [] _decodedData;
     40}
     41
     42void NutRenderer::codec1(byte *dst, const byte *src, int width, int height, int pitch) {
     43        byte val, code;
     44        int32 length;
     45        int h = height, size_line;
     46
     47        for (h = 0; h < height; h++) {
     48                size_line = READ_LE_UINT16(src);
     49                src += 2;
     50                byte bit = 0x80;
     51                byte *dstPtrNext = dst + pitch;
     52                while (size_line > 0) {
     53                        code = *src++;
     54                        size_line--;
     55                        length = (code >> 1) + 1;
     56                        if (code & 1) {
     57                                val = *src++;
     58                                size_line--;
     59                                if (_bitmapFont) {
     60                                } else {
     61                                        if (val)
     62                                                memset(dst, val, length);
     63                                        dst += length;
     64                                }
     65                        } else {
     66                                size_line -= length;
     67                                while (length--) {
     68                                        val = *src++;
     69                                        if (_bitmapFont) {
     70                                                if (val)
     71                                                        *dst |= bit;
     72                                                bit >>= 1;
     73                                                if (!bit) {
     74                                                        bit = 0x80;
     75                                                        dst++;
     76                                                }
     77                                        } else {
     78                                                if (val)
     79                                                        *dst = val;
     80                                                dst++;
     81                                        }
     82                                }
     83                        }
     84                }
     85                dst = dstPtrNext;
    4086        }
    4187}
    4288
    43 void smush_decode_codec1(byte *dst, const byte *src, int left, int top, int width, int height, int pitch);
    44 
    45 static void smush_decode_codec21(byte *dst, const byte *src, int width, int height, int pitch) {
     89void NutRenderer::codec21(byte *dst, const byte *src, int width, int height, int pitch) {
    4690        while (height--) {
    47                 uint8 *dstPtrNext = dst + pitch;
    48                 const uint8 *srcPtrNext = src + 2 + READ_LE_UINT16(src); src += 2;
     91                byte *dstPtrNext = dst + pitch;
     92                const byte *srcPtrNext = src + 2 + READ_LE_UINT16(src);
     93                src += 2;
    4994                int len = width;
     95                byte bit = 0x80;
    5096                do {
     97                        int i;
    5198                        int offs = READ_LE_UINT16(src); src += 2;
    52                         dst += offs;
     99                        if (_bitmapFont) {
     100                                for (i = 0; i < offs; i++) {
     101                                        bit >>= 1;
     102                                        if (!bit) {
     103                                                bit = 0x80;
     104                                                dst++;
     105                                        }
     106                                }
     107                        } else {
     108                                dst += offs;
     109                        }
    53110                        len -= offs;
    54111                        if (len <= 0) {
    55112                                break;
     
    63120                        //  src bytes equal to 255 are replaced by 0 in dst
    64121                        //  src bytes equal to 1 are replaced by a color passed as an argument in the original function
    65122                        //  other src bytes values are copied as-is
    66                         memcpy(dst, src, w); dst += w; src += w;
     123                        if (_bitmapFont) {
     124                                for (i = 0; i < w; i++) {
     125                                        if (src[i])
     126                                                *dst |= bit;
     127                                        bit >>= 1;
     128                                        if (!bit) {
     129                                                bit = 0x80;
     130                                                dst++;
     131                                        }
     132                                }
     133                        } else {
     134                                memcpy(dst, src, w);
     135                                dst += w;
     136                        }
     137                        src += w;
    67138                } while (len > 0);
    68139                dst = dstPtrNext;
    69140                src = srcPtrNext;
    70141        }
    71142}
    72143
    73 bool NutRenderer::loadFont(const char *filename) {
     144bool NutRenderer::loadFont(const char *filename, bool bitmap) {
    74145        if (_loaded) {
    75146                debug(0, "NutRenderer::loadFont() Font already loaded, ok, loading...");
    76147        }
    77148
     149        _bitmapFont = bitmap;
     150
    78151        ScummFile file;
    79152        _vm->openFile(file, filename);
    80153        if (!file.isOpen()) {
     
    89162        }
    90163
    91164        uint32 length = file.readUint32BE();
    92         byte *dataSrc = (byte *)malloc(length);
     165        byte *dataSrc = new byte[length];
    93166        file.read(dataSrc, length);
    94167        file.close();
    95168
     
    99172                return false;
    100173        }
    101174
     175        // We pre-decode the font, which may seem wasteful at first. Actually,
     176        // the memory needed for just the decoded glyphs is smaller than the
     177        // whole of the undecoded font file.
     178
    102179        _numChars = READ_LE_UINT16(dataSrc + 10);
    103180        assert(_numChars <= ARRAYSIZE(_chars));
     181
    104182        uint32 offset = 0;
     183        uint32 decodedLength = 0;
    105184        for (int l = 0; l < _numChars; l++) {
     185                offset += READ_BE_UINT32(dataSrc + offset + 4) + 16;
     186                int width = READ_LE_UINT16(dataSrc + offset + 14);
     187                int height = READ_LE_UINT16(dataSrc + offset + 16);
     188                if (_bitmapFont) {
     189                        decodedLength += (((width + 7) / 8) * height);
     190                } else {
     191                        decodedLength += (width * height);
     192                }
     193        }
     194
     195        // If characters have transparency, then bytes just get skipped and
     196        // so there may appear some garbage. That's why we have to fill it
     197        // with zeroes first.
     198
     199        _decodedData = new byte[decodedLength];
     200        memset(_decodedData, 0, decodedLength);
     201
     202        byte *decodedPtr = _decodedData;
     203
     204        offset = 0;
     205        for (int l = 0; l < _numChars; l++) {
    106206                offset += READ_BE_UINT32(dataSrc + offset + 4) + 8;
    107207                if (READ_BE_UINT32(dataSrc + offset) != 'FRME') {
    108208                        error("NutRenderer::loadFont(%s) there is no FRME chunk %d (offset %x)", filename, l, offset);
     
    114214                        break;
    115215                }
    116216                int codec = READ_LE_UINT16(dataSrc + offset + 8);
    117                 _chars[l].xoffs = READ_LE_UINT16(dataSrc + offset + 10);
    118                 _chars[l].yoffs = READ_LE_UINT16(dataSrc + offset + 12);
     217                // _chars[l].xoffs = READ_LE_UINT16(dataSrc + offset + 10);
     218                // _chars[l].yoffs = READ_LE_UINT16(dataSrc + offset + 12);
    119219                _chars[l].width = READ_LE_UINT16(dataSrc + offset + 14);
    120220                _chars[l].height = READ_LE_UINT16(dataSrc + offset + 16);
    121                 const int srcSize = _chars[l].width * _chars[l].height;
    122                 _chars[l].src = new byte[srcSize];
    123                 // If characters have transparency, then bytes just get skipped and
    124                 // so there may appear some garbage. That's why we have to fill it
    125                 // with zeroes first.
    126                 memset(_chars[l].src, 0, srcSize);
     221                _chars[l].src = decodedPtr;
    127222
     223                int pitch;
     224
     225                if (_bitmapFont) {
     226                        pitch = (_chars[l].width + 7) / 8;
     227                } else {
     228                        pitch = _chars[l].width;
     229                }
     230
     231                decodedPtr += (pitch * _chars[l].height);
     232
    128233                const uint8 *fobjptr = dataSrc + offset + 22;
    129234                switch (codec) {
    130235                case 1:
    131                         smush_decode_codec1(_chars[l].src, fobjptr, 0, 0, _chars[l].width, _chars[l].height, _chars[l].width);
     236                        codec1(_chars[l].src, fobjptr, _chars[l].width, _chars[l].height, pitch);
    132237                        break;
    133238                case 21:
    134239                case 44:
    135                         smush_decode_codec21(_chars[l].src, fobjptr, _chars[l].width, _chars[l].height, _chars[l].width);
     240                        codec21(_chars[l].src, fobjptr, _chars[l].width, _chars[l].height, pitch);
    136241                        break;
    137242                default:
    138243                        error("NutRenderer::loadFont: unknown codec: %d", codec);
    139244                }
    140245        }
    141246
    142         free(dataSrc);
     247        delete [] dataSrc;
    143248        _loaded = true;
    144249        return true;
    145250}
     
    210315}
    211316
    212317void NutRenderer::drawFrame(byte *dst, int c, int x, int y) {
    213         const int width = MIN(_chars[c].width, _vm->_screenWidth - x);
    214         const int height = MIN(_chars[c].height, _vm->_screenHeight - y);
     318        assert(!_bitmapFont);
     319
     320        const int width = MIN((int)_chars[c].width, _vm->_screenWidth - x);
     321        const int height = MIN((int)_chars[c].height, _vm->_screenHeight - y);
    215322        const byte *src = _chars[c].src;
    216323        const int srcPitch = _chars[c].width;
    217324        byte bits = 0;
     
    243350
    244351void NutRenderer::drawChar(const Graphics::Surface &s, byte c, int x, int y, byte color) {
    245352        byte *dst = (byte *)s.pixels + y * s.pitch + x;
    246         const int width = MIN(_chars[c].width, s.w - x);
    247         const int height = MIN(_chars[c].height, s.h - y);
     353        const int width = MIN((int)_chars[c].width, s.w - x);
     354        const int height = MIN((int)_chars[c].height, s.h - y);
    248355        const byte *src = _chars[c].src;
    249         const int srcPitch = _chars[c].width;
     356        int srcPitch;
    250357
     358        if (_bitmapFont) {
     359                srcPitch = (_chars[c].width + 7) / 8;
     360        } else {
     361                srcPitch = _chars[c].width;
     362        }
     363
    251364        const int minX = x < 0 ? -x : 0;
    252365        const int minY = y < 0 ? -y : 0;
    253366
     
    261374        }
    262375
    263376        for (int ty = minY; ty < height; ty++) {
    264                 for (int tx = minX; tx < width; tx++) {
    265                         if (src[tx] != 0) {
    266                                 dst[tx] = color;
     377                int tx;
     378
     379                for (tx = minX; tx < width; tx++) {
     380                        if (_bitmapFont) {
     381                                if (src[tx / 8] & (0x80 >> (tx % 8))) {
     382                                        dst[tx] = color;
     383                                }
     384                        } else {
     385                                if (src[tx] != 0) {
     386                                        dst[tx] = color;
     387                                }
    267388                        }
    268389                }
    269390                src += srcPitch;
  • engines/scumm/nut_renderer.h

     
    3333protected:
    3434        ScummEngine *_vm;
    3535        bool _loaded;
     36        bool _bitmapFont;
    3637        int _numChars;
     38        byte *_decodedData;
    3739        struct {
    38                 int xoffs;
    39                 int yoffs;
    40                 int width;
    41                 int height;
     40                uint16 width;
     41                uint16 height;
    4242                byte *src;
    4343        } _chars[256];
    4444
     45        void codec1(byte *dst, const byte *src, int width, int height, int pitch);
     46        void codec21(byte *dst, const byte *src, int width, int height, int pitch);
     47
    4548        void drawChar(const Graphics::Surface &s, byte c, int x, int y, byte color);
    4649        void draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color);
    4750
     
    5053        virtual ~NutRenderer();
    5154        int getNumChars() const { return _numChars; }
    5255
    53         bool loadFont(const char *filename);
     56        bool loadFont(const char *filename, bool bitmap);
    5457
    5558        void drawFrame(byte *dst, int c, int x, int y);
    5659        void drawShadowChar(const Graphics::Surface &s, int c, int x, int y, byte color, bool showShadow);