--- /dev/null
+Old non-sprite: 7.032967\r
+New non-sprite: 1.043956\r
+Old Sprite: 6.648352\r
+New Sprite: 1.648352\r
--- /dev/null
+Old non-sprite: 10.439561\r
+New non-sprite: 1.373626\r
+Old Sprite: 9.945055\r
+New Sprite: 2.362637\r
--- /dev/null
+#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
--- /dev/null
+/*\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
--- /dev/null
+/* 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
--- /dev/null
+#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
--- /dev/null
+//#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
--- /dev/null
+#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
--- /dev/null
+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
--- /dev/null
+#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, ®s, ®s);\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
--- /dev/null
+/*\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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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 = ↦\r
+// mv2.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
--- /dev/null
+#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
--- /dev/null
+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
--- /dev/null
+#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
--- /dev/null
+/*\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
-//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