From: sparky4 Date: Sat, 26 Jul 2014 04:56:35 +0000 (-0500) Subject: modified: 16/MODEX16.ZIP X-Git-Url: http://4ch.mooo.com/gitweb/?a=commitdiff_plain;h=ee4a2a942f50ad952a56457342f5fa1528427589;p=16.git modified: 16/MODEX16.ZIP renamed: 16/MODEX16.ZIP -> 16/MODEX16_.ZIP modified: 16/Project 16.bfproject modified: 16/modex16/286@12.LOG modified: 16/modex16/286@8.LOG modified: 16/modex16/MAKEFILE modified: 16/modex16/MODEX16.C modified: 16/modex16/MODEX16.H modified: 16/modex16/PCXTEST.C modified: 16/modex16/PCXTEST.EXE modified: 16/modex16/TEST.C modified: 16/modex16/TEST.EXE modified: 16/modex16/TEST2.EXE modified: 16/modex16/makefile new file: 16/modex16/modex16.c new file: 16/modex16/modex16.h modified: 16/modex16/pcxtest.c new file: 16/modex16/pcxtest.exe modified: 16/modex16/test.c new file: 16/modex16/test.exe modified: 16/modex16/test2.c new file: 16/modex16/test2.exe new file: 16/modex16_/286@12.LOG new file: 16/modex16_/286@8.LOG renamed: 16/modex16/COMPUTER.PCX -> 16/modex16_/COMPUTER.PCX renamed: 16/modex16/EDw.PCX -> 16/modex16_/EDw.PCX new file: 16/modex16_/MODEX16.C new file: 16/modex16_/MODEX16.H renamed: 16/modex16/PALVIEW.EXE -> 16/modex16_/PALVIEW.EXE renamed: 16/modex16/PCXTEST.EXE -> 16/modex16_/PCXTEST.EXE new file: 16/modex16_/TEST.EXE renamed: 16/modex16/TEST2.EXE -> 16/modex16_/TEST2.EXE renamed: 16/modex16/chikyuu.pcx -> 16/modex16_/chikyuu.pcx new file: 16/modex16_/ed.pcx renamed: 16/modex16/ed2.pcx -> 16/modex16_/ed2.pcx new file: 16/modex16_/gfx.pal renamed: 16/modex16/koishi.pcx -> 16/modex16_/koishi.pcx renamed: 16/modex16/koishi^^.pcx -> 16/modex16_/koishi^^.pcx new file: 16/modex16_/koishi~.pcx new file: 16/modex16_/makefile new file: 16/modex16_/palettec.c new file: 16/modex16_/pcxtest.c renamed: 16/modex16/q.pcx -> 16/modex16_/q.pcx new file: 16/modex16_/test.c new file: 16/modex16_/test.txt new file: 16/modex16_/test2.c new file: 16/modex16_/types.h renamed: 16/modex16/w.pcx -> 16/modex16_/w.pcx modified: TODO --- diff --git a/16/MODEX16.ZIP b/16/MODEX16.ZIP index a1480fab..c2af47e6 100644 Binary files a/16/MODEX16.ZIP and b/16/MODEX16.ZIP differ diff --git a/16/MODEX16_.ZIP b/16/MODEX16_.ZIP new file mode 100644 index 00000000..a1480fab Binary files /dev/null and b/16/MODEX16_.ZIP differ diff --git a/16/Project 16.bfproject b/16/Project 16.bfproject index 63ad23d1..791c2b5e 100644 --- a/16/Project 16.bfproject +++ b/16/Project 16.bfproject @@ -11,9 +11,11 @@ openfiles: /dos/z/16/16/project16.txt:8063:6091:0: 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 @@ -25,10 +27,10 @@ view_left_panel: 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 @@ -50,8 +52,6 @@ ssearch_regex: 0 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 @@ -82,26 +82,28 @@ recent_files: file:///dos/z/16/16/modex16/MODEX16.C 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: @@ -111,7 +113,6 @@ snr_escape_chars: 0 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 @@ -126,6 +127,7 @@ searchlist: vga searchlist: clock searchlist: setvideo searchlist: gq +searchlist: SC_INDEX autocomplete: 1 outputb_show_all_output: 0 bookmarks_show_mode: 0 diff --git a/16/modex16/286@12.LOG b/16/modex16/286@12.LOG index 34027049..8c4fd5ed 100644 --- a/16/modex16/286@12.LOG +++ b/16/modex16/286@12.LOG @@ -1,4 +1,2 @@ -Old non-sprite: 7.032967 -New non-sprite: 1.043956 -Old Sprite: 6.648352 -New Sprite: 1.648352 +CPU to VGA: 0.989011 +VGA to VGA: 0.274725 diff --git a/16/modex16/286@8.LOG b/16/modex16/286@8.LOG index a29ceffc..e6d68f42 100644 --- a/16/modex16/286@8.LOG +++ b/16/modex16/286@8.LOG @@ -1,4 +1,2 @@ -Old non-sprite: 10.439561 -New non-sprite: 1.373626 -Old Sprite: 9.945055 -New Sprite: 2.362637 +CPU to VGA: 1.373626 +VGA to VGA: 0.329670 diff --git a/16/modex16/MAKEFILE b/16/modex16/MAKEFILE index c48885b8..d0706af2 100644 --- a/16/modex16/MAKEFILE +++ b/16/modex16/MAKEFILE @@ -1,4 +1,4 @@ -FLAGS=-0 -d3 +FLAGS=-0 all: test.exe pcxtest.exe test2.exe test.exe: test.obj modex16.obj diff --git a/16/modex16/MODEX16.C b/16/modex16/MODEX16.C index f6ead33e..71537b66 100644 --- a/16/modex16/MODEX16.C +++ b/16/modex16/MODEX16.C @@ -92,32 +92,14 @@ modexEnter() { ptr[i] = 0x0000; } } - -int old_mode; - -///////////////////////////////////////////////////////////////////////////// -// // -// setvideo() - This function Manages the video modes // -// // -///////////////////////////////////////////////////////////////////////////// -void setvideo(/*byte mode, */short vq){ - union REGS in, out; - - if(!vq){ // deinit the video - // change to the video mode we were in before we switched to mode 13h - in.h.ah = 0x00; - in.h.al = old_mode; - int86(0x10, &in, &out); - - }else if(vq==1){ // init the video - // get old video mode - in.h.ah = 0xf; - int86(0x10, &in, &out); - old_mode = out.h.al; - // enter mode - modexEnter(); - } -} + + +void +modexLeave() { + /* TODO restore original mode and palette */ + vgaSetMode(TEXT_MODE); +} + page_t modexDefaultPage() { @@ -402,13 +384,76 @@ modexDrawSpriteRegion(page_t *page, int x, int y, } +/* copy a region of video memory from one page to another. + * It assumes that the left edge of the tile is the same on both + * regions and the memory areas do not overlap. + */ void -modexCopyPageRegion(page_t *dest, page_t src, +modexCopyPageRegion(page_t *dest, page_t *src, word sx, word sy, word dx, word dy, word width, word height) { - /* todo */ + word doffset = (word)dest->data + dy*(dest->width/4) + dx/4; + word soffset = (word)src->data + sy*(src->width/4) + sx/4; + word scans = width/4; + word nextSrcRow = src->width/4 - scans - 1; + word nextDestRow = dest->width/4 - scans - 1; + byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */ + byte rclip[] = {0x0f, 0x01, 0x03, 0x07}; + byte left = lclip[sx&0x03]; + byte right = rclip[(sx+width)&0x03]; + + __asm { + MOV AX, SCREEN_SEG ; work in the vga space + MOV ES, AX ; + MOV DI, doffset ; + MOV SI, soffset ; + + MOV DX, GC_INDEX ; turn off cpu bits + MOV AX, 0008h ; + OUT DX, AX + + MOV AX, SC_INDEX ; point to the mask register + MOV DX, AX ; + MOV AL, MAP_MASK ; + OUT DX, AL ; + INC DX ; + + ROW_START: + PUSH DS + MOV AX, ES + MOV DS, AX + MOV CX, scans ; the number of latches + + MOV AL, left ; do the left column + OUT DX, AL ; + MOVSB ; + DEC CX ; + + MOV AL, 0fh ; do the inner columns + OUT DX, AL + REP MOVSB ; copy the pixels + + MOV AL, right ; do the right column + OUT DX, AL + MOVSB + POP DS + + MOV AX, SI ; go the start of the next row + ADD AX, nextSrcRow ; + MOV SI, AX ; + MOV AX, DI ; + ADD AX, nextDestRow ; + MOV DI, AX ; + + DEC height ; do the rest of the actions + JNZ ROW_START ; + + MOV DX, GC_INDEX+1 ; go back to CPU data + MOV AL, 0ffh ; none from latches + OUT DX, AL ; + } } diff --git a/16/modex16/MODEX16.H b/16/modex16/MODEX16.H index cde4cd2f..08e7b360 100644 --- a/16/modex16/MODEX16.H +++ b/16/modex16/MODEX16.H @@ -4,8 +4,8 @@ #ifndef MODEX16_H #define MODEX16_H #include -#include "types.h" - +#include "types.h" + /* -========================== Types & Macros ==========================- */ #define PAGE_OFFSET(x,y) (((y)<<6)+((y)<<4)+((x)>>2)) #define PLANE(x) (1<< (x&3)) @@ -27,8 +27,8 @@ typedef struct { /* -============================ Functions =============================- */ /* mode switching, page, and plane functions */ -void modexEnter(); -void setvideo(/*byte mode, */short vq); +void modexEnter(); +void modexLeave(); page_t modexDefaultPage(); page_t modexNextPage(page_t *p); void modexShowPage(page_t *page); @@ -61,7 +61,7 @@ void modexPalUpdate(byte *p); void modexWaitBorder(); /* bitmap functions */ -bitmap_t modexLoadPcx(char *filename); +bitmap_t modexLoadPcx(char *filename); /* -======================= Constants & Vars ==========================- */ extern byte far* VGA; /* The VGA Memory */ @@ -79,6 +79,7 @@ extern byte far* VGA; /* The VGA Memory */ #define SC_DATA 0x03c5 #define CRTC_INDEX 0x03d4 #define CRTC_DATA 0x03d5 +#define GC_INDEX 0x03ce #define MISC_OUTPUT 0x03c2 #define HIGH_ADDRESS 0x0C #define LOW_ADDRESS 0x0D @@ -89,12 +90,5 @@ extern byte far* VGA; /* The VGA Memory */ #define PAL_READ_REG 0x03C7 /* Color register, read address */ #define PAL_WRITE_REG 0x03C8 /* Color register, write address */ #define PAL_DATA_REG 0x03C9 /* Color register, data port */ -#define PAL_SIZE (256 * 3) - -#define NUM_COLORS 256 // number of colors in vga mode -#define BONK 400 -#define LGQ 32 -#define HGQ 55 -#define TILEWH 16 -#define QUADWH TILEWH/2 +#define PAL_SIZE (256 * 3) #endif diff --git a/16/modex16/PCXTEST.C b/16/modex16/PCXTEST.C index 45f783c6..9cd1903d 100644 --- a/16/modex16/PCXTEST.C +++ b/16/modex16/PCXTEST.C @@ -26,14 +26,14 @@ oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite) { void main() { bitmap_t bmp; int i; - float t1, t2, t3, t4; - word start; page_t page; + word start; + float t1, t2; page=modexDefaultPage(); bmp = modexLoadPcx("ed.pcx"); - setvideo(1); + modexEnter(); /* fix up the palette and everything */ modexPalUpdate(bmp.palette); @@ -46,31 +46,33 @@ void main() { for(i=0; i<100 ;i++) { oldDrawBmp(VGA, 20, 20, &bmp, 0); } - t1 = (*clock-start) / 18.2; start = *clock; for(i=0; i<100 ;i++) { modexDrawBmp(&page, 20, 20, &bmp); } - t2 = (*clock-start) / 18.2; + t1 = (*clock-start) /18.2; + + start = *clock; + for(i=0; i<100; i++) { + modexCopyPageRegion(&page, &page, 20, 20, 128, 20, 64, 64); + } + t2 = (*clock-start)/18.2; + start = *clock; for(i=0; i<100 ;i++) { oldDrawBmp(VGA, 20, 20, &bmp, 1); } - t3 = (*clock-start) / 18.2; + start = *clock; for(i=0; i<100 ;i++) { modexDrawSprite(&page, 20, 20, &bmp); } - t4 = (*clock-start) / 18.2; - setvideo(0); - - printf("Old non-sprite: %f\n", t1); - printf("New non-sprite: %f\n", t2); - printf("Old Sprite: %f\n", t3); - printf("New Sprite: %f\n", t4); + modexLeave(); + printf("CPU to VGA: %f\n", t1); + printf("VGA to VGA: %f\n", t2); return; } diff --git a/16/modex16/PCXTEST.EXE b/16/modex16/PCXTEST.EXE index e10ce68d..4ab5474e 100644 Binary files a/16/modex16/PCXTEST.EXE and b/16/modex16/PCXTEST.EXE differ diff --git a/16/modex16/TEST.C b/16/modex16/TEST.C index 35909646..c5b9d7dc 100644 --- a/16/modex16/TEST.C +++ b/16/modex16/TEST.C @@ -3,17 +3,12 @@ word far* clock= (word far*) 0x046C; /* 18.2hz clock */ -void main() { - bitmap_t bmp; +void main() { int i, j; word start, end; page_t page, page2; - float elapsed; byte *pal, *pal2=NULL; - /* load pcx file */ - bmp = modexLoadPcx("ed.pcx"); - /* load our palette */ modexLoadPalFile("gfx.pal", &pal2); @@ -23,7 +18,7 @@ void main() { modexFadeOff(1, pal); modexPalBlack(); - setvideo(1); + modexEnter(); modexPalBlack(); /* set up the page, but with 16 pixels on all borders in offscreen mem */ @@ -40,16 +35,12 @@ void main() { modexClearRegion(&page, 48, 48, SCREEN_WIDTH-64, SCREEN_HEIGHT-64, 128); modexShowPage(&page); - modexDrawSprite(&page, 20, 20, &bmp); - //modexDrawBmp(&page, xb, yb, &bmp); - /* fade in */ modexFadeOn(1, pal2); start = *clock; - //for(i=0; i<5; i++) { - while (!kbhit()){ /* Wait for a keystroke */ + for(i=0; i<5; i++) { /* go right */ for(j=0; j<32; j++) { page.dx++; @@ -73,13 +64,12 @@ void main() { } } - (void) getch(); /* Clear the keyboard buffer */ end = *clock; /* fade back to text mode */ modexFadeOff(1, pal2); modexPalBlack(); - setvideo(0); + modexLeave(); modexPalBlack(); modexFadeOn(1, pal); } diff --git a/16/modex16/TEST.EXE b/16/modex16/TEST.EXE index d19c48e9..b0247b18 100644 Binary files a/16/modex16/TEST.EXE and b/16/modex16/TEST.EXE differ diff --git a/16/modex16/TEST2.EXE b/16/modex16/TEST2.EXE index 57c13a9e..23ca0df0 100644 Binary files a/16/modex16/TEST2.EXE and b/16/modex16/TEST2.EXE differ diff --git a/16/modex16/makefile b/16/modex16/makefile index c48885b8..d0706af2 100644 --- a/16/modex16/makefile +++ b/16/modex16/makefile @@ -1,4 +1,4 @@ -FLAGS=-0 -d3 +FLAGS=-0 all: test.exe pcxtest.exe test2.exe test.exe: test.obj modex16.obj diff --git a/16/modex16/modex16.c b/16/modex16/modex16.c new file mode 100644 index 00000000..71537b66 --- /dev/null +++ b/16/modex16/modex16.c @@ -0,0 +1,704 @@ +#include +#include +#include +#include +#include +#include +#include "modex16.h" + + +byte far* VGA=(byte far*) 0xA0000000; /* this points to video memory. */ + +static void fadePalette(sbyte fade, sbyte start, word iter, byte *palette); +static byte tmppal[PAL_SIZE]; +static struct pcxHeader { + byte id; + byte version; + byte encoding; + byte bpp; + word xmin; + word ymin; + word xmax; + word ymax; + word hres; + word vres; + byte pal16[48]; + byte res1; + word bpplane; + word palType; + word hScreenSize; + word vScreenSize; + byte padding[54]; +}; + + +static void +vgaSetMode(byte mode) +{ + union REGS regs; + + regs.h.ah = SET_MODE; + regs.h.al = mode; + int86(VIDEO_INT, ®s, ®s); +} + + +/* -========================= Entry Points ==========================- */ +void +modexEnter() { + word i; + dword far*ptr=(dword far*)VGA; /* used for faster screen clearing */ + word CRTParms[] = { + 0x0d06, /* vertical total */ + 0x3e07, /* overflow (bit 8 of vertical counts) */ + 0x4109, /* cell height (2 to double-scan */ + 0xea10, /* v sync start */ + 0xac11, /* v sync end and protect cr0-cr7 */ + 0xdf12, /* vertical displayed */ + 0x0014, /* turn off dword mode */ + 0xe715, /* v blank start */ + 0x0616, /* v blank end */ + 0xe317 /* turn on byte mode */ + }; + int CRTParmCount = sizeof(CRTParms) / sizeof(CRTParms[0]); + + /* TODO save current video mode and palette */ + vgaSetMode(VGA_256_COLOR_MODE); + + /* disable chain4 mode */ + outpw(SC_INDEX, 0x0604); + + /* synchronous reset while setting Misc Output */ + outpw(SC_INDEX, 0x0100); + + /* select 25 MHz dot clock & 60 Hz scanning rate */ + outp(MISC_OUTPUT, 0xe3); + + /* undo reset (restart sequencer) */ + outpw(SC_INDEX, 0x0300); + + /* reprogram the CRT controller */ + outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */ + outp(CRTC_DATA, 0x7f); /* get current write protect on varios regs */ + + /* send the CRTParms */ + for(i=0; idata + (p->width/4)*p->height; /* compute the offset */ + result.dx = 0; + result.dy = 0; + result.width = p->width; + result.height = p->height; + + return result; +} + + +void +modexShowPage(page_t *page) { + word high_address; + word low_address; + word offset; + byte crtcOffset; + + /* calculate offset */ + offset = (word) page->data; + offset += page->dy * (page->width >> 2 ); + offset += page->dx >> 2; + + /* calculate crtcOffset according to virtual width */ + crtcOffset = page->width >> 3; + + high_address = HIGH_ADDRESS | (offset & 0xff00); + low_address = LOW_ADDRESS | (offset << 8); + + /* wait for appropriate timing and then program CRTC */ + while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE)); + outpw(CRTC_INDEX, high_address); + outpw(CRTC_INDEX, low_address); + outp(CRTC_INDEX, 0x13); + outp(CRTC_DATA, crtcOffset); + + /* wait for one retrace */ + while (!(inp(INPUT_STATUS_1) & VRETRACE)); + + /* do PEL panning here */ + outp(AC_INDEX, 0x33); + outp(AC_INDEX, (page->dx & 0x03) << 1); +} + + +void +modexPanPage(page_t *page, int dx, int dy) { + page->dx = dx; + page->dy = dy; +} + + +void +modexSelectPlane(byte plane) { + outp(SC_INDEX, MAP_MASK); /* select plane */ + outp(SC_DATA, plane); +} + + +void +modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) { + word pageOff = (word) page->data; + word xoff=x/4; /* xoffset that begins each row */ + word scanCount=w/4; /* number of iterations per row (excluding right clip)*/ + word poffset = pageOff + y*(page->width/4) + xoff; /* starting offset */ + word nextRow = page->width/4-scanCount-1; /* loc of next row */ + byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */ + byte rclip[] = {0x00, 0x01, 0x03, 0x07}; + byte left = lclip[x&0x03]; + byte right = rclip[(x+w)&0x03]; + + /* handle the case which requires an extra group */ + if((x & 0x03) && !((x+w) & 0x03)) { + right=0x0f; + } + + __asm { + MOV AX, SCREEN_SEG ; go to the VGA memory + MOV ES, AX + MOV DI, poffset ; go to the first pixel + MOV DX, SC_INDEX ; point to the map mask + MOV AL, MAP_MASK + OUT DX, AL + INC DX + MOV AL, color ; get ready to write colors + SCAN_START: + MOV CX, scanCount ; count the line + MOV BL, AL ; remember color + MOV AL, left ; do the left clip + OUT DX, AL ; set the left clip + MOV AL, BL ; restore color + STOSB ; write the color + DEC CX + JZ SCAN_DONE ; handle 1 group stuff + + ;-- write the main body of the scanline + MOV BL, AL ; remember color + MOV AL, 0x0f ; write to all pixels + OUT DX, AL + MOV AL, BL ; restore color + REP STOSB ; write the color + SCAN_DONE: + MOV BL, AL ; remeber color + MOV AL, right + OUT DX, AL ; do the right clip + MOV AL, BL ; restore color + STOSB ; write pixel + ADD DI, nextRow ; go to the next row + DEC h + JNZ SCAN_START + } +} + + +void +modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) { + /* draw the region (the entire freakin bitmap) */ + modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp); +} + + +void +modexDrawBmpRegion(page_t *page, int x, int y, + int rx, int ry, int rw, int rh, bitmap_t *bmp) { + word poffset = (word) page->data + y*(page->width/4) + x/4; + byte *data = bmp->data; + word bmpOffset = (word) data + ry * bmp->width + rx; + word width = rw; + word height = rh; + byte plane = 1 << ((byte) x & 0x03); + word scanCount = width/4 + (width%4 ? 1 :0); + word nextPageRow = page->width/4 - scanCount; + word nextBmpRow = (word) bmp->width - width; + word rowCounter; + byte planeCounter = 4; + + __asm { + MOV AX, SCREEN_SEG ; go to the VGA memory + MOV ES, AX + + MOV DX, SC_INDEX ; point at the map mask register + MOV AL, MAP_MASK ; + OUT DX, AL ; + + PLANE_LOOP: + MOV DX, SC_DATA ; select the current plane + MOV AL, plane ; + OUT DX, AL ; + + ;-- begin plane painting + MOV AX, height ; start the row counter + MOV rowCounter, AX ; + MOV DI, poffset ; go to the first pixel + MOV SI, bmpOffset ; go to the bmp pixel + ROW_LOOP: + MOV CX, width ; count the columns + SCAN_LOOP: + MOVSB ; copy the pixel + SUB CX, 3 ; we skip the next 3 + ADD SI, 3 ; skip the bmp pixels + LOOP SCAN_LOOP ; finish the scan + + MOV AX, nextPageRow + ADD DI, AX ; go to the next row on screen + MOV AX, nextBmpRow + ADD SI, AX ; go to the next row on bmp + + DEC rowCounter + JNZ ROW_LOOP ; do all the rows + ;-- end plane painting + + MOV AL, plane ; advance to the next plane + SHL AL, 1 ; + AND AL, 0x0f ; mask the plane properly + MOV plane, AL ; store the plane + + INC bmpOffset ; start bmp at the right spot + + DEC planeCounter + JNZ PLANE_LOOP ; do all 4 planes + } +} + + +void +modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) { + /* draw the whole sprite */ + modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp); +} + +void +modexDrawSpriteRegion(page_t *page, int x, int y, + int rx, int ry, int rw, int rh, bitmap_t *bmp) { + word poffset = (word)page->data + y*(page->width/4) + x/4; + byte *data = bmp->data; + word bmpOffset = (word) data + ry * bmp->width + rx; + word width = rw; + word height = rh; + byte plane = 1 << ((byte) x & 0x03); + word scanCount = width/4 + (width%4 ? 1 :0); + word nextPageRow = page->width/4 - scanCount; + word nextBmpRow = (word) bmp->width - width; + word rowCounter; + byte planeCounter = 4; + + __asm { + MOV AX, SCREEN_SEG ; go to the VGA memory + MOV ES, AX + + MOV DX, SC_INDEX ; point at the map mask register + MOV AL, MAP_MASK ; + OUT DX, AL ; + + PLANE_LOOP: + MOV DX, SC_DATA ; select the current plane + MOV AL, plane ; + OUT DX, AL ; + + ;-- begin plane painting + MOV AX, height ; start the row counter + MOV rowCounter, AX ; + MOV DI, poffset ; go to the first pixel + MOV SI, bmpOffset ; go to the bmp pixel + ROW_LOOP: + MOV CX, width ; count the columns + SCAN_LOOP: + LODSB + DEC SI + CMP AL, 0 + JNE DRAW_PIXEL ; draw non-zero pixels + + INC DI ; skip the transparent pixel + ADD SI, 1 + JMP NEXT_PIXEL + DRAW_PIXEL: + MOVSB ; copy the pixel + NEXT_PIXEL: + SUB CX, 3 ; we skip the next 3 + ADD SI, 3 ; skip the bmp pixels + LOOP SCAN_LOOP ; finish the scan + + MOV AX, nextPageRow + ADD DI, AX ; go to the next row on screen + MOV AX, nextBmpRow + ADD SI, AX ; go to the next row on bmp + + DEC rowCounter + JNZ ROW_LOOP ; do all the rows + ;-- end plane painting + + MOV AL, plane ; advance to the next plane + SHL AL, 1 ; + AND AL, 0x0f ; mask the plane properly + MOV plane, AL ; store the plane + + INC bmpOffset ; start bmp at the right spot + + DEC planeCounter + JNZ PLANE_LOOP ; do all 4 planes + } +} + + +/* copy a region of video memory from one page to another. + * It assumes that the left edge of the tile is the same on both + * regions and the memory areas do not overlap. + */ +void +modexCopyPageRegion(page_t *dest, page_t *src, + word sx, word sy, + word dx, word dy, + word width, word height) +{ + word doffset = (word)dest->data + dy*(dest->width/4) + dx/4; + word soffset = (word)src->data + sy*(src->width/4) + sx/4; + word scans = width/4; + word nextSrcRow = src->width/4 - scans - 1; + word nextDestRow = dest->width/4 - scans - 1; + byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */ + byte rclip[] = {0x0f, 0x01, 0x03, 0x07}; + byte left = lclip[sx&0x03]; + byte right = rclip[(sx+width)&0x03]; + + __asm { + MOV AX, SCREEN_SEG ; work in the vga space + MOV ES, AX ; + MOV DI, doffset ; + MOV SI, soffset ; + + MOV DX, GC_INDEX ; turn off cpu bits + MOV AX, 0008h ; + OUT DX, AX + + MOV AX, SC_INDEX ; point to the mask register + MOV DX, AX ; + MOV AL, MAP_MASK ; + OUT DX, AL ; + INC DX ; + + ROW_START: + PUSH DS + MOV AX, ES + MOV DS, AX + MOV CX, scans ; the number of latches + + MOV AL, left ; do the left column + OUT DX, AL ; + MOVSB ; + DEC CX ; + + MOV AL, 0fh ; do the inner columns + OUT DX, AL + REP MOVSB ; copy the pixels + + MOV AL, right ; do the right column + OUT DX, AL + MOVSB + POP DS + + MOV AX, SI ; go the start of the next row + ADD AX, nextSrcRow ; + MOV SI, AX ; + MOV AX, DI ; + ADD AX, nextDestRow ; + MOV DI, AX ; + + DEC height ; do the rest of the actions + JNZ ROW_START ; + + MOV DX, GC_INDEX+1 ; go back to CPU data + MOV AL, 0ffh ; none from latches + OUT DX, AL ; + } +} + + +/* fade and flash */ +void +modexFadeOn(word fade, byte *palette) { + fadePalette(-fade, 64, 64/fade+1, palette); +} + + +void +modexFadeOff(word fade, byte *palette) { + fadePalette(fade, 0, 64/fade+1, palette); +} + + +void +modexFlashOn(word fade, byte *palette) { + fadePalette(fade, -64, 64/fade+1, palette); +} + + +void +modexFlashOff(word fade, byte *palette) { + fadePalette(-fade, 0, 64/fade+1, palette); +} + + +static void +fadePalette(sbyte fade, sbyte start, word iter, byte *palette) { + word i; + byte dim = start; + + /* handle the case where we just update */ + if(iter == 0) { + modexPalUpdate(palette); + return; + } + + while(iter > 0) { /* FadeLoop */ + for(i=0; i 127) { + tmppal[i] = 0; + } else if(tmppal[i] > 63) { + tmppal[i] = 63; + } + } + modexPalUpdate(tmppal); + iter--; + dim += fade; + } +} + + +/* save and load */ +void +modexPalSave(byte *palette) { + int i; + + outp(PAL_READ_REG, 0); /* start at palette entry 0 */ + for(i=0; i> 2; + } + } else { + /* use the 16 color palette */ + for(index=0; index<48; index++) { + result.palette[index] = head.pal16[index]; + } + } + + fclose(file); + + return result; +} diff --git a/16/modex16/modex16.h b/16/modex16/modex16.h new file mode 100644 index 00000000..08e7b360 --- /dev/null +++ b/16/modex16/modex16.h @@ -0,0 +1,94 @@ +/* + * Functions for handling modex and doing other basic graphics stuff. + */ +#ifndef MODEX16_H +#define MODEX16_H +#include +#include "types.h" + +/* -========================== Types & Macros ==========================- */ +#define PAGE_OFFSET(x,y) (((y)<<6)+((y)<<4)+((x)>>2)) +#define PLANE(x) (1<< (x&3)) +#define SELECT_ALL_PLANES() outpw(0x03c4, 0xff02) +typedef struct { + byte *data; + word width; + word height; + byte *palette; +} bitmap_t; + +typedef struct { + byte far* data; /* the data for the page */ + word dx; /* col we are viewing on the virtual screen */ + word dy; /* row we are viewing on the virtual screen */ + word width; /* virtual width of the page */ + word height; /* virtual height of the page */ +} page_t; + +/* -============================ Functions =============================- */ +/* mode switching, page, and plane functions */ +void modexEnter(); +void modexLeave(); +page_t modexDefaultPage(); +page_t modexNextPage(page_t *p); +void modexShowPage(page_t *page); +void modexPanPage(page_t *page, int dx, int dy); +void modexSelectPlane(byte plane); +void modexClearRegion(page_t *page, int x, int y, int w, int h, byte color); +void modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp); +void modexDrawBmpRegion(page_t *page, int x, int y, int rx, int ry, int rw, int rh, bitmap_t *bmp); +void modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp); +void modexDrawSpriteRegion(page_t *page, int x, int y, int rx, int ry, int rw, int rh, bitmap_t *bmp); + +/* Palette fade and flash effects */ +void modexFadeOn(word fade, byte *palette); +void modexFadeOff(word fade, byte *palette); +void modexFlashOn(word fade, byte *palette); +void modexFlashOff(word fade, byte *palette); + +/* palette loading and saving */ +void modexPalSave(byte *palette); +byte *modexNewPal(); +void modexLoadPalFile(char *filename, byte **palette); +void modexSavePalFile(char *filename, byte *palette); + +/* fixed palette functions */ +void modexPalBlack(); +void modexPalWhite(); + +/* utility functions */ +void modexPalUpdate(byte *p); +void modexWaitBorder(); + +/* bitmap functions */ +bitmap_t modexLoadPcx(char *filename); + +/* -======================= Constants & Vars ==========================- */ +extern byte far* VGA; /* The VGA Memory */ +#define SCREEN_SEG 0xa000 +#define VIDEO_INT 0x10 +#define SET_MODE 0x00 +#define VGA_256_COLOR_MODE 0x13 +#define TEXT_MODE 0x03 +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 240 +#define PAGE_SIZE (word)(SCREEN_WIDTH/4 * SCREEN_HEIGHT) + +#define AC_INDEX 0x03c0 +#define SC_INDEX 0x03c4 +#define SC_DATA 0x03c5 +#define CRTC_INDEX 0x03d4 +#define CRTC_DATA 0x03d5 +#define GC_INDEX 0x03ce +#define MISC_OUTPUT 0x03c2 +#define HIGH_ADDRESS 0x0C +#define LOW_ADDRESS 0x0D +#define VRETRACE 0x08 +#define INPUT_STATUS_1 0x03da +#define DISPLAY_ENABLE 0x01 +#define MAP_MASK 0x02 +#define PAL_READ_REG 0x03C7 /* Color register, read address */ +#define PAL_WRITE_REG 0x03C8 /* Color register, write address */ +#define PAL_DATA_REG 0x03C9 /* Color register, data port */ +#define PAL_SIZE (256 * 3) +#endif diff --git a/16/modex16/pcxtest.c b/16/modex16/pcxtest.c index 45f783c6..9cd1903d 100644 --- a/16/modex16/pcxtest.c +++ b/16/modex16/pcxtest.c @@ -26,14 +26,14 @@ oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite) { void main() { bitmap_t bmp; int i; - float t1, t2, t3, t4; - word start; page_t page; + word start; + float t1, t2; page=modexDefaultPage(); bmp = modexLoadPcx("ed.pcx"); - setvideo(1); + modexEnter(); /* fix up the palette and everything */ modexPalUpdate(bmp.palette); @@ -46,31 +46,33 @@ void main() { for(i=0; i<100 ;i++) { oldDrawBmp(VGA, 20, 20, &bmp, 0); } - t1 = (*clock-start) / 18.2; start = *clock; for(i=0; i<100 ;i++) { modexDrawBmp(&page, 20, 20, &bmp); } - t2 = (*clock-start) / 18.2; + t1 = (*clock-start) /18.2; + + start = *clock; + for(i=0; i<100; i++) { + modexCopyPageRegion(&page, &page, 20, 20, 128, 20, 64, 64); + } + t2 = (*clock-start)/18.2; + start = *clock; for(i=0; i<100 ;i++) { oldDrawBmp(VGA, 20, 20, &bmp, 1); } - t3 = (*clock-start) / 18.2; + start = *clock; for(i=0; i<100 ;i++) { modexDrawSprite(&page, 20, 20, &bmp); } - t4 = (*clock-start) / 18.2; - setvideo(0); - - printf("Old non-sprite: %f\n", t1); - printf("New non-sprite: %f\n", t2); - printf("Old Sprite: %f\n", t3); - printf("New Sprite: %f\n", t4); + modexLeave(); + printf("CPU to VGA: %f\n", t1); + printf("VGA to VGA: %f\n", t2); return; } diff --git a/16/modex16/pcxtest.exe b/16/modex16/pcxtest.exe new file mode 100644 index 00000000..4ab5474e Binary files /dev/null and b/16/modex16/pcxtest.exe differ diff --git a/16/modex16/test.c b/16/modex16/test.c index 35909646..c5b9d7dc 100644 --- a/16/modex16/test.c +++ b/16/modex16/test.c @@ -3,17 +3,12 @@ word far* clock= (word far*) 0x046C; /* 18.2hz clock */ -void main() { - bitmap_t bmp; +void main() { int i, j; word start, end; page_t page, page2; - float elapsed; byte *pal, *pal2=NULL; - /* load pcx file */ - bmp = modexLoadPcx("ed.pcx"); - /* load our palette */ modexLoadPalFile("gfx.pal", &pal2); @@ -23,7 +18,7 @@ void main() { modexFadeOff(1, pal); modexPalBlack(); - setvideo(1); + modexEnter(); modexPalBlack(); /* set up the page, but with 16 pixels on all borders in offscreen mem */ @@ -40,16 +35,12 @@ void main() { modexClearRegion(&page, 48, 48, SCREEN_WIDTH-64, SCREEN_HEIGHT-64, 128); modexShowPage(&page); - modexDrawSprite(&page, 20, 20, &bmp); - //modexDrawBmp(&page, xb, yb, &bmp); - /* fade in */ modexFadeOn(1, pal2); start = *clock; - //for(i=0; i<5; i++) { - while (!kbhit()){ /* Wait for a keystroke */ + for(i=0; i<5; i++) { /* go right */ for(j=0; j<32; j++) { page.dx++; @@ -73,13 +64,12 @@ void main() { } } - (void) getch(); /* Clear the keyboard buffer */ end = *clock; /* fade back to text mode */ modexFadeOff(1, pal2); modexPalBlack(); - setvideo(0); + modexLeave(); modexPalBlack(); modexFadeOn(1, pal); } diff --git a/16/modex16/test.exe b/16/modex16/test.exe new file mode 100644 index 00000000..b0247b18 Binary files /dev/null and b/16/modex16/test.exe differ diff --git a/16/modex16/test2.c b/16/modex16/test2.c index a3669980..9118279f 100644 --- a/16/modex16/test2.c +++ b/16/modex16/test2.c @@ -5,18 +5,15 @@ word far* clock= (word far*) 0x046C; /* 18.2hz clock */ void main() { int i; word start; - float t1, t2; page_t page; page=modexDefaultPage(); - setvideo(1); + modexEnter(); start = *clock; for(i=0; i<500; i++) { modexShowPage(&page); } - t1 = (*clock - start)/18.2; - setvideo(0); + modexLeave(); - printf("Time: %f\n", t1); } diff --git a/16/modex16/test2.exe b/16/modex16/test2.exe new file mode 100644 index 00000000..23ca0df0 Binary files /dev/null and b/16/modex16/test2.exe differ diff --git a/16/modex16_/286@12.LOG b/16/modex16_/286@12.LOG new file mode 100644 index 00000000..34027049 --- /dev/null +++ b/16/modex16_/286@12.LOG @@ -0,0 +1,4 @@ +Old non-sprite: 7.032967 +New non-sprite: 1.043956 +Old Sprite: 6.648352 +New Sprite: 1.648352 diff --git a/16/modex16_/286@8.LOG b/16/modex16_/286@8.LOG new file mode 100644 index 00000000..a29ceffc --- /dev/null +++ b/16/modex16_/286@8.LOG @@ -0,0 +1,4 @@ +Old non-sprite: 10.439561 +New non-sprite: 1.373626 +Old Sprite: 9.945055 +New Sprite: 2.362637 diff --git a/16/modex16/COMPUTER.PCX b/16/modex16_/COMPUTER.PCX similarity index 100% rename from 16/modex16/COMPUTER.PCX rename to 16/modex16_/COMPUTER.PCX diff --git a/16/modex16/EDw.PCX b/16/modex16_/EDw.PCX similarity index 100% rename from 16/modex16/EDw.PCX rename to 16/modex16_/EDw.PCX diff --git a/16/modex16_/MODEX16.C b/16/modex16_/MODEX16.C new file mode 100644 index 00000000..f6ead33e --- /dev/null +++ b/16/modex16_/MODEX16.C @@ -0,0 +1,659 @@ +#include +#include +#include +#include +#include +#include +#include "modex16.h" + + +byte far* VGA=(byte far*) 0xA0000000; /* this points to video memory. */ + +static void fadePalette(sbyte fade, sbyte start, word iter, byte *palette); +static byte tmppal[PAL_SIZE]; +static struct pcxHeader { + byte id; + byte version; + byte encoding; + byte bpp; + word xmin; + word ymin; + word xmax; + word ymax; + word hres; + word vres; + byte pal16[48]; + byte res1; + word bpplane; + word palType; + word hScreenSize; + word vScreenSize; + byte padding[54]; +}; + + +static void +vgaSetMode(byte mode) +{ + union REGS regs; + + regs.h.ah = SET_MODE; + regs.h.al = mode; + int86(VIDEO_INT, ®s, ®s); +} + + +/* -========================= Entry Points ==========================- */ +void +modexEnter() { + word i; + dword far*ptr=(dword far*)VGA; /* used for faster screen clearing */ + word CRTParms[] = { + 0x0d06, /* vertical total */ + 0x3e07, /* overflow (bit 8 of vertical counts) */ + 0x4109, /* cell height (2 to double-scan */ + 0xea10, /* v sync start */ + 0xac11, /* v sync end and protect cr0-cr7 */ + 0xdf12, /* vertical displayed */ + 0x0014, /* turn off dword mode */ + 0xe715, /* v blank start */ + 0x0616, /* v blank end */ + 0xe317 /* turn on byte mode */ + }; + int CRTParmCount = sizeof(CRTParms) / sizeof(CRTParms[0]); + + /* TODO save current video mode and palette */ + vgaSetMode(VGA_256_COLOR_MODE); + + /* disable chain4 mode */ + outpw(SC_INDEX, 0x0604); + + /* synchronous reset while setting Misc Output */ + outpw(SC_INDEX, 0x0100); + + /* select 25 MHz dot clock & 60 Hz scanning rate */ + outp(MISC_OUTPUT, 0xe3); + + /* undo reset (restart sequencer) */ + outpw(SC_INDEX, 0x0300); + + /* reprogram the CRT controller */ + outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */ + outp(CRTC_DATA, 0x7f); /* get current write protect on varios regs */ + + /* send the CRTParms */ + for(i=0; idata + (p->width/4)*p->height; /* compute the offset */ + result.dx = 0; + result.dy = 0; + result.width = p->width; + result.height = p->height; + + return result; +} + + +void +modexShowPage(page_t *page) { + word high_address; + word low_address; + word offset; + byte crtcOffset; + + /* calculate offset */ + offset = (word) page->data; + offset += page->dy * (page->width >> 2 ); + offset += page->dx >> 2; + + /* calculate crtcOffset according to virtual width */ + crtcOffset = page->width >> 3; + + high_address = HIGH_ADDRESS | (offset & 0xff00); + low_address = LOW_ADDRESS | (offset << 8); + + /* wait for appropriate timing and then program CRTC */ + while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE)); + outpw(CRTC_INDEX, high_address); + outpw(CRTC_INDEX, low_address); + outp(CRTC_INDEX, 0x13); + outp(CRTC_DATA, crtcOffset); + + /* wait for one retrace */ + while (!(inp(INPUT_STATUS_1) & VRETRACE)); + + /* do PEL panning here */ + outp(AC_INDEX, 0x33); + outp(AC_INDEX, (page->dx & 0x03) << 1); +} + + +void +modexPanPage(page_t *page, int dx, int dy) { + page->dx = dx; + page->dy = dy; +} + + +void +modexSelectPlane(byte plane) { + outp(SC_INDEX, MAP_MASK); /* select plane */ + outp(SC_DATA, plane); +} + + +void +modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) { + word pageOff = (word) page->data; + word xoff=x/4; /* xoffset that begins each row */ + word scanCount=w/4; /* number of iterations per row (excluding right clip)*/ + word poffset = pageOff + y*(page->width/4) + xoff; /* starting offset */ + word nextRow = page->width/4-scanCount-1; /* loc of next row */ + byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */ + byte rclip[] = {0x00, 0x01, 0x03, 0x07}; + byte left = lclip[x&0x03]; + byte right = rclip[(x+w)&0x03]; + + /* handle the case which requires an extra group */ + if((x & 0x03) && !((x+w) & 0x03)) { + right=0x0f; + } + + __asm { + MOV AX, SCREEN_SEG ; go to the VGA memory + MOV ES, AX + MOV DI, poffset ; go to the first pixel + MOV DX, SC_INDEX ; point to the map mask + MOV AL, MAP_MASK + OUT DX, AL + INC DX + MOV AL, color ; get ready to write colors + SCAN_START: + MOV CX, scanCount ; count the line + MOV BL, AL ; remember color + MOV AL, left ; do the left clip + OUT DX, AL ; set the left clip + MOV AL, BL ; restore color + STOSB ; write the color + DEC CX + JZ SCAN_DONE ; handle 1 group stuff + + ;-- write the main body of the scanline + MOV BL, AL ; remember color + MOV AL, 0x0f ; write to all pixels + OUT DX, AL + MOV AL, BL ; restore color + REP STOSB ; write the color + SCAN_DONE: + MOV BL, AL ; remeber color + MOV AL, right + OUT DX, AL ; do the right clip + MOV AL, BL ; restore color + STOSB ; write pixel + ADD DI, nextRow ; go to the next row + DEC h + JNZ SCAN_START + } +} + + +void +modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) { + /* draw the region (the entire freakin bitmap) */ + modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp); +} + + +void +modexDrawBmpRegion(page_t *page, int x, int y, + int rx, int ry, int rw, int rh, bitmap_t *bmp) { + word poffset = (word) page->data + y*(page->width/4) + x/4; + byte *data = bmp->data; + word bmpOffset = (word) data + ry * bmp->width + rx; + word width = rw; + word height = rh; + byte plane = 1 << ((byte) x & 0x03); + word scanCount = width/4 + (width%4 ? 1 :0); + word nextPageRow = page->width/4 - scanCount; + word nextBmpRow = (word) bmp->width - width; + word rowCounter; + byte planeCounter = 4; + + __asm { + MOV AX, SCREEN_SEG ; go to the VGA memory + MOV ES, AX + + MOV DX, SC_INDEX ; point at the map mask register + MOV AL, MAP_MASK ; + OUT DX, AL ; + + PLANE_LOOP: + MOV DX, SC_DATA ; select the current plane + MOV AL, plane ; + OUT DX, AL ; + + ;-- begin plane painting + MOV AX, height ; start the row counter + MOV rowCounter, AX ; + MOV DI, poffset ; go to the first pixel + MOV SI, bmpOffset ; go to the bmp pixel + ROW_LOOP: + MOV CX, width ; count the columns + SCAN_LOOP: + MOVSB ; copy the pixel + SUB CX, 3 ; we skip the next 3 + ADD SI, 3 ; skip the bmp pixels + LOOP SCAN_LOOP ; finish the scan + + MOV AX, nextPageRow + ADD DI, AX ; go to the next row on screen + MOV AX, nextBmpRow + ADD SI, AX ; go to the next row on bmp + + DEC rowCounter + JNZ ROW_LOOP ; do all the rows + ;-- end plane painting + + MOV AL, plane ; advance to the next plane + SHL AL, 1 ; + AND AL, 0x0f ; mask the plane properly + MOV plane, AL ; store the plane + + INC bmpOffset ; start bmp at the right spot + + DEC planeCounter + JNZ PLANE_LOOP ; do all 4 planes + } +} + + +void +modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) { + /* draw the whole sprite */ + modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp); +} + +void +modexDrawSpriteRegion(page_t *page, int x, int y, + int rx, int ry, int rw, int rh, bitmap_t *bmp) { + word poffset = (word)page->data + y*(page->width/4) + x/4; + byte *data = bmp->data; + word bmpOffset = (word) data + ry * bmp->width + rx; + word width = rw; + word height = rh; + byte plane = 1 << ((byte) x & 0x03); + word scanCount = width/4 + (width%4 ? 1 :0); + word nextPageRow = page->width/4 - scanCount; + word nextBmpRow = (word) bmp->width - width; + word rowCounter; + byte planeCounter = 4; + + __asm { + MOV AX, SCREEN_SEG ; go to the VGA memory + MOV ES, AX + + MOV DX, SC_INDEX ; point at the map mask register + MOV AL, MAP_MASK ; + OUT DX, AL ; + + PLANE_LOOP: + MOV DX, SC_DATA ; select the current plane + MOV AL, plane ; + OUT DX, AL ; + + ;-- begin plane painting + MOV AX, height ; start the row counter + MOV rowCounter, AX ; + MOV DI, poffset ; go to the first pixel + MOV SI, bmpOffset ; go to the bmp pixel + ROW_LOOP: + MOV CX, width ; count the columns + SCAN_LOOP: + LODSB + DEC SI + CMP AL, 0 + JNE DRAW_PIXEL ; draw non-zero pixels + + INC DI ; skip the transparent pixel + ADD SI, 1 + JMP NEXT_PIXEL + DRAW_PIXEL: + MOVSB ; copy the pixel + NEXT_PIXEL: + SUB CX, 3 ; we skip the next 3 + ADD SI, 3 ; skip the bmp pixels + LOOP SCAN_LOOP ; finish the scan + + MOV AX, nextPageRow + ADD DI, AX ; go to the next row on screen + MOV AX, nextBmpRow + ADD SI, AX ; go to the next row on bmp + + DEC rowCounter + JNZ ROW_LOOP ; do all the rows + ;-- end plane painting + + MOV AL, plane ; advance to the next plane + SHL AL, 1 ; + AND AL, 0x0f ; mask the plane properly + MOV plane, AL ; store the plane + + INC bmpOffset ; start bmp at the right spot + + DEC planeCounter + JNZ PLANE_LOOP ; do all 4 planes + } +} + + +void +modexCopyPageRegion(page_t *dest, page_t src, + word sx, word sy, + word dx, word dy, + word width, word height) +{ + /* todo */ +} + + +/* fade and flash */ +void +modexFadeOn(word fade, byte *palette) { + fadePalette(-fade, 64, 64/fade+1, palette); +} + + +void +modexFadeOff(word fade, byte *palette) { + fadePalette(fade, 0, 64/fade+1, palette); +} + + +void +modexFlashOn(word fade, byte *palette) { + fadePalette(fade, -64, 64/fade+1, palette); +} + + +void +modexFlashOff(word fade, byte *palette) { + fadePalette(-fade, 0, 64/fade+1, palette); +} + + +static void +fadePalette(sbyte fade, sbyte start, word iter, byte *palette) { + word i; + byte dim = start; + + /* handle the case where we just update */ + if(iter == 0) { + modexPalUpdate(palette); + return; + } + + while(iter > 0) { /* FadeLoop */ + for(i=0; i 127) { + tmppal[i] = 0; + } else if(tmppal[i] > 63) { + tmppal[i] = 63; + } + } + modexPalUpdate(tmppal); + iter--; + dim += fade; + } +} + + +/* save and load */ +void +modexPalSave(byte *palette) { + int i; + + outp(PAL_READ_REG, 0); /* start at palette entry 0 */ + for(i=0; i> 2; + } + } else { + /* use the 16 color palette */ + for(index=0; index<48; index++) { + result.palette[index] = head.pal16[index]; + } + } + + fclose(file); + + return result; +} diff --git a/16/modex16_/MODEX16.H b/16/modex16_/MODEX16.H new file mode 100644 index 00000000..cde4cd2f --- /dev/null +++ b/16/modex16_/MODEX16.H @@ -0,0 +1,100 @@ +/* + * Functions for handling modex and doing other basic graphics stuff. + */ +#ifndef MODEX16_H +#define MODEX16_H +#include +#include "types.h" + +/* -========================== Types & Macros ==========================- */ +#define PAGE_OFFSET(x,y) (((y)<<6)+((y)<<4)+((x)>>2)) +#define PLANE(x) (1<< (x&3)) +#define SELECT_ALL_PLANES() outpw(0x03c4, 0xff02) +typedef struct { + byte *data; + word width; + word height; + byte *palette; +} bitmap_t; + +typedef struct { + byte far* data; /* the data for the page */ + word dx; /* col we are viewing on the virtual screen */ + word dy; /* row we are viewing on the virtual screen */ + word width; /* virtual width of the page */ + word height; /* virtual height of the page */ +} page_t; + +/* -============================ Functions =============================- */ +/* mode switching, page, and plane functions */ +void modexEnter(); +void setvideo(/*byte mode, */short vq); +page_t modexDefaultPage(); +page_t modexNextPage(page_t *p); +void modexShowPage(page_t *page); +void modexPanPage(page_t *page, int dx, int dy); +void modexSelectPlane(byte plane); +void modexClearRegion(page_t *page, int x, int y, int w, int h, byte color); +void modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp); +void modexDrawBmpRegion(page_t *page, int x, int y, int rx, int ry, int rw, int rh, bitmap_t *bmp); +void modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp); +void modexDrawSpriteRegion(page_t *page, int x, int y, int rx, int ry, int rw, int rh, bitmap_t *bmp); + +/* Palette fade and flash effects */ +void modexFadeOn(word fade, byte *palette); +void modexFadeOff(word fade, byte *palette); +void modexFlashOn(word fade, byte *palette); +void modexFlashOff(word fade, byte *palette); + +/* palette loading and saving */ +void modexPalSave(byte *palette); +byte *modexNewPal(); +void modexLoadPalFile(char *filename, byte **palette); +void modexSavePalFile(char *filename, byte *palette); + +/* fixed palette functions */ +void modexPalBlack(); +void modexPalWhite(); + +/* utility functions */ +void modexPalUpdate(byte *p); +void modexWaitBorder(); + +/* bitmap functions */ +bitmap_t modexLoadPcx(char *filename); + +/* -======================= Constants & Vars ==========================- */ +extern byte far* VGA; /* The VGA Memory */ +#define SCREEN_SEG 0xa000 +#define VIDEO_INT 0x10 +#define SET_MODE 0x00 +#define VGA_256_COLOR_MODE 0x13 +#define TEXT_MODE 0x03 +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 240 +#define PAGE_SIZE (word)(SCREEN_WIDTH/4 * SCREEN_HEIGHT) + +#define AC_INDEX 0x03c0 +#define SC_INDEX 0x03c4 +#define SC_DATA 0x03c5 +#define CRTC_INDEX 0x03d4 +#define CRTC_DATA 0x03d5 +#define MISC_OUTPUT 0x03c2 +#define HIGH_ADDRESS 0x0C +#define LOW_ADDRESS 0x0D +#define VRETRACE 0x08 +#define INPUT_STATUS_1 0x03da +#define DISPLAY_ENABLE 0x01 +#define MAP_MASK 0x02 +#define PAL_READ_REG 0x03C7 /* Color register, read address */ +#define PAL_WRITE_REG 0x03C8 /* Color register, write address */ +#define PAL_DATA_REG 0x03C9 /* Color register, data port */ +#define PAL_SIZE (256 * 3) + +#define NUM_COLORS 256 // number of colors in vga mode +#define BONK 400 +#define LGQ 32 +#define HGQ 55 +#define TILEWH 16 +#define QUADWH TILEWH/2 +#endif diff --git a/16/modex16/PALVIEW.EXE b/16/modex16_/PALVIEW.EXE similarity index 100% rename from 16/modex16/PALVIEW.EXE rename to 16/modex16_/PALVIEW.EXE diff --git a/16/modex16_/PCXTEST.EXE b/16/modex16_/PCXTEST.EXE new file mode 100644 index 00000000..e10ce68d Binary files /dev/null and b/16/modex16_/PCXTEST.EXE differ diff --git a/16/modex16_/TEST.EXE b/16/modex16_/TEST.EXE new file mode 100644 index 00000000..e470ea6e Binary files /dev/null and b/16/modex16_/TEST.EXE differ diff --git a/16/modex16_/TEST2.EXE b/16/modex16_/TEST2.EXE new file mode 100644 index 00000000..57c13a9e Binary files /dev/null and b/16/modex16_/TEST2.EXE differ diff --git a/16/modex16/chikyuu.pcx b/16/modex16_/chikyuu.pcx similarity index 100% rename from 16/modex16/chikyuu.pcx rename to 16/modex16_/chikyuu.pcx diff --git a/16/modex16_/ed.pcx b/16/modex16_/ed.pcx new file mode 100644 index 00000000..41e56317 Binary files /dev/null and b/16/modex16_/ed.pcx differ diff --git a/16/modex16/ed2.pcx b/16/modex16_/ed2.pcx similarity index 100% rename from 16/modex16/ed2.pcx rename to 16/modex16_/ed2.pcx diff --git a/16/modex16_/gfx.pal b/16/modex16_/gfx.pal new file mode 100644 index 00000000..e98ae60e Binary files /dev/null and b/16/modex16_/gfx.pal differ diff --git a/16/modex16/koishi.pcx b/16/modex16_/koishi.pcx similarity index 100% rename from 16/modex16/koishi.pcx rename to 16/modex16_/koishi.pcx diff --git a/16/modex16/koishi^^.pcx b/16/modex16_/koishi^^.pcx similarity index 100% rename from 16/modex16/koishi^^.pcx rename to 16/modex16_/koishi^^.pcx diff --git a/16/modex16_/koishi~.pcx b/16/modex16_/koishi~.pcx new file mode 100644 index 00000000..58a03bb4 Binary files /dev/null and b/16/modex16_/koishi~.pcx differ diff --git a/16/modex16_/makefile b/16/modex16_/makefile new file mode 100644 index 00000000..c48885b8 --- /dev/null +++ b/16/modex16_/makefile @@ -0,0 +1,27 @@ +FLAGS=-0 -d3 +all: test.exe pcxtest.exe test2.exe + +test.exe: test.obj modex16.obj + wcl $(FLAGS) test.obj modex16.obj + +test2.exe: test2.obj modex16.obj + wcl $(FLAGS) test2.obj modex16.obj + +pcxtest.exe: pcxtest.obj modex16.obj + wcl $(FLAGS) pcxtest.obj modex16.obj + +test.obj: test.c modex16.h + wcl $(FLAGS) -c test.c + +test2.obj: test2.c modex16.h + wcl $(FLAGS) -c test2.c + +pcxtest.obj: pcxtest.c modex16.h + wcl $(FLAGS) -c pcxtest.c + +modex16.obj: modex16.h modex16.c + wcl $(FLAGS) -c modex16.c + +clean: + del *.obj + del *.exe diff --git a/16/modex16_/palettec.c b/16/modex16_/palettec.c new file mode 100644 index 00000000..340a9303 --- /dev/null +++ b/16/modex16_/palettec.c @@ -0,0 +1,16 @@ +#include "modex16.h" + +void +main() { + byte *pal; + + modexEnter(); + + pal = modexNewPal(); + modexPalSave(pal); + + modexSavePalFile("gfx.pal", pal); + + modexLeave(); + +} diff --git a/16/modex16_/pcxtest.c b/16/modex16_/pcxtest.c new file mode 100644 index 00000000..45f783c6 --- /dev/null +++ b/16/modex16_/pcxtest.c @@ -0,0 +1,76 @@ +#include +#include "modex16.h" + +word far* clock= (word far*) 0x046C; /* 18.2hz clock */ + +void +oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite) { + byte plane; + word px, py; + word offset; + + /* TODO Make this fast. It's SLOOOOOOW */ + for(plane=0; plane < 4; plane++) { + modexSelectPlane(PLANE(plane+x)); + for(px = plane; px < bmp->width; px+=4) { + offset=px; + for(py=0; pyheight; py++) { + if(!sprite || bmp->data[offset]) + page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset]; + offset+=bmp->width; + } + } + } +} + +void main() { + bitmap_t bmp; + int i; + float t1, t2, t3, t4; + word start; + page_t page; + + page=modexDefaultPage(); + + bmp = modexLoadPcx("ed.pcx"); + setvideo(1); + + /* fix up the palette and everything */ + modexPalUpdate(bmp.palette); + + /* clear and draw one sprite and one bitmap */ + modexClearRegion(&page, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 1); + + /* non sprite comparison */ + start = *clock; + for(i=0; i<100 ;i++) { + oldDrawBmp(VGA, 20, 20, &bmp, 0); + } + t1 = (*clock-start) / 18.2; + + start = *clock; + for(i=0; i<100 ;i++) { + modexDrawBmp(&page, 20, 20, &bmp); + } + t2 = (*clock-start) / 18.2; + + start = *clock; + for(i=0; i<100 ;i++) { + oldDrawBmp(VGA, 20, 20, &bmp, 1); + } + t3 = (*clock-start) / 18.2; + + start = *clock; + for(i=0; i<100 ;i++) { + modexDrawSprite(&page, 20, 20, &bmp); + } + t4 = (*clock-start) / 18.2; + setvideo(0); + + printf("Old non-sprite: %f\n", t1); + printf("New non-sprite: %f\n", t2); + printf("Old Sprite: %f\n", t3); + printf("New Sprite: %f\n", t4); + + return; +} diff --git a/16/modex16/q.pcx b/16/modex16_/q.pcx similarity index 100% rename from 16/modex16/q.pcx rename to 16/modex16_/q.pcx diff --git a/16/modex16_/test.c b/16/modex16_/test.c new file mode 100644 index 00000000..c8f1bfa5 --- /dev/null +++ b/16/modex16_/test.c @@ -0,0 +1,90 @@ +#include "modex16.h" +#include + +word far* clock= (word far*) 0x046C; /* 18.2hz clock */ + +void main() { + bitmap_t bmp; + bitmap_t bmp2; + int i, j; + word start, end; + page_t page, page2; + float elapsed; + byte *pal, *pal2=NULL; + + /* load pcx file */ + bmp = modexLoadPcx("ed.pcx"); + bmp2 = modexLoadPcx("koishi~.pcx"); + modexPalUpdate(bmp2.palette); + + /* load our palette */ + modexLoadPalFile("gfx.pal", &pal2); + + /* save the palette */ + pal = modexNewPal(); + modexPalSave(pal); + modexFadeOff(1, pal); + modexPalBlack(); + + setvideo(1); + modexPalBlack(); + + /* set up the page, but with 16 pixels on all borders in offscreen mem */ + page=modexDefaultPage(); + page2 = modexNextPage(&page); + page.width += 32; + page.height += 32; + + + /* fill the page with one color, but with a black border */ + modexShowPage(&page2); + modexClearRegion(&page, 16, 16, SCREEN_WIDTH, SCREEN_HEIGHT, 128); + modexClearRegion(&page, 32, 32, SCREEN_WIDTH-32, SCREEN_HEIGHT-32, 42); + modexClearRegion(&page, 48, 48, SCREEN_WIDTH-64, SCREEN_HEIGHT-64, 128); + modexShowPage(&page); + + modexDrawSprite(&page, 48, 48, &bmp); + modexDrawSprite(&page, 100, 100, &bmp2); + //modexDrawBmp(&page, xb, yb, &bmp); + + /* fade in */ + modexFadeOn(1, pal2); + +modexPalUpdate(bmp2.palette); + + start = *clock; + //for(i=0; i<5; i++) { + while (!kbhit()){ /* Wait for a keystroke */ + /* go right */ + for(j=0; j<32; j++) { + page.dx++; + modexShowPage(&page); + } + /* go left */ + for(j=0; j<32; j++) { + page.dx--; + modexShowPage(&page); + } + /* go up */ + for(j=0; j<32; j++) { + page.dy++; + modexShowPage(&page); + } + + /* go down */ + for(j=0; j<32; j++) { + page.dy--; + modexShowPage(&page); + } + } + + (void) getch(); /* Clear the keyboard buffer */ + end = *clock; + + /* fade back to text mode */ + modexFadeOff(1, pal2); + modexPalBlack(); + setvideo(0); + modexPalBlack(); + modexFadeOn(1, pal); +} diff --git a/16/modex16_/test.txt b/16/modex16_/test.txt new file mode 100644 index 00000000..05adc9ec --- /dev/null +++ b/16/modex16_/test.txt @@ -0,0 +1,258 @@ +64 x 64 Pixels + +0 0 0 +20 0 0 +0 20 0 +20 20 0 +0 0 20 +20 0 20 +0 20 20 +30 30 30 +30 37 30 +29 32 3c +3f 3f 33 +3f 3f 26 +3f 3f 19 +3f 3f c +3f 33 3f +3f 33 33 +3f 33 26 +3f 33 19 +3f 33 c +3f 33 0 +3f 26 3f +3f 26 33 +3f 26 26 +3f 26 19 +3f 26 c +3f 26 0 +3f 19 3f +3f 19 33 +3f 19 26 +3f 19 19 +3f 19 c +3f 19 0 +3f c 3f +3f c 33 +3f c 26 +3f c 19 +3f c c +3f c 0 +3f 0 33 +3f 0 26 +3f 0 19 +3f 0 c +33 3f 3f +33 3f 33 +33 3f 26 +33 3f 19 +33 3f c +33 3f 0 +33 33 3f +33 33 33 +33 33 26 +33 33 19 +33 33 c +33 33 0 +33 26 3f +33 26 33 +33 26 26 +33 26 19 +33 26 c +33 26 0 +33 19 3f +33 19 33 +33 19 26 +33 19 19 +33 19 c +33 19 0 +33 c 3f +33 c 33 +33 c 26 +33 c 19 +33 c c +33 c 0 +33 0 3f +33 0 33 +33 0 26 +33 0 19 +33 0 c +33 0 0 +26 3f 3f +26 3f 33 +26 3f 26 +26 3f 19 +26 3f c +26 3f 0 +26 33 3f +26 33 33 +26 33 26 +26 33 19 +26 33 c +26 33 0 +26 26 3f +26 26 33 +26 26 26 +26 26 19 +26 26 c +26 26 0 +26 19 3f +26 19 33 +26 19 26 +26 19 19 +26 19 c +26 19 0 +26 c 3f +26 c 33 +26 c 26 +26 c 19 +26 c c +26 c 0 +26 0 3f +26 0 33 +26 0 26 +26 0 19 +26 0 c +26 0 0 +19 3f 3f +19 3f 33 +19 3f 26 +19 3f 19 +19 3f c +19 3f 0 +19 33 3f +19 33 33 +19 33 26 +19 33 19 +19 33 c +19 33 0 +19 26 3f +19 26 33 +19 26 26 +19 26 19 +19 26 c +19 26 0 +19 19 3f +19 19 33 +19 19 26 +19 19 19 +19 19 c +19 19 0 +19 c 3f +19 c 33 +19 c 26 +19 c 19 +19 c c +19 c 0 +19 0 3f +19 0 33 +19 0 26 +19 0 19 +19 0 c +19 0 0 +c 3f 3f +c 3f 33 +c 3f 26 +c 3f 19 +c 3f c +c 3f 0 +c 33 3f +c 33 33 +c 33 26 +c 33 19 +c 33 c +c 33 0 +c 26 3f +c 26 33 +c 26 26 +c 26 19 +c 26 c +c 26 0 +c 19 3f +c 19 33 +c 19 26 +c 19 19 +c 19 c +c 19 0 +c c 3f +c c 33 +c c 26 +c c 19 +c c c +c c 0 +c 0 3f +c 0 33 +c 0 26 +c 0 19 +c 0 c +c 0 0 +0 3f 33 +0 3f 26 +0 3f 19 +0 3f c +0 33 3f +0 33 33 +0 33 26 +0 33 19 +0 33 c +0 33 0 +0 26 3f +0 26 33 +0 26 26 +0 26 19 +0 26 c +0 26 0 +0 19 3f +0 19 33 +0 19 26 +0 19 19 +0 19 c +0 19 0 +0 c 3f +0 c 33 +0 c 26 +0 c 19 +0 c c +0 c 0 +0 0 33 +0 0 26 +0 0 19 +0 0 c +20 3f 3f +10 20 20 +20 3f 0 +10 10 0 +3f 3f 20 +3f 20 0 +3f 20 20 +20 10 0 +20 0 3f +20 0 10 +10 20 3f +0 10 20 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +3f 3e 3c +28 28 29 +20 20 20 +3f 0 0 +0 3f 0 +3f 3f 0 +0 0 3f +3f 0 3f +0 3f 3f +3f 3f 3f \ No newline at end of file diff --git a/16/modex16_/test2.c b/16/modex16_/test2.c new file mode 100644 index 00000000..a3669980 --- /dev/null +++ b/16/modex16_/test2.c @@ -0,0 +1,22 @@ +#include "modex16.h" + +word far* clock= (word far*) 0x046C; /* 18.2hz clock */ + +void main() { + int i; + word start; + float t1, t2; + page_t page; + + page=modexDefaultPage(); + + setvideo(1); + start = *clock; + for(i=0; i<500; i++) { + modexShowPage(&page); + } + t1 = (*clock - start)/18.2; + setvideo(0); + + printf("Time: %f\n", t1); +} diff --git a/16/modex16_/types.h b/16/modex16_/types.h new file mode 100644 index 00000000..039653f2 --- /dev/null +++ b/16/modex16_/types.h @@ -0,0 +1,11 @@ +/* + * Just some handy typedefs that make it easier to think about the low + * level code + */ + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long dword; +typedef signed char sbyte; +typedef signed short sword; +typedef signed long sdword; diff --git a/16/modex16/w.pcx b/16/modex16_/w.pcx similarity index 100% rename from 16/modex16/w.pcx rename to 16/modex16_/w.pcx diff --git a/TODO b/TODO index ac1a4504..59a676b1 100644 --- a/TODO +++ b/TODO @@ -10,7 +10,9 @@ pngwen is making this part! 4. map rendering 5. map and item interaction 6. fix any bugs found -7. script system for text and interaction -8. clean up repository after event 1. - -9. make the game wwww +7. script system for text and interaction + +8. clean up repository after event 1. + +9. basic sounds from opl2 + pc speaker! +10. make the game wwww