openfiles: /dos/z/16/16/16.txt:0:0:0:
openfiles: /dos/z/16/16/lib/x/MODEX.H:5511:2798:0:
openfiles: /dos/z/16/16/modex16/PCXTEST.C:794:497:0:
-openfiles: /dos/z/16/16/lib/MODEX16.C:2334:1895:0:
-openfiles: /dos/z/16/16/lib/MODEX16.H:2926:2348:0:
-openfiles: /dos/z/16/16/TEST.C:335:0:1:
+openfiles: /dos/z/16/16/lib/MODEX16.C:2321:2310:0:
+openfiles: /dos/z/16/16/lib/MODEX16.H:2926:1941:0:
+openfiles: /dos/z/16/16/TEST.C:430:0:0:
+openfiles: /dos/z/16/16/modex16/test.c:350:412:1:
+openfiles: /dos/z/16/16/modex16/pcxtest.c:846:690:0:
snr_recursion_level: 0
convertcolumn_horizontally: 0
adv_open_matchname: 0
default_mime_type: text/plain
e2c.convert_xml: 1
c2e.convert_iso: 0
-opendir: file:///dos/z/16/16/lib
+opendir: file:///dos/z/16/16/modex16
wrap_text_default: 0
bookmarks_filename_mode: 1
-ssearch_text: gq
+ssearch_text: SC_INDEX
snr_casesens: 1
view_blocks: 1
name: project 16
e2c.convert_iso: 0
ssearch_casesens: 0
charmap_block: 1
-recent_files: file:///dos/z/4x4_16/tile.h
-recent_files: file:///dos/z/16/16/lib_com.cpp
recent_files: file:///dos/z/16/16/lib_com.h
recent_files: file:///dos/z/16/16/PCGPE10/SCROLL.TXT
recent_files: file:///dos/z/16/16/lib/x/MXSM.ASM
recent_files: file:///dos/z/4x4_16/w_modex/MODEX.CPP
recent_files: file:///dos/z/16/16/TYPES.H
recent_files: file:///dos/z/16/16/lib/TYPES.H
-recent_files: file:///dos/z/16/16/dos_gfx.cpp
+recent_files: file:///dos/z/16/16/test.c
+recent_files: file:///dos/z/16/16/MODEX16.H
+recent_files: file:///dos/z/16/16/MODEX16.C
+recent_files: file:///dos/z/16/16/lib/types.h
+recent_files: file:///dos/z/16/16/TEST.C
recent_files: file:///dos/z/16/16/dos_gfx.h
recent_files: file:///dos/z/16/16/lib/lib_com.h
+recent_files: file:///dos/z/16/16/lib/lib_com.cpp
recent_files: file:///dos/z/16/16/dos_kb.c
recent_files: file:///dos/z/16/16/dos_kb.h
-recent_files: file:///dos/z/16/16/lib/lib_com.cpp
+recent_files: file:///dos/z/16/16/dos_gfx.cpp
recent_files: file:///dos/z/16/16/scroll.txt
-recent_files: file:///dos/z/16/16/lib/MODEX16.C
recent_files: file:///dos/z/16/16/project16.txt
+recent_files: file:///dos/z/16/16/16.txt
recent_files: file:///dos/z/16/16/lib/MODEX16.H
recent_files: file:///dos/z/16/16/lib/x/MODEX.H
-recent_files: file:///dos/z/16/16/16.txt
+recent_files: file:///dos/z/16/16/lib/MODEX16.C
recent_files: file:///dos/z/16/16/modex16/PCXTEST.C
-recent_files: file:///dos/z/16/16/test.c
-recent_files: file:///dos/z/16/16/TEST.C
-recent_files: file:///dos/z/16/16/MODEX16.H
-recent_files: file:///dos/z/16/16/MODEX16.C
-recent_files: file:///dos/z/16/16/lib/types.h
+recent_files: file:///dos/z/16/16/modex16/test.c
+recent_files: file:///dos/z/16/16/modex16/pcxtest.c
snr_replacetype: 0
-savedir: file:///dos/z/16/16/lib
+savedir: file:///dos/z/16/16/modex16
spell_check_default: 1
spell_insert_entities: 0
last_filefilter:
htmlbar_view: 0
spell_lang: en
ssearch_dotmatchall: 0
-searchlist: modexen
searchlist: modexClearRegion(page_t *page, (SW-palq)+palx+32, paly+32, TILEWH, TILEWH, palcol);
searchlist: mx
searchlist: sw
searchlist: clock
searchlist: setvideo
searchlist: gq
+searchlist: SC_INDEX
autocomplete: 1
outputb_show_all_output: 0
bookmarks_show_mode: 0
-Old non-sprite: 7.032967\r
-New non-sprite: 1.043956\r
-Old Sprite: 6.648352\r
-New Sprite: 1.648352\r
+CPU to VGA: 0.989011\r
+VGA to VGA: 0.274725\r
-Old non-sprite: 10.439561\r
-New non-sprite: 1.373626\r
-Old Sprite: 9.945055\r
-New Sprite: 2.362637\r
+CPU to VGA: 1.373626\r
+VGA to VGA: 0.329670\r
-FLAGS=-0 -d3\r
+FLAGS=-0 \r
all: test.exe pcxtest.exe test2.exe\r
\r
test.exe: test.obj modex16.obj\r
ptr[i] = 0x0000;\r
}\r
}\r
-
-int old_mode;\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// //\r
-// setvideo() - This function Manages the video modes //\r
-// //\r
-/////////////////////////////////////////////////////////////////////////////\r
-void setvideo(/*byte mode, */short vq){\r
- union REGS in, out;\r
-\r
- if(!vq){ // deinit the video\r
- // change to the video mode we were in before we switched to mode 13h\r
- in.h.ah = 0x00;\r
- in.h.al = old_mode;\r
- int86(0x10, &in, &out);\r
-\r
- }else if(vq==1){ // init the video\r
- // get old video mode\r
- in.h.ah = 0xf;\r
- int86(0x10, &in, &out);\r
- old_mode = out.h.al;\r
- // enter mode
- modexEnter();\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
}\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
+modexCopyPageRegion(page_t *dest, page_t *src,\r
word sx, word sy,\r
word dx, word dy,\r
word width, word height)\r
{\r
- /* todo */\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
#ifndef MODEX16_H\r
#define MODEX16_H\r
#include <conio.h>\r
-#include "types.h"
-
+#include "types.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
\r
/* -============================ Functions =============================- */\r
/* mode switching, page, and plane functions */\r
-void modexEnter();
-void setvideo(/*byte mode, */short vq);\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 modexWaitBorder();\r
\r
/* bitmap functions */\r
-bitmap_t modexLoadPcx(char *filename);
+bitmap_t modexLoadPcx(char *filename);\r
\r
/* -======================= Constants & Vars ==========================- */\r
extern byte far* VGA; /* The VGA Memory */\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 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)
-
-#define NUM_COLORS 256 // number of colors in vga mode\r
-#define BONK 400\r
-#define LGQ 32\r
-#define HGQ 55\r
-#define TILEWH 16
-#define QUADWH TILEWH/2\r
+#define PAL_SIZE (256 * 3)\r
#endif\r
void main() {\r
bitmap_t bmp;\r
int i;\r
- float t1, t2, t3, t4;\r
- word start;\r
page_t page;\r
+ word start;\r
+ float t1, t2;\r
\r
page=modexDefaultPage();\r
\r
bmp = modexLoadPcx("ed.pcx");\r
- setvideo(1);\r
+ modexEnter();\r
\r
/* fix up the palette and everything */\r
modexPalUpdate(bmp.palette);\r
for(i=0; i<100 ;i++) {\r
oldDrawBmp(VGA, 20, 20, &bmp, 0);\r
}\r
- t1 = (*clock-start) / 18.2;\r
\r
start = *clock;\r
for(i=0; i<100 ;i++) {\r
modexDrawBmp(&page, 20, 20, &bmp);\r
}\r
- t2 = (*clock-start) / 18.2;\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
- t3 = (*clock-start) / 18.2;\r
+\r
\r
start = *clock;\r
for(i=0; i<100 ;i++) {\r
modexDrawSprite(&page, 20, 20, &bmp);\r
}\r
- t4 = (*clock-start) / 18.2;\r
- setvideo(0);\r
-\r
- printf("Old non-sprite: %f\n", t1);\r
- printf("New non-sprite: %f\n", t2);\r
- printf("Old Sprite: %f\n", t3);\r
- printf("New Sprite: %f\n", t4);\r
+ modexLeave();\r
\r
+ printf("CPU to VGA: %f\n", t1);\r
+ printf("VGA to VGA: %f\n", t2);\r
return;\r
}\r
\r
word far* clock= (word far*) 0x046C; /* 18.2hz clock */\r
\r
-void main() {
- bitmap_t bmp;\r
+void main() {\r
int i, j;\r
word start, end;\r
page_t page, page2;\r
- float elapsed;\r
byte *pal, *pal2=NULL;\r
\r
- /* load pcx file */\r
- bmp = modexLoadPcx("ed.pcx");\r
-\r
/* load our palette */\r
modexLoadPalFile("gfx.pal", &pal2);\r
\r
modexFadeOff(1, pal);\r
modexPalBlack();\r
\r
- setvideo(1);\r
+ modexEnter();\r
modexPalBlack();\r
\r
/* set up the page, but with 16 pixels on all borders in offscreen mem */\r
modexClearRegion(&page, 48, 48, SCREEN_WIDTH-64, SCREEN_HEIGHT-64, 128);\r
modexShowPage(&page);\r
\r
- modexDrawSprite(&page, 20, 20, &bmp);\r
- //modexDrawBmp(&page, xb, yb, &bmp);\r
-\r
/* fade in */\r
modexFadeOn(1, pal2);\r
\r
\r
start = *clock;\r
- //for(i=0; i<5; i++) {\r
- while (!kbhit()){ /* Wait for a keystroke */\r
+ for(i=0; i<5; i++) {\r
/* go right */\r
for(j=0; j<32; j++) {\r
page.dx++;\r
}\r
}\r
\r
- (void) getch(); /* Clear the keyboard buffer */\r
end = *clock;\r
\r
/* fade back to text mode */\r
modexFadeOff(1, pal2);\r
modexPalBlack();\r
- setvideo(0);\r
+ modexLeave();\r
modexPalBlack();\r
modexFadeOn(1, pal);\r
}\r
-FLAGS=-0 -d3\r
+FLAGS=-0 \r
all: test.exe pcxtest.exe test2.exe\r
\r
test.exe: test.obj modex16.obj\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
+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
+};\r
+\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
+\r
+\r
+bitmap_t\r
+modexLoadPcx(char *filename) {\r
+ FILE *file;\r
+ bitmap_t result;\r
+ struct pcxHeader head;\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
+ /* read the header */\r
+ fread(&head, sizeof(char), sizeof(struct pcxHeader), file);\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
+ /* allocate the buffer */\r
+ result.width = head.xmax - head.xmin + 1;\r
+ result.height = head.ymax - head.ymin + 1;\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
+ /* 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
+ fclose(file);\r
+\r
+ return result;\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
+\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
+typedef struct {\r
+ byte *data;\r
+ word width;\r
+ word height;\r
+ byte *palette;\r
+} bitmap_t;\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
+/* bitmap functions */\r
+bitmap_t modexLoadPcx(char *filename);\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
void main() {\r
bitmap_t bmp;\r
int i;\r
- float t1, t2, t3, t4;\r
- word start;\r
page_t page;\r
+ word start;\r
+ float t1, t2;\r
\r
page=modexDefaultPage();\r
\r
bmp = modexLoadPcx("ed.pcx");\r
- setvideo(1);\r
+ modexEnter();\r
\r
/* fix up the palette and everything */\r
modexPalUpdate(bmp.palette);\r
for(i=0; i<100 ;i++) {\r
oldDrawBmp(VGA, 20, 20, &bmp, 0);\r
}\r
- t1 = (*clock-start) / 18.2;\r
\r
start = *clock;\r
for(i=0; i<100 ;i++) {\r
modexDrawBmp(&page, 20, 20, &bmp);\r
}\r
- t2 = (*clock-start) / 18.2;\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
- t3 = (*clock-start) / 18.2;\r
+\r
\r
start = *clock;\r
for(i=0; i<100 ;i++) {\r
modexDrawSprite(&page, 20, 20, &bmp);\r
}\r
- t4 = (*clock-start) / 18.2;\r
- setvideo(0);\r
-\r
- printf("Old non-sprite: %f\n", t1);\r
- printf("New non-sprite: %f\n", t2);\r
- printf("Old Sprite: %f\n", t3);\r
- printf("New Sprite: %f\n", t4);\r
+ modexLeave();\r
\r
+ printf("CPU to VGA: %f\n", t1);\r
+ printf("VGA to VGA: %f\n", t2);\r
return;\r
}\r
\r
word far* clock= (word far*) 0x046C; /* 18.2hz clock */\r
\r
-void main() {
- bitmap_t bmp;\r
+void main() {\r
int i, j;\r
word start, end;\r
page_t page, page2;\r
- float elapsed;\r
byte *pal, *pal2=NULL;\r
\r
- /* load pcx file */\r
- bmp = modexLoadPcx("ed.pcx");\r
-\r
/* load our palette */\r
modexLoadPalFile("gfx.pal", &pal2);\r
\r
modexFadeOff(1, pal);\r
modexPalBlack();\r
\r
- setvideo(1);\r
+ modexEnter();\r
modexPalBlack();\r
\r
/* set up the page, but with 16 pixels on all borders in offscreen mem */\r
modexClearRegion(&page, 48, 48, SCREEN_WIDTH-64, SCREEN_HEIGHT-64, 128);\r
modexShowPage(&page);\r
\r
- modexDrawSprite(&page, 20, 20, &bmp);\r
- //modexDrawBmp(&page, xb, yb, &bmp);\r
-\r
/* fade in */\r
modexFadeOn(1, pal2);\r
\r
\r
start = *clock;\r
- //for(i=0; i<5; i++) {\r
- while (!kbhit()){ /* Wait for a keystroke */\r
+ for(i=0; i<5; i++) {\r
/* go right */\r
for(j=0; j<32; j++) {\r
page.dx++;\r
}\r
}\r
\r
- (void) getch(); /* Clear the keyboard buffer */\r
end = *clock;\r
\r
/* fade back to text mode */\r
modexFadeOff(1, pal2);\r
modexPalBlack();\r
- setvideo(0);\r
+ modexLeave();\r
modexPalBlack();\r
modexFadeOn(1, pal);\r
}\r
void main() {\r
int i;\r
word start;\r
- float t1, t2;\r
page_t page;\r
\r
page=modexDefaultPage();\r
\r
- setvideo(1);\r
+ modexEnter();\r
start = *clock;\r
for(i=0; i<500; i++) {\r
modexShowPage(&page);\r
}\r
- t1 = (*clock - start)/18.2;\r
- setvideo(0);\r
+ modexLeave();\r
\r
- printf("Time: %f\n", t1);\r
}\r
--- /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 <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
+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
+};\r
+\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
+
+int old_mode;\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// //\r
+// setvideo() - This function Manages the video modes //\r
+// //\r
+/////////////////////////////////////////////////////////////////////////////\r
+void setvideo(/*byte mode, */short vq){\r
+ union REGS in, out;\r
+\r
+ if(!vq){ // deinit the video\r
+ // change to the video mode we were in before we switched to mode 13h\r
+ in.h.ah = 0x00;\r
+ in.h.al = old_mode;\r
+ int86(0x10, &in, &out);\r
+\r
+ }else if(vq==1){ // init the video\r
+ // get old video mode\r
+ in.h.ah = 0xf;\r
+ int86(0x10, &in, &out);\r
+ old_mode = out.h.al;\r
+ // enter mode
+ modexEnter();\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
+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
+ /* todo */\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
+\r
+\r
+bitmap_t\r
+modexLoadPcx(char *filename) {\r
+ FILE *file;\r
+ bitmap_t result;\r
+ struct pcxHeader head;\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
+ /* read the header */\r
+ fread(&head, sizeof(char), sizeof(struct pcxHeader), file);\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
+ /* allocate the buffer */\r
+ result.width = head.xmax - head.xmin + 1;\r
+ result.height = head.ymax - head.ymin + 1;\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
+ /* 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
+ fclose(file);\r
+\r
+ return result;\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"
+
+/* -========================== 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
+typedef struct {\r
+ byte *data;\r
+ word width;\r
+ word height;\r
+ byte *palette;\r
+} bitmap_t;\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();
+void setvideo(/*byte mode, */short vq);\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
+/* bitmap functions */\r
+bitmap_t modexLoadPcx(char *filename);
+\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 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)
+
+#define NUM_COLORS 256 // number of colors in vga mode\r
+#define BONK 400\r
+#define LGQ 32\r
+#define HGQ 55\r
+#define TILEWH 16
+#define QUADWH TILEWH/2\r
+#endif\r
--- /dev/null
+FLAGS=-0 -d3\r
+all: test.exe pcxtest.exe test2.exe\r
+\r
+test.exe: test.obj modex16.obj\r
+ wcl $(FLAGS) test.obj modex16.obj\r
+ \r
+test2.exe: test2.obj modex16.obj\r
+ wcl $(FLAGS) test2.obj modex16.obj\r
+ \r
+pcxtest.exe: pcxtest.obj modex16.obj\r
+ wcl $(FLAGS) pcxtest.obj modex16.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
+clean: \r
+ del *.obj\r
+ del *.exe\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
+\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
+ float t1, t2, t3, t4;\r
+ word start;\r
+ page_t page;\r
+\r
+ page=modexDefaultPage();\r
+\r
+ bmp = modexLoadPcx("ed.pcx");\r
+ setvideo(1);\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
+ t1 = (*clock-start) / 18.2;\r
+\r
+ start = *clock;\r
+ for(i=0; i<100 ;i++) {\r
+ modexDrawBmp(&page, 20, 20, &bmp);\r
+ }\r
+ t2 = (*clock-start) / 18.2;\r
+\r
+ start = *clock;\r
+ for(i=0; i<100 ;i++) {\r
+ oldDrawBmp(VGA, 20, 20, &bmp, 1);\r
+ }\r
+ t3 = (*clock-start) / 18.2;\r
+\r
+ start = *clock;\r
+ for(i=0; i<100 ;i++) {\r
+ modexDrawSprite(&page, 20, 20, &bmp);\r
+ }\r
+ t4 = (*clock-start) / 18.2;\r
+ setvideo(0);\r
+\r
+ printf("Old non-sprite: %f\n", t1);\r
+ printf("New non-sprite: %f\n", t2);\r
+ printf("Old Sprite: %f\n", t3);\r
+ printf("New Sprite: %f\n", t4);\r
+\r
+ return;\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() {
+ bitmap_t bmp;
+ bitmap_t bmp2;\r
+ int i, j;\r
+ word start, end;\r
+ page_t page, page2;\r
+ float elapsed;\r
+ byte *pal, *pal2=NULL;\r
+\r
+ /* load pcx file */\r
+ bmp = modexLoadPcx("ed.pcx");
+ bmp2 = modexLoadPcx("koishi~.pcx");
+ modexPalUpdate(bmp2.palette);
+\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
+ setvideo(1);\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
+
+ modexDrawSprite(&page, 48, 48, &bmp);
+ modexDrawSprite(&page, 100, 100, &bmp2);\r
+ //modexDrawBmp(&page, xb, yb, &bmp);\r
+\r
+ /* fade in */\r
+ modexFadeOn(1, pal2);\r
+
+modexPalUpdate(bmp2.palette);\r
+\r
+ start = *clock;\r
+ //for(i=0; i<5; i++) {\r
+ while (!kbhit()){ /* Wait for a keystroke */\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
+ (void) getch(); /* Clear the keyboard buffer */\r
+ end = *clock;\r
+\r
+ /* fade back to text mode */\r
+ modexFadeOff(1, pal2);\r
+ modexPalBlack();\r
+ setvideo(0);\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
+ float t1, t2;\r
+ page_t page;\r
+\r
+ page=modexDefaultPage();\r
+\r
+ setvideo(1);\r
+ start = *clock;\r
+ for(i=0; i<500; i++) {\r
+ modexShowPage(&page);\r
+ }\r
+ t1 = (*clock - start)/18.2;\r
+ setvideo(0);\r
+\r
+ printf("Time: %f\n", t1);\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
4. map rendering\r
5. map and item interaction\r
6. fix any bugs found\r
-7. script system for text and interaction
-8. clean up repository after event 1.
-
-9. make the game wwww\r
+7. script system for text and interaction\r
+\r
+8. clean up repository after event 1.\r
+\r
+9. basic sounds from opl2 + pc speaker!\r
+10. make the game wwww\r