OSDN Git Service

got pcxtest.exe to compile and work
[proj16/16.git] / src / lib / 16_vl.c
index df741a2..1207c84 100755 (executable)
@@ -880,10 +880,10 @@ void modexPalSave(byte *palette)
 }\r
 \r
 \r
-/*byte *\r
+byte *\r
 modexNewPal() {\r
        byte *ptr;\r
-       ptr = mAlloc(PAL_SIZE);\r
+       ptr = malloc(PAL_SIZE);\r
 \r
        // handle errors\r
        if(!ptr) {\r
@@ -891,7 +891,71 @@ modexNewPal() {
        }\r
 \r
        return ptr;\r
-}*/\r
+}\r
+\r
+static struct pcxHeader {\r
+    byte id;\r
+    byte version;\r
+    byte encoding;\r
+    byte bpp;\r
+    word xmin;\r
+    word ymin;\r
+    word xmax;\r
+    word ymax;\r
+    word hres;\r
+    word vres;\r
+    byte pal16[48];\r
+    byte res1;\r
+    word bpplane;\r
+    word palType;\r
+    word hScreenSize;\r
+    word vScreenSize;\r
+    byte padding[54];\r
+} head;\r
+\r
+\r
+static void loadPcxStage1(FILE *file, bitmap_t *result) {\r
+    long bufSize;\r
+    int index;\r
+    byte count, val;\r
+    long int pos;\r
+\r
+    /* read the header */\r
+    fread(&head, sizeof(char), sizeof(struct pcxHeader), file);\r
+\r
+    /* get the width and height */\r
+    result->width = head.xmax - head.xmin + 1;\r
+    result->height = head.ymax - head.ymin + 1;\r
+\r
+    /* make sure this  is 8bpp */\r
+    if(head.bpp != 8) {\r
+       printf("I only know how to handle 8bpp pcx files!\n");\r
+       fclose(file);\r
+       exit(-2);\r
+    }\r
+}\r
+\r
+void loadPcxPalette(FILE *file, bitmap_t *result) {\r
+    byte val;\r
+    int index;\r
+\r
+    /* handle the palette */\r
+    fseek(file, -769, SEEK_END);\r
+    val = fgetc(file);\r
+    result->palette = modexNewPal();\r
+    if(head.version == 5 && val == 12) {\r
+       /* use the vga palette */\r
+       for(index=0; !feof(file) && index < PAL_SIZE; index++) {\r
+           val = fgetc(file);\r
+           result->palette[index] = val >> 2;\r
+       }\r
+    } else {\r
+       /* use the 16 color palette */\r
+       for(index=0; index<48; index++) {\r
+           result->palette[index]  = head.pal16[index];\r
+       }\r
+    }\r
+}\r
 \r
 \r
 void\r
@@ -920,6 +984,422 @@ modexLoadPalFile(byte *filename, byte *palette) {
        fclose(file);\r
 }\r
 \r
+bitmap_t\r
+bitmapLoadPcx(char *filename) {\r
+    FILE *file;\r
+    bitmap_t result;\r
+    long bufSize;\r
+    int index;\r
+    byte count, val;\r
+\r
+    /* open the PCX file for reading */\r
+    file = fopen(filename, "rb");\r
+    if(!file) {\r
+       printf("Could not open %s for reading.\n", filename);\r
+       exit(-2);\r
+    }\r
+\r
+    /* load the first part of the pcx file */\r
+    loadPcxStage1(file, &result);\r
+\r
+    /* allocate the buffer */\r
+    bufSize = result.width * result.height;\r
+    result.data = malloc(bufSize);\r
+    if(!result.data) {\r
+       printf("Could not allocate memory for bitmap data.");\r
+       fclose(file);\r
+       exit(-1);\r
+    }\r
+\r
+    /*  read the buffer in */\r
+    index = 0;\r
+    do {\r
+       /* get the run length and the value */\r
+       count = fgetc(file);\r
+       if(0xC0 ==  (count & 0xC0)) { /* this is the run count */\r
+           count &= 0x3f;\r
+           val = fgetc(file);\r
+       } else {\r
+           val = count;\r
+           count = 1;\r
+       }\r
+\r
+       /* write the pixel the specified number of times */\r
+       for(; count && index < bufSize; count--,index++)  {\r
+           result.data[index] = val;\r
+       }\r
+    } while(index < bufSize);\r
+\r
+    loadPcxPalette(file, &result);\r
+\r
+    fclose(file);\r
+\r
+    return result;\r
+}\r
+\r
+\r
+tileset_t\r
+bitmapLoadPcxTiles(char *filename, word twidth, word theight) {\r
+    tileset_t ts;\r
+    FILE *file;\r
+    bitmap_t result;\r
+    int i;\r
+\r
+    /* open the PCX file for reading */\r
+    file = fopen(filename, "rb");\r
+    if(!file) {\r
+       printf("Could not open %s for reading.\n", filename);\r
+       exit(-2);\r
+    }\r
+\r
+    /* load the first part of the pcx file */\r
+    loadPcxStage1(file, &result);\r
+\r
+    /* get the number of tiles and set up the result structure */\r
+    ts.twidth = twidth;\r
+    ts.theight = theight;\r
+    ts.ntiles = (result.width/twidth) * (result.height/theight);\r
+    ts.palette = result.palette;\r
+\r
+    /* allocate the pixel storage for the tiles */\r
+    ts.data = malloc(sizeof(byte*) * ts.ntiles);\r
+    ts.data[0] = malloc(sizeof(byte) * ts.ntiles * twidth * theight);\r
+    for(i=1; i < ts.ntiles; i++) {\r
+       ts.data[i] = ts.data[i-1] + twidth * theight;\r
+    }\r
+\r
+    /* finish off the file */\r
+    loadPcxPalette(file, &result);\r
+\r
+    fclose(file);\r
+\r
+    return ts;\r
+}\r
+\r
+void\r
+oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)\r
+{\r
+       byte plane;\r
+       word px, py;\r
+       word offset;\r
+\r
+       /* TODO Make this fast.  It's SLOOOOOOW */\r
+       for(plane=0; plane < 4; plane++) {\r
+               modexSelectPlane(PLANE(plane+x));\r
+               for(px = plane; px < bmp->width; px+=4) {\r
+                       offset=px;\r
+                       for(py=0; py<bmp->height; py++) {\r
+                       if(!sprite || bmp->data[offset])\r
+                               page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];\r
+                       offset+=bmp->width;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+//* normal versions *//\r
+void\r
+modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {\r
+    /* draw the region (the entire freakin bitmap) */\r
+    modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
+}\r
+\r
+void\r
+modexDrawBmpRegion(page_t *page, int x, int y,\r
+                  int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
+       word poffset = (word)page->data + y*(page->width/4) + x/4;\r
+       byte *data = bmp->data;//+bmp->offset;\r
+       word bmpOffset = (word) data + ry * bmp->width + rx;\r
+       word width = rw;\r
+       word height = rh;\r
+       byte plane = 1 << ((byte) x & 0x03);\r
+       word scanCount = width/4 + (width%4 ? 1 :0);\r
+       word nextPageRow = page->width/4 - scanCount;\r
+       word nextBmpRow = (word) bmp->width - width;\r
+       word rowCounter=0;\r
+       byte planeCounter = 4;\r
+\r
+    __asm {\r
+               MOV AX, SCREEN_SEG      ; go to the VGA memory\r
+               MOV ES, AX\r
+\r
+               MOV DX, SC_INDEX        ; point at the map mask register\r
+               MOV AL, SC_MAPMASK      ;\r
+               OUT DX, AL            ;\r
+\r
+       PLANE_LOOP:\r
+               MOV DX, SC_DATA  ; select the current plane\r
+               MOV AL, plane      ;\r
+               OUT DX, AL            ;\r
+\r
+               ;-- begin plane painting\r
+               MOV AX, height    ; start the row counter\r
+               MOV rowCounter, AX      ;\r
+               MOV DI, poffset  ; go to the first pixel\r
+               MOV SI, bmpOffset       ; go to the bmp pixel\r
+       ROW_LOOP:\r
+               MOV CX, width      ; count the columns\r
+       SCAN_LOOP:\r
+               MOVSB              ; copy the pixel\r
+               SUB CX, 3              ; we skip the next 3\r
+               ADD SI, 3              ; skip the bmp pixels\r
+               LOOP SCAN_LOOP    ; finish the scan\r
+\r
+               MOV AX, nextPageRow\r
+               ADD DI, AX            ; go to the next row on screen\r
+               MOV AX, nextBmpRow\r
+               ADD SI, AX            ; go to the next row on bmp\r
+\r
+               DEC rowCounter\r
+               JNZ ROW_LOOP        ; do all the rows\r
+               ;-- end plane painting\r
+               MOV AL, plane      ; advance to the next plane\r
+               SHL AL, 1              ;\r
+               AND AL, 0x0f        ; mask the plane properly\r
+               MOV plane, AL      ; store the plane\r
+\r
+               INC bmpOffset      ; start bmp at the right spot\r
+\r
+               DEC planeCounter\r
+               JNZ PLANE_LOOP    ; do all 4 planes\r
+    }\r
+}\r
+\r
+void\r
+modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {\r
+    /* draw the whole sprite */\r
+    modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
+}\r
+\r
+void\r
+modexDrawSpriteRegion(page_t *page, int x, int y,\r
+                     int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
+       word poffset = (word)page->data + y*(page->width/4) + x/4;\r
+       byte *data = bmp->data;//+bmp->offset;\r
+       word bmpOffset = (word) data + ry * bmp->width + rx;\r
+       word width = rw;\r
+       word height = rh;\r
+       byte plane = 1 << ((byte) x & 0x03);\r
+       word scanCount = width/4 + (width%4 ? 1 :0);\r
+       word nextPageRow = page->width/4 - scanCount;\r
+       word nextBmpRow = (word) bmp->width - width;\r
+       word rowCounter=0;\r
+       byte planeCounter = 4;\r
+\r
+    __asm {\r
+               MOV AX, SCREEN_SEG      ; go to the VGA memory\r
+               MOV ES, AX\r
+\r
+               MOV DX, SC_INDEX        ; point at the map mask register\r
+               MOV AL, SC_MAPMASK      ;\r
+               OUT DX, AL            ;\r
+\r
+       PLANE_LOOP:\r
+               MOV DX, SC_DATA  ; select the current plane\r
+               MOV AL, plane      ;\r
+               OUT DX, AL            ;\r
+\r
+               ;-- begin plane painting\r
+               MOV AX, height    ; start the row counter\r
+               MOV rowCounter, AX      ;\r
+               MOV DI, poffset  ; go to the first pixel\r
+               MOV SI, bmpOffset       ; go to the bmp pixel\r
+       ROW_LOOP:\r
+               MOV CX, width      ; count the columns\r
+       SCAN_LOOP:\r
+               LODSB\r
+               DEC SI\r
+               CMP AL, 0\r
+               JNE DRAW_PIXEL    ; draw non-zero pixels\r
+\r
+               INC DI            ; skip the transparent pixel\r
+               ADD SI, 1\r
+               JMP NEXT_PIXEL\r
+       DRAW_PIXEL:\r
+               MOVSB              ; copy the pixel\r
+       NEXT_PIXEL:\r
+               SUB CX, 3              ; we skip the next 3\r
+               ADD SI, 3              ; skip the bmp pixels\r
+               LOOP SCAN_LOOP    ; finish the scan\r
+\r
+               MOV AX, nextPageRow\r
+               ADD DI, AX            ; go to the next row on screen\r
+               MOV AX, nextBmpRow\r
+               ADD SI, AX            ; go to the next row on bmp\r
+\r
+               DEC rowCounter\r
+               JNZ ROW_LOOP        ; do all the rows\r
+               ;-- end plane painting\r
+\r
+               MOV AL, plane      ; advance to the next plane\r
+               SHL AL, 1              ;\r
+               AND AL, 0x0f        ; mask the plane properly\r
+               MOV plane, AL      ; store the plane\r
+\r
+               INC bmpOffset      ; start bmp at the right spot\r
+\r
+               DEC planeCounter\r
+               JNZ PLANE_LOOP    ; do all 4 planes\r
+    }\r
+}\r
+\r
+//* planar buffer versions *//\r
+void\r
+modexDrawBmpPBuf(page_t *page, int x, int y, planar_buf_t *bmp) {\r
+    /* draw the region (the entire freakin bitmap) */\r
+    modexDrawBmpPBufRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
+}\r
+\r
+void\r
+modexDrawBmpPBufRegion(page_t *page, int x, int y,\r
+                  int rx, int ry, int rw, int rh, planar_buf_t *bmp) {\r
+       word poffset = (word) page->data  + y*(page->width/4) + x/4;\r
+       byte *data = (byte *)bmp->plane[0];\r
+       word bmpOffset = (word) data + ry * bmp->width + rx;\r
+       word width = rw;\r
+       word height = rh;\r
+       byte plane = 1 << ((byte) x & 0x03);\r
+       word scanCount = width/4 + (width%4 ? 1 :0);\r
+       word nextPageRow = page->width/4 - scanCount;\r
+       word nextBmpRow = (word) bmp->width - width;\r
+       word rowCounter=0;\r
+       byte planeCounter = 4;\r
+\r
+    __asm {\r
+               MOV AX, SCREEN_SEG      ; go to the VGA memory\r
+               MOV ES, AX\r
+\r
+               MOV DX, SC_INDEX        ; point at the map mask register\r
+               MOV AL, SC_MAPMASK      ;\r
+               OUT DX, AL            ;\r
+\r
+       PLANE_LOOP:\r
+               MOV DX, SC_DATA  ; select the current plane\r
+               MOV AL, plane      ;\r
+               OUT DX, AL            ;\r
+\r
+               ;-- begin plane painting\r
+               MOV AX, height    ; start the row counter\r
+               MOV rowCounter, AX      ;\r
+               MOV DI, poffset  ; go to the first pixel\r
+               MOV SI, bmpOffset       ; go to the bmp pixel\r
+       ROW_LOOP:\r
+               MOV CX, width      ; count the columns\r
+       SCAN_LOOP:\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+               MOVSB              ; copy the pixel\r
+\r
+               SUB CX, 3              ; we skip the next 3\r
+               ADD SI, 3              ; skip the bmp pixels\r
+               LOOP SCAN_LOOP    ; finish the scan\r
+\r
+               MOV AX, nextPageRow\r
+               ADD DI, AX            ; go to the next row on screen\r
+               MOV AX, nextBmpRow\r
+               ADD SI, AX            ; go to the next row on bmp\r
+\r
+               DEC rowCounter\r
+               JNZ ROW_LOOP        ; do all the rows\r
+               ;-- end plane painting\r
+\r
+               MOV AL, plane      ; advance to the next plane\r
+               SHL AL, 1              ;\r
+               AND AL, 0x0f        ; mask the plane properly\r
+               MOV plane, AL      ; store the plane\r
+\r
+               INC bmpOffset      ; start bmp at the right spot\r
+\r
+               DEC planeCounter\r
+               JNZ PLANE_LOOP    ; do all 4 planes\r
+    }\r
+}\r
+\r
+void\r
+modexDrawSpritePBuf(page_t *page, int x, int y, planar_buf_t *bmp) {\r
+    /* draw the whole sprite */\r
+    modexDrawSpritePBufRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
+}\r
+\r
+void\r
+modexDrawSpritePBufRegion(page_t *page, int x, int y,\r
+                     int rx, int ry, int rw, int rh, planar_buf_t *bmp) {\r
+       word poffset = (word)page->data + y*(page->width/4) + x/4;\r
+       byte *data = (byte *)bmp->plane[0];\r
+       word bmpOffset = (word) data + ry * bmp->width + rx;\r
+       word width = rw;\r
+       word height = rh;\r
+       byte plane = 1 << ((byte) x & 0x03);\r
+       word scanCount = width/4 + (width%4 ? 1 :0);\r
+       word nextPageRow = page->width/4 - scanCount;\r
+       word nextBmpRow = (word) bmp->width - width;\r
+       word rowCounter=0;\r
+       byte planeCounter = 4;\r
+\r
+    __asm {\r
+               MOV AX, SCREEN_SEG      ; go to the VGA memory\r
+               MOV ES, AX\r
+\r
+               MOV DX, SC_INDEX        ; point at the map mask register\r
+               MOV AL, SC_MAPMASK      ;\r
+               OUT DX, AL            ;\r
+\r
+       PLANE_LOOP:\r
+               MOV DX, SC_DATA  ; select the current plane\r
+               MOV AL, plane      ;\r
+               OUT DX, AL            ;\r
+\r
+               ;-- begin plane painting\r
+               MOV AX, height    ; start the row counter\r
+               MOV rowCounter, AX      ;\r
+               MOV DI, poffset  ; go to the first pixel\r
+               MOV SI, bmpOffset       ; go to the bmp pixel\r
+       ROW_LOOP:\r
+               MOV CX, width      ; count the columns\r
+       SCAN_LOOP:\r
+               LODSB\r
+               DEC SI\r
+               CMP AL, 0\r
+               JNE DRAW_PIXEL    ; draw non-zero pixels\r
+\r
+               INC DI            ; skip the transparent pixel\r
+               ADD SI, 1\r
+               JMP NEXT_PIXEL\r
+       DRAW_PIXEL:\r
+               MOVSB              ; copy the pixel\r
+       NEXT_PIXEL:\r
+               SUB CX, 3              ; we skip the next 3\r
+               ADD SI, 3              ; skip the bmp pixels\r
+               LOOP SCAN_LOOP    ; finish the scan\r
+\r
+               MOV AX, nextPageRow\r
+               ADD DI, AX            ; go to the next row on screen\r
+               MOV AX, nextBmpRow\r
+               ADD SI, AX            ; go to the next row on bmp\r
+\r
+               DEC rowCounter\r
+               JNZ ROW_LOOP        ; do all the rows\r
+               ;-- end plane painting\r
+\r
+               MOV AL, plane      ; advance to the next plane\r
+               SHL AL, 1              ;\r
+               AND AL, 0x0f        ; mask the plane properly\r
+               MOV plane, AL      ; store the plane\r
+\r
+               INC bmpOffset      ; start bmp at the right spot\r
+\r
+               DEC planeCounter\r
+               JNZ PLANE_LOOP    ; do all 4 planes\r
+    }\r
+}\r
+\r
 #define COREPALSIZE 9//27      //3*9\r
 \r
 void VLL_LoadPalFilewithoffset(const char *filename, byte *palette, word o, word palsize, global_game_variables_t *gvar)\r