]> 4ch.mooo.com Git - 16.git/commitdiff
16_ca needs huge amounts of work and I should remember what needs to be done soon...
authorsparky4 <sparky4@cock.li>
Fri, 21 Apr 2017 13:46:23 +0000 (08:46 -0500)
committersparky4 <sparky4@cock.li>
Fri, 21 Apr 2017 13:46:23 +0000 (08:46 -0500)
37 files changed:
16/modex16/286@12.log [new file with mode: 0755]
16/modex16/286@8.log [new file with mode: 0755]
16/modex16/46113319.pcx [new file with mode: 0755]
16/modex16/bitmap.c [new file with mode: 0755]
16/modex16/bitmap.h [new file with mode: 0755]
16/modex16/chikyuu.pcx [new file with mode: 0755]
16/modex16/computer.pcx [new file with mode: 0755]
16/modex16/dos_kb.c [new file with mode: 0755]
16/modex16/dos_kb.h [new file with mode: 0755]
16/modex16/ed.pcx [new file with mode: 0755]
16/modex16/ed2.pcx [new file with mode: 0755]
16/modex16/edw.pcx [new file with mode: 0755]
16/modex16/gfx.pal [new file with mode: 0755]
16/modex16/koishi.pcx [new file with mode: 0755]
16/modex16/koishi^^.pcx [new file with mode: 0755]
16/modex16/koishi~.pcx [new file with mode: 0755]
16/modex16/lib/lib_com.cpp [new file with mode: 0755]
16/modex16/lib/lib_com.h [new file with mode: 0755]
16/modex16/makefile [new file with mode: 0755]
16/modex16/mayu.pcx [new file with mode: 0755]
16/modex16/modex16.c [new file with mode: 0755]
16/modex16/modex16.h [new file with mode: 0755]
16/modex16/palettec.c [new file with mode: 0755]
16/modex16/pcxtest.c [new file with mode: 0755]
16/modex16/pcxtest.exe [new file with mode: 0755]
16/modex16/q.pcx [new file with mode: 0755]
16/modex16/rarity.pcx [new file with mode: 0755]
16/modex16/scroll.c [new file with mode: 0755]
16/modex16/scroll.exe [new file with mode: 0755]
16/modex16/test.c [new file with mode: 0755]
16/modex16/test.exe [new file with mode: 0755]
16/modex16/test.txt [new file with mode: 0755]
16/modex16/test2.c [new file with mode: 0755]
16/modex16/test2.exe [new file with mode: 0755]
16/modex16/types.h [new file with mode: 0755]
16/modex16/w.pcx [new file with mode: 0755]
src/0croll.c

diff --git a/16/modex16/286@12.log b/16/modex16/286@12.log
new file mode 100755 (executable)
index 0000000..3402704
--- /dev/null
@@ -0,0 +1,4 @@
+Old non-sprite: 7.032967\r
+New non-sprite: 1.043956\r
+Old Sprite: 6.648352\r
+New Sprite: 1.648352\r
diff --git a/16/modex16/286@8.log b/16/modex16/286@8.log
new file mode 100755 (executable)
index 0000000..a29ceff
--- /dev/null
@@ -0,0 +1,4 @@
+Old non-sprite: 10.439561\r
+New non-sprite: 1.373626\r
+Old Sprite: 9.945055\r
+New Sprite: 2.362637\r
diff --git a/16/modex16/46113319.pcx b/16/modex16/46113319.pcx
new file mode 100755 (executable)
index 0000000..ce42ed8
Binary files /dev/null and b/16/modex16/46113319.pcx differ
diff --git a/16/modex16/bitmap.c b/16/modex16/bitmap.c
new file mode 100755 (executable)
index 0000000..8287e57
--- /dev/null
@@ -0,0 +1,162 @@
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include "bitmap.h"\r
+#include "modex16.h"\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
+\r
+static 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
+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
diff --git a/16/modex16/bitmap.h b/16/modex16/bitmap.h
new file mode 100755 (executable)
index 0000000..4c4af98
--- /dev/null
@@ -0,0 +1,24 @@
+/*\r
+ * Functions and types for loading and manipulating bitmaps.\r
+ */\r
+#ifndef BITMAP_H\r
+#define BITMAP_H\r
+#include "types.h"\r
+typedef struct {\r
+    byte *data;\r
+    word width;\r
+    word height;\r
+    byte *palette;\r
+} bitmap_t;\r
+\r
+typedef struct {\r
+    byte **data;\r
+    word ntiles;   /* the number of tiles */\r
+    word twidth;   /* width of the tiles */\r
+    word theight;  /* height of the tiles */\r
+    byte *palette; /* palette for the tile set */\r
+} tileset_t;\r
+\r
+bitmap_t bitmapLoadPcx(char *filename);\r
+tileset_t bitmapLoadPcxTiles(char *filename, word twidth, word theight);\r
+#endif\r
diff --git a/16/modex16/chikyuu.pcx b/16/modex16/chikyuu.pcx
new file mode 100755 (executable)
index 0000000..61eac4c
Binary files /dev/null and b/16/modex16/chikyuu.pcx differ
diff --git a/16/modex16/computer.pcx b/16/modex16/computer.pcx
new file mode 100755 (executable)
index 0000000..07da0a5
Binary files /dev/null and b/16/modex16/computer.pcx differ
diff --git a/16/modex16/dos_kb.c b/16/modex16/dos_kb.c
new file mode 100755 (executable)
index 0000000..dd92418
--- /dev/null
@@ -0,0 +1,142 @@
+/* Thanks to Alex Russell for example code */
+/* Thanks to Gary Neal for example code */
+#include "dos_kb.h"
+
+// keyboard buffer
+static byte key[NUM_SCANCODES]; // pressed
+static byte kea[NUM_SCANCODES]; // released
+
+#ifdef __cplusplus             /* Function must be declared C style */
+extern "C" {
+#endif
+static void interrupt (far *oldkb)(void) = NULL; /* BIOS keyboard handler */
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * Comment out the following #define if you don't want the testing main()
+ * to be included.
+ */
+//#define TESTING
+#define TESTING2
+
+/*****************NEW KEYBOARD 09h ISR***********************/
+void interrupt newkb(void){
+       byte kee;
+       register char qx;
+
+       kee = inp(0x60);        /* Read the keyboard scan code */
+
+       /* Clear keyboard controller on XT machines */
+       qx = inp(0x61);    /* Get keyboard control register */
+       qx |= 0x82;
+       outp(0x61, qx);    /* Toggle acknowledge bit high */
+       qx &= 0x7F;
+       outp(0x61, qx);    /* Toggle acknowledge bit low */
+
+       /* Interpret the scan code and set our flags */
+       #ifdef TESTING2
+       //printf("%d[%d]\n",kee,key[kee]);
+       printf("\0"); // bug
+       #endif
+       if(kee & 0x80)
+               key[kee & 0x7F] = 0; // a key is released
+       else
+               key[kee] = kea[kee] = 1; // a key is pressed
+
+       /* Acknowledge the interrupt to the programmable interrupt controller */
+       outp(0x20, 0x20);      /* Signal non specific end of interrupt */
+}
+
+/* ---------------------- init_keyboard() ---------------- April 17,1993 */
+/* restore the bios keyboard handler */
+/* ---------------------- deinit_keyboard() -------------- April 17,1993 */
+void setkb(int vq){
+       int i;  /* Index variable */
+       if(!vq){ // deinitiation
+               /* Abort if our function pointer has no valid address */
+               if(oldkb == NULL) return;
+               /* Set address in our function pointer in interrupt vector table */
+               _dos_setvect(9, oldkb);
+               /* Reset our function pointer to contain no valid address */
+               oldkb = NULL;
+               #ifdef TESTING
+               /* Print the key heap */
+               printf("\n");
+               for(i=0; i<NUM_SCANCODES; i++){
+                       if(i==NUM_SCANCODES/2) printf("================================\n");
+                       printf("%03d[%d][%d]",i+1,key[i],kea[i]);
+                       if(key[i]==1)printf("====");
+                       printf(",\n");
+               }
+               #endif
+       }else if(vq == 1){ // initiation
+               byte far *lock_key;
+
+               /* Abort if our function pointer has a valid address. */
+               if(oldkb != NULL) return;
+
+               /* Clear the keyboard buttons state arrays */
+               for(i = 0; i < NUM_SCANCODES; i++)
+                       key[i] = kea[i] = 0;
+
+               /* save old BIOS key board handler */
+               oldkb = _dos_getvect(9);
+
+               // turn off num-lock via BIOS
+               lock_key = MK_FP(0x040, 0x017); // Pointing to the address of the bios shift state keys
+               *lock_key&=(~(16 | 32 | 64)); // toggle off the locks by changing the values of the 4th, 5th, and 6th bits of the address byte of 0040:0017
+               oldkb();        // call BIOS keyhandler to change keyboard lights
+
+               /* setup our own handler */
+               _dos_setvect(9, newkb);
+       }
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * keyp                                                              *
+ *                                                                      *
+ * Returns the status of the key requested.                            *
+ * The status is 1 if the key is pressed or has been pressed since the     *
+ * last call to this function for that particular key.              *
+\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+int keyp(byte c){
+       register char retVal;
+
+       /* Key value in range of keyboard keys available */
+       c &= 0x7F;
+
+       /* Get the status of the key requested */
+       retVal = key[c] | kea[c];
+
+       /* Reset the was pressed status for the requested key */
+       kea[c] = 0;
+
+       /* Return the requested key's state */
+       return retVal;
+}
+
+
+/*
+ * The library testing routines follows below.
+ */
+
+#ifdef TESTING
+
+/*
+ * Library test (program) entry point.
+ */
+
+void main(void)
+{
+       byte q;
+       setkb(1);
+       while(!keyp(1))
+       {
+               keyp(q);
+       }
+       setkb(0);
+}
+
+#endif
diff --git a/16/modex16/dos_kb.h b/16/modex16/dos_kb.h
new file mode 100755 (executable)
index 0000000..ea81462
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _DOSLIB_KB_H_\r
+#define _DOSLIB_KB_H_\r
+#include "lib\lib_com.h"\r
+\r
+/* Maximum number of scan codes on keyboard controllers */\r
+#define NUM_SCANCODES   128\r
+\r
+#ifdef __cplusplus      /* Functions must be declared C style */\r
+extern "C" {\r
+#endif\r
+void interrupt far newkb(void);\r
+//extern void interrupt (far *oldkb)(void);\r
+void setkb(int vq);\r
+int keyp(byte c);\r
+\r
+/* Define macro */\r
+//#define kepn(c) key[c & 0x7F]\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif/*_DOSLIB_KB_H_*/\r
diff --git a/16/modex16/ed.pcx b/16/modex16/ed.pcx
new file mode 100755 (executable)
index 0000000..41e5631
Binary files /dev/null and b/16/modex16/ed.pcx differ
diff --git a/16/modex16/ed2.pcx b/16/modex16/ed2.pcx
new file mode 100755 (executable)
index 0000000..b35305e
Binary files /dev/null and b/16/modex16/ed2.pcx differ
diff --git a/16/modex16/edw.pcx b/16/modex16/edw.pcx
new file mode 100755 (executable)
index 0000000..2427b5d
Binary files /dev/null and b/16/modex16/edw.pcx differ
diff --git a/16/modex16/gfx.pal b/16/modex16/gfx.pal
new file mode 100755 (executable)
index 0000000..e98ae60
Binary files /dev/null and b/16/modex16/gfx.pal differ
diff --git a/16/modex16/koishi.pcx b/16/modex16/koishi.pcx
new file mode 100755 (executable)
index 0000000..76d0516
Binary files /dev/null and b/16/modex16/koishi.pcx differ
diff --git a/16/modex16/koishi^^.pcx b/16/modex16/koishi^^.pcx
new file mode 100755 (executable)
index 0000000..0dbbc0d
Binary files /dev/null and b/16/modex16/koishi^^.pcx differ
diff --git a/16/modex16/koishi~.pcx b/16/modex16/koishi~.pcx
new file mode 100755 (executable)
index 0000000..58a03bb
Binary files /dev/null and b/16/modex16/koishi~.pcx differ
diff --git a/16/modex16/lib/lib_com.cpp b/16/modex16/lib/lib_com.cpp
new file mode 100755 (executable)
index 0000000..19ad2dd
--- /dev/null
@@ -0,0 +1,21 @@
+//#include "src\lib\lib_com.h"
+#include "lib\lib_com.h"
+\r
+/* local function */\r
+void wait(clock_t wait);\r
+\r
+/* Function: Wait **********************************************************\r
+*\r
+*     Parameters:    wait - time in microseconds\r
+*\r
+*     Description:    pauses for a specified number of microseconds.\r
+*\r
+*/\r
+void wait(clock_t wait){\r
+       clock_t goal;\r
+\r
+       if(!wait) return;\r
+\r
+       goal = wait + clock();\r
+       while((goal > clock()) && !kbhit()) ;\r
+} /* End of wait */
\ No newline at end of file
diff --git a/16/modex16/lib/lib_com.h b/16/modex16/lib/lib_com.h
new file mode 100755 (executable)
index 0000000..5a203b9
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef _LIBCOM_H_\r
+#define _LIBCOM_H_\r
+#include <dos.h>\r
+#include <stdio.h>\r
+#include <conio.h> // just for wait\r
+#include <time.h> // just for wait
+#include "types.h"\r
+\r
+/* Control codes for all keys on the keyboard */\r
+//here temperarly\r
+#define KEY_A          (0x1E)\r
+#define KEY_B          (0x30)\r
+#define KEY_C          (0x2E)\r
+#define KEY_D          (0x20)\r
+#define KEY_E          (0x12)\r
+#define KEY_F          (0x21)\r
+#define KEY_G          (0x22)\r
+#define KEY_H          (0x23)\r
+#define KEY_I          (0x17)\r
+#define KEY_J          (0x24)\r
+#define KEY_K          (0x25)\r
+#define KEY_L          (0x26)\r
+#define KEY_M          (0x32)\r
+#define KEY_N          (0x31)\r
+#define KEY_O          (0x18)\r
+#define KEY_P          (0x19)\r
+#define KEY_Q          (0x10)\r
+#define KEY_R          (0x13)\r
+#define KEY_S          (0x1F)\r
+#define KEY_T          (0x14)\r
+#define KEY_U          (0x16)\r
+#define KEY_V          (0x2F)\r
+#define KEY_W          (0x11)\r
+#define KEY_X          (0x2D)\r
+#define KEY_Y          (0x15)\r
+#define KEY_Z          (0x2C)\r
+#define KEY_1          (0x02)\r
+#define KEY_2          (0x03)\r
+#define KEY_3          (0x04)\r
+#define KEY_4          (0x05)\r
+#define KEY_5          (0x06)\r
+#define KEY_6          (0x07)\r
+#define KEY_7          (0x08)\r
+#define KEY_8          (0x09)\r
+#define KEY_9          (0x0A)\r
+#define KEY_0          (0x0B)\r
+#define KEY_DASH               (0x0C)  /* -_ */\r
+#define KEY_EQUAL              (0x0D)  /* =+ */\r
+#define KEY_LBRACKET   (0x1A)  /* [{ */\r
+#define KEY_RBRACKET   (0x1B)  /* ]} */\r
+#define KEY_SEMICOLON  (0x27)  /* ;: */\r
+#define KEY_RQUOTE     (0x28)  /* '" */\r
+#define KEY_LQUOTE     (0x29)  /* `~ */\r
+#define KEY_PERIOD     (0x33)  /* .> */\r
+#define KEY_COMMA              (0x34)  /* ,< */\r
+#define KEY_SLASH              (0x35)  /* /? */\r
+#define KEY_BACKSLASH  (0x2B)  /* \| */\r
+#define KEY_F1         (0x3B)\r
+#define KEY_F2         (0x3C)\r
+#define KEY_F3         (0x3D)\r
+#define KEY_F4         (0x3E)\r
+#define KEY_F5         (0x3F)\r
+#define KEY_F6         (0x40)\r
+#define KEY_F7         (0x41)\r
+#define KEY_F8         (0x42)\r
+#define KEY_F9         (0x43)\r
+#define KEY_F10                (0x44)\r
+#define KEY_ESC                (0x01)\r
+#define KEY_BACKSPACE   (0x0E)\r
+#define KEY_TAB                (0x0F)\r
+#define KEY_ENTER              (0x1C)\r
+#define KEY_CONTROL    (0x1D)\r
+#define KEY_LSHIFT     (0x2A)\r
+#define KEY_RSHIFT     (0x36)\r
+#define KEY_PRTSC              (0x37)\r
+#define KEY_ALT                (0x38)\r
+#define KEY_SPACE              (0x39)\r
+#define KEY_CAPSLOCK   (0x3A)\r
+#define KEY_NUMLOCK    (0x45)\r
+#define KEY_SCROLLLOCK (0x46)\r
+#define KEY_HOME               (0x47)\r
+#define KEY_UP         (0x48)\r
+#define KEY_PGUP               (0x49)\r
+#define KEY_MINUS              (0x4A)\r
+#define KEY_LEFT               (0x4B)\r
+#define KEY_CENTER     (0x4C)\r
+#define KEY_RIGHT              (0x4D)\r
+#define KEY_PLUS               (0x4E)\r
+#define KEY_END                (0x4F)\r
+#define KEY_DOWN               (0x50)\r
+#define KEY_PGDOWN     (0x51)\r
+#define KEY_INS                (0x52)\r
+#define KEY_DEL                (0x53)\r
+\r
+#define KEY_LWIN               (0x73)\r
+#define KEY_RWIN               (0x74)\r
+#define KEY_MENU               (0x75)\r
+\r
+\r
+//typedef unsigned char byte;
+//typedef unsigned int word;
+//typedef unsigned short syte;\r
+\r
+void wait(clock_t wait);\r
+\r
+#endif/*_LIBCOM_H_*/\r
diff --git a/16/modex16/makefile b/16/modex16/makefile
new file mode 100755 (executable)
index 0000000..b11f89a
--- /dev/null
@@ -0,0 +1,37 @@
+FLAGS=-0 \r
+all: test.exe pcxtest.exe test2.exe scroll.exe\r
+\r
+scroll.exe: scroll.obj modex16.obj dos_kb.obj bitmap.obj\r
+       wcl $(FLAGS) scroll.obj modex16.obj dos_kb.obj bitmap.obj\r
+scroll.obj: scroll.c\r
+       wcl $(FLAGS) -c scroll.c\r
+test.exe: test.obj modex16.obj bitmap.obj\r
+       wcl $(FLAGS) test.obj modex16.obj bitmap.obj\r
+       \r
+test2.exe: test2.obj modex16.obj bitmap.obj\r
+       wcl $(FLAGS) test2.obj modex16.obj bitmap.obj\r
+       \r
+pcxtest.exe: pcxtest.obj modex16.obj bitmap.obj\r
+       wcl $(FLAGS) pcxtest.obj modex16.obj bitmap.obj\r
+\r
+test.obj: test.c modex16.h\r
+       wcl $(FLAGS) -c test.c\r
+       \r
+test2.obj: test2.c modex16.h\r
+       wcl $(FLAGS) -c test2.c\r
+       \r
+pcxtest.obj: pcxtest.c modex16.h\r
+       wcl $(FLAGS) -c pcxtest.c\r
+\r
+modex16.obj: modex16.h modex16.c\r
+       wcl $(FLAGS) -c modex16.c\r
+\r
+dos_kb.obj: dos_kb.h dos_kb.c\r
+       wcl $(FLAGS) -c dos_kb.c\r
+\r
+bitmap.obj: bitmap.h bitmap.c\r
+       wcl $(FLAGS) -c bitmap.c\r
+       \r
+clean: \r
+       del *.obj\r
+       del *.exe\r
diff --git a/16/modex16/mayu.pcx b/16/modex16/mayu.pcx
new file mode 100755 (executable)
index 0000000..025e7d4
Binary files /dev/null and b/16/modex16/mayu.pcx differ
diff --git a/16/modex16/modex16.c b/16/modex16/modex16.c
new file mode 100755 (executable)
index 0000000..f01116b
--- /dev/null
@@ -0,0 +1,605 @@
+#include <dos.h>\r
+#include <string.h>\r
+#include <mem.h>\r
+#include <conio.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include "modex16.h"\r
+\r
+\r
+byte far* VGA=(byte far*) 0xA0000000;  /* this points to video memory. */\r
+\r
+static void fadePalette(sbyte fade, sbyte start, word iter, byte *palette);\r
+static byte tmppal[PAL_SIZE];\r
+\r
+static void\r
+vgaSetMode(byte mode)\r
+{\r
+  union REGS regs;\r
+\r
+  regs.h.ah = SET_MODE;\r
+  regs.h.al = mode;\r
+  int86(VIDEO_INT, &regs, &regs);\r
+}\r
+\r
+\r
+/* -========================= Entry  Points ==========================- */\r
+void\r
+modexEnter() {\r
+    word i;\r
+    dword far*ptr=(dword far*)VGA;      /* used for faster screen clearing */\r
+    word CRTParms[] = {\r
+       0x0d06,         /* vertical total */\r
+       0x3e07,         /* overflow (bit 8 of vertical counts) */\r
+       0x4109,         /* cell height (2 to double-scan */\r
+       0xea10,         /* v sync start */\r
+       0xac11,         /* v sync end and protect cr0-cr7 */\r
+       0xdf12,         /* vertical displayed */\r
+       0x0014,         /* turn off dword mode */\r
+       0xe715,         /* v blank start */\r
+       0x0616,         /* v blank end */\r
+       0xe317          /* turn on byte mode */\r
+    };\r
+    int CRTParmCount = sizeof(CRTParms) / sizeof(CRTParms[0]);\r
+\r
+    /* TODO save current video mode and palette */\r
+    vgaSetMode(VGA_256_COLOR_MODE);\r
+\r
+    /* disable chain4 mode */\r
+    outpw(SC_INDEX, 0x0604);\r
+\r
+    /* synchronous reset while setting Misc Output */\r
+    outpw(SC_INDEX, 0x0100);\r
+\r
+    /* select 25 MHz dot clock & 60 Hz scanning rate */\r
+    outp(MISC_OUTPUT, 0xe3);\r
+\r
+    /* undo reset (restart sequencer) */\r
+    outpw(SC_INDEX, 0x0300);\r
+\r
+    /* reprogram the CRT controller */\r
+    outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */\r
+    outp(CRTC_DATA, 0x7f);  /* get current write protect on varios regs */\r
+\r
+    /* send the CRTParms */\r
+    for(i=0; i<CRTParmCount; i++) {\r
+       outpw(CRTC_INDEX, CRTParms[i]);\r
+    }\r
+\r
+    /* clear video memory */\r
+    outpw(SC_INDEX, 0x0f02);\r
+    for(i=0; i<0x8000; i++) {\r
+       ptr[i] = 0x0000;\r
+    }\r
+}\r
+\r
+\r
+void\r
+modexLeave() {\r
+    /* TODO restore original mode and palette */\r
+    vgaSetMode(TEXT_MODE);\r
+}\r
+\r
+\r
+page_t\r
+modexDefaultPage() {\r
+    page_t page;\r
+\r
+    /* default page values */\r
+    page.data = VGA;\r
+    page.dx = 0;\r
+    page.dy = 0;\r
+    page.width = SCREEN_WIDTH;\r
+    page.height = SCREEN_HEIGHT;\r
+\r
+    return page;\r
+}\r
+\r
+/* returns the next page in contiguous memory\r
+ * the next page will be the same size as p, by default\r
+ */\r
+page_t\r
+modexNextPage(page_t *p) {\r
+    page_t result;\r
+\r
+    result.data = p->data + (p->width/4)*p->height;  /* compute the offset */\r
+    result.dx = 0;\r
+    result.dy = 0;\r
+    result.width = p->width;\r
+    result.height = p->height;\r
+\r
+    return result;\r
+}\r
+\r
+\r
+void\r
+modexShowPage(page_t *page) {\r
+    word high_address;\r
+    word low_address;\r
+    word offset;\r
+    byte crtcOffset;\r
+\r
+    /* calculate offset */\r
+    offset = (word) page->data;\r
+    offset += page->dy * (page->width >> 2 );\r
+    offset += page->dx >> 2;\r
+\r
+    /* calculate crtcOffset according to virtual width */\r
+    crtcOffset = page->width >> 3;\r
+\r
+    high_address = HIGH_ADDRESS | (offset & 0xff00);\r
+    low_address  = LOW_ADDRESS  | (offset << 8);\r
+\r
+    /* wait for appropriate timing and then program CRTC */\r
+    while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
+    outpw(CRTC_INDEX, high_address);\r
+    outpw(CRTC_INDEX, low_address);\r
+    outp(CRTC_INDEX, 0x13);\r
+    outp(CRTC_DATA, crtcOffset);\r
+\r
+    /*  wait for one retrace */\r
+    while (!(inp(INPUT_STATUS_1) & VRETRACE)); \r
+\r
+    /* do PEL panning here */\r
+    outp(AC_INDEX, 0x33);\r
+    outp(AC_INDEX, (page->dx & 0x03) << 1);\r
+}\r
+\r
+\r
+void\r
+modexPanPage(page_t *page, int dx, int dy) {\r
+    page->dx = dx;\r
+    page->dy = dy;\r
+}\r
+\r
+\r
+void\r
+modexSelectPlane(byte plane) {\r
+    outp(SC_INDEX, MAP_MASK);          /* select plane */\r
+    outp(SC_DATA,  plane);\r
+}\r
+\r
+\r
+void\r
+modexClearRegion(page_t *page, int x, int y, int w, int h, byte  color) {\r
+    word pageOff = (word) page->data;\r
+    word xoff=x/4;       /* xoffset that begins each row */\r
+    word scanCount=w/4;  /* number of iterations per row (excluding right clip)*/\r
+    word poffset = pageOff + y*(page->width/4) + xoff; /* starting offset */\r
+    word nextRow = page->width/4-scanCount-1;  /* loc of next row */\r
+    byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
+    byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
+    byte left = lclip[x&0x03];\r
+    byte right = rclip[(x+w)&0x03];\r
+\r
+    /* handle the case which requires an extra group */\r
+    if((x & 0x03) && !((x+w) & 0x03)) {\r
+      right=0x0f;\r
+    }\r
+\r
+    __asm {\r
+               MOV AX, SCREEN_SEG      ; go to the VGA memory\r
+               MOV ES, AX\r
+               MOV DI, poffset         ; go to the first pixel\r
+               MOV DX, SC_INDEX        ; point to the map mask\r
+               MOV AL, MAP_MASK\r
+               OUT DX, AL\r
+               INC DX\r
+               MOV AL, color           ; get ready to write colors\r
+       SCAN_START:\r
+               MOV CX, scanCount       ; count the line\r
+               MOV BL, AL              ; remember color\r
+               MOV AL, left            ; do the left clip\r
+               OUT DX, AL              ; set the left clip\r
+               MOV AL, BL              ; restore color\r
+               STOSB                   ; write the color\r
+               DEC CX\r
+               JZ SCAN_DONE            ; handle 1 group stuff\r
+\r
+               ;-- write the main body of the scanline\r
+               MOV BL, AL              ; remember color\r
+               MOV AL, 0x0f            ; write to all pixels\r
+               OUT DX, AL\r
+               MOV AL, BL              ; restore color\r
+               REP STOSB               ; write the color\r
+       SCAN_DONE:\r
+               MOV BL, AL              ; remeber color\r
+               MOV AL, right\r
+               OUT DX, AL              ; do the right clip\r
+               MOV AL, BL              ; restore color\r
+               STOSB                   ; write pixel\r
+               ADD DI, nextRow         ; go to the next row\r
+               DEC h\r
+               JNZ SCAN_START\r
+    }\r
+}\r
+\r
+\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
+\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;\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;\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, MAP_MASK        ;\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
+\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
+\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;\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;\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, MAP_MASK        ;\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
+\r
+/* copy a region of video memory from one page to another.\r
+ * It assumes that the left edge of the tile is the same on both\r
+ * regions and the memory areas do not overlap.\r
+ */\r
+void\r
+modexCopyPageRegion(page_t *dest, page_t *src,\r
+                   word sx, word sy,\r
+                   word dx, word dy,\r
+                   word width, word height)\r
+{\r
+    word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;\r
+    word soffset = (word)src->data + sy*(src->width/4) + sx/4;\r
+    word scans   = width/4;\r
+    word nextSrcRow = src->width/4 - scans - 1;\r
+    word nextDestRow = dest->width/4 - scans - 1;\r
+    byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
+    byte rclip[] = {0x0f, 0x01, 0x03, 0x07};\r
+    byte left = lclip[sx&0x03];\r
+    byte right = rclip[(sx+width)&0x03];\r
+\r
+    __asm {\r
+               MOV AX, SCREEN_SEG      ; work in the vga space\r
+               MOV ES, AX              ;\r
+               MOV DI, doffset         ;\r
+               MOV SI, soffset         ;\r
+\r
+               MOV DX, GC_INDEX        ; turn off cpu bits\r
+               MOV AX, 0008h           ;\r
+               OUT DX, AX\r
+\r
+               MOV AX, SC_INDEX        ; point to the mask register\r
+               MOV DX, AX              ;\r
+               MOV AL, MAP_MASK        ;\r
+               OUT DX, AL              ;\r
+               INC DX                  ;\r
+\r
+       ROW_START:\r
+               PUSH DS\r
+               MOV AX, ES\r
+               MOV DS, AX\r
+               MOV CX, scans           ; the number of latches\r
+\r
+               MOV AL, left            ; do the left column\r
+               OUT DX, AL              ;\r
+               MOVSB                   ;\r
+               DEC CX                  ;\r
+\r
+               MOV AL, 0fh             ; do the inner columns\r
+               OUT DX, AL\r
+               REP MOVSB               ; copy the pixels\r
+\r
+               MOV AL, right           ; do the right column\r
+               OUT DX, AL\r
+               MOVSB\r
+               POP DS\r
+\r
+               MOV AX, SI              ; go the start of the next row\r
+               ADD AX, nextSrcRow      ;\r
+               MOV SI, AX              ;\r
+               MOV AX, DI              ;\r
+               ADD AX, nextDestRow     ;\r
+               MOV DI, AX              ;\r
+\r
+               DEC height              ; do the rest of the actions\r
+               JNZ ROW_START           ;\r
+\r
+               MOV DX, GC_INDEX+1      ; go back to CPU data\r
+               MOV AL, 0ffh            ; none from latches\r
+               OUT DX, AL              ;\r
+    }\r
+}\r
+\r
+\r
+/* fade and flash */\r
+void\r
+modexFadeOn(word fade, byte *palette) {\r
+    fadePalette(-fade, 64, 64/fade+1, palette);\r
+}\r
+\r
+\r
+void\r
+modexFadeOff(word fade, byte *palette) {\r
+    fadePalette(fade, 0, 64/fade+1, palette);\r
+}\r
+\r
+\r
+void\r
+modexFlashOn(word fade, byte *palette) {\r
+    fadePalette(fade, -64, 64/fade+1, palette);\r
+}\r
+\r
+\r
+void\r
+modexFlashOff(word fade, byte *palette) {\r
+    fadePalette(-fade, 0, 64/fade+1, palette);\r
+}\r
+\r
+\r
+static void\r
+fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
+    word i;\r
+    byte dim = start;\r
+\r
+    /* handle the case where we just update */\r
+    if(iter == 0) {\r
+       modexPalUpdate(palette);\r
+       return;\r
+    }\r
+\r
+    while(iter > 0) {  /* FadeLoop */\r
+       for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
+           tmppal[i] = palette[i] - dim;\r
+           if(tmppal[i] > 127) {\r
+               tmppal[i] = 0;\r
+           } else if(tmppal[i] > 63) {\r
+               tmppal[i] = 63;\r
+           }\r
+       }\r
+        modexPalUpdate(tmppal);\r
+       iter--;\r
+       dim += fade;\r
+    }\r
+}\r
+\r
+\r
+/* save and load */\r
+void\r
+modexPalSave(byte *palette) {\r
+    int  i;\r
+\r
+    outp(PAL_READ_REG, 0);     /* start at palette entry 0 */\r
+    for(i=0; i<PAL_SIZE; i++) {\r
+       palette[i] = inp(PAL_DATA_REG); /* read the palette data */\r
+    }\r
+}\r
+\r
+\r
+byte *\r
+modexNewPal() {\r
+    byte *ptr;\r
+    ptr = malloc(PAL_SIZE);\r
+\r
+    /* handle errors */\r
+    if(!ptr) {\r
+       printf("Could not allocate palette.\n");\r
+       exit(-1);\r
+    }\r
+\r
+    return ptr;\r
+}\r
+\r
+\r
+void\r
+modexLoadPalFile(byte *filename, byte **palette) {\r
+    FILE *file;\r
+    byte *ptr;\r
+\r
+    /* free the palette if it exists */\r
+    if(*palette) {\r
+       free(*palette);\r
+    }\r
+\r
+    /* allocate the new palette */\r
+    *palette = modexNewPal();\r
+\r
+    /* open the file */\r
+    file = fopen(filename, "rb");\r
+    if(!file) {\r
+       printf("Could not open palette file: %s\n", filename);\r
+       exit(-2);\r
+    }\r
+\r
+    /* read the file */\r
+    ptr = *palette;\r
+    while(!feof(file)) {\r
+       *ptr++ = fgetc(file);\r
+    }\r
+\r
+    fclose(file);\r
+}\r
+\r
+\r
+void\r
+modexSavePalFile(char *filename, byte *pal) {\r
+    unsigned int i;\r
+    FILE *file;\r
+\r
+    /* open the file for writing */\r
+    file = fopen(filename, "wb");\r
+    if(!file) {\r
+       printf("Could not open %s for writing\n", filename);\r
+       exit(-2);\r
+    }\r
+\r
+    /* write the data to the file */\r
+    fwrite(pal, 1, PAL_SIZE, file);\r
+    fclose(file);\r
+}\r
+\r
+\r
+/* blanking */\r
+void\r
+modexPalBlack() {\r
+    fadePalette(-1, 64, 1, tmppal);\r
+}\r
+\r
+\r
+void\r
+modexPalWhite() {\r
+    fadePalette(-1, -64, 1, tmppal);\r
+}\r
+\r
+\r
+/* utility */\r
+void\r
+modexPalUpdate(byte *p) {\r
+    int i;\r
+    modexWaitBorder();\r
+    outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
+    for(i=0; i<PAL_SIZE/2; i++) {\r
+       outp(PAL_DATA_REG, p[i]);\r
+    }\r
+    modexWaitBorder();     /* waits one retrace -- less flicker */\r
+    for(i=PAL_SIZE/2; i<PAL_SIZE; i++) {\r
+       outp(PAL_DATA_REG, p[i]);\r
+    }\r
+}\r
+\r
+\r
+void\r
+modexWaitBorder() {\r
+    while(inp(INPUT_STATUS_1)  & 8)  {\r
+       /* spin */\r
+    }\r
+\r
+    while(!(inp(INPUT_STATUS_1)  & 8))  {\r
+       /* spin */\r
+    }\r
+}\r
diff --git a/16/modex16/modex16.h b/16/modex16/modex16.h
new file mode 100755 (executable)
index 0000000..7757310
--- /dev/null
@@ -0,0 +1,86 @@
+/*\r
+ * Functions for handling modex and doing other basic graphics stuff.\r
+ */\r
+#ifndef MODEX16_H\r
+#define MODEX16_H\r
+#include <conio.h>\r
+#include "types.h"\r
+#include "bitmap.h"\r
+\r
+/* -========================== Types & Macros ==========================- */\r
+#define PAGE_OFFSET(x,y) (((y)<<6)+((y)<<4)+((x)>>2))\r
+#define PLANE(x) (1<< (x&3))\r
+#define SELECT_ALL_PLANES() outpw(0x03c4, 0xff02)\r
+\r
+typedef struct {\r
+    byte far* data;    /* the data for the page */\r
+    word dx;           /* col we are viewing on the virtual screen */\r
+    word dy;           /* row we are viewing on the virtual screen */\r
+    word width;                /* virtual width of the page */\r
+    word height;       /* virtual height of the page */\r
+} page_t;\r
+\r
+/* -============================ Functions =============================- */\r
+/* mode switching, page, and plane functions */\r
+void modexEnter();\r
+void modexLeave();\r
+page_t modexDefaultPage();\r
+page_t modexNextPage(page_t *p);\r
+void modexShowPage(page_t *page);\r
+void modexPanPage(page_t *page, int dx, int dy);\r
+void modexSelectPlane(byte plane);\r
+void modexClearRegion(page_t *page, int x, int y, int w, int h, byte color);\r
+void modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp);\r
+void modexDrawBmpRegion(page_t *page, int x, int y, int rx, int ry, int rw, int rh, bitmap_t *bmp);\r
+void modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp);\r
+void modexDrawSpriteRegion(page_t *page, int x, int y, int rx, int ry, int rw, int rh, bitmap_t *bmp);\r
+\r
+/* Palette fade and flash effects */\r
+void modexFadeOn(word fade, byte *palette);\r
+void modexFadeOff(word fade, byte *palette);\r
+void modexFlashOn(word fade, byte *palette);\r
+void modexFlashOff(word fade, byte *palette);\r
+\r
+/* palette loading and saving */\r
+void modexPalSave(byte *palette);\r
+byte *modexNewPal();\r
+void modexLoadPalFile(char *filename, byte **palette);\r
+void modexSavePalFile(char *filename, byte *palette);\r
+\r
+/* fixed palette functions */\r
+void modexPalBlack();\r
+void modexPalWhite();\r
+\r
+/* utility functions */\r
+void modexPalUpdate(byte *p);\r
+void modexWaitBorder();\r
+\r
+/* -======================= Constants & Vars ==========================- */\r
+extern byte far*  VGA;  /* The VGA Memory */\r
+#define SCREEN_SEG             0xa000\r
+#define VIDEO_INT              0x10\r
+#define SET_MODE               0x00\r
+#define VGA_256_COLOR_MODE     0x13\r
+#define TEXT_MODE              0x03\r
+#define SCREEN_WIDTH           320\r
+#define SCREEN_HEIGHT          240\r
+#define PAGE_SIZE              (word)(SCREEN_WIDTH/4 * SCREEN_HEIGHT)\r
+\r
+#define AC_INDEX               0x03c0\r
+#define SC_INDEX               0x03c4\r
+#define SC_DATA                        0x03c5\r
+#define CRTC_INDEX             0x03d4\r
+#define CRTC_DATA              0x03d5\r
+#define GC_INDEX               0x03ce\r
+#define MISC_OUTPUT            0x03c2\r
+#define HIGH_ADDRESS           0x0C\r
+#define LOW_ADDRESS            0x0D\r
+#define VRETRACE               0x08\r
+#define INPUT_STATUS_1         0x03da\r
+#define DISPLAY_ENABLE         0x01\r
+#define MAP_MASK               0x02\r
+#define PAL_READ_REG            0x03C7   /* Color register, read address */\r
+#define PAL_WRITE_REG           0x03C8   /* Color register, write address */\r
+#define PAL_DATA_REG            0x03C9   /* Color register, data port */\r
+#define PAL_SIZE                (256 * 3)\r
+#endif\r
diff --git a/16/modex16/palettec.c b/16/modex16/palettec.c
new file mode 100755 (executable)
index 0000000..340a930
--- /dev/null
@@ -0,0 +1,16 @@
+#include "modex16.h"\r
+\r
+void\r
+main() {\r
+    byte *pal;\r
+\r
+    modexEnter();\r
+\r
+    pal = modexNewPal();\r
+    modexPalSave(pal);\r
+\r
+    modexSavePalFile("gfx.pal", pal);\r
+\r
+    modexLeave();\r
+\r
+}\r
diff --git a/16/modex16/pcxtest.c b/16/modex16/pcxtest.c
new file mode 100755 (executable)
index 0000000..7373e88
--- /dev/null
@@ -0,0 +1,79 @@
+#include <stdio.h>\r
+#include "modex16.h"\r
+#include "bitmap.h"\r
+\r
+word far* clock= (word far*) 0x046C; /* 18.2hz clock */\r
+\r
+void\r
+oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite) {\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
+void main() {\r
+    bitmap_t bmp;\r
+    int i;\r
+    page_t page;\r
+    word start;\r
+    float t1, t2;\r
+\r
+    page=modexDefaultPage();\r
+\r
+    bmp = bitmapLoadPcx("46113319.pcx");\r
+    modexEnter();\r
+\r
+    /* fix up the palette and everything */\r
+    modexPalUpdate(bmp.palette);\r
+\r
+    /* clear and draw one sprite and one bitmap */\r
+    modexClearRegion(&page, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 1);\r
+\r
+    /* non sprite comparison */\r
+    start = *clock;\r
+    for(i=0; i<100 ;i++) {\r
+      oldDrawBmp(VGA, 20, 20, &bmp, 0);\r
+    }\r
+\r
+    start = *clock;\r
+    for(i=0; i<100 ;i++) {\r
+      modexDrawBmp(&page, 20, 20, &bmp);\r
+    }\r
+    t1 = (*clock-start) /18.2;\r
+\r
+    start = *clock;\r
+    for(i=0; i<100; i++) {\r
+       modexCopyPageRegion(&page, &page, 20, 20, 128, 20, 64, 64);\r
+    }\r
+    t2 = (*clock-start)/18.2;\r
+\r
+\r
+    start = *clock;\r
+    for(i=0; i<100 ;i++) {\r
+      oldDrawBmp(VGA, 20, 20, &bmp, 1);\r
+    }\r
+\r
+\r
+    start = *clock;\r
+    for(i=0; i<100 ;i++) {\r
+      modexDrawSprite(&page, 20, 20, &bmp);\r
+    }\r
+    modexLeave();\r
+\r
+    printf("CPU to VGA: %f\n", t1);\r
+    printf("VGA to VGA: %f\n", t2);\r
+    return;\r
+}\r
diff --git a/16/modex16/pcxtest.exe b/16/modex16/pcxtest.exe
new file mode 100755 (executable)
index 0000000..de765ec
Binary files /dev/null and b/16/modex16/pcxtest.exe differ
diff --git a/16/modex16/q.pcx b/16/modex16/q.pcx
new file mode 100755 (executable)
index 0000000..a51d634
Binary files /dev/null and b/16/modex16/q.pcx differ
diff --git a/16/modex16/rarity.pcx b/16/modex16/rarity.pcx
new file mode 100755 (executable)
index 0000000..8e7e32f
Binary files /dev/null and b/16/modex16/rarity.pcx differ
diff --git a/16/modex16/scroll.c b/16/modex16/scroll.c
new file mode 100755 (executable)
index 0000000..8a960ee
--- /dev/null
@@ -0,0 +1,363 @@
+#include "modex16.h"\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include "dos_kb.h"\r
+\r
+//word far *clock= (word far*) 0x046C; /* 18.2hz clock */\r
+\r
+typedef struct {\r
+       bitmap_t *data;\r
+       word tileHeight;\r
+       word tileWidth;\r
+       unsigned int rows;\r
+       unsigned int cols;\r
+       unsigned int tilex,tiley; // tile position on the map\r
+} tiles_t;\r
+\r
+\r
+typedef struct {\r
+       byte    *data;\r
+       tiles_t *tiles;\r
+       int width;\r
+       int height;\r
+} map_t;\r
+\r
+\r
+typedef struct {\r
+       map_t *map;\r
+       page_t *page;\r
+       int tx; //???? appears to be the tile position on the viewable screen map\r
+       int ty; //???? appears to be the tile position on the viewable screen map\r
+       word dxThresh; //????\r
+       word dyThresh; //????\r
+} map_view_t;\r
+\r
+struct {\r
+       int tx; //player position on the viewable map\r
+       int ty; //player position on the viewable map\r
+} player;\r
+\r
+\r
+map_t allocMap(int w, int h);\r
+void initMap(map_t *map);\r
+void mapScrollRight(map_view_t *mv, byte offset);\r
+void mapScrollLeft(map_view_t *mv, byte offest);\r
+void mapScrollUp(map_view_t *mv, byte offset);\r
+void mapScrollDown(map_view_t *mv, byte offset);\r
+void mapGoTo(map_view_t *mv, int tx, int ty);\r
+void mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y);\r
+void mapDrawRow(map_view_t *mv, int tx, int ty, word y);\r
+void mapDrawCol(map_view_t *mv, int tx, int ty, word x);\r
+\r
+#define TILEWH 16\r
+#define QUADWH (TILEWH/4)\r
+//#define SWAP(a, b) tmp=a; a=b; b=tmp;\r
+void main() {\r
+//     int show1=1;\r
+       int tx, ty;\r
+       int x, y;\r
+       //int ch=0x0;\r
+//     byte ch;\r
+       int q=0;\r
+       page_t screen;//,screen2;\r
+       map_t map;\r
+       map_view_t mv;//, mv2;\r
+       map_view_t *draw;//, *show, *tmp;\r
+       byte *ptr;\r
+\r
+       //default player position on the viewable map\r
+       player.tx = 10;\r
+       player.ty = 8;\r
+\r
+       setkb(1);\r
+       /* create the map */\r
+       map = allocMap(160,120); //20x15 is the resolution of the screen you can make maps smaller than 20x15 but the null space needs to be drawn properly\r
+       initMap(&map);\r
+       mv.map = &map;\r
+//     mv2.map = &map;\r
+\r
+       /* draw the tiles */\r
+       ptr = map.data;\r
+       modexEnter();\r
+       screen = modexDefaultPage();\r
+       screen.width += (TILEWH*2);\r
+       mv.page = &screen;\r
+       mapGoTo(&mv, 16, 16);\r
+//     screen2=modexNextPage(mv.page);\r
+//     mv2.page = &screen2;\r
+//     mapGoTo(&mv2, 16, 16);\r
+//     modexShowPage(mv.page);\r
+\r
+       /* set up paging */\r
+//     show = &mv;\r
+//     draw = &mv2;\r
+       draw = &mv;\r
+\r
+       //TODO: set player position data here according to the viewable map screen thingy\r
+\r
+       while(!keyp(1)) {\r
+       //TODO: top left corner & bottem right corner of map veiw be set as map edge trigger since maps are actually square\r
+       //to stop scrolling and have the player position data move to the edge of the screen with respect to the direction\r
+       //when player.tx or player.ty == 0 or player.tx == 20 or player.ty == 15 then stop because that is edge of map and you do not want to walk of the map\r
+       if(keyp(77)){\r
+//             for(q=0; q<TILEWH; q++) {\r
+               mapScrollRight(draw, 1);\r
+//             modexShowPage(draw->page);\r
+//             mapScrollRight(draw, 1);\r
+//             SWAP(draw, show);\r
+//             }\r
+       }\r
+\r
+       if(keyp(75)){\r
+//             for(q=0; q<TILEWH; q++) {\r
+               mapScrollLeft(draw, 1);\r
+//             modexShowPage(draw->page);\r
+//             mapScrollLeft(show, 1);\r
+//             SWAP(draw, show);\r
+//             }\r
+       }\r
+\r
+       if(keyp(80)){\r
+//             for(q=0; q<TILEWH; q++) {\r
+               mapScrollDown(draw, 1);\r
+//             modexShowPage(draw->page);\r
+//             mapScrollDown(show, 1);\r
+//             SWAP(draw, show);\r
+//             }\r
+       }\r
+\r
+       if(keyp(72)){\r
+//             for(q=0; q<TILEWH; q++) {\r
+               mapScrollUp(draw, 1);\r
+//             modexShowPage(draw->page);\r
+//             mapScrollUp(show, 1);\r
+//             SWAP(draw, show);\r
+//             }\r
+       }\r
+\r
+       //keyp(ch);\r
+       modexShowPage(draw->page);\r
+\r
+       }\r
+\r
+       modexLeave();\r
+       setkb(0);\r
+}\r
+\r
+\r
+map_t\r
+allocMap(int w, int h) {\r
+       map_t result;\r
+\r
+       result.width =w;\r
+       result.height=h;\r
+       result.data = malloc(sizeof(byte) * w * h);\r
+\r
+       return result;\r
+}\r
+\r
+\r
+void\r
+initMap(map_t *map) {\r
+       /* just a place holder to fill out an alternating pattern */\r
+       int x, y;\r
+       int i;\r
+       int tile = 1;\r
+       map->tiles = malloc(sizeof(tiles_t));\r
+\r
+       /* create the tile set */\r
+       map->tiles->data = malloc(sizeof(bitmap_t));\r
+       map->tiles->data->width = (TILEWH*2);\r
+       map->tiles->data->height= TILEWH;\r
+       map->tiles->data->data = malloc((TILEWH*2)*TILEWH);\r
+       map->tiles->tileHeight = TILEWH;\r
+       map->tiles->tileWidth =TILEWH;\r
+       map->tiles->rows = 1;\r
+       map->tiles->cols = 2;\r
+\r
+       i=0;\r
+       for(y=0; y<TILEWH; y++) {\r
+       for(x=0; x<(TILEWH*2); x++) {\r
+               if(x<TILEWH)\r
+                 map->tiles->data->data[i] = 0x24;\r
+               else\r
+                 map->tiles->data->data[i] = 0x34;\r
+               i++;\r
+       }\r
+       }\r
+\r
+       i=0;\r
+       for(y=0; y<map->height; y++) {\r
+               for(x=0; x<map->width; x++) {\r
+                       map->data[i] = tile;\r
+                       tile = tile ? 0 : 1;\r
+                       i++;\r
+               }\r
+               tile = tile ? 0 : 1;\r
+       }\r
+}\r
+\r
+\r
+void\r
+mapScrollRight(map_view_t *mv, byte offset) {\r
+       word x, y;  /* coordinate for drawing */\r
+\r
+       /* increment the pixel position and update the page */\r
+       mv->page->dx += offset;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv->page->dx >= mv->dxThresh ) {\r
+       /* go forward one tile */\r
+       mv->tx++;\r
+       /* Snap the origin forward */\r
+       mv->page->data += 4;\r
+       mv->page->dx = mv->map->tiles->tileWidth;\r
+\r
+\r
+       /* draw the next column */\r
+       x= SCREEN_WIDTH + mv->map->tiles->tileWidth;\r
+               mapDrawCol(mv, mv->tx + 20 , mv->ty-1, x);\r
+       }\r
+}\r
+\r
+\r
+void\r
+mapScrollLeft(map_view_t *mv, byte offset) {\r
+       word x, y;  /* coordinate for drawing */\r
+\r
+       /* increment the pixel position and update the page */\r
+       mv->page->dx -= offset;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv->page->dx == 0) {\r
+       /* go backward one tile */\r
+       mv->tx--;\r
+               \r
+       /* Snap the origin backward */\r
+       mv->page->data -= 4;\r
+       mv->page->dx = mv->map->tiles->tileWidth;\r
+\r
+       /* draw the next column */\r
+               mapDrawCol(mv, mv->tx-1, mv->ty-1, 0);\r
+       }\r
+}\r
+\r
+\r
+void\r
+mapScrollUp(map_view_t *mv, byte offset) {\r
+       word x, y;  /* coordinate for drawing */\r
+\r
+       /* increment the pixel position and update the page */\r
+       mv->page->dy -= offset;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv->page->dy == 0 ) {\r
+       /* go down one tile */\r
+       mv->ty--;\r
+       /* Snap the origin downward */\r
+       mv->page->data -= mv->page->width*4;\r
+       mv->page->dy = mv->map->tiles->tileHeight;\r
+\r
+\r
+       /* draw the next row */\r
+       y= 0;\r
+               mapDrawRow(mv, mv->tx-1 , mv->ty-1, y);\r
+       }\r
+}\r
+\r
+\r
+void\r
+mapScrollDown(map_view_t *mv, byte offset) {\r
+       word x, y;  /* coordinate for drawing */\r
+\r
+       /* increment the pixel position and update the page */\r
+       mv->page->dy += offset;\r
+\r
+       /* check to see if this changes the tile */\r
+       if(mv->page->dy >= mv->dyThresh ) {\r
+       /* go down one tile */\r
+       mv->ty++;\r
+       /* Snap the origin downward */\r
+       mv->page->data += mv->page->width*4;\r
+       mv->page->dy = mv->map->tiles->tileHeight;\r
+\r
+\r
+       /* draw the next row */\r
+       y= SCREEN_HEIGHT + mv->map->tiles->tileHeight;\r
+               mapDrawRow(mv, mv->tx-1 , mv->ty+15, y);\r
+       }\r
+\r
+}\r
+\r
+\r
+void\r
+mapGoTo(map_view_t *mv, int tx, int ty) {\r
+       int px, py;\r
+       unsigned int i;\r
+\r
+       /* set up the coordinates */\r
+       mv->tx = tx;\r
+       mv->ty = ty;\r
+       mv->page->dx = mv->map->tiles->tileWidth;\r
+       mv->page->dy = mv->map->tiles->tileHeight;\r
+\r
+       /* set up the thresholds */\r
+       mv->dxThresh = mv->map->tiles->tileWidth * 2;\r
+       mv->dyThresh = mv->map->tiles->tileHeight * 2;\r
+\r
+       /* draw the tiles */\r
+       modexClearRegion(mv->page, 0, 0, mv->page->width, mv->page->height, 0);\r
+       py=0;\r
+       i=mv->ty * mv->map->width + mv->tx;\r
+       for(ty=mv->ty-1; py < SCREEN_HEIGHT+mv->dyThresh && ty < mv->map->height; ty++, py+=mv->map->tiles->tileHeight) {\r
+               mapDrawRow(mv, tx-1, ty, py);\r
+       i+=mv->map->width - tx;\r
+       }\r
+}\r
+\r
+\r
+void\r
+mapDrawTile(tiles_t *t, word i, page_t *page, word x, word y) {\r
+       word rx;\r
+       word ry;\r
+       rx = (i % t->cols) * t->tileWidth;\r
+       ry = (i / t->cols) * t->tileHeight;\r
+       modexDrawBmpRegion(page, x, y, rx, ry, t->tileWidth, t->tileHeight, t->data);\r
+}\r
+\r
+\r
+void \r
+mapDrawRow(map_view_t *mv, int tx, int ty, word y) {\r
+       word x;\r
+       int i;\r
+\r
+       /* the position within the map array */\r
+       i=ty * mv->map->width + tx;\r
+       for(x=0; x<SCREEN_WIDTH+mv->dxThresh && tx < mv->map->width; x+=mv->map->tiles->tileWidth, tx++) {\r
+       if(i>=0) {\r
+               /* we are in the map, so copy! */\r
+               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);\r
+       }\r
+       i++; /* next! */\r
+       }\r
+}\r
+\r
+\r
+void \r
+mapDrawCol(map_view_t *mv, int tx, int ty, word x) {\r
+       int y;\r
+       int i;\r
+\r
+       /* location in the map array */\r
+       i=ty * mv->map->width + tx;\r
+\r
+       /* We'll copy all of the columns in the screen, \r
+          i + 1 row above and one below */\r
+       for(y=0; y<SCREEN_HEIGHT+mv->dyThresh && ty < mv->map->height; y+=mv->map->tiles->tileHeight, ty++) {\r
+       if(i>=0) {\r
+               /* we are in the map, so copy away! */\r
+               mapDrawTile(mv->map->tiles, mv->map->data[i], mv->page, x, y);\r
+       }\r
+       i += mv->map->width;\r
+       }\r
+}\r
diff --git a/16/modex16/scroll.exe b/16/modex16/scroll.exe
new file mode 100755 (executable)
index 0000000..2376252
Binary files /dev/null and b/16/modex16/scroll.exe differ
diff --git a/16/modex16/test.c b/16/modex16/test.c
new file mode 100755 (executable)
index 0000000..c5b9d7d
--- /dev/null
@@ -0,0 +1,75 @@
+#include "modex16.h"\r
+#include <stdio.h>\r
+\r
+word far* clock= (word far*) 0x046C; /* 18.2hz clock */\r
+\r
+void main() {\r
+    int i, j;\r
+    word start, end;\r
+    page_t page, page2;\r
+    byte *pal, *pal2=NULL;\r
+\r
+    /* load our palette */\r
+    modexLoadPalFile("gfx.pal", &pal2);\r
+\r
+    /* save the palette */\r
+    pal  = modexNewPal();\r
+    modexPalSave(pal);\r
+    modexFadeOff(1, pal);\r
+    modexPalBlack();\r
+\r
+    modexEnter();\r
+    modexPalBlack();\r
+\r
+    /* set up the page, but with 16 pixels on all borders in offscreen mem */\r
+    page=modexDefaultPage();\r
+    page2 = modexNextPage(&page);\r
+    page.width += 32;\r
+    page.height += 32;\r
+\r
+\r
+    /* fill the page with one color, but with a black border */\r
+    modexShowPage(&page2);\r
+    modexClearRegion(&page, 16, 16, SCREEN_WIDTH, SCREEN_HEIGHT, 128);\r
+    modexClearRegion(&page, 32, 32, SCREEN_WIDTH-32, SCREEN_HEIGHT-32, 42);\r
+    modexClearRegion(&page, 48, 48, SCREEN_WIDTH-64, SCREEN_HEIGHT-64, 128);\r
+    modexShowPage(&page);\r
+\r
+    /* fade in */\r
+    modexFadeOn(1, pal2);\r
+\r
+\r
+    start = *clock;\r
+    for(i=0; i<5; i++) {\r
+       /* go right */\r
+       for(j=0; j<32; j++) {\r
+           page.dx++;\r
+           modexShowPage(&page);\r
+       }\r
+       /* go left */\r
+       for(j=0; j<32; j++) {\r
+           page.dx--;\r
+           modexShowPage(&page);\r
+       }\r
+       /* go up */\r
+       for(j=0; j<32; j++) {\r
+           page.dy++;\r
+           modexShowPage(&page);\r
+       }\r
+\r
+       /* go down */\r
+       for(j=0; j<32; j++) {\r
+           page.dy--;\r
+           modexShowPage(&page);\r
+       }\r
+    }\r
+\r
+    end = *clock;\r
+\r
+    /* fade back to text mode */\r
+    modexFadeOff(1, pal2);\r
+    modexPalBlack();\r
+    modexLeave();\r
+    modexPalBlack();\r
+    modexFadeOn(1, pal);\r
+}\r
diff --git a/16/modex16/test.exe b/16/modex16/test.exe
new file mode 100755 (executable)
index 0000000..99404b1
Binary files /dev/null and b/16/modex16/test.exe differ
diff --git a/16/modex16/test.txt b/16/modex16/test.txt
new file mode 100755 (executable)
index 0000000..05adc9e
--- /dev/null
@@ -0,0 +1,258 @@
+64 x 64 Pixels\r
+\r
+0 0 0 \r
+20 0 0 \r
+0 20 0 \r
+20 20 0 \r
+0 0 20 \r
+20 0 20 \r
+0 20 20 \r
+30 30 30 \r
+30 37 30 \r
+29 32 3c \r
+3f 3f 33 \r
+3f 3f 26 \r
+3f 3f 19 \r
+3f 3f c \r
+3f 33 3f \r
+3f 33 33 \r
+3f 33 26 \r
+3f 33 19 \r
+3f 33 c \r
+3f 33 0 \r
+3f 26 3f \r
+3f 26 33 \r
+3f 26 26 \r
+3f 26 19 \r
+3f 26 c \r
+3f 26 0 \r
+3f 19 3f \r
+3f 19 33 \r
+3f 19 26 \r
+3f 19 19 \r
+3f 19 c \r
+3f 19 0 \r
+3f c 3f \r
+3f c 33 \r
+3f c 26 \r
+3f c 19 \r
+3f c c \r
+3f c 0 \r
+3f 0 33 \r
+3f 0 26 \r
+3f 0 19 \r
+3f 0 c \r
+33 3f 3f \r
+33 3f 33 \r
+33 3f 26 \r
+33 3f 19 \r
+33 3f c \r
+33 3f 0 \r
+33 33 3f \r
+33 33 33 \r
+33 33 26 \r
+33 33 19 \r
+33 33 c \r
+33 33 0 \r
+33 26 3f \r
+33 26 33 \r
+33 26 26 \r
+33 26 19 \r
+33 26 c \r
+33 26 0 \r
+33 19 3f \r
+33 19 33 \r
+33 19 26 \r
+33 19 19 \r
+33 19 c \r
+33 19 0 \r
+33 c 3f \r
+33 c 33 \r
+33 c 26 \r
+33 c 19 \r
+33 c c \r
+33 c 0 \r
+33 0 3f \r
+33 0 33 \r
+33 0 26 \r
+33 0 19 \r
+33 0 c \r
+33 0 0 \r
+26 3f 3f \r
+26 3f 33 \r
+26 3f 26 \r
+26 3f 19 \r
+26 3f c \r
+26 3f 0 \r
+26 33 3f \r
+26 33 33 \r
+26 33 26 \r
+26 33 19 \r
+26 33 c \r
+26 33 0 \r
+26 26 3f \r
+26 26 33 \r
+26 26 26 \r
+26 26 19 \r
+26 26 c \r
+26 26 0 \r
+26 19 3f \r
+26 19 33 \r
+26 19 26 \r
+26 19 19 \r
+26 19 c \r
+26 19 0 \r
+26 c 3f \r
+26 c 33 \r
+26 c 26 \r
+26 c 19 \r
+26 c c \r
+26 c 0 \r
+26 0 3f \r
+26 0 33 \r
+26 0 26 \r
+26 0 19 \r
+26 0 c \r
+26 0 0 \r
+19 3f 3f \r
+19 3f 33 \r
+19 3f 26 \r
+19 3f 19 \r
+19 3f c \r
+19 3f 0 \r
+19 33 3f \r
+19 33 33 \r
+19 33 26 \r
+19 33 19 \r
+19 33 c \r
+19 33 0 \r
+19 26 3f \r
+19 26 33 \r
+19 26 26 \r
+19 26 19 \r
+19 26 c \r
+19 26 0 \r
+19 19 3f \r
+19 19 33 \r
+19 19 26 \r
+19 19 19 \r
+19 19 c \r
+19 19 0 \r
+19 c 3f \r
+19 c 33 \r
+19 c 26 \r
+19 c 19 \r
+19 c c \r
+19 c 0 \r
+19 0 3f \r
+19 0 33 \r
+19 0 26 \r
+19 0 19 \r
+19 0 c \r
+19 0 0 \r
+c 3f 3f \r
+c 3f 33 \r
+c 3f 26 \r
+c 3f 19 \r
+c 3f c \r
+c 3f 0 \r
+c 33 3f \r
+c 33 33 \r
+c 33 26 \r
+c 33 19 \r
+c 33 c \r
+c 33 0 \r
+c 26 3f \r
+c 26 33 \r
+c 26 26 \r
+c 26 19 \r
+c 26 c \r
+c 26 0 \r
+c 19 3f \r
+c 19 33 \r
+c 19 26 \r
+c 19 19 \r
+c 19 c \r
+c 19 0 \r
+c c 3f \r
+c c 33 \r
+c c 26 \r
+c c 19 \r
+c c c \r
+c c 0 \r
+c 0 3f \r
+c 0 33 \r
+c 0 26 \r
+c 0 19 \r
+c 0 c \r
+c 0 0 \r
+0 3f 33 \r
+0 3f 26 \r
+0 3f 19 \r
+0 3f c \r
+0 33 3f \r
+0 33 33 \r
+0 33 26 \r
+0 33 19 \r
+0 33 c \r
+0 33 0 \r
+0 26 3f \r
+0 26 33 \r
+0 26 26 \r
+0 26 19 \r
+0 26 c \r
+0 26 0 \r
+0 19 3f \r
+0 19 33 \r
+0 19 26 \r
+0 19 19 \r
+0 19 c \r
+0 19 0 \r
+0 c 3f \r
+0 c 33 \r
+0 c 26 \r
+0 c 19 \r
+0 c c \r
+0 c 0 \r
+0 0 33 \r
+0 0 26 \r
+0 0 19 \r
+0 0 c \r
+20 3f 3f \r
+10 20 20 \r
+20 3f 0 \r
+10 10 0 \r
+3f 3f 20 \r
+3f 20 0 \r
+3f 20 20 \r
+20 10 0 \r
+20 0 3f \r
+20 0 10 \r
+10 20 3f \r
+0 10 20 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+0 0 0 \r
+3f 3e 3c \r
+28 28 29 \r
+20 20 20 \r
+3f 0 0 \r
+0 3f 0 \r
+3f 3f 0 \r
+0 0 3f \r
+3f 0 3f \r
+0 3f 3f \r
+3f 3f 3f 
\ No newline at end of file
diff --git a/16/modex16/test2.c b/16/modex16/test2.c
new file mode 100755 (executable)
index 0000000..9118279
--- /dev/null
@@ -0,0 +1,19 @@
+#include "modex16.h"\r
+\r
+word far* clock= (word far*) 0x046C; /* 18.2hz clock */\r
+\r
+void main() {\r
+    int i;\r
+    word start;\r
+    page_t page;\r
+\r
+    page=modexDefaultPage();\r
+\r
+    modexEnter();\r
+    start = *clock;\r
+    for(i=0; i<500; i++) {\r
+       modexShowPage(&page);\r
+    }\r
+    modexLeave();\r
+\r
+}\r
diff --git a/16/modex16/test2.exe b/16/modex16/test2.exe
new file mode 100755 (executable)
index 0000000..2b870ef
Binary files /dev/null and b/16/modex16/test2.exe differ
diff --git a/16/modex16/types.h b/16/modex16/types.h
new file mode 100755 (executable)
index 0000000..039653f
--- /dev/null
@@ -0,0 +1,11 @@
+/*\r
+ * Just some handy typedefs that make it easier to think about the low\r
+ * level code\r
+ */\r
+\r
+typedef unsigned char byte;\r
+typedef unsigned short word;\r
+typedef unsigned long  dword;\r
+typedef signed char sbyte;\r
+typedef signed short sword;\r
+typedef signed long sdword;\r
diff --git a/16/modex16/w.pcx b/16/modex16/w.pcx
new file mode 100755 (executable)
index 0000000..ad80879
Binary files /dev/null and b/16/modex16/w.pcx differ
index 3a91e17360e1ed00fbe6c984394aab2357bd5b61..4ea630f83392d8ae916767a216916ded8c7d97dc 100755 (executable)
@@ -1,4 +1,4 @@
-//from https://github.com/sparky4/16/commit/a19d7592507e5f7aa91f4a6b6611e021bd1a3e8d\r
+//from https://github.com/sparky4/16/commit/7872dbf5d0240f01177588bd7966c3e042ced554\r
 #include "16/src/lib/omodex16.h"\r
 #include "16/src/lib/bitmap.h"\r
 #include <stdio.h>\r